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

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

Issue 553233002: Dynamically calculate the number of extension icons to show per row in overflow (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Don't resize menu to accommodate Created 6 years, 3 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/ui/views/toolbar/browser_actions_container.h" 5 #include "chrome/browser/ui/views/toolbar/browser_actions_container.h"
6 6
7 #include "base/compiler_specific.h" 7 #include "base/compiler_specific.h"
8 #include "base/stl_util.h" 8 #include "base/stl_util.h"
9 #include "chrome/browser/extensions/extension_action_manager.h" 9 #include "chrome/browser/extensions/extension_action_manager.h"
10 #include "chrome/browser/extensions/extension_util.h" 10 #include "chrome/browser/extensions/extension_util.h"
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 #include "ui/views/controls/button/menu_button.h" 43 #include "ui/views/controls/button/menu_button.h"
44 #include "ui/views/controls/resize_area.h" 44 #include "ui/views/controls/resize_area.h"
45 #include "ui/views/metrics.h" 45 #include "ui/views/metrics.h"
46 #include "ui/views/painter.h" 46 #include "ui/views/painter.h"
47 #include "ui/views/widget/widget.h" 47 #include "ui/views/widget/widget.h"
48 48
49 using extensions::Extension; 49 using extensions::Extension;
50 50
51 namespace { 51 namespace {
52 52
53 // Horizontal spacing between most items in the container, as well as after the
54 // last item or chevron (if visible).
55 const int kItemSpacing = ToolbarView::kStandardSpacing;
56
57 // Horizontal spacing before the chevron (if visible). 53 // Horizontal spacing before the chevron (if visible).
58 const int kChevronSpacing = kItemSpacing - 2; 54 const int kChevronSpacing = ToolbarView::kStandardSpacing - 2;
59
60 // The maximum number of icons to show per row when in overflow mode (showing
61 // icons in the application menu).
62 // TODO(devlin): Compute the right number of icons to show, depending on the
63 // menu width.
64 #if defined(OS_LINUX)
65 const int kIconsPerMenuRow = 8; // The menu on Linux is wider.
66 #else
67 const int kIconsPerMenuRow = 7;
68 #endif
69 55
70 // A version of MenuButton with almost empty insets to fit properly on the 56 // A version of MenuButton with almost empty insets to fit properly on the
71 // toolbar. 57 // toolbar.
72 class ChevronMenuButton : public views::MenuButton { 58 class ChevronMenuButton : public views::MenuButton {
73 public: 59 public:
74 ChevronMenuButton(views::ButtonListener* listener, 60 ChevronMenuButton(views::ButtonListener* listener,
75 const base::string16& text, 61 const base::string16& text,
76 views::MenuButtonListener* menu_button_listener, 62 views::MenuButtonListener* menu_button_listener,
77 bool show_menu_marker) 63 bool show_menu_marker)
78 : views::MenuButton(listener, 64 : views::MenuButton(listener,
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 99
114 BrowserActionsContainer::DropPosition::DropPosition( 100 BrowserActionsContainer::DropPosition::DropPosition(
115 size_t row, size_t icon_in_row) 101 size_t row, size_t icon_in_row)
116 : row(row), icon_in_row(icon_in_row) { 102 : row(row), icon_in_row(icon_in_row) {
117 } 103 }
118 104
119 //////////////////////////////////////////////////////////////////////////////// 105 ////////////////////////////////////////////////////////////////////////////////
120 // BrowserActionsContainer 106 // BrowserActionsContainer
121 107
122 // static 108 // static
109 int BrowserActionsContainer::icons_per_overflow_menu_row_ = 1;
110
111 // static
112 const int BrowserActionsContainer::kItemSpacing = ToolbarView::kStandardSpacing;
113
114 // static
123 bool BrowserActionsContainer::disable_animations_during_testing_ = false; 115 bool BrowserActionsContainer::disable_animations_during_testing_ = false;
124 116
125 BrowserActionsContainer::BrowserActionsContainer( 117 BrowserActionsContainer::BrowserActionsContainer(
126 Browser* browser, 118 Browser* browser,
127 View* owner_view, 119 View* owner_view,
128 BrowserActionsContainer* main_container) 120 BrowserActionsContainer* main_container)
129 : profile_(browser->profile()), 121 : profile_(browser->profile()),
130 browser_(browser), 122 browser_(browser),
131 owner_view_(owner_view), 123 owner_view_(owner_view),
132 main_container_(main_container), 124 main_container_(main_container),
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 319
328 // If there are no actions to show, or we are in overflow mode and the main 320 // If there are no actions to show, or we are in overflow mode and the main
329 // container is already showing them all, then no further work is required. 321 // container is already showing them all, then no further work is required.
330 if (icon_count == 0) 322 if (icon_count == 0)
331 return gfx::Size(); 323 return gfx::Size();
332 324
333 if (in_overflow_mode()) { 325 if (in_overflow_mode()) {
334 // When in overflow, y is multiline, so the pixel count is IconHeight() 326 // When in overflow, y is multiline, so the pixel count is IconHeight()
335 // times the number of rows needed. 327 // times the number of rows needed.
336 return gfx::Size( 328 return gfx::Size(
337 IconCountToWidth(kIconsPerMenuRow, false), 329 IconCountToWidth(icons_per_overflow_menu_row_, false),
338 (((icon_count - 1) / kIconsPerMenuRow) + 1) * IconHeight()); 330 (((icon_count - 1) / icons_per_overflow_menu_row_) + 1) * IconHeight());
339 } 331 }
340 332
341 // We calculate the size of the view by taking the current width and 333 // We calculate the size of the view by taking the current width and
342 // subtracting resize_amount_ (the latter represents how far the user is 334 // subtracting resize_amount_ (the latter represents how far the user is
343 // resizing the view or, if animating the snapping, how far to animate it). 335 // resizing the view or, if animating the snapping, how far to animate it).
344 // But we also clamp it to a minimum size and the maximum size, so that the 336 // But we also clamp it to a minimum size and the maximum size, so that the
345 // container can never shrink too far or take up more space than it needs. 337 // container can never shrink too far or take up more space than it needs.
346 // In other words: MinimumNonemptyWidth() < width() - resize < ClampTo(MAX). 338 // In other words: MinimumNonemptyWidth() < width() - resize < ClampTo(MAX).
347 int preferred_width = std::min( 339 int preferred_width = std::min(
348 std::max(MinimumNonemptyWidth(), container_width_ - resize_amount_), 340 std::max(MinimumNonemptyWidth(), container_width_ - resize_amount_),
349 IconCountToWidth(-1, false)); 341 IconCountToWidth(-1, false));
350 return gfx::Size(preferred_width, IconHeight()); 342 return gfx::Size(preferred_width, IconHeight());
351 } 343 }
352 344
345 int BrowserActionsContainer::GetHeightForWidth(int width) const {
346 if (in_overflow_mode())
347 icons_per_overflow_menu_row_ = (width - kItemSpacing) / IconWidth(true);
348 return GetPreferredSize().height();
349 }
350
353 gfx::Size BrowserActionsContainer::GetMinimumSize() const { 351 gfx::Size BrowserActionsContainer::GetMinimumSize() const {
354 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1, false)); 352 int min_width = std::min(MinimumNonemptyWidth(), IconCountToWidth(-1, false));
355 return gfx::Size(min_width, IconHeight()); 353 return gfx::Size(min_width, IconHeight());
356 } 354 }
357 355
358 void BrowserActionsContainer::Layout() { 356 void BrowserActionsContainer::Layout() {
359 if (browser_action_views_.empty()) { 357 if (browser_action_views_.empty()) {
360 SetVisible(false); 358 SetVisible(false);
361 return; 359 return;
362 } 360 }
(...skipping 25 matching lines...) Expand all
388 i < main_container_->VisibleBrowserActionsAfterAnimation(); ++i) { 386 i < main_container_->VisibleBrowserActionsAfterAnimation(); ++i) {
389 // Ensure that any browser actions shown in the main view are hidden in 387 // Ensure that any browser actions shown in the main view are hidden in
390 // the overflow view. 388 // the overflow view.
391 browser_action_views_[i]->SetVisible(false); 389 browser_action_views_[i]->SetVisible(false);
392 } 390 }
393 391
394 for (size_t i = main_container_->VisibleBrowserActionsAfterAnimation(); 392 for (size_t i = main_container_->VisibleBrowserActionsAfterAnimation();
395 i < browser_action_views_.size(); ++i) { 393 i < browser_action_views_.size(); ++i) {
396 BrowserActionView* view = browser_action_views_[i]; 394 BrowserActionView* view = browser_action_views_[i];
397 size_t index = i - main_container_->VisibleBrowserActionsAfterAnimation(); 395 size_t index = i - main_container_->VisibleBrowserActionsAfterAnimation();
398 int row_index = static_cast<int>(index) / kIconsPerMenuRow; 396 int row_index = static_cast<int>(index) / icons_per_overflow_menu_row_;
399 int x = kItemSpacing + (index * IconWidth(true)) - 397 int x = kItemSpacing + (index * IconWidth(true)) -
400 (row_index * IconWidth(true) * kIconsPerMenuRow); 398 (row_index * IconWidth(true) * icons_per_overflow_menu_row_);
401 gfx::Rect rect_bounds( 399 gfx::Rect rect_bounds(
402 x, IconHeight() * row_index, icon_width, IconHeight()); 400 x, IconHeight() * row_index, icon_width, IconHeight());
403 view->SetBoundsRect(rect_bounds); 401 view->SetBoundsRect(rect_bounds);
404 view->SetVisible(true); 402 view->SetVisible(true);
405 } 403 }
406 } else { 404 } else {
407 for (BrowserActionViews::const_iterator it = browser_action_views_.begin(); 405 for (BrowserActionViews::const_iterator it = browser_action_views_.begin();
408 it < browser_action_views_.end(); ++it) { 406 it < browser_action_views_.end(); ++it) {
409 BrowserActionView* view = *it; 407 BrowserActionView* view = *it;
410 int x = ToolbarView::kStandardSpacing + 408 int x = ToolbarView::kStandardSpacing +
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 kItemSpacing) / IconWidth(true); 483 kItemSpacing) / IconWidth(true);
486 484
487 // We need to figure out how many icons are visible on the relevant row. 485 // We need to figure out how many icons are visible on the relevant row.
488 // In the main container, this will just be the visible actions. 486 // In the main container, this will just be the visible actions.
489 int visible_icons_on_row = VisibleBrowserActionsAfterAnimation(); 487 int visible_icons_on_row = VisibleBrowserActionsAfterAnimation();
490 if (in_overflow_mode()) { 488 if (in_overflow_mode()) {
491 // If this is the final row of the overflow, then this is the remainder of 489 // If this is the final row of the overflow, then this is the remainder of
492 // visible icons. Otherwise, it's a full row (kIconsPerRow). 490 // visible icons. Otherwise, it's a full row (kIconsPerRow).
493 visible_icons_on_row = 491 visible_icons_on_row =
494 row_index == 492 row_index ==
495 static_cast<size_t>(visible_icons_on_row / kIconsPerMenuRow) ? 493 static_cast<size_t>(visible_icons_on_row /
496 visible_icons_on_row % kIconsPerMenuRow : 494 icons_per_overflow_menu_row_) ?
497 kIconsPerMenuRow; 495 visible_icons_on_row % icons_per_overflow_menu_row_ :
496 icons_per_overflow_menu_row_;
498 } 497 }
499 498
500 // Because the user can drag outside the container bounds, we need to clamp to 499 // Because the user can drag outside the container bounds, we need to clamp to
501 // the valid range. Note that the maximum allowable value is (num icons), not 500 // the valid range. Note that the maximum allowable value is (num icons), not
502 // (num icons - 1), because we represent the indicator being past the last 501 // (num icons - 1), because we represent the indicator being past the last
503 // icon as being "before the (last + 1) icon". 502 // icon as being "before the (last + 1) icon".
504 size_t before_icon_in_row = 503 size_t before_icon_in_row =
505 std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row); 504 std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row);
506 505
507 if (!drop_position_.get() || 506 if (!drop_position_.get() ||
(...skipping 16 matching lines...) Expand all
524 const ui::DropTargetEvent& event) { 523 const ui::DropTargetEvent& event) {
525 BrowserActionDragData data; 524 BrowserActionDragData data;
526 if (!data.Read(event.data())) 525 if (!data.Read(event.data()))
527 return ui::DragDropTypes::DRAG_NONE; 526 return ui::DragDropTypes::DRAG_NONE;
528 527
529 // Make sure we have the same view as we started with. 528 // Make sure we have the same view as we started with.
530 DCHECK_EQ(browser_action_views_[data.index()]->extension()->id(), 529 DCHECK_EQ(browser_action_views_[data.index()]->extension()->id(),
531 data.id()); 530 data.id());
532 DCHECK(model_); 531 DCHECK(model_);
533 532
534 size_t i = 533 size_t i = drop_position_->row * icons_per_overflow_menu_row_ +
535 drop_position_->row * kIconsPerMenuRow + drop_position_->icon_in_row; 534 drop_position_->icon_in_row;
536 if (in_overflow_mode()) 535 if (in_overflow_mode())
537 i += GetFirstVisibleIconIndex(); 536 i += GetFirstVisibleIconIndex();
538 // |i| now points to the item to the right of the drop indicator*, which is 537 // |i| now points to the item to the right of the drop indicator*, which is
539 // correct when dragging an icon to the left. When dragging to the right, 538 // correct when dragging an icon to the left. When dragging to the right,
540 // however, we want the icon being dragged to get the index of the item to 539 // however, we want the icon being dragged to get the index of the item to
541 // the left of the drop indicator, so we subtract one. 540 // the left of the drop indicator, so we subtract one.
542 // * Well, it can also point to the end, but not when dragging to the left. :) 541 // * Well, it can also point to the end, but not when dragging to the left. :)
543 if (i > data.index()) 542 if (i > data.index())
544 --i; 543 --i;
545 544
(...skipping 464 matching lines...) Expand 10 before | Expand all | Expand 10 after
1010 int BrowserActionsContainer::IconCountToWidth(int icons, 1009 int BrowserActionsContainer::IconCountToWidth(int icons,
1011 bool display_chevron) const { 1010 bool display_chevron) const {
1012 if (icons < 0) 1011 if (icons < 0)
1013 icons = browser_action_views_.size(); 1012 icons = browser_action_views_.size();
1014 if ((icons == 0) && !display_chevron) 1013 if ((icons == 0) && !display_chevron)
1015 return ToolbarView::kStandardSpacing; 1014 return ToolbarView::kStandardSpacing;
1016 int icons_size = 1015 int icons_size =
1017 (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing); 1016 (icons == 0) ? 0 : ((icons * IconWidth(true)) - kItemSpacing);
1018 int chevron_size = chevron_ && display_chevron ? 1017 int chevron_size = chevron_ && display_chevron ?
1019 (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0; 1018 (kChevronSpacing + chevron_->GetPreferredSize().width()) : 0;
1020 return ToolbarView::kStandardSpacing + icons_size + chevron_size + 1019 // In overflow mode, our padding is to use item spacing on either end (just so
1021 ToolbarView::kStandardSpacing; 1020 // we can see the drop indicator). Otherwise we use the standard toolbar
1021 // spacing.
1022 // Note: These are actually the same thing, but, on the offchance one
1023 // changes, let's get it right.
1024 int padding =
1025 2 * (in_overflow_mode() ? kItemSpacing : ToolbarView::kStandardSpacing);
1026 return icons_size + chevron_size + padding;
1022 } 1027 }
1023 1028
1024 size_t BrowserActionsContainer::WidthToIconCount(int pixels) const { 1029 size_t BrowserActionsContainer::WidthToIconCount(int pixels) const {
1025 // Check for widths large enough to show the entire icon set. 1030 // Check for widths large enough to show the entire icon set.
1026 if (pixels >= IconCountToWidth(-1, false)) 1031 if (pixels >= IconCountToWidth(-1, false))
1027 return browser_action_views_.size(); 1032 return browser_action_views_.size();
1028 1033
1029 // We need to reserve space for the resize area, chevron, and the spacing on 1034 // We need to reserve space for the resize area, chevron, and the spacing on
1030 // either side of the chevron. 1035 // either side of the chevron.
1031 int available_space = pixels - ToolbarView::kStandardSpacing - 1036 int available_space = pixels - ToolbarView::kStandardSpacing -
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 size_t absolute_model_size = 1088 size_t absolute_model_size =
1084 model_size == -1 ? extensions.size() : model_size; 1089 model_size == -1 ? extensions.size() : model_size;
1085 1090
1086 // The main container will try to show |model_size| icons, but reduce if there 1091 // The main container will try to show |model_size| icons, but reduce if there
1087 // aren't enough displayable icons to do so. 1092 // aren't enough displayable icons to do so.
1088 size_t main_displayed = std::min(displayable_icon_count, absolute_model_size); 1093 size_t main_displayed = std::min(displayable_icon_count, absolute_model_size);
1089 // The overflow will display the extras, if any. 1094 // The overflow will display the extras, if any.
1090 return in_overflow_mode() ? 1095 return in_overflow_mode() ?
1091 displayable_icon_count - main_displayed : main_displayed; 1096 displayable_icon_count - main_displayed : main_displayed;
1092 } 1097 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698