summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Staudinger <robsta@gnome.org>2009-08-09 13:24:43 +0200
committerRobert Staudinger <robsta@gnome.org>2009-08-09 13:24:43 +0200
commit0d57803fbb6ee19ad32d3894f1a58b0663899e56 (patch)
treef1c9c1084384cc89181c74866f621840b024c807
parent83ae1af9a5291d11d57f8d9367667acc0bd4d7c2 (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.am1
-rw-r--r--TODO2
-rw-r--r--ccss-cairo/ccss-cairo-style.c195
-rw-r--r--ccss/ccss-property.h4
-rw-r--r--examples/example-8.c15
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)
diff --git a/TODO b/TODO
index c65cf0b..8e0d9e4 100644
--- a/TODO
+++ b/TODO
@@ -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);