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