1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344
|
// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_H_
#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_H_
#include "base/observer_list.h"
#include "chrome/browser/extensions/extension_keybinding_registry.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar.h"
#include "chrome/browser/ui/toolbar/toolbar_actions_bar_delegate.h"
#include "chrome/browser/ui/views/extensions/extension_keybinding_registry_views.h"
#include "chrome/browser/ui/views/toolbar/chevron_menu_button.h"
#include "chrome/browser/ui/views/toolbar/toolbar_action_view.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/gfx/animation/slide_animation.h"
#include "ui/gfx/animation/tween.h"
#include "ui/views/controls/resize_area_delegate.h"
#include "ui/views/drag_controller.h"
#include "ui/views/view.h"
class BrowserActionsContainerObserver;
class ExtensionPopup;
namespace extensions {
class ActiveTabPermissionGranter;
class Command;
class Extension;
}
namespace views {
class ResizeArea;
}
// The BrowserActionsContainer is a container view, responsible for drawing the
// toolbar action icons (including extension icons and icons for component
// toolbar actions). It comes intwo flavors, a main container (when residing on
// the toolbar) and an overflow container (that resides in the main application
// menu, aka the Chrome menu).
//
// When in 'main' mode, the container supports the full functionality of a
// BrowserActionContainer, but in 'overflow' mode the container is effectively
// just an overflow for the 'main' toolbar (shows only the icons that the main
// toolbar does not) and as such does not have an overflow itself. The overflow
// container also does not support resizing. Since the main container only shows
// icons in the Chrome toolbar, it is limited to a single row of icons. The
// overflow container, however, is allowed to display icons in multiple rows.
//
// The main container is placed flush against the omnibox and hot dog menu,
// whereas the overflow container is placed within the hot dog menu. The
// layout is similar to this:
// rI_I_IcCs
// Where the letters are as follows:
// r: An invisible resize area. This is ToolbarView::kStandardSpacing pixels
// wide and directly adjacent to the omnibox. Only shown for the main
// container.
// I: An icon. This is as wide as the IDR_BROWSER_ACTION image.
// _: kItemSpacing pixels of empty space.
// c: kChevronSpacing pixels of empty space. Only present if C is present.
// C: An optional chevron, as wide as the IDR_BROWSER_ACTIONS_OVERFLOW image,
// and visible only when both of the following statements are true:
// - The container is set to a width smaller than needed to show all icons.
// - There is no other container in 'overflow' mode to handle the
// non-visible icons for this container.
// s: ToolbarView::kStandardSpacing pixels of empty space (before the wrench
// menu).
// The reason the container contains the trailing space "s", rather than having
// it be handled by the parent view, is so that when the chevron is invisible
// and the user starts dragging an icon around, we have the space to draw the
// ultimate drop indicator. (Otherwise, we'd be trying to draw it into the
// padding beyond our right edge, and it wouldn't appear.)
//
// The BrowserActionsContainer in 'main' mode follows a few rules, in terms of
// user experience:
//
// 1) The container can never grow beyond the space needed to show all icons
// (hereby referred to as the max width).
// 2) The container can never shrink below the space needed to show just the
// initial padding and the chevron (ignoring the case where there are no icons
// to show, in which case the container won't be visible anyway).
// 3) The container snaps into place (to the pixel count that fits the visible
// icons) to make sure there is no wasted space at the edges of the container.
// 4) If the user adds or removes icons (read: installs/uninstalls browser
// actions) we grow and shrink the container as needed - but ONLY if the
// container was at max width to begin with.
// 5) If the container is NOT at max width (has an overflow menu), we respect
// that size when adding and removing icons and DON'T grow/shrink the container.
// This means that new icons (which always appear at the far right) will show up
// in the overflow. The install bubble for extensions points to the chevron
// menu in this case.
//
// Resizing the BrowserActionsContainer:
//
// The ResizeArea view sends OnResize messages to the BrowserActionsContainer
// class as the user drags it. This modifies the value for |resize_amount_|.
// That indicates to the container that a resize is in progress and is used to
// calculate the size in GetPreferredSize(), though that function never exceeds
// the defined minimum and maximum size of the container.
//
// When the user releases the mouse (ends the resize), we calculate a target
// size for the container (animation_target_size_), clamp that value to the
// containers min and max and then animate from the *current* position (that the
// user has dragged the view to) to the target size.
//
// Animating the BrowserActionsContainer:
//
// Animations are used when snapping the container to a value that fits all
// visible icons. This can be triggered when the user finishes resizing the
// container or when Browser Actions are added/removed.
//
// We always animate from the current width (container_width_) to the target
// size (animation_target_size_), using |resize_amount| to keep track of the
// animation progress.
//
// NOTE: When adding Browser Actions to a maximum width container (no overflow)
// we make sure to suppress the chevron menu if it wasn't visible. This is
// because we won't have enough space to show the new Browser Action until the
// animation ends and we don't want the chevron to flash into view while we are
// growing the container.
//
////////////////////////////////////////////////////////////////////////////////
class BrowserActionsContainer
: public views::View,
public ToolbarActionsBarDelegate,
public views::ResizeAreaDelegate,
public gfx::AnimationDelegate,
public ToolbarActionView::Delegate,
public extensions::ExtensionKeybindingRegistry::Delegate {
public:
// Constructs a BrowserActionContainer for a particular |browser| object. For
// documentation of |main_container|, see class comments.
BrowserActionsContainer(Browser* browser,
BrowserActionsContainer* main_container);
~BrowserActionsContainer() override;
void Init();
// Get the number of toolbar actions being displayed.
size_t num_toolbar_actions() const { return toolbar_action_views_.size(); }
// Returns the chevron, if any.
views::View* chevron() { return chevron_; }
const views::View* chevron() const { return chevron_; }
// Returns the browser this container is associated with.
Browser* browser() const { return browser_; }
ToolbarActionsBar* toolbar_actions_bar() {
return toolbar_actions_bar_.get();
}
// The class that registers for keyboard shortcuts for extension commands.
extensions::ExtensionKeybindingRegistry* extension_keybinding_registry() {
return extension_keybinding_registry_.get();
}
// Get a particular toolbar action view.
ToolbarActionView* GetToolbarActionViewAt(int index) {
return toolbar_action_views_[index];
}
// Whether we are performing resize animation on the container.
bool animating() const {
return resize_animation_ && resize_animation_->is_animating();
}
// Returns the ID of the action represented by the view at |index|.
const std::string& GetIdAt(size_t index) const;
// Returns the ToolbarActionView* associated with the given |extension|, or
// NULL if none exists.
ToolbarActionView* GetViewForId(const std::string& id);
// Update the views to reflect the state of the toolbar actions.
void RefreshToolbarActionViews();
// Returns how many actions are currently visible. If the intent is to find
// how many are visible once the container finishes animation, see
// VisibleBrowserActionsAfterAnimation() below.
size_t VisibleBrowserActions() const;
// Returns how many actions will be visible once the container finishes
// animating to a new size, or (if not animating) the currently visible icons.
size_t VisibleBrowserActionsAfterAnimation() const;
// Executes |command| registered by |extension|.
void ExecuteExtensionCommand(const extensions::Extension* extension,
const extensions::Command& command);
// Add or remove an observer.
void AddObserver(BrowserActionsContainerObserver* observer);
void RemoveObserver(BrowserActionsContainerObserver* observer);
// Overridden from views::View:
gfx::Size GetPreferredSize() const override;
int GetHeightForWidth(int width) const override;
gfx::Size GetMinimumSize() const override;
void Layout() override;
bool GetDropFormats(
int* formats,
std::set<ui::OSExchangeData::CustomFormat>* custom_formats) override;
bool AreDropTypesRequired() override;
bool CanDrop(const ui::OSExchangeData& data) override;
int OnDragUpdated(const ui::DropTargetEvent& event) override;
void OnDragExited() override;
int OnPerformDrop(const ui::DropTargetEvent& event) override;
void GetAccessibleState(ui::AXViewState* state) override;
// Overridden from views::DragController:
void WriteDragDataForView(View* sender,
const gfx::Point& press_pt,
ui::OSExchangeData* data) override;
int GetDragOperationsForView(View* sender, const gfx::Point& p) override;
bool CanStartDragForView(View* sender,
const gfx::Point& press_pt,
const gfx::Point& p) override;
// Overridden from views::ResizeAreaDelegate:
void OnResize(int resize_amount, bool done_resizing) override;
// Overridden from gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationCanceled(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
// Overridden from ToolbarActionView::Delegate:
content::WebContents* GetCurrentWebContents() override;
bool ShownInsideMenu() const override;
void OnToolbarActionViewDragDone() override;
views::MenuButton* GetOverflowReferenceView() override;
void SetPopupOwner(ToolbarActionView* popup_owner) override;
void HideActivePopup() override;
ToolbarActionView* GetMainViewForAction(ToolbarActionView* view) override;
// ToolbarActionsBarDelegate:
void AddViewForAction(ToolbarActionViewController* action,
size_t index) override;
void RemoveViewForAction(ToolbarActionViewController* action) override;
void RemoveAllViews() override;
void Redraw(bool order_changed) override;
void ResizeAndAnimate(gfx::Tween::Type tween_type,
int target_width,
bool suppress_chevron) override;
void SetChevronVisibility(bool chevron_visible) override;
int GetWidth() const override;
bool IsAnimating() const override;
void StopAnimating() override;
int GetChevronWidth() const override;
bool IsPopupRunning() const override;
void OnOverflowedActionWantsToRunChanged(
bool overflowed_action_wants_to_run) override;
// Overridden from extension::ExtensionKeybindingRegistry::Delegate:
extensions::ActiveTabPermissionGranter* GetActiveTabPermissionGranter()
override;
// Retrieve the current popup. This should only be used by unit tests.
gfx::NativeView TestGetPopup();
protected:
// Overridden from views::View:
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
void OnPaint(gfx::Canvas* canvas) override;
void OnThemeChanged() override;
private:
// A struct representing the position at which an action will be dropped.
struct DropPosition;
typedef std::vector<ToolbarActionView*> ToolbarActionViews;
void LoadImages();
const ToolbarActionsBar::PlatformSettings& platform_settings() const {
return toolbar_actions_bar_->platform_settings();
}
// Whether this container is in overflow mode (as opposed to in 'main'
// mode). See class comments for details on the difference.
bool in_overflow_mode() const { return main_container_ != NULL; }
// The controlling ToolbarActionsBar, which handles most non-view logic.
scoped_ptr<ToolbarActionsBar> toolbar_actions_bar_;
// The vector of toolbar actions (icons/image buttons for each action).
ToolbarActionViews toolbar_action_views_;
// The Browser object the container is associated with.
Browser* browser_;
// The main container we are serving as overflow for, or NULL if this
// class is the the main container. See class comments for details on
// the difference between main and overflow.
BrowserActionsContainer* main_container_;
// The view that triggered the current popup (just a reference to a view
// from toolbar_action_views_).
ToolbarActionView* popup_owner_;
// The current width of the container.
int container_width_;
// The resize area for the container.
views::ResizeArea* resize_area_;
// The chevron for accessing the overflow items. Can be NULL when in overflow
// mode or if the toolbar is permanently suppressing the chevron menu.
ChevronMenuButton* chevron_;
// The painter used when we are highlighting a subset of extensions.
scoped_ptr<views::Painter> highlight_painter_;
// The animation that happens when the container snaps to place.
scoped_ptr<gfx::SlideAnimation> resize_animation_;
// Don't show the chevron while animating.
bool suppress_chevron_;
// True if the container has been added to the parent view.
bool added_to_view_;
// This is used while the user is resizing (and when the animations are in
// progress) to know how wide the delta is between the current state and what
// we should draw.
int resize_amount_;
// Keeps track of the absolute pixel width the container should have when we
// are done animating.
int animation_target_size_;
// The DropPosition for the current drag-and-drop operation, or NULL if there
// is none.
scoped_ptr<DropPosition> drop_position_;
// The class that registers for keyboard shortcuts for extension commands.
scoped_ptr<ExtensionKeybindingRegistryViews> extension_keybinding_registry_;
ObserverList<BrowserActionsContainerObserver> observers_;
DISALLOW_COPY_AND_ASSIGN(BrowserActionsContainer);
};
#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTIONS_CONTAINER_H_
|