1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2011 Red Hat, Inc.
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.
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.
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/>.
20 #include "gtkcsspositionvalueprivate.h"
22 #include "gtkcssnumbervalueprivate.h"
31 gtk_css_value_position_free (GtkCssValue *value)
33 _gtk_css_value_unref (value->x);
34 _gtk_css_value_unref (value->y);
36 g_slice_free (GtkCssValue, value);
40 gtk_css_value_position_compute (GtkCssValue *position,
42 GtkStyleProviderPrivate *provider,
43 GtkCssComputedValues *values,
44 GtkCssComputedValues *parent_values,
45 GtkCssDependencies *dependencies)
48 GtkCssDependencies x_deps, y_deps;
50 x = _gtk_css_value_compute (position->x, property_id, provider, values, parent_values, &x_deps);
51 y = _gtk_css_value_compute (position->y, property_id, provider, values, parent_values, &y_deps);
52 *dependencies = _gtk_css_dependencies_union (x_deps, y_deps);
53 if (x == position->x && y == position->y)
55 _gtk_css_value_unref (x);
56 _gtk_css_value_unref (y);
57 return _gtk_css_value_ref (position);
60 return _gtk_css_position_value_new (x, y);
64 gtk_css_value_position_equal (const GtkCssValue *position1,
65 const GtkCssValue *position2)
67 return _gtk_css_value_equal (position1->x, position2->x)
68 && _gtk_css_value_equal (position1->y, position2->y);
72 gtk_css_value_position_transition (GtkCssValue *start,
79 x = _gtk_css_value_transition (start->x, end->x, property_id, progress);
82 y = _gtk_css_value_transition (start->y, end->y, property_id, progress);
85 _gtk_css_value_unref (x);
89 return _gtk_css_position_value_new (x, y);
93 gtk_css_value_position_print (const GtkCssValue *position,
101 { "left", "top", _gtk_css_number_value_new (0, GTK_CSS_PERCENT) },
102 { "right", "bottom", _gtk_css_number_value_new (100, GTK_CSS_PERCENT) }
104 GtkCssValue *center = _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
107 if (_gtk_css_value_equal (position->x, center))
109 if (_gtk_css_value_equal (position->y, center))
111 g_string_append (string, "center");
117 for (i = 0; i < G_N_ELEMENTS (values); i++)
119 if (_gtk_css_value_equal (position->x, values[i].number))
121 g_string_append (string, values[i].x_name);
125 if (i == G_N_ELEMENTS (values))
126 _gtk_css_value_print (position->x, string);
128 if (_gtk_css_value_equal (position->y, center))
131 g_string_append_c (string, ' ');
134 for (i = 0; i < G_N_ELEMENTS (values); i++)
136 if (_gtk_css_value_equal (position->y, values[i].number))
138 g_string_append (string, values[i].y_name);
142 if (i == G_N_ELEMENTS (values))
144 if (_gtk_css_value_equal (position->x, center))
145 g_string_append (string, "center ");
146 _gtk_css_value_print (position->y, string);
150 for (i = 0; i < G_N_ELEMENTS (values); i++)
151 _gtk_css_value_unref (values[i].number);
152 _gtk_css_value_unref (center);
155 static const GtkCssValueClass GTK_CSS_VALUE_POSITION = {
156 gtk_css_value_position_free,
157 gtk_css_value_position_compute,
158 gtk_css_value_position_equal,
159 gtk_css_value_position_transition,
160 gtk_css_value_position_print
164 _gtk_css_position_value_new (GtkCssValue *x,
169 result = _gtk_css_value_new (GtkCssValue, >K_CSS_VALUE_POSITION);
177 position_value_parse (GtkCssParser *parser, gboolean try)
179 static const struct {
185 { "left", 0, TRUE, FALSE },
186 { "right", 100, TRUE, FALSE },
187 { "center", 50, TRUE, TRUE },
188 { "top", 0, FALSE, TRUE },
189 { "bottom", 100, FALSE, TRUE },
190 { NULL , 0, TRUE, FALSE }, /* used for numbers */
191 { NULL , 50, TRUE, TRUE } /* used for no value */
194 GtkCssValue **missing;
197 for (first = 0; names[first].name != NULL; first++)
199 if (_gtk_css_parser_try (parser, names[first].name, TRUE))
201 if (names[first].horizontal)
203 x = _gtk_css_number_value_new (names[first].percentage, GTK_CSS_PERCENT);
208 y = _gtk_css_number_value_new (names[first].percentage, GTK_CSS_PERCENT);
214 if (names[first].name == NULL)
216 if (_gtk_css_parser_has_number (parser))
219 x = _gtk_css_number_value_parse (parser,
220 GTK_CSS_PARSE_PERCENT
221 | GTK_CSS_PARSE_LENGTH);
229 _gtk_css_parser_error (parser, "Unrecognized position value");
234 for (second = 0; names[second].name != NULL; second++)
236 if (_gtk_css_parser_try (parser, names[second].name, TRUE))
238 *missing = _gtk_css_number_value_new (names[second].percentage, GTK_CSS_PERCENT);
243 if (names[second].name == NULL)
245 if (_gtk_css_parser_has_number (parser))
250 _gtk_css_parser_error (parser, "Invalid combination of values");
251 _gtk_css_value_unref (y);
254 y = _gtk_css_number_value_parse (parser,
255 GTK_CSS_PARSE_PERCENT
256 | GTK_CSS_PARSE_LENGTH);
259 _gtk_css_value_unref (x);
266 *missing = _gtk_css_number_value_new (50, GTK_CSS_PERCENT);
271 if ((names[first].horizontal && !names[second].vertical) ||
272 (!names[first].horizontal && !names[second].horizontal))
275 _gtk_css_parser_error (parser, "Invalid combination of values");
276 _gtk_css_value_unref (x);
277 _gtk_css_value_unref (y);
282 return _gtk_css_position_value_new (x, y);
286 _gtk_css_position_value_parse (GtkCssParser *parser)
288 return position_value_parse (parser, FALSE);
292 _gtk_css_position_value_try_parse (GtkCssParser *parser)
294 return position_value_parse (parser, TRUE);
298 _gtk_css_position_value_get_x (const GtkCssValue *position,
299 double one_hundred_percent)
301 g_return_val_if_fail (position != NULL, 0.0);
302 g_return_val_if_fail (position->class == >K_CSS_VALUE_POSITION, 0.0);
304 return _gtk_css_number_value_get (position->x, one_hundred_percent);
308 _gtk_css_position_value_get_y (const GtkCssValue *position,
309 double one_hundred_percent)
311 g_return_val_if_fail (position != NULL, 0.0);
312 g_return_val_if_fail (position->class == >K_CSS_VALUE_POSITION, 0.0);
314 return _gtk_css_number_value_get (position->y, one_hundred_percent);