• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #ifndef ASH_SHELF_SHELF_VIEW_H_
6 #define ASH_SHELF_SHELF_VIEW_H_
7 
8 #include <utility>
9 #include <vector>
10 
11 #include "ash/shelf/shelf_button_host.h"
12 #include "ash/shelf/shelf_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"
21 
22 namespace ui {
23 class MenuModel;
24 }
25 
26 namespace views {
27 class BoundsAnimator;
28 class MenuRunner;
29 class ViewModel;
30 }
31 
32 namespace ash {
33 class ShelfDelegate;
34 class ShelfIconObserver;
35 class ShelfItemDelegateManager;
36 class ShelfModel;
37 struct ShelfItem;
38 class DragImageView;
39 class OverflowBubble;
40 class OverflowButton;
41 class ShelfButton;
42 class ShelfLayoutManager;
43 class ShelfTooltipManager;
44 
45 namespace test {
46 class ShelfViewTestAPI;
47 }
48 
49 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM;
50 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT;
51 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT;
52 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT;
53 
54 class ASH_EXPORT ShelfView : public views::View,
55                              public ShelfModelObserver,
56                              public views::ButtonListener,
57                              public ShelfButtonHost,
58                              public views::ContextMenuController,
59                              public views::FocusTraversable,
60                              public views::BoundsAnimatorObserver,
61                              public app_list::ApplicationDragAndDropHost {
62  public:
63   ShelfView(ShelfModel* model,
64             ShelfDelegate* delegate,
65             ShelfLayoutManager* manager);
66   virtual ~ShelfView();
67 
tooltip_manager()68   ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
69 
shelf_layout_manager()70   ShelfLayoutManager* shelf_layout_manager() { return layout_manager_; }
71 
model()72   ShelfModel* model() { return model_; }
73 
74   void Init();
75 
76   void OnShelfAlignmentChanged();
77   void SchedulePaintForAllButtons();
78 
79   // Returns the ideal bounds of the specified item, or an empty rect if id
80   // isn't know. If the item is in an overflow shelf, the overflow icon location
81   // will be returned.
82   gfx::Rect GetIdealBoundsOfItemIcon(ShelfID id);
83 
84   // Repositions the icon for the specified item by the midpoint of the window.
85   void UpdatePanelIconPosition(ShelfID id, const gfx::Point& midpoint);
86 
87   void AddIconObserver(ShelfIconObserver* observer);
88   void RemoveIconObserver(ShelfIconObserver* observer);
89 
90   // Returns true if we're showing a menu.
91   bool IsShowingMenu() const;
92 
93   // Returns true if overflow bubble is shown.
94   bool IsShowingOverflowBubble() const;
95 
96   // Sets owner overflow bubble instance from which this shelf view pops
97   // out as overflow.
set_owner_overflow_bubble(OverflowBubble * owner)98   void set_owner_overflow_bubble(OverflowBubble* owner) {
99     owner_overflow_bubble_ = owner;
100   }
101 
102   views::View* GetAppListButtonView() const;
103 
104   // Returns true if the mouse cursor exits the area for launcher tooltip.
105   // There are thin gaps between launcher buttons but the tooltip shouldn't hide
106   // in the gaps, but the tooltip should hide if the mouse moved totally outside
107   // of the buttons area.
108   bool ShouldHideTooltip(const gfx::Point& cursor_location);
109 
110   // Returns rectangle bounding all visible launcher items. Used screen
111   // coordinate system.
112   gfx::Rect GetVisibleItemsBoundsInScreen();
113 
114   // Overridden from FocusTraversable:
115   virtual views::FocusSearch* GetFocusSearch() OVERRIDE;
116   virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE;
117   virtual View* GetFocusTraversableParentView() OVERRIDE;
118 
119   // Overridden from app_list::ApplicationDragAndDropHost:
120   virtual void CreateDragIconProxy(
121       const gfx::Point& location_in_screen_coordinates,
122       const gfx::ImageSkia& icon,
123       views::View* replaced_view,
124       const gfx::Vector2d& cursor_offset_from_center,
125       float scale_factor) OVERRIDE;
126   virtual void UpdateDragIconProxy(
127       const gfx::Point& location_in_screen_coordinates) OVERRIDE;
128   virtual void DestroyDragIconProxy() OVERRIDE;
129   virtual bool StartDrag(
130       const std::string& app_id,
131       const gfx::Point& location_in_screen_coordinates) OVERRIDE;
132   virtual bool Drag(const gfx::Point& location_in_screen_coordinates) OVERRIDE;
133   virtual void EndDrag(bool cancel) OVERRIDE;
134 
135   // Return the view model for test purposes.
view_model_for_test()136   const views::ViewModel* view_model_for_test() const {
137     return view_model_.get();
138   }
139 
140  private:
141   friend class ash::test::ShelfViewTestAPI;
142 
143   class FadeOutAnimationDelegate;
144   class StartFadeAnimationDelegate;
145 
146   struct IdealBounds {
147     gfx::Rect overflow_bounds;
148   };
149 
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.
154   };
155 
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.
158   // Note:
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
161   //     button.
is_overflow_mode()162   bool is_overflow_mode() const { return overflow_mode_; }
163 
dragging()164   bool dragging() const {
165     return drag_pointer_ != NONE;
166   }
167 
168   // Sets the bounds of each view to its ideal bounds.
169   void LayoutToIdealBounds();
170 
171   // Update all button's visibility in overflow.
172   void UpdateAllButtonsVisibilityInOverflowMode();
173 
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;
177 
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;
181 
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;
185 
186   // Animates the bounds of each view to its ideal bounds.
187   void AnimateToIdealBounds();
188 
189   // Creates the view used to represent |item|.
190   views::View* CreateViewForItem(const ShelfItem& item);
191 
192   // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
193   void FadeIn(views::View* view);
194 
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);
198 
199   // Invoked when the mouse is dragged. Updates the models as appropriate.
200   void ContinueDrag(const ui::LocatedEvent& event);
201 
202   // Handles ripping off an item from the shelf. Returns true when the item got
203   // removed.
204   bool HandleRipOffDrag(const ui::LocatedEvent& event);
205 
206   // Finalize the rip off dragging by either |cancel| the action or validating.
207   void FinalizeRipOffDrag(bool cancel);
208 
209   // Check if an item can be ripped off or not.
210   RemovableState RemovableByRipOff(int index) const;
211 
212   // Returns true if |typea| and |typeb| should be in the same drag range.
213   bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const;
214 
215   // Returns the range (in the model) the item at the specified index can be
216   // dragged to.
217   std::pair<int, int> GetDragRange(int index);
218 
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);
222 
223   // Returns rectangle bounds used for drag insertion.
224   // Note:
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();
231 
232   // Common setup done for all children.
233   void ConfigureChildView(views::View* view);
234 
235   // Toggles the overflow menu.
236   void ToggleOverflowBubble();
237 
238   // Invoked after the fading out animation for item deletion is ended.
239   void OnFadeOutAnimationEnded();
240 
241   // Fade in last visible item.
242   void StartFadeInLastVisibleItem();
243 
244   // Updates the visible range of overflow items in |overflow_view|.
245   void UpdateOverflowRange(ShelfView* overflow_view) const;
246 
247   // Overridden from views::View:
248   virtual gfx::Size GetPreferredSize() const OVERRIDE;
249   virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
250   virtual FocusTraversable* GetPaneFocusTraversable() OVERRIDE;
251   virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE;
252 
253   // Overridden from ui::EventHandler:
254   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
255 
256   // Overridden from ShelfModelObserver:
257   virtual void ShelfItemAdded(int model_index) OVERRIDE;
258   virtual void ShelfItemRemoved(int model_index, ShelfID id) OVERRIDE;
259   virtual void ShelfItemChanged(int model_index,
260                                 const ShelfItem& old_item) OVERRIDE;
261   virtual void ShelfItemMoved(int start_index, int target_index) OVERRIDE;
262   virtual void ShelfStatusChanged() OVERRIDE;
263 
264   // Overridden from ShelfButtonHost:
265   virtual void PointerPressedOnButton(views::View* view,
266                                       Pointer pointer,
267                                       const ui::LocatedEvent& event) OVERRIDE;
268   virtual void PointerDraggedOnButton(views::View* view,
269                                       Pointer pointer,
270                                       const ui::LocatedEvent& event) OVERRIDE;
271   virtual void PointerReleasedOnButton(views::View* view,
272                                        Pointer pointer,
273                                        bool canceled) OVERRIDE;
274   virtual void MouseMovedOverButton(views::View* view) OVERRIDE;
275   virtual void MouseEnteredButton(views::View* view) OVERRIDE;
276   virtual void MouseExitedButton(views::View* view) OVERRIDE;
277   virtual base::string16 GetAccessibleName(const views::View* view) OVERRIDE;
278 
279   // Overridden from views::ButtonListener:
280   virtual void ButtonPressed(views::Button* sender,
281                              const ui::Event& event) OVERRIDE;
282 
283   // Show the list of all running items for this |item|. It will return true
284   // when the menu was shown and false if there were no possible items to
285   // choose from. |source| specifies the view which is responsible for showing
286   // the menu, and the bubble will point towards it.
287   // The |event_flags| are the flags of the event which triggered this menu.
288   bool ShowListMenuForView(const ShelfItem& item,
289                            views::View* source,
290                            const ui::Event& event);
291 
292   // Overridden from views::ContextMenuController:
293   virtual void ShowContextMenuForView(views::View* source,
294                                       const gfx::Point& point,
295                                       ui::MenuSourceType source_type) OVERRIDE;
296 
297   // Show either a context or normal click menu of given |menu_model|.
298   // If |context_menu| is set, the displayed menu is a context menu and not
299   // a menu listing one or more running applications.
300   // The |click_point| is only used for |context_menu|'s.
301   void ShowMenu(ui::MenuModel* menu_model,
302                 views::View* source,
303                 const gfx::Point& click_point,
304                 bool context_menu,
305                 ui::MenuSourceType source_type);
306 
307   // Overridden from views::BoundsAnimatorObserver:
308   virtual void OnBoundsAnimatorProgressed(
309       views::BoundsAnimator* animator) OVERRIDE;
310   virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE;
311 
312   // Returns false if the click which closed the previous menu is the click
313   // which triggered this event.
314   bool IsUsableEvent(const ui::Event& event);
315 
316   // Convenience accessor to model_->items().
317   const ShelfItem* ShelfItemForView(const views::View* view) const;
318 
319   // Returns true if a tooltip should be shown for |view|.
320   bool ShouldShowTooltipForView(const views::View* view) const;
321 
322   // Get the distance from the given |coordinate| to the closest point on this
323   // launcher/shelf.
324   int CalculateShelfDistance(const gfx::Point& coordinate) const;
325 
326   // The model; owned by Launcher.
327   ShelfModel* model_;
328 
329   // Delegate; owned by Launcher.
330   ShelfDelegate* delegate_;
331 
332   // Used to manage the set of active launcher buttons. There is a view per
333   // item in |model_|.
334   scoped_ptr<views::ViewModel> view_model_;
335 
336   // Index of first visible launcher item.
337   int first_visible_index_;
338 
339   // Last index of a launcher button that is visible
340   // (does not go into overflow).
341   mutable int last_visible_index_;
342 
343   scoped_ptr<views::BoundsAnimator> bounds_animator_;
344 
345   OverflowButton* overflow_button_;
346 
347   scoped_ptr<OverflowBubble> overflow_bubble_;
348 
349   OverflowBubble* owner_overflow_bubble_;
350 
351   scoped_ptr<ShelfTooltipManager> tooltip_;
352 
353   // Pointer device that initiated the current drag operation. If there is no
354   // current dragging operation, this is NONE.
355   Pointer drag_pointer_;
356 
357   // The view being dragged. This is set immediately when the mouse is pressed.
358   // |dragging_| is set only if the mouse is dragged far enough.
359   views::View* drag_view_;
360 
361   // Position of the mouse down event in |drag_view_|'s coordinates.
362   gfx::Point drag_origin_;
363 
364   // Index |drag_view_| was initially at.
365   int start_drag_index_;
366 
367   // Used for the context menu of a particular item.
368   ShelfID context_menu_id_;
369 
370   scoped_ptr<views::FocusSearch> focus_search_;
371 
372   scoped_ptr<ui::MenuModel> context_menu_model_;
373 
374   scoped_ptr<views::MenuRunner> launcher_menu_runner_;
375 
376   ObserverList<ShelfIconObserver> observers_;
377 
378   // Amount content is inset on the left edge (or top edge for vertical
379   // alignment).
380   int leading_inset_;
381 
382   ShelfGestureHandler gesture_handler_;
383 
384   // True when an item being inserted or removed in the model cancels a drag.
385   bool cancelling_drag_model_changed_;
386 
387   // Index of the last hidden launcher item. If there are no hidden items this
388   // will be equal to last_visible_index_ + 1.
389   mutable int last_hidden_index_;
390 
391   // The timestamp of the event which closed the last menu - or 0.
392   base::TimeDelta closing_event_time_;
393 
394   // When this object gets deleted while a menu is shown, this pointed
395   // element will be set to false.
396   bool* got_deleted_;
397 
398   // True if a drag and drop operation created/pinned the item in the launcher
399   // and it needs to be deleted/unpinned again if the operation gets cancelled.
400   bool drag_and_drop_item_pinned_;
401 
402   // The ShelfItem which is currently used for a drag and a drop operation
403   // or 0 otherwise.
404   ShelfID drag_and_drop_shelf_id_;
405 
406   // The application ID of the application which we drag and drop.
407   std::string drag_and_drop_app_id_;
408 
409   // The original launcher item's size before the dragging operation.
410   gfx::Size pre_drag_and_drop_size_;
411 
412   // The image proxy for drag operations when a drag and drop host exists and
413   // the item can be dragged outside the app grid.
414   scoped_ptr<ash::DragImageView> drag_image_;
415 
416   // The cursor offset to the middle of the dragged item.
417   gfx::Vector2d drag_image_offset_;
418 
419   // The view which gets replaced by our drag icon proxy.
420   views::View* drag_replaced_view_;
421 
422   // True when the icon was dragged off the shelf.
423   bool dragged_off_shelf_;
424 
425   // The rip off view when a snap back operation is underway.
426   views::View* snap_back_from_rip_off_view_;
427 
428   // Holds ShelfItemDelegateManager.
429   ShelfItemDelegateManager* item_manager_;
430 
431   // Holds ShelfLayoutManager.
432   ShelfLayoutManager* layout_manager_;
433 
434   // True when this ShelfView is used for Overflow Bubble.
435   bool overflow_mode_;
436 
437   // Holds a pointer to main ShelfView when a ShelfView is in overflow mode.
438   ShelfView* main_shelf_;
439 
440   // True when ripped item from overflow bubble is entered into Shelf.
441   bool dragged_off_from_overflow_to_shelf_;
442 
443   DISALLOW_COPY_AND_ASSIGN(ShelfView);
444 };
445 
446 }  // namespace ash
447 
448 #endif  // ASH_SHELF_SHELF_VIEW_H_
449