diff options
Diffstat (limited to 'chrome/browser/gtk/gtk_chrome_link_button.cc')
-rw-r--r-- | chrome/browser/gtk/gtk_chrome_link_button.cc | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/chrome/browser/gtk/gtk_chrome_link_button.cc b/chrome/browser/gtk/gtk_chrome_link_button.cc new file mode 100644 index 0000000..3fbb7e5 --- /dev/null +++ b/chrome/browser/gtk/gtk_chrome_link_button.cc @@ -0,0 +1,141 @@ +// 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/gtk_chrome_link_button.h" + +#include "base/logging.h" + +static const char* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>"; + +namespace { + +// Set the GTK style on our custom link button. We don't want any border around +// the link text. +void SetLinkButtonStyle() { + static bool style_was_set = false; + + if (style_was_set) + return; + style_was_set = true; + + gtk_rc_parse_string( + "style \"chrome-link-button\" {" + " GtkButton::inner-border = {0, 0, 0, 0}" + " xthickness = 0" + " ythickness = 0" + "}" + "widget \"*chrome-link-button\" style \"chrome-link-button\""); +} + +} // namespace + +G_BEGIN_DECLS +G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) + +static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, + GdkEventExpose* event) { + GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); + GtkWidget* label = button->label; + + if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) { + gtk_label_set_markup(GTK_LABEL(label), button->red_markup); + button->is_blue = FALSE; + } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) { + gtk_label_set_markup(GTK_LABEL(label), button->blue_markup); + button->is_blue = TRUE; + } + + // Draw the link inside the button. + gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); + + // Draw the focus rectangle. + if (GTK_WIDGET_HAS_FOCUS(widget)) { + gtk_paint_focus(widget->style, widget->window, + static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)), + &event->area, widget, NULL, + widget->allocation.x, widget->allocation.y, + widget->allocation.width, widget->allocation.height); + } + + return TRUE; +} + +static void gtk_chrome_link_button_enter(GtkButton* button) { + GtkWidget* widget = GTK_WIDGET(button); + GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button); + gdk_window_set_cursor(widget->window, link_button->hand_cursor); +} + +static void gtk_chrome_link_button_leave(GtkButton* button) { + GtkWidget* widget = GTK_WIDGET(button); + gdk_window_set_cursor(widget->window, NULL); +} + +static void gtk_chrome_link_button_destroy(GtkObject* object) { + GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object); + if (button->blue_markup) { + g_free(button->blue_markup); + button->blue_markup = NULL; + } + if (button->red_markup) { + g_free(button->red_markup); + button->red_markup = NULL; + } + if (button->hand_cursor) { + gdk_cursor_unref(button->hand_cursor); + button->hand_cursor = NULL; + } + + GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object); +} + +static void gtk_chrome_link_button_class_init( + GtkChromeLinkButtonClass* link_button_class) { + GtkWidgetClass* widget_class = + reinterpret_cast<GtkWidgetClass*>(link_button_class); + GtkButtonClass* button_class = + reinterpret_cast<GtkButtonClass*>(link_button_class); + GtkObjectClass* object_class = + reinterpret_cast<GtkObjectClass*>(link_button_class); + widget_class->expose_event = >k_chrome_link_button_expose; + button_class->enter = >k_chrome_link_button_enter; + button_class->leave = >k_chrome_link_button_leave; + object_class->destroy = >k_chrome_link_button_destroy; +} + +static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { + SetLinkButtonStyle(); + + // 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. + button->label = gtk_label_new(NULL); + button->blue_markup = NULL; + button->red_markup = NULL; + button->is_blue = TRUE; + button->hand_cursor = gdk_cursor_new(GDK_HAND2); + + gtk_container_add(GTK_CONTAINER(button), button->label); + gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button"); + gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); +} + +static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button, + const char* text) { + // We should have only been called once or we'd leak the markups. + DCHECK(!button->blue_markup && !button->red_markup); + + button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text); + button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); + gtk_label_set_markup(GTK_LABEL(button->label), button->blue_markup); + button->is_blue = TRUE; +} + +GtkWidget* gtk_chrome_link_button_new(const char* text) { + GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); + gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), text); + return lb; +} + +G_END_DECLS |