diff options
author | Robert Staudinger <robsta@gnome.org> | 2008-12-09 16:17:52 +0100 |
---|---|---|
committer | Robert Staudinger <robsta@gnome.org> | 2008-12-09 16:17:52 +0100 |
commit | 2c9a7e5e3a57a52d10540092b91f4f3021d847c6 (patch) | |
tree | a459ba11fee1c10d98be406df398f851238fc167 /ccss-gtk/ccss-gtk-grammar.c | |
parent | f3fddd34e54b7b7905a6ca1c0bafa5bc29cfae5b (diff) |
* ccss-cairo/Makefile.am:
* ccss-cairo/ccss-cairo-color-priv.h:
* ccss-cairo/ccss-background-parser.c (background_factory):
* ccss-cairo/ccss-background.c (ccss_background_fill):
* ccss-cairo/ccss-background.h:
* ccss-cairo/ccss-border-parser.c (border_color_factory),
(border_factory_impl):
* ccss-cairo/ccss-border.h:
* ccss-cairo/ccss-cairo-color.c (parse_name), (hex), (parse_hex),
(ccss_cairo_color_parse), (ccss_cairo_color_create),
(ccss_cairo_color_destroy), (ccss_cairo_color_convert),
(peek_property_class), (ccss_cairo_color_get_ptable):
* ccss-cairo/ccss-cairo-color.h:
* ccss-cairo/ccss-cairo-grammar.c (ccss_cairo_grammar_create):
* ccss-cairo/ccss-cairo-style.c (ccss_cairo_style_draw_line),
(gather_stroke), (gather_background),
(ccss_cairo_style_draw_rectangle),
(ccss_cairo_style_draw_rectangle_with_gap):
* ccss-cairo/ccss-cairo.h:
* ccss-cairo/ccss-color.c:
* ccss-cairo/ccss-color.h:
Split out public ccss-cairo-color.h.
* ccss-gtk/ccss-gtk-grammar.c (parse_gboolean), (parse_gchararray),
(parse_gfloat), (parse_gint), (parse_guchar), (parse_gdk_color),
(parse_gtk_border), (parse_gtk_relief_style),
(parse_gtk_requisition), (parse_gtk_shadow_type),
(parse_gtk_toolbar_space_style), (parse_gtk_style_property),
(property_destroy), (property_factory), (peek_property_class),
(ccss_gtk_grammar_create):
* ccss-gtk/ccss-gtk-grammar.h:
Work towards parsing gtk style properties.
Diffstat (limited to 'ccss-gtk/ccss-gtk-grammar.c')
-rw-r--r-- | ccss-gtk/ccss-gtk-grammar.c | 501 |
1 files changed, 494 insertions, 7 deletions
diff --git a/ccss-gtk/ccss-gtk-grammar.c b/ccss-gtk/ccss-gtk-grammar.c index 4c612a5..d38df17 100644 --- a/ccss-gtk/ccss-gtk-grammar.c +++ b/ccss-gtk/ccss-gtk-grammar.c @@ -17,13 +17,471 @@ * MA 02110-1301, USA. */ +#include <math.h> +#include <string.h> #include <ccss-cairo/ccss-cairo.h> #include "ccss-gtk-grammar.h" #include "config.h" +static ccss_property_class_t const * +peek_property_class (void); + static ccss_property_class_t const *_generic_property_class = NULL; static bool +parse_gboolean (CRTerm const *values, + ccss_gtk_property_t *property) +{ + char const *str; + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_IDENT: + case TERM_STRING: + ret = true; + str = cr_string_peek_raw_str (values->content.str); + if (0 == g_ascii_strcasecmp ("true", str)) + property->content.gboolean_val = true; + else if (0 == g_ascii_strcasecmp ("false", str)) + property->content.gboolean_val = false; + else + ret = false; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gchararray (CRTerm const *values, + ccss_gtk_property_t *property) +{ + char const *str; + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_IDENT: + case TERM_STRING: + str = cr_string_peek_raw_str (values->content.str); + property->content.gchararray_val = g_strdup (str); + ret = true; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gfloat (CRTerm const *values, + ccss_gtk_property_t *property) +{ + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_NUMBER: + property->content.gfloat_val = values->content.num->val; + ret = true; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gint (CRTerm const *values, + ccss_gtk_property_t *property) +{ + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_NUMBER: + /* Be strict about fractionals. */ + if (lround (values->content.num->val) == values->content.num->val) { + property->content.gint_val = (int) values->content.num->val; + ret = true; + } + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_guchar (CRTerm const *values, + ccss_gtk_property_t *property) +{ + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_NUMBER: + /* Be strict about fractionals. */ + if (lround (values->content.num->val) == values->content.num->val) { + if (values->content.num->val > G_MAXUINT8) + property->content.guchar_val = G_MAXUINT8; + else if (values->content.num->val < 0) + property->content.guchar_val = 0; + else + property->content.guchar_val = (guchar) values->content.num->val; + ret = true; + } + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gdk_color (ccss_grammar_t const *grammar, + CRTerm const *values, + void *user_data, + ccss_gtk_property_t *property) +{ + ccss_cairo_color_t color; + bool ret; + + g_return_val_if_fail (values && property, false); + + memset (&color, 0, sizeof (color)); + ret = ccss_cairo_color_parse (&color, grammar, user_data, &values); + if (ret) { + property->content.gdkcolor_val.red = color.red * 65535; + property->content.gdkcolor_val.green = color.green * 65535; + property->content.gdkcolor_val.blue = color.blue * 65535; + } + + return ret; +} + +static bool +parse_gtk_border (CRTerm const *values, + ccss_gtk_property_t *property) +{ + gint *border_ptr; + int i; + + g_return_val_if_fail (values && property, false); + + border_ptr = (gint *) &property->content.gtkborder_val; + for (i = 0; i < 4; i++) { + + if (!values) { + break; + } + + /* Be strict about fractionals. */ + if (TERM_NUMBER == values->type && + lround (values->content.num->val) == values->content.num->val) { + + border_ptr[i] = (gint) values->content.num->val; + values = values->next; + } + } + + return i == 4; +} + +static bool +parse_gtk_relief_style (CRTerm const *values, + ccss_gtk_property_t *property) +{ + char const *str; + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_IDENT: + case TERM_STRING: + ret = true; + str = cr_string_peek_raw_str (values->content.str); + if (0 == g_ascii_strcasecmp ("normal", str)) + property->content.gtkreliefstyle_val = GTK_RELIEF_NORMAL; + else if (0 == g_ascii_strcasecmp ("half", str)) + property->content.gtkreliefstyle_val = GTK_RELIEF_HALF; + else if (0 == g_ascii_strcasecmp ("none", str)) + property->content.gtkreliefstyle_val = GTK_RELIEF_NONE; + else + ret = false; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gtk_requisition (CRTerm const *values, + ccss_gtk_property_t *property) +{ + gint *border_ptr; + int i; + + g_return_val_if_fail (values && property, false); + + border_ptr = (gint *) &property->content.gtkrequisition_val; + for (i = 0; i < 2; i++) { + + if (!values) { + break; + } + + /* Be strict about fractionals. */ + if (TERM_NUMBER == values->type && + lround (values->content.num->val) == values->content.num->val) { + + border_ptr[i] = (gint) values->content.num->val; + values = values->next; + } + } + + return i == 2; +} + +static bool +parse_gtk_shadow_type (CRTerm const *values, + ccss_gtk_property_t *property) +{ + char const *str; + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_IDENT: + case TERM_STRING: + ret = true; + str = cr_string_peek_raw_str (values->content.str); + if (0 == g_ascii_strcasecmp ("none", str)) + property->content.gtkshadowtype_val = GTK_SHADOW_NONE; + else if (0 == g_ascii_strcasecmp ("in", str)) + property->content.gtkreliefstyle_val = GTK_SHADOW_IN; + else if (0 == g_ascii_strcasecmp ("out", str)) + property->content.gtkreliefstyle_val = GTK_SHADOW_OUT; + else if (0 == g_ascii_strcasecmp ("etched-in", str)) + property->content.gtkreliefstyle_val = GTK_SHADOW_ETCHED_IN; + else if (0 == g_ascii_strcasecmp ("etched-out", str)) + property->content.gtkreliefstyle_val = GTK_SHADOW_ETCHED_OUT; + else + ret = false; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static bool +parse_gtk_toolbar_space_style (CRTerm const *values, + ccss_gtk_property_t *property) +{ + char const *str; + bool ret; + + g_return_val_if_fail (values && property, false); + + ret = false; + switch (values->type) { + case TERM_IDENT: + case TERM_STRING: + ret = true; + str = cr_string_peek_raw_str (values->content.str); + if (0 == g_ascii_strcasecmp ("empty", str)) + property->content.gtktoolbarspacestyle_val = GTK_TOOLBAR_SPACE_EMPTY; + else if (0 == g_ascii_strcasecmp ("line", str)) + property->content.gtktoolbarspacestyle_val = GTK_TOOLBAR_SPACE_LINE; + else + ret = false; + break; + default: + /* Shut up compiler. */ + ret = false; + } + + return ret; +} + +static ccss_gtk_property_t * +parse_gtk_style_property (ccss_grammar_t const *grammar, + char const *name, + CRTerm const *values, + void *user_data) +{ + char **tokens; + char *class_name = NULL; + char *property_name = NULL; + GtkBuilder *builder = NULL; + GType type = 0; + GtkWidget *widget = NULL; + GParamSpec *property = NULL; + ccss_gtk_property_t *self = NULL, s; + + /* Parse property name. */ + tokens = g_strsplit (name, "-", 2); + if (tokens && tokens[0]) { + class_name = tokens[0]; + } else { + goto bail; + } + if (tokens && tokens[1]) { + property_name = tokens[1]; + } else { + goto bail; + } + + /* Introspect property type. */ + builder = gtk_builder_new (); + type = gtk_builder_get_type_from_name (builder, class_name); + if (0 == type) + goto bail; + + widget = GTK_WIDGET (g_object_new (type, NULL)); + if (NULL == widget) + goto bail; + + property = gtk_widget_class_find_style_property (GTK_WIDGET_GET_CLASS (widget), + property_name); + if (NULL == property) + goto bail; + + /* Parse value. */ + memset (&s, 0, sizeof (s)); + ccss_property_init (&self->base, peek_property_class ()); + if (G_TYPE_BOOLEAN == property->value_type) { + if (parse_gboolean (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (G_TYPE_STRING == property->value_type) { + if (parse_gchararray (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (G_TYPE_FLOAT == property->value_type) { + if (parse_gfloat (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (G_TYPE_INT == property->value_type) { + if (parse_gint (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (G_TYPE_UCHAR == property->value_type) { + if (parse_guchar (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GDK_TYPE_COLOR == property->value_type) { + if (parse_gdk_color (grammar, values, user_data, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GTK_TYPE_BORDER == property->value_type) { + if (parse_gtk_border (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GTK_TYPE_RELIEF_STYLE == property->value_type) { + if (parse_gtk_relief_style (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GTK_TYPE_REQUISITION == property->value_type) { + if (parse_gtk_requisition (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GTK_TYPE_SHADOW_TYPE == property->value_type) { + if (parse_gtk_shadow_type (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } else if (GTK_TYPE_TOOLBAR_SPACE_STYLE == property->value_type) { + if (parse_gtk_toolbar_space_style (values, &s)) { + s.gtype = property->value_type; + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + } + } + + if (self) { + self->class_name = class_name, class_name = NULL; + self->property_name = property_name, property_name = NULL; + } + +bail: + if (tokens) + g_free (tokens); + if (class_name) + g_free (class_name); + if (property_name) + g_free (property_name); + if (builder) + g_object_unref (G_OBJECT (builder)); + if (widget) + gtk_widget_destroy (widget); + + return self; +} + +static void +property_destroy (ccss_gtk_property_t *self) +{ + g_return_if_fail (self); + + if (G_TYPE_STRING == self->gtype && self->content.gchararray_val) { + g_free (self->content.gchararray_val); + } + g_free (self); +} + +static bool property_convert (ccss_property_base_t const *self, ccss_property_type_t target, void *value) @@ -38,6 +496,8 @@ property_factory (ccss_grammar_t const *grammar, CRTerm const *values, void *user_data) { + ccss_gtk_property_t s, *self; + g_return_val_if_fail (grammar, false); g_return_val_if_fail (block, false); g_return_val_if_fail (name, false); @@ -45,12 +505,33 @@ property_factory (ccss_grammar_t const *grammar, /* PONDERING: Handle things like GtkSettings `gtk-button-images' in the future? */ - if (0 == g_strcmp0 (name, "x-thickness")) { - // TODO - } else if (0 == g_strcmp0 (name, "y-thickness")) { - // TODO + memset (&s, 0, sizeof (s)); + ccss_property_init (&self->base, peek_property_class ()); + + if (0 == g_strcmp0 (name, "xthickness")) { + if (parse_gint (values, &s)) { + s.class_name = NULL; + s.property_name = g_strdup ("xthickness"); + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + ccss_block_add_property (block, "xthickness", &self->base); + return true; + } + } else if (0 == g_strcmp0 (name, "ythickness")) { + if (parse_gint (values, &s)) { + s.class_name = NULL; + s.property_name = g_strdup ("ythickness"); + self = g_new0 (ccss_gtk_property_t, 1); + *self = s; + ccss_block_add_property (block, "ythickness", &self->base); + return true; + } } else if (g_str_has_prefix (name, "Gtk")) { - // TODO introspect style property + self = parse_gtk_style_property (grammar, name, values, user_data); + if (self) { + ccss_block_add_property (block, name, &self->base); + } + return (bool) self; } else if (g_ascii_isupper (name[0])) { // TODO introspect style property and feed back to gtk directly. // Non-gtk style properties (wnck, nautilus, ...) can't be @@ -71,7 +552,7 @@ static ccss_property_class_t const _properties[] = { { .name = "*", .property_create = NULL, - .property_destroy = (ccss_property_destroy_f) g_free, + .property_destroy = (ccss_property_destroy_f) property_destroy, .property_convert = (ccss_property_convert_f) property_convert, .property_factory = property_factory, .property_inherit = NULL @@ -80,6 +561,12 @@ static ccss_property_class_t const _properties[] = { } }; +static ccss_property_class_t const * +peek_property_class (void) +{ + return &_properties[0]; +} + /** * ccss_gtk_grammar_create: * @@ -102,7 +589,7 @@ ccss_gtk_grammar_create (void) "*"); } - /* TODO add properties */ + ccss_grammar_add_properties (self, _properties); return self; } |