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 views {
     23 class BoundsAnimator;
     24 class MenuModelAdapter;
     25 class MenuRunner;
     26 class ViewModel;
     27 }
     28 
     29 namespace ash {
     30 
     31 namespace test {
     32 class ShelfViewTestAPI;
     33 }
     34 
     35 class ShelfDelegate;
     36 class ShelfIconObserver;
     37 class ShelfItemDelegateManager;
     38 class ShelfModel;
     39 struct LauncherItem;
     40 
     41 namespace internal {
     42 
     43 class DragImageView;
     44 class OverflowBubble;
     45 class OverflowButton;
     46 class ShelfButton;
     47 class ShelfLayoutManager;
     48 class ShelfTooltipManager;
     49 
     50 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM;
     51 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT;
     52 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT;
     53 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT;
     54 
     55 class ASH_EXPORT ShelfView : public views::View,
     56                              public ShelfModelObserver,
     57                              public views::ButtonListener,
     58                              public ShelfButtonHost,
     59                              public views::ContextMenuController,
     60                              public views::FocusTraversable,
     61                              public views::BoundsAnimatorObserver,
     62                              public app_list::ApplicationDragAndDropHost {
     63  public:
     64   ShelfView(ShelfModel* model,
     65             ShelfDelegate* delegate,
     66             ShelfLayoutManager* manager);
     67   virtual ~ShelfView();
     68 
     69   ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
     70 
     71   ShelfLayoutManager* shelf_layout_manager() { return layout_manager_; }
     72 
     73   ShelfModel* model() { return model_; }
     74 
     75   void Init();
     76 
     77   void OnShelfAlignmentChanged();
     78   void SchedulePaintForAllButtons();
     79 
     80   // Returns the ideal bounds of the specified item, or an empty rect if id
     81   // isn't know.
     82   gfx::Rect GetIdealBoundsOfItemIcon(LauncherID id);
     83 
     84   // Repositions the icon for the specified item by the midpoint of the window.
     85   void UpdatePanelIconPosition(LauncherID 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* const 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);
    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 LauncherItem& 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);
    211 
    212   // Returns true if |typea| and |typeb| should be in the same drag range.
    213   bool SameDragType(LauncherItemType typea, LauncherItemType 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   // Update first launcher button's padding. This method adds padding to the
    239   // first button to include the leading inset. It needs to be called once on
    240   // button creation and every time when shelf alignment is changed.
    241   void UpdateFirstButtonPadding();
    242 
    243   // Invoked after the fading out animation for item deletion is ended.
    244   void OnFadeOutAnimationEnded();
    245 
    246   // Fade in last visible item.
    247   void StartFadeInLastVisibleItem();
    248 
    249   // Updates the visible range of overflow items in |overflow_view|.
    250   void UpdateOverflowRange(ShelfView* overflow_view);
    251 
    252   // Returns the launcher button size.
    253   int GetButtonSize() const;
    254 
    255   // Returns the button spacing.
    256   int GetButtonSpacing() const;
    257 
    258   // Overridden from views::View:
    259   virtual gfx::Size GetPreferredSize() OVERRIDE;
    260   virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
    261   virtual FocusTraversable* GetPaneFocusTraversable() OVERRIDE;
    262   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
    263 
    264   // Overridden from ui::EventHandler:
    265   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
    266 
    267   // Overridden from ShelfModelObserver:
    268   virtual void ShelfItemAdded(int model_index) OVERRIDE;
    269   virtual void ShelfItemRemoved(int model_index, LauncherID id) OVERRIDE;
    270   virtual void ShelfItemChanged(int model_index,
    271                                 const LauncherItem& old_item) OVERRIDE;
    272   virtual void ShelfItemMoved(int start_index, int target_index) OVERRIDE;
    273   virtual void ShelfStatusChanged() OVERRIDE;
    274 
    275   // Overridden from ShelfButtonHost:
    276   virtual void PointerPressedOnButton(views::View* view,
    277                                       Pointer pointer,
    278                                       const ui::LocatedEvent& event) OVERRIDE;
    279   virtual void PointerDraggedOnButton(views::View* view,
    280                                       Pointer pointer,
    281                                       const ui::LocatedEvent& event) OVERRIDE;
    282   virtual void PointerReleasedOnButton(views::View* view,
    283                                        Pointer pointer,
    284                                        bool canceled) OVERRIDE;
    285   virtual void MouseMovedOverButton(views::View* view) OVERRIDE;
    286   virtual void MouseEnteredButton(views::View* view) OVERRIDE;
    287   virtual void MouseExitedButton(views::View* view) OVERRIDE;
    288   virtual base::string16 GetAccessibleName(const views::View* view) OVERRIDE;
    289 
    290   // Overridden from views::ButtonListener:
    291   virtual void ButtonPressed(views::Button* sender,
    292                              const ui::Event& event) OVERRIDE;
    293 
    294   // Show the list of all running items for this |item|. It will return true
    295   // when the menu was shown and false if there were no possible items to
    296   // choose from. |source| specifies the view which is responsible for showing
    297   // the menu, and the bubble will point towards it.
    298   // The |event_flags| are the flags of the event which triggered this menu.
    299   bool ShowListMenuForView(const LauncherItem& item,
    300                            views::View* source,
    301                            const ui::Event& event);
    302 
    303   // Overridden from views::ContextMenuController:
    304   virtual void ShowContextMenuForView(views::View* source,
    305                                       const gfx::Point& point,
    306                                       ui::MenuSourceType source_type) OVERRIDE;
    307 
    308   // Show either a context or normal click menu of given |menu_model_adapter|.
    309   // If |context_menu| is set, the displayed menu is a context menu and not
    310   // a menu listing one or more running applications.
    311   // The |click_point| is only used for |context_menu|'s.
    312   void ShowMenu(scoped_ptr<views::MenuModelAdapter> menu_model_adapter,
    313                 views::View* source,
    314                 const gfx::Point& click_point,
    315                 bool context_menu,
    316                 ui::MenuSourceType source_type);
    317 
    318   // Overridden from views::BoundsAnimatorObserver:
    319   virtual void OnBoundsAnimatorProgressed(
    320       views::BoundsAnimator* animator) OVERRIDE;
    321   virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE;
    322 
    323   // Returns false if the click which closed the previous menu is the click
    324   // which triggered this event.
    325   bool IsUsableEvent(const ui::Event& event);
    326 
    327   // Convenience accessor to model_->items().
    328   const LauncherItem* LauncherItemForView(const views::View* view) const;
    329 
    330   // Returns true if a tooltip should be shown for |view|.
    331   bool ShouldShowTooltipForView(const views::View* view) const;
    332 
    333   // Get the distance from the given |coordinate| to the closest point on this
    334   // launcher/shelf.
    335   int CalculateShelfDistance(const gfx::Point& coordinate) const;
    336 
    337   // The model; owned by Launcher.
    338   ShelfModel* model_;
    339 
    340   // Delegate; owned by Launcher.
    341   ShelfDelegate* delegate_;
    342 
    343   // Used to manage the set of active launcher buttons. There is a view per
    344   // item in |model_|.
    345   scoped_ptr<views::ViewModel> view_model_;
    346 
    347   // Index of first visible launcher item.
    348   int first_visible_index_;
    349 
    350   // Last index of a launcher button that is visible
    351   // (does not go into overflow).
    352   int last_visible_index_;
    353 
    354   scoped_ptr<views::BoundsAnimator> bounds_animator_;
    355 
    356   OverflowButton* overflow_button_;
    357 
    358   scoped_ptr<OverflowBubble> overflow_bubble_;
    359 
    360   OverflowBubble* owner_overflow_bubble_;
    361 
    362   scoped_ptr<ShelfTooltipManager> tooltip_;
    363 
    364   // Pointer device that initiated the current drag operation. If there is no
    365   // current dragging operation, this is NONE.
    366   Pointer drag_pointer_;
    367 
    368   // The view being dragged. This is set immediately when the mouse is pressed.
    369   // |dragging_| is set only if the mouse is dragged far enough.
    370   views::View* drag_view_;
    371 
    372   // X coordinate of the mouse down event in |drag_view_|s coordinates.
    373   int drag_offset_;
    374 
    375   // Index |drag_view_| was initially at.
    376   int start_drag_index_;
    377 
    378   // Used for the context menu of a particular item.
    379   LauncherID context_menu_id_;
    380 
    381   scoped_ptr<views::FocusSearch> focus_search_;
    382 
    383   scoped_ptr<views::MenuRunner> launcher_menu_runner_;
    384 
    385   ObserverList<ShelfIconObserver> observers_;
    386 
    387   // Amount content is inset on the left edge (or top edge for vertical
    388   // alignment).
    389   int leading_inset_;
    390 
    391   ShelfGestureHandler gesture_handler_;
    392 
    393   // True when an item being inserted or removed in the model cancels a drag.
    394   bool cancelling_drag_model_changed_;
    395 
    396   // Index of the last hidden launcher item. If there are no hidden items this
    397   // will be equal to last_visible_index_ + 1.
    398   int last_hidden_index_;
    399 
    400   // The timestamp of the event which closed the last menu - or 0.
    401   base::TimeDelta closing_event_time_;
    402 
    403   // When this object gets deleted while a menu is shown, this pointed
    404   // element will be set to false.
    405   bool* got_deleted_;
    406 
    407   // True if a drag and drop operation created/pinned the item in the launcher
    408   // and it needs to be deleted/unpinned again if the operation gets cancelled.
    409   bool drag_and_drop_item_pinned_;
    410 
    411   // The launcher item which is currently used for a drag and a drop operation
    412   // or 0 otherwise.
    413   LauncherID drag_and_drop_launcher_id_;
    414 
    415   // The application ID of the application which we drag and drop.
    416   std::string drag_and_drop_app_id_;
    417 
    418   // The original launcher item's size before the dragging operation.
    419   gfx::Size pre_drag_and_drop_size_;
    420 
    421   // The image proxy for drag operations when a drag and drop host exists and
    422   // the item can be dragged outside the app grid.
    423   scoped_ptr<ash::internal::DragImageView> drag_image_;
    424 
    425   // The cursor offset to the middle of the dragged item.
    426   gfx::Vector2d drag_image_offset_;
    427 
    428   // The view which gets replaced by our drag icon proxy.
    429   views::View* drag_replaced_view_;
    430 
    431   // True when the icon was dragged off the shelf.
    432   bool dragged_off_shelf_;
    433 
    434   // The rip off view when a snap back operation is underway.
    435   views::View* snap_back_from_rip_off_view_;
    436 
    437   // Holds ShelfItemDelegateManager.
    438   ShelfItemDelegateManager* item_manager_;
    439 
    440   // Holds ShelfLayoutManager.
    441   ShelfLayoutManager* layout_manager_;
    442 
    443   // True when this ShelfView is used for Overflow Bubble.
    444   bool overflow_mode_;
    445 
    446   // Holds a pointer to main ShelfView when a ShelfView is in overflow mode.
    447   ShelfView* main_shelf_;
    448 
    449   // True when ripped item from overflow bubble is entered into Shelf.
    450   bool dragged_off_from_overflow_to_shelf_;
    451 
    452   DISALLOW_COPY_AND_ASSIGN(ShelfView);
    453 };
    454 
    455 }  // namespace internal
    456 }  // namespace ash
    457 
    458 #endif  // ASH_SHELF_SHELF_VIEW_H_
    459