| 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 |