blob: 1b4e8e24821c55fd712d61776b41225243670798 [file] [log] [blame]
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_BROWSER_ACTION_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_BROWSER_ACTION_VIEW_H_
#include <string>
#include "chrome/browser/extensions/extension_action_icon_factory.h"
#include "chrome/browser/extensions/extension_context_menu_model.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/button/menu_button.h"
#include "ui/views/controls/button/menu_button_listener.h"
#include "ui/views/drag_controller.h"
#include "ui/views/view.h"
class Browser;
class BrowserActionButton;
class ExtensionAction;
namespace extensions {
class Extension;
}
namespace gfx {
class Image;
}
namespace views {
class MenuItemView;
class MenuRunner;
}
////////////////////////////////////////////////////////////////////////////////
// BrowserActionView
// A single entry in the browser action container. This contains the actual
// BrowserActionButton, as well as the logic to paint the badge.
class BrowserActionView : public views::View {
public:
// Need DragController here because BrowserActionView could be
// dragged/dropped.
class Delegate : public views::DragController,
public ExtensionContextMenuModel::PopupDelegate {
public:
// Returns the current tab's ID, or -1 if there is no current tab.
virtual int GetCurrentTabId() const = 0;
// Called when the user clicks on the browser action icon.
virtual void OnBrowserActionExecuted(BrowserActionButton* button) = 0;
// Called when a browser action becomes visible/hidden.
virtual void OnBrowserActionVisibilityChanged() = 0;
// Returns relative position of a button inside BrowserActionView.
virtual gfx::Point GetViewContentOffset() const = 0;
virtual bool NeedToShowMultipleIconStates() const;
virtual bool NeedToShowTooltip() const;
protected:
virtual ~Delegate() {}
};
BrowserActionView(const extensions::Extension* extension,
Browser* browser,
Delegate* delegate);
virtual ~BrowserActionView();
BrowserActionButton* button() { return button_; }
// Gets browser action button icon with the badge.
gfx::ImageSkia GetIconWithBadge();
// Overridden from views::View:
virtual void Layout() OVERRIDE;
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
virtual gfx::Size GetPreferredSize() OVERRIDE;
protected:
// Overridden from views::View to paint the badge on top of children.
virtual void PaintChildren(gfx::Canvas* canvas) OVERRIDE;
private:
// The Browser object this view is associated with.
Browser* browser_;
// Usually a container for this view.
Delegate* delegate_;
// The button this view contains.
BrowserActionButton* button_;
// Extension this view associated with.
const extensions::Extension* extension_;
DISALLOW_COPY_AND_ASSIGN(BrowserActionView);
};
////////////////////////////////////////////////////////////////////////////////
// BrowserActionButton
// The BrowserActionButton is a specialization of the MenuButton class.
// It acts on a ExtensionAction, in this case a BrowserAction and handles
// loading the image for the button asynchronously on the file thread.
class BrowserActionButton : public views::MenuButton,
public views::ButtonListener,
public views::ContextMenuController,
public content::NotificationObserver,
public ExtensionActionIconFactory::Observer {
public:
BrowserActionButton(const extensions::Extension* extension,
Browser* browser_,
BrowserActionView::Delegate* delegate);
// Call this instead of delete.
void Destroy();
ExtensionAction* browser_action() const { return browser_action_; }
const extensions::Extension* extension() { return extension_; }
// Called to update the display to match the browser action's state.
void UpdateState();
// Does this button's action have a popup?
virtual bool IsPopup();
virtual GURL GetPopupUrl();
// Overridden from views::View:
virtual bool CanHandleAccelerators() const OVERRIDE;
virtual void GetAccessibleState(ui::AccessibleViewState* state) OVERRIDE;
// Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* sender,
const ui::Event& event) OVERRIDE;
// Overridden from views::ContextMenuController.
virtual void ShowContextMenuForView(View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) OVERRIDE;
// Overridden from content::NotificationObserver:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE;
// Overriden from ExtensionActionIconFactory::Observer.
virtual void OnIconUpdated() OVERRIDE;
// MenuButton behavior overrides. These methods all default to TextButton
// behavior unless this button is a popup. In that case, it uses MenuButton
// behavior. MenuButton has the notion of a child popup being shown where the
// button will stay in the pushed state until the "menu" (a popup in this
// case) is dismissed.
virtual bool Activate() OVERRIDE;
virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseReleased(const ui::MouseEvent& event) OVERRIDE;
virtual void OnMouseExited(const ui::MouseEvent& event) OVERRIDE;
virtual bool OnKeyReleased(const ui::KeyEvent& event) OVERRIDE;
virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE;
// Overridden from ui::AcceleratorTarget.
virtual bool AcceleratorPressed(const ui::Accelerator& accelerator) OVERRIDE;
// Notifications when to set button state to pushed/not pushed (for when the
// popup/context menu is hidden or shown by the container).
void SetButtonPushed();
void SetButtonNotPushed();
// Whether the browser action is enabled on this tab. Note that we cannot use
// the built-in views enabled/SetEnabled because disabled views do not
// receive drag events.
bool IsEnabled(int tab_id) const;
// Returns icon factory for the button.
ExtensionActionIconFactory& icon_factory() { return icon_factory_; }
// Returns button icon so it can be accessed during tests.
gfx::ImageSkia GetIconForTest();
protected:
// Overridden from views::View:
virtual void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) OVERRIDE;
private:
virtual ~BrowserActionButton();
// Register an extension command if the extension has an active one.
void MaybeRegisterExtensionCommand();
// Unregisters an extension command, if the extension has registered one and
// it is active.
void MaybeUnregisterExtensionCommand(bool only_if_active);
// The Browser object this button is associated with.
Browser* browser_;
// The browser action this view represents. The ExtensionAction is not owned
// by this class.
ExtensionAction* browser_action_;
// The extension associated with the browser action we're displaying.
const extensions::Extension* extension_;
// The object that will be used to get the browser action icon for us.
// It may load the icon asynchronously (in which case the initial icon
// returned by the factory will be transparent), so we have to observe it for
// updates to the icon.
ExtensionActionIconFactory icon_factory_;
// Delegate that usually represents a container for BrowserActionView.
BrowserActionView::Delegate* delegate_;
// The context menu. This member is non-NULL only when the menu is shown.
views::MenuItemView* context_menu_;
// Used to make sure MaybeRegisterExtensionCommand() is called only once
// from ViewHierarchyChanged().
bool called_registered_extension_command_;
content::NotificationRegistrar registrar_;
// The extension key binding accelerator this browser action is listening for
// (to show the popup).
scoped_ptr<ui::Accelerator> keybinding_;
// Responsible for running the menu.
scoped_ptr<views::MenuRunner> menu_runner_;
friend class base::DeleteHelper<BrowserActionButton>;
DISALLOW_COPY_AND_ASSIGN(BrowserActionButton);
};
#endif // CHROME_BROWSER_UI_VIEWS_BROWSER_ACTION_VIEW_H_