Index: chrome/browser/ui/toolbar/toolbar_actions_bar.cc |
diff --git a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc |
index 619d07d15c8a2aee6e5da2c7100a2c7ebdbb401b..0cfd43e49780d1bbb88aa282ecdd6a1287a94e15 100644 |
--- a/chrome/browser/ui/toolbar/toolbar_actions_bar.cc |
+++ b/chrome/browser/ui/toolbar/toolbar_actions_bar.cc |
@@ -125,6 +125,7 @@ ToolbarActionsBar::ToolbarActionsBar(ToolbarActionsBarDelegate* delegate, |
suppress_animation_(true), |
overflowed_action_wants_to_run_(false), |
checked_extension_bubble_(false), |
+ popped_out_action_(nullptr), |
weak_ptr_factory_(this) { |
if (model_) // |model_| can be null in unittests. |
model_observer_.Add(model_); |
@@ -228,9 +229,15 @@ size_t ToolbarActionsBar::GetIconCount() const { |
if (!model_) |
return 0u; |
+ // We purposefully do not account for any "popped out" actions in overflow |
+ // mode. This is because the popup cannot be showing while the overflow menu |
+ // is open, so there's no concern there. Also, if the user has a popped out |
+ // action, and immediately opens the overflow menu, we *want* the action there |
+ // (since it will close the popup, but do so asynchronously, and we don't |
+ // want to "slide" the action back in. |
size_t visible_icons = in_overflow_mode() ? |
- toolbar_actions_.size() - main_bar_->GetIconCount() : |
- model_->visible_icon_count(); |
+ toolbar_actions_.size() - model_->visible_icon_count() : |
+ model_->visible_icon_count() + (popped_out_action_ ? 1 : 0); |
#if DCHECK_IS_ON() |
// Good time for some sanity checks: We should never try to display more |
@@ -259,6 +266,29 @@ size_t ToolbarActionsBar::GetIconCount() const { |
return visible_icons; |
} |
+std::vector<ToolbarActionViewController*> |
+ToolbarActionsBar::GetActions() const { |
+ std::vector<ToolbarActionViewController*> actions = toolbar_actions_.get(); |
+ |
+ // If there is an action that should be popped out, and it's not visible by |
+ // default, make it the final action in the list. |
+ if (popped_out_action_) { |
+ size_t index = |
+ std::find(actions.begin(), actions.end(), popped_out_action_) - |
+ actions.begin(); |
+ DCHECK_NE(actions.size(), index); |
+ size_t visible = GetIconCount(); |
+ if (index >= visible) { |
+ size_t rindex = actions.size() - index - 1; |
+ std::rotate(actions.rbegin() + rindex, |
+ actions.rbegin() + rindex + 1, |
+ actions.rend() - visible + 1); |
+ } |
+ } |
+ |
+ return actions; |
+} |
+ |
void ToolbarActionsBar::CreateActions() { |
DCHECK(toolbar_actions_.empty()); |
// We wait for the extension system to be initialized before we add any |
@@ -394,6 +424,53 @@ void ToolbarActionsBar::OnDragDrop(int dragged_index, |
model_->SetVisibleIconCount(model_->visible_icon_count() + delta); |
} |
+void ToolbarActionsBar::OnAnimationEnded() { |
+ // Check if we were waiting for animation to finish to run a popup. |
+ if (!popped_out_closure_.is_null()) { |
+ popped_out_closure_.Run(); |
+ popped_out_closure_.Reset(); |
+ } |
+} |
+ |
+bool ToolbarActionsBar::IsActionVisible( |
+ const ToolbarActionViewController* action) const { |
+ size_t index = std::find(toolbar_actions_.begin(), |
+ toolbar_actions_.end(), |
+ action) - toolbar_actions_.begin(); |
+ return index < GetIconCount() || action == popped_out_action_; |
+} |
+ |
+void ToolbarActionsBar::PopOutAction(ToolbarActionViewController* controller, |
+ const base::Closure& closure) { |
+ DCHECK(!popped_out_action_) << "Only one action can be popped out at a time!"; |
+ bool needs_redraw = !IsActionVisible(controller); |
+ popped_out_action_ = controller; |
+ if (needs_redraw) { |
+ // We suppress animation for this draw, because we need the action to get |
+ // into position immediately, since it's about to show its popup. |
+ base::AutoReset<bool> layout_resetter(&suppress_animation_, false); |
+ delegate_->Redraw(true); |
+ } |
+ |
+ ResizeDelegate(gfx::Tween::LINEAR, false); |
+ if (!delegate_->IsAnimating()) { |
+ // Don't call the closure re-entrantly. |
+ base::MessageLoop::current()->PostTask(FROM_HERE, closure); |
+ } else { |
+ popped_out_closure_ = closure; |
+ } |
+} |
+ |
+void ToolbarActionsBar::UndoPopOut() { |
+ DCHECK(popped_out_action_); |
+ ToolbarActionViewController* controller = popped_out_action_; |
+ popped_out_action_ = nullptr; |
+ popped_out_closure_.Reset(); |
+ if (!IsActionVisible(controller)) |
+ delegate_->Redraw(true); |
+ ResizeDelegate(gfx::Tween::LINEAR, false); |
+} |
+ |
void ToolbarActionsBar::SetPopupOwner( |
ToolbarActionViewController* popup_owner) { |
// We should never be setting a popup owner when one already exists, and |