Merge branch 'animate-layout-manager' into ebassi-next

* animate-layout-manager:
  layout-manager: Document the animation support
  layout-manager: Rewind the timeline in begin_animation()
  box-layout: Remove the allocations hash table
  docs: Clean up the README file
  layout: Let begin_animation() return the Alpha
  box-layout: Add knobs for controlling animations
  box-layout: Animate layout properties
  layout: Add animation support to LayoutManager
  Add ActorBox animation methods
This commit is contained in:
Emmanuele Bassi 2009-12-23 10:38:02 +00:00
commit 3d350078a8
9 changed files with 1020 additions and 161 deletions

137
README
View File

@ -1,5 +1,5 @@
Clutter 1.2 README
==================
Clutter - README
===============================================================================
Clutter is an open source software library for creating fast, visually
rich and animated graphical user interfaces.
@ -22,7 +22,6 @@ If you are building the Introspection data you will also need:
• GObject-Introspection >= 0.6.4
The official website is:
http://www.clutter-project.org
@ -42,85 +41,115 @@ Clutter is licensed under the terms of the GNU Lesser General Public
License, version 2.1 or (at your option) later.
INSTALLATION
============
===============================================================================
See the INSTALL file. Info on specific Clutter options;
--enable-debug=[no/minimum/yes]
Controls Clutter debugging level (default=yes):
yes: All glib asserts, checks and runtime clutter verbose messages.
minimum: Just glib cast checks and runtime clutter verbose messagaes.
no: No glib asserts or checks and no runtime clutter verbose messages
(Only really of use in extreme performance cases)
Controls Clutter debugging level:
yes:
All GLib asserts, checks and support for runtime Clutter
debugging notes through CLUTTER_DEBUG. This is the default
value for snapshots.
minimum:
Just GType cast checks and support for runtime Clutter
debugging notes through CLUTTER_DEBUG. This is the default
for stable releases.
no:
No GLib asserts or checks and no support for runtime Clutter
debugging notes. Only use in extreme performance and/or size
optimization cases.
--enable-cogl-debug=[no/minimum/yes]
Controls COGL debugging level (default=minimum):
yes: All runtime verbose messages and error checking for each GL
primitive
minimum: All runtime verbose messages
no: No error checking and no messages
yes:
Support for COGL debugging notes through COGL_DEBUG and
error checking for each GL primitive.
minimum:
Support for COGL debugging notes through COGL_DEBUG. This is
the default for snapshots.
no:
Disable support for COGL runtime debugging notes. This is
the default for stable releases.
--enable-maintainer-flags=[no/yes]
Use strict compiler flags (default=no)
Use strict compiler flags. This defaults to 'yes' for snapshots and
to 'no' for stable releases.
--enable-gtk-doc
use gtk-doc to build API documentation (default=no). Requires gtk-doc
present on system
present on the target system.
--enable-manual=[no/yes]
Build application developers manual. Requires jw and xmlto binaries.
Presently incomplete.
--enable-docs=[no/yes]
Build additional documentation. Requires xsltproc for DocBook
conversion, and optionally jw for PDF generation.
--with-flavour=[glx/eglx/eglnative/sdl/osx/win32/fruity]
--with-flavour=[glx/eglx/eglnative/sdl/osx/win32/fruity]
Select the Clutter backend: (default=glx)
glx: Fully featured GLX backend. Using Open GL.
glx:
Fully featured GLX backend. Using Open GL.
eglx: EGL/Open GL ES backend for EGL on X windows implementations
eglx:
EGL/Open GL ES backend for EGL on X windows implementations
eglnative:
eglnative:
EGL/Open GL ES backend on 'native windowing system' - i.e
raw framebuffer. Expects the EGL implementation to provide
a createNativeWindow() call. Also it optionally supports
tslib for touchscreen events.
sdl: Basic SDL backend, using Open GL. Should provide portability
sdl:
Basic SDL backend, using Open GL. Should provide portability
to Windows and possibly other OS's. (DEPRECATED)
osx: OS X backend. (EXPERIMENTAL)
osx:
OS X backend. (EXPERIMENTAL)
win32:
win32:
Microsoft Windows(tm) WGL backend
fruity:
fruity:
Apple iPod Touch(tm)/iPhone(tm) backend (EXPERIMENTAL)
--with-imagebackend=[gdk-pixbuf/quartz/internal]
--with-imagebackend=[gdk-pixbuf/quartz/internal]
Select the image loading backend used by COGL
gdk-pixbuf: Depend on gdk-pixbuf-2.0 (default for the glx, eglx,
eglnative, sdl, win32 flavours and recommended)
gdk-pixbuf:
Depend on gdk-pixbuf-2.0 (default for the glx, eglx,
eglnative, sdl, win32 flavours and recommended)
quartz: Depend on CoreGraphics (default for the osx flavour)
quartz:
Depend on CoreGraphics (default for the osx flavour)
internal: Internal JPEG and PNG loader. Should only be used
for testing on new platforms
internal:
Internal JPEG and PNG loader. Should only be used
for testing on new platforms
--with-gles=[1.1/2.0]
--with-gles=[1.1/2.0]
Select the GLES version (for EGL backends) (default=1.1)
--with-json=[internal/check/system]
--with-json=[internal/check/system]
Select the JSON-GLib copy to use (default=check)
internal: Use the internal copy of JSON-GLib for ClutterScript
internal:
Use the internal copy of JSON-GLib for ClutterScript
check: Check for the existence of a system copy of JSON-GLib
and if it is available, make Clutter depend on it
check:
Check for the existence of a system copy of JSON-GLib
and if it is available, make Clutter depend on it
system: Only use the system copy of JSON-GLib
system:
Only use the system copy of JSON-GLib
VERSIONING
==========
===============================================================================
Clutter uses the common "Linux kernel" versioning system, where
even-numbered minor versions are stable and odd-numbered minor
@ -137,7 +166,7 @@ numbers are only used for released archives; odd micro numbers are
only used on the SVN repository.
HACKING
=======
===============================================================================
If you want to hack on and improve Clutter, check the contained TODO
file for pending tasks, the HACKING file for general implementation guidelines,
@ -147,7 +176,7 @@ used throughout Clutter. Remember: the coding style is mandatory; patches
not conforming to it will be rejected.
BUGS
====
===============================================================================
Bugs should be reported to the OpenedHand Bugzilla at:
@ -171,8 +200,8 @@ behaviour.
If the bug exposes a crash, the exact text printed out and a stack trace
obtained using gdb are greatly appreciated.
PATCHES
=======
CONTRIBUTING
===============================================================================
Patches should be submitted using Bugzilla. Patches fixing a bug should be
attached to the bug report; patches for new features or for fixing bugs not
@ -199,13 +228,13 @@ If you do not intend to waive your copyright you should contact the Clutter
development team to arrange a suitable solution.
RELEASE NOTES
=============
===============================================================================
Relevant information for developers with existing Clutter applications
wanting to port to newer releases (See NEWS for general new feature info).
Release Notes for Clutter 1.2
-------------------------------
-------------------------------------------------------------------------------
* ClutterStageManager is now publicly available and documented API.
@ -213,7 +242,7 @@ Release Notes for Clutter 1.2
back to the internal copy only if JSON-GLib is not installed.
Cogl API changes for Clutter 1.2
--------------------------------
-------------------------------------------------------------------------------
* cogl_viewport is now deprecated in favour of cogl_set_viewport which
accepts a viewport offset.
@ -250,7 +279,7 @@ Cogl API changes for Clutter 1.2
Release Notes for Clutter 1.0
-------------------------------
-------------------------------------------------------------------------------
* The clutter_actor_set_shader_param() function now takes a
GValue, which can be set using the clutter_value_set_shader()
@ -365,8 +394,8 @@ Release Notes for Clutter 1.0
takes the duration of the timeline in milliseconds, and thus it replaces
the clutter_timeline_new_for_duration() variant.
Cogl API changes for Clutter 1.0
--------------------------------
Cogl API changes for Clutter 1.0
-------------------------------------------------------------------------------
* All drawing functions now use a source material to determine how geometry is
filled. The source material is set via cogl_set_source. Or the convenience
@ -473,7 +502,7 @@ Release Notes for Clutter 1.0
a corresponding cogl_get_depth_test_enabled function has been added.
Release Notes for Clutter 0.8
-------------------------------
-------------------------------------------------------------------------------
* The COGL GL wrapper API has been completely overhauled and now
contains many new features including new greatly improved texture
@ -639,7 +668,7 @@ Release Notes for Clutter 0.8
* ClutterContainer can have per child custom properties via ClutterChildMeta.
Release Notes for Clutter 0.6
-------------------------------
-------------------------------------------------------------------------------
* Now that every actor has events, the class signal handlers have been
removed from ClutterStageClass and moved into ClutterActorClass.
@ -728,7 +757,7 @@ Release Notes for Clutter 0.6
respectively.
Release Notes for Clutter 0.4.0
-------------------------------
-------------------------------------------------------------------------------
* clutter_actor_show_all does not recurse for groups at least (this is to
match the original group_show_all behaviour). This is like 0.3 but was
@ -747,7 +776,7 @@ Release Notes for Clutter 0.4.0
overhauled.
Release Notes for Clutter 0.3.1
-------------------------------
-------------------------------------------------------------------------------
* clutter_actor_apply_transform_to_point() parameters changed to use
ClutterVertices.
@ -758,7 +787,7 @@ Release Notes for Clutter 0.3.1
* Exisiting X11 based egl backend public API calls now prefixed eglx.
Release Notes for Clutter 0.3
-----------------------------
-------------------------------------------------------------------------------
* ClutterTexture changes:
+ clutter_texture_set_pixbuf() now takes a GError paremeter.

