mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 01:50:42 -05:00
Merge branch 'layout-manager'
* layout-manager: (50 commits) docs: Reword a link layout, docs: Add more documentation to LayoutManager layout, docs: Fix description of Bin properties layout, bin: Use ceilf() instead of casting to int layout, docs: Add long description for FlowLayout layout, box: Clean up layout, box: Write long description for Box layout, docs: Remove unused functions layout: Document BoxLayout layout: Add BoxLayout, a single line layout manager layout: Report the correct size of FlowLayout layout: Resizing the stage resizes the FlowLayout box layout: Use the get_request_mode() getter in BinLayout layout: Change the request-mode along with the orientation actor: Add set_request_mode() method [layout] Remove FlowLayout:wrap [layout] Rename BinLayout and FlowLayout interactive tests [layout] Skip invisible children in FlowLayout [layout] Clean up and document FlowLayout [layout] Snap children of FlowLayout to column/row ...
This commit is contained in:
commit
ba25571c8e
3
.gitignore
vendored
3
.gitignore
vendored
@ -132,6 +132,9 @@ TAGS
|
||||
/tests/interactive/redhand_alpha.png
|
||||
/tests/interactive/test-script.json
|
||||
/tests/interactive/test-clutter-cairo-flowers
|
||||
/tests/interactive/test-bin-layout
|
||||
/tests/interactive/test-flow-layout
|
||||
/tests/interactive/test-box-layout
|
||||
/tests/conform/stamp-test-conformance
|
||||
/tests/conform/test-anchors
|
||||
/tests/conform/test-conformance
|
||||
|
@ -64,6 +64,9 @@ source_h = \
|
||||
$(srcdir)/clutter-behaviour-rotate.h \
|
||||
$(srcdir)/clutter-behaviour-scale.h \
|
||||
$(srcdir)/clutter-binding-pool.h \
|
||||
$(srcdir)/clutter-bin-layout.h \
|
||||
$(srcdir)/clutter-box.h \
|
||||
$(srcdir)/clutter-box-layout.h \
|
||||
$(srcdir)/clutter-cairo-texture.h \
|
||||
$(srcdir)/clutter-child-meta.h \
|
||||
$(srcdir)/clutter-clone.h \
|
||||
@ -73,10 +76,14 @@ source_h = \
|
||||
$(srcdir)/clutter-event.h \
|
||||
$(srcdir)/clutter-feature.h \
|
||||
$(srcdir)/clutter-fixed.h \
|
||||
$(srcdir)/clutter-fixed-layout.h \
|
||||
$(srcdir)/clutter-flow-layout.h \
|
||||
$(srcdir)/clutter-frame-source.h \
|
||||
$(srcdir)/clutter-group.h \
|
||||
$(srcdir)/clutter-interval.h \
|
||||
$(srcdir)/clutter-keysyms.h \
|
||||
$(srcdir)/clutter-layout-manager.h \
|
||||
$(srcdir)/clutter-layout-meta.h \
|
||||
$(srcdir)/clutter-list-model.h \
|
||||
$(srcdir)/clutter-main.h \
|
||||
$(srcdir)/clutter-media.h \
|
||||
@ -128,6 +135,9 @@ source_c = \
|
||||
$(srcdir)/clutter-behaviour-scale.c \
|
||||
$(srcdir)/clutter-bezier.c \
|
||||
$(srcdir)/clutter-binding-pool.c \
|
||||
$(srcdir)/clutter-bin-layout.c \
|
||||
$(srcdir)/clutter-box.c \
|
||||
$(srcdir)/clutter-box-layout.c \
|
||||
$(srcdir)/clutter-cairo-texture.c \
|
||||
$(srcdir)/clutter-child-meta.c \
|
||||
$(srcdir)/clutter-clone.c \
|
||||
@ -137,10 +147,14 @@ source_c = \
|
||||
$(srcdir)/clutter-event.c \
|
||||
$(srcdir)/clutter-feature.c \
|
||||
$(srcdir)/clutter-fixed.c \
|
||||
$(srcdir)/clutter-fixed-layout.c \
|
||||
$(srcdir)/clutter-flow-layout.c \
|
||||
$(srcdir)/clutter-frame-source.c \
|
||||
$(srcdir)/clutter-group.c \
|
||||
$(srcdir)/clutter-id-pool.c \
|
||||
$(srcdir)/clutter-interval.c \
|
||||
$(srcdir)/clutter-layout-manager.c \
|
||||
$(srcdir)/clutter-layout-meta.c \
|
||||
$(srcdir)/clutter-list-model.c \
|
||||
$(srcdir)/clutter-main.c \
|
||||
clutter-marshal.c \
|
||||
|
@ -473,8 +473,6 @@ static void clutter_actor_set_natural_width_set (ClutterActor *self,
|
||||
gboolean use_natural_width);
|
||||
static void clutter_actor_set_natural_height_set (ClutterActor *self,
|
||||
gboolean use_natural_height);
|
||||
static void clutter_actor_set_request_mode (ClutterActor *self,
|
||||
ClutterRequestMode mode);
|
||||
static void clutter_actor_update_map_state (ClutterActor *self,
|
||||
MapStateChange change);
|
||||
static void clutter_actor_unrealize_not_hiding (ClutterActor *self);
|
||||
@ -3297,7 +3295,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
|
||||
* gfloat natural_width, min_width;
|
||||
* gfloat natural_height, min_height;
|
||||
*
|
||||
* g_object_get (G_OBJECT (child), "request-mode", &mode, NULL);
|
||||
* mode = clutter_actor_get_request_mode (child);
|
||||
* if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
|
||||
* {
|
||||
* clutter_actor_get_preferred_width (child, -1,
|
||||
@ -5184,11 +5182,28 @@ clutter_actor_set_natural_height_set (ClutterActor *self,
|
||||
clutter_actor_queue_relayout (self);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_actor_set_request_mode (ClutterActor *self,
|
||||
ClutterRequestMode mode)
|
||||
/**
|
||||
* clutter_actor_set_request_mode:
|
||||
* @self: a #ClutterActor
|
||||
* @mode: the request mode
|
||||
*
|
||||
* Sets the geometry request mode of @self.
|
||||
*
|
||||
* The @mode determines the order for invoking
|
||||
* clutter_actor_get_preferred_width() and
|
||||
* clutter_actor_get_preferred_height()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_actor_set_request_mode (ClutterActor *self,
|
||||
ClutterRequestMode mode)
|
||||
{
|
||||
ClutterActorPrivate *priv = self->priv;
|
||||
ClutterActorPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (self));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->request_mode == mode)
|
||||
return;
|
||||
@ -5203,6 +5218,25 @@ clutter_actor_set_request_mode (ClutterActor *self,
|
||||
clutter_actor_queue_relayout (self);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_actor_get_request_mode:
|
||||
* @self: a #ClutterActor
|
||||
*
|
||||
* Retrieves the geometry request mode of @self
|
||||
*
|
||||
* Return value: the request mode for the actor
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterRequestMode
|
||||
clutter_actor_get_request_mode (ClutterActor *self)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (self),
|
||||
CLUTTER_REQUEST_HEIGHT_FOR_WIDTH);
|
||||
|
||||
return self->priv->request_mode;
|
||||
}
|
||||
|
||||
/* variant of set_width() without checks and without notification
|
||||
* freeze+thaw, for internal usage only
|
||||
*/
|
||||
|
@ -301,6 +301,9 @@ void clutter_actor_queue_relayout (ClutterActor
|
||||
void clutter_actor_destroy (ClutterActor *self);
|
||||
|
||||
/* size negotiation */
|
||||
void clutter_actor_set_request_mode (ClutterActor *self,
|
||||
ClutterRequestMode mode);
|
||||
ClutterRequestMode clutter_actor_get_request_mode (ClutterActor *self);
|
||||
void clutter_actor_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
|
865
clutter/clutter-bin-layout.c
Normal file
865
clutter/clutter-bin-layout.c
Normal file
@ -0,0 +1,865 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-bin-layout
|
||||
* @short_description: A simple layout manager
|
||||
*
|
||||
* #ClutterBinLayout is a layout manager which implements the following
|
||||
* policy:
|
||||
*
|
||||
* <itemizedlist>
|
||||
* <listitem><simpara>the preferred size is the maximum preferred size
|
||||
* between all the children of the container using the
|
||||
* layout;</simpara></listitem>
|
||||
* <listitem><simpara>each child is allocated in "layers", on on top
|
||||
* of the other;</simpara></listitem>
|
||||
* <listitem><simpara>for each layer there are horizontal and vertical
|
||||
* alignment policies.</simpara></listitem>
|
||||
* </itemizedlist>
|
||||
*
|
||||
* <example id="example-clutter-bin-layout">
|
||||
* <title>How to pack actors inside a BinLayout</title>
|
||||
* <para>The following code shows how to build a composite actor with
|
||||
* a texture and a background, and add controls overlayed on top. The
|
||||
* background is set to fill the whole allocation, whilst the texture
|
||||
* is centered; there is a control in the top right corner and a label
|
||||
* in the bottom, filling out the whole allocated width.</para>
|
||||
* <programlisting>
|
||||
* ClutterLayoutManager *manager;
|
||||
* ClutterActor *box;
|
||||
*
|
||||
* /* create the layout first */
|
||||
* layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
* CLUTTER_BIN_ALIGNMENT_CENTER);
|
||||
* box = clutter_box_new (layout); /* then the container */
|
||||
*
|
||||
* /* we can use the layout object to add actors */
|
||||
* clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), background,
|
||||
* CLUTTER_BIN_ALIGNMENT_FILL,
|
||||
* CLUTTER_BIN_ALIGNMENT_FILL);
|
||||
* clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), icon,
|
||||
* CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
* CLUTTER_BIN_ALIGNMENT_CENTER);
|
||||
*
|
||||
* /* align to the bottom left */
|
||||
* clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), label,
|
||||
* CLUTTER_BIN_ALIGNMENT_START,
|
||||
* CLUTTER_BIN_ALIGNMENT_END);
|
||||
* /* align to the top right */
|
||||
* clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), button,
|
||||
* CLUTTER_BIN_ALIGNMENT_END,
|
||||
* CLUTTER_BIN_ALIGNMENT_START);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* #ClutterBinLayout is available since Clutter 1.2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "clutter-actor.h"
|
||||
#include "clutter-animatable.h"
|
||||
#include "clutter-bin-layout.h"
|
||||
#include "clutter-child-meta.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-layout-meta.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define CLUTTER_TYPE_BIN_LAYER (clutter_bin_layer_get_type ())
|
||||
#define CLUTTER_BIN_LAYER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYER, ClutterBinLayer))
|
||||
#define CLUTTER_IS_BIN_LAYER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYER))
|
||||
|
||||
#define CLUTTER_BIN_LAYOUT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutPrivate))
|
||||
|
||||
typedef struct _ClutterBinLayer ClutterBinLayer;
|
||||
typedef struct _ClutterLayoutMetaClass ClutterBinLayerClass;
|
||||
|
||||
struct _ClutterBinLayoutPrivate
|
||||
{
|
||||
ClutterBinAlignment x_align;
|
||||
ClutterBinAlignment y_align;
|
||||
|
||||
ClutterContainer *container;
|
||||
};
|
||||
|
||||
struct _ClutterBinLayer
|
||||
{
|
||||
ClutterLayoutMeta parent_instance;
|
||||
|
||||
ClutterBinAlignment x_align;
|
||||
ClutterBinAlignment y_align;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_LAYER_0,
|
||||
|
||||
PROP_LAYER_X_ALIGN,
|
||||
PROP_LAYER_Y_ALIGN
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_X_ALIGN,
|
||||
PROP_Y_ALIGN
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (ClutterBinLayer,
|
||||
clutter_bin_layer,
|
||||
CLUTTER_TYPE_LAYOUT_META);
|
||||
|
||||
G_DEFINE_TYPE (ClutterBinLayout,
|
||||
clutter_bin_layout,
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER);
|
||||
|
||||
/*
|
||||
* ClutterBinLayer
|
||||
*/
|
||||
|
||||
static void
|
||||
set_layer_x_align (ClutterBinLayer *self,
|
||||
ClutterBinAlignment alignment)
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
|
||||
if (self->x_align == alignment)
|
||||
return;
|
||||
|
||||
self->x_align = alignment;
|
||||
|
||||
meta = CLUTTER_LAYOUT_META (self);
|
||||
manager = clutter_layout_meta_get_manager (meta);
|
||||
clutter_layout_manager_layout_changed (manager);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "x-align");
|
||||
}
|
||||
|
||||
static void
|
||||
set_layer_y_align (ClutterBinLayer *self,
|
||||
ClutterBinAlignment alignment)
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
|
||||
if (self->y_align == alignment)
|
||||
return;
|
||||
|
||||
self->y_align = alignment;
|
||||
|
||||
meta = CLUTTER_LAYOUT_META (self);
|
||||
manager = clutter_layout_meta_get_manager (meta);
|
||||
clutter_layout_manager_layout_changed (manager);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "y-align");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layer_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LAYER_X_ALIGN:
|
||||
set_layer_x_align (layer, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_LAYER_Y_ALIGN:
|
||||
set_layer_y_align (layer, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layer_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBinLayer *layer = CLUTTER_BIN_LAYER (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LAYER_X_ALIGN:
|
||||
g_value_set_enum (value, layer->x_align);
|
||||
break;
|
||||
|
||||
case PROP_LAYER_Y_ALIGN:
|
||||
g_value_set_enum (value, layer->y_align);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layer_class_init (ClutterBinLayerClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
gobject_class->set_property = clutter_bin_layer_set_property;
|
||||
gobject_class->get_property = clutter_bin_layer_get_property;
|
||||
|
||||
pspec = g_param_spec_enum ("x-align",
|
||||
"Horizontal Alignment",
|
||||
"Horizontal alignment for the actor "
|
||||
"inside the layer",
|
||||
CLUTTER_TYPE_BIN_ALIGNMENT,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LAYER_X_ALIGN,
|
||||
pspec);
|
||||
|
||||
pspec = g_param_spec_enum ("y-align",
|
||||
"Vertical Alignment",
|
||||
"Vertical alignment for the actor "
|
||||
"inside the layer manager",
|
||||
CLUTTER_TYPE_BIN_ALIGNMENT,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LAYER_Y_ALIGN,
|
||||
pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layer_init (ClutterBinLayer *layer)
|
||||
{
|
||||
layer->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
|
||||
layer->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
|
||||
}
|
||||
|
||||
/*
|
||||
* ClutterBinLayout
|
||||
*/
|
||||
|
||||
static void
|
||||
set_x_align (ClutterBinLayout *self,
|
||||
ClutterBinAlignment alignment)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv = self->priv;
|
||||
|
||||
if (priv->x_align != alignment)
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
|
||||
priv->x_align = alignment;
|
||||
|
||||
manager = CLUTTER_LAYOUT_MANAGER (self);
|
||||
clutter_layout_manager_layout_changed (manager);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "x-align");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
set_y_align (ClutterBinLayout *self,
|
||||
ClutterBinAlignment alignment)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv = self->priv;
|
||||
|
||||
if (priv->y_align != alignment)
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
|
||||
priv->y_align = alignment;
|
||||
|
||||
manager = CLUTTER_LAYOUT_MANAGER (self);
|
||||
clutter_layout_manager_layout_changed (manager);
|
||||
|
||||
g_object_notify (G_OBJECT (self), "y-align");
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
GList *children = clutter_container_get_children (container);
|
||||
GList *l;
|
||||
gfloat min_width, nat_width;
|
||||
|
||||
min_width = nat_width = 0.0;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat minimum, natural;
|
||||
|
||||
clutter_actor_get_preferred_width (child, for_height,
|
||||
&minimum,
|
||||
&natural);
|
||||
|
||||
min_width = MAX (min_width, minimum);
|
||||
nat_width = MAX (nat_width, natural);
|
||||
}
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = min_width;
|
||||
|
||||
if (nat_width_p)
|
||||
*nat_width_p = nat_width;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
GList *children = clutter_container_get_children (container);
|
||||
GList *l;
|
||||
gfloat min_height, nat_height;
|
||||
|
||||
min_height = nat_height = 0.0;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat minimum, natural;
|
||||
|
||||
clutter_actor_get_preferred_height (child, for_width,
|
||||
&minimum,
|
||||
&natural);
|
||||
|
||||
min_height = MAX (min_height, minimum);
|
||||
nat_height = MAX (nat_height, natural);
|
||||
}
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = min_height;
|
||||
|
||||
if (nat_height_p)
|
||||
*nat_height_p = nat_height;
|
||||
}
|
||||
|
||||
static gdouble
|
||||
get_bin_alignment_factor (ClutterBinAlignment alignment)
|
||||
{
|
||||
switch (alignment)
|
||||
{
|
||||
case CLUTTER_BIN_ALIGNMENT_CENTER:
|
||||
return 0.5;
|
||||
|
||||
case CLUTTER_BIN_ALIGNMENT_START:
|
||||
return 0.0;
|
||||
|
||||
case CLUTTER_BIN_ALIGNMENT_END:
|
||||
return 1.0;
|
||||
|
||||
case CLUTTER_BIN_ALIGNMENT_FIXED:
|
||||
case CLUTTER_BIN_ALIGNMENT_FILL:
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_allocate (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
GList *children = clutter_container_get_children (container);
|
||||
GList *l;
|
||||
gfloat available_w, available_h;
|
||||
|
||||
available_w = clutter_actor_box_get_width (allocation);
|
||||
available_h = clutter_actor_box_get_height (allocation);
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
ClutterLayoutMeta *meta;
|
||||
ClutterBinLayer *layer;
|
||||
ClutterActorBox child_alloc = { 0, };
|
||||
gfloat child_width, child_height;
|
||||
ClutterRequestMode request;
|
||||
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
container,
|
||||
child);
|
||||
layer = CLUTTER_BIN_LAYER (meta);
|
||||
|
||||
if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL)
|
||||
{
|
||||
child_alloc.x1 = 0;
|
||||
child_alloc.x2 = ceilf (available_w);
|
||||
}
|
||||
|
||||
if (layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL)
|
||||
{
|
||||
child_alloc.y1 = 0;
|
||||
child_alloc.y2 = ceilf (available_h);
|
||||
}
|
||||
|
||||
/* if we are filling horizontally and vertically then we
|
||||
* can break here because we already have a full allocation
|
||||
*/
|
||||
if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FILL &&
|
||||
layer->y_align == CLUTTER_BIN_ALIGNMENT_FILL)
|
||||
{
|
||||
clutter_actor_allocate (child, &child_alloc, flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
request = clutter_actor_get_request_mode (child);
|
||||
if (request == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH)
|
||||
{
|
||||
gfloat min_width, nat_width;
|
||||
gfloat min_height, nat_height;
|
||||
|
||||
clutter_actor_get_preferred_width (child, available_h,
|
||||
&min_width,
|
||||
&nat_width);
|
||||
child_width = CLAMP (nat_width, min_width, available_w);
|
||||
|
||||
clutter_actor_get_preferred_height (child, child_width,
|
||||
&min_height,
|
||||
&nat_height);
|
||||
child_height = CLAMP (nat_height, min_height, available_h);
|
||||
}
|
||||
else if (request == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT)
|
||||
{
|
||||
gfloat min_width, nat_width;
|
||||
gfloat min_height, nat_height;
|
||||
|
||||
clutter_actor_get_preferred_height (child, available_w,
|
||||
&min_height,
|
||||
&nat_height);
|
||||
child_height = CLAMP (nat_height, min_height, available_h);
|
||||
|
||||
clutter_actor_get_preferred_width (child, child_height,
|
||||
&min_width,
|
||||
&nat_width);
|
||||
child_width = CLAMP (nat_width, min_width, available_w);
|
||||
}
|
||||
|
||||
if (layer->x_align == CLUTTER_BIN_ALIGNMENT_FIXED)
|
||||
{
|
||||
child_alloc.x1 = ceilf (clutter_actor_get_x (child));
|
||||
child_alloc.x2 = ceilf (child_alloc.x1 + child_width);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble x_align = get_bin_alignment_factor (layer->x_align);
|
||||
|
||||
if (layer->x_align != CLUTTER_BIN_ALIGNMENT_FILL)
|
||||
{
|
||||
child_alloc.x1 = ceilf ((available_w - child_width) * x_align);
|
||||
child_alloc.x2 = ceilf (child_alloc.x1 + child_width);
|
||||
}
|
||||
}
|
||||
|
||||
if (layer->y_align == CLUTTER_BIN_ALIGNMENT_FIXED)
|
||||
{
|
||||
child_alloc.y1 = ceilf (clutter_actor_get_y (child));
|
||||
child_alloc.y2 = ceilf (child_alloc.y1 + child_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
gdouble y_align = get_bin_alignment_factor (layer->y_align);
|
||||
|
||||
if (layer->y_align != CLUTTER_BIN_ALIGNMENT_FILL)
|
||||
{
|
||||
child_alloc.y1 = ceilf ((available_h - child_height) * y_align);
|
||||
child_alloc.y2 = ceilf (child_alloc.y1 + child_height);
|
||||
}
|
||||
}
|
||||
|
||||
clutter_actor_allocate (child, &child_alloc, flags);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static ClutterLayoutMeta *
|
||||
clutter_bin_layout_create_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
|
||||
priv = CLUTTER_BIN_LAYOUT (manager)->priv;
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_BIN_LAYER,
|
||||
"container", container,
|
||||
"actor", actor,
|
||||
"manager", manager,
|
||||
"x-align", priv->x_align,
|
||||
"y_align", priv->y_align,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_set_container (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
|
||||
priv = CLUTTER_BIN_LAYOUT (manager)->priv;
|
||||
priv->container = container;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBinLayout *layout = CLUTTER_BIN_LAYOUT (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_X_ALIGN:
|
||||
set_x_align (layout, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
case PROP_Y_ALIGN:
|
||||
set_y_align (layout, g_value_get_enum (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
|
||||
priv = CLUTTER_BIN_LAYOUT (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_X_ALIGN:
|
||||
g_value_set_enum (value, priv->x_align);
|
||||
break;
|
||||
|
||||
case PROP_Y_ALIGN:
|
||||
g_value_set_enum (value, priv->y_align);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_class_init (ClutterBinLayoutClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterLayoutManagerClass *layout_class =
|
||||
CLUTTER_LAYOUT_MANAGER_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterBinLayoutPrivate));
|
||||
|
||||
gobject_class->set_property = clutter_bin_layout_set_property;
|
||||
gobject_class->get_property = clutter_bin_layout_get_property;
|
||||
|
||||
/**
|
||||
* ClutterBinLayout:x-align:
|
||||
*
|
||||
* The default horizontal alignment policy for actors managed
|
||||
* by the #ClutterBinLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_enum ("x-align",
|
||||
"Horizontal Alignment",
|
||||
"Default horizontal alignment for the actors "
|
||||
"inside the layout manager",
|
||||
CLUTTER_TYPE_BIN_ALIGNMENT,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_X_ALIGN, pspec);
|
||||
|
||||
/**
|
||||
* ClutterBinLayout:y-align:
|
||||
*
|
||||
* The default vertical alignment policy for actors managed
|
||||
* by the #ClutterBinLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_enum ("y-align",
|
||||
"Vertical Alignment",
|
||||
"Default vertical alignment for the actors "
|
||||
"inside the layout manager",
|
||||
CLUTTER_TYPE_BIN_ALIGNMENT,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_Y_ALIGN, pspec);
|
||||
|
||||
layout_class->get_preferred_width =
|
||||
clutter_bin_layout_get_preferred_width;
|
||||
layout_class->get_preferred_height =
|
||||
clutter_bin_layout_get_preferred_height;
|
||||
layout_class->allocate =
|
||||
clutter_bin_layout_allocate;
|
||||
layout_class->create_child_meta =
|
||||
clutter_bin_layout_create_child_meta;
|
||||
layout_class->set_container =
|
||||
clutter_bin_layout_set_container;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_bin_layout_init (ClutterBinLayout *self)
|
||||
{
|
||||
self->priv = CLUTTER_BIN_LAYOUT_GET_PRIVATE (self);
|
||||
|
||||
self->priv->x_align = CLUTTER_BIN_ALIGNMENT_CENTER;
|
||||
self->priv->y_align = CLUTTER_BIN_ALIGNMENT_CENTER;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bin_layout_new:
|
||||
* @x_align: the default alignment policy to be used on the
|
||||
* horizontal axis
|
||||
* @y_align: the default alignment policy to be used on the
|
||||
* vertical axis
|
||||
*
|
||||
* Creates a new #ClutterBinLayout layout manager
|
||||
*
|
||||
* Return value: the newly created layout manager
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_bin_layout_new (ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_BIN_LAYOUT,
|
||||
"x-align", x_align,
|
||||
"y-align", y_align,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bin_layout_set_alignment:
|
||||
* @self: a #ClutterBinLayout
|
||||
* @child: (allow-none): a child of @container
|
||||
* @x_align: the horizontal alignment policy to be used for the @child
|
||||
* inside @container
|
||||
* @y_align: the vertical aligment policy to be used on the @child
|
||||
* inside @container
|
||||
*
|
||||
* Sets the horizontal and vertical alignment policies to be applied
|
||||
* to a @child of @self
|
||||
*
|
||||
* If @child is %NULL then the @x_align and @y_align values will
|
||||
* be set as the default alignment policies
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_bin_layout_set_alignment (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
|
||||
g_return_if_fail (child == NULL || CLUTTER_IS_ACTOR (child));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->container == NULL)
|
||||
{
|
||||
if (child == NULL)
|
||||
{
|
||||
set_x_align (self, x_align);
|
||||
set_y_align (self, y_align);
|
||||
}
|
||||
else
|
||||
g_warning ("The layout of type '%s' must be associated to "
|
||||
"a ClutterContainer before setting the alignment "
|
||||
"on its children",
|
||||
G_OBJECT_TYPE_NAME (self));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
manager = CLUTTER_LAYOUT_MANAGER (self);
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
priv->container,
|
||||
child);
|
||||
g_assert (CLUTTER_IS_BIN_LAYER (meta));
|
||||
|
||||
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
|
||||
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bin_layout_get_alignment:
|
||||
* @self: a #ClutterBinLayout
|
||||
* @child: (allow-none): a child of @container
|
||||
* @x_align: (out) (allow-none): return location for the horizontal
|
||||
* alignment policy
|
||||
* @y_align: (out) (allow-none): return location for the vertical
|
||||
* alignment policy
|
||||
*
|
||||
* Retrieves the horizontal and vertical alignment policies for
|
||||
* a child of @self
|
||||
*
|
||||
* If @child is %NULL the default alignment policies will be returned
|
||||
* instead
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_bin_layout_get_alignment (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment *x_align,
|
||||
ClutterBinAlignment *y_align)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
ClutterBinLayer *layer;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->container == NULL)
|
||||
{
|
||||
if (child == NULL)
|
||||
{
|
||||
if (x_align)
|
||||
*x_align = priv->x_align;
|
||||
|
||||
if (y_align)
|
||||
*y_align = priv->y_align;
|
||||
}
|
||||
else
|
||||
g_warning ("The layout of type '%s' must be associated to "
|
||||
"a ClutterContainer before getting the alignment "
|
||||
"of its children",
|
||||
G_OBJECT_TYPE_NAME (self));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
manager = CLUTTER_LAYOUT_MANAGER (self);
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
priv->container,
|
||||
child);
|
||||
g_assert (CLUTTER_IS_BIN_LAYER (meta));
|
||||
|
||||
layer = CLUTTER_BIN_LAYER (meta);
|
||||
|
||||
if (x_align)
|
||||
*x_align = layer->x_align;
|
||||
|
||||
if (y_align)
|
||||
*y_align = layer->y_align;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_bin_layout_add:
|
||||
* @self: a #ClutterBinLayout
|
||||
* @child: a #ClutterActor
|
||||
* @x_align: horizontal alignment policy for @child
|
||||
* @y_align: vertical alignment policy for @child
|
||||
*
|
||||
* Adds a #ClutterActor to the container using @self and
|
||||
* sets the alignment policies for it
|
||||
*
|
||||
* This function is equivalent to clutter_container_add_actor()
|
||||
* and clutter_layout_manager_child_set_property() but it does not
|
||||
* require a pointer to the #ClutterContainer associated to the
|
||||
* #ClutterBinLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_bin_layout_add (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align)
|
||||
{
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
ClutterLayoutManager *manager;
|
||||
ClutterLayoutMeta *meta;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BIN_LAYOUT (self));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (child));
|
||||
|
||||
priv = self->priv;
|
||||
|
||||
if (priv->container == NULL)
|
||||
{
|
||||
g_warning ("The layout of type '%s' must be associated to "
|
||||
"a ClutterContainer before adding children",
|
||||
G_OBJECT_TYPE_NAME (self));
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_container_add_actor (priv->container, child);
|
||||
|
||||
manager = CLUTTER_LAYOUT_MANAGER (self);
|
||||
meta = clutter_layout_manager_get_child_meta (manager,
|
||||
priv->container,
|
||||
child);
|
||||
g_assert (CLUTTER_IS_BIN_LAYER (meta));
|
||||
|
||||
set_layer_x_align (CLUTTER_BIN_LAYER (meta), x_align);
|
||||
set_layer_y_align (CLUTTER_BIN_LAYER (meta), y_align);
|
||||
}
|
123
clutter/clutter-bin-layout.h
Normal file
123
clutter/clutter-bin-layout.h
Normal file
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_BIN_LAYOUT_H__
|
||||
#define __CLUTTER_BIN_LAYOUT_H__
|
||||
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BIN_LAYOUT (clutter_bin_layout_get_type ())
|
||||
#define CLUTTER_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayout))
|
||||
#define CLUTTER_IS_BIN_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BIN_LAYOUT))
|
||||
#define CLUTTER_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutClass))
|
||||
#define CLUTTER_IS_BIN_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BIN_LAYOUT))
|
||||
#define CLUTTER_BIN_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BIN_LAYOUT, ClutterBinLayoutClass))
|
||||
|
||||
typedef struct _ClutterBinLayout ClutterBinLayout;
|
||||
typedef struct _ClutterBinLayoutPrivate ClutterBinLayoutPrivate;
|
||||
typedef struct _ClutterBinLayoutClass ClutterBinLayoutClass;
|
||||
|
||||
/**
|
||||
* ClutterBinAlignment:
|
||||
* @CLUTTER_BIN_ALIGNMENT_FIXED: Fixed position alignment; the
|
||||
* #ClutterBinLayout will honour the fixed position provided
|
||||
* by the actors themselves when allocating them
|
||||
* @CLUTTER_BIN_ALIGNMENT_FILL: Fill the allocation size
|
||||
* @CLUTTER_BIN_ALIGNMENT_START: Position the actors at the top
|
||||
* or left side of the container, depending on the axis
|
||||
* @CLUTTER_BIN_ALIGNMENT_END: Position the actors at the bottom
|
||||
* or right side of the container, depending on the axis
|
||||
* @CLUTTER_BIN_ALIGNMENT_CENTER: Position the actors at the
|
||||
* center of the container, depending on the axis
|
||||
*
|
||||
* The alignment policies available on each axis for #ClutterBinLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
typedef enum {
|
||||
CLUTTER_BIN_ALIGNMENT_FIXED,
|
||||
CLUTTER_BIN_ALIGNMENT_FILL,
|
||||
CLUTTER_BIN_ALIGNMENT_START,
|
||||
CLUTTER_BIN_ALIGNMENT_END,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER
|
||||
} ClutterBinAlignment;
|
||||
|
||||
/**
|
||||
* ClutterBinLayout:
|
||||
*
|
||||
* The #ClutterBinLayout structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBinLayout
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManager parent_instance;
|
||||
|
||||
ClutterBinLayoutPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterBinLayoutClass:
|
||||
*
|
||||
* The #ClutterBinLayoutClass structure contains only private
|
||||
* data and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBinLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_bin_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterLayoutManager *clutter_bin_layout_new (ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align);
|
||||
|
||||
void clutter_bin_layout_set_alignment (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align);
|
||||
void clutter_bin_layout_get_alignment (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment *x_align,
|
||||
ClutterBinAlignment *y_align);
|
||||
|
||||
void clutter_bin_layout_add (ClutterBinLayout *self,
|
||||
ClutterActor *child,
|
||||
ClutterBinAlignment x_align,
|
||||
ClutterBinAlignment y_align);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BIN_LAYOUT_H__ */
|
1496
clutter/clutter-box-layout.c
Normal file
1496
clutter/clutter-box-layout.c
Normal file
File diff suppressed because it is too large
Load Diff
143
clutter/clutter-box-layout.h
Normal file
143
clutter/clutter-box-layout.h
Normal file
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Based on the NBTK NbtkBoxLayout actor by:
|
||||
* Thomas Wood <thomas.wood@intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_BOX_LAYOUT_H__
|
||||
#define __CLUTTER_BOX_LAYOUT_H__
|
||||
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BOX_LAYOUT (clutter_box_layout_get_type ())
|
||||
#define CLUTTER_BOX_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayout))
|
||||
#define CLUTTER_IS_BOX_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX_LAYOUT))
|
||||
#define CLUTTER_BOX_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayoutClass))
|
||||
#define CLUTTER_IS_BOX_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX_LAYOUT))
|
||||
#define CLUTTER_BOX_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX_LAYOUT, ClutterBoxLayoutClass))
|
||||
|
||||
typedef struct _ClutterBoxLayout ClutterBoxLayout;
|
||||
typedef struct _ClutterBoxLayoutPrivate ClutterBoxLayoutPrivate;
|
||||
typedef struct _ClutterBoxLayoutClass ClutterBoxLayoutClass;
|
||||
|
||||
/**
|
||||
* ClutterBoxAlignment:
|
||||
* @CLUTTER_BOX_ALIGNMENT_START: Align the child to the top or to
|
||||
* to the left, depending on the used axis
|
||||
* @CLUTTER_BOX_ALIGNMENT_CENTER: Align the child to the center
|
||||
* @CLUTTER_BOX_ALIGNMENT_END: Align the child to the bottom or to
|
||||
* the right, depending on the used axis
|
||||
*
|
||||
* The alignment policies available on each axis of the #ClutterBoxLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
typedef enum {
|
||||
CLUTTER_BOX_ALIGNMENT_START,
|
||||
CLUTTER_BOX_ALIGNMENT_END,
|
||||
CLUTTER_BOX_ALIGNMENT_CENTER
|
||||
} ClutterBoxAlignment;
|
||||
|
||||
/**
|
||||
* ClutterBoxLayout:
|
||||
*
|
||||
* The #ClutterBoxLayout structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBoxLayout
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManager parent_instance;
|
||||
|
||||
ClutterBoxLayoutPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterBoxLayoutClass:
|
||||
*
|
||||
* The #ClutterBoxLayoutClass structure contains only private
|
||||
* data and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterBoxLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_box_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterLayoutManager *clutter_box_layout_new (void);
|
||||
|
||||
void clutter_box_layout_set_spacing (ClutterBoxLayout *layout,
|
||||
guint spacing);
|
||||
guint clutter_box_layout_get_spacing (ClutterBoxLayout *layout);
|
||||
void clutter_box_layout_set_vertical (ClutterBoxLayout *layout,
|
||||
gboolean vertical);
|
||||
gboolean clutter_box_layout_get_vertical (ClutterBoxLayout *layout);
|
||||
void clutter_box_layout_set_pack_start (ClutterBoxLayout *layout,
|
||||
gboolean pack_start);
|
||||
gboolean clutter_box_layout_get_pack_start (ClutterBoxLayout *layout);
|
||||
|
||||
void clutter_box_layout_pack (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
gboolean expand,
|
||||
gboolean x_fill,
|
||||
gboolean y_fill,
|
||||
ClutterBoxAlignment x_align,
|
||||
ClutterBoxAlignment y_align);
|
||||
void clutter_box_layout_set_alignment (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
ClutterBoxAlignment x_align,
|
||||
ClutterBoxAlignment y_align);
|
||||
void clutter_box_layout_get_alignment (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
ClutterBoxAlignment *x_align,
|
||||
ClutterBoxAlignment *y_align);
|
||||
void clutter_box_layout_set_fill (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
gboolean x_fill,
|
||||
gboolean y_fill);
|
||||
void clutter_box_layout_get_fill (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
gboolean *x_fill,
|
||||
gboolean *y_fill);
|
||||
void clutter_box_layout_set_expand (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor,
|
||||
gboolean expand);
|
||||
gboolean clutter_box_layout_get_expand (ClutterBoxLayout *layout,
|
||||
ClutterActor *actor);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BOX_LAYOUT_H__ */
|
828
clutter/clutter-box.c
Normal file
828
clutter/clutter-box.c
Normal file
@ -0,0 +1,828 @@
|
||||
/**
|
||||
* SECTION:clutter-box
|
||||
* @short_description: A Generic layout container
|
||||
*
|
||||
* #ClutterBox is a #ClutterActor sub-class implementing the #ClutterContainer
|
||||
* interface. A Box delegates the whole size requisition and size allocation to
|
||||
* a #ClutterLayoutManager instance.
|
||||
*
|
||||
* <example id="example-clutter-box">
|
||||
* <title>Using ClutterBox</title>
|
||||
* <para>The following code shows how to create a #ClutterBox with
|
||||
* a #ClutterLayoutManager sub-class, and how to add children to
|
||||
* it via clutter_box_pack().</para>
|
||||
* <programlisting>
|
||||
* ClutterActor *box;
|
||||
* ClutterLayoutManager *layout;
|
||||
*
|
||||
* /* Create the layout manager first */
|
||||
* layout = clutter_box_layout_new ();
|
||||
* clutter_box_layout_set_homogeneous (CLUTTER_BOX_LAYOUT (layout), TRUE);
|
||||
* clutter_box_layout_set_spacing (CLUTTER_BOX_LAYOUT (layout), 12);
|
||||
*
|
||||
* /* Then create the ClutterBox actor. The Box will take
|
||||
* * ownership of the ClutterLayoutManager instance by sinking
|
||||
* * its floating reference
|
||||
* */
|
||||
* box = clutter_box_new (layout);
|
||||
*
|
||||
* /* Now add children to the Box using the variadic arguments
|
||||
* * function clutter_box_pack() to set layout properties
|
||||
* */
|
||||
* clutter_box_pack (CLUTTER_BOX (box), actor,
|
||||
* "x-align", CLUTTER_BOX_ALIGNMENT_CENTER,
|
||||
* "y-align", CLUTTER_BOX_ALIGNMENT_END,
|
||||
* "expand", TRUE,
|
||||
* NULL);
|
||||
* </programlisting>
|
||||
* </example>
|
||||
*
|
||||
* #ClutterBox<!-- -->'s clutter_box_pack() wraps the generic
|
||||
* clutter_container_add_actor() function, but it also allows setting
|
||||
* layout properties while adding the new child to the box.
|
||||
*
|
||||
* #ClutterBox is available since Clutter 1.2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
#include "clutter-box.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-enum-types.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define CLUTTER_BOX_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), CLUTTER_TYPE_BOX, ClutterBoxPrivate))
|
||||
|
||||
struct _ClutterBoxPrivate
|
||||
{
|
||||
ClutterLayoutManager *manager;
|
||||
|
||||
GList *children;
|
||||
|
||||
guint changed_id;
|
||||
|
||||
ClutterColor color;
|
||||
guint color_set : 1;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_LAYOUT_MANAGER,
|
||||
PROP_COLOR,
|
||||
PROP_COLOR_SET
|
||||
};
|
||||
|
||||
static const ClutterColor default_box_color = { 255, 255, 255, 255 };
|
||||
|
||||
static void clutter_container_iface_init (ClutterContainerIface *iface);
|
||||
|
||||
G_DEFINE_TYPE_WITH_CODE (ClutterBox, clutter_box, CLUTTER_TYPE_ACTOR,
|
||||
G_IMPLEMENT_INTERFACE (CLUTTER_TYPE_CONTAINER,
|
||||
clutter_container_iface_init));
|
||||
|
||||
static gint
|
||||
sort_by_depth (gconstpointer a,
|
||||
gconstpointer b)
|
||||
{
|
||||
gfloat depth_a = clutter_actor_get_depth ((ClutterActor *) a);
|
||||
gfloat depth_b = clutter_actor_get_depth ((ClutterActor *) b);
|
||||
|
||||
if (depth_a < depth_b)
|
||||
return -1;
|
||||
|
||||
if (depth_a > depth_b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_add (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
|
||||
g_object_ref (actor);
|
||||
|
||||
priv->children = g_list_insert_sorted (priv->children,
|
||||
actor,
|
||||
sort_by_depth);
|
||||
|
||||
clutter_actor_set_parent (actor, CLUTTER_ACTOR (container));
|
||||
|
||||
clutter_layout_manager_add_child_meta (priv->manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
clutter_actor_queue_relayout (actor);
|
||||
|
||||
g_signal_emit_by_name (container, "actor-added", actor);
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_remove (ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
|
||||
g_object_ref (actor);
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
clutter_actor_unparent (actor);
|
||||
|
||||
clutter_layout_manager_remove_child_meta (priv->manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (container));
|
||||
|
||||
g_signal_emit_by_name (container, "actor-removed", actor);
|
||||
|
||||
g_object_unref (actor);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_foreach (ClutterContainer *container,
|
||||
ClutterCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
GList *l;
|
||||
|
||||
for (l = priv->children; l != NULL; l = l->next)
|
||||
(* callback) (l->data, user_data);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_raise (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
|
||||
if (sibling == NULL)
|
||||
priv->children = g_list_append (priv->children, actor);
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling) + 1;
|
||||
|
||||
priv->children = g_list_insert (priv->children, actor, index_);
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_lower (ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
ClutterActor *sibling)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
|
||||
priv->children = g_list_remove (priv->children, actor);
|
||||
|
||||
if (sibling == NULL)
|
||||
priv->children = g_list_prepend (priv->children, actor);
|
||||
else
|
||||
{
|
||||
gint index_ = g_list_index (priv->children, sibling);
|
||||
|
||||
priv->children = g_list_insert (priv->children, actor, index_);
|
||||
}
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_sort_depth_order (ClutterContainer *container)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (container)->priv;
|
||||
|
||||
priv->children = g_list_sort (priv->children, sort_by_depth);
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (container));
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_container_iface_init (ClutterContainerIface *iface)
|
||||
{
|
||||
iface->add = clutter_box_real_add;
|
||||
iface->remove = clutter_box_real_remove;
|
||||
iface->foreach = clutter_box_real_foreach;
|
||||
iface->raise = clutter_box_real_raise;
|
||||
iface->lower = clutter_box_real_lower;
|
||||
iface->sort_depth_order = clutter_box_real_sort_depth_order;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_paint (ClutterActor *actor)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
|
||||
if (priv->color_set)
|
||||
{
|
||||
ClutterActorBox box = { 0, };
|
||||
gfloat width, height;
|
||||
guint8 tmp_alpha;
|
||||
|
||||
clutter_actor_get_allocation_box (actor, &box);
|
||||
clutter_actor_box_get_size (&box, &width, &height);
|
||||
|
||||
tmp_alpha = clutter_actor_get_paint_opacity (actor)
|
||||
* priv->color.alpha
|
||||
/ 255;
|
||||
|
||||
cogl_set_source_color4ub (priv->color.red,
|
||||
priv->color.green,
|
||||
priv->color.blue,
|
||||
tmp_alpha);
|
||||
|
||||
cogl_rectangle (0, 0, width, height);
|
||||
}
|
||||
|
||||
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_pick (ClutterActor *actor,
|
||||
const ClutterColor *pick)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_box_parent_class)->pick (actor, pick);
|
||||
|
||||
g_list_foreach (priv->children, (GFunc) clutter_actor_paint, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_get_preferred_width (ClutterActor *actor,
|
||||
gfloat for_height,
|
||||
gfloat *min_width,
|
||||
gfloat *natural_width)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
|
||||
/* if we don't have any children don't bother proxying the
|
||||
* call to the layout manager instance
|
||||
*/
|
||||
if (priv->children == NULL)
|
||||
{
|
||||
if (min_width)
|
||||
*min_width = 0.0;
|
||||
|
||||
if (natural_width)
|
||||
*natural_width = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_layout_manager_get_preferred_width (priv->manager,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
for_height,
|
||||
min_width, natural_width);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_get_preferred_height (ClutterActor *actor,
|
||||
gfloat for_width,
|
||||
gfloat *min_height,
|
||||
gfloat *natural_height)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
|
||||
/* if we don't have any children don't bother proxying the
|
||||
* call to the layout manager instance
|
||||
*/
|
||||
if (priv->children == NULL)
|
||||
{
|
||||
if (min_height)
|
||||
*min_height = 0.0;
|
||||
|
||||
if (natural_height)
|
||||
*natural_height = 0.0;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
clutter_layout_manager_get_preferred_height (priv->manager,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
for_width,
|
||||
min_height, natural_height);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_real_allocate (ClutterActor *actor,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
ClutterActorClass *klass;
|
||||
|
||||
klass = CLUTTER_ACTOR_CLASS (clutter_box_parent_class);
|
||||
klass->allocate (actor, allocation, flags);
|
||||
|
||||
if (priv->children == NULL)
|
||||
return;
|
||||
|
||||
clutter_layout_manager_allocate (priv->manager,
|
||||
CLUTTER_CONTAINER (actor),
|
||||
allocation, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_destroy (ClutterActor *actor)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (actor)->priv;
|
||||
|
||||
/* destroy all our children */
|
||||
g_list_foreach (priv->children, (GFunc) clutter_actor_destroy, NULL);
|
||||
|
||||
CLUTTER_ACTOR_CLASS (clutter_box_parent_class)->destroy (actor);
|
||||
}
|
||||
|
||||
static inline void
|
||||
set_layout_manager (ClutterBox *self,
|
||||
ClutterLayoutManager *manager)
|
||||
{
|
||||
ClutterBoxPrivate *priv = self->priv;
|
||||
|
||||
if (priv->manager == manager)
|
||||
return;
|
||||
|
||||
if (priv->manager != NULL)
|
||||
{
|
||||
if (priv->changed_id != 0)
|
||||
g_signal_handler_disconnect (priv->manager, priv->changed_id);
|
||||
|
||||
clutter_layout_manager_set_container (priv->manager, NULL);
|
||||
g_object_unref (priv->manager);
|
||||
|
||||
priv->manager = NULL;
|
||||
priv->changed_id = 0;
|
||||
}
|
||||
|
||||
if (manager != NULL)
|
||||
{
|
||||
priv->manager = g_object_ref_sink (manager);
|
||||
clutter_layout_manager_set_container (manager,
|
||||
CLUTTER_CONTAINER (self));
|
||||
|
||||
priv->changed_id =
|
||||
g_signal_connect_swapped (priv->manager, "layout-changed",
|
||||
G_CALLBACK (clutter_actor_queue_relayout),
|
||||
self);
|
||||
}
|
||||
|
||||
clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
|
||||
g_object_notify (G_OBJECT (self), "layout-manager");
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_dispose (GObject *gobject)
|
||||
{
|
||||
ClutterBox *self = CLUTTER_BOX (gobject);
|
||||
|
||||
set_layout_manager (self, NULL);
|
||||
|
||||
G_OBJECT_CLASS (clutter_box_parent_class)->dispose (gobject);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_set_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBox *self = CLUTTER_BOX (gobject);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LAYOUT_MANAGER:
|
||||
set_layout_manager (self, g_value_get_object (value));
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
clutter_box_set_color (self, clutter_value_get_color (value));
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_get_property (GObject *gobject,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterBoxPrivate *priv = CLUTTER_BOX (gobject)->priv;
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_LAYOUT_MANAGER:
|
||||
g_value_set_object (value, priv->manager);
|
||||
break;
|
||||
|
||||
case PROP_COLOR:
|
||||
clutter_value_set_color (value, &priv->color);
|
||||
break;
|
||||
|
||||
case PROP_COLOR_SET:
|
||||
g_value_set_boolean (value, priv->color_set);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_class_init (ClutterBoxClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_type_class_add_private (klass, sizeof (ClutterBoxPrivate));
|
||||
|
||||
actor_class->get_preferred_width = clutter_box_real_get_preferred_width;
|
||||
actor_class->get_preferred_height = clutter_box_real_get_preferred_height;
|
||||
actor_class->allocate = clutter_box_real_allocate;
|
||||
actor_class->paint = clutter_box_real_paint;
|
||||
actor_class->pick = clutter_box_real_pick;
|
||||
actor_class->destroy = clutter_box_destroy;
|
||||
|
||||
gobject_class->set_property = clutter_box_set_property;
|
||||
gobject_class->get_property = clutter_box_get_property;
|
||||
gobject_class->dispose = clutter_box_dispose;
|
||||
|
||||
/**
|
||||
* ClutterBox:layout-manager:
|
||||
*
|
||||
* The #ClutterLayoutManager used by the #ClutterBox
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_object ("layout-manager",
|
||||
"Layout Manager",
|
||||
"The layout manager used by the box",
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER,
|
||||
CLUTTER_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT);
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_LAYOUT_MANAGER,
|
||||
pspec);
|
||||
|
||||
/**
|
||||
* ClutterBox:color:
|
||||
*
|
||||
* The color to be used to paint the background of the
|
||||
* #ClutterBox. Setting this property will set the
|
||||
* #ClutterBox:color-set property as a side effect
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = clutter_param_spec_color ("color",
|
||||
"Color",
|
||||
"The background color of the box",
|
||||
&default_box_color,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_COLOR, pspec);
|
||||
|
||||
/**
|
||||
* ClutterBox:color-set:
|
||||
*
|
||||
* Whether the #ClutterBox:color property has been set
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_boolean ("color-set",
|
||||
"Color Set",
|
||||
"Whether the background color is set",
|
||||
FALSE,
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_COLOR_SET, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_box_init (ClutterBox *self)
|
||||
{
|
||||
self->priv = CLUTTER_BOX_GET_PRIVATE (self);
|
||||
|
||||
self->priv->color = default_box_color;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_new:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
*
|
||||
* Creates a new #ClutterBox. The children of the box will be layed
|
||||
* out by the passed @manager
|
||||
*
|
||||
* Return value: the newly created #ClutterBox actor
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterActor *
|
||||
clutter_box_new (ClutterLayoutManager *manager)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
|
||||
|
||||
return g_object_new (CLUTTER_TYPE_BOX,
|
||||
"layout-manager", manager,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_set_layout_manager:
|
||||
* @box: a #ClutterBox
|
||||
* @manager: a #ClutterLayoutManager
|
||||
*
|
||||
* Sets the #ClutterLayoutManager for @box
|
||||
*
|
||||
* A #ClutterLayoutManager is a delegate object that controls the
|
||||
* layout of the children of @box
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_box_set_layout_manager (ClutterBox *box,
|
||||
ClutterLayoutManager *manager)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
|
||||
set_layout_manager (box, manager);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_get_layout_manager:
|
||||
* @box: a #ClutterBox
|
||||
*
|
||||
* Retrieves the #ClutterLayoutManager instance used by @box
|
||||
*
|
||||
* Return value: a #ClutterLayoutManager
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_box_get_layout_manager (ClutterBox *box)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_BOX (box), NULL);
|
||||
|
||||
return box->priv->manager;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_packv:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @n_properties: the number of properties to set
|
||||
* @properties: (array length=n_properties) (element-type utf8): a vector
|
||||
* containing the property names to set
|
||||
* @values: (array length=n_properties): a vector containing the property
|
||||
* values to set
|
||||
*
|
||||
* Vector-based variant of clutter_box_pack(), intended for language
|
||||
* bindings to use
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_box_packv (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
guint n_properties,
|
||||
const gchar * const properties[],
|
||||
const GValue *values)
|
||||
{
|
||||
ClutterContainer *container;
|
||||
ClutterBoxPrivate *priv;
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
container = CLUTTER_CONTAINER (box);
|
||||
clutter_container_add_actor (container, actor);
|
||||
|
||||
priv = box->priv;
|
||||
|
||||
meta = clutter_layout_manager_get_child_meta (priv->manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
if (meta == NULL)
|
||||
return;
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
for (i = 0; i < n_properties; i++)
|
||||
{
|
||||
const gchar *pname = properties[i];
|
||||
GParamSpec *pspec;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') does not exist",
|
||||
G_STRLOC,
|
||||
pname,
|
||||
G_OBJECT_TYPE_NAME (priv->manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') is not writable",
|
||||
G_STRLOC,
|
||||
pspec->name,
|
||||
G_OBJECT_TYPE_NAME (priv->manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_layout_manager_child_set_property (priv->manager,
|
||||
container, actor,
|
||||
pname, &values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_pack:
|
||||
* @box: a #ClutterBox
|
||||
* @actor: a #ClutterActor
|
||||
* @first_property: the name of the first property to set, or %NULL
|
||||
* @Varargs: a list of property name and value pairs, terminated by %NULL
|
||||
*
|
||||
* Adds @actor to @box and sets layout properties at the same time,
|
||||
* if the #ClutterLayoutManager used by @box has them
|
||||
*
|
||||
* This function is a wrapper around clutter_container_add_actor()
|
||||
* and clutter_layout_manager_child_set()
|
||||
*
|
||||
* Language bindings should use the vector-based clutter_box_addv()
|
||||
* variant instead
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_box_pack (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
ClutterBoxPrivate *priv;
|
||||
ClutterContainer *container;
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
const gchar *pname;
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
container = CLUTTER_CONTAINER (box);
|
||||
clutter_container_add_actor (container, actor);
|
||||
|
||||
if (first_property == NULL || *first_property == '\0')
|
||||
return;
|
||||
|
||||
priv = box->priv;
|
||||
|
||||
meta = clutter_layout_manager_get_child_meta (priv->manager,
|
||||
container,
|
||||
actor);
|
||||
|
||||
if (meta == NULL)
|
||||
return;
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
va_start (var_args, first_property);
|
||||
|
||||
pname = first_property;
|
||||
while (pname)
|
||||
{
|
||||
GValue value = { 0, };
|
||||
GParamSpec *pspec;
|
||||
gchar *error;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') does not exist",
|
||||
G_STRLOC,
|
||||
pname,
|
||||
G_OBJECT_TYPE_NAME (priv->manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_warning ("%s: the layout property '%s' for managers "
|
||||
"of type '%s' (meta type '%s') is not writable",
|
||||
G_STRLOC,
|
||||
pspec->name,
|
||||
G_OBJECT_TYPE_NAME (priv->manager),
|
||||
G_OBJECT_TYPE_NAME (meta));
|
||||
break;
|
||||
}
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
G_VALUE_COLLECT (&value, var_args, 0, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
break;
|
||||
}
|
||||
|
||||
clutter_layout_manager_child_set_property (priv->manager,
|
||||
container, actor,
|
||||
pspec->name, &value);
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
pname = va_arg (var_args, gchar*);
|
||||
}
|
||||
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_set_color:
|
||||
* @box: a #ClutterBox
|
||||
* @color: (allow-none): the background color, or %NULL to unset
|
||||
*
|
||||
* Sets (or unsets) the background color for @box
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_box_set_color (ClutterBox *box,
|
||||
const ClutterColor *color)
|
||||
{
|
||||
ClutterBoxPrivate *priv;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
|
||||
priv = box->priv;
|
||||
|
||||
if (color)
|
||||
{
|
||||
priv->color = *color;
|
||||
priv->color_set = TRUE;
|
||||
}
|
||||
else
|
||||
priv->color_set = FALSE;
|
||||
|
||||
clutter_actor_queue_redraw (CLUTTER_ACTOR (box));
|
||||
|
||||
g_object_notify (G_OBJECT (box), "color-set");
|
||||
g_object_notify (G_OBJECT (box), "color");
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_box_get_color:
|
||||
* @box: a #ClutterBox
|
||||
* @color: (out): return location for a #ClutterColor
|
||||
*
|
||||
* Retrieves the background color of @box
|
||||
*
|
||||
* If the #ClutterBox:color-set property is set to %FALSE the
|
||||
* returned #ClutterColor is undefined
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_box_get_color (ClutterBox *box,
|
||||
ClutterColor *color)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_BOX (box));
|
||||
g_return_if_fail (color != NULL);
|
||||
|
||||
*color = box->priv->color;
|
||||
}
|
62
clutter/clutter-box.h
Normal file
62
clutter/clutter-box.h
Normal file
@ -0,0 +1,62 @@
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_BOX_H__
|
||||
#define __CLUTTER_BOX_H__
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-container.h>
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_BOX (clutter_box_get_type ())
|
||||
#define CLUTTER_BOX(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_BOX, ClutterBox))
|
||||
#define CLUTTER_IS_BOX(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_BOX))
|
||||
#define CLUTTER_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_BOX, ClutterBoxClass))
|
||||
#define CLUTTER_IS_BOX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_BOX))
|
||||
#define CLUTTER_BOX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_BOX, ClutterBoxClass))
|
||||
|
||||
typedef struct _ClutterBox ClutterBox;
|
||||
typedef struct _ClutterBoxPrivate ClutterBoxPrivate;
|
||||
typedef struct _ClutterBoxClass ClutterBoxClass;
|
||||
|
||||
struct _ClutterBox
|
||||
{
|
||||
ClutterActor parent_instance;
|
||||
|
||||
ClutterBoxPrivate *priv;
|
||||
};
|
||||
|
||||
struct _ClutterBoxClass
|
||||
{
|
||||
ClutterActorClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_box_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterActor * clutter_box_new (ClutterLayoutManager *manager);
|
||||
|
||||
void clutter_box_set_layout_manager (ClutterBox *box,
|
||||
ClutterLayoutManager *manager);
|
||||
ClutterLayoutManager *clutter_box_get_layout_manager (ClutterBox *box);
|
||||
|
||||
void clutter_box_set_color (ClutterBox *box,
|
||||
const ClutterColor *color);
|
||||
void clutter_box_get_color (ClutterBox *box,
|
||||
ClutterColor *color);
|
||||
|
||||
void clutter_box_pack (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void clutter_box_packv (ClutterBox *box,
|
||||
ClutterActor *actor,
|
||||
guint n_properties,
|
||||
const gchar * const properties[],
|
||||
const GValue *values);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_BOX_H__ */
|
186
clutter/clutter-fixed-layout.c
Normal file
186
clutter/clutter-fixed-layout.c
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*
|
||||
* Based on the fixed layout code inside clutter-group.c
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-fixed-layout
|
||||
* @short_description: A fixed layout manager
|
||||
*
|
||||
* #ClutterFixedLayout is a layout manager implementing the same
|
||||
* layout policies as #ClutterGroup.
|
||||
*
|
||||
* #ClutterFixedLayout is available since Clutter 1.2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
G_DEFINE_TYPE (ClutterFixedLayout,
|
||||
clutter_fixed_layout,
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER);
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
GList *children, *l;
|
||||
gdouble min_right;
|
||||
gdouble natural_right;
|
||||
|
||||
min_right = 0;
|
||||
natural_right = 0;
|
||||
|
||||
children = clutter_container_get_children (container);
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat child_x, child_min, child_natural;
|
||||
|
||||
child_x = clutter_actor_get_x (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
&child_min, NULL,
|
||||
&child_natural, NULL);
|
||||
|
||||
if (child_x + child_min > min_right)
|
||||
min_right = child_x + child_min;
|
||||
|
||||
if (child_x + child_natural > natural_right)
|
||||
natural_right = child_x + child_natural;
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = min_right;
|
||||
|
||||
if (nat_width_p)
|
||||
*nat_width_p = natural_right;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
GList *children, *l;
|
||||
gdouble min_bottom;
|
||||
gdouble natural_bottom;
|
||||
|
||||
min_bottom = 0;
|
||||
natural_bottom = 0;
|
||||
|
||||
children = clutter_container_get_children (container);
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat child_y, child_min, child_natural;
|
||||
|
||||
child_y = clutter_actor_get_y (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
NULL, &child_min,
|
||||
NULL, &child_natural);
|
||||
|
||||
if (child_y + child_min > min_bottom)
|
||||
min_bottom = child_y + child_min;
|
||||
|
||||
if (child_y + child_natural > natural_bottom)
|
||||
natural_bottom = child_y + child_natural;
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = min_bottom;
|
||||
|
||||
if (nat_height_p)
|
||||
*nat_height_p = natural_bottom;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_allocate (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
GList *children, *l;
|
||||
|
||||
children = clutter_container_get_children (container);
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
|
||||
clutter_actor_allocate_preferred_size (child, flags);
|
||||
}
|
||||
|
||||
g_list_free (children);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_class_init (ClutterFixedLayoutClass *klass)
|
||||
{
|
||||
ClutterLayoutManagerClass *manager_class =
|
||||
CLUTTER_LAYOUT_MANAGER_CLASS (klass);
|
||||
|
||||
manager_class->get_preferred_width =
|
||||
clutter_fixed_layout_get_preferred_width;
|
||||
manager_class->get_preferred_height =
|
||||
clutter_fixed_layout_get_preferred_height;
|
||||
manager_class->allocate = clutter_fixed_layout_allocate;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_init (ClutterFixedLayout *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_fixed_layout_new:
|
||||
*
|
||||
* Creates a new #ClutterFixedLayout
|
||||
*
|
||||
* Return value: the newly created #ClutterFixedLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_fixed_layout_new (void)
|
||||
{
|
||||
return g_object_new (CLUTTER_TYPE_FIXED_LAYOUT, NULL);
|
||||
}
|
80
clutter/clutter-fixed-layout.h
Normal file
80
clutter/clutter-fixed-layout.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_FIXED_LAYOUT_H__
|
||||
#define __CLUTTER_FIXED_LAYOUT_H__
|
||||
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_FIXED_LAYOUT (clutter_fixed_layout_get_type ())
|
||||
#define CLUTTER_FIXED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayout))
|
||||
#define CLUTTER_IS_FIXED_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_FIXED_LAYOUT))
|
||||
#define CLUTTER_FIXED_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayoutClass))
|
||||
#define CLUTTER_IS_FIXED_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_FIXED_LAYOUT))
|
||||
#define CLUTTER_FIXED_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_FIXED_LAYOUT, ClutterFixedLayoutClass))
|
||||
|
||||
typedef struct _ClutterFixedLayout ClutterFixedLayout;
|
||||
typedef struct _ClutterFixedLayoutClass ClutterFixedLayoutClass;
|
||||
|
||||
/**
|
||||
* ClutterFixedLayout:
|
||||
*
|
||||
* The #ClutterFixedLayout structure contains only private data and
|
||||
* it should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterFixedLayout
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManager parent_instance;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterFixedLayoutClass:
|
||||
*
|
||||
* The #ClutterFixedLayoutClass structure contains only private data
|
||||
* and it should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterFixedLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_fixed_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterLayoutManager *clutter_fixed_layout_new (void);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_FIXED_LAYOUT_H__ */
|
1321
clutter/clutter-flow-layout.c
Normal file
1321
clutter/clutter-flow-layout.c
Normal file
File diff suppressed because it is too large
Load Diff
127
clutter/clutter-flow-layout.h
Normal file
127
clutter/clutter-flow-layout.h
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_FLOW_LAYOUT_H__
|
||||
#define __CLUTTER_FLOW_LAYOUT_H__
|
||||
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_FLOW_LAYOUT (clutter_flow_layout_get_type ())
|
||||
#define CLUTTER_FLOW_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayout))
|
||||
#define CLUTTER_IS_FLOW_LAYOUT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_FLOW_LAYOUT))
|
||||
#define CLUTTER_FLOW_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayoutClass))
|
||||
#define CLUTTER_IS_FLOW_LAYOUT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_FLOW_LAYOUT))
|
||||
#define CLUTTER_FLOW_LAYOUT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_FLOW_LAYOUT, ClutterFlowLayoutClass))
|
||||
|
||||
typedef struct _ClutterFlowLayout ClutterFlowLayout;
|
||||
typedef struct _ClutterFlowLayoutPrivate ClutterFlowLayoutPrivate;
|
||||
typedef struct _ClutterFlowLayoutClass ClutterFlowLayoutClass;
|
||||
|
||||
/**
|
||||
* ClutterFlowOrientation:
|
||||
* @CLUTTER_FLOW_HORIZONTAL: Arrange the children of the flow layout
|
||||
* horizontally first
|
||||
* @CLUTTER_FLOW_VERTICAL: Arrange the children of the flow layout
|
||||
* vertically first
|
||||
*
|
||||
* The direction of the arrangement of the children inside
|
||||
* a #ClutterFlowLayout
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
typedef enum { /*< prefix=CLUTTER_FLOW >*/
|
||||
CLUTTER_FLOW_HORIZONTAL,
|
||||
CLUTTER_FLOW_VERTICAL
|
||||
} ClutterFlowOrientation;
|
||||
|
||||
/**
|
||||
* ClutterFlowLayout:
|
||||
*
|
||||
* The #ClutterFlowLayout structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterFlowLayout
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManager parent_instance;
|
||||
|
||||
ClutterFlowLayoutPrivate *priv;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterFlowLayoutClass:
|
||||
*
|
||||
* The #ClutterFlowLayoutClass structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterFlowLayoutClass
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterLayoutManagerClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_flow_layout_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterLayoutManager * clutter_flow_layout_new (ClutterFlowOrientation orientation);
|
||||
|
||||
void clutter_flow_layout_set_orientation (ClutterFlowLayout *layout,
|
||||
ClutterFlowOrientation orientation);
|
||||
ClutterFlowOrientation clutter_flow_layout_get_orientation (ClutterFlowLayout *layout);
|
||||
void clutter_flow_layout_set_homogeneous (ClutterFlowLayout *layout,
|
||||
gboolean homogeneous);
|
||||
gboolean clutter_flow_layout_get_homogeneous (ClutterFlowLayout *layout);
|
||||
|
||||
void clutter_flow_layout_set_column_spacing (ClutterFlowLayout *layout,
|
||||
gfloat spacing);
|
||||
gfloat clutter_flow_layout_get_column_spacing (ClutterFlowLayout *layout);
|
||||
void clutter_flow_layout_set_row_spacing (ClutterFlowLayout *layout,
|
||||
gfloat spacing);
|
||||
gfloat clutter_flow_layout_get_row_spacing (ClutterFlowLayout *layout);
|
||||
|
||||
void clutter_flow_layout_set_column_width (ClutterFlowLayout *layout,
|
||||
gfloat min_width,
|
||||
gfloat max_width);
|
||||
void clutter_flow_layout_get_column_width (ClutterFlowLayout *layout,
|
||||
gfloat *min_width,
|
||||
gfloat *max_width);
|
||||
void clutter_flow_layout_set_row_height (ClutterFlowLayout *layout,
|
||||
gfloat min_height,
|
||||
gfloat max_height);
|
||||
void clutter_flow_layout_get_row_height (ClutterFlowLayout *layout,
|
||||
gfloat *min_height,
|
||||
gfloat *max_height);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_FLOW_LAYOUT_H__ */
|
@ -45,6 +45,7 @@
|
||||
#include "clutter-group.h"
|
||||
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-private.h"
|
||||
#include "clutter-debug.h"
|
||||
@ -75,6 +76,8 @@ G_DEFINE_TYPE_WITH_CODE (ClutterGroup,
|
||||
struct _ClutterGroupPrivate
|
||||
{
|
||||
GList *children;
|
||||
|
||||
ClutterLayoutManager *layout;
|
||||
};
|
||||
|
||||
|
||||
@ -126,113 +129,19 @@ clutter_group_pick (ClutterActor *actor,
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_width (GList *children,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
GList *l;
|
||||
gdouble min_right, natural_right;
|
||||
|
||||
/* We will always be at least 0 sized (ie, if all of the actors are
|
||||
to the left of the origin we won't return a negative size) */
|
||||
min_right = 0;
|
||||
natural_right = 0;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat child_x, child_min, child_natural;
|
||||
|
||||
child_x = clutter_actor_get_x (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
&child_min, NULL,
|
||||
&child_natural, NULL);
|
||||
|
||||
/* Track the rightmost edge */
|
||||
if (child_x + child_min > min_right)
|
||||
min_right = child_x + child_min;
|
||||
|
||||
if (child_x + child_natural > natural_right)
|
||||
natural_right = child_x + child_natural;
|
||||
}
|
||||
|
||||
/* The size is defined as the distance from the origin to the
|
||||
right-hand edge of the rightmost actor */
|
||||
if (min_width_p)
|
||||
*min_width_p = min_right;
|
||||
|
||||
if (natural_width_p)
|
||||
*natural_width_p = natural_right;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_get_preferred_height (GList *children,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
GList *l;
|
||||
gdouble min_bottom, natural_bottom;
|
||||
|
||||
/* We will always be at least 0 sized (ie, if all of the actors are
|
||||
above the origin we won't return a negative size) */
|
||||
min_bottom = 0;
|
||||
natural_bottom = 0;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
gfloat child_y, child_min, child_natural;
|
||||
|
||||
child_y = clutter_actor_get_y (child);
|
||||
|
||||
clutter_actor_get_preferred_size (child,
|
||||
NULL, &child_min,
|
||||
NULL, &child_natural);
|
||||
|
||||
/* Track the bottommost edge */
|
||||
if (child_y + child_min > min_bottom)
|
||||
min_bottom = child_y + child_min;
|
||||
|
||||
if (child_y + child_natural > natural_bottom)
|
||||
natural_bottom = child_y + child_natural;
|
||||
}
|
||||
|
||||
/* The size is defined as the distance from the origin to the bottom
|
||||
edge of the bottommost actor */
|
||||
if (min_height_p)
|
||||
*min_height_p = min_bottom;
|
||||
|
||||
if (natural_height_p)
|
||||
*natural_height_p = natural_bottom;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_fixed_layout_allocate (GList *children,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
GList *l;
|
||||
|
||||
for (l = children; l != NULL; l = l->next)
|
||||
{
|
||||
ClutterActor *child = l->data;
|
||||
clutter_actor_allocate_preferred_size (child, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_group_get_preferred_width (ClutterActor *self,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *natural_width_p)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
/* for_height is irrelevant to the fixed layout, so it's not used */
|
||||
clutter_fixed_layout_get_preferred_width (priv->children,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
clutter_layout_manager_get_preferred_width (priv->layout, container,
|
||||
for_height,
|
||||
min_width_p,
|
||||
natural_width_p);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -241,12 +150,13 @@ clutter_group_get_preferred_height (ClutterActor *self,
|
||||
gfloat *min_height_p,
|
||||
gfloat *natural_height_p)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
/* for_width is irrelevant to the fixed layout, so it's not used */
|
||||
clutter_fixed_layout_get_preferred_height (priv->children,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
clutter_layout_manager_get_preferred_width (priv->layout, container,
|
||||
for_width,
|
||||
min_height_p,
|
||||
natural_height_p);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -254,17 +164,16 @@ clutter_group_allocate (ClutterActor *self,
|
||||
const ClutterActorBox *box,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterContainer *container = CLUTTER_CONTAINER (self);
|
||||
ClutterGroupPrivate *priv = CLUTTER_GROUP (self)->priv;
|
||||
|
||||
/* chain up to set actor->allocation */
|
||||
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->allocate (self, box, flags);
|
||||
|
||||
/* Note that fixed-layout allocation of children does not care what
|
||||
* allocation the container received, so "box" is not passed in
|
||||
* here. We do not require that children's allocations are completely
|
||||
* contained by our own.
|
||||
*/
|
||||
clutter_fixed_layout_allocate (priv->children, flags);
|
||||
if (priv->children == NULL)
|
||||
return;
|
||||
|
||||
clutter_layout_manager_allocate (priv->layout, container, box, flags);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -281,6 +190,12 @@ clutter_group_dispose (GObject *object)
|
||||
priv->children = NULL;
|
||||
}
|
||||
|
||||
if (priv->layout)
|
||||
{
|
||||
g_object_unref (priv->layout);
|
||||
priv->layout = NULL;
|
||||
}
|
||||
|
||||
G_OBJECT_CLASS (clutter_group_parent_class)->dispose (object);
|
||||
}
|
||||
|
||||
@ -468,8 +383,10 @@ sort_z_order (gconstpointer a,
|
||||
|
||||
if (depth_a < depth_b)
|
||||
return -1;
|
||||
|
||||
if (depth_a > depth_b)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -521,6 +438,9 @@ static void
|
||||
clutter_group_init (ClutterGroup *self)
|
||||
{
|
||||
self->priv = CLUTTER_GROUP_GET_PRIVATE (self);
|
||||
|
||||
self->priv->layout = clutter_fixed_layout_new ();
|
||||
g_object_ref_sink (self->priv->layout);
|
||||
}
|
||||
|
||||
/**
|
||||
|
887
clutter/clutter-layout-manager.c
Normal file
887
clutter/clutter-layout-manager.c
Normal file
@ -0,0 +1,887 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-layout-manager
|
||||
* @short_description: Layout managers base class
|
||||
*
|
||||
* #ClutterLayoutManager is a base abstract class for layout managers. A
|
||||
* layout manager implements the layouting policy for a composite or a
|
||||
* container actor: it controls the preferred size of the actor to which
|
||||
* it has been paired, and it controls the allocation of its children.
|
||||
*
|
||||
* Any composite or container #ClutterActor subclass can delegate the
|
||||
* layouting of its children to a #ClutterLayoutManager. Clutter provides
|
||||
* a generic container using #ClutterLayoutManager called #ClutterBox.
|
||||
*
|
||||
* Clutter provides some simple #ClutterLayoutManager sub-classes, like
|
||||
* #ClutterFixedLayout and #ClutterBinLayout.
|
||||
*
|
||||
* <refsect2 id="ClutterLayoutManager-use-in-Actor">
|
||||
* <title>Using ClutterLayoutManager inside an Actor</title>
|
||||
* <para>In order to use a #ClutterLayoutManager inside a #ClutterActor
|
||||
* sub-class you should invoke clutter_layout_manager_get_preferred_width()
|
||||
* inside the <structname>ClutterActor</structname>::get_preferred_width()
|
||||
* virtual function and clutter_layout_manager_get_preferred_height()
|
||||
* inside the <structname>ClutterActor</structname>::get_preferred_height()
|
||||
* virtual function implementations. You should also call
|
||||
* clutter_layout_manager_allocate() inside the implementation of the
|
||||
* <structname>ClutterActor</structname>::allocate() virtual
|
||||
* function.</para>
|
||||
* <para>In order to receive notifications for changes in the layout
|
||||
* manager policies you should also connect to the
|
||||
* #ClutterLayoutManager::layout-changed signal and queue a relayout
|
||||
* on your actor. The following code should be enough if the actor
|
||||
* does not need to perform specific operations whenever a layout
|
||||
* manager changes:</para>
|
||||
* <informalexample><programlisting>
|
||||
* g_signal_connect_swapped (layout_manager,
|
||||
* "layout-changed",
|
||||
* G_CALLBACK (clutter_actor_queue_relayout),
|
||||
* actor);
|
||||
* </programlisting></informalexample>
|
||||
* </refsect2>
|
||||
*
|
||||
* <refsect2 id="ClutterLayoutManager-implementation">
|
||||
* <title>Implementing a ClutterLayoutManager</title>
|
||||
* <para>The implementation of a layout manager does not differ from
|
||||
* the implementation of the size requisition and allocation bits of
|
||||
* #ClutterActor, so you should read the relative documentation
|
||||
* <link linkend="clutter-subclassing-ClutterActor">for subclassing
|
||||
* ClutterActor</link>.</para>
|
||||
* <para>The layout manager implementation can hold a back reference
|
||||
* to the #ClutterContainer by implementing the set_container()
|
||||
* virtual function. The layout manager should not hold a reference
|
||||
* on the container actor, to avoid reference cycles.</para>
|
||||
* <para>If the layout manager has properties affecting the layout
|
||||
* policies then it should emit the #ClutterLayoutManager::layout-changed
|
||||
* signal on itself by using the clutter_layout_manager_layout_changed()
|
||||
* function.</para>
|
||||
* </refsect2>
|
||||
*
|
||||
* #ClutterLayoutManager is available since Clutter 1.2
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <glib-object.h>
|
||||
#include <gobject/gvaluecollector.h>
|
||||
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-layout-manager.h"
|
||||
#include "clutter-layout-meta.h"
|
||||
#include "clutter-marshal.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
#define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \
|
||||
GObject *_obj = G_OBJECT (m); \
|
||||
g_warning ("Layout managers of type %s do not implement " \
|
||||
"the ClutterLayoutManager::%s method", \
|
||||
G_OBJECT_TYPE_NAME (_obj), \
|
||||
(method)); } G_STMT_END
|
||||
|
||||
enum
|
||||
{
|
||||
LAYOUT_CHANGED,
|
||||
|
||||
LAST_SIGNAL
|
||||
};
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterLayoutManager,
|
||||
clutter_layout_manager,
|
||||
G_TYPE_INITIALLY_UNOWNED);
|
||||
|
||||
static GQuark quark_layout_meta = 0;
|
||||
static guint manager_signals[LAST_SIGNAL] = { 0, };
|
||||
|
||||
static void
|
||||
layout_manager_real_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "get_preferred_width");
|
||||
|
||||
if (min_width_p)
|
||||
*min_width_p = 0.0;
|
||||
|
||||
if (nat_width_p)
|
||||
*nat_width_p = 0.0;
|
||||
}
|
||||
|
||||
static void
|
||||
layout_manager_real_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "get_preferred_height");
|
||||
|
||||
if (min_height_p)
|
||||
*min_height_p = 0.0;
|
||||
|
||||
if (nat_height_p)
|
||||
*nat_height_p = 0.0;
|
||||
}
|
||||
|
||||
static void
|
||||
layout_manager_real_allocate (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED (manager, "allocate");
|
||||
}
|
||||
|
||||
static ClutterLayoutMeta *
|
||||
layout_manager_real_create_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
|
||||
{
|
||||
quark_layout_meta =
|
||||
g_quark_from_static_string ("clutter-layout-manager-child-meta");
|
||||
|
||||
klass->get_preferred_width = layout_manager_real_get_preferred_width;
|
||||
klass->get_preferred_height = layout_manager_real_get_preferred_height;
|
||||
klass->allocate = layout_manager_real_allocate;
|
||||
klass->create_child_meta = layout_manager_real_create_child_meta;
|
||||
|
||||
/**
|
||||
* ClutterLayoutManager::layout-changed:
|
||||
* @manager: the #ClutterLayoutManager that emitted the signal
|
||||
*
|
||||
* The ::layout-changed signal is emitted each time a layout manager
|
||||
* has been changed. Every #ClutterActor using the @manager instance
|
||||
* as a layout manager should connect a handler to the ::layout-changed
|
||||
* signal and queue a relayout on themselves:
|
||||
*
|
||||
* |[
|
||||
* static void layout_changed (ClutterLayoutManager *manager,
|
||||
* ClutterActor *self)
|
||||
* {
|
||||
* clutter_actor_queue_relayout (self);
|
||||
* }
|
||||
* ...
|
||||
* self->manager = g_object_ref_sink (manager);
|
||||
* g_signal_connect (self->manager, "layout-changed",
|
||||
* G_CALLBACK (layout_changed),
|
||||
* self);
|
||||
* ]|
|
||||
*
|
||||
* Sub-classes of #ClutterLayoutManager that implement a layout that
|
||||
* can be controlled or changed using parameters should emit the
|
||||
* ::layout-changed signal whenever one of the parameters changes,
|
||||
* by using clutter_layout_manager_layout_changed().
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
manager_signals[LAYOUT_CHANGED] =
|
||||
g_signal_new (I_("layout-changed"),
|
||||
G_TYPE_FROM_CLASS (klass),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (ClutterLayoutManagerClass,
|
||||
layout_changed),
|
||||
NULL, NULL,
|
||||
clutter_marshal_VOID__VOID,
|
||||
G_TYPE_NONE, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layout_manager_init (ClutterLayoutManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_get_preferred_width:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: the #ClutterContainer using @manager
|
||||
* @for_height: the height for which the width should be computed, or -1
|
||||
* @min_width_p: (out) (allow-none): return location for the minimum width
|
||||
* of the layout, or %NULL
|
||||
* @nat_width_p: (out) (allow-none): return location for the natural width
|
||||
* of the layout, or %NULL
|
||||
*
|
||||
* Computes the minimum and natural widths of the @container according
|
||||
* to @manager.
|
||||
*
|
||||
* See also clutter_actor_get_preferred_width()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p)
|
||||
{
|
||||
ClutterLayoutManagerClass *klass;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
|
||||
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
|
||||
klass->get_preferred_width (manager, container, for_height,
|
||||
min_width_p,
|
||||
nat_width_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_get_preferred_height:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: the #ClutterContainer using @manager
|
||||
* @for_width: the width for which the height should be computed, or -1
|
||||
* @min_height_p: (out) (allow-none): return location for the minimum height
|
||||
* of the layout, or %NULL
|
||||
* @nat_height_p: (out) (allow-none): return location for the natural height
|
||||
* of the layout, or %NULL
|
||||
*
|
||||
* Computes the minimum and natural heights of the @container according
|
||||
* to @manager.
|
||||
*
|
||||
* See also clutter_actor_get_preferred_height()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p)
|
||||
{
|
||||
ClutterLayoutManagerClass *klass;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
|
||||
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
|
||||
klass->get_preferred_height (manager, container, for_width,
|
||||
min_height_p,
|
||||
nat_height_p);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_allocate:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: the #ClutterContainer using @manager
|
||||
* @allocation: the #ClutterActorBox containing the allocated area
|
||||
* of @container
|
||||
* @flags: the allocation flags
|
||||
*
|
||||
* Allocates the children of @container given an area
|
||||
*
|
||||
* See also clutter_actor_allocate()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_allocate (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags)
|
||||
{
|
||||
ClutterLayoutManagerClass *klass;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (allocation != NULL);
|
||||
|
||||
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
|
||||
klass->allocate (manager, container, allocation, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_layout_changed:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
*
|
||||
* Emits the #ClutterLayoutManager::layout-changed signal on @manager
|
||||
*
|
||||
* This function should only be called by implementations of the
|
||||
* #ClutterLayoutManager class
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_layout_changed (ClutterLayoutManager *manager)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
|
||||
g_signal_emit (manager, manager_signals[LAYOUT_CHANGED], 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_set_container:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: (allow-none): a #ClutterContainer using @manager
|
||||
*
|
||||
* If the #ClutterLayoutManager sub-class allows it, allow
|
||||
* adding a weak reference of the @container using @manager
|
||||
* from within the layout manager
|
||||
*
|
||||
* The layout manager should not increase the reference
|
||||
* count of the @container
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_set_container (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container)
|
||||
{
|
||||
ClutterLayoutManagerClass *klass;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (container == NULL || CLUTTER_IS_CONTAINER (container));
|
||||
|
||||
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
|
||||
if (klass->set_container)
|
||||
klass->set_container (manager, container);
|
||||
}
|
||||
|
||||
static inline ClutterLayoutMeta *
|
||||
create_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterLayoutManagerClass *klass;
|
||||
|
||||
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
|
||||
|
||||
return klass->create_child_meta (manager, container, actor);
|
||||
}
|
||||
|
||||
static inline ClutterLayoutMeta *
|
||||
get_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterLayoutMeta *layout = NULL;
|
||||
|
||||
layout = g_object_get_qdata (G_OBJECT (actor), quark_layout_meta);
|
||||
if (layout != NULL)
|
||||
{
|
||||
ClutterChildMeta *child = CLUTTER_CHILD_META (layout);
|
||||
|
||||
if (layout->manager == manager &&
|
||||
child->container == container &&
|
||||
child->actor == actor)
|
||||
return layout;
|
||||
|
||||
/* if the LayoutMeta referenced is not attached to the
|
||||
* layout manager then we simply ask the layout manager
|
||||
* to replace it with the right one
|
||||
*/
|
||||
layout = create_child_meta (manager, container, actor);
|
||||
if (layout != NULL)
|
||||
{
|
||||
g_assert (CLUTTER_IS_LAYOUT_META (layout));
|
||||
g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta,
|
||||
layout,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_get_child_meta:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
*
|
||||
* Retrieves the #ClutterLayoutMeta that the layout @manager associated
|
||||
* to the @actor child of @container
|
||||
*
|
||||
* Return value: a #ClutterLayoutMeta or %NULL
|
||||
*
|
||||
* Since: 1.0
|
||||
*/
|
||||
ClutterLayoutMeta *
|
||||
clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_CONTAINER (container), NULL);
|
||||
g_return_val_if_fail (CLUTTER_IS_ACTOR (actor), NULL);
|
||||
|
||||
return get_child_meta (manager, container, actor);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_add_child_meta:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
*
|
||||
* Creates and binds a #ClutterLayoutMeta for @manager to
|
||||
* a child of @container
|
||||
*
|
||||
* This function should only be used when implementing containers
|
||||
* using #ClutterLayoutManager and not by application code
|
||||
*
|
||||
* Typically, containers should bind a #ClutterLayoutMeta created
|
||||
* by a #ClutterLayoutManager when adding a new child, e.g.:
|
||||
*
|
||||
* |[
|
||||
* static void
|
||||
* my_container_add (ClutterContainer *container,
|
||||
* ClutterActor *actor)
|
||||
* {
|
||||
* MyContainer *self = MY_CONTAINER (container);
|
||||
*
|
||||
* self->children = g_slist_append (self->children, actor);
|
||||
* clutter_actor_set_parent (actor, CLUTTER_ACTOR (self));
|
||||
*
|
||||
* clutter_layout_manager_add_child_meta (self->layout,
|
||||
* container,
|
||||
* actor);
|
||||
*
|
||||
* clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
*
|
||||
* g_signal_emit_by_name (container, "actor-added");
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* The #ClutterLayoutMeta should be removed when removing an
|
||||
* actor; see clutter_layout_manager_remove_child_meta()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_add_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
ClutterLayoutMeta *meta;
|
||||
|
||||
meta = create_child_meta (manager, container, actor);
|
||||
if (meta == NULL)
|
||||
return;
|
||||
|
||||
g_object_set_qdata_full (G_OBJECT (actor), quark_layout_meta,
|
||||
meta,
|
||||
(GDestroyNotify) g_object_unref);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_remove_child_meta:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
*
|
||||
* Unbinds and unrefs a #ClutterLayoutMeta for @manager from
|
||||
* a child of @container
|
||||
*
|
||||
* This function should only be used when implementing containers
|
||||
* using #ClutterLayoutManager and not by application code
|
||||
*
|
||||
* Typically, containers should remove a #ClutterLayoutMeta created
|
||||
* by a #ClutterLayoutManager when removing a child, e.g.:
|
||||
*
|
||||
* |[
|
||||
* static void
|
||||
* my_container_remove (ClutterContainer *container,
|
||||
* ClutterActor *actor)
|
||||
* {
|
||||
* MyContainer *self = MY_CONTAINER (container);
|
||||
*
|
||||
* g_object_ref (actor);
|
||||
*
|
||||
* self->children = g_slist_remove (self->children, actor);
|
||||
* clutter_actor_unparent (actor);
|
||||
*
|
||||
* clutter_layout_manager_remove_child_meta (self->layout,
|
||||
* container,
|
||||
* actor);
|
||||
*
|
||||
* clutter_actor_queue_relayout (CLUTTER_ACTOR (self));
|
||||
*
|
||||
* g_signal_emit_by_name (container, "actor-removed");
|
||||
*
|
||||
* g_object_unref (actor);
|
||||
* }
|
||||
* ]|
|
||||
*
|
||||
* See also clutter_layout_manager_add_child_meta()
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_remove_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor)
|
||||
{
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
|
||||
if (get_child_meta (manager, container, actor))
|
||||
g_object_set_qdata (G_OBJECT (actor), quark_layout_meta, NULL);
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
layout_set_property_internal (ClutterLayoutManager *manager,
|
||||
GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
const GValue *value)
|
||||
{
|
||||
if (pspec->flags & G_PARAM_CONSTRUCT_ONLY)
|
||||
{
|
||||
g_warning ("%s: Child property '%s' of the layout manager of "
|
||||
"type '%s' is constructor-only",
|
||||
G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(pspec->flags & G_PARAM_WRITABLE))
|
||||
{
|
||||
g_warning ("%s: Child property '%s' of the layout manager of "
|
||||
"type '%s' is not writable",
|
||||
G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_set_property (gobject, pspec->name, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static inline gboolean
|
||||
layout_get_property_internal (ClutterLayoutManager *manager,
|
||||
GObject *gobject,
|
||||
GParamSpec *pspec,
|
||||
GValue *value)
|
||||
{
|
||||
if (!(pspec->flags & G_PARAM_READABLE))
|
||||
{
|
||||
g_warning ("%s: Child property '%s' of the layout manager of "
|
||||
"type '%s' is not readable",
|
||||
G_STRLOC, pspec->name, G_OBJECT_TYPE_NAME (manager));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_object_get_property (gobject, pspec->name, value);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_child_set:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
* @first_property: the first property name
|
||||
* @Varargs: a list of property name and value pairs
|
||||
*
|
||||
* Sets a list of properties and their values on the #ClutterLayoutMeta
|
||||
* associated by @manager to a child of @container
|
||||
*
|
||||
* Languages bindings should use clutter_layout_manager_child_set_property()
|
||||
* instead
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_child_set (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
const gchar *pname;
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (first_property != NULL);
|
||||
|
||||
meta = get_child_meta (manager, container, actor);
|
||||
if (meta == NULL)
|
||||
{
|
||||
g_warning ("Layout managers of type '%s' do not support "
|
||||
"child metadata",
|
||||
g_type_name (G_OBJECT_TYPE (manager)));
|
||||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
va_start (var_args, first_property);
|
||||
|
||||
pname = first_property;
|
||||
while (pname)
|
||||
{
|
||||
GValue value = { 0, };
|
||||
GParamSpec *pspec;
|
||||
gchar *error;
|
||||
gboolean res;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: Layout managers of type '%s' have no child "
|
||||
"property named '%s'",
|
||||
G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname);
|
||||
break;
|
||||
}
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
G_VALUE_COLLECT (&value, var_args, 0, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
break;
|
||||
}
|
||||
|
||||
res = layout_set_property_internal (manager, G_OBJECT (meta),
|
||||
pspec,
|
||||
&value);
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
if (!res)
|
||||
break;
|
||||
|
||||
pname = va_arg (var_args, gchar*);
|
||||
}
|
||||
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_child_set_property:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
* @property_name: the name of the property to set
|
||||
* @value: a #GValue with the value of the property to set
|
||||
*
|
||||
* Sets a property on the #ClutterLayoutMeta created by @manager and
|
||||
* attached to a child of @container
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_child_set_property (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *property_name,
|
||||
const GValue *value)
|
||||
{
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
g_return_if_fail (value != NULL);
|
||||
|
||||
meta = get_child_meta (manager, container, actor);
|
||||
if (meta == NULL)
|
||||
{
|
||||
g_warning ("Layout managers of type '%s' do not support "
|
||||
"child metadata",
|
||||
g_type_name (G_OBJECT_TYPE (manager)));
|
||||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
pspec = g_object_class_find_property (klass, property_name);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: Layout managers of type '%s' have no child "
|
||||
"property named '%s'",
|
||||
G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name);
|
||||
return;
|
||||
}
|
||||
|
||||
layout_set_property_internal (manager, G_OBJECT (meta), pspec, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_child_get:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
* @first_property: the name of the first property
|
||||
* @Varargs: a list of property name and return location for the value pairs
|
||||
*
|
||||
* Retrieves the values for a list of properties out of the
|
||||
* #ClutterLayoutMeta created by @manager and attached to the
|
||||
* child of a @container
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_child_get (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...)
|
||||
{
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
const gchar *pname;
|
||||
va_list var_args;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (first_property != NULL);
|
||||
|
||||
meta = get_child_meta (manager, container, actor);
|
||||
if (meta == NULL)
|
||||
{
|
||||
g_warning ("Layout managers of type '%s' do not support "
|
||||
"child metadata",
|
||||
g_type_name (G_OBJECT_TYPE (manager)));
|
||||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
va_start (var_args, first_property);
|
||||
|
||||
pname = first_property;
|
||||
while (pname)
|
||||
{
|
||||
GValue value = { 0, };
|
||||
GParamSpec *pspec;
|
||||
gchar *error;
|
||||
gboolean res;
|
||||
|
||||
pspec = g_object_class_find_property (klass, pname);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: Layout managers of type '%s' have no child "
|
||||
"property named '%s'",
|
||||
G_STRLOC, G_OBJECT_TYPE_NAME (manager), pname);
|
||||
break;
|
||||
}
|
||||
|
||||
g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
|
||||
|
||||
res = layout_get_property_internal (manager, G_OBJECT (meta),
|
||||
pspec,
|
||||
&value);
|
||||
if (!res)
|
||||
{
|
||||
g_value_unset (&value);
|
||||
break;
|
||||
}
|
||||
|
||||
G_VALUE_LCOPY (&value, var_args, 0, &error);
|
||||
if (error)
|
||||
{
|
||||
g_warning ("%s: %s", G_STRLOC, error);
|
||||
g_free (error);
|
||||
g_value_unset (&value);
|
||||
break;
|
||||
}
|
||||
|
||||
g_value_unset (&value);
|
||||
|
||||
pname = va_arg (var_args, gchar*);
|
||||
}
|
||||
|
||||
va_end (var_args);
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_manager_child_get_property:
|
||||
* @manager: a #ClutterLayoutManager
|
||||
* @container: a #ClutterContainer using @manager
|
||||
* @actor: a #ClutterActor child of @container
|
||||
* @property_name: the name of the property to get
|
||||
* @value: a #GValue with the value of the property to get
|
||||
*
|
||||
* Gets a property on the #ClutterLayoutMeta created by @manager and
|
||||
* attached to a child of @container
|
||||
*
|
||||
* The #GValue must already be initialized to the type of the property
|
||||
* and has to be unset with g_value_unset() after extracting the real
|
||||
* value out of it
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
void
|
||||
clutter_layout_manager_child_get_property (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *property_name,
|
||||
GValue *value)
|
||||
{
|
||||
ClutterLayoutMeta *meta;
|
||||
GObjectClass *klass;
|
||||
GParamSpec *pspec;
|
||||
|
||||
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
|
||||
g_return_if_fail (CLUTTER_IS_CONTAINER (container));
|
||||
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
|
||||
g_return_if_fail (property_name != NULL);
|
||||
g_return_if_fail (value != NULL);
|
||||
|
||||
meta = get_child_meta (manager, container, actor);
|
||||
if (meta == NULL)
|
||||
{
|
||||
g_warning ("Layout managers of type %s do not support "
|
||||
"child metadata",
|
||||
g_type_name (G_OBJECT_TYPE (manager)));
|
||||
return;
|
||||
}
|
||||
|
||||
klass = G_OBJECT_GET_CLASS (meta);
|
||||
|
||||
pspec = g_object_class_find_property (klass, property_name);
|
||||
if (pspec == NULL)
|
||||
{
|
||||
g_warning ("%s: Layout managers of type '%s' have no child "
|
||||
"property named '%s'",
|
||||
G_STRLOC, G_OBJECT_TYPE_NAME (manager), property_name);
|
||||
return;
|
||||
}
|
||||
|
||||
layout_get_property_internal (manager, G_OBJECT (meta), pspec, value);
|
||||
}
|
187
clutter/clutter-layout-manager.h
Normal file
187
clutter/clutter-layout-manager.h
Normal file
@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_LAYOUT_MANAGER_H__
|
||||
#define __CLUTTER_LAYOUT_MANAGER_H__
|
||||
|
||||
#include <clutter/clutter-actor.h>
|
||||
#include <clutter/clutter-container.h>
|
||||
#include <clutter/clutter-types.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_LAYOUT_MANAGER (clutter_layout_manager_get_type ())
|
||||
#define CLUTTER_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManager))
|
||||
#define CLUTTER_IS_LAYOUT_MANAGER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYOUT_MANAGER))
|
||||
#define CLUTTER_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManagerClass))
|
||||
#define CLUTTER_IS_LAYOUT_MANAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LAYOUT_MANAGER))
|
||||
#define CLUTTER_LAYOUT_MANAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LAYOUT_MANAGER, ClutterLayoutManagerClass))
|
||||
|
||||
typedef struct _ClutterLayoutManager ClutterLayoutManager;
|
||||
typedef struct _ClutterLayoutManagerClass ClutterLayoutManagerClass;
|
||||
|
||||
/**
|
||||
* ClutterLayoutManager:
|
||||
*
|
||||
* The #ClutterLayoutManager structure contains only private data
|
||||
* and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterLayoutManager
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnowned parent_instance;
|
||||
|
||||
/* padding for future expansion */
|
||||
gpointer dummy;
|
||||
};
|
||||
|
||||
/**
|
||||
* ClutterLayoutManagerClass:
|
||||
* @get_preferred_width: virtual function; override to provide a preferred
|
||||
* width for the layout manager. See also the get_preferred_width()
|
||||
* virtual function in #ClutterActor
|
||||
* @get_preferred_height: virtual function; override to provide a preferred
|
||||
* height for the layout manager. See also the get_preferred_height()
|
||||
* virtual function in #ClutterActor
|
||||
* @allocate: virtual function; override to allocate the children of the
|
||||
* layout manager. See also the allocate() virtual function in
|
||||
* #ClutterActor
|
||||
* @set_container: virtual function; override to set a back pointer
|
||||
* on the #ClutterContainer using the layout manager. The implementation
|
||||
* should not take a reference on the container, but just take a weak
|
||||
* reference, to avoid potential leaks due to reference cycles
|
||||
* @create_child_meta: virtual function; override to create a
|
||||
* #ClutterChildMeta instance associated to a #ClutterContainer and a
|
||||
* child #ClutterActor, used to maintain layout manager specific properties
|
||||
* @layout_changed: class handler for the #ClutterLayoutManager::layout-changed
|
||||
* signal
|
||||
*
|
||||
* The #ClutterLayoutManagerClass structure contains only private
|
||||
* data and should be accessed using the provided API
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterLayoutManagerClass
|
||||
{
|
||||
/*< private >*/
|
||||
GInitiallyUnownedClass parent_class;
|
||||
|
||||
/*< public >*/
|
||||
void (* get_preferred_width) (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *minimum_width_p,
|
||||
gfloat *natural_width_p);
|
||||
void (* get_preferred_height) (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *minimum_height_p,
|
||||
gfloat *natural_height_p);
|
||||
void (* allocate) (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags);
|
||||
|
||||
void (* set_container) (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container);
|
||||
|
||||
ClutterLayoutMeta *(* create_child_meta) (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor);
|
||||
|
||||
void (* layout_changed) (ClutterLayoutManager *manager);
|
||||
|
||||
/*< private >*/
|
||||
/* padding for future expansion */
|
||||
void (* _clutter_padding_1) (void);
|
||||
void (* _clutter_padding_2) (void);
|
||||
void (* _clutter_padding_3) (void);
|
||||
void (* _clutter_padding_4) (void);
|
||||
void (* _clutter_padding_5) (void);
|
||||
void (* _clutter_padding_6) (void);
|
||||
void (* _clutter_padding_7) (void);
|
||||
void (* _clutter_padding_8) (void);
|
||||
};
|
||||
|
||||
GType clutter_layout_manager_get_type (void) G_GNUC_CONST;
|
||||
|
||||
void clutter_layout_manager_get_preferred_width (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_height,
|
||||
gfloat *min_width_p,
|
||||
gfloat *nat_width_p);
|
||||
void clutter_layout_manager_get_preferred_height (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
gfloat for_width,
|
||||
gfloat *min_height_p,
|
||||
gfloat *nat_height_p);
|
||||
void clutter_layout_manager_allocate (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags);
|
||||
|
||||
void clutter_layout_manager_set_container (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container);
|
||||
void clutter_layout_manager_layout_changed (ClutterLayoutManager *manager);
|
||||
|
||||
ClutterLayoutMeta *clutter_layout_manager_get_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor);
|
||||
void clutter_layout_manager_add_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor);
|
||||
void clutter_layout_manager_remove_child_meta (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor);
|
||||
|
||||
void clutter_layout_manager_child_set (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void clutter_layout_manager_child_get (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *first_property,
|
||||
...) G_GNUC_NULL_TERMINATED;
|
||||
void clutter_layout_manager_child_set_property (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *property_name,
|
||||
const GValue *value);
|
||||
void clutter_layout_manager_child_get_property (ClutterLayoutManager *manager,
|
||||
ClutterContainer *container,
|
||||
ClutterActor *actor,
|
||||
const gchar *property_name,
|
||||
GValue *value);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_LAYOUT_MANAGER_H__ */
|
142
clutter/clutter-layout-meta.c
Normal file
142
clutter/clutter-layout-meta.c
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation.
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
/**
|
||||
* SECTION:clutter-layout-meta
|
||||
* @short_description: Wrapper for actors inside a layout manager
|
||||
*
|
||||
* #ClutterLayoutMeta is a wrapper object created by #ClutterLayoutManager
|
||||
* implementations in order to store child-specific data and properties.
|
||||
*
|
||||
* A #ClutterLayoutMeta wraps a #ClutterActor inside a #ClutterContainer
|
||||
* using a #ClutterLayoutManager.
|
||||
*
|
||||
* #ClutterLayoutMeta is available since Clutter 1.2
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "clutter-layout-meta.h"
|
||||
#include "clutter-debug.h"
|
||||
#include "clutter-private.h"
|
||||
|
||||
G_DEFINE_ABSTRACT_TYPE (ClutterLayoutMeta,
|
||||
clutter_layout_meta,
|
||||
CLUTTER_TYPE_CHILD_META);
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
|
||||
PROP_MANAGER
|
||||
};
|
||||
|
||||
static void
|
||||
clutter_layout_meta_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterLayoutMeta *layout_meta = CLUTTER_LAYOUT_META (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MANAGER:
|
||||
layout_meta->manager = g_value_get_object (value);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layout_meta_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
ClutterLayoutMeta *layout_meta = CLUTTER_LAYOUT_META (object);
|
||||
|
||||
switch (prop_id)
|
||||
{
|
||||
case PROP_MANAGER:
|
||||
g_value_set_object (value, layout_meta->manager);
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layout_meta_class_init (ClutterLayoutMetaClass *klass)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
||||
GParamSpec *pspec;
|
||||
|
||||
gobject_class->set_property = clutter_layout_meta_set_property;
|
||||
gobject_class->get_property = clutter_layout_meta_get_property;
|
||||
|
||||
/**
|
||||
* ClutterLayoutMeta:manager:
|
||||
*
|
||||
* The #ClutterLayoutManager that created this #ClutterLayoutMeta.
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
pspec = g_param_spec_object ("manager",
|
||||
"Manager",
|
||||
"The manager that created this data",
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER,
|
||||
G_PARAM_CONSTRUCT_ONLY |
|
||||
CLUTTER_PARAM_READWRITE);
|
||||
g_object_class_install_property (gobject_class, PROP_MANAGER, pspec);
|
||||
}
|
||||
|
||||
static void
|
||||
clutter_layout_meta_init (ClutterLayoutMeta *self)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* clutter_layout_meta_get_manager:
|
||||
* @data: a #ClutterLayoutMeta
|
||||
*
|
||||
* Retrieves the actor wrapped by @data
|
||||
*
|
||||
* Return value: (transfer none): a #ClutterLayoutManager
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
ClutterLayoutManager *
|
||||
clutter_layout_meta_get_manager (ClutterLayoutMeta *data)
|
||||
{
|
||||
g_return_val_if_fail (CLUTTER_IS_LAYOUT_META (data), NULL);
|
||||
|
||||
return data->manager;
|
||||
}
|
85
clutter/clutter-layout-meta.h
Normal file
85
clutter/clutter-layout-meta.h
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Clutter.
|
||||
*
|
||||
* An OpenGL based 'interactive canvas' library.
|
||||
*
|
||||
* Copyright (C) 2009 Intel Corporation
|
||||
*
|
||||
* 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, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Author:
|
||||
* Emmanuele Bassi <ebassi@linux.intel.com>
|
||||
*/
|
||||
|
||||
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
|
||||
#error "Only <clutter/clutter.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#ifndef __CLUTTER_LAYOUT_META_H__
|
||||
#define __CLUTTER_LAYOUT_META_H__
|
||||
|
||||
#include <clutter/clutter-types.h>
|
||||
#include <clutter/clutter-child-meta.h>
|
||||
#include <clutter/clutter-layout-manager.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define CLUTTER_TYPE_LAYOUT_META (clutter_layout_meta_get_type ())
|
||||
#define CLUTTER_LAYOUT_META(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMeta))
|
||||
#define CLUTTER_IS_LAYOUT_META(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CLUTTER_TYPE_LAYOUT_META))
|
||||
#define CLUTTER_LAYOUT_META_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMetaClass))
|
||||
#define CLUTTER_IS_LAYOUT_META_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CLUTTER_TYPE_LAYOUT_META))
|
||||
#define CLUTTER_LAYOUT_META_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CLUTTER_TYPE_LAYOUT_META, ClutterLayoutMetaClass))
|
||||
|
||||
/* ClutterLayoutMeta is defined in clutter-types.h */
|
||||
|
||||
typedef struct _ClutterLayoutMetaClass ClutterLayoutMetaClass;
|
||||
|
||||
/**
|
||||
* ClutterLayoutMeta
|
||||
* @manager: the layout manager handling this data
|
||||
*
|
||||
* Sub-class of #ClutterChildMeta specific for layout managers
|
||||
*
|
||||
* A #ClutterLayoutManager sub-class should create a #ClutterLayoutMeta
|
||||
* instance by overriding the #ClutterLayoutManager::create_child_meta()
|
||||
* virtual function
|
||||
*
|
||||
* Since: 1.2
|
||||
*/
|
||||
struct _ClutterLayoutMeta
|
||||
{
|
||||
/*< private >*/
|
||||
ClutterChildMeta parent_instance;
|
||||
|
||||
/*< public >*/
|
||||
ClutterLayoutManager *manager;
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer dummy;
|
||||
};
|
||||
|
||||
struct _ClutterLayoutMetaClass
|
||||
{
|
||||
ClutterChildMetaClass parent_class;
|
||||
};
|
||||
|
||||
GType clutter_layout_meta_get_type (void) G_GNUC_CONST;
|
||||
|
||||
ClutterLayoutManager *clutter_layout_meta_get_manager (ClutterLayoutMeta *data);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __CLUTTER_LAYOUT_META_H__ */
|
@ -43,6 +43,7 @@ typedef struct _ClutterActor ClutterActor;
|
||||
typedef struct _ClutterStage ClutterStage;
|
||||
typedef struct _ClutterContainer ClutterContainer; /* dummy */
|
||||
typedef struct _ClutterChildMeta ClutterChildMeta;
|
||||
typedef struct _ClutterLayoutMeta ClutterLayoutMeta;
|
||||
|
||||
/**
|
||||
* ClutterGravity:
|
||||
|
@ -43,6 +43,9 @@
|
||||
#include "clutter-behaviour-rotate.h"
|
||||
#include "clutter-behaviour-scale.h"
|
||||
#include "clutter-binding-pool.h"
|
||||
#include "clutter-bin-layout.h"
|
||||
#include "clutter-box.h"
|
||||
#include "clutter-box-layout.h"
|
||||
#include "clutter-cairo-texture.h"
|
||||
#include "clutter-child-meta.h"
|
||||
#include "clutter-clone.h"
|
||||
@ -50,10 +53,14 @@
|
||||
#include "clutter-container.h"
|
||||
#include "clutter-event.h"
|
||||
#include "clutter-feature.h"
|
||||
#include "clutter-fixed-layout.h"
|
||||
#include "clutter-flow-layout.h"
|
||||
#include "clutter-frame-source.h"
|
||||
#include "clutter-group.h"
|
||||
#include "clutter-interval.h"
|
||||
#include "clutter-keysyms.h"
|
||||
#include "clutter-layout-manager.h"
|
||||
#include "clutter-layout-meta.h"
|
||||
#include "clutter-list-model.h"
|
||||
#include "clutter-main.h"
|
||||
#include "clutter-media.h"
|
||||
|
@ -55,6 +55,8 @@
|
||||
<xi:include href="xml/clutter-container.xml"/>
|
||||
<xi:include href="xml/clutter-child-meta.xml"/>
|
||||
<xi:include href="xml/clutter-media.xml"/>
|
||||
<xi:include href="xml/clutter-layout-manager.xml"/>
|
||||
<xi:include href="xml/clutter-layout-meta.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
@ -71,6 +73,16 @@
|
||||
|
||||
<xi:include href="xml/clutter-group.xml"/>
|
||||
<xi:include href="xml/clutter-stage.xml"/>
|
||||
<xi:include href="xml/clutter-box.xml"/>
|
||||
</chapter>
|
||||
|
||||
<chapter>
|
||||
<title>Layout managers</title>
|
||||
|
||||
<xi:include href="xml/clutter-fixed-layout.xml"/>
|
||||
<xi:include href="xml/clutter-bin-layout.xml"/>
|
||||
<xi:include href="xml/clutter-flow-layout.xml"/>
|
||||
<xi:include href="xml/clutter-box-layout.xml"/>
|
||||
</chapter>
|
||||
|
||||
</part>
|
||||
@ -198,13 +210,13 @@
|
||||
<chapter id="clutterobjecthierarchy">
|
||||
<title>Object Hierarchy</title>
|
||||
|
||||
<xi:include href="xml/tree_index.sgml"/>
|
||||
<xi:include href="xml/tree_index.sgml"><xi:fallback /></xi:include>
|
||||
</chapter>
|
||||
|
||||
<chapter id="clutterobjectindex">
|
||||
<title>Object Index</title>
|
||||
|
||||
<xi:include href="xml/object_index.sgml"/>
|
||||
<xi:include href="xml/object_index.sgml"><xi:fallback /></xi:include>
|
||||
</chapter>
|
||||
</part>
|
||||
|
||||
|
@ -305,6 +305,8 @@ clutter_actor_get_preferred_width
|
||||
clutter_actor_get_preferred_height
|
||||
clutter_actor_set_fixed_position_set
|
||||
clutter_actor_get_fixed_position_set
|
||||
clutter_actor_set_request_mode
|
||||
clutter_actor_get_request_mode
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_actor_set_geometry
|
||||
@ -1726,3 +1728,195 @@ CLUTTER_STAGE_MANAGER_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
clutter_stage_manager_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>Layout Managers</TITLE>
|
||||
<FILE>clutter-layout-manager</FILE>
|
||||
ClutterLayoutManager
|
||||
ClutterLayoutManagerClass
|
||||
clutter_layout_manager_get_preferred_width
|
||||
clutter_layout_manager_get_preferred_height
|
||||
clutter_layout_manager_allocate
|
||||
clutter_layout_manager_layout_changed
|
||||
clutter_layout_manager_set_container
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_layout_manager_add_child_meta
|
||||
clutter_layout_manager_remove_child_meta
|
||||
clutter_layout_manager_get_child_meta
|
||||
clutter_layout_manager_child_set
|
||||
clutter_layout_manager_child_set_property
|
||||
clutter_layout_manager_child_get
|
||||
clutter_layout_manager_child_get_property
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_LAYOUT_MANAGER
|
||||
CLUTTER_LAYOUT_MANAGER
|
||||
CLUTTER_LAYOUT_MANAGER_CLASS
|
||||
CLUTTER_IS_LAYOUT_MANAGER
|
||||
CLUTTER_IS_LAYOUT_MANAGER_CLASS
|
||||
CLUTTER_LAYOUT_MANAGER_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
clutter_layout_manager_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>ClutterFixedLayout</TITLE>
|
||||
<FILE>clutter-fixed-layout</FILE>
|
||||
ClutterFixedLayout
|
||||
ClutterFixedLayoutClass
|
||||
clutter_fixed_layout_new
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_FIXED_LAYOUT
|
||||
CLUTTER_FIXED_LAYOUT
|
||||
CLUTTER_FIXED_LAYOUT_CLASS
|
||||
CLUTTER_IS_FIXED_LAYOUT
|
||||
CLUTTER_IS_FIXED_LAYOUT_CLASS
|
||||
CLUTTER_FIXED_LAYOUT_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
clutter_fixed_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>ClutterBinLayout</TITLE>
|
||||
<FILE>clutter-bin-layout</FILE>
|
||||
ClutterBinAlignment
|
||||
ClutterBinLayout
|
||||
ClutterBinLayoutClass
|
||||
clutter_bin_layout_new
|
||||
clutter_bin_layout_set_alignment
|
||||
clutter_bin_layout_get_alignment
|
||||
clutter_bin_layout_add
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_BIN_LAYOUT
|
||||
CLUTTER_BIN_LAYOUT
|
||||
CLUTTER_BIN_LAYOUT_CLASS
|
||||
CLUTTER_IS_BIN_LAYOUT
|
||||
CLUTTER_IS_BIN_LAYOUT_CLASS
|
||||
CLUTTER_BIN_LAYOUT_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
ClutterBinLayoutPrivate
|
||||
clutter_bin_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>ClutterBox</TITLE>
|
||||
<FILE>clutter-box</FILE>
|
||||
ClutterBox
|
||||
ClutterBoxClass
|
||||
clutter_box_new
|
||||
clutter_box_set_layout_manager
|
||||
clutter_box_get_layout_manager
|
||||
clutter_box_set_color
|
||||
clutter_box_get_color
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_box_pack
|
||||
clutter_box_packv
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_BOX
|
||||
CLUTTER_BOX
|
||||
CLUTTER_BOX_CLASS
|
||||
CLUTTER_IS_BOX
|
||||
CLUTTER_IS_BOX_CLASS
|
||||
CLUTTER_BOX_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
ClutterBoxPrivate
|
||||
clutter_box_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>ClutterLayoutMeta</TITLE>
|
||||
<FILE>clutter-layout-meta</FILE>
|
||||
ClutterLayoutMeta
|
||||
ClutterLayoutMetaClass
|
||||
clutter_layout_meta_get_manager
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_LAYOUT_META
|
||||
CLUTTER_LAYOUT_META
|
||||
CLUTTER_LAYOUT_META_CLASS
|
||||
CLUTTER_IS_LAYOUT_META
|
||||
CLUTTER_IS_LAYOUT_META_CLASS
|
||||
CLUTTER_LAYOUT_META_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
clutter_layout_meta_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<FILE>clutter-flow-layout</FILE>
|
||||
<TITLE>ClutterFlowLayout</TITLE>
|
||||
ClutterFlowOrientation
|
||||
ClutterFlowLayout
|
||||
ClutterFlowLayoutClass
|
||||
clutter_flow_layout_new
|
||||
clutter_flow_layout_set_orientation
|
||||
clutter_flow_layout_get_orientation
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_flow_layout_set_column_spacing
|
||||
clutter_flow_layout_get_column_spacing
|
||||
clutter_flow_layout_set_row_spacing
|
||||
clutter_flow_layout_get_row_spacing
|
||||
clutter_flow_layout_set_column_width
|
||||
clutter_flow_layout_get_column_width
|
||||
clutter_flow_layout_set_row_height
|
||||
clutter_flow_layout_get_row_height
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_FLOW_LAYOUT
|
||||
CLUTTER_FLOW_LAYOUT
|
||||
CLUTTER_FLOW_LAYOUT_CLASS
|
||||
CLUTTER_IS_FLOW_LAYOUT
|
||||
CLUTTER_IS_FLOW_LAYOUT_CLASS
|
||||
CLUTTER_FLOW_LAYOUT_GET_CLASS
|
||||
<SUBSECTION Private>
|
||||
ClutterFlowLayoutPrivate
|
||||
clutter_flow_layout_get_type
|
||||
</SECTION>
|
||||
|
||||
<SECTION>
|
||||
<TITLE>ClutterBoxLayout</TITLE>
|
||||
<FILE>clutter-box-layout</FILE>
|
||||
ClutterBoxAlignment
|
||||
ClutterBoxLayout
|
||||
ClutterBoxLayoutClass
|
||||
clutter_box_layout_new
|
||||
clutter_box_layout_set_pack_start
|
||||
clutter_box_layout_get_pack_start
|
||||
clutter_box_layout_set_spacing
|
||||
clutter_box_layout_get_spacing
|
||||
clutter_box_layout_set_vertical
|
||||
clutter_box_layout_get_vertical
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_box_layout_pack
|
||||
|
||||
<SUBSECTION>
|
||||
clutter_box_layout_set_alignment
|
||||
clutter_box_layout_get_alignment
|
||||
clutter_box_layout_set_expand
|
||||
clutter_box_layout_get_expand
|
||||
clutter_box_layout_set_fill
|
||||
clutter_box_layout_get_fill
|
||||
|
||||
<SUBSECTION Standard>
|
||||
CLUTTER_TYPE_BOX_LAYOUT
|
||||
CLUTTER_BOX_LAYOUT
|
||||
CLUTTER_BOX_LAYOUT_CLASS
|
||||
CLUTTER_IS_BOX_LAYOUT
|
||||
CLUTTER_IS_BOX_LAYOUT_CLASS
|
||||
CLUTTER_BOX_LAYOUT_GET_CLASS
|
||||
|
||||
<SUBSECTION Private>
|
||||
ClutterBoxLayoutPrivate
|
||||
clutter_box_layout_get_type
|
||||
</SECTION>
|
||||
|
@ -33,3 +33,10 @@ clutter_animation_get_type
|
||||
clutter_interval_get_type
|
||||
clutter_stage_manager_get_type
|
||||
clutter_binding_pool_get_type
|
||||
clutter_box_get_type
|
||||
clutter_layout_manager_get_type
|
||||
clutter_layout_meta_get_type
|
||||
clutter_fixed_layout_get_type
|
||||
clutter_bin_layout_get_type
|
||||
clutter_flow_layout_get_type
|
||||
clutter_box_layout_get_type
|
||||
|
@ -43,7 +43,10 @@ UNIT_TESTS = \
|
||||
test-text.c \
|
||||
test-text-field.c \
|
||||
test-clutter-cairo-flowers.c \
|
||||
test-cogl-vertex-buffer.c
|
||||
test-cogl-vertex-buffer.c \
|
||||
test-bin-layout.c \
|
||||
test-flow-layout.c \
|
||||
test-box-layout.c
|
||||
|
||||
if X11_TESTS
|
||||
UNIT_TESTS += test-pixmap.c
|
||||
|
185
tests/interactive/test-bin-layout.c
Normal file
185
tests/interactive/test-bin-layout.c
Normal file
@ -0,0 +1,185 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <cairo/cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static ClutterActor *
|
||||
make_background (const ClutterColor *color,
|
||||
gfloat width,
|
||||
gfloat height)
|
||||
{
|
||||
ClutterActor *tex = clutter_cairo_texture_new (width, height);
|
||||
cairo_t *cr = clutter_cairo_texture_create (CLUTTER_CAIRO_TEXTURE (tex));
|
||||
cairo_pattern_t *pat;
|
||||
gfloat x, y;
|
||||
|
||||
#define BG_ROUND_RADIUS 12
|
||||
|
||||
x = y = 0;
|
||||
|
||||
cairo_move_to (cr, BG_ROUND_RADIUS, y);
|
||||
cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
|
||||
cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
|
||||
cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
|
||||
cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
|
||||
cairo_line_to (cr, BG_ROUND_RADIUS, height);
|
||||
cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
|
||||
cairo_line_to (cr, x, BG_ROUND_RADIUS);
|
||||
cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);
|
||||
|
||||
cairo_close_path (cr);
|
||||
|
||||
clutter_cairo_set_source_color (cr, color);
|
||||
cairo_stroke (cr);
|
||||
|
||||
x += 4;
|
||||
y += 4;
|
||||
width -= 4;
|
||||
height -= 4;
|
||||
|
||||
cairo_move_to (cr, BG_ROUND_RADIUS, y);
|
||||
cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
|
||||
cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
|
||||
cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
|
||||
cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
|
||||
cairo_line_to (cr, BG_ROUND_RADIUS, height);
|
||||
cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
|
||||
cairo_line_to (cr, x, BG_ROUND_RADIUS);
|
||||
cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);
|
||||
|
||||
cairo_close_path (cr);
|
||||
|
||||
pat = cairo_pattern_create_linear (0, 0, 0, height);
|
||||
cairo_pattern_add_color_stop_rgba (pat, 1, .85, .85, .85, 1);
|
||||
cairo_pattern_add_color_stop_rgba (pat, .95, 1, 1, 1, 1);
|
||||
cairo_pattern_add_color_stop_rgba (pat, .05, 1, 1, 1, 1);
|
||||
cairo_pattern_add_color_stop_rgba (pat, 0, .85, .85, .85, 1);
|
||||
|
||||
cairo_set_source (cr, pat);
|
||||
cairo_fill (cr);
|
||||
|
||||
cairo_pattern_destroy (pat);
|
||||
cairo_destroy (cr);
|
||||
|
||||
#undef BG_ROUND_RADIUS
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_box_enter (ClutterActor *box,
|
||||
ClutterEvent *event,
|
||||
ClutterActor *emblem)
|
||||
{
|
||||
clutter_actor_animate (emblem, CLUTTER_LINEAR, 150,
|
||||
"opacity", 255,
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
on_box_leave (ClutterActor *box,
|
||||
ClutterEvent *event,
|
||||
ClutterActor *emblem)
|
||||
{
|
||||
clutter_actor_animate (emblem, CLUTTER_LINEAR, 150,
|
||||
"opacity", 0,
|
||||
NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_bin_layout_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *box, *rect;
|
||||
ClutterLayoutManager *layout;
|
||||
ClutterColor stage_color = { 0xe0, 0xf2, 0xfc, 0xff };
|
||||
ClutterColor bg_color = { 0xcc, 0xcc, 0xcc, 0x99 };
|
||||
ClutterColor *color;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Box test");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_actor_set_size (stage, 640, 480);
|
||||
|
||||
layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER);
|
||||
|
||||
box = clutter_box_new (layout);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
|
||||
clutter_actor_set_anchor_point_from_gravity (box, CLUTTER_GRAVITY_CENTER);
|
||||
clutter_actor_set_position (box, 320, 240);
|
||||
clutter_actor_set_reactive (box, TRUE);
|
||||
clutter_actor_set_name (box, "box");
|
||||
|
||||
rect = make_background (&bg_color, 200, 200);
|
||||
|
||||
/* first method: use clutter_box_pack() */
|
||||
clutter_box_pack (CLUTTER_BOX (box), rect,
|
||||
"x-align", CLUTTER_BIN_ALIGNMENT_FILL,
|
||||
"y-align", CLUTTER_BIN_ALIGNMENT_FILL,
|
||||
NULL);
|
||||
|
||||
clutter_actor_lower_bottom (rect);
|
||||
clutter_actor_set_name (rect, "background");
|
||||
|
||||
|
||||
{
|
||||
ClutterActor *tex;
|
||||
GError *error;
|
||||
|
||||
error = NULL;
|
||||
tex = clutter_texture_new_from_file ("redhand.png", &error);
|
||||
if (error)
|
||||
g_error ("Unable to create texture: %s", error->message);
|
||||
|
||||
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (tex), TRUE);
|
||||
|
||||
/* second method: use clutter_bin_layout_add() */
|
||||
clutter_bin_layout_add (CLUTTER_BIN_LAYOUT (layout), tex,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER,
|
||||
CLUTTER_BIN_ALIGNMENT_CENTER);
|
||||
|
||||
clutter_actor_raise (tex, rect);
|
||||
clutter_actor_set_width (tex, 175);
|
||||
clutter_actor_set_name (tex, "texture");
|
||||
}
|
||||
|
||||
color = clutter_color_new (g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
g_random_int_range (0, 255),
|
||||
224);
|
||||
|
||||
rect = clutter_rectangle_new_with_color (color);
|
||||
|
||||
/* third method: container_add() and set_alignment() */
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (box), rect);
|
||||
clutter_bin_layout_set_alignment (CLUTTER_BIN_LAYOUT (layout), rect,
|
||||
CLUTTER_BIN_ALIGNMENT_END,
|
||||
CLUTTER_BIN_ALIGNMENT_END);
|
||||
|
||||
clutter_actor_set_size (rect, 50, 50);
|
||||
clutter_actor_set_opacity (rect, 0);
|
||||
clutter_actor_raise_top (rect);
|
||||
clutter_actor_set_name (rect, "emblem");
|
||||
|
||||
|
||||
g_signal_connect (box,
|
||||
"enter-event", G_CALLBACK (on_box_enter),
|
||||
rect);
|
||||
g_signal_connect (box,
|
||||
"leave-event", G_CALLBACK (on_box_leave),
|
||||
rect);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
clutter_color_free (color);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
207
tests/interactive/test-box-layout.c
Normal file
207
tests/interactive/test-box-layout.c
Normal file
@ -0,0 +1,207 @@
|
||||
/*
|
||||
* Copyright 2009 Intel Corporation.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU Lesser General Public License,
|
||||
* version 2.1, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope 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 program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <gmodule.h>
|
||||
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
static ClutterActor *hover_actor = NULL;
|
||||
|
||||
static void
|
||||
enter_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
ClutterColor color = { 0x00, 0x00, 0x00, 0xff };
|
||||
|
||||
clutter_rectangle_set_border_width (CLUTTER_RECTANGLE (actor), 2);
|
||||
clutter_rectangle_set_border_color (CLUTTER_RECTANGLE (actor), &color);
|
||||
|
||||
hover_actor = actor;
|
||||
}
|
||||
|
||||
static void
|
||||
leave_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
gpointer data)
|
||||
{
|
||||
clutter_rectangle_set_border_width (CLUTTER_RECTANGLE (actor), 0);
|
||||
|
||||
hover_actor = NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
button_release_event (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
ClutterBoxLayout *box)
|
||||
{
|
||||
gboolean xfill, yfill;
|
||||
ClutterBoxAlignment xalign, yalign;
|
||||
gint button;
|
||||
|
||||
button = clutter_event_get_button (event);
|
||||
|
||||
if (button == 1)
|
||||
{
|
||||
clutter_box_layout_get_fill (box, actor, &xfill, &yfill);
|
||||
clutter_box_layout_set_fill (box, actor,
|
||||
xfill ? FALSE : TRUE,
|
||||
yfill ? FALSE : TRUE);
|
||||
}
|
||||
else
|
||||
{
|
||||
clutter_box_layout_get_alignment (box, actor, &xalign, &yalign);
|
||||
|
||||
if (xalign < 2)
|
||||
xalign += 1;
|
||||
else
|
||||
xalign = 0;
|
||||
|
||||
if (yalign < 2)
|
||||
yalign += 1;
|
||||
else
|
||||
yalign = 0;
|
||||
|
||||
clutter_box_layout_set_alignment (box, actor, xalign, yalign);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
add_actor (ClutterBoxLayout *box)
|
||||
{
|
||||
ClutterActor *rect;
|
||||
ClutterColor color = { 0xff, 0xff, 0xff, 255 };
|
||||
static gboolean expand = TRUE;
|
||||
|
||||
clutter_color_from_hls (&color,
|
||||
g_random_double_range (0.0, 360.0),
|
||||
0.5,
|
||||
0.5);
|
||||
|
||||
rect = clutter_rectangle_new_with_color (&color);
|
||||
clutter_actor_set_size (rect, 32, 64);
|
||||
clutter_box_layout_pack (box, rect, expand,
|
||||
FALSE, /* x-fill */
|
||||
FALSE, /* y-fill */
|
||||
CLUTTER_BOX_ALIGNMENT_CENTER,
|
||||
CLUTTER_BOX_ALIGNMENT_CENTER);
|
||||
|
||||
clutter_actor_set_reactive (rect, TRUE);
|
||||
g_signal_connect (rect, "enter-event", G_CALLBACK (enter_event), NULL);
|
||||
g_signal_connect (rect, "leave-event", G_CALLBACK (leave_event), NULL);
|
||||
g_signal_connect (rect, "button-release-event",
|
||||
G_CALLBACK (button_release_event),
|
||||
box);
|
||||
|
||||
expand = !expand;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
key_release_cb (ClutterActor *actor,
|
||||
ClutterEvent *event,
|
||||
ClutterBoxLayout *layout)
|
||||
{
|
||||
gboolean toggle;
|
||||
guint spacing;
|
||||
|
||||
switch (clutter_event_get_key_symbol (event))
|
||||
{
|
||||
case CLUTTER_v:
|
||||
toggle = clutter_box_layout_get_vertical (layout);
|
||||
clutter_box_layout_set_vertical (layout, !toggle);
|
||||
break;
|
||||
|
||||
case CLUTTER_p:
|
||||
toggle = clutter_box_layout_get_pack_start (layout);
|
||||
clutter_box_layout_set_pack_start (layout, !toggle);
|
||||
break;
|
||||
|
||||
case CLUTTER_s:
|
||||
spacing = clutter_box_layout_get_spacing (layout);
|
||||
|
||||
if (spacing > 12)
|
||||
spacing = 0;
|
||||
else
|
||||
spacing++;
|
||||
|
||||
clutter_box_layout_set_spacing (layout, spacing);
|
||||
break;
|
||||
|
||||
case '+':
|
||||
add_actor (layout);
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
stage_size_changed_cb (ClutterActor *stage,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags,
|
||||
ClutterActor *box)
|
||||
{
|
||||
gfloat width, height;
|
||||
|
||||
clutter_actor_box_get_size (allocation, &width, &height);
|
||||
clutter_actor_set_size (box, width - 100, height - 100);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_box_layout_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *box;
|
||||
ClutterLayoutManager *layout;
|
||||
gint i;
|
||||
|
||||
clutter_init (&argc, &argv);
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Box Layout");
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_set_size (stage, 640, 480);
|
||||
|
||||
layout = clutter_box_layout_new ();
|
||||
|
||||
box = clutter_box_new (layout);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
add_actor (CLUTTER_BOX_LAYOUT (layout));
|
||||
|
||||
g_signal_connect (stage, "key-release-event",
|
||||
G_CALLBACK (key_release_cb),
|
||||
layout);
|
||||
g_signal_connect (stage, "allocation-changed",
|
||||
G_CALLBACK (stage_size_changed_cb),
|
||||
box);
|
||||
|
||||
clutter_actor_show (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
171
tests/interactive/test-flow-layout.c
Normal file
171
tests/interactive/test-flow-layout.c
Normal file
@ -0,0 +1,171 @@
|
||||
#include <stdlib.h>
|
||||
#include <gmodule.h>
|
||||
#include <cairo/cairo.h>
|
||||
#include <clutter/clutter.h>
|
||||
|
||||
#define N_RECTS 20
|
||||
|
||||
static gboolean is_homogeneous = FALSE;
|
||||
static gboolean vertical = FALSE;
|
||||
static gboolean random_size = FALSE;
|
||||
|
||||
static gint n_rects = N_RECTS;
|
||||
static gint x_spacing = 0;
|
||||
static gint y_spacing = 0;
|
||||
|
||||
static GOptionEntry entries[] = {
|
||||
{
|
||||
"random-size", 'r',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&random_size,
|
||||
"Randomly size the rectangles", NULL
|
||||
},
|
||||
{
|
||||
"num-rects", 'n',
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&n_rects,
|
||||
"Number of rectangles", "RECTS"
|
||||
},
|
||||
{
|
||||
"vertical", 'v',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&vertical,
|
||||
"Set vertical orientation", NULL
|
||||
},
|
||||
{
|
||||
"homogeneous", 'h',
|
||||
0,
|
||||
G_OPTION_ARG_NONE,
|
||||
&is_homogeneous,
|
||||
"Whether the layout should be homogeneous", NULL
|
||||
},
|
||||
{
|
||||
"x-spacing", 0,
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&x_spacing,
|
||||
"Horizontal spacing between elements", "PX"
|
||||
},
|
||||
{
|
||||
"y-spacing", 0,
|
||||
0,
|
||||
G_OPTION_ARG_INT,
|
||||
&y_spacing,
|
||||
"Vertical spacing between elements", "PX"
|
||||
},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
static void
|
||||
on_stage_resize (ClutterActor *stage,
|
||||
const ClutterActorBox *allocation,
|
||||
ClutterAllocationFlags flags,
|
||||
ClutterActor *box)
|
||||
{
|
||||
gfloat width, height;
|
||||
|
||||
clutter_actor_box_get_size (allocation, &width, &height);
|
||||
|
||||
if (vertical)
|
||||
clutter_actor_set_height (box, height);
|
||||
else
|
||||
clutter_actor_set_width (box, width);
|
||||
}
|
||||
|
||||
G_MODULE_EXPORT int
|
||||
test_flow_layout_main (int argc, char *argv[])
|
||||
{
|
||||
ClutterActor *stage, *box;
|
||||
ClutterLayoutManager *layout;
|
||||
ClutterColor stage_color = { 0xe0, 0xf2, 0xfc, 0xff };
|
||||
ClutterColor box_color = { 255, 255, 255, 255 };
|
||||
GError *error;
|
||||
gint i;
|
||||
|
||||
error = NULL;
|
||||
clutter_init_with_args (&argc, &argv,
|
||||
NULL,
|
||||
entries,
|
||||
NULL,
|
||||
&error);
|
||||
if (error)
|
||||
{
|
||||
g_print ("Unable to run test-flow: %s", error->message);
|
||||
g_error_free (error);
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
stage = clutter_stage_get_default ();
|
||||
clutter_stage_set_title (CLUTTER_STAGE (stage), "Flow Layout");
|
||||
clutter_stage_set_color (CLUTTER_STAGE (stage), &stage_color);
|
||||
clutter_stage_set_user_resizable (CLUTTER_STAGE (stage), TRUE);
|
||||
clutter_actor_set_size (stage, 640, 480);
|
||||
|
||||
layout = clutter_flow_layout_new (vertical ? CLUTTER_FLOW_VERTICAL
|
||||
: CLUTTER_FLOW_HORIZONTAL);
|
||||
clutter_flow_layout_set_homogeneous (CLUTTER_FLOW_LAYOUT (layout),
|
||||
is_homogeneous);
|
||||
clutter_flow_layout_set_column_spacing (CLUTTER_FLOW_LAYOUT (layout),
|
||||
x_spacing);
|
||||
clutter_flow_layout_set_row_spacing (CLUTTER_FLOW_LAYOUT (layout),
|
||||
y_spacing);
|
||||
|
||||
box = clutter_box_new (layout);
|
||||
clutter_box_set_color (CLUTTER_BOX (box), &box_color);
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (stage), box);
|
||||
clutter_actor_set_position (box, 0, 0);
|
||||
|
||||
if (vertical)
|
||||
clutter_actor_set_height (box, 480);
|
||||
else
|
||||
clutter_actor_set_width (box, 640);
|
||||
|
||||
clutter_actor_set_name (box, "box");
|
||||
|
||||
for (i = 0; i < n_rects; i++)
|
||||
{
|
||||
ClutterColor color = { 255, 255, 255, 224 };
|
||||
ClutterActor *rect;
|
||||
gchar *name;
|
||||
gfloat width, height;
|
||||
|
||||
name = g_strdup_printf ("rect%02d", i);
|
||||
|
||||
clutter_color_from_hls (&color,
|
||||
360.0 / n_rects * i,
|
||||
0.5,
|
||||
0.8);
|
||||
rect = clutter_rectangle_new_with_color (&color);
|
||||
|
||||
clutter_container_add_actor (CLUTTER_CONTAINER (box), rect);
|
||||
|
||||
if (random_size)
|
||||
{
|
||||
width = g_random_int_range (50, 100);
|
||||
height = g_random_int_range (50, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
width = height = 50;
|
||||
}
|
||||
|
||||
clutter_actor_set_size (rect, width, height);
|
||||
clutter_actor_set_name (rect, name);
|
||||
|
||||
g_free (name);
|
||||
}
|
||||
|
||||
g_signal_connect (stage,
|
||||
"allocation-changed", G_CALLBACK (on_stage_resize),
|
||||
box);
|
||||
|
||||
clutter_actor_show_all (stage);
|
||||
|
||||
clutter_main ();
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
Loading…
Reference in New Issue
Block a user