1 /* GTK - The GIMP Toolkit
2 * Copyright (C) 2010 Carlos Garnacho <carlosg@gnome.org>
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, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
22 #include "gtkstylepropertyprivate.h"
29 #include <gdk-pixbuf/gdk-pixbuf.h>
30 #include <cairo-gobject.h>
32 #include "gtkcssprovider.h"
33 #include "gtkcssparserprivate.h"
34 #include "gtkcssshorthandpropertyprivate.h"
35 #include "gtkcssstylefuncsprivate.h"
36 #include "gtkcssstylepropertyprivate.h"
37 #include "gtkcsstypesprivate.h"
39 #include "gtkprivatetypebuiltins.h"
40 #include "gtkstylepropertiesprivate.h"
42 /* the actual parsers we have */
43 #include "gtkanimationdescription.h"
44 #include "gtkbindings.h"
45 #include "gtkgradient.h"
46 #include "gtkshadowprivate.h"
47 #include "gtkthemingengine.h"
48 #include "gtktypebuiltins.h"
49 #include "gtkwin32themeprivate.h"
51 /* this is in case round() is not provided by the compiler,
52 * such as in the case of C89 compilers, like MSVC
54 #include "fallback-c89.c"
62 G_DEFINE_ABSTRACT_TYPE (GtkStyleProperty, _gtk_style_property, G_TYPE_OBJECT)
65 gtk_style_property_finalize (GObject *object)
67 GtkStyleProperty *property = GTK_STYLE_PROPERTY (object);
69 g_warning ("finalizing %s `%s', how could this happen?", G_OBJECT_TYPE_NAME (object), property->name);
71 G_OBJECT_CLASS (_gtk_style_property_parent_class)->finalize (object);
75 gtk_style_property_set_property (GObject *object,
80 GtkStyleProperty *property = GTK_STYLE_PROPERTY (object);
81 GtkStylePropertyClass *klass = GTK_STYLE_PROPERTY_GET_CLASS (property);
86 property->name = g_value_dup_string (value);
87 g_assert (property->name);
88 g_assert (g_hash_table_lookup (klass->properties, property->name) == NULL);
89 g_hash_table_insert (klass->properties, property->name, property);
92 property->value_type = g_value_get_gtype (value);
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101 gtk_style_property_get_property (GObject *object,
106 GtkStyleProperty *property = GTK_STYLE_PROPERTY (object);
111 g_value_set_string (value, property->name);
113 case PROP_VALUE_TYPE:
114 g_value_set_gtype (value, property->value_type);
117 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
123 _gtk_style_property_class_init (GtkStylePropertyClass *klass)
125 GObjectClass *object_class = G_OBJECT_CLASS (klass);
127 object_class->finalize = gtk_style_property_finalize;
128 object_class->set_property = gtk_style_property_set_property;
129 object_class->get_property = gtk_style_property_get_property;
131 g_object_class_install_property (object_class,
133 g_param_spec_string ("name",
135 P_("The name of the property"),
137 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
138 g_object_class_install_property (object_class,
140 g_param_spec_gtype ("value-type",
142 P_("The value type returned by GtkStyleContext"),
144 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
146 klass->properties = g_hash_table_new (g_str_hash, g_str_equal);
150 _gtk_style_property_init (GtkStyleProperty *property)
152 property->value_type = G_TYPE_NONE;
156 string_append_double (GString *string,
159 char buf[G_ASCII_DTOSTR_BUF_SIZE];
161 g_ascii_dtostr (buf, sizeof (buf), d);
162 g_string_append (string, buf);
166 string_append_string (GString *str,
171 g_string_append_c (str, '"');
174 len = strcspn (string, "\"\n\r\f");
175 g_string_append (str, string);
182 g_string_append (str, "\\A ");
185 g_string_append (str, "\\D ");
188 g_string_append (str, "\\C ");
191 g_string_append (str, "\\\"");
194 g_assert_not_reached ();
199 g_string_append_c (str, '"');
202 /*** IMPLEMENTATIONS ***/
205 enum_print (int value,
209 GEnumClass *enum_class;
210 GEnumValue *enum_value;
212 enum_class = g_type_class_ref (type);
213 enum_value = g_enum_get_value (enum_class, value);
215 g_string_append (string, enum_value->value_nick);
217 g_type_class_unref (enum_class);
221 font_family_parse (GtkCssParser *parser,
228 /* We don't special case generic families. Pango should do
231 names = g_ptr_array_new ();
234 name = _gtk_css_parser_try_ident (parser, TRUE);
237 GString *string = g_string_new (name);
239 while ((name = _gtk_css_parser_try_ident (parser, TRUE)))
241 g_string_append_c (string, ' ');
242 g_string_append (string, name);
245 name = g_string_free (string, FALSE);
249 name = _gtk_css_parser_read_string (parser);
252 g_ptr_array_free (names, TRUE);
257 g_ptr_array_add (names, name);
258 } while (_gtk_css_parser_try (parser, ",", TRUE));
260 /* NULL-terminate array */
261 g_ptr_array_add (names, NULL);
262 g_value_set_boxed (value, g_ptr_array_free (names, FALSE));
267 font_family_value_print (const GValue *value,
270 const char **names = g_value_get_boxed (value);
272 if (names == NULL || *names == NULL)
274 g_string_append (string, "none");
278 string_append_string (string, *names);
282 g_string_append (string, ", ");
283 string_append_string (string, *names);
289 bindings_value_parse (GtkCssParser *parser,
294 GtkBindingSet *binding_set;
297 array = g_ptr_array_new ();
300 name = _gtk_css_parser_try_ident (parser, TRUE);
303 _gtk_css_parser_error (parser, "Not a valid binding name");
304 g_ptr_array_free (array, TRUE);
308 binding_set = gtk_binding_set_find (name);
312 _gtk_css_parser_error (parser, "No binding set named '%s'", name);
317 g_ptr_array_add (array, binding_set);
320 while (_gtk_css_parser_try (parser, ",", TRUE));
322 g_value_take_boxed (value, array);
328 bindings_value_print (const GValue *value,
334 array = g_value_get_boxed (value);
336 for (i = 0; i < array->len; i++)
338 GtkBindingSet *binding_set = g_ptr_array_index (array, i);
341 g_string_append (string, ", ");
342 g_string_append (string, binding_set->set_name);
347 border_corner_radius_value_parse (GtkCssParser *parser,
351 GtkCssBorderCornerRadius corner;
353 if (!_gtk_css_parser_try_double (parser, &corner.horizontal))
355 _gtk_css_parser_error (parser, "Expected a number");
358 else if (corner.horizontal < 0)
361 if (!_gtk_css_parser_try_double (parser, &corner.vertical))
362 corner.vertical = corner.horizontal;
363 else if (corner.vertical < 0)
366 g_value_set_boxed (value, &corner);
370 _gtk_css_parser_error (parser, "Border radius values cannot be negative");
375 border_corner_radius_value_print (const GValue *value,
378 GtkCssBorderCornerRadius *corner;
380 corner = g_value_get_boxed (value);
384 g_string_append (string, "none");
388 string_append_double (string, corner->horizontal);
389 if (corner->horizontal != corner->vertical)
391 g_string_append_c (string, ' ');
392 string_append_double (string, corner->vertical);
399 _gtk_style_property_parse_value (GtkStyleProperty *property,
401 GtkCssParser *parser,
404 g_return_val_if_fail (value != NULL, FALSE);
405 g_return_val_if_fail (parser != NULL, FALSE);
409 if (_gtk_css_parser_try (parser, "initial", TRUE))
411 /* the initial value can be explicitly specified with the
412 * ‘initial’ keyword which all properties accept.
414 g_value_unset (value);
415 g_value_init (value, GTK_TYPE_CSS_SPECIAL_VALUE);
416 g_value_set_enum (value, GTK_CSS_INITIAL);
419 else if (_gtk_css_parser_try (parser, "inherit", TRUE))
421 /* All properties accept the ‘inherit’ value which
422 * explicitly specifies that the value will be determined
423 * by inheritance. The ‘inherit’ value can be used to
424 * strengthen inherited values in the cascade, and it can
425 * also be used on properties that are not normally inherited.
427 g_value_unset (value);
428 g_value_init (value, GTK_TYPE_CSS_SPECIAL_VALUE);
429 g_value_set_enum (value, GTK_CSS_INHERIT);
432 else if (property->property_parse_func)
434 GError *error = NULL;
438 value_str = _gtk_css_parser_read_value (parser);
439 if (value_str == NULL)
442 success = (*property->property_parse_func) (value_str, value, &error);
449 if (property->parse_func)
450 return (* property->parse_func) (parser, base, value);
453 return _gtk_css_style_parse_value (value, parser, base);
457 _gtk_style_property_print_value (GtkStyleProperty *property,
461 if (G_VALUE_HOLDS (value, GTK_TYPE_CSS_SPECIAL_VALUE))
462 enum_print (g_value_get_enum (value), GTK_TYPE_CSS_SPECIAL_VALUE, string);
463 else if (property && property->print_func)
464 (* property->print_func) (value, string);
466 _gtk_css_style_print_value (value, string);
470 _gtk_style_property_default_value (GtkStyleProperty *property,
471 GtkStyleProperties *properties,
475 g_value_copy (_gtk_css_style_property_get_initial_value (GTK_CSS_STYLE_PROPERTY (property)), value);
479 resolve_color (GtkStyleProperties *props,
484 /* Resolve symbolic color to GdkRGBA */
485 if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &color))
488 /* Store it back, this is where GdkRGBA caching happens */
489 g_value_unset (value);
490 g_value_init (value, GDK_TYPE_RGBA);
491 g_value_set_boxed (value, &color);
497 resolve_color_rgb (GtkStyleProperties *props,
500 GdkColor color = { 0 };
503 if (!gtk_symbolic_color_resolve (g_value_get_boxed (value), props, &rgba))
506 color.red = rgba.red * 65535. + 0.5;
507 color.green = rgba.green * 65535. + 0.5;
508 color.blue = rgba.blue * 65535. + 0.5;
510 g_value_unset (value);
511 g_value_init (value, GDK_TYPE_COLOR);
512 g_value_set_boxed (value, &color);
518 resolve_win32_theme_part (GtkStyleProperties *props,
521 GtkStylePropertyContext *context)
523 GtkWin32ThemePart *part;
524 cairo_pattern_t *pattern;
526 part = g_value_get_boxed (value);
530 pattern = _gtk_win32_theme_part_render (part, context->width, context->height);
532 g_value_take_boxed (value_out, pattern);
539 resolve_gradient (GtkStyleProperties *props,
542 cairo_pattern_t *gradient;
544 if (!gtk_gradient_resolve (g_value_get_boxed (value), props, &gradient))
547 /* Store it back, this is where cairo_pattern_t caching happens */
548 g_value_unset (value);
549 g_value_init (value, CAIRO_GOBJECT_TYPE_PATTERN);
550 g_value_take_boxed (value, gradient);
556 resolve_shadow (GtkStyleProperties *props,
559 GtkShadow *resolved, *base;
561 base = g_value_get_boxed (value);
566 if (_gtk_shadow_get_resolved (base))
569 resolved = _gtk_shadow_resolve (base, props);
570 if (resolved == NULL)
573 g_value_take_boxed (value, resolved);
579 _gtk_style_property_resolve (GtkStyleProperty *property,
580 GtkStyleProperties *props,
582 GtkStylePropertyContext *context,
586 if (G_VALUE_TYPE (val) == GTK_TYPE_CSS_SPECIAL_VALUE)
588 GtkCssSpecialValue special = g_value_get_enum (val);
593 case GTK_CSS_CURRENT_COLOR:
594 g_assert (property->pspec->value_type == GDK_TYPE_RGBA);
595 gtk_style_properties_get_property (props, "color", state, val);
597 case GTK_CSS_INHERIT:
598 case GTK_CSS_INITIAL:
600 g_assert_not_reached ();
603 else if (G_VALUE_TYPE (val) == GTK_TYPE_SYMBOLIC_COLOR)
605 if (property->pspec->value_type == GDK_TYPE_RGBA)
607 if (resolve_color (props, val))
610 else if (property->pspec->value_type == GDK_TYPE_COLOR)
612 if (resolve_color_rgb (props, val))
617 g_value_init (val, property->pspec->value_type);
618 _gtk_style_property_default_value (property, props, state, val);
620 else if (G_VALUE_TYPE (val) == GDK_TYPE_RGBA)
622 if (g_value_get_boxed (val) == NULL)
623 _gtk_style_property_default_value (property, props, state, val);
625 else if (G_VALUE_TYPE (val) == GTK_TYPE_GRADIENT)
627 g_return_if_fail (property->pspec->value_type == CAIRO_GOBJECT_TYPE_PATTERN);
629 if (!resolve_gradient (props, val))
632 g_value_init (val, CAIRO_GOBJECT_TYPE_PATTERN);
633 _gtk_style_property_default_value (property, props, state, val);
636 else if (G_VALUE_TYPE (val) == GTK_TYPE_SHADOW)
638 if (!resolve_shadow (props, val))
639 _gtk_style_property_default_value (property, props, state, val);
641 else if (G_VALUE_TYPE (val) == GTK_TYPE_WIN32_THEME_PART)
643 if (resolve_win32_theme_part (props, val, val_out, context))
644 return; /* Don't copy val, this sets val_out */
645 _gtk_style_property_default_value (property, props, state, val);
649 g_value_copy (val, val_out);
653 _gtk_style_property_unpack (GtkStyleProperty *property,
657 g_return_val_if_fail (property != NULL, NULL);
658 g_return_val_if_fail (property->unpack_func != NULL, NULL);
659 g_return_val_if_fail (value != NULL, NULL);
660 g_return_val_if_fail (n_params != NULL, NULL);
662 return property->unpack_func (value, n_params);
666 _gtk_style_property_pack (GtkStyleProperty *property,
667 GtkStyleProperties *props,
669 GtkStylePropertyContext *context,
672 g_return_if_fail (property != NULL);
673 g_return_if_fail (property->pack_func != NULL);
674 g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
675 g_return_if_fail (G_IS_VALUE (value));
677 property->pack_func (value, props, state, context);
681 _gtk_style_property_assign (GtkStyleProperty *property,
682 GtkStyleProperties *props,
686 g_return_if_fail (GTK_IS_STYLE_PROPERTY (property));
687 g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
688 g_return_if_fail (value != NULL);
690 if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
692 GParameter *parameters;
693 guint i, n_parameters;
695 parameters = _gtk_style_property_unpack (property, value, &n_parameters);
697 for (i = 0; i < n_parameters; i++)
699 _gtk_style_property_assign (_gtk_style_property_lookup (parameters[i].name),
702 ¶meters[i].value);
703 g_value_unset (¶meters[i].value);
708 else if (GTK_IS_CSS_STYLE_PROPERTY (property))
710 _gtk_style_properties_set_property_by_property (props,
711 GTK_CSS_STYLE_PROPERTY (property),
717 g_assert_not_reached ();
722 _gtk_style_property_query (GtkStyleProperty *property,
723 GtkStyleProperties *props,
725 GtkStylePropertyContext *context,
729 g_return_if_fail (property != NULL);
730 g_return_if_fail (GTK_IS_STYLE_PROPERTIES (props));
731 g_return_if_fail (context != NULL);
732 g_return_if_fail (value != NULL);
734 g_value_init (value, property->pspec->value_type);
736 if (GTK_IS_CSS_STYLE_PROPERTY (property))
740 val = _gtk_style_properties_peek_property (props, GTK_CSS_STYLE_PROPERTY (property), state);
742 _gtk_style_property_resolve (property, props, state, context, (GValue *) val, value);
744 _gtk_style_property_default_value (property, props, state, value);
746 else if (GTK_IS_CSS_SHORTHAND_PROPERTY (property))
748 _gtk_style_property_pack (property, props, state, context, value);
752 g_assert_not_reached ();
756 #define rgba_init(rgba, r, g, b, a) G_STMT_START{ \
758 (rgba)->green = (g); \
759 (rgba)->blue = (b); \
760 (rgba)->alpha = (a); \
763 gtk_style_property_init_properties (void)
765 static gboolean initialized = FALSE;
766 GValue value = { 0, };
767 char *default_font_family[] = { "Sans", NULL };
770 if (G_LIKELY (initialized))
775 g_value_init (&value, GDK_TYPE_RGBA);
776 rgba_init (&rgba, 1, 1, 1, 1);
777 g_value_set_boxed (&value, &rgba);
778 _gtk_style_property_register (g_param_spec_boxed ("color",
782 GTK_STYLE_PROPERTY_INHERIT,
787 rgba_init (&rgba, 0, 0, 0, 0);
788 g_value_set_boxed (&value, &rgba);
789 _gtk_style_property_register (g_param_spec_boxed ("background-color",
798 g_value_unset (&value);
800 g_value_init (&value, G_TYPE_STRV);
801 g_value_set_boxed (&value, default_font_family);
802 _gtk_style_property_register (g_param_spec_boxed ("font-family",
806 GTK_STYLE_PROPERTY_INHERIT,
809 font_family_value_print,
811 g_value_unset (&value);
812 _gtk_style_property_register (g_param_spec_enum ("font-style",
816 PANGO_STYLE_NORMAL, 0),
817 GTK_STYLE_PROPERTY_INHERIT,
822 _gtk_style_property_register (g_param_spec_enum ("font-variant",
826 PANGO_VARIANT_NORMAL, 0),
827 GTK_STYLE_PROPERTY_INHERIT,
832 /* xxx: need to parse this properly, ie parse the numbers */
833 _gtk_style_property_register (g_param_spec_enum ("font-weight",
837 PANGO_WEIGHT_NORMAL, 0),
838 GTK_STYLE_PROPERTY_INHERIT,
843 g_value_init (&value, G_TYPE_DOUBLE);
844 g_value_set_double (&value, 10);
845 _gtk_style_property_register (g_param_spec_double ("font-size",
848 0, G_MAXDOUBLE, 0, 0),
849 GTK_STYLE_PROPERTY_INHERIT,
854 g_value_unset (&value);
856 _gtk_style_property_register (g_param_spec_boxed ("text-shadow",
860 GTK_STYLE_PROPERTY_INHERIT,
866 _gtk_style_property_register (g_param_spec_boxed ("icon-shadow",
870 GTK_STYLE_PROPERTY_INHERIT,
876 gtk_style_properties_register_property (NULL,
877 g_param_spec_boxed ("box-shadow",
880 GTK_TYPE_SHADOW, 0));
881 gtk_style_properties_register_property (NULL,
882 g_param_spec_int ("margin-top",
886 gtk_style_properties_register_property (NULL,
887 g_param_spec_int ("margin-left",
891 gtk_style_properties_register_property (NULL,
892 g_param_spec_int ("margin-bottom",
896 gtk_style_properties_register_property (NULL,
897 g_param_spec_int ("margin-right",
901 gtk_style_properties_register_property (NULL,
902 g_param_spec_int ("padding-top",
906 gtk_style_properties_register_property (NULL,
907 g_param_spec_int ("padding-left",
911 gtk_style_properties_register_property (NULL,
912 g_param_spec_int ("padding-bottom",
916 gtk_style_properties_register_property (NULL,
917 g_param_spec_int ("padding-right",
921 gtk_style_properties_register_property (NULL,
922 g_param_spec_int ("border-top-width",
924 "Border width at top",
926 gtk_style_properties_register_property (NULL,
927 g_param_spec_int ("border-left-width",
929 "Border width at left",
931 gtk_style_properties_register_property (NULL,
932 g_param_spec_int ("border-bottom-width",
933 "border bottom width",
934 "Border width at bottom",
936 gtk_style_properties_register_property (NULL,
937 g_param_spec_int ("border-right-width",
938 "border right width",
939 "Border width at right",
942 _gtk_style_property_register (g_param_spec_boxed ("border-top-left-radius",
943 "Border top left radius",
944 "Border radius of top left corner, in pixels",
945 GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
948 border_corner_radius_value_parse,
949 border_corner_radius_value_print,
951 _gtk_style_property_register (g_param_spec_boxed ("border-top-right-radius",
952 "Border top right radius",
953 "Border radius of top right corner, in pixels",
954 GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
957 border_corner_radius_value_parse,
958 border_corner_radius_value_print,
960 _gtk_style_property_register (g_param_spec_boxed ("border-bottom-right-radius",
961 "Border bottom right radius",
962 "Border radius of bottom right corner, in pixels",
963 GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
966 border_corner_radius_value_parse,
967 border_corner_radius_value_print,
969 _gtk_style_property_register (g_param_spec_boxed ("border-bottom-left-radius",
970 "Border bottom left radius",
971 "Border radius of bottom left corner, in pixels",
972 GTK_TYPE_CSS_BORDER_CORNER_RADIUS, 0),
975 border_corner_radius_value_parse,
976 border_corner_radius_value_print,
979 gtk_style_properties_register_property (NULL,
980 g_param_spec_enum ("border-style",
983 GTK_TYPE_BORDER_STYLE,
984 GTK_BORDER_STYLE_NONE, 0));
985 gtk_style_properties_register_property (NULL,
986 g_param_spec_enum ("background-clip",
990 GTK_CSS_AREA_BORDER_BOX, 0));
991 gtk_style_properties_register_property (NULL,
992 g_param_spec_enum ("background-origin",
996 GTK_CSS_AREA_PADDING_BOX, 0));
997 g_value_init (&value, GTK_TYPE_CSS_SPECIAL_VALUE);
998 g_value_set_enum (&value, GTK_CSS_CURRENT_COLOR);
999 _gtk_style_property_register (g_param_spec_boxed ("border-top-color",
1008 _gtk_style_property_register (g_param_spec_boxed ("border-right-color",
1009 "Border right color",
1010 "Border right color",
1017 _gtk_style_property_register (g_param_spec_boxed ("border-bottom-color",
1018 "Border bottom color",
1019 "Border bottom color",
1026 _gtk_style_property_register (g_param_spec_boxed ("border-left-color",
1027 "Border left color",
1028 "Border left color",
1035 g_value_unset (&value);
1037 gtk_style_properties_register_property (NULL,
1038 g_param_spec_boxed ("background-image",
1041 CAIRO_GOBJECT_TYPE_PATTERN, 0));
1042 gtk_style_properties_register_property (NULL,
1043 g_param_spec_boxed ("background-repeat",
1044 "Background repeat",
1045 "Background repeat",
1046 GTK_TYPE_CSS_BACKGROUND_REPEAT, 0));
1048 gtk_style_properties_register_property (NULL,
1049 g_param_spec_boxed ("border-image-source",
1050 "Border image source",
1051 "Border image source",
1052 CAIRO_GOBJECT_TYPE_PATTERN, 0));
1053 gtk_style_properties_register_property (NULL,
1054 g_param_spec_boxed ("border-image-repeat",
1055 "Border image repeat",
1056 "Border image repeat",
1057 GTK_TYPE_CSS_BORDER_IMAGE_REPEAT, 0));
1058 gtk_style_properties_register_property (NULL,
1059 g_param_spec_boxed ("border-image-slice",
1060 "Border image slice",
1061 "Border image slice",
1062 GTK_TYPE_BORDER, 0));
1063 g_value_init (&value, GTK_TYPE_BORDER);
1064 _gtk_style_property_register (g_param_spec_boxed ("border-image-width",
1065 "Border image width",
1066 "Border image width",
1067 GTK_TYPE_BORDER, 0),
1073 g_value_unset (&value);
1074 gtk_style_properties_register_property (NULL,
1075 g_param_spec_object ("engine",
1078 GTK_TYPE_THEMING_ENGINE, 0));
1079 gtk_style_properties_register_property (NULL,
1080 g_param_spec_boxed ("transition",
1081 "Transition animation description",
1082 "Transition animation description",
1083 GTK_TYPE_ANIMATION_DESCRIPTION, 0));
1085 /* Private property holding the binding sets */
1086 _gtk_style_property_register (g_param_spec_boxed ("gtk-key-bindings",
1089 G_TYPE_PTR_ARRAY, 0),
1092 bindings_value_parse,
1093 bindings_value_print,
1096 /* initialize shorthands last, they depend on the real properties existing */
1097 _gtk_css_shorthand_property_init_properties ();
1101 * _gtk_style_property_lookup:
1102 * @name: name of the property to lookup
1104 * Looks up the CSS property with the given @name. If no such
1105 * property exists, %NULL is returned.
1107 * Returns: (transfer none): The property or %NULL if no
1108 * property with the given name exists.
1111 _gtk_style_property_lookup (const char *name)
1113 GtkStylePropertyClass *klass;
1115 g_return_val_if_fail (name != NULL, NULL);
1117 gtk_style_property_init_properties ();
1119 klass = g_type_class_peek (GTK_TYPE_STYLE_PROPERTY);
1121 return g_hash_table_lookup (klass->properties, name);
1125 * _gtk_style_property_get_name:
1126 * @property: the property to query
1128 * Gets the name of the given property.
1130 * Returns: the name of the property
1133 _gtk_style_property_get_name (GtkStyleProperty *property)
1135 g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), NULL);
1137 return property->name;
1141 * _gtk_style_property_get_value_type:
1142 * @property: the property to query
1144 * Gets the value type of the @property, if the property is usable
1145 * in public API via _gtk_style_property_assign() and
1146 * _gtk_style_property_query(). If the @property is not usable in that
1147 * way, %G_TYPE_NONE is returned.
1149 * Returns: the value type in use or %G_TYPE_NONE if none.
1152 _gtk_style_property_get_value_type (GtkStyleProperty *property)
1154 g_return_val_if_fail (GTK_IS_STYLE_PROPERTY (property), G_TYPE_NONE);
1156 return property->value_type;
1161 _gtk_style_property_register (GParamSpec *pspec,
1162 GtkStylePropertyFlags flags,
1163 GtkStylePropertyParser property_parse_func,
1164 GtkStyleParseFunc parse_func,
1165 GtkStylePrintFunc print_func,
1166 const GValue * initial_value)
1168 GtkStyleProperty *node;
1169 GValue initial_fallback = { 0, };
1171 if (initial_value == NULL)
1173 g_value_init (&initial_fallback, pspec->value_type);
1174 if (pspec->value_type == GTK_TYPE_THEMING_ENGINE)
1175 g_value_set_object (&initial_fallback, gtk_theming_engine_load (NULL));
1176 else if (pspec->value_type == PANGO_TYPE_FONT_DESCRIPTION)
1177 g_value_take_boxed (&initial_fallback, pango_font_description_from_string ("Sans 10"));
1178 else if (pspec->value_type == GDK_TYPE_RGBA)
1181 gdk_rgba_parse (&color, "pink");
1182 g_value_set_boxed (&initial_fallback, &color);
1184 else if (pspec->value_type == GTK_TYPE_BORDER)
1186 g_value_take_boxed (&initial_fallback, gtk_border_new ());
1189 g_param_value_set_default (pspec, &initial_fallback);
1191 initial_value = &initial_fallback;
1194 node = g_object_new (GTK_TYPE_CSS_STYLE_PROPERTY,
1195 "inherit", (flags & GTK_STYLE_PROPERTY_INHERIT) ? TRUE : FALSE,
1196 "initial-value", initial_value,
1197 "name", pspec->name,
1198 "value-type", pspec->value_type,
1200 node->pspec = pspec;
1201 node->property_parse_func = property_parse_func;
1202 node->parse_func = parse_func;
1203 node->print_func = print_func;
1205 if (G_IS_VALUE (&initial_fallback))
1206 g_value_unset (&initial_fallback);