--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * ClutterContainer: Generic actor container interface.
+ * Author: Emmanuele Bassi <ebassi@openedhand.com>
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <glib-object.h>
+
+#include "clutter-container.h"
+
+#include "clutter-debug.h"
+#include "clutter-main.h"
+#include "clutter-marshal.h"
+#include "clutter-private.h"
+#include "clutter-enum-types.h"
+
+/**
+ * SECTION:clutter-container
+ * @short_description: An interface for implementing container actors
+ *
+ * #ClutterContainer is an interface for writing actors containing other
+ * #ClutterActor<!-- -->s. It provides a standard API for adding, removing
+ * and iterating on every contained actor.
+ *
+ * An actor implementing #ClutterContainer is #ClutterGroup.
+ *
+ * #ClutterContainer is available since Clutter 0.4
+ */
+
+enum
+{
+ ACTOR_ADDED,
+ ACTOR_REMOVED,
+
+ LAST_SIGNAL
+};
+
+static guint container_signals[LAST_SIGNAL] = { 0, };
+
+static void
+clutter_container_base_init (gpointer g_iface)
+{
+ static gboolean initialised = FALSE;
+
+ if (!initialised)
+ {
+ GType iface_type = G_TYPE_FROM_INTERFACE (g_iface);
+
+ initialised = TRUE;
+
+ /**
+ * ClutterContainer::actor-added:
+ * @container: the actor which received the signal
+ * @actor: the new child that has been added to @container
+ *
+ * The ::actor-added signal is emitted each time an actor
+ * has been added to @container.
+ *
+ * Since: 0.4
+ */
+ container_signals[ACTOR_ADDED] =
+ g_signal_new ("actor-added",
+ iface_type,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ClutterContainerIface, actor_added),
+ NULL, NULL,
+ clutter_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ CLUTTER_TYPE_ACTOR);
+ /**
+ * ClutterContainer::actor-removed:
+ * @container: the actor which received the signal
+ * @actor: the child that has been removed from @container
+ *
+ * The ::actor-removed signal is emitted each time an actor
+ * is removed from @container.
+ *
+ * Since: 0.4
+ */
+ container_signals[ACTOR_REMOVED] =
+ g_signal_new ("actor-removed",
+ iface_type,
+ G_SIGNAL_RUN_FIRST,
+ G_STRUCT_OFFSET (ClutterContainerIface, actor_removed),
+ NULL, NULL,
+ clutter_marshal_VOID__OBJECT,
+ G_TYPE_NONE, 1,
+ CLUTTER_TYPE_ACTOR);
+ }
+}
+
+GType
+clutter_container_get_type (void)
+{
+ static GType container_type = 0;
+
+ if (G_UNLIKELY (!container_type))
+ {
+ GTypeInfo container_info =
+ {
+ sizeof (ClutterContainerIface),
+ clutter_container_base_init,
+ NULL, /* iface_finalize */
+ };
+
+ container_type = g_type_register_static (G_TYPE_INTERFACE,
+ "ClutterContainer",
+ &container_info, 0);
+
+ g_type_interface_add_prerequisite (container_type, CLUTTER_TYPE_ACTOR);
+ }
+
+ return container_type;
+}
+
+/**
+ * clutter_container_add:
+ * @container: a #ClutterContainer
+ * @first_actor: the first #ClutterActor to add
+ * @Varargs: %NULL terminated list of actors to add
+ *
+ * Adds a list of #ClutterActor<!-- -->s to @container. Each time and
+ * actor is added, the "actor-added" signal is emitted. Each actor should
+ * be parented to @container, which takes a reference on the actor. You
+ * cannot add a #ClutterActor to more than one #ClutterContainer.
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_add (ClutterContainer *container,
+ ClutterActor *first_actor,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
+
+ va_start (var_args, first_actor);
+ clutter_container_add_valist (container, first_actor, var_args);
+ va_end (var_args);
+}
+
+/**
+ * clutter_container_add_actor:
+ * @container: a #ClutterContainer
+ * @actor: the first #ClutterActor to add
+ *
+ * Adds a #ClutterActor to @container. This function will emit the
+ * "actor-added" signal is emitted. The actor should be parented to
+ * @container. You cannot add a #ClutterActor to more than one
+ * #ClutterContainer.
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_add_actor (ClutterContainer *container,
+ ClutterActor *actor)
+{
+ ClutterActor *parent;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
+
+ parent = clutter_actor_get_parent (actor);
+ if (parent)
+ {
+ g_warning ("Attempting to add actor of type `%s' to a "
+ "group of type `%s', but the actor has already "
+ "a parent of type `%s'.",
+ g_type_name (G_OBJECT_TYPE (actor)),
+ g_type_name (G_OBJECT_TYPE (container)),
+ g_type_name (G_OBJECT_TYPE (parent)));
+ return;
+ }
+
+ CLUTTER_CONTAINER_GET_IFACE (container)->add (container, actor);
+}
+
+/**
+ * clutter_container_add:
+ * @container: a #ClutterContainer
+ * @first_actor: the first #ClutterActor to add
+ * @var_args: list of actors to add, followed by %NULL
+ *
+ * Alternative va_list version of clutter_container_add().
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_add_valist (ClutterContainer *container,
+ ClutterActor *first_actor,
+ va_list var_args)
+{
+ ClutterActor *actor;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
+
+ actor = first_actor;
+ while (actor)
+ {
+ clutter_container_add_actor (container, actor);
+ actor = va_arg (var_args, ClutterActor*);
+ }
+}
+
+/**
+ * clutter_container_remove:
+ * @container: a #ClutterContainer
+ * @first_actor: first #ClutterActor to remove
+ * @Varargs: a %NULL-terminated list of actors to remove
+ *
+ * Removes a %NULL terminated list of #ClutterActor<!-- -->s from
+ * @container. Each actor should be unparented, so if you want to keep it
+ * around you must hold a reference to it yourself, using g_object_ref().
+ * Each time an actor is removed, the "actor-removed" signal is
+ * emitted by @container.
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_remove (ClutterContainer *container,
+ ClutterActor *first_actor,
+ ...)
+{
+ va_list var_args;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
+
+ va_start (var_args, first_actor);
+ clutter_container_remove_valist (container, first_actor, var_args);
+ va_end (var_args);
+}
+
+/**
+ * clutter_container_remove_actor:
+ * @container: a #ClutterContainer
+ * @actor: a #ClutterActor
+ *
+ * Removes @actor from @container. The actor should be unparented, so
+ * if you want to keep it around you must hold a reference to it
+ * yourself, using g_object_ref(). When the actor has been removed,
+ * the "actor-removed" signal is emitted by @container.
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_remove_actor (ClutterContainer *container,
+ ClutterActor *actor)
+{
+ ClutterActor *parent;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (actor));
+
+ parent = clutter_actor_get_parent (actor);
+ if (parent != CLUTTER_ACTOR (container))
+ {
+ g_warning ("Attempting to remove actor of type `%s' from "
+ "group of class `%s', but the group is not the "
+ "actor's parent.",
+ g_type_name (G_OBJECT_TYPE (actor)),
+ g_type_name (G_OBJECT_TYPE (container)));
+ return;
+ }
+
+ CLUTTER_CONTAINER_GET_IFACE (container)->remove (container, actor);
+}
+
+/**
+ * clutter_container_remove_valist:
+ * @container: a #ClutterContainer
+ * @first_actor: the first #ClutterActor to add
+ * @var_args: list of actors to remove, followed by %NULL
+ *
+ * Alternative va_list version of clutter_container_remove().
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_remove_valist (ClutterContainer *container,
+ ClutterActor *first_actor,
+ va_list var_args)
+{
+ ClutterActor *actor;
+
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (CLUTTER_IS_ACTOR (first_actor));
+
+ actor = first_actor;
+ while (actor)
+ {
+ clutter_container_remove_actor (container, actor);
+
+ actor = va_arg (var_args, ClutterActor*);
+ }
+}
+
+static void
+get_children_cb (ClutterActor *child,
+ gpointer data)
+{
+ GList **children = data;
+
+ *children = g_list_prepend (*children, child);
+}
+
+/**
+ * clutter_container_get_children:
+ * @container: a #ClutterContainer
+ *
+ * Retrieves all the children of @container.
+ *
+ * Return value: a list of #ClutterActor<!-- -->s. Use g_list_free()
+ * on the returned list when done.
+ *
+ * Since: 0.4
+ */
+GList *
+clutter_container_get_children (ClutterContainer *container)
+{
+ GList *retval;
+
+ g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
+
+ retval = NULL;
+ clutter_container_foreach (container, get_children_cb, &retval);
+
+ return g_list_reverse (retval);
+}
+
+/**
+ * clutter_container_foreach:
+ * @container: a #ClutterContainer
+ * @callback: a function to be called for each child
+ * @user_data: data to be passed to the function, or %NULL
+ *
+ * Calls @callback for each child of @container.
+ *
+ * Since: 0.4
+ */
+void
+clutter_container_foreach (ClutterContainer *container,
+ ClutterCallback callback,
+ gpointer user_data)
+{
+ g_return_if_fail (CLUTTER_IS_CONTAINER (container));
+ g_return_if_fail (callback != NULL);
+
+ CLUTTER_CONTAINER_GET_IFACE (container)->foreach (container, callback, user_data);
+}
+
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * ClutterContainer: Generic actor container interface.
+ * Author: Emmanuele Bassi <ebassi@openedhand.com>
+ */
+
+#ifndef __CLUTTER_CONTAINER_H__
+#define __CLUTTER_CONTAINER_H__
+
+#include <clutter/clutter-actor.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_CONTAINER (clutter_container_get_type ())
+#define CLUTTER_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_CONTAINER, ClutterContainer))
+#define CLUTTER_IS_CONTAINER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_CONTAINER))
+#define CLUTTER_CONTAINER_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_CONTAINER, ClutterContainerIface))
+
+typedef struct _ClutterContainer ClutterContainer; /* dummy */
+typedef struct _ClutterContainerIface ClutterContainerIface;
+
+struct _ClutterContainerIface
+{
+ GTypeInterface g_iface;
+
+ void (* add) (ClutterContainer *container,
+ ClutterActor *actor);
+ void (* remove) (ClutterContainer *container,
+ ClutterActor *actor);
+ void (* foreach) (ClutterContainer *container,
+ ClutterCallback callback,
+ gpointer user_data);
+
+ /* signals */
+ void (* actor_added) (ClutterContainer *container,
+ ClutterActor *actor);
+ void (* actor_removed) (ClutterContainer *container,
+ ClutterActor *actor);
+
+ /* padding, for future expansion */
+ void (*_clutter_reserved1) (void);
+ void (*_clutter_reserved2) (void);
+ void (*_clutter_reserved3) (void);
+ void (*_clutter_reserved4) (void);
+ void (*_clutter_reserved5) (void);
+ void (*_clutter_reserved6) (void);
+ void (*_clutter_reserved7) (void);
+ void (*_clutter_reserved8) (void);
+};
+
+GType clutter_container_get_type (void) G_GNUC_CONST;
+
+void clutter_container_add (ClutterContainer *container,
+ ClutterActor *first_actor,
+ ...) G_GNUC_NULL_TERMINATED;
+void clutter_container_add_actor (ClutterContainer *container,
+ ClutterActor *actor);
+void clutter_container_add_valist (ClutterContainer *container,
+ ClutterActor *first_actor,
+ va_list varargs);
+void clutter_container_remove (ClutterContainer *container,
+ ClutterActor *first_actor,
+ ...) G_GNUC_NULL_TERMINATED;
+void clutter_container_remove_actor (ClutterContainer *container,
+ ClutterActor *actor);
+void clutter_container_remove_valist (ClutterContainer *container,
+ ClutterActor *first_actor,
+ va_list varargs);
+GList *clutter_container_get_children (ClutterContainer *container);
+void clutter_container_foreach (ClutterContainer *container,
+ ClutterCallback callback,
+ gpointer user_data);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_CONTAINER_H__ */
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * ClutterLayout: interface to be implemented by actors providing
+ * extended layouts.
+ *
+ * Author: Emmanuele Bassi <ebassi@openedhand.com>
+ */
+
+#include "config.h"
+
+#include "clutter-layout.h"
+#include "clutter-main.h"
+#include "clutter-private.h"
+#include "clutter-units.h"
+#include "clutter-debug.h"
+#include "clutter-enum-types.h"
+
+#define MAX_TUNE_REQUESTS 3
+
+/**
+ * SECTION:clutter-layout
+ * @short_description: An interface for implementing layouts
+ *
+ * #ClutterLayout is an interface that #ClutterActor<!-- -->s might
+ * implement to provide complex or extended layouts. The default
+ * size allocation of a #ClutterActor inside a #ClutterGroup is to
+ * make the group size allocation grow enough to contain the actor.
+ * A #ClutterActor implementing the #ClutterLayout interface will
+ * be queried for its size when it is added to a #ClutterGroup subclass
+ * that honours the #ClutterLayout interface; the resulting size
+ * allocation will depend on the #ClutterLayoutFlags that the actor
+ * supports.
+ *
+ * There are various types of layout available for actors implementing
+ * the #ClutterLayout interface: %CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT will
+ * ask the actor for its width given the height allocated by the
+ * container; %CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH will ask the actor for
+ * its height given the width allocated by the container. These two
+ * layout types are especially useful for labels and unidirectional
+ * container types, like vertical and horizontal boxes.
+ *
+ * Another layout available is %CLUTTER_LAYOUT_NATURAL, which will
+ * query the actor for its natural (default) width and height; the
+ * container actor will then try to allocate as much as it can,
+ * and might resort to scaling the actor to fit the allocation. This
+ * layout type is suited for #ClutterTexture<!-- -->s and shapes.
+ *
+ * Finally, the %CLUTTER_LAYOUT_TUNABLE is an iterative layout. An actor
+ * will be queried multiple times until it's satisfied with the size
+ * given.
+ *
+ * A #ClutterGroup subclass that honours the #ClutterLayout interface
+ * should check whether an actor is implementing this interface when
+ * adding it, by using the %CLUTTER_IS_LAYOUT type check macro. If the
+ * actor does implement the interface, the #ClutterGroup should get
+ * the supported layouts using clutter_layout_get_layout_flags() and
+ * verify which layout is compatible with the group's own layout; for
+ * instance, vertical containers should check for actors implementing the
+ * %CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT layout management, while horizontal
+ * containers should check for actors implementing the
+ * %CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH layout management. If the actor
+ * satisfies the layout requirements, the container actor should query
+ * the actor for a geometry request using the appropriate function and
+ * allocate space for the newly added actor accordingly.
+ *
+ * #ClutterLayout is available since Clutter 0.4
+ */
+
+static void
+clutter_layout_base_init (gpointer g_iface)
+{
+ static gboolean initialised = FALSE;
+
+ if (G_UNLIKELY (!initialised))
+ {
+ initialised = TRUE;
+
+ /**
+ * ClutterLayout:layout-flags:
+ *
+ * The layout types that the #ClutterLayout supports.
+ *
+ * Since: 0.4
+ */
+ g_object_interface_install_property (g_iface,
+ g_param_spec_flags ("layout-flags",
+ "Layout Flags",
+ "Supported layouts",
+ CLUTTER_TYPE_LAYOUT_FLAGS,
+ CLUTTER_LAYOUT_NONE,
+ CLUTTER_PARAM_READABLE));
+ }
+}
+
+GType
+clutter_layout_get_type (void)
+{
+ static GType layout_type = 0;
+
+ if (!layout_type)
+ {
+ GTypeInfo layout_info =
+ {
+ sizeof (ClutterLayoutIface),
+ clutter_layout_base_init,
+ NULL,
+ };
+
+ layout_type = g_type_register_static (G_TYPE_INTERFACE, "ClutterLayout",
+ &layout_info, 0);
+ g_type_interface_add_prerequisite (layout_type, CLUTTER_TYPE_ACTOR);
+ }
+
+ return layout_type;
+}
+
+/*
+ * Public API
+ */
+
+/**
+ * clutter_layout_get_layout_flags:
+ * @layout: a #ClutterLayout
+ *
+ * Retrieves the supported layout types from the #ClutterLayout
+ *
+ * Return value: bitwise or of #ClutterLayoutFlags
+ *
+ * Since: 0.4
+ */
+ClutterLayoutFlags
+clutter_layout_get_layout_flags (ClutterLayout *layout)
+{
+ g_return_val_if_fail (CLUTTER_IS_LAYOUT (layout), CLUTTER_LAYOUT_NONE);
+
+ if (CLUTTER_LAYOUT_GET_IFACE (layout)->get_layout_flags)
+ return CLUTTER_LAYOUT_GET_IFACE (layout)->get_layout_flags (layout);
+
+ return CLUTTER_LAYOUT_NONE;
+}
+
+/**
+ * clutter_layout_width_for_height:
+ * @layout: a #ClutterLayout
+ * @width: return location for the width
+ * @height: height allocated by the parent
+ *
+ * Queries a #ClutterLayout actor for its width with a known height.
+ *
+ * Since: 0.4
+ */
+void
+clutter_layout_width_for_height (ClutterLayout *layout,
+ gint *width,
+ gint height)
+{
+ ClutterLayoutFlags layout_type;
+
+ g_return_if_fail (CLUTTER_IS_LAYOUT (layout));
+
+ layout_type = clutter_layout_get_layout_flags (layout);
+ if (layout_type & CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT)
+ {
+ ClutterUnit u_width, u_height;
+
+ u_height = CLUTTER_UNITS_FROM_INT (height);
+ CLUTTER_LAYOUT_GET_IFACE (layout)->width_for_height (layout,
+ &u_width,
+ u_height);
+
+ if (width)
+ *width = CLUTTER_UNITS_TO_INT (u_width);
+ }
+ else
+ {
+ g_warning ("Actor queried for width with a given height, but "
+ "actors of type `%s' do not support width-for-height "
+ "layouts.",
+ g_type_name (G_OBJECT_TYPE (layout)));
+
+ if (width)
+ *width = -1;
+ }
+}
+
+/**
+ * clutter_layout_height_for_width:
+ * @layout: a #ClutterLayout
+ * @width: width allocated by the parent
+ * @height: return location for the height
+ *
+ * Queries a #ClutterLayout actor for its height with a known width.
+ *
+ * Since: 0.4
+ */
+void
+clutter_layout_height_for_width (ClutterLayout *layout,
+ gint width,
+ gint *height)
+{
+ ClutterLayoutFlags layout_type;
+
+ g_return_if_fail (CLUTTER_IS_LAYOUT (layout));
+
+ layout_type = clutter_layout_get_layout_flags (layout);
+ if (layout_type & CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH)
+ {
+ ClutterUnit u_width, u_height;
+
+ u_width = CLUTTER_UNITS_FROM_INT (width);
+ CLUTTER_LAYOUT_GET_IFACE (layout)->height_for_width (layout,
+ u_width,
+ &u_height);
+
+ if (height)
+ *height = CLUTTER_UNITS_TO_INT (u_height);
+ }
+ else
+ {
+ g_warning ("Actor queried for height with a given width, but "
+ "actors of type `%s' do not support height-for-width "
+ "layouts.",
+ g_type_name (G_OBJECT_TYPE (layout)));
+
+ if (height)
+ *height = -1;
+ }
+}
+
+/**
+ * clutter_layout_natural_request:
+ * @layout: a #ClutterLayout
+ * @width: return location for the natural width
+ * @height: return location for the natural height
+ *
+ * Queries a #ClutterLayout actor for its natural (default) width
+ * and height.
+ *
+ * Since: 0.4
+ */
+void
+clutter_layout_natural_request (ClutterLayout *layout,
+ gint *width,
+ gint *height)
+{
+ ClutterLayoutFlags layout_type;
+
+ g_return_if_fail (CLUTTER_IS_LAYOUT (layout));
+
+ layout_type = clutter_layout_get_layout_flags (layout);
+ if (layout_type & CLUTTER_LAYOUT_NATURAL)
+ {
+ ClutterUnit u_width, u_height;
+
+ CLUTTER_LAYOUT_GET_IFACE (layout)->natural_request (layout,
+ &u_width,
+ &u_height);
+
+ if (width)
+ *width = CLUTTER_UNITS_TO_INT (u_width);
+
+ if (height)
+ *height = CLUTTER_UNITS_TO_INT (u_height);
+ }
+ else
+ {
+ g_warning ("Actor queried for natural size, but actors of type `%s' "
+ "do not support natural-size layouts.",
+ g_type_name (G_OBJECT_TYPE (layout)));
+
+ if (width)
+ *width = -1;
+ if (height)
+ *height = -1;
+ }
+}
+
+/**
+ * clutter_layout_tune_request:
+ * @layout: a #ClutterLayout
+ * @given_width: width allocated by the parent
+ * @given_height: height allocated by the parent
+ * @width: return location for the new width
+ * @height: return location for the new height
+ *
+ * Iteratively queries a #ClutterLayout actor until it finds
+ * its desired size, given a width and height tuple.
+ *
+ * Since: 0.4
+ */
+void
+clutter_layout_tune_request (ClutterLayout *layout,
+ gint given_width,
+ gint given_height,
+ gint *width,
+ gint *height)
+{
+ ClutterLayoutFlags layout_type;
+ gint tries;
+ ClutterUnit try_width, try_height;
+ ClutterUnit new_width, new_height;
+
+ g_return_if_fail (CLUTTER_IS_LAYOUT (layout));
+
+ layout_type = clutter_layout_get_layout_flags (layout);
+ if ((layout_type & CLUTTER_LAYOUT_TUNABLE) == 0)
+ {
+ g_warning ("Actor queried for tunable size size but actors of "
+ "type `%s' do not support tunable layouts.",
+ g_type_name (G_OBJECT_TYPE (layout)));
+
+ if (width)
+ *width = -1;
+
+ if (height)
+ *height = -1;
+
+ return;
+ }
+
+ tries = 0;
+ try_width = CLUTTER_UNITS_FROM_INT (given_width);
+ try_height = CLUTTER_UNITS_FROM_INT (given_height);
+ new_width = new_height = 0;
+
+ do
+ {
+ gboolean res;
+
+ res = CLUTTER_LAYOUT_GET_IFACE (layout)->tune_request (layout,
+ try_width,
+ try_height,
+ &new_width,
+ &new_height);
+
+ if (res)
+ break;
+
+ if (new_width)
+ try_width = new_width;
+
+ if (new_height)
+ try_height = new_height;
+
+ new_width = new_height = 0;
+
+ tries += 1;
+ }
+ while (tries <= MAX_TUNE_REQUESTS);
+
+ if (width)
+ *width = CLUTTER_UNITS_TO_INT (new_width);
+
+ if (height)
+ *height = CLUTTER_UNITS_TO_INT (new_height);
+}
--- /dev/null
+/*
+ * Clutter.
+ *
+ * An OpenGL based 'interactive canvas' library.
+ *
+ * Authored By Matthew Allum <mallum@openedhand.com>
+ *
+ * Copyright (C) 2006 OpenedHand
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * ClutterLayout: interface to be implemented by actors providing
+ * extended layouts.
+ *
+ * Author: Emmanuele Bassi <ebassi@openedhand.com>
+ */
+
+#ifndef __CLUTTER_LAYOUT_H__
+#define __CLUTTER_LAYOUT_H__
+
+#include <clutter/clutter-actor.h>
+
+G_BEGIN_DECLS
+
+#define CLUTTER_TYPE_LAYOUT (clutter_layout_get_type ())
+#define CLUTTER_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYOUT, ClutterLayout))
+#define CLUTTER_IS_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYOUT))
+#define CLUTTER_LAYOUT_GET_IFACE(obj) (G_TYPE_INSTANCE_GET_INTERFACE ((obj), CLUTTER_TYPE_LAYOUT, ClutterLayoutIface))
+
+/**
+ * ClutterLayoutFlags
+ *
+ * Type of layouts supported by an actor.
+ *
+ * @CLUTTER_LAYOUT_NONE: No layout (default behaviour)
+ * @CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT: Width-for-height
+ * @CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH: Height-for-width
+ * @CLUTTER_LAYOUT_NATURAL: Natural size request
+ * @CLUTTER_LAYOUT_TUNABLE: Tunable size request
+ *
+ * Since: 0.4
+ */
+typedef enum {
+ CLUTTER_LAYOUT_NONE = 0,
+ CLUTTER_LAYOUT_WIDTH_FOR_HEIGHT = 1 << 0,
+ CLUTTER_LAYOUT_HEIGHT_FOR_WIDTH = 1 << 1,
+ CLUTTER_LAYOUT_NATURAL = 1 << 2,
+ CLUTTER_LAYOUT_TUNABLE = 1 << 3
+} ClutterLayoutFlags;
+
+typedef struct _ClutterLayout ClutterLayout; /* dummy */
+typedef struct _ClutterLayoutIface ClutterLayoutIface;
+
+struct _ClutterLayoutIface
+{
+ GTypeInterface g_iface;
+
+ /* Retrieve the layout mode used by the actor */
+ ClutterLayoutFlags (* get_layout_flags) (ClutterLayout *layout);
+
+ /* Width-for-Height and Height-for-Width: one size is known
+ * and the other is queried. useful for labels and unidirectional
+ * containers, like vertical and horizontal boxes.
+ */
+ void (* width_for_height) (ClutterLayout *layout,
+ ClutterUnit *width,
+ ClutterUnit height);
+ void (* height_for_width) (ClutterLayout *layout,
+ ClutterUnit width,
+ ClutterUnit *height);
+
+ /* Natural size request: the actor is queried for its natural
+ * size and the container can decide to either scale the actor
+ * or to resize itself to make it fit. useful for textures
+ * or shapes.
+ */
+ void (* natural_request) (ClutterLayout *layout,
+ ClutterUnit *width,
+ ClutterUnit *height);
+
+ /* Iterative allocation: the actor is iteratively queried
+ * for its size, until it finds it.
+ */
+ gboolean (* tune_request) (ClutterLayout *layout,
+ ClutterUnit given_width,
+ ClutterUnit given_height,
+ ClutterUnit *width,
+ ClutterUnit *height);
+
+ /* padding, for future expansion */
+ void (*_clutter_layout1) (void);
+ void (*_clutter_layout2) (void);
+ void (*_clutter_layout3) (void);
+ void (*_clutter_layout4) (void);
+ void (*_clutter_layout5) (void);
+ void (*_clutter_layout6) (void);
+ void (*_clutter_layout7) (void);
+ void (*_clutter_layout8) (void);
+};
+
+GType clutter_layout_get_type (void) G_GNUC_CONST;
+
+ClutterLayoutFlags clutter_layout_get_layout_flags (ClutterLayout *layout);
+void clutter_layout_width_for_height (ClutterLayout *layout,
+ gint *width,
+ gint height);
+void clutter_layout_height_for_width (ClutterLayout *layout,
+ gint width,
+ gint *height);
+void clutter_layout_natural_request (ClutterLayout *layout,
+ gint *width,
+ gint *height);
+void clutter_layout_tune_request (ClutterLayout *layout,
+ gint given_width,
+ gint given_height,
+ gint *width,
+ gint *height);
+
+G_END_DECLS
+
+#endif /* __CLUTTER_LAYOUT_H__ */