From 6ddffac93561b5d3aa6226ee54bd8a5e1fcedeb5 Mon Sep 17 00:00:00 2001 From: Emmanuele Bassi Date: Sun, 27 Sep 2009 11:38:01 +0100 Subject: [PATCH] [docs] Update the "Subclassing Actor" chapter The chapter on how to subclass ClutterActor inside the API reference for Clutter is still using ClutterUnit and referencing to concepts that have been changed since the document was written. --- doc/reference/clutter/subclassing-ClutterActor.xml | 169 +++++++++++++-------- 1 file changed, 107 insertions(+), 62 deletions(-) diff --git a/doc/reference/clutter/subclassing-ClutterActor.xml b/doc/reference/clutter/subclassing-ClutterActor.xml index 7806bac..24915a8 100644 --- a/doc/reference/clutter/subclassing-ClutterActor.xml +++ b/doc/reference/clutter/subclassing-ClutterActor.xml @@ -5,7 +5,7 @@ Bassi
- ebassi@openedhand.com + ebassi@linux.intel.com
@@ -40,13 +40,11 @@ G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR); static void foo_actor_class_init (FooActorClass *klass) { - } static void foo_actor_init (FooActor *actor) { - } @@ -84,10 +82,13 @@ foo_actor_init (FooActor *actor) specific resources associated with being added to the #ClutterStage, and whether their children should be painted or not. A #ClutterContainer implementation should not care about overriding - the ClutterActor::realize(), ClutterActor::unrealize(), - ClutterActor::map() and ClutterActor::unmap() virtual functions, but + the ClutterActor::realize(), + ClutterActor::unrealize(), + ClutterActor::map() and + ClutterActor::unmap() virtual functions, but composite actors with private children MUST implement at least - ClutterActor::map() and ClutterActor::unmap(). + ClutterActor::map() and + ClutterActor::unmap(). @@ -130,8 +131,8 @@ foo_actor_init (FooActor *actor) of space an actor would occupy if nothing would constrain it. The natural size must always be greater than, or equal - to the minimum size. #ClutterActor will warn in case this assumption - is not respected by an implementation. + to the minimum size. #ClutterActor will just ignore a natural size + lesser than a minimum size. The height request may be computed for a specific width, which is passed to the implementation, thus allowing height-for-width @@ -144,7 +145,10 @@ foo_actor_init (FooActor *actor) The clutter_actor_get_preferred_size() function will automatically check the geometry management preferred by the actor and return its preferred size depending on the value of the request-mode - property and on the natural size of the actor. + property and on the natural size of the actor. The get_preferred_size() + method, though, will ignore any notion of "available size" so it should + not be used inside a ClutterActor::allocate() + implementation. The size requisition starts from the #ClutterStage and it is performed on every child of the stage following down the hierarchy @@ -154,11 +158,10 @@ foo_actor_init (FooActor *actor) actor's scale, rotation or anchor point unless an actor is performing layout management depending on those properties. - All the sizes are expressed using #ClutterUnits, the - internal high-precision unit type, which guarantees sub-pixel precision. - #ClutterUnit currently has the same limitations that #ClutterFixed has, - see the fixed point page. - + All the sizes are expressed using pixels with subpixel + precision. The sub-pixel precision is useful when animating actors + but it can produce odd results on screen, so you might want to + truncate the precision of the computed values. Width requisition implementation of a container @@ -174,9 +177,9 @@ foo_actor_init (FooActor *actor) static void foo_actor_get_preferred_width (ClutterActor *actor, - ClutterUnit for_height, - ClutterUnit *min_width_p, - ClutterUnit *natural_width_p) + gfloat for_height, + gfloat *min_width_p, + gfloat *natural_width_p) { GList *l; ClutterUnit min_left, min_right; @@ -190,7 +193,7 @@ foo_actor_get_preferred_width (ClutterActor *actor, for (l = children; l != NULL; l = l->next) { ClutterActor *child = l->data; - ClutterUnit child_x, child_min, child_natural; + gfloat child_x, child_min, child_natural; child_x = clutter_actor_get_xu (child); @@ -270,64 +273,104 @@ foo_actor_get_preferred_width (ClutterActor *actor, The allocate() virtual function implementation will be notified whether the actor has been moved, while clutter_actor_allocate() - will usually be invoked with a boolean flag meaning that the parent - has been moved. + will usually be invoked with the %CLUTTER_ABSOLUTE_ORIGIN_CHANGED flag, + meaning that the parent has been moved. Allocation of a container In this example, FooActor acts like a horizontal box with overflowing, like a toolbar which will display more children as it expands. The children falling outside of the - allocated area will fade out; the children falling inside the - same area will fade in. + allocated area will not be allocated. static void -foo_actor_allocate (ClutterActor *actor, - const ClutterActorBox *box, - gboolean absolute_origin_changed) +foo_actor_allocate (ClutterActor *actor, + const ClutterActorBox *box, + ClutterAllocationFlags flags) { FooActor *foo_actor = FOO_ACTOR (actor); - ClutterUnit current_width; + gfloat available_width, available_height; + gfloat current_width, current_height; + gfloat row_height; GList *l; - /* chain up to set the allocation of the actor */ - CLUTTER_ACTOR_CLASS (foo_actor_parent_class)->allocate (actor, box, absolute_origin_changed); + /* chain up to store the allocation of the actor */ + CLUTTER_ACTOR_CLASS (foo_actor_parent_class)->allocate (actor, box, flags); + + clutter_actor_box_get_size (box, + &available_width, + &available_height); - current_width = foo_actor->padding; + current_width = 0; + current_height = 0; + + row_height = 0; for (l = foo_actor->children; l != NULL; l = l->next) { - FooActorChild *child = l->data; - ClutterUnit natural_width, natural_height; + ClutterActor *child = l->data; ClutterActorBox child_box = { 0, }; + gfloat child_width, child_height; + ClutterRequestMode mode; - /* each child will get as much space as they require */ - clutter_actor_get_preferred_size (CLUTTER_ACTOR (child), - NULL, NULL, - &natural_width, &natural_height); + /* do not allocate invisible children */ + if (!CLUTTER_ACTOR_IS_VISIBLE (child)) + continue; - /* if the child is overflowing, we just fade it out */ - if (current_width + natual_width > box->x2 - box->x1) - foo_actor_fade_child (foo_actor, child, 0); - else + g_object_get (G_OBJECT (child), "request-mode", &mode, NULL); + if (mode == CLUTTER_REQUEST_HEIGHT_FOR_WIDTH) + { + gfloat min, natural; + + clutter_actor_get_preferred_width (child, available_height, + &min, &natural); + child_width = MAX (min, MIN (natural, available_width)); + + clutter_actor_get_preferred_height (child, child_width, + &min, &natural); + child_height = MAX (min, MIN (natural, available_height)); + } + else (mode == CLUTTER_REQUEST_WIDTH_FOR_HEIGHT) { - current_width += natural_width + priv->padding; + gfloat min, natural; - child_box.x1 = current_width; - child_box.y1 = 0; - child_box.x2 = child_box.x1 + natural_width; - child_box.y2 = child_box.y1 + natural_height; + clutter_actor_get_preferred_height (child, available_width, + &min, &natural); + child_height = MAX (min, MIN (natural, available_height)); - /* update the allocation */ - clutter_actor_allocate (CLUTTER_ACTOR (child), - &child_box, - absolute_origin_changed); + clutter_actor_get_preferred_width (child, child_height, + &min, &natural); + child_width = MAX (min, MIN (natural, available_width)); + } + else + g_assert_not_reached (); - /* fade the child in if it wasn't visible */ - foo_actor_fade_child (foo_actor, child, 255); + /* overflow */ + if (current_width + child_width > available_width) + { + current_width = 0; + current_height += row_height; } + else + current_width += child_width; + + /* stop allocating if we are overflowing the available height */ + if (current_height + child_height > available_height) + break; + + child_box.x1 = current_width; + child_box.y1 = current_height; + child_box.x2 = child_box.x1 + child_width; + child_box.y2 = child_box.y1 + child_height; + + /* update the allocation */ + clutter_actor_allocate (child, + &child_box, + flags); + + row_height = MAX (row_height, child_height); } } @@ -346,11 +389,6 @@ foo_actor_allocate (ClutterActor *actor, using the Clutter GL and GLES abstraction library (COGL) or by directly using the GL or GLES API. - Actors performing transformations should push the GL matrix - first and then pop the GL matrix before returning. COGL provides wrapper - functions for this operation, cogl_push_matrix() and cogl_pop_matrix(). - - Paint implementation of a simple actor In this example, the FooActor @@ -568,8 +606,9 @@ foo_actor_add_baz (FooActor *foo_actor, ClutterContainer::add The container actor should hold a pointer to the passed - #ClutterActor, call clutter_actor_set_parent() on it and then - emit the #ClutterContainer::actor-added signal to notify + #ClutterActor, call clutter_actor_set_parent() on it, queue + a relayout on itself and then emit the + #ClutterContainer::actor-added signal to notify handlers of the newly added actor. @@ -593,9 +632,11 @@ foo_actor_add_baz (FooActor *foo_actor, ClutterContainer::foreach_with_internals - The contained should invoke the callback on every + The container should invoke the callback on every child it is holding, including eventual private children - that should not be handled by the #ClutterContainer API. + that should not be handled by the #ClutterContainer API. + This method can be ignored if the container does not + have internal children. @@ -603,7 +644,8 @@ foo_actor_add_baz (FooActor *foo_actor, The container should move the passed child on top of the given sibling, or on top of the paint stack in - case the sibling is NULL. + case the sibling is NULL. This method can be ignored if the + container does not have overlapping children. @@ -611,14 +653,17 @@ foo_actor_add_baz (FooActor *foo_actor, The container should move the passed child below the given sibling, or on the bottom of the paint stack - in case the sibling is NULL. + in case the sibling is NULL. This method can be ignored + if the container does not have overlapping children. ClutterContainer::sort_depth_order The container should sort the paint stack depending - on the relative depths of each child. + on the relative depths of each child. This method can + be ignored if the container does not have overlapping + children. -- 2.7.4