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
3 // found in the LICENSE file.
5 #ifndef ASH_SHELF_SHELF_VIEW_H_
6 #define ASH_SHELF_SHELF_VIEW_H_
12 #include "ash/shelf/shelf_button_host.h"
13 #include "ash/shelf/shelf_item_delegate.h"
14 #include "ash/shelf/shelf_model_observer.h"
15 #include "ash/wm/gestures/shelf_gesture_handler.h"
16 #include "base/observer_list.h"
17 #include "ui/app_list/views/app_list_drag_and_drop_host.h"
18 #include "ui/views/animation/bounds_animator_observer.h"
19 #include "ui/views/context_menu_controller.h"
20 #include "ui/views/controls/button/button.h"
21 #include "ui/views/focus/focus_manager.h"
22 #include "ui/views/view.h"
23 #include "ui/views/view_model.h"
36 class ShelfIconObserver
;
37 class ShelfItemDelegateManager
;
44 class ShelfLayoutManager
;
45 class ShelfTooltipManager
;
48 class ShelfViewTestAPI
;
51 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM
;
52 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT
;
53 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT
;
54 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT
;
56 class ASH_EXPORT ShelfView
: public views::View
,
57 public ShelfModelObserver
,
58 public views::ButtonListener
,
59 public ShelfButtonHost
,
60 public views::ContextMenuController
,
61 public views::FocusTraversable
,
62 public views::BoundsAnimatorObserver
,
63 public app_list::ApplicationDragAndDropHost
{
65 ShelfView(ShelfModel
* model
,
66 ShelfDelegate
* delegate
,
67 ShelfLayoutManager
* manager
);
68 ~ShelfView() override
;
70 ShelfTooltipManager
* tooltip_manager() { return tooltip_
.get(); }
72 ShelfLayoutManager
* shelf_layout_manager() { return layout_manager_
; }
74 ShelfModel
* model() { return model_
; }
78 void OnShelfAlignmentChanged();
79 void SchedulePaintForAllButtons();
81 // Returns the ideal bounds of the specified item, or an empty rect if id
82 // isn't know. If the item is in an overflow shelf, the overflow icon location
84 gfx::Rect
GetIdealBoundsOfItemIcon(ShelfID id
);
86 // Repositions the icon for the specified item by the midpoint of the window.
87 void UpdatePanelIconPosition(ShelfID id
, const gfx::Point
& midpoint
);
89 void AddIconObserver(ShelfIconObserver
* observer
);
90 void RemoveIconObserver(ShelfIconObserver
* observer
);
92 // Returns true if we're showing a menu.
93 bool IsShowingMenu() const;
95 // Returns true if overflow bubble is shown.
96 bool IsShowingOverflowBubble() const;
98 // Sets owner overflow bubble instance from which this shelf view pops
100 void set_owner_overflow_bubble(OverflowBubble
* owner
) {
101 owner_overflow_bubble_
= owner
;
104 views::View
* GetAppListButtonView() const;
106 // Returns true if the mouse cursor exits the area for launcher tooltip.
107 // There are thin gaps between launcher buttons but the tooltip shouldn't hide
108 // in the gaps, but the tooltip should hide if the mouse moved totally outside
109 // of the buttons area.
110 bool ShouldHideTooltip(const gfx::Point
& cursor_location
);
112 // Returns rectangle bounding all visible launcher items. Used screen
113 // coordinate system.
114 gfx::Rect
GetVisibleItemsBoundsInScreen();
116 // Overridden from FocusTraversable:
117 views::FocusSearch
* GetFocusSearch() override
;
118 FocusTraversable
* GetFocusTraversableParent() override
;
119 View
* GetFocusTraversableParentView() override
;
121 // Overridden from app_list::ApplicationDragAndDropHost:
122 void CreateDragIconProxy(const gfx::Point
& location_in_screen_coordinates
,
123 const gfx::ImageSkia
& icon
,
124 views::View
* replaced_view
,
125 const gfx::Vector2d
& cursor_offset_from_center
,
126 float scale_factor
) override
;
127 void UpdateDragIconProxy(
128 const gfx::Point
& location_in_screen_coordinates
) override
;
129 void DestroyDragIconProxy() override
;
130 bool StartDrag(const std::string
& app_id
,
131 const gfx::Point
& location_in_screen_coordinates
) override
;
132 bool Drag(const gfx::Point
& location_in_screen_coordinates
) override
;
133 void EndDrag(bool cancel
) override
;
135 // Return the view model for test purposes.
136 const views::ViewModel
* view_model_for_test() const {
137 return view_model_
.get();
141 friend class ash::test::ShelfViewTestAPI
;
143 class FadeOutAnimationDelegate
;
144 class StartFadeAnimationDelegate
;
147 gfx::Rect overflow_bounds
;
150 enum RemovableState
{
151 REMOVABLE
, // Item can be removed when dragged away.
152 DRAGGABLE
, // Item can be dragged, but will snap always back to origin.
153 NOT_REMOVABLE
, // Item is fixed and can never be removed.
156 // Returns true when this ShelfView is used for Overflow Bubble.
157 // In this mode, it does not show app list, panel and overflow button.
159 // * When Shelf can contain only one item (overflow button) due to very
160 // small resolution screen, overflow bubble can show app list and panel
162 bool is_overflow_mode() const { return overflow_mode_
; }
164 bool dragging() const {
165 return drag_pointer_
!= NONE
;
168 // Sets the bounds of each view to its ideal bounds.
169 void LayoutToIdealBounds();
171 // Update all button's visibility in overflow.
172 void UpdateAllButtonsVisibilityInOverflowMode();
174 // Calculates the ideal bounds. The bounds of each button corresponding to an
175 // item in the model is set in |view_model_|.
176 void CalculateIdealBounds(IdealBounds
* bounds
) const;
178 // Returns the index of the last view whose max primary axis coordinate is
179 // less than |max_value|. Returns -1 if nothing fits, or there are no views.
180 int DetermineLastVisibleIndex(int max_value
) const;
182 // Returns the index of the first panel whose min primary axis coordinate is
183 // at least |min_value|. Returns the index past the last panel if none fit.
184 int DetermineFirstVisiblePanelIndex(int min_value
) const;
186 // Animates the bounds of each view to its ideal bounds.
187 void AnimateToIdealBounds();
189 // Creates the view used to represent |item|.
190 views::View
* CreateViewForItem(const ShelfItem
& item
);
192 // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
193 void FadeIn(views::View
* view
);
195 // Invoked when the pointer has moved enough to trigger a drag. Sets
196 // internal state in preparation for the drag.
197 void PrepareForDrag(Pointer pointer
, const ui::LocatedEvent
& event
);
199 // Invoked when the mouse is dragged. Updates the models as appropriate.
200 void ContinueDrag(const ui::LocatedEvent
& event
);
202 // Handles ripping off an item from the shelf. Returns true when the item got
204 bool HandleRipOffDrag(const ui::LocatedEvent
& event
);
206 // Finalize the rip off dragging by either |cancel| the action or validating.
207 void FinalizeRipOffDrag(bool cancel
);
209 // Check if an item can be ripped off or not.
210 RemovableState
RemovableByRipOff(int index
) const;
212 // Returns true if |typea| and |typeb| should be in the same drag range.
213 bool SameDragType(ShelfItemType typea
, ShelfItemType typeb
) const;
215 // Returns the range (in the model) the item at the specified index can be
217 std::pair
<int, int> GetDragRange(int index
);
219 // If there is a drag operation in progress it's canceled. If |modified_index|
220 // is valid, the new position of the corresponding item is returned.
221 int CancelDrag(int modified_index
);
223 // Returns rectangle bounds used for drag insertion.
225 // * When overflow button is visible, returns bounds from first item
226 // to overflow button.
227 // * When overflow button is visible and one or more panel items exists,
228 // returns bounds from first item to last panel item.
229 // * In the overflow mode, returns only bubble's bounds.
230 gfx::Rect
GetBoundsForDragInsertInScreen();
232 // Common setup done for all children.
233 void ConfigureChildView(views::View
* view
);
235 // Toggles the overflow menu.
236 void ToggleOverflowBubble();
238 // Invoked after the fading out animation for item deletion is ended.
239 void OnFadeOutAnimationEnded();
241 // Fade in last visible item.
242 void StartFadeInLastVisibleItem();
244 // Updates the visible range of overflow items in |overflow_view|.
245 void UpdateOverflowRange(ShelfView
* overflow_view
) const;
247 // Overridden from views::View:
248 gfx::Size
GetPreferredSize() const override
;
249 void OnBoundsChanged(const gfx::Rect
& previous_bounds
) override
;
250 FocusTraversable
* GetPaneFocusTraversable() override
;
251 void GetAccessibleState(ui::AXViewState
* state
) override
;
253 // Overridden from ui::EventHandler:
254 void OnGestureEvent(ui::GestureEvent
* event
) override
;
256 // Overridden from ShelfModelObserver:
257 void ShelfItemAdded(int model_index
) override
;
258 void ShelfItemRemoved(int model_index
, ShelfID id
) override
;
259 void ShelfItemChanged(int model_index
, const ShelfItem
& old_item
) override
;
260 void ShelfItemMoved(int start_index
, int target_index
) override
;
261 void ShelfStatusChanged() override
;
263 // Overridden from ShelfButtonHost:
264 void PointerPressedOnButton(views::View
* view
,
266 const ui::LocatedEvent
& event
) override
;
267 void PointerDraggedOnButton(views::View
* view
,
269 const ui::LocatedEvent
& event
) override
;
270 void PointerReleasedOnButton(views::View
* view
,
272 bool canceled
) override
;
273 void MouseMovedOverButton(views::View
* view
) override
;
274 void MouseEnteredButton(views::View
* view
) override
;
275 void MouseExitedButton(views::View
* view
) override
;
276 base::string16
GetAccessibleName(const views::View
* view
) override
;
278 // Overridden from views::ButtonListener:
279 void ButtonPressed(views::Button
* sender
, const ui::Event
& event
) override
;
281 // Records UMA statistics for the input source when an icon was activated.
282 void RecordIconActivatedSource(const ui::Event
& event
);
284 // Records UMA statistics for the action performed by activating an icon.
285 void RecordIconActivatedAction(
286 ShelfItemDelegate::PerformedAction performed_action
);
288 // Show the list of all running items for this |item|. It will return true
289 // when the menu was shown and false if there were no possible items to
290 // choose from. |source| specifies the view which is responsible for showing
291 // the menu, and the bubble will point towards it.
292 // The |event_flags| are the flags of the event which triggered this menu.
293 bool ShowListMenuForView(const ShelfItem
& item
,
295 const ui::Event
& event
);
297 // Overridden from views::ContextMenuController:
298 void ShowContextMenuForView(views::View
* source
,
299 const gfx::Point
& point
,
300 ui::MenuSourceType source_type
) override
;
302 // Show either a context or normal click menu of given |menu_model|.
303 // If |context_menu| is set, the displayed menu is a context menu and not
304 // a menu listing one or more running applications.
305 // The |click_point| is only used for |context_menu|'s.
306 void ShowMenu(ui::MenuModel
* menu_model
,
308 const gfx::Point
& click_point
,
310 ui::MenuSourceType source_type
);
312 // Overridden from views::BoundsAnimatorObserver:
313 void OnBoundsAnimatorProgressed(views::BoundsAnimator
* animator
) override
;
314 void OnBoundsAnimatorDone(views::BoundsAnimator
* animator
) override
;
316 // Returns true if the (press down) |event| is a repost event from an event
317 // which just closed the menu of a shelf item. If it occurs on the same shelf
318 // item, we should ignore the call.
319 bool IsRepostEvent(const ui::Event
& event
);
321 // Convenience accessor to model_->items().
322 const ShelfItem
* ShelfItemForView(const views::View
* view
) const;
324 // Returns true if a tooltip should be shown for |view|.
325 bool ShouldShowTooltipForView(const views::View
* view
) const;
327 // Get the distance from the given |coordinate| to the closest point on this
329 int CalculateShelfDistance(const gfx::Point
& coordinate
) const;
331 // The model; owned by Launcher.
334 // Delegate; owned by Launcher.
335 ShelfDelegate
* delegate_
;
337 // Used to manage the set of active launcher buttons. There is a view per
339 scoped_ptr
<views::ViewModel
> view_model_
;
341 // Index of first visible launcher item.
342 int first_visible_index_
;
344 // Last index of a launcher button that is visible
345 // (does not go into overflow).
346 mutable int last_visible_index_
;
348 scoped_ptr
<views::BoundsAnimator
> bounds_animator_
;
350 OverflowButton
* overflow_button_
;
352 scoped_ptr
<OverflowBubble
> overflow_bubble_
;
354 OverflowBubble
* owner_overflow_bubble_
;
356 scoped_ptr
<ShelfTooltipManager
> tooltip_
;
358 // Pointer device that initiated the current drag operation. If there is no
359 // current dragging operation, this is NONE.
360 Pointer drag_pointer_
;
362 // The view being dragged. This is set immediately when the mouse is pressed.
363 // |dragging_| is set only if the mouse is dragged far enough.
364 ShelfButton
* drag_view_
;
366 // Position of the mouse down event in |drag_view_|'s coordinates.
367 gfx::Point drag_origin_
;
369 // Index |drag_view_| was initially at.
370 int start_drag_index_
;
372 // Used for the context menu of a particular item.
373 ShelfID context_menu_id_
;
375 scoped_ptr
<views::FocusSearch
> focus_search_
;
377 scoped_ptr
<ui::MenuModel
> context_menu_model_
;
379 scoped_ptr
<views::MenuRunner
> launcher_menu_runner_
;
381 ObserverList
<ShelfIconObserver
> observers_
;
383 // Amount content is inset on the left edge (or top edge for vertical
387 ShelfGestureHandler gesture_handler_
;
389 // True when an item being inserted or removed in the model cancels a drag.
390 bool cancelling_drag_model_changed_
;
392 // Index of the last hidden launcher item. If there are no hidden items this
393 // will be equal to last_visible_index_ + 1.
394 mutable int last_hidden_index_
;
396 // The timestamp of the event which closed the last menu - or 0.
397 base::TimeDelta closing_event_time_
;
399 // When this object gets deleted while a menu is shown, this pointed
400 // element will be set to false.
403 // True if a drag and drop operation created/pinned the item in the launcher
404 // and it needs to be deleted/unpinned again if the operation gets cancelled.
405 bool drag_and_drop_item_pinned_
;
407 // The ShelfItem which is currently used for a drag and a drop operation
409 ShelfID drag_and_drop_shelf_id_
;
411 // The application ID of the application which we drag and drop.
412 std::string drag_and_drop_app_id_
;
414 // The original launcher item's size before the dragging operation.
415 gfx::Size pre_drag_and_drop_size_
;
417 // The image proxy for drag operations when a drag and drop host exists and
418 // the item can be dragged outside the app grid.
419 scoped_ptr
<ash::DragImageView
> drag_image_
;
421 // The cursor offset to the middle of the dragged item.
422 gfx::Vector2d drag_image_offset_
;
424 // The view which gets replaced by our drag icon proxy.
425 views::View
* drag_replaced_view_
;
427 // True when the icon was dragged off the shelf.
428 bool dragged_off_shelf_
;
430 // The rip off view when a snap back operation is underway.
431 views::View
* snap_back_from_rip_off_view_
;
433 // Holds ShelfItemDelegateManager.
434 ShelfItemDelegateManager
* item_manager_
;
436 // Holds ShelfLayoutManager.
437 ShelfLayoutManager
* layout_manager_
;
439 // True when this ShelfView is used for Overflow Bubble.
442 // Holds a pointer to main ShelfView when a ShelfView is in overflow mode.
443 ShelfView
* main_shelf_
;
445 // True when ripped item from overflow bubble is entered into Shelf.
446 bool dragged_off_from_overflow_to_shelf_
;
448 // True if the event is a repost event from a event which has just closed the
449 // menu of the same shelf item.
450 bool is_repost_event_
;
452 // Record the index for the last pressed shelf item. This variable is used to
453 // check if a repost event occurs on the same shelf item as previous one. If
454 // so, the repost event should be ignored.
455 int last_pressed_index_
;
457 DISALLOW_COPY_AND_ASSIGN(ShelfView
);
462 #endif // ASH_SHELF_SHELF_VIEW_H_