]> Pileus Git - ~andy/gtk/blob - gtk/gtkmodifierstyle.c
a8f4d3d72952f0a5a6c6ca7ea02aa50a2cc84171
[~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   GdkColor *color;
102   gchar *str;
103
104   /* Reject non-color types for now */
105   if (pspec->value_type != GDK_TYPE_COLOR)
106     return FALSE;
107
108   priv = GTK_MODIFIER_STYLE (provider)->priv;
109   str = g_strdup_printf ("-%s-%s",
110                          g_type_name (pspec->owner_type),
111                          pspec->name);
112
113   color = g_hash_table_lookup (priv->color_properties, str);
114   g_free (str);
115
116   if (!color)
117     return FALSE;
118
119   g_value_set_boxed (value, color);
120   return TRUE;
121 }
122
123 static void
124 gtk_modifier_style_provider_init (GtkStyleProviderIface *iface)
125 {
126   iface->get_style = gtk_modifier_style_get_style;
127   iface->get_style_property = gtk_modifier_style_get_style_property;
128 }
129
130 static void
131 gtk_modifier_style_finalize (GObject *object)
132 {
133   GtkModifierStylePrivate *priv;
134
135   priv = GTK_MODIFIER_STYLE (object)->priv;
136   g_hash_table_destroy (priv->color_properties);
137   g_object_unref (priv->style);
138
139   G_OBJECT_CLASS (gtk_modifier_style_parent_class)->finalize (object);
140 }
141
142 GtkModifierStyle *
143 gtk_modifier_style_new (void)
144 {
145   return g_object_new (GTK_TYPE_MODIFIER_STYLE, NULL);
146 }
147
148 static void
149 modifier_style_set_color (GtkModifierStyle *style,
150                           const gchar      *prop,
151                           GtkStateFlags     state,
152                           const GdkRGBA    *color)
153 {
154   GtkModifierStylePrivate *priv;
155   GdkRGBA *old_color;
156
157   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
158
159   priv = style->priv;
160   gtk_style_properties_get (priv->style, state,
161                             prop, &old_color,
162                             NULL);
163
164   if ((!color && !old_color) ||
165       (color && old_color && gdk_rgba_equal (color, old_color)))
166     {
167       gdk_rgba_free (old_color);
168       return;
169     }
170
171   if (color)
172     gtk_style_properties_set (priv->style, state,
173                               prop, color,
174                               NULL);
175   else
176     gtk_style_properties_unset_property (priv->style, prop, state);
177
178   g_signal_emit (style, signals[CHANGED], 0);
179   gdk_rgba_free (old_color);
180 }
181
182 void
183 gtk_modifier_style_set_background_color (GtkModifierStyle *style,
184                                          GtkStateFlags     state,
185                                          const GdkRGBA    *color)
186 {
187   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
188
189   modifier_style_set_color (style, "background-color", state, color);
190 }
191
192 void
193 gtk_modifier_style_set_color (GtkModifierStyle *style,
194                               GtkStateFlags     state,
195                               const GdkRGBA    *color)
196 {
197   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
198
199   modifier_style_set_color (style, "color", state, color);
200 }
201
202 void
203 gtk_modifier_style_set_font (GtkModifierStyle           *style,
204                              const PangoFontDescription *font_desc)
205 {
206   GtkModifierStylePrivate *priv;
207   PangoFontDescription *old_font;
208
209   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
210
211   priv = style->priv;
212   gtk_style_properties_get (priv->style, 0,
213                             "font", &old_font,
214                             NULL);
215
216   if ((!old_font && !font_desc) ||
217       (old_font && font_desc &&
218        pango_font_description_equal (old_font, font_desc)))
219     return;
220
221   if (font_desc)
222     gtk_style_properties_set (priv->style, 0,
223                               "font", font_desc,
224                               NULL);
225   else
226     gtk_style_properties_unset_property (priv->style, "font", 0);
227
228   g_signal_emit (style, signals[CHANGED], 0);
229 }
230
231 void
232 gtk_modifier_style_map_color (GtkModifierStyle *style,
233                               const gchar      *name,
234                               const GdkRGBA    *color)
235 {
236   GtkModifierStylePrivate *priv;
237   GtkSymbolicColor *symbolic_color = NULL;
238
239   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
240   g_return_if_fail (name != NULL);
241
242   priv = style->priv;
243
244   if (color)
245     symbolic_color = gtk_symbolic_color_new_literal (color);
246
247   gtk_style_properties_map_color (priv->style,
248                                   name, symbolic_color);
249
250   g_signal_emit (style, signals[CHANGED], 0);
251 }
252
253 void
254 gtk_modifier_style_set_color_property (GtkModifierStyle *style,
255                                        GType             widget_type,
256                                        const gchar      *prop_name,
257                                        const GdkColor   *color)
258 {
259   GtkModifierStylePrivate *priv;
260   const GdkColor *old_color;
261   gchar *str;
262
263   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
264   g_return_if_fail (g_type_is_a (widget_type, GTK_TYPE_WIDGET));
265   g_return_if_fail (prop_name != NULL);
266
267   priv = style->priv;
268   str = g_strdup_printf ("-%s-%s", g_type_name (widget_type), prop_name);
269
270   old_color = g_hash_table_lookup (priv->color_properties, str);
271
272   if ((!color && !old_color) ||
273       (color && old_color && gdk_color_equal (color, old_color)))
274     {
275       g_free (str);
276       return;
277     }
278
279   if (color)
280     g_hash_table_insert (priv->color_properties, str,
281                          gdk_color_copy (color));
282   else
283     g_hash_table_remove (priv->color_properties, str);
284
285   g_signal_emit (style, signals[CHANGED], 0);
286   g_free (str);
287 }