hippo-canvas r7242 - in trunk: . common/hippo linux/hippo python tests
- From: otaylor svn gnome org
- To: svn-commits-list gnome org
- Subject: hippo-canvas r7242 - in trunk: . common/hippo linux/hippo python tests
- Date: Mon, 24 Mar 2008 19:05:00 +0000 (GMT)
Author: otaylor
Date: Mon Mar 24 19:05:00 2008
New Revision: 7242
URL: http://svn.gnome.org/viewvc/hippo-canvas?rev=7242&view=rev
Log:
CSS Theming:
http://mail.gnome.org/archives/online-desktop-list/2008-March/msg00030.html
configure.ac: Add a dependency on libcroco
hippo-canvas-theme.[ch]: "Theme" API binding together a set
of stylesheets and a theme engine.
hippo-canvas-style.[ch]: Add API's for getting styled-propertise
like colors and borders
hippo-canvas-theme-engine.[ch]: Very simple 'theme engine'
interface for drawing a named part.
hippo-canvas-*.c: Use the new style engine API's to get themed
properties
tests/test-theme.py tests/test.css: Simple test of CSS/theme
functionality
Added:
trunk/common/hippo/hippo-canvas-theme-engine.c
trunk/common/hippo/hippo-canvas-theme-engine.h
trunk/common/hippo/hippo-canvas-theme-internal.h
trunk/common/hippo/hippo-canvas-theme.c
trunk/common/hippo/hippo-canvas-theme.h
trunk/tests/test-theme.py
trunk/tests/test.css
Modified:
trunk/Makefile-canvas-sources.am
trunk/common/hippo/hippo-canvas-box.c
trunk/common/hippo/hippo-canvas-box.h
trunk/common/hippo/hippo-canvas-context.c
trunk/common/hippo/hippo-canvas-context.h
trunk/common/hippo/hippo-canvas-item.c
trunk/common/hippo/hippo-canvas-link.c
trunk/common/hippo/hippo-canvas-link.h
trunk/common/hippo/hippo-canvas-style.c
trunk/common/hippo/hippo-canvas-style.h
trunk/common/hippo/hippo-canvas-text.c
trunk/common/hippo/hippo-canvas-type-builtins.c
trunk/common/hippo/hippo-canvas-type-builtins.h
trunk/configure.ac
trunk/linux/hippo/hippo-canvas-helper.c
trunk/linux/hippo/hippo-canvas-helper.h
trunk/linux/hippo/hippo-canvas-widget.c
trunk/linux/hippo/hippo-canvas-widget.h
trunk/linux/hippo/hippo-canvas-widgets.c
trunk/linux/hippo/hippo-canvas-window.c
trunk/linux/hippo/hippo-canvas-window.h
trunk/linux/hippo/hippo-canvas.c
trunk/linux/hippo/hippo-canvas.h
trunk/python/hippo.defs
trunk/python/hippo.override
Modified: trunk/Makefile-canvas-sources.am
==============================================================================
--- trunk/Makefile-canvas-sources.am (original)
+++ trunk/Makefile-canvas-sources.am Mon Mar 24 19:05:00 2008
@@ -79,6 +79,8 @@
$(CANVASSRCDIR)/common/hippo/hippo-canvas-link.h \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-style.h \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-text.h \
+ $(CANVASSRCDIR)/common/hippo/hippo-canvas-theme.h \
+ $(CANVASSRCDIR)/common/hippo/hippo-canvas-theme-engine.h \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-widgets.h \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-util.h \
$(CANVASSRCDIR)/common/hippo/hippo-event.h \
@@ -105,6 +107,9 @@
$(CANVASSRCDIR)/common/hippo/hippo-canvas-text.c \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-test.c \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-test.h \
+ $(CANVASSRCDIR)/common/hippo/hippo-canvas-theme.c \
+ $(CANVASSRCDIR)/common/hippo/hippo-canvas-theme-engine.c \
+ $(CANVASSRCDIR)/common/hippo/hippo-canvas-theme-internal.h \
$(CANVASSRCDIR)/common/hippo/hippo-canvas-util.c \
$(CANVASSRCDIR)/common/hippo/hippo-event.c \
$(CANVASSRCDIR)/common/hippo/hippo-graphics.c
Modified: trunk/common/hippo/hippo-canvas-box.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-box.c (original)
+++ trunk/common/hippo/hippo-canvas-box.c Mon Mar 24 19:05:00 2008
@@ -7,6 +7,9 @@
#include "hippo-canvas-container.h"
#include "hippo-canvas-style.h"
+#define HIPPO_CANVAS_DEFAULT_COLOR 0x000000ff
+#define HIPPO_CANVAS_DEFAULT_BACKGROUND_COLOR 0xffffff00
+
typedef struct {
int minimum;
int natural;
@@ -14,6 +17,10 @@
unsigned int does_not_fit : 1;
} AdjustInfo;
+typedef struct {
+ double border[4];
+ double padding[4];
+} Borders;
static void hippo_canvas_box_init (HippoCanvasBox *box);
static void hippo_canvas_box_class_init (HippoCanvasBoxClass *klass);
@@ -54,10 +61,11 @@
HippoCanvasItem *item,
int *x_p,
int *y_p);
-static void hippo_canvas_box_affect_color (HippoCanvasContext *context,
- guint32 *color_rgba_p);
-static void hippo_canvas_box_affect_font_desc (HippoCanvasContext *context,
- PangoFontDescription *font_desc);
+
+static double hippo_canvas_box_get_resolution (HippoCanvasContext *context);
+static HippoCanvasStyle * hippo_canvas_box_get_style (HippoCanvasContext *context);
+static PangoFontDescription *hippo_canvas_box_get_font (HippoCanvasContext *context);
+
static void hippo_canvas_box_style_changed (HippoCanvasContext *context,
gboolean resize_needed);
@@ -176,6 +184,8 @@
enum {
PROP_0,
+ PROP_ID,
+ PROP_CLASSES,
PROP_ORIENTATION,
PROP_PADDING_TOP,
PROP_PADDING_BOTTOM,
@@ -192,14 +202,14 @@
PROP_XALIGN,
PROP_YALIGN,
PROP_BACKGROUND_COLOR,
+ PROP_BACKGROUND_COLOR_SET,
PROP_BORDER_COLOR,
+ PROP_BORDER_COLOR_SET,
PROP_SPACING,
PROP_COLOR,
- PROP_COLOR_CASCADE,
PROP_COLOR_SET,
PROP_FONT,
PROP_FONT_DESC,
- PROP_FONT_CASCADE,
PROP_TOOLTIP,
PROP_DEBUG_NAME
};
@@ -242,8 +252,9 @@
klass->unregister_widget_item = hippo_canvas_box_unregister_widget_item;
klass->translate_to_widget = hippo_canvas_box_translate_to_widget;
klass->translate_to_screen = hippo_canvas_box_translate_to_screen;
- klass->affect_color = hippo_canvas_box_affect_color;
- klass->affect_font_desc = hippo_canvas_box_affect_font_desc;
+ klass->get_style = hippo_canvas_box_get_style;
+ klass->get_resolution = hippo_canvas_box_get_resolution;
+ klass->get_font = hippo_canvas_box_get_font;
klass->style_changed = hippo_canvas_box_style_changed;
}
@@ -263,14 +274,10 @@
box->y_align = HIPPO_ALIGNMENT_FILL;
box->box_width = -1;
box->box_height = -1;
- box->background_color_rgba = HIPPO_CANVAS_DEFAULT_BACKGROUND_COLOR;
box->content_min_width = -1;
box->content_min_height = -1;
box->needs_width_request = TRUE; /* be sure we do at least one allocation */
box->needs_height_request = TRUE;
-
- box->color_cascade = HIPPO_CASCADE_MODE_INHERIT;
- box->font_cascade = HIPPO_CASCADE_MODE_INHERIT;
}
static void
@@ -284,8 +291,6 @@
object_class->dispose = hippo_canvas_box_dispose;
object_class->finalize = hippo_canvas_box_finalize;
- klass->default_color = HIPPO_CANVAS_DEFAULT_COLOR;
-
klass->paint_background = hippo_canvas_box_paint_background;
klass->paint_children = hippo_canvas_box_paint_children;
klass->get_content_width_request = hippo_canvas_box_get_content_width_request;
@@ -299,7 +304,10 @@
NULL, NULL,
g_cclosure_marshal_VOID__BOOLEAN,
G_TYPE_NONE, 1, G_TYPE_BOOLEAN);
-
+
+ g_object_class_override_property (object_class, PROP_ID, "id");
+ g_object_class_override_property (object_class, PROP_CLASSES, "classes");
+
/**
* HippoCanvasBox:orientation
*
@@ -574,6 +582,8 @@
* Sets an RGBA background color (pack the color into 32-bit unsigned int, just type
* "0xff0000ff" for example for opaque red). The background color covers the
* padding but not the border of the box.
+ *
+ * This property is ignored if the background-color-set property is %FALSE.
*/
g_object_class_install_property(object_class,
PROP_BACKGROUND_COLOR,
@@ -586,6 +596,21 @@
G_PARAM_READABLE | G_PARAM_WRITABLE));
/**
+ * HippoCanvasBox:background-color-set
+ *
+ * Determines whether the background-color property is used, or whether the color is determined
+ * from the item's style. This flag gets set automatically if you write to the background-color
+ * property.
+ */
+ g_object_class_install_property(object_class,
+ PROP_BACKGROUND_COLOR_SET,
+ g_param_spec_boolean("background-color-set",
+ _("Background Color Set"),
+ _("Whether a background color was set"),
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ /**
* HippoCanvasBox:border-color
*
* Sets an RGBA border color (pack the color into 32-bit unsigned int, just type
@@ -606,6 +631,21 @@
G_PARAM_READABLE | G_PARAM_WRITABLE));
/**
+ * HippoCanvasBox:border-color-set
+ *
+ * Determines whether the border-color property is used, or whether the color is determined
+ * from the item's style. This flag gets set automatically if you write to the border-color
+ * property.
+ */
+ g_object_class_install_property(object_class,
+ PROP_BORDER_COLOR_SET,
+ g_param_spec_boolean("border-color-set",
+ _("Border Color Set"),
+ _("Whether a border color was set"),
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ /**
* HippoCanvasBox:spacing
*
* The spacing is a gap to leave between all child items in the box. If you want a gap
@@ -642,27 +682,13 @@
G_MAXUINT,
HIPPO_CANVAS_DEFAULT_COLOR,
G_PARAM_READABLE | G_PARAM_WRITABLE));
- /**
- * HippoCanvasBox:color-cascade
- *
- * If the color-set property is %FALSE, this property determines whether the item inherits
- * its foreground color property from its containing canvas item, or whether the item uses
- * a default color which may depend on the canvas item type.
- */
- g_object_class_install_property(object_class,
- PROP_COLOR_CASCADE,
- g_param_spec_enum("color-cascade",
- _("Foreground Color Cascade"),
- _("Whether to use parent's color if ours is unset"),
- HIPPO_TYPE_CASCADE_MODE,
- HIPPO_CASCADE_MODE_INHERIT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
+
/**
* HippoCanvasBox:color-set
*
- * Determines whether the color property is used, or whether a default color is
- * used according to the color-cascade property. This flag gets set automatically
- * if you write to the color property.
+ * Determines whether the color property is used, or whether the color is determined
+ * from the item's style. This flag gets set automatically if you write to the color
+ * property.
*/
g_object_class_install_property(object_class,
PROP_COLOR_SET,
@@ -675,10 +701,8 @@
* HippoCanvasBox:font
*
* The font to use as a Pango font description string. Only matters for text items, or for
- * boxes that contain text items. If a box contains text items, and the child items
- * have the font-cascade property set to #HIPPO_CASCADE_MODE_INHERIT, then the child
- * items will use the font from the containing box unless they have explicitly set
- * their own font.
+ * boxes that contain text items, overriding any font from the item's style. The font will not
+ * be inherited by child items.
*
* This property is just a way to set the font-desc property, using a string
* instead of a #PangoFontDescription object.
@@ -693,12 +717,8 @@
/**
* HippoCanvasBox:font-desc
*
- * The font to use for text in the item and its children. Children will inherit this font
- * if their font-cascade is set to #HIPPO_CASCADE_MODE_INHERIT and they don't set a font
- * themselves.
- *
- * If the font description is %NULL then the font will be inherited or a default will be
- * used, according to the font-cascade property.
+ * The font to use for text in the item, overriding any font from the style. The font
+ * will not be inherited by child items.
*/
g_object_class_install_property(object_class,
PROP_FONT_DESC,
@@ -709,23 +729,6 @@
G_PARAM_READABLE | G_PARAM_WRITABLE));
/**
- * HippoCanvasBox:font-cascade
- *
- * If the font-desc property is %NULL, this property determines whether the item inherits
- * its font property from its containing canvas item, or whether the item uses
- * a default font.
- *
- */
- g_object_class_install_property(object_class,
- PROP_FONT_CASCADE,
- g_param_spec_enum("font-cascade",
- _("Font Cascade"),
- _("Whether to use parent's font if ours is unset"),
- HIPPO_TYPE_CASCADE_MODE,
- HIPPO_CASCADE_MODE_INHERIT,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
- /**
* HippoCanvasBox:tooltip
*
* A string to display as a tooltip on this canvas item.
@@ -754,6 +757,15 @@
}
static void
+clear_style(HippoCanvasBox *box)
+{
+ if (box->style) {
+ g_object_unref(box->style);
+ box->style = NULL;
+ }
+}
+
+static void
hippo_canvas_box_dispose(GObject *object)
{
HippoCanvasBox *box = HIPPO_CANVAS_BOX(object);
@@ -761,10 +773,7 @@
hippo_canvas_box_clear(box);
hippo_canvas_box_set_layout(box, NULL);
- if (box->style) {
- g_object_unref(box->style);
- box->style = NULL;
- }
+ clear_style(box);
hippo_canvas_item_emit_destroy(HIPPO_CANVAS_ITEM(object));
@@ -794,11 +803,23 @@
}
static void
-ensure_style(HippoCanvasBox *box)
+set_font_description(HippoCanvasBox *box,
+ PangoFontDescription *font_desc,
+ gboolean copy)
{
- if (box->style == NULL) {
- box->style = g_object_new(HIPPO_TYPE_CANVAS_STYLE, NULL);
- }
+ if (box->font_desc == font_desc)
+ return;
+
+ if (box->font_desc != NULL)
+ pango_font_description_free(box->font_desc);
+
+ if (copy && font_desc != NULL)
+ box->font_desc = pango_font_description_copy(font_desc);
+ else
+ box->font_desc = font_desc;
+
+ g_object_notify(G_OBJECT(box), "font-desc");
+ g_object_notify(G_OBJECT(box), "font");
}
static void
@@ -814,45 +835,144 @@
need_resize = TRUE; /* for most of them it's true */
switch (prop_id) {
+ case PROP_ID:
+ {
+ const char *str = g_value_get_string(value);
+ if (str != box->element_id) {
+ if (box->element_id)
+ g_free(box->element_id);
+ box->element_id = g_strdup(str);
+
+ clear_style(box);
+ hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box), TRUE);
+ }
+ }
+ break;
+ case PROP_CLASSES:
+ {
+ const char *str = g_value_get_string(value);
+ if (str != box->element_class) {
+ if (box->element_class)
+ g_free(box->element_class);
+ box->element_class = g_strdup(str);
+
+ clear_style(box);
+ hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box), TRUE);
+ }
+ }
+ break;
case PROP_ORIENTATION:
box->orientation = g_value_get_enum(value);
break;
case PROP_PADDING_TOP:
- box->padding_top = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->padding_top = p;
+ box->padding_top_set = TRUE;
+ } else {
+ box->padding_top_set = FALSE;
+ }
+ }
break;
case PROP_PADDING_BOTTOM:
- box->padding_bottom = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->padding_bottom = p;
+ box->padding_bottom_set = TRUE;
+ } else {
+ box->padding_bottom_set = FALSE;
+ }
+ }
break;
case PROP_PADDING_LEFT:
- box->padding_left = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->padding_left = p;
+ box->padding_left_set = TRUE;
+ } else {
+ box->padding_left_set = FALSE;
+ }
+ }
break;
case PROP_PADDING_RIGHT:
- box->padding_right = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->padding_right = p;
+ box->padding_right_set = TRUE;
+ } else {
+ box->padding_right_set = FALSE;
+ }
+ }
break;
case PROP_PADDING:
{
int p = g_value_get_int(value);
- box->padding_top = box->padding_bottom = p;
- box->padding_left = box->padding_right = p;
+ if (p >= 0) {
+ box->padding_top = box->padding_bottom = box->padding_left = box->padding_right = p;
+ box->padding_top_set = box->padding_bottom_set = box->padding_left_set = box->padding_right_set = TRUE;
+ } else {
+ box->padding_top_set = box->padding_bottom_set = box->padding_left_set = box->padding_right_set = FALSE;
+ }
}
break;
case PROP_BORDER_TOP:
- box->border_top = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->border_top = p;
+ box->border_top_set = TRUE;
+ } else {
+ box->border_top_set = FALSE;
+ }
+ }
break;
case PROP_BORDER_BOTTOM:
- box->border_bottom = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->border_bottom = p;
+ box->border_bottom_set = TRUE;
+ } else {
+ box->border_bottom_set = FALSE;
+ }
+ }
break;
case PROP_BORDER_LEFT:
- box->border_left = g_value_get_int(value);
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->border_left = p;
+ box->border_left_set = TRUE;
+ } else {
+ box->border_left_set = FALSE;
+ }
+ }
break;
case PROP_BORDER_RIGHT:
+ {
+ int p = g_value_get_int(value);
+ if (p >= 0) {
+ box->border_right = p;
+ box->border_right_set = TRUE;
+ } else {
+ box->border_right_set = FALSE;
+ }
+ }
box->border_right = g_value_get_int(value);
break;
case PROP_BORDER:
{
int p = g_value_get_int(value);
- box->border_top = box->border_bottom = p;
- box->border_left = box->border_right = p;
+ if (p >= 0) {
+ box->border_top = box->border_bottom = box->border_left = box->border_right = p;
+ box->border_top_set = box->border_bottom_set = box->border_left_set = box->border_right_set = TRUE;
+ } else {
+ box->border_top_set = box->border_bottom_set = box->border_left_set = box->border_right_set = FALSE;
+ }
}
break;
case PROP_BOX_WIDTH:
@@ -869,11 +989,25 @@
break;
case PROP_BACKGROUND_COLOR:
box->background_color_rgba = g_value_get_uint(value);
+ box->background_color_set = TRUE;
+ g_object_notify(object, "background-color-set");
+ hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
+ need_resize = FALSE;
+ break;
+ case PROP_BACKGROUND_COLOR_SET:
+ box->background_color_set = g_value_get_boolean(value);
hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
need_resize = FALSE;
break;
case PROP_BORDER_COLOR:
box->border_color_rgba = g_value_get_uint(value);
+ box->border_color_set = TRUE;
+ g_object_notify(object, "border-color-set");
+ hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
+ need_resize = FALSE;
+ break;
+ case PROP_BORDER_COLOR_SET:
+ box->border_color_set = g_value_get_boolean(value);
hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
need_resize = FALSE;
break;
@@ -881,57 +1015,28 @@
box->spacing = g_value_get_int(value);
break;
case PROP_COLOR:
- ensure_style(box);
- g_object_set_property(G_OBJECT(box->style), "color", value);
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- FALSE);
+ box->color_rgba = g_value_get_uint(value);
+ box->color_set = TRUE;
+ g_object_notify(object, "color-set");
+ hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
need_resize = FALSE;
break;
case PROP_COLOR_SET:
- if (g_value_get_boolean(value) || box->style != NULL) {
- ensure_style(box);
- g_object_set_property(G_OBJECT(box->style), "color-set", value);
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- FALSE);
- }
- need_resize = FALSE;
- break;
- case PROP_COLOR_CASCADE:
- {
- HippoCascadeMode new_mode = g_value_get_enum(value);
- if (new_mode != box->color_cascade) {
- box->color_cascade = new_mode;
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- FALSE);
- }
- }
+ box->color_set = g_value_get_boolean(value);
+ hippo_canvas_item_emit_paint_needed(HIPPO_CANVAS_ITEM(box), 0, 0, -1, -1);
need_resize = FALSE;
break;
case PROP_FONT:
- if (!(g_value_get_string(value) == NULL && box->style == NULL)) {
- ensure_style(box);
- g_object_set_property(G_OBJECT(box->style), "font", value);
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- TRUE);
+ {
+ const char *str = g_value_get_string(value);
+ if (str != NULL)
+ set_font_description(box, pango_font_description_from_string(str), FALSE);
+ else
+ set_font_description(box, NULL, FALSE);
}
break;
case PROP_FONT_DESC:
- if (!(g_value_get_boxed(value) == NULL && box->style == NULL)) {
- ensure_style(box);
- g_object_set_property(G_OBJECT(box->style), "font-desc", value);
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- TRUE);
- }
- break;
- case PROP_FONT_CASCADE:
- {
- HippoCascadeMode new_mode = g_value_get_enum(value);
- if (new_mode != box->font_cascade) {
- box->font_cascade = new_mode;
- hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box),
- TRUE);
- }
- }
+ set_font_description(box, g_value_get_boxed(value), TRUE);
break;
case PROP_TOOLTIP:
{
@@ -983,32 +1088,38 @@
box = HIPPO_CANVAS_BOX (object);
switch (prop_id) {
+ case PROP_ID:
+ g_value_set_string(value, box->element_id);
+ break;
+ case PROP_CLASSES:
+ g_value_set_string(value, box->element_class);
+ break;
case PROP_ORIENTATION:
g_value_set_enum(value, box->orientation);
break;
case PROP_PADDING_TOP:
- g_value_set_int(value, box->padding_top);
+ g_value_set_int(value, box->padding_top_set ? box->padding_top : -1);
break;
case PROP_PADDING_BOTTOM:
- g_value_set_int(value, box->padding_bottom);
+ g_value_set_int(value, box->padding_bottom_set ? box->padding_bottom : -1);
break;
case PROP_PADDING_LEFT:
- g_value_set_int(value, box->padding_left);
+ g_value_set_int(value, box->padding_left_set ? box->padding_left : -1);
break;
case PROP_PADDING_RIGHT:
- g_value_set_int(value, box->padding_right);
+ g_value_set_int(value, box->padding_right_set ? box->padding_right : -1);
break;
case PROP_BORDER_TOP:
- g_value_set_int(value, box->border_top);
+ g_value_set_int(value, box->border_top_set ? box->border_top : -1);
break;
case PROP_BORDER_BOTTOM:
- g_value_set_int(value, box->border_bottom);
+ g_value_set_int(value, box->border_bottom_set ? box->border_bottom : -1);
break;
case PROP_BORDER_LEFT:
- g_value_set_int(value, box->border_left);
+ g_value_set_int(value, box->border_left_set ? box->border_left : -1);
break;
case PROP_BORDER_RIGHT:
- g_value_set_int(value, box->border_right);
+ g_value_set_int(value, box->border_right_set ? box->border_right : -1);
break;
case PROP_BOX_WIDTH:
g_value_set_int(value, box->box_width);
@@ -1025,45 +1136,34 @@
case PROP_BACKGROUND_COLOR:
g_value_set_uint(value, box->background_color_rgba);
break;
+ case PROP_BACKGROUND_COLOR_SET:
+ g_value_set_boolean(value, box->background_color_set);
+ break;
case PROP_BORDER_COLOR:
g_value_set_uint(value, box->border_color_rgba);
break;
+ case PROP_BORDER_COLOR_SET:
+ g_value_set_boolean(value, box->border_color_set);
+ break;
case PROP_SPACING:
g_value_set_int(value, box->spacing);
break;
case PROP_COLOR:
- if (box->style) {
- g_object_get_property(G_OBJECT(box->style), "color", value);
- } else {
- g_value_set_uint(value, HIPPO_CANVAS_DEFAULT_BACKGROUND_COLOR);
- }
- break;
- case PROP_COLOR_CASCADE:
- g_value_set_enum(value, box->color_cascade);
+ g_value_set_uint(value, box->color_rgba);
break;
case PROP_COLOR_SET:
- if (box->style) {
- g_object_get_property(G_OBJECT(box->style), "color-set", value);
- } else {
- g_value_set_boolean(value, FALSE);
- }
+ g_value_set_boolean(value, box->color_set);
break;
case PROP_FONT:
- if (box->style) {
- g_object_get_property(G_OBJECT(box->style), "font", value);
+ if (box->font_desc) {
+ char *str = pango_font_description_to_string(box->font_desc);
+ g_value_take_string(value, str);
} else {
g_value_set_string(value, NULL);
}
break;
case PROP_FONT_DESC:
- if (box->style) {
- g_object_get_property(G_OBJECT(box->style), "font-desc", value);
- } else {
- g_value_set_boxed(value, NULL);
- }
- break;
- case PROP_FONT_CASCADE:
- g_value_set_enum(value, box->font_cascade);
+ g_value_set_boxed(value, box->font_desc);
break;
case PROP_TOOLTIP:
g_value_set_string(value, box->tooltip);
@@ -1198,30 +1298,36 @@
HIPPO_CANVAS_ITEM(box), x_p, y_p);
}
-static void
-hippo_canvas_box_affect_color(HippoCanvasContext *context,
- guint32 *color_rgba_p)
+static HippoCanvasStyle *
+hippo_canvas_box_get_style(HippoCanvasContext *context)
{
HippoCanvasBox *box = HIPPO_CANVAS_BOX(context);
+
+ if (box->style == NULL) {
+ box->style = hippo_canvas_style_new(box->context,
+ hippo_canvas_context_get_style(box->context),
+ NULL, /* Inherit theme from parent */
+ G_OBJECT_TYPE(box), box->element_id, box->element_class);
+ hippo_canvas_style_set_link_type(box->style, box->link_type);
+ }
- if (box->context && box->color_cascade == HIPPO_CASCADE_MODE_INHERIT)
- hippo_canvas_context_affect_color(box->context, color_rgba_p);
-
- if (box->style)
- hippo_canvas_style_affect_color(box->style, color_rgba_p);
+ return box->style;
}
-static void
-hippo_canvas_box_affect_font_desc(HippoCanvasContext *context,
- PangoFontDescription *font_desc)
+static double
+hippo_canvas_box_get_resolution(HippoCanvasContext *context)
{
HippoCanvasBox *box = HIPPO_CANVAS_BOX(context);
- if (box->context && box->font_cascade == HIPPO_CASCADE_MODE_INHERIT)
- hippo_canvas_context_affect_font_desc(box->context, font_desc);
-
- if (box->style)
- hippo_canvas_style_affect_font_desc(box->style, font_desc);
+ return hippo_canvas_context_get_resolution(box->context);
+}
+
+static PangoFontDescription *
+hippo_canvas_box_get_font(HippoCanvasContext *context)
+{
+ HippoCanvasBox *box = HIPPO_CANVAS_BOX(context);
+
+ return hippo_canvas_context_get_font(box->context);
}
static void
@@ -1251,7 +1357,9 @@
on_context_style_changed(HippoCanvasContext *context,
gboolean resize_needed,
HippoCanvasBox *box)
-{
+{
+ clear_style(box);
+
/* If our context's style changed, then our own style also
* changed since we chain up to the outer context.
*/
@@ -1347,13 +1455,109 @@
}
void
+hippo_canvas_box_set_link_type (HippoCanvasBox *box,
+ HippoCanvasLinkType link_type)
+{
+ g_return_if_fail(HIPPO_IS_CANVAS_BOX(box));
+
+ if (link_type == box->link_type)
+ return;
+
+ box->link_type = link_type;
+
+ clear_style(box);
+ hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(box), TRUE);
+ hippo_canvas_item_emit_request_changed(HIPPO_CANVAS_ITEM(box));
+}
+
+static void
+get_borders(HippoCanvasBox *box,
+ Borders *borders)
+{
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(box));
+
+ if (box->border_left_set)
+ borders->border[HIPPO_CANVAS_SIDE_LEFT] = box->border_left;
+ else
+ borders->border[HIPPO_CANVAS_SIDE_LEFT] = hippo_canvas_style_get_border_width(style, HIPPO_CANVAS_SIDE_LEFT);
+
+ if (box->border_right_set)
+ borders->border[HIPPO_CANVAS_SIDE_RIGHT] = box->border_right;
+ else
+ borders->border[HIPPO_CANVAS_SIDE_RIGHT] = hippo_canvas_style_get_border_width(style, HIPPO_CANVAS_SIDE_RIGHT);
+
+ if (box->border_top_set)
+ borders->border[HIPPO_CANVAS_SIDE_TOP] = box->border_top;
+ else
+ borders->border[HIPPO_CANVAS_SIDE_TOP] = hippo_canvas_style_get_border_width(style, HIPPO_CANVAS_SIDE_TOP);
+
+ if (box->border_bottom_set)
+ borders->border[HIPPO_CANVAS_SIDE_BOTTOM] = box->border_bottom;
+ else
+ borders->border[HIPPO_CANVAS_SIDE_BOTTOM] = hippo_canvas_style_get_border_width(style, HIPPO_CANVAS_SIDE_BOTTOM);
+
+ if (box->padding_left_set)
+ borders->padding[HIPPO_CANVAS_SIDE_LEFT] = box->padding_left;
+ else
+ borders->padding[HIPPO_CANVAS_SIDE_LEFT] = hippo_canvas_style_get_padding(style, HIPPO_CANVAS_SIDE_LEFT);
+
+ if (box->padding_right_set)
+ borders->padding[HIPPO_CANVAS_SIDE_RIGHT] = box->padding_right;
+ else
+ borders->padding[HIPPO_CANVAS_SIDE_RIGHT] = hippo_canvas_style_get_padding(style, HIPPO_CANVAS_SIDE_RIGHT);
+
+ if (box->padding_top_set)
+ borders->padding[HIPPO_CANVAS_SIDE_TOP] = box->padding_top;
+ else
+ borders->padding[HIPPO_CANVAS_SIDE_TOP] = hippo_canvas_style_get_padding(style, HIPPO_CANVAS_SIDE_TOP);
+
+ if (box->padding_bottom_set)
+ borders->padding[HIPPO_CANVAS_SIDE_BOTTOM] = box->padding_bottom;
+ else
+ borders->padding[HIPPO_CANVAS_SIDE_BOTTOM] = hippo_canvas_style_get_padding(style, HIPPO_CANVAS_SIDE_BOTTOM);
+}
+
+void
hippo_canvas_box_get_background_area (HippoCanvasBox *box,
HippoRectangle *area)
{
- area->x = box->border_left;
- area->y = box->border_top;
- area->width = box->allocated_width - box->border_left - box->border_right;
- area->height = box->allocated_height - box->border_top - box->border_bottom;
+ Borders borders;
+ get_borders(box, &borders);
+
+ area->x = borders.border[HIPPO_CANVAS_SIDE_LEFT];
+ area->y = borders.border[HIPPO_CANVAS_SIDE_TOP];
+ area->width = box->allocated_width - borders.border[HIPPO_CANVAS_SIDE_LEFT] - borders.border[HIPPO_CANVAS_SIDE_RIGHT];
+ area->height = box->allocated_height - borders.border[HIPPO_CANVAS_SIDE_TOP] - borders.border[HIPPO_CANVAS_SIDE_BOTTOM];
+}
+
+static void
+draw_border(HippoCanvasBox *box,
+ HippoCanvasStyle *style,
+ cairo_t *cr,
+ HippoCanvasSide side,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ guint32 border_color_rgba;
+
+ if (box->border_color_set)
+ border_color_rgba = box->border_color_set;
+ else
+ border_color_rgba = hippo_canvas_style_get_border_color(style, side);
+
+ if ((border_color_rgba & 0xff) == 0) /* Transparent */
+ return;
+
+ hippo_cairo_set_source_rgba32(cr, border_color_rgba);
+ cairo_rectangle(cr, x, y, width, height);
+
+ /* In the common case of all the borders the same, we could do a single
+ * fill, and optimize things a bit, but we'll leave the complexity aside
+ * for now.
+ */
+ cairo_fill(cr);
}
static void
@@ -1361,47 +1565,49 @@
cairo_t *cr,
HippoRectangle *damaged_box)
{
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(box));
+ guint background_color_rgba;
+ Borders borders;
+
+ if (box->background_color_set)
+ background_color_rgba = box->background_color_rgba;
+ else
+ background_color_rgba = hippo_canvas_style_get_background_color(style);
+
/* fill background, with html div type semantics - covers entire
* item allocation, including padding but not border
*/
- if ((box->background_color_rgba & 0xff) != 0) {
+ if ((background_color_rgba & 0xff) != 0) {
HippoRectangle area;
hippo_canvas_box_get_background_area(box, &area);
- hippo_cairo_set_source_rgba32(cr, box->background_color_rgba);
+ hippo_cairo_set_source_rgba32(cr, background_color_rgba);
cairo_rectangle(cr,
area.x, area.y,
area.width, area.height);
cairo_fill(cr);
}
- /* draw the borders, in four non-overlapping rectangles */
- if ((box->border_color_rgba & 0xff) != 0) {
- hippo_cairo_set_source_rgba32(cr, box->border_color_rgba);
- /* top */
- cairo_rectangle(cr,
- 0, 0,
- box->allocated_width,
- box->border_top);
- /* left */
- cairo_rectangle(cr,
- 0, box->border_top,
- box->border_left,
- box->allocated_height - box->border_top - box->border_bottom);
- /* right */
- cairo_rectangle(cr,
- box->allocated_width - box->border_right,
- box->border_top,
- box->border_right,
- box->allocated_height - box->border_top - box->border_bottom);
- /* bottom */
- cairo_rectangle(cr,
- 0, box->allocated_height - box->border_bottom,
- box->allocated_width,
- box->border_bottom);
- cairo_fill(cr);
- }
+ get_borders(box, &borders);
+
+ draw_border(box, style, cr, HIPPO_CANVAS_SIDE_TOP,
+ 0, 0,
+ box->allocated_width,
+ borders.border[HIPPO_CANVAS_SIDE_TOP]);
+ draw_border(box, style, cr, HIPPO_CANVAS_SIDE_LEFT,
+ 0, borders.border[HIPPO_CANVAS_SIDE_TOP],
+ borders.border[HIPPO_CANVAS_SIDE_LEFT],
+ box->allocated_height - borders.border[HIPPO_CANVAS_SIDE_TOP] - borders.border[HIPPO_CANVAS_SIDE_BOTTOM]);
+ draw_border(box, style, cr, HIPPO_CANVAS_SIDE_RIGHT,
+ box->allocated_width - borders.border[HIPPO_CANVAS_SIDE_RIGHT],
+ borders.border[HIPPO_CANVAS_SIDE_TOP] ,
+ borders.border[HIPPO_CANVAS_SIDE_RIGHT],
+ box->allocated_height - borders.border[HIPPO_CANVAS_SIDE_TOP] - borders.border[HIPPO_CANVAS_SIDE_BOTTOM]);
+ draw_border(box, style, cr, HIPPO_CANVAS_SIDE_BOTTOM,
+ 0, box->allocated_height - borders.border[HIPPO_CANVAS_SIDE_BOTTOM],
+ box->allocated_width,
+ borders.border[HIPPO_CANVAS_SIDE_BOTTOM]);
}
static void
@@ -1485,11 +1691,16 @@
int *x_p,
int *width_p)
{
- int left = box->border_left + box->padding_left;
- int right = box->border_right + box->padding_right;
+ Borders borders;
+ int left;
+ int right;
int unpadded_box_width;
int content_width;
+ get_borders(box, &borders);
+ left = borders.border[HIPPO_CANVAS_SIDE_LEFT] + borders.padding[HIPPO_CANVAS_SIDE_LEFT];
+ right = borders.border[HIPPO_CANVAS_SIDE_RIGHT] + borders.padding[HIPPO_CANVAS_SIDE_RIGHT];
+
g_return_if_fail(requested_content_width >= 0);
if (natural_content_width < allocated_box_width)
@@ -1535,12 +1746,17 @@
int *y_p,
int *height_p)
{
- int top = box->border_top + box->padding_top;
- int bottom = box->border_bottom + box->padding_bottom;
+ Borders borders;
+ int top;
+ int bottom;
int unpadded_box_height;
int content_height;
g_return_if_fail(requested_content_height >= 0);
+
+ get_borders(box, &borders);
+ top = borders.border[HIPPO_CANVAS_SIDE_TOP] + borders.padding[HIPPO_CANVAS_SIDE_TOP];
+ bottom = borders.border[HIPPO_CANVAS_SIDE_BOTTOM] + borders.padding[HIPPO_CANVAS_SIDE_BOTTOM];
if (natural_content_height < allocated_box_height)
content_height = natural_content_height;
@@ -2749,11 +2965,14 @@
{
int content_min_width, content_natural_width;
HippoCanvasBox *box;
-
+ Borders borders;
+
box = HIPPO_CANVAS_BOX(item);
-
+
box->needs_width_request = FALSE;
+ get_borders(box, &borders);
+
/* We need to call this even if just returning the box-width prop,
* so that children can rely on getting the full request, allocate
* cycle in order every time, and so we compute the cached requests.
@@ -2771,8 +2990,8 @@
} else {
int outside;
- outside = box->padding_left + box->padding_right
- + box->border_left + box->border_right;
+ outside = borders.padding[HIPPO_CANVAS_SIDE_LEFT] + borders.padding[HIPPO_CANVAS_SIDE_RIGHT]
+ + borders.border[HIPPO_CANVAS_SIDE_LEFT] + borders.border[HIPPO_CANVAS_SIDE_RIGHT];
if (min_width_p)
*min_width_p = content_min_width + outside;
@@ -2798,14 +3017,17 @@
int content_min_height, content_natural_height;
int content_for_width;
HippoCanvasBox *box;
+ Borders borders;
box = HIPPO_CANVAS_BOX(item);
box->needs_height_request = FALSE;
+ get_borders(box, &borders);
+
content_for_width = for_width
- - box->padding_left - box->padding_right
- - box->border_left - box->border_right;
+ - borders.padding[HIPPO_CANVAS_SIDE_LEFT] - borders.padding[HIPPO_CANVAS_SIDE_RIGHT]
+ - borders.border[HIPPO_CANVAS_SIDE_LEFT] - borders.border[HIPPO_CANVAS_SIDE_RIGHT];
/* We need to call this even if just returning the box-height prop,
* so that children can rely on getting the full request, allocate
@@ -2822,8 +3044,8 @@
*natural_height_p = box->box_height;
} else {
int outside;
- outside = box->padding_top + box->padding_bottom
- + box->border_top + box->border_bottom;
+ outside = borders.padding[HIPPO_CANVAS_SIDE_TOP] + borders.padding[HIPPO_CANVAS_SIDE_BOTTOM]
+ + borders.border[HIPPO_CANVAS_SIDE_TOP] + borders.border[HIPPO_CANVAS_SIDE_BOTTOM];
if (min_height_p)
*min_height_p = content_min_height + outside;
Modified: trunk/common/hippo/hippo-canvas-box.h
==============================================================================
--- trunk/common/hippo/hippo-canvas-box.h (original)
+++ trunk/common/hippo/hippo-canvas-box.h Mon Mar 24 19:05:00 2008
@@ -4,12 +4,10 @@
#include <hippo/hippo-canvas-item.h>
#include <hippo/hippo-canvas-container.h>
+#include <hippo/hippo-canvas-style.h>
G_BEGIN_DECLS
-typedef struct _HippoCanvasStyle HippoCanvasStyle;
-typedef struct _HippoCanvasStyleClass HippoCanvasStyleClass;
-
typedef enum
{
HIPPO_PACK_EXPAND = 1, /**< This is equivalent to both EXPAND and FILL for GtkBox,
@@ -33,11 +31,6 @@
HIPPO_PACK_CLEAR_BOTH = 192 /* Pack below left-and right floated children */
} HippoPackFlags;
-typedef enum {
- HIPPO_CASCADE_MODE_NONE,
- HIPPO_CASCADE_MODE_INHERIT
-} HippoCascadeMode;
-
typedef int (* HippoCanvasCompareChildFunc) (HippoCanvasItem *child_a,
HippoCanvasItem *child_b,
void *data);
@@ -66,6 +59,9 @@
HippoCanvasStyle *style; /* may be NULL if no relevant props set */
GSList *children;
+ char *element_id;
+ char *element_class;
+
HippoCanvasLayout *layout;
char *tooltip;
@@ -90,6 +86,8 @@
int box_width;
int box_height;
+ PangoFontDescription *font_desc;
+ guint32 color_rgba;
guint32 background_color_rgba;
guint32 border_color_rgba;
@@ -119,16 +117,26 @@
guint x_align : 3; /* enum only has 4 values so it fits with extra */
guint y_align : 3; /* enum only has 4 values so it fits with extra */
guint clickable : 1; /* show a hand pointer and emit activated signal */
+ guint link_type : 2; /* enum only has 3 values so it fits with extra */
guint hovering : 1; /* the box or some child contains the pointer (have gotten enter without leave) */
- guint color_cascade : 2; /* enum has only 2 values */
- guint font_cascade : 2; /* enum has only 2 values */
+ guint color_set : 1;
+ guint background_color_set : 1;
+ guint border_color_set : 1;
+
+ guint border_top_set : 1;
+ guint border_bottom_set : 1;
+ guint border_left_set : 1;
+ guint border_right_set : 1;
+
+ guint padding_top_set : 1;
+ guint padding_bottom_set : 1;
+ guint padding_left_set : 1;
+ guint padding_right_set : 1;
};
struct _HippoCanvasBoxClass {
GObjectClass base_class;
- guint32 default_color;
-
void (* paint_background) (HippoCanvasBox *box,
cairo_t *cr,
HippoRectangle *damaged_box);
@@ -227,6 +235,9 @@
gboolean hippo_canvas_box_is_clickable (HippoCanvasBox *box);
+void hippo_canvas_box_set_link_type (HippoCanvasBox *box,
+ HippoCanvasLinkType link_type);
+
/* API for layout managers */
HippoCanvasBoxChild *hippo_canvas_box_find_box_child (HippoCanvasBox *box,
Modified: trunk/common/hippo/hippo-canvas-context.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-context.c (original)
+++ trunk/common/hippo/hippo-canvas-context.c Mon Mar 24 19:05:00 2008
@@ -121,32 +121,28 @@
HIPPO_CANVAS_CONTEXT_GET_IFACE(context)->translate_to_screen(context, item, x_p, y_p);
}
-void
-hippo_canvas_context_affect_color(HippoCanvasContext *context,
- guint32 *color_rgba_p)
+HippoCanvasStyle *
+hippo_canvas_context_get_style (HippoCanvasContext *context)
{
- HippoCanvasContextIface *iface;
+ g_return_val_if_fail(HIPPO_IS_CANVAS_CONTEXT(context), NULL);
- g_return_if_fail(HIPPO_IS_CANVAS_CONTEXT(context));
-
- iface = HIPPO_CANVAS_CONTEXT_GET_IFACE(context);
-
- if (iface->affect_color)
- (* iface->affect_color) (context, color_rgba_p);
+ return HIPPO_CANVAS_CONTEXT_GET_IFACE(context)->get_style(context);
}
-void
-hippo_canvas_context_affect_font_desc(HippoCanvasContext *context,
- PangoFontDescription *font_desc)
+double
+hippo_canvas_context_get_resolution (HippoCanvasContext *context)
{
- HippoCanvasContextIface *iface;
+ g_return_val_if_fail(HIPPO_IS_CANVAS_CONTEXT(context), 96.);
- g_return_if_fail(HIPPO_IS_CANVAS_CONTEXT(context));
-
- iface = HIPPO_CANVAS_CONTEXT_GET_IFACE(context);
+ return HIPPO_CANVAS_CONTEXT_GET_IFACE(context)->get_resolution(context);
+}
+
+PangoFontDescription *
+hippo_canvas_context_get_font (HippoCanvasContext *context)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_CONTEXT(context), NULL);
- if (iface->affect_font_desc)
- (* iface->affect_font_desc) (context, font_desc);
+ return HIPPO_CANVAS_CONTEXT_GET_IFACE(context)->get_font(context);
}
void
Modified: trunk/common/hippo/hippo-canvas-context.h
==============================================================================
--- trunk/common/hippo/hippo-canvas-context.h (original)
+++ trunk/common/hippo/hippo-canvas-context.h Mon Mar 24 19:05:00 2008
@@ -32,9 +32,15 @@
typedef enum {
HIPPO_STOCK_COLOR_BG_NORMAL,
- HIPPO_STOCK_COLOR_BG_PRELIGHT
+ HIPPO_STOCK_COLOR_BG_PRELIGHT,
+ HIPPO_STOCK_COLOR_FG
} HippoStockColor;
+typedef struct _HippoCanvasStyle HippoCanvasStyle;
+typedef struct _HippoCanvasStyleClass HippoCanvasStyleClass;
+typedef struct _HippoCanvasTheme HippoCanvasTheme;
+typedef struct _HippoCanvasThemeClass HippoCanvasThemeClass;
+
typedef struct _HippoCanvasContext HippoCanvasContext;
typedef struct _HippoCanvasContextIface HippoCanvasContextIface;
@@ -66,13 +72,10 @@
HippoCanvasItem *item,
int *x_p,
int *y_p);
+ HippoCanvasStyle *(* get_style) (HippoCanvasContext *context);
+ double (* get_resolution) (HippoCanvasContext *context);
+ PangoFontDescription *(* get_font) (HippoCanvasContext *context);
- /* Style methods (should probably be on a separate interface eventually) */
- void (* affect_color) (HippoCanvasContext *context,
- guint32 *color_rgba_p);
- void (* affect_font_desc) (HippoCanvasContext *context,
- PangoFontDescription *font_desc);
-
/* Signals */
/* Inherited style properties (see affect_* methods) have changed.
@@ -104,12 +107,12 @@
int *x_p,
int *y_p);
-void hippo_canvas_context_affect_color (HippoCanvasContext *context,
- guint32 *color_rgba_p);
-void hippo_canvas_context_affect_font_desc (HippoCanvasContext *context,
- PangoFontDescription *font_desc);
-void hippo_canvas_context_emit_style_changed (HippoCanvasContext *context,
- gboolean resize_needed);
+HippoCanvasStyle *hippo_canvas_context_get_style (HippoCanvasContext *context);
+double hippo_canvas_context_get_resolution (HippoCanvasContext *context);
+PangoFontDescription *hippo_canvas_context_get_font (HippoCanvasContext *context);
+
+void hippo_canvas_context_emit_style_changed(HippoCanvasContext *context,
+ gboolean resize_needed);
G_END_DECLS
Modified: trunk/common/hippo/hippo-canvas-item.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-item.c (original)
+++ trunk/common/hippo/hippo-canvas-item.c Mon Mar 24 19:05:00 2008
@@ -6,7 +6,7 @@
#include "hippo-canvas-container.h"
#include "hippo-canvas-marshal.h"
-static void hippo_canvas_item_base_init (void *klass);
+static void hippo_canvas_item_class_init (void *g_iface);
enum {
DESTROY,
@@ -29,193 +29,209 @@
{
static GType type = 0;
if (type == 0) {
- static const GTypeInfo info =
- {
- sizeof(HippoCanvasItemIface),
- hippo_canvas_item_base_init,
- NULL /* base_finalize */
- };
- type = g_type_register_static(G_TYPE_INTERFACE, "HippoCanvasItem",
- &info, 0);
+ type = g_type_register_static_simple (G_TYPE_INTERFACE,
+ _("HippoCanvasItem"),
+ sizeof (HippoCanvasItemIface),
+ (GClassInitFunc) hippo_canvas_item_class_init,
+ 0, NULL, 0);
}
return type;
}
static void
-hippo_canvas_item_base_init(void *klass)
+hippo_canvas_item_class_init(void *g_iface)
{
- static gboolean initialized = FALSE;
-
- if (!initialized) {
- /* create signals in here */
+ /**
+ * HippoCanvasItem::destroy
+ *
+ * This canvas item has explicitely been destroyed. All references it holds
+ * to other objects will be dropped, and all signal handlers removed.
+ */
+ signals[DESTROY] =
+ g_signal_new ("destroy",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
+ 0, /* No handler; in C implement cleanups in ->dispose() */
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ /**
+ * HippoCanvasItem::paint
+ *
+ * All drawing of a canvas item happens in the handlers for
+ * this signal. The rectangle is the bounding box of the
+ * damage region. Most concrete items derive from #HippoCanvasBox,
+ * whose default paint handler invokes a series of more fine-grained
+ * paint handlers to paint the background, content, etc.; usually you
+ * should override one of those fine-grained handlers rather than this
+ * all-encompassing paint.
+ */
+ signals[PAINT] =
+ g_signal_new ("paint",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, paint),
+ NULL, NULL,
+ hippo_canvas_marshal_VOID__POINTER_BOXED,
+ G_TYPE_NONE, 2, G_TYPE_POINTER, HIPPO_TYPE_RECTANGLE);
+ /**
+ * HippoCanvasItem::request-changed
+ *
+ * Signal emitted when the natural or minimum size of the canvas item
+ * may have changed. The parent canvas or parent canvas item will normally
+ * need to recompute its layout in response.
+ */
+ signals[REQUEST_CHANGED] =
+ g_signal_new ("request-changed",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, request_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ /**
+ * HippoCanvasItem::paint-needed
+ *
+ * Signal emitted when a canvas item needs to be repainted. The
+ * rectangle is the bounding box of the areas that need repainting.
+ */
+ signals[PAINT_NEEDED] =
+ g_signal_new ("paint-needed",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, paint_needed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOXED,
+ G_TYPE_NONE, 1, HIPPO_TYPE_RECTANGLE);
+ /**
+ * HippoCanvasItem::button-press-event
+ *
+ * Signal emitted when a mouse button is pressed down on the canvas item.
+ */
+ signals[BUTTON_PRESS_EVENT] =
+ g_signal_new ("button-press-event",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, button_press_event),
+ g_signal_accumulator_true_handled, NULL,
+ hippo_canvas_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
+ /**
+ * HippoCanvasItem::button-release-event
+ *
+ * Signal emitted when a mouse button is released on the canvas item.
+ */
+ signals[BUTTON_RELEASE_EVENT] =
+ g_signal_new ("button-release-event",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, button_release_event),
+ g_signal_accumulator_true_handled, NULL,
+ hippo_canvas_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
+ /**
+ * HippoCanvasItem::motion-notify-event
+ *
+ * Signal emitted when the mouse pointer enters, leaves, or moves within
+ * a canvas item. Note that unlike #GtkWidget, there are not separate
+ * events for enter and leave.
+ */
+ signals[MOTION_NOTIFY_EVENT] =
+ g_signal_new ("motion-notify-event",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, motion_notify_event),
+ g_signal_accumulator_true_handled, NULL,
+ hippo_canvas_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
- /**
- * HippoCanvasItem::destroy
- *
- * This canvas item has explicitely been destroyed. All references it holds
- * to other objects will be dropped, and all signal handlers removed.
- *
- * (If you
- */
- signals[DESTROY] =
- g_signal_new ("destroy",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_CLEANUP | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
- 0, /* No handler; in C implement cleanups in ->dispose() */
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
-
- /**
- * HippoCanvasItem::paint
- *
- * All drawing of a canvas item happens in the handlers for
- * this signal. The rectangle is the bounding box of the
- * damage region. Most concrete items derive from #HippoCanvasBox,
- * whose default paint handler invokes a series of more fine-grained
- * paint handlers to paint the background, content, etc.; usually you
- * should override one of those fine-grained handlers rather than this
- * all-encompassing paint.
- */
- signals[PAINT] =
- g_signal_new ("paint",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, paint),
- NULL, NULL,
- hippo_canvas_marshal_VOID__POINTER_BOXED,
- G_TYPE_NONE, 2, G_TYPE_POINTER, HIPPO_TYPE_RECTANGLE);
- /**
- * HippoCanvasItem::request-changed
- *
- * Signal emitted when the natural or minimum size of the canvas item
- * may have changed. The parent canvas or parent canvas item will normally
- * need to recompute its layout in response.
- */
- signals[REQUEST_CHANGED] =
- g_signal_new ("request-changed",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, request_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- /**
- * HippoCanvasItem::paint-needed
- *
- * Signal emitted when a canvas item needs to be repainted. The
- * rectangle is the bounding box of the areas that need repainting.
- */
- signals[PAINT_NEEDED] =
- g_signal_new ("paint-needed",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, paint_needed),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOXED,
- G_TYPE_NONE, 1, HIPPO_TYPE_RECTANGLE);
- /**
- * HippoCanvasItem::button-press-event
- *
- * Signal emitted when a mouse button is pressed down on the canvas item.
- */
- signals[BUTTON_PRESS_EVENT] =
- g_signal_new ("button-press-event",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, button_press_event),
- g_signal_accumulator_true_handled, NULL,
- hippo_canvas_marshal_BOOLEAN__BOXED,
+ /**
+ * HippoCanvasItem::scroll-event
+ *
+ * Signal emitted when the mouse wheel or other mechanism requests scrolling.
+ */
+ signals[SCROLL_EVENT] =
+ g_signal_new ("scroll-event",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, scroll_event),
+ g_signal_accumulator_true_handled, NULL,
+ hippo_canvas_marshal_BOOLEAN__BOXED,
G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
- /**
- * HippoCanvasItem::button-release-event
- *
- * Signal emitted when a mouse button is released on the canvas item.
- */
- signals[BUTTON_RELEASE_EVENT] =
- g_signal_new ("button-release-event",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, button_release_event),
- g_signal_accumulator_true_handled, NULL,
- hippo_canvas_marshal_BOOLEAN__BOXED,
- G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
- /**
- * HippoCanvasItem::motion-notify-event
- *
- * Signal emitted when the mouse pointer enters, leaves, or moves within
- * a canvas item. Note that unlike #GtkWidget, there are not separate
- * events for enter and leave.
- */
- signals[MOTION_NOTIFY_EVENT] =
- g_signal_new ("motion-notify-event",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, motion_notify_event),
- g_signal_accumulator_true_handled, NULL,
- hippo_canvas_marshal_BOOLEAN__BOXED,
- G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
-
- /**
- * HippoCanvasItem::scroll-event
- *
- * Signal emitted when the mouse wheel or other mechanism requests scrolling.
- */
- signals[SCROLL_EVENT] =
- g_signal_new ("scroll-event",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, scroll_event),
- g_signal_accumulator_true_handled, NULL,
- hippo_canvas_marshal_BOOLEAN__BOXED,
- G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
- /**
- * HippoCanvasItem::key-press-event
- *
- * Signal emitted when a key is pressed while the canvas item is focused.
- */
- signals[KEY_PRESS_EVENT] =
- g_signal_new ("key-press-event",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, key_press_event),
- g_signal_accumulator_true_handled, NULL,
- hippo_canvas_marshal_BOOLEAN__BOXED,
- G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
- /**
- * HippoCanvasItem::activated
- *
- * Signal emitted when the canvas item is "activated" (e.g. if a button is clicked or
- * an url is clicked).
- */
- signals[ACTIVATED] =
- g_signal_new ("activated",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, activated),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- /**
- * HippoCanvasItem::tooltip-changed
- *
- * Signal emitted when the canvas item's tooltip changes. The code displaying the
- * tooltip may need this signal in order to update in response to changes.
- */
- signals[TOOLTIP_CHANGED] =
- g_signal_new ("tooltip-changed",
- HIPPO_TYPE_CANVAS_ITEM,
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET(HippoCanvasItemIface, tooltip_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
+ /**
+ * HippoCanvasItem::key-press-event
+ *
+ * Signal emitted when a key is pressed while the canvas item is focused.
+ */
+ signals[KEY_PRESS_EVENT] =
+ g_signal_new ("key-press-event",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, key_press_event),
+ g_signal_accumulator_true_handled, NULL,
+ hippo_canvas_marshal_BOOLEAN__BOXED,
+ G_TYPE_BOOLEAN, 1, HIPPO_TYPE_EVENT);
+ /**
+ * HippoCanvasItem::activated
+ *
+ * Signal emitted when the canvas item is "activated" (e.g. if a button is clicked or
+ * an url is clicked).
+ */
+ signals[ACTIVATED] =
+ g_signal_new ("activated",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, activated),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ /**
+ * HippoCanvasItem::tooltip-changed
+ *
+ * Signal emitted when the canvas item's tooltip changes. The code displaying the
+ * tooltip may need this signal in order to update in response to changes.
+ */
+ signals[TOOLTIP_CHANGED] =
+ g_signal_new ("tooltip-changed",
+ HIPPO_TYPE_CANVAS_ITEM,
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(HippoCanvasItemIface, tooltip_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+ /**** properties *****/
+
+ /**
+ * HippoCanvasItem:id
+ *
+ * The ID of the element; this is used when matching a CSS rule selector against
+ * the element tree.
+ */
+ g_object_interface_install_property(g_iface,
+ g_param_spec_string("id",
+ _("ID"),
+ _("ID of the item used for CSS rule matching"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
+
+ /**
+ * HippoCanvasItem:classes
+ *
+ * Class names for the element; this is used when matching a CSS rule selector against
+ * the element tree. Multiple classes can be specified, specified by spaces. (This property
+ * is called 'classes' and not 'class' to avoid problems with language bindings.)
+ */
+ g_object_interface_install_property(g_iface,
+ g_param_spec_string("classes",
+ _("Classes"),
+ _("Class names for the item used for CSS rule matching"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE));
- initialized = TRUE;
- }
}
void
Modified: trunk/common/hippo/hippo-canvas-link.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-link.c (original)
+++ trunk/common/hippo/hippo-canvas-link.c Mon Mar 24 19:05:00 2008
@@ -1,13 +1,15 @@
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
#include "hippo-canvas-internal.h"
#include "hippo-canvas-link.h"
+#include "hippo-canvas-style.h"
#include "hippo-canvas-text.h"
#include "hippo-canvas-box.h"
-static void hippo_canvas_link_init (HippoCanvasLink *link);
-static void hippo_canvas_link_class_init (HippoCanvasLinkClass *klass);
-static void hippo_canvas_link_iface_init (HippoCanvasItemIface *item_class);
-static void hippo_canvas_link_finalize (GObject *object);
+static void hippo_canvas_link_init (HippoCanvasLink *link);
+static void hippo_canvas_link_class_init (HippoCanvasLinkClass *klass);
+static void hippo_canvas_link_item_iface_init (HippoCanvasItemIface *item_class);
+static void hippo_canvas_link_context_iface_init (HippoCanvasContextIface *context_class);
+static void hippo_canvas_link_finalize (GObject *object);
static void hippo_canvas_link_set_property (GObject *object,
guint prop_id,
@@ -18,7 +20,6 @@
GValue *value,
GParamSpec *pspec);
-
#if 0
enum {
LAST_SIGNAL
@@ -33,34 +34,38 @@
};
G_DEFINE_TYPE_WITH_CODE(HippoCanvasLink, hippo_canvas_link, HIPPO_TYPE_CANVAS_TEXT,
- G_IMPLEMENT_INTERFACE(HIPPO_TYPE_CANVAS_ITEM, hippo_canvas_link_iface_init));
+ G_IMPLEMENT_INTERFACE(HIPPO_TYPE_CANVAS_ITEM, hippo_canvas_link_item_iface_init);
+ G_IMPLEMENT_INTERFACE(HIPPO_TYPE_CANVAS_CONTEXT, hippo_canvas_link_context_iface_init));
static void
hippo_canvas_link_init(HippoCanvasLink *link)
{
- /* HippoCanvasText *text = HIPPO_CANVAS_TEXT(link); */
-
- HIPPO_CANVAS_BOX(link)->clickable = TRUE;
+ HippoCanvasBox *box = HIPPO_CANVAS_BOX(link);
- link->base_attrs = NULL;
+ hippo_canvas_box_set_link_type(box, HIPPO_CANVAS_LINK_LINK);
+ hippo_canvas_box_set_clickable(box, TRUE);
}
static HippoCanvasItemIface *item_parent_class;
+static HippoCanvasContextIface *context_parent_class;
static void
-hippo_canvas_link_iface_init(HippoCanvasItemIface *item_class)
+hippo_canvas_link_item_iface_init(HippoCanvasItemIface *item_class)
{
item_parent_class = g_type_interface_peek_parent(item_class);
}
static void
+hippo_canvas_link_context_iface_init(HippoCanvasContextIface *context_class)
+{
+ context_parent_class = g_type_interface_peek_parent(context_class);
+}
+
+static void
hippo_canvas_link_class_init(HippoCanvasLinkClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
- HippoCanvasBoxClass *box_class = HIPPO_CANVAS_BOX_CLASS(klass);
- box_class->default_color = 0x0033ffff;
-
object_class->set_property = hippo_canvas_link_set_property;
object_class->get_property = hippo_canvas_link_get_property;
@@ -79,11 +84,6 @@
static void
hippo_canvas_link_finalize(GObject *object)
{
- HippoCanvasLink *link = HIPPO_CANVAS_LINK(object);
-
- if (link->base_attrs)
- pango_attr_list_unref(link->base_attrs);
-
G_OBJECT_CLASS(hippo_canvas_link_parent_class)->finalize(object);
}
@@ -96,34 +96,19 @@
}
static void
-sync_attributes(HippoCanvasLink *link)
-{
- PangoAttribute *a;
-
- if (link->base_attrs)
- pango_attr_list_unref(link->base_attrs);
- link->base_attrs = pango_attr_list_new();
-
- a = pango_attr_underline_new(PANGO_UNDERLINE_SINGLE);
- a->start_index = 0;
- a->end_index = G_MAXUINT;
- pango_attr_list_insert(link->base_attrs, a);
-
- if (link->visited) {
- a = pango_attr_foreground_new(0x6666, 0x6666, 0x6666);
- a->start_index = 0;
- a->end_index = G_MAXUINT;
- pango_attr_list_insert(link->base_attrs, a);
- }
- g_object_set(link, "attributes", link->base_attrs, NULL);
-}
-
-static void
hippo_canvas_link_set_visited(HippoCanvasLink *link,
gboolean visited)
{
- link->visited = visited;
- sync_attributes(link);
+ visited = visited != FALSE;
+
+ if (visited != link->visited) {
+ HippoCanvasBox *box = HIPPO_CANVAS_BOX(link);
+
+ link->visited = visited;
+
+ hippo_canvas_style_set_link_type(box->style,
+ visited ? HIPPO_CANVAS_LINK_VISITED : HIPPO_CANVAS_LINK_LINK);
+ }
}
static void
Modified: trunk/common/hippo/hippo-canvas-link.h
==============================================================================
--- trunk/common/hippo/hippo-canvas-link.h (original)
+++ trunk/common/hippo/hippo-canvas-link.h Mon Mar 24 19:05:00 2008
@@ -22,7 +22,6 @@
struct _HippoCanvasLink {
HippoCanvasText text;
gboolean visited;
- PangoAttrList *base_attrs;
};
struct _HippoCanvasLinkClass {
Modified: trunk/common/hippo/hippo-canvas-style.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-style.c (original)
+++ trunk/common/hippo/hippo-canvas-style.c Mon Mar 24 19:05:00 2008
@@ -1,9 +1,14 @@
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libcroco/libcroco.h>
+
#include "hippo-canvas-internal.h"
+#include "hippo-canvas-theme-internal.h"
#include "hippo-canvas-type-builtins.h"
#include "hippo-canvas-style.h"
-#include <stdlib.h>
-#include <string.h>
static void hippo_canvas_style_init (HippoCanvasStyle *style);
static void hippo_canvas_style_class_init (HippoCanvasStyleClass *klass);
@@ -11,16 +16,6 @@
static void hippo_canvas_style_finalize (GObject *object);
-static void hippo_canvas_style_set_property (GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec);
-static void hippo_canvas_style_get_property (GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec);
-
-
#if 0
enum {
LAST_SIGNAL
@@ -29,21 +24,33 @@
static int signals[LAST_SIGNAL];
#endif
-enum {
- PROP_0,
- PROP_FONT,
- PROP_FONT_DESC,
- PROP_COLOR,
- PROP_COLOR_SET
-};
-
struct _HippoCanvasStyle {
GObject parent;
- guint32 color_rgba;
+ HippoCanvasContext *context;
+ HippoCanvasStyle *parent_style;
+ HippoCanvasTheme *theme;
+
PangoFontDescription *font_desc;
+
+ guint32 background_color;
+ guint32 foreground_color;
+ guint32 border_color[4];
+ double border_width[4];
+ guint padding[4];
+
+ GType element_type;
+ char *element_id;
+ char *element_class;
+
+ CRDeclaration **properties;
+ int n_properties;
- guint color_set : 1;
+ guint properties_computed : 1;
+ guint borders_computed : 1;
+ guint background_computed : 1;
+ guint foreground_computed : 1;
+ guint link_type : 2;
};
struct _HippoCanvasStyleClass {
@@ -56,7 +63,7 @@
static void
hippo_canvas_style_init(HippoCanvasStyle *style)
{
- style->color_rgba = HIPPO_CANVAS_DEFAULT_COLOR;
+ style->link_type = HIPPO_CANVAS_LINK_NONE;
}
static void
@@ -64,45 +71,8 @@
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->set_property = hippo_canvas_style_set_property;
- object_class->get_property = hippo_canvas_style_get_property;
-
object_class->dispose = hippo_canvas_style_dispose;
object_class->finalize = hippo_canvas_style_finalize;
-
-
- g_object_class_install_property(object_class,
- PROP_COLOR,
- g_param_spec_uint("color",
- _("Foreground Color"),
- _("32-bit RGBA foreground color"),
- 0,
- G_MAXUINT,
- HIPPO_CANVAS_DEFAULT_COLOR,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
- g_object_class_install_property(object_class,
- PROP_COLOR_SET,
- g_param_spec_boolean("color-set",
- _("Foreground Color Set"),
- _("Whether a foreground color was set"),
- FALSE,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
-
- g_object_class_install_property(object_class,
- PROP_FONT,
- g_param_spec_string("font",
- _("Font"),
- _("Font description as a string"),
- NULL,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
- g_object_class_install_property(object_class,
- PROP_FONT_DESC,
- g_param_spec_boxed("font-desc",
- _("Font Description"),
- _("Font description as a PangoFontDescription object"),
- PANGO_TYPE_FONT_DESCRIPTION,
- G_PARAM_READABLE | G_PARAM_WRITABLE));
}
static void
@@ -118,6 +88,15 @@
{
HippoCanvasStyle *style = HIPPO_CANVAS_STYLE(object);
+ g_free (style->element_id);
+ g_free (style->element_class);
+
+ if (style->properties) {
+ g_free(style->properties);
+ style->properties = NULL;
+ style->n_properties = 0;
+ }
+
if (style->font_desc) {
pango_font_description_free(style->font_desc);
style->font_desc = NULL;
@@ -126,186 +105,1196 @@
G_OBJECT_CLASS(hippo_canvas_style_parent_class)->finalize(object);
}
-static int
-parse_int32(const char *s)
+HippoCanvasStyle *
+hippo_canvas_style_new (HippoCanvasContext *context,
+ HippoCanvasStyle *parent_style,
+ HippoCanvasTheme *theme,
+ GType element_type,
+ const char *element_id,
+ const char *element_class)
+{
+ HippoCanvasStyle *style;
+
+ g_return_val_if_fail(HIPPO_IS_CANVAS_CONTEXT(context), NULL);
+ g_return_val_if_fail(parent_style == NULL || HIPPO_IS_CANVAS_STYLE(parent_style), NULL);
+
+ style = g_object_new(HIPPO_TYPE_CANVAS_STYLE, NULL);
+
+ style->context = g_object_ref(context);
+ if (parent_style != NULL)
+ style->parent_style = g_object_ref(parent_style);
+ else
+ style->parent_style = NULL;
+
+ if (theme == NULL && parent_style != NULL)
+ theme = parent_style->theme;
+
+ if (theme != NULL)
+ style->theme = g_object_ref(theme);
+
+ style->element_type = element_type;
+ style->element_id = g_strdup(element_id);
+ style->element_class = g_strdup(element_class);
+
+ return style;
+}
+
+void
+hippo_canvas_style_set_link_type (HippoCanvasStyle *style,
+ HippoCanvasLinkType link_type)
+{
+ g_return_if_fail(HIPPO_IS_CANVAS_STYLE(style));
+
+ style->link_type = link_type;
+}
+
+HippoCanvasLinkType
+hippo_canvas_style_get_link_type (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), HIPPO_CANVAS_LINK_NONE);
+
+ return style->link_type;
+}
+
+HippoCanvasStyle *
+hippo_canvas_style_get_parent (HippoCanvasStyle *style)
{
- char *end;
- long v;
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), NULL);
+
+ return style->parent_style;
+}
+
+HippoCanvasTheme *
+hippo_canvas_style_get_theme (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), NULL);
+
+ return style->theme;
+}
- end = NULL;
- v = strtol(s, &end, 10);
+GType
+hippo_canvas_style_get_element_type (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), G_TYPE_NONE);
+
+ return style->element_type;
+}
+
+const char *
+hippo_canvas_style_get_element_id (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), NULL);
- if (end == NULL) {
- g_warning("Failed to parse '%s' as 32-bit integer", s);
- return 0;
+ return style->element_id;
+}
+
+const char *
+hippo_canvas_style_get_element_class (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), NULL);
+
+ return style->element_class;
+}
+
+static void
+ensure_properties(HippoCanvasStyle *style)
+{
+ if (!style->properties_computed) {
+ style->properties_computed = TRUE;
+
+ if (style->theme)
+ _hippo_canvas_theme_get_matched_properties(style->theme, style,
+ &style->properties, &style->n_properties);
}
+}
- return v;
+typedef enum {
+ VALUE_FOUND,
+ VALUE_NOT_FOUND,
+ VALUE_INHERIT
+} GetFromTermResult;
+
+static GetFromTermResult
+get_color_from_term(HippoCanvasStyle *style,
+ CRTerm *term,
+ guint32 *color)
+{
+ CRRgb rgb;
+ enum CRStatus status;
+
+ status = cr_rgb_set_from_term(&rgb, term);
+ if (status != CR_OK)
+ return VALUE_NOT_FOUND;
+
+ if (rgb.inherit)
+ return VALUE_INHERIT;
+
+ if (rgb.is_percentage)
+ cr_rgb_compute_from_percentage(&rgb);
+
+ *color = (rgb.red << 24) | (rgb.green << 16) | (rgb.blue << 8) | 0xff;
+
+ return VALUE_FOUND;
}
-/* Latest pango supports "NNpx" sizes, but FC5 Pango (1.12) does not */
-static int
-parse_absolute_size_hack(const char *s)
+gboolean
+hippo_canvas_style_get_color (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ guint32 *color)
{
- const char *p;
- const char *number;
- p = strstr(s, "px");
- if (p == NULL)
- return -1;
+ int i;
- number = p;
- --number;
- while (number > s) {
- if (!g_ascii_isdigit(*number)) {
- ++number;
- break;
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
+
+ if (strcmp(decl->property->stryng->str, property_name) == 0) {
+ GetFromTermResult result = get_color_from_term(style, decl->value, color);
+ if (result == VALUE_FOUND) {
+ return TRUE;
+ } else if (result == VALUE_INHERIT) {
+ if (style->parent_style)
+ return hippo_canvas_style_get_color(style->parent_style, property_name, inherit, color);
+ else
+ break;
+ }
}
- --number;
}
- return parse_int32(number);
+ return FALSE;
}
-static void
-hippo_canvas_style_set_property(GObject *object,
- guint prop_id,
- const GValue *value,
- GParamSpec *pspec)
+gboolean
+hippo_canvas_style_get_double (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ double *value)
{
- HippoCanvasStyle *style;
+ gboolean result = FALSE;
+ int i;
+
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
+
+ if (strcmp(decl->property->stryng->str, property_name) == 0) {
+ CRTerm *term = decl->value;
- style = HIPPO_CANVAS_STYLE(object);
+ if (term->type != TERM_NUMBER || term->content.num->type != NUM_GENERIC)
+ continue;
- switch (prop_id) {
- case PROP_COLOR:
- style->color_rgba = g_value_get_uint(value);
- if (style->color_set != TRUE) {
- style->color_set = TRUE;
- g_object_notify(G_OBJECT(style), "color-set");
+ *value = term->content.num->val;
+ result = TRUE;
+ break;
}
+ }
+
+ if (!result && inherit && style->parent_style)
+ result = hippo_canvas_style_get_double(style->parent_style, property_name, inherit, value);
+
+ return result;
+}
+
+static PangoFontDescription *
+get_parent_font(HippoCanvasStyle *style)
+{
+ if (style->parent_style)
+ return hippo_canvas_style_get_font(style->parent_style);
+ else
+ return hippo_canvas_context_get_font(style->context);
+}
+
+static GetFromTermResult
+get_length_from_term(HippoCanvasStyle *style,
+ CRTerm *term,
+ gboolean use_parent_font,
+ gdouble *length)
+{
+ CRNum *num;
+
+ enum {
+ ABSOLUTE,
+ POINTS,
+ FONT_RELATIVE,
+ } type = ABSOLUTE;
+
+ double multiplier = 1.0;
+
+ if (term->type != TERM_NUMBER) {
+ g_warning("Ignoring length property that isn't a number");
+ return FALSE;
+ }
+
+ num = term->content.num;
+
+ switch (num->type) {
+ case NUM_LENGTH_PX:
+ type = ABSOLUTE;
+ multiplier = 1;
+ break;
+ case NUM_LENGTH_PT:
+ type = POINTS;
+ multiplier = 1;
+ break;
+ case NUM_LENGTH_IN:
+ type = POINTS;
+ multiplier = 72;
break;
- case PROP_COLOR_SET:
- style->color_set = g_value_get_boolean(value);
+ case NUM_LENGTH_CM:
+ type = POINTS;
+ multiplier = 72. / 2.54;
break;
- case PROP_FONT:
+ case NUM_LENGTH_MM:
+ type = POINTS;
+ multiplier = 72. / 25.4;
+ break;
+ case NUM_LENGTH_PC:
+ type = POINTS;
+ multiplier = 12. / 25.4;
+ break;
+ case NUM_LENGTH_EM:
+ {
+ type = FONT_RELATIVE;
+ multiplier = 1;
+ break;
+ }
+ case NUM_LENGTH_EX:
+ {
+ /* Doing better would require actually resolving the font description
+ * to a specific font, and Pango doesn't have an ex metric anyways,
+ * so we'd have to try and synthesize it by complicated means.
+ *
+ * The 0.5em is the CSS spec suggested thing to use when nothing
+ * better is available.
+ */
+ type = FONT_RELATIVE;
+ multiplier = 0.5;
+ break;
+ }
+
+ case NUM_INHERIT:
+ return VALUE_INHERIT;
+
+ case NUM_AUTO:
+ g_warning("'auto' not supported for lengths");
+ return VALUE_NOT_FOUND;
+
+ case NUM_GENERIC:
+ g_warning("length values must specify a unit");
+ return VALUE_NOT_FOUND;
+
+ case NUM_PERCENTAGE:
+ g_warning("percentage lengths not currently supported");
+ return VALUE_NOT_FOUND;
+
+ case NUM_ANGLE_DEG:
+ case NUM_ANGLE_RAD:
+ case NUM_ANGLE_GRAD:
+ case NUM_TIME_MS:
+ case NUM_TIME_S:
+ case NUM_FREQ_HZ:
+ case NUM_FREQ_KHZ:
+ case NUM_UNKNOWN_TYPE:
+ case NB_NUM_TYPE:
+ g_warning("Ignoring invalid type of number of length property");
+ return VALUE_NOT_FOUND;
+ }
+
+ switch (type) {
+ case ABSOLUTE:
+ *length = num->val * multiplier;
+ break;
+ case POINTS:
+ {
+ double resolution = hippo_canvas_context_get_resolution(style->context);
+ *length = num->val * multiplier * (resolution / 72.);
+ }
+ break;
+ case FONT_RELATIVE:
{
- const char *s;
PangoFontDescription *desc;
- int absolute;
- s = g_value_get_string(value);
- if (s != NULL) {
- char *no_px = NULL;
- absolute = parse_absolute_size_hack(s);
- if (absolute >= 0) {
- // get the "px" out of the string
- GString *no_px_g = g_string_new(NULL);
- const char *p;
- p = strstr(s, "px");
- g_assert(p != NULL);
- g_string_append_len(no_px_g, s, p - s);
- g_string_append_len(no_px_g, p + 2, strlen(p + 2));
- no_px = g_string_free(no_px_g, FALSE);
+
+ if (use_parent_font)
+ desc = get_parent_font(style);
+ else
+ desc = hippo_canvas_style_get_font(style);
+
+ if (pango_font_description_get_size_is_absolute(desc)) {
+ *length = num->val * multiplier * pango_font_description_get_size(desc);
+ } else {
+ double resolution = hippo_canvas_context_get_resolution(style->context);
+ *length = num->val * multiplier * (resolution / 72.) * pango_font_description_get_size(desc);
+ }
+ }
+ break;
+ default:
+ g_assert_not_reached();
+ }
+
+ return VALUE_FOUND;
+}
+
+static GetFromTermResult
+get_length_internal(HippoCanvasStyle *style,
+ const char *property_name,
+ const char *suffixed,
+ gdouble *length)
+{
+ int i;
+
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
+
+ if (strcmp(decl->property->stryng->str, property_name) == 0 ||
+ (suffixed != NULL && strcmp(decl->property->stryng->str, suffixed) == 0)) {
+ GetFromTermResult result = get_length_from_term(style, decl->value, FALSE, length);
+ if (result != VALUE_NOT_FOUND)
+ return result;
+ }
+ }
+
+ return VALUE_NOT_FOUND;
+}
+
+gboolean
+hippo_canvas_style_get_length (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ gdouble *length)
+{
+ GetFromTermResult result = get_length_internal(style, property_name, NULL, length);
+ if (result == VALUE_FOUND)
+ return TRUE;
+ else if (result == VALUE_INHERIT)
+ inherit = TRUE;
+
+ if (inherit && style->parent_style &&
+ hippo_canvas_style_get_length(style->parent_style, property_name, inherit, length))
+ return TRUE;
+ else
+ return FALSE;
+}
+
+static void
+do_border_property(HippoCanvasStyle *style,
+ CRDeclaration *decl)
+{
+ const char *property_name = decl->property->stryng->str + 6; /* Skip 'border' */
+ HippoCanvasSide side = (HippoCanvasSide)-1;
+ guint32 color;
+ gboolean color_set = FALSE;
+ double width;
+ gboolean width_set = FALSE;
+ int j;
+
+ if (g_str_has_prefix(property_name, "-left")) {
+ side = HIPPO_CANVAS_SIDE_LEFT;
+ property_name += 5;
+ } else if (g_str_has_prefix(property_name, "-right")) {
+ side = HIPPO_CANVAS_SIDE_RIGHT;
+ property_name += 6;
+ } else if (g_str_has_prefix(property_name, "-top")) {
+ side = HIPPO_CANVAS_SIDE_TOP;
+ property_name += 4;
+ } else if (g_str_has_prefix(property_name, "-bottom")) {
+ side = HIPPO_CANVAS_SIDE_BOTTOM;
+ property_name += 7;
+ }
+
+ if (strcmp(property_name, "") == 0) {
+ /* Set value for width/color/style in any order */
+ CRTerm *term;
+
+ for (term = decl->value; term; term = term->next) {
+ GetFromTermResult result;
+
+ if (term->type == TERM_IDENT) {
+ const char *ident = term->content.str->stryng->str;
+ if (strcmp(ident, "none") == 0 || strcmp(ident, "hidden") == 0) {
+ width = 0.;
+ continue;
+ } else if (strcmp(ident, "solid") == 0) {
+ /* The only thing we support */
+ continue;
+ } else if (strcmp(ident, "dotted") == 0 ||
+ strcmp(ident, "dashed") == 0 ||
+ strcmp(ident, "solid") == 0 ||
+ strcmp(ident, "double") == 0 ||
+ strcmp(ident, "groove") == 0 ||
+ strcmp(ident, "ridge") == 0 ||
+ strcmp(ident, "inset") == 0 ||
+ strcmp(ident, "outset") == 0) {
+ /* Treat the same as solid */
+ continue;
}
- desc = pango_font_description_from_string(no_px ? no_px : s);
- g_free(no_px);
- if (desc == NULL) {
- g_warning("Failed to parse font description string '%s'", s);
- } else {
- if (absolute >= 0) {
- pango_font_description_set_absolute_size(desc, absolute * PANGO_SCALE);
- }
+
+ /* Presumably a color, fall through */
+ }
+
+ if (term->type == TERM_NUMBER) {
+ result = get_length_from_term(style, term, FALSE, &width);
+ if (result != VALUE_NOT_FOUND) {
+ width_set = result == VALUE_FOUND;
+ continue;
+ }
+ }
+
+ result = get_color_from_term(style, term, &color);
+ if (result != VALUE_NOT_FOUND) {
+ color_set = result == VALUE_FOUND;
+ continue;
+ }
+ }
+
+ } else if (strcmp(property_name, "-color") == 0) {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (get_color_from_term(style, decl->value, &color) == VALUE_FOUND) { /* Ignore inherit */
+ color_set = TRUE;
+ }
+ } else if (strcmp(property_name, "-width") == 0) {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (get_length_from_term(style, decl->value, FALSE, &width) == VALUE_FOUND) { /* Ignore inherit */
+ width_set = TRUE;
+ }
+ }
+
+ if (side == (HippoCanvasSide)-1) {
+ for (j = 0; j < 4; j++) {
+ if (color_set)
+ style->border_color[j] = color;
+ if (width_set)
+ style->border_width[j] = width;
+ }
+ } else {
+ if (color_set)
+ style->border_color[side] = color;
+ if (width_set)
+ style->border_width[side] = width;
+ }
+}
+
+static void
+do_padding_property_term(HippoCanvasStyle *style,
+ CRTerm *term,
+ gboolean left,
+ gboolean right,
+ gboolean top,
+ gboolean bottom)
+{
+ gdouble value;
+
+ if (get_length_from_term(style, term, FALSE, &value) != VALUE_FOUND)
+ return;
+
+ if (left)
+ style->padding[HIPPO_CANVAS_SIDE_LEFT] = value;
+ if (right)
+ style->padding[HIPPO_CANVAS_SIDE_RIGHT] = value;
+ if (top)
+ style->padding[HIPPO_CANVAS_SIDE_TOP] = value;
+ if (bottom)
+ style->padding[HIPPO_CANVAS_SIDE_BOTTOM] = value;
+}
+
+static void
+do_padding_property(HippoCanvasStyle *style,
+ CRDeclaration *decl)
+{
+ const char *property_name = decl->property->stryng->str + 7; /* Skip 'padding' */
- if ((pango_font_description_get_set_fields(desc) & PANGO_FONT_MASK_SIZE) != 0 &&
- pango_font_description_get_size(desc) <= 0) {
- g_warning("font size set to 0, not going to work well");
+ if (strcmp(property_name, "") == 0) {
+ /* Slight deviation ... if we don't understand some of the terms and understand others,
+ * then we set the ones we understand and ignore the others instead of ignoring the
+ * whole thing
+ */
+ if (decl->value == NULL) /* 0 values */
+ return;
+ else if (decl->value->next == NULL) { /* 1 value */
+ do_padding_property_term(style, decl->value, TRUE, TRUE, TRUE, TRUE); /* left/right/top/bottom */
+ return;
+ } else if (decl->value->next->next == NULL) { /* 2 values */
+ do_padding_property_term(style, decl->value, FALSE, FALSE, TRUE, TRUE); /* top/bottom */
+ do_padding_property_term(style, decl->value->next, TRUE, TRUE, FALSE, FALSE); /* left/right */
+ } else if (decl->value->next->next->next == NULL) { /* 3 values */
+ do_padding_property_term(style, decl->value, FALSE, FALSE, TRUE, FALSE); /* top */
+ do_padding_property_term(style, decl->value->next, TRUE, TRUE, FALSE, FALSE); /* left/right */
+ do_padding_property_term(style, decl->value->next->next, FALSE, FALSE, FALSE, TRUE); /* bottom */
+ } else if (decl->value->next->next->next == NULL) { /* 4 values */
+ do_padding_property_term(style, decl->value, FALSE, FALSE, TRUE, FALSE);
+ do_padding_property_term(style, decl->value->next, FALSE, TRUE, FALSE, FALSE); /* left */
+ do_padding_property_term(style, decl->value->next->next, FALSE, FALSE, FALSE, TRUE);
+ do_padding_property_term(style, decl->value->next->next->next, TRUE, FALSE, FALSE, TRUE); /* left */
+ } else {
+ g_warning("Too many values for padding property");
+ return;
+ }
+ } else {
+ if (decl->value == NULL || decl->value->next != NULL)
+ return;
+
+ if (strcmp(property_name, "-left") == 0) {
+ do_padding_property_term(style, decl->value, TRUE, FALSE, FALSE, FALSE);
+ } else if (strcmp(property_name, "-right") == 0) {
+ do_padding_property_term(style, decl->value, FALSE, TRUE, FALSE, FALSE);
+ } else if (strcmp(property_name, "-top") == 0) {
+ do_padding_property_term(style, decl->value, FALSE, FALSE, TRUE, FALSE);
+ } else if (strcmp(property_name, "-bottom") == 0) {
+ do_padding_property_term(style, decl->value, FALSE, FALSE, FALSE, TRUE);
+ }
+ }
+}
+
+static void
+ensure_borders(HippoCanvasStyle *style)
+{
+ int i, j;
+
+ if (style->borders_computed)
+ return;
+
+ style->borders_computed = TRUE;
+
+ ensure_properties(style);
+
+ for (j = 0; j < 4; j++) {
+ style->border_width[j] = 0;
+ style->border_color[j] = 0x00000000;
+ }
+
+ for (i = 0; i < style->n_properties; i++) {
+ CRDeclaration *decl = style->properties[i];
+ const char *property_name = decl->property->stryng->str;
+
+ if (g_str_has_prefix(property_name, "border")) {
+ do_border_property(style, decl);
+ } else if (g_str_has_prefix(property_name, "padding")) {
+ do_padding_property(style, decl);
+ }
+ }
+}
+
+double
+hippo_canvas_style_get_border_width(HippoCanvasStyle *style,
+ HippoCanvasSide side)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), 0.);
+ g_return_val_if_fail(side >= HIPPO_CANVAS_SIDE_LEFT && side <= HIPPO_CANVAS_SIDE_BOTTOM, 0.);
+
+ ensure_borders(style);
+
+ return style->border_width[side];
+}
+
+static GetFromTermResult
+get_background_color_from_term(HippoCanvasStyle *style,
+ CRTerm *term,
+ guint32 *color)
+{
+ GetFromTermResult result = get_color_from_term(style, term, color);
+ if (result == VALUE_NOT_FOUND) {
+ if (term->type == TERM_IDENT &&
+ strcmp(term->content.str->stryng->str, "transparent") == 0)
+ {
+ *color = 0x00000000;
+ return VALUE_FOUND;
+ }
+ }
+
+ return result;
+}
+
+guint32
+hippo_canvas_style_get_background_color (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), 0);
+
+ if (!style->background_computed) {
+ int i;
+
+ style->background_computed = TRUE;
+ style->background_color = 0x00000000; /* Transparent */
+
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
+ const char *property_name = decl->property->stryng->str;
+
+ if (!g_str_has_prefix(property_name, "background"))
+ continue;
+
+ if (strcmp(property_name, "") == 0) {
+ /* We're very liberal here ... if any term in the expression we take it, and
+ * we ignore the rest. The actual specification is:
+ *
+ * background: [<'background-color'> || <'background-image'> || <'background-repeat'> || <'background-attachment'> || <'background-position'>] | inherit
+ */
+
+ CRTerm *term;
+ for (term = decl->value; term; term = term->next) {
+ GetFromTermResult result = get_background_color_from_term(style, term, &style->background_color);
+ if (result == VALUE_FOUND) {
+ return style->background_color;
+ } else if (result == VALUE_INHERIT) {
+ if (style->parent_style)
+ style->background_color = hippo_canvas_style_get_background_color(style->parent_style);
+
+ return style->background_color;
}
}
- } else {
- desc = NULL;
+
+ } else if (strcmp(property_name, "-color") == 0) {
+ GetFromTermResult result;
+
+ if (decl->value == NULL || decl->value->next != NULL)
+ continue;
+
+ result = get_background_color_from_term(style, decl->value, &style->background_color);
+ if (result == VALUE_FOUND) {
+ return style->background_color;
+ } else if (result == VALUE_INHERIT) {
+ if (style->parent_style)
+ style->background_color = hippo_canvas_style_get_background_color(style->parent_style);
+
+ return style->background_color;
+ }
}
+ }
+ }
+
+ return style->background_color;
+}
+guint32
+hippo_canvas_style_get_foreground_color (HippoCanvasStyle *style)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), 0);
+
+ if (!style->foreground_computed) {
+ int i;
+
+ style->foreground_computed = TRUE;
+
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
- g_object_set(object, "font-desc", desc, NULL);
- if (desc)
- pango_font_description_free(desc);
- }
- break;
- case PROP_FONT_DESC:
- {
- PangoFontDescription *desc = g_value_get_boxed(value);
+ if (strcmp(decl->property->stryng->str, "color") == 0) {
+ GetFromTermResult result = get_color_from_term(style, decl->value, &style->foreground_color);
+ if (result == VALUE_FOUND) {
+ return style->foreground_color;
+ } else if (result == VALUE_INHERIT) {
+ if (style->parent_style) {
+ style->foreground_color = hippo_canvas_style_get_foreground_color(style->parent_style);
+ return style->foreground_color;
+ }
- if (!(desc == NULL && style->font_desc == NULL)) {
- if (style->font_desc) {
- pango_font_description_free(style->font_desc);
- style->font_desc = NULL;
+ break;
}
- if (desc != NULL) {
- style->font_desc = pango_font_description_copy(desc);
+ }
+ }
+
+ style->foreground_color = hippo_canvas_context_get_color(style->context, HIPPO_STOCK_COLOR_FG);
+ }
+
+ return style->foreground_color;
+
+}
+
+guint32
+hippo_canvas_style_get_border_color(HippoCanvasStyle *style,
+ HippoCanvasSide side)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), 0);
+ g_return_val_if_fail(side >= HIPPO_CANVAS_SIDE_LEFT && side <= HIPPO_CANVAS_SIDE_BOTTOM, 0.);
+
+ ensure_borders(style);
+
+ return style->border_color[side];
+}
+
+double
+hippo_canvas_style_get_padding(HippoCanvasStyle *style,
+ HippoCanvasSide side)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), 0.);
+ g_return_val_if_fail(side >= HIPPO_CANVAS_SIDE_LEFT && side <= HIPPO_CANVAS_SIDE_BOTTOM, 0.);
+
+ ensure_borders(style);
+
+ return style->padding[side];
+}
+
+HippoTextDecoration
+hippo_canvas_style_get_text_decoration (HippoCanvasStyle *style)
+{
+ int i;
+
+ ensure_properties(style);
+
+ for (i = style->n_properties - 1; i >= 0; i--) {
+ CRDeclaration *decl = style->properties[i];
+
+ if (strcmp(decl->property->stryng->str, "text-decoration") == 0) {
+ CRTerm *term = decl->value;
+ HippoTextDecoration decoration = 0;
+
+ /* Specification is none | [ underline || overline || line-through || blink ] | inherit
+ *
+ * We're a bit more liberal, and for example treat 'underline none' as the same as
+ * none.
+ */
+ for (; term; term = term->next) {
+ if (term->type != TERM_IDENT)
+ goto next_decl;
+
+ if (strcmp(term->content.str->stryng->str, "none") == 0) {
+ return 0;
+ } else if (strcmp(term->content.str->stryng->str, "inherit") == 0) {
+ if (style->parent_style)
+ return hippo_canvas_style_get_text_decoration(style->parent_style);
+ } else if (strcmp(term->content.str->stryng->str, "underline") == 0) {
+ decoration |= HIPPO_TEXT_DECORATION_UNDERLINE;
+ } else if (strcmp(term->content.str->stryng->str, "overline") == 0) {
+ decoration |= HIPPO_TEXT_DECORATION_OVERLINE;
+ } else if (strcmp(term->content.str->stryng->str, "line-through") == 0) {
+ decoration |= HIPPO_TEXT_DECORATION_LINE_THROUGH;
+ } else if (strcmp(term->content.str->stryng->str, "blink") == 0) {
+ decoration |= HIPPO_TEXT_DECORATION_BLINK;
+ } else {
+ goto next_decl;
}
}
+
+ return decoration;
}
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
+
+ next_decl:
+ ;
}
+
+ return 0;
}
-static void
-hippo_canvas_style_get_property(GObject *object,
- guint prop_id,
- GValue *value,
- GParamSpec *pspec)
+static gboolean
+font_family_from_terms(CRTerm *term,
+ char **family)
{
- HippoCanvasStyle *style;
+ GString *family_string;
+ gboolean result = FALSE;
+ gboolean last_was_quoted = FALSE;
+
+ if (!term)
+ return FALSE;
- style = HIPPO_CANVAS_STYLE (object);
+ family_string = g_string_new(NULL);
- switch (prop_id) {
- case PROP_COLOR:
- g_value_set_uint(value, style->color_rgba);
- break;
- case PROP_COLOR_SET:
- g_value_set_boolean(value, style->color_set);
- break;
- case PROP_FONT:
- {
- char *s;
- if (style->font_desc)
- s = pango_font_description_to_string(style->font_desc);
- else
- s = NULL;
- g_value_take_string(value, s);
+ while (term) {
+ if (term->type != TERM_STRING && term->type != TERM_IDENT) {
+ goto out;
}
- break;
- case PROP_FONT_DESC:
- g_value_set_boxed(value, style->font_desc);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
- break;
+
+ if (family_string->len > 0) {
+ if (term->the_operator != COMMA && term->the_operator != NO_OP)
+ goto out;
+ /* Can concetenate to bare words, but not two quoted strings */
+ if ((term->the_operator == NO_OP && last_was_quoted) || term->type == TERM_STRING)
+ goto out;
+
+ if (term->the_operator == NO_OP) {
+ g_string_append(family_string, " ");
+ } else {
+ g_string_append(family_string, ", ");
+ }
+ } else {
+ if (term->the_operator != NO_OP)
+ goto out;
+ }
+
+ g_string_append(family_string, term->content.str->stryng->str);
+
+ term = term->next;
+ }
+
+ result = TRUE;
+
+ out:
+ if (result) {
+ *family = g_string_free(family_string, FALSE);
+ return TRUE;
+ } else {
+ *family = g_string_free(family_string, TRUE);
+ return FALSE;
}
}
-void
-hippo_canvas_style_affect_color(HippoCanvasStyle *style,
- guint32 *color_rgba_p)
+/* In points */
+static int font_sizes[] = {
+ 6 * 1024, /* xx-small */
+ 8 * 1024, /* x-small */
+ 10 * 1024, /* small */
+ 12 * 1024, /* medium */
+ 16 * 1024, /* large */
+ 20 * 1024, /* x-large */
+ 24 * 1024, /* xx-large */
+};
+
+static gboolean
+font_size_from_term(HippoCanvasStyle *style,
+ CRTerm *term,
+ double *size)
{
- if (!style->color_set)
- return;
+ if (term->type == TERM_IDENT) {
+ double resolution = hippo_canvas_context_get_resolution(style->context);
+ /* We work in integers to avoid double comparisons when converting back
+ * from a size in pixels to a logical size.
+ */
+ int size_points = (int)(0.5 + *size * (72. / resolution));
+
+ if (strcmp(term->content.str->stryng->str, "xx-small") == 0) {
+ size_points = font_sizes[0];
+ } else if (strcmp(term->content.str->stryng->str, "x-small") == 0) {
+ size_points = font_sizes[1];
+ } else if (strcmp(term->content.str->stryng->str, "small") == 0) {
+ size_points = font_sizes[2];
+ } else if (strcmp(term->content.str->stryng->str, "medium") == 0) {
+ size_points = font_sizes[3];
+ } else if (strcmp(term->content.str->stryng->str, "large") == 0) {
+ size_points = font_sizes[4];
+ } else if (strcmp(term->content.str->stryng->str, "x-large") == 0) {
+ size_points = font_sizes[5];
+ } else if (strcmp(term->content.str->stryng->str, "xx-large") == 0) {
+ size_points = font_sizes[6];
+ } else if (strcmp(term->content.str->stryng->str, "smaller") == 0) {
+ /* Find the standard size equal to or smaller than the current size */
+ int i = 0;
+
+ while (i <= 6 && font_sizes[i] < size_points)
+ i++;
+
+ if (i > 6) { /* original size greater than any standard size */
+ size_points = (int)(0.5 + size_points / 1.2);
+ } else {
+ /* Go one smaller than that, if possible */
+ if (i > 0)
+ i--;
- *color_rgba_p = style->color_rgba;
+ size_points = font_sizes[i];
+ }
+ } else if (strcmp(term->content.str->stryng->str, "larger") == 0) {
+ /* Find the standard size equal to or larger than the current size */
+ int i = 6;
+
+ while (i >= 0 && font_sizes[i] > size_points)
+ i--;
+
+ if (i < 0) /* original size smaller than any standard size */
+ i = 0;
+
+ /* Go one larger than that, if possible */
+ if (i < 6)
+ i++;
+
+ size_points = font_sizes[i];
+ } else {
+ return FALSE;
+ }
+
+ *size = size_points * (resolution / 72.);
+ return TRUE;
+
+ } else if (term->type == TERM_NUMBER && term->content.num->type == NUM_PERCENTAGE) {
+ *size *= term->content.num->val;
+ } else if (get_length_from_term(style, term, TRUE, size) == VALUE_FOUND) {
+ /* Convert from pixels to Pango units */
+ *size *= 1024;
+ return TRUE;
+ }
+
+ return FALSE;
}
-void
-hippo_canvas_style_affect_font_desc(HippoCanvasStyle *style,
- PangoFontDescription *font_desc)
+static gboolean
+font_weight_from_term(CRTerm *term,
+ PangoWeight *weight,
+ gboolean *weight_absolute)
{
- if (style->font_desc == NULL)
- return;
+ if (term->type == TERM_NUMBER) {
+ int weight_int;
+
+ /* The spec only allows numeric weights from 100-900, though Pango
+ * will handle any number. We just let anything through.
+ */
+ if (term->content.num->type != NUM_GENERIC)
+ return FALSE;
+
+ weight_int = (int)(term->content.num->val + 0.5);
+
+ *weight = weight_int;
+ *weight_absolute = TRUE;
+
+ } else if (term->type == TERM_IDENT) {
+ /* FIXME: handle INHERIT */
+
+ if (strcmp(term->content.str->stryng->str, "bold") == 0) {
+ *weight = PANGO_WEIGHT_BOLD;
+ *weight_absolute = TRUE;
+ } else if (strcmp(term->content.str->stryng->str, "normal") == 0) {
+ *weight = PANGO_WEIGHT_NORMAL;
+ *weight_absolute = TRUE;
+ } else if (strcmp(term->content.str->stryng->str, "bolder") == 0) {
+ *weight = PANGO_WEIGHT_BOLD;
+ *weight_absolute = FALSE;
+ } else if (strcmp(term->content.str->stryng->str, "lighter") == 0) {
+ *weight = PANGO_WEIGHT_LIGHT;
+ *weight_absolute = FALSE;
+ } else {
+ return FALSE;
+ }
+
+ } else {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+font_style_from_term(CRTerm *term,
+ PangoStyle *style)
+{
+ if (term->type != TERM_IDENT)
+ return FALSE;
+
+ /* FIXME: handle INHERIT */
+
+ if (strcmp(term->content.str->stryng->str, "normal") == 0)
+ *style = PANGO_STYLE_NORMAL;
+ else if (strcmp(term->content.str->stryng->str, "oblique") == 0)
+ *style = PANGO_STYLE_OBLIQUE;
+ else if (strcmp(term->content.str->stryng->str, "italic") == 0)
+ *style = PANGO_STYLE_ITALIC;
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+static gboolean
+font_variant_from_term(CRTerm *term,
+ PangoVariant *variant)
+{
+ if (term->type != TERM_IDENT)
+ return FALSE;
+
+ /* FIXME: handle INHERIT */
+
+ if (strcmp(term->content.str->stryng->str, "normal") == 0)
+ *variant = PANGO_VARIANT_NORMAL;
+ else if (strcmp(term->content.str->stryng->str, "small-caps") == 0)
+ *variant = PANGO_VARIANT_SMALL_CAPS;
+ else
+ return FALSE;
+
+ return TRUE;
+}
+
+PangoFontDescription *
+hippo_canvas_style_get_font (HippoCanvasStyle *style)
+{
+ PangoStyle font_style;
+ gboolean font_style_set = FALSE;
+ PangoVariant variant;
+ gboolean variant_set = FALSE;
+ PangoWeight weight;
+ gboolean weight_absolute;
+ gboolean weight_set = FALSE;
+ double parent_size;
+ double size = 0.; /* Suppress warning */
+ gboolean size_set = FALSE;
+ char *family = NULL;
+ int i;
+
+ if (style->font_desc)
+ return style->font_desc;
+
+ style->font_desc = pango_font_description_copy(get_parent_font(style));
+ parent_size = pango_font_description_get_size(style->font_desc);
+ if (!pango_font_description_get_size_is_absolute(style->font_desc)) {
+ double resolution = hippo_canvas_context_get_resolution(style->context);
+ parent_size *= (resolution / 72.);
+ }
+
+ ensure_properties(style);
+
+ for (i = 0; i < style->n_properties; i++) {
+ CRDeclaration *decl = style->properties[i];
+
+ if (strcmp(decl->property->stryng->str, "font") == 0) {
+ PangoStyle tmp_style = PANGO_STYLE_NORMAL;
+ PangoVariant tmp_variant = PANGO_VARIANT_NORMAL;
+ PangoWeight tmp_weight = PANGO_WEIGHT_NORMAL;
+ gboolean tmp_weight_absolute = FALSE;
+ double tmp_size;
+ CRTerm *term = decl->value;
+
+ /* A font specification starts with style/variant/weight
+ * in any order. Each is allowed to be specified only once,
+ * but we don't enforce that.
+ */
+ for (; term; term = term->next) {
+ if (font_style_from_term(term, &tmp_style))
+ ;
+ else if (font_variant_from_term(term, &tmp_variant))
+ ;
+ else if (font_weight_from_term(term, &tmp_weight, &tmp_weight_absolute))
+ ;
+ else
+ break;
+ }
+
+ /* The size is mandatory */
+
+ if (term == NULL || term->type != TERM_NUMBER) {
+ g_warning("Size missing from font property");
+ continue;
+ }
+
+ tmp_size = parent_size;
+ if (!font_size_from_term(style, term, &tmp_size)) {
+ g_warning("Couldn't parse size in font property");
+ continue;
+ }
+
+ if (term != NULL && term->type && TERM_NUMBER && term->the_operator == DIVIDE) {
+ /* Ignore line-height specification */
+ term = term->next;
+ }
+
+ /* the font family is mandatory - it is a comma-separated list of
+ * names.
+ */
+ if (!font_family_from_terms(term, &family)) {
+ g_warning("Couldn't parse family in font property");
+ continue;
+ }
+
+ font_style = tmp_style;
+ font_style_set = TRUE;
+ weight = tmp_weight;
+ weight_absolute = tmp_weight_absolute;
+ weight_set = TRUE;
+ variant = tmp_variant;
+ variant_set = TRUE;
+
+ size = tmp_size;
+ size_set = TRUE;
+
+ } else if (strcmp(decl->property->stryng->str, "family") == 0) {
+ if (!font_family_from_terms(decl->value, &family)) {
+ g_warning("Couldn't parse family in font property");
+ continue;
+ }
+ } else if (strcmp(decl->property->stryng->str, "font-weight") == 0) {
+ if (decl->value == NULL || decl->value->next != NULL)
+ continue;
+
+ if (font_weight_from_term(decl->value, &weight, &weight_absolute))
+ weight_set = TRUE;
+ } else if (strcmp(decl->property->stryng->str, "font-style") == 0) {
+ if (decl->value == NULL || decl->value->next != NULL)
+ continue;
+
+ if (font_style_from_term(decl->value, &font_style))
+ font_style_set = TRUE;
+ } else if (strcmp(decl->property->stryng->str, "font-variant") == 0) {
+ if (decl->value == NULL || decl->value->next != NULL)
+ continue;
+
+ if (font_variant_from_term(decl->value, &variant))
+ variant_set = TRUE;
+ } else if (strcmp(decl->property->stryng->str, "font-size") == 0) {
+ gdouble tmp_size;
+ if (decl->value == NULL || decl->value->next != NULL)
+ continue;
+
+ tmp_size = parent_size;
+ if (font_size_from_term(style, decl->value, &tmp_size)) {
+ size = tmp_size;
+ size_set = TRUE;
+ }
+ }
+ }
+
+ if (family)
+ pango_font_description_set_family(style->font_desc, family);
+
+ if (size_set)
+ pango_font_description_set_absolute_size(style->font_desc, size);
+
+ if (weight_set) {
+ if (!weight_absolute) {
+ /* bolder/lighter are supposed to switch between available styles, but with
+ * font substitution, that gets to be a pretty fuzzy concept. So we use
+ * a fixed step of 200. (The spec says 100, but that might not take us from
+ * normal to bold.
+ */
+
+ PangoWeight old_weight = pango_font_description_get_weight(style->font_desc);
+ if (weight == PANGO_WEIGHT_BOLD)
+ weight = old_weight + 200;
+ else
+ weight = old_weight - 200;
+
+ if (weight < 100)
+ weight = 100;
+ if (weight > 900)
+ weight = 900;
+ }
+
+ pango_font_description_set_weight(style->font_desc, weight);
+ }
+
+ if (font_style_set)
+ pango_font_description_set_style(style->font_desc, font_style);
+ if (variant_set)
+ pango_font_description_set_variant(style->font_desc, variant);
+
+ return style->font_desc;
+}
+
+gboolean
+hippo_canvas_style_paint (HippoCanvasStyle *style,
+ cairo_t *cr,
+ const char *name,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ HippoCanvasThemeEngine *theme_engine;
+
+ g_return_val_if_fail(HIPPO_IS_CANVAS_STYLE(style), FALSE);
+
+ if (!style->theme)
+ return FALSE;
- pango_font_description_merge(font_desc,
- style->font_desc,
- TRUE); /* TRUE = overwrite anything in the target */
+ theme_engine = hippo_canvas_theme_get_theme_engine(style->theme);
+ if (theme_engine == NULL)
+ return FALSE;
+
+ return hippo_canvas_theme_engine_paint(theme_engine,
+ style, cr, name,
+ x, y, width, height);
}
Modified: trunk/common/hippo/hippo-canvas-style.h
==============================================================================
--- trunk/common/hippo/hippo-canvas-style.h (original)
+++ trunk/common/hippo/hippo-canvas-style.h Mon Mar 24 19:05:00 2008
@@ -3,20 +3,9 @@
#define __HIPPO_CANVAS_STYLE_H__
#include "hippo-canvas-context.h"
-#include "hippo-canvas-box.h"
-
-/* HippoCanvasStyle contains styles that are inherited by children
- * from their container in a tree of canvas items.
- *
- * Right now this is an implementation detail of HippoCanvasBox, not
- * exposed in the HippoCanvasItem/HippoCanvasContext interfaces.
- */
G_BEGIN_DECLS
-#define HIPPO_CANVAS_DEFAULT_COLOR 0x000000ff
-#define HIPPO_CANVAS_DEFAULT_BACKGROUND_COLOR 0xffffff00
-
#define HIPPO_TYPE_CANVAS_STYLE (hippo_canvas_style_get_type ())
#define HIPPO_CANVAS_STYLE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), HIPPO_TYPE_CANVAS_STYLE, HippoCanvasStyle))
#define HIPPO_CANVAS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HIPPO_TYPE_CANVAS_STYLE, HippoCanvasStyleClass))
@@ -24,12 +13,101 @@
#define HIPPO_IS_CANVAS_STYLE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HIPPO_TYPE_CANVAS_STYLE))
#define HIPPO_CANVAS_STYLE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HIPPO_TYPE_CANVAS_STYLE, HippoCanvasStyleClass))
+typedef enum {
+ HIPPO_CANVAS_LINK_NONE,
+ HIPPO_CANVAS_LINK_LINK,
+ HIPPO_CANVAS_LINK_VISITED
+} HippoCanvasLinkType;
+
+typedef enum {
+ HIPPO_CANVAS_SIDE_LEFT,
+ HIPPO_CANVAS_SIDE_RIGHT,
+ HIPPO_CANVAS_SIDE_TOP,
+ HIPPO_CANVAS_SIDE_BOTTOM
+} HippoCanvasSide;
+
+/* These are the CSS values; that doesn't mean we have to implement blink... */
+typedef enum {
+ HIPPO_TEXT_DECORATION_UNDERLINE = 1 << 0,
+ HIPPO_TEXT_DECORATION_OVERLINE = 1 << 1,
+ HIPPO_TEXT_DECORATION_LINE_THROUGH = 1 << 2,
+ HIPPO_TEXT_DECORATION_BLINK = 1 << 3
+} HippoTextDecoration;
+
GType hippo_canvas_style_get_type (void) G_GNUC_CONST;
-void hippo_canvas_style_affect_color (HippoCanvasStyle *style,
- guint32 *color_rgba_p);
-void hippo_canvas_style_affect_font_desc (HippoCanvasStyle *style,
- PangoFontDescription *font_desc);
+/* An element_type of G_TYPE_NONE means this style was created for the canvas root
+ * element and matches a selector element name of 'canvas'
+ */
+HippoCanvasStyle *hippo_canvas_style_new (HippoCanvasContext *context,
+ HippoCanvasStyle *parent_style, /* can be null */
+ HippoCanvasTheme *theme, /* can be null */
+ GType element_type,
+ const char *element_id,
+ const char *element_class);
+
+void hippo_canvas_style_set_link_type (HippoCanvasStyle *style,
+ HippoCanvasLinkType link_type);
+HippoCanvasLinkType hippo_canvas_style_get_link_type (HippoCanvasStyle *style);
+
+HippoCanvasStyle *hippo_canvas_style_get_parent (HippoCanvasStyle *style);
+
+HippoCanvasTheme *hippo_canvas_style_get_theme (HippoCanvasStyle *style);
+
+GType hippo_canvas_style_get_element_type (HippoCanvasStyle *style);
+const char *hippo_canvas_style_get_element_id (HippoCanvasStyle *style);
+const char *hippo_canvas_style_get_element_class (HippoCanvasStyle *style);
+
+/* Generic getters ... these are not cached so are less efficient. The other
+ * reason for adding the more specific version is that we can handle the
+ * details of the actual CSS rules, which can be complicated, especially
+ * for fonts
+ */
+gboolean hippo_canvas_style_get_color (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ guint32 *color);
+
+gboolean hippo_canvas_style_get_double (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ double *value);
+
+/* The length here is already resolved to pixels
+ */
+gboolean hippo_canvas_style_get_length (HippoCanvasStyle *style,
+ const char *property_name,
+ gboolean inherit,
+ gdouble *length);
+
+/* Specific getters for particular properties: cached
+ */
+guint32 hippo_canvas_style_get_background_color (HippoCanvasStyle *style);
+guint32 hippo_canvas_style_get_foreground_color (HippoCanvasStyle *style);
+
+double hippo_canvas_style_get_border_width (HippoCanvasStyle *style,
+ HippoCanvasSide side);
+guint32 hippo_canvas_style_get_border_color(HippoCanvasStyle *style,
+ HippoCanvasSide side);
+double hippo_canvas_style_get_padding (HippoCanvasStyle *style,
+ HippoCanvasSide side);
+
+HippoTextDecoration hippo_canvas_style_get_text_decoration (HippoCanvasStyle *style);
+
+/* Font rule processing is pretty complicated, so we just hardcode it
+ * under the standard font/font-family/font-size/etc names. This means
+ * you can't have multiple separate styled fonts for a single item,
+ * but that should be OK.
+ */
+PangoFontDescription *hippo_canvas_style_get_font (HippoCanvasStyle *style);
+
+gboolean hippo_canvas_style_paint (HippoCanvasStyle *style,
+ cairo_t *cr,
+ const char *name,
+ double x,
+ double y,
+ double width,
+ double height);
G_END_DECLS
Modified: trunk/common/hippo/hippo-canvas-text.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-text.c (original)
+++ trunk/common/hippo/hippo-canvas-text.c Mon Mar 24 19:05:00 2008
@@ -1,6 +1,7 @@
/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
#include "hippo-canvas-type-builtins.h"
#include "hippo-canvas-internal.h"
+#include "hippo-canvas-style.h"
#include "hippo-canvas-text.h"
#include "hippo-canvas-box.h"
#include <pango/pangocairo.h>
@@ -60,8 +61,6 @@
PROP_SIZE_MODE
};
-#define DEFAULT_FOREGROUND 0x000000ff
-
G_DEFINE_TYPE_WITH_CODE(HippoCanvasText, hippo_canvas_text, HIPPO_TYPE_CANVAS_BOX,
G_IMPLEMENT_INTERFACE(HIPPO_TYPE_CANVAS_ITEM, hippo_canvas_text_iface_init));
@@ -373,51 +372,33 @@
create_layout(HippoCanvasText *text,
int allocation_width)
{
- HippoCanvasContext *context;
+ HippoCanvasBox *box = HIPPO_CANVAS_BOX(text);
PangoLayout *layout;
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(text));
- /* Note that our context is *ourselves* not box->context i.e. we want
- * our own style, etc. to affect what we render. Our context methods
- * will chain up as needed.
- */
- context = HIPPO_CANVAS_CONTEXT(text);
-
- g_return_val_if_fail(context != NULL, NULL);
+ g_return_val_if_fail(box->context != NULL, NULL);
- layout = hippo_canvas_context_create_layout(context);
-
- {
- const PangoFontDescription *old;
- PangoFontDescription *composite;
-
- composite = pango_font_description_new();
-
- old = pango_layout_get_font_description(layout);
- /* if no font desc is set on the layout, the layout uses the one
- * from the context, so emulate that here.
- */
- if (old == NULL)
- old = pango_context_get_font_description(pango_layout_get_context(layout));
-
- if (old != NULL)
- pango_font_description_merge(composite, old, TRUE);
+ layout = hippo_canvas_context_create_layout(box->context);
- hippo_canvas_context_affect_font_desc(context,
- composite);
-
- pango_layout_set_font_description(layout, composite);
-
- pango_font_description_free(composite);
+ if (box->font_desc) {
+ PangoFontDescription *merged = pango_font_description_copy(hippo_canvas_style_get_font(style));
+ pango_font_description_merge(merged, box->font_desc, TRUE);
+ pango_layout_set_font_description(layout, merged);
+ pango_font_description_free(merged);
+ } else {
+ pango_layout_set_font_description(layout, hippo_canvas_style_get_font(style));
}
{
PangoAttrList *attrs;
+ HippoTextDecoration decoration = hippo_canvas_style_get_text_decoration(style);
if (text->attributes)
attrs = pango_attr_list_copy(text->attributes);
else
attrs = pango_attr_list_new();
+
if (ABS(1.0 - text->font_scale) > .000001) {
PangoAttribute *attr = pango_attr_scale_new(text->font_scale);
attr->start_index = 0;
@@ -425,6 +406,20 @@
pango_attr_list_insert(attrs, attr);
}
+ if ((decoration & HIPPO_TEXT_DECORATION_UNDERLINE) != 0) {
+ PangoAttribute *attr = pango_attr_underline_new(TRUE);
+ attr->start_index = 0;
+ attr->end_index = G_MAXUINT;
+ pango_attr_list_insert(attrs, attr);
+ }
+
+ if ((decoration & HIPPO_TEXT_DECORATION_LINE_THROUGH) != 0) {
+ PangoAttribute *attr = pango_attr_strikethrough_new(TRUE);
+ attr->start_index = 0;
+ attr->end_index = G_MAXUINT;
+ pango_attr_list_insert(attrs, attr);
+ }
+
pango_layout_set_attributes(layout, attrs);
pango_attr_list_unref(attrs);
}
@@ -555,14 +550,14 @@
{
HippoCanvasText *text = HIPPO_CANVAS_TEXT(box);
guint32 color_rgba;
- HippoCanvasContext *context;
- /* note, we want to use _ourselves_ as context so we get our own style */
- context = HIPPO_CANVAS_CONTEXT(box);
-
- color_rgba = HIPPO_CANVAS_BOX_GET_CLASS(box)->default_color;
- hippo_canvas_context_affect_color(context, &color_rgba);
-
+ if (box->color_set) {
+ color_rgba = box->color_rgba;
+ } else {
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(text));
+ color_rgba = hippo_canvas_style_get_foreground_color(style);
+ }
+
/* It would seem more natural to compute whether we are ellipsized or
* not when we are allocated to some width, but we don't have a layout
* at that point. We could do it in get_content_height_request(), but
Added: trunk/common/hippo/hippo-canvas-theme-engine.c
==============================================================================
--- (empty file)
+++ trunk/common/hippo/hippo-canvas-theme-engine.c Mon Mar 24 19:05:00 2008
@@ -0,0 +1,62 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+#include <string.h>
+
+#include "hippo-canvas-theme-engine.h"
+
+static void hippo_canvas_item_base_init (void *klass);
+
+#if 0
+enum {
+ LAST_SIGNAL
+};
+
+static int signals[LAST_SIGNAL];
+#endif
+
+GType
+hippo_canvas_theme_engine_get_type(void)
+{
+ static GType type = 0;
+ if (type == 0) {
+ static const GTypeInfo info =
+ {
+ sizeof(HippoCanvasThemeEngineIface),
+ hippo_canvas_item_base_init,
+ NULL /* base_finalize */
+ };
+ type = g_type_register_static(G_TYPE_INTERFACE, "HippoCanvasThemeEngine",
+ &info, 0);
+
+ g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
+ }
+
+ return type;
+}
+
+static void
+hippo_canvas_item_base_init(void *klass)
+{
+ static gboolean initialized = FALSE;
+
+ if (!initialized) {
+ /* create signals in here */
+ }
+}
+
+gboolean
+hippo_canvas_theme_engine_paint (HippoCanvasThemeEngine *engine,
+ HippoCanvasStyle *style,
+ cairo_t *cr,
+ const char *name,
+ double x,
+ double y,
+ double width,
+ double height)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_THEME_ENGINE(engine), FALSE);
+
+ return HIPPO_CANVAS_THEME_ENGINE_GET_IFACE(engine)->paint(engine,
+ style, cr, name,
+ x, y, width, height);
+}
+
Added: trunk/common/hippo/hippo-canvas-theme-engine.h
==============================================================================
--- (empty file)
+++ trunk/common/hippo/hippo-canvas-theme-engine.h Mon Mar 24 19:05:00 2008
@@ -0,0 +1,46 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+#ifndef __HIPPO_CANVAS_THEME_ENGINE_H__
+#define __HIPPO_CANVAS_THEME_ENGINE_H__
+
+#include <cairo.h>
+#include <hippo/hippo-event.h>
+#include <hippo/hippo-graphics.h>
+#include <hippo/hippo-canvas-style.h>
+
+G_BEGIN_DECLS
+
+typedef struct _HippoCanvasThemeEngine HippoCanvasThemeEngine;
+typedef struct _HippoCanvasThemeEngineIface HippoCanvasThemeEngineIface;
+
+#define HIPPO_TYPE_CANVAS_THEME_ENGINE (hippo_canvas_theme_engine_get_type ())
+#define HIPPO_CANVAS_THEME_ENGINE(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), HIPPO_TYPE_CANVAS_THEME_ENGINE, HippoCanvasThemeEngine))
+#define HIPPO_IS_CANVAS_THEME_ENGINE(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), HIPPO_TYPE_CANVAS_THEME_ENGINE))
+#define HIPPO_CANVAS_THEME_ENGINE_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), HIPPO_TYPE_CANVAS_THEME_ENGINE, HippoCanvasThemeEngineIface))
+
+struct _HippoCanvasThemeEngineIface {
+ GTypeInterface base_iface;
+
+ gboolean (* paint) (HippoCanvasThemeEngine *engine,
+ HippoCanvasStyle *style,
+ cairo_t *cr,
+ const char *name,
+ double x,
+ double y,
+ double width,
+ double height);
+};
+
+GType hippo_canvas_theme_engine_get_type (void) G_GNUC_CONST;
+
+gboolean hippo_canvas_theme_engine_paint (HippoCanvasThemeEngine *engine,
+ HippoCanvasStyle *style,
+ cairo_t *cr,
+ const char *name,
+ double x,
+ double y,
+ double width,
+ double height);
+
+G_END_DECLS
+
+#endif /* __HIPPO_CANVAS_THEME_ENGINE_H__ */
Added: trunk/common/hippo/hippo-canvas-theme-internal.h
==============================================================================
--- (empty file)
+++ trunk/common/hippo/hippo-canvas-theme-internal.h Mon Mar 24 19:05:00 2008
@@ -0,0 +1,17 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+#ifndef __HIPPO_CANVAS_THEME_INTERNAL_H__
+#define __HIPPO_CANVAS_THEME_INTERNAL_H__
+
+#include <libcroco/libcroco.h>
+#include "hippo-canvas-theme.h"
+
+G_BEGIN_DECLS
+
+void _hippo_canvas_theme_get_matched_properties (HippoCanvasTheme *theme,
+ HippoCanvasStyle *style,
+ CRDeclaration ***properties,
+ int *n_properties);
+
+G_END_DECLS
+
+#endif /* __HIPPO_CANVAS_THEME_INTERNAL_H__ */
Added: trunk/common/hippo/hippo-canvas-theme.c
==============================================================================
--- (empty file)
+++ trunk/common/hippo/hippo-canvas-theme.c Mon Mar 24 19:05:00 2008
@@ -0,0 +1,937 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+
+/* This file started as a cut-and-paste of cr-sel-eng.c from libcroco.
+ *
+ * It has been:
+ * - Reformatted and otherwise edited to match our coding style
+ * - Switched from handling xmlNode to handling HippoStyle
+ * - Simplified by removing things that we don't need or that don't
+ * make sense in our context.
+ * - The code to get a list of matching properties works quite differently;
+ * we order things in priority order, but we don't actually try to
+ * coelesce properties with the same name.
+ */
+
+/*
+ * This file is part of The Croco Library
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 2.1 of the GNU Lesser General Public
+ * License as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser
+ * General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA
+ *
+ * Copyright (C) 2003-2004 Dodji Seketeli. All Rights Reserved.
+ */
+
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "hippo-canvas-internal.h"
+#include "hippo-canvas-style.h"
+#include "hippo-canvas-theme-internal.h"
+
+static GObject *hippo_canvas_theme_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties);
+
+static void hippo_canvas_theme_dispose (GObject *object);
+static void hippo_canvas_theme_finalize (GObject *object);
+
+static void hippo_canvas_theme_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec);
+static void hippo_canvas_theme_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec);
+
+#if 0
+enum {
+ LAST_SIGNAL
+};
+
+static int signals[LAST_SIGNAL];
+#endif
+
+struct _HippoCanvasTheme {
+ GObject parent;
+
+ HippoCanvasThemeEngine *theme_engine;
+
+ char *application_stylesheet;
+ char *default_stylesheet;
+ char *theme_stylesheet;
+
+ CRCascade *cascade;
+};
+
+struct _HippoCanvasThemeClass {
+ GObjectClass parent_class;
+
+};
+
+enum {
+ PROP_0,
+ PROP_THEME_ENGINE,
+ PROP_APPLICATION_STYLESHEET,
+ PROP_THEME_STYLESHEET,
+ PROP_DEFAULT_STYLESHEET
+};
+
+G_DEFINE_TYPE(HippoCanvasTheme, hippo_canvas_theme, G_TYPE_OBJECT)
+
+/* Quick strcmp. Test only for == 0 or != 0, not < 0 or > 0. */
+#define strqcmp(str,lit,lit_len) \
+ (strlen (str) != (lit_len) || memcmp (str, lit, lit_len))
+
+static void
+hippo_canvas_theme_init(HippoCanvasTheme *theme)
+{
+}
+
+static void
+hippo_canvas_theme_class_init(HippoCanvasThemeClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->constructor = hippo_canvas_theme_constructor;
+ object_class->dispose = hippo_canvas_theme_dispose;
+ object_class->finalize = hippo_canvas_theme_finalize;
+ object_class->set_property = hippo_canvas_theme_set_property;
+ object_class->get_property = hippo_canvas_theme_get_property;
+
+ /**
+ * HippoCanvasImage:theme-engine
+ *
+ * The theme engine object, used to draw control parts in a theme-specific manner.
+ */
+ g_object_class_install_property(object_class,
+ PROP_THEME_ENGINE,
+ g_param_spec_object("theme-engine",
+ _("Theme Engine"),
+ _("Theme engine object used to draw control parts"),
+ HIPPO_TYPE_CANVAS_THEME_ENGINE,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * HippoCanvasImage:application-stylesheet
+ *
+ * The highest priority stylesheet, representing application-specific
+ * styling; this is associated with the CSS "author" stylesheet.
+ */
+ g_object_class_install_property(object_class,
+ PROP_APPLICATION_STYLESHEET,
+ g_param_spec_string("application-stylesheet",
+ _("Application Stylesheet"),
+ _("Stylesheet with application-specific styling"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * HippoCanvasImage:theme-stylesheet
+ *
+ * The second priority stylesheet, representing theme-specific styling;
+ * this is associated with the CSS "user" stylesheet.
+ */
+ g_object_class_install_property(object_class,
+ PROP_THEME_STYLESHEET,
+ g_param_spec_string("theme-stylesheet",
+ _("Theme Stylesheet"),
+ _("Stylesheet with theme-specific styling"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ /**
+ * HippoCanvasImage:default-stylesheet
+ *
+ * The lowest priority stylesheet, representing global default
+ * styling; this is associated with the CSS "user agent" stylesheet.
+ */
+ g_object_class_install_property(object_class,
+ PROP_DEFAULT_STYLESHEET,
+ g_param_spec_string("default-stylesheet",
+ _("Default Stylesheet"),
+ _("Stylesheet with global default styling"),
+ NULL,
+ G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+}
+
+static CRStyleSheet *
+parse_stylesheet(const char *filename)
+{
+ enum CRStatus status;
+ CRStyleSheet *stylesheet;
+
+ if (filename == NULL)
+ return NULL;
+
+ status = cr_om_parser_simply_parse_file ((const guchar *)filename,
+ CR_UTF_8,
+ &stylesheet);
+
+ if (status != CR_OK) {
+ g_warning("Error parsing stylesheet '%s'", filename);
+ return NULL;
+ }
+
+ return stylesheet;
+}
+
+static GObject *
+hippo_canvas_theme_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ GObject *object;
+ HippoCanvasTheme *theme;
+
+ object = (*G_OBJECT_CLASS (hippo_canvas_theme_parent_class)->constructor) (type,
+ n_construct_properties,
+ construct_properties);
+ theme = HIPPO_CANVAS_THEME (object);
+
+ theme->cascade = cr_cascade_new(parse_stylesheet(theme->application_stylesheet),
+ parse_stylesheet(theme->theme_stylesheet),
+ parse_stylesheet(theme->default_stylesheet));
+
+ if (theme->cascade == NULL)
+ g_error("Out of memory when creating cascade object");
+
+ return object;
+}
+
+static void
+hippo_canvas_theme_dispose(GObject *object)
+{
+ /* HippoCanvasTheme *theme = HIPPO_CANVAS_THEME(object); */
+
+ G_OBJECT_CLASS(hippo_canvas_theme_parent_class)->dispose(object);
+}
+
+static void
+hippo_canvas_theme_finalize(GObject *object)
+{
+ HippoCanvasTheme *theme = HIPPO_CANVAS_THEME(object);
+
+ if (theme->theme_engine)
+ g_object_unref(theme->theme_engine);
+
+ g_free(theme->application_stylesheet);
+ g_free(theme->theme_stylesheet);
+ g_free(theme->default_stylesheet);
+
+ if (theme->cascade) {
+ cr_cascade_unref(theme->cascade);
+ theme->cascade = NULL;
+ }
+
+ G_OBJECT_CLASS(hippo_canvas_theme_parent_class)->finalize(object);
+}
+
+static void
+hippo_canvas_theme_set_property(GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ HippoCanvasTheme *theme = HIPPO_CANVAS_THEME(object);
+
+ switch (prop_id) {
+ case PROP_THEME_ENGINE:
+ {
+ HippoCanvasThemeEngine *theme_engine = g_value_get_object(value);
+
+ if (theme_engine != theme->theme_engine) {
+ if (theme->theme_engine)
+ g_object_unref(theme->theme_engine);
+ theme->theme_engine = theme_engine;
+ if (theme->theme_engine)
+ g_object_ref(theme->theme_engine);
+ }
+ }
+ break;
+ case PROP_APPLICATION_STYLESHEET:
+ {
+ const char *path = g_value_get_string(value);
+
+ if (path != theme->application_stylesheet) {
+ g_free(theme->application_stylesheet);
+ theme->application_stylesheet = g_strdup(path);
+ }
+
+ break;
+ }
+ case PROP_THEME_STYLESHEET:
+ {
+ const char *path = g_value_get_string(value);
+
+ if (path != theme->theme_stylesheet) {
+ g_free(theme->theme_stylesheet);
+ theme->theme_stylesheet = g_strdup(path);
+ }
+
+ break;
+ }
+ case PROP_DEFAULT_STYLESHEET:
+ {
+ const char *path = g_value_get_string(value);
+
+ if (path != theme->default_stylesheet) {
+ g_free(theme->default_stylesheet);
+ theme->default_stylesheet = g_strdup(path);
+ }
+
+ break;
+ }
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+hippo_canvas_theme_get_property(GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ HippoCanvasTheme *theme = HIPPO_CANVAS_THEME (object);
+
+ switch (prop_id) {
+ case PROP_THEME_ENGINE:
+ g_value_set_object(value, theme->theme_engine);
+ break;
+ case PROP_APPLICATION_STYLESHEET:
+ g_value_set_string(value, theme->application_stylesheet);
+ break;
+ case PROP_THEME_STYLESHEET:
+ g_value_set_string(value, theme->theme_stylesheet);
+ break;
+ case PROP_DEFAULT_STYLESHEET:
+ g_value_set_string(value, theme->default_stylesheet);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
+ break;
+ }
+}
+
+/**
+ * hippo_canvas_theme_new:
+ * @theme_engine: The theme engine object used for theme-specific drawing code, may be %NULL
+ * @application_stylesheet: The highest priority stylesheet, representing application-specific
+ * styling; this is associated with the CSS "author" stylesheet, may be %NULL
+ * @theme_stylesheet: The second priority stylesheet, representing theme-specific styling ;
+ * this is associated with the CSS "user" stylesheet, may be %NULL
+ * @default_stylesheet: The lowest priority stylesheet, representing global default styling;
+ * this is associated with the CSS "user agent" stylesheet, may be %NULL
+ *
+ * Return value: the newly created theme object
+ **/
+HippoCanvasTheme *
+hippo_canvas_theme_new (HippoCanvasThemeEngine *theme_engine,
+ const char *application_stylesheet,
+ const char *theme_stylesheet,
+ const char *default_stylesheet)
+{
+ HippoCanvasTheme *theme = g_object_new(HIPPO_TYPE_CANVAS_THEME,
+ "theme-engine", theme_engine,
+ "application-stylesheet", application_stylesheet,
+ "theme-stylesheet", theme_stylesheet,
+ "default-stylesheet", default_stylesheet,
+ NULL);
+
+ return theme;
+}
+
+HippoCanvasThemeEngine *
+hippo_canvas_theme_get_theme_engine (HippoCanvasTheme *theme)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_THEME(theme), NULL);
+
+ return theme->theme_engine;
+}
+
+
+static gboolean
+link_class_add_sel_matches_style(HippoCanvasTheme *a_this,
+ CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ return hippo_canvas_style_get_link_type(a_style) == HIPPO_CANVAS_LINK_LINK;
+}
+
+static gboolean
+visited_class_add_sel_matches_style(HippoCanvasTheme *a_this,
+ CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ return hippo_canvas_style_get_link_type(a_style) == HIPPO_CANVAS_LINK_VISITED;
+}
+
+static gboolean
+pseudo_class_add_sel_matches_style (HippoCanvasTheme *a_this,
+ CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ g_return_val_if_fail(a_this
+ && a_add_sel
+ && a_add_sel->content.pseudo
+ && a_add_sel->content.pseudo->name
+ && a_add_sel->content.pseudo->name->stryng
+ && a_add_sel->content.pseudo->name->stryng->str
+ && a_style, FALSE);
+
+ if (strcmp(a_add_sel->content.pseudo->name->stryng->str, "link") == 0) {
+ return link_class_add_sel_matches_style(a_this, a_add_sel, a_style);
+ } else if (strcmp(a_add_sel->content.pseudo->name->stryng->str, "visited") == 0) {
+ return visited_class_add_sel_matches_style(a_this, a_add_sel, a_style);
+ } else {
+ return FALSE;
+ }
+}
+
+/**
+ * param a_add_sel the class additional selector to consider.
+ * param a_style the style object to consider.
+ * return TRUE if the class additional selector matches
+ *the style object given in argument, FALSE otherwise.
+ */
+static gboolean
+class_add_sel_matches_style (CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ const char *klass;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == CLASS_ADD_SELECTOR
+ && a_add_sel->content.class_name
+ && a_add_sel->content.class_name->stryng
+ && a_add_sel->content.class_name->stryng->str
+ && a_style, FALSE);
+
+ klass = hippo_canvas_style_get_element_class(a_style);
+ if (klass != NULL) {
+ const char *cur;
+
+ for (cur = klass; *cur;) {
+ while (*cur && cr_utils_is_white_space (*cur))
+ cur++;
+
+ if (strncmp (cur,
+ a_add_sel->content.class_name->stryng->str,
+ a_add_sel->content.class_name->stryng->len) == 0) {
+ cur += a_add_sel->content.class_name->stryng->len;
+ if ((!*cur) || cr_utils_is_white_space (*cur))
+ return TRUE;
+ }
+
+ /* skip to next whitespace character */
+ while (*cur && !cr_utils_is_white_space(*cur))
+ cur++;
+
+ }
+ }
+
+ return FALSE;
+}
+
+/**
+ * return TRUE if the additional attribute selector matches
+ *the current style object given in argument, FALSE otherwise.
+ * param a_add_sel the additional attribute selector to consider.
+ * param a_style the style object to consider.
+ */
+static gboolean
+id_add_sel_matches_style (CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ gboolean result = FALSE;
+ const char *id;
+
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_add_sel->content.id_name
+ && a_add_sel->content.id_name->stryng
+ && a_add_sel->content.id_name->stryng->str
+ && a_style, FALSE);
+ g_return_val_if_fail (a_add_sel
+ && a_add_sel->type == ID_ADD_SELECTOR
+ && a_style, FALSE);
+
+ id = hippo_canvas_style_get_element_id(a_style);
+
+ if (id != NULL) {
+ if (!strqcmp (id, a_add_sel->content.id_name->stryng->str,
+ a_add_sel->content.id_name->stryng->len)) {
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+
+/**
+ *Evaluates if a given additional selector matches an style object.
+ * param a_add_sel the additional selector to consider.
+ * param a_style the style object to consider.
+ * return TRUE is a_add_sel matches a_style, FALSE otherwise.
+ */
+static gboolean
+additional_selector_matches_style (HippoCanvasTheme *a_this,
+ CRAdditionalSel *a_add_sel,
+ HippoCanvasStyle *a_style)
+{
+ CRAdditionalSel *cur_add_sel = NULL;
+ CRAdditionalSel *tail;
+ gboolean evaluated = FALSE;
+
+ g_return_val_if_fail (a_add_sel, FALSE) ;
+
+ for (tail = a_add_sel;
+ tail && tail->next;
+ tail = tail->next)
+ ;
+
+ for (cur_add_sel = tail ;
+ cur_add_sel ;
+ cur_add_sel = cur_add_sel->prev) {
+
+ evaluated = TRUE ;
+ if (cur_add_sel->type == NO_ADD_SELECTOR) {
+ return FALSE;
+ }
+
+ if (cur_add_sel->type == CLASS_ADD_SELECTOR
+ && cur_add_sel->content.class_name
+ && cur_add_sel->content.class_name->stryng
+ && cur_add_sel->content.class_name->stryng->str) {
+ if (!class_add_sel_matches_style (cur_add_sel, a_style)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ID_ADD_SELECTOR
+ && cur_add_sel->content.id_name
+ && cur_add_sel->content.id_name->stryng
+ && cur_add_sel->content.id_name->stryng->str) {
+ if (!id_add_sel_matches_style (cur_add_sel, a_style)) {
+ return FALSE;
+ }
+ continue ;
+ } else if (cur_add_sel->type == ATTRIBUTE_ADD_SELECTOR
+ && cur_add_sel->content.attr_sel) {
+ g_warning("Attribute selectors not supported");
+ return FALSE;
+ } else if (cur_add_sel->type == PSEUDO_CLASS_ADD_SELECTOR
+ && cur_add_sel->content.pseudo) {
+ /* FIXME: is this right?????; it's backwards from the rest */
+ if (pseudo_class_add_sel_matches_style(a_this, cur_add_sel, a_style)) {
+ return TRUE;
+ }
+ return FALSE;
+ }
+ }
+
+ if (evaluated)
+ return TRUE;
+
+ return FALSE ;
+}
+
+/* This is a workaround for:
+ * - Python encodes '.' as '+' in type names
+ * - libcroco doesn't correctly parse the \+ escape in types
+ * - it's far too ugly to write foo\2b\bar\2bWidget...
+ *
+ * So we consider an element name of foo-bar-Widget to match a type
+ * of foo+bar+Widget
+ */
+static gboolean
+element_name_matches_type_name(const char *element_name,
+ const char *type_name)
+{
+ const char *p = element_name;
+ const char *q = type_name;
+
+ while (*p || *q) {
+ if (*p == '-') {
+ if (*q != '-' && *q != '+')
+ return FALSE;
+ } else {
+ if (*p != *q)
+ return FALSE;
+ }
+
+ p++;
+ q++;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+element_name_matches_type(const char *element_name,
+ GType element_type)
+{
+ /* This is not efficient, but the number of selectors with an element_name
+ * is probably fairly small.
+ */
+ if (element_type == G_TYPE_NONE) {
+ return strcmp(element_name, "canvas") == 0;
+ } else {
+ while (TRUE) {
+ if (element_name_matches_type_name(element_name, g_type_name(element_type)))
+ return TRUE;
+
+ if (element_type == G_TYPE_OBJECT)
+ return FALSE;
+
+ element_type = g_type_parent(element_type);
+ }
+ }
+}
+
+/**
+ *Evaluate a selector (a simple selectors list) and says
+ *if it matches the style object given in parameter.
+ *The algorithm used here is the following:
+ *Walk the combinator separated list of simple selectors backward, starting
+ *from the end of the list. For each simple selector, looks if
+ *if matches the current style.
+ *
+ * param a_this the selection engine.
+ * param a_sel the simple selection list.
+ * param a_style the style object.
+ * param a_result out parameter. Set to true if the
+ *selector matches the style object, FALSE otherwise.
+ * param a_recurse if set to TRUE, the function will walk to
+ *the next simple selector (after the evaluation of the current one)
+ *and recursively evaluate it. Must be usually set to TRUE unless you
+ *know what you are doing.
+ */
+static enum CRStatus
+sel_matches_style_real (HippoCanvasTheme *a_this,
+ CRSimpleSel *a_sel,
+ HippoCanvasStyle *a_style,
+ gboolean *a_result,
+ gboolean a_eval_sel_list_from_end,
+ gboolean a_recurse)
+{
+ CRSimpleSel *cur_sel = NULL;
+ HippoCanvasStyle *cur_style = NULL;
+ GType cur_type;
+
+ *a_result = FALSE;
+
+ if (a_eval_sel_list_from_end) {
+ /*go and get the last simple selector of the list */
+ for (cur_sel = a_sel; cur_sel && cur_sel->next; cur_sel = cur_sel->next) ;
+ } else {
+ cur_sel = a_sel;
+ }
+
+ cur_style = a_style;
+ cur_type = hippo_canvas_style_get_element_type(cur_style);
+
+ while (cur_sel) {
+ if (((cur_sel->type_mask & TYPE_SELECTOR)
+ && (cur_sel->name
+ && cur_sel->name->stryng
+ && cur_sel->name->stryng->str)
+ && (element_name_matches_type (cur_sel->name->stryng->str, cur_type)))
+ || (cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ /*
+ *this simple selector
+ *matches the current style object
+ *Let's see if the preceding
+ *simple selectors also match
+ *their style object counterpart.
+ */
+ if (cur_sel->add_sel) {
+ if (additional_selector_matches_style (a_this, cur_sel->add_sel, cur_style)) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto walk_a_step_in_expr;
+ }
+ }
+ if (!(cur_sel->type_mask & TYPE_SELECTOR)
+ && !(cur_sel->type_mask & UNIVERSAL_SELECTOR)) {
+ if (!cur_sel->add_sel) {
+ goto done;
+ }
+ if (additional_selector_matches_style(a_this, cur_sel->add_sel, cur_style)) {
+ goto walk_a_step_in_expr;
+ } else {
+ goto done;
+ }
+ } else {
+ goto done ;
+ }
+
+ walk_a_step_in_expr:
+ if (a_recurse == FALSE) {
+ *a_result = TRUE;
+ goto done;
+ }
+
+ /*
+ *here, depending on the combinator of cur_sel
+ *choose the axis of the element tree traversal
+ *and walk one step in the element tree.
+ */
+ if (!cur_sel->prev)
+ break;
+
+ switch (cur_sel->combinator) {
+ case NO_COMBINATOR:
+ break;
+
+ case COMB_WS: /*descendant selector */
+ {
+ HippoCanvasStyle *n = NULL;
+
+ /*
+ *walk the element tree upward looking for a parent
+ *style that matches the preceding selector.
+ */
+ for (n = hippo_canvas_style_get_parent(a_style); n; n = hippo_canvas_style_get_parent(n)) {
+ enum CRStatus status;
+ gboolean matches = FALSE;
+
+ status = sel_matches_style_real(a_this, cur_sel->prev, n, &matches, FALSE, TRUE);
+
+ if (status != CR_OK)
+ goto done;
+
+ if (matches) {
+ cur_style = n;
+ cur_type = hippo_canvas_style_get_element_type(cur_style);
+ break;
+ }
+ }
+
+ if (!n) {
+ /*
+ *didn't find any ancestor that matches
+ *the previous simple selector.
+ */
+ goto done;
+ }
+ /*
+ *in this case, the preceding simple sel
+ *will have been interpreted twice, which
+ *is a cpu and mem waste ... I need to find
+ *another way to do this. Anyway, this is
+ *my first attempt to write this function and
+ *I am a bit clueless.
+ */
+ break;
+ }
+
+ case COMB_PLUS:
+ g_warning("+ combinators are not supported");
+ goto done;
+
+ case COMB_GT:
+ cur_style = hippo_canvas_style_get_parent (cur_style);
+ if (!cur_style)
+ goto done;
+ cur_type = hippo_canvas_style_get_element_type(cur_style);
+ break;
+
+ default:
+ goto done;
+ }
+
+ cur_sel = cur_sel->prev;
+ }
+
+ /*
+ *if we reached this point, it means the selector matches
+ *the style object.
+ */
+ *a_result = TRUE;
+
+ done:
+ return CR_OK;
+}
+
+
+static void
+add_matched_properties (HippoCanvasTheme *a_this,
+ CRStyleSheet *a_stylesheet,
+ HippoCanvasStyle *a_style,
+ GPtrArray *props)
+{
+ CRStatement *cur_stmt = NULL;
+ CRSelector *sel_list = NULL;
+ CRSelector *cur_sel = NULL;
+ gboolean matches = FALSE;
+ enum CRStatus status = CR_OK;
+
+ /*
+ *walk through the list of statements and,
+ *get the selectors list inside the statements that
+ *contain some, and try to match our style object in these
+ *selectors lists.
+ */
+ for (cur_stmt = a_stylesheet->statements; cur_stmt; cur_stmt = cur_stmt->next) {
+ /*
+ *initialyze the selector list in which we will
+ *really perform the search.
+ */
+ sel_list = NULL;
+
+ /*
+ *get the the damn selector list in
+ *which we have to look
+ */
+ switch (cur_stmt->type) {
+ case RULESET_STMT:
+ if (cur_stmt->kind.ruleset
+ && cur_stmt->kind.ruleset->sel_list) {
+ sel_list = cur_stmt->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_MEDIA_RULE_STMT:
+ if (cur_stmt->kind.media_rule
+ && cur_stmt->kind.media_rule->rulesets
+ && cur_stmt->kind.media_rule->rulesets->kind.ruleset
+ && cur_stmt->kind.media_rule->rulesets->kind.ruleset->sel_list) {
+ sel_list = cur_stmt->kind.media_rule->rulesets->kind.ruleset->sel_list;
+ }
+ break;
+
+ case AT_IMPORT_RULE_STMT:
+ /*
+ *some recursivity may be needed here.
+ *I don't like this :(
+ */
+ break;
+ default:
+ break;
+ }
+
+ if (!sel_list)
+ continue;
+
+ /*
+ *now, we have a comma separated selector list to look in.
+ *let's walk it and try to match the style object
+ *on each item of the list.
+ */
+ for (cur_sel = sel_list; cur_sel; cur_sel = cur_sel->next) {
+ if (!cur_sel->simple_sel)
+ continue;
+
+ status = sel_matches_style_real(a_this, cur_sel->simple_sel, a_style, &matches, TRUE, TRUE);
+
+ if (status == CR_OK && matches) {
+ CRDeclaration *cur_decl = NULL;
+
+ /* In order to sort the matching properties, we need to compute the
+ * specificity of the selector that actually matched this
+ * element. In a non-thread-safe fashion, we store it in the
+ * ruleset. (Fixing this would mean cut-and-pasting
+ * cr_simple_sel_compute_specificity(), and have no need for
+ * thread-safety anyways.)
+ *
+ * Once we've sorted the properties, the specificity no longer
+ * matters and it can be safely overriden.
+ */
+ cr_simple_sel_compute_specificity (cur_sel->simple_sel);
+
+ cur_stmt->specificity = cur_sel->simple_sel->specificity;
+
+ for (cur_decl = cur_stmt->kind.ruleset->decl_list; cur_decl; cur_decl = cur_decl->next)
+ g_ptr_array_add(props, cur_decl);
+ }
+ }
+ }
+}
+
+#define ORIGIN_AUTHOR_IMPORTANT (ORIGIN_AUTHOR + 1)
+#define ORIGIN_USER_IMPORTANT (ORIGIN_AUTHOR + 2)
+
+static inline int
+get_origin(const CRDeclaration *decl)
+{
+ enum CRStyleOrigin origin = decl->parent_statement->parent_sheet->origin;
+
+ if (decl->important) {
+ if (origin == ORIGIN_AUTHOR)
+ return ORIGIN_AUTHOR_IMPORTANT;
+ else if (origin == ORIGIN_USER)
+ return ORIGIN_USER_IMPORTANT;
+ }
+
+ return origin;
+}
+
+/* Order of comparison is so that higher priority statements compare after
+ * lower priority statements */
+static int
+compare_declarations(gconstpointer a,
+ gconstpointer b)
+{
+ /* g_ptr_array_sort() is broooken */
+ CRDeclaration *decl_a = *(CRDeclaration **)a;
+ CRDeclaration *decl_b = *(CRDeclaration **)b;
+
+ int origin_a = get_origin(decl_a);
+ int origin_b = get_origin(decl_b);
+
+ if (origin_a != origin_b)
+ return origin_a - origin_b;
+
+ if (decl_a->parent_statement->specificity != decl_b->parent_statement->specificity)
+ return decl_a->parent_statement->specificity - decl_b->parent_statement->specificity;
+
+ return 0;
+}
+
+void
+_hippo_canvas_theme_get_matched_properties (HippoCanvasTheme *theme,
+ HippoCanvasStyle *style,
+ CRDeclaration ***properties,
+ int *n_properties)
+{
+ enum CRStyleOrigin origin = 0;
+ CRStyleSheet *sheet = NULL;
+ GPtrArray *props = g_ptr_array_new();
+
+ g_return_if_fail (HIPPO_IS_CANVAS_THEME(theme));
+ g_return_if_fail (HIPPO_IS_CANVAS_STYLE(style));
+
+ for (origin = ORIGIN_UA; origin < NB_ORIGINS; origin++) {
+ sheet = cr_cascade_get_sheet (theme->cascade, origin);
+ if (!sheet)
+ continue;
+
+ add_matched_properties(theme, sheet, style, props);
+ }
+
+ /* We count on a stable sort here so that later declarations come
+ * after earlier declarations */
+ g_ptr_array_sort(props, compare_declarations);
+
+ *n_properties = props->len;
+ *properties = (CRDeclaration **)g_ptr_array_free(props, FALSE);
+}
Added: trunk/common/hippo/hippo-canvas-theme.h
==============================================================================
--- (empty file)
+++ trunk/common/hippo/hippo-canvas-theme.h Mon Mar 24 19:05:00 2008
@@ -0,0 +1,30 @@
+/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+#ifndef __HIPPO_CANVAS_THEME_H__
+#define __HIPPO_CANVAS_THEME_H__
+
+#include <hippo/hippo-canvas-context.h>
+#include <hippo/hippo-canvas-box.h>
+#include <hippo/hippo-canvas-theme-engine.h>
+
+G_BEGIN_DECLS
+
+#define HIPPO_TYPE_CANVAS_THEME (hippo_canvas_theme_get_type ())
+#define HIPPO_CANVAS_THEME(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), HIPPO_TYPE_CANVAS_THEME, HippoCanvasTheme))
+#define HIPPO_CANVAS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), HIPPO_TYPE_CANVAS_THEME, HippoCanvasThemeClass))
+#define HIPPO_IS_CANVAS_THEME(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), HIPPO_TYPE_CANVAS_THEME))
+#define HIPPO_IS_CANVAS_THEME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), HIPPO_TYPE_CANVAS_THEME))
+#define HIPPO_CANVAS_THEME_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), HIPPO_TYPE_CANVAS_THEME, HippoCanvasThemeClass))
+
+GType hippo_canvas_theme_get_type (void) G_GNUC_CONST;
+
+HippoCanvasTheme *hippo_canvas_theme_new (HippoCanvasThemeEngine *theme_engine,
+ const char *application_stylesheet,
+ const char *theme_stylesheet,
+ const char *default_stylesheet);
+
+HippoCanvasThemeEngine *hippo_canvas_theme_get_theme_engine (HippoCanvasTheme *theme);
+
+
+G_END_DECLS
+
+#endif /* __HIPPO_CANVAS_THEME_H__ */
Modified: trunk/common/hippo/hippo-canvas-type-builtins.c
==============================================================================
--- trunk/common/hippo/hippo-canvas-type-builtins.c (original)
+++ trunk/common/hippo/hippo-canvas-type-builtins.c Mon Mar 24 19:05:00 2008
@@ -30,29 +30,13 @@
return type;
}
-const GEnumValue _hippo_cascade_mode_values[] = {
- { HIPPO_CASCADE_MODE_NONE, "HIPPO_CASCADE_MODE_NONE", "none" },
- { HIPPO_CASCADE_MODE_INHERIT, "HIPPO_CASCADE_MODE_INHERIT", "inherit" },
- { 0, NULL, NULL }
-};
-
-GType
-hippo_cascade_mode_get_type (void)
-{
- static GType type = 0;
-
- if (G_UNLIKELY (type == 0))
- type = g_enum_register_static ("HippoCascadeMode", _hippo_cascade_mode_values);
-
- return type;
-}
-
/* enumerations from "hippo/hippo-canvas-context.h" */
#include "hippo/hippo-canvas-context.h"
const GEnumValue _hippo_stock_color_values[] = {
- { HIPPO_STOCK_COLOR_BG_NORMAL, "HIPPO_STOCK_COLOR_BG_NORMAL", "normal" },
- { HIPPO_STOCK_COLOR_BG_PRELIGHT, "HIPPO_STOCK_COLOR_BG_PRELIGHT", "prelight" },
+ { HIPPO_STOCK_COLOR_BG_NORMAL, "HIPPO_STOCK_COLOR_BG_NORMAL", "bg-normal" },
+ { HIPPO_STOCK_COLOR_BG_PRELIGHT, "HIPPO_STOCK_COLOR_BG_PRELIGHT", "bg-prelight" },
+ { HIPPO_STOCK_COLOR_FG, "HIPPO_STOCK_COLOR_FG", "fg" },
{ 0, NULL, NULL }
};
@@ -108,6 +92,65 @@
}
+/* enumerations from "hippo/hippo-canvas-style.h" */
+#include "hippo/hippo-canvas-style.h"
+const GEnumValue _hippo_canvas_link_type_values[] = {
+ { HIPPO_CANVAS_LINK_NONE, "HIPPO_CANVAS_LINK_NONE", "none" },
+ { HIPPO_CANVAS_LINK_LINK, "HIPPO_CANVAS_LINK_LINK", "link" },
+ { HIPPO_CANVAS_LINK_VISITED, "HIPPO_CANVAS_LINK_VISITED", "visited" },
+ { 0, NULL, NULL }
+};
+
+GType
+hippo_canvas_link_type_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ type = g_enum_register_static ("HippoCanvasLinkType", _hippo_canvas_link_type_values);
+
+ return type;
+}
+
+const GEnumValue _hippo_canvas_side_values[] = {
+ { HIPPO_CANVAS_SIDE_LEFT, "HIPPO_CANVAS_SIDE_LEFT", "left" },
+ { HIPPO_CANVAS_SIDE_RIGHT, "HIPPO_CANVAS_SIDE_RIGHT", "right" },
+ { HIPPO_CANVAS_SIDE_TOP, "HIPPO_CANVAS_SIDE_TOP", "top" },
+ { HIPPO_CANVAS_SIDE_BOTTOM, "HIPPO_CANVAS_SIDE_BOTTOM", "bottom" },
+ { 0, NULL, NULL }
+};
+
+GType
+hippo_canvas_side_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ type = g_enum_register_static ("HippoCanvasSide", _hippo_canvas_side_values);
+
+ return type;
+}
+
+const GFlagsValue _hippo_text_decoration_values[] = {
+ { HIPPO_TEXT_DECORATION_UNDERLINE, "HIPPO_TEXT_DECORATION_UNDERLINE", "underline" },
+ { HIPPO_TEXT_DECORATION_OVERLINE, "HIPPO_TEXT_DECORATION_OVERLINE", "overline" },
+ { HIPPO_TEXT_DECORATION_LINE_THROUGH, "HIPPO_TEXT_DECORATION_LINE_THROUGH", "line-through" },
+ { HIPPO_TEXT_DECORATION_BLINK, "HIPPO_TEXT_DECORATION_BLINK", "blink" },
+ { 0, NULL, NULL }
+};
+
+GType
+hippo_text_decoration_get_type (void)
+{
+ static GType type = 0;
+
+ if (G_UNLIKELY (type == 0))
+ type = g_flags_register_static ("HippoTextDecoration", _hippo_text_decoration_values);
+
+ return type;
+}
+
+
/* enumerations from "hippo/hippo-canvas-text.h" */
#include "hippo/hippo-canvas-text.h"
const GEnumValue _hippo_canvas_size_mode_values[] = {
Modified: trunk/common/hippo/hippo-canvas-type-builtins.h
==============================================================================
--- trunk/common/hippo/hippo-canvas-type-builtins.h (original)
+++ trunk/common/hippo/hippo-canvas-type-builtins.h Mon Mar 24 19:05:00 2008
@@ -12,8 +12,6 @@
/* --- hippo/hippo-canvas-box.h --- */
#define HIPPO_TYPE_PACK_FLAGS hippo_pack_flags_get_type()
GType hippo_pack_flags_get_type (void);
-#define HIPPO_TYPE_CASCADE_MODE hippo_cascade_mode_get_type()
-GType hippo_cascade_mode_get_type (void);
/* --- hippo/hippo-canvas-context.h --- */
#define HIPPO_TYPE_STOCK_COLOR hippo_stock_color_get_type()
@@ -25,6 +23,14 @@
#define HIPPO_TYPE_ITEM_ALIGNMENT hippo_item_alignment_get_type()
GType hippo_item_alignment_get_type (void);
+/* --- hippo/hippo-canvas-style.h --- */
+#define HIPPO_TYPE_CANVAS_LINK_TYPE hippo_canvas_link_type_get_type()
+GType hippo_canvas_link_type_get_type (void);
+#define HIPPO_TYPE_CANVAS_SIDE hippo_canvas_side_get_type()
+GType hippo_canvas_side_get_type (void);
+#define HIPPO_TYPE_TEXT_DECORATION hippo_text_decoration_get_type()
+GType hippo_text_decoration_get_type (void);
+
/* --- hippo/hippo-canvas-text.h --- */
#define HIPPO_TYPE_CANVAS_SIZE_MODE hippo_canvas_size_mode_get_type()
GType hippo_canvas_size_mode_get_type (void);
Modified: trunk/configure.ac
==============================================================================
--- trunk/configure.ac (original)
+++ trunk/configure.ac Mon Mar 24 19:05:00 2008
@@ -142,8 +142,10 @@
GLIB2_REQUIRED=2.6.0
GTK2_REQUIRED=2.6.0
+LIBCROCO_REQUIRED=0.6.0
+PANGO_REQUIRED=1.14
-PKG_CHECK_MODULES(LIBHIPPOCANVAS, gobject-2.0 >= $GLIB2_REQUIRED gtk+-2.0 >= $GTK2_REQUIRED cairo pango)
+PKG_CHECK_MODULES(LIBHIPPOCANVAS, gobject-2.0 >= $GLIB2_REQUIRED gtk+-2.0 >= $GTK2_REQUIRED libcroco-0.6 >= $LIBCROCO_REQUIRED cairo pango >= $PANGO_REQUIRED)
GLIB_GENMARSHAL=`$PKG_CONFIG --variable=glib_genmarshal glib-2.0`
AC_SUBST(GLIB_GENMARSHAL)
Modified: trunk/linux/hippo/hippo-canvas-helper.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-helper.c (original)
+++ trunk/linux/hippo/hippo-canvas-helper.c Mon Mar 24 19:05:00 2008
@@ -2,6 +2,8 @@
#include <config.h>
#include <glib/gi18n-lib.h>
#include <hippo/hippo-canvas-context.h>
+#include <hippo/hippo-canvas-style.h>
+#include <hippo/hippo-canvas-theme.h>
#include <gtk/gtkcontainer.h>
#include "hippo-canvas-widget.h"
#include "hippo-canvas-helper.h"
@@ -58,6 +60,10 @@
int *x_p,
int *y_p);
+HippoCanvasStyle * hippo_canvas_helper_get_style (HippoCanvasContext *context);
+double hippo_canvas_helper_get_resolution (HippoCanvasContext *context);
+PangoFontDescription *hippo_canvas_helper_get_font (HippoCanvasContext *context);
+
static void hippo_canvas_helper_fixup_resize_state (HippoCanvasHelper *canvas);
static void tooltip_window_update (GtkWidget *tip,
@@ -75,6 +81,9 @@
GtkWidget *widget;
+ HippoCanvasTheme *theme;
+ HippoCanvasStyle *style;
+
HippoCanvasItem *root;
HippoCanvasPointer pointer;
@@ -143,6 +152,9 @@
klass->unregister_widget_item = hippo_canvas_helper_unregister_widget_item;
klass->translate_to_widget = hippo_canvas_helper_translate_to_widget;
klass->translate_to_screen = hippo_canvas_helper_translate_to_screen;
+ klass->get_style = hippo_canvas_helper_get_style;
+ klass->get_resolution = hippo_canvas_helper_get_resolution;
+ klass->get_font = hippo_canvas_helper_get_font;
}
static void
@@ -165,6 +177,7 @@
if (helper->root != NULL) {
HippoCanvasItem *old_root = g_object_ref(helper->root);
hippo_canvas_helper_set_root(helper, NULL);
+ hippo_canvas_helper_set_theme(helper, NULL);
hippo_canvas_item_destroy(old_root);
g_object_unref(old_root);
}
@@ -671,6 +684,32 @@
}
void
+hippo_canvas_helper_set_window_background (HippoCanvasHelper *helper,
+ GdkWindow *window)
+{
+ HippoCanvasStyle *style = hippo_canvas_context_get_style(HIPPO_CANVAS_CONTEXT(helper));
+ guint32 color;
+
+ if (hippo_canvas_style_get_color(style, "background-color", FALSE, &color)) {
+ GdkColormap *colormap = gdk_window_get_colormap(window);
+ GdkColor color_gdk;
+
+ color_gdk.red = (color & 0xFF000000) >> 24;
+ color_gdk.red = color_gdk.red * 0x101;
+ color_gdk.green = (color & 0x00FF0000) >> 16;
+ color_gdk.green = color_gdk.green * 0x101;
+ color_gdk.blue = (color & 0x0000FF00) >> 8;
+ color_gdk.blue = color_gdk.blue * 0x101;
+
+ gdk_rgb_find_color(colormap, &color_gdk);
+
+ gdk_window_set_background(window, &color_gdk);
+ } else {
+ gtk_style_set_background (helper->widget->style, window, GTK_STATE_NORMAL);
+ }
+}
+
+void
hippo_canvas_helper_add(HippoCanvasHelper *helper,
GtkWidget *widget)
{
@@ -789,6 +828,9 @@
case HIPPO_STOCK_COLOR_BG_PRELIGHT:
return convert_color(&style->bg[GTK_STATE_PRELIGHT]);
break;
+ case HIPPO_STOCK_COLOR_FG:
+ return convert_color(&style->fg[GTK_STATE_NORMAL]);
+ break;
}
g_warning("unknown stock color %d", color);
@@ -975,6 +1017,35 @@
*y_p += window_y;
}
+HippoCanvasStyle *
+hippo_canvas_helper_get_style (HippoCanvasContext *context)
+{
+ HippoCanvasHelper *helper = HIPPO_CANVAS_HELPER(context);
+
+ if (helper->style == NULL) {
+ helper->style = hippo_canvas_style_new(context, NULL, helper->theme,
+ G_TYPE_NONE, NULL, NULL);
+ }
+
+ return helper->style;
+}
+
+double
+hippo_canvas_helper_get_resolution (HippoCanvasContext *context)
+{
+ HippoCanvasHelper *helper = HIPPO_CANVAS_HELPER(context);
+
+ return gdk_screen_get_resolution(gtk_widget_get_screen(helper->widget));
+}
+
+PangoFontDescription *
+hippo_canvas_helper_get_font (HippoCanvasContext *context)
+{
+ HippoCanvasHelper *helper = HIPPO_CANVAS_HELPER(context);
+
+ return helper->widget->style->font_desc;
+}
+
static void
canvas_root_destroy(HippoCanvasItem *root,
HippoCanvasHelper *helper)
@@ -1077,6 +1148,32 @@
gtk_widget_queue_resize(widget);
}
+void
+hippo_canvas_helper_set_theme(HippoCanvasHelper *canvas_helper,
+ HippoCanvasTheme *theme)
+{
+ g_return_if_fail(HIPPO_IS_CANVAS_HELPER(canvas_helper));
+ g_return_if_fail(theme == NULL || HIPPO_IS_CANVAS_THEME(theme));
+
+ if (theme == canvas_helper->theme)
+ return;
+
+ if (canvas_helper->theme)
+ g_object_unref(canvas_helper->theme);
+
+ canvas_helper->theme = theme;
+
+ if (canvas_helper->theme)
+ g_object_ref(canvas_helper->theme);
+
+ if (canvas_helper->style) {
+ g_object_unref(canvas_helper->style);
+ canvas_helper->style = NULL;
+ }
+
+ hippo_canvas_context_emit_style_changed(HIPPO_CANVAS_CONTEXT(canvas_helper), TRUE);
+}
+
GtkWidget *
hippo_canvas_helper_get_widget(HippoCanvasHelper *helper)
{
Modified: trunk/linux/hippo/hippo-canvas-helper.h
==============================================================================
--- trunk/linux/hippo/hippo-canvas-helper.h (original)
+++ trunk/linux/hippo/hippo-canvas-helper.h Mon Mar 24 19:05:00 2008
@@ -31,6 +31,9 @@
HippoCanvasHelper* hippo_canvas_helper_new (GtkContainer *base_container);
void hippo_canvas_helper_set_root (HippoCanvasHelper *helper,
HippoCanvasItem *root);
+void hippo_canvas_helper_set_theme(HippoCanvasHelper *canvas_helper,
+ HippoCanvasTheme *theme);
+
GtkWidget *hippo_canvas_helper_get_widget(HippoCanvasHelper *helper);
/* Set an explicit width on the helper; this will be used instead of the minimum
@@ -69,6 +72,9 @@
void hippo_canvas_helper_hierarchy_changed (HippoCanvasHelper *helper,
GtkWidget *old_toplevel);
+void hippo_canvas_helper_set_window_background (HippoCanvasHelper *helper,
+ GdkWindow *window);
+
void hippo_canvas_helper_add (HippoCanvasHelper *helper,
GtkWidget *widget);
void hippo_canvas_helper_remove (HippoCanvasHelper *helper,
Modified: trunk/linux/hippo/hippo-canvas-widget.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-widget.c (original)
+++ trunk/linux/hippo/hippo-canvas-widget.c Mon Mar 24 19:05:00 2008
@@ -4,6 +4,7 @@
#include <string.h>
#include <gtk/gtkwidget.h>
#include "hippo-canvas-widget.h"
+#include "hippo-canvas-style.h"
static void hippo_canvas_widget_init (HippoCanvasWidget *widget);
static void hippo_canvas_widget_class_init (HippoCanvasWidgetClass *klass);
@@ -202,6 +203,27 @@
}
static void
+on_context_style_changed(HippoCanvasContext *context,
+ gboolean resize_needed,
+ HippoCanvasWidget *widget)
+{
+ HippoCanvasStyle *style = NULL;
+ HippoCanvasTheme *theme = NULL;
+
+ if (context != NULL)
+ style = hippo_canvas_context_get_style(context);
+ if (style != NULL)
+ theme = hippo_canvas_style_get_theme(style);
+
+ if (theme != widget->theme) {
+ widget->theme = theme;
+
+ if (HIPPO_CANVAS_WIDGET_GET_CLASS(widget)->theme_changed)
+ HIPPO_CANVAS_WIDGET_GET_CLASS(widget)->theme_changed(widget);
+ }
+}
+
+static void
hippo_canvas_widget_set_context(HippoCanvasItem *item,
HippoCanvasContext *context)
{
@@ -210,14 +232,26 @@
if (context == box->context)
return;
- if (box->context)
+ if (box->context) {
hippo_canvas_context_unregister_widget_item(box->context, item);
+ g_signal_handlers_disconnect_by_func(box->context,
+ (gpointer)on_context_style_changed,
+ context);
+ }
+
/* chain up, which invalidates our old context */
item_parent_class->set_context(item, context);
- if (box->context)
+ if (box->context) {
hippo_canvas_context_register_widget_item(box->context, item);
+
+ g_signal_connect(box->context, "style-changed",
+ G_CALLBACK(on_context_style_changed), item);
+
+ }
+
+ on_context_style_changed(context, TRUE, HIPPO_CANVAS_WIDGET(item));
}
static void
Modified: trunk/linux/hippo/hippo-canvas-widget.h
==============================================================================
--- trunk/linux/hippo/hippo-canvas-widget.h (original)
+++ trunk/linux/hippo/hippo-canvas-widget.h Mon Mar 24 19:05:00 2008
@@ -23,11 +23,14 @@
struct _HippoCanvasWidget {
HippoCanvasBox box;
+ HippoCanvasTheme *theme;
GtkWidget *widget;
};
struct _HippoCanvasWidgetClass {
HippoCanvasBoxClass parent_class;
+
+ void (*theme_changed) (HippoCanvasWidget *widget);
};
GType hippo_canvas_widget_get_type (void) G_GNUC_CONST;
Modified: trunk/linux/hippo/hippo-canvas-widgets.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-widgets.c (original)
+++ trunk/linux/hippo/hippo-canvas-widgets.c Mon Mar 24 19:05:00 2008
@@ -13,18 +13,11 @@
#define HIPPO_DEFINE_WIDGET_ITEM(lower, Camel) \
struct _HippoCanvas##Camel { HippoCanvasWidget parent; }; \
struct _HippoCanvas##Camel##Class { HippoCanvasWidgetClass parent; }; \
- static void hippo_canvas_##lower##_class_init(HippoCanvas##Camel##Class *lower) {} \
G_DEFINE_TYPE(HippoCanvas##Camel, hippo_canvas_##lower, HIPPO_TYPE_CANVAS_WIDGET)
-#define HIPPO_DEFINE_WIDGET_ITEM_CUSTOM_INIT(lower, Camel) \
- struct _HippoCanvas##Camel { HippoCanvasWidget parent; }; \
- struct _HippoCanvas##Camel##Class { HippoCanvasWidgetClass parent; }; \
- G_DEFINE_TYPE(HippoCanvas##Camel, hippo_canvas_##lower, HIPPO_TYPE_CANVAS_WIDGET)
-
-
-HIPPO_DEFINE_WIDGET_ITEM_CUSTOM_INIT(button, Button);
+HIPPO_DEFINE_WIDGET_ITEM(button, Button);
HIPPO_DEFINE_WIDGET_ITEM(scrollbars, Scrollbars);
-HIPPO_DEFINE_WIDGET_ITEM_CUSTOM_INIT(entry, Entry);
+HIPPO_DEFINE_WIDGET_ITEM(entry, Entry);
enum {
BUTTON_PROP_0,
@@ -178,6 +171,23 @@
}
static void
+hippo_canvas_scrollbars_theme_changed(HippoCanvasWidget *widget_item)
+{
+ GtkWidget *viewport = gtk_bin_get_child(GTK_BIN(widget_item->widget));
+ GtkWidget *canvas = gtk_bin_get_child(GTK_BIN(viewport));
+
+ hippo_canvas_set_theme(HIPPO_CANVAS(canvas), widget_item->theme);
+}
+
+static void
+hippo_canvas_scrollbars_class_init(HippoCanvasScrollbarsClass *class)
+{
+ HippoCanvasWidgetClass *widget_class = HIPPO_CANVAS_WIDGET_CLASS(class);
+
+ widget_class->theme_changed = hippo_canvas_scrollbars_theme_changed;
+}
+
+static void
hippo_canvas_scrollbars_init(HippoCanvasScrollbars *scrollbars)
{
GtkWidget *widget;
Modified: trunk/linux/hippo/hippo-canvas-window.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas-window.c (original)
+++ trunk/linux/hippo/hippo-canvas-window.c Mon Mar 24 19:05:00 2008
@@ -22,6 +22,8 @@
GValue *value,
GParamSpec *pspec);
+static void hippo_canvas_window_realize (GtkWidget *widget);
+
static gboolean hippo_canvas_window_button_press (GtkWidget *widget,
GdkEventButton *event);
static gboolean hippo_canvas_window_button_release (GtkWidget *widget,
@@ -71,6 +73,7 @@
object_class->dispose = hippo_canvas_window_dispose;
object_class->finalize = hippo_canvas_window_finalize;
+ widget_class->realize = hippo_canvas_window_realize;
widget_class->button_press_event = hippo_canvas_window_button_press;
widget_class->button_release_event = hippo_canvas_window_button_release;
widget_class->motion_notify_event = hippo_canvas_window_motion_notify;
@@ -85,6 +88,8 @@
GtkWidget *widget = GTK_WIDGET(canvas_window);
GtkWidget *window_child;
+ gtk_widget_set_app_paintable(widget, TRUE);
+
gtk_widget_add_events(widget, HIPPO_CANVAS_EVENT_MASK);
window_child = hippo_canvas_window_child_new();
@@ -164,6 +169,16 @@
}
}
+static void
+hippo_canvas_window_realize (GtkWidget *widget)
+{
+ HippoCanvasWindow *canvas_window = HIPPO_CANVAS_WINDOW(widget);
+
+ GTK_WIDGET_CLASS(hippo_canvas_window_parent_class)->realize(widget);
+
+ hippo_canvas_helper_set_window_background(canvas_window->helper, widget->window);
+}
+
static gboolean
hippo_canvas_window_button_press(GtkWidget *widget,
GdkEventButton *event)
@@ -262,3 +277,23 @@
hippo_canvas_helper_set_root(canvas_window->helper, item);
}
+
+void
+hippo_canvas_window_set_theme(HippoCanvasWindow *canvas_window,
+ HippoCanvasTheme *theme)
+{
+ g_return_if_fail(HIPPO_IS_CANVAS_WINDOW(canvas_window));
+
+ hippo_canvas_helper_set_theme(canvas_window->helper, theme);
+ if (GTK_WIDGET_REALIZED(canvas_window))
+ hippo_canvas_helper_set_window_background(canvas_window->helper, GTK_WIDGET(canvas_window)->window);
+}
+
+HippoCanvasContext *
+hippo_canvas_window_get_context(HippoCanvasWindow *canvas_window)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS_WINDOW(canvas_window), NULL);
+
+ return HIPPO_CANVAS_CONTEXT(canvas_window->helper);
+}
+
Modified: trunk/linux/hippo/hippo-canvas-window.h
==============================================================================
--- trunk/linux/hippo/hippo-canvas-window.h (original)
+++ trunk/linux/hippo/hippo-canvas-window.h Mon Mar 24 19:05:00 2008
@@ -26,6 +26,10 @@
void hippo_canvas_window_set_root(HippoCanvasWindow *canvas_window,
HippoCanvasItem *item);
+void hippo_canvas_window_set_theme(HippoCanvasWindow *canvas_window,
+ HippoCanvasTheme *theme);
+
+HippoCanvasContext *hippo_canvas_window_get_context(HippoCanvasWindow *canvas_window);
G_END_DECLS
Modified: trunk/linux/hippo/hippo-canvas.c
==============================================================================
--- trunk/linux/hippo/hippo-canvas.c (original)
+++ trunk/linux/hippo/hippo-canvas.c Mon Mar 24 19:05:00 2008
@@ -365,7 +365,7 @@
gdk_window_set_user_data (widget->window, widget);
widget->style = gtk_style_attach (widget->style, widget->window);
- gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+ hippo_canvas_helper_set_window_background(canvas->helper, widget->window);
hippo_canvas_helper_realize(canvas->helper);
}
@@ -448,6 +448,17 @@
}
void
+hippo_canvas_set_theme(HippoCanvas *canvas,
+ HippoCanvasTheme *theme)
+{
+ g_return_if_fail(HIPPO_IS_CANVAS(canvas));
+
+ hippo_canvas_helper_set_theme(canvas->helper, theme);
+ if (GTK_WIDGET_REALIZED(canvas))
+ hippo_canvas_helper_set_window_background(canvas->helper, GTK_WIDGET(canvas)->window);
+}
+
+void
hippo_canvas_set_width(HippoCanvas *canvas,
int width)
{
@@ -456,6 +467,14 @@
hippo_canvas_helper_set_width(canvas->helper, width);
}
+HippoCanvasContext *
+hippo_canvas_get_context(HippoCanvas *canvas)
+{
+ g_return_val_if_fail(HIPPO_IS_CANVAS(canvas), NULL);
+
+ return HIPPO_CANVAS_CONTEXT(canvas->helper);
+}
+
GtkWidget *
hippo_canvas_get_canvas_for_item(HippoCanvasItem *item)
{
Modified: trunk/linux/hippo/hippo-canvas.h
==============================================================================
--- trunk/linux/hippo/hippo-canvas.h (original)
+++ trunk/linux/hippo/hippo-canvas.h Mon Mar 24 19:05:00 2008
@@ -30,11 +30,16 @@
GtkWidget* hippo_canvas_new (void);
void hippo_canvas_set_root (HippoCanvas *canvas,
HippoCanvasItem *root);
+void hippo_canvas_set_theme(HippoCanvas *canvas,
+ HippoCanvasTheme *theme);
+
void hippo_canvas_set_width (HippoCanvas *canvas,
int width);
void hippo_canvas_set_load_image_hook(HippoCanvasLoadImageHook hook);
+HippoCanvasContext *hippo_canvas_get_context(HippoCanvas *canvas);
+
GtkWidget *hippo_canvas_get_canvas_for_item(HippoCanvasItem *item);
void hippo_canvas_open_test_window(void);
Modified: trunk/python/hippo.defs
==============================================================================
--- trunk/python/hippo.defs (original)
+++ trunk/python/hippo.defs Mon Mar 24 19:05:00 2008
@@ -85,6 +85,26 @@
(gtype-id "HIPPO_TYPE_CANVAS_LINK")
)
+(define-object CanvasStyle
+ (in-module "Hippo")
+ (parent "GObject")
+ (c-name "HippoCanvasStyle")
+ (gtype-id "HIPPO_TYPE_CANVAS_STYLE")
+)
+
+(define-object CanvasTheme
+ (in-module "Hippo")
+ (parent "GObject")
+ (c-name "HippoCanvasTheme")
+ (gtype-id "HIPPO_TYPE_CANVAS_THEME")
+)
+
+(define-interface CanvasThemeEngine
+ (in-module "Hippo")
+ (c-name "HippoCanvasThemeEngine")
+ (gtype-id "HIPPO_TYPE_CANVAS_THEME_ENGINE")
+)
+
(define-object CanvasWidget
(in-module "Hippo")
(parent "HippoCanvasBox")
@@ -147,16 +167,6 @@
)
)
-(define-enum CascadeMode
- (in-module "Hippo")
- (c-name "HippoCascadeMode")
- (gtype-id "HIPPO_TYPE_CASCADE_MODE")
- (values
- '("none" "HIPPO_CASCADE_MODE_NONE")
- '("inherit" "HIPPO_CASCADE_MODE_INHERIT")
- )
-)
-
(define-enum StockColor
(in-module "Hippo")
(c-name "HippoStockColor")
@@ -329,6 +339,21 @@
)
)
+(define-method set_theme
+ (of-object "HippoCanvas")
+ (c-name "hippo_canvas_set_theme")
+ (return-type "none")
+ (parameters
+ '("HippoCanvasTheme*" "theme")
+ )
+)
+
+(define-method get_context
+ (of-object "HippoCanvas")
+ (c-name "hippo_canvas_get_context")
+ (return-type "HippoCanvasContext*")
+)
+
(define-function canvas_set_load_image_hook
(c-name "hippo_canvas_set_load_image_hook")
(return-type "none")
@@ -405,7 +430,20 @@
)
)
+(define-method set_theme
+ (of-object "HippoCanvasWindow")
+ (c-name "hippo_canvas_window_set_theme")
+ (return-type "none")
+ (parameters
+ '("HippoCanvasTheme*" "theme")
+ )
+)
+(define-method get_context
+ (of-object "HippoCanvasWindow")
+ (c-name "hippo_canvas_window_get_context")
+ (return-type "HippoCanvasContext*")
+)
;; From hippo-canvas-box.h
@@ -767,6 +805,12 @@
)
)
+(define-method get_style
+ (of-object "HippoCanvasContext")
+ (c-name "hippo_canvas_context_get_style")
+ (return-type "HippoCanvasStyle*")
+)
+
(define-method register_widget_item
(of-object "HippoCanvasContext")
(c-name "hippo_canvas_context_register_widget_item")
@@ -807,24 +851,6 @@
)
)
-(define-method affect_color
- (of-object "HippoCanvasContext")
- (c-name "hippo_canvas_context_affect_color")
- (return-type "none")
- (parameters
- '("guint32*" "color_rgba_p")
- )
-)
-
-(define-method affect_font_desc
- (of-object "HippoCanvasContext")
- (c-name "hippo_canvas_context_affect_font_desc")
- (return-type "none")
- (parameters
- '("PangoFontDescription*" "font_desc")
- )
-)
-
(define-method emit_style_changed
(of-object "HippoCanvasContext")
(c-name "hippo_canvas_context_emit_style_changed")
@@ -1274,7 +1300,6 @@
)
-
;; From hippo-canvas-style.h
(define-function canvas_style_get_type
@@ -1282,24 +1307,47 @@
(return-type "GType")
)
-(define-method affect_color
+(define-method get_theme
(of-object "HippoCanvasStyle")
- (c-name "hippo_canvas_style_affect_color")
- (return-type "none")
+ (c-name "hippo_canvas_style_get_theme")
+ (return-type "HippoCanvasTheme*")
+)
+
+(define-method get_color
+ (of-object "HippoCanvasStyle")
+ (c-name "hippo_canvas_style_get_color")
+ (return-type "gboolean")
(parameters
- '("guint32*" "color_rgba_p")
+ '("const-char*" "property_name")
+ '("gboolean" "inherit")
+ '("guint32*" "color")
)
)
-(define-method affect_font_desc
+(define-method get_double
(of-object "HippoCanvasStyle")
- (c-name "hippo_canvas_style_affect_font_desc")
- (return-type "none")
+ (c-name "hippo_canvas_style_get_double")
+ (return-type "gboolean")
(parameters
- '("PangoFontDescription*" "font_desc")
+ '("const-char*" "property_name")
+ '("gboolean" "inherit")
+ '("double*" "color")
)
)
+(define-method paint
+ (of-object "HippoCanvasStyle")
+ (c-name "hippo_canvas_style_paint")
+ (return-type "gboolean")
+ (parameters
+ '("cairo_t*" "cr")
+ '("const-char*" "name")
+ '("double" "x")
+ '("double" "y")
+ '("double" "width")
+ '("double" "height")
+ )
+)
;; From hippo-canvas-test.h
@@ -1324,6 +1372,52 @@
(return-type "HippoCanvasItem*")
)
+;; From hippo-canvas-theme-engine.h
+
+(define-function canvas_theme_engine_get_type
+ (c-name "hippo_canvas_theme_engine_get_type")
+ (return-type "GType")
+)
+
+(define-virtual paint
+ (of-object "HippoCanvasThemeEngine")
+ (return-type "gboolean")
+ (parameters
+ '("HippoCanvasStyle*" "style")
+ '("cairo_t*" "cr")
+ '("const-char*" "name")
+ '("double" "x")
+ '("double" "y")
+ '("double" "width")
+ '("double" "height")
+ )
+)
+
+;; From hippo-canvas-theme.h
+
+(define-function canvas_theme_get_type
+ (c-name "hippo_canvas_theme_get_type")
+ (return-type "GType")
+)
+
+(define-function canvas_theme_new
+ (c-name "hippo_canvas_theme_new")
+ (is-constructor-of "HippoCanvasTheme")
+ (return-type "HippoCanvasTheme*")
+ (properties
+ '("theme_engine" (optional))
+ '("application_stylesheet" (optional))
+ '("theme_stylesheet" (optional))
+ '("default_stylesheet" (optional))
+ )
+)
+
+(define-method get_theme_engine
+ (of-object "HippoCanvasTheme")
+ (c-name "hippo_canvas_theme_get_theme_engine")
+ (return-type "HippoCanvasThemeEngine*")
+)
+
;; From hippo-canvas-widgets.h
(define-function button_get_type
Modified: trunk/python/hippo.override
==============================================================================
--- trunk/python/hippo.override (original)
+++ trunk/python/hippo.override Mon Mar 24 19:05:00 2008
@@ -15,6 +15,7 @@
#include "hippo/hippo-canvas-link.h"
#include "hippo/hippo-canvas-gradient.h"
#include "hippo/hippo-canvas.h"
+#include "hippo/hippo-canvas-theme.h"
#include "hippo/hippo-canvas-widget.h"
#include "hippo/hippo-canvas-window.h"
#include "hippo/hippo-canvas-widgets.h"
@@ -836,6 +837,52 @@
pyg_gil_state_release(__py_state);
}
%%
+override hippo_canvas_style_get_color kwargs
+static PyObject *
+_wrap_hippo_canvas_style_get_color(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "property_name", "inherit", NULL };
+ char *property_name;
+ int inherit;
+ guint32 color;
+ PyObject *result;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"si:HippoCanvasStyle.get_color", kwlist, &property_name, &inherit))
+ return NULL;
+
+ if (hippo_canvas_style_get_color(HIPPO_CANVAS_STYLE(self->obj), property_name, inherit, &color)) {
+ result = PyLong_FromUnsignedLong(color);
+ } else {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+%%
+override hippo_canvas_style_get_double kwargs
+static PyObject *
+_wrap_hippo_canvas_style_get_double(PyGObject *self, PyObject *args, PyObject *kwargs)
+{
+ static char *kwlist[] = { "property_name", "inherit", NULL };
+ char *property_name;
+ int inherit;
+ double value;
+ PyObject *result;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs,"si:HippoCanvasStyle.get_double", kwlist, &property_name, &inherit))
+ return NULL;
+
+ if (hippo_canvas_style_get_double(HIPPO_CANVAS_STYLE(self->obj), property_name, inherit, &value)) {
+ result = PyFloat_FromDouble(value);
+ } else {
+ Py_INCREF(Py_None);
+ result = Py_None;
+ }
+
+ return result;
+}
+%%
override hippo_cairo_surface_from_gdk_pixbuf kwargs
static cairo_surface_t*
_cairo_surface_from_pixbuf (GdkPixbuf *pixbuf)
Added: trunk/tests/test-theme.py
==============================================================================
--- (empty file)
+++ trunk/tests/test-theme.py Mon Mar 24 19:05:00 2008
@@ -0,0 +1,50 @@
+import pygtk
+pygtk.require('2.0')
+import gtk
+import hippo
+
+window = gtk.Window()
+
+canvas = hippo.Canvas()
+theme = hippo.CanvasTheme(theme_stylesheet="test.css")
+canvas.set_theme(theme)
+
+window.add(canvas)
+canvas.show()
+
+box = hippo.CanvasBox(xalign=hippo.ALIGNMENT_FILL,
+ yalign=hippo.ALIGNMENT_FILL,
+ orientation=hippo.ORIENTATION_VERTICAL)
+canvas.set_root(box)
+canvas.set_size_request(400, 400)
+
+text = hippo.CanvasText(text="Default Text")
+box.append(text)
+
+box2 = hippo.CanvasBox(xalign=hippo.ALIGNMENT_FILL,
+ yalign=hippo.ALIGNMENT_FILL,
+ orientation=hippo.ORIENTATION_VERTICAL,
+ id="box2")
+box.append(box2)
+text = hippo.CanvasText(text="Larger Text")
+box2.append(text)
+text = hippo.CanvasText(text="Red Text", classes="important")
+box2.append(text)
+
+link = hippo.CanvasLink(text="A Link")
+box2.append(link)
+
+link = hippo.CanvasLink(text="Visited Link", visited=True)
+box2.append(link)
+
+parent = box
+for i in xrange(0, 5):
+ nested = hippo.CanvasBox(xalign=hippo.ALIGNMENT_FILL,
+ yalign=hippo.ALIGNMENT_FILL,
+ classes="nested")
+ parent.append(nested)
+ parent = nested
+
+window.show()
+
+gtk.main()
Added: trunk/tests/test.css
==============================================================================
--- (empty file)
+++ trunk/tests/test.css Mon Mar 24 19:05:00 2008
@@ -0,0 +1,39 @@
+/* The canvas itself doesn't paint a background, but it's immediate box
+ * child does.
+ */
+canvas {
+ background-color: white;
+}
+
+:link {
+ text-decoration: underline;
+ color: blue;
+}
+
+:visited {
+ text-decoration: underline;
+ color: #666666;
+}
+
+#box2 {
+ font-size: large;
+ border-top: 5px solid red;
+ border-bottom: 5px solid green;
+ border-left: 5px solid blue;
+ border-right: 5px solid yellow;
+}
+
+.important {
+ color: red;
+ font-size: larger;
+ font-style: italic;
+ border: 1px solid green;
+}
+
+.nested {
+ border: 1px solid black;
+ background-color: red;
+ padding: 2px;
+ padding-left: 4px;
+ padding-right: 4px;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]