]> Pileus Git - ~andy/gtk/blob - gtk/gtkcssenumvalue.c
css: Introduce dependencies for value computations
[~andy/gtk] / gtk / gtkcssenumvalue.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 2011 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, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include "config.h"
19
20 #include "gtkcssenumvalueprivate.h"
21
22 #include "gtkstylepropertyprivate.h"
23
24 /* repeated API */
25
26 struct _GtkCssValue {
27   GTK_CSS_VALUE_BASE
28   int value;
29   const char *name;
30 };
31
32 static void
33 gtk_css_value_enum_free (GtkCssValue *value)
34 {
35   g_slice_free (GtkCssValue, value);
36 }
37
38 static GtkCssValue *
39 gtk_css_value_enum_compute (GtkCssValue        *value,
40                             guint               property_id,
41                             GtkStyleContext    *context,
42                             GtkCssDependencies *dependencies)
43 {
44   return _gtk_css_value_ref (value);
45 }
46
47 static gboolean
48 gtk_css_value_enum_equal (const GtkCssValue *enum1,
49                           const GtkCssValue *enum2)
50 {
51   return enum1 == enum2;
52 }
53
54 static GtkCssValue *
55 gtk_css_value_enum_transition (GtkCssValue *start,
56                                GtkCssValue *end,
57                                double       progress)
58 {
59   return NULL;
60 }
61
62 static void
63 gtk_css_value_enum_print (const GtkCssValue *value,
64                           GString           *string)
65 {
66   g_string_append (string, value->name);
67 }
68
69 /* GtkBorderStyle */
70
71 static const GtkCssValueClass GTK_CSS_VALUE_BORDER_STYLE = {
72   gtk_css_value_enum_free,
73   gtk_css_value_enum_compute,
74   gtk_css_value_enum_equal,
75   gtk_css_value_enum_transition,
76   gtk_css_value_enum_print
77 };
78
79 static GtkCssValue border_style_values[] = {
80   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_NONE, "none" },
81   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_SOLID, "solid" },
82   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_INSET, "inset" },
83   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_OUTSET, "outset" },
84   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_HIDDEN, "hidden" },
85   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOTTED, "dotted" },
86   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DASHED, "dashed" },
87   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_DOUBLE, "double" },
88   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_GROOVE, "groove" },
89   { &GTK_CSS_VALUE_BORDER_STYLE, 1, GTK_BORDER_STYLE_RIDGE, "ridge" }
90 };
91
92 GtkCssValue *
93 _gtk_css_border_style_value_new (GtkBorderStyle border_style)
94 {
95   g_return_val_if_fail (border_style < G_N_ELEMENTS (border_style_values), NULL);
96
97   return _gtk_css_value_ref (&border_style_values[border_style]);
98 }
99
100 GtkCssValue *
101 _gtk_css_border_style_value_try_parse (GtkCssParser *parser)
102 {
103   guint i;
104
105   g_return_val_if_fail (parser != NULL, NULL);
106
107   for (i = 0; i < G_N_ELEMENTS (border_style_values); i++)
108     {
109       if (_gtk_css_parser_try (parser, border_style_values[i].name, TRUE))
110         return _gtk_css_value_ref (&border_style_values[i]);
111     }
112
113   return NULL;
114 }
115
116 GtkBorderStyle
117 _gtk_css_border_style_value_get (const GtkCssValue *value)
118 {
119   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_BORDER_STYLE, GTK_BORDER_STYLE_NONE);
120
121   return value->value;
122 }
123
124 /* PangoStyle */
125
126 static const GtkCssValueClass GTK_CSS_VALUE_FONT_STYLE = {
127   gtk_css_value_enum_free,
128   gtk_css_value_enum_compute,
129   gtk_css_value_enum_equal,
130   gtk_css_value_enum_transition,
131   gtk_css_value_enum_print
132 };
133
134 static GtkCssValue font_style_values[] = {
135   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_NORMAL, "normal" },
136   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_OBLIQUE, "oblique" },
137   { &GTK_CSS_VALUE_FONT_STYLE, 1, PANGO_STYLE_ITALIC, "italic" }
138 };
139
140 GtkCssValue *
141 _gtk_css_font_style_value_new (PangoStyle font_style)
142 {
143   g_return_val_if_fail (font_style < G_N_ELEMENTS (font_style_values), NULL);
144
145   return _gtk_css_value_ref (&font_style_values[font_style]);
146 }
147
148 GtkCssValue *
149 _gtk_css_font_style_value_try_parse (GtkCssParser *parser)
150 {
151   guint i;
152
153   g_return_val_if_fail (parser != NULL, NULL);
154
155   for (i = 0; i < G_N_ELEMENTS (font_style_values); i++)
156     {
157       if (_gtk_css_parser_try (parser, font_style_values[i].name, TRUE))
158         return _gtk_css_value_ref (&font_style_values[i]);
159     }
160
161   return NULL;
162 }
163
164 PangoStyle
165 _gtk_css_font_style_value_get (const GtkCssValue *value)
166 {
167   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_STYLE, PANGO_STYLE_NORMAL);
168
169   return value->value;
170 }
171
172 /* PangoVariant */
173
174 static const GtkCssValueClass GTK_CSS_VALUE_FONT_VARIANT = {
175   gtk_css_value_enum_free,
176   gtk_css_value_enum_compute,
177   gtk_css_value_enum_equal,
178   gtk_css_value_enum_transition,
179   gtk_css_value_enum_print
180 };
181
182 static GtkCssValue font_variant_values[] = {
183   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_NORMAL, "normal" },
184   { &GTK_CSS_VALUE_FONT_VARIANT, 1, PANGO_VARIANT_SMALL_CAPS, "small-caps" }
185 };
186
187 GtkCssValue *
188 _gtk_css_font_variant_value_new (PangoVariant font_variant)
189 {
190   g_return_val_if_fail (font_variant < G_N_ELEMENTS (font_variant_values), NULL);
191
192   return _gtk_css_value_ref (&font_variant_values[font_variant]);
193 }
194
195 GtkCssValue *
196 _gtk_css_font_variant_value_try_parse (GtkCssParser *parser)
197 {
198   guint i;
199
200   g_return_val_if_fail (parser != NULL, NULL);
201
202   for (i = 0; i < G_N_ELEMENTS (font_variant_values); i++)
203     {
204       if (_gtk_css_parser_try (parser, font_variant_values[i].name, TRUE))
205         return _gtk_css_value_ref (&font_variant_values[i]);
206     }
207
208   return NULL;
209 }
210
211 PangoVariant
212 _gtk_css_font_variant_value_get (const GtkCssValue *value)
213 {
214   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_VARIANT, PANGO_VARIANT_NORMAL);
215
216   return value->value;
217 }
218
219 /* PangoWeight */
220
221 static const GtkCssValueClass GTK_CSS_VALUE_FONT_WEIGHT = {
222   gtk_css_value_enum_free,
223   gtk_css_value_enum_compute,
224   gtk_css_value_enum_equal,
225   gtk_css_value_enum_transition,
226   gtk_css_value_enum_print
227 };
228
229 static GtkCssValue font_weight_values[] = {
230   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_THIN, "100" },
231   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRALIGHT, "200" },
232   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_LIGHT, "300" },
233   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_NORMAL, "normal" },
234   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_MEDIUM, "500" },
235   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_SEMIBOLD, "600" },
236   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_BOLD, "bold" },
237   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_ULTRABOLD, "800" },
238   { &GTK_CSS_VALUE_FONT_WEIGHT, 1, PANGO_WEIGHT_HEAVY, "900" }
239 };
240
241 GtkCssValue *
242 _gtk_css_font_weight_value_new (PangoWeight font_weight)
243 {
244   guint i;
245   gint w;
246
247   w = ((font_weight + 50) / 100) * 100;
248
249   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
250     {
251       if (font_weight_values[i].value == w)
252         return _gtk_css_value_ref (&font_weight_values[i]);
253     }
254
255   g_return_val_if_reached (NULL);
256 }
257
258 GtkCssValue *
259 _gtk_css_font_weight_value_try_parse (GtkCssParser *parser)
260 {
261   guint i;
262
263   g_return_val_if_fail (parser != NULL, NULL);
264
265   for (i = 0; i < G_N_ELEMENTS (font_weight_values); i++)
266     {
267       if (_gtk_css_parser_try (parser, font_weight_values[i].name, TRUE))
268         return _gtk_css_value_ref (&font_weight_values[i]);
269     }
270   /* special cases go here */
271   if (_gtk_css_parser_try (parser, "400", TRUE))
272     return _gtk_css_value_ref (&font_weight_values[3]);
273   if (_gtk_css_parser_try (parser, "700", TRUE))
274     return _gtk_css_value_ref (&font_weight_values[6]);
275
276   return NULL;
277 }
278
279 PangoWeight
280 _gtk_css_font_weight_value_get (const GtkCssValue *value)
281 {
282   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_FONT_WEIGHT, PANGO_WEIGHT_NORMAL);
283
284   return value->value;
285 }
286
287 /* GtkCssArea */
288
289 static const GtkCssValueClass GTK_CSS_VALUE_AREA = {
290   gtk_css_value_enum_free,
291   gtk_css_value_enum_compute,
292   gtk_css_value_enum_equal,
293   gtk_css_value_enum_transition,
294   gtk_css_value_enum_print
295 };
296
297 static GtkCssValue area_values[] = {
298   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_BORDER_BOX, "border-box" },
299   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_PADDING_BOX, "padding-box" },
300   { &GTK_CSS_VALUE_AREA, 1, GTK_CSS_AREA_CONTENT_BOX, "content-box" }
301 };
302
303 GtkCssValue *
304 _gtk_css_area_value_new (GtkCssArea area)
305 {
306   guint i;
307
308   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
309     {
310       if (area_values[i].value == area)
311         return _gtk_css_value_ref (&area_values[i]);
312     }
313
314   g_return_val_if_reached (NULL);
315 }
316
317 GtkCssValue *
318 _gtk_css_area_value_try_parse (GtkCssParser *parser)
319 {
320   guint i;
321
322   g_return_val_if_fail (parser != NULL, NULL);
323
324   for (i = 0; i < G_N_ELEMENTS (area_values); i++)
325     {
326       if (_gtk_css_parser_try (parser, area_values[i].name, TRUE))
327         return _gtk_css_value_ref (&area_values[i]);
328     }
329
330   return NULL;
331 }
332
333 GtkCssArea
334 _gtk_css_area_value_get (const GtkCssValue *value)
335 {
336   g_return_val_if_fail (value->class == &GTK_CSS_VALUE_AREA, GTK_CSS_AREA_BORDER_BOX);
337
338   return value->value;
339 }
340