| 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/launcher/overflow_bubble.h" | 5 #include "ash/launcher/overflow_bubble.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "ash/launcher/launcher_types.h" | 9 #include "ash/launcher/launcher_types.h" |
| 10 #include "ash/launcher/launcher_view.h" | 10 #include "ash/launcher/launcher_view.h" |
| 11 #include "ash/system/tray/system_tray.h" | 11 #include "ash/system/tray/system_tray.h" |
| 12 #include "ash/shell.h" | 12 #include "ash/shell.h" |
| 13 #include "ash/wm/shelf_layout_manager.h" |
| 13 #include "ui/gfx/insets.h" | 14 #include "ui/gfx/insets.h" |
| 14 #include "ui/gfx/screen.h" | 15 #include "ui/gfx/screen.h" |
| 15 #include "ui/views/bubble/bubble_delegate.h" | 16 #include "ui/views/bubble/bubble_delegate.h" |
| 16 #include "ui/views/bubble/bubble_frame_view.h" | 17 #include "ui/views/bubble/bubble_frame_view.h" |
| 17 #include "ui/views/widget/widget.h" | 18 #include "ui/views/widget/widget.h" |
| 18 | 19 |
| 19 namespace ash { | 20 namespace ash { |
| 20 namespace internal { | 21 namespace internal { |
| 21 | 22 |
| 22 namespace { | 23 namespace { |
| 23 | 24 |
| 24 // Max bubble size to screen size ratio. | 25 // Max bubble size to screen size ratio. |
| 25 const float kMaxBubbleSizeToScreenRatio = 0.5f; | 26 const float kMaxBubbleSizeToScreenRatio = 0.5f; |
| 26 | 27 |
| 27 // Inner padding in pixels for launcher view inside bubble. | 28 // Inner padding in pixels for launcher view inside bubble. |
| 28 const int kPadding = 2; | 29 const int kPadding = 2; |
| 29 | 30 |
| 30 // Padding space in pixels between LauncherView's left/top edge to its contents. | 31 // Padding space in pixels between LauncherView's left/top edge to its contents. |
| 31 const int kLauncherViewLeadingInset = 8; | 32 const int kLauncherViewLeadingInset = 8; |
| 32 | 33 |
| 33 // Gets arrow location based on shelf alignment. | |
| 34 views::BubbleBorder::ArrowLocation GetBubbleArrowLocation( | |
| 35 ShelfAlignment shelf_alignment) { | |
| 36 switch (shelf_alignment) { | |
| 37 case ash::SHELF_ALIGNMENT_BOTTOM: | |
| 38 return views::BubbleBorder::BOTTOM_LEFT; | |
| 39 case ash::SHELF_ALIGNMENT_LEFT: | |
| 40 return views::BubbleBorder::LEFT_TOP; | |
| 41 case ash::SHELF_ALIGNMENT_RIGHT: | |
| 42 return views::BubbleBorder::RIGHT_TOP; | |
| 43 default: | |
| 44 NOTREACHED() << "Unknown shelf alignment " << shelf_alignment; | |
| 45 return views::BubbleBorder::BOTTOM_LEFT; | |
| 46 } | |
| 47 } | |
| 48 | |
| 49 //////////////////////////////////////////////////////////////////////////////// | 34 //////////////////////////////////////////////////////////////////////////////// |
| 50 // OverflowBubbleView | 35 // OverflowBubbleView |
| 51 // OverflowBubbleView hosts a LauncherView to display overflown items. | 36 // OverflowBubbleView hosts a LauncherView to display overflown items. |
| 52 | 37 |
| 53 class OverflowBubbleView : public views::BubbleDelegateView { | 38 class OverflowBubbleView : public views::BubbleDelegateView { |
| 54 public: | 39 public: |
| 55 OverflowBubbleView(); | 40 OverflowBubbleView(); |
| 56 virtual ~OverflowBubbleView(); | 41 virtual ~OverflowBubbleView(); |
| 57 | 42 |
| 58 void InitOverflowBubble(LauncherDelegate* delegate, | 43 void InitOverflowBubble(LauncherDelegate* delegate, |
| 59 LauncherModel* model, | 44 LauncherModel* model, |
| 60 views::View* anchor, | 45 views::View* anchor, |
| 61 ShelfAlignment shelf_alignment, | |
| 62 int overflow_start_index); | 46 int overflow_start_index); |
| 63 | 47 |
| 64 private: | 48 private: |
| 65 bool is_horizontal_alignment() const { | 49 bool IsHorizontalAlignment() const { |
| 66 return shelf_alignment_ == SHELF_ALIGNMENT_BOTTOM; | 50 return GetShelfLayoutManagerForLauncher()->IsHorizontalAlignment(); |
| 67 } | 51 } |
| 68 | 52 |
| 69 const gfx::Size GetContentsSize() const { | 53 const gfx::Size GetContentsSize() const { |
| 70 return static_cast<views::View*>(launcher_view_)->GetPreferredSize(); | 54 return static_cast<views::View*>(launcher_view_)->GetPreferredSize(); |
| 71 } | 55 } |
| 72 | 56 |
| 57 // Gets arrow location based on shelf alignment. |
| 58 views::BubbleBorder::ArrowLocation GetBubbleArrowLocation() const { |
| 59 return GetShelfLayoutManagerForLauncher()->SelectValueForShelfAlignment( |
| 60 views::BubbleBorder::BOTTOM_LEFT, |
| 61 views::BubbleBorder::LEFT_TOP, |
| 62 views::BubbleBorder::RIGHT_TOP); |
| 63 } |
| 64 |
| 73 void ScrollByXOffset(int x_offset); | 65 void ScrollByXOffset(int x_offset); |
| 74 void ScrollByYOffset(int y_offset); | 66 void ScrollByYOffset(int y_offset); |
| 75 | 67 |
| 76 // views::View overrides: | 68 // views::View overrides: |
| 77 virtual gfx::Size GetPreferredSize() OVERRIDE; | 69 virtual gfx::Size GetPreferredSize() OVERRIDE; |
| 78 virtual void Layout() OVERRIDE; | 70 virtual void Layout() OVERRIDE; |
| 79 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; | 71 virtual void ChildPreferredSizeChanged(views::View* child) OVERRIDE; |
| 80 virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE; | 72 virtual bool OnMouseWheel(const ui::MouseWheelEvent& event) OVERRIDE; |
| 81 | 73 |
| 82 // ui::EventHandler overrides: | 74 // ui::EventHandler overrides: |
| 83 virtual ui::EventResult OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; | 75 virtual ui::EventResult OnScrollEvent(ui::ScrollEvent* event) OVERRIDE; |
| 84 | 76 |
| 85 // views::BubbleDelegate overrides: | 77 // views::BubbleDelegate overrides: |
| 86 virtual gfx::Rect GetBubbleBounds() OVERRIDE; | 78 virtual gfx::Rect GetBubbleBounds() OVERRIDE; |
| 87 | 79 |
| 88 ShelfAlignment shelf_alignment_; | 80 ShelfLayoutManager* GetShelfLayoutManagerForLauncher() const { |
| 81 return ShelfLayoutManager::ForLauncher( |
| 82 anchor_view()->GetWidget()->GetNativeView()); |
| 83 } |
| 84 |
| 89 LauncherView* launcher_view_; // Owned by views hierarchy. | 85 LauncherView* launcher_view_; // Owned by views hierarchy. |
| 90 gfx::Vector2d scroll_offset_; | 86 gfx::Vector2d scroll_offset_; |
| 91 | 87 |
| 92 DISALLOW_COPY_AND_ASSIGN(OverflowBubbleView); | 88 DISALLOW_COPY_AND_ASSIGN(OverflowBubbleView); |
| 93 }; | 89 }; |
| 94 | 90 |
| 95 OverflowBubbleView::OverflowBubbleView() | 91 OverflowBubbleView::OverflowBubbleView() |
| 96 : shelf_alignment_(SHELF_ALIGNMENT_BOTTOM), | 92 : launcher_view_(NULL) { |
| 97 launcher_view_(NULL) { | |
| 98 } | 93 } |
| 99 | 94 |
| 100 OverflowBubbleView::~OverflowBubbleView() { | 95 OverflowBubbleView::~OverflowBubbleView() { |
| 101 } | 96 } |
| 102 | 97 |
| 103 void OverflowBubbleView::InitOverflowBubble(LauncherDelegate* delegate, | 98 void OverflowBubbleView::InitOverflowBubble(LauncherDelegate* delegate, |
| 104 LauncherModel* model, | 99 LauncherModel* model, |
| 105 views::View* anchor, | 100 views::View* anchor, |
| 106 ShelfAlignment shelf_alignment, | |
| 107 int overflow_start_index) { | 101 int overflow_start_index) { |
| 108 shelf_alignment_ = shelf_alignment; | |
| 109 | |
| 110 // Makes bubble view has a layer and clip its children layers. | 102 // Makes bubble view has a layer and clip its children layers. |
| 111 SetPaintToLayer(true); | 103 SetPaintToLayer(true); |
| 112 SetFillsBoundsOpaquely(false); | 104 SetFillsBoundsOpaquely(false); |
| 113 layer()->SetMasksToBounds(true); | 105 layer()->SetMasksToBounds(true); |
| 106 ShelfAlignment shelf_alignment = GetShelfLayoutManagerForLauncher()-> |
| 107 GetAlignment(); |
| 114 | 108 |
| 115 launcher_view_ = new LauncherView(model, delegate, NULL); | 109 launcher_view_ = new LauncherView(model, delegate, NULL); |
| 116 launcher_view_->set_first_visible_index(overflow_start_index); | 110 launcher_view_->set_first_visible_index(overflow_start_index); |
| 117 launcher_view_->set_leading_inset(kLauncherViewLeadingInset); | 111 launcher_view_->set_leading_inset(kLauncherViewLeadingInset); |
| 118 launcher_view_->Init(); | 112 launcher_view_->Init(); |
| 119 launcher_view_->SetAlignment(shelf_alignment); | 113 launcher_view_->SetAlignment(shelf_alignment); |
| 120 AddChildView(launcher_view_); | 114 AddChildView(launcher_view_); |
| 121 | 115 |
| 122 set_anchor_view(anchor); | 116 set_anchor_view(anchor); |
| 123 set_arrow_location(GetBubbleArrowLocation(shelf_alignment)); | 117 set_arrow_location(GetBubbleArrowLocation()); |
| 124 set_background(NULL); | 118 set_background(NULL); |
| 125 set_color(SkColorSetARGB(kLauncherBackgroundAlpha, 0, 0, 0)); | 119 set_color(SkColorSetARGB(kLauncherBackgroundAlpha, 0, 0, 0)); |
| 126 set_margins(gfx::Insets(kPadding, kPadding, kPadding, kPadding)); | 120 set_margins(gfx::Insets(kPadding, kPadding, kPadding, kPadding)); |
| 127 set_move_with_anchor(true); | 121 set_move_with_anchor(true); |
| 128 views::BubbleDelegateView::CreateBubble(this); | 122 views::BubbleDelegateView::CreateBubble(this); |
| 129 } | 123 } |
| 130 | 124 |
| 131 void OverflowBubbleView::ScrollByXOffset(int x_offset) { | 125 void OverflowBubbleView::ScrollByXOffset(int x_offset) { |
| 132 const gfx::Rect visible_bounds(GetContentsBounds()); | 126 const gfx::Rect visible_bounds(GetContentsBounds()); |
| 133 const gfx::Size contents_size(GetContentsSize()); | 127 const gfx::Size contents_size(GetContentsSize()); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 145 std::max(0, scroll_offset_.y() + y_offset)); | 139 std::max(0, scroll_offset_.y() + y_offset)); |
| 146 scroll_offset_.set_y(y); | 140 scroll_offset_.set_y(y); |
| 147 } | 141 } |
| 148 | 142 |
| 149 gfx::Size OverflowBubbleView::GetPreferredSize() { | 143 gfx::Size OverflowBubbleView::GetPreferredSize() { |
| 150 gfx::Size preferred_size = GetContentsSize(); | 144 gfx::Size preferred_size = GetContentsSize(); |
| 151 | 145 |
| 152 const gfx::Rect monitor_rect = Shell::GetScreen()->GetDisplayNearestPoint( | 146 const gfx::Rect monitor_rect = Shell::GetScreen()->GetDisplayNearestPoint( |
| 153 GetAnchorRect().CenterPoint()).work_area(); | 147 GetAnchorRect().CenterPoint()).work_area(); |
| 154 if (!monitor_rect.IsEmpty()) { | 148 if (!monitor_rect.IsEmpty()) { |
| 155 if (is_horizontal_alignment()) { | 149 if (IsHorizontalAlignment()) { |
| 156 preferred_size.set_width(std::min( | 150 preferred_size.set_width(std::min( |
| 157 preferred_size.width(), | 151 preferred_size.width(), |
| 158 static_cast<int>(monitor_rect.width() * | 152 static_cast<int>(monitor_rect.width() * |
| 159 kMaxBubbleSizeToScreenRatio))); | 153 kMaxBubbleSizeToScreenRatio))); |
| 160 } else { | 154 } else { |
| 161 preferred_size.set_height(std::min( | 155 preferred_size.set_height(std::min( |
| 162 preferred_size.height(), | 156 preferred_size.height(), |
| 163 static_cast<int>(monitor_rect.height() * | 157 static_cast<int>(monitor_rect.height() * |
| 164 kMaxBubbleSizeToScreenRatio))); | 158 kMaxBubbleSizeToScreenRatio))); |
| 165 } | 159 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 176 void OverflowBubbleView::ChildPreferredSizeChanged(views::View* child) { | 170 void OverflowBubbleView::ChildPreferredSizeChanged(views::View* child) { |
| 177 // Ensures |launch_view_| is still visible. | 171 // Ensures |launch_view_| is still visible. |
| 178 ScrollByXOffset(0); | 172 ScrollByXOffset(0); |
| 179 ScrollByYOffset(0); | 173 ScrollByYOffset(0); |
| 180 Layout(); | 174 Layout(); |
| 181 | 175 |
| 182 SizeToContents(); | 176 SizeToContents(); |
| 183 } | 177 } |
| 184 | 178 |
| 185 bool OverflowBubbleView::OnMouseWheel(const ui::MouseWheelEvent& event) { | 179 bool OverflowBubbleView::OnMouseWheel(const ui::MouseWheelEvent& event) { |
| 186 if (is_horizontal_alignment()) | 180 if (IsHorizontalAlignment()) |
| 187 ScrollByXOffset(-event.offset()); | 181 ScrollByXOffset(-event.offset()); |
| 188 else | 182 else |
| 189 ScrollByYOffset(-event.offset()); | 183 ScrollByYOffset(-event.offset()); |
| 190 Layout(); | 184 Layout(); |
| 191 | 185 |
| 192 return true; | 186 return true; |
| 193 } | 187 } |
| 194 | 188 |
| 195 ui::EventResult OverflowBubbleView::OnScrollEvent(ui::ScrollEvent* event) { | 189 ui::EventResult OverflowBubbleView::OnScrollEvent(ui::ScrollEvent* event) { |
| 196 ScrollByXOffset(-event->x_offset()); | 190 ScrollByXOffset(-event->x_offset()); |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 : bubble_(NULL) { | 244 : bubble_(NULL) { |
| 251 } | 245 } |
| 252 | 246 |
| 253 OverflowBubble::~OverflowBubble() { | 247 OverflowBubble::~OverflowBubble() { |
| 254 Hide(); | 248 Hide(); |
| 255 } | 249 } |
| 256 | 250 |
| 257 void OverflowBubble::Show(LauncherDelegate* delegate, | 251 void OverflowBubble::Show(LauncherDelegate* delegate, |
| 258 LauncherModel* model, | 252 LauncherModel* model, |
| 259 views::View* anchor, | 253 views::View* anchor, |
| 260 ShelfAlignment shelf_alignment, | |
| 261 int overflow_start_index) { | 254 int overflow_start_index) { |
| 262 Hide(); | 255 Hide(); |
| 263 | 256 |
| 264 OverflowBubbleView* bubble_view = new OverflowBubbleView(); | 257 OverflowBubbleView* bubble_view = new OverflowBubbleView(); |
| 265 bubble_view->InitOverflowBubble(delegate, | 258 bubble_view->InitOverflowBubble(delegate, |
| 266 model, | 259 model, |
| 267 anchor, | 260 anchor, |
| 268 shelf_alignment, | |
| 269 overflow_start_index); | 261 overflow_start_index); |
| 270 | 262 |
| 271 bubble_ = bubble_view; | 263 bubble_ = bubble_view; |
| 272 ash::Shell::GetInstance()->system_tray()->InitializeBubbleAnimations( | 264 ash::Shell::GetInstance()->system_tray()->InitializeBubbleAnimations( |
| 273 bubble_->GetWidget()); | 265 bubble_->GetWidget()); |
| 274 bubble_->GetWidget()->AddObserver(this); | 266 bubble_->GetWidget()->AddObserver(this); |
| 275 bubble_->GetWidget()->Show(); | 267 bubble_->GetWidget()->Show(); |
| 276 } | 268 } |
| 277 | 269 |
| 278 void OverflowBubble::Hide() { | 270 void OverflowBubble::Hide() { |
| 279 if (!IsShowing()) | 271 if (!IsShowing()) |
| 280 return; | 272 return; |
| 281 | 273 |
| 282 bubble_->GetWidget()->RemoveObserver(this); | 274 bubble_->GetWidget()->RemoveObserver(this); |
| 283 bubble_->GetWidget()->Close(); | 275 bubble_->GetWidget()->Close(); |
| 284 bubble_ = NULL; | 276 bubble_ = NULL; |
| 285 } | 277 } |
| 286 | 278 |
| 287 void OverflowBubble::OnWidgetClosing(views::Widget* widget) { | 279 void OverflowBubble::OnWidgetClosing(views::Widget* widget) { |
| 288 DCHECK(widget == bubble_->GetWidget()); | 280 DCHECK(widget == bubble_->GetWidget()); |
| 289 bubble_ = NULL; | 281 bubble_ = NULL; |
| 290 } | 282 } |
| 291 | 283 |
| 292 } // namespace internal | 284 } // namespace internal |
| 293 } // namespace ash | 285 } // namespace ash |
| OLD | NEW |