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_
11 #include "ash/launcher/launcher_button_host.h"
12 #include "ash/launcher/launcher_model_observer.h"
13 #include "ash/wm/gestures/shelf_gesture_handler.h"
14 #include "base/observer_list.h"
15 #include "ui/app_list/views/app_list_drag_and_drop_host.h"
16 #include "ui/views/animation/bounds_animator_observer.h"
17 #include "ui/views/context_menu_controller.h"
18 #include "ui/views/controls/button/button.h"
19 #include "ui/views/focus/focus_manager.h"
20 #include "ui/views/view.h"
24 class MenuModelAdapter;
32 class ShelfViewTestAPI;
35 class LauncherDelegate;
37 class LauncherItemDelegateManager;
39 class ShelfIconObserver;
47 class ShelfLayoutManager;
48 class ShelfTooltipManager;
50 class ASH_EXPORT ShelfView : public views::View,
51 public LauncherModelObserver,
52 public views::ButtonListener,
53 public LauncherButtonHost,
54 public views::ContextMenuController,
55 public views::FocusTraversable,
56 public views::BoundsAnimatorObserver,
57 public app_list::ApplicationDragAndDropHost {
59 ShelfView(LauncherModel* model,
60 LauncherDelegate* delegate,
61 ShelfLayoutManager* shelf_layout_manager);
64 ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
66 ShelfLayoutManager* shelf_layout_manager() { return layout_manager_; }
68 LauncherModel* model() { return model_; }
72 void OnShelfAlignmentChanged();
73 void SchedulePaintForAllButtons();
75 // Returns the ideal bounds of the specified item, or an empty rect if id
77 gfx::Rect GetIdealBoundsOfItemIcon(LauncherID id);
79 // Repositions the icon for the specified item by the midpoint of the window.
80 void UpdatePanelIconPosition(LauncherID id, const gfx::Point& midpoint);
82 void AddIconObserver(ShelfIconObserver* observer);
83 void RemoveIconObserver(ShelfIconObserver* observer);
85 // Returns true if we're showing a menu.
86 bool IsShowingMenu() const;
88 // Returns true if overflow bubble is shown.
89 bool IsShowingOverflowBubble() const;
91 // Sets owner overflow bubble instance from which this shelf view pops
93 void set_owner_overflow_bubble(OverflowBubble* owner) {
94 owner_overflow_bubble_ = owner;
97 views::View* GetAppListButtonView() const;
99 // Returns true if the mouse cursor exits the area for launcher tooltip.
100 // There are thin gaps between launcher buttons but the tooltip shouldn't hide
101 // in the gaps, but the tooltip should hide if the mouse moved totally outside
102 // of the buttons area.
103 bool ShouldHideTooltip(const gfx::Point& cursor_location);
105 // Returns rectangle bounding all visible launcher items. Used screen
106 // coordinate system.
107 gfx::Rect GetVisibleItemsBoundsInScreen();
109 // Overridden from FocusTraversable:
110 virtual views::FocusSearch* GetFocusSearch() OVERRIDE;
111 virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE;
112 virtual View* GetFocusTraversableParentView() OVERRIDE;
114 // Overridden from app_list::ApplicationDragAndDropHost:
115 virtual void CreateDragIconProxy(
116 const gfx::Point& location_in_screen_coordinates,
117 const gfx::ImageSkia& icon,
118 views::View* replaced_view,
119 const gfx::Vector2d& cursor_offset_from_center,
120 float scale_factor) OVERRIDE;
121 virtual void UpdateDragIconProxy(
122 const gfx::Point& location_in_screen_coordinates) OVERRIDE;
123 virtual void DestroyDragIconProxy() OVERRIDE;
124 virtual bool StartDrag(
125 const std::string& app_id,
126 const gfx::Point& location_in_screen_coordinates) OVERRIDE;
127 virtual bool Drag(const gfx::Point& location_in_screen_coordinates) OVERRIDE;
128 virtual void EndDrag(bool cancel) OVERRIDE;
130 // Return the view model for test purposes.
131 const views::ViewModel* const view_model_for_test() const {
132 return view_model_.get();
136 friend class ash::test::ShelfViewTestAPI;
138 class FadeOutAnimationDelegate;
139 class StartFadeAnimationDelegate;
142 gfx::Rect overflow_bounds;
145 enum RemovableState {
146 REMOVABLE, // Item can be removed when dragged away.
147 DRAGGABLE, // Item can be dragged, but will snap always back to origin.
148 NOT_REMOVABLE, // Item is fixed and can never be removed.
151 bool is_overflow_mode() const {
152 return first_visible_index_ > 0;
155 bool dragging() const {
156 return drag_pointer_ != NONE;
159 // Sets the bounds of each view to its ideal bounds.
160 void LayoutToIdealBounds();
162 // Calculates the ideal bounds. The bounds of each button corresponding to an
163 // item in the model is set in |view_model_|.
164 void CalculateIdealBounds(IdealBounds* bounds);
166 // Returns the index of the last view whose max primary axis coordinate is
167 // less than |max_value|. Returns -1 if nothing fits, or there are no views.
168 int DetermineLastVisibleIndex(int max_value) const;
170 // Returns the index of the first panel whose min primary axis coordinate is
171 // at least |min_value|. Returns the index past the last panel if none fit.
172 int DetermineFirstVisiblePanelIndex(int min_value) const;
174 // Animates the bounds of each view to its ideal bounds.
175 void AnimateToIdealBounds();
177 // Creates the view used to represent |item|.
178 views::View* CreateViewForItem(const LauncherItem& item);
180 // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
181 void FadeIn(views::View* view);
183 // Invoked when the pointer has moved enough to trigger a drag. Sets
184 // internal state in preparation for the drag.
185 void PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event);
187 // Invoked when the mouse is dragged. Updates the models as appropriate.
188 void ContinueDrag(const ui::LocatedEvent& event);
190 // Handles ripping off an item from the shelf. Returns true when the item got
192 bool HandleRipOffDrag(const ui::LocatedEvent& event);
194 // Finalize the rip off dragging by either |cancel| the action or validating.
195 void FinalizeRipOffDrag(bool cancel);
197 // Check if an item can be ripped off or not.
198 RemovableState RemovableByRipOff(int index);
200 // Returns true if |typea| and |typeb| should be in the same drag range.
201 bool SameDragType(LauncherItemType typea, LauncherItemType typeb) const;
203 // Returns the range (in the model) the item at the specified index can be
205 std::pair<int, int> GetDragRange(int index);
207 // If there is a drag operation in progress it's canceled. If |modified_index|
208 // is valid, the new position of the corresponding item is returned.
209 int CancelDrag(int modified_index);
211 // Common setup done for all children.
212 void ConfigureChildView(views::View* view);
214 // Toggles the overflow menu.
215 void ToggleOverflowBubble();
217 // Update first launcher button's padding. This method adds padding to the
218 // first button to include the leading inset. It needs to be called once on
219 // button creation and every time when shelf alignment is changed.
220 void UpdateFirstButtonPadding();
222 // Invoked after the fading out animation for item deletion is ended.
223 void OnFadeOutAnimationEnded();
225 // Fade in last visible item.
226 void StartFadeInLastVisibleItem();
228 // Updates the visible range of overflow items in |overflow_view|.
229 void UpdateOverflowRange(ShelfView* overflow_view);
231 // Overridden from views::View:
232 virtual gfx::Size GetPreferredSize() OVERRIDE;
233 virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
234 virtual FocusTraversable* GetPaneFocusTraversable() OVERRIDE;
235 virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
237 // Overridden from ui::EventHandler:
238 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
240 // Overridden from LauncherModelObserver:
241 virtual void LauncherItemAdded(int model_index) OVERRIDE;
242 virtual void LauncherItemRemoved(int model_index, LauncherID id) OVERRIDE;
243 virtual void LauncherItemChanged(int model_index,
244 const ash::LauncherItem& old_item) OVERRIDE;
245 virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
246 virtual void LauncherStatusChanged() OVERRIDE;
248 // Overridden from LauncherButtonHost:
249 virtual void PointerPressedOnButton(
252 const ui::LocatedEvent& event) OVERRIDE;
253 virtual void PointerDraggedOnButton(
256 const ui::LocatedEvent& event) OVERRIDE;
257 virtual void PointerReleasedOnButton(views::View* view,
259 bool canceled) OVERRIDE;
260 virtual void MouseMovedOverButton(views::View* view) OVERRIDE;
261 virtual void MouseEnteredButton(views::View* view) OVERRIDE;
262 virtual void MouseExitedButton(views::View* view) OVERRIDE;
263 virtual base::string16 GetAccessibleName(const views::View* view) OVERRIDE;
265 // Overridden from views::ButtonListener:
266 virtual void ButtonPressed(views::Button* sender,
267 const ui::Event& event) OVERRIDE;
269 // Show the list of all running items for this |item|. It will return true
270 // when the menu was shown and false if there were no possible items to
271 // choose from. |source| specifies the view which is responsible for showing
272 // the menu, and the bubble will point towards it.
273 // The |event_flags| are the flags of the event which triggered this menu.
274 bool ShowListMenuForView(const LauncherItem& item,
276 const ui::Event& event);
278 // Overridden from views::ContextMenuController:
279 virtual void ShowContextMenuForView(views::View* source,
280 const gfx::Point& point,
281 ui::MenuSourceType source_type) OVERRIDE;
283 // Show either a context or normal click menu of given |menu_model_adapter|.
284 // If |context_menu| is set, the displayed menu is a context menu and not
285 // a menu listing one or more running applications.
286 // The |click_point| is only used for |context_menu|'s.
287 void ShowMenu(scoped_ptr<views::MenuModelAdapter> menu_model_adapter,
289 const gfx::Point& click_point,
291 ui::MenuSourceType source_type);
293 // Overridden from views::BoundsAnimatorObserver:
294 virtual void OnBoundsAnimatorProgressed(
295 views::BoundsAnimator* animator) OVERRIDE;
296 virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE;
298 // Returns false if the click which closed the previous menu is the click
299 // which triggered this event.
300 bool IsUsableEvent(const ui::Event& event);
302 // Convenience accessor to model_->items().
303 const LauncherItem* LauncherItemForView(const views::View* view) const;
305 // Returns true if a tooltip should be shown for |view|.
306 bool ShouldShowTooltipForView(const views::View* view) const;
308 // Get the distance from the given |coordinate| to the closest point on this
310 int CalculateShelfDistance(const gfx::Point& coordinate) const;
312 // The model; owned by Launcher.
313 LauncherModel* model_;
315 // Delegate; owned by Launcher.
316 LauncherDelegate* delegate_;
318 // Used to manage the set of active launcher buttons. There is a view per
320 scoped_ptr<views::ViewModel> view_model_;
322 // Index of first visible launcher item. When it it greater than 0,
323 // ShelfView is hosted in an overflow bubble. In this mode, it does not
324 // show app list, panel, and overflow button.
325 int first_visible_index_;
327 // Last index of a launcher button that is visible
328 // (does not go into overflow).
329 int last_visible_index_;
331 scoped_ptr<views::BoundsAnimator> bounds_animator_;
333 OverflowButton* overflow_button_;
335 scoped_ptr<OverflowBubble> overflow_bubble_;
337 OverflowBubble* owner_overflow_bubble_;
339 scoped_ptr<ShelfTooltipManager> tooltip_;
341 // Pointer device that initiated the current drag operation. If there is no
342 // current dragging operation, this is NONE.
343 Pointer drag_pointer_;
345 // The view being dragged. This is set immediately when the mouse is pressed.
346 // |dragging_| is set only if the mouse is dragged far enough.
347 views::View* drag_view_;
349 // X coordinate of the mouse down event in |drag_view_|s coordinates.
352 // Index |drag_view_| was initially at.
353 int start_drag_index_;
355 // Used for the context menu of a particular item.
356 LauncherID context_menu_id_;
358 scoped_ptr<views::FocusSearch> focus_search_;
360 scoped_ptr<views::MenuRunner> launcher_menu_runner_;
362 ObserverList<ShelfIconObserver> observers_;
364 // Amount content is inset on the left edge (or top edge for vertical
368 ShelfGestureHandler gesture_handler_;
370 // True when an item being inserted or removed in the model cancels a drag.
371 bool cancelling_drag_model_changed_;
373 // Index of the last hidden launcher item. If there are no hidden items this
374 // will be equal to last_visible_index_ + 1.
375 int last_hidden_index_;
377 // The timestamp of the event which closed the last menu - or 0.
378 base::TimeDelta closing_event_time_;
380 // When this object gets deleted while a menu is shown, this pointed
381 // element will be set to false.
384 // True if a drag and drop operation created/pinned the item in the launcher
385 // and it needs to be deleted/unpinned again if the operation gets cancelled.
386 bool drag_and_drop_item_pinned_;
388 // The launcher item which is currently used for a drag and a drop operation
390 LauncherID drag_and_drop_launcher_id_;
392 // The application ID of the application which we drag and drop.
393 std::string drag_and_drop_app_id_;
395 // The original launcher item's size before the dragging operation.
396 gfx::Size pre_drag_and_drop_size_;
398 // The image proxy for drag operations when a drag and drop host exists and
399 // the item can be dragged outside the app grid.
400 scoped_ptr<ash::internal::DragImageView> drag_image_;
402 // The cursor offset to the middle of the dragged item.
403 gfx::Vector2d drag_image_offset_;
405 // The view which gets replaced by our drag icon proxy.
406 views::View* drag_replaced_view_;
408 // True when the icon was dragged off the shelf.
409 bool dragged_off_shelf_;
411 // The rip off view when a snap back operation is underway.
412 views::View* snap_back_from_rip_off_view_;
414 // Holds LauncherItemDelegateManager.
415 LauncherItemDelegateManager* item_manager_;
417 // Holds ShelfLayoutManager.
418 ShelfLayoutManager* layout_manager_;
420 DISALLOW_COPY_AND_ASSIGN(ShelfView);
423 } // namespace internal
426 #endif // ASH_SHELF_SHELF_VIEW_H_