]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssshadowsvalue.c
cssvalue: Pass property ID to transition function
[~andy/gtk] / gtk / gtkcssshadowsvalue.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 Red Hat, Inc.
3  *
4  * Author: Cosimo Cecchi <cosimoc@gnome.org>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "config.h"
21
22 #include "gtkcssshadowsvalueprivate.h"
23
24 #include "gtkcssshadowvalueprivate.h"
25
26 #include <string.h>
27
28 struct _GtkCssValue {
29   GTK_CSS_VALUE_BASE
30   guint         len;
31   GtkCssValue  *values[1];
32 };
33
34 static GtkCssValue *    gtk_css_shadows_value_new       (GtkCssValue **values,
35                                                          guint         len);
36
37 static void
38 gtk_css_value_shadows_free (GtkCssValue *value)
39 {
40   guint i;
41
42   for (i = 0; i < value->len; i++)
43     {
44       _gtk_css_value_unref (value->values[i]);
45     }
46
47   g_slice_free1 (sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (value->len - 1), value);
48 }
49
50 static GtkCssValue *
51 gtk_css_value_shadows_compute (GtkCssValue        *value,
52                                guint               property_id,
53                                GtkStyleContext    *context,
54                                GtkCssDependencies *dependencies)
55 {
56   GtkCssValue *result;
57   GtkCssDependencies child_deps;
58   guint i;
59
60   if (value->len == 0)
61     return _gtk_css_value_ref (value);
62
63   result = gtk_css_shadows_value_new (value->values, value->len);
64   for (i = 0; i < value->len; i++)
65     {
66       result->values[i] = _gtk_css_value_compute (value->values[i], property_id, context, &child_deps);
67       *dependencies = _gtk_css_dependencies_union (*dependencies, child_deps);
68     }
69
70   return result;
71 }
72
73 static gboolean
74 gtk_css_value_shadows_equal (const GtkCssValue *value1,
75                              const GtkCssValue *value2)
76 {
77   guint i;
78
79   /* XXX: Should we fill up here? */
80   if (value1->len != value2->len)
81     return FALSE;
82
83   for (i = 0; i < value1->len; i++)
84     {
85       if (!_gtk_css_value_equal (value1->values[i],
86                                  value2->values[i]))
87         return FALSE;
88     }
89
90   return TRUE;
91 }
92
93 static GtkCssValue *
94 gtk_css_value_shadows_transition (GtkCssValue *start,
95                                   GtkCssValue *end,
96                                   guint        property_id,
97                                   double       progress)
98 {
99   GtkCssValue *result;
100   guint i;
101
102   /* catches the important case of 2 none values */
103   if (start == end)
104     return _gtk_css_value_ref (start);
105
106   if (start->len > end->len)
107     result = gtk_css_shadows_value_new (start->values, start->len);
108   else
109     result = gtk_css_shadows_value_new (end->values, end->len);
110
111   for (i = 0; i < MIN (start->len, end->len); i++)
112     {
113       result->values[i] = _gtk_css_value_transition (start->values[i], end->values[i], property_id, progress);
114     }
115   if (start->len > end->len)
116     {
117       for (; i < result->len; i++)
118         {
119           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (start->values[i]);
120           result->values[i] = _gtk_css_value_transition (start->values[i], fill, property_id, progress);
121           _gtk_css_value_unref (fill);
122         }
123     }
124   else
125     {
126       for (; i < result->len; i++)
127         {
128           GtkCssValue *fill = _gtk_css_shadow_value_new_for_transition (end->values[i]);
129           result->values[i] = _gtk_css_value_transition (fill, end->values[i], property_id, progress);
130           _gtk_css_value_unref (fill);
131         }
132     }
133
134   return result;
135 }
136
137 static void
138 gtk_css_value_shadows_print (const GtkCssValue *value,
139                              GString           *string)
140 {
141   guint i;
142
143   if (value->len == 0)
144     {
145       g_string_append (string, "none");
146       return;
147     }
148
149   for (i = 0; i < value->len; i++)
150     {
151       if (i > 0)
152         g_string_append (string, ", ");
153       _gtk_css_value_print (value->values[i], string);
154     }
155 }
156
157 static const GtkCssValueClass GTK_CSS_VALUE_SHADOWS = {
158   gtk_css_value_shadows_free,
159   gtk_css_value_shadows_compute,
160   gtk_css_value_shadows_equal,
161   gtk_css_value_shadows_transition,
162   gtk_css_value_shadows_print
163 };
164
165 static GtkCssValue none_singleton = { &GTK_CSS_VALUE_SHADOWS, 1, 0, { NULL } };
166
167 GtkCssValue *
168 _gtk_css_shadows_value_new_none (void)
169 {
170   return _gtk_css_value_ref (&none_singleton);
171 }
172
173 static GtkCssValue *
174 gtk_css_shadows_value_new (GtkCssValue **values,
175                            guint         len)
176 {
177   GtkCssValue *result;
178            
179   g_return_val_if_fail (values != NULL, NULL);
180   g_return_val_if_fail (len > 0, NULL);
181          
182   result = _gtk_css_value_alloc (&GTK_CSS_VALUE_SHADOWS, sizeof (GtkCssValue) + sizeof (GtkCssValue *) * (len - 1));
183   result->len = len;
184   memcpy (&result->values[0], values, sizeof (GtkCssValue *) * len);
185             
186   return result;
187 }
188
189 GtkCssValue *
190 _gtk_css_shadows_value_parse (GtkCssParser *parser)
191 {
192   GtkCssValue *value, *result;
193   GPtrArray *values;
194
195   if (_gtk_css_parser_try (parser, "none", TRUE))
196     return _gtk_css_shadows_value_new_none ();
197
198   values = g_ptr_array_new ();
199
200   do {
201     value = _gtk_css_shadow_value_parse (parser);
202
203     if (value == NULL)
204       {
205         g_ptr_array_set_free_func (values, (GDestroyNotify) _gtk_css_value_unref);
206         g_ptr_array_free (values, TRUE);
207         return NULL;
208       }
209
210     g_ptr_array_add (values, value);
211   } while (_gtk_css_parser_try (parser, ",", TRUE));
212
213   result = gtk_css_shadows_value_new ((GtkCssValue **) values->pdata, values->len);
214   g_ptr_array_free (values, TRUE);
215   return result;
216 }
217
218 void
219 _gtk_css_shadows_value_paint_layout (const GtkCssValue *shadows,
220                                      cairo_t           *cr,
221                                      PangoLayout       *layout)
222 {
223   guint i;
224
225   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
226
227   for (i = 0; i < shadows->len; i++)
228     {
229       _gtk_css_shadow_value_paint_layout (shadows->values[i], cr, layout);
230     }
231 }
232
233 void
234 _gtk_css_shadows_value_paint_icon (const GtkCssValue *shadows,
235                                    cairo_t           *cr)
236 {
237   guint i;
238
239   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
240
241   for (i = 0; i < shadows->len; i++)
242     {
243       _gtk_css_shadow_value_paint_icon (shadows->values[i], cr);
244     }
245 }
246
247 void
248 _gtk_css_shadows_value_paint_spinner (const GtkCssValue *shadows,
249                                       cairo_t           *cr,
250                                       gdouble            radius,
251                                       gdouble            progress)
252 {
253   guint i;
254
255   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
256
257   for (i = 0; i < shadows->len; i++)
258     {
259       _gtk_css_shadow_value_paint_spinner (shadows->values[i], cr, radius, progress);
260     }
261 }
262
263 void
264 _gtk_css_shadows_value_paint_box (const GtkCssValue   *shadows,
265                                   cairo_t             *cr,
266                                   const GtkRoundedBox *padding_box)
267 {
268   guint i;
269
270   g_return_if_fail (shadows->class == &GTK_CSS_VALUE_SHADOWS);
271
272   for (i = 0; i < shadows->len; i++)
273     {
274       _gtk_css_shadow_value_paint_box (shadows->values[i], cr, padding_box);
275     }
276 }