Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(141)

Side by Side Diff: chrome/browser/views/browser_actions_container.cc

Issue 3057016: Browser actions container layout changes for M6 theme. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 10 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/views/browser_actions_container.h ('k') | chrome/browser/views/toolbar_view.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/views/browser_actions_container.h" 5 #include "chrome/browser/views/browser_actions_container.h"
6 6
7 #include "app/l10n_util.h" 7 #include "app/l10n_util.h"
8 #include "app/resource_bundle.h" 8 #include "app/resource_bundle.h"
9 #include "app/slide_animation.h" 9 #include "app/slide_animation.h"
10 #include "base/stl_util-inl.h" 10 #include "base/stl_util-inl.h"
11 #include "base/string_util.h" 11 #include "base/string_util.h"
12 #include "chrome/browser/browser.h" 12 #include "chrome/browser/browser.h"
13 #include "chrome/browser/browser_theme_provider.h" 13 #include "chrome/browser/browser_theme_provider.h"
14 #include "chrome/browser/browser_window.h" 14 #include "chrome/browser/browser_window.h"
15 #include "chrome/browser/extensions/extension_browser_event_router.h" 15 #include "chrome/browser/extensions/extension_browser_event_router.h"
16 #include "chrome/browser/extensions/extension_host.h" 16 #include "chrome/browser/extensions/extension_host.h"
17 #include "chrome/browser/extensions/extensions_service.h" 17 #include "chrome/browser/extensions/extensions_service.h"
18 #include "chrome/browser/extensions/extension_tabs_module.h" 18 #include "chrome/browser/extensions/extension_tabs_module.h"
19 #include "chrome/browser/renderer_host/render_widget_host_view.h" 19 #include "chrome/browser/renderer_host/render_widget_host_view.h"
20 #include "chrome/browser/renderer_host/render_view_host.h" 20 #include "chrome/browser/renderer_host/render_view_host.h"
21 #include "chrome/browser/profile.h" 21 #include "chrome/browser/profile.h"
22 #include "chrome/browser/tab_contents/tab_contents.h" 22 #include "chrome/browser/tab_contents/tab_contents.h"
23 #include "chrome/browser/view_ids.h" 23 #include "chrome/browser/view_ids.h"
24 #include "chrome/browser/views/detachable_toolbar_view.h" 24 #include "chrome/browser/views/detachable_toolbar_view.h"
25 #include "chrome/browser/views/extensions/browser_action_drag_data.h" 25 #include "chrome/browser/views/extensions/browser_action_drag_data.h"
26 #include "chrome/browser/views/extensions/extension_popup.h" 26 #include "chrome/browser/views/extensions/extension_popup.h"
27 #include "chrome/browser/views/toolbar_view.h"
27 #include "chrome/common/extensions/extension_action.h" 28 #include "chrome/common/extensions/extension_action.h"
28 #include "chrome/common/extensions/extension_resource.h" 29 #include "chrome/common/extensions/extension_resource.h"
29 #include "chrome/common/notification_source.h" 30 #include "chrome/common/notification_source.h"
30 #include "chrome/common/notification_type.h" 31 #include "chrome/common/notification_type.h"
31 #include "chrome/common/pref_names.h" 32 #include "chrome/common/pref_names.h"
32 #include "gfx/canvas.h" 33 #include "gfx/canvas.h"
33 #include "gfx/canvas_skia.h" 34 #include "gfx/canvas_skia.h"
34 #include "grit/app_resources.h" 35 #include "grit/app_resources.h"
35 #include "grit/generated_resources.h" 36 #include "grit/generated_resources.h"
36 #include "third_party/skia/include/core/SkBitmap.h" 37 #include "third_party/skia/include/core/SkBitmap.h"
37 #include "third_party/skia/include/core/SkTypeface.h" 38 #include "third_party/skia/include/core/SkTypeface.h"
38 #include "third_party/skia/include/effects/SkGradientShader.h" 39 #include "third_party/skia/include/effects/SkGradientShader.h"
39 #include "views/controls/button/menu_button.h" 40 #include "views/controls/button/menu_button.h"
40 #include "views/controls/button/text_button.h" 41 #include "views/controls/button/text_button.h"
41 #include "views/controls/menu/menu_2.h" 42 #include "views/controls/menu/menu_2.h"
42 #include "views/drag_utils.h" 43 #include "views/drag_utils.h"
43 #include "views/window/window.h" 44 #include "views/window/window.h"
44 45
45 #include "grit/theme_resources.h" 46 #include "grit/theme_resources.h"
46 47
47 namespace { 48 // Horizontal spacing between most items in the container, as well as after the
49 // last item or chevron (if visible).
50 static const int kItemSpacing = ToolbarView::kStandardSpacing;
51 // Horizontal spacing before the chevron (if visible).
52 static const int kChevronSpacing = kItemSpacing - 2;
48 53
49 // The size (both dimensions) of the buttons for page actions. 54 // static
50 static const int kButtonSize = 29;
51
52 // The padding between the browser actions and the OmniBox/page menu.
53 static const int kHorizontalPadding = 4;
54 static const int kHorizontalPaddingRtl = 8;
55
56 // The padding between browser action buttons. Visually, the actual number of
57 // empty (non-drawing) pixels is this value + 2 when adjacent browser icons
58 // use their maximum allowed size.
59 static const int kBrowserActionButtonPadding = 3;
60
61 // This is the same value from toolbar.cc. We position the browser actions
62 // container flush with the edges of the toolbar as a special case so that we
63 // can draw the badge outside the visual bounds of the container.
64 static const int kControlVertOffset = 6;
65
66 // The margin between the divider and the chrome menu buttons.
67 static const int kDividerHorizontalMargin = 2;
68
69 // The padding above and below the divider.
70 static const int kDividerVerticalPadding = 9;
71
72 // The margin above the chevron.
73 static const int kChevronTopMargin = 9;
74
75 // The margin to the right of the chevron.
76 static const int kChevronRightMargin = 4;
77
78 // Width for the resize area.
79 static const int kResizeAreaWidth = 4;
80
81 // The x offset for the drop indicator (how much we shift it by).
82 static const int kDropIndicatorOffsetLtr = 3;
83 static const int kDropIndicatorOffsetRtl = 9;
84
85 } // namespace.
86
87 // Static.
88 bool BrowserActionsContainer::disable_animations_during_testing_ = false; 55 bool BrowserActionsContainer::disable_animations_during_testing_ = false;
89 56
90 //////////////////////////////////////////////////////////////////////////////// 57 ////////////////////////////////////////////////////////////////////////////////
91 // BrowserActionButton 58 // BrowserActionButton
92 59
93 BrowserActionButton::BrowserActionButton(Extension* extension, 60 BrowserActionButton::BrowserActionButton(Extension* extension,
94 BrowserActionsContainer* panel) 61 BrowserActionsContainer* panel)
95 : ALLOW_THIS_IN_INITIALIZER_LIST( 62 : ALLOW_THIS_IN_INITIALIZER_LIST(
96 MenuButton(this, std::wstring(), NULL, false)), 63 MenuButton(this, std::wstring(), NULL, false)),
97 browser_action_(extension->browser_action()), 64 browser_action_(extension->browser_action()),
98 extension_(extension), 65 extension_(extension),
99 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)), 66 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(this)),
100 showing_context_menu_(false), 67 showing_context_menu_(false),
101 panel_(panel) { 68 panel_(panel) {
69 set_border(NULL);
102 set_alignment(TextButton::ALIGN_CENTER); 70 set_alignment(TextButton::ALIGN_CENTER);
103 71
104 // No UpdateState() here because View hierarchy not setup yet. Our parent 72 // No UpdateState() here because View hierarchy not setup yet. Our parent
105 // should call UpdateState() after creation. 73 // should call UpdateState() after creation.
106 74
107 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED, 75 registrar_.Add(this, NotificationType::EXTENSION_BROWSER_ACTION_UPDATED,
108 Source<ExtensionAction>(browser_action_)); 76 Source<ExtensionAction>(browser_action_));
109 77
110 // The Browser Action API does not allow the default icon path to be changed 78 // The Browser Action API does not allow the default icon path to be changed
111 // at runtime, so we can load this now and cache it. 79 // at runtime, so we can load this now and cache it.
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
147 // Call back to UpdateState() because a more specific icon might have been set 115 // Call back to UpdateState() because a more specific icon might have been set
148 // while the load was outstanding. 116 // while the load was outstanding.
149 UpdateState(); 117 UpdateState();
150 } 118 }
151 119
152 void BrowserActionButton::UpdateState() { 120 void BrowserActionButton::UpdateState() {
153 int tab_id = panel_->GetCurrentTabId(); 121 int tab_id = panel_->GetCurrentTabId();
154 if (tab_id < 0) 122 if (tab_id < 0)
155 return; 123 return;
156 124
157 SkBitmap image = browser_action()->GetIcon(tab_id); 125 SkBitmap icon(browser_action()->GetIcon(tab_id));
158 if (!image.isNull()) 126 if (icon.isNull())
159 SetIcon(image); 127 icon = default_icon_;
160 else if (!default_icon_.isNull()) 128 if (!icon.isNull()) {
161 SetIcon(default_icon_); 129 SkPaint paint;
130 paint.setXfermode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
131 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
132
133 SkBitmap bg;
134 rb.GetBitmapNamed(IDR_BROWSER_ACTION)->copyTo(&bg,
135 SkBitmap::kARGB_8888_Config);
136 SkCanvas bg_canvas(bg);
137 bg_canvas.drawBitmap(icon, SkIntToScalar((bg.width() - icon.width()) / 2),
138 SkIntToScalar((bg.height() - icon.height()) / 2), &paint);
139 SetIcon(bg);
140
141 SkBitmap bg_h;
142 rb.GetBitmapNamed(IDR_BROWSER_ACTION_H)->copyTo(&bg_h,
143 SkBitmap::kARGB_8888_Config);
144 SkCanvas bg_h_canvas(bg_h);
145 bg_h_canvas.drawBitmap(icon,
146 SkIntToScalar((bg_h.width() - icon.width()) / 2),
147 SkIntToScalar((bg_h.height() - icon.height()) / 2), &paint);
148 SetHoverIcon(bg_h);
149
150 SkBitmap bg_p;
151 rb.GetBitmapNamed(IDR_BROWSER_ACTION_P)->copyTo(&bg_p,
152 SkBitmap::kARGB_8888_Config);
153 SkCanvas bg_p_canvas(bg_p);
154 bg_p_canvas.drawBitmap(icon,
155 SkIntToScalar((bg_p.width() - icon.width()) / 2),
156 SkIntToScalar((bg_p.height() - icon.height()) / 2), &paint);
157 SetPushedIcon(bg_p);
158 }
162 159
163 // If the browser action name is empty, show the extension name instead. 160 // If the browser action name is empty, show the extension name instead.
164 std::wstring name = UTF8ToWide(browser_action()->GetTitle(tab_id)); 161 std::wstring name = UTF8ToWide(browser_action()->GetTitle(tab_id));
165 if (name.empty()) 162 if (name.empty())
166 name = UTF8ToWide(extension()->name()); 163 name = UTF8ToWide(extension()->name());
167 SetTooltipText(name); 164 SetTooltipText(name);
168 SetAccessibleName(name); 165 SetAccessibleName(name);
169 GetParent()->SchedulePaint(); 166 GetParent()->SchedulePaint();
170 } 167 }
171 168
(...skipping 16 matching lines...) Expand all
188 GURL BrowserActionButton::GetPopupUrl() { 185 GURL BrowserActionButton::GetPopupUrl() {
189 int tab_id = panel_->GetCurrentTabId(); 186 int tab_id = panel_->GetCurrentTabId();
190 DCHECK_GE(tab_id, 0); 187 DCHECK_GE(tab_id, 0);
191 return browser_action_->GetPopupUrl(tab_id); 188 return browser_action_->GetPopupUrl(tab_id);
192 } 189 }
193 190
194 bool BrowserActionButton::Activate() { 191 bool BrowserActionButton::Activate() {
195 if (!IsPopup()) 192 if (!IsPopup())
196 return true; 193 return true;
197 194
198 panel_->OnBrowserActionExecuted(this, false); // |inspect_with_devtools|. 195 panel_->OnBrowserActionExecuted(this, false);
199 196
200 // TODO(erikkay): Run a nested modal loop while the mouse is down to 197 // TODO(erikkay): Run a nested modal loop while the mouse is down to
201 // enable menu-like drag-select behavior. 198 // enable menu-like drag-select behavior.
202 199
203 // The return value of this method is returned via OnMousePressed. 200 // The return value of this method is returned via OnMousePressed.
204 // We need to return false here since we're handing off focus to another 201 // We need to return false here since we're handing off focus to another
205 // widget/view, and true will grab it right back and try to send events 202 // widget/view, and true will grab it right back and try to send events
206 // to us. 203 // to us.
207 return false; 204 return false;
208 } 205 }
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
299 int tab_id = panel_->GetCurrentTabId(); 296 int tab_id = panel_->GetCurrentTabId();
300 297
301 SkBitmap icon = button_->extension()->browser_action()->GetIcon(tab_id); 298 SkBitmap icon = button_->extension()->browser_action()->GetIcon(tab_id);
302 if (icon.isNull()) 299 if (icon.isNull())
303 icon = button_->default_icon(); 300 icon = button_->default_icon();
304 301
305 gfx::Canvas* canvas = new gfx::CanvasSkia(icon.width(), icon.height(), false); 302 gfx::Canvas* canvas = new gfx::CanvasSkia(icon.width(), icon.height(), false);
306 canvas->DrawBitmapInt(icon, 0, 0); 303 canvas->DrawBitmapInt(icon, 0, 0);
307 304
308 if (tab_id >= 0) { 305 if (tab_id >= 0) {
309 gfx::Rect bounds(icon.width(), icon.height() + kControlVertOffset); 306 gfx::Rect bounds(icon.width(), icon.height() + ToolbarView::kVertSpacing);
310 button_->extension()->browser_action()->PaintBadge(canvas, bounds, tab_id); 307 button_->extension()->browser_action()->PaintBadge(canvas, bounds, tab_id);
311 } 308 }
312 309
313 return canvas; 310 return canvas;
314 } 311 }
315 312
316 bool BrowserActionView::GetAccessibleRole(AccessibilityTypes::Role* role) { 313 bool BrowserActionView::GetAccessibleRole(AccessibilityTypes::Role* role) {
317 DCHECK(role); 314 DCHECK(role);
318 *role = AccessibilityTypes::ROLE_GROUPING; 315 *role = AccessibilityTypes::ROLE_GROUPING;
319 return true; 316 return true;
320 } 317 }
321 318
322 void BrowserActionView::Layout() { 319 void BrowserActionView::Layout() {
323 button_->SetBounds(0, kControlVertOffset, width(), kButtonSize); 320 // We can't rely on button_->GetPreferredSize() here because that's not set
321 // correctly until the first call to
322 // BrowserActionsContainer::RefreshBrowserActionViews(), whereas this can be
323 // called before that when the initial bounds are set (and then not after,
324 // since the bounds don't change). So instead of setting the height from the
325 // button's preferred size, we use IconHeight(), since that's how big the
326 // button should be regardless of what it's displaying.
327 button_->SetBounds(0, ToolbarView::kVertSpacing, width(),
328 BrowserActionsContainer::IconHeight());
324 } 329 }
325 330
326 void BrowserActionView::PaintChildren(gfx::Canvas* canvas) { 331 void BrowserActionView::PaintChildren(gfx::Canvas* canvas) {
327 View::PaintChildren(canvas); 332 View::PaintChildren(canvas);
328 ExtensionAction* action = button()->browser_action(); 333 ExtensionAction* action = button()->browser_action();
329 int tab_id = panel_->GetCurrentTabId(); 334 int tab_id = panel_->GetCurrentTabId();
330 if (tab_id >= 0) 335 if (tab_id >= 0)
331 action->PaintBadge(canvas, gfx::Rect(width(), height()), tab_id); 336 action->PaintBadge(canvas, gfx::Rect(width(), height()), tab_id);
332 } 337 }
333 338
334 //////////////////////////////////////////////////////////////////////////////// 339 ////////////////////////////////////////////////////////////////////////////////
335 // BrowserActionsContainer 340 // BrowserActionsContainer
336 341
337 BrowserActionsContainer::BrowserActionsContainer(Browser* browser, 342 BrowserActionsContainer::BrowserActionsContainer(Browser* browser,
338 View* owner_view) 343 View* owner_view)
339 : profile_(browser->profile()), 344 : profile_(browser->profile()),
340 browser_(browser), 345 browser_(browser),
341 owner_view_(owner_view), 346 owner_view_(owner_view),
342 popup_(NULL), 347 popup_(NULL),
343 popup_button_(NULL), 348 popup_button_(NULL),
344 model_(NULL), 349 model_(NULL),
350 container_width_(0),
345 chevron_(NULL), 351 chevron_(NULL),
346 overflow_menu_(NULL), 352 overflow_menu_(NULL),
347 suppress_chevron_(false), 353 suppress_chevron_(false),
348 resize_amount_(0), 354 resize_amount_(0),
349 animation_target_size_(0), 355 animation_target_size_(0),
350 drop_indicator_position_(-1), 356 drop_indicator_position_(-1),
351 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)), 357 ALLOW_THIS_IN_INITIALIZER_LIST(task_factory_(this)),
352 ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_task_factory_(this)) { 358 ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_task_factory_(this)) {
353 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR); 359 SetID(VIEW_ID_BROWSER_ACTION_TOOLBAR);
354 360
355 if (profile_->GetExtensionsService()) { 361 if (profile_->GetExtensionsService()) {
356 model_ = profile_->GetExtensionsService()->toolbar_model(); 362 model_ = profile_->GetExtensionsService()->toolbar_model();
357 model_->AddObserver(this); 363 model_->AddObserver(this);
358 } 364 }
359 365
360 resize_animation_.reset(new SlideAnimation(this)); 366 resize_animation_.reset(new SlideAnimation(this));
361 resize_area_ = new views::ResizeArea(this); 367 resize_area_ = new views::ResizeArea(this);
362 resize_area_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_SEPARATOR)); 368 resize_area_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_SEPARATOR));
363 AddChildView(resize_area_); 369 AddChildView(resize_area_);
364 370
365 // TODO(glen): Come up with a new bitmap for the chevron.
366 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
367 SkBitmap* chevron_image = rb.GetBitmapNamed(IDR_BOOKMARK_BAR_CHEVRONS);
368 chevron_ = new views::MenuButton(NULL, std::wstring(), this, false); 371 chevron_ = new views::MenuButton(NULL, std::wstring(), this, false);
369 chevron_->SetVisible(false); 372 chevron_->set_border(NULL);
370 chevron_->SetIcon(*chevron_image); 373 chevron_->EnableCanvasFlippingForRTLUI(true);
371 chevron_->SetAccessibleName( 374 chevron_->SetAccessibleName(
372 l10n_util::GetString(IDS_ACCNAME_EXTENSIONS_CHEVRON)); 375 l10n_util::GetString(IDS_ACCNAME_EXTENSIONS_CHEVRON));
373 // Chevron contains >> that should point left in LTR locales. 376 chevron_->SetVisible(false);
374 chevron_->EnableCanvasFlippingForRTLUI(true);
375 AddChildView(chevron_); 377 AddChildView(chevron_);
376 378
377 if (model_ &&
378 !profile_->GetPrefs()->HasPrefPath(prefs::kExtensionToolbarSize)) {
379 // Migration code to the new VisibleIconCount pref.
380 // TODO(mpcomplete): remove this after users are upgraded to 5.0.
381 int predefined_width =
382 profile_->GetPrefs()->GetInteger(prefs::kBrowserActionContainerWidth);
383 if (predefined_width != 0) {
384 model_->SetVisibleIconCount((predefined_width - WidthOfNonIconArea()) /
385 (kButtonSize + kBrowserActionButtonPadding));
386 }
387 }
388 if (model_ && model_->extensions_initialized())
389 SetContainerWidth();
390
391 SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_EXTENSIONS)); 379 SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_EXTENSIONS));
392 } 380 }
393 381
394 BrowserActionsContainer::~BrowserActionsContainer() { 382 BrowserActionsContainer::~BrowserActionsContainer() {
395 if (model_) 383 if (model_)
396 model_->RemoveObserver(this); 384 model_->RemoveObserver(this);
397 StopShowFolderDropMenuTimer(); 385 StopShowFolderDropMenuTimer();
398 HidePopup(); 386 HidePopup();
399 DeleteBrowserActionViews(); 387 DeleteBrowserActionViews();
400 } 388 }
401 389
402 // Static. 390 // Static.
403 void BrowserActionsContainer::RegisterUserPrefs(PrefService* prefs) { 391 void BrowserActionsContainer::RegisterUserPrefs(PrefService* prefs) {
404 prefs->RegisterIntegerPref(prefs::kBrowserActionContainerWidth, 0); 392 prefs->RegisterIntegerPref(prefs::kBrowserActionContainerWidth, 0);
405 } 393 }
406 394
395 void BrowserActionsContainer::Init() {
396 LoadImages();
397
398 // We wait to set the container width until now so that the chevron images
399 // will be loaded. The width calculation needs to know the chevron size.
400 if (model_ &&
401 !profile_->GetPrefs()->HasPrefPath(prefs::kExtensionToolbarSize)) {
402 // Migration code to the new VisibleIconCount pref.
403 // TODO(mpcomplete): remove this after users are upgraded to 5.0.
404 int predefined_width =
405 profile_->GetPrefs()->GetInteger(prefs::kBrowserActionContainerWidth);
406 if (predefined_width != 0)
407 model_->SetVisibleIconCount(WidthToIconCount(predefined_width));
408 }
409 if (model_ && model_->extensions_initialized())
410 SetContainerWidth();
411 }
412
407 int BrowserActionsContainer::GetCurrentTabId() const { 413 int BrowserActionsContainer::GetCurrentTabId() const {
408 TabContents* tab_contents = browser_->GetSelectedTabContents(); 414 TabContents* tab_contents = browser_->GetSelectedTabContents();
409 return tab_contents ? tab_contents->controller().session_id().id() : -1; 415 return tab_contents ? tab_contents->controller().session_id().id() : -1;
410 } 416 }
411 417
412 BrowserActionView* BrowserActionsContainer::GetBrowserActionView( 418 BrowserActionView* BrowserActionsContainer::GetBrowserActionView(
413 ExtensionAction* action) { 419 ExtensionAction* action) {
414 for (BrowserActionViews::iterator iter = browser_action_views_.begin(); 420 for (BrowserActionViews::iterator iter = browser_action_views_.begin();
415 iter != browser_action_views_.end(); ++iter) { 421 iter != browser_action_views_.end(); ++iter) {
416 if ((*iter)->button()->browser_action() == action) 422 if ((*iter)->button()->browser_action() == action)
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
503 509
504 popup_ = ExtensionPopup::Show(button->GetPopupUrl(), browser_, 510 popup_ = ExtensionPopup::Show(button->GetPopupUrl(), browser_,
505 browser_->profile(), frame_window, rect, arrow_location, true, 511 browser_->profile(), frame_window, rect, arrow_location, true,
506 inspect_with_devtools, ExtensionPopup::BUBBLE_CHROME, this); 512 inspect_with_devtools, ExtensionPopup::BUBBLE_CHROME, this);
507 popup_button_ = button; 513 popup_button_ = button;
508 popup_button_->SetButtonPushed(); 514 popup_button_->SetButtonPushed();
509 } 515 }
510 516
511 gfx::Size BrowserActionsContainer::GetPreferredSize() { 517 gfx::Size BrowserActionsContainer::GetPreferredSize() {
512 if (browser_action_views_.empty()) 518 if (browser_action_views_.empty())
513 return gfx::Size(0, 0); 519 return gfx::Size(ToolbarView::kStandardSpacing, 0);
514 520
515 // We calculate the size of the view by taking the current width and 521 // We calculate the size of the view by taking the current width and
516 // subtracting resize_amount_ (the latter represents how far the user is 522 // subtracting resize_amount_ (the latter represents how far the user is
517 // resizing the view or, if animating the snapping, how far to animate it). 523 // resizing the view or, if animating the snapping, how far to animate it).
518 // But we also clamp it to a minimum size and the maximum size, so that the 524 // But we also clamp it to a minimum size and the maximum size, so that the
519 // container can never shrink too far or take up more space than it needs. In 525 // container can never shrink too far or take up more space than it needs. In
520 // other words: ContainerMinSize() < width() - resize < ClampTo(MAX). 526 // other words: ContainerMinSize() < width() - resize < ClampTo(MAX).
521 int clamped_width = std::min( 527 int clamped_width = std::min(
522 std::max(ContainerMinSize(), container_width_ - resize_amount_), 528 std::max(ContainerMinSize(), container_width_ - resize_amount_),
523 ClampToNearestIconCount(-1, false)); 529 IconCountToWidth(-1, false));
524 return gfx::Size(clamped_width, kButtonSize); 530 return gfx::Size(clamped_width, 0);
525 } 531 }
526 532
527 void BrowserActionsContainer::Layout() { 533 void BrowserActionsContainer::Layout() {
528 if (browser_action_views_.empty()) { 534 if (browser_action_views_.empty()) {
529 SetVisible(false); 535 SetVisible(false);
530 chevron_->SetVisible(false);
531 return; 536 return;
532 } 537 }
533 538
534 SetVisible(true); 539 SetVisible(true);
540 resize_area_->SetBounds(0, ToolbarView::kVertSpacing, kItemSpacing,
541 IconHeight());
535 542
536 resize_area_->SetBounds(0, 0, kResizeAreaWidth, height()); 543 // If the icons don't all fit, show the chevron (unless suppressed).
537 int x = kResizeAreaWidth; 544 int max_x = GetPreferredSize().width();
538 545 if ((IconCountToWidth(-1, false) > max_x) && !suppress_chevron_) {
539 x += base::i18n::IsRTL() ? kHorizontalPaddingRtl : kHorizontalPadding;
540
541 // Calculate if all icons fit without showing the chevron. We need to know
542 // this beforehand, because showing the chevron will decrease the space that
543 // we have to draw the visible ones (ie. if one icon is visible and another
544 // doesn't have enough room).
545 int last_x_of_icons = x +
546 (browser_action_views_.size() * kButtonSize) +
547 ((browser_action_views_.size() - 1) *
548 kBrowserActionButtonPadding);
549
550 gfx::Size sz = GetPreferredSize();
551 int max_x = sz.width() - kDividerHorizontalMargin - kChevronRightMargin;
552
553 // If they don't all fit, show the chevron (unless suppressed).
554 if (last_x_of_icons >= max_x && !suppress_chevron_) {
555 chevron_->SetVisible(true); 546 chevron_->SetVisible(true);
556 gfx::Size chevron_size(chevron_->GetPreferredSize()); 547 gfx::Size chevron_size(chevron_->GetPreferredSize());
557 max_x -= chevron_size.width(); 548 max_x -=
558 chevron_->SetBounds(width() - chevron_size.width() - kChevronRightMargin, 549 ToolbarView::kStandardSpacing + chevron_size.width() + kChevronSpacing;
559 kChevronTopMargin, 550 chevron_->SetBounds(
560 chevron_size.width(), chevron_size.height()); 551 width() - ToolbarView::kStandardSpacing - chevron_size.width(),
552 ToolbarView::kVertSpacing, chevron_size.width(), chevron_size.height());
561 } else { 553 } else {
562 chevron_->SetVisible(false); 554 chevron_->SetVisible(false);
563 } 555 }
564 556
565 // Now draw the icons for the browser actions in the available space. 557 // Now draw the icons for the browser actions in the available space.
558 int icon_width = IconWidth(false);
566 for (size_t i = 0; i < browser_action_views_.size(); ++i) { 559 for (size_t i = 0; i < browser_action_views_.size(); ++i) {
567 BrowserActionView* view = browser_action_views_[i]; 560 BrowserActionView* view = browser_action_views_[i];
568 // Add padding between buttons if multiple buttons. 561 int x = ToolbarView::kStandardSpacing + (i * IconWidth(true));
569 int padding = (i > 0) ? kBrowserActionButtonPadding : 0; 562 if (x + icon_width <= max_x) {
570 if (x + kButtonSize + padding < max_x) { 563 view->SetBounds(x, 0, icon_width, height());
571 x += padding;
572 view->SetBounds(x, 0, kButtonSize, height());
573 view->SetVisible(true); 564 view->SetVisible(true);
574 x += kButtonSize;
575 } else { 565 } else {
576 view->SetVisible(false); 566 view->SetVisible(false);
577 } 567 }
578 } 568 }
579 } 569 }
580 570
581 void BrowserActionsContainer::Paint(gfx::Canvas* canvas) { 571 void BrowserActionsContainer::Paint(gfx::Canvas* canvas) {
582 // The one-pixel themed vertical divider to the right of the browser actions.
583 int x = base::i18n::IsRTL() ?
584 kDividerHorizontalMargin : (width() - kDividerHorizontalMargin);
585 DetachableToolbarView::PaintVerticalDivider(
586 canvas, x, height(), kDividerVerticalPadding,
587 DetachableToolbarView::kEdgeDividerColor,
588 DetachableToolbarView::kMiddleDividerColor,
589 GetThemeProvider()->GetColor(BrowserThemeProvider::COLOR_TOOLBAR));
590
591 // TODO(sky/glen): Instead of using a drop indicator, animate the icons while 572 // TODO(sky/glen): Instead of using a drop indicator, animate the icons while
592 // dragging (like we do for tab dragging). 573 // dragging (like we do for tab dragging).
593 if (drop_indicator_position_ > -1) { 574 if (drop_indicator_position_ > -1) {
594 // The two-pixel width drop indicator. 575 // The two-pixel width drop indicator.
595 static const int kDropIndicatorWidth = 2; 576 static const int kDropIndicatorWidth = 2;
596 gfx::Rect indicator_bounds( 577 gfx::Rect indicator_bounds(
597 drop_indicator_position_ - (kDropIndicatorWidth / 2), 578 drop_indicator_position_ - (kDropIndicatorWidth / 2),
598 kDividerVerticalPadding, kDropIndicatorWidth, 579 ToolbarView::kVertSpacing, kDropIndicatorWidth, IconHeight());
599 height() - (2 * kDividerVerticalPadding));
600 580
601 // Color of the drop indicator. 581 // Color of the drop indicator.
602 static const SkColor kDropIndicatorColor = SK_ColorBLACK; 582 static const SkColor kDropIndicatorColor = SK_ColorBLACK;
603 canvas->FillRectInt(kDropIndicatorColor, indicator_bounds.x(), 583 canvas->FillRectInt(kDropIndicatorColor, indicator_bounds.x(),
604 indicator_bounds.y(), indicator_bounds.width(), 584 indicator_bounds.y(), indicator_bounds.width(),
605 indicator_bounds.height()); 585 indicator_bounds.height());
606 } 586 }
607 } 587 }
608 588
609 void BrowserActionsContainer::ViewHierarchyChanged(bool is_add, 589 void BrowserActionsContainer::ViewHierarchyChanged(bool is_add,
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
646 int BrowserActionsContainer::OnDragUpdated( 626 int BrowserActionsContainer::OnDragUpdated(
647 const views::DropTargetEvent& event) { 627 const views::DropTargetEvent& event) {
648 // First check if we are above the chevron (overflow) menu. 628 // First check if we are above the chevron (overflow) menu.
649 if (GetViewForPoint(event.location()) == chevron_) { 629 if (GetViewForPoint(event.location()) == chevron_) {
650 if (show_menu_task_factory_.empty() && !overflow_menu_) 630 if (show_menu_task_factory_.empty() && !overflow_menu_)
651 StartShowFolderDropMenuTimer(); 631 StartShowFolderDropMenuTimer();
652 return DragDropTypes::DRAG_MOVE; 632 return DragDropTypes::DRAG_MOVE;
653 } 633 }
654 StopShowFolderDropMenuTimer(); 634 StopShowFolderDropMenuTimer();
655 635
656 // Modifying the x value before clamping affects how far you have to drag to 636 // Figure out where to display the indicator. This is a complex calculation:
657 // get the drop indicator to shift to another position. Modifying after
658 // clamping affects where the drop indicator is drawn.
659 637
660 // We add half a button size so that when you drag a button to the right and 638 // First, we figure out how much space is to the left of the icon area, so we
661 // you are half-way dragging across a button the drop indicator moves from the 639 // can calculate the true offset into the icon area.
662 // left of that button to the right of that button. 640 int width_before_icons = ToolbarView::kStandardSpacing +
663 int x = event.x() + (kButtonSize / 2) + (2 * kBrowserActionButtonPadding); 641 (base::i18n::IsRTL() ?
664 if (chevron_->IsVisible()) 642 (chevron_->GetPreferredSize().width() + kChevronSpacing) : 0);
665 x += chevron_->bounds().width(); 643 int offset_into_icon_area = event.x() - width_before_icons;
666 x = ClampToNearestIconCount(x, false);
667 644
668 if (!base::i18n::IsRTL() && chevron_->IsVisible()) { 645 // Next, we determine which icon to place the indicator in front of. We want
669 // The clamping function includes the chevron width. In LTR locales, the 646 // to place the indicator in front of icon n when the cursor is between the
670 // chevron is on the right and we never want to account for its width. In 647 // midpoints of icons (n - 1) and n. To do this we take the offset into the
671 // RTL it is on the left and we always want to count the width. 648 // icon area and transform it as follows:
672 x -= chevron_->width(); 649 //
673 } 650 // Real icon area:
651 // 0 a * b c
652 // | | | |
653 // |[IC|ON] [IC|ON] [IC|ON]
654 // We want to be before icon 0 for 0 < x <= a, icon 1 for a < x <= b, etc.
655 // Here the "*" represents the offset into the icon area, and since it's
656 // between a and b, we want to return "1".
657 //
658 // Transformed "icon area":
659 // 0 a * b c
660 // | | | |
661 // |[ICON] |[ICON] |[ICON] |
662 // If we shift both our offset and our divider points later by half an icon
663 // plus one spacing unit, then it becomes very easy to calculate how many
664 // divider points we've passed, because they're the multiples of "one icon
665 // plus padding".
666 int before_icon_unclamped = (offset_into_icon_area + (IconWidth(false) / 2) +
667 kItemSpacing) / IconWidth(true);
674 668
675 // Clamping gives us a value where the next button will be drawn, but we want 669 // Because the user can drag outside the container bounds, we need to clamp to
676 // to subtract the padding (and then some) to make it appear in-between the 670 // the valid range. Note that the maximum allowable value is (num icons), not
677 // buttons. 671 // (num icons - 1), because we represent the indicator being past the last
678 SetDropIndicator(x - kBrowserActionButtonPadding - (base::i18n::IsRTL() ? 672 // icon as being "before the (last + 1) icon".
679 kDropIndicatorOffsetRtl : kDropIndicatorOffsetLtr)); 673 int before_icon = std::min(std::max(before_icon_unclamped, 0),
674 static_cast<int>(VisibleBrowserActions()));
675
676 // Now we convert back to a pixel offset into the container. We want to place
677 // the center of the drop indicator at the midpoint of the space before our
678 // chosen icon.
679 SetDropIndicator(width_before_icons + (before_icon * IconWidth(true)) -
680 (kItemSpacing / 2));
681
680 return DragDropTypes::DRAG_MOVE; 682 return DragDropTypes::DRAG_MOVE;
681 } 683 }
682 684
683 void BrowserActionsContainer::OnDragExited() { 685 void BrowserActionsContainer::OnDragExited() {
684 StopShowFolderDropMenuTimer(); 686 StopShowFolderDropMenuTimer();
685 drop_indicator_position_ = -1; 687 drop_indicator_position_ = -1;
686 SchedulePaint(); 688 SchedulePaint();
687 } 689 }
688 690
689 int BrowserActionsContainer::OnPerformDrop( 691 int BrowserActionsContainer::OnPerformDrop(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 if (profile_->IsOffTheRecord()) 723 if (profile_->IsOffTheRecord())
722 i = model_->IncognitoIndexToOriginal(i); 724 i = model_->IncognitoIndexToOriginal(i);
723 725
724 model_->MoveBrowserAction( 726 model_->MoveBrowserAction(
725 browser_action_views_[data.index()]->button()->extension(), i); 727 browser_action_views_[data.index()]->button()->extension(), i);
726 728
727 OnDragExited(); // Perform clean up after dragging. 729 OnDragExited(); // Perform clean up after dragging.
728 return DragDropTypes::DRAG_MOVE; 730 return DragDropTypes::DRAG_MOVE;
729 } 731 }
730 732
733 void BrowserActionsContainer::OnThemeChanged() {
734 LoadImages();
735 }
736
731 bool BrowserActionsContainer::GetAccessibleRole( 737 bool BrowserActionsContainer::GetAccessibleRole(
732 AccessibilityTypes::Role* role) { 738 AccessibilityTypes::Role* role) {
733 DCHECK(role); 739 DCHECK(role);
734 *role = AccessibilityTypes::ROLE_GROUPING; 740 *role = AccessibilityTypes::ROLE_GROUPING;
735 return true; 741 return true;
736 } 742 }
737 743
738 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) { 744 void BrowserActionsContainer::RunMenu(View* source, const gfx::Point& pt) {
739 if (source == chevron_) { 745 if (source == chevron_) {
740 overflow_menu_ = new BrowserActionOverflowMenuController( 746 overflow_menu_ = new BrowserActionOverflowMenuController(
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 return DragDropTypes::DRAG_MOVE; 778 return DragDropTypes::DRAG_MOVE;
773 } 779 }
774 780
775 bool BrowserActionsContainer::CanStartDrag(View* sender, 781 bool BrowserActionsContainer::CanStartDrag(View* sender,
776 const gfx::Point& press_pt, 782 const gfx::Point& press_pt,
777 const gfx::Point& p) { 783 const gfx::Point& p) {
778 return true; 784 return true;
779 } 785 }
780 786
781 void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) { 787 void BrowserActionsContainer::OnResize(int resize_amount, bool done_resizing) {
782 if (!done_resizing) { 788 if (done_resizing) {
789 // Up until now we've only been modifying the resize_amount, but now it is
790 // time to set the container size to the size we have resized to, and then
791 // animate to the nearest icon count size if necessary (which may be 0).
792 int max_width = IconCountToWidth(-1, false);
793 container_width_ =
794 std::min(std::max(0, container_width_ - resize_amount), max_width);
795 if (container_width_ < max_width) {
796 animation_target_size_ =
797 IconCountToWidth(WidthToIconCount(container_width_), true);
798 resize_animation_->Reset();
799 resize_animation_->SetTweenType(Tween::EASE_OUT);
800 resize_animation_->Show();
801 return;
802 }
803 } else {
783 resize_amount_ = resize_amount; 804 resize_amount_ = resize_amount;
784 OnBrowserActionVisibilityChanged();
785 } else {
786 // For details on why we do the following see the class comments in the
787 // header.
788
789 // Clamp lower limit to 0 and upper limit to the amount that allows enough
790 // room for all icons to show.
791 int new_width = std::max(0, container_width_ - resize_amount);
792 int max_width = ClampToNearestIconCount(-1, false);
793 new_width = std::min(new_width, max_width);
794
795 // Up until now we've only been modifying the resize_amount, but now it is
796 // time to set the container size to the size we have resized to, but then
797 // animate to the nearest icon count size (or down to min size if no icon).
798 container_width_ = new_width;
799 animation_target_size_ = ClampToNearestIconCount(new_width, true);
800 resize_animation_->Reset();
801 resize_animation_->SetTweenType(Tween::EASE_OUT);
802 resize_animation_->Show();
803 } 805 }
806 OnBrowserActionVisibilityChanged();
804 } 807 }
805 808
806 void BrowserActionsContainer::AnimationProgressed(const Animation* animation) { 809 void BrowserActionsContainer::AnimationProgressed(const Animation* animation) {
807 DCHECK_EQ(resize_animation_.get(), animation); 810 DCHECK_EQ(resize_animation_.get(), animation);
808 resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() * 811 resize_amount_ = static_cast<int>(resize_animation_->GetCurrentValue() *
809 (container_width_ - animation_target_size_)); 812 (container_width_ - animation_target_size_));
810 OnBrowserActionVisibilityChanged(); 813 OnBrowserActionVisibilityChanged();
811 } 814 }
812 815
813 void BrowserActionsContainer::AnimationEnded(const Animation* animation) { 816 void BrowserActionsContainer::AnimationEnded(const Animation* animation) {
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 } 855 }
853 } 856 }
854 857
855 void BrowserActionsContainer::HidePopup() { 858 void BrowserActionsContainer::HidePopup() {
856 if (popup_) 859 if (popup_)
857 popup_->Close(); 860 popup_->Close();
858 } 861 }
859 862
860 void BrowserActionsContainer::TestExecuteBrowserAction(int index) { 863 void BrowserActionsContainer::TestExecuteBrowserAction(int index) {
861 BrowserActionButton* button = browser_action_views_[index]->button(); 864 BrowserActionButton* button = browser_action_views_[index]->button();
862 OnBrowserActionExecuted(button, false); // |inspect_with_devtools|. 865 OnBrowserActionExecuted(button, false);
863 } 866 }
864 867
865 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) { 868 void BrowserActionsContainer::TestSetIconVisibilityCount(size_t icons) {
869 model_->SetVisibleIconCount(icons);
866 chevron_->SetVisible(icons < browser_action_views_.size()); 870 chevron_->SetVisible(icons < browser_action_views_.size());
867 container_width_ = IconCountToWidth(icons); 871 container_width_ = IconCountToWidth(icons, chevron_->IsVisible());
868 Layout(); 872 Layout();
869 SchedulePaint(); 873 SchedulePaint();
870 } 874 }
871 875
876 // static
877 int BrowserActionsContainer::IconWidth(bool include_padding) {
878 static bool initialized = false;
879 static int icon_width = 0;
880 if (!initialized) {
881 initialized = true;
882 icon_width = ResourceBundle::GetSharedInstance().GetBitmapNamed(
883 IDR_BROWSER_ACTION)->width();
884 }
885 return icon_width + (include_padding ? kItemSpacing : 0);
886 }
887
888 // static
889 int BrowserActionsContainer::IconHeight() {
890 static bool initialized = false;
891 static int icon_height = 0;
892 if (!initialized) {
893 initialized = true;
894 icon_height = ResourceBundle::GetSharedInstance().GetBitmapNamed(
895 IDR_BROWSER_ACTION)->height();
896 }
897 return icon_height;
898 }
899
872 void BrowserActionsContainer::BrowserActionAdded(Extension* extension, 900 void BrowserActionsContainer::BrowserActionAdded(Extension* extension,
873 int index) { 901 int index) {
874 #if defined(DEBUG) 902 #if defined(DEBUG)
875 for (size_t i = 0; i < browser_action_views_.size(); ++i) { 903 for (size_t i = 0; i < browser_action_views_.size(); ++i) {
876 DCHECK(browser_action_views_[i]->button()->extension() != extension) << 904 DCHECK(browser_action_views_[i]->button()->extension() != extension) <<
877 "Asked to add a browser action view for an extension that already " 905 "Asked to add a browser action view for an extension that already "
878 "exists."; 906 "exists.";
879 } 907 }
880 #endif 908 #endif
881 CloseOverflowMenu(); 909 CloseOverflowMenu();
882 910
883 if (!ShouldDisplayBrowserAction(extension)) 911 if (!ShouldDisplayBrowserAction(extension))
884 return; 912 return;
885 913
886 size_t visible_actions = VisibleBrowserActions(); 914 size_t visible_actions = VisibleBrowserActions();
887 915
888 // Add the new browser action to the vector and the view hierarchy. 916 // Add the new browser action to the vector and the view hierarchy.
889 if (profile_->IsOffTheRecord()) 917 if (profile_->IsOffTheRecord())
890 index = model_->OriginalIndexToIncognito(index); 918 index = model_->OriginalIndexToIncognito(index);
891
892 BrowserActionView* view = new BrowserActionView(extension, this); 919 BrowserActionView* view = new BrowserActionView(extension, this);
893 browser_action_views_.insert(browser_action_views_.begin() + index, view); 920 browser_action_views_.insert(browser_action_views_.begin() + index, view);
894 AddChildView(index, view); 921 AddChildView(index, view);
895 922
896 // If we are still initializing the container, don't bother animating. 923 // If we are still initializing the container, don't bother animating.
897 if (!model_->extensions_initialized()) 924 if (!model_->extensions_initialized())
898 return; 925 return;
899 926
900 // For details on why we do the following see the class comments in the 927 // Enlarge the container if it was already at maximum size and we're not in
901 // header. 928 // the middle of upgrading.
902 929 if ((model_->GetVisibleIconCount() < 0) && !extension->being_upgraded()) {
903 // Determine if we need to increase (we only do that if the container was 930 int target_size = IconCountToWidth(visible_actions + 1, false);
904 // showing all icons before the addition of this icon). 931 suppress_chevron_ = true;
905 if (model_->GetVisibleIconCount() >= 0 || extension->being_upgraded()) { 932 Animate(Tween::LINEAR, target_size);
906 // Some icons were hidden, don't increase the size of the container. 933 } else {
934 // Just redraw the (possibly modified) visible icon set.
907 OnBrowserActionVisibilityChanged(); 935 OnBrowserActionVisibilityChanged();
908 } else {
909 // Container was at max, increase the size of it by one icon.
910 int target_size = IconCountToWidth(visible_actions + 1);
911
912 // We don't want the chevron to appear while we animate. See documentation
913 // in the header for why we do this.
914 suppress_chevron_ = !chevron_->IsVisible();
915
916 Animate(Tween::LINEAR, target_size);
917 } 936 }
918 } 937 }
919 938
920 void BrowserActionsContainer::BrowserActionRemoved(Extension* extension) { 939 void BrowserActionsContainer::BrowserActionRemoved(Extension* extension) {
921 CloseOverflowMenu(); 940 CloseOverflowMenu();
922 941
923 if (popup_ && popup_->host()->extension() == extension) 942 if (popup_ && popup_->host()->extension() == extension)
924 HidePopup(); 943 HidePopup();
925 944
926 size_t visible_actions = VisibleBrowserActions(); 945 size_t visible_actions = VisibleBrowserActions();
927 for (BrowserActionViews::iterator iter = browser_action_views_.begin(); 946 for (BrowserActionViews::iterator iter = browser_action_views_.begin();
928 iter != browser_action_views_.end(); ++iter) { 947 iter != browser_action_views_.end(); ++iter) {
929 if ((*iter)->button()->extension() == extension) { 948 if ((*iter)->button()->extension() == extension) {
930 RemoveChildView(*iter); 949 RemoveChildView(*iter);
931 delete *iter; 950 delete *iter;
932 browser_action_views_.erase(iter); 951 browser_action_views_.erase(iter);
933 952
934 // If the extension is being upgraded we don't want the bar to shrink 953 // If the extension is being upgraded we don't want the bar to shrink
935 // because the icon is just going to get re-added to the same location. 954 // because the icon is just going to get re-added to the same location.
936 if (extension->being_upgraded()) 955 if (extension->being_upgraded())
937 return; 956 return;
938 957
939 // For details on why we do the following see the class comments in the 958 if (browser_action_views_.size() > visible_actions) {
940 // header. 959 // If we have more icons than we can show, then we must not be changing
941 960 // the container size (since we either removed an icon from the main
942 // Calculate the target size we'll animate to (end state). This might be 961 // area and one from the overflow list will have shifted in, or we
943 // the same size (if the icon we are removing is in the overflow bucket 962 // removed an entry directly from the overflow list).
944 // and there are other icons there). We don't decrement visible_actions 963 OnBrowserActionVisibilityChanged();
945 // because we want the container to stay the same size (clamping will take 964 } else {
946 // care of shrinking the container if there aren't enough icons to show). 965 // Either we went from overflow to no-overflow, or we shrunk the no-
947 int target_size = 966 // overflow container by 1. Either way the size changed, so animate.
948 ClampToNearestIconCount(IconCountToWidth(visible_actions), true); 967 chevron_->SetVisible(false);
949 968 Animate(Tween::EASE_OUT, IconCountToWidth(-1, false));
950 Animate(Tween::EASE_OUT, target_size); 969 }
951 return; 970 return;
952 } 971 }
953 } 972 }
954 } 973 }
955 974
956 void BrowserActionsContainer::BrowserActionMoved(Extension* extension, 975 void BrowserActionsContainer::BrowserActionMoved(Extension* extension,
957 int index) { 976 int index) {
958 if (!ShouldDisplayBrowserAction(extension)) 977 if (!ShouldDisplayBrowserAction(extension))
959 return; 978 return;
960 979
961 if (profile_->IsOffTheRecord()) 980 if (profile_->IsOffTheRecord())
962 index = model_->OriginalIndexToIncognito(index); 981 index = model_->OriginalIndexToIncognito(index);
963 982
964 DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size())); 983 DCHECK(index >= 0 && index < static_cast<int>(browser_action_views_.size()));
965 984
966 DeleteBrowserActionViews(); 985 DeleteBrowserActionViews();
967 CreateBrowserActionViews(); 986 CreateBrowserActionViews();
968 Layout(); 987 Layout();
969 SchedulePaint(); 988 SchedulePaint();
970 } 989 }
971 990
972 void BrowserActionsContainer::ModelLoaded() { 991 void BrowserActionsContainer::ModelLoaded() {
973 SetContainerWidth(); 992 SetContainerWidth();
974 } 993 }
975 994
995 void BrowserActionsContainer::LoadImages() {
996 ThemeProvider* tp = GetThemeProvider();
997 chevron_->SetIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW));
998 chevron_->SetHoverIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW_H));
999 chevron_->SetPushedIcon(*tp->GetBitmapNamed(IDR_BROWSER_ACTIONS_OVERFLOW_P));
1000 }
1001
976 void BrowserActionsContainer::SetContainerWidth() { 1002 void BrowserActionsContainer::SetContainerWidth() {
977 int visible_actions = model_->GetVisibleIconCount(); 1003 int visible_actions = model_->GetVisibleIconCount();
978 if (visible_actions < 0) // All icons should be visible. 1004 if (visible_actions < 0) // All icons should be visible.
979 visible_actions = model_->size(); 1005 visible_actions = model_->size();
980 chevron_->SetVisible(static_cast<size_t>(visible_actions) < model_->size()); 1006 chevron_->SetVisible(static_cast<size_t>(visible_actions) < model_->size());
981 container_width_ = IconCountToWidth(visible_actions); 1007 container_width_ = IconCountToWidth(visible_actions, chevron_->IsVisible());
982 } 1008 }
983 1009
984 void BrowserActionsContainer::CloseOverflowMenu() { 1010 void BrowserActionsContainer::CloseOverflowMenu() {
985 if (overflow_menu_) 1011 if (overflow_menu_)
986 overflow_menu_->CancelMenu(); 1012 overflow_menu_->CancelMenu();
987 } 1013 }
988 1014
989 void BrowserActionsContainer::StopShowFolderDropMenuTimer() { 1015 void BrowserActionsContainer::StopShowFolderDropMenuTimer() {
990 show_menu_task_factory_.RevokeAll(); 1016 show_menu_task_factory_.RevokeAll();
991 } 1017 }
(...skipping 15 matching lines...) Expand all
1007 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), true); 1033 overflow_menu_->RunMenu(GetWindow()->GetNativeWindow(), true);
1008 } 1034 }
1009 1035
1010 void BrowserActionsContainer::SetDropIndicator(int x_pos) { 1036 void BrowserActionsContainer::SetDropIndicator(int x_pos) {
1011 if (drop_indicator_position_ != x_pos) { 1037 if (drop_indicator_position_ != x_pos) {
1012 drop_indicator_position_ = x_pos; 1038 drop_indicator_position_ = x_pos;
1013 SchedulePaint(); 1039 SchedulePaint();
1014 } 1040 }
1015 } 1041 }
1016 1042
1017 int BrowserActionsContainer::ClampToNearestIconCount( 1043 int BrowserActionsContainer::IconCountToWidth(int icons,
1018 int pixelWidth, 1044 bool display_chevron) const {
1019 bool allow_shrink_to_minimum) const { 1045 if (icons < 0)
1020 // Calculate the width of one icon. 1046 icons = browser_action_views_.size();
1021 int icon_width = (kButtonSize + kBrowserActionButtonPadding); 1047 if ((icons == 0) && !display_chevron)
1022 1048 return ToolbarView::kStandardSpacing;
1023 // Calculate pixel count for the area not used by the icons. 1049 int icons_size =
1024 int extras = WidthOfNonIconArea(); 1050 (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing);
1025 1051 int chevron_size = display_chevron ?
1026 size_t icon_count = 0u; 1052 (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0;
1027 if (pixelWidth >= 0) { 1053 return ToolbarView::kStandardSpacing + icons_size + chevron_size +
1028 // Caller wants to know how many icons fit within a given space so we start 1054 ToolbarView::kStandardSpacing;
1029 // by subtracting the padding, resize area and dividers.
1030 int icon_area = pixelWidth - extras;
1031 icon_area = std::max(0, icon_area);
1032
1033 // Make sure we never throw an icon into the chevron menu just because
1034 // there isn't enough enough space for the invisible padding around buttons.
1035 icon_area += kBrowserActionButtonPadding - 1;
1036
1037 // Count the number of icons that fit within that area.
1038 icon_count = icon_area / icon_width;
1039
1040 if (icon_count == 0 && allow_shrink_to_minimum) {
1041 extras = ContainerMinSize(); // Allow very narrow width if no icons.
1042 } else if (icon_count > browser_action_views_.size()) {
1043 // No use allowing more than what we have.
1044 icon_count = browser_action_views_.size();
1045 }
1046 } else {
1047 // A negative |pixels| count indicates caller wants to know the max width
1048 // that fits all icons;
1049 icon_count = browser_action_views_.size();
1050 }
1051
1052 return extras + (icon_count * icon_width);
1053 } 1055 }
1054 1056
1055 int BrowserActionsContainer::WidthOfNonIconArea() const { 1057 int BrowserActionsContainer::WidthToIconCount(int pixels) const {
1056 int chevron_size = (chevron_->IsVisible()) ? 1058 // We need to reserve space for the resize area, chevron, and the spacing on
1057 chevron_->GetPreferredSize().width() : 0; 1059 // either side of the chevron.
1058 int padding = base::i18n::IsRTL() ? 1060 int available_space = pixels - ToolbarView::kStandardSpacing -
1059 kHorizontalPaddingRtl : kHorizontalPadding; 1061 chevron_->GetPreferredSize().width() - kChevronSpacing -
1060 return kResizeAreaWidth + padding + chevron_size + kChevronRightMargin + 1062 ToolbarView::kStandardSpacing;
1061 kDividerHorizontalMargin; 1063 // Now we add an extra between-item padding value so the space can be divided
1062 } 1064 // evenly by (size of icon with padding).
1063 1065 return std::max(0, available_space + kItemSpacing) / IconWidth(true);
1064 int BrowserActionsContainer::IconCountToWidth(int icons) const {
1065 DCHECK_GE(icons, 0);
1066 if (icons == 0)
1067 return ContainerMinSize();
1068
1069 int icon_width = kButtonSize + kBrowserActionButtonPadding;
1070
1071 return WidthOfNonIconArea() + (icons * icon_width);
1072 } 1066 }
1073 1067
1074 int BrowserActionsContainer::ContainerMinSize() const { 1068 int BrowserActionsContainer::ContainerMinSize() const {
1075 return kResizeAreaWidth + chevron_->width() + kChevronRightMargin; 1069 return ToolbarView::kStandardSpacing + kChevronSpacing +
1070 chevron_->GetPreferredSize().width() + ToolbarView::kStandardSpacing;
1076 } 1071 }
1077 1072
1078 void BrowserActionsContainer::Animate(Tween::Type tween_type, int target_size) { 1073 void BrowserActionsContainer::Animate(Tween::Type tween_type, int target_size) {
1079 if (!disable_animations_during_testing_) { 1074 if (!disable_animations_during_testing_) {
1080 // Animate! We have to set the animation_target_size_ after calling Reset(), 1075 // Animate! We have to set the animation_target_size_ after calling Reset(),
1081 // because that could end up calling AnimationEnded which clears the value. 1076 // because that could end up calling AnimationEnded which clears the value.
1082 resize_animation_->Reset(); 1077 resize_animation_->Reset();
1083 resize_animation_->SetTweenType(tween_type); 1078 resize_animation_->SetTweenType(tween_type);
1084 animation_target_size_ = target_size; 1079 animation_target_size_ = target_size;
1085 resize_animation_->Show(); 1080 resize_animation_->Show();
1086 } else { 1081 } else {
1087 animation_target_size_ = target_size; 1082 animation_target_size_ = target_size;
1088 AnimationEnded(resize_animation_.get()); 1083 AnimationEnded(resize_animation_.get());
1089 } 1084 }
1090 } 1085 }
1091 1086
1092 bool BrowserActionsContainer::ShouldDisplayBrowserAction(Extension* extension) { 1087 bool BrowserActionsContainer::ShouldDisplayBrowserAction(Extension* extension) {
1093 // Only display incognito-enabled extensions while in incognito mode. 1088 // Only display incognito-enabled extensions while in incognito mode.
1094 return (!profile_->IsOffTheRecord() || 1089 return (!profile_->IsOffTheRecord() ||
1095 profile_->GetExtensionsService()->IsIncognitoEnabled(extension)); 1090 profile_->GetExtensionsService()->IsIncognitoEnabled(extension));
1096 } 1091 }
OLDNEW
« no previous file with comments | « chrome/browser/views/browser_actions_container.h ('k') | chrome/browser/views/toolbar_view.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698