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