mirror of
https://github.com/brl/mutter.git
synced 2024-12-23 03:22:04 +00:00
Don't forget files when committing, stoopeed
This commit is contained in:
parent
e30df678ae
commit
42ebf073bd
379
clutter/clutter-container.c
Normal file
379
clutter/clutter-container.c
Normal file
@ -0,0 +1,379 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
||||||
|
|
98
clutter/clutter-container.h
Normal file
98
clutter/clutter-container.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
378
clutter/clutter-layout.c
Normal file
378
clutter/clutter-layout.c
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
/*
|
||||||
|
* 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);
|
||||||
|
}
|
134
clutter/clutter-layout.h
Normal file
134
clutter/clutter-layout.h
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/*
|
||||||
|
* 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__ */
|
Loading…
Reference in New Issue
Block a user