From 08f5dc08d0e11e2f03b3a9c8889222a584cbe0e7 Mon Sep 17 00:00:00 2001 From: Elliot Smith Date: Mon, 31 Jan 2011 10:53:52 +0000 Subject: [PATCH] docs: Complete composite actor recipe Add some extra detail to the Discussion section of the composite actor recipe, concentrating on the pros and cons of this approach. Also explain more about the Clutter parts of the implementation. Also general tidy up of language and style. --- doc/cookbook/actors.xml | 220 +++++++++++++++++++++++++++++++--------- 1 file changed, 170 insertions(+), 50 deletions(-) diff --git a/doc/cookbook/actors.xml b/doc/cookbook/actors.xml index 3fd3a6a8e..35b202c55 100644 --- a/doc/cookbook/actors.xml +++ b/doc/cookbook/actors.xml @@ -44,9 +44,10 @@
Problem - You want to implement your own ClutterActor. For - example, a widget (button, scrollbar, checkbox etc.) composed of - several Clutter primitives. + You want to implement your own ClutterActor; + for example, a very simple button widget. But you want to base it + on existing Clutter primitives (rectangles, text) to minimise + the work required.
@@ -54,19 +55,25 @@ Implement a custom actor composed from a ClutterBox packed with other ClutterActors. The custom actor - effectively provides a facade for these internal actors, simplifying + provides a facade over these internal actors, simplifying access to their properties and behavior. - In this recipe, we make the simplest possible button widget - (CbButton) to demonstrate the basic principles of - implementing a ClutterActor. It is not a complete - button implementation: see - MxButton - for a more - comprehensive example (and the basis for this recipe). But - it does cover the most important parts of a ClutterActor - implementation, as well some useful GObject-related - code. + In this recipe, we subclass ClutterActor using this + approach to create a very simple button widget, CbButton. + It is not a complete button implementation: see + + MxButton for a more comprehensive example + (and the basis for this recipe). But this recipe does cover the most + important parts of a ClutterActor implementation, + as well some useful GObject-related code. + + + As Clutter is a GObject-based library, it relies + heavily on GObject concepts and idioms. If you are unfamiliar with + GObject, please read + the GObject + Reference Manual before proceeding. + The code for this solution is structured like standard GObject C library code: @@ -88,13 +95,19 @@ Each of these files is described in more detail below. - - As Clutter is a GObject-based library, it relies - heavily on GObject concepts and idioms. If you are unfamiliar with GObject, - please read - the GObject - Reference Manual before proceeding. - + + In a more realistic context, CbButton would + have some build infrastructure (for example, autotooling) + so it could be compiled, installed, and reused in a variety of + applications. However, for the purposes of cookbook examples, + these issues are ignored here. + + If you are planning on building + your own widgets using Clutter as part of an application, or + to create your own library, the + Mx toolkit + provides an excellent example of how to autotool your project. + <filename>cb-button.h</filename>: header file @@ -115,10 +128,12 @@ and GObject implementation This is the main C code file which implements both - the GObject and Clutter parts of CbButton. - The example below is commented liberally, and gives some samples - of gtk-doc annotations to generate API docs for the - widget. The discussion + the GObject and Clutter elements of CbButton. + The example below is liberally commented, and also gives some samples + of annotations to generate + gtk-docs for the + widget. The + discussion section comments more specifically about the Clutter-specific parts of it. @@ -151,40 +166,145 @@
Discussion - Explain about GObject a bit??? - - Note size requisition in the example application??? - - The actor implemented here is put together through - simple composition. This has the advantage of simplifying the - code for the subclass: we can just wrap a facade round - existing Clutter classes, rather than writing code to implement - everything ourselves. In the example here, we make use of a + The actor implemented here is based on + simple composition: bundling several actors together and wrapping + their behavior and properties. In the example here, we make use of a ClutterLayoutManager to handle positioning of the ClutterText; we change the background color of the button by changing the color of the - ClutterBox; we use a ClutterClickAction + ClutterBox; and we use a ClutterClickAction to simplify implementation of a click signal. - On the other hand, it puts some constraints on the outline of - the actor: it makes it harder to use a custom outline, for - example, to round the corners of the button. This approach may - not be suitable where you need to do a lot of custom animation - and drawing. + You may find that this approach is appropriate if you need + to implement a simple rectangular actor. However, it puts some + constraints on the outline of the actor, making it harder to + use a custom outline: for example, a rectangle with rounded corners + or a shape which can't be approximated by a rectangle. Such cases + require both pick() and paint() + implementations using Cogl (or similar): see + this recipe + for more details. - This isn't the whole story: if you aren't using this simple - composition approach, you may need to do more: see the notes in - the Clutter reference manual. Also, if you're implementing a - container, you'll need to do more. + The composition approach may also be inappropriate where + you need to do a lot of custom animation and drawing; and it is + likely to be inappropriate for implementing a container + actor. See the notes on implementing a new actor in the Clutter + reference manual for more details of what may be required + in these cases. - use Mx for inspiration??? +
+ Implementing <type>ClutterActor</type> virtual functions - GObject implementation parts vs. Clutter implementation??? + While most of the CbButton implementation + revolves around GObject, there are some elements of it + specific to Clutter. Due to the simplicity of + the CbButton actor, the implementation of + these functions is fairly trivial, as explained below: - something about how the ClutterBox is parented onto the - ClutterActor subclass we are implementing; we just create - an allocation for the ClutterBox based on the allocation of its - parent??? + + + + + + Size requisition: + <function>cb_button_get_preferred_height()</function> + and <function>cb_button_get_preferred_width()</function> + + During the size requisition phase, Clutter asks each + actor the minimum size it should be to remain useful, + and the maximum size it would be if unconstrained. This is done + by calling the get_preferred_height() + and get_preferred_width() functions + on each actor in turn. + + + If an actor will only ever be explictly sized + (via clutter_actor_set_size(), + clutter_actor_set_height() and/or + clutter_actor_set_width()), + there is no need to implement the get_preferred_*() + functions. (Some actors like ClutterRectangle + work this way and require explicit sizing.) + + However, if an actor's size should be negotiated during + the size requisition phase, you can implement these functions, + using the size of the child actors as a basis for the + preferred height and width. In the case of + CbButton, a preferred height and width can be + computed; these are based on the height and width of + the child ClutterBox, plus 20 pixels on each + axis. Because the size of the box is itself dependent on + the size of the ClutterText inside it, the net + result is that the CbButton preferred size + is the size of the text actor inside it, plus 20 pixels on each + axis. + + + + + + + Allocation: + <function>cb_button_allocate()</function> + + The requests gathered during size requisition + are then negotiated by Clutter, each actor + receiving some allocation of the available space. At the + end of this process, each actor is allocated a + box, representing the space available + to it on the stage. + + + An actor implementation is responsible for distributing + space from its allocation box to its children as it sees + fit. In the case of CbButton, there is only a single + ClutterBox actor which needs allocation; + cb_button_allocate() therefore + allocates all of the button's space to its child + ClutterBox. + + + + + + + Painting and picking: + <function>cb_button_paint()</function> + + Clutter works its way through the actors on the + stage, following the actor hierarchy (top level + actors directly inside the stage first); + clutter_actor_paint() + is called on each actor. This, in turn, calls the actor's + paint() implementation. If the actor + is a container, it may iterate over its children, + calling paint() on each; the children + may call paint() on their children...; + and so on, until the leaves of the actor hierarchy are + reached. + + + As our actor consists of a single ClutterBox + child, its paint() implementation simply + has to retrieve the reference to that ClutterBox + (from its private structure) and call + clutter_actor_paint() + on it. Painting of the ClutterBox's child + (the ClutterText) is handled by the + ClutterBox. + + In cases where an actor is non-rectangular, you also + need to implement a pick() function. + (This is used to determine which actor was the recipient of + an event occurring within the stage.) However, because + the actor in this recipe is a simple rectangle, there is no + need to implement pick(). + + + + + +