Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" | 5 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "chrome/browser/ui/gtk/gtk_util.h" | 9 #include "chrome/browser/ui/gtk/gtk_util.h" |
| 10 #include "ui/base/gtk/gtk_compat.h" | 10 #include "ui/base/gtk/gtk_compat.h" |
| 11 #include "ui/gfx/gtk_util.h" | 11 #include "ui/gfx/gtk_util.h" |
| 12 | 12 |
| 13 static const gchar* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>"; | 13 static const gchar* kLinkMarkup = "<u><span color=\"%s\">%s</span></u>"; |
| 14 static const gchar* kInsensitiveLinkMarkup = "<span color=\"%s\">%s</span>"; | |
| 14 | 15 |
| 15 namespace { | 16 namespace { |
| 16 | 17 |
| 17 // Set the GTK style on our custom link button. We don't want any border around | 18 // Set the GTK style on our custom link button. We don't want any border around |
| 18 // the link text. | 19 // the link text. |
| 19 void SetLinkButtonStyle() { | 20 void SetLinkButtonStyle() { |
| 20 static bool style_was_set = false; | 21 static bool style_was_set = false; |
| 21 | 22 |
| 22 if (style_was_set) | 23 if (style_was_set) |
| 23 return; | 24 return; |
| 24 style_was_set = true; | 25 style_was_set = true; |
| 25 | 26 |
| 26 gtk_rc_parse_string( | 27 gtk_rc_parse_string( |
| 27 "style \"chrome-link-button\" {" | 28 "style \"chrome-link-button\" {" |
| 28 " GtkButton::inner-border = {0, 0, 0, 0}" | 29 " GtkButton::inner-border = {0, 0, 0, 0}" |
| 29 " GtkButton::child-displacement-x = 0" | 30 " GtkButton::child-displacement-x = 0" |
| 30 " GtkButton::child-displacement-y = 0" | 31 " GtkButton::child-displacement-y = 0" |
| 31 " xthickness = 0" | 32 " xthickness = 0" |
| 32 " ythickness = 0" | 33 " ythickness = 0" |
| 33 "}" | 34 "}" |
| 34 "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\""); | 35 "widget_class \"*.<GtkChromeLinkButton>\" style \"chrome-link-button\""); |
| 35 } | 36 } |
| 36 | 37 |
| 37 static void gtk_chrome_link_button_destroy_text_resources( | 38 static void gtk_chrome_link_button_destroy_text_resources( |
| 38 GtkChromeLinkButton* button) { | 39 GtkChromeLinkButton* button) { |
| 39 g_free(button->native_markup); | 40 g_free(button->native_markup); |
| 40 button->native_markup = NULL; | 41 button->native_markup = NULL; |
| 41 g_free(button->normal_markup); | 42 g_free(button->normal_markup); |
| 42 button->normal_markup = NULL; | 43 button->normal_markup = NULL; |
| 44 g_free(button->insensitive_markup); | |
| 45 button->insensitive_markup = NULL; | |
| 43 g_free(button->pressed_markup); | 46 g_free(button->pressed_markup); |
| 44 button->pressed_markup = NULL; | 47 button->pressed_markup = NULL; |
| 45 | 48 |
| 46 g_free(button->text); | 49 g_free(button->text); |
| 47 button->text = NULL; | 50 button->text = NULL; |
| 48 } | 51 } |
| 49 | 52 |
| 50 } // namespace | 53 } // namespace |
| 51 | 54 |
| 52 G_BEGIN_DECLS | 55 G_BEGIN_DECLS |
| 53 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) | 56 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) |
| 54 | 57 |
| 55 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) { | 58 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) { |
| 56 // If we were called before we were realized, abort. We'll be called for | 59 // If we were called before we were realized, abort. We'll be called for |
| 57 // real when |button| is realized. | 60 // real when |button| is realized. |
| 58 if (!gtk_widget_get_realized(GTK_WIDGET(button))) | 61 if (!gtk_widget_get_realized(GTK_WIDGET(button))) |
| 59 return; | 62 return; |
| 60 | 63 |
| 61 g_free(button->native_markup); | 64 g_free(button->native_markup); |
| 62 button->native_markup = NULL; | 65 button->native_markup = NULL; |
| 63 g_free(button->normal_markup); | 66 g_free(button->normal_markup); |
| 64 button->normal_markup = NULL; | 67 button->normal_markup = NULL; |
| 65 g_free(button->pressed_markup); | 68 g_free(button->pressed_markup); |
| 66 button->pressed_markup = NULL; | 69 button->pressed_markup = NULL; |
| 70 g_free(button->insensitive_markup); | |
| 71 button->insensitive_markup = NULL; | |
| 67 | 72 |
| 68 gchar* text = button->text; | 73 gchar* text = button->text; |
| 69 gboolean uses_markup = button->uses_markup; | 74 gboolean uses_markup = button->uses_markup; |
| 70 | 75 |
| 71 if (!uses_markup) { | 76 if (!uses_markup) { |
| 72 button->normal_markup = g_markup_printf_escaped(kLinkMarkup, | 77 button->normal_markup = g_markup_printf_escaped(kLinkMarkup, |
| 73 button->normal_color, | 78 button->normal_color, |
| 74 text); | 79 text); |
| 75 button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); | 80 button->pressed_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); |
| 81 button->insensitive_markup = g_markup_printf_escaped(kInsensitiveLinkMarkup, | |
| 82 "black", | |
|
James Hawkins
2012/03/30 21:35:02
Do we need to read system prefs for this color?
Evan Stade
2012/03/30 21:38:25
I don't think this will look too good on dark GTK
binji
2012/03/30 23:03:51
Done.
| |
| 83 text); | |
| 76 } else { | 84 } else { |
| 77 button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color, | 85 button->normal_markup = g_strdup_printf(kLinkMarkup, button->normal_color, |
| 78 text); | 86 text); |
| 79 | 87 |
| 80 button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text); | 88 button->pressed_markup = g_strdup_printf(kLinkMarkup, "red", text); |
| 89 button->insensitive_markup = g_strdup_printf(kInsensitiveLinkMarkup, | |
| 90 "black", | |
| 91 text); | |
| 81 } | 92 } |
| 82 | 93 |
| 83 // Get the current GTK theme's link button text color. | 94 // Get the current GTK theme's link button text color. |
| 84 GdkColor* native_color = NULL; | 95 GdkColor* native_color = NULL; |
| 85 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL); | 96 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL); |
| 86 | 97 |
| 87 if (native_color) { | 98 if (native_color) { |
| 88 gchar color_spec[9]; | 99 gchar color_spec[9]; |
| 89 snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257, | 100 snprintf(color_spec, 9, "#%02X%02X%02X", native_color->red / 257, |
| 90 native_color->green / 257, native_color->blue / 257); | 101 native_color->green / 257, native_color->blue / 257); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 113 gtk_chrome_link_button_set_text(button); | 124 gtk_chrome_link_button_set_text(button); |
| 114 | 125 |
| 115 if (gtk_widget_get_visible(GTK_WIDGET(button))) | 126 if (gtk_widget_get_visible(GTK_WIDGET(button))) |
| 116 gtk_widget_queue_draw(GTK_WIDGET(button)); | 127 gtk_widget_queue_draw(GTK_WIDGET(button)); |
| 117 } | 128 } |
| 118 | 129 |
| 119 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, | 130 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, |
| 120 GdkEventExpose* event) { | 131 GdkEventExpose* event) { |
| 121 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); | 132 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); |
| 122 GtkWidget* label = button->label; | 133 GtkWidget* label = button->label; |
| 134 GtkStateType widget_state = gtk_widget_get_state(widget); | |
| 123 | 135 |
| 124 if (gtk_widget_get_state(widget) == GTK_STATE_ACTIVE && button->is_normal) { | 136 if (widget_state != button->label_state) { |
| 125 gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup); | 137 switch (widget_state) { |
| 126 button->is_normal = FALSE; | 138 case GTK_STATE_NORMAL: |
| 127 } else if (gtk_widget_get_state(widget) != GTK_STATE_ACTIVE && | 139 gtk_label_set_markup(GTK_LABEL(label), |
| 128 !button->is_normal) { | 140 button->using_native_theme ? button->native_markup : |
| 129 gtk_label_set_markup(GTK_LABEL(label), | 141 button->normal_markup); |
| 130 button->using_native_theme ? button->native_markup : | 142 break; |
| 131 button->normal_markup); | 143 case GTK_STATE_ACTIVE: |
| 132 button->is_normal = TRUE; | 144 gtk_label_set_markup(GTK_LABEL(label), button->pressed_markup); |
| 145 break; | |
| 146 case GTK_STATE_INSENSITIVE: | |
| 147 gtk_label_set_markup(GTK_LABEL(label), button->insensitive_markup); | |
| 148 break; | |
| 149 default: | |
| 150 break; | |
| 151 } | |
| 152 button->label_state = widget_state; | |
| 133 } | 153 } |
| 134 | 154 |
| 135 // Draw the link inside the button. | 155 // Draw the link inside the button. |
| 136 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); | 156 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); |
| 137 | 157 |
| 138 // Draw the focus rectangle. | 158 // Draw the focus rectangle. |
| 139 if (gtk_widget_has_focus(widget)) { | 159 if (gtk_widget_has_focus(widget)) { |
| 140 GtkAllocation allocation; | 160 GtkAllocation allocation; |
| 141 gtk_widget_get_allocation(widget, &allocation); | 161 gtk_widget_get_allocation(widget, &allocation); |
| 142 gtk_paint_focus(gtk_widget_get_style(widget), | 162 gtk_paint_focus(gtk_widget_get_style(widget), |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 188 | 208 |
| 189 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { | 209 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { |
| 190 SetLinkButtonStyle(); | 210 SetLinkButtonStyle(); |
| 191 | 211 |
| 192 // We put a label in a button so we can connect to the click event. We don't | 212 // We put a label in a button so we can connect to the click event. We don't |
| 193 // let the button draw itself; catch all expose events to the button and pass | 213 // let the button draw itself; catch all expose events to the button and pass |
| 194 // them through to the label. | 214 // them through to the label. |
| 195 button->label = gtk_label_new(NULL); | 215 button->label = gtk_label_new(NULL); |
| 196 button->normal_markup = NULL; | 216 button->normal_markup = NULL; |
| 197 button->pressed_markup = NULL; | 217 button->pressed_markup = NULL; |
| 198 button->is_normal = TRUE; | 218 button->label_state = GTK_STATE_NORMAL; |
| 199 strncpy(button->normal_color, "blue", 9); | 219 strncpy(button->normal_color, "blue", 9); |
| 200 button->native_markup = NULL; | 220 button->native_markup = NULL; |
| 201 button->using_native_theme = TRUE; | 221 button->using_native_theme = TRUE; |
| 202 button->hand_cursor = gfx::GetCursor(GDK_HAND2); | 222 button->hand_cursor = gfx::GetCursor(GDK_HAND2); |
| 203 button->text = NULL; | 223 button->text = NULL; |
| 204 | 224 |
| 205 gtk_container_add(GTK_CONTAINER(button), button->label); | 225 gtk_container_add(GTK_CONTAINER(button), button->label); |
| 206 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); | 226 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); |
| 207 g_signal_connect(button, "realize", | 227 g_signal_connect(button, "realize", |
| 208 G_CALLBACK(gtk_chrome_link_button_set_text), NULL); | 228 G_CALLBACK(gtk_chrome_link_button_set_text), NULL); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 strncpy(button->normal_color, "blue", 9); | 278 strncpy(button->normal_color, "blue", 9); |
| 259 } | 279 } |
| 260 | 280 |
| 261 gtk_chrome_link_button_set_text(button); | 281 gtk_chrome_link_button_set_text(button); |
| 262 | 282 |
| 263 if (gtk_widget_get_visible(GTK_WIDGET(button))) | 283 if (gtk_widget_get_visible(GTK_WIDGET(button))) |
| 264 gtk_widget_queue_draw(GTK_WIDGET(button)); | 284 gtk_widget_queue_draw(GTK_WIDGET(button)); |
| 265 } | 285 } |
| 266 | 286 |
| 267 G_END_DECLS | 287 G_END_DECLS |
| OLD | NEW |