View File

@ -8454,6 +8454,53 @@ clutter_actor_box_from_vertices (ClutterActorBox *box,
box->y2 = y_2;
}
/**
* clutter_actor_box_interpolate:
* @initial: the initial #ClutterActorBox
* @final: the final #ClutterActorBox
* @progress: the interpolation progress
* @result: (out): return location for the interpolation
*
* Interpolates between @initial and @final #ClutterActorBox<!-- -->es
* using @progress
*
* Since: 1.2
*/
void
clutter_actor_box_interpolate (const ClutterActorBox *initial,
const ClutterActorBox *final,
gdouble progress,
ClutterActorBox *result)
{
g_return_if_fail (initial != NULL);
g_return_if_fail (final != NULL);
g_return_if_fail (result != NULL);
result->x1 = initial->x1 + (final->x1 - initial->x1) * progress;
result->y1 = initial->y1 + (final->y1 - initial->y1) * progress;
result->x2 = initial->x2 + (final->x2 - initial->x2) * progress;
result->y2 = initial->y2 + (final->y2 - initial->y2) * progress;
}
/**
* clutter_actor_box_clamp_to_pixel:
* @box: (inout): the #ClutterActorBox to clamp
*
* Clamps the components of @box to the nearest integer
*
* Since: 1.2
*/
void
clutter_actor_box_clamp_to_pixel (ClutterActorBox *box)
{
g_return_if_fail (box != NULL);
box->x1 = floorf (box->x1 + 0.5);
box->y1 = floorf (box->y1 + 0.5);
box->x2 = floorf (box->x2 + 0.5);
box->y2 = floorf (box->y2 + 0.5);
}
/******************************************************************************/
struct _ShaderData

View File

