]> Pileus Git - ~andy/gtk/blob - gtk/gtkmodifierstyle.c
efb1008111d2b12015665d60bcf07238a7c1ae55
[~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 "gtkstyleproviderprivate.h"
23 #include "gtkintl.h"
24
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_provider_private_init (GtkStyleProviderPrivateInterface *iface);
42 static void gtk_modifier_style_finalize              (GObject                          *object);
43
44 G_DEFINE_TYPE_EXTENDED (GtkModifierStyle, _gtk_modifier_style, G_TYPE_OBJECT, 0,
45                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER,
46                                                gtk_modifier_style_provider_init)
47                         G_IMPLEMENT_INTERFACE (GTK_TYPE_STYLE_PROVIDER_PRIVATE,
48                                                gtk_modifier_style_provider_private_init));
49
50 static void
51 _gtk_modifier_style_class_init (GtkModifierStyleClass *klass)
52 {
53   GObjectClass *object_class;
54
55   object_class = G_OBJECT_CLASS (klass);
56
57   object_class->finalize = gtk_modifier_style_finalize;
58
59   signals[CHANGED] =
60     g_signal_new (I_("changed"),
61                   G_TYPE_FROM_CLASS (object_class),
62                   G_SIGNAL_RUN_LAST,
63                   0, NULL, NULL,
64                   g_cclosure_marshal_VOID__VOID,
65                   G_TYPE_NONE, 0);
66
67   g_type_class_add_private (object_class, sizeof (GtkModifierStylePrivate));
68 }
69
70 static void
71 _gtk_modifier_style_init (GtkModifierStyle *modifier_style)
72 {
73   GtkModifierStylePrivate *priv;
74
75   priv = modifier_style->priv = G_TYPE_INSTANCE_GET_PRIVATE (modifier_style,
76                                                              GTK_TYPE_MODIFIER_STYLE,
77                                                              GtkModifierStylePrivate);
78
79   priv->color_properties = g_hash_table_new_full (g_str_hash,
80                                                   g_str_equal,
81                                                   (GDestroyNotify) g_free,
82                                                   (GDestroyNotify) gdk_rgba_free);
83   priv->style = gtk_style_properties_new ();
84 }
85
86 static GtkStyleProperties *
87 gtk_modifier_style_get_style (GtkStyleProvider *provider,
88                               GtkWidgetPath    *path)
89 {
90   GtkModifierStylePrivate *priv;
91
92   priv = GTK_MODIFIER_STYLE (provider)->priv;
93   return g_object_ref (priv->style);
94 }
95
96 static gboolean
97 gtk_modifier_style_get_style_property (GtkStyleProvider *provider,
98                                        GtkWidgetPath    *path,
99                                        GtkStateFlags     state,
100                                        GParamSpec       *pspec,
101                                        GValue           *value)
102 {
103   GtkModifierStylePrivate *priv;
104   GdkRGBA *rgba;
105   GdkColor color;
106   gchar *str;
107
108   /* Reject non-color types for now */
109   if (pspec->value_type != GDK_TYPE_COLOR)
110     return FALSE;
111
112   priv = GTK_MODIFIER_STYLE (provider)->priv;
113   str = g_strdup_printf ("-%s-%s",
114                          g_type_name (pspec->owner_type),
115                          pspec->name);
116
117   rgba = g_hash_table_lookup (priv->color_properties, str);
118   g_free (str);
119
120   if (!rgba)
121     return FALSE;
122
123   color.red = (guint) (rgba->red * 65535.) + 0.5;
124   color.green = (guint) (rgba->green * 65535.) + 0.5;
125   color.blue = (guint) (rgba->blue * 65535.) + 0.5;
126
127   g_value_set_boxed (value, &color);
128   return TRUE;
129 }
130
131 static void
132 gtk_modifier_style_provider_init (GtkStyleProviderIface *iface)
133 {
134   iface->get_style = gtk_modifier_style_get_style;
135   iface->get_style_property = gtk_modifier_style_get_style_property;
136 }
137
138 static GtkSymbolicColor *
139 gtk_modifier_style_provider_get_color (GtkStyleProviderPrivate *provider,
140                                        const char              *name)
141 {
142   GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider);
143
144   return _gtk_style_provider_private_get_color (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style), name);
145 }
146
147 static void
148 gtk_modifier_style_provider_lookup (GtkStyleProviderPrivate *provider,
149                                     GtkWidgetPath           *path,
150                                     GtkStateFlags            state,
151                                     GtkCssLookup            *lookup)
152 {
153   GtkModifierStyle *style = GTK_MODIFIER_STYLE (provider);
154
155   _gtk_style_provider_private_lookup (GTK_STYLE_PROVIDER_PRIVATE (style->priv->style),
156                                       path,
157                                       state,
158                                       lookup);
159 }
160
161 static void
162 gtk_modifier_style_provider_private_init (GtkStyleProviderPrivateInterface *iface)
163 {
164   iface->get_color = gtk_modifier_style_provider_get_color;
165   iface->lookup = gtk_modifier_style_provider_lookup;
166 }
167
168 static void
169 gtk_modifier_style_finalize (GObject *object)
170 {
171   GtkModifierStylePrivate *priv;
172
173   priv = GTK_MODIFIER_STYLE (object)->priv;
174   g_hash_table_destroy (priv->color_properties);
175   g_object_unref (priv->style);
176
177   G_OBJECT_CLASS (_gtk_modifier_style_parent_class)->finalize (object);
178 }
179
180 GtkModifierStyle *
181 _gtk_modifier_style_new (void)
182 {
183   return g_object_new (GTK_TYPE_MODIFIER_STYLE, NULL);
184 }
185
186 static void
187 modifier_style_set_color (GtkModifierStyle *style,
188                           const gchar      *prop,
189                           GtkStateFlags     state,
190                           const GdkRGBA    *color)
191 {
192   GtkModifierStylePrivate *priv;
193
194   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
195
196   priv = style->priv;
197
198   if (color)
199     gtk_style_properties_set (priv->style, state,
200                               prop, color,
201                               NULL);
202   else
203     gtk_style_properties_unset_property (priv->style, prop, state);
204
205   g_signal_emit (style, signals[CHANGED], 0);
206 }
207
208 void
209 _gtk_modifier_style_set_background_color (GtkModifierStyle *style,
210                                           GtkStateFlags     state,
211                                           const GdkRGBA    *color)
212 {
213   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
214
215   modifier_style_set_color (style, "background-color", state, color);
216 }
217
218 void
219 _gtk_modifier_style_set_color (GtkModifierStyle *style,
220                                GtkStateFlags     state,
221                                const GdkRGBA    *color)
222 {
223   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
224
225   modifier_style_set_color (style, "color", state, color);
226 }
227
228 void
229 _gtk_modifier_style_set_font (GtkModifierStyle           *style,
230                               const PangoFontDescription *font_desc)
231 {
232   GtkModifierStylePrivate *priv;
233
234   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
235
236   priv = style->priv;
237
238   if (font_desc)
239     gtk_style_properties_set (priv->style, 0,
240                               "font", font_desc,
241                               NULL);
242   else
243     gtk_style_properties_unset_property (priv->style, "font", 0);
244
245   g_signal_emit (style, signals[CHANGED], 0);
246 }
247
248 void
249 _gtk_modifier_style_map_color (GtkModifierStyle *style,
250                                const gchar      *name,
251                                const GdkRGBA    *color)
252 {
253   GtkModifierStylePrivate *priv;
254   GtkSymbolicColor *symbolic_color = NULL;
255
256   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
257   g_return_if_fail (name != NULL);
258
259   priv = style->priv;
260
261   if (color)
262     symbolic_color = gtk_symbolic_color_new_literal (color);
263
264   gtk_style_properties_map_color (priv->style,
265                                   name, symbolic_color);
266
267   g_signal_emit (style, signals[CHANGED], 0);
268 }
269
270 void
271 _gtk_modifier_style_set_color_property (GtkModifierStyle *style,
272                                         GType             widget_type,
273                                         const gchar      *prop_name,
274                                         const GdkRGBA    *color)
275 {
276   GtkModifierStylePrivate *priv;
277   const GdkRGBA *old_color;
278   gchar *str;
279
280   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
281   g_return_if_fail (g_type_is_a (widget_type, GTK_TYPE_WIDGET));
282   g_return_if_fail (prop_name != NULL);
283
284   priv = style->priv;
285   str = g_strdup_printf ("-%s-%s", g_type_name (widget_type), prop_name);
286
287   old_color = g_hash_table_lookup (priv->color_properties, str);
288
289   if ((!color && !old_color) ||
290       (color && old_color && gdk_rgba_equal (color, old_color)))
291     {
292       g_free (str);
293       return;
294     }
295
296   if (color)
297     {
298       g_hash_table_insert (priv->color_properties, str,
299                            gdk_rgba_copy (color));
300     }
301   else
302     {
303       g_hash_table_remove (priv->color_properties, str);
304       g_free (str);
305     }
306
307   g_signal_emit (style, signals[CHANGED], 0);
308 }