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/system_tray_bubble.h" | 5 #include "ash/system/tray/system_tray_bubble.h" |
6 | 6 |
7 #include "ash/shell.h" | 7 #include "ash/shell.h" |
8 #include "ash/shell_window_ids.h" | |
9 #include "ash/system/tray/system_tray.h" | 8 #include "ash/system/tray/system_tray.h" |
10 #include "ash/system/tray/system_tray_delegate.h" | 9 #include "ash/system/tray/system_tray_delegate.h" |
11 #include "ash/system/tray/system_tray_item.h" | 10 #include "ash/system/tray/system_tray_item.h" |
12 #include "ash/system/tray/tray_constants.h" | 11 #include "ash/system/tray/tray_constants.h" |
13 #include "ash/wm/shelf_layout_manager.h" | |
14 #include "ash/wm/window_animations.h" | 12 #include "ash/wm/window_animations.h" |
15 #include "base/message_loop.h" | 13 #include "base/message_loop.h" |
16 #include "grit/ash_strings.h" | |
17 #include "third_party/skia/include/core/SkCanvas.h" | |
18 #include "third_party/skia/include/core/SkColor.h" | |
19 #include "third_party/skia/include/core/SkPaint.h" | |
20 #include "third_party/skia/include/core/SkPath.h" | |
21 #include "third_party/skia/include/effects/SkBlurImageFilter.h" | |
22 #include "ui/aura/event.h" | 14 #include "ui/aura/event.h" |
23 #include "ui/aura/window.h" | 15 #include "ui/aura/window.h" |
24 #include "ui/base/accessibility/accessible_view_state.h" | |
25 #include "ui/base/l10n/l10n_util.h" | |
26 #include "ui/compositor/layer.h" | 16 #include "ui/compositor/layer.h" |
27 #include "ui/compositor/layer_animation_observer.h" | 17 #include "ui/compositor/layer_animation_observer.h" |
28 #include "ui/compositor/scoped_layer_animation_settings.h" | 18 #include "ui/compositor/scoped_layer_animation_settings.h" |
29 #include "ui/gfx/canvas.h" | 19 #include "ui/gfx/canvas.h" |
30 #include "ui/gfx/screen.h" | |
31 #include "ui/views/bubble/bubble_frame_view.h" | |
32 #include "ui/views/layout/box_layout.h" | 20 #include "ui/views/layout/box_layout.h" |
33 #include "ui/views/layout/fill_layout.h" | |
34 #include "ui/views/view.h" | 21 #include "ui/views/view.h" |
35 | 22 |
36 namespace ash { | 23 namespace ash { |
37 | 24 |
38 namespace { | 25 namespace { |
39 | 26 |
40 const int kShadowThickness = 4; | |
41 | |
42 const int kBottomLineHeight = 1; | |
43 | |
44 const int kSystemTrayBubbleHorizontalInset = 1; | |
45 const int kSystemTrayBubbleVerticalInset = 1; | |
46 | |
47 const int kArrowHeight = 10; | |
48 const int kArrowWidth = 20; | |
49 const int kArrowPaddingFromRight = 20; | |
50 const int kArrowPaddingFromBottom = 17; | |
51 const int kMinArrowOffset = 12; | |
52 | |
53 const int kAnimationDurationForPopupMS = 200; | 27 const int kAnimationDurationForPopupMS = 200; |
54 | 28 |
55 // Normally a detailed view is the same size as the default view. However, | 29 // Normally a detailed view is the same size as the default view. However, |
56 // when showing a detailed view directly (e.g. clicking on a notification), | 30 // when showing a detailed view directly (e.g. clicking on a notification), |
57 // we may not know the height of the default view, or the default view may | 31 // we may not know the height of the default view, or the default view may |
58 // be too short, so we use this as a default and minimum height for any | 32 // be too short, so we use this as a default and minimum height for any |
59 // detailed view. | 33 // detailed view. |
60 const int kDetailedBubbleMaxHeight = kTrayPopupItemHeight * 5; | 34 const int kDetailedBubbleMaxHeight = kTrayPopupItemHeight * 5; |
61 | 35 |
62 const SkColor kShadowColor = SkColorSetARGB(0xff, 0, 0, 0); | |
63 | |
64 void DrawBlurredShadowAroundView(gfx::Canvas* canvas, | |
65 int top, | |
66 int bottom, | |
67 int width, | |
68 const gfx::Insets& inset) { | |
69 SkPath path; | |
70 path.incReserve(4); | |
71 path.moveTo(SkIntToScalar(inset.left() + kShadowThickness), | |
72 SkIntToScalar(top + kShadowThickness + 1)); | |
73 path.lineTo(SkIntToScalar(inset.left() + kShadowThickness), | |
74 SkIntToScalar(bottom)); | |
75 path.lineTo(SkIntToScalar(width), | |
76 SkIntToScalar(bottom)); | |
77 path.lineTo(SkIntToScalar(width), | |
78 SkIntToScalar(top + kShadowThickness + 1)); | |
79 | |
80 SkPaint paint; | |
81 paint.setColor(kShadowColor); | |
82 paint.setStyle(SkPaint::kStroke_Style); | |
83 paint.setXfermodeMode(SkXfermode::kSrcOver_Mode); | |
84 paint.setStrokeWidth(SkIntToScalar(3)); | |
85 paint.setImageFilter(new SkBlurImageFilter( | |
86 SkIntToScalar(3), SkIntToScalar(3)))->unref(); | |
87 canvas->sk_canvas()->drawPath(path, paint); | |
88 } | |
89 | |
90 // A view with some special behaviour for tray items in the popup: | 36 // A view with some special behaviour for tray items in the popup: |
91 // - changes background color on hover. | 37 // - changes background color on hover. |
92 class TrayPopupItemContainer : public views::View { | 38 class TrayPopupItemContainer : public views::View { |
93 public: | 39 public: |
94 explicit TrayPopupItemContainer(views::View* view) : hover_(false) { | 40 explicit TrayPopupItemContainer(views::View* view) : hover_(false) { |
95 set_notify_enter_exit_on_child(true); | 41 set_notify_enter_exit_on_child(true); |
96 set_border(view->border() ? views::Border::CreateEmptyBorder(0, 0, 0, 0) : | 42 set_border(view->border() ? views::Border::CreateEmptyBorder(0, 0, 0, 0) : |
97 views::Border::CreateSolidSidedBorder(1, 1, 0, 1, kBorderDarkColor)); | 43 views::Border::CreateSolidSidedBorder(1, 1, 0, 1, kBorderDarkColor)); |
98 views::BoxLayout* layout = new views::BoxLayout( | 44 views::BoxLayout* layout = new views::BoxLayout( |
99 views::BoxLayout::kVertical, 0, 0, 0); | 45 views::BoxLayout::kVertical, 0, 0, 0); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
140 canvas->FillRect(gfx::Rect(size()), | 86 canvas->FillRect(gfx::Rect(size()), |
141 hover_ ? kHoverBackgroundColor : kBackgroundColor); | 87 hover_ ? kHoverBackgroundColor : kBackgroundColor); |
142 } | 88 } |
143 } | 89 } |
144 | 90 |
145 bool hover_; | 91 bool hover_; |
146 | 92 |
147 DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); | 93 DISALLOW_COPY_AND_ASSIGN(TrayPopupItemContainer); |
148 }; | 94 }; |
149 | 95 |
150 class SystemTrayBubbleBorder : public views::BubbleBorder { | |
151 public: | |
152 SystemTrayBubbleBorder(views::View* owner, | |
153 views::BubbleBorder::ArrowLocation arrow_location, | |
154 int arrow_offset) | |
155 : views::BubbleBorder(arrow_location, | |
156 views::BubbleBorder::NO_SHADOW), | |
157 owner_(owner), | |
158 arrow_offset_(std::max(arrow_offset, kMinArrowOffset)) { | |
159 set_alignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | |
160 } | |
161 | |
162 virtual ~SystemTrayBubbleBorder() {} | |
163 | |
164 private: | |
165 // Overridden from views::BubbleBorder. | |
166 // Override views::BubbleBorder to set the bubble on top of the anchor when | |
167 // it has no arrow. | |
168 virtual gfx::Rect GetBounds(const gfx::Rect& position_relative_to, | |
169 const gfx::Size& contents_size) const OVERRIDE { | |
170 if (arrow_location() != NONE) { | |
171 return views::BubbleBorder::GetBounds(position_relative_to, | |
172 contents_size); | |
173 } | |
174 | |
175 gfx::Size border_size(contents_size); | |
176 gfx::Insets insets; | |
177 GetInsets(&insets); | |
178 border_size.Enlarge(insets.width(), insets.height()); | |
179 | |
180 const int kArrowOverlap = 3; | |
181 int x = position_relative_to.x() + | |
182 position_relative_to.width() / 2 - border_size.width() / 2; | |
183 // Position the bubble on top of the anchor. | |
184 int y = position_relative_to.y() + | |
185 kArrowOverlap - border_size.height(); | |
186 return gfx::Rect(x, y, border_size.width(), border_size.height()); | |
187 } | |
188 | |
189 // Overridden from views::Border. | |
190 virtual void Paint(const views::View& view, | |
191 gfx::Canvas* canvas) const OVERRIDE { | |
192 gfx::Insets inset; | |
193 GetInsets(&inset); | |
194 DrawBlurredShadowAroundView(canvas, 0, owner_->height(), owner_->width(), | |
195 inset); | |
196 | |
197 // Draw the bottom line. | |
198 int y = owner_->height() + 1; | |
199 canvas->FillRect(gfx::Rect(inset.left(), y, owner_->width(), | |
200 kBottomLineHeight), kBorderDarkColor); | |
201 | |
202 if (!Shell::GetInstance()->shelf()->IsVisible() || | |
203 arrow_location() == views::BubbleBorder::NONE) | |
204 return; | |
205 | |
206 // Draw the arrow after drawing child borders, so that the arrow can cover | |
207 // the its overlap section with child border. | |
208 SkPath path; | |
209 path.incReserve(4); | |
210 if (arrow_location() == views::BubbleBorder::BOTTOM_RIGHT) { | |
211 int tip_x = base::i18n::IsRTL() ? arrow_offset_ : | |
212 owner_->width() - arrow_offset_; | |
213 if (tip_x < kArrowPaddingFromRight + kArrowWidth / 2) | |
214 tip_x = kArrowPaddingFromRight + kArrowWidth / 2; | |
215 if (tip_x > owner_->width() - kArrowPaddingFromRight - kArrowWidth / 2) | |
216 tip_x = owner_->width() - kArrowPaddingFromRight - kArrowWidth / 2; | |
217 int left_base_x = tip_x - kArrowWidth / 2; | |
218 int left_base_y = y; | |
219 int tip_y = left_base_y + kArrowHeight; | |
220 path.moveTo(SkIntToScalar(left_base_x), SkIntToScalar(left_base_y)); | |
221 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); | |
222 path.lineTo(SkIntToScalar(left_base_x + kArrowWidth), | |
223 SkIntToScalar(left_base_y)); | |
224 } else if (arrow_location() == views::BubbleBorder::LEFT_BOTTOM) { | |
225 int tip_y = y - arrow_offset_; | |
226 int top_base_y = tip_y - kArrowWidth / 2; | |
227 int top_base_x = inset.left() + kSystemTrayBubbleHorizontalInset; | |
228 int tip_x = top_base_x - kArrowHeight; | |
229 path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); | |
230 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); | |
231 path.lineTo(SkIntToScalar(top_base_x), | |
232 SkIntToScalar(top_base_y + kArrowWidth)); | |
233 } else if (arrow_location() == views::BubbleBorder::RIGHT_BOTTOM){ | |
234 int tip_y = y - arrow_offset_; | |
235 int top_base_y = tip_y - kArrowWidth / 2; | |
236 int top_base_x = inset.left() + owner_->width() - | |
237 kSystemTrayBubbleHorizontalInset; | |
238 int tip_x = top_base_x + kArrowHeight; | |
239 path.moveTo(SkIntToScalar(top_base_x), SkIntToScalar(top_base_y)); | |
240 path.lineTo(SkIntToScalar(tip_x), SkIntToScalar(tip_y)); | |
241 path.lineTo(SkIntToScalar(top_base_x), | |
242 SkIntToScalar(top_base_y + kArrowWidth)); | |
243 } | |
244 | |
245 SkPaint paint; | |
246 paint.setStyle(SkPaint::kFill_Style); | |
247 paint.setColor(kHeaderBackgroundColorDark); | |
248 canvas->DrawPath(path, paint); | |
249 | |
250 // Now draw the arrow border. | |
251 paint.setStyle(SkPaint::kStroke_Style); | |
252 paint.setColor(kBorderDarkColor); | |
253 canvas->DrawPath(path, paint); | |
254 | |
255 } | |
256 | |
257 views::View* owner_; | |
258 const int arrow_offset_; | |
259 | |
260 DISALLOW_COPY_AND_ASSIGN(SystemTrayBubbleBorder); | |
261 }; | |
262 | |
263 // Implicit animation observer that deletes itself and the layer at the end of | 96 // Implicit animation observer that deletes itself and the layer at the end of |
264 // the animation. | 97 // the animation. |
265 class AnimationObserverDeleteLayer : public ui::ImplicitAnimationObserver { | 98 class AnimationObserverDeleteLayer : public ui::ImplicitAnimationObserver { |
266 public: | 99 public: |
267 explicit AnimationObserverDeleteLayer(ui::Layer* layer) | 100 explicit AnimationObserverDeleteLayer(ui::Layer* layer) |
268 : layer_(layer) { | 101 : layer_(layer) { |
269 } | 102 } |
270 | 103 |
271 virtual ~AnimationObserverDeleteLayer() { | 104 virtual ~AnimationObserverDeleteLayer() { |
272 } | 105 } |
273 | 106 |
274 virtual void OnImplicitAnimationsCompleted() OVERRIDE { | 107 virtual void OnImplicitAnimationsCompleted() OVERRIDE { |
275 MessageLoopForUI::current()->DeleteSoon(FROM_HERE, this); | 108 MessageLoopForUI::current()->DeleteSoon(FROM_HERE, this); |
276 } | 109 } |
277 | 110 |
278 private: | 111 private: |
279 scoped_ptr<ui::Layer> layer_; | 112 scoped_ptr<ui::Layer> layer_; |
280 | 113 |
281 DISALLOW_COPY_AND_ASSIGN(AnimationObserverDeleteLayer); | 114 DISALLOW_COPY_AND_ASSIGN(AnimationObserverDeleteLayer); |
282 }; | 115 }; |
283 | 116 |
284 } // namespace | 117 } // namespace |
285 | 118 |
286 namespace internal { | 119 namespace internal { |
287 | 120 |
288 // SystemTrayBubbleView | |
289 | |
290 SystemTrayBubbleView::SystemTrayBubbleView( | |
291 views::View* anchor, | |
292 views::BubbleBorder::ArrowLocation arrow_location, | |
293 SystemTrayBubble* host, | |
294 bool can_activate) | |
295 : views::BubbleDelegateView(anchor, arrow_location), | |
296 host_(host), | |
297 can_activate_(can_activate), | |
298 max_height_(0) { | |
299 set_margin(0); | |
300 set_parent_window(ash::Shell::GetInstance()->GetContainer( | |
301 ash::internal::kShellWindowId_SettingBubbleContainer)); | |
302 set_notify_enter_exit_on_child(true); | |
303 SetPaintToLayer(true); | |
304 SetFillsBoundsOpaquely(true); | |
305 } | |
306 | |
307 SystemTrayBubbleView::~SystemTrayBubbleView() { | |
308 // Inform host items (models) that their views are being destroyed. | |
309 if (host_) | |
310 host_->DestroyItemViews(); | |
311 } | |
312 | |
313 void SystemTrayBubbleView::SetBubbleBorder(views::BubbleBorder* border) { | |
314 GetBubbleFrameView()->SetBubbleBorder(border); | |
315 } | |
316 | |
317 void SystemTrayBubbleView::UpdateAnchor() { | |
318 SizeToContents(); | |
319 GetWidget()->GetRootView()->SchedulePaint(); | |
320 } | |
321 | |
322 void SystemTrayBubbleView::Init() { | |
323 views::BoxLayout* layout = | |
324 new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 0); | |
325 layout->set_spread_blank_space(true); | |
326 SetLayoutManager(layout); | |
327 set_background(NULL); | |
328 } | |
329 | |
330 gfx::Rect SystemTrayBubbleView::GetAnchorRect() { | |
331 gfx::Rect rect; | |
332 if (host_) | |
333 rect = host_->GetAnchorRect(); | |
334 // TODO(jennyz): May need to add left/right alignment in the following code. | |
335 if (rect.IsEmpty()) { | |
336 rect = gfx::Screen::GetPrimaryMonitor().bounds(); | |
337 rect = gfx::Rect( | |
338 base::i18n::IsRTL() ? kPaddingFromRightEdgeOfScreenBottomAlignment : | |
339 rect.width() - kPaddingFromRightEdgeOfScreenBottomAlignment, | |
340 rect.height() - kPaddingFromBottomOfScreenBottomAlignment, | |
341 0, 0); | |
342 } | |
343 return rect; | |
344 } | |
345 | |
346 bool SystemTrayBubbleView::CanActivate() const { | |
347 return can_activate_; | |
348 } | |
349 | |
350 gfx::Size SystemTrayBubbleView::GetPreferredSize() { | |
351 gfx::Size size = views::BubbleDelegateView::GetPreferredSize(); | |
352 int height = size.height(); | |
353 if (max_height_ != 0 && height > max_height_) | |
354 height = max_height_; | |
355 return gfx::Size(kTrayPopupWidth, height); | |
356 } | |
357 | |
358 void SystemTrayBubbleView::OnMouseEntered(const views::MouseEvent& event) { | |
359 if (host_) | |
360 host_->StopAutoCloseTimer(); | |
361 } | |
362 | |
363 void SystemTrayBubbleView::OnMouseExited(const views::MouseEvent& event) { | |
364 if (host_) | |
365 host_->RestartAutoCloseTimer(); | |
366 } | |
367 | |
368 void SystemTrayBubbleView::GetAccessibleState(ui::AccessibleViewState* state) { | |
369 if (can_activate_) { | |
370 state->role = ui::AccessibilityTypes::ROLE_WINDOW; | |
371 state->name = l10n_util::GetStringUTF16( | |
372 IDS_ASH_STATUS_TRAY_ACCESSIBLE_NAME); | |
373 } | |
374 } | |
375 | |
376 void SystemTrayBubbleView::ChildPreferredSizeChanged(View* child) { | |
377 SizeToContents(); | |
378 } | |
379 | |
380 void SystemTrayBubbleView::ViewHierarchyChanged(bool is_add, | |
381 views::View* parent, | |
382 views::View* child) { | |
383 if (is_add && child == this) { | |
384 parent->SetPaintToLayer(true); | |
385 parent->SetFillsBoundsOpaquely(true); | |
386 parent->layer()->SetMasksToBounds(true); | |
387 } | |
388 } | |
389 | |
390 // SystemTrayBubble::InitParams | 121 // SystemTrayBubble::InitParams |
391 SystemTrayBubble::InitParams::InitParams( | 122 SystemTrayBubble::InitParams::InitParams( |
392 SystemTrayBubble::AnchorType anchor_type, | 123 SystemTrayBubble::AnchorType anchor_type, |
393 ShelfAlignment shelf_alignment) | 124 ShelfAlignment shelf_alignment) |
394 : anchor(NULL), | 125 : anchor(NULL), |
395 anchor_type(anchor_type), | 126 anchor_type(anchor_type), |
396 can_activate(false), | 127 can_activate(false), |
397 login_status(ash::user::LOGGED_IN_NONE), | 128 login_status(ash::user::LOGGED_IN_NONE), |
398 arrow_offset( | 129 arrow_offset(0), |
399 (shelf_alignment == SHELF_ALIGNMENT_BOTTOM ? | |
400 kArrowPaddingFromRight : kArrowPaddingFromBottom) | |
401 + kArrowWidth / 2), | |
402 max_height(0) { | 130 max_height(0) { |
403 } | 131 } |
404 | 132 |
405 // SystemTrayBubble | 133 // SystemTrayBubble |
406 | 134 |
407 SystemTrayBubble::SystemTrayBubble( | 135 SystemTrayBubble::SystemTrayBubble( |
408 ash::SystemTray* tray, | 136 ash::SystemTray* tray, |
409 const std::vector<ash::SystemTrayItem*>& items, | 137 const std::vector<ash::SystemTrayItem*>& items, |
410 BubbleType bubble_type) | 138 BubbleType bubble_type) |
411 : tray_(tray), | 139 : tray_(tray), |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
487 | 215 |
488 DestroyItemViews(); | 216 DestroyItemViews(); |
489 bubble_view_->RemoveAllChildViews(true); | 217 bubble_view_->RemoveAllChildViews(true); |
490 | 218 |
491 items_ = items; | 219 items_ = items; |
492 bubble_type_ = bubble_type; | 220 bubble_type_ = bubble_type; |
493 CreateItemViews(Shell::GetInstance()->tray_delegate()->GetUserLoginStatus()); | 221 CreateItemViews(Shell::GetInstance()->tray_delegate()->GetUserLoginStatus()); |
494 bubble_widget_->GetContentsView()->Layout(); | 222 bubble_widget_->GetContentsView()->Layout(); |
495 // Make sure that the bubble is large enough for the default view. | 223 // Make sure that the bubble is large enough for the default view. |
496 if (bubble_type_ == BUBBLE_TYPE_DEFAULT) { | 224 if (bubble_type_ == BUBBLE_TYPE_DEFAULT) { |
497 bubble_view_->set_max_height(0); // Clear max height limit. | 225 bubble_view_->SetMaxHeight(0); // Clear max height limit. |
498 bubble_view_->SizeToContents(); | |
499 } | 226 } |
500 | 227 |
501 // When transitioning from default view to detailed view, animate the new | 228 // When transitioning from default view to detailed view, animate the new |
502 // view (slide in from the right). | 229 // view (slide in from the right). |
503 if (bubble_type == BUBBLE_TYPE_DETAILED) { | 230 if (bubble_type == BUBBLE_TYPE_DETAILED) { |
504 ui::Layer* new_layer = bubble_view_->layer(); | 231 ui::Layer* new_layer = bubble_view_->layer(); |
505 gfx::Rect bounds = new_layer->bounds(); | 232 gfx::Rect bounds = new_layer->bounds(); |
506 ui::Transform transform; | 233 ui::Transform transform; |
507 transform.SetTranslateX(bounds.width()); | 234 transform.SetTranslateX(bounds.width()); |
508 new_layer->SetTransform(transform); | 235 new_layer->SetTransform(transform); |
(...skipping 23 matching lines...) Expand all Loading... |
532 arrow_location = views::BubbleBorder::NONE; | 259 arrow_location = views::BubbleBorder::NONE; |
533 } | 260 } |
534 bubble_view_ = new SystemTrayBubbleView( | 261 bubble_view_ = new SystemTrayBubbleView( |
535 init_params.anchor, arrow_location, this, init_params.can_activate); | 262 init_params.anchor, arrow_location, this, init_params.can_activate); |
536 if (bubble_type_ == BUBBLE_TYPE_NOTIFICATION) | 263 if (bubble_type_ == BUBBLE_TYPE_NOTIFICATION) |
537 bubble_view_->set_close_on_deactivate(false); | 264 bubble_view_->set_close_on_deactivate(false); |
538 int max_height = init_params.max_height; | 265 int max_height = init_params.max_height; |
539 if (bubble_type_ == BUBBLE_TYPE_DETAILED && | 266 if (bubble_type_ == BUBBLE_TYPE_DETAILED && |
540 max_height < kDetailedBubbleMaxHeight) | 267 max_height < kDetailedBubbleMaxHeight) |
541 max_height = kDetailedBubbleMaxHeight; | 268 max_height = kDetailedBubbleMaxHeight; |
542 bubble_view_->set_max_height(max_height); | 269 bubble_view_->SetMaxHeight(max_height); |
543 | 270 |
544 CreateItemViews(init_params.login_status); | 271 CreateItemViews(init_params.login_status); |
545 | 272 |
546 DCHECK(bubble_widget_ == NULL); | 273 DCHECK(bubble_widget_ == NULL); |
547 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); | 274 bubble_widget_ = views::BubbleDelegateView::CreateBubble(bubble_view_); |
548 | 275 |
549 // Must occur after call to CreateBubble() | 276 // Must occur after call to CreateBubble() |
550 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); | 277 bubble_view_->SetAlignment(views::BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE); |
551 bubble_widget_->non_client_view()->frame_view()->set_background(NULL); | 278 bubble_widget_->non_client_view()->frame_view()->set_background(NULL); |
552 SystemTrayBubbleBorder* bubble_border = new SystemTrayBubbleBorder( | 279 bubble_view_->SetBubbleBorder(init_params.arrow_offset); |
553 bubble_view_, arrow_location, init_params.arrow_offset); | |
554 bubble_view_->SetBubbleBorder(bubble_border); | |
555 // Recalculate with new border. | |
556 bubble_view_->SizeToContents(); | |
557 | 280 |
558 bubble_widget_->AddObserver(this); | 281 bubble_widget_->AddObserver(this); |
559 | 282 |
560 // Setup animation. | 283 // Setup animation. |
561 ash::SetWindowVisibilityAnimationType( | 284 ash::SetWindowVisibilityAnimationType( |
562 bubble_widget_->GetNativeWindow(), | 285 bubble_widget_->GetNativeWindow(), |
563 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); | 286 ash::WINDOW_VISIBILITY_ANIMATION_TYPE_FADE); |
564 ash::SetWindowVisibilityAnimationTransition( | 287 ash::SetWindowVisibilityAnimationTransition( |
565 bubble_widget_->GetNativeWindow(), | 288 bubble_widget_->GetNativeWindow(), |
566 ash::ANIMATE_BOTH); | 289 ash::ANIMATE_BOTH); |
567 ash::SetWindowVisibilityAnimationDuration( | 290 ash::SetWindowVisibilityAnimationDuration( |
568 bubble_widget_->GetNativeWindow(), | 291 bubble_widget_->GetNativeWindow(), |
569 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); | 292 base::TimeDelta::FromMilliseconds(kAnimationDurationForPopupMS)); |
570 | 293 |
571 bubble_view_->Show(); | 294 bubble_view_->Show(); |
572 } | 295 } |
573 | 296 |
| 297 void SystemTrayBubble::BubbleViewDestroyed() { |
| 298 DestroyItemViews(); |
| 299 } |
| 300 |
574 gfx::Rect SystemTrayBubble::GetAnchorRect() const { | 301 gfx::Rect SystemTrayBubble::GetAnchorRect() const { |
575 gfx::Rect rect; | 302 gfx::Rect rect; |
576 views::Widget* widget = bubble_view()->anchor_widget(); | 303 views::Widget* widget = bubble_view()->anchor_widget(); |
577 if (widget->IsVisible()) { | 304 if (widget->IsVisible()) { |
578 rect = widget->GetWindowScreenBounds(); | 305 rect = widget->GetWindowScreenBounds(); |
579 if (anchor_type_ == ANCHOR_TYPE_TRAY) { | 306 if (anchor_type_ == ANCHOR_TYPE_TRAY) { |
580 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { | 307 if (tray_->shelf_alignment() == SHELF_ALIGNMENT_BOTTOM) { |
581 rect.Inset( | 308 rect.Inset( |
582 base::i18n::IsRTL() ? | 309 base::i18n::IsRTL() ? |
583 kPaddingFromRightEdgeOfScreenBottomAlignment : 0, | 310 kPaddingFromRightEdgeOfScreenBottomAlignment : 0, |
(...skipping 14 matching lines...) Expand all Loading... |
598 // be deducted out from the anchor rect. | 325 // be deducted out from the anchor rect. |
599 views::View* anchor_view = bubble_view()->anchor_view(); | 326 views::View* anchor_view = bubble_view()->anchor_view(); |
600 rect = anchor_view->GetScreenBounds(); | 327 rect = anchor_view->GetScreenBounds(); |
601 gfx::Insets insets = anchor_view->GetInsets(); | 328 gfx::Insets insets = anchor_view->GetInsets(); |
602 rect.Inset(insets); | 329 rect.Inset(insets); |
603 } | 330 } |
604 } | 331 } |
605 return rect; | 332 return rect; |
606 } | 333 } |
607 | 334 |
| 335 void SystemTrayBubble::OnMouseEnteredView() { |
| 336 StopAutoCloseTimer(); |
| 337 } |
| 338 |
| 339 void SystemTrayBubble::OnMouseExitedView() { |
| 340 RestartAutoCloseTimer(); |
| 341 } |
| 342 |
608 void SystemTrayBubble::DestroyItemViews() { | 343 void SystemTrayBubble::DestroyItemViews() { |
609 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | 344 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); |
610 it != items_.end(); | 345 it != items_.end(); |
611 ++it) { | 346 ++it) { |
612 switch (bubble_type_) { | 347 switch (bubble_type_) { |
613 case BUBBLE_TYPE_DEFAULT: | 348 case BUBBLE_TYPE_DEFAULT: |
614 (*it)->DestroyDefaultView(); | 349 (*it)->DestroyDefaultView(); |
615 break; | 350 break; |
616 case BUBBLE_TYPE_DETAILED: | 351 case BUBBLE_TYPE_DETAILED: |
617 (*it)->DestroyDetailedView(); | 352 (*it)->DestroyDetailedView(); |
(...skipping 22 matching lines...) Expand all Loading... |
640 void SystemTrayBubble::RestartAutoCloseTimer() { | 375 void SystemTrayBubble::RestartAutoCloseTimer() { |
641 if (autoclose_delay_) | 376 if (autoclose_delay_) |
642 StartAutoCloseTimer(autoclose_delay_); | 377 StartAutoCloseTimer(autoclose_delay_); |
643 } | 378 } |
644 | 379 |
645 void SystemTrayBubble::Close() { | 380 void SystemTrayBubble::Close() { |
646 if (bubble_widget_) | 381 if (bubble_widget_) |
647 bubble_widget_->Close(); | 382 bubble_widget_->Close(); |
648 } | 383 } |
649 | 384 |
| 385 void SystemTrayBubble::SetVisible(bool is_visible) { |
| 386 if (bubble_widget_) { |
| 387 if (is_visible) |
| 388 bubble_widget_->Show(); |
| 389 else |
| 390 bubble_widget_->Hide(); |
| 391 } |
| 392 } |
| 393 |
| 394 bool SystemTrayBubble::IsVisible() { |
| 395 return bubble_widget_ && bubble_widget_->IsVisible(); |
| 396 } |
| 397 |
650 void SystemTrayBubble::CreateItemViews(user::LoginStatus login_status) { | 398 void SystemTrayBubble::CreateItemViews(user::LoginStatus login_status) { |
651 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); | 399 for (std::vector<ash::SystemTrayItem*>::iterator it = items_.begin(); |
652 it != items_.end(); | 400 it != items_.end(); |
653 ++it) { | 401 ++it) { |
654 views::View* view = NULL; | 402 views::View* view = NULL; |
655 switch (bubble_type_) { | 403 switch (bubble_type_) { |
656 case BUBBLE_TYPE_DEFAULT: | 404 case BUBBLE_TYPE_DEFAULT: |
657 view = (*it)->CreateDefaultView(login_status); | 405 view = (*it)->CreateDefaultView(login_status); |
658 break; | 406 break; |
659 case BUBBLE_TYPE_DETAILED: | 407 case BUBBLE_TYPE_DETAILED: |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 } | 461 } |
714 | 462 |
715 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) { | 463 void SystemTrayBubble::OnWidgetClosing(views::Widget* widget) { |
716 CHECK_EQ(bubble_widget_, widget); | 464 CHECK_EQ(bubble_widget_, widget); |
717 bubble_widget_ = NULL; | 465 bubble_widget_ = NULL; |
718 tray_->RemoveBubble(this); | 466 tray_->RemoveBubble(this); |
719 } | 467 } |
720 | 468 |
721 } // namespace internal | 469 } // namespace internal |
722 } // namespace ash | 470 } // namespace ash |
OLD | NEW |