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" 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (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/app_list_button.h" 16424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/overflow_bubble.h" 17f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/overflow_bubble_view.h" 18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "ash/shelf/overflow_button.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "ash/shelf/shelf_button.h" 205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ash/shelf/shelf_constants.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" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (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" 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/ash_strings.h" 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 37a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)#include "ui/aura/client/screen_position_client.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/aura/window.h" 39a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/aura/window_event_dispatcher.h" 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/models/simple_menu_model.h" 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/compositor/layer_animator.h" 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/compositor/scoped_animation_duration_scale_mode.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "ui/gfx/point.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/animation/bounds_animator.h" 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/border.h" 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/views/controls/button/image_button.h" 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_model_adapter.h" 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/menu/menu_runner.h" 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/focus/focus_search.h" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_model.h" 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/view_model_utils.h" 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include "ui/wm/core/coordinate_conversion.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) 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM = 0; 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT = 1; 66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT = 2; 67f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)const int SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT = 3; 68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Default amount content is inset on the left edge. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kDefaultLeadingInset = 8; 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Minimum distance before drag starts. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kMinimumDragDistance = 8; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Additional spacing for the left and right side of icons. 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kHorizontalIconSpacing = 2; 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Inset for items which do not have an icon. 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kHorizontalNoIconInsetSpacing = 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kHorizontalIconSpacing + kDefaultLeadingInset; 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The proportion of the shelf space reserved for non-panel icons. Panels 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// may flow into this space but will be put into the overflow bubble if there 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is contention for the space. 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const float kReservedNonPanelIconProportion = 0.67f; 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is the command id of the menu item which contains the name of the menu. 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kCommandIdOfMenuName = 0; 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The background color of the active item in the list. 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kActiveListItemBackgroundColor = SkColorSetRGB(203 , 219, 241); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The background color of the active & hovered item in the list. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kFocusedActiveListItemBackgroundColor = 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColorSetRGB(193, 211, 236); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The text color of the caption item in a list. 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const SkColor kCaptionItemForegroundColor = SK_ColorBLACK; 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum allowable length of a menu line of an application menu in pixels. 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kMaximumAppMenuItemLength = 350; 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The distance of the cursor from the outer rim of the shelf before it 104f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// separates. 105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const int kRipOffDistance = 48; 106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)// The rip off drag and drop proxy image should get scaled by this factor. 108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)const float kDragAndDropProxyScale = 1.5f; 109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// The opacity represents that this partially disappeared item will get removed. 111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)const float kDraggedImageOpacity = 0.5f; 112a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A class to temporarily disable a given bounds animator. 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class BoundsAnimatorDisabler { 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 1181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci explicit BoundsAnimatorDisabler(views::BoundsAnimator* bounds_animator) 1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : old_duration_(bounds_animator->GetAnimationDuration()), 1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bounds_animator_(bounds_animator) { 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bounds_animator_->SetAnimationDuration(1); 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~BoundsAnimatorDisabler() { 1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bounds_animator_->SetAnimationDuration(old_duration_); 1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The previous animation duration. 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int old_duration_; 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The bounds animator which gets used. 1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) views::BoundsAnimator* bounds_animator_; 1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(BoundsAnimatorDisabler); 1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The MenuModelAdapter gets slightly changed to adapt the menu appearance to 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// our requirements. 139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ShelfMenuModelAdapter : public views::MenuModelAdapter { 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) explicit ShelfMenuModelAdapter(ShelfMenuModel* menu_model); 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // views::MenuModelAdapter: 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual const gfx::FontList* GetLabelFontList(int command_id) const OVERRIDE; 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool IsCommandEnabled(int id) const OVERRIDE; 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual void GetHorizontalIconMargins(int id, 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int icon_size, 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* left_margin, 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int* right_margin) const OVERRIDE; 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetForegroundColor(int command_id, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_hovered, 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor* override_color) const OVERRIDE; 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool GetBackgroundColor(int command_id, 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool is_hovered, 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkColor* override_color) const OVERRIDE; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual int GetMaxWidthForMenu(views::MenuItemView* menu) OVERRIDE; 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) virtual bool ShouldReserveSpaceForSubmenuIndicator() const OVERRIDE; 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private: 160a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfMenuModel* menu_model_; 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ShelfMenuModelAdapter); 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)ShelfMenuModelAdapter::ShelfMenuModelAdapter(ShelfMenuModel* menu_model) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : MenuModelAdapter(menu_model), 167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) menu_model_(menu_model) { 168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const gfx::FontList* ShelfMenuModelAdapter::GetLabelFontList( 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int command_id) const { 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command_id != kCommandIdOfMenuName) 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return MenuModelAdapter::GetLabelFontList(command_id); 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return &rb.GetFontList(ui::ResourceBundle::BoldFont); 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::IsCommandEnabled(int id) const { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id != kCommandIdOfMenuName; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::GetForegroundColor(int command_id, 184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_hovered, 185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SkColor* override_color) const { 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (command_id != kCommandIdOfMenuName) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *override_color = kCaptionItemForegroundColor; 1902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::GetBackgroundColor(int command_id, 194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool is_hovered, 195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) SkColor* override_color) const { 196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!menu_model_->IsCommandActive(command_id)) 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *override_color = is_hovered ? kFocusedActiveListItemBackgroundColor : 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kActiveListItemBackgroundColor; 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 204a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ShelfMenuModelAdapter::GetHorizontalIconMargins(int command_id, 205a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int icon_size, 206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int* left_margin, 207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int* right_margin) const { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *left_margin = kHorizontalIconSpacing; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *right_margin = (command_id != kCommandIdOfMenuName) ? 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) kHorizontalIconSpacing : -(icon_size + kHorizontalNoIconInsetSpacing); 2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 213a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)int ShelfMenuModelAdapter::GetMaxWidthForMenu(views::MenuItemView* menu) { 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kMaximumAppMenuItemLength; 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 217a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool ShelfMenuModelAdapter::ShouldReserveSpaceForSubmenuIndicator() const { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Custom FocusSearch used to navigate the shelf in the order items are in 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the ViewModel. 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class ShelfFocusSearch : public views::FocusSearch { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit ShelfFocusSearch(views::ViewModel* view_model) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : FocusSearch(NULL, true, true), 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_(view_model) {} 2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ~ShelfFocusSearch() {} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // views::FocusSearch overrides: 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual View* FindNextFocusableView( 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View* starting_view, 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool reverse, 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Direction direction, 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool check_starting_view, 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::FocusTraversable** focus_traversable, 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) View** focus_traversable_view) OVERRIDE { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = view_model_->GetIndexOfView(starting_view); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index == -1) 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view_model_->view_at(0); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (reverse) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --index; 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index < 0) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = view_model_->view_size() - 1; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++index; 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (index >= view_model_->view_size()) 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = 0; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view_model_->view_at(index); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ViewModel* view_model_; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ShelfFocusSearch); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AnimationDelegate used when inserting a new item. This steadily increases the 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opacity of the layer as the animation progress. 262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class FadeInAnimationDelegate : public gfx::AnimationDelegate { 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit FadeInAnimationDelegate(views::View* view) : view_(view) {} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~FadeInAnimationDelegate() {} 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AnimationDelegate overrides: 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationProgressed(const Animation* animation) OVERRIDE { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->SetOpacity(animation->GetCurrentValue()); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->ScheduleDraw(); 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationEnded(const Animation* animation) OVERRIDE { 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->SetOpacity(1.0f); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->ScheduleDraw(); 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationCanceled(const Animation* animation) OVERRIDE { 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->SetOpacity(1.0f); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->ScheduleDraw(); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view_; 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FadeInAnimationDelegate); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ReflectItemStatus(const ShelfItem& item, ShelfButton* button) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (item.status) { 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATUS_CLOSED: 290f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ACTIVE); 291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_RUNNING); 292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ATTENTION); 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATUS_RUNNING: 295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ACTIVE); 296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->AddState(ShelfButton::STATE_RUNNING); 297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ATTENTION); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATUS_ACTIVE: 300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->AddState(ShelfButton::STATE_ACTIVE); 301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_RUNNING); 302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ATTENTION); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case STATUS_ATTENTION: 305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_ACTIVE); 306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_RUNNING); 307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->AddState(ShelfButton::STATE_ATTENTION); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// AnimationDelegate used when deleting an item. This steadily decreased the 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// opacity of the layer as the animation progress. 316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ShelfView::FadeOutAnimationDelegate : public gfx::AnimationDelegate { 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) FadeOutAnimationDelegate(ShelfView* host, views::View* view) 3198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : shelf_view_(host), 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_(view) {} 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~FadeOutAnimationDelegate() {} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AnimationDelegate overrides: 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationProgressed(const Animation* animation) OVERRIDE { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->SetOpacity(1 - animation->GetCurrentValue()); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->ScheduleDraw(); 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationEnded(const Animation* animation) OVERRIDE { 3298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) shelf_view_->OnFadeOutAnimationEnded(); 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationCanceled(const Animation* animation) OVERRIDE { 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ShelfView* shelf_view_; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::View> view_; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FadeOutAnimationDelegate); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// AnimationDelegate used to trigger fading an element in. When an item is 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// inserted this delegate is attached to the animation that expands the size of 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the item. When done it kicks off another animation to fade the item in. 344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ShelfView::StartFadeAnimationDelegate : public gfx::AnimationDelegate { 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 3468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) StartFadeAnimationDelegate(ShelfView* host, 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view) 3488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) : shelf_view_(host), 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_(view) {} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~StartFadeAnimationDelegate() {} 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // AnimationDelegate overrides: 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationEnded(const Animation* animation) OVERRIDE { 3548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) shelf_view_->FadeIn(view_); 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void AnimationCanceled(const Animation* animation) OVERRIDE { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_->layer()->SetOpacity(1.0f); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 3618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ShelfView* shelf_view_; 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view_; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(StartFadeAnimationDelegate); 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)ShelfView::ShelfView(ShelfModel* model, 368a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfDelegate* delegate, 369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfLayoutManager* manager) 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : model_(model), 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delegate_(delegate), 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_(new views::ViewModel), 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_visible_index_(0), 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_visible_index_(-1), 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_(NULL), 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) owner_overflow_bubble_(NULL), 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pointer_(NONE), 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_view_(NULL), 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_drag_index_(-1), 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context_menu_id_(0), 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) leading_inset_(kDefaultLeadingInset), 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cancelling_drag_model_changed_(false), 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_hidden_index_(0), 384c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) closing_event_time_(base::TimeDelta()), 385b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) got_deleted_(NULL), 3867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) drag_and_drop_item_pinned_(false), 3875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) drag_and_drop_shelf_id_(0), 388424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dragged_off_shelf_(false), 389424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) snap_back_from_rip_off_view_(NULL), 390a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) item_manager_(Shell::GetInstance()->shelf_item_delegate_manager()), 391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) layout_manager_(manager), 392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) overflow_mode_(false), 393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_(NULL), 394a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_(false) { 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model_); 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_.reset(new views::BoundsAnimator(this)); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->AddObserver(this); 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_context_menu_controller(this); 3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) focus_search_.reset(new ShelfFocusSearch(view_model_.get())); 400a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) tooltip_.reset(new ShelfTooltipManager(manager, this)); 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)ShelfView::~ShelfView() { 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->RemoveObserver(this); 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If we are inside the MenuRunner, we need to know if we were getting 407c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // deleted while it was running. 408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (got_deleted_) 409c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) *got_deleted_ = true; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::Init() { 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ShelfItems& items(model_->items()); 4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (ShelfItems::const_iterator i = items.begin(); i != items.end(); ++i) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* child = CreateViewForItem(*i); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child->SetPaintToLayer(true); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Add(child, static_cast<int>(i - items.begin())); 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(child); 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_ = new OverflowButton(this); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->set_context_menu_controller(this); 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConfigureChildView(overflow_button_); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(overflow_button_); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We'll layout when our bounds change. 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnShelfAlignmentChanged() { 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_button_->OnShelfAlignmentChanged(); 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayoutToIdealBounds(); 4331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (int i = 0; i < view_model_->view_size(); ++i) { 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i >= first_visible_index_ && i <= last_visible_index_) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->view_at(i)->Layout(); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 437d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tooltip_->Close(); 438c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (overflow_bubble_) 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_bubble_->Hide(); 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::SchedulePaintForAllButtons() { 443ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch for (int i = 0; i < view_model_->view_size(); ++i) { 444ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (i >= first_visible_index_ && i <= last_visible_index_) 445ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch view_model_->view_at(i)->SchedulePaint(); 446ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 447ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (overflow_button_ && overflow_button_->visible()) 448ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch overflow_button_->SchedulePaint(); 449ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch} 450ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)gfx::Rect ShelfView::GetIdealBoundsOfItemIcon(ShelfID id) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = model_->ItemIndexByID(id); 453cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (index == -1) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return gfx::Rect(); 455cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Map all items from overflow area to the overflow button. Note that the 456cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // section between last_index_hidden_ and model_->FirstPanelIndex() is the 457cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // list of invisible panel items. However, these items are currently nowhere 458cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // represented and get dropped instead - see (crbug.com/378907). As such there 459cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // is no way to address them or place them. We therefore move them over the 460cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // overflow button. 461cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (index > last_visible_index_ && index < model_->FirstPanelIndex()) 462cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) index = last_visible_index_ + 1; 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) 4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ShelfView::UpdatePanelIconPosition(ShelfID 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; 545c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch drag_image_.reset(new ash::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) { 563a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // TODO(jennyz): Investigate why drag_image_ becomes NULL at this point per 564a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // crbug.com/34722, while the app list item is still being dragged around. 565a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (drag_image_) { 566a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) drag_image_->SetScreenPosition( 567a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) location_in_screen_coordinates - drag_image_offset_); 568a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 569a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 570a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::DestroyDragIconProxy() { 572a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) drag_image_.reset(); 573a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) drag_image_offset_ = gfx::Vector2d(0, 0); 574a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)} 575a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 5768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::StartDrag(const std::string& app_id, 5778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const gfx::Point& location_in_screen_coordinates) { 578b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Bail if an operation is already going on - or the cursor is not inside. 579b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // This could happen if mouse / touch operations overlap. 5805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (drag_and_drop_shelf_id_ || 581b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !GetBoundsInScreen().Contains(location_in_screen_coordinates)) 582b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 583b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 584b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // If the AppsGridView (which was dispatching this event) was opened by our 5858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // button, ShelfView dragging operations are locked and we have to unlock. 586b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CancelDrag(-1); 5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) drag_and_drop_item_pinned_ = false; 588b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) drag_and_drop_app_id_ = app_id; 5895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) drag_and_drop_shelf_id_ = 5905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetShelfIDForAppID(drag_and_drop_app_id_); 5917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Check if the application is known and pinned - if not, we have to pin it so 5925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // that we can re-arrange the shelf order accordingly. Note that items have 5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // to be pinned to give them the same (order) possibilities as a shortcut. 594a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // When an item is dragged from overflow to shelf, IsShowingOverflowBubble() 595a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // returns true. At this time, we don't need to pin the item. 596a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!IsShowingOverflowBubble() && 5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) (!drag_and_drop_shelf_id_ || 598a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !delegate_->IsAppPinned(app_id))) { 599b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) delegate_->PinAppWithID(app_id); 6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) drag_and_drop_shelf_id_ = 6015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetShelfIDForAppID(drag_and_drop_app_id_); 6025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!drag_and_drop_shelf_id_) 603b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 6047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) drag_and_drop_item_pinned_ = true; 605b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 606b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) views::View* drag_and_drop_view = view_model_->view_at( 6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->ItemIndexByID(drag_and_drop_shelf_id_)); 608b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) DCHECK(drag_and_drop_view); 609b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 610a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Since there is already an icon presented by the caller, we hide this item 611a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // for now. That has to be done by reducing the size since the visibility will 612a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // change once a regrouping animation is performed. 613a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) pre_drag_and_drop_size_ = drag_and_drop_view->size(); 614a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) drag_and_drop_view->SetSize(gfx::Size()); 615a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) 616b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // First we have to center the mouse cursor over the item. 617b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) gfx::Point pt = drag_and_drop_view->GetBoundsInScreen().CenterPoint(); 618b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) views::View::ConvertPointFromScreen(drag_and_drop_view, &pt); 619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Point point_in_root = location_in_screen_coordinates; 6206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ::wm::ConvertPointFromScreen( 6216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root); 6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::MouseEvent event(ui::ET_MOUSE_PRESSED, pt, point_in_root, 0, 0); 623f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PointerPressedOnButton(drag_and_drop_view, 624f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButtonHost::DRAG_AND_DROP, 625f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event); 626b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 627b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Drag the item where it really belongs. 628b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Drag(location_in_screen_coordinates); 629b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 630b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 631b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::Drag(const gfx::Point& location_in_screen_coordinates) { 6335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!drag_and_drop_shelf_id_ || 634b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) !GetBoundsInScreen().Contains(location_in_screen_coordinates)) 635b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return false; 636b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 637b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) gfx::Point pt = location_in_screen_coordinates; 638b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) views::View* drag_and_drop_view = view_model_->view_at( 6395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->ItemIndexByID(drag_and_drop_shelf_id_)); 640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConvertPointFromScreen(drag_and_drop_view, &pt); 641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Point point_in_root = location_in_screen_coordinates; 6426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ::wm::ConvertPointFromScreen( 6436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ash::wm::GetRootWindowAt(location_in_screen_coordinates), &point_in_root); 6445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ui::MouseEvent event(ui::ET_MOUSE_DRAGGED, pt, point_in_root, 0, 0); 645f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PointerDraggedOnButton(drag_and_drop_view, 646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButtonHost::DRAG_AND_DROP, 647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) event); 648b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 649b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 650b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::EndDrag(bool cancel) { 6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!drag_and_drop_shelf_id_) 653b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return; 654b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 655b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) views::View* drag_and_drop_view = view_model_->view_at( 6565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) model_->ItemIndexByID(drag_and_drop_shelf_id_)); 657b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) PointerReleasedOnButton( 658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) drag_and_drop_view, ShelfButtonHost::DRAG_AND_DROP, cancel); 659b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 660a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) // Either destroy the temporarily created item - or - make the item visible. 6611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (drag_and_drop_item_pinned_ && cancel) { 662424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) delegate_->UnpinAppWithID(drag_and_drop_app_id_); 6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else if (drag_and_drop_view) { 66458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) if (cancel) { 66558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // When a hosted drag gets canceled, the item can remain in the same slot 66658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // and it might have moved within the bounds. In that case the item need 66758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // to animate back to its correct location. 66858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) AnimateToIdealBounds(); 66958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } else { 67058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) drag_and_drop_view->SetSize(pre_drag_and_drop_size_); 67158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 67258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) } 673b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) drag_and_drop_shelf_id_ = 0; 675b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 676b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 6778bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::LayoutToIdealBounds() { 6781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (bounds_animator_->IsAnimating()) { 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToIdealBounds(); 6801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 6811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) IdealBounds ideal_bounds; 6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CalculateIdealBounds(&ideal_bounds); 6851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) views::ViewModelUtils::SetViewBoundsToIdealBounds(*view_model_); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void ShelfView::UpdateAllButtonsVisibilityInOverflowMode() { 690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The overflow button is not shown in overflow mode. 691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) overflow_button_->SetVisible(false); 692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) DCHECK_LT(last_visible_index_, view_model_->view_size()); 693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (int i = 0; i < view_model_->view_size(); ++i) { 694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bool visible = i >= first_visible_index_ && 695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) i <= last_visible_index_; 696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // To track the dragging of |drag_view_| continuously, its visibility 697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // should be always true regardless of its position. 698a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (dragged_off_from_overflow_to_shelf_ && 699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) view_model_->view_at(i) == drag_view_) 700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) view_model_->view_at(i)->SetVisible(true); 701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) else 702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) view_model_->view_at(i)->SetVisible(visible); 703a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 704a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)} 705a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) 706cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ShelfView::CalculateIdealBounds(IdealBounds* bounds) const { 7071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int available_size = layout_manager_->PrimaryAxisValue(width(), height()); 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(model_->item_count() == view_model_->view_size()); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!available_size) 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int first_panel_index = model_->FirstPanelIndex(); 713ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int last_button_index = first_panel_index - 1; 7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 715a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int x = 0; 716a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int y = 0; 717a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int button_size = kShelfButtonSize; 718a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch int button_spacing = kShelfButtonSpacing; 719ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 7201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int w = layout_manager_->PrimaryAxisValue(button_size, width()); 7211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int h = layout_manager_->PrimaryAxisValue(height(), button_size); 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < view_model_->view_size(); ++i) { 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i < first_visible_index_) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->set_ideal_bounds(i, gfx::Rect(x, y, 0, 0)); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h)); 729ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (i != last_button_index) { 7301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) x = layout_manager_->PrimaryAxisValue(x + w + button_spacing, x); 7311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) y = layout_manager_->PrimaryAxisValue(y, y + h + button_spacing); 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_overflow_mode()) { 736cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const_cast<ShelfView*>(this)->UpdateAllButtonsVisibilityInOverflowMode(); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Right aligned icons. 741ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch int end_position = available_size - button_spacing; 7421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) x = layout_manager_->PrimaryAxisValue(end_position, 0); 7431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) y = layout_manager_->PrimaryAxisValue(0, end_position); 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = view_model_->view_size() - 1; 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) i >= first_panel_index; --i) { 7461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) x = layout_manager_->PrimaryAxisValue(x - w - button_spacing, x); 7471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) y = layout_manager_->PrimaryAxisValue(y, y - h - button_spacing); 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h)); 7491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) end_position = layout_manager_->PrimaryAxisValue(x, y); 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Icons on the left / top are guaranteed up to kLeftIconProportion of 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the available space. 7541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int last_icon_position = layout_manager_->PrimaryAxisValue( 755ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch view_model_->ideal_bounds(last_button_index).right(), 756a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch view_model_->ideal_bounds(last_button_index).bottom()) + button_size; 7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int reserved_icon_space = available_size * kReservedNonPanelIconProportion; 7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (last_icon_position < reserved_icon_space) 7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) end_position = last_icon_position; 7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) end_position = std::max(end_position, reserved_icon_space); 7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bounds->overflow_bounds.set_size( 7641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) gfx::Size(layout_manager_->PrimaryAxisValue(w, width()), 7651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) layout_manager_->PrimaryAxisValue(height(), h))); 7664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 767a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch last_visible_index_ = DetermineLastVisibleIndex( 768a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch end_position - button_size); 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_hidden_index_ = DetermineFirstVisiblePanelIndex(end_position) - 1; 770a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool show_overflow = last_visible_index_ < last_button_index || 771a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch last_hidden_index_ >= first_panel_index; 772ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 773ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // Create Space for the overflow button 774a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (show_overflow && 77558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) last_visible_index_ > 0 && last_visible_index_ < last_button_index) 776ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch --last_visible_index_; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < view_model_->view_size(); ++i) { 778ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bool visible = i <= last_visible_index_ || i > last_hidden_index_; 779cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // To receive drag event continuously from |drag_view_| during the dragging 7804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // off from the shelf, don't make |drag_view_| invisible. It will be 7814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // eventually invisible and removed from the |view_model_| by 7824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // FinalizeRipOffDrag(). 7834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (dragged_off_shelf_ && view_model_->view_at(i) == drag_view_) 7844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) continue; 785ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch view_model_->view_at(i)->SetVisible(visible); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->SetVisible(show_overflow); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (show_overflow) { 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(0, view_model_->view_size()); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_visible_index_ == -1) { 792a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch x = 0; 793a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch y = 0; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 7951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) x = layout_manager_->PrimaryAxisValue( 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(last_visible_index_).right(), 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(last_visible_index_).x()); 7981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) y = layout_manager_->PrimaryAxisValue( 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(last_visible_index_).y(), 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(last_visible_index_).bottom()); 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Set all hidden panel icon positions to be on the overflow button. 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (int i = first_panel_index; i <= last_hidden_index_; ++i) 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->set_ideal_bounds(i, gfx::Rect(x, y, w, h)); 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Add more space between last visible item and overflow button. 8071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Without this, two buttons look too close compared with other items. 808a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch x = layout_manager_->PrimaryAxisValue(x + button_spacing, x); 809a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch y = layout_manager_->PrimaryAxisValue(y, y + button_spacing); 8101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 811ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bounds->overflow_bounds.set_x(x); 812ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch bounds->overflow_bounds.set_y(y); 8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (overflow_bubble_.get() && overflow_bubble_->IsShowing()) 8148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UpdateOverflowRange(overflow_bubble_->shelf_view()); 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 816c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (overflow_bubble_) 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_bubble_->Hide(); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::DetermineLastVisibleIndex(int max_value) const { 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = model_->FirstPanelIndex() - 1; 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (index >= 0 && 8241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) layout_manager_->PrimaryAxisValue( 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(index).right(), 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(index).bottom()) > max_value) { 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index--; 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return index; 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::DetermineFirstVisiblePanelIndex(int min_value) const { 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int index = model_->FirstPanelIndex(); 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (index < view_model_->view_size() && 8351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) layout_manager_->PrimaryAxisValue( 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->ideal_bounds(index).right(), 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->ideal_bounds(index).bottom()) < min_value) { 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++index; 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return index; 8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::AddIconObserver(ShelfIconObserver* observer) { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.AddObserver(observer); 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::RemoveIconObserver(ShelfIconObserver* observer) { 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) observers_.RemoveObserver(observer); 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::AnimateToIdealBounds() { 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdealBounds ideal_bounds; 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalculateIdealBounds(&ideal_bounds); 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < view_model_->view_size(); ++i) { 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) View* view = view_model_->view_at(i); 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds_animator_->AnimateViewTo(view, view_model_->ideal_bounds(i)); 8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Now that the item animation starts, we have to make sure that the 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // padding of the first gets properly transferred to the new first item. 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (i && view->border()) 8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) view->SetBorder(views::Border::NullBorder()); 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_button_->SetBoundsRect(ideal_bounds.overflow_bounds); 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)views::View* ShelfView::CreateViewForItem(const ShelfItem& item) { 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view = NULL; 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (item.type) { 86890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case TYPE_BROWSER_SHORTCUT: 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_APP_SHORTCUT: 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TYPE_WINDOWED_APP: 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_PLATFORM_APP: 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case TYPE_DIALOG: 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_APP_PANEL: { 874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButton* button = ShelfButton::Create(this, this, layout_manager_); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->SetImage(item.image); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReflectItemStatus(item, button); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view = button; 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_APP_LIST: { 882a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch view = new AppListButton(this, this, layout_manager_->shelf_widget()); 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->set_context_menu_controller(this); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(view); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ConfigureChildView(view); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return view; 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::FadeIn(views::View* view) { 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetVisible(true); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->layer()->SetOpacity(0); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToIdealBounds(); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->SetAnimationDelegate( 901f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) view, 902f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<gfx::AnimationDelegate>(new FadeInAnimationDelegate(view))); 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PrepareForDrag(Pointer pointer, const ui::LocatedEvent& event) { 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!dragging()); 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(drag_view_); 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pointer_ = pointer; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) start_drag_index_ = view_model_->GetIndexOfView(drag_view_); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 911424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (start_drag_index_== -1) { 912424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CancelDrag(-1); 913424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 914424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 915424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the item is no longer draggable, bail out. 917a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate( 9184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_->items()[start_drag_index_].id); 9194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!item_delegate->IsDraggable()) { 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelDrag(-1); 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Move the view to the front so that it appears on top of other views. 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReorderChildView(drag_view_, -1); 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->StopAnimatingView(drag_view_); 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ContinueDrag(const ui::LocatedEvent& event) { 930424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Due to a syncing operation the application might have been removed. 931424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Bail if it is gone. 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int current_index = view_model_->GetIndexOfView(drag_view_); 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_NE(-1, current_index); 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 935a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate( 9364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_->items()[current_index].id); 9374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!item_delegate->IsDraggable()) { 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelDrag(-1); 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 942424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If this is not a drag and drop host operation and not the app list item, 943424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // check if the item got ripped off the shelf - if it did we are done. 944a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if (!drag_and_drop_shelf_id_ && 945424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) RemovableByRipOff(current_index) != NOT_REMOVABLE) { 946424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (HandleRipOffDrag(event)) 947424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 948424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // The rip off handler could have changed the location of the item. 949424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) current_index = view_model_->GetIndexOfView(drag_view_); 950424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 951424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 952424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // TODO: I don't think this works correctly with RTL. 953424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::Point drag_point(event.location()); 954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConvertPointToTarget(drag_view_, this, &drag_point); 955424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Constrain the location to the range of valid indices for the type. 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::pair<int, int> indices(GetDragRange(current_index)); 9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int first_drag_index = indices.first; 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int last_drag_index = indices.second; 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the last index isn't valid, we're overflowing. Constrain to the app list 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (which is the last visible item). 9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (first_drag_index < model_->FirstPanelIndex() && 9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_drag_index > last_visible_index_) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_drag_index = last_visible_index_; 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int x = 0, y = 0; 9661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (layout_manager_->IsHorizontalAlignment()) { 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = std::max(view_model_->ideal_bounds(indices.first).x(), 968f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) drag_point.x() - drag_origin_.x()); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x = std::min(view_model_->ideal_bounds(last_drag_index).right() - 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(current_index).width(), 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x); 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_view_->x() == x) 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_view_->SetX(x); 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = std::max(view_model_->ideal_bounds(indices.first).y(), 977f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) drag_point.y() - drag_origin_.y()); 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y = std::min(view_model_->ideal_bounds(last_drag_index).bottom() - 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->ideal_bounds(current_index).height(), 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) y); 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_view_->y() == y) 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_view_->SetY(y); 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_index = 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ViewModelUtils::DetermineMoveIndex( 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *view_model_, drag_view_, 9891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) layout_manager_->IsHorizontalAlignment() ? 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ViewModelUtils::HORIZONTAL : 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::ViewModelUtils::VERTICAL, 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x, y); 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target_index = 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(indices.second, std::max(target_index, indices.first)); 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (target_index == current_index) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Change the model, the ShelfItemMoved() callback will handle the 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |view_model_| update. 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(current_index, target_index); 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->StopAnimatingView(drag_view_); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::HandleRipOffDrag(const ui::LocatedEvent& event) { 1005424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int current_index = view_model_->GetIndexOfView(drag_view_); 1006424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK_NE(-1, current_index); 1007a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) std::string dragged_app_id = 10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetAppIDForShelfID(model_->items()[current_index].id); 1009f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1010f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Point screen_location = event.root_location(); 10116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ::wm::ConvertPointToScreen(GetWidget()->GetNativeWindow()->GetRootWindow(), 10126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) &screen_location); 1013f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1014424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // To avoid ugly forwards and backwards flipping we use different constants 1015424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // for ripping off / re-inserting the items. 1016424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (dragged_off_shelf_) { 1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // If the shelf/overflow bubble bounds contains |screen_location| we insert 1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // the item back into the shelf. 1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (GetBoundsForDragInsertInScreen().Contains(screen_location)) { 1020a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (dragged_off_from_overflow_to_shelf_) { 1021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // During the dragging an item from Shelf to Overflow, it can enter here 1022a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // directly because both are located very closly. 1023a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->EndDrag(true); 1024a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Stops the animation of |drag_view_| and sets its bounds explicitly 1025a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // becase ContinueDrag() stops its animation. Without this, unexpected 1026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // bounds will be set. 1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bounds_animator_->StopAnimatingView(drag_view_); 1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int drag_view_index = view_model_->GetIndexOfView(drag_view_); 1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_view_->SetBoundsRect(view_model_->ideal_bounds(drag_view_index)); 1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_ = false; 1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1032424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Destroy our proxy view item. 1033424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DestroyDragIconProxy(); 1034424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Re-insert the item and return simply false since the caller will handle 1035424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // the move as in any normal case. 1036424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dragged_off_shelf_ = false; 1037424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_->layer()->SetOpacity(1.0f); 1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // The size of Overflow bubble should be updated immediately when an item 1039a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // is re-inserted. 1040f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_overflow_mode()) 1041f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PreferredSizeChanged(); 1042424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (is_overflow_mode() && 1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->GetBoundsForDragInsertInScreen().Contains( 1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) screen_location)) { 1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (!dragged_off_from_overflow_to_shelf_) { 1047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_ = true; 1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_image_->SetOpacity(1.0f); 1049a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->StartDrag(dragged_app_id, screen_location); 1050a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else { 1051a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->Drag(screen_location); 1052a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } 1053a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (dragged_off_from_overflow_to_shelf_) { 1054a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Makes the |drag_image_| partially disappear again. 1055a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_ = false; 1056a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_image_->SetOpacity(kDraggedImageOpacity); 1057a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->EndDrag(true); 1058a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) bounds_animator_->StopAnimatingView(drag_view_); 1059a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) int drag_view_index = view_model_->GetIndexOfView(drag_view_); 1060a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_view_->SetBoundsRect(view_model_->ideal_bounds(drag_view_index)); 1061424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1062424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Move our proxy view item. 1063f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UpdateDragIconProxy(screen_location); 1064424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 1065424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1066424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Check if we are too far away from the shelf to enter the ripped off state. 1067f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Determine the distance to the shelf. 10685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int delta = CalculateShelfDistance(screen_location); 1069424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (delta > kRipOffDistance) { 1070424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Create a proxy view item which can be moved anywhere. 1071f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButton* button = static_cast<ShelfButton*>(drag_view_); 1072424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) CreateDragIconProxy(event.root_location(), 1073424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) button->GetImage(), 1074424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_, 1075424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::Vector2d(0, 0), 1076424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) kDragAndDropProxyScale); 1077424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_->layer()->SetOpacity(0.0f); 10784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) dragged_off_shelf_ = true; 1079424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (RemovableByRipOff(current_index) == REMOVABLE) { 10801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Move the item to the front of the first panel item and hide it. 10815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // ShelfItemMoved() callback will handle the |view_model_| update and 10821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // call AnimateToIdealBounds(). 1083f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (current_index != model_->FirstPanelIndex() - 1) { 1084f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model_->Move(current_index, model_->FirstPanelIndex() - 1); 1085f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) StartFadeInLastVisibleItem(); 1086f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else if (is_overflow_mode()) { 1087f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Overflow bubble should be shrunk when an item is ripped off. 1088f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) PreferredSizeChanged(); 1089f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1090424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Make the item partially disappear to show that it will get removed if 1091424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // dropped. 1092a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_image_->SetOpacity(kDraggedImageOpacity); 1093424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1094424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 1095424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1096424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 1097424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 1098424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 10998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::FinalizeRipOffDrag(bool cancel) { 1100424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!dragged_off_shelf_) 1101424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 1102424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Make sure we do not come in here again. 1103424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) dragged_off_shelf_ = false; 1104424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1105424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Coming here we should always have a |drag_view_|. 1106424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DCHECK(drag_view_); 1107424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int current_index = view_model_->GetIndexOfView(drag_view_); 1108424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // If the view isn't part of the model anymore (|current_index| == -1), a sync 1109424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // operation must have removed it. In that case we shouldn't change the model 1110424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // and only delete the proxy image. 1111424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (current_index == -1) { 1112424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DestroyDragIconProxy(); 1113424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 1114424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1115424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1116424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Set to true when the animation should snap back to where it was before. 1117424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) bool snap_back = false; 1118424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Items which cannot be dragged off will be handled as a cancel. 1119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!cancel) { 1120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (dragged_off_from_overflow_to_shelf_) { 1121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_ = false; 1122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->EndDrag(false); 1123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_view_->layer()->SetOpacity(1.0f); 1124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (RemovableByRipOff(current_index) != REMOVABLE) { 1125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Make sure we do not try to remove un-removable items like items which 1126a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // were not pinned or have to be always there. 1127424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) cancel = true; 1128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) snap_back = true; 1129424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } else { 1130424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Make sure the item stays invisible upon removal. 1131424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_->SetVisible(false); 1132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) std::string app_id = 11335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) delegate_->GetAppIDForShelfID(model_->items()[current_index].id); 1134424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) delegate_->UnpinAppWithID(app_id); 1135424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1137424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (cancel || snap_back) { 1138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (dragged_off_from_overflow_to_shelf_) { 1139a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_from_overflow_to_shelf_ = false; 1140a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // Main shelf handles revert of dragged item. 1141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) main_shelf_->EndDrag(true); 1142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) drag_view_->layer()->SetOpacity(1.0f); 1143a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) } else if (!cancelling_drag_model_changed_) { 1144424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Only do something if the change did not come through a model change. 1145424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::Rect drag_bounds = drag_image_->GetBoundsInScreen(); 1146424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::Point relative_to = GetBoundsInScreen().origin(); 1147424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::Rect target( 1148424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) gfx::PointAtOffsetFromOrigin(drag_bounds.origin()- relative_to), 1149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_bounds.size()); 1150424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_->SetBoundsRect(target); 1151424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Hide the status from the active item since we snap it back now. Upon 1152424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // animation end the flag gets cleared if |snap_back_from_rip_off_view_| 1153424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // is set. 1154424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) snap_back_from_rip_off_view_ = drag_view_; 1155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButton* button = static_cast<ShelfButton*>(drag_view_); 1156f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->AddState(ShelfButton::STATE_HIDDEN); 1157424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // When a canceling drag model is happening, the view model is diverged 1158424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // from the menu model and movements / animations should not be done. 1159424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) model_->Move(current_index, start_drag_index_); 1160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) AnimateToIdealBounds(); 1161424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) drag_view_->layer()->SetOpacity(1.0f); 1163424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) DestroyDragIconProxy(); 1165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 1166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShelfView::RemovableState ShelfView::RemovableByRipOff(int index) const { 1168f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(index >= 0 && index < model_->item_count()); 11695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfItemType type = model_->items()[index].type; 11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (type == TYPE_APP_LIST || type == TYPE_DIALOG || !delegate_->CanPin()) 1171424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return NOT_REMOVABLE; 11725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string app_id = delegate_->GetAppIDForShelfID(model_->items()[index].id); 1174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // Note: Only pinned app shortcuts can be removed! 1175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return (type == TYPE_APP_SHORTCUT && delegate_->IsAppPinned(app_id)) ? 1176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) REMOVABLE : DRAGGABLE; 1177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 1178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShelfView::SameDragType(ShelfItemType typea, ShelfItemType typeb) const { 1180ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch switch (typea) { 1181ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case TYPE_APP_SHORTCUT: 1182ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case TYPE_BROWSER_SHORTCUT: 1183ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return (typeb == TYPE_APP_SHORTCUT || typeb == TYPE_BROWSER_SHORTCUT); 118468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) case TYPE_APP_LIST: 1185424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case TYPE_PLATFORM_APP: 1186ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case TYPE_WINDOWED_APP: 1187ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch case TYPE_APP_PANEL: 11885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case TYPE_DIALOG: 1189ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return typeb == typea; 1190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case TYPE_UNDEFINED: 11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED() << "ShelfItemType must be set."; 1192424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return false; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)std::pair<int, int> ShelfView::GetDragRange(int index) { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int min_index = -1; 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_index = -1; 12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfItemType type = model_->items()[index].type; 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < model_->item_count(); ++i) { 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (SameDragType(model_->items()[i].type, type)) { 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (min_index == -1) 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) min_index = i; 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_index = i; 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::pair<int, int>(min_index, max_index); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ConfigureChildView(views::View* view) { 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetPaintToLayer(true); 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->layer()->SetFillsBoundsOpaquely(false); 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ToggleOverflowBubble() { 12182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (IsShowingOverflowBubble()) { 12192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_bubble_->Hide(); 12202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 12212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!overflow_bubble_) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_bubble_.reset(new OverflowBubble()); 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ShelfView* overflow_view = 12271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ShelfView(model_, delegate_, layout_manager_); 1228f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) overflow_view->overflow_mode_ = true; 12292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_view->Init(); 12304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) overflow_view->set_owner_overflow_bubble(overflow_bubble_.get()); 12312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_view->OnShelfAlignmentChanged(); 1232a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) overflow_view->main_shelf_ = this; 12332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateOverflowRange(overflow_view); 12342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_bubble_->Show(overflow_button_, overflow_view); 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shell::GetInstance()->UpdateShelfVisibility(); 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnFadeOutAnimationEnded() { 12412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AnimateToIdealBounds(); 12421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) StartFadeInLastVisibleItem(); 12431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void ShelfView::StartFadeInLastVisibleItem() { 12462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If overflow button is visible and there is a valid new last item, fading 12472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the new last item in after sliding animation is finished. 12482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (overflow_button_->visible() && last_visible_index_ >= 0) { 12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View* last_visible_view = view_model_->view_at(last_visible_index_); 12502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_visible_view->layer()->SetOpacity(0); 12512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bounds_animator_->SetAnimationDelegate( 12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_visible_view, 1253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<gfx::AnimationDelegate>( 1254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new StartFadeAnimationDelegate(this, last_visible_view))); 12552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 12562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ShelfView::UpdateOverflowRange(ShelfView* overflow_view) const { 12592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int first_overflow_index = last_visible_index_ + 1; 12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const int last_overflow_index = last_hidden_index_; 12612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LE(first_overflow_index, last_overflow_index); 12622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(last_overflow_index, view_model_->view_size()); 12632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_view->first_visible_index_ = first_overflow_index; 12652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) overflow_view->last_visible_index_ = last_overflow_index; 12662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 12672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 12688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::ShouldHideTooltip(const gfx::Point& cursor_location) { 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect active_bounds; 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < child_count(); ++i) { 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* child = child_at(i); 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child == overflow_button_) 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ShouldShowTooltipForView(child)) 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Rect child_bounds = child->GetMirroredBounds(); 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_bounds.Union(child_bounds); 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !active_bounds.Contains(cursor_location); 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12858bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)gfx::Rect ShelfView::GetVisibleItemsBoundsInScreen() { 12864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Size preferred_size = GetPreferredSize(); 12874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0); 12884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ConvertPointToScreen(this, &origin); 12894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return gfx::Rect(origin, preferred_size); 12904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 12914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)gfx::Rect ShelfView::GetBoundsForDragInsertInScreen() { 1293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Size preferred_size; 1294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_overflow_mode()) { 1295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK(owner_overflow_bubble_); 1296f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect bubble_bounds = 1297f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) owner_overflow_bubble_->bubble_view()->GetBubbleBounds(); 1298f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) preferred_size = bubble_bounds.size(); 1299f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 1300f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const int last_button_index = view_model_->view_size() - 1; 1301f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Rect last_button_bounds = 1302f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) view_model_->view_at(last_button_index)->bounds(); 1303f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (overflow_button_->visible() && 1304f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) model_->GetItemIndexForType(TYPE_APP_PANEL) == -1) { 1305f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // When overflow button is visible and shelf has no panel items, 1306f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // last_button_bounds should be overflow button's bounds. 1307f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_button_bounds = overflow_button_->bounds(); 1308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (layout_manager_->IsHorizontalAlignment()) { 1311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) preferred_size = gfx::Size(last_button_bounds.right() + leading_inset_, 1312a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch kShelfSize); 1313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } else { 1314a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch preferred_size = gfx::Size(kShelfSize, 1315f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_button_bounds.bottom() + leading_inset_); 1316f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1317f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) } 1318f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) gfx::Point origin(GetMirroredXWithWidthInView(0, preferred_size.width()), 0); 1319f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1320f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // In overflow mode, we should use OverflowBubbleView as a source for 1321f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // converting |origin| to screen coordinates. When a scroll operation is 1322f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // occurred in OverflowBubble, the bounds of ShelfView in OverflowBubble can 1323f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // be changed. 1324f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (is_overflow_mode()) 1325f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConvertPointToScreen(owner_overflow_bubble_->bubble_view(), &origin); 1326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) else 1327f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ConvertPointToScreen(this, &origin); 1328f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) return gfx::Rect(origin, preferred_size); 1330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 13328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::CancelDrag(int modified_index) { 1333424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FinalizeRipOffDrag(true); 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!drag_view_) 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return modified_index; 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool was_dragging = dragging(); 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int drag_view_index = view_model_->GetIndexOfView(drag_view_); 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pointer_ = NONE; 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_view_ = NULL; 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_view_index == modified_index) { 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The view that was being dragged is being modified. Don't do anything. 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return modified_index; 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!was_dragging) 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return modified_index; 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Restore previous position, tracking the position of the modified view. 13482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool at_end = modified_index == view_model_->view_size(); 13492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) views::View* modified_view = 13502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (modified_index >= 0 && !at_end) ? 13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->view_at(modified_index) : NULL; 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->Move(drag_view_index, start_drag_index_); 13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the modified view will be at the end of the list, return the new end of 13552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the list. 13562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (at_end) 13572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return view_model_->view_size(); 13582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return modified_view ? view_model_->GetIndexOfView(modified_view) : -1; 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size ShelfView::GetPreferredSize() const { 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdealBounds ideal_bounds; 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalculateIdealBounds(&ideal_bounds); 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) int last_button_index = is_overflow_mode() ? 1366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_visible_index_ : view_model_->view_size() - 1; 1367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1368f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // When an item is dragged off from the overflow bubble, it is moved to last 1369f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // position and and changed to invisible. Overflow bubble size should be 1370f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // shrunk to fit only for visible items. 1371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // If |dragged_off_from_overflow_to_shelf_| is set, there will be no invisible 1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) // items in the shelf. 1373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if (is_overflow_mode() && 1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) dragged_off_shelf_ && 1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !dragged_off_from_overflow_to_shelf_ && 1376f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RemovableByRipOff(view_model_->GetIndexOfView(drag_view_)) == REMOVABLE) 1377f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) last_button_index--; 1378f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Rect last_button_bounds = 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) last_button_index >= first_visible_index_ ? 1381f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) view_model_->ideal_bounds(last_button_index) : 1382a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch gfx::Rect(gfx::Size(kShelfSize, kShelfSize)); 13832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 13841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (layout_manager_->IsHorizontalAlignment()) { 1385a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return gfx::Size(last_button_bounds.right() + leading_inset_, kShelfSize); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1388a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return gfx::Size(kShelfSize, 13891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) last_button_bounds.bottom() + leading_inset_); 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsChanged(const gfx::Rect& previous_bounds) { 13935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // This bounds change is produced by the shelf movement and all content has 13945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // to follow. Using an animation at that time would produce a time lag since 13955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // the animation of the BoundsAnimator has itself a delay before it arrives 13965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // at the required location. As such we tell the animator to go there 13975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // immediately. 13985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) BoundsAnimatorDisabler disabler(bounds_animator_.get()); 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LayoutToIdealBounds(); 14001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FOR_EACH_OBSERVER(ShelfIconObserver, observers_, 14011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OnShelfIconPositionsChanged()); 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsShowingOverflowBubble()) 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_bubble_->Hide(); 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)views::FocusTraversable* ShelfView::GetPaneFocusTraversable() { 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return this; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1411a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void ShelfView::GetAccessibleState(ui::AXViewState* state) { 1412a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_TOOLBAR; 14132385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch state->name = l10n_util::GetStringUTF16(IDS_ASH_SHELF_ACCESSIBLE_NAME); 141490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 141590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 14168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnGestureEvent(ui::GestureEvent* event) { 14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (gesture_handler_.ProcessGestureEvent(*event)) 14182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) event->StopPropagation(); 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemAdded(int model_index) { 14222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 14232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> cancelling_drag( 14242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelling_drag_model_changed_, true); 14252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_index = CancelDrag(model_index); 14262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view = CreateViewForItem(model_->items()[model_index]); 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(view); 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Hide the view, it'll be made visible when the animation is done. Using 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // opacity 0 here to avoid messing with CalculateIdealBounds which touches 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the view's visibility. 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->layer()->SetOpacity(0); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Add(view, model_index); 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Give the button its ideal bounds. That way if we end up animating the 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // button before this animation completes it doesn't appear at some random 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // spot (because it was in the middle of animating from 0,0 0x0 to its 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // target). 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IdealBounds ideal_bounds; 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CalculateIdealBounds(&ideal_bounds); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetBoundsRect(view_model_->ideal_bounds(model_index)); 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The first animation moves all the views to their target position. |view| 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // is hidden, so it visually appears as though we are providing space for 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // it. When done we'll fade the view in. 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToIdealBounds(); 14472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (model_index <= last_visible_index_ || 14482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_index >= model_->FirstPanelIndex()) { 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->SetAnimationDelegate( 1450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) view, 1451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<gfx::AnimationDelegate>( 1452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new StartFadeAnimationDelegate(this, view))); 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Undo the hiding if animation does not run. 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->layer()->SetOpacity(1.0f); 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ShelfView::ShelfItemRemoved(int model_index, ShelfID id) { 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (id == context_menu_id_) 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) launcher_menu_runner_.reset(); 14622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::AutoReset<bool> cancelling_drag( 14642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &cancelling_drag_model_changed_, true); 14652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) model_index = CancelDrag(model_index); 14662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view = view_model_->view_at(model_index); 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Remove(model_index); 14690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 14700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // When the overflow bubble is visible, the overflow range needs to be set 14710f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // before CalculateIdealBounds() gets called. Otherwise CalculateIdealBounds() 14725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // could trigger a ShelfItemChanged() by hiding the overflow bubble and 1473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // since the overflow bubble is not yet synced with the ShelfModel this 14740f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // could cause a crash. 14752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (overflow_bubble_ && overflow_bubble_->IsShowing()) { 14762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) last_hidden_index_ = std::min(last_hidden_index_, 14772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_model_->view_size() - 1); 14788bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) UpdateOverflowRange(overflow_bubble_->shelf_view()); 14792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1480d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 14810f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (view->visible()) { 14820f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // The first animation fades out the view. When done we'll animate the rest 14830f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // of the views to their target location. 14840f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bounds_animator_->AnimateViewTo(view, view->bounds()); 14850f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) bounds_animator_->SetAnimationDelegate( 1486f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) view, 1487f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<gfx::AnimationDelegate>( 1488f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) new FadeOutAnimationDelegate(this, view))); 14890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } else { 14900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // We don't need to show a fade out animation for invisible |view|. When an 14910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // item is ripped out from the shelf, its |view| is already invisible. 14920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AnimateToIdealBounds(); 14930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 14940f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1495d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Close the tooltip because it isn't needed any longer and its anchor view 1496d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // will be deleted soon. 1497d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) if (tooltip_->GetCurrentAnchorView() == view) 1498d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) tooltip_->Close(); 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ShelfView::ShelfItemChanged(int model_index, const ShelfItem& old_item) { 15025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ShelfItem& item(model_->items()[model_index]); 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_item.type != item.type) { 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Type changed, swap the views. 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_index = CancelDrag(model_index); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<views::View> old_view(view_model_->view_at(model_index)); 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bounds_animator_->StopAnimatingView(old_view.get()); 15083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // Removing and re-inserting a view in our view model will strip the ideal 15093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // bounds from the item. To avoid recalculation of everything the bounds 15103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) // get remembered and restored after the insertion to the previous value. 15113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) gfx::Rect old_ideal_bounds = view_model_->ideal_bounds(model_index); 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Remove(model_index); 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* new_view = CreateViewForItem(item); 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(new_view); 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Add(new_view, model_index); 15163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) view_model_->set_ideal_bounds(model_index, old_ideal_bounds); 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_view->SetBoundsRect(old_view->bounds()); 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) views::View* view = view_model_->view_at(model_index); 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (item.type) { 15232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TYPE_BROWSER_SHORTCUT: 1524f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Fallthrough for the new Shelf since it needs to show the activation 15252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // change as well. 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_APP_SHORTCUT: 15272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case TYPE_WINDOWED_APP: 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_PLATFORM_APP: 15295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case TYPE_DIALOG: 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case TYPE_APP_PANEL: { 1531f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButton* button = static_cast<ShelfButton*>(view); 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReflectItemStatus(item, button); 15332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The browser shortcut is currently not a "real" item and as such the 15342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the image is bogous as well. We therefore keep the image as is for it. 15352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (item.type != TYPE_BROWSER_SHORTCUT) 15362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) button->SetImage(item.image); 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) button->SchedulePaint(); 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1546f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfItemMoved(int start_index, int target_index) { 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_model_->Move(start_index, target_index); 15485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // When cancelling a drag due to a shelf item being added, the currently 15492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // dragged item is moved back to its initial position. AnimateToIdealBounds 15502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // will be called again when the new item is added to the |view_model_| but 15512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // at this time the |view_model_| is inconsistent with the |model_|. 15522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!cancelling_drag_model_changed_) 15532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AnimateToIdealBounds(); 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1556f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void ShelfView::ShelfStatusChanged() { 1557a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // Nothing to do here. 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerPressedOnButton(views::View* view, 15618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Pointer pointer, 15628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ui::LocatedEvent& event) { 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_view_) 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int index = view_model_->GetIndexOfView(view); 1567424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (index == -1) 1568424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return; 1569424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate( 15714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_->items()[index].id); 15724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (view_model_->view_size() <= 1 || !item_delegate->IsDraggable()) 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; // View is being deleted or not draggable, ignore request. 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_view_ = view; 1576f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) drag_origin_ = gfx::Point(event.x(), event.y()); 1577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) UMA_HISTOGRAM_ENUMERATION("Ash.ShelfAlignmentUsage", 1578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) layout_manager_->SelectValueForShelfAlignment( 1579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SHELF_ALIGNMENT_UMA_ENUM_VALUE_BOTTOM, 1580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SHELF_ALIGNMENT_UMA_ENUM_VALUE_LEFT, 1581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SHELF_ALIGNMENT_UMA_ENUM_VALUE_RIGHT, 1582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) -1), 1583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) SHELF_ALIGNMENT_UMA_ENUM_VALUE_COUNT); 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15868bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerDraggedOnButton(views::View* view, 15878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Pointer pointer, 15888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ui::LocatedEvent& event) { 15890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // To prepare all drag types (moving an item in the shelf and dragging off), 15900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) // we should check the x-axis and y-axis offset. 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!dragging() && drag_view_ && 1592f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ((std::abs(event.x() - drag_origin_.x()) >= kMinimumDragDistance) || 1593f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (std::abs(event.y() - drag_origin_.y()) >= kMinimumDragDistance))) { 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrepareForDrag(pointer, event); 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (drag_pointer_ == pointer) 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContinueDrag(event); 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::PointerReleasedOnButton(views::View* view, 16018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) Pointer pointer, 16028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool canceled) { 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (canceled) { 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CancelDrag(-1); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (drag_pointer_ == pointer) { 1606424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) FinalizeRipOffDrag(false); 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_pointer_ = NONE; 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimateToIdealBounds(); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1610ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // If the drag pointer is NONE, no drag operation is going on and the 1611ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch // drag_view can be released. 1612ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch if (drag_pointer_ == NONE) 1613ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch drag_view_ = NULL; 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseMovedOverButton(views::View* view) { 16172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ShouldShowTooltipForView(view)) 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tooltip_->IsVisible()) 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tooltip_->ResetTimer(); 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseEnteredButton(views::View* view) { 16252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!ShouldShowTooltipForView(view)) 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tooltip_->IsVisible()) { 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tooltip_->ShowImmediately(view, GetAccessibleName(view)); 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tooltip_->ShowDelayed(view, GetAccessibleName(view)); 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::MouseExitedButton(views::View* view) { 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tooltip_->IsVisible()) 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tooltip_->StopTimer(); 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)base::string16 ShelfView::GetAccessibleName(const views::View* view) { 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int view_index = view_model_->GetIndexOfView(view); 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // May be -1 while in the process of animating closed. 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_index == -1) 1644c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return base::string16(); 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1646a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate( 16474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_->items()[view_index].id); 16484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return item_delegate->GetTitle(); 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ButtonPressed(views::Button* sender, const ui::Event& event) { 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Do not handle mouse release during drag. 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dragging()) 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sender == overflow_button_) { 16572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ToggleOverflowBubble(); 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int view_index = view_model_->GetIndexOfView(sender); 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // May be -1 while in the process of animating closed. 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_index == -1) 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the previous menu was closed by the same event as this one, we ignore 16672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the call. 16682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsUsableEvent(event)) 16692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 16702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 16711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Don't activate the item twice on double-click. Otherwise the window starts 16721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // animating open due to the first click, then immediately minimizes due to 16731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the second click. The user most likely intended to open or minimize the 16741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // item once, not do both. 16751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (event.flags() & ui::EF_IS_DOUBLE_CLICK) 16761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 16771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 16782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { 1679a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ScopedTargetRootWindow scoped_target( 1680a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) sender->GetWidget()->GetNativeView()->GetRootWindow()); 16812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Slow down activation animations if shift key is pressed. 16822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_ptr<ui::ScopedAnimationDurationScaleMode> slowing_animations; 16832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (event.IsShiftDown()) { 16842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) slowing_animations.reset(new ui::ScopedAnimationDurationScaleMode( 16852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ScopedAnimationDurationScaleMode::SLOW_DURATION)); 16862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 16872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1688b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Collect usage statistics before we decide what to do with the click. 1689b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) switch (model_->items()[view_index].type) { 1690b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case TYPE_APP_SHORTCUT: 1691b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case TYPE_WINDOWED_APP: 1692b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case TYPE_PLATFORM_APP: 169390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) case TYPE_BROWSER_SHORTCUT: 16945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()->metrics()->RecordUserMetricsAction( 1695b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_LAUNCHER_CLICK_ON_APP); 1696b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1698b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) case TYPE_APP_LIST: 16995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) Shell::GetInstance()->metrics()->RecordUserMetricsAction( 1700b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) UMA_LAUNCHER_CLICK_ON_APPLIST_BUTTON); 1701424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 1702424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1703424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case TYPE_APP_PANEL: 17045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case TYPE_DIALOG: 1705424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 1706424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1707424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) case TYPE_UNDEFINED: 17085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOTREACHED() << "ShelfItemType must be set."; 1709b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) break; 17102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1711424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 1712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = 1713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) item_manager_->GetShelfItemDelegate(model_->items()[view_index].id); 1714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (!item_delegate->ItemSelected(event)) 1715f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShowListMenuForView(model_->items()[view_index], sender, event); 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool ShelfView::ShowListMenuForView(const ShelfItem& item, 17208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) views::View* source, 17218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const ui::Event& event) { 1722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = 1723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) item_manager_->GetShelfItemDelegate(item.id); 17241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci scoped_ptr<ui::MenuModel> list_menu_model( 17251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci item_delegate->CreateApplicationMenu(event.flags())); 17262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Make sure we have a menu and it has at least two items in addition to the 17282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // application title and the 3 spacing separators. 17291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!list_menu_model.get() || list_menu_model->GetItemCount() <= 5) 17302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 17312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ShowMenu(list_menu_model.get(), 17332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source, 17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Point(), 17357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) false, 17367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ui::GetMenuSourceTypeForEvent(event)); 17372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::ShowContextMenuForView(views::View* source, 17418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const gfx::Point& point, 17428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ui::MenuSourceType source_type) { 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int view_index = view_model_->GetIndexOfView(source); 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (view_index == -1) { 17457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Shell::GetInstance()->ShowContextMenu(point, source_type); 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1749a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = item_manager_->GetShelfItemDelegate( 17504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) model_->items()[view_index].id); 1751cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) context_menu_model_.reset(item_delegate->CreateContextMenu( 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) source->GetWidget()->GetNativeView()->GetRootWindow())); 1753cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!context_menu_model_) 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1755424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 17565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::AutoReset<ShelfID> reseter( 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &context_menu_id_, 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view_index == -1 ? 0 : model_->items()[view_index].id); 17592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1760cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ShowMenu(context_menu_model_.get(), 17612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) source, 17622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) point, 17637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) true, 17647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) source_type); 17652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 17662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1767cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void ShelfView::ShowMenu(ui::MenuModel* menu_model, 17688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) views::View* source, 17698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) const gfx::Point& click_point, 17708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) bool context_menu, 17718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) ui::MenuSourceType source_type) { 17722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_event_time_ = base::TimeDelta(); 1773116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch launcher_menu_runner_.reset(new views::MenuRunner( 1774116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch menu_model, context_menu ? views::MenuRunner::CONTEXT_MENU : 0)); 17752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1776a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ScopedTargetRootWindow scoped_target( 1777a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) source->GetWidget()->GetNativeView()->GetRootWindow()); 1778a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 17792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Determine the menu alignment dependent on the shelf. 17805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu views::MenuAnchorPosition menu_alignment = views::MENU_ANCHOR_TOPLEFT; 17812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect anchor_point = gfx::Rect(click_point, gfx::Size()); 17822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfWidget* shelf = RootWindowController::ForShelf( 1784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetWidget()->GetNativeView())->shelf(); 17852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!context_menu) { 17862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Application lists use a bubble. 17875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfAlignment align = shelf->GetAlignment(); 17882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) anchor_point = source->GetBoundsInScreen(); 17892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 17907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // It is possible to invoke the menu while it is sliding into view. To cover 17917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // that case, the screen coordinates are offsetted by the animation delta. 17927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) gfx::Vector2d offset = 17937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) source->GetWidget()->GetNativeWindow()->bounds().origin() - 17947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) source->GetWidget()->GetNativeWindow()->GetTargetBounds().origin(); 17957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) anchor_point.set_x(anchor_point.x() - offset.x()); 17967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) anchor_point.set_y(anchor_point.y() - offset.y()); 17977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 1798f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Shelf items can have an asymmetrical border for spacing reasons. 17992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Adjust anchor location for this. 18002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (source->border()) 18012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) anchor_point.Inset(source->border()->GetInsets()); 18022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (align) { 18045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_BOTTOM: 18055c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu menu_alignment = views::MENU_ANCHOR_BUBBLE_ABOVE; 18062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_LEFT: 18085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu menu_alignment = views::MENU_ANCHOR_BUBBLE_RIGHT; 18092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_RIGHT: 18115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu menu_alignment = views::MENU_ANCHOR_BUBBLE_LEFT; 18122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_TOP: 18145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu menu_alignment = views::MENU_ANCHOR_BUBBLE_BELOW; 18152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) break; 18162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 18185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // If this gets deleted while we are in the menu, the shelf will be gone 1819c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // as well. 1820c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool got_deleted = false; 1821c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) got_deleted_ = &got_deleted; 1822c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 1823c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shelf->ForceUndimming(true); 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: if you convert to HAS_MNEMONICS be sure and update menu building 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // code. 1826116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (launcher_menu_runner_->RunMenuAt(source->GetWidget(), 1827116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch NULL, 1828116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch anchor_point, 1829116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch menu_alignment, 1830116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch source_type) == 18317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) views::MenuRunner::MENU_DELETED) { 1832c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!got_deleted) { 1833c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) got_deleted_ = NULL; 1834c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shelf->ForceUndimming(false); 1835c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1837c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1838c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) got_deleted_ = NULL; 1839c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shelf->ForceUndimming(false); 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // If it is a context menu and we are showing overflow bubble 18424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // we want to hide overflow bubble. 18434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (owner_overflow_bubble_) 18444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) owner_overflow_bubble_->HideBubbleAndRefreshButton(); 18454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 18462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Unpinning an item will reset the |launcher_menu_runner_| before coming 18472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // here. 1848c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (launcher_menu_runner_) 18492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_event_time_ = launcher_menu_runner_->closing_event_time(); 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Shell::GetInstance()->UpdateShelfVisibility(); 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsAnimatorProgressed(views::BoundsAnimator* animator) { 18541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FOR_EACH_OBSERVER(ShelfIconObserver, observers_, 18551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) OnShelfIconPositionsChanged()); 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PreferredSizeChanged(); 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void ShelfView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) { 1860424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (snap_back_from_rip_off_view_ && animator == bounds_animator_) { 1861424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!animator->IsAnimating(snap_back_from_rip_off_view_)) { 1862f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // Coming here the animation of the ShelfButton is finished and the 1863424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // previously hidden status can be shown again. Since the button itself 1864424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // might have gone away or changed locations we check that the button 1865424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) // is still in the shelf and show its status again. 1866424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) for (int index = 0; index < view_model_->view_size(); index++) { 1867424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) views::View* view = view_model_->view_at(index); 1868424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (view == snap_back_from_rip_off_view_) { 1869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ShelfButton* button = static_cast<ShelfButton*>(view); 1870f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) button->ClearState(ShelfButton::STATE_HIDDEN); 1871424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 1872424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1873424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1874424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) snap_back_from_rip_off_view_ = NULL; 1875424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1876424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18798bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::IsUsableEvent(const ui::Event& event) { 18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (closing_event_time_ == base::TimeDelta()) 18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta delta = 18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::TimeDelta(event.time_stamp() - closing_event_time_); 18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) closing_event_time_ = base::TimeDelta(); 18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(skuhne): This time seems excessive, but it appears that the reposting 18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // takes that long. Need to come up with a better way of doing this. 18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (delta.InMilliseconds() < 0 || delta.InMilliseconds() > 130); 18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)const ShelfItem* ShelfView::ShelfItemForView(const views::View* view) const { 18922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int view_index = view_model_->GetIndexOfView(view); 18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (view_index == -1) 18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return &(model_->items()[view_index]); 18962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 18988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool ShelfView::ShouldShowTooltipForView(const views::View* view) const { 18992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (view == GetAppListButtonView() && 19002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Shell::GetInstance()->GetAppListWindow()) 19012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 19025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ShelfItem* item = ShelfItemForView(view); 1903424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) if (!item) 1904424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return true; 1905a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) ShelfItemDelegate* item_delegate = 1906a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) item_manager_->GetShelfItemDelegate(item->id); 19074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return item_delegate->ShouldShowTooltip(); 1908424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)} 1909424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 19108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)int ShelfView::CalculateShelfDistance(const gfx::Point& coordinate) const { 19115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfWidget* shelf = RootWindowController::ForShelf( 1912424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) GetWidget()->GetNativeView())->shelf(); 19135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ShelfAlignment align = shelf->GetAlignment(); 1914424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) const gfx::Rect bounds = GetBoundsInScreen(); 1915424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) int distance = 0; 1916424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) switch (align) { 19175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_BOTTOM: 1918424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) distance = bounds.y() - coordinate.y(); 1919424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 19205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_LEFT: 1921424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) distance = coordinate.x() - bounds.right(); 1922424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 19235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_RIGHT: 1924424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) distance = bounds.x() - coordinate.x(); 1925424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 19265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SHELF_ALIGNMENT_TOP: 1927424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) distance = coordinate.y() - bounds.bottom(); 1928424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) break; 1929424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) } 1930424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) return distance > 0 ? distance : 0; 19312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 19322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace ash 1934