summaryrefslogtreecommitdiff
path: root/ccss-gtk/ccss-gtk-grammar.c
diff options
context:
space:
mode:
authorRobert Staudinger <robsta@gnome.org>2008-12-09 16:17:52 +0100
committerRobert Staudinger <robsta@gnome.org>2008-12-09 16:17:52 +0100
commit2c9a7e5e3a57a52d10540092b91f4f3021d847c6 (patch)
treea459ba11fee1c10d98be406df398f851238fc167 /ccss-gtk/ccss-gtk-grammar.c
parentf3fddd34e54b7b7905a6ca1c0bafa5bc29cfae5b (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.c501
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;
}