Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/gtk/gtk_chrome_link_button.h" | 5 #include "chrome/browser/gtk/gtk_chrome_link_button.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 | 10 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 30 " ythickness = 0" | 30 " ythickness = 0" |
| 31 "}" | 31 "}" |
| 32 "widget \"*chrome-link-button\" style \"chrome-link-button\""); | 32 "widget \"*chrome-link-button\" style \"chrome-link-button\""); |
| 33 } | 33 } |
| 34 | 34 |
| 35 } // namespace | 35 } // namespace |
| 36 | 36 |
| 37 G_BEGIN_DECLS | 37 G_BEGIN_DECLS |
| 38 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) | 38 G_DEFINE_TYPE(GtkChromeLinkButton, gtk_chrome_link_button, GTK_TYPE_BUTTON) |
| 39 | 39 |
| 40 // Should be called after we are realized so that the "link-color" property | |
| 41 // can be read. | |
| 42 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button) { | |
| 43 // We only set the markup once. | |
| 44 if (button->blue_markup) | |
| 45 return; | |
| 46 | |
| 47 gchar* text = button->text; | |
| 48 gboolean uses_markup = button->uses_markup; | |
| 49 | |
| 50 if (!uses_markup) { | |
| 51 button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text); | |
| 52 button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); | |
| 53 } else { | |
| 54 button->blue_markup = static_cast<gchar*>( | |
| 55 g_malloc(strlen(kLinkMarkup) + strlen("blue") + strlen(text) + 1)); | |
| 56 sprintf(button->blue_markup, kLinkMarkup, "blue", text); | |
| 57 | |
| 58 button->red_markup = static_cast<gchar*>( | |
| 59 g_malloc(strlen(kLinkMarkup) + strlen("red") + strlen(text) + 1)); | |
| 60 sprintf(button->red_markup, kLinkMarkup, "red", text); | |
| 61 } | |
| 62 | |
| 63 // Get the current GTK theme's link button text color. | |
| 64 GdkColor* native_color = NULL; | |
| 65 gtk_widget_style_get(GTK_WIDGET(button), "link-color", &native_color, NULL); | |
| 66 | |
| 67 if (native_color) { | |
| 68 gchar color_spec[9]; | |
| 69 sprintf(color_spec, "#%02X%02X%02X", native_color->red / 257, | |
| 70 native_color->green / 257, native_color->blue / 257); | |
| 71 gdk_color_free(native_color); | |
| 72 | |
| 73 if (!uses_markup) { | |
| 74 button->native_markup = g_markup_printf_escaped(kLinkMarkup, | |
| 75 color_spec, text); | |
| 76 } else { | |
| 77 button->native_markup = static_cast<gchar*>( | |
| 78 g_malloc(strlen(kLinkMarkup) + strlen(color_spec) + strlen(text) + | |
| 79 1)); | |
| 80 sprintf(button->native_markup, kLinkMarkup, color_spec, text); | |
| 81 } | |
| 82 } else { | |
| 83 // If the theme doesn't have a link color, just use blue. This matches the | |
| 84 // default for GtkLinkButton. | |
| 85 button->native_markup = button->blue_markup; | |
| 86 } | |
| 87 | |
| 88 gtk_label_set_markup(GTK_LABEL(button->label), | |
| 89 button->using_native_theme ? button->native_markup : button->blue_markup); | |
| 90 } | |
| 91 | |
| 40 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, | 92 static gboolean gtk_chrome_link_button_expose(GtkWidget* widget, |
| 41 GdkEventExpose* event) { | 93 GdkEventExpose* event) { |
| 42 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); | 94 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(widget); |
| 43 GtkWidget* label = button->label; | 95 GtkWidget* label = button->label; |
| 44 | 96 |
| 97 gtk_chrome_link_button_set_text(button); | |
| 98 | |
| 45 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) { | 99 if (GTK_WIDGET_STATE(widget) == GTK_STATE_ACTIVE && button->is_blue) { |
| 46 gtk_label_set_markup(GTK_LABEL(label), button->red_markup); | 100 gtk_label_set_markup(GTK_LABEL(label), button->red_markup); |
| 47 button->is_blue = FALSE; | 101 button->is_blue = FALSE; |
| 48 } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) { | 102 } else if (GTK_WIDGET_STATE(widget) != GTK_STATE_ACTIVE && !button->is_blue) { |
| 49 gtk_label_set_markup(GTK_LABEL(label), button->blue_markup); | 103 gtk_label_set_markup(GTK_LABEL(label), |
| 104 button->using_native_theme ? button->native_markup : button->blue_markup ); | |
| 50 button->is_blue = TRUE; | 105 button->is_blue = TRUE; |
| 51 } | 106 } |
| 52 | 107 |
| 53 // Draw the link inside the button. | 108 // Draw the link inside the button. |
| 54 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); | 109 gtk_container_propagate_expose(GTK_CONTAINER(widget), label, event); |
| 55 | 110 |
| 56 // Draw the focus rectangle. | 111 // Draw the focus rectangle. |
| 57 if (GTK_WIDGET_HAS_FOCUS(widget)) { | 112 if (GTK_WIDGET_HAS_FOCUS(widget)) { |
| 58 gtk_paint_focus(widget->style, widget->window, | 113 gtk_paint_focus(widget->style, widget->window, |
| 59 static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)), | 114 static_cast<GtkStateType>(GTK_WIDGET_STATE(widget)), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 107 static void gtk_chrome_link_button_leave(GtkButton* button) { | 162 static void gtk_chrome_link_button_leave(GtkButton* button) { |
| 108 GtkWidget* widget = GTK_WIDGET(button); | 163 GtkWidget* widget = GTK_WIDGET(button); |
| 109 GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button); | 164 GtkChromeLinkButton* link_button = GTK_CHROME_LINK_BUTTON(button); |
| 110 gdk_window_set_cursor(widget->window, NULL); | 165 gdk_window_set_cursor(widget->window, NULL); |
| 111 free(link_button->click_button_event); | 166 free(link_button->click_button_event); |
| 112 link_button->click_button_event = NULL; | 167 link_button->click_button_event = NULL; |
| 113 } | 168 } |
| 114 | 169 |
| 115 static void gtk_chrome_link_button_destroy(GtkObject* object) { | 170 static void gtk_chrome_link_button_destroy(GtkObject* object) { |
| 116 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object); | 171 GtkChromeLinkButton* button = GTK_CHROME_LINK_BUTTON(object); |
| 172 if (button->native_markup && (button->native_markup != button->blue_markup)) | |
| 173 g_free(button->native_markup); | |
| 174 button->native_markup = NULL; | |
|
Evan Stade
2009/08/01 01:34:00
the difference from the last change is making it a
| |
| 117 if (button->blue_markup) { | 175 if (button->blue_markup) { |
| 118 g_free(button->blue_markup); | 176 g_free(button->blue_markup); |
| 119 button->blue_markup = NULL; | 177 button->blue_markup = NULL; |
| 120 } | 178 } |
| 121 if (button->red_markup) { | 179 if (button->red_markup) { |
| 122 g_free(button->red_markup); | 180 g_free(button->red_markup); |
| 123 button->red_markup = NULL; | 181 button->red_markup = NULL; |
| 124 } | 182 } |
| 125 if (button->hand_cursor) { | 183 if (button->hand_cursor) { |
| 126 gdk_cursor_unref(button->hand_cursor); | 184 gdk_cursor_unref(button->hand_cursor); |
| 127 button->hand_cursor = NULL; | 185 button->hand_cursor = NULL; |
| 128 } | 186 } |
| 187 | |
| 129 free(button->click_button_event); | 188 free(button->click_button_event); |
| 130 button->click_button_event = NULL; | 189 button->click_button_event = NULL; |
| 131 | 190 |
| 191 free(button->text); | |
| 192 button->text = NULL; | |
| 193 | |
| 132 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object); | 194 GTK_OBJECT_CLASS(gtk_chrome_link_button_parent_class)->destroy(object); |
| 133 } | 195 } |
| 134 | 196 |
| 135 static void gtk_chrome_link_button_class_init( | 197 static void gtk_chrome_link_button_class_init( |
| 136 GtkChromeLinkButtonClass* link_button_class) { | 198 GtkChromeLinkButtonClass* link_button_class) { |
| 137 GtkWidgetClass* widget_class = | 199 GtkWidgetClass* widget_class = |
| 138 reinterpret_cast<GtkWidgetClass*>(link_button_class); | 200 reinterpret_cast<GtkWidgetClass*>(link_button_class); |
| 139 GtkButtonClass* button_class = | 201 GtkButtonClass* button_class = |
| 140 reinterpret_cast<GtkButtonClass*>(link_button_class); | 202 reinterpret_cast<GtkButtonClass*>(link_button_class); |
| 141 GtkObjectClass* object_class = | 203 GtkObjectClass* object_class = |
| 142 reinterpret_cast<GtkObjectClass*>(link_button_class); | 204 reinterpret_cast<GtkObjectClass*>(link_button_class); |
| 143 widget_class->expose_event = >k_chrome_link_button_expose; | 205 widget_class->expose_event = >k_chrome_link_button_expose; |
| 144 widget_class->button_press_event = >k_chrome_link_button_button_press; | 206 widget_class->button_press_event = >k_chrome_link_button_button_press; |
| 145 widget_class->button_release_event = >k_chrome_link_button_button_release; | 207 widget_class->button_release_event = >k_chrome_link_button_button_release; |
| 146 button_class->enter = >k_chrome_link_button_enter; | 208 button_class->enter = >k_chrome_link_button_enter; |
| 147 button_class->leave = >k_chrome_link_button_leave; | 209 button_class->leave = >k_chrome_link_button_leave; |
| 148 object_class->destroy = >k_chrome_link_button_destroy; | 210 object_class->destroy = >k_chrome_link_button_destroy; |
| 149 } | 211 } |
| 150 | 212 |
| 151 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { | 213 static void gtk_chrome_link_button_init(GtkChromeLinkButton* button) { |
| 152 SetLinkButtonStyle(); | 214 SetLinkButtonStyle(); |
| 153 | 215 |
| 154 // We put a label in a button so we can connect to the click event. We don't | 216 // We put a label in a button so we can connect to the click event. We don't |
| 155 // let the button draw itself; catch all expose events to the button and pass | 217 // let the button draw itself; catch all expose events to the button and pass |
| 156 // them through to the label. | 218 // them through to the label. |
| 157 button->label = gtk_label_new(NULL); | 219 button->label = gtk_label_new(NULL); |
| 158 button->blue_markup = NULL; | 220 button->blue_markup = NULL; |
| 159 button->red_markup = NULL; | 221 button->red_markup = NULL; |
| 160 button->is_blue = TRUE; | 222 button->is_blue = TRUE; |
| 223 button->native_markup = NULL; | |
| 224 button->using_native_theme = TRUE; | |
| 161 button->hand_cursor = gdk_cursor_new(GDK_HAND2); | 225 button->hand_cursor = gdk_cursor_new(GDK_HAND2); |
| 162 button->click_button_event = NULL; | 226 button->click_button_event = NULL; |
| 227 button->text = NULL; | |
| 163 | 228 |
| 164 gtk_container_add(GTK_CONTAINER(button), button->label); | 229 gtk_container_add(GTK_CONTAINER(button), button->label); |
| 165 gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button"); | 230 gtk_widget_set_name(GTK_WIDGET(button), "chrome-link-button"); |
| 166 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); | 231 gtk_widget_set_app_paintable(GTK_WIDGET(button), TRUE); |
| 167 } | 232 } |
| 168 | 233 |
| 169 static void gtk_chrome_link_button_set_text(GtkChromeLinkButton* button, | |
| 170 const char* text, | |
| 171 bool contains_markup) { | |
| 172 // We should have only been called once or we'd leak the markups. | |
| 173 DCHECK(!button->blue_markup && !button->red_markup); | |
| 174 | |
| 175 if (!contains_markup) { | |
| 176 button->blue_markup = g_markup_printf_escaped(kLinkMarkup, "blue", text); | |
| 177 button->red_markup = g_markup_printf_escaped(kLinkMarkup, "red", text); | |
| 178 } else { | |
| 179 button->blue_markup = static_cast<gchar*>( | |
| 180 g_malloc(strlen(kLinkMarkup) + strlen("blue") + strlen(text) + 1)); | |
| 181 sprintf(button->blue_markup, kLinkMarkup, "blue", text); | |
| 182 | |
| 183 button->red_markup = static_cast<gchar*>( | |
| 184 g_malloc(strlen(kLinkMarkup) + strlen("red") + strlen(text) + 1)); | |
| 185 sprintf(button->red_markup, kLinkMarkup, "red", text); | |
| 186 } | |
| 187 | |
| 188 gtk_label_set_markup(GTK_LABEL(button->label), button->blue_markup); | |
| 189 button->is_blue = TRUE; | |
| 190 } | |
| 191 | |
| 192 GtkWidget* gtk_chrome_link_button_new(const char* text) { | 234 GtkWidget* gtk_chrome_link_button_new(const char* text) { |
| 193 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); | 235 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); |
| 194 gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), text, false); | 236 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(text); |
| 237 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = FALSE; | |
| 195 return lb; | 238 return lb; |
| 196 } | 239 } |
| 197 | 240 |
| 198 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) { | 241 GtkWidget* gtk_chrome_link_button_new_with_markup(const char* markup) { |
| 199 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); | 242 GtkWidget* lb = GTK_WIDGET(g_object_new(GTK_TYPE_CHROME_LINK_BUTTON, NULL)); |
| 200 gtk_chrome_link_button_set_text(GTK_CHROME_LINK_BUTTON(lb), markup, true); | 243 GTK_CHROME_LINK_BUTTON(lb)->text = strdup(markup); |
| 244 GTK_CHROME_LINK_BUTTON(lb)->uses_markup = TRUE; | |
| 201 return lb; | 245 return lb; |
| 202 } | 246 } |
| 203 | 247 |
| 248 void gtk_chrome_link_button_set_use_gtk_theme(GtkChromeLinkButton* button, | |
| 249 gboolean use_gtk) { | |
| 250 if (use_gtk != button->using_native_theme) { | |
| 251 button->using_native_theme = use_gtk; | |
| 252 if (GTK_WIDGET_VISIBLE(button)) | |
| 253 gtk_widget_queue_draw(GTK_WIDGET(button)); | |
| 254 } | |
| 255 } | |
| 256 | |
| 204 const GdkEventButton* gtk_chrome_link_button_get_event_for_click( | 257 const GdkEventButton* gtk_chrome_link_button_get_event_for_click( |
| 205 GtkChromeLinkButton* button) { | 258 GtkChromeLinkButton* button) { |
| 206 return button->click_button_event; | 259 return button->click_button_event; |
| 207 } | 260 } |
| 208 | 261 |
| 209 G_END_DECLS | 262 G_END_DECLS |
| OLD | NEW |