@ -94,8 +94,13 @@ struct _ClutterBoxLayoutPrivate
guint spacing;
guint is_vertical : 1;
guint is_pack_start : 1;
gulong easing_mode;
guint easing_duration;
guint is_vertical : 1;
guint is_pack_start : 1;
guint is_animating : 1;
guint use_animations : 1;
};
struct _ClutterBoxChild
@ -109,6 +114,11 @@ struct _ClutterBoxChild
guint y_fill : 1;
guint expand : 1;
/* the last stable allocation before an animation; it is
* used as the initial ActorBox when interpolating
*/
ClutterActorBox *last_allocation;
};
enum
@ -128,7 +138,10 @@ enum
PROP_SPACING,
PROP_VERTICAL,
PROP_PACK_START
PROP_PACK_START,
PROP_USE_ANIMATIONS,
PROP_EASING_MODE,
PROP_EASING_DURATION
};
G_DEFINE_TYPE (ClutterBoxChild,
@ -167,9 +180,19 @@ box_child_set_align (ClutterBoxChild *self,
if (x_changed || y_changed)
{
ClutterLayoutManager *layout;
ClutterBoxLayout *box;
layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
clutter_layout_manager_layout_changed (layout);
box = CLUTTER_BOX_LAYOUT (layout);
if (box->priv->use_animations)
{
clutter_layout_manager_begin_animation (layout,
box->priv->easing_duration,
box->priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (layout);
if (x_changed)
g_object_notify (G_OBJECT (self), "x-align");
@ -203,9 +226,19 @@ box_child_set_fill (ClutterBoxChild *self,
if (x_changed || y_changed)
{
ClutterLayoutManager *layout;
ClutterBoxLayout *box;
layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
clutter_layout_manager_layout_changed (layout);
box = CLUTTER_BOX_LAYOUT (layout);
if (box->priv->use_animations)
{
clutter_layout_manager_begin_animation (layout,
box->priv->easing_duration,
box->priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (layout);
if (x_changed)
g_object_notify (G_OBJECT (self), "x-fill");
@ -222,11 +255,21 @@ box_child_set_expand (ClutterBoxChild *self,
if (self->expand != expand)
{
ClutterLayoutManager *layout;
ClutterBoxLayout *box;
self->expand = expand;
layout = clutter_layout_meta_get_manager (CLUTTER_LAYOUT_META (self));
clutter_layout_manager_layout_changed (layout);
box = CLUTTER_BOX_LAYOUT (layout);
if (box->priv->use_animations)
{
clutter_layout_manager_begin_animation (layout,
box->priv->easing_duration,
box->priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (layout);
g_object_notify (G_OBJECT (self), "expand");
}
@ -312,6 +355,16 @@ clutter_box_child_get_property (GObject *gobject,
}
}
static void
clutter_box_child_finalize (GObject *gobject)
{
ClutterBoxChild *self = CLUTTER_BOX_CHILD (gobject);
clutter_actor_box_free (self->last_allocation);
G_OBJECT_CLASS (clutter_box_child_parent_class)->finalize (gobject);
}
static void
clutter_box_child_class_init (ClutterBoxChildClass *klass)
{
@ -320,6 +373,7 @@ clutter_box_child_class_init (ClutterBoxChildClass *klass)
gobject_class->set_property = clutter_box_child_set_property;
gobject_class->get_property = clutter_box_child_get_property;
gobject_class->finalize = clutter_box_child_finalize;
pspec = g_param_spec_boolean ("expand",
"Expand",
@ -374,6 +428,8 @@ clutter_box_child_init (ClutterBoxChild *self)
self->x_fill = self->y_fill = FALSE;
self->expand = FALSE;
self->last_allocation = NULL;
}
static inline void
@ -698,14 +754,6 @@ allocate_box_child (ClutterBoxLayout *self,
child_box.x1 = 0;
child_box.x2 = floorf (avail_width + 0.5);
allocate_fill (child, &child_box, box_child);
clutter_actor_allocate (child, &child_box, flags);
if (box_child->expand)
*position += (child_nat + priv->spacing + extra_space);
else
*position += (child_nat + priv->spacing);
}
else
{
@ -721,15 +769,61 @@ allocate_box_child (ClutterBoxLayout *self,
child_box.y1 = 0;
child_box.y2 = floorf (avail_height + 0.5);
allocate_fill (child, &child_box, box_child);
clutter_actor_allocate (child, &child_box, flags);
if (box_child->expand)
*position += (child_nat + priv->spacing + extra_space);
else
*position += (child_nat + priv->spacing);
}
allocate_fill (child, &child_box, box_child);
if (priv->use_animations && priv->is_animating)
{
ClutterLayoutManager *manager = CLUTTER_LAYOUT_MANAGER (self);
ClutterActorBox *start = NULL;
ClutterActorBox end = { 0, };
gdouble p;
p = clutter_layout_manager_get_animation_progress (manager);
start = box_child->last_allocation;
if (start == NULL)
{
/* if there is no allocation available then the child has just
* been added to the container; we put it in the final state
* and store its allocation for later
*/
box_child->last_allocation = clutter_actor_box_copy (&child_box);
goto do_allocate;
}
end = child_box;
/* interpolate between the initial and final values */
clutter_actor_box_interpolate (start, &end, p, &child_box);
CLUTTER_NOTE (ANIMATION,
"Animate { %.1f, %.1f, %.1f, %.1f }\t"
"%.3f * { %.1f, %.1f, %.1f, %.1f }\t"
"-> { %.1f, %.1f, %.1f, %.1f }",
start->x1, start->y1,
start->x2, start->y2,
p,
child_box.x1, child_box.y1,
child_box.x2, child_box.y2,
end.x1, end.y1,
end.x2, end.y2);
}
else
{
/* store the allocation for later animations */
box_child->last_allocation = clutter_actor_box_copy (&child_box);
}
do_allocate:
clutter_actor_allocate (child, &child_box, flags);
if (box_child->expand)
*position += (child_nat + priv->spacing + extra_space);
else
*position += (child_nat + priv->spacing);
}
static void
@ -887,6 +981,35 @@ clutter_box_layout_allocate (ClutterLayoutManager *layout,
g_list_free (children);
}
static ClutterAlpha *
clutter_box_layout_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong easing)
{
ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (manager)->priv;
ClutterLayoutManagerClass *parent_class;
priv->is_animating = TRUE;
/* we want the default implementation */
parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_box_layout_parent_class);
return parent_class->begin_animation (manager, duration, easing);
}
static void
clutter_box_layout_end_animation (ClutterLayoutManager *manager)
{
ClutterBoxLayoutPrivate *priv = CLUTTER_BOX_LAYOUT (manager)->priv;
ClutterLayoutManagerClass *parent_class;
priv->is_animating = FALSE;
/* we want the default implementation */
parent_class = CLUTTER_LAYOUT_MANAGER_CLASS (clutter_box_layout_parent_class);
parent_class->end_animation (manager);
}
static void
clutter_box_layout_set_property (GObject *gobject,
guint prop_id,
@ -909,6 +1032,18 @@ clutter_box_layout_set_property (GObject *gobject,
clutter_box_layout_set_pack_start (self, g_value_get_boolean (value));
break;
case PROP_USE_ANIMATIONS:
clutter_box_layout_set_use_animations (self, g_value_get_boolean (value));
break;
case PROP_EASING_MODE:
clutter_box_layout_set_easing_mode (self, g_value_get_ulong (value));
break;
case PROP_EASING_DURATION:
clutter_box_layout_set_easing_duration (self, g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@ -937,6 +1072,18 @@ clutter_box_layout_get_property (GObject *gobject,
g_value_set_boolean (value, priv->is_pack_start);
break;
case PROP_USE_ANIMATIONS:
g_value_set_boolean (value, priv->use_animations);
break;
case PROP_EASING_MODE:
g_value_set_ulong (value, priv->easing_mode);
break;
case PROP_EASING_DURATION:
g_value_set_uint (value, priv->easing_duration);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
@ -963,6 +1110,8 @@ clutter_box_layout_class_init (ClutterBoxLayoutClass *klass)
layout_class->set_container = clutter_box_layout_set_container;
layout_class->get_child_meta_type =
clutter_box_layout_get_child_meta_type;
layout_class->begin_animation = clutter_box_layout_begin_animation;
layout_class->end_animation = clutter_box_layout_end_animation;
g_type_class_add_private (klass, sizeof (ClutterBoxLayoutPrivate));
@ -1010,6 +1159,62 @@ clutter_box_layout_class_init (ClutterBoxLayoutClass *klass)
0, G_MAXUINT, 0,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_SPACING, pspec);
/**
* ClutterBoxLayout:use-animations:
*
* Whether the #ClutterBoxLayout should animate changes in the
* layout properties
*
* Since: 1.2
*/
pspec = g_param_spec_boolean ("use-animations",
"Use Animations",
"Whether layout changes should be animated",
FALSE,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_USE_ANIMATIONS, pspec);
/**
* ClutterBoxLayout:easing-mode:
*
* The easing mode for the animations, in case
* #ClutterBoxLayout:use-animations is set to %TRUE
*
* The easing mode has the same semantics of #ClutterAnimation:mode: it can
* either be a value from the #ClutterAnimationMode enumeration, like
* %CLUTTER_EASE_OUT_CUBIC, or a logical id as returned by
* clutter_alpha_register_func()
*
* The default value is %CLUTTER_EASE_OUT_CUBIC
*
* Since: 1.2
*/
pspec = g_param_spec_ulong ("easing-mode",
"Easing Mode",
"The easing mode of the animations",
0, G_MAXULONG,
CLUTTER_EASE_OUT_CUBIC,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_EASING_MODE, pspec);
/**
* ClutterBoxLayout:easing-duration:
*
* The duration of the animations, in case #ClutterBoxLayout:use-animations
* is set to %TRUE
*
* The duration is expressed in milliseconds
*
* Since: 1.2
*/
pspec = g_param_spec_uint ("easing-duration",
"Easing Duration",
"The duration of the animations",
0, G_MAXUINT,
500,
CLUTTER_PARAM_READWRITE);
g_object_class_install_property (gobject_class, PROP_EASING_DURATION, pspec);
}
static void
@ -1022,6 +1227,10 @@ clutter_box_layout_init (ClutterBoxLayout *layout)
priv->is_vertical = FALSE;
priv->is_pack_start = FALSE;
priv->spacing = 0;
priv->use_animations = FALSE;
priv->easing_mode = CLUTTER_EASE_OUT_CUBIC;
priv->easing_duration = 500;
}
/**
@ -1065,7 +1274,15 @@ clutter_box_layout_set_spacing (ClutterBoxLayout *layout,
priv->spacing = spacing;
manager = CLUTTER_LAYOUT_MANAGER (layout);
clutter_layout_manager_layout_changed (manager);
if (priv->use_animations)
{
clutter_layout_manager_begin_animation (manager,
priv->easing_duration,
priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (manager);
g_object_notify (G_OBJECT (layout), "spacing");
}
@ -1116,7 +1333,15 @@ clutter_box_layout_set_vertical (ClutterBoxLayout *layout,
priv->is_vertical = vertical ? TRUE : FALSE;
manager = CLUTTER_LAYOUT_MANAGER (layout);
clutter_layout_manager_layout_changed (manager);
if (priv->use_animations)
{
clutter_layout_manager_begin_animation (manager,
priv->easing_duration,
priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (manager);
g_object_notify (G_OBJECT (layout), "vertical");
}
@ -1170,7 +1395,15 @@ clutter_box_layout_set_pack_start (ClutterBoxLayout *layout,
priv->is_pack_start = pack_start ? TRUE : FALSE;
manager = CLUTTER_LAYOUT_MANAGER (layout);
clutter_layout_manager_layout_changed (manager);
if (priv->use_animations)
{
clutter_layout_manager_begin_animation (manager,
priv->easing_duration,
priv->easing_mode);
}
else
clutter_layout_manager_layout_changed (manager);
g_object_notify (G_OBJECT (layout), "pack-start");
}
@ -1574,3 +1807,154 @@ clutter_box_layout_get_expand (ClutterBoxLayout *layout,
return CLUTTER_BOX_CHILD (meta)->expand;
}
/**
* clutter_box_layout_set_use_animations:
* @layout: a #ClutterBoxLayout
* @animate: %TRUE if the @layout should use animations
*
* Sets whether @layout should animate changes in the layout properties
*
* The duration of the animations is controlled by
* clutter_box_layout_set_easing_duration(); the easing mode to be used
* by the animations is controlled by clutter_box_layout_set_easing_mode()
*
* Since: 1.2
*/
void
clutter_box_layout_set_use_animations (ClutterBoxLayout *layout,
gboolean animate)
{
ClutterBoxLayoutPrivate *priv;
g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout));
priv = layout->priv;
if (priv->use_animations != animate)
{
priv->use_animations = animate;
g_object_notify (G_OBJECT (layout), "use-animations");
}
}
/**
* clutter_box_layout_get_use_animations:
* @layout: a #ClutterBoxLayout
*
* Retrieves whether @layout should animate changes in the layout properties
*
* Since clutter_box_layout_set_use_animations()
*
* Return value: %TRUE if the animations should be used, %FALSE otherwise
*
* Since: 1.2
*/
gboolean
clutter_box_layout_get_use_animations (ClutterBoxLayout *layout)
{
g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), FALSE);
return layout->priv->use_animations;
}
/**
* clutter_box_layout_set_easing_mode:
* @layout: a #ClutterBoxLayout
* @mode: an easing mode, either from #ClutterAnimationMode or a logical id
* from clutter_alpha_register_func()
*
* Sets the easing mode to be used by @layout when animating changes in layout
* properties
*
* Use clutter_box_layout_set_use_animations() to enable and disable the
* animations
*
* Since: 1.2
*/
void
clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout,
gulong mode)
{
ClutterBoxLayoutPrivate *priv;
g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout));
priv = layout->priv;
if (priv->easing_mode != mode)
{
priv->easing_mode = mode;
g_object_notify (G_OBJECT (layout), "easing-mode");
}
}
/**
* clutter_box_layout_get_easing_mode:
* @layout: a #ClutterBoxLayout
*
* Retrieves the easing mode set using clutter_box_layout_set_easing_mode()
*
* Return value: an easing mode
*
* Since: 1.2
*/
gulong
clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout)
{
g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout),
CLUTTER_EASE_OUT_CUBIC);
return layout->priv->easing_mode;
}
/**
* clutter_box_layout_set_easing_duration:
* @layout: a #ClutterBoxLayout
* @msecs: the duration of the animations, in milliseconds
*
* Sets the duration of the animations used by @layout when animating changes
* in the layout properties
*
* Use clutter_box_layout_set_use_animations() to enable and disable the
* animations
*
* Since: 1.2
*/
void
clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout,
guint msecs)
{
ClutterBoxLayoutPrivate *priv;
g_return_if_fail (CLUTTER_IS_BOX_LAYOUT (layout));
priv = layout->priv;
if (priv->easing_duration != msecs)
{
priv->easing_duration = msecs;
g_object_notify (G_OBJECT (layout), "easing-duration");
}
}
/**
* clutter_box_layout_get_easing_duration:
* @layout: a #ClutterBoxLayout
*
* Retrieves the duration set using clutter_box_layout_set_easing_duration()
*
* Return value: the duration of the animations, in milliseconds
*
* Since: 1.2
*/
guint
clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout)
{
g_return_val_if_fail (CLUTTER_IS_BOX_LAYOUT (layout), 500);
return layout->priv->easing_duration;
}

