diff options
-rw-r--r-- | chrome/browser/gtk/download_shelf_gtk.cc | 67 | ||||
-rw-r--r-- | chrome/browser/gtk/download_shelf_gtk.h | 4 | ||||
-rw-r--r-- | chrome/browser/gtk/link_button_gtk.cc | 65 | ||||
-rw-r--r-- | chrome/browser/gtk/link_button_gtk.h | 37 | ||||
-rw-r--r-- | chrome/chrome.gyp | 2 |
5 files changed, 115 insertions, 60 deletions
diff --git a/chrome/browser/gtk/download_shelf_gtk.cc b/chrome/browser/gtk/download_shelf_gtk.cc index 9ba9f4a..3e46436 100644 --- a/chrome/browser/gtk/download_shelf_gtk.cc +++ b/chrome/browser/gtk/download_shelf_gtk.cc @@ -8,6 +8,7 @@ #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/download_item_gtk.h" +#include "chrome/browser/gtk/link_button_gtk.h" #include "chrome/browser/tab_contents/tab_contents.h" #include "chrome/common/l10n_util.h" #include "chrome/common/resource_bundle.h" @@ -39,55 +40,6 @@ static GdkColor kBackgroundColor = GDK_COLOR_RGB(230, 237, 244); // Border color (the top pixel of the shelf). static GdkColor kBorderColor = GDK_COLOR_RGB(214, 214, 214); -const char* kLinkMarkup = - "<u><span color=\"blue\">%s</span></u>"; - -gboolean OnLinkExpose(GtkWidget* widget, GdkEventExpose* e, void*) { - // Draw the link inside the button. - gtk_container_propagate_expose(GTK_CONTAINER(widget), - gtk_bin_get_child(GTK_BIN(widget)), - e); - // Don't let the button draw itself, ever. - return TRUE; -} - -// |button| and |box| are out parameters. The caller of this function will want -// to connect to the click event on |button|. |box| will be set to the highest -// level widget. -// TODO(estade): either figure out a way to use GtkLinkButton, or move this -// to base/gfx/gtk_util.cc -void MakeLinkButton(const char* text, GdkColor* background_color, - GtkWidget** button, GtkWidget** box) { - // We put a label in a button so we can connect to the click event. We put the - // button in an event box so we can attach a cursor to it. We don't let the - // button draw itself; catch all expose events to the button and pass them - // through to the label. We stick the event box in an hbox, and to the left of - // that pack the download icon. - // TODO(estade): the link should turn red during the user's click. - - GtkWidget* label = gtk_label_new(NULL); - char* markup = g_markup_printf_escaped(kLinkMarkup, text); - gtk_label_set_markup(GTK_LABEL(label), markup); - g_free(markup); - - *button = gtk_button_new(); - gtk_widget_set_app_paintable(GTK_WIDGET(*button), TRUE); - g_signal_connect(G_OBJECT(*button), "expose-event", - G_CALLBACK(OnLinkExpose), NULL); - gtk_container_add(GTK_CONTAINER(*button), label); - - *box = gtk_event_box_new(); - gtk_widget_modify_bg(*box, GTK_STATE_NORMAL, background_color); - gtk_container_add(GTK_CONTAINER(*box), *button); -} - -// This should be called only after |link_box| has been realized. -void AttachCursorToLinkButton(GtkWidget* link_box) { - GdkCursor* cursor = gdk_cursor_new(GDK_HAND2); - gdk_window_set_cursor(link_box->window, cursor); - gdk_cursor_unref(cursor); -} - } // namespace // static @@ -131,18 +83,14 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) // Create and pack the close button. close_button_.reset(CustomDrawButton::AddBarCloseButton(hbox_)); - g_signal_connect(G_OBJECT(close_button_->widget()), "clicked", + g_signal_connect(close_button_->widget(), "clicked", G_CALLBACK(OnButtonClick), this); - // Create and pack the "Show all downloads..." link. - // TODO(estade): there are some pixels above and below the link that - // can be clicked. I tried to fix this with a vbox, but no dice. - GtkWidget* link_box; - GtkWidget* link_button; + // Create the "Show all downloads..." link and connect to the click event. std::string link_text = WideToUTF8(l10n_util::GetString(IDS_SHOW_ALL_DOWNLOADS)); - MakeLinkButton(link_text.c_str(), &kBackgroundColor, &link_button, &link_box); - g_signal_connect(G_OBJECT(link_button), "clicked", + link_button_.reset(new LinkButtonGtk(link_text.c_str())); + g_signal_connect(link_button_->widget(), "clicked", G_CALLBACK(OnButtonClick), this); // Make the download arrow icon. @@ -154,15 +102,14 @@ DownloadShelfGtk::DownloadShelfGtk(TabContents* tab_contents) // Pack the link and the icon in an hbox. link_hbox_ = gtk_hbox_new(FALSE, 0); gtk_box_pack_start(GTK_BOX(link_hbox_), download_image, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(link_hbox_), link_box, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(link_hbox_), link_button_->widget(), + FALSE, FALSE, 0); gtk_box_pack_end(GTK_BOX(hbox_), link_hbox_, FALSE, FALSE, 0); // Stick ourselves at the bottom of the parent tab contents. GtkWidget* parent_contents = tab_contents->GetNativeView(); gtk_box_pack_end(GTK_BOX(parent_contents), shelf_, FALSE, FALSE, 0); Show(); - - AttachCursorToLinkButton(link_box); } DownloadShelfGtk::~DownloadShelfGtk() { diff --git a/chrome/browser/gtk/download_shelf_gtk.h b/chrome/browser/gtk/download_shelf_gtk.h index 89f2fc9..78297d1 100644 --- a/chrome/browser/gtk/download_shelf_gtk.h +++ b/chrome/browser/gtk/download_shelf_gtk.h @@ -15,6 +15,7 @@ class BaseDownloadItemModel; class CustomDrawButton; class DownloadItemGtk; +class LinkButtonGtk; class DownloadShelfGtk : public DownloadShelf { public: @@ -46,6 +47,9 @@ class DownloadShelfGtk : public DownloadShelf { // distinction of being the leftmost non-download item widget on the shelf. GtkWidget* link_hbox_; + // The clickable "Show all downloads..." link text. + scoped_ptr<LinkButtonGtk> link_button_; + // The 'x' that the user can press to hide the download shelf. scoped_ptr<CustomDrawButton> close_button_; diff --git a/chrome/browser/gtk/link_button_gtk.cc b/chrome/browser/gtk/link_button_gtk.cc new file mode 100644 index 0000000..4b1d010 --- /dev/null +++ b/chrome/browser/gtk/link_button_gtk.cc @@ -0,0 +1,65 @@ +// 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/link_button_gtk.h" + +static const char* kLinkMarkup = "<u><span color=\"blue\">%s</span></u>"; + +LinkButtonGtk::LinkButtonGtk(const char* text) + : hand_cursor_(gdk_cursor_new(GDK_HAND2)) { + // We put a label in a button so we can connect to the click event. We don't + // let the button draw itself; catch all expose events to the button and pass + // them through to the label. + // TODO(estade): the link should turn red during the user's click. + GtkWidget* label = gtk_label_new(NULL); + char* markup = g_markup_printf_escaped(kLinkMarkup, text); + gtk_label_set_markup(GTK_LABEL(label), markup); + g_free(markup); + + widget_.Own(gtk_button_new()); + gtk_widget_set_app_paintable(widget_.get(), TRUE); + g_signal_connect(widget_.get(), "expose-event", + G_CALLBACK(OnExpose), NULL); + // We connect to these signals so we can set the cursor appropriately. We + // could give the link button its own GdkWindow (e.g. by placing it in a + // GtkEventBox), but that would wreak havok with painting of the parent + // widget. We can't use the enter- and leave- notify events as they operate + // on the widget's GdkWindow, and |label| nor |button| has its own GdkWindow. + g_signal_connect(widget_.get(), "enter", + G_CALLBACK(OnEnter), this); + g_signal_connect(widget_.get(), "leave", + G_CALLBACK(OnLeave), this); + gtk_container_add(GTK_CONTAINER(widget_.get()), label); +} + +LinkButtonGtk::~LinkButtonGtk() { + gdk_cursor_unref(hand_cursor_); + widget_.Destroy(); +} + +// static +gboolean LinkButtonGtk::OnEnter(GtkWidget* widget, + LinkButtonGtk* link_button) { + gdk_window_set_cursor(widget->window, link_button->hand_cursor_); + return FALSE; +} + +// static +gboolean LinkButtonGtk::OnLeave(GtkWidget* widget, + LinkButtonGtk* link_button) { + gdk_window_set_cursor(widget->window, NULL); + return FALSE; +} + +// static +gboolean LinkButtonGtk::OnExpose(GtkWidget* widget, + GdkEventExpose* event, + gpointer user_data) { + // Draw the link inside the button. + gtk_container_propagate_expose(GTK_CONTAINER(widget), + gtk_bin_get_child(GTK_BIN(widget)), + event); + // Don't let the button draw itself, ever. + return TRUE; +} diff --git a/chrome/browser/gtk/link_button_gtk.h b/chrome/browser/gtk/link_button_gtk.h new file mode 100644 index 0000000..2dfce7d --- /dev/null +++ b/chrome/browser/gtk/link_button_gtk.h @@ -0,0 +1,37 @@ +// 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 <gdk/gdk.h> +#include <gtk/gtk.h> + +#include "chrome/common/owned_widget_gtk.h" + +// Creates a link button that shows |text| in blue and underlined. The cursor +// changes to a hand when over the link. +// TODO(estade): the link should turn red during the user's click. +class LinkButtonGtk { + public: + explicit LinkButtonGtk(const char* text); + virtual ~LinkButtonGtk(); + + GtkWidget* widget() { return widget_.get(); } + + private: + // Called when the pointer enters or leaves the button. + static gboolean OnEnter(GtkWidget* widget, LinkButtonGtk* link_button); + static gboolean OnLeave(GtkWidget* widget, LinkButtonGtk* link_button); + + // Called when the pointer moves over the link button's gdk window. + static gboolean OnMotionNotify(GtkWidget* widget, + GdkEventMotion* event, + LinkButtonGtk* link_button); + + // Called when the widget is exposed. + static gboolean OnExpose(GtkWidget* widget, + GdkEventExpose* event, + gpointer user_data); + + OwnedWidgetGtk widget_; + GdkCursor* hand_cursor_; +}; diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp index b38c506..cc402c5 100644 --- a/chrome/chrome.gyp +++ b/chrome/chrome.gyp @@ -725,6 +725,8 @@ 'browser/gtk/infobar_container_gtk.h', 'browser/gtk/find_bar_gtk.cc', 'browser/gtk/find_bar_gtk.h', + 'browser/gtk/link_button_gtk.cc', + 'browser/gtk/link_button_gtk.cc', 'browser/gtk/location_bar_view_gtk.cc', 'browser/gtk/location_bar_view_gtk.h', 'browser/gtk/menu_gtk.cc', |