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