Commit 9bdf4531 authored by rdevlin.cronin's avatar rdevlin.cronin Committed by Commit bot

Allow the user to drag an extension to the overflow menu, even when its empty

We need to show an empty bar for the user to drag extension actions into for
overflow when there are none currently overflowed. Obviously, this empty bar
should only be displayed when the user is dragging an extension action.

BUG=414386

Review URL: https://codereview.chromium.org/556293003

Cr-Commit-Position: refs/heads/master@{#295179}
parent fedbb0d1
...@@ -268,8 +268,15 @@ void BrowserActionsContainer::ExecuteExtensionCommand( ...@@ -268,8 +268,15 @@ void BrowserActionsContainer::ExecuteExtensionCommand(
void BrowserActionsContainer::NotifyActionMovedToOverflow() { void BrowserActionsContainer::NotifyActionMovedToOverflow() {
// When an action is moved to overflow, we shrink the size of the container // When an action is moved to overflow, we shrink the size of the container
// by 1. // by 1.
if (!profile_->IsOffTheRecord()) if (!profile_->IsOffTheRecord()) {
model_->SetVisibleIconCount(model_->GetVisibleIconCount() - 1); int icon_count = model_->GetVisibleIconCount();
// Since this happens when an icon moves from the main bar to overflow, we
// can't possibly have had no visible icons on the main bar.
DCHECK_NE(0, icon_count);
if (icon_count == -1)
icon_count = browser_action_views_.size();
model_->SetVisibleIconCount(icon_count - 1);
}
Animate(gfx::Tween::EASE_OUT, Animate(gfx::Tween::EASE_OUT,
VisibleBrowserActionsAfterAnimation() - 1); VisibleBrowserActionsAfterAnimation() - 1);
} }
...@@ -322,24 +329,23 @@ void BrowserActionsContainer::RemoveObserver( ...@@ -322,24 +329,23 @@ void BrowserActionsContainer::RemoveObserver(
} }
gfx::Size BrowserActionsContainer::GetPreferredSize() const { gfx::Size BrowserActionsContainer::GetPreferredSize() const {
// Note: We can't use GetIconCount() for the main bar, since we may also
// have to include items that are in the chevron's overflow.
size_t icon_count =
in_overflow_mode() ? GetIconCount() : browser_action_views_.size();
// If there are no actions to show, or we are in overflow mode and the main
// container is already showing them all, then no further work is required.
if (icon_count == 0)
return gfx::Size();
if (in_overflow_mode()) { if (in_overflow_mode()) {
// When in overflow, y is multiline, so the pixel count is IconHeight() int icon_count = GetIconCount();
// times the number of rows needed. // In overflow, we always have a preferred size of a full row (even if we
// don't use it), and always of at least one row. The parent may decide to
// show us even when empty, e.g. as a drag target for dragging in icons from
// the main container.
int row_count =
((std::max(0, icon_count - 1)) / icons_per_overflow_menu_row_) + 1;
return gfx::Size( return gfx::Size(
IconCountToWidth(icons_per_overflow_menu_row_, false), IconCountToWidth(icons_per_overflow_menu_row_, false),
(((icon_count - 1) / icons_per_overflow_menu_row_) + 1) * IconHeight()); row_count * IconHeight());
} }
// If there are no actions to show, then don't show the container at all.
if (browser_action_views_.empty())
return gfx::Size();
// We calculate the size of the view by taking the current width and // We calculate the size of the view by taking the current width and
// subtracting resize_amount_ (the latter represents how far the user is // subtracting resize_amount_ (the latter represents how far the user is
// resizing the view or, if animating the snapping, how far to animate it). // resizing the view or, if animating the snapping, how far to animate it).
...@@ -448,24 +454,25 @@ int BrowserActionsContainer::OnDragUpdated( ...@@ -448,24 +454,25 @@ int BrowserActionsContainer::OnDragUpdated(
} }
StopShowFolderDropMenuTimer(); StopShowFolderDropMenuTimer();
size_t row_index = 0;
size_t before_icon_in_row = 0;
// If there are no visible browser actions (such as when dragging an icon to
// an empty overflow/main container), then 0, 0 for row, column is correct.
if (VisibleBrowserActions() != 0) {
// Figure out where to display the indicator. This is a complex calculation: // Figure out where to display the indicator. This is a complex calculation:
// First, we figure out how much space is to the left of the icon area, so we // First, we subtract out the padding to the left of the icon area, which is
// can calculate the true offset into the icon area. The easiest way to do // ToolbarView::kStandardSpacing. If we're right-to-left, we also mirror the
// this is to just find where the first icon starts. // event.x() so that our calculations are consistent with left-to-right.
int width_before_icons =
browser_action_views_[GetFirstVisibleIconIndex()]->x();
// If we're right-to-left, we flip the mirror the event.x() so that our
// calculations are consistent with left-to-right.
int offset_into_icon_area = int offset_into_icon_area =
GetMirroredXInView(event.x()) - width_before_icons; GetMirroredXInView(event.x()) - ToolbarView::kStandardSpacing;
// Next, figure out what row we're on. This only matters for overflow mode, // Next, figure out what row we're on. This only matters for overflow mode,
// but the calculation is the same for both. // but the calculation is the same for both.
size_t row_index = event.y() / IconHeight(); row_index = event.y() / IconHeight();
// Sanity check - we should never be on a different row in the main container. // Sanity check - we should never be on a different row in the main
// container.
DCHECK(in_overflow_mode() || row_index == 0); DCHECK(in_overflow_mode() || row_index == 0);
// Next, we determine which icon to place the indicator in front of. We want // Next, we determine which icon to place the indicator in front of. We want
...@@ -489,7 +496,8 @@ int BrowserActionsContainer::OnDragUpdated( ...@@ -489,7 +496,8 @@ int BrowserActionsContainer::OnDragUpdated(
// plus one spacing unit, then it becomes very easy to calculate how many // plus one spacing unit, then it becomes very easy to calculate how many
// divider points we've passed, because they're the multiples of "one icon // divider points we've passed, because they're the multiples of "one icon
// plus padding". // plus padding".
int before_icon_unclamped = (offset_into_icon_area + (IconWidth(false) / 2) + int before_icon_unclamped =
(offset_into_icon_area + (IconWidth(false) / 2) +
kItemSpacing) / IconWidth(true); kItemSpacing) / IconWidth(true);
// We need to figure out how many icons are visible on the relevant row. // We need to figure out how many icons are visible on the relevant row.
...@@ -506,12 +514,13 @@ int BrowserActionsContainer::OnDragUpdated( ...@@ -506,12 +514,13 @@ int BrowserActionsContainer::OnDragUpdated(
icons_per_overflow_menu_row_; icons_per_overflow_menu_row_;
} }
// Because the user can drag outside the container bounds, we need to clamp to // Because the user can drag outside the container bounds, we need to clamp
// the valid range. Note that the maximum allowable value is (num icons), not // to the valid range. Note that the maximum allowable value is (num icons),
// (num icons - 1), because we represent the indicator being past the last // not (num icons - 1), because we represent the indicator being past the
// icon as being "before the (last + 1) icon". // last icon as being "before the (last + 1) icon".
size_t before_icon_in_row = before_icon_in_row =
std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row); std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row);
}
if (!drop_position_.get() || if (!drop_position_.get() ||
!(drop_position_->row == row_index && !(drop_position_->row == row_index &&
...@@ -543,7 +552,7 @@ int BrowserActionsContainer::OnPerformDrop( ...@@ -543,7 +552,7 @@ int BrowserActionsContainer::OnPerformDrop(
size_t i = drop_position_->row * icons_per_overflow_menu_row_ + size_t i = drop_position_->row * icons_per_overflow_menu_row_ +
drop_position_->icon_in_row; drop_position_->icon_in_row;
if (in_overflow_mode()) if (in_overflow_mode())
i += GetFirstVisibleIconIndex(); i += main_container_->VisibleBrowserActionsAfterAnimation();
// |i| now points to the item to the right of the drop indicator*, which is // |i| now points to the item to the right of the drop indicator*, which is
// correct when dragging an icon to the left. When dragging to the right, // correct when dragging an icon to the left. When dragging to the right,
// however, we want the icon being dragged to get the index of the item to // however, we want the icon being dragged to get the index of the item to
...@@ -702,11 +711,6 @@ extensions::ActiveTabPermissionGranter* ...@@ -702,11 +711,6 @@ extensions::ActiveTabPermissionGranter*
active_tab_permission_granter(); active_tab_permission_granter();
} }
size_t BrowserActionsContainer::GetFirstVisibleIconIndex() const {
return in_overflow_mode() ?
main_container_->VisibleBrowserActionsAfterAnimation() : 0;
}
ExtensionPopup* BrowserActionsContainer::TestGetPopup() { ExtensionPopup* BrowserActionsContainer::TestGetPopup() {
return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL; return popup_owner_ ? popup_owner_->view_controller()->popup() : NULL;
} }
...@@ -731,7 +735,7 @@ void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) { ...@@ -731,7 +735,7 @@ void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) {
// Convert back to a pixel offset into the container. First find the X // Convert back to a pixel offset into the container. First find the X
// coordinate of the drop icon. // coordinate of the drop icon.
int drop_icon_x = browser_action_views_[GetFirstVisibleIconIndex()]->x() + int drop_icon_x = ToolbarView::kStandardSpacing +
(drop_position_->icon_in_row * IconWidth(true)); (drop_position_->icon_in_row * IconWidth(true));
// Next, find the space before the drop icon. This will either be // Next, find the space before the drop icon. This will either be
// kItemSpacing or ToolbarView::kStandardSpacing, depending on whether this // kItemSpacing or ToolbarView::kStandardSpacing, depending on whether this
......
...@@ -349,9 +349,6 @@ class BrowserActionsContainer ...@@ -349,9 +349,6 @@ class BrowserActionsContainer
// for incognito. // for incognito.
bool ShouldDisplayBrowserAction(const extensions::Extension* extension) const; bool ShouldDisplayBrowserAction(const extensions::Extension* extension) const;
// Return the index of the first visible icon.
size_t GetFirstVisibleIconIndex() const;
// Returns the number of icons that this container should draw. This differs // Returns the number of icons that this container should draw. This differs
// from the model's GetVisibleIconCount if this container is for the overflow. // from the model's GetVisibleIconCount if this container is for the overflow.
size_t GetIconCount() const; size_t GetIconCount() const;
......
...@@ -44,6 +44,9 @@ ExtensionToolbarMenuView::ExtensionToolbarMenuView(Browser* browser, ...@@ -44,6 +44,9 @@ ExtensionToolbarMenuView::ExtensionToolbarMenuView(Browser* browser,
main); main);
container_->Init(); container_->Init();
AddChildView(container_); AddChildView(container_);
// We Layout() the container here so that we know the number of actions
// that will be visible in ShouldShow().
container_->Layout();
// If we were opened for a drop command, we have to wait for the drop to // If we were opened for a drop command, we have to wait for the drop to
// finish so we can close the wrench menu. // finish so we can close the wrench menu.
...@@ -56,6 +59,11 @@ ExtensionToolbarMenuView::ExtensionToolbarMenuView(Browser* browser, ...@@ -56,6 +59,11 @@ ExtensionToolbarMenuView::ExtensionToolbarMenuView(Browser* browser,
ExtensionToolbarMenuView::~ExtensionToolbarMenuView() { ExtensionToolbarMenuView::~ExtensionToolbarMenuView() {
} }
bool ExtensionToolbarMenuView::ShouldShow() {
return wrench_menu_->for_drop() ||
container_->VisibleBrowserActionsAfterAnimation();
}
gfx::Size ExtensionToolbarMenuView::GetPreferredSize() const { gfx::Size ExtensionToolbarMenuView::GetPreferredSize() const {
return container_->GetPreferredSize(); return container_->GetPreferredSize();
} }
......
...@@ -25,6 +25,11 @@ class ExtensionToolbarMenuView : public views::View, ...@@ -25,6 +25,11 @@ class ExtensionToolbarMenuView : public views::View,
ExtensionToolbarMenuView(Browser* browser, WrenchMenu* wrench_menu); ExtensionToolbarMenuView(Browser* browser, WrenchMenu* wrench_menu);
virtual ~ExtensionToolbarMenuView(); virtual ~ExtensionToolbarMenuView();
// Returns whether the wrench menu should show this view. This is true when
// either |container_| has icons to display or the menu was opened for a drag-
// and-drop operation.
bool ShouldShow();
// views::View: // views::View:
virtual gfx::Size GetPreferredSize() const OVERRIDE; virtual gfx::Size GetPreferredSize() const OVERRIDE;
virtual int GetHeightForWidth(int width) const OVERRIDE; virtual int GetHeightForWidth(int width) const OVERRIDE;
......
...@@ -1137,7 +1137,7 @@ void WrenchMenu::PopulateMenu(MenuItemView* parent, ...@@ -1137,7 +1137,7 @@ void WrenchMenu::PopulateMenu(MenuItemView* parent,
case IDC_EXTENSIONS_OVERFLOW_MENU: { case IDC_EXTENSIONS_OVERFLOW_MENU: {
scoped_ptr<ExtensionToolbarMenuView> extension_toolbar( scoped_ptr<ExtensionToolbarMenuView> extension_toolbar(
new ExtensionToolbarMenuView(browser_, this)); new ExtensionToolbarMenuView(browser_, this));
if (extension_toolbar->GetPreferredSize().height() > 0) if (extension_toolbar->ShouldShow())
item->AddChildView(extension_toolbar.release()); item->AddChildView(extension_toolbar.release());
else else
item->SetVisible(false); item->SetVisible(false);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment