Don't preload rarely seen large images
[chromium-blink-merge.git] / ash / shelf / shelf_view.h
blob82ea7faf58e59af740b42d912e68dad25bb9c054
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.
5 #ifndef ASH_SHELF_SHELF_VIEW_H_
6 #define ASH_SHELF_SHELF_VIEW_H_
8 #include <string>
9 #include <utility>
10 #include <vector>
12 #include "ash/shelf/shelf_button_host.h"
13 #include "ash/shelf/shelf_button_pressed_metric_tracker.h"
14 #include "ash/shelf/shelf_item_delegate.h"
15 #include "ash/shelf/shelf_model_observer.h"
16 #include "ash/wm/gestures/shelf_gesture_handler.h"
17 #include "base/observer_list.h"
18 #include "ui/app_list/views/app_list_drag_and_drop_host.h"
19 #include "ui/views/animation/bounds_animator_observer.h"
20 #include "ui/views/context_menu_controller.h"
21 #include "ui/views/controls/button/button.h"
22 #include "ui/views/focus/focus_manager.h"
23 #include "ui/views/view.h"
24 #include "ui/views/view_model.h"
26 namespace ui {
27 class MenuModel;
30 namespace views {
31 class BoundsAnimator;
32 class MenuRunner;
35 namespace ash {
36 class ShelfDelegate;
37 class ShelfIconObserver;
38 class ShelfItemDelegateManager;
39 class ShelfModel;
40 struct ShelfItem;
41 class DragImageView;
42 class OverflowBubble;
43 class OverflowButton;
44 class ShelfButton;
45 class ShelfLayoutManager;
46 class ShelfTooltipManager;
48 namespace test {
49 class ShelfViewTestAPI;
52 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM;
53 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT;
54 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT;
55 extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT;
57 class ASH_EXPORT ShelfView : public views::View,
58 public ShelfModelObserver,
59 public views::ButtonListener,
60 public ShelfButtonHost,
61 public views::ContextMenuController,
62 public views::FocusTraversable,
63 public views::BoundsAnimatorObserver,
64 public app_list::ApplicationDragAndDropHost {
65 public:
66 ShelfView(ShelfModel* model,
67 ShelfDelegate* delegate,
68 ShelfLayoutManager* manager);
69 ~ShelfView() override;
71 ShelfTooltipManager* tooltip_manager() { return tooltip_.get(); }
73 ShelfLayoutManager* shelf_layout_manager() { return layout_manager_; }
75 ShelfModel* model() { return model_; }
77 void Init();
79 void OnShelfAlignmentChanged();
80 void SchedulePaintForAllButtons();
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);
87 // Repositions the icon for the specified item by the midpoint of the window.
88 void UpdatePanelIconPosition(ShelfID id, const gfx::Point& midpoint);
90 void AddIconObserver(ShelfIconObserver* observer);
91 void RemoveIconObserver(ShelfIconObserver* observer);
93 // Returns true if we're showing a menu.
94 bool IsShowingMenu() const;
96 // Returns true if overflow bubble is shown.
97 bool IsShowingOverflowBubble() const;
99 // Sets owner overflow bubble instance from which this shelf view pops
100 // out as overflow.
101 void set_owner_overflow_bubble(OverflowBubble* owner) {
102 owner_overflow_bubble_ = owner;
105 views::View* GetAppListButtonView() const;
107 // Returns true if the mouse cursor exits the area for launcher tooltip.
108 // There are thin gaps between launcher buttons but the tooltip shouldn't hide
109 // in the gaps, but the tooltip should hide if the mouse moved totally outside
110 // of the buttons area.
111 bool ShouldHideTooltip(const gfx::Point& cursor_location);
113 // Returns rectangle bounding all visible launcher items. Used screen
114 // coordinate system.
115 gfx::Rect GetVisibleItemsBoundsInScreen();
117 // Overridden from FocusTraversable:
118 views::FocusSearch* GetFocusSearch() override;
119 FocusTraversable* GetFocusTraversableParent() override;
120 View* GetFocusTraversableParentView() override;
122 // Overridden from app_list::ApplicationDragAndDropHost:
123 void CreateDragIconProxy(const gfx::Point& location_in_screen_coordinates,
124 const gfx::ImageSkia& icon,
125 views::View* replaced_view,
126 const gfx::Vector2d& cursor_offset_from_center,
127 float scale_factor) override;
128 void UpdateDragIconProxy(
129 const gfx::Point& location_in_screen_coordinates) override;
130 void DestroyDragIconProxy() override;
131 bool StartDrag(const std::string& app_id,
132 const gfx::Point& location_in_screen_coordinates) override;
133 bool Drag(const gfx::Point& location_in_screen_coordinates) override;
134 void EndDrag(bool cancel) override;
136 // Return the view model for test purposes.
137 const views::ViewModel* view_model_for_test() const {
138 return view_model_.get();
141 private:
142 friend class ash::test::ShelfViewTestAPI;
144 class FadeOutAnimationDelegate;
145 class StartFadeAnimationDelegate;
147 struct IdealBounds {
148 gfx::Rect overflow_bounds;
151 enum RemovableState {
152 REMOVABLE, // Item can be removed when dragged away.
153 DRAGGABLE, // Item can be dragged, but will snap always back to origin.
154 NOT_REMOVABLE, // Item is fixed and can never be removed.
157 // Returns true when this ShelfView is used for Overflow Bubble.
158 // In this mode, it does not show app list, panel and overflow button.
159 // Note:
160 // * When Shelf can contain only one item (overflow button) due to very
161 // small resolution screen, overflow bubble can show app list and panel
162 // button.
163 bool is_overflow_mode() const { return overflow_mode_; }
165 bool dragging() const {
166 return drag_pointer_ != NONE;
169 // Sets the bounds of each view to its ideal bounds.
170 void LayoutToIdealBounds();
172 // Update all button's visibility in overflow.
173 void UpdateAllButtonsVisibilityInOverflowMode();
175 // Calculates the ideal bounds. The bounds of each button corresponding to an
176 // item in the model is set in |view_model_|.
177 void CalculateIdealBounds(IdealBounds* bounds) const;
179 // Returns the index of the last view whose max primary axis coordinate is
180 // less than |max_value|. Returns -1 if nothing fits, or there are no views.
181 int DetermineLastVisibleIndex(int max_value) const;
183 // Returns the index of the first panel whose min primary axis coordinate is
184 // at least |min_value|. Returns the index past the last panel if none fit.
185 int DetermineFirstVisiblePanelIndex(int min_value) const;
187 // Animates the bounds of each view to its ideal bounds.
188 void AnimateToIdealBounds();
190 // Creates the view used to represent |item|.
191 views::View* CreateViewForItem(const ShelfItem& item);
193 // Fades |view| from an opacity of 0 to 1. This is when adding a new item.
194 void FadeIn(views::View* view);
196 // Invoked when the pointer has moved enough to trigger a drag. Sets
197 // internal state in preparation for the drag.
198 void PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event);
200 // Invoked when the mouse is dragged. Updates the models as appropriate.
201 void ContinueDrag(const ui::LocatedEvent& event);
203 // Handles ripping off an item from the shelf. Returns true when the item got
204 // removed.
205 bool HandleRipOffDrag(const ui::LocatedEvent& event);
207 // Finalize the rip off dragging by either |cancel| the action or validating.
208 void FinalizeRipOffDrag(bool cancel);
210 // Check if an item can be ripped off or not.
211 RemovableState RemovableByRipOff(int index) const;
213 // Returns true if |typea| and |typeb| should be in the same drag range.
214 bool SameDragType(ShelfItemType typea, ShelfItemType typeb) const;
216 // Returns the range (in the model) the item at the specified index can be
217 // dragged to.
218 std::pair<int, int> GetDragRange(int index);
220 // If there is a drag operation in progress it's canceled. If |modified_index|
221 // is valid, the new position of the corresponding item is returned.
222 int CancelDrag(int modified_index);
224 // Returns rectangle bounds used for drag insertion.
225 // Note:
226 // * When overflow button is visible, returns bounds from first item
227 // to overflow button.
228 // * When overflow button is visible and one or more panel items exists,
229 // returns bounds from first item to last panel item.
230 // * In the overflow mode, returns only bubble's bounds.
231 gfx::Rect GetBoundsForDragInsertInScreen();
233 // Common setup done for all children.
234 void ConfigureChildView(views::View* view);
236 // Toggles the overflow menu.
237 void ToggleOverflowBubble();
239 // Invoked after the fading out animation for item deletion is ended.
240 void OnFadeOutAnimationEnded();
242 // Fade in last visible item.
243 void StartFadeInLastVisibleItem();
245 // Updates the visible range of overflow items in |overflow_view|.
246 void UpdateOverflowRange(ShelfView* overflow_view) const;
248 // Overridden from views::View:
249 gfx::Size GetPreferredSize() const override;
250 void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
251 FocusTraversable* GetPaneFocusTraversable() override;
252 void GetAccessibleState(ui::AXViewState* state) override;
254 // Overridden from ui::EventHandler:
255 void OnGestureEvent(ui::GestureEvent* event) override;
257 // Overridden from ShelfModelObserver:
258 void ShelfItemAdded(int model_index) override;
259 void ShelfItemRemoved(int model_index, ShelfID id) override;
260 void ShelfItemChanged(int model_index, const ShelfItem& old_item) override;
261 void ShelfItemMoved(int start_index, int target_index) override;
262 void ShelfStatusChanged() override;
264 // Overridden from ShelfButtonHost:
265 void PointerPressedOnButton(views::View* view,
266 Pointer pointer,
267 const ui::LocatedEvent& event) override;
268 void PointerDraggedOnButton(views::View* view,
269 Pointer pointer,
270 const ui::LocatedEvent& event) override;
271 void PointerReleasedOnButton(views::View* view,
272 Pointer pointer,
273 bool canceled) override;
274 void MouseMovedOverButton(views::View* view) override;
275 void MouseEnteredButton(views::View* view) override;
276 void MouseExitedButton(views::View* view) override;
277 base::string16 GetAccessibleName(const views::View* view) override;
279 // Overridden from views::ButtonListener:
280 void ButtonPressed(views::Button* sender, const ui::Event& event) override;
282 // Show the list of all running items for this |item|. It will return true
283 // when the menu was shown and false if there were no possible items to
284 // choose from. |source| specifies the view which is responsible for showing
285 // the menu, and the bubble will point towards it.
286 // The |event_flags| are the flags of the event which triggered this menu.
287 bool ShowListMenuForView(const ShelfItem& item,
288 views::View* source,
289 const ui::Event& event);
291 // Overridden from views::ContextMenuController:
292 void ShowContextMenuForView(views::View* source,
293 const gfx::Point& point,
294 ui::MenuSourceType source_type) override;
296 // Show either a context or normal click menu of given |menu_model|.
297 // If |context_menu| is set, the displayed menu is a context menu and not
298 // a menu listing one or more running applications.
299 // The |click_point| is only used for |context_menu|'s.
300 void ShowMenu(ui::MenuModel* menu_model,
301 views::View* source,
302 const gfx::Point& click_point,
303 bool context_menu,
304 ui::MenuSourceType source_type);
306 // Overridden from views::BoundsAnimatorObserver:
307 void OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) override;
308 void OnBoundsAnimatorDone(views::BoundsAnimator* animator) override;
310 // Returns true if the (press down) |event| is a repost event from an event
311 // which just closed the menu of a shelf item. If it occurs on the same shelf
312 // item, we should ignore the call.
313 bool IsRepostEvent(const ui::Event& event);
315 // Convenience accessor to model_->items().
316 const ShelfItem* ShelfItemForView(const views::View* view) const;
318 // Returns true if a tooltip should be shown for |view|.
319 bool ShouldShowTooltipForView(const views::View* view) const;
321 // Get the distance from the given |coordinate| to the closest point on this
322 // launcher/shelf.
323 int CalculateShelfDistance(const gfx::Point& coordinate) const;
325 // The model; owned by Launcher.
326 ShelfModel* model_;
328 // Delegate; owned by Launcher.
329 ShelfDelegate* delegate_;
331 // Used to manage the set of active launcher buttons. There is a view per
332 // item in |model_|.
333 scoped_ptr<views::ViewModel> view_model_;
335 // Index of first visible launcher item.
336 int first_visible_index_;
338 // Last index of a launcher button that is visible
339 // (does not go into overflow).
340 mutable int last_visible_index_;
342 scoped_ptr<views::BoundsAnimator> bounds_animator_;
344 OverflowButton* overflow_button_;
346 scoped_ptr<OverflowBubble> overflow_bubble_;
348 OverflowBubble* owner_overflow_bubble_;
350 scoped_ptr<ShelfTooltipManager> tooltip_;
352 // Pointer device that initiated the current drag operation. If there is no
353 // current dragging operation, this is NONE.
354 Pointer drag_pointer_;
356 // The view being dragged. This is set immediately when the mouse is pressed.
357 // |dragging_| is set only if the mouse is dragged far enough.
358 ShelfButton* drag_view_;
360 // Position of the mouse down event in |drag_view_|'s coordinates.
361 gfx::Point drag_origin_;
363 // Index |drag_view_| was initially at.
364 int start_drag_index_;
366 // Used for the context menu of a particular item.
367 ShelfID context_menu_id_;
369 scoped_ptr<views::FocusSearch> focus_search_;
371 scoped_ptr<ui::MenuModel> context_menu_model_;
373 scoped_ptr<views::MenuRunner> launcher_menu_runner_;
375 base::ObserverList<ShelfIconObserver> observers_;
377 // Amount content is inset on the left edge (or top edge for vertical
378 // alignment).
379 int leading_inset_;
381 ShelfGestureHandler gesture_handler_;
383 // True when an item being inserted or removed in the model cancels a drag.
384 bool cancelling_drag_model_changed_;
386 // Index of the last hidden launcher item. If there are no hidden items this
387 // will be equal to last_visible_index_ + 1.
388 mutable int last_hidden_index_;
390 // The timestamp of the event which closed the last menu - or 0.
391 base::TimeDelta closing_event_time_;
393 // When this object gets deleted while a menu is shown, this pointed
394 // element will be set to false.
395 bool* got_deleted_;
397 // True if a drag and drop operation created/pinned the item in the launcher
398 // and it needs to be deleted/unpinned again if the operation gets cancelled.
399 bool drag_and_drop_item_pinned_;
401 // The ShelfItem which is currently used for a drag and a drop operation
402 // or 0 otherwise.
403 ShelfID drag_and_drop_shelf_id_;
405 // The application ID of the application which we drag and drop.
406 std::string drag_and_drop_app_id_;
408 // The original launcher item's size before the dragging operation.
409 gfx::Size pre_drag_and_drop_size_;
411 // The image proxy for drag operations when a drag and drop host exists and
412 // the item can be dragged outside the app grid.
413 scoped_ptr<ash::DragImageView> drag_image_;
415 // The cursor offset to the middle of the dragged item.
416 gfx::Vector2d drag_image_offset_;
418 // The view which gets replaced by our drag icon proxy.
419 views::View* drag_replaced_view_;
421 // True when the icon was dragged off the shelf.
422 bool dragged_off_shelf_;
424 // The rip off view when a snap back operation is underway.
425 views::View* snap_back_from_rip_off_view_;
427 // Holds ShelfItemDelegateManager.
428 ShelfItemDelegateManager* item_manager_;
430 // Holds ShelfLayoutManager.
431 ShelfLayoutManager* layout_manager_;
433 // True when this ShelfView is used for Overflow Bubble.
434 bool overflow_mode_;
436 // Holds a pointer to main ShelfView when a ShelfView is in overflow mode.
437 ShelfView* main_shelf_;
439 // True when ripped item from overflow bubble is entered into Shelf.
440 bool dragged_off_from_overflow_to_shelf_;
442 // True if the event is a repost event from a event which has just closed the
443 // menu of the same shelf item.
444 bool is_repost_event_;
446 // Record the index for the last pressed shelf item. This variable is used to
447 // check if a repost event occurs on the same shelf item as previous one. If
448 // so, the repost event should be ignored.
449 int last_pressed_index_;
451 // Tracks UMA metrics based on shelf button press actions.
452 ShelfButtonPressedMetricTracker shelf_button_pressed_metric_tracker_;
454 DISALLOW_COPY_AND_ASSIGN(ShelfView);
457 } // namespace ash
459 #endif // ASH_SHELF_SHELF_VIEW_H_