From b53e2b6b83f0b0b0f0889322590647a723e1f999 Mon Sep 17 00:00:00 2001 From: Koos Vriezen Date: Sat, 19 Apr 2008 17:58:17 +0200 Subject: [PATCH] Work out initialisation phase for attributes Call setAttribute for each attribute. We can't do that during construct, because attribute that might point to other nodes by id. Had to make the attributes hash table public for this. It becomes too rigid when only node does that. Eg. layout wants to set attributes first, look up the root-layout, create the ClutterGroup and then traverse its children --- src/laugh-dom.c | 80 ++++++++++++++++++++++++++--------------- src/laugh-dom.h | 17 +++++++-- src/laugh-layout.c | 104 +++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 147 insertions(+), 54 deletions(-) diff --git a/src/laugh-dom.c b/src/laugh-dom.c index 071f41d..04d6ace 100644 --- a/src/laugh-dom.c +++ b/src/laugh-dom.c @@ -71,10 +71,9 @@ static LaughIdMapping _laugh_tag_map; static LaughIdMapping _laugh_attr_map; -struct _LaughNodePrivate +/*struct _LaughNodePrivate { - GHashTable *attributes; -}; +};*/ static gpointer laugh_node_parent_class = ((void *)0); @@ -88,8 +87,8 @@ static void laugh_node_dispose (GObject *object) LaughNode *node = LAUGH_NODE(object); LaughNode *child; - if (node->priv->attributes) - g_hash_table_destroy (node->priv->attributes); + if (node->attributes) + g_hash_table_destroy (node->attributes); for (child = node->first_child; child; ) { LaughNode *tmp = child->next_sibling; @@ -100,26 +99,33 @@ static void laugh_node_dispose (GObject *object) G_OBJECT_CLASS (laugh_node_parent_class)->dispose (object); } -static -void _laugh_node_set_attribute (LaughNode *node, - LaughNodeAttributeId att, const gchar *val, gpointer *undo) +void laugh_node_base_set_attribute (LaughNode *node, + LaughNodeAttributeId attr, const gchar *val, gpointer *undo) { - LaughNodePrivate *priv = node->priv; + /*TODO: if val is NULL and undo is not NULL, free *undo and + * set *undo to old value*/ /* TODO: create a dynamic attribute list, create or handle undo */ - if (priv->attributes) - g_hash_table_insert (priv->attributes, - (gpointer) (long) att, (gpointer) val); + + /*This is ugly, during initialize g_hash_table_foreach call us */ + if (node->state > LaughStateInit && node->attributes) + g_hash_table_insert (node->attributes, + (gpointer) (long) attr, (gpointer) val); +} + +static +void _laugh_node_set_attribute (LaughNode *node, + LaughNodeAttributeId attr, const gchar *val, gpointer *undo) +{ + laugh_node_base_set_attribute (node, attr, val, undo); } static const gchar *_laugh_node_get_attribute (LaughNode *node, LaughNodeAttributeId att) { - LaughNodePrivate *priv = node->priv; - - if (priv->attributes) + if (node->attributes) return (gchar *) g_hash_table_lookup ( - priv->attributes, (gpointer) (long) att); + node->attributes, (gpointer) (long) att); return NULL; } @@ -127,6 +133,9 @@ static void _laugh_node_init (LaughNode *node, LaughInitializer *initializer) { LaughNode *child; + if (node->attributes) + g_hash_table_foreach (node->attributes, laugh_attributes_set, node); + for (child = node->first_child; child; child = child->next_sibling) laugh_node_init (child, initializer); } @@ -149,7 +158,7 @@ static void laugh_node_class_init (LaughNodeClass *klass) klass->get_attribute = _laugh_node_get_attribute; klass->init = _laugh_node_init; - g_type_class_add_private (gobject_class, sizeof (LaughNodePrivate)); + /*g_type_class_add_private (gobject_class, sizeof (LaughNodePrivate));*/ laugh_node_signals[INITIALIZED] = g_signal_new ("initialized", @@ -208,6 +217,8 @@ static void laugh_node_class_init (LaughNodeClass *klass) _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdTop, "top"); _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdWidth, "width"); _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdHeight, "height"); + _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdRight, "right"); + _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBottom, "bottom"); _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgColor, "background-color"); _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgColor1, "backgroundColor"); _laugh_add_mapping (&_laugh_attr_map, LaughAttrIdBgImage, "backgroundImage"); @@ -256,13 +267,14 @@ static void laugh_node_instance_init (GTypeInstance *instance, gpointer g_class) { LaughNode *self = (LaughNode *)instance; - self->priv = LAUGH_NODE_GET_PRIVATE (self); + /*self->priv = LAUGH_NODE_GET_PRIVATE (self);*/ + self->state = LaughStateInit; self->parent_node = NULL; self->first_child = NULL; self->previous_sibling = NULL; self->next_sibling = NULL; - self->priv->attributes = NULL; + self->attributes = NULL; } GType laugh_node_get_type (void) @@ -328,17 +340,21 @@ void _lauch_document_mime_type (LaughIO *io, const gchar *mime, gpointer d) static void _lauch_document_completed (LaughIO *io, gsize sz, gpointer data, gpointer d) { - LaughNode *node = LAUGH_NODE (d); + LaughInitializer *initializer = (LaughInitializer *)d; + LaughNode *node = initializer->node; g_printf ("_lauch_document_completed: %u\n", sz); if (data) { laugh_node_set_inner_xml (node, (const gchar *) data); g_free (data); + + if (node->first_child) + laugh_node_init (node->first_child, initializer); } g_object_unref (G_OBJECT (io)); - /*TODO init children and wait for initialized signals*/ + /*TODO wait for initialized signals*/ laugh_node_base_emit_initialized (node); } @@ -346,12 +362,13 @@ static void _laugh_document_init (LaughNode *doc, LaughInitializer *initializer) { LaughDocumentPrivate *priv = LAUGH_DOCUMENT (doc)->priv; + initializer->node = doc; priv->io = laugh_io_new (priv->uri); g_signal_connect (G_OBJECT (priv->io), "mime-type", (GCallback) _lauch_document_mime_type, (gpointer) doc); g_signal_connect (G_OBJECT (priv->io), "completed", - (GCallback) _lauch_document_completed, (gpointer) doc); + (GCallback) _lauch_document_completed, (gpointer) initializer); laugh_io_open (priv->io); } @@ -438,7 +455,7 @@ LaughNode *laugh_node_new (LaughDocument *document, LaughNodeTagId id, { LaughNode *node = LAUGH_NODE (g_object_new (LAUGH_TYPE_NODE, NULL)); - laugh_node_base_init (document, node, id, attrs); + laugh_node_base_construct (document, node, id, attrs); return node; } @@ -448,18 +465,24 @@ LaughDocument *laugh_document_new (const gchar *uri) LaughDocument *d = LAUGH_DOCUMENT(g_object_new (LAUGH_TYPE_DOCUMENT, NULL)); LaughNode *node = (LaughNode *)d; - laugh_node_base_init (d, node, LaughTagIdDocument, NULL); + laugh_node_base_construct (d, node, LaughTagIdDocument, NULL); d->priv->uri = g_strdup (uri); return d; } -void laugh_node_base_init (LaughDocument *document, LaughNode *node, +void laugh_node_base_construct (LaughDocument *document, LaughNode *node, LaughNodeTagId id, GHashTable *attributes) { node->id = id; node->document = document; - node->priv->attributes = attributes; + node->attributes = attributes; +} + +void laugh_attributes_set (gpointer key, gpointer val, gpointer data) +{ + laugh_node_set_attribute ((LaughNode *)data, + (LaughNodeAttributeId) (long) key, (const gchar *) val, NULL); } void laugh_node_base_emit_initialized (LaughNode *node) @@ -548,7 +571,6 @@ void laugh_node_set_inner_xml (LaughNode *node, const gchar *xml) static void _laugh_node_get_outer_xml (LaughNode *node, GString *buffer, int sp) { - LaughNodePrivate *priv = node->priv; gchar *indent = ""; if (sp > 0) { @@ -560,10 +582,10 @@ static void _laugh_node_get_outer_xml (LaughNode *node, GString *buffer, int sp) g_string_append_c (buffer, '<'); g_string_append (buffer, laugh_tag_from_id (node->id)); - if (priv->attributes) { + if (node->attributes) { GHashTableIter iter; gpointer key, value; - g_hash_table_iter_init (&iter, priv->attributes); + g_hash_table_iter_init (&iter, node->attributes); while (g_hash_table_iter_next (&iter, &key, &value)) { g_string_append_c (buffer, ' '); g_string_append (buffer, laugh_attribute_from_id ((long) key)); diff --git a/src/laugh-dom.h b/src/laugh-dom.h index 4aca408..2b57aae 100644 --- a/src/laugh-dom.h +++ b/src/laugh-dom.h @@ -85,7 +85,9 @@ typedef enum _LaughNodeTagId LaughNodeTagId; typedef enum _LaughNodeAttributeId LaughNodeAttributeId; enum _LaughNodeState { - StateInit, StateBegun, StatePaused, StateStopped, StateFreezed + LaughStateInit, LaughStateInitialized, + LaughStateBegun, LaughStatePaused, + LaughStateStopped, LaughStateFreezed }; enum _LaughNodeTagId { @@ -115,6 +117,8 @@ enum _LaughNodeAttributeId { LaughAttrIdTop, LaughAttrIdWidth, LaughAttrIdHeight, + LaughAttrIdRight, + LaughAttrIdBottom, LaughAttrIdBgColor, LaughAttrIdBgColor1, LaughAttrIdBgImage, @@ -164,6 +168,7 @@ enum _LaughNodeAttributeId { struct _LaughInitializer { + LaughNode *node; /*ClutterGroup *parent_region*/ LaughTimingSegment *parent_segment; LaughTimingSegment *previous_segment; @@ -182,10 +187,11 @@ struct _LaughNode LaughNode *first_child; LaughNode *last_child; LaughDocument *document; + GHashTable *attributes; LaughNodeState state; /*< private >*/ - LaughNodePrivate *priv; + /*LaughNodePrivate *priv;*/ }; struct _LaughNodeClass @@ -244,9 +250,12 @@ LaughNode *laugh_node_new (LaughDocument *document, LaughNodeTagId id, LaughDocument *laugh_document_new (const gchar *uri); /* sub classing */ -void laugh_node_base_init (LaughDocument *document, LaughNode *node, +void laugh_node_base_construct (LaughDocument *document, LaughNode *node, LaughNodeTagId id, GHashTable *attributes); +void laugh_node_base_set_attribute (LaughNode *node, + LaughNodeAttributeId attr, const gchar *val, gpointer *undo); + void laugh_node_base_emit_initialized (LaughNode *node); /* attributes */ @@ -256,6 +265,8 @@ const gchar *laugh_node_get_attribute (LaughNode *node, void laugh_node_set_attribute (LaughNode *node, LaughNodeAttributeId attr, const gchar *val, gpointer *undo); +void laugh_attributes_set (gpointer key, gpointer val, gpointer data); + /* (de)serializing */ void laugh_node_set_inner_xml (LaughNode *node, const gchar *xml); diff --git a/src/laugh-layout.c b/src/laugh-layout.c index 5ac15c9..90e6725 100644 --- a/src/laugh-layout.c +++ b/src/laugh-layout.c @@ -95,22 +95,76 @@ _lauch_layout_completed (LaughIO *io, gsize sz, gpointer data, gpointer d) static void _laugh_layout_init (LaughNode *node, LaughInitializer *initializer) { - LaughLayoutPrivate *priv = LAUGH_LAYOUT (node)->priv; - const gchar *bg_image = laugh_node_get_attribute (node, - g_quark_from_string ("backgroundImage")); + LaughNode *child; - if (bg_image) { - priv->io = laugh_io_new (bg_image); + if (node->attributes) + g_hash_table_foreach (node->attributes, laugh_attributes_set, node); - g_signal_connect (G_OBJECT (priv->io), "mime-type", - (GCallback) _lauch_layout_mime_type, (gpointer) node); - g_signal_connect (G_OBJECT (priv->io), "completed", - (GCallback) _lauch_layout_completed, (gpointer) node); + /*TODO create ClutterGroup */ - laugh_io_open (priv->io); - } else { - laugh_node_base_emit_initialized (node); + for (child = node->first_child; child; child = child->next_sibling) + laugh_node_init (child, initializer); +} + +static void _laugh_layout_set_attribute (LaughNode *node, + LaughNodeAttributeId att, const gchar *val, gpointer *undo) +{ + const gchar *value = val; + gboolean need_sizing = FALSE; + LaughLayout *self = (LaughLayout *)node; + + laugh_node_base_set_attribute (node, att, val, undo); + g_printf ("_laugh_layout_set_attribute %s=%s\n", laugh_attribute_from_id (att), value); + + if (!val && undo) + val = *(const gchar **)undo; + + switch (att) { + case LaughAttrIdLeft: + laugh_size_set_string (&self->size_setting.left, value); + need_sizing = TRUE; + break; + case LaughAttrIdTop: + laugh_size_set_string (&self->size_setting.top, value); + need_sizing = TRUE; + break; + case LaughAttrIdWidth: + laugh_size_set_string (&self->size_setting.width, value); + need_sizing = TRUE; + break; + case LaughAttrIdHeight: + laugh_size_set_string (&self->size_setting.height, value); + need_sizing = TRUE; + break; + case LaughAttrIdRight: + laugh_size_set_string (&self->size_setting.right, value); + need_sizing = TRUE; + break; + case LaughAttrIdBottom: + laugh_size_set_string (&self->size_setting.bottom, value); + need_sizing = TRUE; + break; + case LaughAttrIdBgColor: + case LaughAttrIdBgColor1: + /*TODO destory existing CluttorActor */ + /*TODO create CluttorActor */ + break; + case LaughAttrIdBgImage: + /*TODO destory existing CluttorActor */ + if (value) { + self->priv->io = laugh_io_new (value); + + g_signal_connect (G_OBJECT (self->priv->io), "mime-type", + (GCallback) _lauch_layout_mime_type, (gpointer) node); + g_signal_connect (G_OBJECT (self->priv->io), "completed", + (GCallback) _lauch_layout_completed, (gpointer) node); + + laugh_io_open (self->priv->io); + } + break; + /*TODO showBackground */ } + //TODO if (node->state > LaughStateInit && need_sizing) } static void laugh_layout_class_init (LaughLayoutClass *klass) @@ -123,6 +177,7 @@ static void laugh_layout_class_init (LaughLayoutClass *klass) gobject_class->finalize = laugh_layout_finalize; gobject_class->dispose = laugh_layout_dispose; node_class->init = _laugh_layout_init; + node_class->set_attribute = _laugh_layout_set_attribute; g_type_class_add_private (gobject_class, sizeof (LaughLayoutPrivate)); } @@ -160,16 +215,21 @@ GType laugh_layout_get_type (void) void laugh_size_set_string (LaughSize *size, const gchar *value) { char *ep; - char *p = strchr (value, '%'); - - if (p) { - size->abs_size = 0.0; - size->perc_size = strtod (value, &ep); - size->is_set = ep != value; + char *p; + + if (value) { + p = strchr (value, '%'); + if (p) { + size->abs_size = 0.0; + size->perc_size = strtod (value, &ep); + size->is_set = ep != value; + } else { + size->abs_size = strtod (value, &ep); + size->perc_size = 0.0; + size->is_set = ep != value; + } } else { - size->abs_size = strtod (value, &ep); - size->perc_size = 0.0; - size->is_set = ep != value; + size->is_set = FALSE; } } @@ -230,7 +290,7 @@ LaughNode *laugh_layout_new (LaughDocument *doc, LaughNodeTagId id, { LaughNode *node = LAUGH_NODE(g_object_new (LAUGH_TYPE_LAYOUT, NULL)); - laugh_node_base_init (doc, node, id, attributes); + laugh_node_base_construct (doc, node, id, attributes); return node; } -- 2.11.4.GIT