]> Pileus Git - ~andy/gtk/blob - gtk/gtkmodifierstyle.c
Merge branch 'master' into broadway2
[~andy/gtk] / gtk / gtkmodifierstyle.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 #include "config.h"
21 #include "gtkmodifierstyle.h"
22 #include "gtkintl.h"
23
24 typedef struct GtkModifierStylePrivate GtkModifierStylePrivate;
25 typedef struct StylePropertyValue StylePropertyValue;
26
27 struct GtkModifierStylePrivate
28 {
29   GtkStyleProperties *style;
30   GHashTable *color_properties;
31 };
32
33 enum {
34   CHANGED,
35   LAST_SIGNAL
36 };
37
38 static guint signals [LAST_SIGNAL] = { 0 };
39
40 static void gtk_modifier_style_provider_init (GtkStyleProviderIface *iface);
41 static void gtk_modifier_style_finalize      (GObject      *object);
42
43 G_DEFINE_TYPE_EXTENDED (GtkModifierStyle, gtk_modifier_style, G_TYPE_OBJECT, 0,
44                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
45                                                gtk_modifier_style_provider_init));
46
47 static void
48 gtk_modifier_style_class_init (GtkModifierStyleClass *klass)
49 {
50   GObjectClass *object_class;
51
52   object_class = G_OBJECT_CLASS (klass);
53
54   object_class->finalize = gtk_modifier_style_finalize;
55
56   signals[CHANGED] =
57     g_signal_new (I_("changed"),
58                   G_TYPE_FROM_CLASS (object_class),
59                   G_SIGNAL_RUN_LAST,
60                   0, NULL, NULL,
61                   g_cclosure_marshal_VOID__VOID,
62                   G_TYPE_NONE, 0);
63
64   g_type_class_add_private (object_class, sizeof (GtkModifierStylePrivate));
65 }
66
67 static void
68 gtk_modifier_style_init (GtkModifierStyle *modifier_style)
69 {
70   GtkModifierStylePrivate *priv;
71
72   priv = modifier_style->priv = G_TYPE_INSTANCE_GET_PRIVATE (modifier_style,
73                                                              GTK_TYPE_MODIFIER_STYLE,
74                                                              GtkModifierStylePrivate);
75
76   priv->color_properties = g_hash_table_new_full (g_str_hash,
77                                                   g_str_equal,
78                                                   (GDestroyNotify) g_free,
79                                                   (GDestroyNotify) gdk_rgba_free);
80   priv->style = gtk_style_properties_new ();
81 }
82
83 static GtkStyleProperties *
84 gtk_modifier_style_get_style (GtkStyleProvider *provider,
85                               GtkWidgetPath    *path)
86 {
87   GtkModifierStylePrivate *priv;
88
89   priv = GTK_MODIFIER_STYLE (provider)->priv;
90   return g_object_ref (priv->style);
91 }
92
93 static gboolean
94 gtk_modifier_style_get_style_property (GtkStyleProvider *provider,
95                                        GtkWidgetPath    *path,
96                                        GtkStateFlags     state,
97                                        GParamSpec       *pspec,
98                                        GValue           *value)
99 {
100   GtkModifierStylePrivate *priv;
101   GdkRGBA *rgba;
102   GdkColor color;
103   gchar *str;
104
105   /* Reject non-color types for now */
106   if (pspec->value_type != GDK_TYPE_COLOR)
107     return FALSE;
108
109   priv = GTK_MODIFIER_STYLE (provider)->priv;
110   str = g_strdup_printf ("-%s-%s",
111                          g_type_name (pspec->owner_type),
112                          pspec->name);
113
114   rgba = g_hash_table_lookup (priv->color_properties, str);
115   g_free (str);
116
117   if (!rgba)
118     return FALSE;
119
120   color.red = (guint) (rgba->red * 65535.) + 0.5;
121   color.green = (guint) (rgba->green * 65535.) + 0.5;
122   color.blue = (guint) (rgba->blue * 65535.) + 0.5;
123
124   g_value_set_boxed (value, &color);
125   return TRUE;
126 }
127
128 static void
129 gtk_modifier_style_provider_init (GtkStyleProviderIface *iface)
130 {
131   iface->get_style = gtk_modifier_style_get_style;
132   iface->get_style_property = gtk_modifier_style_get_style_property;
133 }
134
135 static void
136 gtk_modifier_style_finalize (GObject *object)
137 {
138   GtkModifierStylePrivate *priv;
139
140   priv = GTK_MODIFIER_STYLE (object)->priv;
141   g_hash_table_destroy (priv->color_properties);
142   g_object_unref (priv->style);
143
144   G_OBJECT_CLASS (gtk_modifier_style_parent_class)->finalize (object);
145 }
146
147 GtkModifierStyle *
148 gtk_modifier_style_new (void)
149 {
150   return g_object_new (GTK_TYPE_MODIFIER_STYLE, NULL);
151 }
152
153 static void
154 modifier_style_set_color (GtkModifierStyle *style,
155                           const gchar      *prop,
156                           GtkStateFlags     state,
157                           const GdkRGBA    *color)
158 {
159   GtkModifierStylePrivate *priv;
160   GdkRGBA *old_color;
161
162   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
163
164   priv = style->priv;
165   gtk_style_properties_get (priv->style, state,
166                             prop, &old_color,
167                             NULL);
168
169   if ((!color && !old_color) ||
170       (color && old_color && gdk_rgba_equal (color, old_color)))
171     {
172       gdk_rgba_free (old_color);
173       return;
174     }
175
176   if (color)
177     gtk_style_properties_set (priv->style, state,
178                               prop, color,
179                               NULL);
180   else
181     gtk_style_properties_unset_property (priv->style, prop, state);
182
183   g_signal_emit (style, signals[CHANGED], 0);
184   gdk_rgba_free (old_color);
185 }
186
187 void
188 gtk_modifier_style_set_background_color (GtkModifierStyle *style,
189                                          GtkStateFlags     state,
190                                          const GdkRGBA    *color)
191 {
192   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
193
194   modifier_style_set_color (style, "background-color", state, color);
195 }
196
197 void
198 gtk_modifier_style_set_color (GtkModifierStyle *style,
199                               GtkStateFlags     state,
200                               const GdkRGBA    *color)
201 {
202   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
203
204   modifier_style_set_color (style, "color", state, color);
205 }
206
207 void
208 gtk_modifier_style_set_font (GtkModifierStyle           *style,
209                              const PangoFontDescription *font_desc)
210 {
211   GtkModifierStylePrivate *priv;
212   PangoFontDescription *old_font;
213
214   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
215
216   priv = style->priv;
217   gtk_style_properties_get (priv->style, 0,
218                             "font", &old_font,
219                             NULL);
220
221   if ((!old_font && !font_desc) ||
222       (old_font && font_desc &&
223        pango_font_description_equal (old_font, font_desc)))
224     {
225       if (old_font)
226         pango_font_description_free (old_font);
227
228       return;
229     }
230
231   if (font_desc)
232     gtk_style_properties_set (priv->style, 0,
233                               "font", font_desc,
234                               NULL);
235   else
236     gtk_style_properties_unset_property (priv->style, "font", 0);
237
238   if (old_font)
239     pango_font_description_free (old_font);
240
241   g_signal_emit (style, signals[CHANGED], 0);
242 }
243
244 void
245 gtk_modifier_style_map_color (GtkModifierStyle *style,
246                               const gchar      *name,
247                               const GdkRGBA    *color)
248 {
249   GtkModifierStylePrivate *priv;
250   GtkSymbolicColor *symbolic_color = NULL;
251
252   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
253   g_return_if_fail (name != NULL);
254
255   priv = style->priv;
256
257   if (color)
258     symbolic_color = gtk_symbolic_color_new_literal (color);
259
260   gtk_style_properties_map_color (priv->style,
261                                   name, symbolic_color);
262
263   g_signal_emit (style, signals[CHANGED], 0);
264 }
265
266 void
267 gtk_modifier_style_set_color_property (GtkModifierStyle *style,
268                                        GType             widget_type,
269                                        const gchar      *prop_name,
270                                        const GdkRGBA    *color)
271 {
272   GtkModifierStylePrivate *priv;
273   const GdkRGBA *old_color;
274   gchar *str;
275
276   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
277   g_return_if_fail (g_type_is_a (widget_type, GTK_TYPE_WIDGET));
278   g_return_if_fail (prop_name != NULL);
279
280   priv = style->priv;
281   str = g_strdup_printf ("-%s-%s", g_type_name (widget_type), prop_name);
282
283   old_color = g_hash_table_lookup (priv->color_properties, str);
284
285   if ((!color && !old_color) ||
286       (color && old_color && gdk_rgba_equal (color, old_color)))
287     {
288       g_free (str);
289       return;
290     }
291
292   if (color)
293     {
294       g_hash_table_insert (priv->color_properties, str,
295                            gdk_rgba_copy (color));
296     }
297   else
298     {
299       g_hash_table_remove (priv->color_properties, str);
300       g_free (str);
301     }
302
303   g_signal_emit (style, signals[CHANGED], 0);
304 }