browser_actions_container.cc revision 03b57e008b61dfcb1fbad3aea950ae0e001748b0
1f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Copyright 2013 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) 5f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_actions_container.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h" 903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "chrome/browser/extensions/extension_action_manager.h" 108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/extensions/extension_util.h" 11f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/extensions/extension_view_host.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include "chrome/browser/ui/browser_window.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/tabs/tab_strip_model.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/view_ids.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/browser_action_drag_data.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/views/extensions/extension_popup.h" 215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/browser_actions_container_observer.h" 22f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/ui/views/toolbar/toolbar_view.h" 23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "chrome/common/extensions/command.h" 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/runtime_data.h" 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/feature_switch.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/generated_resources.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/theme_resources.h" 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "third_party/skia/include/core/SkColor.h" 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "ui/accessibility/ax_view_state.h" 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/dragdrop/drag_utils.h" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/base/nine_image_painter_factory.h" 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/theme_provider.h" 37d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "ui/gfx/animation/slide_animation.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/gfx/canvas.h" 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/gfx/geometry/rect.h" 4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "ui/resources/grit/ui_resources.h" 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "ui/views/controls/button/label_button_border.h" 425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "ui/views/controls/button/menu_button.h" 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/controls/resize_area.h" 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/metrics.h" 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/views/painter.h" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/views/widget/widget.h" 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using extensions::Extension; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Horizontal spacing between most items in the container, as well as after the 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// last item or chevron (if visible). 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kItemSpacing = ToolbarView::kStandardSpacing; 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Horizontal spacing before the chevron (if visible). 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kChevronSpacing = kItemSpacing - 2; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 59116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// The maximum number of icons to show per row when in overflow mode (showing 60116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// icons in the application menu). 61116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// TODO(devlin): Compute the right number of icons to show, depending on the 62116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// menu width. 63116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#if defined(OS_LINUX) 64116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kIconsPerMenuRow = 8; // The menu on Linux is wider. 65116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#else 66116680a4aac90f2aa7413d9095a592090648e557Ben Murdochconst int kIconsPerMenuRow = 7; 67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#endif 68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 6903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Returns the ExtensionAction for the given |extension|. 7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)ExtensionAction* GetExtensionAction(const Extension& extension, 7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Profile* profile) { 7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extensions::ExtensionActionManager* action_manager = 7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) extensions::ExtensionActionManager::Get(profile); 7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionAction* action = action_manager->GetBrowserAction(extension); 7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return action ? action : action_manager->GetPageAction(extension); 7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A version of MenuButton with almost empty insets to fit properly on the 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// toolbar. 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ChevronMenuButton : public views::MenuButton { 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ChevronMenuButton(views::ButtonListener* listener, 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::string16& text, 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) views::MenuButtonListener* menu_button_listener, 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool show_menu_marker) 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : views::MenuButton(listener, 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) text, 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) menu_button_listener, 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) show_menu_marker) { 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~ChevronMenuButton() {} 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OVERRIDE { 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The chevron resource was designed to not have any insets. 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<views::LabelButtonBorder> border = 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) views::MenuButton::CreateDefaultBorder(); 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) border->set_insets(gfx::Insets()); 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return border.Pass(); 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ChevronMenuButton); 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// BrowserActionsContainer::DropPosition 1115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct BrowserActionsContainer::DropPosition { 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DropPosition(size_t row, size_t icon_in_row); 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The (0-indexed) row into which the action will be dropped. 1165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t row; 1175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The (0-indexed) icon in the row before the action will be dropped. 1195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t icon_in_row; 1205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 1215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BrowserActionsContainer::DropPosition::DropPosition( 1235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t row, size_t icon_in_row) 1245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : row(row), icon_in_row(icon_in_row) { 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserActionsContainer 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static 1315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool BrowserActionsContainer::disable_animations_during_testing_ = false; 1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 133116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBrowserActionsContainer::BrowserActionsContainer( 134116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Browser* browser, 135116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch View* owner_view, 136116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionsContainer* main_container) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : profile_(browser->profile()), 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view_(owner_view), 140116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch main_container_(main_container), 1415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_(NULL), 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(NULL), 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_(0), 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_(NULL), 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_(NULL), 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_(NULL), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_(false), 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_(0), 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_(0), 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) task_factory_(this), 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) show_menu_task_factory_(this) { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch model_ = extensions::ExtensionToolbarModel::Get(browser->profile()); 155f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (model_) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool overflow_experiment = 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions::FeatureSwitch::extension_action_redesign()->IsEnabled(); 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!in_overflow_mode() || overflow_experiment); 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!in_overflow_mode()) { 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews( 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser->profile(), 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch owner_view->GetFocusManager(), 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS, 167116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this)); 168116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 169116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_animation_.reset(new gfx::SlideAnimation(this)); 170116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_ = new views::ResizeArea(this); 171116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddChildView(resize_area_); 172116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 173116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 'Main' mode doesn't need a chevron overflow when overflow is shown inside 174116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the Chrome menu. 175116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!overflow_experiment) { 176116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_ = new ChevronMenuButton(NULL, base::string16(), this, false); 177116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetBorder(views::Border::NullBorder()); 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->EnableCanvasFlippingForRTLUI(true); 179116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetAccessibleName( 180116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_CHEVRON)); 181116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible(false); 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddChildView(chevron_); 183116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 184116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsContainer::~BrowserActionsContainer() { 188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerDestroyed()); 191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (overflow_menu_) 1937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) overflow_menu_->set_observer(NULL); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 1975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HideActivePopup(); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteBrowserActionViews(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Init() { 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait to set the container width until now so that the chevron images 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be loaded. The width calculation needs to know the chevron size. 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_ && model_->extensions_initialized()) 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionView* BrowserActionsContainer::GetBrowserActionView( 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAction* action) { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserActionViews::iterator i(browser_action_views_.begin()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != browser_action_views_.end(); ++i) { 2146e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((*i)->extension_action() == action) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return *i; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::RefreshBrowserActionViews() { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) 2226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) browser_action_views_[i]->UpdateState(); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CreateBrowserActionViews() { 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser_action_views_.empty()); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& toolbar_items = model_->toolbar_items(); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (extensions::ExtensionList::const_iterator i(toolbar_items.begin()); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != toolbar_items.end(); ++i) { 2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!ShouldDisplayBrowserAction(i->get())) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = 23703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new BrowserActionView(i->get(), 23803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) GetExtensionAction(*i->get(), profile_), 23903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_, 24003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this); 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.push_back(view); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(view); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::DeleteBrowserActionViews() { 2475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HideActivePopup(); 248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (overflow_menu_) 249116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->NotifyBrowserActionViewsDeleting(); 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&browser_action_views_); 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActions() const { 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t visible_actions = 0; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_[i]->visible()) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++visible_actions; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return visible_actions; 26046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 26146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 26246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActionsAfterAnimation() const { 26346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!animating()) 26446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return VisibleBrowserActions(); 26546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return WidthToIconCount(animation_target_size_); 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 269a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserActionsContainer::ExecuteExtensionCommand( 270a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Extension* extension, 271a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Command& command) { 272a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Global commands are handled by the ExtensionCommandsGlobalRegistry 273a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // instance. 274a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!command.global()); 275a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extension_keybinding_registry_->ExecuteCommand(extension->id(), 276a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command.accelerator()); 277a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 278a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 279116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BrowserActionsContainer::ShownInsideMenu() const { 280116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return in_overflow_mode(); 281116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 282116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BrowserActionsContainer::OnBrowserActionViewDragDone() { 2845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We notify here as well as in OnPerformDrop because the dragged view is 2855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // removed in OnPerformDrop, so it will never get its OnDragDone() call. 2865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(devlin): we should see about fixing that. 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 2885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnBrowserActionDragDone()); 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)views::View* BrowserActionsContainer::GetOverflowReferenceView() { 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We should only need an overflow reference when using the traditional 2945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // chevron overflow. 2955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(chevron_); 2965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return chevron_; 2975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionsContainer::SetPopupOwner(BrowserActionView* popup_owner) { 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We should never be setting a popup owner when one already exists. 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(!popup_owner_ || !popup_owner); 3025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_ = popup_owner; 3035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BrowserActionsContainer::HideActivePopup() { 3065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (popup_owner_) 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_->view_controller()->HidePopup(); 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::AddObserver( 311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.AddObserver(observer); 313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::RemoveObserver( 316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.RemoveObserver(observer); 318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 320cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetPreferredSize() const { 32103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t icon_count = GetIconCount(); 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // If there are no actions to show, or we are in overflow mode and the main 324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // container is already showing them all, then no further work is required. 325116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (icon_count == 0) 326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size(); 327116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (in_overflow_mode()) { 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // When in overflow, y is multiline, so the pixel count is IconHeight() 330116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // times the number of rows needed. 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size( 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IconCountToWidth(kIconsPerMenuRow, false), 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (((icon_count - 1) / kIconsPerMenuRow) + 1) * IconHeight()); 334116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We calculate the size of the view by taking the current width and 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subtracting resize_amount_ (the latter represents how far the user is 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resizing the view or, if animating the snapping, how far to animate it). 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // But we also clamp it to a minimum size and the maximum size, so that the 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // container can never shrink too far or take up more space than it needs. 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // In other words: MinimumNonemptyWidth() < width() - resize < ClampTo(MAX). 342cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int preferred_width = std::min( 343cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::max(MinimumNonemptyWidth(), container_width_ - resize_amount_), 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconCountToWidth(-1, false)); 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size(preferred_width, IconHeight()); 346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 347cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 348cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetMinimumSize() const { 349cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1, false)); 350116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size(min_width, IconHeight()); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Layout() { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.empty()) { 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(false); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(true); 360116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (resize_area_) 361116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_->SetBounds(0, 0, kItemSpacing, height()); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icons don't all fit, show the chevron (unless suppressed). 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_x = GetPreferredSize().width(); 365116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((IconCountToWidth(-1, false) > max_x) && !suppress_chevron_ && chevron_) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(true); 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size chevron_size(chevron_->GetPreferredSize()); 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_x -= 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing + chevron_size.width() + kChevronSpacing; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetBounds( 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - ToolbarView::kStandardSpacing - chevron_size.width(), 372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 0, 373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.width(), 374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.height()); 375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (chevron_) { 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(false); 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now draw the icons for the browser actions in the available space. 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_width = IconWidth(false); 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (in_overflow_mode()) { 382116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t i = 0; 383116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch i < main_container_->VisibleBrowserActionsAfterAnimation(); ++i) { 384116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Ensure that any browser actions shown in the main view are hidden in 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the overflow view. 386116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_[i]->SetVisible(false); 387116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 388116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 389116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t i = main_container_->VisibleBrowserActionsAfterAnimation(); 390116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch i < browser_action_views_.size(); ++i) { 391116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionView* view = browser_action_views_[i]; 392116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t index = i - main_container_->VisibleBrowserActionsAfterAnimation(); 393116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int row_index = static_cast<int>(index) / kIconsPerMenuRow; 3945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int x = kItemSpacing + (index * IconWidth(true)) - 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (row_index * IconWidth(true) * kIconsPerMenuRow); 396116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect rect_bounds( 397116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch x, IconHeight() * row_index, icon_width, IconHeight()); 398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetBoundsRect(rect_bounds); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetVisible(true); 400116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (BrowserActionViews::const_iterator it = browser_action_views_.begin(); 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it < browser_action_views_.end(); ++it) { 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionView* view = *it; 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int x = ToolbarView::kStandardSpacing + 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ((it - browser_action_views_.begin()) * IconWidth(true)); 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetVisible(x + icon_width <= max_x); 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (view->visible()) 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetBounds(x, 0, icon_width, IconHeight()); 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::GetDropFormats( 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<OSExchangeData::CustomFormat>* custom_formats) { 4175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::GetDropFormats(custom_formats); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::AreDropTypesRequired() { 4215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::AreDropTypesRequired(); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { 4255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::CanDrop(data, profile_); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnDragEntered( 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnDragUpdated( 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check if we are above the chevron (overflow) menu. 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (GetEventHandlerForPoint(event.location()) == chevron_) { 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!show_menu_task_factory_.HasWeakPtrs() && !overflow_menu_) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartShowFolderDropMenuTimer(); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Figure out where to display the indicator. This is a complex calculation: 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, we figure out how much space is to the left of the icon area, so we 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // can calculate the true offset into the icon area. The easiest way to do 4465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // this is to just find where the first icon starts. 4475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int width_before_icons = 4485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) browser_action_views_[GetFirstVisibleIconIndex()]->x(); 4495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If we're right-to-left, we flip the mirror the event.x() so that our 4515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // calculations are consistent with left-to-right. 4525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int offset_into_icon_area = 4535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) GetMirroredXInView(event.x()) - width_before_icons; 4545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Next, figure out what row we're on. This only matters for overflow mode, 4565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // but the calculation is the same for both. 4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t row_index = event.y() / IconHeight(); 4585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Sanity check - we should never be on a different row in the main container. 4605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK(in_overflow_mode() || row_index == 0); 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Next, we determine which icon to place the indicator in front of. We want 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to place the indicator in front of icon n when the cursor is between the 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // midpoints of icons (n - 1) and n. To do this we take the offset into the 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon area and transform it as follows: 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Real icon area: 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 a * b c 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // | | | | 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |[IC|ON] [IC|ON] [IC|ON] 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We want to be before icon 0 for 0 < x <= a, icon 1 for a < x <= b, etc. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Here the "*" represents the offset into the icon area, and since it's 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // between a and b, we want to return "1". 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Transformed "icon area": 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 0 a * b c 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // | | | | 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |[ICON] |[ICON] |[ICON] | 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we shift both our offset and our divider points later by half an icon 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plus one spacing unit, then it becomes very easy to calculate how many 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // divider points we've passed, because they're the multiples of "one icon 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // plus padding". 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int before_icon_unclamped = (offset_into_icon_area + (IconWidth(false) / 2) + 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kItemSpacing) / IconWidth(true); 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // We need to figure out how many icons are visible on the relevant row. 4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // In the main container, this will just be the visible actions. 4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int visible_icons_on_row = VisibleBrowserActionsAfterAnimation(); 4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (in_overflow_mode()) { 4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If this is the final row of the overflow, then this is the remainder of 4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // visible icons. Otherwise, it's a full row (kIconsPerRow). 4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visible_icons_on_row = 4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row_index == 4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) static_cast<size_t>(visible_icons_on_row / kIconsPerMenuRow) ? 4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) visible_icons_on_row % kIconsPerMenuRow : 4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kIconsPerMenuRow; 4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because the user can drag outside the container bounds, we need to clamp to 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the valid range. Note that the maximum allowable value is (num icons), not 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (num icons - 1), because we represent the indicator being past the last 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // icon as being "before the (last + 1) icon". 5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t before_icon_in_row = 5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_position_.get() || 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !(drop_position_->row == row_index && 5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_->icon_in_row == before_icon_in_row)) { 5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_.reset(new DropPosition(row_index, before_icon_in_row)); 5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SchedulePaint(); 5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnDragExited() { 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_.reset(); 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnPerformDrop( 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionDragData data; 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!data.Read(event.data())) 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we have the same view as we started with. 5296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(browser_action_views_[data.index()]->extension()->id(), 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.id()); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model_); 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t i = 5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_->row * kIconsPerMenuRow + drop_position_->icon_in_row; 5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (in_overflow_mode()) 5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) i += GetFirstVisibleIconIndex(); 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |i| now points to the item to the right of the drop indicator*, which is 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correct when dragging an icon to the left. When dragging to the right, 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // however, we want the icon being dragged to get the index of the item to 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the left of the drop indicator, so we subtract one. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * Well, it can also point to the end, but not when dragging to the left. :) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > data.index()) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --i; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = model_->IncognitoIndexToOriginal(i); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 54803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_->MoveExtensionIcon( 5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) browser_action_views_[data.index()]->extension(), i); 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnDragExited(); // Perform clean up after dragging. 5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnBrowserActionDragDone()); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::GetAccessibleState( 559a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui::AXViewState* state) { 560a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_GROUP; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS); 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnMenuButtonClicked(views::View* source, 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) { 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source == chevron_) { 567116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_ = 568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BrowserActionOverflowMenuController(this, 569116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_, 570116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_, 571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_, 572116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisibleBrowserActions(), 573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch false); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 575116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->RunMenu(GetWidget()); 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::WriteDragDataForView(View* sender, 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSExchangeData* data) { 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 5856e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BrowserActionView* view = browser_action_views_[i]; 5866e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (view == sender) { 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the dragging image for the icon. 5886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gfx::ImageSkia badge(view->GetIconWithBadge()); 589f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) drag_utils::SetDragImageOnDataObject(badge, 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) press_pt.OffsetFromOrigin(), 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill in the remaining info. 5946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BrowserActionDragData drag_data(view->extension()->id(), i); 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data.Write(profile_, data); 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::GetDragOperationsForView(View* sender, 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanStartDragForView(View* sender, 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 609effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // We don't allow dragging while we're highlighting. 610effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return !model_->is_highlighting(); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) { 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done_resizing) { 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = resize_amount; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Up until now we've only been modifying the resize_amount, but now it is 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time to set the container size to the size we have resized to, and then 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animate to the nearest icon count size if necessary (which may be 0). 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_width = IconCountToWidth(-1, false); 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(std::max(0, container_width_ - resize_amount), max_width); 62603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 62703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Save off the desired number of visible icons. We do this now instead of at 62803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the end of the animation so that even if the browser is shut down while 62903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // animating, the right value will be restored on next run. 63003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // NOTE: Don't save the icon count in incognito because there may be fewer 63103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // icons in that mode. The result is that the container in a normal window is 63203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // always at least as wide as in an incognito window. 63303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int visible_icons = WidthToIconCount(container_width_); 63403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!profile_->IsOffTheRecord()) 63503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_->SetVisibleIconCount(visible_icons); 63603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 63703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, visible_icons); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::AnimationProgressed( 641d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(resize_animation_.get(), animation); 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (container_width_ - animation_target_size_)); 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 648d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BrowserActionsContainer::AnimationEnded(const gfx::Animation* animation) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = animation_target_size_; 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = 0; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = 0; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_ = false; 653a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 654effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 655effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 656effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 657effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerAnimationEnded()); 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::NotifyMenuDeleted( 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionOverflowMenuController* controller) { 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(overflow_menu_, controller); 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_ = NULL; 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { 6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return browser_->tab_strip_model()->GetActiveWebContents(); 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::ActiveTabPermissionGranter* 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionsContainer::GetActiveTabPermissionGranter() { 6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents = 6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!web_contents) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions::TabHelper::FromWebContents(web_contents)-> 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_tab_permission_granter(); 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::MoveBrowserAction(const std::string& extension_id, 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t new_index) { 6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension = extensions::ExtensionRegistry::Get(profile_)-> 6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) enabled_extensions().GetByID(extension_id); 68403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_->MoveExtensionIcon(extension, new_index); 6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SchedulePaint(); 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)size_t BrowserActionsContainer::GetFirstVisibleIconIndex() const { 6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return in_overflow_mode() ? model_->GetVisibleIconCount() : 0; 690a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 691a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ExtensionPopup* BrowserActionsContainer::TestGetPopup() { 6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->SetVisibleIconCount(icons); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(icons < browser_action_views_.size()); 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = IconCountToWidth(icons, chevron_->visible()); 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { 705effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the views haven't been initialized yet, wait for the next call to 706effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // paint (one will be triggered by entering highlight mode). 707effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (model_->is_highlighting() && !browser_action_views_.empty()) { 708effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch views::Painter::PaintPainterAt( 709effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas, highlight_painter_.get(), GetLocalBounds()); 710effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 711effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky/glen): Instead of using a drop indicator, animate the icons while 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dragging (like we do for tab dragging). 7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (drop_position_.get()) { 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The two-pixel width drop indicator. 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kDropIndicatorWidth = 2; 7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Convert back to a pixel offset into the container. First find the X 7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // coordinate of the drop icon. 7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int drop_icon_x = browser_action_views_[GetFirstVisibleIconIndex()]->x() + 7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (drop_position_->icon_in_row * IconWidth(true)); 7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Next, find the space before the drop icon. This will either be 7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // kItemSpacing or ToolbarView::kStandardSpacing, depending on whether this 7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // is the first icon. 7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // NOTE: Right now, these are the same. But let's do this right for if they 7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ever aren't. 7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int space_before_drop_icon = drop_position_->icon_in_row == 0 ? 7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ToolbarView::kStandardSpacing : kItemSpacing; 7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Now place the drop indicator halfway between this and the end of the 7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // previous icon. If there is an odd amount of available space between the 7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // two icons (or the icon and the address bar) after subtracting the drop 7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // indicator width, this calculation puts the extra pixel on the left side 7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // of the indicator, since when the indicator is between the address bar and 7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the first icon, it looks better closer to the icon. 7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int drop_indicator_x = drop_icon_x - 7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ((space_before_drop_icon + kDropIndicatorWidth) / 2); 7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int row_height = IconHeight(); 7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int drop_indicator_y = row_height * drop_position_->row; 7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Rect indicator_bounds(drop_indicator_x, 7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_indicator_y, 7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kDropIndicatorWidth, 7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row_height); 7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) indicator_bounds.set_x(GetMirroredXForRect(indicator_bounds)); 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Color of the drop indicator. 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const SkColor kDropIndicatorColor = SK_ColorBLACK; 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->FillRect(indicator_bounds, kDropIndicatorColor); 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnThemeChanged() { 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void BrowserActionsContainer::ViewHierarchyChanged( 756a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const ViewHierarchyChangedDetails& details) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No extensions (e.g., incognito). 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 761a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details.is_add && details.child == this) { 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initial toolbar button creation and placement in the widget hierarchy. 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do this here instead of in the constructor because AddBrowserAction 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls Layout on the Toolbar, which needs this object to be constructed 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before its Layout function is called. 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateBrowserActionViews(); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconWidth(bool include_padding) { 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_width = 0; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_width = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->width(); 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_width + (include_padding ? kItemSpacing : 0); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconHeight() { 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_height = 0; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_height = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->height(); 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_height; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 79403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionAdded(const Extension* extension, 79503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int index) { 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DEBUG) 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 7986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(browser_action_views_[i]->extension() != extension) << 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Asked to add a browser action view for an extension that already " 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "exists."; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the new browser action to the vector and the view hierarchy. 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 81103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = 81203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new BrowserActionView(extension, 81303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) GetExtensionAction(*extension, profile_), 81403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_, 81503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this); 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.insert(browser_action_views_.begin() + index, view); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildViewAt(view, index); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are still initializing the container, don't bother animating. 820f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!model_->extensions_initialized()) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Enlarge the container if it was already at maximum size and we're not in 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the middle of upgrading. 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((model_->GetVisibleIconCount() < 0) && 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) !extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) { 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_ = true; 82903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::LINEAR, browser_action_views_.size()); 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Just redraw the (possibly modified) visible icon set. 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 83603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionRemoved( 83703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) { 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 84046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t visible_actions = VisibleBrowserActionsAfterAnimation(); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserActionViews::iterator i(browser_action_views_.begin()); 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != browser_action_views_.end(); ++i) { 8436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((*i)->extension() == extension) { 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete *i; 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.erase(i); 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the extension is being upgraded we don't want the bar to shrink 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because the icon is just going to get re-added to the same location. 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.size() > visible_actions) { 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have more icons than we can show, then we must not be changing 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the container size (since we either removed an icon from the main 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // area and one from the overflow list will have shifted in, or we 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed an entry directly from the overflow list). 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either we went from overflow to no-overflow, or we shrunk the no- 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overflow container by 1. Either way the size changed, so animate. 862116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (chevron_) 863116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible(false); 86403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, browser_action_views_.size()); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 866116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; // We have found the action to remove, bail out. 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionMoved(const Extension* extension, 87203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int index) { 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 88103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionViews::iterator iter = browser_action_views_.begin(); 88203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int old_index = 0; 88303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (iter != browser_action_views_.end() && 88403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*iter)->extension() != extension) { 88503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++iter; 88603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++old_index; 88703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 88803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 88903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(iter != browser_action_views_.end()); 89003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (old_index == index) 89103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; // Already in place. 89203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 89303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* moved_view = *iter; 89403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.erase(iter); 89503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.insert( 89603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.begin() + index, moved_view); 89703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionUpdated( 90303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) { 90403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = GetViewForExtension(extension); 90503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (view) 90603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) view->UpdateState(); 90703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 90803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 90903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BrowserActionsContainer::ShowExtensionActionPopup( 9105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Extension* extension) { 9115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return ShowPopupForExtension(extension, false, false); 9128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 9138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 91403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarVisibleCountChanged() { 91503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int old_container_width = container_width_; 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetContainerWidth(); 91703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (old_container_width != container_width_) 91803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, GetIconCount()); 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 92103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarHighlightModeChanged( 92203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool is_highlighting) { 923effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // The visual highlighting is done in OnPaint(). It's a bit of a pain that 92403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // we delete and recreate everything here, but given everything else going on 92503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // (the lack of highlight, n more extensions appearing, etc), it's not worth 92603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the extra complexity to create and insert only the new extensions. 927effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DeleteBrowserActionViews(); 928effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateBrowserActionViews(); 92903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::LINEAR, browser_action_views_.size()); 930effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 931effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::LoadImages() { 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ThemeProvider* tp = GetThemeProvider(); 934116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!tp || !chevron_) 935116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 936116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 937f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) chevron_->SetImage(views::Button::STATE_NORMAL, 938f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *tp->GetImageSkiaNamed(IDR_BROWSER_ACTIONS_OVERFLOW)); 939effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 940effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const int kImages[] = IMAGE_GRID(IDR_DEVELOPER_MODE_HIGHLIGHT); 941effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlight_painter_.reset(views::Painter::CreateImageGridPainter(kImages)); 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 94403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::OnBrowserActionVisibilityChanged() { 94503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetVisible(!browser_action_views_.empty()); 94603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (owner_view_) { 94703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) owner_view_->Layout(); 94803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) owner_view_->SchedulePaint(); 94903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 95003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 95103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::SetContainerWidth() { 95303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int visible_actions = GetIconCount(); 954116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (chevron_) { 955116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible( 956116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch static_cast<size_t>(visible_actions) < model_->toolbar_items().size()); 957116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 958116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch container_width_ = 959116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch IconCountToWidth(visible_actions, chevron_ && chevron_->visible()); 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CloseOverflowMenu() { 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overflow_menu_) 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->CancelMenu(); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StopShowFolderDropMenuTimer() { 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.InvalidateWeakPtrs(); 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StartShowFolderDropMenuTimer() { 972b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BrowserActionsContainer::ShowDropFolder, 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.GetWeakPtr()), 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay())); 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::ShowDropFolder() { 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!overflow_menu_); 9815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_.reset(); 982116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_ = 983116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BrowserActionOverflowMenuController(this, 984116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_, 985116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_, 986116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_, 987116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisibleBrowserActions(), 988116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true); 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 990116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->RunMenu(GetWidget()); 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconCountToWidth(int icons, 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool display_chevron) const { 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icons < 0) 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icons = browser_action_views_.size(); 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((icons == 0) && !display_chevron) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing; 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icons_size = 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing); 1001116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int chevron_size = chevron_ && display_chevron ? 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing + icons_size + chevron_size + 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing; 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for widths large enough to show the entire icon set. 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pixels >= IconCountToWidth(-1, false)) 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser_action_views_.size(); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We need to reserve space for the resize area, chevron, and the spacing on 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // either side of the chevron. 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int available_space = pixels - ToolbarView::kStandardSpacing - 1015116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch (chevron_ ? chevron_->GetPreferredSize().width() : 0) - 1016116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch kChevronSpacing - ToolbarView::kStandardSpacing; 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we add an extra between-item padding value so the space can be divided 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // evenly by (size of icon with padding). 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<size_t>( 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, available_space + kItemSpacing) / IconWidth(true)); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1023cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BrowserActionsContainer::MinimumNonemptyWidth() const { 1024116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!chevron_) 1025116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ToolbarView::kStandardSpacing; 1026116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + 1027116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->GetPreferredSize().width(); 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 103003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type, 103103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t num_visible_icons) { 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_size = IconCountToWidth(num_visible_icons, 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_visible_icons < browser_action_views_.size()); 1034116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (resize_animation_ && !disable_animations_during_testing_) { 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate! We have to set the animation_target_size_ after calling Reset(), 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because that could end up calling AnimationEnded which clears the value. 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Reset(); 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->SetTweenType(tween_type); 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Show(); 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimationEnded(resize_animation_.get()); 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::ShouldDisplayBrowserAction( 104803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) const { 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only display incognito-enabled extensions while in incognito mode. 10505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !profile_->IsOffTheRecord() || 10515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::util::IsIncognitoEnabled(extension->id(), profile_); 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool BrowserActionsContainer::ShowPopupForExtension( 10555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const extensions::Extension* extension, 10565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool grant_tab_permissions, 10575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) bool can_override) { 10585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // If the popup cannot override other views, then no other popups can be 10595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // showing, and it must be shown in the active widow with a visible toolbar. 10605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // TODO(justinlin): Remove toolbar check when http://crbug.com/308645 is 10615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // fixed. 10625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!can_override && 10635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (popup_owner_ || 10645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !browser_->window()->IsActive() || 10655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !browser_->window()->IsToolbarVisible())) { 10668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) return false; 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 106903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = GetViewForExtension(extension); 107003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return view ? view->view_controller()->ExecuteAction( 107103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ExtensionPopup::SHOW, grant_tab_permissions) : false; 107203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 107303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 107403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)BrowserActionView* BrowserActionsContainer::GetViewForExtension( 107503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) { 107603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (BrowserActionViews::iterator view = browser_action_views_.begin(); 107703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) view != browser_action_views_.end(); ++view) { 107803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if ((*view)->extension() == extension) 107903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return *view; 108003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 108103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 108203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return NULL; 108303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 108403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 108503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)size_t BrowserActionsContainer::GetIconCount() const { 108603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!model_) 108703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return 0u; 108803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Find the number of icons which could be displayed. 108903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t displayable_icon_count = 0u; 109003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const extensions::ExtensionList& extensions = model_->toolbar_items(); 109103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for (extensions::ExtensionList::const_iterator iter = extensions.begin(); 109203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) iter != extensions.end(); ++iter) { 109303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) displayable_icon_count += ShouldDisplayBrowserAction(*iter) ? 1u : 0u; 10945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 109503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Find the absolute value for the model's visible count. 109603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int model_size = model_->GetVisibleIconCount(); 109703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t absolute_model_size = 109803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_size == -1 ? extensions.size() : model_size; 109903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 110003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The main container will try to show |model_size| icons, but reduce if there 110103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // aren't enough displayable icons to do so. 110203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t main_displayed = std::min(displayable_icon_count, absolute_model_size); 110303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // The overflow will display the extras, if any. 110403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return in_overflow_mode() ? 110503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) displayable_icon_count - main_displayed : main_displayed; 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1107