View File

@ -97,46 +97,56 @@ struct _ClutterBoxLayoutClass
GType clutter_box_layout_get_type (void) G_GNUC_CONST;
ClutterLayoutManager *clutter_box_layout_new (void);
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_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);
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);
void clutter_box_layout_set_use_animations (ClutterBoxLayout *layout,
gboolean animate);
gboolean clutter_box_layout_get_use_animations (ClutterBoxLayout *layout);
void clutter_box_layout_set_easing_mode (ClutterBoxLayout *layout,
gulong mode);
gulong clutter_box_layout_get_easing_mode (ClutterBoxLayout *layout);
void clutter_box_layout_set_easing_duration (ClutterBoxLayout *layout,
guint msecs);
guint clutter_box_layout_get_easing_duration (ClutterBoxLayout *layout);
G_END_DECLS

View File

@ -36,10 +36,10 @@
* a generic container using #ClutterLayoutManager called #ClutterBox.
*
* Clutter provides some simple #ClutterLayoutManager sub-classes, like
* #ClutterFixedLayout and #ClutterBinLayout.
* #ClutterFlowLayout and #ClutterBinLayout.
*
* <refsect2 id="ClutterLayoutManager-use-in-Actor">
* <title>Using ClutterLayoutManager inside an Actor</title>
* <title>Using a Layout Manager 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()
@ -56,10 +56,10 @@
* 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);
* g_signal_connect_swapped (layout_manager,
* "layout-changed",
* G_CALLBACK (clutter_actor_queue_relayout),
* actor);
* </programlisting></informalexample>
* </refsect2>
*
@ -70,18 +70,20 @@
* #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>The layout manager implementation can hold a back pointer
* to the #ClutterContainer by implementing the
* <function>set_container()</function> virtual function. The layout manager
* should not hold a real reference (i.e. call g_object_ref()) 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>
* function whenever one of these properties changes.</para>
* <para>If the layout manager has layout properties, that is properties that
* should exist only as the result of the presence of a specific (layout
* manager, container actor, child actor) combination, then it should
* override the <structname>ClutterLayoutManager</structname>::get_child_meta_type()
* manager, container actor, child actor) combination, and it wishes to store
* those properties inside a #ClutterLayoutMeta then it should override the
* <structname>ClutterLayoutManager</structname>::get_child_meta_type()
* virtual function to return the #GType of the #ClutterLayoutMeta sub-class
* used to store the layout properties; optionally, the #ClutterLayoutManager
* sub-class might also override the
@ -89,17 +91,17 @@
* function to control how the #ClutterLayoutMeta instance is created,
* otherwise the default implementation will be equivalent to:</para>
* <informalexample><programlisting>
* ClutterLayoutManagerClass *klass;
* GType meta_type;
* ClutterLayoutManagerClass *klass;
* GType meta_type;
*
* klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
* meta_type = klass->get_child_meta_type (manager);
* klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
* meta_type = klass->get_child_meta_type (manager);
*
* return g_object_new (meta_type,
* "manager", manager,
* "container", container,
* "actor", actor,
* NULL);
* return g_object_new (meta_type,
* "manager", manager,
* "container", container,
* "actor", actor,
* NULL);
* </programlisting></informalexample>
* <para>Where <varname>manager</varname> is the #ClutterLayoutManager,
* <varname>container</varname> is the #ClutterContainer using the
@ -107,6 +109,176 @@
* child of the #ClutterContainer.</para>
* </refsect2>
*
* <refsect2 id="ClutterLayoutManager-animation">
* <title>Animating a ClutterLayoutManager</title>
* <para>A layout manager is used to let a #ClutterContainer take complete
* ownership over the layout (that is: the position and sizing) of its
* children; this means that using the Clutter animation API, like
* clutter_actor_animate(), to animate the position and sizing of a child of
* a layout manager it is not going to work properly, as the animation will
* automatically override any setting done by the layout manager
* itself.</para>
* <para>It is possible for a #ClutterLayoutManager sub-class to animate its
* children layout by using the base class animation support. The
* #ClutterLayoutManager animation support consists of three virtual
* functions: <function>begin_animation()</function>,
* <function>get_animation_progress()</function> and
* <function>end_animation()</function>.</para>
* <variablelist>
* <varlistentry>
* <term><function>begin_animation (duration, easing)</function></term>
* <listitem><para>This virtual function is invoked when the layout
* manager should begin an animation. The implementation should set up
* the state for the animation and create the ancillary objects for
* animating the layout. The default implementation creates a
* #ClutterTimeline for the given duration and a #ClutterAlpha binding
* the timeline to the given easing mode. This function returns a
* #ClutterAlpha which should be used to control the animation from
* the caller perspective.</para></listitem>
* </varlistentry>
* <varlistentry>
* <term><function>get_animation_progress()</function></term>
* <listitem><para>This virtual function should be invoked when animating
* a layout manager. It returns the progress of the animation, using the
* same semantics as the #ClutterAlpha:alpha value.</para></listitem>
* </varlistentry>
* <varlistentry>
* <term><function>end_animation()</function></term>
* <listitem><para>This virtual function is invoked when the animation of
* a layout manager ends, and it is meant to be used for bookkeeping the
* objects created in the <function>begin_animation()</function>
* function. The default implementation will call it implicitly when the
* timeline is complete.</para></listitem>
* </varlistentry>
* </variablelist>
* <para>The simplest way to animate a layout is to create a #ClutterTimeline
* inside the <function>begin_animation()</function> virtual function, along
* with a #ClutterAlpha, and for each #ClutterTimeline::new-frame signal
* emission call clutter_layout_manager_layout_changed(), which will cause a
* relayout. The #ClutterTimeline::completed signal emission should cause
* clutter_layout_manager_end_animation() to be called. The default
* implementation provided internally by #ClutterLayoutManager does exactly
* this, so most sub-classes should either not override any animation-related
* virtual function or simply override <function>begin_animation()</function>
* and <function>end_animation()</function> to set up ad hoc state, and then
* chain up to the parent's implementation.</para>
* <example id="example-ClutterLayoutManager-animation">
* <title>Animation of a Layout Manager</title>
* <para>The code below shows how a #ClutterLayoutManager sub-class should
* provide animating the allocation of its children from within the
* <function>allocate()</function> virtual function implementation. The
* animation is computed between the last stable allocation performed
* before the animation started and the desired final allocation.</para>
* <para>The <varname>is_animating</varname> variable is stored inside the
* #ClutterLayoutManager sub-class and it is updated by overriding the
* <function>begin_animation()</function> and
* <function>end_animation()</function> virtual functions and chaining up
* to the base class implementation.</para>
* <para>The last stable allocation is stored within a #ClutterLayoutMeta
* sub-class used by the implementation.</para>
* <programlisting>
* static void
* my_layout_manager_allocate (ClutterLayoutManager *manager,
* ClutterContainer *container,
* const ClutterActorBox *allocation,
* ClutterAllocationFlags flags)
* {
* MyLayoutManager *self = MY_LAYOUT_MANAGER (manager);
* GList *children, *l;
*
* children = clutter_container_get_children (container);
*
* for (l = children; l != NULL; l = l-&gt;next)
* {
* ClutterActor *child = l->data;
* ClutterLayoutMeta *meta;
* MyLayoutMeta *my_meta;
*
* /&ast; retrieve the layout meta-object &ast;/
* meta = clutter_layout_manager_get_child_meta (manager,
* container,
* child);
* my_meta = MY_LAYOUT_META (meta);
*
* /&ast; compute the desired allocation for the child &ast;/
* compute_allocation (self, my_meta, child,
* allocation, flags,
* &amp;child_box);
*
* /&ast; this is the additional code that deals with the animation
* &ast; of the layout manager
* &ast;/
* if (!self-&gt;is_animating)
* {
* /&ast; store the last stable allocation for later use &ast;/
* my_meta-&gt;last_alloc = clutter_actor_box_copy (&amp;child_box);
* }
* else
* {
* ClutterActorBox end = { 0, };
* gdouble p;
*
* /&ast; get the progress of the animation &ast;/
* p = clutter_layout_manager_get_animation_progress (manager);
*
* if (my_meta-&gt;last_alloc != NULL)
* {
* /&ast; copy the desired allocation as the final state &ast;/
* end = child_box;
*
* /&ast; then interpolate the initial and final state
* &ast; depending on the progress of the animation,
* &ast; and put the result inside the box we will use
* &ast; to allocate the child
* &ast;/
* clutter_actor_box_interpolate (my_meta-&gt;last_alloc,
* &amp;end,
* p,
* &amp;child_box);
* }
* else
* {
* /&ast; if there is no stable allocation then the child was
* &ast; added while animating; one possible course of action
* &ast; is to just bail out and fall through to the allocation
* &ast; to position the child directly at its final state
* &ast;/
* my_meta-&gt;last_alloc =
* clutter_actor_box_copy (&amp;child_box);
* }
* }
*
* /&ast; allocate the child &ast;/
* clutter_actor_allocate (child, &child_box, flags);
* }
*
* g_list_free (children);
* }
* </programlisting>
* </example>
* <para>Sub-classes of #ClutterLayoutManager that support animations of the
* layout changes should call clutter_layout_manager_begin_animation()
* whenever a layout property changes value, e.g.:</para>
* <informalexample>
* <programlisting>
* if (self->orientation != new_orientation)
* {
* ClutterLayoutManager *manager;
*
* self->orientation = new_orientation;
*
* manager = CLUTTER_LAYOUT_MANAGER (self);
* clutter_layout_manager_layout_changed (manager);
* clutter_layout_manager_begin_animation (manager, 500, CLUTTER_LINEAR);
*
* g_object_notify (G_OBJECT (self), "orientation");
* }
* </programlisting>
* </informalexample>
* <para>The code above will animate a change in the
* <varname>orientation</varname> layout property of a layout manager.</para>
* </refsect2>
*
* #ClutterLayoutManager is available since Clutter 1.2
*/
@ -117,11 +289,13 @@
#include <glib-object.h>
#include <gobject/gvaluecollector.h>
#include "clutter-alpha.h"
#include "clutter-debug.h"
#include "clutter-layout-manager.h"
#include "clutter-layout-meta.h"
#include "clutter-marshal.h"
#include "clutter-private.h"
#include "clutter-timeline.h"
#define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \
GObject *_obj = G_OBJECT (m); \
@ -141,7 +315,9 @@ G_DEFINE_ABSTRACT_TYPE (ClutterLayoutManager,
clutter_layout_manager,
G_TYPE_INITIALLY_UNOWNED);
static GQuark quark_layout_meta = 0;
static GQuark quark_layout_meta = 0;
static GQuark quark_layout_alpha = 0;
static guint manager_signals[LAST_SIGNAL] = { 0, };
static void
@ -217,17 +393,105 @@ layout_manager_real_get_child_meta_type (ClutterLayoutManager *manager)
return G_TYPE_INVALID;
}
static ClutterAlpha *
layout_manager_real_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha != NULL)
{
clutter_alpha_set_mode (alpha, mode);
timeline = clutter_alpha_get_timeline (alpha);
clutter_timeline_set_duration (timeline, duration);
clutter_timeline_rewind (timeline);
return alpha;
};
timeline = clutter_timeline_new (duration);
alpha = clutter_alpha_new_full (timeline, mode);
/* let the alpha take ownership of the timeline */
g_object_unref (timeline);
g_signal_connect_swapped (timeline, "completed",
G_CALLBACK (clutter_layout_manager_end_animation),
manager);
g_signal_connect_swapped (timeline, "new-frame",
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata_full (G_OBJECT (manager),
quark_layout_alpha, alpha,
(GDestroyNotify) g_object_unref);
clutter_timeline_start (timeline);
return alpha;
}
static gdouble
layout_manager_real_get_animation_progress (ClutterLayoutManager *manager)
{
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return 1.0;
return clutter_alpha_get_alpha (alpha);
}
static void
layout_manager_real_end_animation (ClutterLayoutManager *manager)
{
ClutterTimeline *timeline;
ClutterAlpha *alpha;
alpha = g_object_get_qdata (G_OBJECT (manager), quark_layout_alpha);
if (alpha == NULL)
return;
timeline = clutter_alpha_get_timeline (alpha);
g_assert (timeline != NULL);
if (clutter_timeline_is_playing (timeline))
clutter_timeline_stop (timeline);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_end_animation),
manager);
g_signal_handlers_disconnect_by_func (timeline,
G_CALLBACK (clutter_layout_manager_layout_changed),
manager);
g_object_set_qdata (G_OBJECT (manager), quark_layout_alpha, NULL);
clutter_layout_manager_layout_changed (manager);
}
static void
clutter_layout_manager_class_init (ClutterLayoutManagerClass *klass)
{
quark_layout_meta =
g_quark_from_static_string ("clutter-layout-manager-child-meta");
quark_layout_alpha =
g_quark_from_static_string ("clutter-layout-manager-alpha");
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;
klass->get_child_meta_type = layout_manager_real_get_child_meta_type;
klass->begin_animation = layout_manager_real_begin_animation;
klass->get_animation_progress = layout_manager_real_get_animation_progress;
klass->end_animation = layout_manager_real_end_animation;
/**
* ClutterLayoutManager::layout-changed:
@ -905,3 +1169,81 @@ clutter_layout_manager_list_child_properties (ClutterLayoutManager *manager,
return pspecs;
}
/**
* clutter_layout_manager_begin_animation:
* @manager: a #ClutterLayoutManager
* @duration: the duration of the animation, in milliseconds
* @mode: the easing mode of the animation
*
* Begins an animation of @duration milliseconds, using the provided
* easing @mode
*
* The easing mode can be specified either as a #ClutterAnimationMode
* or as a logical id returned by clutter_alpha_register_func()
*
* The result of this function depends on the @manager implementation
*
* Return value: (transfer none): The #ClutterAlpha created by the
* layout manager; the returned instance is owned by the layout
* manager and should not be unreferenced
*
* Since: 1.2
*/
ClutterAlpha *
clutter_layout_manager_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode)
{
ClutterLayoutManagerClass *klass;
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), NULL);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
return klass->begin_animation (manager, duration, mode);
}
/**
* clutter_layout_manager_end_animation:
* @manager: a #ClutterLayoutManager
*
* Ends an animation started by clutter_layout_manager_begin_animation()
*
* The result of this call depends on the @manager implementation
*
* Since: 1.2
*/
void
clutter_layout_manager_end_animation (ClutterLayoutManager *manager)
{
g_return_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager));
CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager)->end_animation (manager);
}
/**
* clutter_layout_manager_get_animation_progress:
* @manager: a #ClutterLayoutManager
*
* Retrieves the progress of the animation, if one has been started by
* clutter_layout_manager_begin_animation()
*
* The returned value has the same semantics of the #ClutterAlpha:alpha
* value
*
* Return value: the progress of the animation
*
* Since: 1.2
*/
gdouble
clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager)
{
ClutterLayoutManagerClass *klass;
g_return_val_if_fail (CLUTTER_IS_LAYOUT_MANAGER (manager), 1.0);
klass = CLUTTER_LAYOUT_MANAGER_GET_CLASS (manager);
return klass->get_animation_progress (manager);
}

