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(). + + + + + +