From c075d26fb2abcd53821c816fe1feb20e0578cce1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 14 May 2010 16:42:50 +0100 Subject: [PATCH] actor: Add ActorMeta, a base class for actor modifiers ClutterActorMeta is a base, abstract class that can be used to derive classes that are attached to a ClutterActor instance in order to modify the way an actor is painted, sized/positioned or responds to events. A typed container for ActorMeta instances is also provided to the sub-classes can be attached to an Actor. --- clutter/Makefile.am | 3 + clutter/clutter-actor-meta-private.h | 42 +++ clutter/clutter-actor-meta.c | 413 +++++++++++++++++++++++++++ clutter/clutter-actor-meta.h | 84 ++++++ clutter/clutter-types.h | 4 + clutter/clutter.h | 1 + 6 files changed, 547 insertions(+) create mode 100644 clutter/clutter-actor-meta-private.h create mode 100644 clutter/clutter-actor-meta.c create mode 100644 clutter/clutter-actor-meta.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index cb0a6c0ef..eef680ccd 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -65,6 +65,7 @@ AM_CFLAGS = $(CLUTTER_CFLAGS) $(MAINTAINER_CFLAGS) $(GCOV_CFLAGS) # please, keep this sorted alphabetically source_h = \ + $(srcdir)/clutter-actor-meta.h \ $(srcdir)/clutter-actor.h \ $(srcdir)/clutter-alpha.h \ $(srcdir)/clutter-animatable.h \ @@ -138,6 +139,7 @@ include $(top_srcdir)/build/autotools/Makefile.am.enums # please, keep this sorted alphabetically source_c = \ + $(srcdir)/clutter-actor-meta.c \ $(srcdir)/clutter-actor.c \ $(srcdir)/clutter-alpha.c \ $(srcdir)/clutter-animatable.c \ @@ -206,6 +208,7 @@ source_c_priv = \ $(NULL) source_h_priv = \ + $(srcdir)/clutter-actor-meta-private.h \ $(srcdir)/clutter-bezier.h \ $(srcdir)/clutter-debug.h \ $(srcdir)/clutter-keysyms-table.h \ diff --git a/clutter/clutter-actor-meta-private.h b/clutter/clutter-actor-meta-private.h new file mode 100644 index 000000000..e880d025f --- /dev/null +++ b/clutter/clutter-actor-meta-private.h @@ -0,0 +1,42 @@ +#ifndef __CLUTTER_ACTOR_META_PRIVATE_H__ +#define __CLUTTER_ACTOR_META_PRIVATE_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_META_GROUP (_clutter_meta_group_get_type ()) +#define CLUTTER_META_GROUP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_META_GROUP, ClutterMetaGroup)) +#define CLUTTER_IS_META_GROUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_META_GROUP)) + +typedef struct _ClutterMetaGroup ClutterMetaGroup; +typedef struct _ClutterMetaGroupClass ClutterMetaGroupClass; + +struct _ClutterMetaGroup +{ + GObject parent_instance; + + ClutterActor *actor; + + GList *meta; +}; + +struct _ClutterMetaGroupClass +{ + GObjectClass parent_class; +}; + +GType _clutter_meta_group_get_type (void) G_GNUC_CONST; + +void _clutter_meta_group_add_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta); +void _clutter_meta_group_remove_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta); +G_CONST_RETURN GList *_clutter_meta_group_peek_metas (ClutterMetaGroup *group); +void _clutter_meta_group_clear_metas (ClutterMetaGroup *group); +ClutterActorMeta * _clutter_meta_group_get_meta (ClutterMetaGroup *group, + const gchar *name); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_META_PRIVATE_H__ */ diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c new file mode 100644 index 000000000..e8c79b031 --- /dev/null +++ b/clutter/clutter-actor-meta.c @@ -0,0 +1,413 @@ +/** + * SECTION:ClutterActorMeta + * @Title: ClutterActorMeta + * @Short_Description: Base class of actor modifiers + * + * #ClutterActorMeta is an abstract class providing a common API for + * modifiers of #ClutterActor + * + * A #ClutterActorMeta can only be owned by a single #ClutterActor at + * any time + * + * #ClutterActorMeta is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-actor-meta-private.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +struct _ClutterActorMetaPrivate +{ + ClutterActor *actor; + + gchar *name; + + guint is_enabled : 1; +}; + +enum +{ + PROP_0, + + PROP_ACTOR, + PROP_NAME, + PROP_ENABLED +}; + +G_DEFINE_ABSTRACT_TYPE (ClutterActorMeta, + clutter_actor_meta, + G_TYPE_INITIALLY_UNOWNED); + +static void +clutter_actor_meta_real_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + meta->priv->actor = actor; +} + +static void +clutter_actor_meta_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + + switch (prop_id) + { + case PROP_NAME: + clutter_actor_meta_set_name (meta, g_value_get_string (value)); + break; + + case PROP_ENABLED: + clutter_actor_meta_set_enabled (meta, g_value_get_boolean (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_actor_meta_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject); + + switch (prop_id) + { + case PROP_ACTOR: + g_value_set_object (value, meta->priv->actor); + break; + + case PROP_NAME: + g_value_set_string (value, meta->priv->name); + break; + + case PROP_ENABLED: + g_value_set_boolean (value, meta->priv->is_enabled); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_actor_meta_finalize (GObject *gobject) +{ + ClutterActorMetaPrivate *priv = CLUTTER_ACTOR_META (gobject)->priv; + + g_free (priv->name); + + G_OBJECT_CLASS (clutter_actor_meta_parent_class)->finalize (gobject); +} + +void +clutter_actor_meta_class_init (ClutterActorMetaClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (ClutterActorMetaPrivate)); + + klass->set_actor = clutter_actor_meta_real_set_actor; + + gobject_class->set_property = clutter_actor_meta_set_property; + gobject_class->get_property = clutter_actor_meta_get_property; + gobject_class->finalize = clutter_actor_meta_finalize; + + /** + * ClutterActorMeta:actor: + * + * The #ClutterActor attached to the #ClutterActorMeta instance + * + * Since: 1.4 + */ + pspec = g_param_spec_object ("actor", + "Actor", + "The actor attached to the meta", + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READABLE); + g_object_class_install_property (gobject_class, PROP_ACTOR, pspec); + + /** + * ClutterActorMeta:name: + * + * The unique name to access the #ClutterActorMeta + * + * Since: 1.4 + */ + pspec = g_param_spec_string ("name", + "Name", + "The name of the meta", + NULL, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY); + g_object_class_install_property (gobject_class, PROP_NAME, pspec); + + /** + * ClutterActorMeta:enabled: + * + * Whether or not the #ClutterActorMeta is enabled + * + * Since: 1.4 + */ + pspec = g_param_spec_boolean ("enabled", + "Enabled", + "Whether the meta is enabled", + TRUE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_ENABLED, pspec); +} + +void +clutter_actor_meta_init (ClutterActorMeta *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, + CLUTTER_TYPE_ACTOR_META, + ClutterActorMetaPrivate); + + self->priv->is_enabled = TRUE; +} + +/** + * clutter_actor_meta_set_name: + * @meta: a #ClutterActorMeta + * @name: the name of @meta + * + * Sets the name of @meta + * + * The name can be used to identify the #ClutterActorMeta instance + * + * Since: 1.4 + */ +void +clutter_actor_meta_set_name (ClutterActorMeta *meta, + const gchar *name) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + if (g_strcmp0 (meta->priv->name, name) == 0) + return; + + g_free (meta->priv->name); + meta->priv->name = g_strdup (name); + + g_object_notify (G_OBJECT (meta), "name"); +} + +/** + * clutter_actor_meta_get_name: + * @meta: a #ClutterActorMeta + * + * Retrieves the name set using clutter_actor_meta_set_name() + * + * Return value: (transfer none): the name of the #ClutterActorMeta + * instance, or %NULL if none was set. The returned string is owned + * by the #ClutterActorMeta instance and it should not be modified + * or freed + * + * Since: 1.4 + */ +G_CONST_RETURN gchar * +clutter_actor_meta_get_name (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL); + + return meta->priv->name; +} + +/** + * clutter_actor_meta_set_enabled: + * @meta: a #ClutterActorMeta + * @is_enabled: whether @meta is enabled + * + * Sets whether @meta should be enabled or not + * + * Since: 1.4 + */ +void +clutter_actor_meta_set_enabled (ClutterActorMeta *meta, + gboolean is_enabled) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + + is_enabled = !!is_enabled; + + if (meta->priv->is_enabled == is_enabled) + return; + + meta->priv->is_enabled = is_enabled; + + g_object_notify (G_OBJECT (meta), "enabled"); +} + +/** + * clutter_actor_meta_get_enabled: + * @meta: a #ClutterActorMeta + * + * Retrieves whether @meta is enabled + * + * Return value: %TRUE if the #ClutterActorMeta instance is enabled + * + * Since: 1.4 + */ +gboolean +clutter_actor_meta_get_enabled (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), FALSE); + + return meta->priv->is_enabled; +} + +/* + * _clutter_actor_meta_set_actor + * @meta: a #ClutterActorMeta + * @actor: a #ClutterActor or %NULL + * + * Sets or unsets a back pointer to the #ClutterActor that owns + * the @meta + * + * Since: 1.4 + */ +void +_clutter_actor_meta_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + g_return_if_fail (actor == NULL || CLUTTER_IS_ACTOR (actor)); + + CLUTTER_ACTOR_META_GET_CLASS (meta)->set_actor (meta, actor); +} + +/** + * clutter_actor_meta_get_actor: + * @meta: a #ClutterActorMeta + * + * Retrieves a pointer to the #ClutterActor that owns @meta + * + * Return value: (transfer none): a pointer to a #ClutterActor or %NULL + * + * Since: 1.4 + */ +ClutterActor * +clutter_actor_meta_get_actor (ClutterActorMeta *meta) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR_META (meta), NULL); + + return meta->priv->actor; +} + +G_DEFINE_TYPE (ClutterMetaGroup, _clutter_meta_group, G_TYPE_OBJECT); + +static void +_clutter_meta_group_dispose (GObject *gobject) +{ + _clutter_meta_group_clear_metas (CLUTTER_META_GROUP (gobject)); + + G_OBJECT_CLASS (_clutter_meta_group_parent_class)->dispose (gobject); +} + +static void +_clutter_meta_group_class_init (ClutterMetaGroupClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = _clutter_meta_group_dispose; +} + +static void +_clutter_meta_group_init (ClutterMetaGroup *self) +{ +} + +void +_clutter_meta_group_add_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta) +{ + if (meta->priv->actor != NULL) + { + g_warning ("The meta of type '%s' with name '%s' is " + "already attached to actor '%s'", + G_OBJECT_TYPE_NAME (meta), + meta->priv->name != NULL + ? meta->priv->name + : "", + clutter_actor_get_name (meta->priv->actor) != NULL + ? clutter_actor_get_name (meta->priv->actor) + : G_OBJECT_TYPE_NAME (meta->priv->actor)); + return; + } + + group->meta = g_list_append (group->meta, meta); + g_object_ref_sink (meta); + + _clutter_actor_meta_set_actor (meta, group->actor); +} + +void +_clutter_meta_group_remove_meta (ClutterMetaGroup *group, + ClutterActorMeta *meta) +{ + if (meta->priv->actor != group->actor) + { + g_warning ("The meta of type '%s' with name '%s' is not " + "attached to the actor '%s'", + G_OBJECT_TYPE_NAME (meta), + meta->priv->name != NULL + ? meta->priv->name + : "", + clutter_actor_get_name (group->actor) != NULL + ? clutter_actor_get_name (group->actor) + : G_OBJECT_TYPE_NAME (group->actor)); + return; + } + + _clutter_actor_meta_set_actor (meta, NULL); + + group->meta = g_list_remove (group->meta, meta); + g_object_unref (meta); +} + +G_CONST_RETURN GList * +_clutter_meta_group_peek_metas (ClutterMetaGroup *group) +{ + return group->meta; +} + +void +_clutter_meta_group_clear_metas (ClutterMetaGroup *group) +{ + g_list_foreach (group->meta, (GFunc) _clutter_actor_meta_set_actor, NULL); + + g_list_foreach (group->meta, (GFunc) g_object_unref, NULL); + g_list_free (group->meta); + group->meta = NULL; +} + +ClutterActorMeta * +_clutter_meta_group_get_meta (ClutterMetaGroup *group, + const gchar *name) +{ + GList *l; + + for (l = group->meta; l != NULL; l = l->next) + { + ClutterActorMeta *meta = l->data; + + if (g_strcmp0 (meta->priv->name, name) == 0) + return meta; + } + + return NULL; +} diff --git a/clutter/clutter-actor-meta.h b/clutter/clutter-actor-meta.h new file mode 100644 index 000000000..4c8ed5e01 --- /dev/null +++ b/clutter/clutter-actor-meta.h @@ -0,0 +1,84 @@ +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ACTOR_META_H__ +#define __CLUTTER_ACTOR_META_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTOR_META (clutter_actor_meta_get_type ()) +#define CLUTTER_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMeta)) +#define CLUTTER_IS_ACTOR_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTOR_META)) +#define CLUTTER_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) +#define CLUTTER_IS_ACTOR_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTOR_META)) +#define CLUTTER_ACTOR_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTOR_META, ClutterActorMetaClass)) + +typedef struct _ClutterActorMetaPrivate ClutterActorMetaPrivate; +typedef struct _ClutterActorMetaClass ClutterActorMetaClass; + +/** + * ClutterActorMeta: + * + * The ClutterActorMeta structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterActorMeta +{ + /*< private >*/ + GInitiallyUnowned parent_instance; + + ClutterActorMetaPrivate *priv; +}; + +/** + * ClutterActorMetaClass: + * @set_actor: virtual function, invoked when attaching and detaching + * a #ClutterActorMeta instance to a #ClutterActor + * + * The ClutterActorMetaClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterActorMetaClass +{ + /*< private >*/ + GInitiallyUnownedClass parent_class; + + /*< public >*/ + void (* set_actor) (ClutterActorMeta *meta, + ClutterActor *actor); + + /*< private >*/ + void (* _clutter_meta1) (void); + void (* _clutter_meta2) (void); + void (* _clutter_meta3) (void); + void (* _clutter_meta4) (void); + void (* _clutter_meta5) (void); + void (* _clutter_meta6) (void); + void (* _clutter_meta7) (void); +}; + +GType clutter_actor_meta_get_type (void) G_GNUC_CONST; + +void clutter_actor_meta_set_name (ClutterActorMeta *meta, + const gchar *name); +G_CONST_RETURN gchar *clutter_actor_meta_get_name (ClutterActorMeta *meta); +void clutter_actor_meta_set_enabled (ClutterActorMeta *meta, + gboolean is_enabled); +gboolean clutter_actor_meta_get_enabled (ClutterActorMeta *meta); + +ClutterActor * clutter_actor_meta_get_actor (ClutterActorMeta *meta); + +/* private */ +void _clutter_actor_meta_set_actor (ClutterActorMeta *meta, + ClutterActor *actor); + +G_END_DECLS + +#endif /* __CLUTTER_ACTOR_META_H__ */ diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index 72090fa2a..ca7ba4be6 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -40,12 +40,16 @@ G_BEGIN_DECLS /* Forward delarations to avoid header catch 22's */ typedef struct _ClutterActor ClutterActor; + typedef struct _ClutterStage ClutterStage; typedef struct _ClutterContainer ClutterContainer; /* dummy */ typedef struct _ClutterChildMeta ClutterChildMeta; typedef struct _ClutterLayoutMeta ClutterLayoutMeta; + typedef struct _ClutterAnimator ClutterAnimator; +typedef struct _ClutterActorMeta ClutterActorMeta; + typedef union _ClutterEvent ClutterEvent; /** diff --git a/clutter/clutter.h b/clutter/clutter.h index f56876173..c6dd78f68 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -31,6 +31,7 @@ #include "clutter-deprecated.h" #include "clutter-actor.h" +#include "clutter-actor-meta.h" #include "clutter-alpha.h" #include "clutter-animatable.h" #include "clutter-animation.h"