View File

@ -30,6 +30,7 @@
#define __CLUTTER_LAYOUT_MANAGER_H__
#include <clutter/clutter-actor.h>
#include <clutter/clutter-alpha.h>
#include <clutter/clutter-container.h>
#include <clutter/clutter-types.h>
@ -82,6 +83,12 @@ struct _ClutterLayoutManager
* @create_child_meta: virtual function; override to create a
* #ClutterLayoutMeta instance associated to a #ClutterContainer and a
* child #ClutterActor, used to maintain layout manager specific properties
* @begin_animation: virtual function; override to control the animation
* of a #ClutterLayoutManager with the given duration and easing mode
* @end_animation: virtual function; override to end an animation started
* by clutter_layout_manager_begin_animation()
* @get_animation_progress: virtual function; override to control the
* progress of the animation of a #ClutterLayoutManager
* @layout_changed: class handler for the #ClutterLayoutManager::layout-changed
* signal
*
@ -96,30 +103,38 @@ struct _ClutterLayoutManagerClass
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);
/* vfuncs, not signals */
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);
void (* set_container) (ClutterLayoutManager *manager,
ClutterContainer *container);
GType (* get_child_meta_type) (ClutterLayoutManager *manager);
ClutterLayoutMeta *(* create_child_meta) (ClutterLayoutManager *manager,
ClutterContainer *container,
ClutterActor *actor);
GType (* get_child_meta_type) (ClutterLayoutManager *manager);
ClutterLayoutMeta *(* create_child_meta) (ClutterLayoutManager *manager,
ClutterContainer *container,
ClutterActor *actor);
void (* layout_changed) (ClutterLayoutManager *manager);
ClutterAlpha * (* begin_animation) (ClutterLayoutManager *manager,
guint duration,
gulong mode);
gdouble (* get_animation_progress) (ClutterLayoutManager *manager);
void (* end_animation) (ClutterLayoutManager *manager);
/* signals */
void (* layout_changed) (ClutterLayoutManager *manager);
/*< private >*/
/* padding for future expansion */
@ -184,6 +199,12 @@ void clutter_layout_manager_child_get_property (ClutterLayoutMa
const gchar *property_name,
GValue *value);
ClutterAlpha * clutter_layout_manager_begin_animation (ClutterLayoutManager *manager,
guint duration,
gulong mode);
void clutter_layout_manager_end_animation (ClutterLayoutManager *manager);
gdouble clutter_layout_manager_get_animation_progress (ClutterLayoutManager *manager);
G_END_DECLS
#endif /* __CLUTTER_LAYOUT_MANAGER_H__ */

