Home | History | Annotate | Download | only in views
      1 // Copyright (c) 2012 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_BROWSER_ACTION_VIEW_H_
      6 #define CHROME_BROWSER_UI_VIEWS_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 
     20 class Browser;
     21 class BrowserActionButton;
     22 class ExtensionAction;
     23 
     24 namespace extensions {
     25 class Extension;
     26 }
     27 
     28 namespace gfx {
     29 class Image;
     30 }
     31 
     32 namespace views {
     33 class MenuItemView;
     34 class 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.
     41 class 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.
    108 class 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_BROWSER_ACTION_VIEW_H_
    239