]> Pileus Git - ~andy/gtk/blob - gtk/gtkrcdata.c
and on goes the crusade. it just takes another dozen patchup commits
[~andy/gtk] / gtk / gtkrcdata.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2000 Red Hat, Inc.
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 Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include        "gtkrcdata.h"
19
20
21
22 /* --- prototypes --- */
23 static void     gtk_rc_data_init                (GtkRCData              *data);
24 static void     gtk_rc_data_class_init          (GtkRCDataClass         *class);
25 static GObject* gtk_rc_data_constructor         (GType                   type,
26                                                  guint                   n_construct_properties,
27                                                  GObjectConstructParam  *construct_properties);
28 static void     gtk_rc_data_get_property        (GObject                *object,
29                                                  guint                   property_id,
30                                                  GValue                 *value,
31                                                  GParamSpec             *pspec,
32                                                  const gchar            *trailer);
33 static void     gtk_rc_data_set_property        (GObject                *object,
34                                                  guint                   property_id,
35                                                  const GValue           *value,
36                                                  GParamSpec             *pspec,
37                                                  const gchar            *trailer);
38 static void     gtk_rc_data_notify              (GObject                *object,
39                                                  GParamSpec             *pspec);
40
41
42 /* --- variables --- */
43 static gpointer          parent_class = NULL;
44 static GtkRCData        *the_singleton = NULL;
45
46
47 /* --- functions --- */
48 GType
49 gtk_rc_data_get_type (void)
50 {
51   static GType rc_data_type = 0;
52
53   if (!rc_data_type)
54     {
55       static const GTypeInfo rc_data_info =
56       {
57         sizeof (GtkRCDataClass),
58         NULL,           /* base_init */
59         NULL,           /* base_finalize */
60         (GClassInitFunc) gtk_rc_data_class_init,
61         NULL,           /* class_finalize */
62         NULL,           /* class_data */
63         sizeof (GtkRCData),
64         0,              /* n_preallocs */
65         (GInstanceInitFunc) gtk_rc_data_init,
66       };
67
68       rc_data_type = g_type_register_static (G_TYPE_OBJECT, "GtkRCData", &rc_data_info, 0);
69     }
70
71   return rc_data_type;
72 }
73
74 static void
75 gtk_rc_data_init (GtkRCData *data)
76 {
77   g_datalist_init (&data->qvalues);
78   data->pvalues = NULL;
79 }
80
81 static void
82 gtk_rc_data_class_init (GtkRCDataClass *class)
83 {
84   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
85
86   parent_class = g_type_class_peek_parent (class);
87
88   gobject_class->constructor = gtk_rc_data_constructor;
89   gobject_class->get_property = gtk_rc_data_get_property;
90   gobject_class->set_property = gtk_rc_data_set_property;
91   gobject_class->notify = gtk_rc_data_notify;
92 }
93
94 static GObject*
95 gtk_rc_data_constructor (GType                  type,
96                          guint                  n_construct_properties,
97                          GObjectConstructParam *construct_properties)
98 {
99   GObject *object;
100
101   if (!the_singleton)
102     {
103       object = G_OBJECT_CLASS (parent_class)->constructor (type,
104                                                            n_construct_properties,
105                                                            construct_properties);
106       the_singleton = GTK_RC_DATA (g_object_ref (object));
107     }
108   else
109     object = g_object_ref (G_OBJECT (the_singleton));
110
111   return object;
112 }
113
114 GtkRCData*
115 gtk_rc_data_get_global (void)
116 {
117   if (!the_singleton)
118     g_object_new (GTK_TYPE_RC_DATA, NULL);
119
120   return the_singleton; /* we don't add a reference count here, we'd be rc_data_ref_global() if we did */
121 }
122
123 static void
124 set_property (GtkRCData      *data,
125               GParamSpec     *pspec,
126               GtkRCDataValue *dvalue)
127 {
128   if (g_value_types_exchangable (G_VALUE_TYPE (&dvalue->rc_value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
129     {
130       GValue tmp_value = { 0, };
131
132       g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
133       g_value_convert (&dvalue->rc_value, &tmp_value);
134       g_param_value_validate (pspec, &tmp_value);
135       g_object_set_property (G_OBJECT (data), pspec->name, &tmp_value);
136       g_value_unset (&tmp_value);
137     }
138   else
139     g_message ("%s: unable to convert rc-value of type `%s' for rc-property \"%s\" of type `%s'",
140                dvalue->location,
141                G_VALUE_TYPE_NAME (&dvalue->rc_value),
142                pspec->name,
143                g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)));
144 }
145
146 static void
147 gtk_rc_data_set_property (GObject      *object,
148                           guint         property_id,
149                           const GValue *value,
150                           GParamSpec   *pspec,
151                           const gchar  *trailer)
152 {
153   GtkRCData *data = GTK_RC_DATA (object);
154
155   g_value_copy (value, data->pvalues + property_id - 1);
156 }
157
158 static void
159 gtk_rc_data_get_property (GObject     *object,
160                           guint        property_id,
161                           GValue      *value,
162                           GParamSpec  *pspec,
163                           const gchar *trailer)
164 {
165   GtkRCData *data = GTK_RC_DATA (object);
166
167   g_value_copy (data->pvalues + property_id - 1, value);
168 }
169
170 static void
171 gtk_rc_data_notify (GObject    *object,
172                     GParamSpec *pspec)
173 {
174   GValue tmp_value = { 0, };
175
176   g_value_init (&tmp_value, G_PARAM_SPEC_VALUE_TYPE (pspec));
177   g_object_get_property (object, pspec->name, &tmp_value);
178   g_print ("rc-file property \"%s\" set to %p\n",
179            pspec->name,
180            tmp_value.data[0].v_pointer);
181   g_value_unset (&tmp_value);
182 }
183
184 void
185 gtk_rc_data_install_property (GParamSpec *pspec)
186 {
187   GtkRCData *data = gtk_rc_data_get_global ();
188
189   g_return_if_fail (G_IS_PARAM_SPEC (pspec));
190
191   switch (G_TYPE_FUNDAMENTAL (G_PARAM_SPEC_VALUE_TYPE (pspec)))
192     {
193     case G_TYPE_BOOLEAN:
194     case G_TYPE_UCHAR:
195     case G_TYPE_CHAR:
196     case G_TYPE_UINT:
197     case G_TYPE_INT:
198     case G_TYPE_ULONG:
199     case G_TYPE_LONG:
200     case G_TYPE_FLOAT:
201     case G_TYPE_DOUBLE:
202     case G_TYPE_STRING:
203       break;
204     default:
205       g_warning (G_STRLOC ": property type `%s' is not supported for rc-data property \"%s\"",
206                  g_type_name (G_PARAM_SPEC_VALUE_TYPE (pspec)), pspec->name);
207       return;
208     }
209   g_object_freeze_notify (G_OBJECT (data));
210   if (!g_object_class_find_property (G_OBJECT_GET_CLASS (data), pspec->name))
211     {
212       static guint n_properties = 0;
213       GtkRCDataValue *dvalue;
214
215       g_object_class_install_property (G_OBJECT_GET_CLASS (data), ++n_properties, pspec);
216       data->pvalues = g_renew (GValue, data->pvalues, n_properties);
217       data->pvalues[n_properties - 1].g_type = 0;
218       g_value_init (data->pvalues + n_properties - 1, G_PARAM_SPEC_VALUE_TYPE (pspec));
219       g_param_value_set_default (pspec, data->pvalues + n_properties - 1);
220       g_object_notify (G_OBJECT (data), pspec->name);
221
222       dvalue = g_datalist_get_data (&data->qvalues, pspec->name);
223       if (dvalue)
224         set_property (data, pspec, dvalue);
225     }
226   else
227     g_warning (G_STRLOC ": an rc-data property \"%s\" already exists",
228                pspec->name);
229   g_object_thaw_notify (G_OBJECT (data));
230 }
231
232 static void
233 free_value (gpointer data)
234 {
235   GtkRCDataValue *dvalue = data;
236
237   g_value_unset (&dvalue->rc_value);
238   g_free (dvalue->location);
239   g_free (dvalue);
240 }
241
242 static void
243 set_value (GtkRCData   *data,
244            const gchar *vname,
245            GValue      *value,
246            const gchar *location)
247 {
248   GtkRCDataValue *dvalue;
249   GParamSpec *pspec;
250   gchar *name = g_strdup (vname);
251
252   g_strcanon (name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
253
254   dvalue = g_datalist_get_data (&data->qvalues, name);
255   if (!dvalue)
256     {
257       dvalue = g_new0 (GtkRCDataValue, 1);
258       g_datalist_set_data_full (&data->qvalues, name, dvalue, free_value);
259     }
260   else
261     g_value_unset (&dvalue->rc_value);
262   g_free (dvalue->location);
263   dvalue->location = g_strdup (location);
264   g_value_init (&dvalue->rc_value, G_VALUE_TYPE (value));
265   g_value_copy (value, &dvalue->rc_value);
266   pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (data), name);
267   if (pspec)
268     set_property (data, pspec, dvalue);
269   g_free (name);
270 }
271
272 void
273 gtk_rc_data_set_string_property (const gchar *name,
274                                  const gchar *v_string,
275                                  const gchar *location)
276 {
277   GtkRCData *data = gtk_rc_data_get_global ();
278   GValue value = { 0, };
279
280   g_return_if_fail (name != NULL);
281   g_return_if_fail (v_string != NULL);
282
283   g_object_freeze_notify (G_OBJECT (data));
284   g_value_init (&value, G_TYPE_STRING);
285   g_value_set_static_string (&value, v_string);
286   set_value (data, name, &value, location);
287   g_value_unset (&value);
288   g_object_thaw_notify (G_OBJECT (data));
289 }
290
291 void
292 gtk_rc_data_set_long_property (const gchar *name,
293                                glong        v_long,
294                                const gchar *location)
295 {
296   GtkRCData *data = gtk_rc_data_get_global ();
297   GValue value = { 0, };
298
299   g_return_if_fail (name != NULL);
300
301   g_object_freeze_notify (G_OBJECT (data));
302   g_value_init (&value, G_TYPE_LONG);
303   g_value_set_long (&value, v_long);
304   set_value (data, name, &value, location);
305   g_value_unset (&value);
306   g_object_thaw_notify (G_OBJECT (data));
307 }
308
309 void
310 gtk_rc_data_set_double_property (const gchar *name,
311                                  gdouble      v_double,
312                                  const gchar *location)
313 {
314   GtkRCData *data = gtk_rc_data_get_global ();
315   GValue value = { 0, };
316
317   g_return_if_fail (name != NULL);
318
319   g_object_freeze_notify (G_OBJECT (data));
320   g_value_init (&value, G_TYPE_DOUBLE);
321   g_value_set_double (&value, v_double);
322   set_value (data, name, &value, location);
323   g_value_unset (&value);
324   g_object_thaw_notify (G_OBJECT (data));
325 }