View File

@ -153,6 +153,11 @@ gboolean clutter_actor_box_contains (const ClutterActorBox *box,
gfloat y);
void clutter_actor_box_from_vertices (ClutterActorBox *box,
const ClutterVertex verts[]);
void clutter_actor_box_interpolate (const ClutterActorBox *initial,
const ClutterActorBox *final,
gdouble progress,
ClutterActorBox *result);
void clutter_actor_box_clamp_to_pixel (ClutterActorBox *box);
/**
* ClutterGeometry:

View File

@ -416,6 +416,8 @@ clutter_actor_box_get_size
clutter_actor_box_get_area
clutter_actor_box_contains
clutter_actor_box_from_vertices
clutter_actor_box_clamp_to_pixel
clutter_actor_box_interpolate
<SUBSECTION>
ClutterVertex
@ -1771,6 +1773,11 @@ clutter_layout_manager_child_get_property
clutter_layout_manager_find_child_property
clutter_layout_manager_list_child_properties
<SUBSECTION>
clutter_layout_manager_begin_animation
clutter_layout_manager_end_animation
clutter_layout_manager_get_animation_progress
<SUBSECTION Standard>
CLUTTER_TYPE_LAYOUT_MANAGER
CLUTTER_LAYOUT_MANAGER
@ -1935,6 +1942,14 @@ clutter_box_layout_get_expand
clutter_box_layout_set_fill
clutter_box_layout_get_fill
<SUBSECTION>
clutter_box_layout_set_use_animations
clutter_box_layout_get_use_animations
clutter_box_layout_set_easing_duration
clutter_box_layout_get_easing_duration
clutter_box_layout_set_easing_mode
clutter_box_layout_get_easing_mode
<SUBSECTION Standard>
CLUTTER_TYPE_BOX_LAYOUT
CLUTTER_BOX_LAYOUT

View File

@ -29,6 +29,7 @@
"Press v\t\342\236\236\tSwitch horizontal/vertical\n" \
"Press p\t\342\236\236\tSwitch pack start/end\n" \
"Press s\t\342\236\236\tIncrement spacing (up to 12px)\n" \
"Press a\t\342\236\236\tSwitch animations on/off\n" \
"Press q\t\342\236\236\tQuit"
static ClutterActor *hover_actor = NULL;
@ -169,6 +170,11 @@ key_release_cb (ClutterActor *actor,
switch (clutter_event_get_key_symbol (event))
{
case CLUTTER_a:
toggle = clutter_box_layout_get_use_animations (layout);
clutter_box_layout_set_use_animations (layout, !toggle);
break;
case CLUTTER_v:
toggle = clutter_box_layout_get_vertical (layout);
clutter_box_layout_set_vertical (layout, !toggle);