diff options
author | Robert Staudinger <robsta@gnome.org> | 2009-08-09 13:24:43 +0200 |
---|---|---|
committer | Robert Staudinger <robsta@gnome.org> | 2009-08-09 13:24:43 +0200 |
commit | 0d57803fbb6ee19ad32d3894f1a58b0663899e56 (patch) | |
tree | f1c9c1084384cc89181c74866f621840b024c807 | |
parent | 83ae1af9a5291d11d57f8d9367667acc0bd4d7c2 (diff) |
[cairo-style] Pass gap info as custom properties to appearance hooks.
Appearance hook functions can now query the style for 'ccss-gap-side',
'ccss-gap-start' and 'ccss-gap-width' when drawing rectangles. This
allows for custom rendering of gtk's notebooks and frames.
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | TODO | 2 | ||||
-rw-r--r-- | ccss-cairo/ccss-cairo-style.c | 195 | ||||
-rw-r--r-- | ccss/ccss-property.h | 4 | ||||
-rw-r--r-- | examples/example-8.c | 15 |
5 files changed, 212 insertions, 5 deletions
diff --git a/Makefile.am b/Makefile.am index 3cb1b45..e17e52e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,7 @@ DIST_SUBDIRS = \ ccss-cairo \ ccss-cairo-doc \ ccss-gtk \ + ccss-gtk-doc \ examples \ $(NULL) @@ -9,6 +9,8 @@ Also see gtk-css-engine's TODO for now. * Implement gaps by passing a custom property "-gce-gap" with a ccss_property_t that contains a cairo_rectangle_t? Or -gce-gap-side, -gce-gap-start, -gce-gap-width? +* Ship clearlooks' gtkrc hacks as a separate file and include it in the themes. +* Move over gce-node, separate them. * Improve test suite. Libxml backend for cascading tests? * Cairo-style error handling? Or something else? * "char * foo_serialize()" API instead of _dump(). diff --git a/ccss-cairo/ccss-cairo-style.c b/ccss-cairo/ccss-cairo-style.c index 2517e9d..416d396 100644 --- a/ccss-cairo/ccss-cairo-style.c +++ b/ccss-cairo/ccss-cairo-style.c @@ -30,6 +30,25 @@ #include "ccss-cairo-property.h" #include "config.h" +typedef struct { + ccss_property_base_t base; + ccss_cairo_gap_side_t side; +} gap_side_t; + +typedef struct { + ccss_property_base_t base; + double start; +} gap_start_t; + +typedef struct { + ccss_property_base_t base; + double width; +} gap_width_t; + + +static ccss_property_class_t const * +peek_property_class (char const *property_name); + struct { char const *name; char const *fallback; @@ -371,6 +390,64 @@ ccss_cairo_style_draw_rectangle_with_gap (ccss_style_t const *self, double l, t, w, h; + ccss_cairo_appearance_t *appearance = NULL; + if (ccss_style_get_property (self, + "ccss-appearance", + (ccss_property_base_t const **) &appearance) && + appearance->base.state == CCSS_PROPERTY_STATE_SET && + appearance->draw_function) { + + static GQuark gap_side_id = 0; + static GQuark gap_start_id = 0; + static GQuark gap_width_id = 0; + + gap_side_t gap_side_property; + gap_start_t gap_start_property; + gap_width_t gap_width_property; + + bool ret; + + if (gap_side_id == 0) + gap_side_id = g_quark_from_static_string ("ccss-gap-side"); + ccss_property_init (&gap_side_property.base, + peek_property_class ("ccss-gap-side")); + gap_side_property.side = gap_side; + gap_side_property.base.state = CCSS_PROPERTY_STATE_SET; + g_hash_table_insert (self->properties, + (gpointer) gap_side_id, + &gap_side_property); + + if (gap_start_id == 0) + gap_start_id = g_quark_from_static_string ("ccss-gap-start"); + ccss_property_init (&gap_start_property.base, + peek_property_class ("ccss-gap-start")); + gap_start_property.start = gap_start; + gap_start_property.base.state = CCSS_PROPERTY_STATE_SET; + g_hash_table_insert (self->properties, + (gpointer) gap_start_id, + &gap_start_property); + + if (gap_width_id == 0) + gap_width_id = g_quark_from_static_string ("ccss-gap-width"); + ccss_property_init (&gap_width_property.base, + peek_property_class ("ccss-gap-width")); + gap_width_property.width = gap_width; + gap_width_property.base.state = CCSS_PROPERTY_STATE_SET; + g_hash_table_insert (self->properties, + (gpointer) gap_width_id, + &gap_width_property); + + ret = appearance->draw_function (self, cr, + x, y, width, height); + + g_hash_table_remove (self->properties, (gpointer) gap_side_id); + g_hash_table_remove (self->properties, (gpointer) gap_start_id); + g_hash_table_remove (self->properties, (gpointer) gap_width_id); + + if (ret) + return; + } + gather_outline (self, &bottom, &left, &right, &top, &bl, &br, &tl, &tr); @@ -677,3 +754,121 @@ ccss_cairo_style_get_property (ccss_style_t const *self, return (bool) *property; } +static void +gap_destroy_nop (ccss_property_base_t *property) +{ + /* Gap properties are stack-allocated. */ +} + +static bool +gap_side_convert (gap_side_t const *property, + ccss_property_type_t target, + void *value) +{ + g_return_val_if_fail (property && value, false); + + if (CCSS_PROPERTY_TYPE_DOUBLE == target) + return false; + + switch (property->side) { + case CCSS_CAIRO_GAP_SIDE_LEFT: + * (char const **) value = g_strdup ("left"); + break; + case CCSS_CAIRO_GAP_SIDE_RIGHT: + * (char const **) value = g_strdup ("right"); + break; + case CCSS_CAIRO_GAP_SIDE_TOP: + * (char const **) value = g_strdup ("top"); + break; + case CCSS_CAIRO_GAP_SIDE_BOTTOM: + * (char const **) value = g_strdup ("bottom"); + break; + } + + return true; +} + +static bool +gap_start_convert (gap_start_t const *property, + ccss_property_type_t target, + void *value) +{ + g_return_val_if_fail (property && value, false); + + switch (target) { + case CCSS_PROPERTY_TYPE_DOUBLE: + * (double *) value = property->start; + return true; + case CCSS_PROPERTY_TYPE_STRING: + * (char **) value = g_strdup_printf ("%f", property->start); + return true; + default: + g_assert_not_reached (); + return false; + } + + return false; +} + +static bool +gap_width_convert (gap_width_t const *property, + ccss_property_type_t target, + void *value) +{ + g_return_val_if_fail (property && value, false); + + switch (target) { + case CCSS_PROPERTY_TYPE_DOUBLE: + * (double *) value = property->width; + return true; + case CCSS_PROPERTY_TYPE_STRING: + * (char **) value = g_strdup_printf ("%f", property->width); + return true; + default: + g_assert_not_reached (); + return false; + } + + return false; +} + +static ccss_property_class_t const _ptable[] = { + { + .name = "ccss-gap-side", + .property_create = NULL, + .property_destroy = (ccss_property_destroy_f) gap_destroy_nop, + .property_convert = (ccss_property_convert_f) gap_side_convert, + .property_factory = NULL, + .property_inherit = NULL + }, { + .name = "ccss-gap-start", + .property_create = NULL, + .property_destroy = (ccss_property_destroy_f) gap_destroy_nop, + .property_convert = (ccss_property_convert_f) gap_start_convert, + .property_factory = NULL, + .property_inherit = NULL + }, { + .name = "ccss-gap-width", + .property_create = NULL, + .property_destroy = (ccss_property_destroy_f) gap_destroy_nop, + .property_convert = (ccss_property_convert_f) gap_width_convert, + .property_factory = NULL, + .property_inherit = NULL + }, { + .name = NULL + } +}; + +static ccss_property_class_t const * +peek_property_class (char const *property_name) +{ + for (unsigned int i = 0; i < G_N_ELEMENTS (_ptable); i++) { + if (0 == g_strcmp0 (property_name, _ptable[i].name)) + return &_ptable[i]; + } + + g_return_val_if_fail (0, NULL); + + return NULL; +} + diff --git a/ccss/ccss-property.h b/ccss/ccss-property.h index b63b5cb..b24357d 100644 --- a/ccss/ccss-property.h +++ b/ccss/ccss-property.h @@ -146,6 +146,8 @@ typedef bool (*ccss_property_inherit_f) (struct ccss_style_ const *container_sty * @property_inherit: inherit hook, see #ccss_property_inherit_f. * * Property interpretation vtable entry. + * + * TODO: drop vtable functions 'property' prefix. **/ typedef struct { char const *name; @@ -162,6 +164,8 @@ typedef struct { * @state: property state, see #ccss_property_state_t. * * This structure has to be embedded at the beginning of every custom property. + * + * TODO: Rename to ccss_property_t. **/ struct ccss_property_base_ { ccss_property_class_t const *property_class; diff --git a/examples/example-8.c b/examples/example-8.c index cd9b851..5eb43d5 100644 --- a/examples/example-8.c +++ b/examples/example-8.c @@ -40,6 +40,8 @@ custom_box (ccss_style_t const *self, cairo_set_line_cap (cr, CAIRO_LINE_JOIN_ROUND); cairo_stroke (cr); + ccss_style_dump (self); + return true; } @@ -56,11 +58,14 @@ expose_cb (GtkWidget *widget, cr = gdk_cairo_create (widget->window); - ccss_cairo_style_draw_rectangle (style, cr, - widget->allocation.x + 10, - widget->allocation.y + 10, - widget->allocation.width - 20, - widget->allocation.height - 20); + ccss_cairo_style_draw_rectangle_with_gap (style, cr, + widget->allocation.x + 10, + widget->allocation.y + 10, + widget->allocation.width - 20, + widget->allocation.height - 20, + CCSS_CAIRO_GAP_SIDE_TOP, + 10, + 30); cairo_destroy (cr); |