| OLD | NEW |
| (Empty) |
| 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 <memory> | |
| 9 #include <string> | |
| 10 #include <utility> | |
| 11 #include <vector> | |
| 12 | |
| 13 #include "ash/common/shelf/ink_drop_button_listener.h" | |
| 14 #include "ash/common/shelf/shelf_button_pressed_metric_tracker.h" | |
| 15 #include "ash/common/shelf/shelf_item_delegate.h" | |
| 16 #include "ash/common/shelf/shelf_model_observer.h" | |
| 17 #include "ash/common/shelf/shelf_tooltip_manager.h" | |
| 18 #include "base/macros.h" | |
| 19 #include "base/observer_list.h" | |
| 20 #include "ui/app_list/views/app_list_drag_and_drop_host.h" | |
| 21 #include "ui/views/animation/bounds_animator_observer.h" | |
| 22 #include "ui/views/animation/ink_drop_state.h" | |
| 23 #include "ui/views/context_menu_controller.h" | |
| 24 #include "ui/views/controls/button/button.h" | |
| 25 #include "ui/views/focus/focus_manager.h" | |
| 26 #include "ui/views/view.h" | |
| 27 #include "ui/views/view_model.h" | |
| 28 | |
| 29 namespace ui { | |
| 30 class MenuModel; | |
| 31 } | |
| 32 | |
| 33 namespace views { | |
| 34 class BoundsAnimator; | |
| 35 class MenuModelAdapter; | |
| 36 class MenuRunner; | |
| 37 } | |
| 38 | |
| 39 namespace ash { | |
| 40 class AppListButton; | |
| 41 class DragImageView; | |
| 42 class OverflowBubble; | |
| 43 class OverflowButton; | |
| 44 class ScopedRootWindowForNewWindows; | |
| 45 class Shelf; | |
| 46 class ShelfButton; | |
| 47 class ShelfDelegate; | |
| 48 class ShelfIconObserver; | |
| 49 class ShelfModel; | |
| 50 struct ShelfItem; | |
| 51 class WmShelf; | |
| 52 | |
| 53 namespace test { | |
| 54 class ShelfViewTestAPI; | |
| 55 } | |
| 56 | |
| 57 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM; | |
| 58 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT; | |
| 59 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT; | |
| 60 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT; | |
| 61 | |
| 62 class ASH_EXPORT ShelfView : public views::View, | |
| 63 public ShelfModelObserver, | |
| 64 public InkDropButtonListener, | |
| 65 public views::ContextMenuController, | |
| 66 public views::FocusTraversable, | |
| 67 public views::BoundsAnimatorObserver, | |
| 68 public app_list::ApplicationDragAndDropHost { | |
| 69 public: | |
| 70 ShelfView(ShelfModel* model, | |
| 71 ShelfDelegate* delegate, | |
| 72 WmShelf* wm_shelf, | |
| 73 Shelf* shelf); | |
| 74 ~ShelfView() override; | |
| 75 | |
| 76 Shelf* shelf() const { return shelf_; } | |
| 77 WmShelf* wm_shelf() const { return wm_shelf_; } | |
| 78 ShelfModel* model() const { return model_; } | |
| 79 | |
| 80 void Init(); | |
| 81 | |
| 82 void OnShelfAlignmentChanged(); | |
| 83 void SchedulePaintForAllButtons(); | |
| 84 | |
| 85 // Returns the ideal bounds of the specified item, or an empty rect if id | |
| 86 // isn't know. If the item is in an overflow shelf, the overflow icon location | |
| 87 // will be returned. | |
| 88 gfx::Rect GetIdealBoundsOfItemIcon(ShelfID id); | |
| 89 | |
| 90 // Repositions the icon for the specified item by the midpoint of the window. | |
| 91 void UpdatePanelIconPosition(ShelfID id, const gfx::Point& midpoint); | |
| 92 | |
| 93 void AddIconObserver(ShelfIconObserver* observer); | |
| 94 void RemoveIconObserver(ShelfIconObserver* observer); | |
| 95 | |
| 96 // Returns true if we're showing a menu. | |
| 97 bool IsShowingMenu() const; | |
| 98 | |
| 99 // Returns true if overflow bubble is shown. | |
| 100 bool IsShowingOverflowBubble() const; | |
| 101 | |
| 102 // Sets owner overflow bubble instance from which this shelf view pops | |
| 103 // out as overflow. | |
| 104 void set_owner_overflow_bubble(OverflowBubble* owner) { | |
| 105 owner_overflow_bubble_ = owner; | |
| 106 } | |
| 107 | |
| 108 AppListButton* GetAppListButton() const; | |
| 109 | |
| 110 // Returns true if the mouse cursor exits the area for launcher tooltip. | |
| 111 // There are thin gaps between launcher buttons but the tooltip shouldn't hide | |
| 112 // in the gaps, but the tooltip should hide if the mouse moved totally outside | |
| 113 // of the buttons area. | |
| 114 bool ShouldHideTooltip(const gfx::Point& cursor_location) const; | |
| 115 | |
| 116 // Returns true if a tooltip should be shown for the shelf item |view|. | |
| 117 bool ShouldShowTooltipForView(const views::View* view) const; | |
| 118 | |
| 119 // Returns the title of the shelf item |view|. | |
| 120 base::string16 GetTitleForView(const views::View* view) const; | |
| 121 | |
| 122 // Returns rectangle bounding all visible launcher items. Used screen | |
| 123 // coordinate system. | |
| 124 gfx::Rect GetVisibleItemsBoundsInScreen(); | |
| 125 | |
| 126 // Overridden from FocusTraversable: | |
| 127 views::FocusSearch* GetFocusSearch() override; | |
| 128 FocusTraversable* GetFocusTraversableParent() override; | |
| 129 View* GetFocusTraversableParentView() override; | |
| 130 | |
| 131 // Overridden from app_list::ApplicationDragAndDropHost: | |
| 132 void CreateDragIconProxy(const gfx::Point& location_in_screen_coordinates, | |
| 133 const gfx::ImageSkia& icon, | |
| 134 views::View* replaced_view, | |
| 135 const gfx::Vector2d& cursor_offset_from_center, | |
| 136 float scale_factor) override; | |
| 137 void UpdateDragIconProxy( | |
| 138 const gfx::Point& location_in_screen_coordinates) override; | |
| 139 void DestroyDragIconProxy() override; | |
| 140 bool StartDrag(const std::string& app_id, | |
| 141 const gfx::Point& location_in_screen_coordinates) override; | |
| 142 bool Drag(const gfx::Point& location_in_screen_coordinates) override; | |
| 143 void EndDrag(bool cancel) override; | |
| 144 | |
| 145 // Returns true if |event| on the shelf item is going to activate the item. | |
| 146 // Used to determine whether a pending ink drop should be shown or not. | |
| 147 bool ShouldEventActivateButton(views::View* view, const ui::Event& event); | |
| 148 | |
| 149 // The shelf buttons use the Pointer interface to enable item reordering. | |
| 150 enum Pointer { NONE, DRAG_AND_DROP, MOUSE, TOUCH }; | |
| 151 void PointerPressedOnButton(views::View* view, | |
| 152 Pointer pointer, | |
| 153 const ui::LocatedEvent& event); | |
| 154 void PointerDraggedOnButton(views::View* view, | |
| 155 Pointer pointer, | |
| 156 const ui::LocatedEvent& event); | |
| 157 void PointerReleasedOnButton(views::View* view, | |
| 158 Pointer pointer, | |
| 159 bool canceled); | |
| 160 | |
| 161 // Updates the background for the shelf items. | |
| 162 void UpdateShelfItemBackground(int alpha); | |
| 163 | |
| 164 // Return the view model for test purposes. | |
| 165 const views::ViewModel* view_model_for_test() const { | |
| 166 return view_model_.get(); | |
| 167 } | |
| 168 | |
| 169 private: | |
| 170 friend class ash::test::ShelfViewTestAPI; | |
| 171 | |
| 172 class FadeOutAnimationDelegate; | |
| 173 class StartFadeAnimationDelegate; | |
| 174 | |
| 175 struct IdealBounds { | |
| 176 gfx::Rect overflow_bounds; | |
| 177 }; | |
| 178 | |
| 179 enum RemovableState { | |
| 180 REMOVABLE, // Item can be removed when dragged away. | |
| 181 DRAGGABLE, // Item can be dragged, but will snap always back to origin. | |
| 182 NOT_REMOVABLE, // Item is fixed and can never be removed. | |
| 183 }; | |
| 184 | |
| 185 // Minimum distance before drag starts. | |
| 186 static const int kMinimumDragDistance; | |
| 187 | |
| 188 // Returns true when this ShelfView is used for Overflow Bubble. | |
| 189 // In this mode, it does not show app list, panel and overflow button. | |
| 190 // Note: | |
| 191 // * When Shelf can contain only one item (overflow button) due to very | |
| 192 // small resolution screen, overflow bubble can show app list and panel | |
| 193 // button. | |
| 194 bool is_overflow_mode() const { return overflow_mode_; } | |
| 195 | |
| 196 bool dragging() const { return drag_pointer_ != NONE; } | |
| 197 | |
| 198 // Sets the bounds of each view to its ideal bounds. | |
| 199 void LayoutToIdealBounds(); | |
| 200 | |
| 201 // Update all button's visibility in overflow. | |
| 202 void UpdateAllButtonsVisibilityInOverflowMode(); | |
| 203 | |
| 204 // Calculates the ideal bounds. The bounds of each button corresponding to an | |
| 205 // item in the model is set in |view_model_|. | |
| 206 void CalculateIdealBounds(IdealBounds* bounds) const; | |
| 207 | |
| 208 // Returns the index of the last view whose max primary axis coordinate is | |
| 209 // less than |max_value|. Returns -1 if nothing fits, or there are no views. | |
| 210 int DetermineLastVisibleIndex(int max_value) const; | |
| 211 | |
| 212 // Returns the index of the first panel whose min primary axis coordinate is | |
| 213 // at least |min_value|. Returns the index past the last panel if none fit. | |
| 214 int DetermineFirstVisiblePanelIndex(int min_value) const; | |
| 215 | |
| 216 // Animates the bounds of each view to its ideal bounds. | |
| 217 void AnimateToIdealBounds(); | |
| 218 | |
| 219 // Creates the view used to represent |item|. | |
| 220 views::View* CreateViewForItem(const ShelfItem& item); | |
| 221 | |
| 222 // Fades |view| from an opacity of 0 to 1. This is when adding a new item. | |
| 223 void FadeIn(views::View* view); | |
| 224 | |
| 225 // Invoked when the pointer has moved enough to trigger a drag. Sets | |
| 226 // internal state in preparation for the drag. | |
| 227 void PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event); | |
| 228 | |
| 229 // Invoked when the mouse is dragged. Updates the models as appropriate. | |
| 230 void ContinueDrag(const ui::LocatedEvent& event); | |
| 231 | |
| 232 // Handles ripping off an item from the shelf. Returns true when the item got | |
| 233 // removed. | |
| 234 bool HandleRipOffDrag(const ui::LocatedEvent& event); | |
| 235 | |
| 236 // Finalize the rip off dragging by either |cancel| the action or validating. | |
| 237 void FinalizeRipOffDrag(bool cancel); | |
| 238 | |
| 239 // Check if an item can be ripped off or not. | |
| 240 RemovableState RemovableByRipOff(int index) const; | |
| 241 | |
| 242 // Returns true if |typea| and |typeb| should be in the same drag range. | |
| 243 bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const; | |
| 244 | |
| 245 // Returns the range (in the model) the item at the specified index can be | |
| 246 // dragged to. | |
| 247 std::pair<int, int> GetDragRange(int index); | |
| 248 | |
| 249 // If there is a drag operation in progress it's canceled. If |modified_index| | |
| 250 // is valid, the new position of the corresponding item is returned. | |
| 251 int CancelDrag(int modified_index); | |
| 252 | |
| 253 // Returns rectangle bounds used for drag insertion. | |
| 254 // Note: | |
| 255 // * When overflow button is visible, returns bounds from first item | |
| 256 // to overflow button. | |
| 257 // * When overflow button is visible and one or more panel items exists, | |
| 258 // returns bounds from first item to last panel item. | |
| 259 // * In the overflow mode, returns only bubble's bounds. | |
| 260 gfx::Rect GetBoundsForDragInsertInScreen(); | |
| 261 | |
| 262 // Common setup done for all children. | |
| 263 void ConfigureChildView(views::View* view); | |
| 264 | |
| 265 // Toggles the overflow menu. | |
| 266 void ToggleOverflowBubble(); | |
| 267 | |
| 268 // Invoked after the fading out animation for item deletion is ended. | |
| 269 void OnFadeOutAnimationEnded(); | |
| 270 | |
| 271 // Fade in last visible item. | |
| 272 void StartFadeInLastVisibleItem(); | |
| 273 | |
| 274 // Updates the visible range of overflow items in |overflow_view|. | |
| 275 void UpdateOverflowRange(ShelfView* overflow_view) const; | |
| 276 | |
| 277 // Overridden from views::View: | |
| 278 gfx::Size GetPreferredSize() const override; | |
| 279 void OnBoundsChanged(const gfx::Rect& previous_bounds) override; | |
| 280 FocusTraversable* GetPaneFocusTraversable() override; | |
| 281 void GetAccessibleState(ui::AXViewState* state) override; | |
| 282 void ViewHierarchyChanged( | |
| 283 const ViewHierarchyChangedDetails& details) override; | |
| 284 | |
| 285 // Overridden from ui::EventHandler: | |
| 286 void OnGestureEvent(ui::GestureEvent* event) override; | |
| 287 | |
| 288 // Overridden from ShelfModelObserver: | |
| 289 void ShelfItemAdded(int model_index) override; | |
| 290 void ShelfItemRemoved(int model_index, ShelfID id) override; | |
| 291 void ShelfItemChanged(int model_index, const ShelfItem& old_item) override; | |
| 292 void ShelfItemMoved(int start_index, int target_index) override; | |
| 293 void OnSetShelfItemDelegate(ShelfID id, | |
| 294 ShelfItemDelegate* item_delegate) override; | |
| 295 | |
| 296 // Overridden from InkDropButtonListener: | |
| 297 void ButtonPressed(views::Button* sender, | |
| 298 const ui::Event& event, | |
| 299 views::InkDrop* ink_drop) override; | |
| 300 | |
| 301 // Show a list of all running items for this shelf |item|; it only shows a | |
| 302 // menu if there are multiple running items. |source| specifies the view | |
| 303 // responsible for showing the menu, and the bubble will point towards it. | |
| 304 // The |event_flags| are the flags of the event which triggered this menu. | |
| 305 // Returns |true| if a menu is shown. | |
| 306 bool ShowListMenuForView(const ShelfItem& item, | |
| 307 views::View* source, | |
| 308 const ui::Event& event, | |
| 309 views::InkDrop* ink_drop); | |
| 310 | |
| 311 // Overridden from views::ContextMenuController: | |
| 312 void ShowContextMenuForView(views::View* source, | |
| 313 const gfx::Point& point, | |
| 314 ui::MenuSourceType source_type) override; | |
| 315 | |
| 316 // Show either a context or normal click menu of given |menu_model|. | |
| 317 // If |context_menu| is set, the displayed menu is a context menu and not | |
| 318 // a menu listing one or more running applications. | |
| 319 // The |click_point| is only used for |context_menu|'s. | |
| 320 void ShowMenu(std::unique_ptr<ui::MenuModel> menu_model, | |
| 321 views::View* source, | |
| 322 const gfx::Point& click_point, | |
| 323 bool context_menu, | |
| 324 ui::MenuSourceType source_type, | |
| 325 views::InkDrop* ink_drop); | |
| 326 | |
| 327 // Callback for MenuModelAdapter. | |
| 328 void OnMenuClosed(views::InkDrop* ink_drop); | |
| 329 | |
| 330 // Overridden from views::BoundsAnimatorObserver: | |
| 331 void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override; | |
| 332 void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override; | |
| 333 | |
| 334 // Returns true if the (press down) |event| is a repost event from an event | |
| 335 // which just closed the menu of a shelf item. If it occurs on the same shelf | |
| 336 // item, we should ignore the call. | |
| 337 bool IsRepostEvent(const ui::Event& event); | |
| 338 | |
| 339 // Convenience accessor to model_->items(). | |
| 340 const ShelfItem* ShelfItemForView(const views::View* view) const; | |
| 341 | |
| 342 // Get the distance from the given |coordinate| to the closest point on this | |
| 343 // launcher/shelf. | |
| 344 int CalculateShelfDistance(const gfx::Point& coordinate) const; | |
| 345 | |
| 346 // The model; owned by Launcher. | |
| 347 ShelfModel* model_; | |
| 348 | |
| 349 // Delegate; owned by Launcher. | |
| 350 ShelfDelegate* delegate_; | |
| 351 | |
| 352 // The shelf controller; owned by RootWindowController. | |
| 353 WmShelf* wm_shelf_; | |
| 354 | |
| 355 // The shelf; owned by ShelfWidget. | |
| 356 Shelf* shelf_; | |
| 357 | |
| 358 // Used to manage the set of active launcher buttons. There is a view per | |
| 359 // item in |model_|. | |
| 360 std::unique_ptr<views::ViewModel> view_model_; | |
| 361 | |
| 362 // Index of first visible launcher item. | |
| 363 int first_visible_index_; | |
| 364 | |
| 365 // Last index of a launcher button that is visible | |
| 366 // (does not go into overflow). | |
| 367 mutable int last_visible_index_; | |
| 368 | |
| 369 std::unique_ptr<views::BoundsAnimator> bounds_animator_; | |
| 370 | |
| 371 OverflowButton* overflow_button_; | |
| 372 | |
| 373 std::unique_ptr<OverflowBubble> overflow_bubble_; | |
| 374 | |
| 375 OverflowBubble* owner_overflow_bubble_; | |
| 376 | |
| 377 ShelfTooltipManager tooltip_; | |
| 378 | |
| 379 // Pointer device that initiated the current drag operation. If there is no | |
| 380 // current dragging operation, this is NONE. | |
| 381 Pointer drag_pointer_; | |
| 382 | |
| 383 // The view being dragged. This is set immediately when the mouse is pressed. | |
| 384 // |dragging_| is set only if the mouse is dragged far enough. | |
| 385 ShelfButton* drag_view_; | |
| 386 | |
| 387 // Position of the mouse down event in |drag_view_|'s coordinates. | |
| 388 gfx::Point drag_origin_; | |
| 389 | |
| 390 // Index |drag_view_| was initially at. | |
| 391 int start_drag_index_; | |
| 392 | |
| 393 // Used for the context menu of a particular item. | |
| 394 ShelfID context_menu_id_; | |
| 395 | |
| 396 std::unique_ptr<views::FocusSearch> focus_search_; | |
| 397 | |
| 398 // Manages the context menu, and the list menu. | |
| 399 std::unique_ptr<ui::MenuModel> menu_model_; | |
| 400 std::unique_ptr<views::MenuModelAdapter> menu_model_adapter_; | |
| 401 std::unique_ptr<views::MenuRunner> launcher_menu_runner_; | |
| 402 std::unique_ptr<ScopedRootWindowForNewWindows> | |
| 403 scoped_root_window_for_new_windows_; | |
| 404 | |
| 405 base::ObserverList<ShelfIconObserver> observers_; | |
| 406 | |
| 407 // Amount content is inset on the left edge (or top edge for vertical | |
| 408 // alignment). | |
| 409 int leading_inset_; | |
| 410 | |
| 411 // True when an item being inserted or removed in the model cancels a drag. | |
| 412 bool cancelling_drag_model_changed_; | |
| 413 | |
| 414 // Index of the last hidden launcher item. If there are no hidden items this | |
| 415 // will be equal to last_visible_index_ + 1. | |
| 416 mutable int last_hidden_index_; | |
| 417 | |
| 418 // The timestamp of the event which closed the last menu - or 0. | |
| 419 base::TimeTicks closing_event_time_; | |
| 420 | |
| 421 // True if a drag and drop operation created/pinned the item in the launcher | |
| 422 // and it needs to be deleted/unpinned again if the operation gets cancelled. | |
| 423 bool drag_and_drop_item_pinned_; | |
| 424 | |
| 425 // The ShelfItem which is currently used for a drag and a drop operation | |
| 426 // or 0 otherwise. | |
| 427 ShelfID drag_and_drop_shelf_id_; | |
| 428 | |
| 429 // The application ID of the application which we drag and drop. | |
| 430 std::string drag_and_drop_app_id_; | |
| 431 | |
| 432 // The original launcher item's size before the dragging operation. | |
| 433 gfx::Size pre_drag_and_drop_size_; | |
| 434 | |
| 435 // The image proxy for drag operations when a drag and drop host exists and | |
| 436 // the item can be dragged outside the app grid. | |
| 437 std::unique_ptr<ash::DragImageView> drag_image_; | |
| 438 | |
| 439 // The cursor offset to the middle of the dragged item. | |
| 440 gfx::Vector2d drag_image_offset_; | |
| 441 | |
| 442 // The view which gets replaced by our drag icon proxy. | |
| 443 views::View* drag_replaced_view_; | |
| 444 | |
| 445 // True when the icon was dragged off the shelf. | |
| 446 bool dragged_off_shelf_; | |
| 447 | |
| 448 // The rip off view when a snap back operation is underway. | |
| 449 views::View* snap_back_from_rip_off_view_; | |
| 450 | |
| 451 // True when this ShelfView is used for Overflow Bubble. | |
| 452 bool overflow_mode_; | |
| 453 | |
| 454 // Holds a pointer to main ShelfView when a ShelfView is in overflow mode. | |
| 455 ShelfView* main_shelf_; | |
| 456 | |
| 457 // True when ripped item from overflow bubble is entered into Shelf. | |
| 458 bool dragged_off_from_overflow_to_shelf_; | |
| 459 | |
| 460 // True if the event is a repost event from a event which has just closed the | |
| 461 // menu of the same shelf item. | |
| 462 bool is_repost_event_on_same_item_; | |
| 463 | |
| 464 // Record the index for the last pressed shelf item. This variable is used to | |
| 465 // check if a repost event occurs on the same shelf item as previous one. If | |
| 466 // so, the repost event should be ignored. | |
| 467 int last_pressed_index_; | |
| 468 | |
| 469 // Tracks UMA metrics based on shelf button press actions. | |
| 470 ShelfButtonPressedMetricTracker shelf_button_pressed_metric_tracker_; | |
| 471 | |
| 472 DISALLOW_COPY_AND_ASSIGN(ShelfView); | |
| 473 }; | |
| 474 | |
| 475 } // namespace ash | |
| 476 | |
| 477 #endif // ASH_SHELF_SHELF_VIEW_H_ | |
| OLD | NEW |