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

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

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