mutter/clutter/clutter-actor-meta.c
Neil Roberts 8d51617979 Conditionally use g_object_notify_by_pspec
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
2010-08-10 17:12:06 +01:00

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;
}