Home | History | Annotate | Download | only in shelf
      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 
     68   ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
     69 
     70   ShelfLayoutManager* shelf_layout_manager() { return layout_manager_; }
     71 
     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.
     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.
    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.
    162   bool is_overflow_mode() const { return overflow_mode_; }
    163 
    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