diff options
author | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-09 06:40:57 +0000 |
---|---|---|
committer | willchan@chromium.org <willchan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-04-09 06:40:57 +0000 |
commit | 64f001a8a74f5d861d9948155c92419f53928e50 (patch) | |
tree | 4f215495257c68c34f8f1bbc4724e35a73be1788 | |
parent | 253071feeaf010115a8fbe498d1ebd634c2d1626 (diff) | |
download | chromium_src-64f001a8a74f5d861d9948155c92419f53928e50.zip chromium_src-64f001a8a74f5d861d9948155c92419f53928e50.tar.gz chromium_src-64f001a8a74f5d861d9948155c92419f53928e50.tar.bz2 |
Implement stop/go button for Linux.
Refactored code out of CustomDrawButton into CustomDrawButtonBase to be shared with GoButtonGtk.
Replaced the existing non-togglable go button with GoButtonGtk.
Note that tooltip support isn't done yet, as it changes based on the state of the location bar and the go/stop state.
Add a simple test.
Fix some minor lint errors.
BUG=9381
Review URL: http://codereview.chromium.org/62154
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@13409 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.cc | 8 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_toolbar_gtk.h | 5 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 5 | ||||
-rw-r--r-- | chrome/browser/gtk/custom_button.cc | 63 | ||||
-rw-r--r-- | chrome/browser/gtk/custom_button.h | 32 | ||||
-rw-r--r-- | chrome/browser/gtk/go_button_gtk.cc | 156 | ||||
-rw-r--r-- | chrome/browser/gtk/go_button_gtk.h | 76 | ||||
-rw-r--r-- | chrome/browser/gtk/go_button_gtk_unittest.cc | 130 | ||||
-rw-r--r-- | chrome/browser/views/go_button.cc | 3 | ||||
-rw-r--r-- | chrome/browser/views/go_button.h | 9 | ||||
-rw-r--r-- | chrome/chrome.gyp | 5 |
11 files changed, 452 insertions, 40 deletions
diff --git a/chrome/browser/gtk/browser_toolbar_gtk.cc b/chrome/browser/gtk/browser_toolbar_gtk.cc index 37cbd5d..8455157 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.cc +++ b/chrome/browser/gtk/browser_toolbar_gtk.cc @@ -13,6 +13,7 @@ #include "chrome/browser/browser.h" #include "chrome/browser/gtk/back_forward_menu_model_gtk.h" #include "chrome/browser/gtk/custom_button.h" +#include "chrome/browser/gtk/go_button_gtk.h" #include "chrome/browser/gtk/location_bar_view_gtk.h" #include "chrome/browser/gtk/nine_box.h" #include "chrome/browser/gtk/standard_menus.h" @@ -121,7 +122,8 @@ void BrowserToolbarGtk::Init(Profile* profile, location_bar_->Init(); gtk_box_pack_start(GTK_BOX(toolbar_), location_bar_->widget(), TRUE, TRUE, 0); - go_.reset(BuildToolbarButton(IDR_GO, IDR_GO_P, IDR_GO_H, 0, L"")); + go_.reset(new GoButtonGtk(browser_)); + gtk_box_pack_start(GTK_BOX(toolbar_), go_->widget(), FALSE, FALSE, 0); gtk_box_pack_start(GTK_BOX(toolbar_), gtk_label_new(" "), FALSE, FALSE, 0); @@ -285,8 +287,6 @@ void BrowserToolbarGtk::OnButtonClick(GtkWidget* button, tag = IDC_FORWARD; else if (button == toolbar->reload_->widget()) tag = IDC_RELOAD; - else if (button == toolbar->go_->widget()) - tag = IDC_GO; else if (toolbar->home_.get() && button == toolbar->home_->widget()) tag = IDC_HOME; else if (button == toolbar->star_->widget()) @@ -295,7 +295,7 @@ void BrowserToolbarGtk::OnButtonClick(GtkWidget* button, if (tag == IDC_BACK || tag == IDC_FORWARD) toolbar->show_menu_factory_.RevokeAll(); - DCHECK(tag != -1) << "Impossible button click callback"; + DCHECK_NE(tag, -1) << "Impossible button click callback"; toolbar->browser_->ExecuteCommand(tag); } diff --git a/chrome/browser/gtk/browser_toolbar_gtk.h b/chrome/browser/gtk/browser_toolbar_gtk.h index 1223061..3f391a7 100644 --- a/chrome/browser/gtk/browser_toolbar_gtk.h +++ b/chrome/browser/gtk/browser_toolbar_gtk.h @@ -18,6 +18,7 @@ class BackForwardMenuModelGtk; class Browser; class CustomContainerButton; class CustomDrawButton; +class GoButtonGtk; class LocationBar; class LocationBarViewGtk; class NineBox; @@ -47,6 +48,8 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, virtual LocationBar* GetLocationBar() const; + GoButtonGtk* GetGoButton() { return go_.get(); } + // Overridden from CommandUpdater::CommandObserver: virtual void EnabledStateChangedForCommand(int id, bool enabled); @@ -130,7 +133,7 @@ class BrowserToolbarGtk : public CommandUpdater::CommandObserver, scoped_ptr<CustomDrawButton> reload_; scoped_ptr<CustomDrawButton> home_; // May be NULL. scoped_ptr<ToolbarStarToggleGtk> star_; - scoped_ptr<CustomDrawButton> go_; + scoped_ptr<GoButtonGtk> go_; scoped_ptr<CustomContainerButton> page_menu_button_, app_menu_button_; // The model that contains the security level, text, icon to display... diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 7e0e81e..d8417ab 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -20,6 +20,7 @@ #include "chrome/browser/browser_list.h" #include "chrome/browser/gtk/bookmark_bar_gtk.h" #include "chrome/browser/gtk/browser_toolbar_gtk.h" +#include "chrome/browser/gtk/go_button_gtk.h" #include "chrome/browser/gtk/infobar_container_gtk.h" #include "chrome/browser/gtk/find_bar_gtk.h" #include "chrome/browser/gtk/status_bubble_gtk.h" @@ -413,8 +414,8 @@ void BrowserWindowGtk::SetFocusToLocationBar() { } void BrowserWindowGtk::UpdateStopGoState(bool is_loading) { - // Need to implement stop/go button. - // http://code.google.com/p/chromium/issues/detail?id=9381 + toolbar_->GetGoButton()->ChangeMode( + is_loading ? GoButtonGtk::MODE_STOP : GoButtonGtk::MODE_GO); } void BrowserWindowGtk::UpdateToolbar(TabContents* contents, diff --git a/chrome/browser/gtk/custom_button.cc b/chrome/browser/gtk/custom_button.cc index 150d29f..4ff475c 100644 --- a/chrome/browser/gtk/custom_button.cc +++ b/chrome/browser/gtk/custom_button.cc @@ -10,10 +10,11 @@ #include "grit/theme_resources.h" -CustomDrawButton::CustomDrawButton(int normal_id, - int active_id, int highlight_id, int depressed_id) { - widget_.Own(gtk_button_new()); - +CustomDrawButtonBase::CustomDrawButtonBase( + int normal_id, + int active_id, + int highlight_id, + int depressed_id) { // Load the button images from the resource bundle. ResourceBundle& rb = ResourceBundle::GetSharedInstance(); pixbufs_[GTK_STATE_NORMAL] = normal_id ? rb.LoadPixbuf(normal_id) : NULL; @@ -23,35 +24,21 @@ CustomDrawButton::CustomDrawButton(int normal_id, pixbufs_[GTK_STATE_SELECTED] = NULL; pixbufs_[GTK_STATE_INSENSITIVE] = depressed_id ? rb.LoadPixbuf(depressed_id) : NULL; - - gtk_widget_set_size_request(widget_.get(), - gdk_pixbuf_get_width(pixbufs_[0]), - gdk_pixbuf_get_height(pixbufs_[0])); - - gtk_widget_set_app_paintable(widget_.get(), TRUE); - // We effectively double-buffer by virtue of having only one image... - gtk_widget_set_double_buffered(widget_.get(), FALSE); - g_signal_connect(G_OBJECT(widget_.get()), "expose-event", - G_CALLBACK(OnExpose), this); } -CustomDrawButton::~CustomDrawButton() { +CustomDrawButtonBase::~CustomDrawButtonBase() { for (size_t i = 0; i < arraysize(pixbufs_); ++i) { if (pixbufs_[i]) - gdk_pixbuf_unref(pixbufs_[i]); + g_object_unref(pixbufs_[i]); } - - widget_.Destroy(); } -// static -gboolean CustomDrawButton::OnExpose(GtkWidget* widget, GdkEventExpose* e, - CustomDrawButton* button) { - GdkPixbuf* pixbuf = button->pixbufs_[GTK_WIDGET_STATE(widget)]; +gboolean CustomDrawButtonBase::OnExpose(GtkWidget* widget, GdkEventExpose* e) { + GdkPixbuf* pixbuf = pixbufs(GTK_WIDGET_STATE(widget)); // Fall back to the default image if we don't have one for this state. if (!pixbuf) - pixbuf = button->pixbufs_[GTK_STATE_NORMAL]; + pixbuf = pixbufs(GTK_STATE_NORMAL); if (!pixbuf) return FALSE; @@ -66,6 +53,36 @@ gboolean CustomDrawButton::OnExpose(GtkWidget* widget, GdkEventExpose* e, return TRUE; } +CustomDrawButton::CustomDrawButton( + int normal_id, + int active_id, + int highlight_id, + int depressed_id) + : button_base_(normal_id, active_id, highlight_id, depressed_id) { + widget_.Own(gtk_button_new()); + + gtk_widget_set_size_request(widget_.get(), + gdk_pixbuf_get_width(button_base_.pixbufs(0)), + gdk_pixbuf_get_height(button_base_.pixbufs(0))); + + gtk_widget_set_app_paintable(widget_.get(), TRUE); + // We effectively double-buffer by virtue of having only one image... + gtk_widget_set_double_buffered(widget_.get(), FALSE); + g_signal_connect(G_OBJECT(widget_.get()), "expose-event", + G_CALLBACK(OnExpose), this); +} + +CustomDrawButton::~CustomDrawButton() { + widget_.Destroy(); +} + +// static +gboolean CustomDrawButton::OnExpose(GtkWidget* widget, + GdkEventExpose* e, + CustomDrawButton* button) { + return button->button_base_.OnExpose(widget, e); +} + // static CustomDrawButton* CustomDrawButton::AddBarCloseButton(GtkWidget* hbox) { CustomDrawButton* rv = new CustomDrawButton(IDR_CLOSE_BAR, IDR_CLOSE_BAR_P, diff --git a/chrome/browser/gtk/custom_button.h b/chrome/browser/gtk/custom_button.h index 518f069..96b4ad6 100644 --- a/chrome/browser/gtk/custom_button.h +++ b/chrome/browser/gtk/custom_button.h @@ -17,6 +17,29 @@ class NineBox; // These classes implement two kinds of custom-drawn buttons. They're // used on the toolbar and the bookmarks bar. +// CustomDrawButtonBase provides the base for building a custom drawn button. +// It handles managing the pixbufs containing all the static images used to draw +// the button. It also manages painting these pixbufs. +class CustomDrawButtonBase { + public: + CustomDrawButtonBase(int normal_id, + int active_id, + int highlight_id, + int depressed_id); + ~CustomDrawButtonBase(); + + GdkPixbuf* pixbufs(int i) const { return pixbufs_[i]; } + + gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e); + + private: + // We store one GdkPixbuf* for each possible state of the button; + // INSENSITIVE is the last available state; + GdkPixbuf* pixbufs_[GTK_STATE_INSENSITIVE + 1]; + + DISALLOW_COPY_AND_ASSIGN(CustomDrawButtonBase); +}; + // CustomDrawButton is a plain button where all its various states are drawn // with static images. class CustomDrawButton { @@ -40,15 +63,16 @@ class CustomDrawButton { private: // Callback for expose, used to draw the custom graphics. - static gboolean OnExpose(GtkWidget* widget, GdkEventExpose* e, + static gboolean OnExpose(GtkWidget* widget, + GdkEventExpose* e, CustomDrawButton* obj); // The actual button widget. OwnedWidgetGtk widget_; - // We store one GdkPixbuf* for each possible state of the button; - // INSENSITIVE is the last available state; - GdkPixbuf* pixbufs_[GTK_STATE_INSENSITIVE + 1]; + CustomDrawButtonBase button_base_; + + DISALLOW_COPY_AND_ASSIGN(CustomDrawButton); }; // CustomContainerButton wraps another widget and uses a NineBox of diff --git a/chrome/browser/gtk/go_button_gtk.cc b/chrome/browser/gtk/go_button_gtk.cc new file mode 100644 index 0000000..2f32e64 --- /dev/null +++ b/chrome/browser/gtk/go_button_gtk.cc @@ -0,0 +1,156 @@ +// Copyright (c) 2009 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. + +#include "chrome/browser/gtk/go_button_gtk.h" +#include "base/logging.h" +#include "base/message_loop.h" +#include "chrome/app/chrome_dll_resource.h" +#include "chrome/browser/browser.h" +#include "grit/theme_resources.h" + +GoButtonGtk::GoButtonGtk(Browser* browser) + : browser_(browser), + button_delay_(0), + stop_timer_(this), + intended_mode_(MODE_GO), + visible_mode_(MODE_GO), + state_(BS_NORMAL), + go_(IDR_GO, IDR_GO_P, IDR_GO_H, 0), + stop_(IDR_STOP, IDR_STOP_P, IDR_STOP_H, 0), + widget_(gtk_button_new()) { + gtk_widget_set_size_request(widget_.get(), + gdk_pixbuf_get_width(go_.pixbufs(0)), + gdk_pixbuf_get_height(go_.pixbufs(0))); + + gtk_widget_set_app_paintable(widget_.get(), TRUE); + // We effectively double-buffer by virtue of having only one image... + gtk_widget_set_double_buffered(widget_.get(), FALSE); + + g_signal_connect(G_OBJECT(widget_.get()), "expose-event", + G_CALLBACK(OnExpose), this); + g_signal_connect(G_OBJECT(widget_.get()), "enter", + G_CALLBACK(OnEnter), this); + g_signal_connect(G_OBJECT(widget_.get()), "leave", + G_CALLBACK(OnLeave), this); + g_signal_connect(G_OBJECT(widget_.get()), "clicked", + G_CALLBACK(OnClicked), this); + GTK_WIDGET_UNSET_FLAGS(widget_.get(), GTK_CAN_FOCUS); + + // TODO(willchan): Implement tooltips. + gtk_widget_set_tooltip_text(widget_.get(), "Implement toggleable tooltips"); +} + +GoButtonGtk::~GoButtonGtk() { + widget_.Destroy(); +} + +void GoButtonGtk::ChangeMode(Mode mode) { + if (mode != visible_mode_) { + gtk_widget_queue_draw(widget_.get()); + } + stop_timer_.RevokeAll(); + intended_mode_ = mode; + visible_mode_ = mode; +} + +void GoButtonGtk::ScheduleChangeMode(Mode mode) { + if (mode == MODE_STOP) { + // If we still have a timer running, we can't yet change to a stop sign, + // so we'll queue up the change for when the timer expires or for when + // the mouse exits the button. + if (!stop_timer_.empty() && state() == BS_HOT) { + intended_mode_ = MODE_STOP; + } else { + ChangeMode(MODE_STOP); + } + } else { + // If we want to change the button to a go button, but the user's mouse + // is hovering, don't change the mode just yet - this prevents the + // stop button changing to a go under the user's mouse cursor. + if (visible_mode_ == MODE_STOP && state() == BS_HOT) { + intended_mode_ = MODE_GO; + } else { + ChangeMode(MODE_GO); + } + } +} + +Task* GoButtonGtk::CreateButtonTimerTask() { + return stop_timer_.NewRunnableMethod(&GoButtonGtk::OnButtonTimer); +} + +void GoButtonGtk::OnButtonTimer() { + if (intended_mode_ != visible_mode_) { + ChangeMode(intended_mode_); + } + + stop_timer_.RevokeAll(); +} + +// static +gboolean GoButtonGtk::OnExpose(GtkWidget* widget, + GdkEventExpose* e, + GoButtonGtk* button) { + if (button->visible_mode_ == MODE_GO) { + return button->go_.OnExpose(widget, e); + } else { + return button->stop_.OnExpose(widget, e); + } +} + +// static +gboolean GoButtonGtk::OnEnter(GtkButton* widget, GoButtonGtk* button) { + DCHECK_EQ(BS_NORMAL, button->state()); + button->state_ = BS_HOT; + return TRUE; +} + +// static +gboolean GoButtonGtk::OnLeave(GtkButton* widget, GoButtonGtk* button) { + DCHECK_EQ(BS_HOT, button->state()); + button->state_ = BS_NORMAL; + if (button->visible_mode_ != button->intended_mode_) { + button->ChangeMode(button->intended_mode_); + } + return TRUE; +} + +// static +gboolean GoButtonGtk::OnClicked(GtkButton* widget, GoButtonGtk* button) { + if (button->visible_mode_ == MODE_STOP) { + if (button->browser_) + button->browser_->Stop(); + + // The user has clicked, so we can feel free to update the button, + // even if the mouse is still hovering. + button->ChangeMode(MODE_GO); + } else if (button->visible_mode_ == MODE_GO && button->stop_timer_.empty()) { + // If the go button is visible and not within the double click timer, go. + if (button->browser_) + button->browser_->ExecuteCommand(IDC_GO); + + // Figure out the system double-click time. + if (button->button_delay_ == 0) { + GtkSettings* settings = gtk_settings_get_default(); + g_object_get(G_OBJECT(settings), + "gtk-double-click-time", + &button->button_delay_, + NULL); + } + + // Stop any existing timers. + button->stop_timer_.RevokeAll(); + + // Start a timer - while this timer is running, the go button + // cannot be changed to a stop button. We do not set intended_mode_ + // to MODE_STOP here as we want to wait for the browser to tell + // us that it has started loading (and this may occur only after + // some delay). + MessageLoop::current()->PostDelayedTask(FROM_HERE, + button->CreateButtonTimerTask(), + button->button_delay_); + } + + return TRUE; +} diff --git a/chrome/browser/gtk/go_button_gtk.h b/chrome/browser/gtk/go_button_gtk.h new file mode 100644 index 0000000..047feec --- /dev/null +++ b/chrome/browser/gtk/go_button_gtk.h @@ -0,0 +1,76 @@ +// Copyright (c) 2009 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_GTK_GO_BUTTON_GTK_H_ +#define CHROME_BROWSER_GTK_GO_BUTTON_GTK_H_ + +#include <gtk/gtk.h> + +#include "base/basictypes.h" +#include "base/task.h" +#include "chrome/browser/gtk/custom_button.h" +#include "chrome/common/owned_widget_gtk.h" + +class Browser; +class Task; + +class GoButtonGtk { + public: + enum Mode { MODE_GO = 0, MODE_STOP }; + enum ButtonState { BS_NORMAL = 0, BS_HOT }; + + explicit GoButtonGtk(Browser* browser); + ~GoButtonGtk(); + + GtkWidget* widget() const { return widget_.get(); } + ButtonState state() const { return state_; } + + // Force the button state. Useful for when the foreground tab changes. + void ChangeMode(Mode mode); + + // Ask for a specified button state. This is called when the loading state of + // the tab changes. This method may postpone the actual ChangeMode() call + // until another event (such as waiting for a potential double click to end, + // or for the mouse to stop hovering over the button). + void ScheduleChangeMode(Mode mode); + + private: + friend class GoButtonGtkPeer; + + // gtk signals + static gboolean OnExpose(GtkWidget* widget, + GdkEventExpose* e, + GoButtonGtk* button); + static gboolean OnEnter(GtkButton* widget, GoButtonGtk* button); + static gboolean OnLeave(GtkButton* widget, GoButtonGtk* button); + static gboolean OnClicked(GtkButton* widget, GoButtonGtk* button); + + Task* CreateButtonTimerTask(); + void OnButtonTimer(); + + // Keep a pointer to the Browser object to execute commands on it. + Browser* const browser_; + + // Delay time to wait before allowing a mode change. This is to prevent a + // mode switch while the user is double clicking. + int button_delay_; + ScopedRunnableMethodFactory<GoButtonGtk> stop_timer_; + + // The mode we should be in + Mode intended_mode_; + + // The currently-visible mode - this may different from the intended mode + Mode visible_mode_; + + ButtonState state_; + + CustomDrawButtonBase go_; + CustomDrawButtonBase stop_; + + OwnedWidgetGtk widget_; + + DISALLOW_COPY_AND_ASSIGN(GoButtonGtk); +}; + +#endif // CHROME_BROWSER_GTK_GO_BUTTON_GTK_H_ diff --git a/chrome/browser/gtk/go_button_gtk_unittest.cc b/chrome/browser/gtk/go_button_gtk_unittest.cc new file mode 100644 index 0000000..723f587 --- /dev/null +++ b/chrome/browser/gtk/go_button_gtk_unittest.cc @@ -0,0 +1,130 @@ +// Copyright (c) 2009 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. + +#include "chrome/browser/gtk/go_button_gtk.h" +#include "base/task.h" +#include "testing/gtest/include/gtest/gtest.h" + +class GoButtonGtkPeer { + public: + explicit GoButtonGtkPeer(GoButtonGtk* go) : go_(go) { } + + // const accessors for internal state + GoButtonGtk::Mode intended_mode() const { return go_->intended_mode_; } + GoButtonGtk::Mode visible_mode() const { return go_->visible_mode_; } + + // mutable accessors for internal state + ScopedRunnableMethodFactory<GoButtonGtk>* stop_timer() { + return &go_->stop_timer_; + } + + // mutators for internal state + void set_state(GoButtonGtk::ButtonState state) { go_->state_ = state; } + void set_intended_mode(GoButtonGtk::Mode mode) { go_->intended_mode_ = mode; } + void set_visible_mode(GoButtonGtk::Mode mode) { go_->visible_mode_ = mode; } + + // forwarders to private methods + Task* CreateButtonTimerTask() { return go_->CreateButtonTimerTask(); } + gboolean OnLeave() { + return GoButtonGtk::OnLeave(GTK_BUTTON(go_->widget()), go_); + } + + gboolean OnClicked() { + return GoButtonGtk::OnClicked(GTK_BUTTON(go_->widget()), go_); + } + + private: + GoButtonGtk* const go_; +}; + +namespace { + +class GoButtonGtkTest : public testing::Test { + protected: + GoButtonGtkTest() : go_(NULL), peer_(&go_) { } + + protected: + GoButtonGtk go_; + GoButtonGtkPeer peer_; +}; + +TEST_F(GoButtonGtkTest, ChangeModeGo) { + go_.ChangeMode(GoButtonGtk::MODE_GO); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ChangeModeStop) { + go_.ChangeMode(GoButtonGtk::MODE_GO); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ScheduleChangeModeNormalGo) { + peer_.set_visible_mode(GoButtonGtk::MODE_STOP); + peer_.set_state(GoButtonGtk::BS_NORMAL); + go_.ScheduleChangeMode(GoButtonGtk::MODE_GO); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ScheduleChangeModeHotGo) { + peer_.set_visible_mode(GoButtonGtk::MODE_STOP); + peer_.set_state(GoButtonGtk::BS_HOT); + go_.ScheduleChangeMode(GoButtonGtk::MODE_GO); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ScheduleChangeModeNormalStop) { + peer_.set_visible_mode(GoButtonGtk::MODE_GO); + peer_.set_state(GoButtonGtk::BS_NORMAL); + go_.ScheduleChangeMode(GoButtonGtk::MODE_STOP); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ScheduleChangeModeHotStop) { + peer_.set_visible_mode(GoButtonGtk::MODE_GO); + peer_.set_state(GoButtonGtk::BS_HOT); + go_.ScheduleChangeMode(GoButtonGtk::MODE_STOP); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, ScheduleChangeModeTimerHotStop) { + peer_.set_visible_mode(GoButtonGtk::MODE_GO); + peer_.set_state(GoButtonGtk::BS_HOT); + scoped_ptr<Task> task(peer_.CreateButtonTimerTask()); + go_.ScheduleChangeMode(GoButtonGtk::MODE_STOP); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.intended_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); +} + +TEST_F(GoButtonGtkTest, OnLeaveIntendedStop) { + peer_.set_state(GoButtonGtk::BS_HOT); + peer_.set_visible_mode(GoButtonGtk::MODE_GO); + peer_.set_intended_mode(GoButtonGtk::MODE_STOP); + EXPECT_TRUE(peer_.OnLeave()); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.visible_mode()); + EXPECT_EQ(GoButtonGtk::MODE_STOP, peer_.intended_mode()); +} + +TEST_F(GoButtonGtkTest, OnLeaveIntendedGo) { + peer_.set_state(GoButtonGtk::BS_HOT); + peer_.set_visible_mode(GoButtonGtk::MODE_STOP); + peer_.set_intended_mode(GoButtonGtk::MODE_GO); + EXPECT_TRUE(peer_.OnLeave()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); +} + +TEST_F(GoButtonGtkTest, OnClickedStop) { + peer_.set_visible_mode(GoButtonGtk::MODE_STOP); + EXPECT_TRUE(peer_.OnClicked()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.visible_mode()); + EXPECT_EQ(GoButtonGtk::MODE_GO, peer_.intended_mode()); +} + +} // namespace diff --git a/chrome/browser/views/go_button.cc b/chrome/browser/views/go_button.cc index 48773ae..f276e92 100644 --- a/chrome/browser/views/go_button.cc +++ b/chrome/browser/views/go_button.cc @@ -4,6 +4,7 @@ #include "chrome/browser/views/go_button.h" +#include "base/message_loop.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/browser.h" #include "chrome/browser/views/event_utils.h" @@ -97,8 +98,6 @@ void GoButton::ButtonPressed(views::Button* button) { // GoButton, View overrides: void GoButton::OnMouseExited(const views::MouseEvent& e) { - using namespace views; - if (visible_mode_ != intended_mode_) ChangeMode(intended_mode_); diff --git a/chrome/browser/views/go_button.h b/chrome/browser/views/go_button.h index a830191..cdd5bea 100644 --- a/chrome/browser/views/go_button.h +++ b/chrome/browser/views/go_button.h @@ -5,8 +5,9 @@ #ifndef CHROME_BROWSER_VIEWS_GO_BUTTON_H__ #define CHROME_BROWSER_VIEWS_GO_BUTTON_H__ -#include "chrome/views/controls/button/image_button.h" +#include "base/basictypes.h" #include "base/task.h" +#include "chrome/views/controls/button/image_button.h" class Browser; class LocationBarView; @@ -26,11 +27,11 @@ class LocationBarView; class GoButton : public views::ToggleImageButton, public views::ButtonListener { public: + typedef enum Mode { MODE_GO = 0, MODE_STOP }; + GoButton(LocationBarView* location_bar, Browser* Browser); virtual ~GoButton(); - typedef enum Mode { MODE_GO = 0, MODE_STOP }; - // Force the button state void ChangeMode(Mode mode); @@ -60,7 +61,7 @@ class GoButton : public views::ToggleImageButton, // The currently-visible mode - this may different from the intended mode Mode visible_mode_; - DISALLOW_EVIL_CONSTRUCTORS(GoButton); + DISALLOW_COPY_AND_ASSIGN(GoButton); }; #endif // CHROME_BROWSER_VIEWS_GO_BUTTON_H__ diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index 4130904..4707153 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -698,6 +698,8 @@ 'browser/gtk/download_item_gtk.h', 'browser/gtk/download_shelf_gtk.cc', 'browser/gtk/download_shelf_gtk.h', + 'browser/gtk/go_button_gtk.cc', + 'browser/gtk/go_button_gtk.h', 'browser/gtk/infobar_gtk.cc', 'browser/gtk/infobar_gtk.h', 'browser/gtk/infobar_container_gtk.cc', @@ -2098,6 +2100,7 @@ 'browser/extensions/test_extension_loader.cc', 'browser/extensions/user_script_master_unittest.cc', 'browser/google_url_tracker_unittest.cc', + 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', 'browser/history/expire_history_backend_unittest.cc', 'browser/history/history_backend_unittest.cc', @@ -2237,6 +2240,7 @@ 'sources!': [ 'browser/back_forward_menu_model_unittest.cc', 'browser/download/download_manager_unittest.cc', + 'browser/gtk/go_button_gtk_unittest.cc', 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', 'browser/navigation_controller_unittest.cc', 'browser/sessions/session_backend_unittest.cc', @@ -2259,6 +2263,7 @@ ], 'sources!': [ 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', + 'browser/gtk/tabs/tab_renderer_gtk_unittest.cc', 'common/file_descriptor_set_unittest.cc', 'common/net/url_util_unittest.cc', ], |