msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 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 MASH_SHELF_SHELF_VIEW_H_ |
| 6 | #define MASH_SHELF_SHELF_VIEW_H_ |
| 7 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 8 | #include <string> |
| 9 | #include <utility> |
| 10 | #include <vector> |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 11 | |
| 12 | #include "base/macros.h" |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 13 | #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" |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 21 | #include "ui/views/controls/button/button.h" |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 22 | #include "ui/views/focus/focus_manager.h" |
| 23 | #include "ui/views/view.h" |
| 24 | #include "ui/views/view_model.h" |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 25 | |
| 26 | namespace mojo { |
ben | 3a7cbe0 | 2016-02-07 04:35:30 | [diff] [blame] | 27 | class Shell; |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 28 | } |
| 29 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 30 | namespace ui { |
| 31 | class MenuModel; |
| 32 | } |
| 33 | |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 34 | namespace views { |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 35 | class BoundsAnimator; |
| 36 | class MenuRunner; |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | namespace mash { |
| 40 | namespace shelf { |
| 41 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 42 | class ShelfButton; |
| 43 | |
| 44 | namespace test { |
| 45 | class ShelfViewTestAPI; |
| 46 | } |
| 47 | |
| 48 | extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM; |
| 49 | extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT; |
| 50 | extern const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT; |
| 51 | extern 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. |
| 55 | class ShelfView : public views::View, |
| 56 | public ShelfModelObserver, |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 57 | public views::ButtonListener, |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 58 | public ShelfButtonHost, |
| 59 | public views::ContextMenuController, |
| 60 | public views::FocusTraversable, |
| 61 | public views::BoundsAnimatorObserver { |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 62 | public: |
ben | 3a7cbe0 | 2016-02-07 04:35:30 | [diff] [blame] | 63 | explicit ShelfView(mojo::Shell* shell); |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 64 | ~ShelfView() override; |
| 65 | |
ben | 3a7cbe0 | 2016-02-07 04:35:30 | [diff] [blame] | 66 | mojo::Shell* shell() const { return shell_; } |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 67 | |
| 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 | |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 133 | private: |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 134 | 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; |
msw | ccf39414 | 2016-01-15 00:16:42 | [diff] [blame] | 233 | |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 234 | // Overridden from views::View: |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 235 | gfx::Size GetPreferredSize() const override; |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 236 | void OnBoundsChanged(const gfx::Rect& previous_bounds) override; |
| 237 | FocusTraversable* GetPaneFocusTraversable() override; |
| 238 | void GetAccessibleState(ui::AXViewState* state) override; |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 239 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 240 | /* 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; |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 267 | |
| 268 | // Overridden from views::ButtonListener: |
| 269 | void ButtonPressed(views::Button* sender, const ui::Event& event) override; |
| 270 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 271 | // 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); |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 279 | |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 280 | // 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. |
ben | 3a7cbe0 | 2016-02-07 04:35:30 | [diff] [blame] | 315 | mojo::Shell* shell_; |
msw | 16ae0289 | 2016-01-27 21:07:14 | [diff] [blame] | 316 | |
| 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_;*/ |
msw | 85273d0c | 2016-01-14 05:05:17 | [diff] [blame] | 447 | |
| 448 | DISALLOW_COPY_AND_ASSIGN(ShelfView); |
| 449 | }; |
| 450 | |
| 451 | } // namespace shelf |
| 452 | } // namespace mash |
| 453 | |
| 454 | #endif // MASH_SHELF_SHELF_VIEW_H_ |