diff --git a/doc/reference/ChangeLog b/doc/reference/ChangeLog index fa6d1f6dd..ad9c4f983 100644 --- a/doc/reference/ChangeLog +++ b/doc/reference/ChangeLog @@ -1,3 +1,10 @@ +2008-06-10 Emmanuele Bassi + + * clutter/clutter-sections.txt: Update with the new API. + + * clutter/subclassing-ClutterActor.sgml: Update with the new + size negotiation API. + 2008-06-09 Chris Lord * cogl/cogl-sections.txt: diff --git a/doc/reference/clutter/clutter-sections.txt b/doc/reference/clutter/clutter-sections.txt index e96906134..487554541 100644 --- a/doc/reference/clutter/clutter-sections.txt +++ b/doc/reference/clutter/clutter-sections.txt @@ -255,15 +255,15 @@ clutter_container_lower_child clutter_container_sort_depth_order -clutter_container_find_child_property -clutter_container_list_child_properties +clutter_container_class_find_child_property +clutter_container_class_list_child_properties clutter_container_child_set_property clutter_container_child_get_property clutter_container_child_set clutter_container_child_get -clutter_container_get_child_data +clutter_container_get_child_meta CLUTTER_TYPE_CONTAINER @@ -275,21 +275,21 @@ clutter_container_get_type
-clutter-child-data -ClutterChildData<TITLE> -ClutterChildData -ClutterChildDataClass -clutter_child_data_get_container -clutter_child_data_get_actor +<FILE>clutter-child-meta</FILE> +<TITLE>ClutterChildMeta +ClutterChildMeta +ClutterChildMetaClass +clutter_child_meta_get_container +clutter_child_meta_get_actor -CLUTTER_TYPE_CHILD_DATA -CLUTTER_CHILD_DATA -CLUTTER_IS_CHILD_DATA -CLUTTER_CHILD_DATA_CLASS -CLUTTER_IS_CHILD_DATA_CLASS -CLUTTER_CHILD_DATA_GET_CLASS +CLUTTER_TYPE_CHILD_META +CLUTTER_CHILD_META +CLUTTER_IS_CHILD_META +CLUTTER_CHILD_META_CLASS +CLUTTER_IS_CHILD_META_CLASS +CLUTTER_CHILD_META_GET_CLASS -clutter_child_data_get_type +clutter_child_meta_get_type
@@ -330,6 +330,7 @@ CLUTTER_ACTOR_IS_REACTIVE ClutterActorBox ClutterActorFlags +ClutterRequestMode ClutterGeometry CLUTTER_CALLBACK ClutterCallback @@ -343,22 +344,32 @@ clutter_actor_realize clutter_actor_unrealize clutter_actor_paint clutter_actor_queue_redraw +clutter_actor_queue_relayout clutter_actor_destroy -clutter_actor_request_coords -clutter_actor_query_coords clutter_actor_event clutter_actor_pick clutter_actor_should_pick_paint + +clutter_actor_allocate +clutter_actor_get_allocation_coords +clutter_actor_get_allocation_box +clutter_actor_get_allocation_geometry +clutter_actor_get_allocation_vertices +clutter_actor_get_preferred_size +clutter_actor_get_preferred_width +clutter_actor_get_preferred_height +clutter_actor_get_paint_area +clutter_actor_set_fixed_position_set +clutter_actor_get_fixed_position_set + clutter_actor_set_geometry clutter_actor_get_geometry -clutter_actor_get_coords clutter_actor_set_size clutter_actor_get_size clutter_actor_set_position clutter_actor_get_position -clutter_actor_get_abs_position clutter_actor_set_width clutter_actor_get_width clutter_actor_set_height @@ -392,6 +403,7 @@ clutter_actor_raise clutter_actor_lower clutter_actor_raise_top clutter_actor_lower_bottom +clutter_actor_get_stage clutter_actor_set_depth @@ -399,15 +411,16 @@ clutter_actor_get_depth clutter_actor_set_scale clutter_actor_get_scale clutter_actor_is_scaled -clutter_actor_get_abs_size clutter_actor_apply_transform_to_point clutter_actor_transform_stage_point clutter_actor_apply_relative_transform_to_point +clutter_actor_get_transformed_position +clutter_actor_get_transformed_size +clutter_actor_get_paint_opacity +clutter_actor_get_abs_allocation_vertices ClutterVertex -clutter_actor_get_vertices -clutter_actor_get_relative_vertices clutter_actor_box_get_from_vertices @@ -444,7 +457,11 @@ clutter_actor_get_anchor_pointu clutter_actor_move_anchor_pointu clutter_actor_set_clipu clutter_actor_get_clipu +clutter_actor_set_rotationu +clutter_actor_get_rotationu clutter_actor_move_byu +clutter_actor_get_transformed_positionu +clutter_actor_get_transformed_sizeu clutter_actor_set_scalex @@ -516,8 +533,9 @@ ClutterStage ClutterStageClass CLUTTER_STAGE_WIDTH CLUTTER_STAGE_HEIGHT -clutter_stage_new clutter_stage_get_default +clutter_stage_new +clutter_stage_is_default clutter_stage_set_color @@ -528,6 +546,7 @@ clutter_stage_show_cursor clutter_stage_hide_cursor clutter_stage_get_actor_at_pos clutter_stage_ensure_current +clutter_stage_queue_redraw clutter_stage_event clutter_stage_set_key_focus clutter_stage_get_key_focus @@ -564,9 +583,9 @@ CLUTTER_TYPE_STAGE CLUTTER_STAGE_CLASS CLUTTER_IS_STAGE_CLASS CLUTTER_STAGE_GET_CLASS +CLUTTER_STAGE_TYPE CLUTTER_TYPE_PERSPECTIVE CLUTTER_TYPE_FOG -CLUTTER_STAGE_TYPE ClutterStagePrivate clutter_stage_get_type @@ -821,6 +840,8 @@ clutter_backend_get_double_click_time clutter_backend_set_double_click_time clutter_backend_get_double_click_distance clutter_backend_set_double_click_distance +clutter_backend_set_font_options +clutter_backend_get_font_options CLUTTER_BACKEND CLUTTER_IS_BACKEND @@ -1014,6 +1035,7 @@ clutter_key_event_symbol clutter_key_event_code clutter_key_event_unicode clutter_keysym_to_unicode + CLUTTER_TYPE_EVENT @@ -1028,6 +1050,7 @@ ClutterInitError clutter_init clutter_init_with_args clutter_get_option_group + clutter_main clutter_main_quit @@ -1044,6 +1067,9 @@ clutter_set_motion_events_enabled clutter_get_motion_events_enabled clutter_set_motion_events_frequency clutter_get_motion_events_frequency +clutter_clear_glyph_cache +clutter_set_use_mipmapped_text +clutter_get_use_mipmapped_text clutter_threads_set_lock_functions @@ -1102,10 +1128,10 @@ clutter_x11_remove_filter
clutter-win32 Win32 Specific Support -clutter_win32_get_stage_from_window -clutter_win32_get_stage_window clutter_win32_disable_event_retrieval clutter_win32_set_stage_foreign +clutter_win32_get_stage_from_window +clutter_win32_get_stage_window
diff --git a/doc/reference/clutter/subclassing-ClutterActor.sgml b/doc/reference/clutter/subclassing-ClutterActor.sgml index 68ab96d42..81ba171c0 100644 --- a/doc/reference/clutter/subclassing-ClutterActor.sgml +++ b/doc/reference/clutter/subclassing-ClutterActor.sgml @@ -14,135 +14,524 @@ Implementing a new actor In order to implement a new #ClutterActor subclass the usual - machinery for subclassing a GObject should be used. After that, the - ClutterActor::query_coords() and ClutterActor::request_coords() virtual - functions should be overidden. Optionally, also the ClutterActor::paint() - virtual functions should be overridden. - - The ClutterActor::query_coords() method of a #ClutterActor is - invoked when clutter_actor_query_coords() is called on an instance - of that actor class. It is used to return a #ClutterActorBox containing - the coordinates of the bounding box for the actor (the coordinates - of the top left corner and of the bottom right corner of the rectangle - that fully contains the actor). Container actors, or composite actors - with internal children, should call clutter_actor_query_coords() on - each visible child. Remember: the returned coordinates must be relative - to the parent actor. - - All the coordinates are expressed using #ClutterUnits, - the internal high-precision unit type, which guarantee sub-pixel - precision. #ClutterUnit has the same limitation that #ClutterFixed - has, see the fixed point page. - - - This example shows how an actor class should override the - query_coords() virtual function of #ClutterActor. In this case, - the returned bounding box is the sum of the bounding boxes of all - the FooActor children. + machinery for subclassing a #GObject should be used: + -static void -foo_actor_query_coords (ClutterActor *actor, - ClutterActorBox *box) +#define FOO_TYPE_ACTOR (foo_actor_get_type ()) +#define FOO_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), FOO_TYPE_ACTOR, FooActor)) +#define FOO_IS_ACTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), FOO_TYPE_ACTOR)) +#define FOO_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), FOO_TYPE_ACTOR, FooActorClass)) +#define FOO_IS_ACTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), FOO_TYPE_ACTOR)) +#define FOO_ACTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), FOO_TYPE_ACTOR, FooActorClass)) + +typedef struct _FooActor { - FooActor *foo_actor = FOO_ACTOR (actor); - GList *child; + ClutterActor parent_instance; +} FooActor; - /* Clutter uses high-precision units which can be converted from - * and into pixels, typographic points, percentages, etc. - */ - ClutterUnit width, height; +typedef struct _FooActorClass +{ + ClutterActorClass parent_class; +} FooActorClass; - /* initialize our size */ - width = height = 0; +G_DEFINE_TYPE (FooActor, foo_actor, CLUTTER_TYPE_ACTOR); - for (l = foo_actor->children; l != NULL; l = l->next) +static void +foo_actor_class_init (FooActorClass *klass) +{ + +} + +static void +foo_actor_init (FooActor *actor) +{ + +} + + + + The implementation of an actor roughly depends on what kind + of actor the class should display. + + The implementation process can be broken down into sections: + + + + size requisition + used by containers to know how much space + an actor requires for itself and its eventual + children. + + + + size allocation + used by containers to define how much space + an actor should have for itself and its eventual + children. + + + + painting and picking + the actual actor painting and the "picking" + done to determine the actors that received events + + + + + + + Container actors should also implement the #ClutterContainer + interface to provide a consistent API for adding, removing and iterating + over their children. + + + Size requisition + + Actors should usually implement the size requisition virtual + functions unless they depend on explicit sizing by the developer, + using the clutter_actor_set_width() and clutter_actor_set_height() + functions and their wrappers. + + The size requisition is split into two different phases: width + requisition and height requisition. + + The ClutterActor::get_preferred_width() and + ClutterActor::get_preferred_height() methods of a + #ClutterActor are invoked when clutter_actor_get_preferred_width() and + clutter_actor_get_preferred_height() are respectively called on an instance + of that actor class. They are used to return the preferred size of the + actor. Container actors, or composite actors with internal children, + should call clutter_actor_get_preferred_width() and + clutter_actor_get_preferred_height() on each visible child inside + their implementation of the get_preferred_width() and get_preferred_height() + virtual functions. + + The get_preferred_width() and get_preferred_height() virtual + functions return both the minimum size of the actor and its natural + size. The minimum size is defined as the amount of space an actor + must occupy to be useful; the natural size is defined as the amount + 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. + + The height request may be computed for a specific width, which + is passed to the implementation, thus allowing height-for-width + geometry management. Similarly, the width request may be computed + for a specific height, allowing width-for-height geometry management. + By default, every #ClutterActor uses the height-for-width geometry + management, but the setting can be changed by using the + #ClutterActor:request-mode property. + + The clutter_actor_get_preferred_size() function will + automatically check the geometry management preferred by the actor + and return its preferred size depending on it and on the natural + size. + + The size requisition starts from the #ClutterStage and it is + performed on every child of the stage following down the hierarchy + of the scene graph. + + The size requisition should not take into account the + 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. + + + + Width requisition implementation of a container + + This example shows how an actor class should override the + get_preferred_width() virtual function of #ClutterActor. In this case, + the returned widths are the union of the extents of all the + FooActor children. + + The get_preferred_height() implementation would be similar to the + get_preferred_width() implementation, so it is omitted. + + +static void +foo_actor_get_preferred_width (ClutterActor *actor, + ClutterUnit for_height, + ClutterUnit *min_width_p, + ClutterUnit *natural_width_p) +{ + GList *l; + ClutterUnit min_left, min_right; + ClutterUnit natural_left, natural_right; + + min_left = 0; + min_right = 0; + natural_left = 0; + natural_right = 0; + + for (l = children; l != NULL; l = l->next) { - ClutterActor *child_actor = child->data; + ClutterActor *child = l->data; + ClutterUnit child_x, child_min, child_natural; - /* we consider only visible actors */ - if (CLUTTER_ACTOR_IS_VISIBLE (child_actor)) + child_x = clutter_actor_get_xu (child); + + clutter_actor_get_preferred_width (child, for_height, + &child_min, + &child_natural); + + if (l == children) { - ClutterActorBox child_box = { 0, }; + /* First child */ + min_left = child_x; + natural_left = child_x; + min_right = min_left + child_min; + natural_right = natural_left + child_natural; + } + else + { + if (child_x < min_left) + min_left = child_x; - clutter_actor_query_coords (child_actor, &child_box); - - width += child_box.x2 - child_box.x2; - height += child_box.y2 - child_box.y1; + if (child_x < natural_left) + natural_left = child_x; + + 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; } } - box->x2 = box->x1 + width - box->y2 = box->y1 + height; + /* The request is defined as the width and height we want starting from + * our origin, since our allocation will set the origin; so we now need + * to remove any part of the request that is to the left of the origin. + */ + if (min_left < 0) + min_left = 0; + + if (natural_left < 0) + natural_left = 0; + + if (min_right < 0) + min_right = 0; + + if (natural_right < 0) + natural_right = 0; + + g_assert (min_right >= min_left); + g_assert (natural_right >= natural_left); + + if (min_width_p) + *min_width_p = min_right - min_left; + + if (natural_width_p) + *natural_width_p = natural_right - min_left; } - - + + + + + + + Size allocation + + The ClutterActor::allocate() method of a + #ClutterActor is invoked when clutter_actor_allocate() is called on an + instance of that actor class. It is used by a parent actor to set the + coordinates of the bounding box for its children actors. Hence, + container actors, or composite actors with internal children, should + override the allocate() virtual function and call clutter_actor_allocate() + on each visible child. + + Each actor can know from their allocation box whether they + have been moved with respect to their parent actor. Each child will + also be able to tell whether their parent has been moved with respect + to the stage. + + 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. + + + 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. + +static void +foo_actor_allocate (ClutterActor *actor, + const ClutterActorBox *box, + gboolean absolute_origin_changed) +{ + FooActor *foo_actor = FOO_ACTOR (actor); + ClutterUnit current_width; + GList *l; + + /* chain up to set the allocation of the actor */ + CLUTTER_ACTOR_CLASS (foo_actor_parent_class)->allocate (actor, box, absolute_origin_changed); + + current_width = foo_actor->padding; + + for (l = foo_actor->children; + l != NULL; + l = l->next) + { + FooActorChild *child = l->data; + ClutterUnit natural_width, natural_height; + ClutterActorBox child_box = { 0, }; + + /* each child will get as much space as they require */ + clutter_actor_get_preferred_size (CLUTTER_ACTOR (child), + NULL, NULL, + &natural_width, &natural_height); + + /* 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 + { + current_width += natural_width + priv->padding; + + 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; + + /* update the allocation */ + clutter_actor_allocate (CLUTTER_ACTOR (child), + &child_box, + absolute_origin_changed); + + /* fade the child in if it wasn't visible */ + foo_actor_fade_child (foo_actor, child, 255); + } + } +} + + + + An actor should always paint inside its allocation. It is, + however, possible to paint outside the negotiated size by overriding + the ClutterActor::get_paint_area() virtual + function and setting the passed #ClutterActorBox with their + untransformed paint area. This allows writing + actors that can effectively paint on an area different in size and + position from the allocation area. + + The ClutterActor::get_paint_area() method of + a #ClutterActor is internally invoked when clutter_actor_get_paint_area() + is called on an instance of that actor class. The get_paint_area() + virtual function must return the untransformed area used by the + actor to paint itself; clutter_actor_get_paint_area() will then + proceed to transform the area coordinates into the frame of reference + of the actor's parent (taking into account anchor point, scaling + and rotation). + + The default paint area is the allocation area of the + actor. + + + Implementation of get_paint_area() + In this example, FooActor implements + the get_paint_area() virtual function to return an area equivalent + to those of its children plus a border which is not taken into + account by the size negotiation process. + +static void +foo_actor_get_paint_area (ClutterActor *actor, + ClutterActorBox *box) +{ + FooActor *foo_actor = FOO_ACTOR (actor); + + if (!foo_actor->children) + { + /* if we don't have any children we return the + * allocation given to us + */ + clutter_actor_get_allocation_box (actor, box); + } + else + { + ClutterActorBox all_box = { 0, }; + GList *l; + + /* our paint area is the union of the children + * paint areas, plus a border + */ + for (l = foo_actor->children; l != NULL; l = l>next) + { + ClutterActor *child = l->data; + ClutterActorBox child_box = { 0, }; + + clutter_actor_get_paint_area (child, &child_box); + + if (l == foo_actor->children) + all_box = child_box; + else + { + if (child_box.x1 < all_box.x1) + all_box.x1 = child_box.x1; + + if (child_box.y1 < all_box.y1) + all_box.y1 = child_box.y1; + + if (child_box.x2 < all_box.x2) + all_box.x2 = child_box.x2; + + if (child_box.y2 < all_box.y2) + all_box.y2 = child_box.y2; + } + } + + /* apply the border width around the box */ + all_box.x1 -= (foo_actor->border_width / 2); + all_box.y1 -= (foo_actor->border_width / 2); + all_box.x2 += (foo_actor->border_width / 2); + all_box.y2 += (foo_actor->border_width / 2); + + *box = all_box; + } +} + + + + + + + Painting and picking + + The ClutterActor::paint() method should be + overridden if the actor needs to control its drawing process, either by + 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. - The ClutterActor::request_coords() method of a #ClutterActor - is invoked when clutter_actor_request_coords() is called on an instance - of that actor class. It is used to set the coordinates of the bounding - box for the actor. Container actors, or composite actors with internal - children, should override the request_coords() virtual function and call - clutter_actor_request_coords() on each visible child. Every actor class - overriding the request_coords() virtual function must chain up to the - parent class request_coords() method. + + Paint implementation of a simple actor + In this example, the FooActor + implementation of the paint() virtual function is drawing a rectangle + with rounded corners with a custom color. The COGL API is used, to + allow portability between GL and GLES platforms. + +static void +foo_actor_paint (ClutterActor *actor) +{ + FooActor *foo_actor = FOO_ACTOR (actor); + ClutterColor color = { 0, }; + ClutterUnit w, h, r; - The ClutterActor::paint() method should be overridden if the - actor needs to control its drawing process, by using the GL API - directly. Actors performing transformations should push the GL matrix - first and then pop the GL matrix before returning. Container actors - or composite actors with internal children should do the same, and call - clutter_actor_paint() on every visible child: + cogl_push_matrix (); - When inside the ClutterActor::paint() method the actor is already - positioned at the coordinates specified by its bounding box; all the - paint operations should then take place from the (0, 0) coordinates. + /* FooActor has a specific background color */ + color.red = foo_actor->bg_color.red; + color.green = foo_actor->bg_color.green; + color.blue = foo_actor->bg_color.blue; - - + /* the alpha component must take into account the absolute + * opacity of the actor on the screen at this point in the + * scenegraph; this value is obtained by calling + * clutter_actor_get_paint_opacity(). + */ + color.alpha = clutter_actor_get_paint_opacity (actor); + + /* set the color of the pen */ + cogl_color (&color); + + /* get the size of the actor with sub-pixel precision */ + w = CLUTTER_UNITS_TO_FIXED (clutter_actor_get_widthu (actor)); + h = CLUTTER_UNITS_TO_FIXED (clutter_actor_get_heightu (actor)); + + /* this is the arc radius for the rounded rectangle corners */ + r = CLUTTER_UNITS_TO_FIXED (foo_actor->radius); + + /* paint a rounded rectangle using GL primitives; the area of + * paint is (0, 0) - (width, height), which means the whole + * allocation or, if the actor has a fixed size, the size that + * has been set. + */ + cogl_round_rectangle (0, 0, w, h, r, 5); + + /* and fill it with the current color */ + cogl_fill (); + + cogl_pop_matrix (); +} + + + + When inside the ClutterActor::paint() + method the actor is already positioned at the coordinates specified by + its parent; all the paint operations should take place from the (0, 0) + coordinates. + + Container actors or composite actors with internal children should + also override the paint method, and call clutter_actor_paint() on every + visible child: + + + Paint implementation of a container + In this example, FooActor is a simple + container invoking clutter_actor_paint() on every visible child. To + allow transformations on itself to affect the children, the GL modelview + matrix is pushed at the beginning of the paint sequence, and the popped + at the end. + static void foo_actor_paint (ClutterActor *actor) { FooActor *foo_actor = FOO_ACTOR (actor); GList *child; - /* by including <clutter/cogl.h> it's possible to use the internal - * COGL abstraction API, which is also used by Clutter itself and avoids - * changing the GL calls depending on the target platform (GL or GL/ES). - */ cogl_push_matrix (); - for (child = foo_actor->children; child != NULL; child = child->next) + for (child = foo_actor->children; + child != NULL; + child = child->next) { ClutterActor *child_actor = child->data; - if (CLUTTER_ACTOR_IS_MAPPED (child_actor)) + /* paint only visible children */ + if (CLUTTER_ACTOR_IS_VISIBLE (child_actor)) clutter_actor_paint (child_actor); } cogl_pop_matrix (); } - - + + - When painting a blended actor, cogl_enable() should be called with - the %CGL_BLEND flag; or, alternatively, glEnable() with %GL_BLEND on - OpenGL. + A container imposing a layout on its children may + opt to use the paint area as returned by clutter_actor_get_paint_area() + instead of the allocation. - If the actor has a non-rectangular shape, or it has internal childrens - that needs to be distinguished by the events delivery mechanism, the - ClutterActor::pick() method should also be overridden. The ::pick() method - works exactly like the ::paint() method, but the actor should paint just - its shape with the passed colour: + If the actor has a non-rectangular shape, or it has internal + children that need to be distinguished by the events delivery mechanism, + the ClutterActor::pick() method should also be + overridden. The pick() method works exactly like the paint() method, but + the actor should paint just its shape with the passed colour: - - + + Pick implementation of a simple actor + In this example, FooActor overrides the + pick() virtual function default implementation to paint itself with a + shaped silhouette, to allow events only on the actual shape of the actor + instead of the paint area. + static void foo_actor_pick (ClutterActor *actor, const ClutterColor *pick_color) { FooActor *foo_actor = FOO_ACTOR (actor); - guint width, height; + ClutterUnit w, h, r; /* it is possible to avoid a costly paint by checking whether the * actor should really be painted in pick mode @@ -150,32 +539,56 @@ foo_actor_pick (ClutterActor *actor, if (!clutter_actor_should_pick_paint (actor)) return; - /* by including <clutter/cogl.h> it's possible to use the internal - * COGL abstraction API, which is also used by Clutter itself and avoids - * changing the GL calls depending on the target platform (GL or GL/ES). - */ + w = CLUTTER_UNITS_TO_FIXED (clutter_actor_get_widthu (actor)); + h = CLUTTER_UNITS_TO_FIXED (clutter_actor_get_heightu (actor)); + + /* this is the arc radius for the rounded rectangle corners */ + r = CLUTTER_UNITS_TO_FIXED (foo_actor->radius); + + /* use the passed color to paint ourselves */ cogl_color (pick_color); - clutter_actor_get_size (actor, &width, &height); + /* paint a round rectangle */ + cogl_round_rectangle (0, 0, w, h, r, 5); - /* it is also possible to use raw GL calls, at the cost of losing - * portability - */ - glEnable (GL_BLEND); - - /* draw a triangular shape */ - glBegin (GL_POLYGON); - glVertex2i (width / 2, 0 ); - glVertex2i (width , height); - glVertex2i (0 , height); - glEnd (); + /* and fill it with the current color */ + cogl_fill (); cogl_pop_matrix (); } - - + + -
+ Containers should simply chain up to the parent class' + pick() implementation to get their silhouette painted and then + paint their children: + + + Pick implementation of a container + In this example, FooActor allows the + picking of each child it contains, as well as itself. + +static void +foo_actor_pick (ClutterActor *actor, + const ClutterColor *pick_color) +{ + FooActor *foo_actor = FOO_ACTOR (actor); + + /* this will paint a silhouette corresponding to the paint box */ + CLUTTER_ACTOR_CLASS (foo_actor_parent_class)->pick (actor, pick_color); + + /* clutter_actor_paint() is context-sensitive, and will perform + * a pick paint if the scene graph is in pick mode + */ + if (CLUTTER_ACTOR_IS_VISIBLE (foo_actor->child)) + clutter_actor_paint (foo_actor->child); +} + + + + + + Implementing Containers @@ -192,6 +605,13 @@ foo_actor_pick (ClutterActor *actor, + Parenting an actor + In this example, FooActor has an internal + child of type BazActor which is assigned using a + specific function called foo_actor_add_baz(). The + FooActor instance takes ownership of the + BazActor instance and sets the parent-child + relationship using clutter_actor_set_parent(). void foo_actor_add_baz (FooActor *foo_actor, @@ -208,14 +628,20 @@ foo_actor_add_baz (FooActor *foo_actor, foo_actor->baz = baz_actor; - /* this will cause the initial floating reference to disappear, - * and add a new reference on baz_actor. foo_actor has now taken - * ownership of baz_actor + /* this will cause the initial floating reference of ClutterActor to + * disappear, and add a new reference on baz_actor. foo_actor has now + * taken ownership of baz_actor, so that: + * + * foo_actor_add_baz (foo_actor, baz_actor_new ()); + * + * is a safe statement (no reference is leaked). */ clutter_actor_set_parent (CLUTTER_ACTOR (baz_actor), CLUTTER_ACTOR (foo_actor)); + /* emit a signal and notification */ g_signal_emit (foo_actor, foo_actor_signals[BAZ_CHANGED], 0, baz_actor); + g_object_notify (G_OBJECT (foo_actor), "baz"); } @@ -228,43 +654,56 @@ 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 + handlers of the newly added actor. ClutterContainer::remove - + The container actor should increase the reference count + of the passed #ClutterActor, remove the pointer held on the + child and call clutter_actor_unparent() on it; then, emit the + #ClutterContainer::actor-removed signal and decrease the + reference count. ClutterContainer::foreach - + The container should invoke the callback on every + child it is holding. ClutterContainer::raise - + 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. ClutterContainer::lower - + 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. ClutterContainer::sort_depth_order - + The container should sort the paint stack depending + on the relative depths of each child. -
+