blob: e114d8374972ae91abfc77872c2520bda4c6b0de [file] [log] [blame]
// Copyright 2013 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_TOOLBAR_TOOLBAR_ACTION_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ACTION_VIEW_H_
#include "base/callback.h"
#include "base/macros.h"
#include "chrome/browser/ui/views/toolbar/toolbar_action_view_delegate_views.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/controls/menu/menu_model_adapter.h"
#include "ui/views/drag_controller.h"
#include "ui/views/view.h"
class ExtensionAction;
namespace extensions {
class Extension;
}
namespace gfx {
class Image;
}
namespace views {
class MenuItemView;
class MenuModelAdapter;
class MenuRunner;
}
////////////////////////////////////////////////////////////////////////////////
// ToolbarActionView
// A wrapper around a ToolbarActionViewController to display a toolbar action
// action in the BrowserActionsContainer.
class ToolbarActionView : public views::MenuButton,
public ToolbarActionViewDelegateViews,
public views::MenuButtonListener,
public views::ContextMenuController {
public:
// Need DragController here because ToolbarActionView could be
// dragged/dropped.
class Delegate : public views::DragController {
public:
// Returns the current web contents.
virtual content::WebContents* GetCurrentWebContents() = 0;
// Whether the container for this button is shown inside a menu.
virtual bool ShownInsideMenu() const = 0;
// Notifies that a drag completed.
virtual void OnToolbarActionViewDragDone() = 0;
// Returns the view of the toolbar actions overflow menu to use as a
// reference point for a popup when this view isn't visible.
virtual views::MenuButton* GetOverflowReferenceView() = 0;
protected:
~Delegate() override {}
};
// Callback type used for testing.
using ContextMenuCallback = base::Callback<void(ToolbarActionView*)>;
ToolbarActionView(ToolbarActionViewController* view_controller,
Delegate* delegate);
~ToolbarActionView() override;
// views::MenuButton:
void GetAccessibleState(ui::AXViewState* state) override;
std::unique_ptr<views::LabelButtonBorder> CreateDefaultBorder()
const override;
bool IsTriggerableEvent(const ui::Event& event) override;
SkColor GetInkDropBaseColor() const override;
bool ShouldShowInkDropHighlight() const override;
// ToolbarActionViewDelegateViews:
content::WebContents* GetCurrentWebContents() const override;
void UpdateState() override;
// views::MenuButtonListener:
void OnMenuButtonClicked(views::MenuButton* source,
const gfx::Point& point,
const ui::Event* event) override;
ToolbarActionViewController* view_controller() {
return view_controller_;
}
// Returns button icon so it can be accessed during tests.
gfx::ImageSkia GetIconForTest();
bool IsMenuRunningForTesting() const;
bool wants_to_run_for_testing() const { return wants_to_run_; }
views::MenuItemView* menu_for_testing() { return menu_; }
private:
// views::MenuButton:
gfx::Size GetPreferredSize() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
void OnDragDone() override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
// ToolbarActionViewDelegateViews:
views::View* GetAsView() override;
views::FocusManager* GetFocusManagerForAccelerator() override;
views::View* GetReferenceViewForPopup() override;
bool IsMenuRunning() const override;
void OnPopupShown(bool by_user) override;
void OnPopupClosed() override;
// views::ContextMenuController:
void ShowContextMenuForView(views::View* source,
const gfx::Point& point,
ui::MenuSourceType source_type) override;
// Shows the context menu (if one exists) for the toolbar action.
void DoShowContextMenu(ui::MenuSourceType source_type);
// Closes the currently-active menu, if needed. This is the case when there
// is an active menu that wouldn't close automatically when a new one is
// opened.
// Returns true if a menu was closed, false otherwise.
bool CloseActiveMenuIfNeeded();
// Callback for MenuModelAdapter.
void OnMenuClosed();
// A lock to keep the MenuButton pressed when a menu or popup is visible.
std::unique_ptr<views::MenuButton::PressedLock> pressed_lock_;
// The controller for this toolbar action view.
ToolbarActionViewController* view_controller_;
// Delegate that usually represents a container for ToolbarActionView.
Delegate* delegate_;
// Used to make sure we only register the command once.
bool called_register_command_;
// The cached value of whether or not the action wants to run on the current
// tab.
bool wants_to_run_;
// Responsible for converting the context menu model into |menu_|.
std::unique_ptr<views::MenuModelAdapter> menu_adapter_;
// Responsible for running the menu.
std::unique_ptr<views::MenuRunner> menu_runner_;
// The root MenuItemView for the context menu, or null if no menu is being
// shown.
views::MenuItemView* menu_;
// The time the popup was last closed.
base::TimeTicks popup_closed_time_;
base::WeakPtrFactory<ToolbarActionView> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(ToolbarActionView);
};
#endif // CHROME_BROWSER_UI_VIEWS_TOOLBAR_TOOLBAR_ACTION_VIEW_H_