browser_action_view.h revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright 2013 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. 4 5#ifndef CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_ 6#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_ 7 8#include <string> 9 10#include "chrome/browser/extensions/extension_action_icon_factory.h" 11#include "chrome/browser/extensions/extension_context_menu_model.h" 12#include "content/public/browser/notification_observer.h" 13#include "content/public/browser/notification_registrar.h" 14#include "ui/views/context_menu_controller.h" 15#include "ui/views/controls/button/menu_button.h" 16#include "ui/views/controls/button/menu_button_listener.h" 17#include "ui/views/drag_controller.h" 18#include "ui/views/view.h" 19 20class Browser; 21class BrowserActionButton; 22class ExtensionAction; 23 24namespace extensions { 25class Extension; 26} 27 28namespace gfx { 29class Image; 30} 31 32namespace views { 33class MenuItemView; 34class MenuRunner; 35} 36 37//////////////////////////////////////////////////////////////////////////////// 38// BrowserActionView 39// A single entry in the browser action container. This contains the actual 40// BrowserActionButton, as well as the logic to paint the badge. 41class BrowserActionView : public views::View { 42 public: 43 // Need DragController here because BrowserActionView could be 44 // dragged/dropped. 45 class Delegate : public views::DragController, 46 public ExtensionContextMenuModel::PopupDelegate { 47 public: 48 // Returns the current tab's ID, or -1 if there is no current tab. 49 virtual int GetCurrentTabId() const = 0; 50 51 // Called when the user clicks on the browser action icon. 52 virtual void OnBrowserActionExecuted(BrowserActionButton* button) = 0; 53 54 // Called when a browser action becomes visible/hidden. 55 virtual void OnBrowserActionVisibilityChanged() = 0; 56 57 // Whether the container for this button is shown inside a menu. 58 virtual bool ShownInsideMenu() const = 0; 59 60 protected: 61 virtual ~Delegate() {} 62 }; 63 64 BrowserActionView(const extensions::Extension* extension, 65 Browser* browser, 66 Delegate* delegate); 67 virtual ~BrowserActionView(); 68 69 BrowserActionButton* button() { return button_; } 70 71 // Gets browser action button icon with the badge. 72 gfx::ImageSkia GetIconWithBadge(); 73 74 // Overridden from views::View: 75 virtual void Layout() OVERRIDE; 76 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 77 virtual gfx::Size GetPreferredSize() const OVERRIDE; 78 79 protected: 80 // Overridden from views::View to paint the badge on top of children. 81 virtual void PaintChildren(gfx::Canvas* canvas, 82 const views::CullSet& cull_set) OVERRIDE; 83 84 private: 85 // The Browser object this view is associated with. 86 Browser* browser_; 87 88 // Usually a container for this view. 89 Delegate* delegate_; 90 91 // The button this view contains. 92 BrowserActionButton* button_; 93 94 // Extension this view associated with. 95 const extensions::Extension* extension_; 96 97 DISALLOW_COPY_AND_ASSIGN(BrowserActionView); 98}; 99 100//////////////////////////////////////////////////////////////////////////////// 101// BrowserActionButton 102 103// The BrowserActionButton is a specialization of the MenuButton class. 104// It acts on a ExtensionAction, in this case a BrowserAction and handles 105// loading the image for the button asynchronously on the file thread. 106class BrowserActionButton : public views::MenuButton, 107 public views::ButtonListener, 108 public views::ContextMenuController, 109 public content::NotificationObserver, 110 public ExtensionActionIconFactory::Observer { 111 public: 112 // The IconObserver will receive a notification when the button's icon has 113 // been updated. 114 class IconObserver { 115 public: 116 virtual void OnIconUpdated(const gfx::ImageSkia& icon) = 0; 117 118 protected: 119 virtual ~IconObserver() {} 120 }; 121 122 BrowserActionButton(const extensions::Extension* extension, 123 Browser* browser_, 124 BrowserActionView::Delegate* delegate); 125 126 // Call this instead of delete. 127 void Destroy(); 128 129 ExtensionAction* browser_action() const { return browser_action_; } 130 const extensions::Extension* extension() { return extension_; } 131 132 void set_icon_observer(IconObserver* icon_observer) { 133 icon_observer_ = icon_observer; 134 } 135 136 // Called to update the display to match the browser action's state. 137 void UpdateState(); 138 139 // Does this button's action have a popup? 140 virtual bool IsPopup(); 141 virtual GURL GetPopupUrl(); 142 143 // Overridden from views::View: 144 virtual bool CanHandleAccelerators() const OVERRIDE; 145 virtual void GetAccessibleState(ui::AXViewState* state) OVERRIDE; 146 147 // Overridden from views::ButtonListener: 148 virtual void ButtonPressed(views::Button* sender, 149 const ui::Event& event) OVERRIDE; 150 151 // Overridden from views::ContextMenuController. 152 virtual void ShowContextMenuForView(View* source, 153 const gfx::Point& point, 154 ui::MenuSourceType source_type) OVERRIDE; 155 156 // Overridden from content::NotificationObserver: 157 virtual void Observe(int type, 158 const content::NotificationSource& source, 159 const content::NotificationDetails& details) OVERRIDE; 160 161 // Overriden from ExtensionActionIconFactory::Observer. 162 virtual void OnIconUpdated() OVERRIDE; 163 164 // MenuButton behavior overrides. These methods all default to LabelButton 165 // behavior unless this button is a popup. In that case, it uses MenuButton 166 // behavior. MenuButton has the notion of a child popup being shown where the 167 // button will stay in the pushed state until the "menu" (a popup in this 168 // case) is dismissed. 169 virtual bool Activate() OVERRIDE; 170 virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE; 171 virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE; 172 virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE; 173 virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE; 174 virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE; 175 virtual scoped_ptr<views::LabelButtonBorder> CreateDefaultBorder() const 176 OVERRIDE; 177 178 // Overridden from ui::AcceleratorTarget. 179 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 180 181 // Notifications when to set button state to pushed/not pushed (for when the 182 // popup/context menu is hidden or shown by the container). 183 void SetButtonPushed(); 184 void SetButtonNotPushed(); 185 186 // Whether the browser action is enabled on this tab. Note that we cannot use 187 // the built-in views enabled/SetEnabled because disabled views do not 188 // receive drag events. 189 bool IsEnabled(int tab_id) const; 190 191 // Returns icon factory for the button. 192 ExtensionActionIconFactory& icon_factory() { return icon_factory_; } 193 194 // Gets the icon of this button and its badge. 195 gfx::ImageSkia GetIconWithBadge(); 196 197 // Returns button icon so it can be accessed during tests. 198 gfx::ImageSkia GetIconForTest(); 199 200 protected: 201 // Overridden from views::View: 202 virtual void ViewHierarchyChanged( 203 const ViewHierarchyChangedDetails& details) OVERRIDE; 204 205 private: 206 virtual ~BrowserActionButton(); 207 208 // Register an extension command if the extension has an active one. 209 void MaybeRegisterExtensionCommand(); 210 211 // Unregisters an extension command, if the extension has registered one and 212 // it is active. 213 void MaybeUnregisterExtensionCommand(bool only_if_active); 214 215 // The Browser object this button is associated with. 216 Browser* browser_; 217 218 // The browser action this view represents. The ExtensionAction is not owned 219 // by this class. 220 ExtensionAction* browser_action_; 221 222 // The extension associated with the browser action we're displaying. 223 const extensions::Extension* extension_; 224 225 // The object that will be used to get the browser action icon for us. 226 // It may load the icon asynchronously (in which case the initial icon 227 // returned by the factory will be transparent), so we have to observe it for 228 // updates to the icon. 229 ExtensionActionIconFactory icon_factory_; 230 231 // Delegate that usually represents a container for BrowserActionView. 232 BrowserActionView::Delegate* delegate_; 233 234 // Used to make sure MaybeRegisterExtensionCommand() is called only once 235 // from ViewHierarchyChanged(). 236 bool called_registered_extension_command_; 237 238 content::NotificationRegistrar registrar_; 239 240 // The extension key binding accelerator this browser action is listening for 241 // (to show the popup). 242 scoped_ptr<ui::Accelerator> keybinding_; 243 244 // Responsible for running the menu. 245 scoped_ptr<views::MenuRunner> menu_runner_; 246 247 // The observer that we need to notify when the icon of the button has been 248 // updated. 249 IconObserver* icon_observer_; 250 251 friend class base::DeleteHelper<BrowserActionButton>; 252 253 DISALLOW_COPY_AND_ASSIGN(BrowserActionButton); 254}; 255 256#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_ 257