blob: 1a799bebf9cc1bbc5a4efdd75a41a755ea9f7a1d [file] [log] [blame]
msw16ae02892016-01-27 21:07:141// Copyright (c) 2012 The Chromium Authors. All rights reserved.
msw85273d0c2016-01-14 05:05:172// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef MASH_SHELF_SHELF_VIEW_H_
6#define MASH_SHELF_SHELF_VIEW_H_
7
msw16ae02892016-01-27 21:07:148#include <string>
9#include <utility>
10#include <vector>
msw85273d0c2016-01-14 05:05:1711
12#include "base/macros.h"
msw16ae02892016-01-27 21:07:1413#include "base/memory/scoped_ptr.h"
14#include "mash/shelf/shelf_button_host.h"
15#include "mash/shelf/shelf_model.h"
16#include "mash/shelf/shelf_model_observer.h"
17#include "mash/shelf/shelf_tooltip_manager.h"
18#include "mash/shelf/shelf_types.h"
19#include "ui/views/animation/bounds_animator_observer.h"
20#include "ui/views/context_menu_controller.h"
msw85273d0c2016-01-14 05:05:1721#include "ui/views/controls/button/button.h"
msw16ae02892016-01-27 21:07:1422#include "ui/views/focus/focus_manager.h"
23#include "ui/views/view.h"
24#include "ui/views/view_model.h"
msw85273d0c2016-01-14 05:05:1725
26namespace mojo {
ben3a7cbe02016-02-07 04:35:3027class Shell;
msw85273d0c2016-01-14 05:05:1728}
29
msw16ae02892016-01-27 21:07:1430namespace ui {
31class MenuModel;
32}
33
msw85273d0c2016-01-14 05:05:1734namespace views {
msw16ae02892016-01-27 21:07:1435class BoundsAnimator;
36class MenuRunner;
msw85273d0c2016-01-14 05:05:1737}
38
39namespace mash {
40namespace shelf {
41
msw16ae02892016-01-27 21:07:1442class ShelfButton;
43
44namespace test {
45class ShelfViewTestAPI;
46}
47
48extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM;
49extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT;
50extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT;
51extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT;
52
53// TODO(msw): Restore missing features and testing from the ash shelf:
54// Alignment, overflow, applist, drag, background, hiding, pinning, panels, etc.
55class ShelfView : public views::View,
56 public ShelfModelObserver,
msw85273d0c2016-01-14 05:05:1757 public views::ButtonListener,
msw16ae02892016-01-27 21:07:1458 public ShelfButtonHost,
59 public views::ContextMenuController,
60 public views::FocusTraversable,
61 public views::BoundsAnimatorObserver {
msw85273d0c2016-01-14 05:05:1762 public:
ben3a7cbe02016-02-07 04:35:3063 explicit ShelfView(mojo::Shell* shell);
msw85273d0c2016-01-14 05:05:1764 ~ShelfView() override;
65
ben3a7cbe02016-02-07 04:35:3066 mojo::Shell* shell() const { return shell_; }
msw16ae02892016-01-27 21:07:1467
68 void SetAlignment(ShelfAlignment alignment);
69
70 void SchedulePaintForAllButtons();
71
72 // Returns the ideal bounds of the specified item, or an empty rect if id
73 // isn't know. If the item is in an overflow shelf, the overflow icon location
74 // will be returned.
75 gfx::Rect GetIdealBoundsOfItemIcon(ShelfID id);
76
77 // Repositions the icon for the specified item by the midpoint of the window.
78 void UpdatePanelIconPosition(ShelfID id, const gfx::Point& midpoint);
79
80 /* TODO(msw): Restore functionality:
81 void AddIconObserver(ShelfIconObserver* observer);
82 void RemoveIconObserver(ShelfIconObserver* observer);*/
83
84 // Returns true if we're showing a menu.
85 bool IsShowingMenu() const;
86
87 // Returns true if overflow bubble is shown.
88 bool IsShowingOverflowBubble() const;
89
90 // Sets owner overflow bubble instance from which this shelf view pops
91 // out as overflow.
92 /* TODO(msw): Restore functionality:
93 void set_owner_overflow_bubble(OverflowBubble* owner) {
94 owner_overflow_bubble_ = owner;
95 }*/
96
97 views::View* GetAppListButtonView() const;
98
99 // Returns true if the mouse cursor exits the area for launcher tooltip.
100 // There are thin gaps between launcher buttons but the tooltip shouldn't hide
101 // in the gaps, but the tooltip should hide if the mouse moved totally outside
102 // of the buttons area.
103 bool ShouldHideTooltip(const gfx::Point& cursor_location);
104
105 // Returns rectangle bounding all visible launcher items. Used screen
106 // coordinate system.
107 gfx::Rect GetVisibleItemsBoundsInScreen();
108
109 // Overridden from FocusTraversable:
110 views::FocusSearch* GetFocusSearch() override;
111 FocusTraversable* GetFocusTraversableParent() override;
112 View* GetFocusTraversableParentView() override;
113
114 /* TODO(msw): Restore drag/drop functionality.
115 // Overridden from app_list::ApplicationDragAndDropHost:
116 void CreateDragIconProxy(const gfx::Point& location_in_screen_coordinates,
117 const gfx::ImageSkia& icon,
118 views::View* replaced_view,
119 const gfx::Vector2d& cursor_offset_from_center,
120 float scale_factor) override;
121 void UpdateDragIconProxy(
122 const gfx::Point& location_in_screen_coordinates) override;
123 void DestroyDragIconProxy() override;
124 bool StartDrag(const std::string& app_id,
125 const gfx::Point& location_in_screen_coordinates) override;
126 bool Drag(const gfx::Point& location_in_screen_coordinates) override;
127 void EndDrag(bool cancel) override;
128 */
129
130 // Return the view model for test purposes.
131 const views::ViewModel* view_model_for_test() const { return &view_model_; }
132
msw85273d0c2016-01-14 05:05:17133 private:
msw16ae02892016-01-27 21:07:14134 friend class mash::shelf::test::ShelfViewTestAPI;
135
136 class FadeOutAnimationDelegate;
137 class StartFadeAnimationDelegate;
138
139 enum RemovableState {
140 REMOVABLE, // Item can be removed when dragged away.
141 DRAGGABLE, // Item can be dragged, but will snap always back to origin.
142 NOT_REMOVABLE, // Item is fixed and can never be removed.
143 };
144
145 // Returns true when this ShelfView is used for Overflow Bubble.
146 // In this mode, it does not show app list, panel and overflow button.
147 // Note:
148 // * When Shelf can contain only one item (overflow button) due to very
149 // small resolution screen, overflow bubble can show app list and panel
150 // button.
151 bool is_overflow_mode() const { return overflow_mode_; }
152
153 bool dragging() const { return drag_pointer_ != NONE; }
154
155 // Sets the bounds of each view to its ideal bounds.
156 void LayoutToIdealBounds();
157
158 // Update all button's visibility in overflow.
159 void UpdateAllButtonsVisibilityInOverflowMode();
160
161 // Calculates the ideal bounds. The bounds of each button corresponding to an
162 // item in the model is set in |view_model_|. Returns overflow button bounds.
163 gfx::Rect CalculateIdealBounds();
164
165 // Returns the index of the last view whose max primary axis coordinate is
166 // less than |max_value|. Returns -1 if nothing fits, or there are no views.
167 int DetermineLastVisibleIndex(int max_value) const;
168
169 // Returns the index of the first panel whose min primary axis coordinate is
170 // at least |min_value|. Returns the index past the last panel if none fit.
171 int DetermineFirstVisiblePanelIndex(int min_value) const;
172
173 // Animates the bounds of each view to its ideal bounds.
174 void AnimateToIdealBounds();
175
176 // Creates the view used to represent |item|.
177 views::View* CreateViewForItem(const ShelfItem& item);
178
179 // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
180 void FadeIn(views::View* view);
181
182 // Invoked when the pointer has moved enough to trigger a drag. Sets
183 // internal state in preparation for the drag.
184 void PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event);
185
186 // Invoked when the mouse is dragged. Updates the models as appropriate.
187 void ContinueDrag(const ui::LocatedEvent& event);
188
189 // Handles ripping off an item from the shelf. Returns true when the item got
190 // removed.
191 bool HandleRipOffDrag(const ui::LocatedEvent& event);
192
193 // Finalize the rip off dragging by either |cancel| the action or validating.
194 void FinalizeRipOffDrag(bool cancel);
195
196 // Check if an item can be ripped off or not.
197 RemovableState RemovableByRipOff(int index) const;
198
199 // Returns true if |typea| and |typeb| should be in the same drag range.
200 bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const;
201
202 // Returns the range (in the model) the item at the specified index can be
203 // dragged to.
204 std::pair<int, int> GetDragRange(int index);
205
206 // If there is a drag operation in progress it's canceled. If |modified_index|
207 // is valid, the new position of the corresponding item is returned.
208 int CancelDrag(int modified_index);
209
210 // Returns rectangle bounds used for drag insertion.
211 // Note:
212 // * When overflow button is visible, returns bounds from first item
213 // to overflow button.
214 // * When overflow button is visible and one or more panel items exists,
215 // returns bounds from first item to last panel item.
216 // * In the overflow mode, returns only bubble's bounds.
217 gfx::Rect GetBoundsForDragInsertInScreen();
218
219 // Common setup done for all children.
220 void ConfigureChildView(views::View* view);
221
222 // Toggles the overflow menu.
223 void ToggleOverflowBubble();
224
225 // Invoked after the fading out animation for item deletion is ended.
226 void OnFadeOutAnimationEnded();
227
228 // Fade in last visible item.
229 void StartFadeInLastVisibleItem();
230
231 // Updates the visible range of overflow items in |overflow_view|.
232 void UpdateOverflowRange(ShelfView* overflow_view) const;
mswccf394142016-01-15 00:16:42233
msw85273d0c2016-01-14 05:05:17234 // Overridden from views::View:
msw85273d0c2016-01-14 05:05:17235 gfx::Size GetPreferredSize() const override;
msw16ae02892016-01-27 21:07:14236 void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
237 FocusTraversable* GetPaneFocusTraversable() override;
238 void GetAccessibleState(ui::AXViewState* state) override;
msw85273d0c2016-01-14 05:05:17239
msw16ae02892016-01-27 21:07:14240 /* TODO(msw): Restore functionality:
241 // Overridden from ui::EventHandler:
242 void OnGestureEvent(ui::GestureEvent* event) override;*/
243
244 // Overridden from ShelfModelObserver:
245 void ShelfItemAdded(int model_index) override;
246 void ShelfItemRemoved(int model_index, ShelfID id) override;
247 void ShelfItemChanged(int model_index, const ShelfItem& old_item) override;
248 void ShelfItemMoved(int start_index, int target_index) override;
249 void ShelfStatusChanged() override;
250
251 // Overridden from ShelfButtonHost:
252 ShelfAlignment GetAlignment() const override;
253 bool IsHorizontalAlignment() const override;
254 void PointerPressedOnButton(views::View* view,
255 Pointer pointer,
256 const ui::LocatedEvent& event) override;
257 void PointerDraggedOnButton(views::View* view,
258 Pointer pointer,
259 const ui::LocatedEvent& event) override;
260 void PointerReleasedOnButton(views::View* view,
261 Pointer pointer,
262 bool canceled) override;
263 void MouseMovedOverButton(views::View* view) override;
264 void MouseEnteredButton(views::View* view) override;
265 void MouseExitedButton(views::View* view) override;
266 base::string16 GetAccessibleName(const views::View* view) override;
msw85273d0c2016-01-14 05:05:17267
268 // Overridden from views::ButtonListener:
269 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
270
msw16ae02892016-01-27 21:07:14271 // Show the list of all running items for this |item|. It will return true
272 // when the menu was shown and false if there were no possible items to
273 // choose from. |source| specifies the view which is responsible for showing
274 // the menu, and the bubble will point towards it.
275 // The |event_flags| are the flags of the event which triggered this menu.
276 bool ShowListMenuForView(const ShelfItem& item,
277 views::View* source,
278 const ui::Event& event);
msw85273d0c2016-01-14 05:05:17279
msw16ae02892016-01-27 21:07:14280 // Overridden from views::ContextMenuController:
281 void ShowContextMenuForView(views::View* source,
282 const gfx::Point& point,
283 ui::MenuSourceType source_type) override;
284
285 // Show either a context or normal click menu of given |menu_model|.
286 // If |context_menu| is set, the displayed menu is a context menu and not
287 // a menu listing one or more running applications.
288 // The |click_point| is only used for |context_menu|'s.
289 void ShowMenu(ui::MenuModel* menu_model,
290 views::View* source,
291 const gfx::Point& click_point,
292 bool context_menu,
293 ui::MenuSourceType source_type);
294
295 // Overridden from views::BoundsAnimatorObserver:
296 void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override;
297 void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
298
299 // Returns true if the (press down) |event| is a repost event from an event
300 // which just closed the menu of a shelf item. If it occurs on the same shelf
301 // item, we should ignore the call.
302 bool IsRepostEvent(const ui::Event& event);
303
304 // Convenience accessor to model_->items().
305 const ShelfItem* ShelfItemForView(const views::View* view) const;
306
307 // Returns true if a tooltip should be shown for |view|.
308 bool ShouldShowTooltipForView(const views::View* view) const;
309
310 // Get the distance from the given |coordinate| to the closest point on this
311 // launcher/shelf.
312 int CalculateShelfDistance(const gfx::Point& coordinate) const;
313
314 // The shelf application instance.
ben3a7cbe02016-02-07 04:35:30315 mojo::Shell* shell_;
msw16ae02892016-01-27 21:07:14316
317 // The shelf model.
318 ShelfModel model_;
319
320 ShelfAlignment alignment_;
321
322 // Used to manage the set of active launcher buttons. There is a view per
323 // item in |model_|.
324 views::ViewModel view_model_;
325
326 // Index of first visible launcher item.
327 int first_visible_index_;
328
329 // Last index of a launcher button that is visible
330 // (does not go into overflow).
331 mutable int last_visible_index_;
332
333 scoped_ptr<views::BoundsAnimator> bounds_animator_;
334
335 /* TODO(msw): Restore the overflow button and bubble, etc.
336 OverflowButton* overflow_button_;
337
338 scoped_ptr<OverflowBubble> overflow_bubble_;
339
340 OverflowBubble* owner_overflow_bubble_;*/
341
342 ShelfTooltipManager tooltip_;
343
344 // Pointer device that initiated the current drag operation. If there is no
345 // current dragging operation, this is NONE.
346 Pointer drag_pointer_;
347
348 // The view being dragged. This is set immediately when the mouse is pressed.
349 // |dragging_| is set only if the mouse is dragged far enough.
350 ShelfButton* drag_view_;
351
352 // Position of the mouse down event in |drag_view_|'s coordinates.
353 gfx::Point drag_origin_;
354
355 // Index |drag_view_| was initially at.
356 int start_drag_index_;
357
358 // Used for the context menu of a particular item.
359 ShelfID context_menu_id_;
360
361 scoped_ptr<views::FocusSearch> focus_search_;
362
363 scoped_ptr<ui::MenuModel> context_menu_model_;
364
365 scoped_ptr<views::MenuRunner> launcher_menu_runner_;
366
367 /* TODO(msw): Restore functionality:
368 base::ObserverList<ShelfIconObserver> observers_;*/
369
370 // Amount content is inset on the left edge (or top edge for vertical
371 // alignment).
372 int leading_inset_;
373
374 /* TODO(msw): Restore functionality:
375 ShelfGestureHandler gesture_handler_;*/
376
377 // True when an item being inserted or removed in the model cancels a drag.
378 bool cancelling_drag_model_changed_;
379
380 // Index of the last hidden launcher item. If there are no hidden items this
381 // will be equal to last_visible_index_ + 1.
382 mutable int last_hidden_index_;
383
384 // The timestamp of the event which closed the last menu - or 0.
385 base::TimeDelta closing_event_time_;
386
387 // When this object gets deleted while a menu is shown, this pointed
388 // element will be set to false.
389 bool* got_deleted_;
390
391 // True if a drag and drop operation created/pinned the item in the launcher
392 // and it needs to be deleted/unpinned again if the operation gets cancelled.
393 bool drag_and_drop_item_pinned_;
394
395 // The ShelfItem which is currently used for a drag and a drop operation
396 // or 0 otherwise.
397 ShelfID drag_and_drop_shelf_id_;
398
399 // The application ID of the application which we drag and drop.
400 std::string drag_and_drop_app_id_;
401
402 // The original launcher item's size before the dragging operation.
403 gfx::Size pre_drag_and_drop_size_;
404
405 // The image proxy for drag operations when a drag and drop host exists and
406 // the item can be dragged outside the app grid.
407 /* TODO(msw): Restore functionality:
408 scoped_ptr<ash::DragImageView> drag_image_;*/
409
410 // The cursor offset to the middle of the dragged item.
411 gfx::Vector2d drag_image_offset_;
412
413 // The view which gets replaced by our drag icon proxy.
414 views::View* drag_replaced_view_;
415
416 // True when the icon was dragged off the shelf.
417 bool dragged_off_shelf_;
418
419 // The rip off view when a snap back operation is underway.
420 views::View* snap_back_from_rip_off_view_;
421
422 /* TODO(msw): Restore functionality:
423 // Holds ShelfItemDelegateManager.
424 ShelfItemDelegateManager* item_manager_;*/
425
426 // True when this ShelfView is used for Overflow Bubble.
427 bool overflow_mode_;
428
429 // Holds a pointer to main ShelfView when a ShelfView is in overflow mode.
430 ShelfView* main_shelf_;
431
432 // True when ripped item from overflow bubble is entered into Shelf.
433 bool dragged_off_from_overflow_to_shelf_;
434
435 // True if the event is a repost event from a event which has just closed the
436 // menu of the same shelf item.
437 bool is_repost_event_;
438
439 // Record the index for the last pressed shelf item. This variable is used to
440 // check if a repost event occurs on the same shelf item as previous one. If
441 // so, the repost event should be ignored.
442 int last_pressed_index_;
443
444 /* TODO(msw): Restore functionality:
445 // Tracks UMA metrics based on shelf button press actions.
446 ShelfButtonPressedMetricTracker shelf_button_pressed_metric_tracker_;*/
msw85273d0c2016-01-14 05:05:17447
448 DISALLOW_COPY_AND_ASSIGN(ShelfView);
449};
450
451} // namespace shelf
452} // namespace mash
453
454#endif // MASH_SHELF_SHELF_VIEW_H_