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_popup.h" 201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/browser/ui/views/frame/browser_view.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" 241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h" 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "extensions/browser/extension_registry.h" 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/extension_system.h" 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "extensions/browser/runtime_data.h" 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "extensions/common/feature_switch.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 before the chevron (if visible). 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int kChevronSpacing = ToolbarView::kStandardSpacing - 2; 5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A version of MenuButton with almost empty insets to fit properly on the 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// toolbar. 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ChevronMenuButton : public views::MenuButton { 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ChevronMenuButton(views::ButtonListener* listener, 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const base::string16& text, 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) views::MenuButtonListener* menu_button_listener, 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool show_menu_marker) 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) : views::MenuButton(listener, 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) text, 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) menu_button_listener, 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) show_menu_marker) { 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual ~ChevronMenuButton() {} 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) virtual scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) OVERRIDE { 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The chevron resource was designed to not have any insets. 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) scoped_ptr<views::LabelButtonBorder> border = 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) views::MenuButton::CreateDefaultBorder(); 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) border->set_insets(gfx::Insets()); 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return border.Pass(); 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ChevronMenuButton); 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// BrowserActionsContainer::DropPosition 885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)struct BrowserActionsContainer::DropPosition { 905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DropPosition(size_t row, size_t icon_in_row); 915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The (0-indexed) row into which the action will be dropped. 935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t row; 945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // The (0-indexed) icon in the row before the action will be dropped. 965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t icon_in_row; 975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}; 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)BrowserActionsContainer::DropPosition::DropPosition( 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t row, size_t icon_in_row) 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) : row(row), icon_in_row(icon_in_row) { 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//////////////////////////////////////////////////////////////////////////////// 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// BrowserActionsContainer 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// static 1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint BrowserActionsContainer::icons_per_overflow_menu_row_ = 1; 1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst int BrowserActionsContainer::kItemSpacing = ToolbarView::kStandardSpacing; 1121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci// static 1145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)bool BrowserActionsContainer::disable_animations_during_testing_ = false; 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 116116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBrowserActionsContainer::BrowserActionsContainer( 117116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch Browser* browser, 118116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch View* owner_view, 119116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionsContainer* main_container) 1201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : initialized_(false), 1211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci profile_(browser->profile()), 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_(browser), 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) owner_view_(owner_view), 124116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch main_container_(main_container), 1255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_(NULL), 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_(NULL), 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_(0), 128116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_(NULL), 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_(NULL), 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_(NULL), 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_(false), 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_(0), 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_(0), 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) show_menu_task_factory_(this) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch model_ = extensions::ExtensionToolbarModel::Get(browser->profile()); 138f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (model_) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->AddObserver(this); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 141116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool overflow_experiment = 142116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions::FeatureSwitch::extension_action_redesign()->IsEnabled(); 143116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch DCHECK(!in_overflow_mode() || overflow_experiment); 144116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 145116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!in_overflow_mode()) { 146116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extension_keybinding_registry_.reset(new ExtensionKeybindingRegistryViews( 147116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser->profile(), 148116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch owner_view->GetFocusManager(), 149116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch extensions::ExtensionKeybindingRegistry::ALL_EXTENSIONS, 150116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch this)); 151116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 152116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_animation_.reset(new gfx::SlideAnimation(this)); 153116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_ = new views::ResizeArea(this); 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddChildView(resize_area_); 155116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 156116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // 'Main' mode doesn't need a chevron overflow when overflow is shown inside 157116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the Chrome menu. 158116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!overflow_experiment) { 159116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_ = new ChevronMenuButton(NULL, base::string16(), this, false); 160116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->EnableCanvasFlippingForRTLUI(true); 161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetAccessibleName( 162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS_CHEVRON)); 163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible(false); 164116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch AddChildView(chevron_); 165116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 166116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BrowserActionsContainer::~BrowserActionsContainer() { 170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerDestroyed()); 173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (overflow_menu_) 1757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) overflow_menu_->set_observer(NULL); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (model_) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) model_->RemoveObserver(this); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 1795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HideActivePopup(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteBrowserActionViews(); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Init() { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We wait to set the container width until now so that the chevron images 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will be loaded. The width calculation needs to know the chevron size. 1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (model_ && model_->extensions_initialized()) { 1891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci container_width_ = GetPreferredWidth(); 1901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetChevronVisibility(); 1911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 1921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 1931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci initialized_ = true; 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowserActionView* BrowserActionsContainer::GetViewForExtension( 1971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension) { 1981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (BrowserActionViews::iterator view = browser_action_views_.begin(); 1991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci view != browser_action_views_.end(); ++view) { 2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if ((*view)->extension() == extension) 2011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return *view; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::RefreshBrowserActionViews() { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) 2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) browser_action_views_[i]->UpdateState(); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CreateBrowserActionViews() { 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(browser_action_views_.empty()); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionActionManager* action_manager = 2171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionActionManager::Get(profile_); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::ExtensionList& toolbar_items = model_->toolbar_items(); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (extensions::ExtensionList::const_iterator i(toolbar_items.begin()); 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != toolbar_items.end(); ++i) { 2217d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!ShouldDisplayBrowserAction(i->get())) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = 22503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new BrowserActionView(i->get(), 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci action_manager->GetExtensionAction(**i), 22703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_, 22803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.push_back(view); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildView(view); 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::DeleteBrowserActionViews() { 2355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) HideActivePopup(); 236116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (overflow_menu_) 237116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->NotifyBrowserActionViewsDeleting(); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) STLDeleteElements(&browser_action_views_); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActions() const { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t visible_actions = 0; 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_[i]->visible()) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ++visible_actions; 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return visible_actions; 24846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 24946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 25046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)size_t BrowserActionsContainer::VisibleBrowserActionsAfterAnimation() const { 25146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!animating()) 25246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return VisibleBrowserActions(); 25346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return WidthToIconCount(animation_target_size_); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void BrowserActionsContainer::ExecuteExtensionCommand( 258a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Extension* extension, 259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const extensions::Command& command) { 260a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // Global commands are handled by the ExtensionCommandsGlobalRegistry 261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // instance. 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) DCHECK(!command.global()); 263a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) extension_keybinding_registry_->ExecuteCommand(extension->id(), 264a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) command.accelerator()); 265a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 266a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserActionsContainer::NotifyActionMovedToOverflow() { 2681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // When an action is moved to overflow, we shrink the size of the container 2691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // by 1. 2701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!profile_->IsOffTheRecord()) { 2711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int icon_count = model_->GetVisibleIconCount(); 2721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Since this happens when an icon moves from the main bar to overflow, we 2731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // can't possibly have had no visible icons on the main bar. 2741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK_NE(0, icon_count); 2751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (icon_count == -1) 2761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icon_count = browser_action_views_.size(); 2771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci model_->SetVisibleIconCount(icon_count - 1); 2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Animate(gfx::Tween::EASE_OUT, 2801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VisibleBrowserActionsAfterAnimation() - 1); 2811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 2821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 283116680a4aac90f2aa7413d9095a592090648e557Ben Murdochbool BrowserActionsContainer::ShownInsideMenu() const { 284116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return in_overflow_mode(); 285116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 286116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 2875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BrowserActionsContainer::OnBrowserActionViewDragDone() { 2881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ToolbarVisibleCountChanged(); 2895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 2905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) observers_, 2915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) OnBrowserActionDragDone()); 2925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 2935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciviews::MenuButton* BrowserActionsContainer::GetOverflowReferenceView() { 2951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // With traditional overflow, the reference is the chevron. With the 2961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // redesign, we use the wrench menu instead. 2971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return chevron_ ? 2981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chevron_ : 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserView::GetBrowserViewForBrowser(browser_)->toolbar()->app_menu(); 3005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void BrowserActionsContainer::SetPopupOwner(BrowserActionView* popup_owner) { 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We should never be setting a popup owner when one already exists, and 3041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // never unsetting one when one wasn't set. 3051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK((!popup_owner_ && popup_owner) || 3061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (popup_owner_ && !popup_owner)); 3075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_ = popup_owner; 3085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void BrowserActionsContainer::HideActivePopup() { 3115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (popup_owner_) 3125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) popup_owner_->view_controller()->HidePopup(); 3135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowserActionView* BrowserActionsContainer::GetMainViewForExtension( 3161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension) { 3171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return in_overflow_mode() ? 3181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main_container_->GetViewForExtension(extension) : 3191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetViewForExtension(extension); 3201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::AddObserver( 323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.AddObserver(observer); 325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BrowserActionsContainer::RemoveObserver( 328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch BrowserActionsContainerObserver* observer) { 329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_.RemoveObserver(observer); 330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetPreferredSize() const { 333116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (in_overflow_mode()) { 3341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int icon_count = GetIconCount(); 3351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // In overflow, we always have a preferred size of a full row (even if we 3361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // don't use it), and always of at least one row. The parent may decide to 3371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // show us even when empty, e.g. as a drag target for dragging in icons from 3381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the main container. 3391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int row_count = 3401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ((std::max(0, icon_count - 1)) / icons_per_overflow_menu_row_) + 1; 341116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size( 3421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci IconCountToWidth(icons_per_overflow_menu_row_, false), 3431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci row_count * IconHeight()); 344116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 345116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there are no actions to show, then don't show the container at all. 3471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (browser_action_views_.empty()) 3481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return gfx::Size(); 3491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We calculate the size of the view by taking the current width and 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // subtracting resize_amount_ (the latter represents how far the user is 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // resizing the view or, if animating the snapping, how far to animate it). 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // But we also clamp it to a minimum size and the maximum size, so that the 354116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // container can never shrink too far or take up more space than it needs. 355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // In other words: MinimumNonemptyWidth() < width() - resize < ClampTo(MAX). 356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int preferred_width = std::min( 357cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) std::max(MinimumNonemptyWidth(), container_width_ - resize_amount_), 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconCountToWidth(-1, false)); 359116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size(preferred_width, IconHeight()); 360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 361cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 3621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint BrowserActionsContainer::GetHeightForWidth(int width) const { 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (in_overflow_mode()) 3641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icons_per_overflow_menu_row_ = (width - kItemSpacing) / IconWidth(true); 3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return GetPreferredSize().height(); 3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 368cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)gfx::Size BrowserActionsContainer::GetMinimumSize() const { 369cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1, false)); 370116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return gfx::Size(min_width, IconHeight()); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::Layout() { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.empty()) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(false); 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetVisible(true); 380116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (resize_area_) 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch resize_area_->SetBounds(0, 0, kItemSpacing, height()); 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the icons don't all fit, show the chevron (unless suppressed). 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_x = GetPreferredSize().width(); 385116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if ((IconCountToWidth(-1, false) > max_x) && !suppress_chevron_ && chevron_) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(true); 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) gfx::Size chevron_size(chevron_->GetPreferredSize()); 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) max_x -= 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ToolbarView::kStandardSpacing + chevron_size.width() + kChevronSpacing; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetBounds( 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) width() - ToolbarView::kStandardSpacing - chevron_size.width(), 392effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 0, 393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.width(), 394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chevron_size.height()); 395116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else if (chevron_) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chevron_->SetVisible(false); 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now draw the icons for the browser actions in the available space. 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icon_width = IconWidth(false); 401116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (in_overflow_mode()) { 402116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t i = 0; 403116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch i < main_container_->VisibleBrowserActionsAfterAnimation(); ++i) { 404116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // Ensure that any browser actions shown in the main view are hidden in 405116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // the overflow view. 406116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_[i]->SetVisible(false); 407116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 408116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 409116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (size_t i = main_container_->VisibleBrowserActionsAfterAnimation(); 410116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch i < browser_action_views_.size(); ++i) { 411116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionView* view = browser_action_views_[i]; 412116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch size_t index = i - main_container_->VisibleBrowserActionsAfterAnimation(); 4131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int row_index = static_cast<int>(index) / icons_per_overflow_menu_row_; 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int x = kItemSpacing + (index * IconWidth(true)) - 4151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (row_index * IconWidth(true) * icons_per_overflow_menu_row_); 416116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch gfx::Rect rect_bounds( 417116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch x, IconHeight() * row_index, icon_width, IconHeight()); 418116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetBoundsRect(rect_bounds); 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) view->SetVisible(true); 420116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 421116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } else { 422116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch for (BrowserActionViews::const_iterator it = browser_action_views_.begin(); 423116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch it < browser_action_views_.end(); ++it) { 424116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch BrowserActionView* view = *it; 425116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int x = ToolbarView::kStandardSpacing + 426116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ((it - browser_action_views_.begin()) * IconWidth(true)); 427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetVisible(x + icon_width <= max_x); 428116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (view->visible()) 429116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch view->SetBounds(x, 0, icon_width, IconHeight()); 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::GetDropFormats( 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int* formats, 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<OSExchangeData::CustomFormat>* custom_formats) { 4375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::GetDropFormats(custom_formats); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::AreDropTypesRequired() { 4415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::AreDropTypesRequired(); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanDrop(const OSExchangeData& data) { 4455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return BrowserActionDragData::CanDrop(data, profile_); 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnDragUpdated( 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First check if we are above the chevron (overflow) menu. 4511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (chevron_ && GetEventHandlerForPoint(event.location()) == chevron_) { 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!show_menu_task_factory_.HasWeakPtrs() && !overflow_menu_) 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StartShowFolderDropMenuTimer(); 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t row_index = 0; 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t before_icon_in_row = 0; 4601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If there are no visible browser actions (such as when dragging an icon to 4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // an empty overflow/main container), then 0, 0 for row, column is correct. 4621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (VisibleBrowserActions() != 0) { 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Figure out where to display the indicator. This is a complex calculation: 4641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // First, we subtract out the padding to the left of the icon area, which is 4661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ToolbarView::kStandardSpacing. If we're right-to-left, we also mirror the 4671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // event.x() so that our calculations are consistent with left-to-right. 4681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int offset_into_icon_area = 4691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetMirroredXInView(event.x()) - ToolbarView::kStandardSpacing; 4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Next, figure out what row we're on. This only matters for overflow mode, 4721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // but the calculation is the same for both. 4731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci row_index = event.y() / IconHeight(); 4741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Sanity check - we should never be on a different row in the main 4761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // container. 4771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DCHECK(in_overflow_mode() || row_index == 0); 4781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Next, we determine which icon to place the indicator in front of. We want 4801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to place the indicator in front of icon n when the cursor is between the 4811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // midpoints of icons (n - 1) and n. To do this we take the offset into the 4821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // icon area and transform it as follows: 4831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Real icon area: 4851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 0 a * b c 4861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // | | | | 4871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |[IC|ON] [IC|ON] [IC|ON] 4881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We want to be before icon 0 for 0 < x <= a, icon 1 for a < x <= b, etc. 4891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Here the "*" represents the offset into the icon area, and since it's 4901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // between a and b, we want to return "1". 4911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 4921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Transformed "icon area": 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // 0 a * b c 4941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // | | | | 4951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // |[ICON] |[ICON] |[ICON] | 4961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If we shift both our offset and our divider points later by half an icon 4971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // plus one spacing unit, then it becomes very easy to calculate how many 4981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // divider points we've passed, because they're the multiples of "one icon 4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // plus padding". 5001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int before_icon_unclamped = 5011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (offset_into_icon_area + (IconWidth(false) / 2) + 5021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci kItemSpacing) / IconWidth(true); 5031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We need to figure out how many icons are visible on the relevant row. 5051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // In the main container, this will just be the visible actions. 5061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int visible_icons_on_row = VisibleBrowserActionsAfterAnimation(); 5071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (in_overflow_mode()) { 5081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this is the final row of the overflow, then this is the remainder of 5091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // visible icons. Otherwise, it's a full row (kIconsPerRow). 5101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci visible_icons_on_row = 5111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci row_index == 5121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci static_cast<size_t>(visible_icons_on_row / 5131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icons_per_overflow_menu_row_) ? 5141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci visible_icons_on_row % icons_per_overflow_menu_row_ : 5151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci icons_per_overflow_menu_row_; 5161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 5181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Because the user can drag outside the container bounds, we need to clamp 5191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // to the valid range. Note that the maximum allowable value is (num icons), 5201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // not (num icons - 1), because we represent the indicator being past the 5211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // last icon as being "before the (last + 1) icon". 5221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci before_icon_in_row = 5231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row); 5241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (!drop_position_.get() || 5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) !(drop_position_->row == row_index && 5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_->icon_in_row == before_icon_in_row)) { 5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_.reset(new DropPosition(row_index, before_icon_in_row)); 5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) SchedulePaint(); 5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnDragExited() { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) StopShowFolderDropMenuTimer(); 5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_position_.reset(); 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::OnPerformDrop( 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ui::DropTargetEvent& event) { 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionDragData data; 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!data.Read(event.data())) 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_NONE; 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure we have the same view as we started with. 5496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK_EQ(browser_action_views_[data.index()]->extension()->id(), 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data.id()); 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(model_); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t i = drop_position_->row * icons_per_overflow_menu_row_ + 5541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci drop_position_->icon_in_row; 5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (in_overflow_mode()) 5561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci i += main_container_->VisibleBrowserActionsAfterAnimation(); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |i| now points to the item to the right of the drop indicator*, which is 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // correct when dragging an icon to the left. When dragging to the right, 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // however, we want the icon being dragged to get the index of the item to 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the left of the drop indicator, so we subtract one. 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // * Well, it can also point to the end, but not when dragging to the left. :) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i > data.index()) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) --i; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i = model_->IncognitoIndexToOriginal(i); 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this was a drag between containers, we will have to adjust the number of 5691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // visible icons. 5701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool drag_between_containers = 5711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci !browser_action_views_[data.index()]->visible(); 57203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_->MoveExtensionIcon( 5736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) browser_action_views_[data.index()]->extension(), i); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (drag_between_containers) { 5761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Add one for the dropped icon. 5771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t new_icon_count = VisibleBrowserActionsAfterAnimation() + 1; 5781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Let the main container update the model. 5801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (in_overflow_mode()) 5811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main_container_->NotifyActionMovedToOverflow(); 5821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else if (!profile_->IsOffTheRecord()) // This is the main container. 5831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci model_->SetVisibleIconCount(model_->GetVisibleIconCount() + 1); 5841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The size changed, so we need to animate. 5861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Animate(gfx::Tween::EASE_OUT, new_icon_count); 5871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 5881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnDragExited(); // Perform clean up after dragging. 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::GetAccessibleState( 594a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ui::AXViewState* state) { 595a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) state->role = ui::AX_ROLE_GROUP; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_EXTENSIONS); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnMenuButtonClicked(views::View* source, 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& point) { 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (source == chevron_) { 602116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_ = 603116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BrowserActionOverflowMenuController(this, 604116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_, 605116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_, 606116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_, 607116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisibleBrowserActions(), 608116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch false); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 610116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->RunMenu(GetWidget()); 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::WriteDragDataForView(View* sender, 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OSExchangeData* data) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(data); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 6206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BrowserActionView* view = browser_action_views_[i]; 6216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if (view == sender) { 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set the dragging image for the icon. 6236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) gfx::ImageSkia badge(view->GetIconWithBadge()); 624f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) drag_utils::SetDragImageOnDataObject(badge, 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) press_pt.OffsetFromOrigin(), 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data); 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Fill in the remaining info. 6296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) BrowserActionDragData drag_data(view->extension()->id(), i); 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) drag_data.Write(profile_, data); 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::GetDragOperationsForView(View* sender, 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ui::DragDropTypes::DRAG_MOVE; 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::CanStartDragForView(View* sender, 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& press_pt, 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const gfx::Point& p) { 644effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // We don't allow dragging while we're highlighting. 645effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return !model_->is_highlighting(); 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) { 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!done_resizing) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = resize_amount; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Up until now we've only been modifying the resize_amount, but now it is 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // time to set the container size to the size we have resized to, and then 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // animate to the nearest icon count size if necessary (which may be 0). 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_width = IconCountToWidth(-1, false); 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::min(std::max(0, container_width_ - resize_amount), max_width); 66103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 66203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Save off the desired number of visible icons. We do this now instead of at 66303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the end of the animation so that even if the browser is shut down while 66403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // animating, the right value will be restored on next run. 66503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // NOTE: Don't save the icon count in incognito because there may be fewer 66603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // icons in that mode. The result is that the container in a normal window is 66703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // always at least as wide as in an incognito window. 66803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int visible_icons = WidthToIconCount(container_width_); 66903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!profile_->IsOffTheRecord()) 67003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) model_->SetVisibleIconCount(visible_icons); 67103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, visible_icons); 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::AnimationProgressed( 675d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const gfx::Animation* animation) { 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(resize_animation_.get(), animation); 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (container_width_ - animation_target_size_)); 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 682d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void BrowserActionsContainer::AnimationEnded(const gfx::Animation* animation) { 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) container_width_ = animation_target_size_; 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = 0; 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_amount_ = 0; 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) suppress_chevron_ = false; 6871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SetChevronVisibility(); 688a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 689effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 690effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch FOR_EACH_OBSERVER(BrowserActionsContainerObserver, 691effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch observers_, 692effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnBrowserActionsContainerAnimationEnded()); 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::NotifyMenuDeleted( 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionOverflowMenuController* controller) { 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(overflow_menu_, controller); 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_ = NULL; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)content::WebContents* BrowserActionsContainer::GetCurrentWebContents() { 7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return browser_->tab_strip_model()->GetActiveWebContents(); 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)extensions::ActiveTabPermissionGranter* 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserActionsContainer::GetActiveTabPermissionGranter() { 7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) content::WebContents* web_contents = 7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) browser_->tab_strip_model()->GetActiveWebContents(); 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!web_contents) 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extensions::TabHelper::FromWebContents(web_contents)-> 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) active_tab_permission_granter(); 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)ExtensionPopup* BrowserActionsContainer::TestGetPopup() { 7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL; 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { 7201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci model_->SetVisibleIconCountForTest(icons); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { 724effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If the views haven't been initialized yet, wait for the next call to 725effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // paint (one will be triggered by entering highlight mode). 726effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (model_->is_highlighting() && !browser_action_views_.empty()) { 727effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch views::Painter::PaintPainterAt( 728effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas, highlight_painter_.get(), GetLocalBounds()); 729effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 730effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(sky/glen): Instead of using a drop indicator, animate the icons while 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // dragging (like we do for tab dragging). 7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (drop_position_.get()) { 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The two-pixel width drop indicator. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const int kDropIndicatorWidth = 2; 7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Convert back to a pixel offset into the container. First find the X 7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // coordinate of the drop icon. 7391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int drop_icon_x = ToolbarView::kStandardSpacing + 7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) (drop_position_->icon_in_row * IconWidth(true)); 7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Next, find the space before the drop icon. This will either be 7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // kItemSpacing or ToolbarView::kStandardSpacing, depending on whether this 7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // is the first icon. 7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // NOTE: Right now, these are the same. But let's do this right for if they 7455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // ever aren't. 7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int space_before_drop_icon = drop_position_->icon_in_row == 0 ? 7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ToolbarView::kStandardSpacing : kItemSpacing; 7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // Now place the drop indicator halfway between this and the end of the 7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // previous icon. If there is an odd amount of available space between the 7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // two icons (or the icon and the address bar) after subtracting the drop 7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // indicator width, this calculation puts the extra pixel on the left side 7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // of the indicator, since when the indicator is between the address bar and 7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) // the first icon, it looks better closer to the icon. 7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int drop_indicator_x = drop_icon_x - 7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) ((space_before_drop_icon + kDropIndicatorWidth) / 2); 7565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int row_height = IconHeight(); 7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) int drop_indicator_y = row_height * drop_position_->row; 7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) gfx::Rect indicator_bounds(drop_indicator_x, 7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) drop_indicator_y, 7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) kDropIndicatorWidth, 7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) row_height); 7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) indicator_bounds.set_x(GetMirroredXForRect(indicator_bounds)); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Color of the drop indicator. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const SkColor kDropIndicatorColor = SK_ColorBLACK; 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) canvas->FillRect(indicator_bounds, kDropIndicatorColor); 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::OnThemeChanged() { 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LoadImages(); 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 774a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)void BrowserActionsContainer::ViewHierarchyChanged( 775a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) const ViewHierarchyChangedDetails& details) { 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No extensions (e.g., incognito). 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!model_) 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 780a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles) if (details.is_add && details.child == this) { 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Initial toolbar button creation and placement in the widget hierarchy. 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We do this here instead of in the constructor because AddBrowserAction 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // calls Layout on the Toolbar, which needs this object to be constructed 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // before its Layout function is called. 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateBrowserActionViews(); 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconWidth(bool include_padding) { 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_width = 0; 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_width = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->width(); 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_width + (include_padding ? kItemSpacing : 0); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconHeight() { 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static bool initialized = false; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static int icon_height = 0; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!initialized) { 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) initialized = true; 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icon_height = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDR_BROWSER_ACTION)->height(); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return icon_height; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 81303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionAdded(const Extension* extension, 81403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int index) { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(DEBUG) 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < browser_action_views_.size(); ++i) { 8176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) DCHECK(browser_action_views_[i]->extension() != extension) << 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Asked to add a browser action view for an extension that already " 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "exists."; 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 824f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the new browser action to the vector and the view hierarchy. 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 83003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = 83103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) new BrowserActionView(extension, 8321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci extensions::ExtensionActionManager::Get(profile_)-> 8331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci GetExtensionAction(*extension), 83403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_, 83503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) this); 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.insert(browser_action_views_.begin() + index, view); 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AddChildViewAt(view, index); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we are still initializing the container, don't bother animating. 840f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!model_->extensions_initialized()) 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this is just an upgrade, then don't worry about resizing. 8441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) { 8461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We need to resize if either: 8471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - The container is set to display all icons (visible count = -1), or 8481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // - The container will need to expand to include the chevron. This can 8491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // happen when the container is set to display <n> icons, where <n> is 8501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // the number of icons before the new icon. With the new icon, the chevron 8511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // will need to be displayed. 8521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int model_icon_count = model_->GetVisibleIconCount(); 8531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (model_icon_count == -1 || 8541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (static_cast<size_t>(model_icon_count) < browser_action_views_.size() && 8551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci (chevron_ && !chevron_->visible()))) { 8561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci suppress_chevron_ = true; 8571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Animate(gfx::Tween::LINEAR, GetIconCount()); 8581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return; 8591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 8621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Otherwise, we don't have to resize, so just redraw the (possibly modified) 8631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // visible icon set. 8641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci OnBrowserActionVisibilityChanged(); 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 86703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionRemoved( 86803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) { 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CloseOverflowMenu(); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) size_t visible_actions = VisibleBrowserActionsAfterAnimation(); 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (BrowserActionViews::iterator i(browser_action_views_.begin()); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != browser_action_views_.end(); ++i) { 8746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if ((*i)->extension() == extension) { 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete *i; 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) browser_action_views_.erase(i); 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the extension is being upgraded we don't want the bar to shrink 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because the icon is just going to get re-added to the same location. 8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (extensions::ExtensionSystem::Get(profile_)->runtime_data()-> 8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsBeingUpgraded(extension)) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (browser_action_views_.size() > visible_actions) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we have more icons than we can show, then we must not be changing 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the container size (since we either removed an icon from the main 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // area and one from the overflow list will have shifted in, or we 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // removed an entry directly from the overflow list). 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnBrowserActionVisibilityChanged(); 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Either we went from overflow to no-overflow, or we shrunk the no- 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // overflow container by 1. Either way the size changed, so animate. 893116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (chevron_) 894116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible(false); 89503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, browser_action_views_.size()); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 897116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; // We have found the action to remove, bail out. 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 90203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionMoved(const Extension* extension, 90303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int index) { 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!ShouldDisplayBrowserAction(extension)) 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_->IsOffTheRecord()) 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) index = model_->OriginalIndexToIncognito(index); 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 91203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionViews::iterator iter = browser_action_views_.begin(); 91303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) int old_index = 0; 91403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) while (iter != browser_action_views_.end() && 91503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) (*iter)->extension() != extension) { 91603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++iter; 91703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ++old_index; 91803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 91903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 92003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) DCHECK(iter != browser_action_views_.end()); 92103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (old_index == index) 92203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return; // Already in place. 92303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 92403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* moved_view = *iter; 92503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.erase(iter); 92603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.insert( 92703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) browser_action_views_.begin() + index, moved_view); 92803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Layout(); 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchedulePaint(); 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 93303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarExtensionUpdated( 93403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) { 93503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) BrowserActionView* view = GetViewForExtension(extension); 93603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (view) 93703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) view->UpdateState(); 93803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 93903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 94003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)bool BrowserActionsContainer::ShowExtensionActionPopup( 9411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const Extension* extension, 9421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool grant_active_tab) { 9431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Don't override another popup, and only show in the active window. 9441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (popup_owner_ || !browser_->window()->IsActive()) 9451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return false; 9461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9471320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BrowserActionView* view = GetViewForExtension(extension); 9481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return view && view->view_controller()->ExecuteAction(ExtensionPopup::SHOW, 9491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci grant_active_tab); 9508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)} 9518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 95203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarVisibleCountChanged() { 9531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (GetPreferredWidth() != container_width_) 95403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) Animate(gfx::Tween::EASE_OUT, GetIconCount()); 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::ToolbarHighlightModeChanged( 95803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) bool is_highlighting) { 959effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // The visual highlighting is done in OnPaint(). It's a bit of a pain that 96003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // we delete and recreate everything here, but given everything else going on 96103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // (the lack of highlight, n more extensions appearing, etc), it's not worth 96203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // the extra complexity to create and insert only the new extensions. 963effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DeleteBrowserActionViews(); 964effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateBrowserActionViews(); 9651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Animate(gfx::Tween::LINEAR, GetIconCount()); 9661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 9671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 9681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciBrowser* BrowserActionsContainer::GetBrowser() { 9691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return browser_; 970effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 971effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::LoadImages() { 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ui::ThemeProvider* tp = GetThemeProvider(); 974116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!tp || !chevron_) 975116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return; 976116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 977f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) chevron_->SetImage(views::Button::STATE_NORMAL, 978f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) *tp->GetImageSkiaNamed(IDR_BROWSER_ACTIONS_OVERFLOW)); 979effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 980effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const int kImages[] = IMAGE_GRID(IDR_DEVELOPER_MODE_HIGHLIGHT); 981effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch highlight_painter_.reset(views::Painter::CreateImageGridPainter(kImages)); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 98403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::OnBrowserActionVisibilityChanged() { 98503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) SetVisible(!browser_action_views_.empty()); 98603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (owner_view_) { 98703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) owner_view_->Layout(); 98803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) owner_view_->SchedulePaint(); 9891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } else { 9901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // In overflow mode, we don't have an owner view, but we still have to 9911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // update ourselves. 9921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci Layout(); 9931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SchedulePaint(); 99403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) } 99503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)} 99603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 9971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint BrowserActionsContainer::GetPreferredWidth() { 9981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t visible_actions = GetIconCount(); 9991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return IconCountToWidth( 10001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci visible_actions, 10011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci chevron_ && visible_actions < browser_action_views_.size()); 10021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 10031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 10041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid BrowserActionsContainer::SetChevronVisibility() { 1005116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (chevron_) { 1006116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->SetVisible( 10071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VisibleBrowserActionsAfterAnimation() < browser_action_views_.size()); 1008116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::CloseOverflowMenu() { 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (overflow_menu_) 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->CancelMenu(); 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StopShowFolderDropMenuTimer() { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.InvalidateWeakPtrs(); 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::StartShowFolderDropMenuTimer() { 1021b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) base::MessageLoop::current()->PostDelayedTask( 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&BrowserActionsContainer::ShowDropFolder, 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) show_menu_task_factory_.GetWeakPtr()), 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta::FromMilliseconds(views::GetMenuShowDelay())); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BrowserActionsContainer::ShowDropFolder() { 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!overflow_menu_); 1030116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_ = 1031116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch new BrowserActionOverflowMenuController(this, 1032116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_, 1033116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_, 1034116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch browser_action_views_, 1035116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch VisibleBrowserActions(), 1036116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch true); 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) overflow_menu_->set_observer(this); 1038116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch overflow_menu_->RunMenu(GetWidget()); 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int BrowserActionsContainer::IconCountToWidth(int icons, 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool display_chevron) const { 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (icons < 0) 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icons = browser_action_views_.size(); 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((icons == 0) && !display_chevron) 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ToolbarView::kStandardSpacing; 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int icons_size = 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing); 1049116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch int chevron_size = chevron_ && display_chevron ? 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; 10511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // In overflow mode, our padding is to use item spacing on either end (just so 10521320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we can see the drop indicator). Otherwise we use the standard toolbar 10531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // spacing. 10541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Note: These are actually the same thing, but, on the offchance one 10551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // changes, let's get it right. 10561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int padding = 10571320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 2 * (in_overflow_mode() ? kItemSpacing : ToolbarView::kStandardSpacing); 10581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return icons_size + chevron_size + padding; 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Check for widths large enough to show the entire icon set. 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pixels >= IconCountToWidth(-1, false)) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return browser_action_views_.size(); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We reserve space for the padding on either side of the toolbar... 10671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int available_space = pixels - (ToolbarView::kStandardSpacing * 2); 10681320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ... and, if the chevron is enabled, the chevron. 10691320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (chevron_) 10701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci available_space -= (chevron_->GetPreferredSize().width() + kChevronSpacing); 10711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now we add an extra between-item padding value so the space can be divided 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // evenly by (size of icon with padding). 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<size_t>( 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::max(0, available_space + kItemSpacing) / IconWidth(true)); 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1078cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int BrowserActionsContainer::MinimumNonemptyWidth() const { 1079116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (!chevron_) 1080116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return ToolbarView::kStandardSpacing; 1081116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch return (ToolbarView::kStandardSpacing * 2) + kChevronSpacing + 1082116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch chevron_->GetPreferredSize().width(); 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 108503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)void BrowserActionsContainer::Animate(gfx::Tween::Type tween_type, 108603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t num_visible_icons) { 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int target_size = IconCountToWidth(num_visible_icons, 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_visible_icons < browser_action_views_.size()); 1089116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (resize_animation_ && !disable_animations_during_testing_) { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Animate! We have to set the animation_target_size_ after calling Reset(), 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // because that could end up calling AnimationEnded which clears the value. 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Reset(); 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->SetTweenType(tween_type); 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resize_animation_->Show(); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) animation_target_size_ = target_size; 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AnimationEnded(resize_animation_.get()); 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BrowserActionsContainer::ShouldDisplayBrowserAction( 110303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) const Extension* extension) const { 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only display incognito-enabled extensions while in incognito mode. 11055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return !profile_->IsOffTheRecord() || 11065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) extensions::util::IsIncognitoEnabled(extension->id(), profile_); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 110903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)size_t BrowserActionsContainer::GetIconCount() const { 111003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (!model_) 111103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return 0u; 11121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const extensions::ExtensionList& extensions = model_->toolbar_items(); 11141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Find the absolute value for the model's visible count. 11161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int model_visible_size = model_->GetVisibleIconCount(); 11171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t absolute_model_visible_size = 11181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci model_visible_size == -1 ? extensions.size() : model_visible_size; 11191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 112003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) // Find the number of icons which could be displayed. 112103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) size_t displayable_icon_count = 0u; 11221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci size_t main_displayed = 0u; 11231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (size_t i = 0; i < extensions.size(); ++i) { 11241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Should there be an icon for this extension at all? 11251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (ShouldDisplayBrowserAction(extensions[i].get())) { 11261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++displayable_icon_count; 11271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Should we display it on the main bar? If this is an incognito window, 11281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // icons have the same overflow status they do in a regular window. 11291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main_displayed += i < absolute_model_visible_size ? 1u : 0u; 11301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 11315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) } 11321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // If this is an existing (initialized) container from an incognito profile, 11341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // we can't trust the model (because the incognito bars don't adjust model 11351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // settings). Instead, we go off what we currently have displayed. 11361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (initialized_ && profile_->IsOffTheRecord()) { 11371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main_displayed = in_overflow_mode() ? 11381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci main_container_->VisibleBrowserActionsAfterAnimation() : 11391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci VisibleBrowserActionsAfterAnimation(); 11401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 11411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 11421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // The overflow displays any (displayable) icons not shown by the main bar. 114303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return in_overflow_mode() ? 114403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) displayable_icon_count - main_displayed : main_displayed; 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1146