Home | History | Annotate | Download | only in launcher
      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_LAUNCHER_LAUNCHER_VIEW_H_
      6 #define ASH_LAUNCHER_LAUNCHER_VIEW_H_
      7 
      8 #include <utility>
      9 #include <vector>
     10 
     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"
     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 LauncherViewTestAPI;
     33 }
     34 
     35 class LauncherDelegate;
     36 struct LauncherItem;
     37 class LauncherIconObserver;
     38 class LauncherModel;
     39 
     40 namespace internal {
     41 
     42 class DragImageView;
     43 class LauncherButton;
     44 class LauncherTooltipManager;
     45 class ShelfLayoutManager;
     46 class OverflowBubble;
     47 class OverflowButton;
     48 
     49 class ASH_EXPORT LauncherView : public views::View,
     50                                 public LauncherModelObserver,
     51                                 public views::ButtonListener,
     52                                 public LauncherButtonHost,
     53                                 public views::ContextMenuController,
     54                                 public views::FocusTraversable,
     55                                 public views::BoundsAnimatorObserver,
     56                                 public app_list::ApplicationDragAndDropHost {
     57  public:
     58   LauncherView(LauncherModel* model,
     59                LauncherDelegate* delegate,
     60                ShelfLayoutManager* shelf_layout_manager);
     61   virtual ~LauncherView();
     62 
     63   LauncherTooltipManager* tooltip_manager() { return tooltip_.get(); }
     64 
     65   LauncherModel* model() { return model_; }
     66 
     67   void Init();
     68 
     69   void OnShelfAlignmentChanged();
     70   void SchedulePaintForAllButtons();
     71 
     72   // Returns the ideal bounds of the specified item, or an empty rect if id
     73   // isn't know.
     74   gfx::Rect GetIdealBoundsOfItemIcon(LauncherID id);
     75 
     76   // Repositions the icon for the specified item by the midpoint of the window.
     77   void UpdatePanelIconPosition(LauncherID id, const gfx::Point& midpoint);
     78 
     79   void AddIconObserver(LauncherIconObserver* observer);
     80   void RemoveIconObserver(LauncherIconObserver* observer);
     81 
     82   // Returns true if we're showing a menu.
     83   bool IsShowingMenu() const;
     84 
     85   // Returns true if overflow bubble is shown.
     86   bool IsShowingOverflowBubble() const;
     87 
     88   views::View* GetAppListButtonView() const;
     89 
     90   // Returns true if the mouse cursor exits the area for launcher tooltip.
     91   // There are thin gaps between launcher buttons but the tooltip shouldn't hide
     92   // in the gaps, but the tooltip should hide if the mouse moved totally outside
     93   // of the buttons area.
     94   bool ShouldHideTooltip(const gfx::Point& cursor_location);
     95 
     96   int leading_inset() const { return leading_inset_; }
     97   void set_leading_inset(int leading_inset) { leading_inset_ = leading_inset; }
     98 
     99   // Overridden from FocusTraversable:
    100   virtual views::FocusSearch* GetFocusSearch() OVERRIDE;
    101   virtual FocusTraversable* GetFocusTraversableParent() OVERRIDE;
    102   virtual View* GetFocusTraversableParentView() OVERRIDE;
    103 
    104   // Overridden from app_list::ApplicationDragAndDropHost:
    105   virtual void CreateDragIconProxy(
    106       const gfx::Point& location_in_screen_coordinates,
    107       const gfx::ImageSkia& icon,
    108       views::View* replaced_view,
    109       const gfx::Vector2d& cursor_offset_from_center,
    110       float scale_factor) OVERRIDE;
    111   virtual void UpdateDragIconProxy(
    112       const gfx::Point& location_in_screen_coordinates) OVERRIDE;
    113   virtual void DestroyDragIconProxy() OVERRIDE;
    114   virtual bool StartDrag(
    115       const std::string& app_id,
    116       const gfx::Point& location_in_screen_coordinates) OVERRIDE;
    117   virtual bool Drag(const gfx::Point& location_in_screen_coordinates) OVERRIDE;
    118   virtual void EndDrag(bool cancel) OVERRIDE;
    119 
    120   // Return the view model for test purposes.
    121   const views::ViewModel* const view_model_for_test() const {
    122     return view_model_.get();
    123   }
    124 
    125  private:
    126   friend class ash::test::LauncherViewTestAPI;
    127 
    128   class FadeOutAnimationDelegate;
    129   class StartFadeAnimationDelegate;
    130 
    131   struct IdealBounds {
    132     gfx::Rect overflow_bounds;
    133   };
    134 
    135   bool is_overflow_mode() const {
    136     return first_visible_index_ > 0;
    137   }
    138 
    139   bool dragging() const {
    140     return drag_pointer_ != NONE;
    141   }
    142 
    143   // Sets the bounds of each view to its ideal bounds.
    144   void LayoutToIdealBounds();
    145 
    146   // Calculates the ideal bounds. The bounds of each button corresponding to an
    147   // item in the model is set in |view_model_|.
    148   void CalculateIdealBounds(IdealBounds* bounds);
    149 
    150   // Returns the index of the last view whose max primary axis coordinate is
    151   // less than |max_value|. Returns -1 if nothing fits, or there are no views.
    152   int DetermineLastVisibleIndex(int max_value) const;
    153 
    154   // Returns the index of the first panel whose min primary axis coordinate is
    155   // at least |min_value|. Returns the index past the last panel if none fit.
    156   int DetermineFirstVisiblePanelIndex(int min_value) const;
    157 
    158   // Animates the bounds of each view to its ideal bounds.
    159   void AnimateToIdealBounds();
    160 
    161   // Creates the view used to represent |item|.
    162   views::View* CreateViewForItem(const LauncherItem& item);
    163 
    164   // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
    165   void FadeIn(views::View* view);
    166 
    167   // Invoked when the pointer has moved enough to trigger a drag. Sets
    168   // internal state in preparation for the drag.
    169   void PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event);
    170 
    171   // Invoked when the mouse is dragged. Updates the models as appropriate.
    172   void ContinueDrag(const ui::LocatedEvent& event);
    173 
    174   // Returns true if |typea| and |typeb| should be in the same drag range.
    175   bool SameDragType(LauncherItemType typea, LauncherItemType typeb) const;
    176 
    177   // Returns the range (in the model) the item at the specified index can be
    178   // dragged to.
    179   std::pair<int, int> GetDragRange(int index);
    180 
    181   // If there is a drag operation in progress it's canceled. If |modified_index|
    182   // is valid, the new position of the corresponding item is returned.
    183   int CancelDrag(int modified_index);
    184 
    185   // Common setup done for all children.
    186   void ConfigureChildView(views::View* view);
    187 
    188   // Toggles the overflow menu.
    189   void ToggleOverflowBubble();
    190 
    191   // Update first launcher button's padding. This method adds padding to the
    192   // first button to include the leading inset. It needs to be called once on
    193   // button creation and every time when shelf alignment is changed.
    194   void UpdateFirstButtonPadding();
    195 
    196   // Invoked after the fading out animation for item deletion is ended.
    197   void OnFadeOutAnimationEnded();
    198 
    199   // Updates the visible range of overflow items in |overflow_view|.
    200   void UpdateOverflowRange(LauncherView* overflow_view);
    201 
    202   // Overridden from views::View:
    203   virtual gfx::Size GetPreferredSize() OVERRIDE;
    204   virtual void OnBoundsChanged(const gfx::Rect& previous_bounds) OVERRIDE;
    205   virtual FocusTraversable* GetPaneFocusTraversable() OVERRIDE;
    206   virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
    207 
    208   // Overridden from ui::EventHandler:
    209   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
    210 
    211   // Overridden from LauncherModelObserver:
    212   virtual void LauncherItemAdded(int model_index) OVERRIDE;
    213   virtual void LauncherItemRemoved(int model_index, LauncherID id) OVERRIDE;
    214   virtual void LauncherItemChanged(int model_index,
    215                                    const ash::LauncherItem& old_item) OVERRIDE;
    216   virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE;
    217   virtual void LauncherStatusChanged() OVERRIDE;
    218 
    219   // Overridden from LauncherButtonHost:
    220   virtual void PointerPressedOnButton(
    221       views::View* view,
    222       Pointer pointer,
    223       const ui::LocatedEvent& event) OVERRIDE;
    224   virtual void PointerDraggedOnButton(
    225       views::View* view,
    226       Pointer pointer,
    227       const ui::LocatedEvent& event) OVERRIDE;
    228   virtual void PointerReleasedOnButton(views::View* view,
    229                                        Pointer pointer,
    230                                        bool canceled) OVERRIDE;
    231   virtual void MouseMovedOverButton(views::View* view) OVERRIDE;
    232   virtual void MouseEnteredButton(views::View* view) OVERRIDE;
    233   virtual void MouseExitedButton(views::View* view) OVERRIDE;
    234   virtual base::string16 GetAccessibleName(const views::View* view) OVERRIDE;
    235 
    236   // Overridden from views::ButtonListener:
    237   virtual void ButtonPressed(views::Button* sender,
    238                              const ui::Event& event) OVERRIDE;
    239 
    240   // Show the list of all running items for this |item|. It will return true
    241   // when the menu was shown and false if there were no possible items to
    242   // choose from. |source| specifies the view which is responsible for showing
    243   // the menu, and the bubble will point towards it.
    244   // The |event_flags| are the flags of the event which triggered this menu.
    245   bool ShowListMenuForView(const LauncherItem& item,
    246                            views::View* source,
    247                            const ui::Event& event);
    248 
    249   // Overridden from views::ContextMenuController:
    250   virtual void ShowContextMenuForView(views::View* source,
    251                                       const gfx::Point& point,
    252                                       ui::MenuSourceType source_type) OVERRIDE;
    253 
    254   // Show either a context or normal click menu of given |menu_model_adapter|.
    255   // If |context_menu| is set, the displayed menu is a context menu and not
    256   // a menu listing one or more running applications.
    257   // The |click_point| is only used for |context_menu|'s.
    258   void ShowMenu(scoped_ptr<views::MenuModelAdapter> menu_model_adapter,
    259                 views::View* source,
    260                 const gfx::Point& click_point,
    261                 bool context_menu,
    262                 ui::MenuSourceType source_type);
    263 
    264   // Overridden from views::BoundsAnimatorObserver:
    265   virtual void OnBoundsAnimatorProgressed(
    266       views::BoundsAnimator* animator) OVERRIDE;
    267   virtual void OnBoundsAnimatorDone(views::BoundsAnimator* animator) OVERRIDE;
    268 
    269   // Returns false if the click which closed the previous menu is the click
    270   // which triggered this event.
    271   bool IsUsableEvent(const ui::Event& event);
    272 
    273   // Convenience accessor to model_->items().
    274   const LauncherItem* LauncherItemForView(const views::View* view) const;
    275 
    276   // Returns true if a tooltip should be shown for |view|.
    277   bool ShouldShowTooltipForView(const views::View* view) const;
    278 
    279   // The model; owned by Launcher.
    280   LauncherModel* model_;
    281 
    282   // Delegate; owned by Launcher.
    283   LauncherDelegate* delegate_;
    284 
    285   // Used to manage the set of active launcher buttons. There is a view per
    286   // item in |model_|.
    287   scoped_ptr<views::ViewModel> view_model_;
    288 
    289   // Index of first visible launcher item. When it it greater than 0,
    290   // LauncherView is hosted in an overflow bubble. In this mode, it does not
    291   // show browser, app list and overflow button.
    292   int first_visible_index_;
    293 
    294   // Last index of a launcher button that is visible
    295   // (does not go into overflow).
    296   int last_visible_index_;
    297 
    298   scoped_ptr<views::BoundsAnimator> bounds_animator_;
    299 
    300   OverflowButton* overflow_button_;
    301 
    302   scoped_ptr<OverflowBubble> overflow_bubble_;
    303 
    304   scoped_ptr<LauncherTooltipManager> tooltip_;
    305 
    306   // Pointer device that initiated the current drag operation. If there is no
    307   // current dragging operation, this is NONE.
    308   Pointer drag_pointer_;
    309 
    310   // The view being dragged. This is set immediately when the mouse is pressed.
    311   // |dragging_| is set only if the mouse is dragged far enough.
    312   views::View* drag_view_;
    313 
    314   // X coordinate of the mouse down event in |drag_view_|s coordinates.
    315   int drag_offset_;
    316 
    317   // Index |drag_view_| was initially at.
    318   int start_drag_index_;
    319 
    320   // Used for the context menu of a particular item.
    321   LauncherID context_menu_id_;
    322 
    323   scoped_ptr<views::FocusSearch> focus_search_;
    324 
    325 #if !defined(OS_MACOSX)
    326   scoped_ptr<views::MenuRunner> launcher_menu_runner_;
    327 #endif
    328 
    329   ObserverList<LauncherIconObserver> observers_;
    330 
    331   // Amount content is inset on the left edge (or top edge for vertical
    332   // alignment).
    333   int leading_inset_;
    334 
    335   ShelfGestureHandler gesture_handler_;
    336 
    337   // True when an item being inserted or removed in the model cancels a drag.
    338   bool cancelling_drag_model_changed_;
    339 
    340   // Index of the last hidden launcher item. If there are no hidden items this
    341   // will be equal to last_visible_index_ + 1.
    342   int last_hidden_index_;
    343 
    344   // The timestamp of the event which closed the last menu - or 0.
    345   base::TimeDelta closing_event_time_;
    346 
    347   // When this object gets deleted while a menu is shown, this pointed
    348   // element will be set to false.
    349   bool* got_deleted_;
    350 
    351   // True if a drag and drop operation created/pinned the item in the launcher
    352   // and it needs to be deleted/unpinned again if the operation gets cancelled.
    353   bool drag_and_drop_item_pinned_;
    354 
    355   // The launcher item which is currently used for a drag and a drop operation
    356   // or 0 otherwise.
    357   LauncherID drag_and_drop_launcher_id_;
    358 
    359   // The application ID of the application which we drag and drop.
    360   std::string drag_and_drop_app_id_;
    361 
    362   // The original launcher item's size before the dragging operation.
    363   gfx::Size pre_drag_and_drop_size_;
    364 
    365   // The image proxy for drag operations when a drag and drop host exists and
    366   // the item can be dragged outside the app grid.
    367   scoped_ptr<ash::internal::DragImageView> drag_image_;
    368 
    369   // The cursor offset to the middle of the dragged item.
    370   gfx::Vector2d drag_image_offset_;
    371 
    372   // The view which gets replaced by our drag icon proxy.
    373   views::View* drag_replaced_view_;
    374 
    375   DISALLOW_COPY_AND_ASSIGN(LauncherView);
    376 };
    377 
    378 }  // namespace internal
    379 }  // namespace ash
    380 
    381 #endif  // ASH_LAUNCHER_LAUNCHER_VIEW_H_
    382