15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
58bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "ash/shelf/shelf_view.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ash/ash_constants.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/ash_switches.h"
11a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ash/drag_drop/drag_image_view.h"
12d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "ash/metrics/user_metrics_recorder.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/root_window_controller.h"
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "ash/scoped_target_root_window.h"
15424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/alternate_app_list_button.h"
16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/app_list_button.h"
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/overflow_bubble.h"
18f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/overflow_bubble_view.h"
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/overflow_button.h"
20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_button.h"
21a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/shelf/shelf_delegate.h"
221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "ash/shelf/shelf_icon_observer.h"
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/shelf/shelf_item_delegate.h"
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/shelf/shelf_item_delegate_manager.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_layout_manager.h"
26a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "ash/shelf/shelf_menu_model.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_model.h"
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "ash/shelf/shelf_tooltip_manager.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ash/shelf/shelf_widget.h"
30d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)#include "ash/shell.h"
31f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/wm/coordinate_conversion.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
34f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "base/metrics/histogram.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ash_resources.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ash_strings.h"
37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ui/aura/client/screen_position_client.h"
38a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ui/aura/root_window.h"
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h"
4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/base/accessibility/accessible_view_state.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/simple_menu_model.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animator.h"
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_animation_duration_scale_mode.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h"
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gfx/point.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/animation/bounds_animator.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h"
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/image_button.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_model_adapter.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_runner.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/focus/focus_search.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_model.h"
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_model_utils.h"
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h"
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
59d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using gfx::Animation;
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using views::View;
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace ash {
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internal {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM = 0;
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT = 1;
67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT = 2;
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT = 3;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default amount content is inset on the left edge.
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultLeadingInset = 8;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum distance before drag starts.
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumDragDistance = 8;
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Size between the buttons.
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kButtonSpacing = 4;
78ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst int kAlternateButtonSpacing = 10;
79ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
80ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch// Size allocated to for each button.
81ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdochconst int kButtonSize = 44;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Additional spacing for the left and right side of icons.
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kHorizontalIconSpacing = 2;
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Inset for items which do not have an icon.
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kHorizontalNoIconInsetSpacing =
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    kHorizontalIconSpacing + kDefaultLeadingInset;
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The proportion of the launcher space reserved for non-panel icons. Panels
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// may flow into this space but will be put into the overflow bubble if there
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is contention for the space.
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kReservedNonPanelIconProportion = 0.67f;
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is the command id of the menu item which contains the name of the menu.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCommandIdOfMenuName = 0;
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The background color of the active item in the list.
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kActiveListItemBackgroundColor = SkColorSetRGB(203 , 219, 241);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The background color of the active & hovered item in the list.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kFocusedActiveListItemBackgroundColor =
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SkColorSetRGB(193, 211, 236);
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The text color of the caption item in a list.
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kCaptionItemForegroundColor = SK_ColorBLACK;
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum allowable length of a menu line of an application menu in pixels.
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaximumAppMenuItemLength = 350;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The distance of the cursor from the outer rim of the shelf before it
112f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// separates.
113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int kRipOffDistance = 48;
114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The rip off drag and drop proxy image should get scaled by this factor.
116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const float kDragAndDropProxyScale = 1.5f;
117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The opacity represents that this partially disappeared item will get removed.
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const float kDraggedImageOpacity = 0.5f;
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The MenuModelAdapter gets slightly changed to adapt the menu appearance to
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// our requirements.
125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ShelfMenuModelAdapter : public views::MenuModelAdapter {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit ShelfMenuModelAdapter(ShelfMenuModel* menu_model);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
129a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // views::MenuModelAdapter:
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual const gfx::Font* GetLabelFont(int command_id) const OVERRIDE;
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool IsCommandEnabled(int id) const OVERRIDE;
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void GetHorizontalIconMargins(int id,
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        int icon_size,
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        int* left_margin,
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        int* right_margin) const OVERRIDE;
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetForegroundColor(int command_id,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  bool is_hovered,
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  SkColor* override_color) const OVERRIDE;
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool GetBackgroundColor(int command_id,
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  bool is_hovered,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  SkColor* override_color) const OVERRIDE;
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual int GetMaxWidthForMenu(views::MenuItemView* menu) OVERRIDE;
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ShouldReserveSpaceForSubmenuIndicator() const OVERRIDE;
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfMenuModel* menu_model_;
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ShelfMenuModelAdapter);
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
151a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ShelfMenuModelAdapter::ShelfMenuModelAdapter(ShelfMenuModel* menu_model)
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : MenuModelAdapter(menu_model),
153a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      menu_model_(menu_model) {
154a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
156a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const gfx::Font* ShelfMenuModelAdapter::GetLabelFont(int command_id) const {
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (command_id != kCommandIdOfMenuName)
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return MenuModelAdapter::GetLabelFont(command_id);
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &rb.GetFont(ui::ResourceBundle::BoldFont);
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::IsCommandEnabled(int id) const {
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return id != kCommandIdOfMenuName;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::GetForegroundColor(int command_id,
169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               bool is_hovered,
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               SkColor* override_color) const {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (command_id != kCommandIdOfMenuName)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *override_color = kCaptionItemForegroundColor;
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::GetBackgroundColor(int command_id,
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               bool is_hovered,
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                               SkColor* override_color) const {
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!menu_model_->IsCommandActive(command_id))
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *override_color = is_hovered ? kFocusedActiveListItemBackgroundColor :
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 kActiveListItemBackgroundColor;
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ShelfMenuModelAdapter::GetHorizontalIconMargins(int command_id,
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                     int icon_size,
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                     int* left_margin,
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                     int* right_margin) const {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *left_margin = kHorizontalIconSpacing;
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *right_margin = (command_id != kCommandIdOfMenuName) ?
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      kHorizontalIconSpacing : -(icon_size + kHorizontalNoIconInsetSpacing);
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
198a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int ShelfMenuModelAdapter::GetMaxWidthForMenu(views::MenuItemView* menu) {
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return kMaximumAppMenuItemLength;
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
202a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::ShouldReserveSpaceForSubmenuIndicator() const {
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Custom FocusSearch used to navigate the launcher in the order items are in
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ViewModel.
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class LauncherFocusSearch : public views::FocusSearch {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit LauncherFocusSearch(views::ViewModel* view_model)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : FocusSearch(NULL, true, true),
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view_model_(view_model) {}
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~LauncherFocusSearch() {}
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // views::FocusSearch overrides:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual View* FindNextFocusableView(
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      View* starting_view,
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool reverse,
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Direction direction,
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool check_starting_view,
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      views::FocusTraversable** focus_traversable,
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      View** focus_traversable_view) OVERRIDE {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int index = view_model_->GetIndexOfView(starting_view);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (index == -1)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return view_model_->view_at(0);
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reverse) {
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      --index;
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index < 0)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index = view_model_->view_size() - 1;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++index;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (index >= view_model_->view_size())
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        index = 0;
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return view_model_->view_at(index);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::ViewModel* view_model_;
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(LauncherFocusSearch);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AnimationDelegate used when inserting a new item. This steadily increases the
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opacity of the layer as the animation progress.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class FadeInAnimationDelegate
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public views::BoundsAnimator::OwnedAnimationDelegate {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit FadeInAnimationDelegate(views::View* view) : view_(view) {}
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FadeInAnimationDelegate() {}
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AnimationDelegate overrides:
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationProgressed(const Animation* animation) OVERRIDE {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(animation->GetCurrentValue());
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->ScheduleDraw();
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationEnded(const Animation* animation) OVERRIDE {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1.0f);
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->ScheduleDraw();
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationCanceled(const Animation* animation) OVERRIDE {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1.0f);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->ScheduleDraw();
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view_;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FadeInAnimationDelegate);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
273f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ReflectItemStatus(const ash::LauncherItem& item, ShelfButton* button) {
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (item.status) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATUS_CLOSED:
276f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ACTIVE);
277f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_RUNNING);
278f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ATTENTION);
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATUS_RUNNING:
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ACTIVE);
282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->AddState(ShelfButton::STATE_RUNNING);
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ATTENTION);
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATUS_ACTIVE:
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->AddState(ShelfButton::STATE_ACTIVE);
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_RUNNING);
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ATTENTION);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATUS_ATTENTION:
291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_ACTIVE);
292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->ClearState(ShelfButton::STATE_RUNNING);
293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->AddState(ShelfButton::STATE_ATTENTION);
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AnimationDelegate used when deleting an item. This steadily decreased the
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opacity of the layer as the animation progress.
3028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class ShelfView::FadeOutAnimationDelegate
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public views::BoundsAnimator::OwnedAnimationDelegate {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  FadeOutAnimationDelegate(ShelfView* host, views::View* view)
3068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : shelf_view_(host),
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view_(view) {}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~FadeOutAnimationDelegate() {}
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AnimationDelegate overrides:
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationProgressed(const Animation* animation) OVERRIDE {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1 - animation->GetCurrentValue());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->ScheduleDraw();
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationEnded(const Animation* animation) OVERRIDE {
3168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    shelf_view_->OnFadeOutAnimationEnded();
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationCanceled(const Animation* animation) OVERRIDE {
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ShelfView* shelf_view_;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<views::View> view_;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(FadeOutAnimationDelegate);
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AnimationDelegate used to trigger fading an element in. When an item is
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inserted this delegate is attached to the animation that expands the size of
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the item.  When done it kicks off another animation to fade the item in.
3318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)class ShelfView::StartFadeAnimationDelegate
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public views::BoundsAnimator::OwnedAnimationDelegate {
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  StartFadeAnimationDelegate(ShelfView* host,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             views::View* view)
3368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      : shelf_view_(host),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view_(view) {}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~StartFadeAnimationDelegate() {}
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // AnimationDelegate overrides:
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationEnded(const Animation* animation) OVERRIDE {
3428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    shelf_view_->FadeIn(view_);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void AnimationCanceled(const Animation* animation) OVERRIDE {
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_->layer()->SetOpacity(1.0f);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ShelfView* shelf_view_;
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view_;
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ShelfView::ShelfView(ShelfModel* model,
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     ShelfDelegate* delegate,
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                     ShelfLayoutManager* manager)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : model_(model),
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delegate_(delegate),
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_model_(new views::ViewModel),
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      first_visible_index_(0),
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_visible_index_(-1),
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overflow_button_(NULL),
3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      owner_overflow_bubble_(NULL),
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_pointer_(NONE),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_view_(NULL),
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      drag_offset_(0),
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      start_drag_index_(-1),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      context_menu_id_(0),
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      leading_inset_(kDefaultLeadingInset),
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cancelling_drag_model_changed_(false),
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_hidden_index_(0),
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      closing_event_time_(base::TimeDelta()),
374b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      got_deleted_(NULL),
3757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      drag_and_drop_item_pinned_(false),
376424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      drag_and_drop_launcher_id_(0),
377424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      dragged_off_shelf_(false),
378424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      snap_back_from_rip_off_view_(NULL),
379a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()),
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      layout_manager_(manager),
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      overflow_mode_(false),
382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      main_shelf_(NULL),
383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dragged_off_from_overflow_to_shelf_(false) {
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(model_);
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_.reset(new views::BoundsAnimator(this));
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_->AddObserver(this);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_context_menu_controller(this);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  focus_search_.reset(new LauncherFocusSearch(view_model_.get()));
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  tooltip_.reset(new ShelfTooltipManager(manager, this));
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ShelfView::~ShelfView() {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_->RemoveObserver(this);
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->RemoveObserver(this);
395c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If we are inside the MenuRunner, we need to know if we were getting
396c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // deleted while it was running.
397c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (got_deleted_)
398c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    *got_deleted_ = true;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::Init() {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->AddObserver(this);
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const LauncherItems& items(model_->items());
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (LauncherItems::const_iterator i = items.begin(); i != items.end(); ++i) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* child = CreateViewForItem(*i);
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    child->SetPaintToLayer(true);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_model_->Add(child, static_cast<int>(i - items.begin()));
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildView(child);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShelfStatusChanged();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_ = new OverflowButton(this);
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_->set_context_menu_controller(this);
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureChildView(overflow_button_);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(overflow_button_);
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateFirstButtonPadding();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We'll layout when our bounds change.
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnShelfAlignmentChanged() {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateFirstButtonPadding();
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_button_->OnShelfAlignmentChanged();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LayoutToIdealBounds();
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i=0; i < view_model_->view_size(); ++i) {
426f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // TODO: remove when AppIcon is a Shelf Button.
427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    if (TYPE_APP_LIST == model_->items()[i].type &&
428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        !ash::switches::UseAlternateShelfLayout()) {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      static_cast<AppListButton*>(view_model_->view_at(i))->SetImageAlignment(
4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          layout_manager_->SelectValueForShelfAlignment(
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_CENTER,
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_LEFT,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_RIGHT,
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_CENTER),
4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          layout_manager_->SelectValueForShelfAlignment(
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_TOP,
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_MIDDLE,
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_MIDDLE,
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)              views::ImageButton::ALIGN_BOTTOM));
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i >= first_visible_index_ && i <= last_visible_index_)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      view_model_->view_at(i)->Layout();
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
444d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  tooltip_->Close();
445c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (overflow_bubble_)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overflow_bubble_->Hide();
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::SchedulePaintForAllButtons() {
450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  for (int i = 0; i < view_model_->view_size(); ++i) {
451ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (i >= first_visible_index_ && i <= last_visible_index_)
452ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view_model_->view_at(i)->SchedulePaint();
453ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
454ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (overflow_button_ && overflow_button_->visible())
455ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    overflow_button_->SchedulePaint();
456ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch}
457ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
4588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Rect ShelfView::GetIdealBoundsOfItemIcon(LauncherID id) {
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = model_->ItemIndexByID(id);
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (index == -1 || (index > last_visible_index_ &&
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      index < model_->FirstPanelIndex()))
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return gfx::Rect();
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect& ideal_bounds(view_model_->ideal_bounds(index));
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(TYPE_APP_LIST, model_->items()[index].type);
465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ShelfButton* button = static_cast<ShelfButton*>(view_model_->view_at(index));
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect icon_bounds = button->GetIconBounds();
467868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return gfx::Rect(GetMirroredXWithWidthInView(
468868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       ideal_bounds.x() + icon_bounds.x(), icon_bounds.width()),
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   ideal_bounds.y() + icon_bounds.y(),
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   icon_bounds.width(),
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   icon_bounds.height());
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::UpdatePanelIconPosition(LauncherID id,
4758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                        const gfx::Point& midpoint) {
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int current_index = model_->ItemIndexByID(id);
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int first_panel_index = model_->FirstPanelIndex();
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_index < first_panel_index)
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
481868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  gfx::Point midpoint_in_view(GetMirroredXInView(midpoint.x()),
482868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                              midpoint.y());
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int target_index = current_index;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (target_index > first_panel_index &&
4851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(
4861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             view_model_->ideal_bounds(target_index).x(),
4871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)             view_model_->ideal_bounds(target_index).y()) >
4881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(midpoint_in_view.x(),
4891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           midpoint_in_view.y())) {
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    --target_index;
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (target_index < view_model_->view_size() - 1 &&
4931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             view_model_->ideal_bounds(target_index).right(),
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             view_model_->ideal_bounds(target_index).bottom()) <
4961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(midpoint_in_view.x(),
4971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                           midpoint_in_view.y())) {
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++target_index;
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (current_index != target_index)
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model_->Move(current_index, target_index);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::IsShowingMenu() const {
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (launcher_menu_runner_.get() &&
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       launcher_menu_runner_->IsRunning());
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::IsShowingOverflowBubble() const {
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return overflow_bubble_.get() && overflow_bubble_->IsShowing();
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::View* ShelfView::GetAppListButtonView() const {
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < model_->item_count(); ++i) {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (model_->items()[i].type == TYPE_APP_LIST)
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return view_model_->view_at(i);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED() << "Applist button not found";
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
5248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)// ShelfView, FocusTraversable implementation:
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::FocusSearch* ShelfView::GetFocusSearch() {
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return focus_search_.get();
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::FocusTraversable* ShelfView::GetFocusTraversableParent() {
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return parent()->GetFocusTraversable();
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)View* ShelfView::GetFocusTraversableParentView() {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5388bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::CreateDragIconProxy(
539a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const gfx::Point& location_in_screen_coordinates,
540a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const gfx::ImageSkia& icon,
541a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    views::View* replaced_view,
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const gfx::Vector2d& cursor_offset_from_center,
543a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    float scale_factor) {
544a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_replaced_view_ = replaced_view;
545a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_.reset(new ash::internal::DragImageView(
5464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      drag_replaced_view_->GetWidget()->GetNativeWindow()->GetRootWindow(),
5474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE));
548a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_->SetImage(icon);
549a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  gfx::Size size = drag_image_->GetPreferredSize();
550a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  size.set_width(size.width() * scale_factor);
551a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  size.set_height(size.height() * scale_factor);
552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  drag_image_offset_ = gfx::Vector2d(size.width() / 2, size.height() / 2) +
553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       cursor_offset_from_center;
554a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  gfx::Rect drag_image_bounds(
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      location_in_screen_coordinates - drag_image_offset_,
556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      size);
557a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_->SetBoundsInScreen(drag_image_bounds);
558a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_->SetWidgetVisible(true);
559a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
560a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::UpdateDragIconProxy(
562a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const gfx::Point& location_in_screen_coordinates) {
563a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_->SetScreenPosition(
564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      location_in_screen_coordinates - drag_image_offset_);
565a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
566a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::DestroyDragIconProxy() {
568a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_.reset();
569a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_image_offset_ = gfx::Vector2d(0, 0);
570a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
571a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::StartDrag(const std::string& app_id,
5738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                          const gfx::Point& location_in_screen_coordinates) {
574b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Bail if an operation is already going on - or the cursor is not inside.
575b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // This could happen if mouse / touch operations overlap.
576b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (drag_and_drop_launcher_id_ ||
577b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      !GetBoundsInScreen().Contains(location_in_screen_coordinates))
578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
580b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // If the AppsGridView (which was dispatching this event) was opened by our
5818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // button, ShelfView dragging operations are locked and we have to unlock.
582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  CancelDrag(-1);
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  drag_and_drop_item_pinned_ = false;
584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  drag_and_drop_app_id_ = app_id;
585b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  drag_and_drop_launcher_id_ =
586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      delegate_->GetLauncherIDForAppID(drag_and_drop_app_id_);
5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // Check if the application is known and pinned - if not, we have to pin it so
5887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // that we can re-arrange the launcher order accordingly. Note that items have
5897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // to be pinned to give them the same (order) possibilities as a shortcut.
590a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // When an item is dragged from overflow to shelf, IsShowingOverflowBubble()
591a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // returns true. At this time, we don't need to pin the item.
592a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!IsShowingOverflowBubble() &&
593a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      (!drag_and_drop_launcher_id_ ||
594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       !delegate_->IsAppPinned(app_id))) {
595b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    delegate_->PinAppWithID(app_id);
596b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    drag_and_drop_launcher_id_ =
597b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        delegate_->GetLauncherIDForAppID(drag_and_drop_app_id_);
598b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (!drag_and_drop_launcher_id_)
599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      return false;
6007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    drag_and_drop_item_pinned_ = true;
601b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
602b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  views::View* drag_and_drop_view = view_model_->view_at(
603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      model_->ItemIndexByID(drag_and_drop_launcher_id_));
604b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  DCHECK(drag_and_drop_view);
605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
606a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Since there is already an icon presented by the caller, we hide this item
607a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // for now. That has to be done by reducing the size since the visibility will
608a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // change once a regrouping animation is performed.
609a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  pre_drag_and_drop_size_ = drag_and_drop_view->size();
610a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  drag_and_drop_view->SetSize(gfx::Size());
611a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
612b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // First we have to center the mouse cursor over the item.
613b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  gfx::Point pt = drag_and_drop_view->GetBoundsInScreen().CenterPoint();
614b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  views::View::ConvertPointFromScreen(drag_and_drop_view, &pt);
615f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point point_in_root = location_in_screen_coordinates;
616f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ash::wm::ConvertPointFromScreen(
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ash::wm::GetRootWindowAt(location_in_screen_coordinates),
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      &point_in_root);
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root, 0);
620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PointerPressedOnButton(drag_and_drop_view,
621f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         ShelfButtonHost::DRAG_AND_DROP,
622f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         event);
623b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
624b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Drag the item where it really belongs.
625b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  Drag(location_in_screen_coordinates);
626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::Drag(const gfx::Point& location_in_screen_coordinates) {
630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!drag_and_drop_launcher_id_ ||
631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      !GetBoundsInScreen().Contains(location_in_screen_coordinates))
632b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return false;
633b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  gfx::Point pt = location_in_screen_coordinates;
635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  views::View* drag_and_drop_view = view_model_->view_at(
636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      model_->ItemIndexByID(drag_and_drop_launcher_id_));
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ConvertPointFromScreen(drag_and_drop_view, &pt);
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point point_in_root = location_in_screen_coordinates;
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ash::wm::ConvertPointFromScreen(
640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ash::wm::GetRootWindowAt(location_in_screen_coordinates),
641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      &point_in_root);
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root, 0);
643f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  PointerDraggedOnButton(drag_and_drop_view,
644f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         ShelfButtonHost::DRAG_AND_DROP,
645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                         event);
646b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  return true;
647b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::EndDrag(bool cancel) {
650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  if (!drag_and_drop_launcher_id_)
651b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    return;
652b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  views::View* drag_and_drop_view = view_model_->view_at(
654b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      model_->ItemIndexByID(drag_and_drop_launcher_id_));
655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  PointerReleasedOnButton(
656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      drag_and_drop_view, ShelfButtonHost::DRAG_AND_DROP, cancel);
657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
658a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Either destroy the temporarily created item - or - make the item visible.
6597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (drag_and_drop_item_pinned_ && cancel)
660424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    delegate_->UnpinAppWithID(drag_and_drop_app_id_);
66158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  else if (drag_and_drop_view) {
66258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    if (cancel) {
66358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // When a hosted drag gets canceled, the item can remain in the same slot
66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // and it might have moved within the bounds. In that case the item need
66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      // to animate back to its correct location.
66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      AnimateToIdealBounds();
66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else {
66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      drag_and_drop_view->SetSize(pre_drag_and_drop_size_);
66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    }
67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
671b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
672b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  drag_and_drop_launcher_id_ = 0;
673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
674b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
6758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::LayoutToIdealBounds() {
6761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (bounds_animator_->IsAnimating()) {
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AnimateToIdealBounds();
6781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return;
6791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  }
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  IdealBounds ideal_bounds;
6821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  CalculateIdealBounds(&ideal_bounds);
6831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_);
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds);
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ShelfView::UpdateAllButtonsVisibilityInOverflowMode() {
688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // The overflow button is not shown in overflow mode.
689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  overflow_button_->SetVisible(false);
690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int last_button_index = model_->FirstPanelIndex() - 1;
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK_LT(last_visible_index_, view_model_->view_size());
692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (int i = 0; i < view_model_->view_size(); ++i) {
693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    bool visible = i >= first_visible_index_ &&
694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        i <= last_visible_index_;
695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!ash::switches::UseAlternateShelfLayout())
696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      visible &= i != last_button_index;
697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // To track the dragging of |drag_view_| continuously, its visibility
699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // should be always true regardless of its position.
700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (dragged_off_from_overflow_to_shelf_ &&
701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        view_model_->view_at(i) == drag_view_)
702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      view_model_->view_at(i)->SetVisible(true);
703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    else
704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      view_model_->view_at(i)->SetVisible(visible);
705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
706a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
707a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
7088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::CalculateIdealBounds(IdealBounds* bounds) {
7091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int available_size = layout_manager_->PrimaryAxisValue(width(), height());
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(model_->item_count() == view_model_->view_size());
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!available_size)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int first_panel_index = model_->FirstPanelIndex();
715ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int last_button_index = first_panel_index - 1;
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initial x,y values account both leading_inset in primary
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // coordinate and secondary coordinate based on the dynamic edge of the
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // launcher (eg top edge on bottom-aligned launcher).
7201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int inset = ash::switches::UseAlternateShelfLayout() ? 0 : leading_inset_;
7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int x = layout_manager_->SelectValueForShelfAlignment(inset, 0, 0, inset);
7221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int y = layout_manager_->SelectValueForShelfAlignment(0, inset, inset, 0);
723ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
724f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int button_size = GetButtonSize();
725f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int button_spacing = GetButtonSpacing();
726ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
7271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int w = layout_manager_->PrimaryAxisValue(button_size, width());
7281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int h = layout_manager_->PrimaryAxisValue(height(), button_size);
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < view_model_->view_size(); ++i) {
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i < first_visible_index_) {
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0));
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
736ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (i != last_button_index) {
7371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      x = layout_manager_->PrimaryAxisValue(x + w + button_spacing, x);
7381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      y = layout_manager_->PrimaryAxisValue(y, y + h + button_spacing);
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_overflow_mode()) {
743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    UpdateAllButtonsVisibilityInOverflowMode();
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // To address Fitt's law, we make the first launcher button include the
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // leading inset (if there is one).
749ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!ash::switches::UseAlternateShelfLayout()) {
750ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (view_model_->view_size() > 0) {
751ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view_model_->set_ideal_bounds(0, gfx::Rect(gfx::Size(
7521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          layout_manager_->PrimaryAxisValue(inset + w, w),
7531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          layout_manager_->PrimaryAxisValue(h, inset + h))));
754ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Right aligned icons.
758ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  int end_position = available_size - button_spacing;
7591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  x = layout_manager_->PrimaryAxisValue(end_position, 0);
7601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  y = layout_manager_->PrimaryAxisValue(0, end_position);
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (int i = view_model_->view_size() - 1;
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       i >= first_panel_index; --i) {
7631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    x = layout_manager_->PrimaryAxisValue(x - w - button_spacing, x);
7641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    y = layout_manager_->PrimaryAxisValue(y, y - h - button_spacing);
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
7661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    end_position = layout_manager_->PrimaryAxisValue(x, y);
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Icons on the left / top are guaranteed up to kLeftIconProportion of
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the available space.
7711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  int last_icon_position = layout_manager_->PrimaryAxisValue(
772ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view_model_->ideal_bounds(last_button_index).right(),
773ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view_model_->ideal_bounds(last_button_index).bottom())
774ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      + button_size + inset;
775ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (!ash::switches::UseAlternateShelfLayout())
776ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      last_icon_position += button_size;
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int reserved_icon_space = available_size * kReservedNonPanelIconProportion;
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (last_icon_position < reserved_icon_space)
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    end_position = last_icon_position;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  else
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    end_position = std::max(end_position, reserved_icon_space);
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  bounds->overflow_bounds.set_size(
7841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      gfx::Size(layout_manager_->PrimaryAxisValue(w, width()),
7851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                layout_manager_->PrimaryAxisValue(height(), h)));
7864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
7874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (ash::switches::UseAlternateShelfLayout()) {
788ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    last_visible_index_ = DetermineLastVisibleIndex(
789ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        end_position - button_size);
7904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  } else {
791ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    last_visible_index_ = DetermineLastVisibleIndex(
792ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        end_position - inset - 2 * button_size);
7934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  }
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_hidden_index_ = DetermineFirstVisiblePanelIndex(end_position) - 1;
795ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool show_overflow =
796ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      ((ash::switches::UseAlternateShelfLayout() ? 0 : 1) +
797ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      last_visible_index_ < last_button_index ||
798ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      last_hidden_index_ >= first_panel_index);
799ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
800ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // Create Space for the overflow button
801ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (show_overflow && ash::switches::UseAlternateShelfLayout() &&
80258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      last_visible_index_ > 0 && last_visible_index_ < last_button_index)
803ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    --last_visible_index_;
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < view_model_->view_size(); ++i) {
805ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bool visible = i <= last_visible_index_ || i > last_hidden_index_;
806ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    // Always show the app list.
807ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!ash::switches::UseAlternateShelfLayout())
808ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      visible |= (i == last_button_index);
8094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // To receive drag event continously from |drag_view_| during the dragging
8104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // off from the shelf, don't make |drag_view_| invisible. It will be
8114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // eventually invisible and removed from the |view_model_| by
8124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // FinalizeRipOffDrag().
8134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    if (dragged_off_shelf_ && view_model_->view_at(i) == drag_view_)
8144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      continue;
815ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    view_model_->view_at(i)->SetVisible(visible);
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_->SetVisible(show_overflow);
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (show_overflow) {
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_NE(0, view_model_->view_size());
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_visible_index_ == -1) {
8221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      x = layout_manager_->SelectValueForShelfAlignment(inset, 0, 0, inset);
8231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      y = layout_manager_->SelectValueForShelfAlignment(0, inset, inset, 0);
82458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    } else if (last_visible_index_ == last_button_index
82558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        && !ash::switches::UseAlternateShelfLayout()) {
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      x = view_model_->ideal_bounds(last_visible_index_).x();
8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      y = view_model_->ideal_bounds(last_visible_index_).y();
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
8291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      x = layout_manager_->PrimaryAxisValue(
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          view_model_->ideal_bounds(last_visible_index_).right(),
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          view_model_->ideal_bounds(last_visible_index_).x());
8321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      y = layout_manager_->PrimaryAxisValue(
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          view_model_->ideal_bounds(last_visible_index_).y(),
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          view_model_->ideal_bounds(last_visible_index_).bottom());
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Set all hidden panel icon positions to be on the overflow button.
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (int i = first_panel_index; i <= last_hidden_index_; ++i)
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h));
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Add more space between last visible item and overflow button.
8411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    // Without this, two buttons look too close compared with other items.
8421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (ash::switches::UseAlternateShelfLayout()) {
8431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      x = layout_manager_->PrimaryAxisValue(x + button_spacing, x);
8441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      y = layout_manager_->PrimaryAxisValue(y, y + button_spacing);
8451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    }
8461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
847ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bounds->overflow_bounds.set_x(x);
848ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    bounds->overflow_bounds.set_y(y);
849ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    if (!ash::switches::UseAlternateShelfLayout()) {
850ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      // Position app list after overflow button.
851ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      gfx::Rect app_list_bounds = view_model_->ideal_bounds(last_button_index);
852ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
8531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      x = layout_manager_->PrimaryAxisValue(x + w + button_spacing, x);
8541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      y = layout_manager_->PrimaryAxisValue(y, y + h + button_spacing);
855ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      app_list_bounds.set_x(x);
856ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      app_list_bounds.set_y(y);
857ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      view_model_->set_ideal_bounds(last_button_index, app_list_bounds);
858ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    }
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (overflow_bubble_.get() && overflow_bubble_->IsShowing())
8608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      UpdateOverflowRange(overflow_bubble_->shelf_view());
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
862c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (overflow_bubble_)
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      overflow_bubble_->Hide();
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::DetermineLastVisibleIndex(int max_value) const {
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int index = model_->FirstPanelIndex() - 1;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (index >= 0 &&
8701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             view_model_->ideal_bounds(index).right(),
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             view_model_->ideal_bounds(index).bottom()) > max_value) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    index--;
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return index;
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::DetermineFirstVisiblePanelIndex(int min_value) const {
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int index = model_->FirstPanelIndex();
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  while (index < view_model_->view_size() &&
8811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)         layout_manager_->PrimaryAxisValue(
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             view_model_->ideal_bounds(index).right(),
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             view_model_->ideal_bounds(index).bottom()) < min_value) {
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ++index;
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return index;
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::AddIconObserver(ShelfIconObserver* observer) {
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.AddObserver(observer);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::RemoveIconObserver(ShelfIconObserver* observer) {
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  observers_.RemoveObserver(observer);
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::AnimateToIdealBounds() {
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdealBounds ideal_bounds;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdealBounds(&ideal_bounds);
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < view_model_->view_size(); ++i) {
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    View* view = view_model_->view_at(i);
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i));
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Now that the item animation starts, we have to make sure that the
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // padding of the first gets properly transferred to the new first item.
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i && view->border())
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      view->set_border(NULL);
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else if (!i && !view->border())
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      UpdateFirstButtonPadding();
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds);
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::View* ShelfView::CreateViewForItem(const LauncherItem& item) {
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view = NULL;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (item.type) {
91690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case TYPE_BROWSER_SHORTCUT:
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_APP_SHORTCUT:
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case TYPE_WINDOWED_APP:
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_PLATFORM_APP:
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_APP_PANEL: {
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShelfButton* button = ShelfButton::Create(this, this, layout_manager_);
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button->SetImage(item.image);
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReflectItemStatus(item, button);
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view = button;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_APP_LIST: {
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (ash::switches::UseAlternateShelfLayout()) {
9301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        view = new AlternateAppListButton(this,
9311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                          this,
9321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                          layout_manager_->shelf_widget());
933eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      } else {
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // TODO(dave): turn this into a ShelfButton too.
935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        AppListButton* button = new AppListButton(this, this);
936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        button->SetImageAlignment(
9371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            layout_manager_->SelectValueForShelfAlignment(
938eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_CENTER,
939eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_LEFT,
940eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_RIGHT,
941eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_CENTER),
9421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)            layout_manager_->SelectValueForShelfAlignment(
943eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_TOP,
944eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_MIDDLE,
945eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_MIDDLE,
946eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                views::ImageButton::ALIGN_BOTTOM));
947eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        view = button;
948eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      }
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->set_context_menu_controller(this);
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(view);
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ConfigureChildView(view);
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return view;
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::FadeIn(views::View* view) {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetVisible(true);
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->layer()->SetOpacity(0);
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnimateToIdealBounds();
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_->SetAnimationDelegate(
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view, new FadeInAnimationDelegate(view), true);
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event) {
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!dragging());
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(drag_view_);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_pointer_ = pointer;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  start_drag_index_ = view_model_->GetIndexOfView(drag_view_);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
976424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (start_drag_index_== -1) {
977424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    CancelDrag(-1);
978424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
979424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
980424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the item is no longer draggable, bail out.
982a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
9834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      model_->items()[start_drag_index_].id);
9844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!item_delegate->IsDraggable()) {
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelDrag(-1);
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Move the view to the front so that it appears on top of other views.
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReorderChildView(drag_view_, -1);
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_->StopAnimatingView(drag_view_);
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ContinueDrag(const ui::LocatedEvent& event) {
995424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Due to a syncing operation the application might have been removed.
996424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Bail if it is gone.
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int current_index = view_model_->GetIndexOfView(drag_view_);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(-1, current_index);
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1000a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
10014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      model_->items()[current_index].id);
10024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (!item_delegate->IsDraggable()) {
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelDrag(-1);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1007424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If this is not a drag and drop host operation and not the app list item,
1008424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // check if the item got ripped off the shelf - if it did we are done.
1009424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!drag_and_drop_launcher_id_ && ash::switches::UseDragOffShelf() &&
1010424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      RemovableByRipOff(current_index) != NOT_REMOVABLE) {
1011424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (HandleRipOffDrag(event))
1012424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return;
1013424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // The rip off handler could have changed the location of the item.
1014424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    current_index = view_model_->GetIndexOfView(drag_view_);
1015424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1016424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1017424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO: I don't think this works correctly with RTL.
1018424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  gfx::Point drag_point(event.location());
1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ConvertPointToTarget(drag_view_, this, &drag_point);
1020424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Constrain the location to the range of valid indices for the type.
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::pair<int, int> indices(GetDragRange(current_index));
10232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int first_drag_index = indices.first;
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int last_drag_index = indices.second;
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the last index isn't valid, we're overflowing. Constrain to the app list
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (which is the last visible item).
10272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (first_drag_index < model_->FirstPanelIndex() &&
10282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_drag_index > last_visible_index_)
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_drag_index = last_visible_index_;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int x = 0, y = 0;
10311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (layout_manager_->IsHorizontalAlignment()) {
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = std::max(view_model_->ideal_bounds(indices.first).x(),
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     drag_point.x() - drag_offset_);
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    x = std::min(view_model_->ideal_bounds(last_drag_index).right() -
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 view_model_->ideal_bounds(current_index).width(),
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 x);
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (drag_view_->x() == x)
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_view_->SetX(x);
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y = std::max(view_model_->ideal_bounds(indices.first).y(),
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     drag_point.y() - drag_offset_);
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    y = std::min(view_model_->ideal_bounds(last_drag_index).bottom() -
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 view_model_->ideal_bounds(current_index).height(),
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 y);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (drag_view_->y() == y)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_view_->SetY(y);
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int target_index =
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      views::ViewModelUtils::DetermineMoveIndex(
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *view_model_, drag_view_,
10541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          layout_manager_->IsHorizontalAlignment() ?
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              views::ViewModelUtils::HORIZONTAL :
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              views::ViewModelUtils::VERTICAL,
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          x, y);
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  target_index =
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::min(indices.second, std::max(target_index, indices.first));
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (target_index == current_index)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Change the model, the LauncherItemMoved() callback will handle the
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |view_model_| update.
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->Move(current_index, target_index);
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bounds_animator_->StopAnimatingView(drag_view_);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::HandleRipOffDrag(const ui::LocatedEvent& event) {
1070424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int current_index = view_model_->GetIndexOfView(drag_view_);
1071424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK_NE(-1, current_index);
1072a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string dragged_app_id =
1073a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      delegate_->GetAppIDForLauncherID(model_->items()[current_index].id);
1074f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1075f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point screen_location = event.root_location();
1076f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  ash::wm::ConvertPointToScreen(GetWidget()->GetNativeWindow()->GetRootWindow(),
1077f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                &screen_location);
1078f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1079424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // To avoid ugly forwards and backwards flipping we use different constants
1080424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // for ripping off / re-inserting the items.
1081424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (dragged_off_shelf_) {
1082f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // If the shelf/overflow bubble bounds contains |screen_location| we insert
1083f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // the item back into the shelf.
1084f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (GetBoundsForDragInsertInScreen().Contains(screen_location)) {
1085a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (dragged_off_from_overflow_to_shelf_) {
1086a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // During the dragging an item from Shelf to Overflow, it can enter here
1087a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // directly because both are located very closly.
1088a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        main_shelf_->EndDrag(true);
1089a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // Stops the animation of |drag_view_| and sets its bounds explicitly
1090a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // becase ContinueDrag() stops its animation. Without this, unexpected
1091a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        // bounds will be set.
1092a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        bounds_animator_->StopAnimatingView(drag_view_);
1093a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        int drag_view_index = view_model_->GetIndexOfView(drag_view_);
1094a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        drag_view_->SetBoundsRect(view_model_->ideal_bounds(drag_view_index));
1095a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        dragged_off_from_overflow_to_shelf_ = false;
1096a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
1097424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Destroy our proxy view item.
1098424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      DestroyDragIconProxy();
1099424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Re-insert the item and return simply false since the caller will handle
1100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // the move as in any normal case.
1101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      dragged_off_shelf_ = false;
1102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      drag_view_->layer()->SetOpacity(1.0f);
1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // The size of Overflow bubble should be updated immediately when an item
1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // is re-inserted.
1105f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (is_overflow_mode())
1106f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        PreferredSizeChanged();
1107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return false;
1108a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (is_overflow_mode() &&
1109a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               main_shelf_->GetBoundsForDragInsertInScreen().Contains(
1110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   screen_location)) {
1111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (!dragged_off_from_overflow_to_shelf_) {
1112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        dragged_off_from_overflow_to_shelf_ = true;
1113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        drag_image_->SetOpacity(1.0f);
1114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        main_shelf_->StartDrag(dragged_app_id, screen_location);
1115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      } else {
1116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        main_shelf_->Drag(screen_location);
1117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      }
1118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (dragged_off_from_overflow_to_shelf_) {
1119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Makes the |drag_image_| partially disappear again.
1120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dragged_off_from_overflow_to_shelf_ = false;
1121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      drag_image_->SetOpacity(kDraggedImageOpacity);
1122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      main_shelf_->EndDrag(true);
1123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      bounds_animator_->StopAnimatingView(drag_view_);
1124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      int drag_view_index = view_model_->GetIndexOfView(drag_view_);
1125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      drag_view_->SetBoundsRect(view_model_->ideal_bounds(drag_view_index));
1126424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Move our proxy view item.
1128f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    UpdateDragIconProxy(screen_location);
1129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
1130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Check if we are too far away from the shelf to enter the ripped off state.
1132f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Determine the distance to the shelf.
1133d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)  int delta = CalculateShelfDistance(screen_location);
1134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (delta > kRipOffDistance) {
1135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    // Create a proxy view item which can be moved anywhere.
1136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ShelfButton* button = static_cast<ShelfButton*>(drag_view_);
1137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    CreateDragIconProxy(event.root_location(),
1138424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                        button->GetImage(),
1139424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                        drag_view_,
1140424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                        gfx::Vector2d(0, 0),
1141424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)                        kDragAndDropProxyScale);
1142424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    drag_view_->layer()->SetOpacity(0.0f);
11434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    dragged_off_shelf_ = true;
1144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (RemovableByRipOff(current_index) == REMOVABLE) {
11451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // Move the item to the front of the first panel item and hide it.
11461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // LauncherItemMoved() callback will handle the |view_model_| update and
11471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      // call AnimateToIdealBounds().
1148f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (current_index != model_->FirstPanelIndex() - 1) {
1149f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        model_->Move(current_index, model_->FirstPanelIndex() - 1);
1150f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        StartFadeInLastVisibleItem();
1151f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      } else if (is_overflow_mode()) {
1152f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        // Overflow bubble should be shrunk when an item is ripped off.
1153f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        PreferredSizeChanged();
1154f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
1155424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Make the item partially disappear to show that it will get removed if
1156424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // dropped.
1157a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      drag_image_->SetOpacity(kDraggedImageOpacity);
1158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
1160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return false;
1162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
1163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
11648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::FinalizeRipOffDrag(bool cancel) {
1165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!dragged_off_shelf_)
1166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
1167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Make sure we do not come in here again.
1168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  dragged_off_shelf_ = false;
1169424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Coming here we should always have a |drag_view_|.
1171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DCHECK(drag_view_);
1172424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int current_index = view_model_->GetIndexOfView(drag_view_);
1173424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // If the view isn't part of the model anymore (|current_index| == -1), a sync
1174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // operation must have removed it. In that case we shouldn't change the model
1175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // and only delete the proxy image.
1176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (current_index == -1) {
1177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    DestroyDragIconProxy();
1178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
1179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1181424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Set to true when the animation should snap back to where it was before.
1182424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  bool snap_back = false;
1183424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Items which cannot be dragged off will be handled as a cancel.
1184424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!cancel) {
1185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (dragged_off_from_overflow_to_shelf_) {
1186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dragged_off_from_overflow_to_shelf_ = false;
1187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      main_shelf_->EndDrag(false);
1188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      drag_view_->layer()->SetOpacity(1.0f);
1189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (RemovableByRipOff(current_index) != REMOVABLE) {
1190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Make sure we do not try to remove un-removable items like items which
1191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // were not pinned or have to be always there.
1192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      cancel = true;
1193424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      snap_back = true;
1194424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    } else {
1195424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Make sure the item stays invisible upon removal.
1196424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      drag_view_->SetVisible(false);
1197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      std::string app_id =
1198424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          delegate_->GetAppIDForLauncherID(model_->items()[current_index].id);
1199424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      delegate_->UnpinAppWithID(app_id);
1200424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1202424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (cancel || snap_back) {
1203a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (dragged_off_from_overflow_to_shelf_) {
1204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dragged_off_from_overflow_to_shelf_ = false;
1205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      // Main shelf handles revert of dragged item.
1206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      main_shelf_->EndDrag(true);
1207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      drag_view_->layer()->SetOpacity(1.0f);
1208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (!cancelling_drag_model_changed_) {
1209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Only do something if the change did not come through a model change.
1210424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      gfx::Rect drag_bounds = drag_image_->GetBoundsInScreen();
1211424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      gfx::Point relative_to = GetBoundsInScreen().origin();
1212424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      gfx::Rect target(
1213424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          gfx::PointAtOffsetFromOrigin(drag_bounds.origin()- relative_to),
1214424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          drag_bounds.size());
1215424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      drag_view_->SetBoundsRect(target);
1216424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // Hide the status from the active item since we snap it back now. Upon
1217424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // animation end the flag gets cleared if |snap_back_from_rip_off_view_|
1218424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // is set.
1219424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      snap_back_from_rip_off_view_ = drag_view_;
1220f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShelfButton* button = static_cast<ShelfButton*>(drag_view_);
1221f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      button->AddState(ShelfButton::STATE_HIDDEN);
1222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // When a canceling drag model is happening, the view model is diverged
1223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // from the menu model and movements / animations should not be done.
1224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      model_->Move(current_index, start_drag_index_);
1225424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      AnimateToIdealBounds();
1226424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1227424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    drag_view_->layer()->SetOpacity(1.0f);
1228424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
1229424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  DestroyDragIconProxy();
1230424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
1231424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
12328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ShelfView::RemovableState ShelfView::RemovableByRipOff(int index) {
1233f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DCHECK(index >= 0 && index < model_->item_count());
1234424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  LauncherItemType type = model_->items()[index].type;
123558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  if (type == TYPE_APP_LIST || !delegate_->CanPin())
1236424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return NOT_REMOVABLE;
1237424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  std::string app_id =
1238424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      delegate_->GetAppIDForLauncherID(model_->items()[index].id);
1239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // Note: Only pinned app shortcuts can be removed!
1240424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return (type == TYPE_APP_SHORTCUT && delegate_->IsAppPinned(app_id)) ?
1241424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      REMOVABLE : DRAGGABLE;
1242424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
1243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
12448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::SameDragType(LauncherItemType typea,
12458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                             LauncherItemType typeb) const {
1246ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  switch (typea) {
1247ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case TYPE_APP_SHORTCUT:
1248ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case TYPE_BROWSER_SHORTCUT:
1249ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT);
125068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    case TYPE_APP_LIST:
1251424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case TYPE_PLATFORM_APP:
1252ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case TYPE_WINDOWED_APP:
1253ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    case TYPE_APP_PANEL:
1254ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      return typeb == typea;
1255424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case TYPE_UNDEFINED:
1256424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      NOTREACHED() << "LauncherItemType must be set.";
1257424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      return false;
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::pair<int, int> ShelfView::GetDragRange(int index) {
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int min_index = -1;
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int max_index = -1;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LauncherItemType type = model_->items()[index].type;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < model_->item_count(); ++i) {
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (SameDragType(model_->items()[i].type, type)) {
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (min_index == -1)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        min_index = i;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      max_index = i;
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::pair<int, int>(min_index, max_index);
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ConfigureChildView(views::View* view) {
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetPaintToLayer(true);
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->layer()->SetFillsBoundsOpaquely(false);
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ToggleOverflowBubble() {
12832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (IsShowingOverflowBubble()) {
12842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    overflow_bubble_->Hide();
12852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
12862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!overflow_bubble_)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overflow_bubble_.reset(new OverflowBubble());
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  ShelfView* overflow_view =
12921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)      new ShelfView(model_, delegate_, layout_manager_);
1293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  overflow_view->overflow_mode_ = true;
12942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_view->Init();
12954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  overflow_view->set_owner_overflow_bubble(overflow_bubble_.get());
12962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_view->OnShelfAlignmentChanged();
1297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  overflow_view->main_shelf_ = this;
12982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateOverflowRange(overflow_view);
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_bubble_->Show(overflow_button_, overflow_view);
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::GetInstance()->UpdateShelfVisibility();
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::UpdateFirstButtonPadding() {
1306ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (ash::switches::UseAlternateShelfLayout())
1307ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
1308ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Creates an empty border for first launcher button to make included leading
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inset act as the button's padding. This is only needed on button creation
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and when shelf alignment changes.
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_model_->view_size() > 0) {
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_model_->view_at(0)->set_border(views::Border::CreateEmptyBorder(
13141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        layout_manager_->PrimaryAxisValue(0, leading_inset_),
13151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        layout_manager_->PrimaryAxisValue(leading_inset_, 0),
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0,
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        0));
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnFadeOutAnimationEnded() {
13222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AnimateToIdealBounds();
13231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  StartFadeInLastVisibleItem();
13241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}
13252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::StartFadeInLastVisibleItem() {
13272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If overflow button is visible and there is a valid new last item, fading
13282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the new last item in after sliding animation is finished.
13292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (overflow_button_->visible() && last_visible_index_ >= 0) {
13302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    views::View* last_visible_view = view_model_->view_at(last_visible_index_);
13312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_visible_view->layer()->SetOpacity(0);
13322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bounds_animator_->SetAnimationDelegate(
13332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        last_visible_view,
13348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        new ShelfView::StartFadeAnimationDelegate(this, last_visible_view),
13352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        true);
13362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
13372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::UpdateOverflowRange(ShelfView* overflow_view) {
13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int first_overflow_index = last_visible_index_ + 1;
13412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const int last_overflow_index = last_hidden_index_;
13422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LE(first_overflow_index, last_overflow_index);
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_LT(last_overflow_index, view_model_->view_size());
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_view->first_visible_index_ = first_overflow_index;
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  overflow_view->last_visible_index_ = last_overflow_index;
13472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1349f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int ShelfView::GetButtonSize() const {
1350f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ash::switches::UseAlternateShelfLayout() ?
1351f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kButtonSize : kLauncherPreferredSize;
1352f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int ShelfView::GetButtonSpacing() const {
1355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return ash::switches::UseAlternateShelfLayout() ?
1356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      kAlternateButtonSpacing : kButtonSpacing;
1357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
13598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) {
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  gfx::Rect active_bounds;
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < child_count(); ++i) {
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* child = child_at(i);
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (child == overflow_button_)
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!ShouldShowTooltipForView(child))
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    gfx::Rect child_bounds = child->GetMirroredBounds();
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    active_bounds.Union(child_bounds);
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !active_bounds.Contains(cursor_location);
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() {
13774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Size preferred_size = GetPreferredSize();
13784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
13794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ConvertPointToScreen(this, &origin);
13804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return gfx::Rect(origin, preferred_size);
13814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)}
13824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1383f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() {
1384f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Size preferred_size;
1385f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (is_overflow_mode()) {
1386f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DCHECK(owner_overflow_bubble_);
1387f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect bubble_bounds =
1388f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        owner_overflow_bubble_->bubble_view()->GetBubbleBounds();
1389f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    preferred_size = bubble_bounds.size();
1390f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  } else {
1391f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const int preferred_shelf_size = layout_manager_->GetPreferredShelfSize();
1392f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1393f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const int last_button_index = view_model_->view_size() - 1;
1394f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    gfx::Rect last_button_bounds =
1395f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        view_model_->view_at(last_button_index)->bounds();
1396f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (overflow_button_->visible() &&
1397f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        model_->GetItemIndexForType(TYPE_APP_PANEL) == -1) {
1398f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // When overflow button is visible and shelf has no panel items,
1399f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // last_button_bounds should be overflow button's bounds.
1400f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      last_button_bounds = overflow_button_->bounds();
1401f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1402f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1403f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (layout_manager_->IsHorizontalAlignment()) {
1404f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      preferred_size = gfx::Size(last_button_bounds.right() + leading_inset_,
1405f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 preferred_shelf_size);
1406f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    } else {
1407f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      preferred_size = gfx::Size(preferred_shelf_size,
1408f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 last_button_bounds.bottom() + leading_inset_);
1409f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
1410f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
1411f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0);
1412f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1413f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // In overflow mode, we should use OverflowBubbleView as a source for
1414f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // converting |origin| to screen coordinates. When a scroll operation is
1415f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // occurred in OverflowBubble, the bounds of ShelfView in OverflowBubble can
1416f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // be changed.
1417f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (is_overflow_mode())
1418f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ConvertPointToScreen(owner_overflow_bubble_->bubble_view(), &origin);
1419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  else
1420f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    ConvertPointToScreen(this, &origin);
1421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return gfx::Rect(origin, preferred_size);
1423f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
1424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::CancelDrag(int modified_index) {
1426424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  FinalizeRipOffDrag(true);
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!drag_view_)
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return modified_index;
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_dragging = dragging();
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int drag_view_index = view_model_->GetIndexOfView(drag_view_);
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_pointer_ = NONE;
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_view_ = NULL;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_view_index == modified_index) {
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The view that was being dragged is being modified. Don't do anything.
14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return modified_index;
14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!was_dragging)
14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return modified_index;
14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Restore previous position, tracking the position of the modified view.
14412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool at_end = modified_index == view_model_->view_size();
14422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::View* modified_view =
14432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (modified_index >= 0 && !at_end) ?
14442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      view_model_->view_at(modified_index) : NULL;
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_->Move(drag_view_index, start_drag_index_);
14462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the modified view will be at the end of the list, return the new end of
14482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the list.
14492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (at_end)
14502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return view_model_->view_size();
14512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return modified_view ? view_model_->GetIndexOfView(modified_view) : -1;
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Size ShelfView::GetPreferredSize() {
14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdealBounds ideal_bounds;
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdealBounds(&ideal_bounds);
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int preferred_size = layout_manager_->GetPreferredShelfSize();
14594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1460f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  int last_button_index = is_overflow_mode() ?
1461f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      last_visible_index_ : view_model_->view_size() - 1;
1462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1463f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // When an item is dragged off from the overflow bubble, it is moved to last
1464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // position and and changed to invisible. Overflow bubble size should be
1465f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // shrunk to fit only for visible items.
1466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // If |dragged_off_from_overflow_to_shelf_| is set, there will be no invisible
1467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // items in the shelf.
1468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (is_overflow_mode() &&
1469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      dragged_off_shelf_ &&
1470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !dragged_off_from_overflow_to_shelf_ &&
1471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      RemovableByRipOff(view_model_->GetIndexOfView(drag_view_)) == REMOVABLE)
1472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    last_button_index--;
1473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const gfx::Rect last_button_bounds =
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last_button_index  >= first_visible_index_ ?
1476f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          view_model_->ideal_bounds(last_button_index) :
14774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          gfx::Rect(gfx::Size(preferred_size, preferred_size));
14782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
14791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  if (layout_manager_->IsHorizontalAlignment()) {
14801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    return gfx::Size(last_button_bounds.right() + leading_inset_,
14814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                     preferred_size);
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return gfx::Size(preferred_size,
14851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                   last_button_bounds.bottom() + leading_inset_);
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LayoutToIdealBounds();
14901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  FOR_EACH_OBSERVER(ShelfIconObserver, observers_,
14911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    OnShelfIconPositionsChanged());
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsShowingOverflowBubble())
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    overflow_bubble_->Hide();
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::FocusTraversable* ShelfView::GetPaneFocusTraversable() {
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this;
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::GetAccessibleState(ui::AccessibleViewState* state) {
150290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  state->role = ui::AccessibilityTypes::ROLE_TOOLBAR;
15032385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch  state->name = l10n_util::GetStringUTF16(IDS_ASH_SHELF_ACCESSIBLE_NAME);
150490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
150590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
15068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnGestureEvent(ui::GestureEvent* event) {
15072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (gesture_handler_.ProcessGestureEvent(*event))
15082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event->StopPropagation();
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1511f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemAdded(int model_index) {
15122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
15132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<bool> cancelling_drag(
15142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &cancelling_drag_model_changed_, true);
15152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model_index = CancelDrag(model_index);
15162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view = CreateViewForItem(model_->items()[model_index]);
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddChildView(view);
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Hide the view, it'll be made visible when the animation is done. Using
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // opacity 0 here to avoid messing with CalculateIdealBounds which touches
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the view's visibility.
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->layer()->SetOpacity(0);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_model_->Add(view, model_index);
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give the button its ideal bounds. That way if we end up animating the
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // button before this animation completes it doesn't appear at some random
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // spot (because it was in the middle of animating from 0,0 0x0 to its
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // target).
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IdealBounds ideal_bounds;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CalculateIdealBounds(&ideal_bounds);
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view->SetBoundsRect(view_model_->ideal_bounds(model_index));
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first animation moves all the views to their target position. |view|
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is hidden, so it visually appears as though we are providing space for
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it. When done we'll fade the view in.
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AnimateToIdealBounds();
15372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (model_index <= last_visible_index_ ||
15382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      model_index >= model_->FirstPanelIndex()) {
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds_animator_->SetAnimationDelegate(
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        view, new StartFadeAnimationDelegate(this, view), true);
15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Undo the hiding if animation does not run.
15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view->layer()->SetOpacity(1.0f);
15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1547f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemRemoved(int model_index, LauncherID id) {
15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (id == context_menu_id_)
15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    launcher_menu_runner_.reset();
15502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
15512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<bool> cancelling_drag(
15522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &cancelling_drag_model_changed_, true);
15532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    model_index = CancelDrag(model_index);
15542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view = view_model_->view_at(model_index);
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_model_->Remove(model_index);
15570f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
15580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // When the overflow bubble is visible, the overflow range needs to be set
15590f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // before CalculateIdealBounds() gets called. Otherwise CalculateIdealBounds()
15600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // could trigger a LauncherItemChanged() by hiding the overflow bubble and
1561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // since the overflow bubble is not yet synced with the ShelfModel this
15620f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // could cause a crash.
15632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (overflow_bubble_ && overflow_bubble_->IsShowing()) {
15642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    last_hidden_index_ = std::min(last_hidden_index_,
15652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  view_model_->view_size() - 1);
15668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    UpdateOverflowRange(overflow_bubble_->shelf_view());
15672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1568d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)
15690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (view->visible()) {
15700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // The first animation fades out the view. When done we'll animate the rest
15710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // of the views to their target location.
15720f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    bounds_animator_->AnimateViewTo(view, view->bounds());
15730f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    bounds_animator_->SetAnimationDelegate(
15740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)        view, new FadeOutAnimationDelegate(this, view), true);
15750f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  } else {
15760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // We don't need to show a fade out animation for invisible |view|. When an
15770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    // item is ripped out from the shelf, its |view| is already invisible.
15780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    AnimateToIdealBounds();
15790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
15800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1581d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // Close the tooltip because it isn't needed any longer and its anchor view
1582d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  // will be deleted soon.
1583d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  if (tooltip_->GetCurrentAnchorView() == view)
1584d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    tooltip_->Close();
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemChanged(int model_index,
1588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                 const LauncherItem& old_item) {
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const LauncherItem& item(model_->items()[model_index]);
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (old_item.type != item.type) {
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Type changed, swap the views.
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    model_index = CancelDrag(model_index);
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<views::View> old_view(view_model_->view_at(model_index));
15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bounds_animator_->StopAnimatingView(old_view.get());
15953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // Removing and re-inserting a view in our view model will strip the ideal
15963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // bounds from the item. To avoid recalculation of everything the bounds
15973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    // get remembered and restored after the insertion to the previous value.
15983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    gfx::Rect old_ideal_bounds = view_model_->ideal_bounds(model_index);
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_model_->Remove(model_index);
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    views::View* new_view = CreateViewForItem(item);
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChildView(new_view);
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_model_->Add(new_view, model_index);
16033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    view_model_->set_ideal_bounds(model_index, old_ideal_bounds);
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_view->SetBoundsRect(old_view->bounds());
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  views::View* view = view_model_->view_at(model_index);
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (item.type) {
16102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case TYPE_BROWSER_SHORTCUT:
1611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Fallthrough for the new Shelf since it needs to show the activation
16122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // change as well.
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_APP_SHORTCUT:
16142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case TYPE_WINDOWED_APP:
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_PLATFORM_APP:
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case TYPE_APP_PANEL: {
1617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShelfButton* button = static_cast<ShelfButton*>(view);
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ReflectItemStatus(item, button);
16192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // The browser shortcut is currently not a "real" item and as such the
16202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // the image is bogous as well. We therefore keep the image as is for it.
16212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (item.type != TYPE_BROWSER_SHORTCUT)
16222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        button->SetImage(item.image);
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      button->SchedulePaint();
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1632f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemMoved(int start_index, int target_index) {
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  view_model_->Move(start_index, target_index);
16342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // When cancelling a drag due to a launcher item being added, the currently
16352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // dragged item is moved back to its initial position. AnimateToIdealBounds
16362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // will be called again when the new item is added to the |view_model_| but
16372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // at this time the |view_model_| is inconsistent with the |model_|.
16382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cancelling_drag_model_changed_)
16392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    AnimateToIdealBounds();
16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfStatusChanged() {
1643eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  if (ash::switches::UseAlternateShelfLayout())
1644eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return;
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AppListButton* app_list_button =
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      static_cast<AppListButton*>(GetAppListButtonView());
1647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (model_->status() == ShelfModel::STATUS_LOADING)
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_list_button->StartLoadingAnimation();
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    app_list_button->StopLoadingAnimation();
16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerPressedOnButton(views::View* view,
16548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       Pointer pointer,
16558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       const ui::LocatedEvent& event) {
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_view_)
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int index = view_model_->GetIndexOfView(view);
1660424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (index == -1)
1661424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return;
1662424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
16644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      model_->items()[index].id);
16654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable())
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // View is being deleted or not draggable, ignore request.
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  drag_view_ = view;
16691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  drag_offset_ = layout_manager_->PrimaryAxisValue(event.x(), event.y());
1670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage",
1671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      layout_manager_->SelectValueForShelfAlignment(
1672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM,
1673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT,
1674f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT,
1675f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          -1),
1676f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT);
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerDraggedOnButton(views::View* view,
16808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       Pointer pointer,
16818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       const ui::LocatedEvent& event) {
16820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // To prepare all drag types (moving an item in the shelf and dragging off),
16830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  // we should check the x-axis and y-axis offset.
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!dragging() && drag_view_ &&
16850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      ((abs(event.x() - drag_offset_) >= kMinimumDragDistance) ||
16860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)       (abs(event.y() - drag_offset_) >= kMinimumDragDistance))) {
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrepareForDrag(pointer, event);
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (drag_pointer_ == pointer)
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ContinueDrag(event);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerReleasedOnButton(views::View* view,
16948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                        Pointer pointer,
16958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                        bool canceled) {
16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (canceled) {
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelDrag(-1);
16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (drag_pointer_ == pointer) {
1699424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    FinalizeRipOffDrag(false);
17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    drag_pointer_ = NONE;
17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AnimateToIdealBounds();
17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1703ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // If the drag pointer is NONE, no drag operation is going on and the
1704ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  // drag_view can be released.
1705ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  if (drag_pointer_ == NONE)
1706ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    drag_view_ = NULL;
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseMovedOverButton(views::View* view) {
17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ShouldShowTooltipForView(view))
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tooltip_->IsVisible())
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tooltip_->ResetTimer();
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseEnteredButton(views::View* view) {
17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!ShouldShowTooltipForView(view))
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (tooltip_->IsVisible()) {
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tooltip_->ShowImmediately(view, GetAccessibleName(view));
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tooltip_->ShowDelayed(view, GetAccessibleName(view));
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseExitedButton(views::View* view) {
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!tooltip_->IsVisible())
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    tooltip_->StopTimer();
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)base::string16 ShelfView::GetAccessibleName(const views::View* view) {
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int view_index = view_model_->GetIndexOfView(view);
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be -1 while in the process of animating closed.
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_index == -1)
1737c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return base::string16();
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
17404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      model_->items()[view_index].id);
17414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return item_delegate->GetTitle();
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) {
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do not handle mouse release during drag.
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dragging())
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sender == overflow_button_) {
17502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ToggleOverflowBubble();
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int view_index = view_model_->GetIndexOfView(sender);
17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // May be -1 while in the process of animating closed.
17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_index == -1)
17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If the previous menu was closed by the same event as this one, we ignore
17602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the call.
17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!IsUsableEvent(event))
17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
17632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  {
1765a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    ScopedTargetRootWindow scoped_target(
1766a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        sender->GetWidget()->GetNativeView()->GetRootWindow());
17672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Slow down activation animations if shift key is pressed.
17682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ui::ScopedAnimationDurationScaleMode> slowing_animations;
17692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (event.IsShiftDown()) {
17702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      slowing_animations.reset(new ui::ScopedAnimationDurationScaleMode(
17712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            ui::ScopedAnimationDurationScaleMode::SLOW_DURATION));
17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
17732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1774b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    // Collect usage statistics before we decide what to do with the click.
1775b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    switch (model_->items()[view_index].type) {
1776b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      case TYPE_APP_SHORTCUT:
1777b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      case TYPE_WINDOWED_APP:
1778b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      case TYPE_PLATFORM_APP:
177990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      case TYPE_BROWSER_SHORTCUT:
1780d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        Shell::GetInstance()->metrics()->RecordUserMetricsAction(
1781b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            UMA_LAUNCHER_CLICK_ON_APP);
1782b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        break;
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1784b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)      case TYPE_APP_LIST:
1785d57369da7c6519fef57db42085f7b42d4c8845c1Torne (Richard Coles)        Shell::GetInstance()->metrics()->RecordUserMetricsAction(
1786b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)            UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON);
1787424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
1788424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1789424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      case TYPE_APP_PANEL:
1790424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        break;
1791424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1792424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      case TYPE_UNDEFINED:
1793424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        NOTREACHED() << "LauncherItemType must be set.";
1794b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        break;
17952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1796424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
1797a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ShelfItemDelegate* item_delegate =
1798a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        item_manager_->GetShelfItemDelegate(model_->items()[view_index].id);
1799f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!item_delegate->ItemSelected(event))
1800f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      ShowListMenuForView(model_->items()[view_index], sender, event);
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::ShowListMenuForView(const LauncherItem& item,
18058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                    views::View* source,
18068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                    const ui::Event& event) {
1807a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  scoped_ptr<ShelfMenuModel> menu_model;
1808a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate =
1809a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      item_manager_->GetShelfItemDelegate(item.id);
18104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  menu_model.reset(item_delegate->CreateApplicationMenu(event.flags()));
18112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Make sure we have a menu and it has at least two items in addition to the
18132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // application title and the 3 spacing separators.
18142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!menu_model.get() || menu_model->GetItemCount() <= 5)
18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShowMenu(scoped_ptr<views::MenuModelAdapter>(
1818a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)               new ShelfMenuModelAdapter(menu_model.get())),
18192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           source,
18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           gfx::Point(),
18217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           false,
18227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           ui::GetMenuSourceTypeForEvent(event));
18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ShowContextMenuForView(views::View* source,
18278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       const gfx::Point& point,
18288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                       ui::MenuSourceType source_type) {
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int view_index = view_model_->GetIndexOfView(source);
1830424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  // TODO(simon.hong81): Create LauncherContextMenu for applist in its
1831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // ShelfItemDelegate.
1832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (view_index != -1 && model_->items()[view_index].type == TYPE_APP_LIST) {
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    view_index = -1;
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (view_index == -1) {
18377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    Shell::GetInstance()->ShowContextMenu(point, source_type);
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1840424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  scoped_ptr<ui::MenuModel> menu_model;
1841a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate(
18424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      model_->items()[view_index].id);
1843424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  menu_model.reset(item_delegate->CreateContextMenu(
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      source->GetWidget()->GetNativeView()->GetRootWindow()));
1845c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!menu_model)
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1847424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
18482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<LauncherID> reseter(
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &context_menu_id_,
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      view_index == -1 ? 0 : model_->items()[view_index].id);
18512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ShowMenu(scoped_ptr<views::MenuModelAdapter>(
18532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)               new views::MenuModelAdapter(menu_model.get())),
18542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           source,
18552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)           point,
18567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           true,
18577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)           source_type);
18582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ShowMenu(scoped_ptr<views::MenuModelAdapter> menu_model_adapter,
18618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         views::View* source,
18628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         const gfx::Point& click_point,
18638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         bool context_menu,
18648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                         ui::MenuSourceType source_type) {
18652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closing_event_time_ = base::TimeDelta();
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  launcher_menu_runner_.reset(
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      new views::MenuRunner(menu_model_adapter->CreateMenu()));
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1869a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  ScopedTargetRootWindow scoped_target(
1870a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      source->GetWidget()->GetNativeView()->GetRootWindow());
1871a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Determine the menu alignment dependent on the shelf.
18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  views::MenuItemView::AnchorPosition menu_alignment =
18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      views::MenuItemView::TOPLEFT;
18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  gfx::Rect anchor_point = gfx::Rect(click_point, gfx::Size());
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  ShelfWidget* shelf = RootWindowController::ForLauncher(
1878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      GetWidget()->GetNativeView())->shelf();
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!context_menu) {
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Application lists use a bubble.
1881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    ash::ShelfAlignment align = shelf->GetAlignment();
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    anchor_point = source->GetBoundsInScreen();
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // It is possible to invoke the menu while it is sliding into view. To cover
18857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // that case, the screen coordinates are offsetted by the animation delta.
18867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    gfx::Vector2d offset =
18877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        source->GetWidget()->GetNativeWindow()->bounds().origin() -
18887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        source->GetWidget()->GetNativeWindow()->GetTargetBounds().origin();
18897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    anchor_point.set_x(anchor_point.x() - offset.x());
18907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    anchor_point.set_y(anchor_point.y() - offset.y());
18917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
1892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // Shelf items can have an asymmetrical border for spacing reasons.
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Adjust anchor location for this.
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (source->border())
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      anchor_point.Inset(source->border()->GetInsets());
18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (align) {
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ash::SHELF_ALIGNMENT_BOTTOM:
18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        menu_alignment = views::MenuItemView::BUBBLE_ABOVE;
19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ash::SHELF_ALIGNMENT_LEFT:
19022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        menu_alignment = views::MenuItemView::BUBBLE_RIGHT;
19032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
19042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ash::SHELF_ALIGNMENT_RIGHT:
19052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        menu_alignment = views::MenuItemView::BUBBLE_LEFT;
19062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
19072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case ash::SHELF_ALIGNMENT_TOP:
19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        menu_alignment = views::MenuItemView::BUBBLE_BELOW;
19092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        break;
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1912c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // If this gets deleted while we are in the menu, the launcher will be gone
1913c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // as well.
1914c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool got_deleted = false;
1915c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  got_deleted_ = &got_deleted;
1916c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
1917c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shelf->ForceUndimming(true);
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: if you convert to HAS_MNEMONICS be sure and update menu building
19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code.
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (launcher_menu_runner_->RunMenuAt(
19212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          source->GetWidget(),
19222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          NULL,
19232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          anchor_point,
19242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          menu_alignment,
19257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          source_type,
19267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          context_menu ? views::MenuRunner::CONTEXT_MENU : 0) ==
19277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      views::MenuRunner::MENU_DELETED) {
1928c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!got_deleted) {
1929c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      got_deleted_ = NULL;
1930c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      shelf->ForceUndimming(false);
1931c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1933c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
1934c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  got_deleted_ = NULL;
1935c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  shelf->ForceUndimming(false);
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // If it is a context menu and we are showing overflow bubble
19384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // we want to hide overflow bubble.
19394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (owner_overflow_bubble_)
19404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    owner_overflow_bubble_->HideBubbleAndRefreshButton();
19414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Unpinning an item will reset the |launcher_menu_runner_| before coming
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // here.
1944c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (launcher_menu_runner_)
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    closing_event_time_ = launcher_menu_runner_->closing_event_time();
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Shell::GetInstance()->UpdateShelfVisibility();
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) {
19501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  FOR_EACH_OBSERVER(ShelfIconObserver, observers_,
19511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                    OnShelfIconPositionsChanged());
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PreferredSizeChanged();
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
1956424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (snap_back_from_rip_off_view_ && animator == bounds_animator_) {
1957424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    if (!animator->IsAnimating(snap_back_from_rip_off_view_)) {
1958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // Coming here the animation of the ShelfButton is finished and the
1959424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // previously hidden status can be shown again. Since the button itself
1960424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // might have gone away or changed locations we check that the button
1961424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      // is still in the shelf and show its status again.
1962424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      for (int index = 0; index < view_model_->view_size(); index++) {
1963424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        views::View* view = view_model_->view_at(index);
1964424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        if (view == snap_back_from_rip_off_view_) {
1965f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          ShelfButton* button = static_cast<ShelfButton*>(view);
1966f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          button->ClearState(ShelfButton::STATE_HIDDEN);
1967424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)          break;
1968424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)        }
1969424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      }
1970424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      snap_back_from_rip_off_view_ = NULL;
1971424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    }
1972424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::IsUsableEvent(const ui::Event& event) {
19762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (closing_event_time_ == base::TimeDelta())
19772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return true;
19782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::TimeDelta delta =
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::TimeDelta(event.time_stamp() - closing_event_time_);
19812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  closing_event_time_ = base::TimeDelta();
19822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(skuhne): This time seems excessive, but it appears that the reposting
19832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // takes that long.  Need to come up with a better way of doing this.
19842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (delta.InMilliseconds() < 0 || delta.InMilliseconds() > 130);
19852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)const LauncherItem* ShelfView::LauncherItemForView(
19882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const views::View* view) const {
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int view_index = view_model_->GetIndexOfView(view);
19902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (view_index == -1)
19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return NULL;
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return &(model_->items()[view_index]);
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::ShouldShowTooltipForView(const views::View* view) const {
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (view == GetAppListButtonView() &&
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      Shell::GetInstance()->GetAppListWindow())
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const LauncherItem* item = LauncherItemForView(view);
2000424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  if (!item)
2001424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    return true;
2002a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  ShelfItemDelegate* item_delegate =
2003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      item_manager_->GetShelfItemDelegate(item->id);
20044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  return item_delegate->ShouldShowTooltip();
2005424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)}
2006424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
20078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::CalculateShelfDistance(const gfx::Point& coordinate) const {
2008424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ShelfWidget* shelf = RootWindowController::ForLauncher(
2009424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      GetWidget()->GetNativeView())->shelf();
2010424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  ash::ShelfAlignment align = shelf->GetAlignment();
2011424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  const gfx::Rect bounds = GetBoundsInScreen();
2012424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  int distance = 0;
2013424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  switch (align) {
2014424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case ash::SHELF_ALIGNMENT_BOTTOM:
2015424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      distance = bounds.y() - coordinate.y();
2016424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
2017424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case ash::SHELF_ALIGNMENT_LEFT:
2018424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      distance = coordinate.x() - bounds.right();
2019424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
2020424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case ash::SHELF_ALIGNMENT_RIGHT:
2021424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      distance = bounds.x() - coordinate.x();
2022424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
2023424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    case ash::SHELF_ALIGNMENT_TOP:
2024424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      distance = coordinate.y() - bounds.bottom();
2025424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      break;
2026424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  }
2027424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  return distance > 0 ? distance : 0;
20282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
20292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internal
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace ash
2032