4 * An OpenGL based 'interactive canvas' library.
6 * Authored By Matthew Allum <mallum@openedhand.com>
8 * Copyright (C) 2006 OpenedHand
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
25 * ClutterContainer: Generic actor container interface.
26 * Author: Emmanuele Bassi <ebassi@openedhand.com>
34 #include <glib-object.h>
35 #include <gobject/gvaluecollector.h>
37 #define CLUTTER_DISABLE_DEPRECATION_WARNINGS
38 #include "deprecated/clutter-container.h"
40 #include "clutter-actor-private.h"
41 #include "clutter-child-meta.h"
42 #include "clutter-debug.h"
43 #include "clutter-main.h"
44 #include "clutter-marshal.h"
45 #include "clutter-private.h"
46 #include "clutter-enum-types.h"
48 #define CLUTTER_CONTAINER_WARN_NOT_IMPLEMENTED(container,vfunc) \
50 g_warning ("Container of type '%s' does not implement " \
51 "the required ClutterContainer::%s virtual " \
53 G_OBJECT_TYPE_NAME ((container)), \
57 #define CLUTTER_CONTAINER_NOTE_NOT_IMPLEMENTED(container,vfunc) \
59 CLUTTER_NOTE (ACTOR, "Container of type '%s' does not " \
60 "implement the ClutterContainer::%s " \
61 "virtual function.", \
62 G_OBJECT_TYPE_NAME ((container)), \
67 * SECTION:clutter-container
68 * @short_description: An interface for container actors
70 * #ClutterContainer is an interface implemented by #ClutterActor, and
71 * it provides some common API for notifying when a child actor is added
72 * or removed, as well as the infrastructure for accessing child properties
73 * through #ClutterChildMeta.
75 * Until Clutter 1.10, the #ClutterContainer interface was also the public
76 * API for implementing container actors; this part of the interface has
77 * been deprecated: #ClutterContainer has a default implementation which
78 * defers to #ClutterActor the child addition and removal, as well as the
79 * iteration. See the documentation of #ClutterContainerIface for the list
80 * of virtual functions that should be overridden.
92 static guint container_signals[LAST_SIGNAL] = { 0, };
93 static GQuark quark_child_meta = 0;
95 static ClutterChildMeta *get_child_meta (ClutterContainer *container,
97 static void create_child_meta (ClutterContainer *container,
99 static void destroy_child_meta (ClutterContainer *container,
100 ClutterActor *actor);
101 static void child_notify (ClutterContainer *container,
105 typedef ClutterContainerIface ClutterContainerInterface;
107 G_DEFINE_INTERFACE (ClutterContainer, clutter_container, G_TYPE_OBJECT);
110 container_real_add (ClutterContainer *container,
113 clutter_actor_add_child (CLUTTER_ACTOR (container), actor);
117 container_real_remove (ClutterContainer *container,
120 clutter_actor_remove_child (CLUTTER_ACTOR (container), actor);
124 ClutterCallback callback;
129 foreach_cb (ClutterActor *actor,
132 ForeachClosure *clos = data;
134 clos->callback (actor, clos->data);
140 container_real_foreach (ClutterContainer *container,
141 ClutterCallback callback,
146 clos.callback = callback;
147 clos.data = user_data;
149 _clutter_actor_foreach_child (CLUTTER_ACTOR (container),
155 container_real_raise (ClutterContainer *container,
157 ClutterActor *sibling)
159 ClutterActor *self = CLUTTER_ACTOR (container);
161 clutter_actor_set_child_above_sibling (self, child, sibling);
165 container_real_lower (ClutterContainer *container,
167 ClutterActor *sibling)
169 ClutterActor *self = CLUTTER_ACTOR (container);
171 clutter_actor_set_child_below_sibling (self, child, sibling);
175 container_real_sort_depth_order (ClutterContainer *container)
180 clutter_container_default_init (ClutterContainerInterface *iface)
182 GType iface_type = G_TYPE_FROM_INTERFACE (iface);
185 g_quark_from_static_string ("clutter-container-child-data");
188 * ClutterContainer::actor-added:
189 * @container: the actor which received the signal
190 * @actor: the new child that has been added to @container
192 * The ::actor-added signal is emitted each time an actor
193 * has been added to @container.
197 container_signals[ACTOR_ADDED] =
198 g_signal_new (I_("actor-added"),
201 G_STRUCT_OFFSET (ClutterContainerIface, actor_added),
203 _clutter_marshal_VOID__OBJECT,
207 * ClutterContainer::actor-removed:
208 * @container: the actor which received the signal
209 * @actor: the child that has been removed from @container
211 * The ::actor-removed signal is emitted each time an actor
212 * is removed from @container.
216 container_signals[ACTOR_REMOVED] =
217 g_signal_new (I_("actor-removed"),
220 G_STRUCT_OFFSET (ClutterContainerIface, actor_removed),
222 _clutter_marshal_VOID__OBJECT,
227 * ClutterContainer::child-notify:
228 * @container: the container which received the signal
229 * @actor: the child that has had a property set
230 * @pspec: (type GParamSpec): the #GParamSpec of the property set
232 * The ::child-notify signal is emitted each time a property is
233 * being set through the clutter_container_child_set() and
234 * clutter_container_child_set_property() calls.
238 container_signals[CHILD_NOTIFY] =
239 g_signal_new (I_("child-notify"),
241 G_SIGNAL_RUN_FIRST | G_SIGNAL_DETAILED,
242 G_STRUCT_OFFSET (ClutterContainerIface, child_notify),
244 _clutter_marshal_VOID__OBJECT_PARAM,
246 CLUTTER_TYPE_ACTOR, G_TYPE_PARAM);
248 iface->add = container_real_add;
249 iface->remove = container_real_remove;
250 iface->foreach = container_real_foreach;
251 iface->raise = container_real_raise;
252 iface->lower = container_real_lower;
253 iface->sort_depth_order = container_real_sort_depth_order;
255 iface->child_meta_type = G_TYPE_INVALID;
256 iface->create_child_meta = create_child_meta;
257 iface->destroy_child_meta = destroy_child_meta;
258 iface->get_child_meta = get_child_meta;
259 iface->child_notify = child_notify;
263 container_add_actor (ClutterContainer *container,
266 ClutterActor *parent;
268 parent = clutter_actor_get_parent (actor);
269 if (G_UNLIKELY (parent != NULL))
271 g_warning ("Attempting to add actor of type '%s' to a "
272 "container of type '%s', but the actor has "
273 "already a parent of type '%s'.",
274 g_type_name (G_OBJECT_TYPE (actor)),
275 g_type_name (G_OBJECT_TYPE (container)),
276 g_type_name (G_OBJECT_TYPE (parent)));
280 clutter_container_create_child_meta (container, actor);
282 #ifdef CLUTTER_ENABLE_DEBUG
283 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
285 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
287 if (iface->add != container_real_add)
288 _clutter_diagnostic_message ("The ClutterContainer::add() virtual "
289 "function has been deprecated and it "
290 "should not be overridden by newly "
293 #endif /* CLUTTER_ENABLE_DEBUG */
295 CLUTTER_CONTAINER_GET_IFACE (container)->add (container, actor);
299 container_remove_actor (ClutterContainer *container,
302 ClutterActor *parent;
304 parent = clutter_actor_get_parent (actor);
305 if (parent != CLUTTER_ACTOR (container))
307 g_warning ("Attempting to remove actor of type '%s' from "
308 "group of class '%s', but the container is not "
309 "the actor's parent.",
310 g_type_name (G_OBJECT_TYPE (actor)),
311 g_type_name (G_OBJECT_TYPE (container)));
315 clutter_container_destroy_child_meta (container, actor);
317 #ifdef CLUTTER_ENABLE_DEBUG
318 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
320 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
322 if (iface->remove != container_real_remove)
323 _clutter_diagnostic_message ("The ClutterContainer::remove() virtual "
324 "function has been deprecated and it "
325 "should not be overridden by newly "
328 #endif /* CLUTTER_ENABLE_DEBUG */
330 CLUTTER_CONTAINER_GET_IFACE (container)->remove (container, actor);
334 container_add_valist (ClutterContainer *container,
335 ClutterActor *first_actor,
338 ClutterActor *actor = first_actor;
340 while (actor != NULL)
342 container_add_actor (container, actor);
343 actor = va_arg (args, ClutterActor *);
348 container_remove_valist (ClutterContainer *container,
349 ClutterActor *first_actor,
352 ClutterActor *actor = first_actor;
354 while (actor != NULL)
356 container_remove_actor (container, actor);
357 actor = va_arg (args, ClutterActor *);
362 * clutter_container_add: (skip)
363 * @container: a #ClutterContainer
364 * @first_actor: the first #ClutterActor to add
365 * @...: %NULL terminated list of actors to add
367 * Adds a list of #ClutterActor<!-- -->s to @container. Each time and
368 * actor is added, the "actor-added" signal is emitted. Each actor should
369 * be parented to @container, which takes a reference on the actor. You
370 * cannot add a #ClutterActor to more than one #ClutterContainer.
372 * This function will call #ClutterContainerIface.add(), which is a
373 * deprecated virtual function. The default implementation will
374 * call clutter_actor_add_child().
378 * Deprecated: 1.10: Use clutter_actor_add_child() instead.
381 clutter_container_add (ClutterContainer *container,
382 ClutterActor *first_actor,
387 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
388 g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
390 va_start (args, first_actor);
391 container_add_valist (container, first_actor, args);
396 * clutter_container_add_actor:
397 * @container: a #ClutterContainer
398 * @actor: the first #ClutterActor to add
400 * Adds a #ClutterActor to @container. This function will emit the
401 * "actor-added" signal. The actor should be parented to
402 * @container. You cannot add a #ClutterActor to more than one
405 * This function will call #ClutterContainerIface.add(), which is a
406 * deprecated virtual function. The default implementation will
407 * call clutter_actor_add_child().
413 * Deprecated: 1.10: Use clutter_actor_add_child() instead.
416 clutter_container_add_actor (ClutterContainer *container,
419 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
420 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
422 container_add_actor (container, actor);
426 * clutter_container_add_valist: (skip)
427 * @container: a #ClutterContainer
428 * @first_actor: the first #ClutterActor to add
429 * @var_args: list of actors to add, followed by %NULL
431 * Alternative va_list version of clutter_container_add().
433 * This function will call #ClutterContainerIface.add(), which is a
434 * deprecated virtual function. The default implementation will
435 * call clutter_actor_add_child().
439 * Deprecated: 1.10: Use clutter_actor_add_child() instead.
442 clutter_container_add_valist (ClutterContainer *container,
443 ClutterActor *first_actor,
446 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
447 g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
449 container_add_valist (container, first_actor, var_args);
453 * clutter_container_remove: (skip)
454 * @container: a #ClutterContainer
455 * @first_actor: first #ClutterActor to remove
456 * @...: a %NULL-terminated list of actors to remove
458 * Removes a %NULL terminated list of #ClutterActor<!-- -->s from
459 * @container. Each actor should be unparented, so if you want to keep it
460 * around you must hold a reference to it yourself, using g_object_ref().
461 * Each time an actor is removed, the "actor-removed" signal is
462 * emitted by @container.
464 * This function will call #ClutterContainerIface.remove(), which is a
465 * deprecated virtual function. The default implementation will call
466 * clutter_actor_remove_child().
470 * Deprecated: 1.10: Use clutter_actor_remove_child() instead.
473 clutter_container_remove (ClutterContainer *container,
474 ClutterActor *first_actor,
479 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
480 g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
482 va_start (var_args, first_actor);
483 container_remove_valist (container, first_actor, var_args);
488 * clutter_container_remove_actor:
489 * @container: a #ClutterContainer
490 * @actor: a #ClutterActor
492 * Removes @actor from @container. The actor should be unparented, so
493 * if you want to keep it around you must hold a reference to it
494 * yourself, using g_object_ref(). When the actor has been removed,
495 * the "actor-removed" signal is emitted by @container.
497 * This function will call #ClutterContainerIface.remove(), which is a
498 * deprecated virtual function. The default implementation will call
499 * clutter_actor_remove_child().
505 * Deprecated: 1.10: Use clutter_actor_remove_child() instead.
508 clutter_container_remove_actor (ClutterContainer *container,
511 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
512 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
514 container_remove_actor (container, actor);
518 * clutter_container_remove_valist: (skip)
519 * @container: a #ClutterContainer
520 * @first_actor: the first #ClutterActor to add
521 * @var_args: list of actors to remove, followed by %NULL
523 * Alternative va_list version of clutter_container_remove().
525 * This function will call #ClutterContainerIface.remove(), which is a
526 * deprecated virtual function. The default implementation will call
527 * clutter_actor_remove_child().
531 * Deprecated: 1.10: Use clutter_actor_remove_child() instead.
534 clutter_container_remove_valist (ClutterContainer *container,
535 ClutterActor *first_actor,
538 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
539 g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
541 container_remove_valist (container, first_actor, var_args);
545 get_children_cb (ClutterActor *child,
548 GList **children = data;
550 *children = g_list_prepend (*children, child);
554 * clutter_container_get_children:
555 * @container: a #ClutterContainer
557 * Retrieves all the children of @container.
559 * Return value: (element-type Clutter.Actor) (transfer container): a list
560 * of #ClutterActor<!-- -->s. Use g_list_free() on the returned
565 * Deprecated: 1.10: Use clutter_actor_get_children() instead.
568 clutter_container_get_children (ClutterContainer *container)
572 g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
575 clutter_container_foreach (container, get_children_cb, &retval);
577 return g_list_reverse (retval);
581 * clutter_container_foreach:
582 * @container: a #ClutterContainer
583 * @callback: (scope call): a function to be called for each child
584 * @user_data: data to be passed to the function, or %NULL
586 * Calls @callback for each child of @container that was added
587 * by the application (with clutter_container_add_actor()). Does
588 * not iterate over "internal" children that are part of the
589 * container's own implementation, if any.
591 * This function calls the #ClutterContainerIface.foreach()
592 * virtual function, which has been deprecated.
596 * Deprecated: 1.10: Use clutter_actor_get_first_child() or
597 * clutter_actor_get_last_child() to retrieve the beginning of
598 * the list of children, and clutter_actor_get_next_sibling()
599 * and clutter_actor_get_previous_sibling() to iterate over it;
600 * alternatively, use the #ClutterActorIter API.
603 clutter_container_foreach (ClutterContainer *container,
604 ClutterCallback callback,
607 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
608 g_return_if_fail (callback != NULL);
610 #ifdef CLUTTER_ENABLE_DEBUG
611 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
613 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
615 if (iface->foreach != container_real_foreach)
616 _clutter_diagnostic_message ("The ClutterContainer::foreach() "
617 "virtual function has been deprecated "
618 "and it should not be overridden by "
619 "newly written code");
621 #endif /* CLUTTER_ENABLE_DEBUG */
623 CLUTTER_CONTAINER_GET_IFACE (container)->foreach (container,
629 * clutter_container_foreach_with_internals:
630 * @container: a #ClutterContainer
631 * @callback: (scope call): a function to be called for each child
632 * @user_data: data to be passed to the function, or %NULL
634 * Calls @callback for each child of @container, including "internal"
635 * children built in to the container itself that were never added
636 * by the application.
638 * This function calls the #ClutterContainerIface.foreach_with_internals()
639 * virtual function, which has been deprecated.
643 * Deprecated: 1.10: See clutter_container_foreach().
646 clutter_container_foreach_with_internals (ClutterContainer *container,
647 ClutterCallback callback,
650 ClutterContainerIface *iface;
652 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
653 g_return_if_fail (callback != NULL);
655 iface = CLUTTER_CONTAINER_GET_IFACE (container);
657 #ifdef CLUTTER_ENABLE_DEBUG
658 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
660 if (iface->foreach_with_internals != NULL)
661 _clutter_diagnostic_message ("The ClutterContainer::foreach_with_internals() "
662 "virtual function has been deprecated "
663 "and it should not be overridden by "
664 "newly written code");
666 #endif /* CLUTTER_ENABLE_DEBUG */
668 if (iface->foreach_with_internals != NULL)
669 iface->foreach_with_internals (container, callback, user_data);
671 iface->foreach (container, callback, user_data);
675 * clutter_container_raise_child:
676 * @container: a #ClutterContainer
677 * @actor: the actor to raise
678 * @sibling: (allow-none): the sibling to raise to, or %NULL to raise
681 * Raises @actor to @sibling level, in the depth ordering.
683 * This function calls the #ClutterContainerIface.raise() virtual function,
684 * which has been deprecated. The default implementation will call
685 * clutter_actor_set_child_above_sibling().
691 * Deprecated: 1.10: Use clutter_actor_set_child_above_sibling() instead.
694 clutter_container_raise_child (ClutterContainer *container,
696 ClutterActor *sibling)
698 ClutterContainerIface *iface;
701 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
702 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
703 g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
705 if (actor == sibling)
708 self = CLUTTER_ACTOR (container);
710 if (clutter_actor_get_parent (actor) != self)
712 g_warning ("Actor of type '%s' is not a child of the container "
714 g_type_name (G_OBJECT_TYPE (actor)),
715 g_type_name (G_OBJECT_TYPE (container)));
719 if (sibling != NULL &&
720 clutter_actor_get_parent (sibling) != self)
722 g_warning ("Actor of type '%s' is not a child of the container "
724 g_type_name (G_OBJECT_TYPE (sibling)),
725 g_type_name (G_OBJECT_TYPE (container)));
729 iface = CLUTTER_CONTAINER_GET_IFACE (container);
731 #ifdef CLUTTER_ENABLE_DEBUG
732 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
734 if (iface->raise != container_real_raise)
735 _clutter_diagnostic_message ("The ClutterContainer::raise() "
736 "virtual function has been deprecated "
737 "and it should not be overridden by "
738 "newly written code");
740 #endif /* CLUTTER_ENABLE_DEBUG */
742 iface->raise (container, actor, sibling);
746 * clutter_container_lower_child:
747 * @container: a #ClutterContainer
748 * @actor: the actor to raise
749 * @sibling: (allow-none): the sibling to lower to, or %NULL to lower
752 * Lowers @actor to @sibling level, in the depth ordering.
754 * This function calls the #ClutterContainerIface.lower() virtual function,
755 * which has been deprecated. The default implementation will call
756 * clutter_actor_set_child_below_sibling().
762 * Deprecated: 1.10: Use clutter_actor_set_child_below_sibling() instead.
765 clutter_container_lower_child (ClutterContainer *container,
767 ClutterActor *sibling)
769 ClutterContainerIface *iface;
772 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
773 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
774 g_return_if_fail (sibling == NULL || CLUTTER_IS_ACTOR (sibling));
776 if (actor == sibling)
779 self = CLUTTER_ACTOR (container);
781 if (clutter_actor_get_parent (actor) != self)
783 g_warning ("Actor of type '%s' is not a child of the container "
785 g_type_name (G_OBJECT_TYPE (actor)),
786 g_type_name (G_OBJECT_TYPE (container)));
790 if (sibling != NULL&&
791 clutter_actor_get_parent (sibling) != self)
793 g_warning ("Actor of type '%s' is not a child of the container "
795 g_type_name (G_OBJECT_TYPE (sibling)),
796 g_type_name (G_OBJECT_TYPE (container)));
800 iface = CLUTTER_CONTAINER_GET_IFACE (container);
802 #ifdef CLUTTER_ENABLE_DEBUG
803 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
805 if (iface->lower != container_real_lower)
806 _clutter_diagnostic_message ("The ClutterContainer::lower() "
807 "virtual function has been deprecated "
808 "and it should not be overridden by "
809 "newly written code");
811 #endif /* CLUTTER_ENABLE_DEBUG */
813 iface->lower (container, actor, sibling);
817 * clutter_container_sort_depth_order:
818 * @container: a #ClutterContainer
820 * Sorts a container's children using their depth. This function should not
821 * be normally used by applications.
825 * Deprecated: 1.10: The #ClutterContainerIface.sort_depth_order() virtual
826 * function should not be used any more; the default implementation in
827 * #ClutterContainer does not do anything.
830 clutter_container_sort_depth_order (ClutterContainer *container)
832 ClutterContainerIface *iface;
834 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
836 iface = CLUTTER_CONTAINER_GET_IFACE (container);
838 #ifdef CLUTTER_ENABLE_DEBUG
839 if (G_UNLIKELY (_clutter_diagnostic_enabled ()))
841 if (iface->sort_depth_order != container_real_sort_depth_order)
842 _clutter_diagnostic_message ("The ClutterContainer::sort_depth_order() "
843 "virtual function has been deprecated "
844 "and it should not be overridden by "
845 "newly written code");
847 #endif /* CLUTTER_ENABLE_DEBUG */
849 iface->sort_depth_order (container);
853 * clutter_container_find_child_by_name:
854 * @container: a #ClutterContainer
855 * @child_name: the name of the requested child.
857 * Finds a child actor of a container by its name. Search recurses
858 * into any child container.
860 * Return value: (transfer none): The child actor with the requested name,
861 * or %NULL if no actor with that name was found.
866 clutter_container_find_child_by_name (ClutterContainer *container,
867 const gchar *child_name)
871 ClutterActor *actor = NULL;
873 g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
874 g_return_val_if_fail (child_name != NULL, NULL);
876 children = clutter_container_get_children (container);
878 for (iter = children; iter; iter = g_list_next (iter))
881 const gchar *iter_name;
883 a = CLUTTER_ACTOR (iter->data);
884 iter_name = clutter_actor_get_name (a);
886 if (iter_name && !strcmp (iter_name, child_name))
892 if (CLUTTER_IS_CONTAINER (a))
894 ClutterContainer *c = CLUTTER_CONTAINER (a);
896 actor = clutter_container_find_child_by_name (c, child_name);
902 g_list_free (children);
907 static ClutterChildMeta *
908 get_child_meta (ClutterContainer *container,
911 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
912 ClutterChildMeta *meta;
914 if (iface->child_meta_type == G_TYPE_INVALID)
917 meta = g_object_get_qdata (G_OBJECT (actor), quark_child_meta);
918 if (meta != NULL && meta->actor == actor)
925 create_child_meta (ClutterContainer *container,
928 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
929 ClutterChildMeta *child_meta = NULL;
931 if (iface->child_meta_type == G_TYPE_INVALID)
934 if (!g_type_is_a (iface->child_meta_type, CLUTTER_TYPE_CHILD_META))
936 g_warning ("%s: Child data of type '%s' is not a ClutterChildMeta",
937 G_STRLOC, g_type_name (iface->child_meta_type));
941 child_meta = g_object_new (iface->child_meta_type,
942 "container", container,
946 g_object_set_qdata_full (G_OBJECT (actor), quark_child_meta,
948 (GDestroyNotify) g_object_unref);
952 destroy_child_meta (ClutterContainer *container,
955 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
957 if (iface->child_meta_type == G_TYPE_INVALID)
960 g_object_set_qdata (G_OBJECT (actor), quark_child_meta, NULL);
964 * clutter_container_get_child_meta:
965 * @container: a #ClutterContainer
966 * @actor: a #ClutterActor that is a child of @container.
968 * Retrieves the #ClutterChildMeta which contains the data about the
969 * @container specific state for @actor.
971 * Return value: (transfer none): the #ClutterChildMeta for the @actor child
972 * of @container or %NULL if the specifiec actor does not exist or the
973 * container is not configured to provide #ClutterChildMeta<!-- -->s
978 clutter_container_get_child_meta (ClutterContainer *container,
981 ClutterContainerIface *iface = CLUTTER_CONTAINER_GET_IFACE (container);
983 if (iface->child_meta_type == G_TYPE_INVALID)
986 if (G_LIKELY (iface->get_child_meta))
987 return iface->get_child_meta (container, actor);
993 * clutter_container_create_child_meta:
994 * @container: a #ClutterContainer
995 * @actor: a #ClutterActor
997 * Creates the #ClutterChildMeta wrapping @actor inside the
998 * @container, if the #ClutterContainerIface::child_meta_type
999 * class member is not set to %G_TYPE_INVALID.
1001 * This function is only useful when adding a #ClutterActor to
1002 * a #ClutterContainer implementation outside of the
1003 * #ClutterContainer::add() virtual function implementation.
1005 * Applications should not call this function.
1010 clutter_container_create_child_meta (ClutterContainer *container,
1011 ClutterActor *actor)
1013 ClutterContainerIface *iface;
1015 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1016 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1018 iface = CLUTTER_CONTAINER_GET_IFACE (container);
1020 if (iface->child_meta_type == G_TYPE_INVALID)
1023 g_assert (g_type_is_a (iface->child_meta_type, CLUTTER_TYPE_CHILD_META));
1025 if (G_LIKELY (iface->create_child_meta))
1026 iface->create_child_meta (container, actor);
1030 * clutter_container_destroy_child_meta:
1031 * @container: a #ClutterContainer
1032 * @actor: a #ClutterActor
1034 * Destroys the #ClutterChildMeta wrapping @actor inside the
1035 * @container, if any.
1037 * This function is only useful when removing a #ClutterActor to
1038 * a #ClutterContainer implementation outside of the
1039 * #ClutterContainer::add() virtual function implementation.
1041 * Applications should not call this function.
1046 clutter_container_destroy_child_meta (ClutterContainer *container,
1047 ClutterActor *actor)
1049 ClutterContainerIface *iface;
1051 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1052 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1054 iface = CLUTTER_CONTAINER_GET_IFACE (container);
1056 if (iface->child_meta_type == G_TYPE_INVALID)
1059 if (G_LIKELY (iface->destroy_child_meta))
1060 iface->destroy_child_meta (container, actor);
1064 * clutter_container_class_find_child_property:
1065 * @klass: a #GObjectClass implementing the #ClutterContainer interface.
1066 * @property_name: a property name.
1068 * Looks up the #GParamSpec for a child property of @klass.
1070 * Return value: (transfer none): The #GParamSpec for the property or %NULL
1071 * if no such property exist.
1076 clutter_container_class_find_child_property (GObjectClass *klass,
1077 const gchar *property_name)
1079 ClutterContainerIface *iface;
1080 GObjectClass *child_class;
1083 g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL);
1084 g_return_val_if_fail (property_name != NULL, NULL);
1085 g_return_val_if_fail (g_type_is_a (G_TYPE_FROM_CLASS (klass),
1086 CLUTTER_TYPE_CONTAINER),
1089 iface = g_type_interface_peek (klass, CLUTTER_TYPE_CONTAINER);
1090 g_return_val_if_fail (iface != NULL, NULL);
1092 if (iface->child_meta_type == G_TYPE_INVALID)
1095 child_class = g_type_class_ref (iface->child_meta_type);
1096 pspec = g_object_class_find_property (child_class, property_name);
1097 g_type_class_unref (child_class);
1103 * clutter_container_class_list_child_properties:
1104 * @klass: a #GObjectClass implementing the #ClutterContainer interface.
1105 * @n_properties: return location for length of returned array.
1107 * Returns an array of #GParamSpec for all child properties.
1109 * Return value: (array length=n_properties) (transfer full): an array
1110 * of #GParamSpec<!-- -->s which should be freed after use.
1115 clutter_container_class_list_child_properties (GObjectClass *klass,
1116 guint *n_properties)
1118 ClutterContainerIface *iface;
1119 GObjectClass *child_class;
1120 GParamSpec **retval;
1122 g_return_val_if_fail (G_IS_OBJECT_CLASS (klass), NULL);
1123 g_return_val_if_fail (g_type_is_a (G_TYPE_FROM_CLASS (klass),
1124 CLUTTER_TYPE_CONTAINER),
1127 iface = g_type_interface_peek (klass, CLUTTER_TYPE_CONTAINER);
1128 g_return_val_if_fail (iface != NULL, NULL);
1130 if (iface->child_meta_type == G_TYPE_INVALID)
1133 child_class = g_type_class_ref (iface->child_meta_type);
1134 retval = g_object_class_list_properties (child_class, n_properties);
1135 g_type_class_unref (child_class);
1141 child_notify (ClutterContainer *container,
1142 ClutterActor *actor,
1148 container_set_child_property (ClutterContainer *container,
1149 ClutterActor *actor,
1150 const GValue *value,
1153 ClutterChildMeta *data;
1155 data = clutter_container_get_child_meta (container, actor);
1156 g_object_set_property (G_OBJECT (data), pspec->name, value);
1158 g_signal_emit (container, container_signals[CHILD_NOTIFY],
1159 (pspec->flags & G_PARAM_STATIC_NAME)
1160 ? g_quark_from_static_string (pspec->name)
1161 : g_quark_from_string (pspec->name),
1166 * clutter_container_child_set_property:
1167 * @container: a #ClutterContainer
1168 * @child: a #ClutterActor that is a child of @container.
1169 * @property: the name of the property to set.
1170 * @value: the value.
1172 * Sets a container-specific property on a child of @container.
1177 clutter_container_child_set_property (ClutterContainer *container,
1178 ClutterActor *child,
1179 const gchar *property,
1180 const GValue *value)
1182 GObjectClass *klass;
1185 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1186 g_return_if_fail (CLUTTER_IS_ACTOR (child));
1187 g_return_if_fail (property != NULL);
1188 g_return_if_fail (value != NULL);
1190 klass = G_OBJECT_GET_CLASS (container);
1192 pspec = clutter_container_class_find_child_property (klass, property);
1195 g_warning ("%s: Containers of type '%s' have no child "
1196 "property named '%s'",
1197 G_STRLOC, G_OBJECT_TYPE_NAME (container), property);
1201 if (!(pspec->flags & G_PARAM_WRITABLE))
1203 g_warning ("%s: Child property '%s' of the container '%s' "
1205 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container));
1209 container_set_child_property (container, child, value, pspec);
1213 * clutter_container_child_set:
1214 * @container: a #ClutterContainer
1215 * @actor: a #ClutterActor that is a child of @container.
1216 * @first_prop: name of the first property to be set.
1217 * @...: value for the first property, followed optionally by more name/value
1218 * pairs terminated with NULL.
1220 * Sets container specific properties on the child of a container.
1225 clutter_container_child_set (ClutterContainer *container,
1226 ClutterActor *actor,
1227 const gchar *first_prop,
1230 GObjectClass *klass;
1234 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1235 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1237 klass = G_OBJECT_GET_CLASS (container);
1239 va_start (var_args, first_prop);
1244 GValue value = G_VALUE_INIT;
1245 gchar *error = NULL;
1248 pspec = clutter_container_class_find_child_property (klass, name);
1251 g_warning ("%s: Containers of type '%s' have no child "
1252 "property named '%s'",
1253 G_STRLOC, G_OBJECT_TYPE_NAME (container), name);
1257 if (!(pspec->flags & G_PARAM_WRITABLE))
1259 g_warning ("%s: Child property '%s' of the container '%s' "
1261 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container));
1265 G_VALUE_COLLECT_INIT (&value, G_PARAM_SPEC_VALUE_TYPE (pspec),
1271 /* we intentionally leak the GValue because it might
1272 * be in an undefined state and calling g_value_unset()
1275 g_warning ("%s: %s", G_STRLOC, error);
1280 container_set_child_property (container, actor, &value, pspec);
1282 g_value_unset (&value);
1284 name = va_arg (var_args, gchar*);
1291 container_get_child_property (ClutterContainer *container,
1292 ClutterActor *actor,
1296 ClutterChildMeta *data;
1298 data = clutter_container_get_child_meta (container, actor);
1299 g_object_get_property (G_OBJECT (data), pspec->name, value);
1303 * clutter_container_child_get_property:
1304 * @container: a #ClutterContainer
1305 * @child: a #ClutterActor that is a child of @container.
1306 * @property: the name of the property to set.
1307 * @value: the value.
1309 * Gets a container specific property of a child of @container, In general,
1310 * a copy is made of the property contents and the caller is responsible for
1311 * freeing the memory by calling g_value_unset().
1313 * Note that clutter_container_child_set_property() is really intended for
1314 * language bindings, clutter_container_child_set() is much more convenient
1315 * for C programming.
1320 clutter_container_child_get_property (ClutterContainer *container,
1321 ClutterActor *child,
1322 const gchar *property,
1325 GObjectClass *klass;
1328 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1329 g_return_if_fail (CLUTTER_IS_ACTOR (child));
1330 g_return_if_fail (property != NULL);
1331 g_return_if_fail (value != NULL);
1333 klass = G_OBJECT_GET_CLASS (container);
1335 pspec = clutter_container_class_find_child_property (klass, property);
1338 g_warning ("%s: Containers of type '%s' have no child "
1339 "property named '%s'",
1340 G_STRLOC, G_OBJECT_TYPE_NAME (container), property);
1344 if (!(pspec->flags & G_PARAM_READABLE))
1346 g_warning ("%s: Child property '%s' of the container '%s' "
1348 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container));
1352 container_get_child_property (container, child, value, pspec);
1357 * clutter_container_child_get:
1358 * @container: a #ClutterContainer
1359 * @actor: a #ClutterActor that is a child of @container.
1360 * @first_prop: name of the first property to be set.
1361 * @...: value for the first property, followed optionally by more name/value
1362 * pairs terminated with NULL.
1364 * Gets @container specific properties of an actor.
1366 * In general, a copy is made of the property contents and the caller is
1367 * responsible for freeing the memory in the appropriate manner for the type, for
1368 * instance by calling g_free() or g_object_unref().
1373 clutter_container_child_get (ClutterContainer *container,
1374 ClutterActor *actor,
1375 const gchar *first_prop,
1378 GObjectClass *klass;
1382 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1383 g_return_if_fail (CLUTTER_IS_ACTOR (actor));
1385 klass = G_OBJECT_GET_CLASS (container);
1387 va_start (var_args, first_prop);
1392 GValue value = G_VALUE_INIT;
1393 gchar *error = NULL;
1396 pspec = clutter_container_class_find_child_property (klass, name);
1399 g_warning ("%s: container '%s' has no child property named '%s'",
1400 G_STRLOC, G_OBJECT_TYPE_NAME (container), name);
1404 if (!(pspec->flags & G_PARAM_READABLE))
1406 g_warning ("%s: child property '%s' of container '%s' is not readable",
1407 G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (container));
1411 g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
1413 container_get_child_property (container, actor, &value, pspec);
1415 G_VALUE_LCOPY (&value, var_args, 0, &error);
1418 g_warning ("%s: %s", G_STRLOC, error);
1420 g_value_unset (&value);
1424 g_value_unset (&value);
1426 name = va_arg (var_args, gchar*);
1433 * clutter_container_child_notify:
1434 * @container: a #ClutterContainer
1435 * @child: a #ClutterActor
1436 * @pspec: a #GParamSpec
1438 * Calls the #ClutterContainerIface.child_notify() virtual function
1439 * of #ClutterContainer. The default implementation will emit the
1440 * #ClutterContainer::child-notify signal.
1445 clutter_container_child_notify (ClutterContainer *container,
1446 ClutterActor *child,
1449 g_return_if_fail (CLUTTER_IS_CONTAINER (container));
1450 g_return_if_fail (CLUTTER_IS_ACTOR (child));
1451 g_return_if_fail (pspec != NULL);
1453 g_return_if_fail (clutter_actor_get_parent (child) == CLUTTER_ACTOR (container));
1455 CLUTTER_CONTAINER_GET_IFACE (container)->child_notify (container,