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