1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_ACTIONS_BAR_H_
6 #define CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_ACTIONS_BAR_H_
8 #include "base/callback.h"
9 #include "base/macros.h"
10 #include "base/memory/scoped_vector.h"
11 #include "base/memory/weak_ptr.h"
12 #include "base/scoped_observer.h"
13 #include "chrome/browser/ui/toolbar/toolbar_actions_bar_bubble_delegate.h"
14 #include "chrome/browser/ui/toolbar/toolbar_actions_model.h"
15 #include "ui/gfx/animation/tween.h"
16 #include "ui/gfx/geometry/size.h"
18 namespace extensions
{
20 class ExtensionMessageBubbleController
;
23 namespace user_prefs
{
24 class PrefRegistrySyncable
;
27 class ToolbarActionsBarDelegate
;
28 class ToolbarActionViewController
;
30 // A platform-independent version of the container for toolbar actions,
31 // including extension actions and component actions.
33 // This is a per-window instance, unlike the ToolbarActionsModel, which is
34 // per-profile. In most cases, ordering and visible count will be identical
35 // between the base model and the window; however, there are exceptions in the
36 // case of very small windows (which may be too narrow to display all the
37 // icons), or windows in which an action is "popped out", resulting in a
40 // This can come in two flavors, main and "overflow". The main bar is visible
41 // next to the omnibox, and the overflow bar is visible inside the chrome
42 // (fka wrench) menu. The main bar can have only a single row of icons with
43 // flexible width, whereas the overflow bar has multiple rows of icons with a
44 // fixed width (the width of the menu).
45 class ToolbarActionsBar
: public ToolbarActionsModel::Observer
{
47 // A struct to contain the platform settings.
48 struct PlatformSettings
{
49 explicit PlatformSettings(bool in_overflow_mode
);
51 // The padding that comes before the first icon in the container.
53 // The padding following the final icon in the container.
55 // The spacing between each of the icons.
57 // The number of icons per row in the overflow menu.
58 int icons_per_overflow_menu_row
;
59 // Whether or not the overflow menu is displayed as a chevron (this is being
64 // The type of drag that occurred in a drag-and-drop operation.
66 // The icon was dragged to the same container it started in.
68 // The icon was dragged from the main container to the overflow.
70 // The icon was dragged from the overflow container to the main.
80 ToolbarActionsBar(ToolbarActionsBarDelegate
* delegate
,
82 ToolbarActionsBar
* main_bar
);
83 ~ToolbarActionsBar() override
;
85 // Returns the width of a browser action icon, optionally including the
87 static int IconWidth(bool include_padding
);
89 // Returns the height of a browser action icon.
90 static int IconHeight();
92 // Registers profile preferences.
93 static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable
* registry
);
95 // Returns the preferred size for the toolbar; this does *not* reflect any
96 // animations that may be running.
97 gfx::Size
GetPreferredSize() const;
99 // Returns the [minimum|maximum] possible width for the toolbar.
100 int GetMinimumWidth() const;
101 int GetMaximumWidth() const;
103 // Returns the width for the given number of icons.
104 int IconCountToWidth(int icons
) const;
106 // Returns the number of icons that can fit within the given width.
107 size_t WidthToIconCount(int width
) const;
109 // Returns the number of icons that should be displayed if space allows.
110 size_t GetIconCount() const;
112 // Returns the starting index (inclusive) for displayable icons.
113 size_t GetStartIndexInBounds() const;
115 // Returns the ending index (exclusive) for displayable icons.
116 size_t GetEndIndexInBounds() const;
118 // Returns true if an overflow container is necessary to display any other
119 // icons for this particular window. This is different than
120 // ToolbarActionsModel::all_icons_visible() because the ToolbarActionsBar
121 // is limited to a single window, whereas the model is the underlying model
122 // of *all* windows, independent of size. As such, the model is identical
123 // between a very wide window and a very narrow window, and the user's stored
124 // preference may be to have all icons visible. But if the very narrow window
125 // doesn't have the width to display all those actions, some will need to be
126 // implicitly pushed to the overflow, even though the user's global preference
128 bool NeedsOverflow() const;
130 // Returns the frame (bounds) that the specified index should have, taking
131 // into account if this is the main or overflow bar. If this is the overflow
132 // bar and the index should not be displayed (i.e., it is shown on the main
133 // bar), returns an empty rect.
134 gfx::Rect
GetFrameForIndex(size_t index
) const;
136 // Returns the actions in the proper order; this may differ from the
137 // underlying order in the case of actions being popped out to show a popup.
138 std::vector
<ToolbarActionViewController
*> GetActions() const;
140 // Creates the toolbar actions.
141 void CreateActions();
143 // Deletes all toolbar actions.
144 void DeleteActions();
146 // Updates all the toolbar actions.
149 // Shows the popup for the action with |id|, returning true if a popup is
150 // shown. If |grant_active_tab| is true, then active tab permissions should
151 // be given to the action (only do this if this is through a user action).
152 bool ShowToolbarActionPopup(const std::string
& id
, bool grant_active_tab
);
154 // Sets the width for the overflow menu rows.
155 void SetOverflowRowWidth(int width
);
157 // Notifies the ToolbarActionsBar that a user completed a resize gesture, and
158 // the new width is |width|.
159 void OnResizeComplete(int width
);
161 // Notifies the ToolbarActionsBar that the user has started a drag-and-drop
163 void OnDragStarted();
165 // Notifies the ToolbarActionsBar that a drag-and-drop sequence ended. This
166 // may not coincide with OnDragDrop(), since the view may be dropped somewhere
170 // Notifies the ToolbarActionsBar that a user completed a drag and drop event,
171 // and dragged the view from |dragged_index| to |dropped_index|.
172 // |drag_type| indicates whether or not the icon was dragged between the
173 // overflow and main containers.
174 // The main container should handle all drag/drop notifications.
175 void OnDragDrop(int dragged_index
,
179 // Notifies the ToolbarActionsBar that the delegate finished animating.
180 void OnAnimationEnded();
182 // Returns true if the given |action| is visible on the main toolbar.
183 bool IsActionVisibleOnMainBar(const ToolbarActionViewController
* action
)
186 // Pops out a given |action|, ensuring it is visible.
187 // |closure| will be called once any animation is complete.
188 void PopOutAction(ToolbarActionViewController
* action
,
189 const base::Closure
& closure
);
191 // Undoes the current "pop out"; i.e., moves the popped out action back into
195 // Sets the active popup owner to be |popup_owner|.
196 void SetPopupOwner(ToolbarActionViewController
* popup_owner
);
198 // Hides the actively showing popup, if any.
199 void HideActivePopup();
201 // Returns the main (i.e., not overflow) controller for the given action.
202 ToolbarActionViewController
* GetMainControllerForAction(
203 ToolbarActionViewController
* action
);
205 // Returns the underlying toolbar actions, but does not order them. Primarily
206 // for use in testing.
207 const std::vector
<ToolbarActionViewController
*>& toolbar_actions_unordered()
209 return toolbar_actions_
.get();
211 bool enabled() const { return model_
!= nullptr; }
212 bool suppress_layout() const { return suppress_layout_
; }
213 bool suppress_animation() const {
214 return suppress_animation_
|| disable_animations_for_testing_
;
216 bool is_highlighting() const { return model_
&& model_
->is_highlighting(); }
217 ToolbarActionsModel::HighlightType
highlight_type() const {
218 return model_
? model_
->highlight_type()
219 : ToolbarActionsModel::HIGHLIGHT_NONE
;
221 const PlatformSettings
& platform_settings() const {
222 return platform_settings_
;
224 ToolbarActionViewController
* popup_owner() { return popup_owner_
; }
225 ToolbarActionViewController
* popped_out_action() {
226 return popped_out_action_
;
228 bool in_overflow_mode() const { return main_bar_
!= nullptr; }
230 ToolbarActionsBarDelegate
* delegate_for_test() { return delegate_
; }
232 // During testing we can disable animations by setting this flag to true,
233 // so that the bar resizes instantly, instead of having to poll it while it
234 // animates to open/closed status.
235 static bool disable_animations_for_testing_
;
238 using ToolbarActions
= ScopedVector
<ToolbarActionViewController
>;
240 // ToolbarActionsModel::Observer:
241 void OnToolbarActionAdded(const std::string
& action_id
, int index
) override
;
242 void OnToolbarActionRemoved(const std::string
& action_id
) override
;
243 void OnToolbarActionMoved(const std::string
& action_id
, int index
) override
;
244 void OnToolbarActionUpdated(const std::string
& action_id
) override
;
245 void OnToolbarVisibleCountChanged() override
;
246 void OnToolbarHighlightModeChanged(bool is_highlighting
) override
;
247 void OnToolbarModelInitialized() override
;
249 // Resizes the delegate (if necessary) to the preferred size using the given
250 // |tween_type| and optionally suppressing the chevron.
251 void ResizeDelegate(gfx::Tween::Type tween_type
, bool suppress_chevron
);
253 // Returns the action for the given |id|, if one exists.
254 ToolbarActionViewController
* GetActionForId(const std::string
& action_id
);
256 // Returns the current web contents.
257 content::WebContents
* GetCurrentWebContents();
259 // Reorders the toolbar actions to reflect the model and, optionally, to
260 // "pop out" any overflowed actions that want to run (depending on the
261 // value of |pop_out_actions_to_run|.
262 void ReorderActions();
264 // Shows an extension message bubble, if any should be shown.
265 void MaybeShowExtensionBubble(
266 scoped_ptr
<extensions::ExtensionMessageBubbleController
> controller
);
268 // The delegate for this object (in a real build, this is the view).
269 ToolbarActionsBarDelegate
* delegate_
;
271 // The associated browser.
274 // The observed toolbar model.
275 ToolbarActionsModel
* model_
;
277 // The controller for the main toolbar actions bar. This will be null if this
279 ToolbarActionsBar
* main_bar_
;
281 // Platform-specific settings for dimensions and the overflow chevron.
282 PlatformSettings platform_settings_
;
284 // The toolbar actions.
285 ToolbarActions toolbar_actions_
;
287 // The action that triggered the current popup (just a reference to an action
288 // from toolbar_actions_).
289 ToolbarActionViewController
* popup_owner_
;
291 ScopedObserver
<ToolbarActionsModel
, ToolbarActionsModel::Observer
>
294 // True if we should suppress layout, such as when we are creating or
295 // adjusting a lot of actions at once.
296 bool suppress_layout_
;
298 // True if we should suppress animation; we do this when first creating the
299 // toolbar, and also when switching tabs changes the state of the icons.
300 bool suppress_animation_
;
302 // If this is true, actions that want to run (e.g., an extension's page
303 // action) will pop out of overflow to draw more attention.
304 // See also TabOrderHelper in the .cc file.
305 static bool pop_out_actions_to_run_
;
307 // True if we have checked to see if there is an extension bubble that should
308 // be displayed, and, if there is, shown that bubble.
309 bool checked_extension_bubble_
;
311 // Whether or not the user is in the middle of a drag-and-drop operation.
312 bool is_drag_in_progress_
;
314 // The action, if any, which is currently "popped out" of the overflow in
315 // order to show a popup.
316 ToolbarActionViewController
* popped_out_action_
;
318 // The task to alert the |popped_out_action_| that animation has finished, and
319 // it is fully popped out.
320 base::Closure popped_out_closure_
;
322 // The controller of the bubble to show once animation finishes, if any.
323 scoped_ptr
<extensions::ExtensionMessageBubbleController
>
324 pending_extension_bubble_controller_
;
326 base::WeakPtrFactory
<ToolbarActionsBar
> weak_ptr_factory_
;
328 DISALLOW_COPY_AND_ASSIGN(ToolbarActionsBar
);
331 #endif // CHROME_BROWSER_UI_TOOLBAR_TOOLBAR_ACTIONS_BAR_H_