OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ash/system/tray/tray_bubble_view.h" | 5 #include "ash/system/tray/tray_bubble_view.h" |
6 | 6 |
7 #include "ash/root_window_controller.h" | |
8 #include "ash/shell.h" | |
9 #include "ash/shell_window_ids.h" | |
10 #include "ash/system/tray/tray_constants.h" | |
11 #include "ash/wm/property_util.h" | |
12 #include "ash/wm/shelf_layout_manager.h" | |
13 #include "ash/wm/window_animations.h" | |
14 #include "grit/ash_strings.h" | |
15 #include "third_party/skia/include/core/SkCanvas.h" | 7 #include "third_party/skia/include/core/SkCanvas.h" |
16 #include "third_party/skia/include/core/SkColor.h" | 8 #include "third_party/skia/include/core/SkColor.h" |
17 #include "third_party/skia/include/core/SkPaint.h" | 9 #include "third_party/skia/include/core/SkPaint.h" |
18 #include "third_party/skia/include/core/SkPath.h" | 10 #include "third_party/skia/include/core/SkPath.h" |
19 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | 11 #include "third_party/skia/include/effects/SkBlurImageFilter.h" |
20 #include "ui/aura/window.h" | 12 #include "ui/aura/window.h" |
21 #include "ui/base/accessibility/accessible_view_state.h" | 13 #include "ui/base/accessibility/accessible_view_state.h" |
22 #include "ui/base/events/event.h" | 14 #include "ui/base/events/event.h" |
23 #include "ui/base/l10n/l10n_util.h" | 15 #include "ui/base/l10n/l10n_util.h" |
24 #include "ui/gfx/canvas.h" | 16 #include "ui/gfx/canvas.h" |
25 #include "ui/gfx/insets.h" | 17 #include "ui/gfx/insets.h" |
26 #include "ui/gfx/path.h" | 18 #include "ui/gfx/path.h" |
27 #include "ui/gfx/screen.h" | |
28 #include "ui/gfx/skia_util.h" | 19 #include "ui/gfx/skia_util.h" |
29 #include "ui/views/bubble/bubble_frame_view.h" | 20 #include "ui/views/bubble/bubble_frame_view.h" |
30 #include "ui/views/layout/box_layout.h" | 21 #include "ui/views/layout/box_layout.h" |
31 #include "ui/views/widget/widget.h" | 22 #include "ui/views/widget/widget.h" |
32 | 23 |
33 namespace ash { | |
34 | |
35 namespace internal { | |
36 | |
37 // Inset the arrow a bit from the edge. | 24 // Inset the arrow a bit from the edge. |
38 const int kArrowMinOffset = 20; | 25 const int kArrowMinOffset = 20; |
39 const int kBubbleSpacing = 20; | 26 const int kBubbleSpacing = 20; |
40 | 27 |
41 const int kAnimationDurationForPopupMS = 200; | |
42 | |
43 // Custom border for TrayBubbleView. Contains special logic for GetBounds() | 28 // Custom border for TrayBubbleView. Contains special logic for GetBounds() |
44 // to stack bubbles with no arrows correctly. Also calculates the arrow offset. | 29 // to stack bubbles with no arrows correctly. Also calculates the arrow offset. |
45 class TrayBubbleBorder : public views::BubbleBorder { | 30 class TrayBubbleBorder : public views::BubbleBorder { |
46 public: | 31 public: |
47 TrayBubbleBorder(views::View* owner, | 32 TrayBubbleBorder(views::View* owner, |
48 views::View* anchor, | 33 views::View* anchor, |
49 views::BubbleBorder::ArrowLocation arrow_location, | |
50 TrayBubbleView::InitParams params) | 34 TrayBubbleView::InitParams params) |
51 : views::BubbleBorder(arrow_location, params.shadow), | 35 : views::BubbleBorder(params.arrow_location, params.shadow), |
52 owner_(owner), | 36 owner_(owner), |
53 anchor_(anchor), | 37 anchor_(anchor), |
54 tray_arrow_offset_(params.arrow_offset) { | 38 tray_arrow_offset_(params.arrow_offset) { |
55 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 39 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
56 set_background_color(params.arrow_color); | 40 set_background_color(params.arrow_color); |
57 } | 41 } |
58 | 42 |
59 virtual ~TrayBubbleBorder() {} | 43 virtual ~TrayBubbleBorder() {} |
60 | 44 |
61 // Overridden from views::BubbleBorder. | 45 // Overridden from views::BubbleBorder. |
(...skipping 18 matching lines...) Expand all Loading... | |
80 + insets.height() - kBubbleSpacing; | 64 + insets.height() - kBubbleSpacing; |
81 return gfx::Rect(x, y, border_size.width(), border_size.height()); | 65 return gfx::Rect(x, y, border_size.width(), border_size.height()); |
82 } | 66 } |
83 | 67 |
84 void UpdateArrowOffset() { | 68 void UpdateArrowOffset() { |
85 int arrow_offset = 0; | 69 int arrow_offset = 0; |
86 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || | 70 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT || |
87 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { | 71 arrow_location() == views::BubbleBorder::BOTTOM_LEFT) { |
88 // Note: tray_arrow_offset_ is relative to the anchor widget. | 72 // Note: tray_arrow_offset_ is relative to the anchor widget. |
89 if (tray_arrow_offset_ == | 73 if (tray_arrow_offset_ == |
90 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) { | 74 TrayBubbleView::InitParams::kArrowDefaultOffset) { |
91 arrow_offset = kArrowMinOffset; | 75 arrow_offset = kArrowMinOffset; |
92 } else { | 76 } else { |
93 const int width = owner_->GetWidget()->GetContentsView()->width(); | 77 const int width = owner_->GetWidget()->GetContentsView()->width(); |
94 gfx::Point pt(tray_arrow_offset_, 0); | 78 gfx::Point pt(tray_arrow_offset_, 0); |
95 views::View::ConvertPointToScreen( | 79 views::View::ConvertPointToScreen( |
96 anchor_->GetWidget()->GetRootView(), &pt); | 80 anchor_->GetWidget()->GetRootView(), &pt); |
97 views::View::ConvertPointFromScreen( | 81 views::View::ConvertPointFromScreen( |
98 owner_->GetWidget()->GetRootView(), &pt); | 82 owner_->GetWidget()->GetRootView(), &pt); |
99 arrow_offset = pt.x(); | 83 arrow_offset = pt.x(); |
100 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) | 84 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) |
101 arrow_offset = width - arrow_offset; | 85 arrow_offset = width - arrow_offset; |
102 arrow_offset = std::max(arrow_offset, kArrowMinOffset); | 86 arrow_offset = std::max(arrow_offset, kArrowMinOffset); |
103 } | 87 } |
104 } else { | 88 } else { |
105 if (tray_arrow_offset_ == | 89 if (tray_arrow_offset_ == |
106 internal::TrayBubbleView::InitParams::kArrowDefaultOffset) { | 90 TrayBubbleView::InitParams::kArrowDefaultOffset) { |
107 arrow_offset = kArrowMinOffset; | 91 arrow_offset = kArrowMinOffset; |
108 } else { | 92 } else { |
109 gfx::Point pt(0, tray_arrow_offset_); | 93 gfx::Point pt(0, tray_arrow_offset_); |
110 views::View::ConvertPointToScreen( | 94 views::View::ConvertPointToScreen( |
111 anchor_->GetWidget()->GetRootView(), &pt); | 95 anchor_->GetWidget()->GetRootView(), &pt); |
112 views::View::ConvertPointFromScreen( | 96 views::View::ConvertPointFromScreen( |
113 owner_->GetWidget()->GetRootView(), &pt); | 97 owner_->GetWidget()->GetRootView(), &pt); |
114 arrow_offset = pt.y(); | 98 arrow_offset = pt.y(); |
115 arrow_offset = std::max(arrow_offset, kArrowMinOffset); | 99 arrow_offset = std::max(arrow_offset, kArrowMinOffset); |
116 } | 100 } |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
178 SkColor bottom_color_; | 162 SkColor bottom_color_; |
179 SkScalar radius_; | 163 SkScalar radius_; |
180 | 164 |
181 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBackground); | 165 DISALLOW_COPY_AND_ASSIGN(TrayBubbleBackground); |
182 }; | 166 }; |
183 | 167 |
184 // Custom layout for the bubble-view. Does the default box-layout if there is | 168 // Custom layout for the bubble-view. Does the default box-layout if there is |
185 // enough height. Otherwise, makes sure the bottom rows are visible. | 169 // enough height. Otherwise, makes sure the bottom rows are visible. |
186 class BottomAlignedBoxLayout : public views::BoxLayout { | 170 class BottomAlignedBoxLayout : public views::BoxLayout { |
187 public: | 171 public: |
188 explicit BottomAlignedBoxLayout(internal::TrayBubbleView* bubble_view) | 172 explicit BottomAlignedBoxLayout(TrayBubbleView* bubble_view) |
189 : views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0), | 173 : views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0), |
190 bubble_view_(bubble_view) { | 174 bubble_view_(bubble_view) { |
191 } | 175 } |
192 | 176 |
193 virtual ~BottomAlignedBoxLayout() {} | 177 virtual ~BottomAlignedBoxLayout() {} |
194 | 178 |
195 private: | 179 private: |
196 virtual void Layout(views::View* host) OVERRIDE { | 180 virtual void Layout(views::View* host) OVERRIDE { |
197 if (host->height() >= host->GetPreferredSize().height() || | 181 if (host->height() >= host->GetPreferredSize().height() || |
198 !bubble_view_->is_gesture_dragging()) { | 182 !bubble_view_->is_gesture_dragging()) { |
199 views::BoxLayout::Layout(host); | 183 views::BoxLayout::Layout(host); |
200 return; | 184 return; |
201 } | 185 } |
202 | 186 |
203 int consumed_height = 0; | 187 int consumed_height = 0; |
204 for (int i = host->child_count() - 1; | 188 for (int i = host->child_count() - 1; |
205 i >= 0 && consumed_height < host->height(); --i) { | 189 i >= 0 && consumed_height < host->height(); --i) { |
206 views::View* child = host->child_at(i); | 190 views::View* child = host->child_at(i); |
207 if (!child->visible()) | 191 if (!child->visible()) |
208 continue; | 192 continue; |
209 gfx::Size size = child->GetPreferredSize(); | 193 gfx::Size size = child->GetPreferredSize(); |
210 child->SetBounds(0, host->height() - consumed_height - size.height(), | 194 child->SetBounds(0, host->height() - consumed_height - size.height(), |
211 host->width(), size.height()); | 195 host->width(), size.height()); |
212 consumed_height += size.height(); | 196 consumed_height += size.height(); |
213 } | 197 } |
214 } | 198 } |
215 | 199 |
216 internal::TrayBubbleView* bubble_view_; | 200 TrayBubbleView* bubble_view_; |
217 | 201 |
218 DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout); | 202 DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout); |
219 }; | 203 }; |
220 | 204 |
221 // static | 205 // static |
222 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1; | 206 const int TrayBubbleView::InitParams::kArrowDefaultOffset = -1; |
223 | 207 |
224 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type, | 208 TrayBubbleView::InitParams::InitParams(AnchorType anchor_type, |
225 ShelfAlignment shelf_alignment) | 209 AnchorAlignment anchor_alignment, |
210 int bubble_width) | |
226 : anchor_type(anchor_type), | 211 : anchor_type(anchor_type), |
227 shelf_alignment(shelf_alignment), | 212 anchor_alignment(anchor_alignment), |
228 bubble_width(kTrayPopupWidth), | 213 bubble_width(bubble_width), |
229 max_height(0), | 214 max_height(0), |
230 can_activate(false), | 215 can_activate(false), |
231 close_on_deactivate(true), | 216 close_on_deactivate(true), |
232 top_color(SK_ColorBLACK), | 217 top_color(SK_ColorBLACK), |
233 arrow_color(SK_ColorBLACK), | 218 arrow_color(SK_ColorBLACK), |
219 arrow_location(views::BubbleBorder::NONE), | |
234 arrow_offset(kArrowDefaultOffset), | 220 arrow_offset(kArrowDefaultOffset), |
235 shadow(views::BubbleBorder::BIG_SHADOW) { | 221 shadow(views::BubbleBorder::BIG_SHADOW) { |
236 } | 222 } |
237 | 223 |
238 TrayBubbleView* TrayBubbleView::Create(views::View* anchor, | 224 TrayBubbleView* TrayBubbleView::Create(aura::Window* parent_window, |
239 Host* host, | 225 views::View* anchor, |
240 const InitParams& init_params) { | 226 Delegate* delegate, |
227 InitParams* init_params) { | |
241 // Set arrow_location here so that it can be passed correctly to the | 228 // Set arrow_location here so that it can be passed correctly to the |
242 // BubbleView constructor. | 229 // BubbleView constructor. |
243 views::BubbleBorder::ArrowLocation arrow_location; | 230 if (init_params->anchor_type == ANCHOR_TYPE_TRAY) { |
244 if (init_params.anchor_type == ANCHOR_TYPE_TRAY) { | 231 if (init_params->anchor_alignment == ANCHOR_ALIGNMENT_BOTTOM) { |
245 if (init_params.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) { | 232 init_params->arrow_location = base::i18n::IsRTL() ? |
246 arrow_location = base::i18n::IsRTL() ? | |
247 views::BubbleBorder::BOTTOM_LEFT : views::BubbleBorder::BOTTOM_RIGHT; | 233 views::BubbleBorder::BOTTOM_LEFT : views::BubbleBorder::BOTTOM_RIGHT; |
248 } else if (init_params.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | 234 } else if (init_params->anchor_alignment == ANCHOR_ALIGNMENT_LEFT) { |
249 arrow_location = views::BubbleBorder::LEFT_BOTTOM; | 235 init_params->arrow_location = views::BubbleBorder::LEFT_BOTTOM; |
250 } else { | 236 } else { |
251 arrow_location = views::BubbleBorder::RIGHT_BOTTOM; | 237 init_params->arrow_location = views::BubbleBorder::RIGHT_BOTTOM; |
252 } | 238 } |
253 } else { | 239 } else { |
254 arrow_location = views::BubbleBorder::NONE; | 240 init_params->arrow_location = views::BubbleBorder::NONE; |
255 } | 241 } |
256 | 242 |
257 return new TrayBubbleView(init_params, arrow_location, anchor, host); | 243 return new TrayBubbleView(parent_window, anchor, delegate, *init_params); |
258 } | 244 } |
259 | 245 |
260 TrayBubbleView::TrayBubbleView( | 246 TrayBubbleView::TrayBubbleView(aura::Window* parent_window, |
261 const InitParams& init_params, | 247 views::View* anchor, |
262 views::BubbleBorder::ArrowLocation arrow_location, | 248 Delegate* delegate, |
263 views::View* anchor, | 249 const InitParams& init_params) |
264 Host* host) | 250 : views::BubbleDelegateView(anchor, init_params.arrow_location), |
265 : views::BubbleDelegateView(anchor, arrow_location), | |
266 params_(init_params), | 251 params_(init_params), |
267 host_(host), | 252 delegate_(delegate), |
268 bubble_border_(NULL), | 253 bubble_border_(NULL), |
269 bubble_background_(NULL), | 254 bubble_background_(NULL), |
270 is_gesture_dragging_(false) { | 255 is_gesture_dragging_(false) { |
271 set_parent_window(Shell::GetContainer( | 256 set_parent_window(parent_window); |
272 anchor->GetWidget()->GetNativeWindow()->GetRootWindow(), | |
273 internal::kShellWindowId_SettingBubbleContainer)); | |
274 set_notify_enter_exit_on_child(true); | 257 set_notify_enter_exit_on_child(true); |
275 set_close_on_deactivate(init_params.close_on_deactivate); | 258 set_close_on_deactivate(init_params.close_on_deactivate); |
276 SetPaintToLayer(true); | 259 SetPaintToLayer(true); |
277 SetFillsBoundsOpaquely(true); | 260 SetFillsBoundsOpaquely(true); |
278 | 261 |
279 bubble_border_ = new TrayBubbleBorder( | 262 bubble_border_ = new TrayBubbleBorder(this, anchor_view(), params_); |
280 this, anchor_view(), arrow_location, params_); | |
281 | 263 |
282 bubble_background_ = new TrayBubbleBackground( | 264 bubble_background_ = new TrayBubbleBackground( |
283 bubble_border_, init_params.top_color, init_params.arrow_color); | 265 bubble_border_, init_params.top_color, init_params.arrow_color); |
284 | 266 |
285 // Inset the view on the top and bottom by the corner radius to avoid drawing | 267 // Inset the view on the top and bottom by the corner radius to avoid drawing |
286 // over the the bubble corners. | 268 // over the the bubble corners. |
287 const int radius = bubble_background_->radius(); | 269 const int radius = bubble_background_->radius(); |
288 set_margins(gfx::Insets(radius, 0, radius, 0)); | 270 set_margins(gfx::Insets(radius, 0, radius, 0)); |
289 } | 271 } |
290 | 272 |
291 TrayBubbleView::~TrayBubbleView() { | 273 TrayBubbleView::~TrayBubbleView() { |
292 // Inform host items (models) that their views are being destroyed. | 274 // Inform host items (models) that their views are being destroyed. |
293 if (host_) | 275 if (delegate_) |
294 host_->BubbleViewDestroyed(); | 276 delegate_->BubbleViewDestroyed(); |
277 } | |
278 | |
279 void TrayBubbleView::InitializeAndShowBubble(views::Widget* widget) { | |
280 // Must occur after call to BubbleDelegateView::CreateBubble(). | |
281 SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | |
282 bubble_border_->UpdateArrowOffset(); | |
283 | |
284 Show(); | |
285 UpdateBubble(); | |
295 } | 286 } |
296 | 287 |
297 void TrayBubbleView::UpdateBubble() { | 288 void TrayBubbleView::UpdateBubble() { |
298 SizeToContents(); | 289 SizeToContents(); |
299 GetWidget()->GetRootView()->SchedulePaint(); | 290 GetWidget()->GetRootView()->SchedulePaint(); |
300 } | 291 } |
301 | 292 |
302 void TrayBubbleView::SetMaxHeight(int height) { | 293 void TrayBubbleView::SetMaxHeight(int height) { |
303 params_.max_height = height; | 294 params_.max_height = height; |
304 if (GetWidget()) | 295 if (GetWidget()) |
305 SizeToContents(); | 296 SizeToContents(); |
306 } | 297 } |
307 | 298 |
299 void TrayBubbleView::GetBorderInsets(gfx::Insets* insets) const { | |
300 bubble_border_->GetInsets(insets); | |
301 } | |
302 | |
308 void TrayBubbleView::Init() { | 303 void TrayBubbleView::Init() { |
309 views::BoxLayout* layout = new BottomAlignedBoxLayout(this); | 304 views::BoxLayout* layout = new BottomAlignedBoxLayout(this); |
310 layout->set_spread_blank_space(true); | 305 layout->set_spread_blank_space(true); |
311 SetLayoutManager(layout); | 306 SetLayoutManager(layout); |
312 } | 307 } |
313 | 308 |
314 gfx::Rect TrayBubbleView::GetAnchorRect() { | 309 gfx::Rect TrayBubbleView::GetAnchorRect() { |
315 gfx::Rect rect; | 310 gfx::Rect rect; |
316 | 311 if (delegate_) { |
317 if (anchor_widget() && anchor_widget()->IsVisible()) { | 312 rect = delegate_->GetAnchorRect(anchor_widget(), |
318 rect = anchor_widget()->GetWindowBoundsInScreen(); | 313 params_.anchor_type, |
319 if (params_.anchor_type == ANCHOR_TYPE_TRAY) { | 314 params_.anchor_alignment); |
miket_OOO
2012/10/12 19:53:59
Nice.
| |
320 if (params_.shelf_alignment == SHELF_ALIGNMENT_BOTTOM) { | |
321 bool rtl = base::i18n::IsRTL(); | |
322 rect.Inset( | |
323 rtl ? kPaddingFromRightEdgeOfScreenBottomAlignment : 0, | |
324 0, | |
325 rtl ? 0 : kPaddingFromRightEdgeOfScreenBottomAlignment, | |
326 kPaddingFromBottomOfScreenBottomAlignment); | |
327 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | |
328 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
329 kPaddingFromBottomOfScreenVerticalAlignment); | |
330 } else { | |
331 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
332 0, 0, kPaddingFromBottomOfScreenVerticalAlignment); | |
333 } | |
334 } else if (params_.anchor_type == ANCHOR_TYPE_BUBBLE) { | |
335 // Invert the offsets to align with the bubble below. | |
336 if (params_.shelf_alignment == SHELF_ALIGNMENT_LEFT) { | |
337 rect.Inset(kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
338 0, 0, kPaddingFromBottomOfScreenVerticalAlignment); | |
339 } else if (params_.shelf_alignment == SHELF_ALIGNMENT_RIGHT) { | |
340 rect.Inset(0, 0, kPaddingFromInnerEdgeOfLauncherVerticalAlignment, | |
341 kPaddingFromBottomOfScreenVerticalAlignment); | |
342 } | |
343 } | |
344 } | |
345 | |
346 // TODO(jennyz): May need to add left/right alignment in the following code. | |
347 if (rect.IsEmpty()) { | |
348 rect = gfx::Screen::GetPrimaryDisplay().bounds(); | |
349 rect = gfx::Rect( | |
350 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : | |
351 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, | |
352 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, | |
353 0, 0); | |
354 } | 315 } |
355 return rect; | 316 return rect; |
356 } | 317 } |
357 | 318 |
358 bool TrayBubbleView::CanActivate() const { | 319 bool TrayBubbleView::CanActivate() const { |
359 return params_.can_activate; | 320 return params_.can_activate; |
360 } | 321 } |
361 | 322 |
362 // Overridden to create BubbleFrameView and set a custom border and background. | 323 // Overridden to create BubbleFrameView and set a custom border and background. |
363 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView( | 324 views::NonClientFrameView* TrayBubbleView::CreateNonClientFrameView( |
(...skipping 15 matching lines...) Expand all Loading... | |
379 | 340 |
380 gfx::Size TrayBubbleView::GetPreferredSize() { | 341 gfx::Size TrayBubbleView::GetPreferredSize() { |
381 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); | 342 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); |
382 int height = size.height(); | 343 int height = size.height(); |
383 if (params_.max_height != 0 && height > params_.max_height) | 344 if (params_.max_height != 0 && height > params_.max_height) |
384 height = params_.max_height; | 345 height = params_.max_height; |
385 return gfx::Size(params_.bubble_width, height); | 346 return gfx::Size(params_.bubble_width, height); |
386 } | 347 } |
387 | 348 |
388 void TrayBubbleView::OnMouseEntered(const ui::MouseEvent& event) { | 349 void TrayBubbleView::OnMouseEntered(const ui::MouseEvent& event) { |
389 if (host_) | 350 if (delegate_) |
390 host_->OnMouseEnteredView(); | 351 delegate_->OnMouseEnteredView(); |
391 } | 352 } |
392 | 353 |
393 void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) { | 354 void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) { |
394 if (host_) | 355 if (delegate_) |
395 host_->OnMouseExitedView(); | 356 delegate_->OnMouseExitedView(); |
396 } | 357 } |
397 | 358 |
398 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { | 359 void TrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { |
399 if (params_.can_activate) { | 360 if (params_.can_activate) { |
400 state->role = ui::AccessibilityTypes::ROLE_WINDOW; | 361 state->role = ui::AccessibilityTypes::ROLE_WINDOW; |
401 state->name = host_->GetAccessibleName(); | 362 state->name = delegate_->GetAccessibleName(); |
402 } | 363 } |
403 } | 364 } |
404 | 365 |
405 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { | 366 void TrayBubbleView::ChildPreferredSizeChanged(View* child) { |
406 SizeToContents(); | 367 SizeToContents(); |
407 } | 368 } |
408 | 369 |
409 void TrayBubbleView::ViewHierarchyChanged(bool is_add, | 370 void TrayBubbleView::ViewHierarchyChanged(bool is_add, |
410 views::View* parent, | 371 views::View* parent, |
411 views::View* child) { | 372 views::View* child) { |
412 if (is_add && child == this) { | 373 if (is_add && child == this) { |
413 parent->SetPaintToLayer(true); | 374 parent->SetPaintToLayer(true); |
414 parent->SetFillsBoundsOpaquely(true); | 375 parent->SetFillsBoundsOpaquely(true); |
415 parent->layer()->SetMasksToBounds(true); | 376 parent->layer()->SetMasksToBounds(true); |
416 } | 377 } |
417 } | 378 } |
418 | |
419 TrayBubbleView::Host::Host() | |
420 : widget_(NULL), | |
421 bubble_view_(NULL), | |
422 tray_view_(NULL) { | |
423 Shell::GetInstance()->AddEnvEventFilter(this); | |
424 } | |
425 | |
426 TrayBubbleView::Host::~Host() { | |
427 Shell::GetInstance()->RemoveEnvEventFilter(this); | |
428 } | |
429 | |
430 void TrayBubbleView::Host::InitializeAndShowBubble(views::Widget* widget, | |
431 TrayBubbleView* bubble_view, | |
432 views::View* tray_view) { | |
433 widget_ = widget; | |
434 bubble_view_ = bubble_view; | |
435 tray_view_ = tray_view; | |
436 | |
437 // Must occur after call to BubbleDelegateView::CreateBubble(). | |
438 bubble_view->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | |
439 | |
440 bubble_view->bubble_border()->UpdateArrowOffset(); | |
441 | |
442 // Setup animation. | |
443 ash::SetWindowVisibilityAnimationType( | |
444 widget->GetNativeWindow(), | |
445 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | |
446 ash::SetWindowVisibilityAnimationTransition( | |
447 widget->GetNativeWindow(), | |
448 ash::ANIMATE_BOTH); | |
449 ash::SetWindowVisibilityAnimationDuration( | |
450 widget->GetNativeWindow(), | |
451 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); | |
452 | |
453 bubble_view->Show(); | |
454 bubble_view->UpdateBubble(); | |
455 } | |
456 | |
457 bool TrayBubbleView::Host::PreHandleKeyEvent(aura::Window* target, | |
458 ui::KeyEvent* event) { | |
459 return false; | |
460 } | |
461 | |
462 bool TrayBubbleView::Host::PreHandleMouseEvent(aura::Window* target, | |
463 ui::MouseEvent* event) { | |
464 if (event->type() == ui::ET_MOUSE_PRESSED) | |
465 ProcessLocatedEvent(target, *event); | |
466 return false; | |
467 } | |
468 | |
469 ui::TouchStatus TrayBubbleView::Host::PreHandleTouchEvent( | |
470 aura::Window* target, | |
471 ui::TouchEvent* event) { | |
472 if (event->type() == ui::ET_TOUCH_PRESSED) | |
473 ProcessLocatedEvent(target, *event); | |
474 return ui::TOUCH_STATUS_UNKNOWN; | |
475 } | |
476 | |
477 ui::EventResult TrayBubbleView::Host::PreHandleGestureEvent( | |
478 aura::Window* target, | |
479 ui::GestureEvent* event) { | |
480 return ui::ER_UNHANDLED; | |
481 } | |
482 | |
483 void TrayBubbleView::Host::ProcessLocatedEvent( | |
484 aura::Window* target, const ui::LocatedEvent& event) { | |
485 if (target) { | |
486 // Don't process events that occurred inside an embedded menu. | |
487 RootWindowController* root_controller = | |
488 GetRootWindowController(target->GetRootWindow()); | |
489 if (root_controller && root_controller->GetContainer( | |
490 ash::internal::kShellWindowId_MenuContainer)->Contains(target)) { | |
491 return; | |
492 } | |
493 } | |
494 if (!widget_) | |
495 return; | |
496 gfx::Rect bounds = widget_->GetWindowBoundsInScreen(); | |
497 gfx::Insets insets; | |
498 bubble_view_->bubble_border()->GetInsets(&insets); | |
499 bounds.Inset(insets); | |
500 if (bounds.Contains(event.root_location())) | |
501 return; | |
502 if (tray_view_) { | |
503 // If the user clicks on the parent tray, don't process the event here, | |
504 // let the tray logic handle the event and determine show/hide behavior. | |
505 bounds = tray_view_->GetWidget()->GetClientAreaBoundsInScreen(); | |
506 if (bounds.Contains(event.root_location())) | |
507 return; | |
508 } | |
509 // Handle clicking outside the bubble and tray. We don't block the event, so | |
510 // it will also be handled by whatever widget was clicked on. | |
511 OnClickedOutsideView(); | |
512 } | |
513 | |
514 | |
515 } // namespace internal | |
516 } // namespace ash | |
OLD | NEW |