]> Pileus Git - ~andy/gtk/blob - gtk/gtkmodifierstyle.c
d81b9bcb06aa7d5bd80c567e60e394eed1a8b9eb
[~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 StylePropertyValue StylePropertyValue;
25
26 struct _GtkModifierStylePrivate
27 {
28   GtkStyleProperties *style;
29   GHashTable *color_properties;
30 };
31
32 enum {
33   CHANGED,
34   LAST_SIGNAL
35 };
36
37 static guint signals [LAST_SIGNAL] = { 0 };
38
39 static void gtk_modifier_style_provider_init (GtkStyleProviderIface *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
46 static void
47 _gtk_modifier_style_class_init (GtkModifierStyleClass *klass)
48 {
49   GObjectClass *object_class;
50
51   object_class = G_OBJECT_CLASS (klass);
52
53   object_class->finalize = gtk_modifier_style_finalize;
54
55   signals[CHANGED] =
56     g_signal_new (I_("changed"),
57                   G_TYPE_FROM_CLASS (object_class),
58                   G_SIGNAL_RUN_LAST,
59                   0, NULL, NULL,
60                   g_cclosure_marshal_VOID__VOID,
61                   G_TYPE_NONE, 0);
62
63   g_type_class_add_private (object_class, sizeof (GtkModifierStylePrivate));
64 }
65
66 static void
67 _gtk_modifier_style_init (GtkModifierStyle *modifier_style)
68 {
69   GtkModifierStylePrivate *priv;
70
71   priv = modifier_style->priv = G_TYPE_INSTANCE_GET_PRIVATE (modifier_style,
72                                                              GTK_TYPE_MODIFIER_STYLE,
73                                                              GtkModifierStylePrivate);
74
75   priv->color_properties = g_hash_table_new_full (g_str_hash,
76                                                   g_str_equal,
77                                                   (GDestroyNotify) g_free,
78                                                   (GDestroyNotify) gdk_rgba_free);
79   priv->style = gtk_style_properties_new ();
80 }
81
82 static GtkStyleProperties *
83 gtk_modifier_style_get_style (GtkStyleProvider *provider,
84                               GtkWidgetPath    *path)
85 {
86   GtkModifierStylePrivate *priv;
87
88   priv = GTK_MODIFIER_STYLE (provider)->priv;
89   return g_object_ref (priv->style);
90 }
91
92 static gboolean
93 gtk_modifier_style_get_style_property (GtkStyleProvider *provider,
94                                        GtkWidgetPath    *path,
95                                        GtkStateFlags     state,
96                                        GParamSpec       *pspec,
97                                        GValue           *value)
98 {
99   GtkModifierStylePrivate *priv;
100   GdkRGBA *rgba;
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   rgba = g_hash_table_lookup (priv->color_properties, str);
114   g_free (str);
115
116   if (!rgba)
117     return FALSE;
118
119   color.red = (guint) (rgba->red * 65535.) + 0.5;
120   color.green = (guint) (rgba->green * 65535.) + 0.5;
121   color.blue = (guint) (rgba->blue * 65535.) + 0.5;
122
123   g_value_set_boxed (value, &color);
124   return TRUE;
125 }
126
127 static void
128 gtk_modifier_style_provider_init (GtkStyleProviderIface *iface)
129 {
130   iface->get_style = gtk_modifier_style_get_style;
131   iface->get_style_property = gtk_modifier_style_get_style_property;
132 }
133
134 static void
135 gtk_modifier_style_finalize (GObject *object)
136 {
137   GtkModifierStylePrivate *priv;
138
139   priv = GTK_MODIFIER_STYLE (object)->priv;
140   g_hash_table_destroy (priv->color_properties);
141   g_object_unref (priv->style);
142
143   G_OBJECT_CLASS (_gtk_modifier_style_parent_class)->finalize (object);
144 }
145
146 GtkModifierStyle *
147 _gtk_modifier_style_new (void)
148 {
149   return g_object_new (GTK_TYPE_MODIFIER_STYLE, NULL);
150 }
151
152 static void
153 modifier_style_set_color (GtkModifierStyle *style,
154                           const gchar      *prop,
155                           GtkStateFlags     state,
156                           const GdkRGBA    *color)
157 {
158   GtkModifierStylePrivate *priv;
159
160   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
161
162   priv = style->priv;
163
164   if (color)
165     gtk_style_properties_set (priv->style, state,
166                               prop, color,
167                               NULL);
168   else
169     gtk_style_properties_unset_property (priv->style, prop, state);
170
171   g_signal_emit (style, signals[CHANGED], 0);
172 }
173
174 void
175 _gtk_modifier_style_set_background_color (GtkModifierStyle *style,
176                                           GtkStateFlags     state,
177                                           const GdkRGBA    *color)
178 {
179   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
180
181   modifier_style_set_color (style, "background-color", state, color);
182 }
183
184 void
185 _gtk_modifier_style_set_color (GtkModifierStyle *style,
186                                GtkStateFlags     state,
187                                const GdkRGBA    *color)
188 {
189   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
190
191   modifier_style_set_color (style, "color", state, color);
192 }
193
194 void
195 _gtk_modifier_style_set_font (GtkModifierStyle           *style,
196                               const PangoFontDescription *font_desc)
197 {
198   GtkModifierStylePrivate *priv;
199
200   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
201
202   priv = style->priv;
203
204   if (font_desc)
205     gtk_style_properties_set (priv->style, 0,
206                               "font", font_desc,
207                               NULL);
208   else
209     gtk_style_properties_unset_property (priv->style, "font", 0);
210
211   g_signal_emit (style, signals[CHANGED], 0);
212 }
213
214 void
215 _gtk_modifier_style_map_color (GtkModifierStyle *style,
216                                const gchar      *name,
217                                const GdkRGBA    *color)
218 {
219   GtkModifierStylePrivate *priv;
220   GtkSymbolicColor *symbolic_color = NULL;
221
222   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
223   g_return_if_fail (name != NULL);
224
225   priv = style->priv;
226
227   if (color)
228     symbolic_color = gtk_symbolic_color_new_literal (color);
229
230   gtk_style_properties_map_color (priv->style,
231                                   name, symbolic_color);
232
233   g_signal_emit (style, signals[CHANGED], 0);
234 }
235
236 void
237 _gtk_modifier_style_set_color_property (GtkModifierStyle *style,
238                                         GType             widget_type,
239                                         const gchar      *prop_name,
240                                         const GdkRGBA    *color)
241 {
242   GtkModifierStylePrivate *priv;
243   const GdkRGBA *old_color;
244   gchar *str;
245
246   g_return_if_fail (GTK_IS_MODIFIER_STYLE (style));
247   g_return_if_fail (g_type_is_a (widget_type, GTK_TYPE_WIDGET));
248   g_return_if_fail (prop_name != NULL);
249
250   priv = style->priv;
251   str = g_strdup_printf ("-%s-%s", g_type_name (widget_type), prop_name);
252
253   old_color = g_hash_table_lookup (priv->color_properties, str);
254
255   if ((!color && !old_color) ||
256       (color && old_color && gdk_rgba_equal (color, old_color)))
257     {
258       g_free (str);
259       return;
260     }
261
262   if (color)
263     {
264       g_hash_table_insert (priv->color_properties, str,
265                            gdk_rgba_copy (color));
266     }
267   else
268     {
269       g_hash_table_remove (priv->color_properties, str);
270       g_free (str);
271     }
272
273   g_signal_emit (style, signals[CHANGED], 0);
274 }