1 | /* |
2 | * Copyright © 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.1 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 | * Authors: Benjamin Otte <otte@gnome.org> |
18 | */ |
19 | |
20 | #include "config.h" |
21 | |
22 | #include "gtkcssshorthandpropertyprivate.h" |
23 | |
24 | #include "gtkcssarrayvalueprivate.h" |
25 | #include "gtkcssinheritvalueprivate.h" |
26 | #include "gtkcssinitialvalueprivate.h" |
27 | #include "gtkcssunsetvalueprivate.h" |
28 | #include "gtkintl.h" |
29 | |
30 | enum { |
31 | PROP_0, |
32 | PROP_SUBPROPERTIES, |
33 | }; |
34 | |
35 | G_DEFINE_TYPE (GtkCssShorthandProperty, _gtk_css_shorthand_property, GTK_TYPE_STYLE_PROPERTY) |
36 | |
37 | static void |
38 | gtk_css_shorthand_property_set_property (GObject *object, |
39 | guint prop_id, |
40 | const GValue *value, |
41 | GParamSpec *pspec) |
42 | { |
43 | GtkCssShorthandProperty *property = GTK_CSS_SHORTHAND_PROPERTY (object); |
44 | const char **subproperties; |
45 | guint i; |
46 | |
47 | switch (prop_id) |
48 | { |
49 | case PROP_SUBPROPERTIES: |
50 | subproperties = g_value_get_boxed (value); |
51 | g_assert (subproperties); |
52 | for (i = 0; subproperties[i] != NULL; i++) |
53 | { |
54 | GtkStyleProperty *subproperty = _gtk_style_property_lookup (name: subproperties[i]); |
55 | g_assert (GTK_IS_CSS_STYLE_PROPERTY (subproperty)); |
56 | g_ptr_array_add (array: property->subproperties, data: subproperty); |
57 | } |
58 | break; |
59 | default: |
60 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
61 | break; |
62 | } |
63 | } |
64 | |
65 | static GtkCssValue * |
66 | gtk_css_shorthand_property_parse_value (GtkStyleProperty *property, |
67 | GtkCssParser *parser) |
68 | { |
69 | GtkCssShorthandProperty *shorthand = GTK_CSS_SHORTHAND_PROPERTY (property); |
70 | const guint n_props = shorthand->subproperties->len; |
71 | GtkCssValue **data; |
72 | GtkCssValue *result; |
73 | guint i; |
74 | |
75 | data = g_newa (GtkCssValue *, n_props); |
76 | memset (s: data, c: 0, n: sizeof (GtkCssValue *) * n_props); |
77 | |
78 | if (gtk_css_parser_try_ident (self: parser, ident: "initial" )) |
79 | { |
80 | /* the initial value can be explicitly specified with the |
81 | * ‘initial’ keyword which all properties accept. |
82 | */ |
83 | return _gtk_css_initial_value_new (); |
84 | } |
85 | else if (gtk_css_parser_try_ident (self: parser, ident: "inherit" )) |
86 | { |
87 | /* All properties accept the ‘inherit’ value which |
88 | * explicitly specifies that the value will be determined |
89 | * by inheritance. The ‘inherit’ value can be used to |
90 | * strengthen inherited values in the cascade, and it can |
91 | * also be used on properties that are not normally inherited. |
92 | */ |
93 | return _gtk_css_inherit_value_new (); |
94 | } |
95 | else if (gtk_css_parser_try_ident (self: parser, ident: "unset" )) |
96 | { |
97 | /* If the cascaded value of a property is the unset keyword, |
98 | * then if it is an inherited property, this is treated as |
99 | * inherit, and if it is not, this is treated as initial. |
100 | */ |
101 | return _gtk_css_unset_value_new (); |
102 | } |
103 | else if (!shorthand->parse (shorthand, data, parser)) |
104 | { |
105 | for (i = 0; i < n_props; i++) |
106 | { |
107 | if (data[i] != NULL) |
108 | _gtk_css_value_unref (value: data[i]); |
109 | } |
110 | return NULL; |
111 | } |
112 | |
113 | /* All values that aren't set by the parse func are set to their |
114 | * default values here. |
115 | * XXX: Is the default always initial or can it be inherit? */ |
116 | for (i = 0; i < n_props; i++) |
117 | { |
118 | if (data[i] == NULL) |
119 | data[i] = _gtk_css_initial_value_new (); |
120 | } |
121 | |
122 | result = _gtk_css_array_value_new_from_array (values: data, n_values: n_props); |
123 | |
124 | return result; |
125 | } |
126 | |
127 | static void |
128 | _gtk_css_shorthand_property_class_init (GtkCssShorthandPropertyClass *klass) |
129 | { |
130 | GObjectClass *object_class = G_OBJECT_CLASS (klass); |
131 | GtkStylePropertyClass *property_class = GTK_STYLE_PROPERTY_CLASS (klass); |
132 | |
133 | object_class->set_property = gtk_css_shorthand_property_set_property; |
134 | |
135 | g_object_class_install_property (oclass: object_class, |
136 | property_id: PROP_SUBPROPERTIES, |
137 | pspec: g_param_spec_boxed (name: "subproperties" , |
138 | P_("Subproperties" ), |
139 | P_("The list of subproperties" ), |
140 | G_TYPE_STRV, |
141 | flags: G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); |
142 | |
143 | property_class->parse_value = gtk_css_shorthand_property_parse_value; |
144 | } |
145 | |
146 | static void |
147 | _gtk_css_shorthand_property_init (GtkCssShorthandProperty *shorthand) |
148 | { |
149 | shorthand->subproperties = g_ptr_array_new_with_free_func (element_free_func: g_object_unref); |
150 | } |
151 | |
152 | GtkCssStyleProperty * |
153 | _gtk_css_shorthand_property_get_subproperty (GtkCssShorthandProperty *shorthand, |
154 | guint property) |
155 | { |
156 | g_return_val_if_fail (GTK_IS_CSS_SHORTHAND_PROPERTY (shorthand), NULL); |
157 | g_return_val_if_fail (property < shorthand->subproperties->len, NULL); |
158 | |
159 | return g_ptr_array_index (shorthand->subproperties, property); |
160 | } |
161 | |
162 | guint |
163 | _gtk_css_shorthand_property_get_n_subproperties (GtkCssShorthandProperty *shorthand) |
164 | { |
165 | g_return_val_if_fail (GTK_IS_CSS_SHORTHAND_PROPERTY (shorthand), 0); |
166 | |
167 | return shorthand->subproperties->len; |
168 | } |
169 | |
170 | |