browser_action_view.h revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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 virtual bool NeedToShowMultipleIconStates() const; 58 virtual bool NeedToShowTooltip() const; 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 TextButton 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 176 // Overridden from ui::AcceleratorTarget. 177 virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE; 178 179 // Notifications when to set button state to pushed/not pushed (for when the 180 // popup/context menu is hidden or shown by the container). 181 void SetButtonPushed(); 182 void SetButtonNotPushed(); 183 184 // Whether the browser action is enabled on this tab. Note that we cannot use 185 // the built-in views enabled/SetEnabled because disabled views do not 186 // receive drag events. 187 bool IsEnabled(int tab_id) const; 188 189 // Returns icon factory for the button. 190 ExtensionActionIconFactory& icon_factory() { return icon_factory_; } 191 192 // Gets the icon of this button and its badge. 193 gfx::ImageSkia GetIconWithBadge(); 194 195 // Returns button icon so it can be accessed during tests. 196 gfx::ImageSkia GetIconForTest(); 197 198 protected: 199 // Overridden from views::View: 200 virtual void ViewHierarchyChanged( 201 const ViewHierarchyChangedDetails& details) OVERRIDE; 202 203 private: 204 virtual ~BrowserActionButton(); 205 206 // Register an extension command if the extension has an active one. 207 void MaybeRegisterExtensionCommand(); 208 209 // Unregisters an extension command, if the extension has registered one and 210 // it is active. 211 void MaybeUnregisterExtensionCommand(bool only_if_active); 212 213 // The Browser object this button is associated with. 214 Browser* browser_; 215 216 // The browser action this view represents. The ExtensionAction is not owned 217 // by this class. 218 ExtensionAction* browser_action_; 219 220 // The extension associated with the browser action we're displaying. 221 const extensions::Extension* extension_; 222 223 // The object that will be used to get the browser action icon for us. 224 // It may load the icon asynchronously (in which case the initial icon 225 // returned by the factory will be transparent), so we have to observe it for 226 // updates to the icon. 227 ExtensionActionIconFactory icon_factory_; 228 229 // Delegate that usually represents a container for BrowserActionView. 230 BrowserActionView::Delegate* delegate_; 231 232 // The context menu. This member is non-NULL only when the menu is shown. 233 views::MenuItemView* context_menu_; 234 235 // Used to make sure MaybeRegisterExtensionCommand() is called only once 236 // from ViewHierarchyChanged(). 237 bool called_registered_extension_command_; 238 239 content::NotificationRegistrar registrar_; 240 241 // The extension key binding accelerator this browser action is listening for 242 // (to show the popup). 243 scoped_ptr<ui::Accelerator> keybinding_; 244 245 // Responsible for running the menu. 246 scoped_ptr<views::MenuRunner> menu_runner_; 247 248 // The observer that we need to notify when the icon of the button has been 249 // updated. 250 IconObserver* icon_observer_; 251 252 friend class base::DeleteHelper<BrowserActionButton>; 253 254 DISALLOW_COPY_AND_ASSIGN(BrowserActionButton); 255}; 256 257#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_ 258