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

Unified Diff: chrome/browser/ui/views/toolbar/browser_actions_container.cc

Issue 399173004: Adjust BrowserActionsContainer drag and drop to work for overflow (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 5 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/toolbar/browser_actions_container.cc
diff --git a/chrome/browser/ui/views/toolbar/browser_actions_container.cc b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
index 57aff05e5cf0437185da07fc29ae4233a606bd5e..8f625fef5d09a3f43265159c8588050021a8b857 100644
--- a/chrome/browser/ui/views/toolbar/browser_actions_container.cc
+++ b/chrome/browser/ui/views/toolbar/browser_actions_container.cc
@@ -102,6 +102,25 @@ class ChevronMenuButton : public views::MenuButton {
// static
bool BrowserActionsContainer::disable_animations_during_testing_ = false;
+struct BrowserActionsContainer::DropPosition {
+ DropPosition(size_t row, size_t icon_in_row);
+ ~DropPosition();
+
+ // The (0-indexed) row into which the action will be dropped.
+ size_t row;
+
+ // The (0-indexed) icon in the row before the action will be dropped.
+ size_t icon_in_row;
+};
+
+BrowserActionsContainer::DropPosition::DropPosition(
+ size_t row, size_t icon_in_row)
+ : row(row), icon_in_row(icon_in_row) {
+}
+
+BrowserActionsContainer::DropPosition::~DropPosition() {
+}
+
////////////////////////////////////////////////////////////////////////////////
// BrowserActionsContainer
@@ -123,7 +142,6 @@ BrowserActionsContainer::BrowserActionsContainer(
suppress_chevron_(false),
resize_amount_(0),
animation_target_size_(0),
- drop_indicator_position_(-1),
task_factory_(this),
show_menu_task_factory_(this) {
set_id(VIEW_ID_BROWSER_ACTION_TOOLBAR);
@@ -359,7 +377,7 @@ void BrowserActionsContainer::Layout() {
BrowserActionView* view = browser_action_views_[i];
size_t index = i - main_container_->VisibleBrowserActionsAfterAnimation();
int row_index = static_cast<int>(index) / kIconsPerMenuRow;
- int x = (index * IconWidth(true)) -
+ int x = kItemSpacing + (index * IconWidth(true)) -
Devlin 2014/07/17 22:26:30 We need this so that we can see the drop indicator
(row_index * IconWidth(true) * kIconsPerMenuRow);
gfx::Rect rect_bounds(
x, IconHeight() * row_index, icon_width, IconHeight());
@@ -407,20 +425,22 @@ int BrowserActionsContainer::OnDragUpdated(
}
StopShowFolderDropMenuTimer();
- // TODO(devlin): This calculation needs to take 'overflow' mode into account
- // once the wrench menu becomes a drag target for browser action icons.
-
// 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
- // can calculate the true offset into the icon area.
- int width_before_icons = ToolbarView::kStandardSpacing;
- if (chevron_ && base::i18n::IsRTL()) {
- width_before_icons +=
- chevron_->GetPreferredSize().width() + kChevronSpacing;
- }
+ // can calculate the true offset into the icon area. The easiest way to do
+ // this is to just find where the first icon starts.
+ int width_before_icons =
+ browser_action_views_[GetFirstVisibleIconIndex()]->x();
Finnur 2014/07/18 10:52:41 Will this work in RTL?
Devlin 2014/07/18 17:58:20 Nope! But it does now. :)
int offset_into_icon_area = event.x() - width_before_icons;
+ // Next, figure out what row we're on. This only matters for overflow mode,
+ // but the calculation is the same for both.
+ int row_index = event.y() / IconHeight();
+
+ // Sanity check - we should never be on a different row in the main container.
+ DCHECK(in_overflow_mode() || row_index == 0);
+
// Next, we determine which icon to place the indicator in front of. We want
// to place the indicator in front of icon n when the cursor is between the
// midpoints of icons (n - 1) and n. To do this we take the offset into the
@@ -445,25 +465,33 @@ int BrowserActionsContainer::OnDragUpdated(
int before_icon_unclamped = (offset_into_icon_area + (IconWidth(false) / 2) +
kItemSpacing) / IconWidth(true);
+ // We need to figure out how many icons are visible on the relevant row.
+ // In the main container, this will just be the visible actions.
+ int visible_icons_on_row = VisibleBrowserActionsAfterAnimation();
+ if (in_overflow_mode()) {
+ // If this is the final row of the overflow, then this is the remainder of
+ // visible icons. Otherwise, it's a full row (kIconsPerRow).
+ visible_icons_on_row =
+ row_index == (visible_icons_on_row / kIconsPerMenuRow) ?
+ visible_icons_on_row % kIconsPerMenuRow :
+ kIconsPerMenuRow;
+ }
+
// Because the user can drag outside the container bounds, we need to clamp to
// the valid range. Note that the maximum allowable value is (num icons), not
// (num icons - 1), because we represent the indicator being past the last
// icon as being "before the (last + 1) icon".
- int before_icon = std::min(std::max(before_icon_unclamped, 0),
- static_cast<int>(VisibleBrowserActions()));
+ int before_icon_in_row =
+ std::min(std::max(before_icon_unclamped, 0), visible_icons_on_row);
Devlin 2014/07/17 22:26:30 These calculations plus using a row/icon_on_row st
- // Now we convert back to a pixel offset into the container. We want to place
- // the center of the drop indicator at the midpoint of the space before our
- // chosen icon.
- SetDropIndicator(width_before_icons + (before_icon * IconWidth(true)) -
- (kItemSpacing / 2));
+ SetDropPosition(row_index, before_icon_in_row);
return ui::DragDropTypes::DRAG_MOVE;
}
void BrowserActionsContainer::OnDragExited() {
StopShowFolderDropMenuTimer();
- drop_indicator_position_ = -1;
+ ResetDropPosition();
SchedulePaint();
}
@@ -478,18 +506,10 @@ int BrowserActionsContainer::OnPerformDrop(
data.id());
DCHECK(model_);
- size_t i = 0;
- for (; i < browser_action_views_.size(); ++i) {
- int view_x = browser_action_views_[i]->GetMirroredBounds().x();
- if (!browser_action_views_[i]->visible() ||
- (base::i18n::IsRTL() ? (view_x < drop_indicator_position_) :
- (view_x >= drop_indicator_position_))) {
- // We have reached the end of the visible icons or found one that has a
- // higher x position than the drop point.
- break;
- }
- }
-
+ size_t i =
+ drop_position_->row * kIconsPerMenuRow + drop_position_->icon_in_row;
+ if (in_overflow_mode())
+ i += GetFirstVisibleIconIndex();
// |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,
// however, we want the icon being dragged to get the index of the item to
@@ -690,6 +710,10 @@ bool BrowserActionsContainer::ShowPopup(const extensions::Extension* extension,
return false;
}
+size_t BrowserActionsContainer::GetFirstVisibleIconIndex() const {
+ return in_overflow_mode() ? model_->GetVisibleIconCount() : 0;
+}
+
void BrowserActionsContainer::HidePopup() {
// Remove this as an observer and clear |popup_| and |popup_button_| here,
// since we might change them before OnWidgetDestroying() gets called.
@@ -727,14 +751,32 @@ void BrowserActionsContainer::OnPaint(gfx::Canvas* canvas) {
// TODO(sky/glen): Instead of using a drop indicator, animate the icons while
// dragging (like we do for tab dragging).
- if (drop_indicator_position_ > -1) {
+ if (drop_position_.get()) {
// The two-pixel width drop indicator.
static const int kDropIndicatorWidth = 2;
- gfx::Rect indicator_bounds(
- drop_indicator_position_ - (kDropIndicatorWidth / 2),
- 0,
- kDropIndicatorWidth,
- height());
+
+ // Convert back to a pixel offset into the container. We want to place
+ // the center of the drop indicator at the midpoint of the space before our
+ // chosen icon.
Finnur 2014/07/18 10:52:41 Nit: "Chosen icon" is a bit weird here, because yo
Devlin 2014/07/18 17:58:20 Done.
+ // This is:
+ // The width before the first icon, plus
+ // The width of all icons before the target icon in the row, minus
+ // Half the spacing between the target icon and the previous icon, minus
+ // Half the width of the drop indicator, so it's centered.
+ int drop_indicator_x =
+ browser_action_views_[GetFirstVisibleIconIndex()]->x() +
+ drop_position_->icon_in_row * IconWidth(true) -
+ kItemSpacing / 2 -
+ kDropIndicatorWidth / 2;
+
+ // The y is simply the start of the row (which for the main container is
+ // always 0).
+ int drop_indicator_y = IconHeight() * drop_position_->row;
+
+ gfx::Rect indicator_bounds(drop_indicator_x,
+ drop_indicator_y,
+ kDropIndicatorWidth,
+ IconHeight());
// Color of the drop indicator.
static const SkColor kDropIndicatorColor = SK_ColorBLACK;
@@ -945,7 +987,7 @@ void BrowserActionsContainer::StartShowFolderDropMenuTimer() {
void BrowserActionsContainer::ShowDropFolder() {
DCHECK(!overflow_menu_);
- SetDropIndicator(-1);
+ ResetDropPosition();
overflow_menu_ =
new BrowserActionOverflowMenuController(this,
browser_,
@@ -957,13 +999,19 @@ void BrowserActionsContainer::ShowDropFolder() {
overflow_menu_->RunMenu(GetWidget());
}
-void BrowserActionsContainer::SetDropIndicator(int x_pos) {
- if (drop_indicator_position_ != x_pos) {
- drop_indicator_position_ = x_pos;
+void BrowserActionsContainer::SetDropPosition(size_t row, size_t icon_in_row) {
+ if (!drop_position_.get() ||
+ !(drop_position_->row == row &&
+ drop_position_->icon_in_row == icon_in_row)) {
+ drop_position_.reset(new DropPosition(row, icon_in_row));
SchedulePaint();
}
}
+void BrowserActionsContainer::ResetDropPosition() {
+ drop_position_.reset();
+}
+
int BrowserActionsContainer::IconCountToWidth(int icons,
bool display_chevron) const {
if (icons < 0)

Powered by Google App Engine
This is Rietveld 408576698