browser_action_view.h revision f2477e01787aa58f445919b809d89e252beef54f
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    // Returns relative position of a button inside BrowserActionView.
58    virtual gfx::Point GetViewContentOffset() const = 0;
59
60    virtual bool NeedToShowMultipleIconStates() const;
61    virtual bool NeedToShowTooltip() const;
62
63   protected:
64    virtual ~Delegate() {}
65  };
66
67  BrowserActionView(const extensions::Extension* extension,
68                    Browser* browser,
69                    Delegate* delegate);
70  virtual ~BrowserActionView();
71
72  BrowserActionButton* button() { return button_; }
73
74  // Gets browser action button icon with the badge.
75  gfx::ImageSkia GetIconWithBadge();
76
77  // Overridden from views::View:
78  virtual void Layout() OVERRIDE;
79  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
80  virtual gfx::Size GetPreferredSize() OVERRIDE;
81
82 protected:
83  // Overridden from views::View to paint the badge on top of children.
84  virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
85
86 private:
87  // The Browser object this view is associated with.
88  Browser* browser_;
89
90  // Usually a container for this view.
91  Delegate* delegate_;
92
93  // The button this view contains.
94  BrowserActionButton* button_;
95
96  // Extension this view associated with.
97  const extensions::Extension* extension_;
98
99  DISALLOW_COPY_AND_ASSIGN(BrowserActionView);
100};
101
102////////////////////////////////////////////////////////////////////////////////
103// BrowserActionButton
104
105// The BrowserActionButton is a specialization of the MenuButton class.
106// It acts on a ExtensionAction, in this case a BrowserAction and handles
107// loading the image for the button asynchronously on the file thread.
108class BrowserActionButton : public views::MenuButton,
109                            public views::ButtonListener,
110                            public views::ContextMenuController,
111                            public content::NotificationObserver,
112                            public ExtensionActionIconFactory::Observer {
113 public:
114  BrowserActionButton(const extensions::Extension* extension,
115                      Browser* browser_,
116                      BrowserActionView::Delegate* delegate);
117
118  // Call this instead of delete.
119  void Destroy();
120
121  ExtensionAction* browser_action() const { return browser_action_; }
122  const extensions::Extension* extension() { return extension_; }
123
124  // Called to update the display to match the browser action's state.
125  void UpdateState();
126
127  // Does this button's action have a popup?
128  virtual bool IsPopup();
129  virtual GURL GetPopupUrl();
130
131  // Overridden from views::View:
132  virtual bool CanHandleAccelerators() const OVERRIDE;
133  virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
134
135  // Overridden from views::ButtonListener:
136  virtual void ButtonPressed(views::Button* sender,
137                             const ui::Event& event) OVERRIDE;
138
139  // Overridden from views::ContextMenuController.
140  virtual void ShowContextMenuForView(View* source,
141                                      const gfx::Point& point,
142                                      ui::MenuSourceType source_type) OVERRIDE;
143
144  // Overridden from content::NotificationObserver:
145  virtual void Observe(int type,
146                       const content::NotificationSource& source,
147                       const content::NotificationDetails& details) OVERRIDE;
148
149  // Overriden from ExtensionActionIconFactory::Observer.
150  virtual void OnIconUpdated() OVERRIDE;
151
152  // MenuButton behavior overrides.  These methods all default to TextButton
153  // behavior unless this button is a popup.  In that case, it uses MenuButton
154  // behavior.  MenuButton has the notion of a child popup being shown where the
155  // button will stay in the pushed state until the "menu" (a popup in this
156  // case) is dismissed.
157  virtual bool Activate() OVERRIDE;
158  virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
159  virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
160  virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
161  virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
162  virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
163
164  // Overridden from ui::AcceleratorTarget.
165  virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
166
167  // Notifications when to set button state to pushed/not pushed (for when the
168  // popup/context menu is hidden or shown by the container).
169  void SetButtonPushed();
170  void SetButtonNotPushed();
171
172  // Whether the browser action is enabled on this tab. Note that we cannot use
173  // the built-in views enabled/SetEnabled because disabled views do not
174  // receive drag events.
175  bool IsEnabled(int tab_id) const;
176
177  // Returns icon factory for the button.
178  ExtensionActionIconFactory& icon_factory() { return icon_factory_; }
179
180  // Returns button icon so it can be accessed during tests.
181  gfx::ImageSkia GetIconForTest();
182
183 protected:
184  // Overridden from views::View:
185  virtual void ViewHierarchyChanged(
186      const ViewHierarchyChangedDetails& details) OVERRIDE;
187
188 private:
189  virtual ~BrowserActionButton();
190
191  // Register an extension command if the extension has an active one.
192  void MaybeRegisterExtensionCommand();
193
194  // Unregisters an extension command, if the extension has registered one and
195  // it is active.
196  void MaybeUnregisterExtensionCommand(bool only_if_active);
197
198  // The Browser object this button is associated with.
199  Browser* browser_;
200
201  // The browser action this view represents. The ExtensionAction is not owned
202  // by this class.
203  ExtensionAction* browser_action_;
204
205  // The extension associated with the browser action we're displaying.
206  const extensions::Extension* extension_;
207
208  // The object that will be used to get the browser action icon for us.
209  // It may load the icon asynchronously (in which case the initial icon
210  // returned by the factory will be transparent), so we have to observe it for
211  // updates to the icon.
212  ExtensionActionIconFactory icon_factory_;
213
214  // Delegate that usually represents a container for BrowserActionView.
215  BrowserActionView::Delegate* delegate_;
216
217  // The context menu.  This member is non-NULL only when the menu is shown.
218  views::MenuItemView* context_menu_;
219
220  // Used to make sure MaybeRegisterExtensionCommand() is called only once
221  // from ViewHierarchyChanged().
222  bool called_registered_extension_command_;
223
224  content::NotificationRegistrar registrar_;
225
226  // The extension key binding accelerator this browser action is listening for
227  // (to show the popup).
228  scoped_ptr<ui::Accelerator> keybinding_;
229
230  // Responsible for running the menu.
231  scoped_ptr<views::MenuRunner> menu_runner_;
232
233  friend class base::DeleteHelper<BrowserActionButton>;
234
235  DISALLOW_COPY_AND_ASSIGN(BrowserActionButton);
236};
237
238#endif  // CHROME_BROWSER_UI_VIEWS_TOOLBAR_BROWSER_ACTION_VIEW_H_
239