From c075d26fb2abcd53821c816fe1feb20e0578cce1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 14 May 2010 16:42:50 +0100 Subject: [PATCH 01/24] 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" From 0e0db0d6242f84c8fb44ba57ec46d6dff5f265b3 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Tue, 11 May 2010 17:09:13 +0100 Subject: [PATCH 02/24] action: Add ClutterAction ClutterAction is an abstract class that should be used as the ancestor for objects that change how an actor behaves when dealing with events coming from user input. --- clutter/Makefile.am | 2 + clutter/clutter-action.c | 61 +++++++++++++++ clutter/clutter-action.h | 94 +++++++++++++++++++++++ clutter/clutter-actor.c | 160 +++++++++++++++++++++++++++++++++++++-- clutter/clutter-types.h | 1 + clutter/clutter.h | 1 + 6 files changed, 312 insertions(+), 7 deletions(-) create mode 100644 clutter/clutter-action.c create mode 100644 clutter/clutter-action.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index eef680ccd..e0ba87ad6 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-action.h \ $(srcdir)/clutter-actor-meta.h \ $(srcdir)/clutter-actor.h \ $(srcdir)/clutter-alpha.h \ @@ -139,6 +140,7 @@ include $(top_srcdir)/build/autotools/Makefile.am.enums # please, keep this sorted alphabetically source_c = \ + $(srcdir)/clutter-action.c \ $(srcdir)/clutter-actor-meta.c \ $(srcdir)/clutter-actor.c \ $(srcdir)/clutter-alpha.c \ diff --git a/clutter/clutter-action.c b/clutter/clutter-action.c new file mode 100644 index 000000000..41b956f80 --- /dev/null +++ b/clutter/clutter-action.c @@ -0,0 +1,61 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:ClutterAction + * @Title: ClutterAction + * @Short_Description: Abstract class for actor actions + * @See_Also: #ClutterEffect + * + * #ClutterAction is an abstract base class for action that modify the + * user interaction of a #ClutterActor, just like #ClutterEffect is an + * abstract class for modifiers of the appearance of a #ClutterActor. + * + * Implementations of #ClutterAction are associated to an actor and can + * provide behavioral changes when dealing with user input - for instance + * drag and drop capabilities, or scrolling, or panning. + * + * #ClutterAction is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-action.h" + +#include "clutter-debug.h" +#include "clutter-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterAction, clutter_action, CLUTTER_TYPE_ACTOR_META); + +static void +clutter_action_class_init (ClutterActionClass *klass) +{ +} + +static void +clutter_action_init (ClutterAction *self) +{ +} diff --git a/clutter/clutter-action.h b/clutter/clutter-action.h new file mode 100644 index 000000000..7f3c8501c --- /dev/null +++ b/clutter/clutter-action.h @@ -0,0 +1,94 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ACTION_H__ +#define __CLUTTER_ACTION_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ACTION (clutter_action_get_type ()) +#define CLUTTER_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ACTION, ClutterAction)) +#define CLUTTER_IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ACTION)) +#define CLUTTER_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ACTION, ClutterActionClass)) +#define CLUTTER_IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ACTION)) +#define CLUTTER_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ACTION, ClutterActionClass)) + +typedef struct _ClutterActionClass ClutterActionClass; + +/** + * ClutterAction: + * + * The ClutterAction structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterAction +{ + /*< private >*/ + ClutterActorMeta parent_instance; +}; + +/** + * ClutterActionClass: + * + * The ClutterActionClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterActionClass +{ + /*< private >*/ + ClutterActorMetaClass parent_class; + + void (* _clutter_action1) (void); + void (* _clutter_action2) (void); + void (* _clutter_action3) (void); + void (* _clutter_action4) (void); + void (* _clutter_action5) (void); + void (* _clutter_action6) (void); + void (* _clutter_action7) (void); + void (* _clutter_action8) (void); +}; + +GType clutter_action_get_type (void) G_GNUC_CONST; + +/* ClutterActor API */ +void clutter_actor_add_action (ClutterActor *self, + ClutterAction *action); +void clutter_actor_remove_action (ClutterActor *self, + ClutterAction *action); +GList *clutter_actor_get_actions (ClutterActor *self); +void clutter_actor_clear_actions (ClutterActor *self); + +G_END_DECLS + +#endif /* __CLUTTER_ACTION_H__ */ diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 4e2f46b76..a60aeeea1 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -226,17 +226,21 @@ #endif #include "clutter-actor.h" + +#include "clutter-action.h" +#include "clutter-actor-meta-private.h" #include "clutter-container.h" -#include "clutter-main.h" +#include "clutter-debug.h" #include "clutter-enum-types.h" -#include "clutter-scriptable.h" -#include "clutter-script.h" +#include "clutter-main.h" #include "clutter-marshal.h" #include "clutter-private.h" -#include "clutter-debug.h" -#include "clutter-units.h" #include "clutter-profile.h" +#include "clutter-scriptable.h" +#include "clutter-script.h" #include "clutter-stage.h" +#include "clutter-units.h" + #include "cogl/cogl.h" typedef struct _ShaderData ShaderData; @@ -391,6 +395,8 @@ struct _ClutterActorPrivate * See clutter_actor_queue_clipped_redraw() for details. */ const ClutterActorBox *oob_queue_redraw_clip; + + ClutterMetaGroup *actions; }; enum @@ -471,7 +477,9 @@ enum PROP_SHOW_ON_SET_PARENT, PROP_TEXT_DIRECTION, - PROP_HAS_POINTER + PROP_HAS_POINTER, + + PROP_ACTIONS }; enum @@ -2892,6 +2900,10 @@ clutter_actor_set_property (GObject *object, clutter_actor_set_text_direction (actor, g_value_get_enum (value)); break; + case PROP_ACTIONS: + clutter_actor_add_action (actor, g_value_get_object (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3199,12 +3211,18 @@ clutter_actor_dispose (GObject *object) destroy_shader_data (self); - if (priv->pango_context) + if (priv->pango_context != NULL) { g_object_unref (priv->pango_context); priv->pango_context = NULL; } + if (priv->actions != NULL) + { + g_object_unref (priv->actions); + priv->actions = NULL; + } + g_signal_emit (self, actor_signals[DESTROY], 0); G_OBJECT_CLASS (clutter_actor_parent_class)->dispose (object); @@ -3999,6 +4017,20 @@ clutter_actor_class_init (ClutterActorClass *klass) PROP_HAS_POINTER, pspec); + /** + * ClutterActor:actions: + * + * Adds a #ClutterAction to the actor + * + * Since: 1.4 + */ + pspec = g_param_spec_object ("actions", + "Actions", + "Adds an action to the actor", + CLUTTER_TYPE_ACTION, + CLUTTER_PARAM_WRITABLE); + g_object_class_install_property (object_class, PROP_ACTIONS, pspec); + /** * ClutterActor::destroy: * @actor: the object which received the signal @@ -10172,3 +10204,117 @@ clutter_actor_has_allocation (ClutterActor *self) CLUTTER_ACTOR_IS_VISIBLE (self) && !priv->needs_allocation; } + +/** + * clutter_actor_add_action: + * @self: a #ClutterActor + * @action: a #ClutterAction + * + * Adds @action to the list of actions applied to @self + * + * A #ClutterAction can only belong to one actor at a time + * + * The #ClutterActor will hold a reference on @action until either + * clutter_actor_remove_action() or clutter_actor_clear_actions() + * is called + * + * Since: 1.4 + */ +void +clutter_actor_add_action (ClutterActor *self, + ClutterAction *action) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + priv = self->priv; + + if (priv->actions == NULL) + { + priv->actions = g_object_new (CLUTTER_TYPE_META_GROUP, NULL); + priv->actions->actor = self; + } + + _clutter_meta_group_add_meta (priv->actions, CLUTTER_ACTOR_META (action)); + + g_object_notify (G_OBJECT (self), "actions"); +} + +/** + * clutter_actor_remove_action: + * @self: a #ClutterActor + * @action: a #ClutterAction + * + * Removes @action from the list of actions applied to @self + * + * The reference held by @self on the #ClutterAction will be released + * + * Since: 1.4 + */ +void +clutter_actor_remove_action (ClutterActor *self, + ClutterAction *action) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (action)); + + priv = self->priv; + + if (priv->actions == NULL) + return; + + _clutter_meta_group_remove_meta (priv->actions, CLUTTER_ACTOR_META (action)); + + g_object_notify (G_OBJECT (self), "actions"); +} + +/** + * clutter_actor_get_actions: + * @self: a #ClutterActor + * + * Retrieves the list of actions applied to @self + * + * Return value: (transfer container) (element-type ClutterAction): a copy + * of the list of #ClutterActions. The contents of the list are + * owned by the #ClutterActor. Use g_list_free() to free the resources + * allocated by the returned #GList + * + * Since: 1.4 + */ +GList * +clutter_actor_get_actions (ClutterActor *self) +{ + const GList *actions; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + if (self->priv->actions == NULL) + return NULL; + + actions = _clutter_meta_group_peek_metas (self->priv->actions); + + return g_list_copy ((GList *) actions); +} + +/** + * clutter_actor_clear_actions: + * @self: a #ClutterActor + * + * Clears the list of actions applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_clear_actions (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->actions == NULL) + return; + + _clutter_meta_group_clear_metas (self->priv->actions); +} diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index ca7ba4be6..597ebf38f 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -47,6 +47,7 @@ typedef struct _ClutterChildMeta ClutterChildMeta; typedef struct _ClutterLayoutMeta ClutterLayoutMeta; typedef struct _ClutterAnimator ClutterAnimator; +typedef struct _ClutterAction ClutterAction; typedef struct _ClutterActorMeta ClutterActorMeta; diff --git a/clutter/clutter.h b/clutter/clutter.h index c6dd78f68..d69f74fed 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -30,6 +30,7 @@ #include "clutter-deprecated.h" +#include "clutter-action.h" #include "clutter-actor.h" #include "clutter-actor-meta.h" #include "clutter-alpha.h" From 4fd74e71e640b0762f883a7f7c2f996c54379fee Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 12 May 2010 12:00:33 +0100 Subject: [PATCH 03/24] action: Add DragAction, an action implementing drag capabilities MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit DragAction is an Action sub-class that provides dragging capabilities to any actor. DragAction has: • drag-begin, drag-motion and drag-end signals, relaying the event information like coordinates, button and modifiers to user code; • drag-threshold property, for delaying the drag start by a given amount of pixels; • drag-handle property, to allow using other actors as the drag handle. • drag-axis property, to allow constraining the dragging to a specific axis. An interactive test demonstrating the various features is also provided. --- .gitignore | 1 + clutter/Makefile.am | 2 + clutter/clutter-drag-action.c | 813 ++++++++++++++++++++++++++++++++++ clutter/clutter-drag-action.h | 148 +++++++ clutter/clutter-marshal.list | 2 + clutter/clutter.h | 1 + tests/interactive/Makefile.am | 3 +- tests/interactive/test-drag.c | 189 ++++++++ 8 files changed, 1158 insertions(+), 1 deletion(-) create mode 100644 clutter/clutter-drag-action.c create mode 100644 clutter/clutter-drag-action.h create mode 100644 tests/interactive/test-drag.c diff --git a/.gitignore b/.gitignore index 65a694870..495821ae4 100644 --- a/.gitignore +++ b/.gitignore @@ -149,6 +149,7 @@ TAGS /tests/interactive/stamp-test-interactive /tests/interactive/test-animator /tests/interactive/test-stage-sizing +/tests/interactive/test-drag /tests/conform/stamp-test-conformance /tests/conform/test-anchors /tests/conform/test-cogl-backface-culling diff --git a/clutter/Makefile.am b/clutter/Makefile.am index e0ba87ad6..3f55d972d 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -91,6 +91,7 @@ source_h = \ $(srcdir)/clutter-container.h \ $(srcdir)/clutter-deprecated.h \ $(srcdir)/clutter-device-manager.h \ + $(srcdir)/clutter-drag-action.h \ $(srcdir)/clutter-event.h \ $(srcdir)/clutter-feature.h \ $(srcdir)/clutter-fixed.h \ @@ -166,6 +167,7 @@ source_c = \ $(srcdir)/clutter-color.c \ $(srcdir)/clutter-container.c \ $(srcdir)/clutter-device-manager.c \ + $(srcdir)/clutter-drag-action.c \ clutter-enum-types.c \ $(srcdir)/clutter-event.c \ $(srcdir)/clutter-feature.c \ diff --git a/clutter/clutter-drag-action.c b/clutter/clutter-drag-action.c new file mode 100644 index 000000000..1a34b6764 --- /dev/null +++ b/clutter/clutter-drag-action.c @@ -0,0 +1,813 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:ClutterDragAction + * @Title: ClutterDragAction + * @Short_Description: Action enabling dragging on actors + * + * #ClutterDragAction is a sub-class of #ClutterAction that implements + * all the necessary logic for dragging actors. + * + * The simplest usage of #ClutterDragAction consists in adding it to + * a #ClutterActor and connecting to the #ClutterDragAction::drag-motion + * signal handler to move the actor; for instance: + * + * |[ + * ClutterAction *action = clutter_drag_action_new (); + * + * g_signal_connect (action, "drag-motion", + * G_CALLBACK (on_drag_motion), + * NULL); + * + * clutter_actor_add_action (actor, action); + * ]| + * + * Where the on_drag_motion() signal handler calls clutter_actor_move_by() + * using the delta between motion events passed to the handler: + * + * |[ + * static void + * on_drag_motion (ClutterDragAction *action, + * ClutterActor *actor, + * gfloat delta_x, + * gfloat delta_y, + * ClutterModifierType modifiers) + * { + * clutter_actor_move_by (actor, delta_x, delta_y); + * } + * ]| + * + * It is also possible to set another #ClutterActor as the dragged actor + * by calling clutter_drag_action_set_drag_handle() from within a handle + * of the #ClutterDragAction::drag-begin signal. The drag handle must be + * parented and exist between the emission of #ClutterDragAction::drag-begin + * and #ClutterDragAction::drag-end. + * + * #ClutterDragAction is available since Clutter 1.4 + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-drag-action.h" + +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-marshal.h" +#include "clutter-private.h" + +struct _ClutterDragActionPrivate +{ + ClutterActor *stage; + + gfloat drag_threshold; + ClutterActor *drag_handle; + ClutterDragAxis drag_axis; + + gulong button_press_id; + gulong capture_id; + + gfloat press_x; + gfloat press_y; + ClutterModifierType press_state; + gint press_button; + + gfloat last_motion_x; + gfloat last_motion_y; + + gfloat transformed_press_x; + gfloat transformed_press_y; + + guint emit_delayed_press : 1; + guint in_drag : 1; +}; + +enum +{ + PROP_0, + + PROP_DRAG_THRESHOLD, + PROP_DRAG_HANDLE, + PROP_DRAG_AXIS +}; + +enum +{ + DRAG_BEGIN, + DRAG_MOTION, + DRAG_END, + + LAST_SIGNAL +}; + +static guint drag_signals[LAST_SIGNAL] = { 0, }; + +/* forward declaration */ +static gboolean on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterDragAction *action); + +G_DEFINE_TYPE (ClutterDragAction, clutter_drag_action, CLUTTER_TYPE_ACTION); + +static void +emit_drag_begin (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + + g_signal_emit (action, drag_signals[DRAG_BEGIN], 0, + actor, + priv->press_x, priv->press_y, + priv->press_button, + priv->press_state); +} + +static void +emit_drag_motion (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterActor *drag_handle = NULL; + gfloat delta_x, delta_y; + gfloat motion_x, motion_y; + + clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + + if (priv->drag_handle != NULL && !priv->emit_delayed_press) + drag_handle = priv->drag_handle; + else + drag_handle = actor; + + motion_x = motion_y = 0.0f; + clutter_actor_transform_stage_point (drag_handle, + priv->last_motion_x, + priv->last_motion_y, + &motion_x, &motion_y); + + delta_x = delta_y = 0.0f; + + switch (priv->drag_axis) + { + case CLUTTER_DRAG_AXIS_NONE: + delta_x = motion_x - priv->transformed_press_x; + delta_y = motion_y - priv->transformed_press_y; + break; + + case CLUTTER_DRAG_X_AXIS: + delta_x = motion_x - priv->transformed_press_x; + break; + + case CLUTTER_DRAG_Y_AXIS: + delta_y = motion_y - priv->transformed_press_y; + break; + + default: + g_assert_not_reached (); + return; + } + + if (priv->emit_delayed_press) + { + if (ABS (delta_x) >= priv->drag_threshold || + ABS (delta_y) >= priv->drag_threshold) + { + priv->emit_delayed_press = FALSE; + + emit_drag_begin (action, actor, NULL); + } + else + return; + } + + g_signal_emit (action, drag_signals[DRAG_MOTION], 0, + actor, + delta_x, delta_y); +} + +static void +emit_drag_end (ClutterDragAction *action, + ClutterActor *actor, + ClutterEvent *event) +{ + ClutterDragActionPrivate *priv = action->priv; + + clutter_event_get_coords (event, &priv->last_motion_x, &priv->last_motion_y); + + /* we might not have emitted ::drag-begin yet */ + if (!priv->emit_delayed_press) + g_signal_emit (action, drag_signals[DRAG_END], 0, + actor, + priv->last_motion_x, priv->last_motion_y, + clutter_event_get_button (event), + clutter_event_get_state (event)); + + /* disconnect the capture */ + if (priv->capture_id != 0) + { + g_signal_handler_disconnect (priv->stage, priv->capture_id); + priv->capture_id = 0; + } + + priv->in_drag = FALSE; +} + +static gboolean +on_captured_event (ClutterActor *stage, + ClutterEvent *event, + ClutterDragAction *action) +{ + ClutterDragActionPrivate *priv = action->priv; + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action)); + + if (!priv->in_drag) + return FALSE; + + switch (clutter_event_type (event)) + { + case CLUTTER_MOTION: + { + ClutterModifierType mods = clutter_event_get_state (event); + + /* we might miss a button-release event in case of grabs, + * so we need to check whether the button is still down + * during a motion event + */ + if (mods & CLUTTER_BUTTON1_MASK) + emit_drag_motion (action, actor, event); + else + emit_drag_end (action, actor, event); + } + break; + + case CLUTTER_BUTTON_RELEASE: + if (priv->in_drag) + emit_drag_end (action, actor, event); + break; + + default: + break; + } + + return FALSE; +} + +static gboolean +on_button_press (ClutterActor *actor, + ClutterEvent *event, + ClutterDragAction *action) +{ + ClutterDragActionPrivate *priv = action->priv; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (action))) + return FALSE; + + if (priv->stage == NULL) + priv->stage = clutter_actor_get_stage (actor); + + clutter_event_get_coords (event, &priv->press_x, &priv->press_y); + priv->press_button = clutter_event_get_button (event); + priv->press_state = clutter_event_get_state (event); + + priv->last_motion_x = priv->press_x; + priv->last_motion_y = priv->press_y; + + priv->transformed_press_x = priv->press_x; + priv->transformed_press_y = priv->press_y; + clutter_actor_transform_stage_point (actor, priv->press_x, priv->press_y, + &priv->transformed_press_x, + &priv->transformed_press_y); + + if (priv->drag_threshold == 0) + emit_drag_begin (action, actor, event); + else + priv->emit_delayed_press = TRUE; + + priv->in_drag = TRUE; + priv->capture_id = g_signal_connect_after (priv->stage, "captured-event", + G_CALLBACK (on_captured_event), + action); + + return FALSE; +} + +static void +clutter_drag_action_set_actor (ClutterActorMeta *meta, + ClutterActor *actor) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (meta)->priv; + + if (priv->button_press_id != 0) + { + ClutterActor *old_actor; + + old_actor = clutter_actor_meta_get_actor (meta); + + g_signal_handler_disconnect (old_actor, priv->button_press_id); + + if (priv->capture_id != 0) + g_signal_handler_disconnect (old_actor, priv->capture_id); + + priv->button_press_id = 0; + priv->capture_id = 0; + + priv->stage = NULL; + } + + if (actor != NULL) + priv->button_press_id = g_signal_connect (actor, "button-press-event", + G_CALLBACK (on_button_press), + meta); + + CLUTTER_ACTOR_META_CLASS (clutter_drag_action_parent_class)->set_actor (meta, actor); +} + +static void +clutter_drag_action_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterDragAction *action = CLUTTER_DRAG_ACTION (gobject); + + switch (prop_id) + { + case PROP_DRAG_THRESHOLD: + clutter_drag_action_set_drag_threshold (action, g_value_get_uint (value)); + break; + + case PROP_DRAG_HANDLE: + clutter_drag_action_set_drag_handle (action, g_value_get_object (value)); + break; + + case PROP_DRAG_AXIS: + clutter_drag_action_set_drag_axis (action, g_value_get_enum (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_drag_action_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; + + switch (prop_id) + { + case PROP_DRAG_THRESHOLD: + g_value_set_uint (value, priv->drag_threshold); + break; + + case PROP_DRAG_HANDLE: + g_value_set_object (value, priv->drag_handle); + break; + + case PROP_DRAG_AXIS: + g_value_set_enum (value, priv->drag_axis); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + } +} + +static void +clutter_drag_action_dispose (GObject *gobject) +{ + ClutterDragActionPrivate *priv = CLUTTER_DRAG_ACTION (gobject)->priv; + + if (priv->capture_id != 0) + { + if (priv->stage != NULL) + g_signal_handler_disconnect (priv->stage, priv->capture_id); + + priv->capture_id = 0; + priv->stage = NULL; + } + + if (priv->button_press_id != 0) + { + ClutterActor *actor; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (gobject)); + g_signal_handler_disconnect (actor, priv->button_press_id); + priv->button_press_id = 0; + } + + G_OBJECT_CLASS (clutter_drag_action_parent_class)->dispose (gobject); +} + +static void +clutter_drag_action_class_init (ClutterDragActionClass *klass) +{ + ClutterActorMetaClass *meta_class = CLUTTER_ACTOR_META_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + g_type_class_add_private (klass, sizeof (ClutterDragActionPrivate)); + + gobject_class->set_property = clutter_drag_action_set_property; + gobject_class->get_property = clutter_drag_action_get_property; + gobject_class->dispose = clutter_drag_action_dispose; + + meta_class->set_actor = clutter_drag_action_set_actor; + + /** + * ClutterDragAction:drag-threshold: + * + * The threshold, in pixels, that begins a drag action + * + * When set to a non-zero value, #ClutterDragAction will only emit + * #ClutterDragAction::drag-begin if the pointer has moved at least + * of the given amount of pixels since the button press event + * + * Since: 1.4 + */ + pspec = g_param_spec_uint ("drag-threshold", + "Drag Threshold", + "The amount of pixels required to start " + "dragging", + 0, G_MAXUINT, + 0, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_DRAG_THRESHOLD, pspec); + + /** + * ClutterDragAction:drag-handle: + * + * The #ClutterActor that is effectively being dragged + * + * A #ClutterDragActor will, be default, use the #ClutterActor that + * has been attached to the action; it is possible to create a + * separate #ClutterActor and use it instead. + * + * Setting this property has no effect on the #ClutterActor argument + * passed to the #ClutterDragAction signals + * + * Since: 1.4 + */ + pspec = g_param_spec_object ("drag-handle", + "Drag Handle", + "The actor that is being dragged", + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_DRAG_HANDLE, pspec); + + /** + * ClutterDragAction:drag-axis: + * + * Constraints the dragging action to the specified axis + * + * Since: 1.4 + */ + pspec = g_param_spec_enum ("drag-axis", + "Drag Axis", + "Constraints the dragging to an axis", + CLUTTER_TYPE_DRAG_AXIS, + CLUTTER_DRAG_AXIS_NONE, + CLUTTER_PARAM_READWRITE); + g_object_class_install_property (gobject_class, PROP_DRAG_AXIS, pspec); + + /** + * ClutterDragAction::drag-begin: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @event_x: the X coordinate (in stage space) of the press event + * @event_y: the Y coordinate (in stage space) of the press event + * @button: the button of the press event + * @modifiers: the modifiers of the press event + * + * The ::drag-begin signal is emitted when the #ClutterDragAction + * starts the dragging + * + * The emission of this signal can be delayed by using the + * #ClutterDragAction:drag-threshold property + * + * Since: 1.4 + */ + drag_signals[DRAG_BEGIN] = + g_signal_new (I_("drag-begin"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_begin), + NULL, NULL, + clutter_marshal_VOID__OBJECT_FLOAT_FLOAT_INT_FLAGS, + G_TYPE_NONE, 5, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT, + G_TYPE_INT, + CLUTTER_TYPE_MODIFIER_TYPE); + + /** + * ClutterDragAction::drag-motion + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @delta_x: the X component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * @delta_y: the Y component of the distance between the press event + * that began the dragging and the current position of the pointer, + * as of the latest motion event + * @modifiers: the modifiers of the latest motion event + * + * The ::drag-motion signal is emitted for each motion event after + * the #ClutterDragAction::drag-begin signal has been emitted. + * + * The components of the distance between the press event and the + * latest motion event are computed in the actor's coordinate space, + * to take into account eventual transformations. If you want the + * stage coordinates of the latest motion event you can use + * clutter_drag_action_get_motion_coords(). + * + * Since: 1.4 + */ + drag_signals[DRAG_MOTION] = + g_signal_new (I_("drag-motion"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_motion), + NULL, NULL, + clutter_marshal_VOID__OBJECT_FLOAT_FLOAT, + G_TYPE_NONE, 3, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT); + + /** + * ClutterDragAction::drag-end: + * @action: the #ClutterDragAction that emitted the signal + * @actor: the #ClutterActor attached to the action + * @event_x: the X coordinate (in stage space) of the release event + * @event_y: the Y coordinate (in stage space) of the release event + * @button: the button of the release event + * @modifiers: the modifiers of the release event + * + * The ::drag-end signal is emitted at the end of the dragging, + * when the pointer button's is released + * + * This signal is emitted if and only if the #ClutterDragAction::drag-begin + * signal has been emitted first + * + * Since: 1.4 + */ + drag_signals[DRAG_END] = + g_signal_new (I_("drag-end"), + CLUTTER_TYPE_DRAG_ACTION, + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (ClutterDragActionClass, drag_end), + NULL, NULL, + clutter_marshal_VOID__OBJECT_FLOAT_FLOAT_INT_FLAGS, + G_TYPE_NONE, 5, + CLUTTER_TYPE_ACTOR, + G_TYPE_FLOAT, + G_TYPE_FLOAT, + G_TYPE_INT, + CLUTTER_TYPE_MODIFIER_TYPE); +} + +static void +clutter_drag_action_init (ClutterDragAction *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, CLUTTER_TYPE_DRAG_ACTION, + ClutterDragActionPrivate); +} + +/** + * clutter_drag_action_new: + * + * Creates a new #ClutterDragAction instance + * + * Return value: the newly created #ClutterDragAction + * + * Since: 1.4 + */ +ClutterAction * +clutter_drag_action_new (void) +{ + return g_object_new (CLUTTER_TYPE_DRAG_ACTION, NULL); +} + +/** + * clutter_drag_action_set_drag_threshold: + * @action: a #ClutterDragAction + * @threshold: a distance, in pixels + * + * Sets the drag threshold that must be cleared by the pointer + * before @action can begin the dragging + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_threshold (ClutterDragAction *action, + guint threshold) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + priv = action->priv; + + if (priv->drag_threshold == threshold) + return; + + priv->drag_threshold = threshold; + + g_object_notify (G_OBJECT (action), "drag-threshold"); +} + +/** + * clutter_drag_action_get_drag_threshold: + * @action: a #ClutterDragAction + * + * Retrieves the value set by clutter_drag_action_set_drag_threshold() + * + * Return value: the drag threshold value, in pixels + * + * Since: 1.4 + */ +guint +clutter_drag_action_get_drag_threshold (ClutterDragAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), 0); + + return action->priv->drag_threshold; +} + +/** + * clutter_drag_action_set_drag_handle: + * @action: a #ClutterDragHandle + * @handle: a #ClutterActor + * + * Sets the actor to be used as the drag handle + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_handle (ClutterDragAction *action, + ClutterActor *handle) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + g_return_if_fail (CLUTTER_IS_ACTOR (handle)); + + priv = action->priv; + + if (priv->drag_handle == handle) + return; + + priv->drag_handle = handle; + + g_object_notify (G_OBJECT (action), "drag-handle"); +} + +/** + * clutter_drag_action_get_drag_handle: + * @action: a #ClutterDragAction + * + * Retrieves the drag handle set by clutter_drag_action_set_drag_handle() + * + * Return value: (transfer none): a #ClutterActor, used as the drag + * handle, or %NULL if none was set + * + * Since: 1.4 + */ +ClutterActor * +clutter_drag_action_get_drag_handle (ClutterDragAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), NULL); + + return action->priv->drag_handle; +} + +/** + * clutter_drag_action_set_drag_axis: + * @action: a #ClutterDragAction + * @axis: the axis to constraint the dragging to + * + * Restricts the dragging action to a specific axis + * + * Since: 1.4 + */ +void +clutter_drag_action_set_drag_axis (ClutterDragAction *action, + ClutterDragAxis axis) +{ + ClutterDragActionPrivate *priv; + + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + g_return_if_fail (axis >= CLUTTER_DRAG_AXIS_NONE && + axis <= CLUTTER_DRAG_Y_AXIS); + + priv = action->priv; + + if (priv->drag_axis == axis) + return; + + priv->drag_axis = axis; + + g_object_notify (G_OBJECT (action), "drag-axis"); +} + +/** + * clutter_drag_action_get_drag_axis: + * @action: a #ClutterDragAction + * + * Retrieves the axis constraint set by clutter_drag_action_set_drag_axis() + * + * Return value: the axis constraint + * + * Since: 1.4 + */ +ClutterDragAxis +clutter_drag_action_get_drag_axis (ClutterDragAction *action) +{ + g_return_val_if_fail (CLUTTER_IS_DRAG_ACTION (action), + CLUTTER_DRAG_AXIS_NONE); + + return action->priv->drag_axis; +} + +/** + * clutter_drag_action_get_press_coords: + * @action: a #ClutterDragAction + * @press_x: (out): return location for the press event's X coordinate + * @press_y: (out): return location for the press event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the press event + * that started the dragging + * + * Since: 1.4 + */ +void +clutter_drag_action_get_press_coords (ClutterDragAction *action, + gfloat *press_x, + gfloat *press_y) +{ + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + if (press_x) + *press_x = action->priv->press_x; + + if (press_y) + *press_y = action->priv->press_y; +} + +/** + * clutter_drag_action_get_motion_coords: + * @action: a #ClutterDragAction + * @motion_x: (out): return location for the latest motion + * event's X coordinate + * @motion_y: (out): return location for the latest motion + * event's Y coordinate + * + * Retrieves the coordinates, in stage space, of the latest motion + * event during the dragging + * + * Since: 1.4 + */ +void +clutter_drag_action_get_motion_coords (ClutterDragAction *action, + gfloat *motion_x, + gfloat *motion_y) +{ + g_return_if_fail (CLUTTER_IS_DRAG_ACTION (action)); + + if (motion_x) + *motion_x = action->priv->last_motion_x; + + if (motion_y) + *motion_y = action->priv->last_motion_y; +} diff --git a/clutter/clutter-drag-action.h b/clutter/clutter-drag-action.h new file mode 100644 index 000000000..78290dcf5 --- /dev/null +++ b/clutter/clutter-drag-action.h @@ -0,0 +1,148 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_DRAG_ACTION_H__ +#define __CLUTTER_DRAG_ACTION_H__ + +#include +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_DRAG_ACTION (clutter_drag_action_get_type ()) +#define CLUTTER_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragAction)) +#define CLUTTER_IS_DRAG_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_DRAG_ACTION)) +#define CLUTTER_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) +#define CLUTTER_IS_DRAG_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_DRAG_ACTION)) +#define CLUTTER_DRAG_ACTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_DRAG_ACTION, ClutterDragActionClass)) + +typedef struct _ClutterDragAction ClutterDragAction; +typedef struct _ClutterDragActionPrivate ClutterDragActionPrivate; +typedef struct _ClutterDragActionClass ClutterDragActionClass; + +/** + * ClutterDragAxis: + * @CLUTTER_DRAG_AXIS_NONE: No constraint + * @CLUTTER_DRAG_X_AXIS: Set a constraint on the X axis + * @CLUTTER_DRAG_Y_AXIS: Set a constraint on the Y axis + * + * The axis of the constraint that should be applied on the + * dragging action + * + * Since: 1.4 + */ +typedef enum { /*< prefix=CLUTTER_DRAG >*/ + CLUTTER_DRAG_AXIS_NONE = 0, + + CLUTTER_DRAG_X_AXIS, + CLUTTER_DRAG_Y_AXIS +} ClutterDragAxis; + +/** + * ClutterDragAction: + * + * The ClutterDragAction structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterDragAction +{ + /*< private >*/ + ClutterAction parent_instance; + + ClutterDragActionPrivate *priv; +}; + +/** + * ClutterDragActionClass: + * @drag_begin: class handler of the #ClutterDragAction::drag-begin signal + * @drag_motion: class handler of the #ClutterDragAction::drag-motion signal + * @drag_end: class handler of the #ClutterDragAction::drag-end signal + * + * The ClutterDragActionClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterDragActionClass +{ + /*< private >*/ + ClutterActionClass parent_class; + + /*< public >*/ + void (* drag_begin) (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + gint button, + ClutterModifierType modifiers); + void (* drag_motion) (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y, + ClutterModifierType modifiers); + void (* drag_end) (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + gint button, + ClutterModifierType modifiers); + + /*< private >*/ + void (* _clutter_drag_action1) (void); + void (* _clutter_drag_action2) (void); + void (* _clutter_drag_action3) (void); + void (* _clutter_drag_action4) (void); + void (* _clutter_drag_action5) (void); +}; + +GType clutter_drag_action_get_type (void) G_GNUC_CONST; + +ClutterAction * clutter_drag_action_new (void); + +void clutter_drag_action_set_drag_threshold (ClutterDragAction *action, + guint threshold); +guint clutter_drag_action_get_drag_threshold (ClutterDragAction *action); +void clutter_drag_action_set_drag_handle (ClutterDragAction *action, + ClutterActor *handle); +ClutterActor * clutter_drag_action_get_drag_handle (ClutterDragAction *action); +void clutter_drag_action_set_drag_axis (ClutterDragAction *action, + ClutterDragAxis axis); +ClutterDragAxis clutter_drag_action_get_drag_axis (ClutterDragAction *action); + +void clutter_drag_action_get_press_coords (ClutterDragAction *action, + gfloat *press_x, + gfloat *press_y); +void clutter_drag_action_get_motion_coords (ClutterDragAction *action, + gfloat *motion_x, + gfloat *motion_y); + +G_END_DECLS + +#endif /* __CLUTTER_DRAG_ACTION_H__ */ diff --git a/clutter/clutter-marshal.list b/clutter/clutter-marshal.list index 8296f9add..0ad57424f 100644 --- a/clutter/clutter-marshal.list +++ b/clutter/clutter-marshal.list @@ -10,6 +10,8 @@ VOID:INT,INT VOID:FLOAT,FLOAT VOID:INT,INT,INT,INT VOID:OBJECT +VOID:OBJECT,FLOAT,FLOAT +VOID:OBJECT,FLOAT,FLOAT,INT,FLAGS VOID:OBJECT,OBJECT,PARAM VOID:OBJECT,POINTER VOID:POINTER diff --git a/clutter/clutter.h b/clutter/clutter.h index d69f74fed..08d20887a 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -55,6 +55,7 @@ #include "clutter-color.h" #include "clutter-container.h" #include "clutter-device-manager.h" +#include "clutter-drag-action.h" #include "clutter-event.h" #include "clutter-feature.h" #include "clutter-fixed-layout.h" diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index b7e6295d3..d45caa8f5 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -48,7 +48,8 @@ UNIT_TESTS = \ test-bin-layout.c \ test-flow-layout.c \ test-box-layout.c \ - test-stage-sizing.c + test-stage-sizing.c \ + test-drag.c if X11_TESTS UNIT_TESTS += test-pixmap.c diff --git a/tests/interactive/test-drag.c b/tests/interactive/test-drag.c new file mode 100644 index 000000000..e8c479cfd --- /dev/null +++ b/tests/interactive/test-drag.c @@ -0,0 +1,189 @@ +#include +#include +#include + +static void +on_drag_begin (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + gint button, + ClutterModifierType modifiers) +{ + gboolean is_copy = (modifiers & CLUTTER_SHIFT_MASK) ? TRUE : FALSE; + ClutterActor *drag_handle = NULL; + + if (is_copy) + { + ClutterActor *stage = clutter_actor_get_stage (actor); + ClutterColor handle_color; + + drag_handle = clutter_rectangle_new (); + clutter_actor_set_size (drag_handle, 48, 48); + + clutter_color_from_string (&handle_color, "#204a87aa"); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (drag_handle), &handle_color); + + clutter_container_add_actor (CLUTTER_CONTAINER (stage), drag_handle); + clutter_actor_set_position (drag_handle, event_x, event_y); + } + else + drag_handle = actor; + + clutter_drag_action_set_drag_handle (action, drag_handle); + + clutter_actor_set_opacity (actor, 128); +} + +static void +on_drag_motion (ClutterDragAction *action, + ClutterActor *actor, + gfloat delta_x, + gfloat delta_y, + ClutterModifierType modifiers) +{ + ClutterActor *drag_handle; + + drag_handle = clutter_drag_action_get_drag_handle (action); + g_assert (drag_handle != NULL); + + clutter_actor_move_by (drag_handle, delta_x, delta_y); +} + +static void +on_drag_end (ClutterDragAction *action, + ClutterActor *actor, + gfloat event_x, + gfloat event_y, + gint button, + ClutterModifierType modifiers) +{ + ClutterActor *drag_handle; + + drag_handle = clutter_drag_action_get_drag_handle (action); + if (actor != drag_handle) + { + gfloat real_x, real_y; + ClutterActor *parent; + + /* if we are dragging a copy we can destroy the copy now + * and animate the real actor to the drop coordinates, + * transformed in the parent's coordinate space + */ + clutter_actor_animate (drag_handle, CLUTTER_LINEAR, 150, + "opacity", 0, + "signal-swapped-after::completed", + G_CALLBACK (clutter_actor_destroy), + drag_handle, + NULL); + + parent = clutter_actor_get_parent (actor); + clutter_actor_transform_stage_point (parent, event_x, event_y, + &real_x, + &real_y); + + clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 150, + "opacity", 255, + "x", real_x, + "y", real_y, + NULL); + } + else + clutter_actor_animate (actor, CLUTTER_LINEAR, 150, + "opacity", 255, + NULL); +} + +static ClutterDragAxis +get_drag_axis (const gchar *str) +{ + if (str == NULL || *str == '\0') + return CLUTTER_DRAG_AXIS_NONE; + + if (*str == 'x' || *str == 'X') + return CLUTTER_DRAG_X_AXIS; + + if (*str == 'y' || *str == 'Y') + return CLUTTER_DRAG_Y_AXIS; + + g_warn_if_reached (); + + return CLUTTER_DRAG_AXIS_NONE; +} + +static gchar *drag_axis = NULL; +static gint drag_threshold = 0; + +static GOptionEntry entries[] = { + { + "threshold", 't', + 0, + G_OPTION_ARG_INT, + &drag_threshold, + "Set the drag threshold", "PIXELS" + }, + { + "axis", 'a', + 0, + G_OPTION_ARG_STRING, + &drag_axis, + "Set the drag axis", "AXIS" + }, + + { NULL } +}; + +G_MODULE_EXPORT int +test_drag_main (int argc, char *argv[]) +{ + ClutterActor *stage, *handle; + ClutterAction *action; + ClutterColor handle_color; + GError *error; + + error = NULL; + clutter_init_with_args (&argc, &argv, + "test-drag", + entries, + NULL, + &error); + if (error != NULL) + { + g_print ("Unable to run test-drag: %s\n", error->message); + g_error_free (error); + + return EXIT_FAILURE; + } + + stage = clutter_stage_new (); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Drag Test"); + clutter_actor_set_size (stage, 800, 600); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + + clutter_color_from_string (&handle_color, "#729fcfff"); + + handle = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (handle), &handle_color); + clutter_actor_set_size (handle, 128, 128); + clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2); + clutter_actor_set_reactive (handle, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), handle); + + action = clutter_drag_action_new (); + clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action), + drag_threshold); + clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action), + get_drag_axis (drag_axis)); + + g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL); + g_signal_connect (action, "drag-motion", G_CALLBACK (on_drag_motion), NULL); + g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL); + + clutter_actor_add_action (handle, action); + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} From c007b7489b240af4fc7b3c24cdf62252757c6aa7 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Mon, 17 May 2010 14:34:31 +0100 Subject: [PATCH 04/24] action: Warn if set_name() is called multiple times --- clutter/clutter-actor-meta.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c index e8c79b031..f01df3713 100644 --- a/clutter/clutter-actor-meta.c +++ b/clutter/clutter-actor-meta.c @@ -197,6 +197,15 @@ clutter_actor_meta_set_name (ClutterActorMeta *meta, { g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); + if (meta->priv->name != NULL) + { + g_warning ("The ClutterActorMeta of type '%s' has already " + "been named '%s'", + G_OBJECT_TYPE_NAME (meta), + meta->priv->name); + return; + } + if (g_strcmp0 (meta->priv->name, name) == 0) return; From b842f0ad8edacae353facf33b9ad3d43b02a60af Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Fri, 14 May 2010 12:13:49 +0100 Subject: [PATCH 05/24] constraint: Add ClutterConstraint base class The Constraint base, abstract class should be used to implement Actor modifiers that affect the way an actor is sized or positioned inside a fixed layout manager. --- clutter/Makefile.am | 2 + clutter/clutter-actor.c | 138 ++++++++++++++++++++++++++++++++++- clutter/clutter-constraint.c | 21 ++++++ clutter/clutter-constraint.h | 100 +++++++++++++++++++++++++ clutter/clutter-types.h | 5 +- clutter/clutter.h | 1 + 6 files changed, 264 insertions(+), 3 deletions(-) create mode 100644 clutter/clutter-constraint.c create mode 100644 clutter/clutter-constraint.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 3f55d972d..9571cd232 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -88,6 +88,7 @@ source_h = \ $(srcdir)/clutter-child-meta.h \ $(srcdir)/clutter-clone.h \ $(srcdir)/clutter-color.h \ + $(srcdir)/clutter-constraint.h \ $(srcdir)/clutter-container.h \ $(srcdir)/clutter-deprecated.h \ $(srcdir)/clutter-device-manager.h \ @@ -165,6 +166,7 @@ source_c = \ $(srcdir)/clutter-child-meta.c \ $(srcdir)/clutter-clone.c \ $(srcdir)/clutter-color.c \ + $(srcdir)/clutter-constraint.c \ $(srcdir)/clutter-container.c \ $(srcdir)/clutter-device-manager.c \ $(srcdir)/clutter-drag-action.c \ diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index a60aeeea1..22ed6a60f 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -229,6 +229,7 @@ #include "clutter-action.h" #include "clutter-actor-meta-private.h" +#include "clutter-constraint.h" #include "clutter-container.h" #include "clutter-debug.h" #include "clutter-enum-types.h" @@ -397,6 +398,7 @@ struct _ClutterActorPrivate const ClutterActorBox *oob_queue_redraw_clip; ClutterMetaGroup *actions; + ClutterMetaGroup *constraints; }; enum @@ -479,7 +481,8 @@ enum PROP_TEXT_DIRECTION, PROP_HAS_POINTER, - PROP_ACTIONS + PROP_ACTIONS, + PROP_CONSTRAINTS }; enum @@ -2904,6 +2907,10 @@ clutter_actor_set_property (GObject *object, clutter_actor_add_action (actor, g_value_get_object (value)); break; + case PROP_CONSTRAINTS: + clutter_actor_add_constraint (actor, g_value_get_object (value)); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -4031,6 +4038,20 @@ clutter_actor_class_init (ClutterActorClass *klass) CLUTTER_PARAM_WRITABLE); g_object_class_install_property (object_class, PROP_ACTIONS, pspec); + /** + * ClutterActor:constraints: + * + * Adds a #ClutterConstaint to the actor + * + * Since: 1.4 + */ + pspec = g_param_spec_object ("constraints", + "Constraints", + "Adds a constraint to the actor", + CLUTTER_TYPE_CONSTRAINT, + CLUTTER_PARAM_WRITABLE); + g_object_class_install_property (object_class, PROP_CONSTRAINTS, pspec); + /** * ClutterActor::destroy: * @actor: the object which received the signal @@ -10318,3 +10339,118 @@ clutter_actor_clear_actions (ClutterActor *self) _clutter_meta_group_clear_metas (self->priv->actions); } + +/** + * clutter_actor_add_constraint: + * @self: a #ClutterActor + * @constraint: a #ClutterConstraint + * + * Adds @constraint to the list of #ClutterConstraints applied + * to @self + * + * The #ClutterActor will hold a reference on the @constraint until + * either clutter_actor_remove_constraint() or + * clutter_actor_clear_constraints() is called. + * + * Since: 1.4 + */ +void +clutter_actor_add_constraint (ClutterActor *self, + ClutterConstraint *constraint) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (constraint)); + + priv = self->priv; + + if (priv->constraints == NULL) + { + priv->constraints = g_object_new (CLUTTER_TYPE_META_GROUP, NULL); + priv->constraints->actor = self; + } + + _clutter_meta_group_add_meta (priv->constraints, + CLUTTER_ACTOR_META (constraint)); + + g_object_notify (G_OBJECT (self), "constraints"); +} + +/** + * clutter_actor_remove_constraint: + * @self: a #ClutterActor + * @constraint: a #ClutterConstraint + * + * Removes @constraint from the list of constraints applied to @self + * + * The reference held by @self on the #ClutterConstraint will be released + * + * Since: 1.4 + */ +void +clutter_actor_remove_constraint (ClutterActor *self, + ClutterConstraint *constraint) +{ + ClutterActorPrivate *priv; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (CLUTTER_IS_ACTION (constraint)); + + priv = self->priv; + + if (priv->constraints == NULL) + return; + + _clutter_meta_group_remove_meta (priv->constraints, + CLUTTER_ACTOR_META (constraint)); + + g_object_notify (G_OBJECT (self), "constraints"); +} + +/** + * clutter_actor_get_constraints: + * @self: a #ClutterActor + * + * Retrieves the list of constraints applied to @self + * + * Return value: (transfer container) (element-type ClutterConstraint): a copy + * of the list of #ClutterConstraints. The contents of the list are + * owned by the #ClutterActor. Use g_list_free() to free the resources + * allocated by the returned #GList + * + * Since: 1.4 + */ +GList * +clutter_actor_get_constraints (ClutterActor *self) +{ + const GList *constraints; + + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + + if (self->priv->constraints == NULL) + return NULL; + + constraints = _clutter_meta_group_peek_metas (self->priv->constraints); + + return g_list_copy ((GList *) constraints); +} + +/** + * clutter_actor_clear_constraints: + * @self: a #ClutterActor + * + * Clears the list of constraints applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_clear_constraints (ClutterActor *self) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + + if (self->priv->constraints == NULL) + return; + + _clutter_meta_group_clear_metas (self->priv->constraints); +} diff --git a/clutter/clutter-constraint.c b/clutter/clutter-constraint.c new file mode 100644 index 000000000..0caf41b32 --- /dev/null +++ b/clutter/clutter-constraint.c @@ -0,0 +1,21 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-constraint.h" + +#include "clutter-actor-meta-private.h" + +G_DEFINE_ABSTRACT_TYPE (ClutterConstraint, + clutter_constraint, + CLUTTER_TYPE_ACTOR_META); + +static void +clutter_constraint_class_init (ClutterConstraintClass *klass) +{ +} + +static void +clutter_constraint_init (ClutterConstraint *self) +{ +} diff --git a/clutter/clutter-constraint.h b/clutter/clutter-constraint.h new file mode 100644 index 000000000..99e6dc4de --- /dev/null +++ b/clutter/clutter-constraint.h @@ -0,0 +1,100 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_CONSTRAINT_H__ +#define __CLUTTER_CONSTRAINT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_CONSTRAINT (clutter_constraint_get_type ()) +#define CLUTTER_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONSTRAINT, ClutterConstraint)) +#define CLUTTER_IS_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONSTRAINT)) +#define CLUTTER_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_CONSTRAINT, ClutterConstraintClass)) +#define CLUTTER_IS_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CONSTRAINT)) +#define CLUTTER_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CONSTRAINT, ClutterConstraintClass)) + +typedef struct _ClutterConstraintPrivate ClutterConstraintPrivate; +typedef struct _ClutterConstraintClass ClutterConstraintClass; + +/** + * ClutterConstraint: + * + * The ClutterConstraint structure contains only + * private data and should be accessed using the provided API + * + * Since: 1.4 + */ +struct _ClutterConstraint +{ + /*< private >*/ + ClutterActorMeta parent_instance; + + ClutterConstraintPrivate *priv; +}; + +/** + * ClutterConstraintClass: + * @set_actor: virtual function, called when a constraint is applied to + * a #ClutterActor + * + * The ClutterConstraintClass structure contains + * only private data + * + * Since: 1.4 + */ +struct _ClutterConstraintClass +{ + /*< private >*/ + ClutterActorMetaClass parent_class; + + /*< private >*/ + void (* _clutter_constraint1) (void); + void (* _clutter_constraint2) (void); + void (* _clutter_constraint3) (void); + void (* _clutter_constraint4) (void); + void (* _clutter_constraint5) (void); + void (* _clutter_constraint6) (void); + void (* _clutter_constraint7) (void); + void (* _clutter_constraint8) (void); +}; + +GType clutter_constraint_get_type (void) G_GNUC_CONST; + +/* ClutterActor API */ +void clutter_actor_add_constraint (ClutterActor *actor, + ClutterConstraint *constraint); +void clutter_actor_remove_constraint (ClutterActor *actor, + ClutterConstraint *constraint); +GList *clutter_actor_get_constraints (ClutterActor *actor); +void clutter_actor_clear_constraints (ClutterActor *actor); + +G_END_DECLS + +#endif /* __CLUTTER_CONSTRAINT_H__ */ diff --git a/clutter/clutter-types.h b/clutter/clutter-types.h index 597ebf38f..9d53ea9a0 100644 --- a/clutter/clutter-types.h +++ b/clutter/clutter-types.h @@ -45,11 +45,12 @@ typedef struct _ClutterStage ClutterStage; typedef struct _ClutterContainer ClutterContainer; /* dummy */ typedef struct _ClutterChildMeta ClutterChildMeta; typedef struct _ClutterLayoutMeta ClutterLayoutMeta; +typedef struct _ClutterActorMeta ClutterActorMeta; typedef struct _ClutterAnimator ClutterAnimator; -typedef struct _ClutterAction ClutterAction; -typedef struct _ClutterActorMeta ClutterActorMeta; +typedef struct _ClutterAction ClutterAction; +typedef struct _ClutterConstraint ClutterConstraint; typedef union _ClutterEvent ClutterEvent; diff --git a/clutter/clutter.h b/clutter/clutter.h index 08d20887a..9347e0930 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -53,6 +53,7 @@ #include "clutter-child-meta.h" #include "clutter-clone.h" #include "clutter-color.h" +#include "clutter-constraint.h" #include "clutter-container.h" #include "clutter-device-manager.h" #include "clutter-drag-action.h" From 3a1162cbcffd4147f3022b3241101e3269a54169 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 12:21:54 +0100 Subject: [PATCH 06/24] animatable: Add custom properties to Animatable Like ClutterScriptable, it would be good to have the Animatable interface allow defining custom properties that can be animated. --- clutter/clutter-animatable.c | 63 ++++++++++++++++++++++++++++++++++++ clutter/clutter-animatable.h | 51 +++++++++++++++++++++-------- 2 files changed, 100 insertions(+), 14 deletions(-) diff --git a/clutter/clutter-animatable.c b/clutter/clutter-animatable.c index e448a694f..d0dde8a64 100644 --- a/clutter/clutter-animatable.c +++ b/clutter/clutter-animatable.c @@ -124,3 +124,66 @@ clutter_animatable_animate_property (ClutterAnimatable *animatable, return res; } + +GParamSpec * +clutter_animatable_find_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name) +{ + ClutterAnimatableIface *iface; + + g_return_val_if_fail (CLUTTER_IS_ANIMATABLE (animatable), NULL); + g_return_val_if_fail (CLUTTER_IS_ANIMATION (animation), NULL); + g_return_val_if_fail (property_name != NULL, NULL); + + CLUTTER_NOTE (ANIMATION, "Looking for property '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->find_property != NULL) + return iface->find_property (animatable, animation, property_name); + + return g_object_class_find_property (G_OBJECT_GET_CLASS (animatable), + property_name); +} + +void +clutter_animatable_get_initial_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + GValue *value) +{ + ClutterAnimatableIface *iface; + + g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable)); + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (property_name != NULL); + + CLUTTER_NOTE (ANIMATION, "Getting initial state of '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->get_initial_state != NULL) + iface->get_initial_state (animatable, animation, property_name, value); + else + g_object_get_property (G_OBJECT (animatable), property_name, value); +} + +void +clutter_animatable_set_final_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *value) +{ + ClutterAnimatableIface *iface; + + g_return_if_fail (CLUTTER_IS_ANIMATABLE (animatable)); + g_return_if_fail (CLUTTER_IS_ANIMATION (animation)); + g_return_if_fail (property_name != NULL); + + CLUTTER_NOTE (ANIMATION, "Setting state of property '%s'", property_name); + + iface = CLUTTER_ANIMATABLE_GET_IFACE (animatable); + if (iface->set_final_state != NULL) + iface->set_final_state (animatable, animation, property_name, value); + else + g_object_set_property (G_OBJECT (animatable), property_name, value); +} diff --git a/clutter/clutter-animatable.h b/clutter/clutter-animatable.h index a82d13a4b..04df1dc45 100644 --- a/clutter/clutter-animatable.h +++ b/clutter/clutter-animatable.h @@ -65,24 +65,47 @@ struct _ClutterAnimatableIface GTypeInterface parent_iface; /*< public >*/ - gboolean (* animate_property) (ClutterAnimatable *animatable, - ClutterAnimation *animation, - const gchar *property_name, - const GValue *initial_value, - const GValue *final_value, - gdouble progress, - GValue *value); + gboolean (* animate_property) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value); + GParamSpec *(* find_property) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name); + void (* get_initial_state) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + GValue *value); + void (* set_final_state) (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *value); }; GType clutter_animatable_get_type (void) G_GNUC_CONST; -gboolean clutter_animatable_animate_property (ClutterAnimatable *animatable, - ClutterAnimation *animation, - const gchar *property_name, - const GValue *initial_value, - const GValue *final_value, - gdouble progress, - GValue *value); +gboolean clutter_animatable_animate_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial_value, + const GValue *final_value, + gdouble progress, + GValue *value); + +GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name); +void clutter_animatable_get_initial_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + GValue *initial); +void clutter_animatable_set_final_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *final); G_END_DECLS From d9a05ac94b453ec2a4e6313aa587d2194e46cfb1 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 12:22:48 +0100 Subject: [PATCH 07/24] animation: Use the new Animatable API for custom properties The Animation class should use the Animatable API for custom properties to override finding a property definition, getting the initial state and setting the final state of an object. --- clutter/clutter-animation.c | 154 ++++++++++++++++++++++++++++-------- 1 file changed, 122 insertions(+), 32 deletions(-) diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index f7d8711b3..2c8deaa05 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -212,6 +212,7 @@ static void clutter_animation_real_completed (ClutterAnimation *self) { ClutterAnimationPrivate *priv = self->priv; + ClutterAnimatable *animatable = NULL; ClutterAnimation *animation; ClutterTimeline *timeline; ClutterTimelineDirection direction; @@ -221,6 +222,9 @@ clutter_animation_real_completed (ClutterAnimation *self) timeline = clutter_animation_get_timeline (self); direction = clutter_timeline_get_direction (timeline); + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + /* explicitly set the final state of the animation */ CLUTTER_NOTE (ANIMATION, "Set final state on object [%p]", priv->object); g_hash_table_iter_init (&iter, priv->properties); @@ -235,7 +239,12 @@ clutter_animation_real_completed (ClutterAnimation *self) else p_value = clutter_interval_peek_initial_value (interval); - g_object_set_property (priv->object, p_name, p_value); + if (animatable != NULL) + clutter_animatable_set_final_state (animatable, self, + p_name, + p_value); + else + g_object_set_property (priv->object, p_name, p_value); } /* at this point, if this animation was created by clutter_actor_animate() @@ -580,6 +589,7 @@ clutter_animation_init (ClutterAnimation *self) static inline void clutter_animation_bind_property_internal (ClutterAnimation *animation, + const gchar *property_name, GParamSpec *pspec, ClutterInterval *interval) { @@ -589,17 +599,18 @@ clutter_animation_bind_property_internal (ClutterAnimation *animation, { g_warning ("Cannot bind property '%s': the interval is out " "of bounds", - pspec->name); + property_name); return; } g_hash_table_insert (priv->properties, - g_strdup (pspec->name), + g_strdup (property_name), g_object_ref_sink (interval)); } static inline void clutter_animation_update_property_internal (ClutterAnimation *animation, + const gchar *property_name, GParamSpec *pspec, ClutterInterval *interval) { @@ -609,12 +620,12 @@ clutter_animation_update_property_internal (ClutterAnimation *animation, { g_warning ("Cannot bind property '%s': the interval is out " "of bounds", - pspec->name); + property_name); return; } g_hash_table_replace (priv->properties, - g_strdup (pspec->name), + g_strdup (property_name), g_object_ref_sink (interval)); } @@ -624,7 +635,6 @@ clutter_animation_validate_bind (ClutterAnimation *animation, GType argtype) { ClutterAnimationPrivate *priv; - GObjectClass *klass; GParamSpec *pspec; GType pspec_type; @@ -647,9 +657,22 @@ clutter_animation_validate_bind (ClutterAnimation *animation, return NULL; } - klass = G_OBJECT_GET_CLASS (priv->object); - pspec = g_object_class_find_property (klass, property_name); - if (!pspec) + if (CLUTTER_IS_ANIMATABLE (priv->object)) + { + ClutterAnimatable *animatable = CLUTTER_ANIMATABLE (priv->object); + + pspec = clutter_animatable_find_property (animatable, + animation, + property_name); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (priv->object); + + pspec = g_object_class_find_property (klass, property_name); + } + + if (pspec == NULL) { g_warning ("Cannot bind property '%s': objects of type '%s' have " "no such property", @@ -715,7 +738,9 @@ clutter_animation_bind_interval (ClutterAnimation *animation, if (pspec == NULL) return NULL; - clutter_animation_bind_property_internal (animation, pspec, interval); + clutter_animation_bind_property_internal (animation, property_name, + pspec, + interval); return animation; } @@ -760,12 +785,21 @@ clutter_animation_bind (ClutterAnimation *animation, return NULL; g_value_init (&initial, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_object_get_property (priv->object, property_name, &initial); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_get_initial_state (CLUTTER_ANIMATABLE (priv->object), + animation, + property_name, + &initial); + else + g_object_get_property (priv->object, property_name, &initial); interval = clutter_interval_new_with_values (type, &initial, final); g_value_unset (&initial); - clutter_animation_bind_property_internal (animation, pspec, interval); + clutter_animation_bind_property_internal (animation, property_name, + pspec, + interval); return animation; } @@ -845,7 +879,6 @@ clutter_animation_update_interval (ClutterAnimation *animation, ClutterInterval *interval) { ClutterAnimationPrivate *priv; - GObjectClass *klass; GParamSpec *pspec; GType pspec_type, int_type; @@ -863,9 +896,22 @@ clutter_animation_update_interval (ClutterAnimation *animation, return; } - klass = G_OBJECT_GET_CLASS (priv->object); - pspec = g_object_class_find_property (klass, property_name); - if (!pspec) + if (CLUTTER_IS_ANIMATABLE (priv->object)) + { + ClutterAnimatable *animatable = CLUTTER_ANIMATABLE (priv->object); + + pspec = clutter_animatable_find_property (animatable, + animation, + property_name); + } + else + { + GObjectClass *klass = G_OBJECT_GET_CLASS (priv->object); + + pspec = g_object_class_find_property (klass, property_name); + } + + if (pspec == NULL) { g_warning ("Cannot update property '%s': objects of type '%s' have " "no such property", @@ -889,7 +935,9 @@ clutter_animation_update_interval (ClutterAnimation *animation, return; } - clutter_animation_update_property_internal (animation, pspec, interval); + clutter_animation_update_property_internal (animation, property_name, + pspec, + interval); } /** @@ -1050,7 +1098,14 @@ on_alpha_notify (GObject *gobject, } if (apply) - g_object_set_property (priv->object, p_name, &value); + { + if (is_animatable) + clutter_animatable_set_final_state (animatable, animation, + p_name, + &value); + else + g_object_set_property (priv->object, p_name, &value); + } g_value_unset (&value); } @@ -1688,26 +1743,41 @@ done: GValue cur_value = { 0, }; g_value_init (&cur_value, G_PARAM_SPEC_VALUE_TYPE (pspec)); - g_object_get_property (priv->object, property_name, &cur_value); + + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_get_initial_state (CLUTTER_ANIMATABLE (priv->object), + animation, + property_name, + &cur_value); + else + g_object_get_property (priv->object, property_name, &cur_value); interval = clutter_interval_new_with_values (G_PARAM_SPEC_VALUE_TYPE (pspec), &cur_value, &real_value); - if (!clutter_animation_has_property (animation, pspec->name)) - clutter_animation_bind_property_internal (animation, + if (!clutter_animation_has_property (animation, property_name)) + clutter_animation_bind_property_internal (animation, property_name, pspec, interval); else - clutter_animation_update_property_internal (animation, + clutter_animation_update_property_internal (animation, property_name, pspec, interval); g_value_unset (&cur_value); } else - g_object_set_property (priv->object, property_name, &real_value); + { + if (CLUTTER_IS_ANIMATABLE (priv->object)) + clutter_animatable_set_final_state (CLUTTER_ANIMATABLE (priv->object), + animation, + property_name, + &real_value); + else + g_object_set_property (priv->object, property_name, &real_value); + } g_value_unset (&real_value); } @@ -1719,11 +1789,15 @@ clutter_animation_setupv (ClutterAnimation *animation, const GValue *values) { ClutterAnimationPrivate *priv = animation->priv; - GObjectClass *klass; - gint i; + ClutterAnimatable *animatable = NULL; + GObjectClass *klass = NULL; gboolean is_fixed = FALSE; + gint i; - klass = G_OBJECT_GET_CLASS (priv->object); + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + else + klass = G_OBJECT_GET_CLASS (priv->object); for (i = 0; i < n_properties; i++) { @@ -1736,8 +1810,14 @@ clutter_animation_setupv (ClutterAnimation *animation, is_fixed = TRUE; } - pspec = g_object_class_find_property (klass, property_name); - if (!pspec) + if (animatable != NULL) + pspec = clutter_animatable_find_property (animatable, + animation, + property_name); + else + pspec = g_object_class_find_property (klass, property_name); + + if (pspec == NULL) { g_warning ("Cannot bind property '%s': objects of type '%s' do " "not have this property", @@ -1792,10 +1872,14 @@ clutter_animation_setup_valist (ClutterAnimation *animation, va_list var_args) { ClutterAnimationPrivate *priv = animation->priv; - GObjectClass *klass; + ClutterAnimatable *animatable = NULL; + GObjectClass *klass = NULL; const gchar *property_name; - klass = G_OBJECT_GET_CLASS (priv->object); + if (CLUTTER_IS_ANIMATABLE (priv->object)) + animatable = CLUTTER_ANIMATABLE (priv->object); + else + klass = G_OBJECT_GET_CLASS (priv->object); property_name = first_property_name; while (property_name != NULL) @@ -1827,8 +1911,14 @@ clutter_animation_setup_valist (ClutterAnimation *animation, is_fixed = TRUE; } - pspec = g_object_class_find_property (klass, property_name); - if (!pspec) + if (animatable != NULL) + pspec = clutter_animatable_find_property (animatable, + animation, + property_name); + else + pspec = g_object_class_find_property (klass, property_name); + + if (pspec == NULL) { g_warning ("Cannot bind property '%s': objects of type '%s' do " "not have this property", From 29257af30c08eeb06089aebb460baacbfd78a052 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 12:23:57 +0100 Subject: [PATCH 08/24] actor: Implement Animatable By implementing the newly added support for custom animatable properties, we can allow addressing action and constraint properties from ClutterAnimation and clutter_actor_animate(). --- clutter/clutter-actor.c | 162 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index 22ed6a60f..f8227fe81 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -229,6 +229,7 @@ #include "clutter-action.h" #include "clutter-actor-meta-private.h" +#include "clutter-animatable.h" #include "clutter-constraint.h" #include "clutter-container.h" #include "clutter-debug.h" @@ -517,6 +518,7 @@ enum static guint actor_signals[LAST_SIGNAL] = { 0, }; static void clutter_scriptable_iface_init (ClutterScriptableIface *iface); +static void clutter_animatable_iface_init (ClutterAnimatableIface *iface); static void _clutter_actor_apply_modelview_transform (ClutterActor *self); @@ -582,7 +584,9 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor, clutter_actor, G_TYPE_INITIALLY_UNOWNED, G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_SCRIPTABLE, - clutter_scriptable_iface_init)); + clutter_scriptable_iface_init) + G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_ANIMATABLE, + clutter_animatable_iface_init)); static const gchar * get_actor_debug_name (ClutterActor *actor) @@ -8157,6 +8161,158 @@ clutter_scriptable_iface_init (ClutterScriptableIface *iface) iface->set_custom_property = clutter_actor_set_custom_property; } +static ClutterActorMeta * +get_meta_from_animation_property (ClutterActor *actor, + const gchar *name, + gchar **name_p) +{ + ClutterActorPrivate *priv = actor->priv; + ClutterActorMeta *meta = NULL; + gchar **tokens; + + /* if this is not a special property, fall through */ + if (name[0] != '@') + return NULL; + + /* detect the properties named using the following spec: + * + * @
.. + * + * where
can be one of the following: + * + * - actions + * - constraints + * + * and is the name set on a specific ActorMeta + */ + + tokens = g_strsplit (name + 1, ".", -1); + if (tokens == NULL || g_strv_length (tokens) != 3) + { + CLUTTER_NOTE (ANIMATION, "Invalid property name '%s'", + name + 1); + g_strfreev (tokens); + return NULL; + } + + if (strcmp (tokens[0], "actions") == 0) + meta = _clutter_meta_group_get_meta (priv->actions, tokens[1]); + + if (strcmp (tokens[0], "constraints") == 0) + meta = _clutter_meta_group_get_meta (priv->constraints, tokens[1]); + + if (name_p != NULL) + *name_p = g_strdup (tokens[2]); + + CLUTTER_NOTE (ANIMATION, + "Looking for property '%s' of object '%s' in section '%s'", + tokens[2], + tokens[1], + tokens[0]); + + g_strfreev (tokens); + + return meta; +} + +static GParamSpec * +clutter_actor_find_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name) +{ + ClutterActorMeta *meta = NULL; + GObjectClass *klass = NULL; + GParamSpec *pspec = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (CLUTTER_ACTOR (animatable), + property_name, + &p_name); + + if (meta != NULL) + { + klass = G_OBJECT_GET_CLASS (meta); + + pspec = g_object_class_find_property (klass, p_name); + + g_free (p_name); + } + else + { + klass = G_OBJECT_GET_CLASS (animatable); + + pspec = g_object_class_find_property (klass, property_name); + } + + return pspec; +} + +static void +clutter_actor_get_initial_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + GValue *initial) +{ + ClutterActorMeta *meta = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (CLUTTER_ACTOR (animatable), + property_name, + &p_name); + + if (meta != NULL) + g_object_get_property (G_OBJECT (meta), p_name, initial); + else + g_object_get_property (G_OBJECT (animatable), property_name, initial); + + g_free (p_name); +} + +static void +clutter_actor_set_final_state (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *final) +{ + ClutterActorMeta *meta = NULL; + gchar *p_name = NULL; + + meta = get_meta_from_animation_property (CLUTTER_ACTOR (animatable), + property_name, + &p_name); + if (meta != NULL) + g_object_set_property (G_OBJECT (meta), p_name, final); + else + g_object_set_property (G_OBJECT (animatable), property_name, final); + + g_free (p_name); +} + +static gboolean +clutter_actor_animate_property (ClutterAnimatable *animatable, + ClutterAnimation *animation, + const gchar *property_name, + const GValue *initial, + const GValue *final, + gdouble progress, + GValue *new_value) +{ + ClutterInterval *interval; + + interval = clutter_animation_get_interval (animation, property_name); + + return clutter_interval_compute_value (interval, progress, new_value); +} + +static void +clutter_animatable_iface_init (ClutterAnimatableIface *iface) +{ + iface->animate_property = clutter_actor_animate_property; + iface->find_property = clutter_actor_find_property; + iface->get_initial_state = clutter_actor_get_initial_state; + iface->set_final_state = clutter_actor_set_final_state; +} + /** * clutter_actor_transform_stage_point * @self: A #ClutterActor @@ -10361,7 +10517,7 @@ clutter_actor_add_constraint (ClutterActor *self, ClutterActorPrivate *priv; g_return_if_fail (CLUTTER_IS_ACTOR (self)); - g_return_if_fail (CLUTTER_IS_ACTION (constraint)); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); priv = self->priv; @@ -10395,7 +10551,7 @@ clutter_actor_remove_constraint (ClutterActor *self, ClutterActorPrivate *priv; g_return_if_fail (CLUTTER_IS_ACTOR (self)); - g_return_if_fail (CLUTTER_IS_ACTION (constraint)); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); priv = self->priv; From 769e964424f4de41b7e875b8a08a2bd17fdd2f70 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 12:25:28 +0100 Subject: [PATCH 09/24] constraint: Add BindConstraint The BindConstraint object is a constraint that binds the current position of an actor on a given axis to the actor that has the constraint applied. --- clutter/Makefile.am | 2 + clutter/clutter-bind-constraint.c | 267 ++++++++++++++++++++++++++++++ clutter/clutter-bind-constraint.h | 32 ++++ clutter/clutter.h | 1 + 4 files changed, 302 insertions(+) create mode 100644 clutter/clutter-bind-constraint.c create mode 100644 clutter/clutter-bind-constraint.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index 9571cd232..e753d910b 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -80,6 +80,7 @@ source_h = \ $(srcdir)/clutter-behaviour-path.h \ $(srcdir)/clutter-behaviour-rotate.h \ $(srcdir)/clutter-behaviour-scale.h \ + $(srcdir)/clutter-bind-constraint.h \ $(srcdir)/clutter-binding-pool.h \ $(srcdir)/clutter-bin-layout.h \ $(srcdir)/clutter-box.h \ @@ -158,6 +159,7 @@ source_c = \ $(srcdir)/clutter-behaviour-rotate.c \ $(srcdir)/clutter-behaviour-scale.c \ $(srcdir)/clutter-bezier.c \ + $(srcdir)/clutter-bind-constraint.c \ $(srcdir)/clutter-binding-pool.c \ $(srcdir)/clutter-bin-layout.c \ $(srcdir)/clutter-box.c \ diff --git a/clutter/clutter-bind-constraint.c b/clutter/clutter-bind-constraint.c new file mode 100644 index 000000000..199b3f526 --- /dev/null +++ b/clutter/clutter-bind-constraint.c @@ -0,0 +1,267 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-bind-constraint.h" + +#include "clutter-constraint.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define CLUTTER_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass)) +#define CLUTTER_IS_BIND_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIND_CONSTRAINT)) +#define CLUTTER_BIND_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraintClass)) + +typedef struct _ClutterBindConstraintClass ClutterBindConstraintClass; + +struct _ClutterBindConstraint +{ + ClutterConstraint parent_instance; + + ClutterActor *source; + ClutterBindAxis bind_axis; + gfloat offset; +}; + +struct _ClutterBindConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SOURCE, + PROP_BIND_AXIS, + PROP_OFFSET +}; + +G_DEFINE_TYPE (ClutterBindConstraint, + clutter_bind_constraint, + CLUTTER_TYPE_CONSTRAINT); + +static void +update_actor_position (ClutterBindConstraint *bind) +{ + ClutterVertex source_position; + ClutterActor *actor; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (bind))) + return; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (bind)); + if (actor == NULL) + return; + + source_position.x = clutter_actor_get_x (bind->source); + source_position.y = clutter_actor_get_y (bind->source); + source_position.z = clutter_actor_get_depth (bind->source); + + switch (bind->bind_axis) + { + case CLUTTER_BIND_X_AXIS: + clutter_actor_set_x (actor, source_position.x + bind->offset); + break; + + case CLUTTER_BIND_Y_AXIS: + clutter_actor_set_y (actor, source_position.y + bind->offset); + break; + + case CLUTTER_BIND_Z_AXIS: + clutter_actor_set_depth (actor, source_position.z + bind->offset); + break; + } +} + +static void +source_position_changed (GObject *gobject, + GParamSpec *pspec, + ClutterBindConstraint *bind) +{ + if (strcmp (pspec->name, "x") == 0 || + strcmp (pspec->name, "y") == 0 || + strcmp (pspec->name, "depth") == 0) + { + update_actor_position (bind); + } +} + +static void +source_destroyed (ClutterActor *actor, + ClutterBindConstraint *bind) +{ + bind->source = NULL; +} + +static void +_clutter_bind_constraint_set_source (ClutterBindConstraint *bind, + ClutterActor *source) +{ + ClutterActor *old_source = bind->source; + + if (old_source != NULL) + { + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_destroyed), + bind); + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_position_changed), + bind); + } + + bind->source = source; + g_signal_connect (bind->source, "notify", + G_CALLBACK (source_position_changed), + bind); + g_signal_connect (bind->source, "destroy", + G_CALLBACK (source_destroyed), + bind); + + update_actor_position (bind); + + g_object_notify (G_OBJECT (bind), "source"); +} + +static void +_clutter_bind_constraint_set_bind_axis (ClutterBindConstraint *bind, + ClutterBindAxis axis) +{ + if (bind->bind_axis == axis) + return; + + bind->bind_axis = axis; + + update_actor_position (bind); + + g_object_notify (G_OBJECT (bind), "bind-axis"); +} + +static void +_clutter_bind_constraint_set_offset (ClutterBindConstraint *bind, + gfloat offset) +{ + if (fabs (bind->offset - offset) < 0.00001f) + return; + + bind->offset = offset; + + update_actor_position (bind); + + g_object_notify (G_OBJECT (bind), "offset"); +} + +static void +clutter_bind_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + _clutter_bind_constraint_set_source (bind, g_value_get_object (value)); + break; + + case PROP_BIND_AXIS: + _clutter_bind_constraint_set_bind_axis (bind, g_value_get_enum (value)); + break; + + case PROP_OFFSET: + _clutter_bind_constraint_set_offset (bind, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bind_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterBindConstraint *bind = CLUTTER_BIND_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, bind->source); + break; + + case PROP_BIND_AXIS: + g_value_set_enum (value, bind->bind_axis); + break; + + case PROP_OFFSET: + g_value_set_float (value, bind->offset); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_bind_constraint_set_property; + gobject_class->get_property = clutter_bind_constraint_get_property; + + pspec = g_param_spec_object ("source", + "Source", + "The source of the binding", + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_SOURCE, pspec); + + pspec = g_param_spec_enum ("bind-axis", + "Bind Axis", + "The axis to bind the position from", + CLUTTER_TYPE_BIND_AXIS, + CLUTTER_BIND_X_AXIS, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_BIND_AXIS, pspec); + + pspec = g_param_spec_float ("offset", + "Offset", + "The offset in pixels to apply to the binding", + -G_MAXFLOAT, G_MAXFLOAT, + 0.0f, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_OFFSET, pspec); +} + +static void +clutter_bind_constraint_init (ClutterBindConstraint *self) +{ + self->source = NULL; + self->bind_axis = CLUTTER_BIND_X_AXIS; + self->offset = 0.0f; +} + +ClutterConstraint * +clutter_bind_constraint_new (ClutterActor *source, + ClutterBindAxis axis, + gfloat offset) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (source), NULL); + + return g_object_new (CLUTTER_TYPE_BIND_CONSTRAINT, + "source", source, + "bind-axis", axis, + "offset", offset, + NULL); +} diff --git a/clutter/clutter-bind-constraint.h b/clutter/clutter-bind-constraint.h new file mode 100644 index 000000000..8aaed181c --- /dev/null +++ b/clutter/clutter-bind-constraint.h @@ -0,0 +1,32 @@ +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_BIND_CONSTRAINT_H__ +#define __CLUTTER_BIND_CONSTRAINT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_BIND_CONSTRAINT (clutter_bind_constraint_get_type ()) +#define CLUTTER_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraint)) +#define CLUTTER_IS_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIND_CONSTRAINT)) + +typedef struct _ClutterBindConstraint ClutterBindConstraint; + +typedef enum { /*< prefix=CLUTTER_BIND >*/ + CLUTTER_BIND_X_AXIS, + CLUTTER_BIND_Y_AXIS, + CLUTTER_BIND_Z_AXIS +} ClutterBindAxis; + +GType clutter_bind_constraint_get_type (void) G_GNUC_CONST; + +ClutterConstraint *clutter_bind_constraint_new (ClutterActor *source, + ClutterBindAxis axis, + gfloat offset); + +G_END_DECLS + +#endif /* __CLUTTER_BIND_CONSTRAINT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index 9347e0930..ccf729837 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -45,6 +45,7 @@ #include "clutter-behaviour-path.h" #include "clutter-behaviour-rotate.h" #include "clutter-behaviour-scale.h" +#include "clutter-bind-constraint.h" #include "clutter-binding-pool.h" #include "clutter-bin-layout.h" #include "clutter-box.h" From 56e8e7d62f782266d510ff52269507a9d7796b93 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 12:27:09 +0100 Subject: [PATCH 10/24] tests: Add a constraints interactive test Show how to use constraints and how to animate them. --- .gitignore | 1 + tests/interactive/Makefile.am | 3 +- tests/interactive/test-constraints.c | 138 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 tests/interactive/test-constraints.c diff --git a/.gitignore b/.gitignore index 495821ae4..9381cacfe 100644 --- a/.gitignore +++ b/.gitignore @@ -150,6 +150,7 @@ TAGS /tests/interactive/test-animator /tests/interactive/test-stage-sizing /tests/interactive/test-drag +/tests/interactive/test-constraints /tests/conform/stamp-test-conformance /tests/conform/test-anchors /tests/conform/test-cogl-backface-culling diff --git a/tests/interactive/Makefile.am b/tests/interactive/Makefile.am index d45caa8f5..19f829177 100644 --- a/tests/interactive/Makefile.am +++ b/tests/interactive/Makefile.am @@ -49,7 +49,8 @@ UNIT_TESTS = \ test-flow-layout.c \ test-box-layout.c \ test-stage-sizing.c \ - test-drag.c + test-drag.c \ + test-constraints.c if X11_TESTS UNIT_TESTS += test-pixmap.c diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c new file mode 100644 index 000000000..6c3733584 --- /dev/null +++ b/tests/interactive/test-constraints.c @@ -0,0 +1,138 @@ +#include +#include +#include + +#define H_PADDING 32 + +static ClutterActor *center_rect = NULL; +static ClutterActor *left_rect = NULL; +static ClutterActor *right_rect = NULL; + +static gboolean is_expanded = FALSE; + +static gboolean +on_button_release (ClutterActor *actor, + ClutterEvent *event, + gpointer data G_GNUC_UNUSED) +{ + if (!is_expanded) + { + gfloat left_offset = (clutter_actor_get_width (left_rect) + H_PADDING) + * -1.0f; + gfloat right_offset = clutter_actor_get_width (right_rect) + H_PADDING; + + clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", left_offset, + NULL); + clutter_actor_animate (right_rect, CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", right_offset, + NULL); + } + else + { + clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 0, + "@constraints.x-bind.offset", 0.0f, + NULL); + clutter_actor_animate (right_rect, CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 0, + "@constraints.x-bind.offset", 0.0f, + NULL); + } + + is_expanded = !is_expanded; + + return TRUE; +} + +G_MODULE_EXPORT int +test_constraints_main (int argc, char *argv[]) +{ + ClutterActor *stage, *rect; + ClutterColor rect_color; + ClutterConstraint *constraint; + + clutter_init (&argc, &argv); + + stage = clutter_stage_new (); + g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); + clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints"); + clutter_actor_set_size (stage, 800, 600); + + /* main rect */ + clutter_color_from_string (&rect_color, "#73d216ff"); + rect = clutter_rectangle_new (); + g_signal_connect (rect, "button-release-event", + G_CALLBACK (on_button_release), + NULL); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); + clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_reactive (rect, TRUE); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + +#if 0 + constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-align"); + clutter_actor_add_constraint (rect, constraint); + + constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); + clutter_actor_add_constraint (rect, constraint); +#else + clutter_actor_set_position (rect, (800 - 256) / 2.0, (600 - 256) / 2.0); +#endif + + center_rect = rect; + + /* left rectangle */ + clutter_color_from_string (&rect_color, "#cc0000ff"); + rect = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); + clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_opacity (rect, 0); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X_AXIS, 0.0f); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); + clutter_actor_add_constraint (rect, constraint); + +#if 0 + constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); + clutter_actor_add_constraint (rect, constraint); +#else + clutter_actor_set_y (rect, (600 - 256) / 2.0); +#endif + + left_rect = rect; + + /* right rectangle */ + clutter_color_from_string (&rect_color, "#3465a4ff"); + rect = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); + clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_opacity (rect, 0); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + + constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X_AXIS, 0.0f); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); + clutter_actor_add_constraint (rect, constraint); + +#if 0 + constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); + clutter_actor_add_constraint (rect, constraint); +#else + clutter_actor_set_y (rect, (600 - 256) / 2.0); +#endif + + right_rect = rect; + + clutter_actor_show (stage); + + clutter_main (); + + return EXIT_SUCCESS; +} From f857457b9d01cbbc5b59609e28b2e6a3fd0c3636 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 13:02:43 +0100 Subject: [PATCH 11/24] constraints: Add AlignConstraint AlignConstraint is a simple constraint that keeps an actor's position aligned to the width or height of another actor, multiplied by an alignment factor. --- clutter/Makefile.am | 2 + clutter/clutter-align-constraint.c | 259 +++++++++++++++++++++++++++ clutter/clutter-align-constraint.h | 31 ++++ clutter/clutter.h | 1 + tests/interactive/test-constraints.c | 12 -- 5 files changed, 293 insertions(+), 12 deletions(-) create mode 100644 clutter/clutter-align-constraint.c create mode 100644 clutter/clutter-align-constraint.h diff --git a/clutter/Makefile.am b/clutter/Makefile.am index e753d910b..6b777f0ae 100644 --- a/clutter/Makefile.am +++ b/clutter/Makefile.am @@ -68,6 +68,7 @@ source_h = \ $(srcdir)/clutter-action.h \ $(srcdir)/clutter-actor-meta.h \ $(srcdir)/clutter-actor.h \ + $(srcdir)/clutter-align-constraint.h \ $(srcdir)/clutter-alpha.h \ $(srcdir)/clutter-animatable.h \ $(srcdir)/clutter-animation.h \ @@ -146,6 +147,7 @@ source_c = \ $(srcdir)/clutter-action.c \ $(srcdir)/clutter-actor-meta.c \ $(srcdir)/clutter-actor.c \ + $(srcdir)/clutter-align-constraint.c \ $(srcdir)/clutter-alpha.c \ $(srcdir)/clutter-animatable.c \ $(srcdir)/clutter-animation.c \ diff --git a/clutter/clutter-align-constraint.c b/clutter/clutter-align-constraint.c new file mode 100644 index 000000000..c08334029 --- /dev/null +++ b/clutter/clutter-align-constraint.c @@ -0,0 +1,259 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "clutter-align-constraint.h" + +#include "clutter-constraint.h" +#include "clutter-debug.h" +#include "clutter-enum-types.h" +#include "clutter-private.h" + +#define CLUTTER_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass)) +#define CLUTTER_IS_ALIGN_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_ALIGN_CONSTRAINT)) +#define CLUTTER_ALIGN_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraintClass)) + +typedef struct _ClutterAlignConstraintClass ClutterAlignConstraintClass; + +struct _ClutterAlignConstraint +{ + ClutterConstraint parent_instance; + + ClutterActor *source; + ClutterAlignAxis align_axis; + gfloat factor; +}; + +struct _ClutterAlignConstraintClass +{ + ClutterConstraintClass parent_class; +}; + +enum +{ + PROP_0, + + PROP_SOURCE, + PROP_ALIGN_AXIS, + PROP_FACTOR +}; + +G_DEFINE_TYPE (ClutterAlignConstraint, + clutter_align_constraint, + CLUTTER_TYPE_CONSTRAINT); + +static void +update_actor_position (ClutterAlignConstraint *align) +{ + gfloat source_width, source_height; + gfloat actor_width, actor_height; + ClutterActor *actor; + + if (!clutter_actor_meta_get_enabled (CLUTTER_ACTOR_META (align))) + return; + + actor = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (align)); + if (actor == NULL) + return; + + clutter_actor_get_size (align->source, &source_width, &source_height); + clutter_actor_get_size (actor, &actor_width, &actor_height); + + switch (align->align_axis) + { + case CLUTTER_ALIGN_X_AXIS: + clutter_actor_set_x (actor, (source_width - actor_width) * align->factor); + break; + + case CLUTTER_ALIGN_Y_AXIS: + clutter_actor_set_y (actor, (source_height - actor_height) * align->factor); + break; + } +} + +static void +source_position_changed (GObject *gobject, + GParamSpec *pspec, + ClutterAlignConstraint *align) +{ + if (strcmp (pspec->name, "width") == 0 || + strcmp (pspec->name, "height") == 0) + { + update_actor_position (align); + } +} + +static void +source_destroyed (ClutterActor *actor, + ClutterAlignConstraint *align) +{ + align->source = NULL; +} + +static void +_clutter_align_constraint_set_source (ClutterAlignConstraint *align, + ClutterActor *source) +{ + ClutterActor *old_source = align->source; + + if (old_source != NULL) + { + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_destroyed), + align); + g_signal_handlers_disconnect_by_func (old_source, + G_CALLBACK (source_position_changed), + align); + } + + align->source = source; + g_signal_connect (align->source, "notify", + G_CALLBACK (source_position_changed), + align); + g_signal_connect (align->source, "destroy", + G_CALLBACK (source_destroyed), + align); + + update_actor_position (align); + + g_object_notify (G_OBJECT (align), "source"); +} + +static void +_clutter_align_constraint_set_align_axis (ClutterAlignConstraint *align, + ClutterAlignAxis axis) +{ + if (align->align_axis == axis) + return; + + align->align_axis = axis; + + update_actor_position (align); + + g_object_notify (G_OBJECT (align), "align-axis"); +} + +static void +_clutter_align_constraint_set_factor (ClutterAlignConstraint *align, + gfloat factor) +{ + align->factor = CLAMP (factor, 0.0, 1.0); + + update_actor_position (align); + + g_object_notify (G_OBJECT (align), "factor"); +} + +static void +clutter_align_constraint_set_property (GObject *gobject, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + _clutter_align_constraint_set_source (align, g_value_get_object (value)); + break; + + case PROP_ALIGN_AXIS: + _clutter_align_constraint_set_align_axis (align, g_value_get_enum (value)); + break; + + case PROP_FACTOR: + _clutter_align_constraint_set_factor (align, g_value_get_float (value)); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_align_constraint_get_property (GObject *gobject, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + ClutterAlignConstraint *align = CLUTTER_ALIGN_CONSTRAINT (gobject); + + switch (prop_id) + { + case PROP_SOURCE: + g_value_set_object (value, align->source); + break; + + case PROP_ALIGN_AXIS: + g_value_set_enum (value, align->align_axis); + break; + + case PROP_FACTOR: + g_value_set_float (value, align->factor); + break; + + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec); + break; + } +} + +static void +clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GParamSpec *pspec; + + gobject_class->set_property = clutter_align_constraint_set_property; + gobject_class->get_property = clutter_align_constraint_get_property; + + pspec = g_param_spec_object ("source", + "Source", + "The source of the binding", + CLUTTER_TYPE_ACTOR, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_SOURCE, pspec); + + pspec = g_param_spec_enum ("align-axis", + "Align Axis", + "The axis to align the position to", + CLUTTER_TYPE_ALIGN_AXIS, + CLUTTER_ALIGN_X_AXIS, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_ALIGN_AXIS, pspec); + + pspec = g_param_spec_float ("factor", + "Factor", + "The alignment factor, between 0.0 and 1.0", + 0.0, 1.0, + 0.0, + CLUTTER_PARAM_READWRITE | + G_PARAM_CONSTRUCT); + g_object_class_install_property (gobject_class, PROP_FACTOR, pspec); +} + +static void +clutter_align_constraint_init (ClutterAlignConstraint *self) +{ + self->source = NULL; + self->align_axis = CLUTTER_ALIGN_X_AXIS; + self->factor = 0.0f; +} + +ClutterConstraint * +clutter_align_constraint_new (ClutterActor *source, + ClutterAlignAxis axis, + gfloat factor) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (source), NULL); + + return g_object_new (CLUTTER_TYPE_ALIGN_CONSTRAINT, + "source", source, + "align-axis", axis, + "factor", factor, + NULL); +} diff --git a/clutter/clutter-align-constraint.h b/clutter/clutter-align-constraint.h new file mode 100644 index 000000000..34e376d77 --- /dev/null +++ b/clutter/clutter-align-constraint.h @@ -0,0 +1,31 @@ +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#ifndef __CLUTTER_ALIGN_CONSTRAINT_H__ +#define __CLUTTER_ALIGN_CONSTRAINT_H__ + +#include + +G_BEGIN_DECLS + +#define CLUTTER_TYPE_ALIGN_CONSTRAINT (clutter_align_constraint_get_type ()) +#define CLUTTER_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraint)) +#define CLUTTER_IS_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT)) + +typedef struct _ClutterAlignConstraint ClutterAlignConstraint; + +typedef enum { /*< prefix=CLUTTER_ALIGN >*/ + CLUTTER_ALIGN_X_AXIS, + CLUTTER_ALIGN_Y_AXIS, +} ClutterAlignAxis; + +GType clutter_align_constraint_get_type (void) G_GNUC_CONST; + +ClutterConstraint *clutter_align_constraint_new (ClutterActor *source, + ClutterAlignAxis axis, + gfloat factor); + +G_END_DECLS + +#endif /* __CLUTTER_ALIGN_CONSTRAINT_H__ */ diff --git a/clutter/clutter.h b/clutter/clutter.h index ccf729837..49c3dabe3 100644 --- a/clutter/clutter.h +++ b/clutter/clutter.h @@ -33,6 +33,7 @@ #include "clutter-action.h" #include "clutter-actor.h" #include "clutter-actor-meta.h" +#include "clutter-align-constraint.h" #include "clutter-alpha.h" #include "clutter-animatable.h" #include "clutter-animation.h" diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 6c3733584..a2b7b28af 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -72,7 +72,6 @@ test_constraints_main (int argc, char *argv[]) clutter_actor_set_reactive (rect, TRUE); clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); -#if 0 constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-align"); clutter_actor_add_constraint (rect, constraint); @@ -80,9 +79,6 @@ test_constraints_main (int argc, char *argv[]) constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); clutter_actor_add_constraint (rect, constraint); -#else - clutter_actor_set_position (rect, (800 - 256) / 2.0, (600 - 256) / 2.0); -#endif center_rect = rect; @@ -98,13 +94,9 @@ test_constraints_main (int argc, char *argv[]) clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); clutter_actor_add_constraint (rect, constraint); -#if 0 constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); clutter_actor_add_constraint (rect, constraint); -#else - clutter_actor_set_y (rect, (600 - 256) / 2.0); -#endif left_rect = rect; @@ -120,13 +112,9 @@ test_constraints_main (int argc, char *argv[]) clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); clutter_actor_add_constraint (rect, constraint); -#if 0 constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); clutter_actor_add_constraint (rect, constraint); -#else - clutter_actor_set_y (rect, (600 - 256) / 2.0); -#endif right_rect = rect; From e9b93d5676237e94975fb22824827a8f7153da4d Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 14:34:18 +0100 Subject: [PATCH 12/24] constraint: Rename BindConstraint:bind-axis We're not binding an axis: we're really binding a coordinate of an actor to the coordinate of another one. --- clutter/clutter-bind-constraint.c | 124 +++++++++++++++++++++------ clutter/clutter-bind-constraint.h | 38 ++++++-- tests/interactive/test-constraints.c | 16 ++-- 3 files changed, 139 insertions(+), 39 deletions(-) diff --git a/clutter/clutter-bind-constraint.c b/clutter/clutter-bind-constraint.c index 199b3f526..d43cae793 100644 --- a/clutter/clutter-bind-constraint.c +++ b/clutter/clutter-bind-constraint.c @@ -1,3 +1,39 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:ClutterBindConstraint + * @Title: ClutterBindConstraint + * @Short_Description: A constraint binding the position of an actor + * + * #ClutterBindConstraint is a #ClutterConstraint that binds the position of + * the #ClutterActor to which it is applied to the the position of another + * #ClutterActor. + * + * #ClutterBindConstraint is available since Clutter 1.4 + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -20,7 +56,7 @@ struct _ClutterBindConstraint ClutterConstraint parent_instance; ClutterActor *source; - ClutterBindAxis bind_axis; + ClutterBindCoordinate coordinate; gfloat offset; }; @@ -34,7 +70,7 @@ enum PROP_0, PROP_SOURCE, - PROP_BIND_AXIS, + PROP_COORDINATE, PROP_OFFSET }; @@ -59,17 +95,17 @@ update_actor_position (ClutterBindConstraint *bind) source_position.y = clutter_actor_get_y (bind->source); source_position.z = clutter_actor_get_depth (bind->source); - switch (bind->bind_axis) + switch (bind->coordinate) { - case CLUTTER_BIND_X_AXIS: + case CLUTTER_BIND_X: clutter_actor_set_x (actor, source_position.x + bind->offset); break; - case CLUTTER_BIND_Y_AXIS: + case CLUTTER_BIND_Y: clutter_actor_set_y (actor, source_position.y + bind->offset); break; - case CLUTTER_BIND_Z_AXIS: + case CLUTTER_BIND_Z: clutter_actor_set_depth (actor, source_position.z + bind->offset); break; } @@ -89,7 +125,7 @@ source_position_changed (GObject *gobject, } static void -source_destroyed (ClutterActor *actor, +source_destroyed (ClutterActor *actor, ClutterBindConstraint *bind) { bind->source = NULL; @@ -125,17 +161,17 @@ _clutter_bind_constraint_set_source (ClutterBindConstraint *bind, } static void -_clutter_bind_constraint_set_bind_axis (ClutterBindConstraint *bind, - ClutterBindAxis axis) +_clutter_bind_constraint_set_coordinate (ClutterBindConstraint *bind, + ClutterBindCoordinate coord) { - if (bind->bind_axis == axis) + if (bind->coordinate == coord) return; - bind->bind_axis = axis; + bind->coordinate = coord; update_actor_position (bind); - g_object_notify (G_OBJECT (bind), "bind-axis"); + g_object_notify (G_OBJECT (bind), "coordinate"); } static void @@ -166,8 +202,8 @@ clutter_bind_constraint_set_property (GObject *gobject, _clutter_bind_constraint_set_source (bind, g_value_get_object (value)); break; - case PROP_BIND_AXIS: - _clutter_bind_constraint_set_bind_axis (bind, g_value_get_enum (value)); + case PROP_COORDINATE: + _clutter_bind_constraint_set_coordinate (bind, g_value_get_enum (value)); break; case PROP_OFFSET: @@ -194,8 +230,8 @@ clutter_bind_constraint_get_property (GObject *gobject, g_value_set_object (value, bind->source); break; - case PROP_BIND_AXIS: - g_value_set_enum (value, bind->bind_axis); + case PROP_COORDINATE: + g_value_set_enum (value, bind->coordinate); break; case PROP_OFFSET: @@ -217,6 +253,13 @@ clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass) gobject_class->set_property = clutter_bind_constraint_set_property; gobject_class->get_property = clutter_bind_constraint_get_property; + /** + * ClutterBindConstraint:source: + * + * The #ClutterActor used as the source for the binding + * + * Since: 1.4 + */ pspec = g_param_spec_object ("source", "Source", "The source of the binding", @@ -225,15 +268,29 @@ clutter_bind_constraint_class_init (ClutterBindConstraintClass *klass) G_PARAM_CONSTRUCT); g_object_class_install_property (gobject_class, PROP_SOURCE, pspec); - pspec = g_param_spec_enum ("bind-axis", - "Bind Axis", - "The axis to bind the position from", - CLUTTER_TYPE_BIND_AXIS, - CLUTTER_BIND_X_AXIS, + /** + * ClutterBindConstraint:coordinate: + * + * The coordinate to be bound + * + * Since: 1.4 + */ + pspec = g_param_spec_enum ("coordinate", + "Coordinate", + "The coordinate to bind", + CLUTTER_TYPE_BIND_COORDINATE, + CLUTTER_BIND_X, CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); - g_object_class_install_property (gobject_class, PROP_BIND_AXIS, pspec); + g_object_class_install_property (gobject_class, PROP_COORDINATE, pspec); + /** + * ClutterBindConstraint:offset: + * + * The offset, in pixels, to be applied to the binding + * + * Since: 1.4 + */ pspec = g_param_spec_float ("offset", "Offset", "The offset in pixels to apply to the binding", @@ -248,20 +305,33 @@ static void clutter_bind_constraint_init (ClutterBindConstraint *self) { self->source = NULL; - self->bind_axis = CLUTTER_BIND_X_AXIS; + self->coordinate = CLUTTER_BIND_X; self->offset = 0.0f; } +/** + * clutter_bind_constraint_new: + * @source: the #ClutterActor to use as the source of the binding + * @coordinate: the coordinate to bind + * @offset: the offset to apply to the binding, in pixels + * + * Creates a new constraint, binding a #ClutterActor's position to + * the given @coordinate of the position of @source + * + * Return value: the newly created #ClutterBindConstraint + * + * Since: 1.4 + */ ClutterConstraint * -clutter_bind_constraint_new (ClutterActor *source, - ClutterBindAxis axis, - gfloat offset) +clutter_bind_constraint_new (ClutterActor *source, + ClutterBindCoordinate coordinate, + gfloat offset) { g_return_val_if_fail (CLUTTER_IS_ACTOR (source), NULL); return g_object_new (CLUTTER_TYPE_BIND_CONSTRAINT, "source", source, - "bind-axis", axis, + "coordinate", coordinate, "offset", offset, NULL); } diff --git a/clutter/clutter-bind-constraint.h b/clutter/clutter-bind-constraint.h index 8aaed181c..8be650034 100644 --- a/clutter/clutter-bind-constraint.h +++ b/clutter/clutter-bind-constraint.h @@ -1,3 +1,27 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) #error "Only can be included directly." #endif @@ -16,16 +40,16 @@ G_BEGIN_DECLS typedef struct _ClutterBindConstraint ClutterBindConstraint; typedef enum { /*< prefix=CLUTTER_BIND >*/ - CLUTTER_BIND_X_AXIS, - CLUTTER_BIND_Y_AXIS, - CLUTTER_BIND_Z_AXIS -} ClutterBindAxis; + CLUTTER_BIND_X, + CLUTTER_BIND_Y, + CLUTTER_BIND_Z +} ClutterBindCoordinate; GType clutter_bind_constraint_get_type (void) G_GNUC_CONST; -ClutterConstraint *clutter_bind_constraint_new (ClutterActor *source, - ClutterBindAxis axis, - gfloat offset); +ClutterConstraint *clutter_bind_constraint_new (ClutterActor *source, + ClutterBindCoordinate coordinate, + gfloat offset); G_END_DECLS diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index a2b7b28af..161a435c8 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -21,6 +21,9 @@ on_button_release (ClutterActor *actor, * -1.0f; gfloat right_offset = clutter_actor_get_width (right_rect) + H_PADDING; + clutter_actor_animate (center_rect, CLUTTER_LINEAR, 500, + "opacity", 128, + NULL); clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, "opacity", 255, "@constraints.x-bind.offset", left_offset, @@ -32,6 +35,9 @@ on_button_release (ClutterActor *actor, } else { + clutter_actor_animate (center_rect, CLUTTER_LINEAR, 500, + "opacity", 255, + NULL); clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, "opacity", 0, "@constraints.x-bind.offset", 0.0f, @@ -68,7 +74,7 @@ test_constraints_main (int argc, char *argv[]) G_CALLBACK (on_button_release), NULL); clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); - clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_size (rect, 128, 128); clutter_actor_set_reactive (rect, TRUE); clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); @@ -86,11 +92,11 @@ test_constraints_main (int argc, char *argv[]) clutter_color_from_string (&rect_color, "#cc0000ff"); rect = clutter_rectangle_new (); clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); - clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_size (rect, 128, 128); clutter_actor_set_opacity (rect, 0); clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X_AXIS, 0.0f); + constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X, 0.0f); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); clutter_actor_add_constraint (rect, constraint); @@ -104,11 +110,11 @@ test_constraints_main (int argc, char *argv[]) clutter_color_from_string (&rect_color, "#3465a4ff"); rect = clutter_rectangle_new (); clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); - clutter_actor_set_size (rect, 256, 256); + clutter_actor_set_size (rect, 128, 128); clutter_actor_set_opacity (rect, 0); clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X_AXIS, 0.0f); + constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X, 0.0f); clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); clutter_actor_add_constraint (rect, constraint); From 9f7e4b2b6412c1733200f50eedaf67b53c19ec54 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 14:46:02 +0100 Subject: [PATCH 13/24] docs: Document BindConstraint and AlignConstraint Add the missing gtk-doc annotations for BindConstraint and AlignConstraint, plus the licensing blurb. --- clutter/clutter-align-constraint.c | 78 +++++++++++++++++++++++++++++- clutter/clutter-align-constraint.h | 42 ++++++++++++++++ clutter/clutter-bind-constraint.h | 18 +++++++ 3 files changed, 137 insertions(+), 1 deletion(-) diff --git a/clutter/clutter-align-constraint.c b/clutter/clutter-align-constraint.c index c08334029..379fe387b 100644 --- a/clutter/clutter-align-constraint.c +++ b/clutter/clutter-align-constraint.c @@ -1,3 +1,39 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + +/** + * SECTION:ClutterAlignConstraint + * @Title: ClutterAlignConstraint + * @Short_Description: A constraint aligning the position of an actor + * + * #ClutterAlignConstraint is a #ClutterConstraint that aligns the position + * of the #ClutterActor to which it is applied to the size of another + * #ClutterActor using an alignment factor + * + * #ClutterAlignConstraint is available since Clutter 1.4 + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -209,14 +245,28 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass) gobject_class->set_property = clutter_align_constraint_set_property; gobject_class->get_property = clutter_align_constraint_get_property; + /** + * ClutterAlignConstraint:source: + * + * The #ClutterActor used as the source for the alignment + * + * Since: 1.4 + */ pspec = g_param_spec_object ("source", "Source", - "The source of the binding", + "The source of the alignment", CLUTTER_TYPE_ACTOR, CLUTTER_PARAM_READWRITE | G_PARAM_CONSTRUCT); g_object_class_install_property (gobject_class, PROP_SOURCE, pspec); + /** + * ClutterAlignConstraint:align-axis: + * + * The axis to be used to compute the alignment + * + * Since: 1.4 + */ pspec = g_param_spec_enum ("align-axis", "Align Axis", "The axis to align the position to", @@ -226,6 +276,18 @@ clutter_align_constraint_class_init (ClutterAlignConstraintClass *klass) G_PARAM_CONSTRUCT); g_object_class_install_property (gobject_class, PROP_ALIGN_AXIS, pspec); + /** + * ClutterAlignConstraint:factor: + * + * The alignment factor, as a normalized value between 0.0 and 1.0 + * + * The #ClutterAlignConstraint:factor depends on the + * #ClutterAlignConstraint:align-axis value: with %CLUTTER_ALIGN_X_AXIS, + * 0.0 means left and 1.0 means right; with %CLUTTER_ALIGN_Y_AXIS, 0.0 + * means top and 1.0 means bottom + * + * Since: 1.4 + */ pspec = g_param_spec_float ("factor", "Factor", "The alignment factor, between 0.0 and 1.0", @@ -244,6 +306,20 @@ clutter_align_constraint_init (ClutterAlignConstraint *self) self->factor = 0.0f; } +/** + * clutter_align_constraint_new: + * @source: the #ClutterActor to use as the source of the alignment + * @axis: the axis to be used to compute the alignment + * @factor: the alignment factor, between 0.0 and 1.0 + * + * Creates a new constraint, aligning a #ClutterActor's position with + * regards of the size of the actor to @source, with the given alignment + * @factor + * + * Return value: the newly created #ClutterAlignConstraint + * + * Since: 1.4 + */ ClutterConstraint * clutter_align_constraint_new (ClutterActor *source, ClutterAlignAxis axis, diff --git a/clutter/clutter-align-constraint.h b/clutter/clutter-align-constraint.h index 34e376d77..c2289c9ee 100644 --- a/clutter/clutter-align-constraint.h +++ b/clutter/clutter-align-constraint.h @@ -1,3 +1,27 @@ +/* + * Clutter. + * + * An OpenGL based 'interactive canvas' library. + * + * Copyright (C) 2010 Intel Corporation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library. If not, see . + * + * Author: + * Emmanuele Bassi + */ + #if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) #error "Only can be included directly." #endif @@ -13,8 +37,26 @@ G_BEGIN_DECLS #define CLUTTER_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT, ClutterAlignConstraint)) #define CLUTTER_IS_ALIGN_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_ALIGN_CONSTRAINT)) +/** + * ClutterAlignConstraint: + * + * ClutterAlignConstraint is an opaque structure + * whose members cannot be directly accesses + * + * Since: 1.4 + */ typedef struct _ClutterAlignConstraint ClutterAlignConstraint; +/** + * ClutterAlignAxis: + * @CLUTTER_ALIGN_X_AXIS: Maintain the alignment on the X axis + * @CLUTTER_ALIGN_Y_AXIS: Maintain the alignment on the Y axis + * + * Specifies the axis on which #ClutterAlignConstraint should maintain + * the alignment + * + * Since: 1.4 + */ typedef enum { /*< prefix=CLUTTER_ALIGN >*/ CLUTTER_ALIGN_X_AXIS, CLUTTER_ALIGN_Y_AXIS, diff --git a/clutter/clutter-bind-constraint.h b/clutter/clutter-bind-constraint.h index 8be650034..8c713604f 100644 --- a/clutter/clutter-bind-constraint.h +++ b/clutter/clutter-bind-constraint.h @@ -37,8 +37,26 @@ G_BEGIN_DECLS #define CLUTTER_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIND_CONSTRAINT, ClutterBindConstraint)) #define CLUTTER_IS_BIND_CONSTRAINT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIND_CONSTRAINT)) +/** + * ClutterBindConstraint: + * + * ClutterBindConstraint is an opaque structure + * whose members cannot be directly accessed + * + * Since: 1.4 + */ typedef struct _ClutterBindConstraint ClutterBindConstraint; +/** + * ClutterBindCoordinate: + * @CLUTTER_BIND_X: Bind the X coordinate + * @CLUTTER_BIND_Y: Bind the Y coordinate + * @CLUTTER_BIND_Z: Bind the Z coordinate + * + * Specifies which coordinate should be used in a binding + * + * Since: 1.4 + */ typedef enum { /*< prefix=CLUTTER_BIND >*/ CLUTTER_BIND_X, CLUTTER_BIND_Y, From 52acc71161532126d6c67923befadb18c1836932 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 15:09:47 +0100 Subject: [PATCH 14/24] docs: Document animating action and constraint properties Add a refsect for the syntax to be used when animating action and constraint properties with ClutterAnimation. --- clutter/clutter-actor.c | 59 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index f8227fe81..a1dcde57d 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -155,6 +155,65 @@ * should read the documentation for the #ClutterUnits parser format for * the valid units and syntax. * + * + * + * Custom animatable properties + * #ClutterActor allows accessing properties of #ClutterAction + * and #ClutterConstraint instances associated to an actor instance + * for animation purposes. + * In order to access a specific #ClutterAction or a #ClutterConstraint + * property it is necessary to set the #ClutterActorMeta:name property on the + * given action or constraint. + * The property can be accessed using the the following syntax: + * + * + * @<section>.<meta-name>.<property-name> + * + * + * The initial @ is mandatory. + * The section fragment can be one between + * "actions" or "constraints". + * The meta-name fragment is the name of the + * action or constraint, as specified by the #ClutterActorMeta:name + * property. + * The property-name fragment is the name of the + * action or constraint property to be animated. + * + * Animating a constraint property + * The example below animates a #ClutterBindConstraint applied to an + * actor using clutter_actor_animate(). The rect has + * a binding constraint for the origin actor, and in + * its initial state is fully transparent and overlapping the actor to + * which is bound to. + * + * constraint = clutter_bind_constraint_new (origin, CLUTTER_BIND_X, 0.0); + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "bind-x"); + * clutter_actor_add_constraint (rect, constraint); + * + * constraint = clutter_bind_constraint_new (origin, CLUTTER_BIND_Y, 0.0); + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "bind-y"); + * clutter_actor_add_constraint (rect, constraint); + * + * clutter_actor_set_reactive (rect, TRUE); + * clutter_actor_set_opacity (rect, 0); + * + * g_signal_connect (rect, "button-press-event", + * G_CALLBACK (on_button_press), + * NULL); + * + * On button press, the rectangle "slides" from behind the actor to + * which is bound to, using the #ClutterBindConstraint:offset property and + * the #ClutterActor:opacity property. + * + * float new_offset = clutter_actor_get_width (origin) + h_padding; + * + * clutter_actor_animate (rect, CLUTTER_EASE_OUT_CUBIC, 500, + * "opacity", 255, + * "@constraints.bind-x.offset", new_offset, + * NULL); + * + * + * */ /** From 6457f66976c68abf1b131841356cebbfa7dad655 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 16:10:05 +0100 Subject: [PATCH 15/24] Miscellaneous documentation fixes --- clutter/clutter-action.c | 2 +- clutter/clutter-actor-meta.c | 2 +- clutter/clutter-align-constraint.c | 2 +- clutter/clutter-animatable.c | 35 ++++++ clutter/clutter-animatable.h | 13 +- clutter/clutter-animation.c | 6 +- clutter/clutter-animator.c | 2 +- clutter/clutter-bind-constraint.c | 2 +- clutter/clutter-box-layout.c | 2 +- clutter/clutter-constraint.c | 12 ++ clutter/clutter-constraint.h | 13 +- clutter/clutter-drag-action.c | 2 +- clutter/clutter-event.h | 2 +- clutter/clutter-media.h | 1 + clutter/clutter-stage-manager.h | 4 - configure.ac | 6 +- doc/reference/clutter/Makefile.am | 1 + doc/reference/clutter/clutter-docs.xml.in | 11 ++ doc/reference/clutter/clutter-sections.txt | 139 ++++++++++++++++++++- doc/reference/clutter/clutter.types | 6 + 20 files changed, 232 insertions(+), 31 deletions(-) diff --git a/clutter/clutter-action.c b/clutter/clutter-action.c index 41b956f80..636ab67ed 100644 --- a/clutter/clutter-action.c +++ b/clutter/clutter-action.c @@ -23,7 +23,7 @@ */ /** - * SECTION:ClutterAction + * SECTION:clutter-action * @Title: ClutterAction * @Short_Description: Abstract class for actor actions * @See_Also: #ClutterEffect diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c index f01df3713..f2b50683a 100644 --- a/clutter/clutter-actor-meta.c +++ b/clutter/clutter-actor-meta.c @@ -1,5 +1,5 @@ /** - * SECTION:ClutterActorMeta + * SECTION:clutter-actor-meta * @Title: ClutterActorMeta * @Short_Description: Base class of actor modifiers * diff --git a/clutter/clutter-align-constraint.c b/clutter/clutter-align-constraint.c index 379fe387b..0ed459c8e 100644 --- a/clutter/clutter-align-constraint.c +++ b/clutter/clutter-align-constraint.c @@ -23,7 +23,7 @@ */ /** - * SECTION:ClutterAlignConstraint + * SECTION:clutter-align-constraint * @Title: ClutterAlignConstraint * @Short_Description: A constraint aligning the position of an actor * diff --git a/clutter/clutter-animatable.c b/clutter/clutter-animatable.c index d0dde8a64..0674abf7c 100644 --- a/clutter/clutter-animatable.c +++ b/clutter/clutter-animatable.c @@ -125,6 +125,19 @@ clutter_animatable_animate_property (ClutterAnimatable *animatable, return res; } +/** + * clutter_animatable_find_property: + * @animatable: a #ClutterAnimatable + * @animation: a #ClutterAnimation + * @property_name: the name of the animatable property to find + * + * Finds the #GParamSpec for @property_name + * + * Return value: (transfer none): The #GParamSpec for the given property + * or %NULL + * + * Since: 1.4 + */ GParamSpec * clutter_animatable_find_property (ClutterAnimatable *animatable, ClutterAnimation *animation, @@ -146,6 +159,17 @@ clutter_animatable_find_property (ClutterAnimatable *animatable, property_name); } +/** + * clutter_animatable_get_initial_state: + * @animatable: a #ClutterAnimatable + * @animation: a #ClutterAnimation + * @property_name: the name of the animatable property to retrieve + * @value: a #GValue initialized to the type of the property to retrieve + * + * Retrieves the current state of @property_name and sets @value with it + * + * Since: 1.4 + */ void clutter_animatable_get_initial_state (ClutterAnimatable *animatable, ClutterAnimation *animation, @@ -167,6 +191,17 @@ clutter_animatable_get_initial_state (ClutterAnimatable *animatable, g_object_get_property (G_OBJECT (animatable), property_name, value); } +/** + * clutter_animatable_set_final_state: + * @animatable: a #ClutterAnimatable + * @animation: a #ClutterAnimation + * @property_name: the name of the animatable property to set + * @value: the value of the animatable property to set + * + * Sets the current state of @property_name to @value + * + * Since: 1.4 + */ void clutter_animatable_set_final_state (ClutterAnimatable *animatable, ClutterAnimation *animation, diff --git a/clutter/clutter-animatable.h b/clutter/clutter-animatable.h index 04df1dc45..bddcc5ed0 100644 --- a/clutter/clutter-animatable.h +++ b/clutter/clutter-animatable.h @@ -52,7 +52,14 @@ typedef struct _ClutterAnimatableIface ClutterAnimatableIface; /** * ClutterAnimatableIface: - * @animate_property: virtual function for animating a property + * @animate_property: virtual function for custom interpolation of a + * property + * @find_property: virtual function for retrieving the #GParamSpec of + * an animatable property + * @get_initial_state: virtual function for retrieving the initial + * state of an animatable property + * @set_final_state: virtual function for setting the state of an + * animatable property * * Base interface for #GObjects that can be animated by a * a #ClutterAnimation. @@ -101,11 +108,11 @@ GParamSpec *clutter_animatable_find_property (ClutterAnimatable *animatable, void clutter_animatable_get_initial_state (ClutterAnimatable *animatable, ClutterAnimation *animation, const gchar *property_name, - GValue *initial); + GValue *value); void clutter_animatable_set_final_state (ClutterAnimatable *animatable, ClutterAnimation *animation, const gchar *property_name, - const GValue *final); + const GValue *value); G_END_DECLS diff --git a/clutter/clutter-animation.c b/clutter/clutter-animation.c index 2c8deaa05..dd9599af3 100644 --- a/clutter/clutter-animation.c +++ b/clutter/clutter-animation.c @@ -1989,7 +1989,7 @@ animation_create_for_actor (ClutterActor *actor) * @actor: a #ClutterActor * @alpha: a #ClutterAlpha * @first_property_name: the name of a property - * @VarArgs: a %NULL terminated list of property names and + * @Varargs: a %NULL terminated list of property names and * property values * * Animates the given list of properties of @actor between the current @@ -2046,7 +2046,7 @@ clutter_actor_animate_with_alpha (ClutterActor *actor, * @mode: an animation mode logical id * @timeline: a #ClutterTimeline * @first_property_name: the name of a property - * @VarArgs: a %NULL terminated list of property names and + * @Varargs: a %NULL terminated list of property names and * property values * * Animates the given list of properties of @actor between the current @@ -2097,7 +2097,7 @@ clutter_actor_animate_with_timeline (ClutterActor *actor, * @mode: an animation mode logical id * @duration: duration of the animation, in milliseconds * @first_property_name: the name of a property - * @VarArgs: a %NULL terminated list of property names and + * @Varargs: a %NULL terminated list of property names and * property values * * Animates the given list of properties of @actor between the current diff --git a/clutter/clutter-animator.c b/clutter/clutter-animator.c index 973e1e25e..273113d38 100644 --- a/clutter/clutter-animator.c +++ b/clutter/clutter-animator.c @@ -1147,7 +1147,7 @@ clutter_animator_get_duration (ClutterAnimator *animator) * @first_mode: the id of the alpha function to use * @first_progress: at which stage of the animation this value applies; the * range is a normalized floating point value between 0 and 1 - * @VarArgs: the value first_property_name should have for first_object + * @Varargs: the value first_property_name should have for first_object * at first_progress, followed by more (object, property_name, mode, * progress, value) tuples, followed by %NULL * diff --git a/clutter/clutter-bind-constraint.c b/clutter/clutter-bind-constraint.c index d43cae793..583ffd18b 100644 --- a/clutter/clutter-bind-constraint.c +++ b/clutter/clutter-bind-constraint.c @@ -23,7 +23,7 @@ */ /** - * SECTION:ClutterBindConstraint + * SECTION:clutter-bind-constraint * @Title: ClutterBindConstraint * @Short_Description: A constraint binding the position of an actor * diff --git a/clutter/clutter-box-layout.c b/clutter/clutter-box-layout.c index b4902317b..28730bb5b 100644 --- a/clutter/clutter-box-layout.c +++ b/clutter/clutter-box-layout.c @@ -1419,7 +1419,7 @@ clutter_box_layout_get_vertical (ClutterBoxLayout *layout) /** * clutter_box_layout_set_homogeneous: * @layout: a #ClutterBoxLayout - * @vertical: %TRUE if the layout should be homogeneous + * @homogeneous: %TRUE if the layout should be homogeneous * * Sets whether the size of @layout children should be * homogeneous diff --git a/clutter/clutter-constraint.c b/clutter/clutter-constraint.c index 0caf41b32..49d30c968 100644 --- a/clutter/clutter-constraint.c +++ b/clutter/clutter-constraint.c @@ -1,3 +1,15 @@ +/** + * SECTION:clutter-constraint + * @Title: ClutterConstraint + * @Short_Description: A constraint on an actor's position or size + * @See_Also: #ClutterAction + * + * #ClutterConstraint is a base abstract class for modifiers of a #ClutterActor + * position or size. + * + * #ClutterConstraint is available since Clutter 1.4 + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif diff --git a/clutter/clutter-constraint.h b/clutter/clutter-constraint.h index 99e6dc4de..03c664c06 100644 --- a/clutter/clutter-constraint.h +++ b/clutter/clutter-constraint.h @@ -40,7 +40,6 @@ G_BEGIN_DECLS #define CLUTTER_IS_CONSTRAINT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_CONSTRAINT)) #define CLUTTER_CONSTRAINT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_CONSTRAINT, ClutterConstraintClass)) -typedef struct _ClutterConstraintPrivate ClutterConstraintPrivate; typedef struct _ClutterConstraintClass ClutterConstraintClass; /** @@ -55,14 +54,10 @@ struct _ClutterConstraint { /*< private >*/ ClutterActorMeta parent_instance; - - ClutterConstraintPrivate *priv; }; /** * ClutterConstraintClass: - * @set_actor: virtual function, called when a constraint is applied to - * a #ClutterActor * * The ClutterConstraintClass structure contains * only private data @@ -88,12 +83,12 @@ struct _ClutterConstraintClass GType clutter_constraint_get_type (void) G_GNUC_CONST; /* ClutterActor API */ -void clutter_actor_add_constraint (ClutterActor *actor, +void clutter_actor_add_constraint (ClutterActor *self, ClutterConstraint *constraint); -void clutter_actor_remove_constraint (ClutterActor *actor, +void clutter_actor_remove_constraint (ClutterActor *self, ClutterConstraint *constraint); -GList *clutter_actor_get_constraints (ClutterActor *actor); -void clutter_actor_clear_constraints (ClutterActor *actor); +GList *clutter_actor_get_constraints (ClutterActor *self); +void clutter_actor_clear_constraints (ClutterActor *self); G_END_DECLS diff --git a/clutter/clutter-drag-action.c b/clutter/clutter-drag-action.c index 1a34b6764..ae51e8104 100644 --- a/clutter/clutter-drag-action.c +++ b/clutter/clutter-drag-action.c @@ -23,7 +23,7 @@ */ /** - * SECTION:ClutterDragAction + * SECTION:clutter-drag-action * @Title: ClutterDragAction * @Short_Description: Action enabling dragging on actors * diff --git a/clutter/clutter-event.h b/clutter/clutter-event.h index f0dc8a357..d5e641b6b 100644 --- a/clutter/clutter-event.h +++ b/clutter/clutter-event.h @@ -417,7 +417,6 @@ struct _ClutterStageStateEvent /** * ClutterEvent: - * @type: event type * * Generic event wrapper. * @@ -425,6 +424,7 @@ struct _ClutterStageStateEvent */ union _ClutterEvent { + /*< private >*/ ClutterEventType type; ClutterAnyEvent any; diff --git a/clutter/clutter-media.h b/clutter/clutter-media.h index a1a768818..7471940d4 100644 --- a/clutter/clutter-media.h +++ b/clutter/clutter-media.h @@ -65,6 +65,7 @@ struct _ClutterMediaIface /*< private >*/ GTypeInterface base_iface; + /*< public >*/ /* signals */ void (* eos) (ClutterMedia *media); void (* error) (ClutterMedia *media, diff --git a/clutter/clutter-stage-manager.h b/clutter/clutter-stage-manager.h index 09a334c14..6cb9c5171 100644 --- a/clutter/clutter-stage-manager.h +++ b/clutter/clutter-stage-manager.h @@ -53,10 +53,6 @@ typedef struct _ClutterStageManagerClass ClutterStageManagerClass; /** * ClutterStageManagerClass: - * @stage_added: class handler for the #ClutterStageManager::stage-added - * signal - * @stage_removed: class handler for the #ClutterStageManager::stage-removed - * signal * * The #ClutterStageManagerClass structure contains only private data * and should be accessed using the provided API diff --git a/configure.ac b/configure.ac index b55d091e4..a7c29b1da 100644 --- a/configure.ac +++ b/configure.ac @@ -766,8 +766,8 @@ PKG_CHECK_MODULES(CLUTTER_DEPS, [$CLUTTER_REQUIRES]) AC_SUBST(CLUTTER_REQUIRES) -CLUTTER_CFLAGS="$SDL_CFLAGS $EGL_CFLAGS $GLX_CFLAGS $OSX_CFLAGS $WIN32_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_PROFILE_CFLAGS" -CLUTTER_LIBS="$SDL_LIBS $EGL_LIBS $X11_LIBS $GLX_LIBS $OSX_LIBS $WIN32_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_PROFILE_LDFLAGS" +CLUTTER_CFLAGS="$EGL_CFLAGS $GLX_CFLAGS $OSX_CFLAGS $WIN32_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_PROFILE_CFLAGS" +CLUTTER_LIBS="$EGL_LIBS $X11_LIBS $GLX_LIBS $OSX_LIBS $WIN32_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_PROFILE_LDFLAGS" AC_SUBST(CLUTTER_CFLAGS) AC_SUBST(CLUTTER_LIBS) @@ -778,7 +778,7 @@ GOBJECT_INTROSPECTION_CHECK([0.6.7]) dnl === GTK Doc check ========================================================= -GTK_DOC_CHECK([1.13]) +GTK_DOC_CHECK([1.13], [--flavour no-tmpl]) # we don't want to build the documentation from a Git clone unless we # explicitly tell configure to do so; this allows avoiding to recurse into diff --git a/doc/reference/clutter/Makefile.am b/doc/reference/clutter/Makefile.am index bcedb36ec..57a3eabfe 100644 --- a/doc/reference/clutter/Makefile.am +++ b/doc/reference/clutter/Makefile.am @@ -64,6 +64,7 @@ CFILE_GLOB=$(top_srcdir)/clutter/*.c \ # e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h IGNORE_HFILES=\ clutter.h \ + clutter-actor-meta-private.h \ clutter-bezier.h \ clutter-debug.h \ clutter-deprecated.h \ diff --git a/doc/reference/clutter/clutter-docs.xml.in b/doc/reference/clutter/clutter-docs.xml.in index 2fa61f3ca..080d3297b 100644 --- a/doc/reference/clutter/clutter-docs.xml.in +++ b/doc/reference/clutter/clutter-docs.xml.in @@ -60,6 +60,7 @@ + @@ -88,6 +89,16 @@ + + Actor Modifiers + + + + + + + + diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 7c65d53d4..318e9e7ff 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -274,7 +274,6 @@ CLUTTER_ACTOR_IS_REACTIVE ClutterActorFlags ClutterRequestMode -ClutterGeometry CLUTTER_CALLBACK ClutterCallback ClutterActor @@ -409,6 +408,16 @@ clutter_actor_set_text_direction clutter_actor_get_text_direction clutter_actor_has_pointer + +clutter_actor_add_action +clutter_actor_remove_action +clutter_actor_get_actions +clutter_actor_clear_actions +clutter_actor_add_constraint +clutter_actor_remove_constraint +clutter_actor_get_constraints +clutter_actor_clear_constraints + ClutterActorBox clutter_actor_box_new @@ -434,6 +443,10 @@ clutter_vertex_copy clutter_vertex_free clutter_vertex_equal + +ClutterGeometry +clutter_geometry_union + CLUTTER_TYPE_GEOMETRY CLUTTER_TYPE_ACTOR_BOX @@ -444,7 +457,9 @@ CLUTTER_TYPE_ACTOR CLUTTER_ACTOR_CLASS CLUTTER_IS_ACTOR_CLASS CLUTTER_ACTOR_GET_CLASS + +ClutterRedrawFlags ClutterActorPrivate clutter_actor_get_type clutter_actor_box_get_type @@ -1712,6 +1727,9 @@ clutter_text_get_type ClutterAnimatable ClutterAnimatableIface clutter_animatable_animate_property +clutter_animatable_find_property +clutter_animatable_get_initial_state +clutter_animatable_set_final_state CLUTTER_TYPE_ANIMATABLE @@ -1993,6 +2011,8 @@ clutter_box_layout_set_spacing clutter_box_layout_get_spacing clutter_box_layout_set_vertical clutter_box_layout_get_vertical +clutter_box_layout_set_homogeneous +clutter_box_layout_get_homogeneous clutter_box_layout_pack @@ -2075,3 +2095,120 @@ clutter_animator_get_type clutter_animator_key_get_type ClutterAnimatorPrivate
+ +
+clutter-actor-meta +ClutterActorMeta +ClutterActorMeta +ClutterActorMetaClass +clutter_actor_meta_set_name +clutter_actor_meta_get_name +clutter_actor_meta_set_enabled +clutter_actor_meta_get_enabled + + +clutter_actor_meta_get_actor + + +CLUTTER_TYPE_ACTOR_META +CLUTTER_ACTOR_META +CLUTTER_ACTOR_META_CLASS +CLUTTER_IS_ACTOR_META +CLUTTER_IS_ACTOR_META_CLASS +CLUTTER_ACTOR_META_GET_CLASS +clutter_actor_meta_get_type + + +ClutterActorMetaPrivate +
+ +
+clutter-action +ClutterAction +ClutterAction +ClutterActionClass + + +CLUTTER_TYPE_ACTION +CLUTTER_ACTION +CLUTTER_ACTION_CLASS +CLUTTER_IS_ACTION +CLUTTER_IS_ACTION_CLASS +CLUTTER_ACTION_GET_CLASS +clutter_action_get_type +
+ +
+clutter-constraint +ClutterConstraint +ClutterConstraint +ClutterConstraintClass + + +CLUTTER_TYPE_CONSTRAINT +CLUTTER_CONSTRAINT +CLUTTER_CONSTRAINT_CLASS +CLUTTER_IS_CONSTRAINT +CLUTTER_IS_CONSTRAINT_CLASS +CLUTTER_CONSTRAINT_GET_CLASS +clutter_constraint_get_type +
+ +
+clutter-drag-action +ClutterDragAction +ClutterDragAction +ClutterDragActionClass +clutter_drag_action_new +clutter_drag_action_set_drag_threshold +clutter_drag_action_get_drag_threshold +clutter_drag_action_set_drag_handle +clutter_drag_action_get_drag_handle +ClutterDragAxis +clutter_drag_action_set_drag_axis +clutter_drag_action_get_drag_axis + + +clutter_drag_action_get_press_coords +clutter_drag_action_get_motion_coords + + +CLUTTER_TYPE_DRAG_ACTION +CLUTTER_DRAG_ACTION +CLUTTER_DRAG_ACTION_CLASS +CLUTTER_IS_DRAG_ACTION +CLUTTER_IS_DRAG_ACTION_CLASS +CLUTTER_DRAG_ACTION_GET_CLASS +clutter_drag_action_get_type + + +ClutterDragActionPrivate +
+ +
+clutter-bind-constraint +ClutterBindConstraint +ClutterBindConstraint +ClutterBindCoordinate +clutter_bind_constraint_new + + +CLUTTER_TYPE_BIND_CONSTRAINT +CLUTTER_BIND_CONSTRAINT +CLUTTER_IS_BIND_CONSTRAINT +clutter_bind_constraint_get_type +
+ +
+clutter-align-constraint +ClutterAlignConstraint +ClutterAlignConstraint +ClutterAlignAxis +clutter_align_constraint_new + + +CLUTTER_TYPE_ALIGN_CONSTRAINT +CLUTTER_ALIGN_CONSTRAINT +CLUTTER_IS_ALIGN_CONSTRAINT +clutter_align_constraint_get_type +
diff --git a/doc/reference/clutter/clutter.types b/doc/reference/clutter/clutter.types index 21b6a809d..ce8d6ab13 100644 --- a/doc/reference/clutter/clutter.types +++ b/doc/reference/clutter/clutter.types @@ -43,3 +43,9 @@ clutter_box_layout_get_type clutter_input_device_get_type clutter_device_manager_get_type clutter_animator_get_type +clutter_actor_meta_get_type +clutter_action_get_type +clutter_drag_action_get_type +clutter_constraint_get_type +clutter_bind_constraint_get_type +clutter_align_constraint_get_type From 5d1b18669b94afc68389bd75771f21cedd4e0d88 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 18:17:49 +0100 Subject: [PATCH 16/24] Use a 9 grid for the constraints test Let's complicate the interactive constraints test a little bit by adding more actors and animating two constraints at a time. --- tests/interactive/test-constraints.c | 156 +++++++++++++++++---------- 1 file changed, 102 insertions(+), 54 deletions(-) diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 161a435c8..86f5d4d10 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -3,10 +3,23 @@ #include #define H_PADDING 32 +#define V_PADDING 32 -static ClutterActor *center_rect = NULL; -static ClutterActor *left_rect = NULL; -static ClutterActor *right_rect = NULL; +enum +{ + NorthWest, North, NorthEast, + West, Center, East, + SouthWest, South, SouthEast, + + N_RECTS +}; + +static ClutterActor *rects[N_RECTS] = { NULL, }; +static const gchar *colors[N_RECTS] = { + "#8ae234", "#73d216", "#4e9a06", + "#729fcf", "#3465a4", "#204a87", + "#ef2929", "#cc0000", "#a40000" +}; static gboolean is_expanded = FALSE; @@ -17,35 +30,82 @@ on_button_release (ClutterActor *actor, { if (!is_expanded) { - gfloat left_offset = (clutter_actor_get_width (left_rect) + H_PADDING) - * -1.0f; - gfloat right_offset = clutter_actor_get_width (right_rect) + H_PADDING; + gfloat north_offset, south_offset; + gfloat west_offset, east_offset; - clutter_actor_animate (center_rect, CLUTTER_LINEAR, 500, + north_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING) + * -1.0f; + south_offset = (clutter_actor_get_height (rects[Center]) + V_PADDING); + + west_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING) + * -1.0f; + east_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING); + + clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, "opacity", 128, NULL); - clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, + + clutter_actor_animate (rects[NorthWest], CLUTTER_EASE_OUT_CUBIC, 500, "opacity", 255, - "@constraints.x-bind.offset", left_offset, + "@constraints.x-bind.offset", west_offset, + "@constraints.y-bind.offset", north_offset, NULL); - clutter_actor_animate (right_rect, CLUTTER_EASE_OUT_CUBIC, 500, + clutter_actor_animate (rects[North], CLUTTER_EASE_OUT_CUBIC, 500, "opacity", 255, - "@constraints.x-bind.offset", right_offset, + "@constraints.y-bind.offset", north_offset, + NULL); + clutter_actor_animate (rects[NorthEast], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + "@constraints.y-bind.offset", north_offset, + NULL); + + clutter_actor_animate (rects[West], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", west_offset, + NULL); + clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, + "opacity", 128, + NULL); + clutter_actor_animate (rects[East], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + NULL); + + clutter_actor_animate (rects[SouthWest], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", west_offset, + "@constraints.y-bind.offset", south_offset, + NULL); + clutter_actor_animate (rects[South], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.y-bind.offset", south_offset, + NULL); + clutter_actor_animate (rects[SouthEast], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 255, + "@constraints.x-bind.offset", east_offset, + "@constraints.y-bind.offset", south_offset, NULL); } else { - clutter_actor_animate (center_rect, CLUTTER_LINEAR, 500, + gint i; + + clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, "opacity", 255, NULL); - clutter_actor_animate (left_rect, CLUTTER_EASE_OUT_CUBIC, 500, - "opacity", 0, - "@constraints.x-bind.offset", 0.0f, - NULL); - clutter_actor_animate (right_rect, CLUTTER_EASE_OUT_CUBIC, 500, - "opacity", 0, - "@constraints.x-bind.offset", 0.0f, - NULL); + + for (i = NorthWest; i < N_RECTS; i++) + { + if (i == Center) + continue; + + clutter_actor_animate (rects[i], CLUTTER_EASE_OUT_CUBIC, 500, + "opacity", 0, + "@constraints.x-bind.offset", 0.0f, + "@constraints.y-bind.offset", 0.0f, + NULL); + } } is_expanded = !is_expanded; @@ -57,8 +117,9 @@ G_MODULE_EXPORT int test_constraints_main (int argc, char *argv[]) { ClutterActor *stage, *rect; - ClutterColor rect_color; ClutterConstraint *constraint; + ClutterColor rect_color; + gint i; clutter_init (&argc, &argv); @@ -68,7 +129,7 @@ test_constraints_main (int argc, char *argv[]) clutter_actor_set_size (stage, 800, 600); /* main rect */ - clutter_color_from_string (&rect_color, "#73d216ff"); + clutter_color_from_string (&rect_color, "#3465a4"); rect = clutter_rectangle_new (); g_signal_connect (rect, "button-release-event", G_CALLBACK (on_button_release), @@ -86,43 +147,30 @@ test_constraints_main (int argc, char *argv[]) clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); clutter_actor_add_constraint (rect, constraint); - center_rect = rect; + rects[Center] = rect; - /* left rectangle */ - clutter_color_from_string (&rect_color, "#cc0000ff"); - rect = clutter_rectangle_new (); - clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); - clutter_actor_set_size (rect, 128, 128); - clutter_actor_set_opacity (rect, 0); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); + for (i = 0; i < N_RECTS; i++) + { + if (i == Center) + continue; - constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X, 0.0f); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); - clutter_actor_add_constraint (rect, constraint); + clutter_color_from_string (&rect_color, colors[i]); + rect = clutter_rectangle_new (); + clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); + clutter_actor_set_size (rect, 128, 128); + clutter_actor_set_opacity (rect, 0); + clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); - clutter_actor_add_constraint (rect, constraint); + constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_X, 0.0); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); + clutter_actor_add_constraint (rect, constraint); - left_rect = rect; + constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0); + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-bind"); + clutter_actor_add_constraint (rect, constraint); - /* right rectangle */ - clutter_color_from_string (&rect_color, "#3465a4ff"); - rect = clutter_rectangle_new (); - clutter_rectangle_set_color (CLUTTER_RECTANGLE (rect), &rect_color); - clutter_actor_set_size (rect, 128, 128); - clutter_actor_set_opacity (rect, 0); - clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); - - constraint = clutter_bind_constraint_new (center_rect, CLUTTER_BIND_X, 0.0f); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); - clutter_actor_add_constraint (rect, constraint); - - constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); - clutter_actor_add_constraint (rect, constraint); - - right_rect = rect; + rects[i] = rect; + } clutter_actor_show (stage); From 86a773536f9b31db1ac4cd6c74a4e4f790041d8f Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 18:20:27 +0100 Subject: [PATCH 17/24] Set the stage resizable in test-constraints To demonstrate that constraints can be used to reposition actors in a resizable stage, set the :user-resizable property to TRUE, and spend the next 15 minutes playing with the stage size. --- tests/interactive/test-constraints.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 86f5d4d10..5c0fd4350 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -126,6 +126,7 @@ test_constraints_main (int argc, char *argv[]) stage = clutter_stage_new (); g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); clutter_stage_set_title (CLUTTER_STAGE (stage), "Constraints"); + clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE); clutter_actor_set_size (stage, 800, 600); /* main rect */ From 4dc91339c308395997aee5330a2630c57fa8037c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Wed, 19 May 2010 18:23:29 +0100 Subject: [PATCH 18/24] Remove a redundant animation --- tests/interactive/test-constraints.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 5c0fd4350..0f57ff21f 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -41,10 +41,6 @@ on_button_release (ClutterActor *actor, * -1.0f; east_offset = (clutter_actor_get_width (rects[Center]) + H_PADDING); - clutter_actor_animate (rects[Center], CLUTTER_LINEAR, 500, - "opacity", 128, - NULL); - clutter_actor_animate (rects[NorthWest], CLUTTER_EASE_OUT_CUBIC, 500, "opacity", 255, "@constraints.x-bind.offset", west_offset, From 7ce26939447327f8d87be5015ddec48b70c5c442 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 11:19:51 +0100 Subject: [PATCH 19/24] Add named modifiers for Action and Constraint The ClutterActor API should have modifier methods for adding, removing and retrieving Actions and Constraints using the ClutterActorMeta:name property - mostly, for convenience. --- clutter/clutter-action.h | 19 ++- clutter/clutter-actor.c | 182 +++++++++++++++++++++ clutter/clutter-constraint.h | 19 ++- doc/reference/clutter/clutter-sections.txt | 6 + tests/interactive/test-constraints.c | 12 +- 5 files changed, 218 insertions(+), 20 deletions(-) diff --git a/clutter/clutter-action.h b/clutter/clutter-action.h index 7f3c8501c..afeafd91c 100644 --- a/clutter/clutter-action.h +++ b/clutter/clutter-action.h @@ -82,12 +82,19 @@ struct _ClutterActionClass GType clutter_action_get_type (void) G_GNUC_CONST; /* ClutterActor API */ -void clutter_actor_add_action (ClutterActor *self, - ClutterAction *action); -void clutter_actor_remove_action (ClutterActor *self, - ClutterAction *action); -GList *clutter_actor_get_actions (ClutterActor *self); -void clutter_actor_clear_actions (ClutterActor *self); +void clutter_actor_add_action (ClutterActor *self, + ClutterAction *action); +void clutter_actor_add_action_with_name (ClutterActor *self, + const gchar *name, + ClutterAction *action); +void clutter_actor_remove_action (ClutterActor *self, + ClutterAction *action); +void clutter_actor_remove_action_by_name (ClutterActor *self, + const gchar *name); +ClutterAction *clutter_actor_get_action (ClutterActor *self, + const gchar *name); +GList * clutter_actor_get_actions (ClutterActor *self); +void clutter_actor_clear_actions (ClutterActor *self); G_END_DECLS diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index a1dcde57d..b8d8475be 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -10478,6 +10478,37 @@ clutter_actor_add_action (ClutterActor *self, g_object_notify (G_OBJECT (self), "actions"); } +/** + * clutter_actor_add_action_with_name: + * @self: a #ClutterActor + * @name: the name to set on the action + * @constraint: a #ClutterAction + * + * A convenience function for setting the name of a #ClutterAction + * while adding it to the list of actions applied to @self + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (action), name); + * clutter_actor_add_action (self, action); + * ]| + * + * Since: 1.4 + */ +void +clutter_actor_add_action_with_name (ClutterActor *self, + const gchar *name, + ClutterAction *action) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_ACTION (self)); + + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (action), name); + clutter_actor_add_action (self, action); +} + /** * clutter_actor_remove_action: * @self: a #ClutterActor @@ -10508,6 +10539,40 @@ clutter_actor_remove_action (ClutterActor *self, g_object_notify (G_OBJECT (self), "actions"); } +/** + * clutter_actor_remove_action_by_name: + * @self: a #ClutterActor + * @name: the name of the action to remove + * + * Removes the #ClutterAction with the given name from the list + * of actions applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_remove_action_by_name (ClutterActor *self, + const gchar *name) +{ + ClutterActorPrivate *priv; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + priv = self->priv; + + if (priv->actions == NULL) + return; + + meta = _clutter_meta_group_get_meta (priv->actions, name); + if (meta == NULL) + return; + + _clutter_meta_group_remove_meta (priv->actions, meta); + + g_object_notify (G_OBJECT (self), "actions"); +} + /** * clutter_actor_get_actions: * @self: a #ClutterActor @@ -10536,6 +10601,33 @@ clutter_actor_get_actions (ClutterActor *self) return g_list_copy ((GList *) actions); } +/** + * clutter_actor_get_action: + * @self: a #ClutterActor + * @name: the name of the action to retrieve + * + * Retrieves the #ClutterAction with the given name in the list + * of actions applied to @self + * + * Return value: (transfer none): a #ClutterAction for the given + * name, or %NULL. The returned #ClutterAction is owned by the + * actor and it should not be unreferenced directly + * + * Since: 1.4 + */ +ClutterAction * +clutter_actor_get_action (ClutterActor *self, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + if (self->priv->actions == NULL) + return NULL; + + return CLUTTER_ACTION (_clutter_meta_group_get_meta (self->priv->actions, name)); +} + /** * clutter_actor_clear_actions: * @self: a #ClutterActor @@ -10592,6 +10684,37 @@ clutter_actor_add_constraint (ClutterActor *self, g_object_notify (G_OBJECT (self), "constraints"); } +/** + * clutter_actor_add_constraint_with_name: + * @self: a #ClutterActor + * @name: the name to set on the constraint + * @constraint: a #ClutterConstraint + * + * A convenience function for setting the name of a #ClutterConstraint + * while adding it to the list of constraints applied to @self + * + * This function is the logical equivalent of: + * + * |[ + * clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), name); + * clutter_actor_add_constraint (self, constraint); + * ]| + * + * Since: 1.4 + */ +void +clutter_actor_add_constraint_with_name (ClutterActor *self, + const gchar *name, + ClutterConstraint *constraint) +{ + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint)); + + clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), name); + clutter_actor_add_constraint (self, constraint); +} + /** * clutter_actor_remove_constraint: * @self: a #ClutterActor @@ -10623,6 +10746,38 @@ clutter_actor_remove_constraint (ClutterActor *self, g_object_notify (G_OBJECT (self), "constraints"); } +/** + * clutter_actor_remove_constraint_by_name: + * @self: a #ClutterActor + * @name: the name of the constraint to remove + * + * Removes the #ClutterConstraint with the given name from the list + * of constraints applied to @self + * + * Since: 1.4 + */ +void +clutter_actor_remove_constraint_by_name (ClutterActor *self, + const gchar *name) +{ + ClutterActorPrivate *priv; + ClutterActorMeta *meta; + + g_return_if_fail (CLUTTER_IS_ACTOR (self)); + g_return_if_fail (name != NULL); + + priv = self->priv; + + if (priv->constraints == NULL) + return; + + meta = _clutter_meta_group_get_meta (priv->constraints, name); + if (meta == NULL) + return; + + _clutter_meta_group_remove_meta (priv->constraints, meta); +} + /** * clutter_actor_get_constraints: * @self: a #ClutterActor @@ -10651,6 +10806,33 @@ clutter_actor_get_constraints (ClutterActor *self) return g_list_copy ((GList *) constraints); } +/** + * clutter_actor_get_constraint: + * @self: a #ClutterActor + * @name: the name of the constraint to retrieve + * + * Retrieves the #ClutterConstraint with the given name in the list + * of constraints applied to @self + * + * Return value: (transfer none): a #ClutterConstraint for the given + * name, or %NULL. The returned #ClutterConstraint is owned by the + * actor and it should not be unreferenced directly + * + * Since: 1.4 + */ +ClutterConstraint * +clutter_actor_get_constraint (ClutterActor *self, + const gchar *name) +{ + g_return_val_if_fail (CLUTTER_IS_ACTOR (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + if (self->priv->constraints == NULL) + return NULL; + + return CLUTTER_CONSTRAINT (_clutter_meta_group_get_meta (self->priv->constraints, name)); +} + /** * clutter_actor_clear_constraints: * @self: a #ClutterActor diff --git a/clutter/clutter-constraint.h b/clutter/clutter-constraint.h index 03c664c06..948670585 100644 --- a/clutter/clutter-constraint.h +++ b/clutter/clutter-constraint.h @@ -83,12 +83,19 @@ struct _ClutterConstraintClass GType clutter_constraint_get_type (void) G_GNUC_CONST; /* ClutterActor API */ -void clutter_actor_add_constraint (ClutterActor *self, - ClutterConstraint *constraint); -void clutter_actor_remove_constraint (ClutterActor *self, - ClutterConstraint *constraint); -GList *clutter_actor_get_constraints (ClutterActor *self); -void clutter_actor_clear_constraints (ClutterActor *self); +void clutter_actor_add_constraint (ClutterActor *self, + ClutterConstraint *constraint); +void clutter_actor_add_constraint_with_name (ClutterActor *self, + const gchar *name, + ClutterConstraint *constraint); +void clutter_actor_remove_constraint (ClutterActor *self, + ClutterConstraint *constraint); +void clutter_actor_remove_constraint_by_name (ClutterActor *self, + const gchar *name); +GList * clutter_actor_get_constraints (ClutterActor *self); +ClutterConstraint *clutter_actor_get_constraint (ClutterActor *self, + const gchar *name); +void clutter_actor_clear_constraints (ClutterActor *self); G_END_DECLS diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index 318e9e7ff..ae870b997 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -410,12 +410,18 @@ clutter_actor_has_pointer clutter_actor_add_action +clutter_actor_add_action_with_name clutter_actor_remove_action +clutter_actor_remove_action_by_name clutter_actor_get_actions +clutter_actor_get_action clutter_actor_clear_actions clutter_actor_add_constraint +clutter_actor_add_constraint_with_name clutter_actor_remove_constraint +clutter_actor_remove_constraint_by_name clutter_actor_get_constraints +clutter_actor_get_constraint clutter_actor_clear_constraints diff --git a/tests/interactive/test-constraints.c b/tests/interactive/test-constraints.c index 0f57ff21f..9efb55dab 100644 --- a/tests/interactive/test-constraints.c +++ b/tests/interactive/test-constraints.c @@ -137,12 +137,10 @@ test_constraints_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-align"); - clutter_actor_add_constraint (rect, constraint); + clutter_actor_add_constraint_with_name (rect, "x-align", constraint); constraint = clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-align"); - clutter_actor_add_constraint (rect, constraint); + clutter_actor_add_constraint_with_name (rect, "y-align", constraint); rects[Center] = rect; @@ -159,12 +157,10 @@ test_constraints_main (int argc, char *argv[]) clutter_container_add_actor (CLUTTER_CONTAINER (stage), rect); constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_X, 0.0); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "x-bind"); - clutter_actor_add_constraint (rect, constraint); + clutter_actor_add_constraint_with_name (rect, "x-bind", constraint); constraint = clutter_bind_constraint_new (rects[Center], CLUTTER_BIND_Y, 0.0); - clutter_actor_meta_set_name (CLUTTER_ACTOR_META (constraint), "y-bind"); - clutter_actor_add_constraint (rect, constraint); + clutter_actor_add_constraint_with_name (rect, "y-bind", constraint); rects[i] = rect; } From 80a8568e0e72db27776f9bdd22cf331ffcd2ba74 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 11:45:25 +0100 Subject: [PATCH 20/24] doc: Fix parameter documentation --- clutter/clutter-actor.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clutter/clutter-actor.c b/clutter/clutter-actor.c index b8d8475be..93ad88f00 100644 --- a/clutter/clutter-actor.c +++ b/clutter/clutter-actor.c @@ -10482,7 +10482,7 @@ clutter_actor_add_action (ClutterActor *self, * clutter_actor_add_action_with_name: * @self: a #ClutterActor * @name: the name to set on the action - * @constraint: a #ClutterAction + * @action: a #ClutterAction * * A convenience function for setting the name of a #ClutterAction * while adding it to the list of actions applied to @self From c75a6b1a1d63f5b68a878f1a8724586ad56fd3dd Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 11:45:54 +0100 Subject: [PATCH 21/24] doc: Remove gtk-doc annotations from the json-glib copy There's no need to use gtk-doc annotations: the API is internal to Clutter. --- clutter/json/json-array.c | 52 ++++++++++++++++---------------- clutter/json/json-generator.c | 18 +++++------ clutter/json/json-node.c | 56 +++++++++++++++++------------------ clutter/json/json-object.c | 56 +++++++++++++++++------------------ clutter/json/json-parser.c | 32 ++++++++++---------- 5 files changed, 107 insertions(+), 107 deletions(-) diff --git a/clutter/json/json-array.c b/clutter/json/json-array.c index 16f36a4b0..83e2e0245 100644 --- a/clutter/json/json-array.c +++ b/clutter/json/json-array.c @@ -27,7 +27,7 @@ #include "json-types-private.h" -/** +/* * SECTION:json-array * @short_description: a JSON array representation * @@ -57,7 +57,7 @@ json_array_get_type (void) return array_type; } -/** +/* * json_array_new: * * Creates a new #JsonArray. @@ -77,7 +77,7 @@ json_array_new (void) return array; } -/** +/* * json_array_sized_new: * @n_elements: number of slots to pre-allocate * @@ -98,7 +98,7 @@ json_array_sized_new (guint n_elements) return array; } -/** +/* * json_array_ref: * @array: a #JsonArray * @@ -118,7 +118,7 @@ json_array_ref (JsonArray *array) return array; } -/** +/* * json_array_unref: * @array: a #JsonArray * @@ -151,7 +151,7 @@ json_array_unref (JsonArray *array) } } -/** +/* * json_array_get_elements: * @array: a #JsonArray * @@ -178,7 +178,7 @@ json_array_get_elements (JsonArray *array) return g_list_reverse (retval); } -/** +/* * json_array_dup_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -207,7 +207,7 @@ json_array_dup_element (JsonArray *array, return json_node_copy (retval); } -/** +/* * json_array_get_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -227,7 +227,7 @@ json_array_get_element (JsonArray *array, return g_ptr_array_index (array->elements, index_); } -/** +/* * json_array_get_int_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -257,7 +257,7 @@ json_array_get_int_element (JsonArray *array, return json_node_get_int (node); } -/** +/* * json_array_get_double_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -287,7 +287,7 @@ json_array_get_double_element (JsonArray *array, return json_node_get_double (node); } -/** +/* * json_array_get_boolean_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -317,7 +317,7 @@ json_array_get_boolean_element (JsonArray *array, return json_node_get_boolean (node); } -/** +/* * json_array_get_string_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -348,7 +348,7 @@ json_array_get_string_element (JsonArray *array, return json_node_get_string (node); } -/** +/* * json_array_get_null_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -376,7 +376,7 @@ json_array_get_null_element (JsonArray *array, return JSON_NODE_TYPE (node) == JSON_NODE_NULL; } -/** +/* * json_array_get_array_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -406,7 +406,7 @@ json_array_get_array_element (JsonArray *array, return json_node_get_array (node); } -/** +/* * json_array_get_object_element: * @array: a #JsonArray * @index_: the index of the element to retrieve @@ -436,7 +436,7 @@ json_array_get_object_element (JsonArray *array, return json_node_get_object (node); } -/** +/* * json_array_get_length: * @array: a #JsonArray * @@ -452,7 +452,7 @@ json_array_get_length (JsonArray *array) return array->elements->len; } -/** +/* * json_array_add_element: * @array: a #JsonArray * @node: a #JsonNode @@ -470,7 +470,7 @@ json_array_add_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_int_element: * @array: a #JsonArray * @value: an integer value @@ -495,7 +495,7 @@ json_array_add_int_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_double_element: * @array: a #JsonArray * @value: a floating point value @@ -520,7 +520,7 @@ json_array_add_double_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_boolean_element: * @array: a #JsonArray * @value: a boolean value @@ -545,7 +545,7 @@ json_array_add_boolean_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_string_element: * @array: a #JsonArray * @value: a string value @@ -571,7 +571,7 @@ json_array_add_string_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_null_element: * @array: a #JsonArray * @@ -593,7 +593,7 @@ json_array_add_null_element (JsonArray *array) g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_array_element: * @array: a #JsonArray * @value: a #JsonArray @@ -620,7 +620,7 @@ json_array_add_array_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_add_object_element: * @array: a #JsonArray * @value: a #JsonObject @@ -647,7 +647,7 @@ json_array_add_object_element (JsonArray *array, g_ptr_array_add (array->elements, node); } -/** +/* * json_array_remove_element: * @array: a #JsonArray * @index_: the position of the element to be removed @@ -665,7 +665,7 @@ json_array_remove_element (JsonArray *array, json_node_free (g_ptr_array_remove_index (array->elements, index_)); } -/** +/* * json_array_foreach_element: * @array: a #JsonArray * @func: the function to be called on each element diff --git a/clutter/json/json-generator.c b/clutter/json/json-generator.c index c77830e61..0766df34b 100644 --- a/clutter/json/json-generator.c +++ b/clutter/json/json-generator.c @@ -21,7 +21,7 @@ * Emmanuele Bassi */ -/** +/* * SECTION:json-generator * @short_description: Generates JSON data streams * @@ -191,7 +191,7 @@ json_generator_class_init (JsonGeneratorClass *klass) gobject_class->get_property = json_generator_get_property; gobject_class->finalize = json_generator_finalize; - /** + /* * JsonGenerator:pretty: * * Whether the output should be "pretty-printed", with indentation and @@ -205,7 +205,7 @@ json_generator_class_init (JsonGeneratorClass *klass) "Pretty-print the output", FALSE, G_PARAM_READWRITE)); - /** + /* * JsonGenerator:indent: * * Number of spaces to be used to indent when pretty printing. @@ -218,7 +218,7 @@ json_generator_class_init (JsonGeneratorClass *klass) 0, G_MAXUINT, 2, G_PARAM_READWRITE)); - /** + /* * JsonGenerator:root: * * The root #JsonNode to be used when constructing a JSON data @@ -233,7 +233,7 @@ json_generator_class_init (JsonGeneratorClass *klass) "Root of the JSON data tree", JSON_TYPE_NODE, G_PARAM_READWRITE)); - /** + /* * JsonGenerator:indent-char: * * The character that should be used when indenting in pretty print. @@ -519,7 +519,7 @@ dump_object (JsonGenerator *generator, return g_string_free (buffer, FALSE); } -/** +/* * json_generator_new: * * Creates a new #JsonGenerator. You can use this object to generate a @@ -534,7 +534,7 @@ json_generator_new (void) return g_object_new (JSON_TYPE_GENERATOR, NULL); } -/** +/* * json_generator_to_data: * @generator: a #JsonGenerator * @length: (out): return location for the length of the returned @@ -588,7 +588,7 @@ json_generator_to_data (JsonGenerator *generator, return retval; } -/** +/* * json_generator_to_file: * @generator: a #JsonGenerator * @filename: path to the target file @@ -618,7 +618,7 @@ json_generator_to_file (JsonGenerator *generator, return retval; } -/** +/* * json_generator_set_root: * @generator: a #JsonGenerator * @node: a #JsonNode diff --git a/clutter/json/json-node.c b/clutter/json/json-node.c index e1e457a7d..a56fc7493 100644 --- a/clutter/json/json-node.c +++ b/clutter/json/json-node.c @@ -29,7 +29,7 @@ #include "json-types-private.h" -/** +/* * SECTION:json-node * @short_description: Node in a JSON object model * @@ -61,7 +61,7 @@ json_node_get_type (void) return node_type; } -/** +/* * json_node_get_value_type: * @node: a #JsonNode * @@ -96,7 +96,7 @@ json_node_get_value_type (JsonNode *node) } } -/** +/* * json_node_new: * @type: a #JsonNodeType * @@ -118,7 +118,7 @@ json_node_new (JsonNodeType type) return data; } -/** +/* * json_node_copy: * @node: a #JsonNode * @@ -167,7 +167,7 @@ json_node_copy (JsonNode *node) return copy; } -/** +/* * json_node_set_object: * @node: a #JsonNode * @object: a #JsonObject @@ -190,7 +190,7 @@ json_node_set_object (JsonNode *node, node->data.object = NULL; } -/** +/* * json_node_take_object: * @node: a #JsonNode * @object: a #JsonObject @@ -214,7 +214,7 @@ json_node_take_object (JsonNode *node, node->data.object = object; } -/** +/* * json_node_get_object: * @node: a #JsonNode * @@ -231,7 +231,7 @@ json_node_get_object (JsonNode *node) return node->data.object; } -/** +/* * json_node_dup_object: * @node: a #JsonNode * @@ -252,7 +252,7 @@ json_node_dup_object (JsonNode *node) return NULL; } -/** +/* * json_node_set_array: * @node: a #JsonNode * @array: a #JsonArray @@ -275,7 +275,7 @@ json_node_set_array (JsonNode *node, node->data.array = NULL; } -/** +/* * json_node_take_array: * @node: a #JsonNode * @array: a #JsonArray @@ -299,7 +299,7 @@ json_node_take_array (JsonNode *node, node->data.array = array; } -/** +/* * json_node_get_array: * @node: a #JsonNode * @@ -316,7 +316,7 @@ json_node_get_array (JsonNode *node) return node->data.array; } -/** +/* * json_node_dup_array * @node: a #JsonNode * @@ -337,7 +337,7 @@ json_node_dup_array (JsonNode *node) return NULL; } -/** +/* * json_node_get_value: * @node: a #JsonNode * @value: return location for an uninitialized value @@ -366,7 +366,7 @@ node_value_unset (JsonNode *node) g_value_unset (&(node->data.value)); } -/** +/* * json_node_set_value: * @node: a #JsonNode * @value: the #GValue to set @@ -417,7 +417,7 @@ json_node_set_value (JsonNode *node, } -/** +/* * json_node_free: * @node: a #JsonNode * @@ -452,7 +452,7 @@ json_node_free (JsonNode *node) } } -/** +/* * json_node_type_name: * @node: a #JsonNode * @@ -484,7 +484,7 @@ json_node_type_name (JsonNode *node) return "unknown"; } -/** +/* * json_node_get_parent: * @node: a #JsonNode * @@ -500,7 +500,7 @@ json_node_get_parent (JsonNode *node) return node->parent; } -/** +/* * json_node_set_string: * @node: a #JsonNode of type %JSON_NODE_VALUE * @value: a string value @@ -530,7 +530,7 @@ json_node_set_string (JsonNode *node, } } -/** +/* * json_node_get_string: * @node: a #JsonNode of type %JSON_NODE_VALUE * @@ -552,7 +552,7 @@ json_node_get_string (JsonNode *node) return NULL; } -/** +/* * json_node_dup_string: * @node: a #JsonNode of type %JSON_NODE_VALUE * @@ -575,7 +575,7 @@ json_node_dup_string (JsonNode *node) return NULL; } -/** +/* * json_node_set_int: * @node: a #JsonNode of type %JSON_NODE_VALUE * @value: an integer value @@ -605,7 +605,7 @@ json_node_set_int (JsonNode *node, } } -/** +/* * json_node_get_int: * @node: a #JsonNode of type %JSON_NODE_VALUE * @@ -627,7 +627,7 @@ json_node_get_int (JsonNode *node) return 0; } -/** +/* * json_node_set_double: * @node: a #JsonNode of type %JSON_NODE_VALUE * @value: a double value @@ -657,7 +657,7 @@ json_node_set_double (JsonNode *node, } } -/** +/* * json_node_get_double: * @node: a #JsonNode of type %JSON_NODE_VALUE * @@ -679,7 +679,7 @@ json_node_get_double (JsonNode *node) return 0.0; } -/** +/* * json_node_set_boolean: * @node: a #JsonNode of type %JSON_NODE_VALUE * @value: a boolean value @@ -709,7 +709,7 @@ json_node_set_boolean (JsonNode *node, } } -/** +/* * json_node_get_boolean: * @node: a #JsonNode of type %JSON_NODE_VALUE * @@ -731,7 +731,7 @@ json_node_get_boolean (JsonNode *node) return FALSE; } -/** +/* * json_node_get_node_type: * @node: a #JsonNode * @@ -749,7 +749,7 @@ json_node_get_node_type (JsonNode *node) return node->type; } -/** +/* * json_node_is_null: * @node: a #JsonNode * diff --git a/clutter/json/json-object.c b/clutter/json/json-object.c index d1bbe98cd..f3324976b 100644 --- a/clutter/json/json-object.c +++ b/clutter/json/json-object.c @@ -29,7 +29,7 @@ #include "json-types-private.h" -/** +/* * SECTION:json-object * @short_description: a JSON object representation * @@ -64,7 +64,7 @@ json_object_get_type (void) return object_type; } -/** +/* * json_object_new: * * Creates a new #JsonObject, an JSON object type representation. @@ -86,7 +86,7 @@ json_object_new (void) return object; } -/** +/* * json_object_ref: * @object: a #JsonObject * @@ -106,7 +106,7 @@ json_object_ref (JsonObject *object) return object; } -/** +/* * json_object_unref: * @object: a #JsonObject * @@ -144,7 +144,7 @@ object_set_member_internal (JsonObject *object, node); } -/** +/* * json_object_add_member: * @object: a #JsonObject * @member_name: the name of the member @@ -178,7 +178,7 @@ json_object_add_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_member: * @object: a #JsonObject * @member_name: the name of the member @@ -204,7 +204,7 @@ json_object_set_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_int_member: * @object: a #JsonObject * @member_name: the name of the member @@ -232,7 +232,7 @@ json_object_set_int_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_double_member: * @object: a #JsonObject * @member_name: the name of the member @@ -260,7 +260,7 @@ json_object_set_double_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_boolean_member: * @object: a #JsonObject * @member_name: the name of the member @@ -288,7 +288,7 @@ json_object_set_boolean_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_string_member: * @object: a #JsonObject * @member_name: the name of the member @@ -316,7 +316,7 @@ json_object_set_string_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_null_member: * @object: a #JsonObject * @member_name: the name of the member @@ -341,7 +341,7 @@ json_object_set_null_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_array_member: * @object: a #JsonObject * @member_name: the name of the member @@ -371,7 +371,7 @@ json_object_set_array_member (JsonObject *object, object_set_member_internal (object, member_name, node); } -/** +/* * json_object_set_object_member: * @object: a #JsonObject * @member_name: the name of the member @@ -448,7 +448,7 @@ g_hash_table_get_values (GHashTable *hash_table) } #endif /* GLIB_MAJOR_VERSION == 2 && GLIB_MINOR_VERSION < 14 */ -/** +/* * json_object_get_members: * @object: a #JsonObject * @@ -468,7 +468,7 @@ json_object_get_members (JsonObject *object) return g_hash_table_get_keys (object->members); } -/** +/* * json_object_get_values: * @object: a #JsonObject * @@ -487,7 +487,7 @@ json_object_get_values (JsonObject *object) return g_hash_table_get_values (object->members); } -/** +/* * json_object_dup_member: * @object: a #JsonObject * @member_name: the name of the JSON object member to access @@ -523,7 +523,7 @@ object_get_member_internal (JsonObject *object, return g_hash_table_lookup (object->members, member_name); } -/** +/* * json_object_get_member: * @object: a #JsonObject * @member_name: the name of the JSON object member to access @@ -544,7 +544,7 @@ json_object_get_member (JsonObject *object, return object_get_member_internal (object, member_name); } -/** +/* * json_object_get_int_member: * @object: a #JsonObject * @member_name: the name of the member @@ -574,7 +574,7 @@ json_object_get_int_member (JsonObject *object, return json_node_get_int (node); } -/** +/* * json_object_get_double_member: * @object: a #JsonObject * @member_name: the name of the member @@ -604,7 +604,7 @@ json_object_get_double_member (JsonObject *object, return json_node_get_double (node); } -/** +/* * json_object_get_boolean_member: * @object: a #JsonObject * @member_name: the name of the member @@ -634,7 +634,7 @@ json_object_get_boolean_member (JsonObject *object, return json_node_get_boolean (node); } -/** +/* * json_object_get_null_member: * @object: a #JsonObject * @member_name: the name of the member @@ -663,7 +663,7 @@ json_object_get_null_member (JsonObject *object, return JSON_NODE_TYPE (node) == JSON_NODE_NULL; } -/** +/* * json_object_get_string_member: * @object: a #JsonObject * @member_name: the name of the member @@ -693,7 +693,7 @@ json_object_get_string_member (JsonObject *object, return json_node_get_string (node); } -/** +/* * json_object_get_array_member: * @object: a #JsonObject * @member_name: the name of the member @@ -723,7 +723,7 @@ json_object_get_array_member (JsonObject *object, return json_node_get_array (node); } -/** +/* * json_object_get_object_member: * @object: a #JsonObject * @member_name: the name of the member @@ -753,7 +753,7 @@ json_object_get_object_member (JsonObject *object, return json_node_get_object (node); } -/** +/* * json_object_has_member: * @object: a #JsonObject * @member_name: the name of a JSON object member @@ -772,7 +772,7 @@ json_object_has_member (JsonObject *object, return (g_hash_table_lookup (object->members, member_name) != NULL); } -/** +/* * json_object_get_size: * @object: a #JsonObject * @@ -788,7 +788,7 @@ json_object_get_size (JsonObject *object) return g_hash_table_size (object->members); } -/** +/* * json_object_remove_member: * @object: a #JsonObject * @member_name: the name of the member to remove @@ -827,7 +827,7 @@ json_object_foreach_internal (gpointer key, clos->func (clos->object, member_name, member_node, clos->data); } -/** +/* * json_object_foreach_member: * @object: a #JsonObject * @func: the function to be called on each member diff --git a/clutter/json/json-parser.c b/clutter/json/json-parser.c index 3ef5afb93..0cd2f64e4 100644 --- a/clutter/json/json-parser.c +++ b/clutter/json/json-parser.c @@ -17,7 +17,7 @@ * Emmanuele Bassi */ -/** +/* * SECTION:json-parser * @short_description: Parse JSON data streams * @@ -167,7 +167,7 @@ json_parser_class_init (JsonParserClass *klass) gobject_class->dispose = json_parser_dispose; - /** + /* * JsonParser::parse-start: * @parser: the #JsonParser that received the signal * @@ -182,7 +182,7 @@ json_parser_class_init (JsonParserClass *klass) NULL, NULL, _json_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** + /* * JsonParser::parse-end: * @parser: the #JsonParser that received the signal * @@ -197,7 +197,7 @@ json_parser_class_init (JsonParserClass *klass) NULL, NULL, _json_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** + /* * JsonParser::object-start: * @parser: the #JsonParser that received the signal * @@ -212,7 +212,7 @@ json_parser_class_init (JsonParserClass *klass) NULL, NULL, _json_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** + /* * JsonParser::object-member: * @parser: the #JsonParser that received the signal * @object: a #JsonObject @@ -232,7 +232,7 @@ json_parser_class_init (JsonParserClass *klass) G_TYPE_NONE, 2, JSON_TYPE_OBJECT, G_TYPE_STRING); - /** + /* * JsonParser::object-end: * @parser: the #JsonParser that received the signal * @object: the parsed #JsonObject @@ -249,7 +249,7 @@ json_parser_class_init (JsonParserClass *klass) _json_marshal_VOID__BOXED, G_TYPE_NONE, 1, JSON_TYPE_OBJECT); - /** + /* * JsonParser::array-start: * @parser: the #JsonParser that received the signal * @@ -264,7 +264,7 @@ json_parser_class_init (JsonParserClass *klass) NULL, NULL, _json_marshal_VOID__VOID, G_TYPE_NONE, 0); - /** + /* * JsonParser::array-element: * @parser: the #JsonParser that received the signal * @array: a #JsonArray @@ -284,7 +284,7 @@ json_parser_class_init (JsonParserClass *klass) G_TYPE_NONE, 2, JSON_TYPE_ARRAY, G_TYPE_INT); - /** + /* * JsonParser::array-end: * @parser: the #JsonParser that received the signal * @array: the parsed #JsonArrary @@ -301,7 +301,7 @@ json_parser_class_init (JsonParserClass *klass) _json_marshal_VOID__BOXED, G_TYPE_NONE, 1, JSON_TYPE_ARRAY); - /** + /* * JsonParser::error: * @parser: the parser instance that received the signal * @error: a pointer to the #GError @@ -885,7 +885,7 @@ json_scanner_new (JsonParser *parser) return scanner; } -/** +/* * json_parser_new: * * Creates a new #JsonParser instance. You can use the #JsonParser to @@ -901,7 +901,7 @@ json_parser_new (void) return g_object_new (JSON_TYPE_PARSER, NULL); } -/** +/* * json_parser_load_from_file: * @parser: a #JsonParser * @filename: the path for the file to parse @@ -944,7 +944,7 @@ json_parser_load_from_file (JsonParser *parser, return retval; } -/** +/* * json_parser_load_from_data: * @parser: a #JsonParser * @data: the buffer to parse @@ -1067,7 +1067,7 @@ json_parser_load_from_data (JsonParser *parser, return retval; } -/** +/* * json_parser_get_root: * @parser: a #JsonParser * @@ -1084,7 +1084,7 @@ json_parser_get_root (JsonParser *parser) return parser->priv->root; } -/** +/* * json_parser_get_current_line: * @parser: a #JsonParser * @@ -1103,7 +1103,7 @@ json_parser_get_current_line (JsonParser *parser) return 0; } -/** +/* * json_parser_get_current_pos: * @parser: a #JsonParser * From 1b0be8e3b98ea9c76155eabe27096f2a559eed5c Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 12:02:13 +0100 Subject: [PATCH 22/24] Remove the construct-only flag from ActorMeta:name The ClutterActorMeta:name property should be read-write, and be writeable at any time. --- clutter/clutter-actor-meta.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c index f2b50683a..ca9e0fa18 100644 --- a/clutter/clutter-actor-meta.c +++ b/clutter/clutter-actor-meta.c @@ -151,8 +151,7 @@ clutter_actor_meta_class_init (ClutterActorMetaClass *klass) "Name", "The name of the meta", NULL, - CLUTTER_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY); + CLUTTER_PARAM_READWRITE); g_object_class_install_property (gobject_class, PROP_NAME, pspec); /** @@ -197,15 +196,6 @@ clutter_actor_meta_set_name (ClutterActorMeta *meta, { g_return_if_fail (CLUTTER_IS_ACTOR_META (meta)); - if (meta->priv->name != NULL) - { - g_warning ("The ClutterActorMeta of type '%s' has already " - "been named '%s'", - G_OBJECT_TYPE_NAME (meta), - meta->priv->name); - return; - } - if (g_strcmp0 (meta->priv->name, name) == 0) return; From cc4729d42f9e67d826c4af41b8ac8c50197dcb97 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 12:03:10 +0100 Subject: [PATCH 23/24] Document the internal MetaGroup class Just because it's an internal class, ClutterMetaGroup should not be left undocumented. --- clutter/clutter-actor-meta.c | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/clutter/clutter-actor-meta.c b/clutter/clutter-actor-meta.c index ca9e0fa18..e318b8f86 100644 --- a/clutter/clutter-actor-meta.c +++ b/clutter/clutter-actor-meta.c @@ -307,6 +307,10 @@ clutter_actor_meta_get_actor (ClutterActorMeta *meta) return meta->priv->actor; } +/* + * ClutterMetaGroup: a collection of ClutterActorMeta instances + */ + G_DEFINE_TYPE (ClutterMetaGroup, _clutter_meta_group, G_TYPE_OBJECT); static void @@ -330,6 +334,16 @@ _clutter_meta_group_init (ClutterMetaGroup *self) { } +/* + * _clutter_meta_group_add_meta: + * @group: a #ClutterMetaGroup + * @meta: a #ClutterActorMeta to add + * + * Adds @meta to @group + * + * This function will remove the floating reference of @meta or, if the + * floating reference has already been sunk, add a reference to it + */ void _clutter_meta_group_add_meta (ClutterMetaGroup *group, ClutterActorMeta *meta) @@ -354,6 +368,13 @@ _clutter_meta_group_add_meta (ClutterMetaGroup *group, _clutter_actor_meta_set_actor (meta, group->actor); } +/* + * _clutter_meta_group_remove_meta: + * @group: a #ClutterMetaGroup + * @meta: a #ClutterActorMeta to remove + * + * Removes @meta from @group and releases the reference being held on it + */ void _clutter_meta_group_remove_meta (ClutterMetaGroup *group, ClutterActorMeta *meta) @@ -378,12 +399,27 @@ _clutter_meta_group_remove_meta (ClutterMetaGroup *group, g_object_unref (meta); } +/* + * _clutter_meta_group_peek_metas: + * @group: a #ClutterMetaGroup + * + * Returns a pointer to the #ClutterActorMeta list + * + * Return value: a const pointer to the #GList of #ClutterActorMeta + */ G_CONST_RETURN GList * _clutter_meta_group_peek_metas (ClutterMetaGroup *group) { return group->meta; } +/* + * _clutter_meta_group_clear_metas: + * @group: a #ClutterMetaGroup + * + * Clears @group of all #ClutterActorMeta instances and releases + * the reference on them + */ void _clutter_meta_group_clear_metas (ClutterMetaGroup *group) { @@ -394,6 +430,15 @@ _clutter_meta_group_clear_metas (ClutterMetaGroup *group) group->meta = NULL; } +/* + * _clutter_meta_group_get_meta: + * @group: a #ClutterMetaGroup + * @name: the name of the #ClutterActorMeta to retrieve + * + * Retrieves a named #ClutterActorMeta from @group + * + * Return value: a #ClutterActorMeta for the given name, or %NULL + */ ClutterActorMeta * _clutter_meta_group_get_meta (ClutterMetaGroup *group, const gchar *name) From 65678006a8763361d2b9b00b12a0deee90c1d580 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Thu, 20 May 2010 12:03:47 +0100 Subject: [PATCH 24/24] Add the Cogl API reference to the fixxref extra directories --- doc/reference/clutter/Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/reference/clutter/Makefile.am b/doc/reference/clutter/Makefile.am index 57a3eabfe..f0486c28c 100644 --- a/doc/reference/clutter/Makefile.am +++ b/doc/reference/clutter/Makefile.am @@ -38,6 +38,7 @@ MKTMPL_OPTIONS= # Extra options to supply to gtkdoc-fixref. Not normally needed. # e.g. FIXXREF_OPTIONS=--extra-dir=../gdk-pixbuf/html --extra-dir=../gdk/html FIXXREF_OPTIONS=\ + --extra-dir=../cogl/html \ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/glib \ --extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html/gobject \ --extra-dir=$(CAIRO_PREFIX)/share/gtk-doc/html/cairo \ @@ -84,7 +85,7 @@ IGNORE_HFILES=\ cogl \ eglnative \ eglx \ - fruity \ + fruity \ glx \ osx \ x11 \