Commit 58e29035 authored by gene@chromium.org's avatar gene@chromium.org

Added Reload drop-down menu for when in Dev mode for Windows.

(Already added for Linux in previous CL).

BUG=none
TEST=Run browser on Windows, switch to Dev mode, verify drop-down menu from Reload.

Review URL: https://chromiumcodereview.appspot.com/10779019

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@150138 0039d316-1c4b-4281-b951-d872f2087c98
parent 0f7bee56
......@@ -32,6 +32,7 @@
#define IDC_STOP 33006
#define IDC_RELOAD_IGNORING_CACHE 33007
#define IDC_LOAD_NEW_TAB_PAGE 33008
#define IDC_RELOAD_CLEARING_CACHE 33009
// Window management commands
#define IDC_NEW_WINDOW 34000
......
......@@ -127,6 +127,7 @@ SimpleWebViewDialog::SimpleWebViewDialog(Profile* profile)
command_updater_->UpdateCommandEnabled(IDC_STOP, true);
command_updater_->UpdateCommandEnabled(IDC_RELOAD, true);
command_updater_->UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
command_updater_->UpdateCommandEnabled(IDC_RELOAD_CLEARING_CACHE, true);
}
SimpleWebViewDialog::~SimpleWebViewDialog() {
......@@ -345,6 +346,7 @@ void SimpleWebViewDialog::ExecuteCommandWithDisposition(
case IDC_RELOAD:
// Always reload ignoring cache.
case IDC_RELOAD_IGNORING_CACHE:
case IDC_RELOAD_CLEARING_CACHE:
web_contents->GetController().ReloadIgnoringCache(true);
break;
default:
......@@ -373,20 +375,7 @@ void SimpleWebViewDialog::LoadImages() {
forward_->SetImage(views::CustomButton::BS_DISABLED,
tp->GetImageSkiaNamed(IDR_FORWARD_D));
reload_->SetImage(views::CustomButton::BS_NORMAL,
tp->GetImageSkiaNamed(IDR_RELOAD));
reload_->SetImage(views::CustomButton::BS_HOT,
tp->GetImageSkiaNamed(IDR_RELOAD_H));
reload_->SetImage(views::CustomButton::BS_PUSHED,
tp->GetImageSkiaNamed(IDR_RELOAD_P));
reload_->SetToggledImage(views::CustomButton::BS_NORMAL,
tp->GetImageSkiaNamed(IDR_STOP));
reload_->SetToggledImage(views::CustomButton::BS_HOT,
tp->GetImageSkiaNamed(IDR_STOP_H));
reload_->SetToggledImage(views::CustomButton::BS_PUSHED,
tp->GetImageSkiaNamed(IDR_STOP_P));
reload_->SetToggledImage(views::CustomButton::BS_DISABLED,
tp->GetImageSkiaNamed(IDR_STOP_D));
reload_->LoadImages(tp);
}
void SimpleWebViewDialog::UpdateButtons() {
......
......@@ -236,9 +236,10 @@ DevToolsWindow::~DevToolsWindow() {
}
void DevToolsWindow::InspectedContentsClosing() {
UpdateBrowserToolbar();
if (docked_) {
// Update dev tools to reflect removed dev tools window.
BrowserWindow* inspected_window = GetInspectedBrowserWindow();
if (inspected_window)
inspected_window->UpdateDevTools();
......@@ -482,6 +483,7 @@ void DevToolsWindow::Observe(int type,
// Notify manager that this DevToolsClientHost no longer exists and
// initiate self-destuct here.
DevToolsManager::GetInstance()->ClientHostClosing(frontend_host_);
UpdateBrowserToolbar();
delete this;
}
} else if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
......@@ -634,6 +636,9 @@ DevToolsWindow* DevToolsWindow::ToggleDevToolsWindow(
do_open = true;
}
// Update toolbar to reflect DevTools changes.
window->UpdateBrowserToolbar();
// If window is docked and visible, we hide it on toggle. If window is
// undocked, we show (activate) it.
if (!window->is_docked() || do_open)
......@@ -771,3 +776,11 @@ void DevToolsWindow::RunFileChooser(WebContents* web_contents,
FileSelectHelper::RunFileChooser(web_contents, params);
}
void DevToolsWindow::UpdateBrowserToolbar() {
if (!inspected_tab_)
return;
BrowserWindow* inspected_window = GetInspectedBrowserWindow();
if (inspected_window)
inspected_window->UpdateToolbar(inspected_tab_, false);
}
......@@ -154,6 +154,8 @@ class DevToolsWindow : private content::NotificationObserver,
void RequestSetDocked(bool docked);
void UpdateBrowserToolbar();
Profile* profile_;
TabContents* inspected_tab_;
TabContents* tab_contents_;
......
......@@ -258,6 +258,9 @@ void BrowserCommandController::ExecuteCommandWithDisposition(
case IDC_RELOAD:
Reload(browser_, disposition);
break;
case IDC_RELOAD_CLEARING_CACHE:
ClearCache(browser_);
// FALL THROUGH
case IDC_RELOAD_IGNORING_CACHE:
ReloadIgnoringCache(browser_, disposition);
break;
......@@ -680,6 +683,7 @@ void BrowserCommandController::InitCommandState() {
// Navigation commands
command_updater_.UpdateCommandEnabled(IDC_RELOAD, true);
command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE, true);
command_updater_.UpdateCommandEnabled(IDC_RELOAD_CLEARING_CACHE, true);
// Window management commands
command_updater_.UpdateCommandEnabled(IDC_CLOSE_WINDOW, true);
......@@ -862,6 +866,8 @@ void BrowserCommandController::UpdateCommandsForTabState() {
command_updater_.UpdateCommandEnabled(IDC_RELOAD, CanReload(browser_));
command_updater_.UpdateCommandEnabled(IDC_RELOAD_IGNORING_CACHE,
CanReload(browser_));
command_updater_.UpdateCommandEnabled(IDC_RELOAD_CLEARING_CACHE,
CanReload(browser_));
// Window management commands
command_updater_.UpdateCommandEnabled(IDC_DUPLICATE_TAB,
......
......@@ -12,18 +12,34 @@
#include "chrome/browser/ui/search/search_model.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/theme_provider.h"
#include "ui/views/metrics.h"
#include "ui/views/widget/widget.h"
// static
const char ReloadButton::kViewClassName[] = "browser/ui/views/ReloadButton";
const int kReloadImages[] =
{ IDR_RELOAD, IDR_RELOAD_H, IDR_RELOAD_P, IDR_RELOAD_D };
const int kStopImages[] = { IDR_STOP, IDR_STOP_H, IDR_STOP_P, IDR_STOP_D };
// Contents of the Reload drop-down menu.
const int kReloadMenuItems[] = {
IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM,
IDS_RELOAD_MENU_HARD_RELOAD_ITEM,
IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM,
};
////////////////////////////////////////////////////////////////////////////////
// ReloadButton, public:
ReloadButton::ReloadButton(LocationBarView* location_bar,
CommandUpdater* command_updater)
: ALLOW_THIS_IN_INITIALIZER_LIST(ToggleImageButton(this)),
: ALLOW_THIS_IN_INITIALIZER_LIST(ButtonDropDown(this, CreateMenuModel())),
location_bar_(location_bar),
command_updater_(command_updater),
intended_mode_(MODE_RELOAD),
......@@ -31,6 +47,7 @@ ReloadButton::ReloadButton(LocationBarView* location_bar,
double_click_timer_delay_(
base::TimeDelta::FromMilliseconds(views::GetDoubleClickInterval())),
stop_to_reload_timer_delay_(base::TimeDelta::FromMilliseconds(1350)),
menu_enabled_(false),
testing_mouse_hovered_(false),
testing_reload_count_(0) {
}
......@@ -49,8 +66,7 @@ void ReloadButton::ChangeMode(Mode mode, bool force) {
!double_click_timer_.IsRunning() : (visible_mode_ != MODE_STOP))) {
double_click_timer_.Stop();
stop_to_reload_timer_.Stop();
SetToggled(mode == MODE_STOP);
visible_mode_ = mode;
ChangeModeInternal(mode);
// For instant extended API, if mode is NTP, disable button state.
bool disabled = location_bar_ && location_bar_->search_model() &&
chrome::search::IsInstantExtendedAPIEnabled(location_bar_->profile()) &&
......@@ -74,11 +90,31 @@ void ReloadButton::ChangeMode(Mode mode, bool force) {
}
}
void ReloadButton::LoadImages(ui::ThemeProvider* tp) {
DCHECK_EQ(static_cast<int>(arraysize(kReloadImages)), BS_COUNT);
DCHECK_EQ(static_cast<int>(arraysize(kStopImages)), BS_COUNT);
gfx::ImageSkia* reload_images = images_;
gfx::ImageSkia* stop_images = alternate_images_;
if (visible_mode_ == MODE_STOP)
std::swap(reload_images, stop_images);
for (int i = 0; i < BS_COUNT; i++) {
reload_images[i] = *(tp->GetImageSkiaNamed(kReloadImages[i]));
stop_images[i] = *(tp->GetImageSkiaNamed(kStopImages[i]));
}
SchedulePaint();
PreferredSizeChanged();
}
////////////////////////////////////////////////////////////////////////////////
// ReloadButton, views::ButtonListener implementation:
void ReloadButton::ButtonPressed(views::Button* /* button */,
const views::Event& event) {
ClearPendingMenu();
if (visible_mode_ == MODE_STOP) {
if (command_updater_)
command_updater_->ExecuteCommandWithDisposition(IDC_STOP, CURRENT_TAB);
......@@ -98,15 +134,6 @@ void ReloadButton::ButtonPressed(views::Button* /* button */,
command = IDC_RELOAD;
}
WindowOpenDisposition disposition =
chrome::DispositionFromEventFlags(flags);
if ((disposition == CURRENT_TAB) && location_bar_) {
// Forcibly reset the location bar, since otherwise it won't discard any
// ongoing user edits, since it doesn't realize this is a user-initiated
// action.
location_bar_->Revert();
}
// Start a timer - while this timer is running, the reload button cannot be
// changed to a stop button. We do not set |intended_mode_| to MODE_STOP
// here as the browser will do that when it actually starts loading (which
......@@ -115,8 +142,7 @@ void ReloadButton::ButtonPressed(views::Button* /* button */,
double_click_timer_.Start(FROM_HERE, double_click_timer_delay_, this,
&ReloadButton::OnDoubleClickTimer);
if (command_updater_)
command_updater_->ExecuteCommandWithDisposition(command, disposition);
ExecuteBrowserCommand(command, flags);
++testing_reload_count_;
}
}
......@@ -125,15 +151,17 @@ void ReloadButton::ButtonPressed(views::Button* /* button */,
// ReloadButton, View overrides:
void ReloadButton::OnMouseExited(const views::MouseEvent& event) {
ChangeMode(intended_mode_, true);
if (state() != BS_DISABLED)
SetState(BS_NORMAL);
ButtonDropDown::OnMouseExited(event);
if (!IsMenuShowing())
ChangeMode(intended_mode_, true);
}
bool ReloadButton::GetTooltipText(const gfx::Point& p,
string16* tooltip) const {
int reload_tooltip = menu_enabled_ ?
IDS_TOOLTIP_RELOAD_WITH_MENU : IDS_TOOLTIP_RELOAD;
int text_id = (visible_mode_ == MODE_RELOAD) ?
IDS_TOOLTIP_RELOAD : IDS_TOOLTIP_STOP;
reload_tooltip : IDS_TOOLTIP_STOP;
tooltip->assign(l10n_util::GetStringUTF16(text_id));
return true;
}
......@@ -142,13 +170,108 @@ std::string ReloadButton::GetClassName() const {
return kViewClassName;
}
bool ReloadButton::ShouldShowMenu() {
return menu_enabled_ && (visible_mode_ == MODE_RELOAD);
}
void ReloadButton::ShowDropDownMenu() {
ButtonDropDown::ShowDropDownMenu(); // Blocks.
ChangeMode(intended_mode_, true);
}
////////////////////////////////////////////////////////////////////////////////
// ReloadButton, ui::SimpleMenuModel::Delegate overrides:
bool ReloadButton::IsCommandIdChecked(int command_id) const {
return false;
}
bool ReloadButton::IsCommandIdEnabled(int command_id) const {
return true;
}
bool ReloadButton::IsCommandIdVisible(int command_id) const {
return true;
}
bool ReloadButton::GetAcceleratorForCommandId(int command_id,
ui::Accelerator* accelerator) {
switch (command_id) {
case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
GetWidget()->GetAccelerator(IDC_RELOAD, accelerator);
return true;
case IDS_RELOAD_MENU_HARD_RELOAD_ITEM:
GetWidget()->GetAccelerator(IDC_RELOAD_IGNORING_CACHE, accelerator);
return true;
}
return GetWidget()->GetAccelerator(command_id, accelerator);
}
void ReloadButton::ExecuteCommand(int command_id) {
ExecuteCommand(command_id, 0);
}
void ReloadButton::ExecuteCommand(int command_id, int event_flags) {
int browser_command = 0;
switch (command_id) {
case IDS_RELOAD_MENU_NORMAL_RELOAD_ITEM:
browser_command = IDC_RELOAD;
break;
case IDS_RELOAD_MENU_HARD_RELOAD_ITEM:
browser_command = IDC_RELOAD_IGNORING_CACHE;
break;
case IDS_RELOAD_MENU_EMPTY_AND_HARD_RELOAD_ITEM:
browser_command = IDC_RELOAD_CLEARING_CACHE;
break;
default:
NOTREACHED();
}
ExecuteBrowserCommand(browser_command, event_flags);
}
////////////////////////////////////////////////////////////////////////////////
// ReloadButton, private:
ui::SimpleMenuModel* ReloadButton::CreateMenuModel() {
ui::SimpleMenuModel* menu_model_ = new ui::SimpleMenuModel(this);
for (size_t i = 0; i < arraysize(kReloadMenuItems); i++) {
menu_model_->AddItemWithStringId(kReloadMenuItems[i],
kReloadMenuItems[i]);
}
return menu_model_;
}
void ReloadButton::ExecuteBrowserCommand(int command, int event_flags) {
if (!command_updater_)
return;
WindowOpenDisposition disposition =
chrome::DispositionFromEventFlags(event_flags);
if ((disposition == CURRENT_TAB) && location_bar_) {
// Forcibly reset the location bar, since otherwise it won't discard any
// ongoing user edits, since it doesn't realize this is a user-initiated
// action.
location_bar_->Revert();
}
command_updater_->ExecuteCommandWithDisposition(command, disposition);
}
void ReloadButton::ChangeModeInternal(Mode mode) {
if (visible_mode_ == mode)
return;
for (size_t i = 0; i < BS_COUNT; ++i)
std::swap(images_[i], alternate_images_[i]);
visible_mode_ = mode;
SchedulePaint();
}
void ReloadButton::OnDoubleClickTimer() {
ChangeMode(intended_mode_, false);
if (!IsMenuShowing())
ChangeMode(intended_mode_, false);
}
void ReloadButton::OnStopToReloadTimer() {
DCHECK(!IsMenuShowing());
ChangeMode(intended_mode_, true);
}
......@@ -8,7 +8,8 @@
#include "base/basictypes.h"
#include "base/gtest_prod_util.h"
#include "base/timer.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/views/controls/button/button_dropdown.h"
class CommandUpdater;
class LocationBarView;
......@@ -24,21 +25,28 @@ class LocationBarView;
//
////////////////////////////////////////////////////////////////////////////////
class ReloadButton : public views::ToggleImageButton,
public views::ButtonListener {
class ReloadButton : public views::ButtonDropDown,
public views::ButtonListener,
public ui::SimpleMenuModel::Delegate {
public:
enum Mode { MODE_RELOAD = 0, MODE_STOP };
// The button's class name.
static const char kViewClassName[];
ReloadButton(LocationBarView* location_bar, CommandUpdater* command_updater);
ReloadButton(LocationBarView* location_bar,
CommandUpdater* command_updater);
virtual ~ReloadButton();
// Ask for a specified button state. If |force| is true this will be applied
// immediately.
void ChangeMode(Mode mode, bool force);
// Enable reload drop-down menu.
void set_menu_enabled(bool enable) { menu_enabled_ = enable; }
void LoadImages(ui::ThemeProvider* tp);
// Overridden from views::ButtonListener:
virtual void ButtonPressed(views::Button* /* button */,
const views::Event& event) OVERRIDE;
......@@ -49,9 +57,28 @@ class ReloadButton : public views::ToggleImageButton,
string16* tooltip) const OVERRIDE;
virtual std::string GetClassName() const OVERRIDE;
// Overridden from views::ButtonDropDown:
virtual bool ShouldShowMenu() OVERRIDE;
virtual void ShowDropDownMenu() OVERRIDE;
// Overridden from ui::SimpleMenuModel::Delegate:
virtual bool IsCommandIdChecked(int command_id) const OVERRIDE;
virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE;
virtual bool IsCommandIdVisible(int command_id) const OVERRIDE;
virtual bool GetAcceleratorForCommandId(
int command_id,
ui::Accelerator* accelerator) OVERRIDE;
virtual void ExecuteCommand(int command_id) OVERRIDE;
virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE;
private:
friend class ReloadButtonTest;
ui::SimpleMenuModel* CreateMenuModel();
void ExecuteBrowserCommand(int command, int event_flags);
void ChangeModeInternal(Mode mode);
void OnDoubleClickTimer();
void OnStopToReloadTimer();
......@@ -73,6 +100,14 @@ class ReloadButton : public views::ToggleImageButton,
base::TimeDelta double_click_timer_delay_;
base::TimeDelta stop_to_reload_timer_delay_;
// Indicates if reload menu is enabled.
bool menu_enabled_;
// The parent class's images_ member is used for the current images,
// and this array is used to hold the alternative images.
// We swap between the two when changing mode.
gfx::ImageSkia alternate_images_[BS_COUNT];
// TESTING ONLY
// True if we should pretend the button is hovered.
bool testing_mouse_hovered_;
......
......@@ -265,7 +265,6 @@ void ToolbarView::Init(views::View* location_bar_parent,
reload_->set_triggerable_event_flags(ui::EF_LEFT_MOUSE_BUTTON |
ui::EF_MIDDLE_MOUSE_BUTTON);
reload_->set_tag(IDC_RELOAD);
reload_->SetTooltipText(l10n_util::GetStringUTF16(IDS_TOOLTIP_RELOAD));
reload_->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_RELOAD));
reload_->set_id(VIEW_ID_RELOAD_BUTTON);
......@@ -326,6 +325,9 @@ void ToolbarView::Update(WebContents* tab, bool should_restore_state) {
if (browser_actions_)
browser_actions_->RefreshBrowserActionViews();
if (reload_)
reload_->set_menu_enabled(chrome::IsDebuggerAttachedToCurrentTab(browser_));
}
void ToolbarView::SetPaneFocusAndFocusAppMenu() {
......@@ -619,7 +621,7 @@ bool ToolbarView::GetAcceleratorForCommandId(int command_id,
// ToolbarView, views::View overrides:
gfx::Size ToolbarView::GetPreferredSize() {
if (IsDisplayModeNormal()) {
if (is_display_mode_normal()) {
int min_width = kLeftEdgeSpacing +
back_->GetPreferredSize().width() + kButtonSpacing +
forward_->GetPreferredSize().width() + kButtonSpacing +
......@@ -655,7 +657,7 @@ void ToolbarView::Layout() {
return;
bool maximized = browser_->window() && browser_->window()->IsMaximized();
if (!IsDisplayModeNormal()) {
if (!is_display_mode_normal()) {
int edge_width = maximized ?
0 : kPopupBackgroundEdge->width(); // See OnPaint().
SetLocationBarContainerBounds(gfx::Rect(edge_width, PopupTopSpacing(),
......@@ -775,7 +777,7 @@ bool ToolbarView::HitTest(const gfx::Point& point) const {
void ToolbarView::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
if (IsDisplayModeNormal())
if (is_display_mode_normal())
return;
// In maximized mode, we don't draw the endcaps on the location bar, because
......@@ -908,22 +910,7 @@ void ToolbarView::LoadImages() {
forward_->SetImage(views::CustomButton::BS_DISABLED,
tp->GetImageSkiaNamed(IDR_FORWARD_D));
reload_->SetImage(views::CustomButton::BS_NORMAL,
tp->GetImageSkiaNamed(IDR_RELOAD));
reload_->SetImage(views::CustomButton::BS_HOT,
tp->GetImageSkiaNamed(IDR_RELOAD_H));
reload_->SetImage(views::CustomButton::BS_PUSHED,
tp->GetImageSkiaNamed(IDR_RELOAD_P));
reload_->SetImage(views::CustomButton::BS_DISABLED,
tp->GetImageSkiaNamed(IDR_RELOAD_D));
reload_->SetToggledImage(views::CustomButton::BS_NORMAL,
tp->GetImageSkiaNamed(IDR_STOP));
reload_->SetToggledImage(views::CustomButton::BS_HOT,
tp->GetImageSkiaNamed(IDR_STOP_H));
reload_->SetToggledImage(views::CustomButton::BS_PUSHED,
tp->GetImageSkiaNamed(IDR_STOP_P));
reload_->SetToggledImage(views::CustomButton::BS_DISABLED,
tp->GetImageSkiaNamed(IDR_STOP_D));
reload_->LoadImages(tp);
home_->SetImage(views::CustomButton::BS_NORMAL,
tp->GetImageSkiaNamed(IDR_HOME));
......
......@@ -171,6 +171,13 @@ class ToolbarView : public views::AccessiblePaneView,
virtual void RemovePaneFocus() OVERRIDE;
private:
// Types of display mode this toolbar can have.
enum DisplayMode {
DISPLAYMODE_NORMAL, // Normal toolbar with buttons, etc.
DISPLAYMODE_LOCATION // Slimline toolbar showing only compact location
// bar, used for popups.
};
// Returns true if we should show the upgrade recommended dot.
bool ShouldShowUpgradeRecommended();
......@@ -186,13 +193,7 @@ class ToolbarView : public views::AccessiblePaneView,
// Loads the images for all the child views.
void LoadImages();
// Types of display mode this toolbar can have.
enum DisplayMode {
DISPLAYMODE_NORMAL, // Normal toolbar with buttons, etc.
DISPLAYMODE_LOCATION // Slimline toolbar showing only compact location
// bar, used for popups.
};
bool IsDisplayModeNormal() const {
bool is_display_mode_normal() const {
return display_mode_ == DISPLAYMODE_NORMAL;
}
......
......@@ -35,6 +35,7 @@ const int kMenuTimerDelay = 500;
ButtonDropDown::ButtonDropDown(ButtonListener* listener, ui::MenuModel* model)
: ImageButton(listener),
model_(model),
menu_showing_(false),
y_position_on_lbuttondown_(0),
ALLOW_THIS_IN_INITIALIZER_LIST(show_menu_factory_(this)) {
}
......@@ -42,6 +43,14 @@ ButtonDropDown::ButtonDropDown(ButtonListener* listener, ui::MenuModel* model)
ButtonDropDown::~ButtonDropDown() {
}
void ButtonDropDown::ClearPendingMenu() {
show_menu_factory_.InvalidateWeakPtrs();
}
bool ButtonDropDown::IsMenuShowing() const {
return menu_showing_;
}
////////////////////////////////////////////////////////////////////////////////
//
// ButtonDropDown - Events
......@@ -49,7 +58,8 @@ ButtonDropDown::~ButtonDropDown() {
////////////////////////////////////////////////////////////////////////////////
bool ButtonDropDown::OnMousePressed(const MouseEvent& event) {
if (enabled() && IsTriggerableEvent(event) && HitTest(event.location())) {
if (enabled() && ShouldShowMenu() &&
IsTriggerableEvent(event) && HitTest(event.location())) {
// Store the y pos of the mouse coordinates so we can use them later to
// determine if the user dragged the mouse down (which should pop up the
// drag down menu immediately, instead of waiting for the timer)
......@@ -59,8 +69,7 @@ bool ButtonDropDown::OnMousePressed(const MouseEvent& event) {
MessageLoop::current()->PostDelayedTask(
FROM_HERE,
base::Bind(&ButtonDropDown::ShowDropDownMenu,
show_menu_factory_.GetWeakPtr(),
GetWidget()->GetNativeView()),
show_menu_factory_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kMenuTimerDelay));
}
return ImageButton::OnMousePressed(event);
......@@ -75,7 +84,7 @@ bool ButtonDropDown::OnMouseDragged(const MouseEvent& event) {
// it immediately.
if (event.y() > y_position_on_lbuttondown_ + GetHorizontalDragThreshold()) {
show_menu_factory_.InvalidateWeakPtrs();
ShowDropDownMenu(GetWidget()->GetNativeView());
ShowDropDownMenu();
}
}
......@@ -93,7 +102,7 @@ void ButtonDropDown::OnMouseReleased(const MouseEvent& event) {
if (enabled() && event.IsRightMouseButton() && HitTest(event.location())) {
show_menu_factory_.InvalidateWeakPtrs();
ShowDropDownMenu(GetWidget()->GetNativeView());
ShowDropDownMenu();
}
}
......@@ -112,7 +121,7 @@ void ButtonDropDown::OnMouseExited(const MouseEvent& event) {
void ButtonDropDown::ShowContextMenu(const gfx::Point& p,
bool is_mouse_gesture) {
show_menu_factory_.InvalidateWeakPtrs();
ShowDropDownMenu(GetWidget()->GetNativeView());
ShowDropDownMenu();
SetState(BS_HOT);
}
......@@ -132,7 +141,14 @@ bool ButtonDropDown::ShouldEnterPushedState(const Event& event) {
ui::EF_RIGHT_MOUSE_BUTTON) & event.flags()) != 0);
}
void ButtonDropDown::ShowDropDownMenu(gfx::NativeView window) {
bool ButtonDropDown::ShouldShowMenu() {
return true;
}
void ButtonDropDown::ShowDropDownMenu() {
if (!ShouldShowMenu())
return;
gfx::Rect lb = GetLocalBounds();
// Both the menu position and the menu anchor type change if the UI layout
......@@ -156,27 +172,35 @@ void ButtonDropDown::ShowDropDownMenu(gfx::NativeView window) {
// Make the button look depressed while the menu is open.
SetState(BS_PUSHED);
menu_showing_ = true;
// Create and run menu. Display an empty menu if model is NULL.
if (model_) {
MenuModelAdapter menu_delegate(model_);
menu_delegate.set_triggerable_event_flags(triggerable_event_flags());
MenuRunner runner(menu_delegate.CreateMenu());
if (runner.RunMenuAt(GetWidget(), NULL,
gfx::Rect(menu_position, gfx::Size(0, 0)),
MenuItemView::TOPLEFT,
MenuRunner::HAS_MNEMONICS) == MenuRunner::MENU_DELETED)
menu_runner_.reset(new MenuRunner(menu_delegate.CreateMenu()));
MenuRunner::RunResult result =
menu_runner_->RunMenuAt(GetWidget(), NULL,
gfx::Rect(menu_position, gfx::Size(0, 0)),
MenuItemView::TOPLEFT,
MenuRunner::HAS_MNEMONICS);
if (result == MenuRunner::MENU_DELETED)
return;
} else {
MenuDelegate menu_delegate;
MenuItemView* menu = new MenuItemView(&menu_delegate);
MenuRunner runner(menu);
if (runner.RunMenuAt(GetWidget(), NULL,
gfx::Rect(menu_position, gfx::Size(0, 0)),
views::MenuItemView::TOPLEFT,
MenuRunner::HAS_MNEMONICS) == MenuRunner::MENU_DELETED)
menu_runner_.reset(new MenuRunner(menu));
MenuRunner::RunResult result =
menu_runner_->RunMenuAt(GetWidget(), NULL,
gfx::Rect(menu_position, gfx::Size(0, 0)),
MenuItemView::TOPLEFT,
MenuRunner::HAS_MNEMONICS);
if (result == MenuRunner::MENU_DELETED)
return;
}
menu_showing_ = false;
// Need to explicitly clear mouse handler so that events get sent
// properly after the menu finishes running. If we don't do this, then
// the first click to other parts of the UI is eaten.
......
......@@ -14,6 +14,8 @@ class MenuModel;
namespace views {
class MenuRunner;
////////////////////////////////////////////////////////////////////////////////
//
// ButtonDropDown
......@@ -30,6 +32,12 @@ class VIEWS_EXPORT ButtonDropDown : public ImageButton {
ButtonDropDown(ButtonListener* listener, ui::MenuModel* model);
virtual ~ButtonDropDown();
// If menu is currently pending for long press - stop it.
void ClearPendingMenu();
// Indicates if menu is currently showing.
bool IsMenuShowing() const;
// Overridden from views::View
virtual bool OnMousePressed(const MouseEvent& event) OVERRIDE;
virtual bool OnMouseDragged(const MouseEvent& event) OVERRIDE;
......@@ -51,16 +59,25 @@ class VIEWS_EXPORT ButtonDropDown : public ImageButton {
// to the PUSHED state.
virtual bool ShouldEnterPushedState(const Event& event) OVERRIDE;
private:
// Internal function to show the dropdown menu
void ShowDropDownMenu(gfx::NativeView window);
// Returns if menu should be shown. Override this to change default behavior.
virtual bool ShouldShowMenu();
// Function to show the dropdown menu.
virtual void ShowDropDownMenu();
private:
// The model that populates the attached menu.
ui::MenuModel* model_;
// Indicates if menu is currently showing.
bool menu_showing_;
// Y position of mouse when left mouse button is pressed
int y_position_on_lbuttondown_;
// Menu runner to display drop down menu.
scoped_ptr<MenuRunner> menu_runner_;
// A factory for tasks that show the dropdown context menu for the button.
base::WeakPtrFactory<ButtonDropDown> show_menu_factory_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment