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