8d51617979
This adds a wrapper macro to clutter-private that will use g_object_notify_by_pspec if it's compiled against a version of GLib that is sufficiently new. Otherwise it will notify by the property name as before by extracting the name from the pspec. The objects can then store a static array of GParamSpecs and notify using those as suggested in the documentation for g_object_notify_by_pspec. Note that the name of the variable used for storing the array of GParamSpecs is obj_props instead of properties as used in the documentation because some places in Clutter uses 'properties' as the name of a local variable. Mose of the classes in Clutter have been converted using the script in the bug report. Some classes have not been modified even though the script picked them up as described here: json-generator: We probably don't want to modify the internal copy of JSON behaviour-depth: rectangle: score: stage-manager: These aren't using the separate GParamSpec* variable style. blur-effect: win32/device-manager: Don't actually define any properties even though it has the enum. box-layout: flow-layout: Have some per-child properties that don't work automatically with the script. clutter-model: The script gets confused with ClutterModelIter stage: Script gets confused because PROP_USER_RESIZE doesn't match "user-resizable" test-layout: Don't really want to modify the tests http://bugzilla.clutter-project.org/show_bug.cgi?id=2150
488 lines
12 KiB
C
488 lines
12 KiB
C
/**
|
|
* SECTION:clutter-actor-meta
|
|
* @Title: ClutterActorMeta
|
|
* @Short_Description: Base class of actor modifiers
|
|
* @See_Also: #ClutterAction, #ClutterConstraint
|
|
*
|
|
* #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;
|
|
guint destroy_id;
|
|
|
|
gchar *name;
|
|
|
|
guint is_enabled : 1;
|
|
};
|
|
|
|
enum
|
|
{
|
|
PROP_0,
|
|
|
|
PROP_ACTOR,
|
|
PROP_NAME,
|
|
PROP_ENABLED,
|
|
|
|
PROP_LAST
|
|
};
|
|
|
|
static GParamSpec *obj_props[PROP_LAST];
|
|
|
|
G_DEFINE_ABSTRACT_TYPE (ClutterActorMeta,
|
|
clutter_actor_meta,
|
|
G_TYPE_INITIALLY_UNOWNED);
|
|
|
|
static void
|
|
on_actor_destroy (ClutterActor *actor,
|
|
ClutterActorMeta *meta)
|
|
{
|
|
meta->priv->actor = NULL;
|
|
}
|
|
|
|
static void
|
|
clutter_actor_meta_real_set_actor (ClutterActorMeta *meta,
|
|
ClutterActor *actor)
|
|
{
|
|
if (meta->priv->actor == actor)
|
|
return;
|
|
|
|
if (meta->priv->destroy_id != 0)
|
|
g_signal_handler_disconnect (meta->priv->actor, meta->priv->destroy_id);
|
|
|
|
meta->priv->actor = actor;
|
|
|
|
if (meta->priv->actor != NULL)
|
|
meta->priv->destroy_id = g_signal_connect (meta->priv->actor, "destroy",
|
|
G_CALLBACK (on_actor_destroy),
|
|
meta);
|
|
}
|
|
|
|
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;
|
|
|
|
if (priv->destroy_id != 0 && priv->actor != NULL)
|
|
g_signal_handler_disconnect (priv->actor, priv->destroy_id);
|
|
|
|
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",
|
|
P_("Actor"),
|
|
P_("The actor attached to the meta"),
|
|
CLUTTER_TYPE_ACTOR,
|
|
CLUTTER_PARAM_READABLE);
|
|
obj_props[PROP_ACTOR] = pspec;
|
|
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",
|
|
P_("Name"),
|
|
P_("The name of the meta"),
|
|
NULL,
|
|
CLUTTER_PARAM_READWRITE);
|
|
obj_props[PROP_NAME] = pspec;
|
|
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",
|
|
P_("Enabled"),
|
|
P_("Whether the meta is enabled"),
|
|
TRUE,
|
|
CLUTTER_PARAM_READWRITE);
|
|
obj_props[PROP_ENABLED] = pspec;
|
|
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);
|
|
|
|
_clutter_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_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;
|
|
|
|
_clutter_notify_by_pspec (G_OBJECT (meta), obj_props[PROP_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;
|
|
}
|
|
|
|
/*
|
|
* ClutterMetaGroup: a collection of ClutterActorMeta instances
|
|
*/
|
|
|
|
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)
|
|
{
|
|
}
|
|
|
|
/*
|
|
* _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)
|
|
{
|
|
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
|
|
: "<unknown>",
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* _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)
|
|
{
|
|
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
|
|
: "<unknown>",
|
|
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);
|
|
}
|
|
|
|
/*
|
|
* _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)
|
|
{
|
|
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;
|
|
}
|
|
|
|
/*
|
|
* _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)
|
|
{
|
|
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;
|
|
}
|