mirror of
https://github.com/brl/mutter.git
synced 2024-11-23 08:30:42 -05:00
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.
This commit is contained in:
parent
238fd52c4b
commit
08f5dc08d0
@ -44,9 +44,10 @@
|
||||
<section id="actors-composite-problem">
|
||||
<title>Problem</title>
|
||||
|
||||
<para>You want to implement your own <type>ClutterActor</type>. For
|
||||
example, a widget (button, scrollbar, checkbox etc.) composed of
|
||||
several Clutter primitives.</para>
|
||||
<para>You want to implement your own <type>ClutterActor</type>;
|
||||
for example, a very simple button widget. But you want to base it
|
||||
on existing Clutter primitives (rectangles, text) to minimise
|
||||
the work required.</para>
|
||||
</section>
|
||||
|
||||
<section id="actors-composite-solution">
|
||||
@ -54,19 +55,25 @@
|
||||
|
||||
<para>Implement a custom actor composed from a <type>ClutterBox</type>
|
||||
packed with other <type>ClutterActors</type>. 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.</para>
|
||||
|
||||
<para>In this recipe, we make the simplest possible button widget
|
||||
(<type>CbButton</type>) to demonstrate the basic principles of
|
||||
implementing a <type>ClutterActor</type>. It is not a complete
|
||||
button implementation: see
|
||||
<ulink url="http://git.clutter-project.org/mx/tree/mx/mx-button.c"><type>MxButton</type></ulink>
|
||||
for a more
|
||||
comprehensive example (and the basis for this recipe). But
|
||||
it does cover the most important parts of a <type>ClutterActor</type>
|
||||
implementation, as well some useful <type>GObject</type>-related
|
||||
code.</para>
|
||||
<para>In this recipe, we subclass <type>ClutterActor</type> using this
|
||||
approach to create a very simple button widget, <type>CbButton</type>.
|
||||
It is not a complete button implementation: see
|
||||
<ulink url="http://git.clutter-project.org/mx/tree/mx/mx-button.c">
|
||||
<type>MxButton</type></ulink> for a more comprehensive example
|
||||
(and the basis for this recipe). But this recipe does cover the most
|
||||
important parts of a <type>ClutterActor</type> implementation,
|
||||
as well some useful <type>GObject</type>-related code.</para>
|
||||
|
||||
<tip>
|
||||
<para>As Clutter is a GObject-based library, it relies
|
||||
heavily on GObject concepts and idioms. If you are unfamiliar with
|
||||
GObject, please read
|
||||
<ulink url="http://library.gnome.org/devel/gobject/unstable/">the GObject
|
||||
Reference Manual</ulink> before proceeding.</para>
|
||||
</tip>
|
||||
|
||||
<para>The code for this solution is structured like standard GObject
|
||||
C library code:</para>
|
||||
@ -88,13 +95,19 @@
|
||||
|
||||
<para>Each of these files is described in more detail below.</para>
|
||||
|
||||
<tip>
|
||||
<para>As Clutter is a GObject-based library, it relies
|
||||
heavily on GObject concepts and idioms. If you are unfamiliar with GObject,
|
||||
please read
|
||||
<ulink url="http://library.gnome.org/devel/gobject/unstable/">the GObject
|
||||
Reference Manual</ulink> before proceeding.</para>
|
||||
</tip>
|
||||
<note>
|
||||
<para>In a more realistic context, <type>CbButton</type> 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.</para>
|
||||
|
||||
<para>If you <emphasis>are</emphasis> planning on building
|
||||
your own widgets using Clutter as part of an application, or
|
||||
to create your own library, the
|
||||
<ulink url="http://git.clutter-project.org/mx/">Mx toolkit</ulink>
|
||||
provides an excellent example of how to autotool your project.</para>
|
||||
</note>
|
||||
|
||||
<example id="actors-composite-cb-button-h">
|
||||
<title><filename>cb-button.h</filename>: header file</title>
|
||||
@ -115,10 +128,12 @@
|
||||
and GObject implementation</title>
|
||||
|
||||
<para>This is the main C code file which implements both
|
||||
the GObject and Clutter parts of <type>CbButton</type>.
|
||||
The example below is commented liberally, and gives some samples
|
||||
of gtk-doc annotations to generate API docs for the
|
||||
widget. The <link linkend="actors-composite-discussion">discussion
|
||||
the GObject and Clutter elements of <type>CbButton</type>.
|
||||
The example below is liberally commented, and also gives some samples
|
||||
of annotations to generate
|
||||
<ulink url="http://www.gtk.org/gtk-doc/">gtk-docs</ulink> for the
|
||||
widget. The
|
||||
<link linkend="actors-composite-discussion-clutter-virtual-functions">discussion
|
||||
section</link> comments more specifically about the Clutter-specific
|
||||
parts of it.</para>
|
||||
|
||||
@ -151,40 +166,145 @@
|
||||
<section id="actors-composite-discussion">
|
||||
<title>Discussion</title>
|
||||
|
||||
<para>Explain about GObject a bit???</para>
|
||||
|
||||
<para>Note size requisition in the example application???</para>
|
||||
|
||||
<para>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
|
||||
<para>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
|
||||
<type>ClutterLayoutManager</type> to handle positioning of
|
||||
the <type>ClutterText</type>; we change the background color of
|
||||
the button by changing the color of the
|
||||
<type>ClutterBox</type>; we use a <type>ClutterClickAction</type>
|
||||
<type>ClutterBox</type>; and we use a <type>ClutterClickAction</type>
|
||||
to simplify implementation of a click signal.</para>
|
||||
|
||||
<para>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.</para>
|
||||
<para>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 <function>pick()</function> and <function>paint()</function>
|
||||
implementations using Cogl (or similar): see
|
||||
<link linkend="actors-non-rectangular">this recipe</link>
|
||||
for more details.</para>
|
||||
|
||||
<para>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.</para>
|
||||
<para>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.</para>
|
||||
|
||||
<para>use Mx for inspiration???</para>
|
||||
<section id="actors-composite-discussion-clutter-virtual-functions">
|
||||
<title>Implementing <type>ClutterActor</type> virtual functions</title>
|
||||
|
||||
<para>GObject implementation parts vs. Clutter implementation???</para>
|
||||
<para>While most of the <type>CbButton</type> implementation
|
||||
revolves around GObject, there are some elements of it
|
||||
specific to Clutter. Due to the simplicity of
|
||||
the <type>CbButton</type> actor, the implementation of
|
||||
these functions is fairly trivial, as explained below:</para>
|
||||
|
||||
<para>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???</para>
|
||||
<itemizedlist>
|
||||
|
||||
<listitem>
|
||||
|
||||
<formalpara>
|
||||
<title>Size requisition:
|
||||
<function>cb_button_get_preferred_height()</function>
|
||||
and <function>cb_button_get_preferred_width()</function></title>
|
||||
|
||||
<para>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 <function>get_preferred_height()</function>
|
||||
and <function>get_preferred_width()</function> functions
|
||||
on each actor in turn.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>If an actor will only ever be explictly sized
|
||||
(via <function>clutter_actor_set_size()</function>,
|
||||
<function>clutter_actor_set_height()</function> and/or
|
||||
<function>clutter_actor_set_width()</function>),
|
||||
there is no need to implement the <function>get_preferred_*()</function>
|
||||
functions. (Some actors like <type>ClutterRectangle</type>
|
||||
work this way and require explicit sizing.)</para>
|
||||
|
||||
<para>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
|
||||
<type>CbButton</type>, a preferred height and width can be
|
||||
computed; these are based on the height and width of
|
||||
the child <type>ClutterBox</type>, plus 20 pixels on each
|
||||
axis. Because the size of the box is itself dependent on
|
||||
the size of the <type>ClutterText</type> inside it, the net
|
||||
result is that the <type>CbButton</type> preferred size
|
||||
is the size of the text actor inside it, plus 20 pixels on each
|
||||
axis.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
||||
<formalpara>
|
||||
<title>Allocation:
|
||||
<function>cb_button_allocate()</function></title>
|
||||
|
||||
<para>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
|
||||
<emphasis>box</emphasis>, representing the space available
|
||||
to it on the stage.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>An actor implementation is responsible for distributing
|
||||
space from its allocation box to its children as it sees
|
||||
fit. In the case of <type>CbButton</type>, there is only a single
|
||||
<type>ClutterBox</type> actor which needs allocation;
|
||||
<function>cb_button_allocate()</function> therefore
|
||||
allocates all of the button's space to its child
|
||||
<type>ClutterBox</type>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
<listitem>
|
||||
|
||||
<formalpara>
|
||||
<title>Painting and picking:
|
||||
<function>cb_button_paint()</function></title>
|
||||
|
||||
<para>Clutter works its way through the actors on the
|
||||
stage, following the actor hierarchy (top level
|
||||
actors directly inside the stage first);
|
||||
<function>clutter_actor_paint()</function>
|
||||
is called on each actor. This, in turn, calls the actor's
|
||||
<function>paint()</function> implementation. If the actor
|
||||
is a container, it may iterate over its children,
|
||||
calling <function>paint()</function> on each; the children
|
||||
may call <function>paint()</function> on their children...;
|
||||
and so on, until the leaves of the actor hierarchy are
|
||||
reached.</para>
|
||||
</formalpara>
|
||||
|
||||
<para>As our actor consists of a single <type>ClutterBox</type>
|
||||
child, its <function>paint()</function> implementation simply
|
||||
has to retrieve the reference to that <type>ClutterBox</type>
|
||||
(from its private structure) and call
|
||||
<function>clutter_actor_paint()</function>
|
||||
on it. Painting of the <type>ClutterBox's</type> child
|
||||
(the <type>ClutterText</type>) is handled by the
|
||||
<type>ClutterBox</type>.</para>
|
||||
|
||||
<para>In cases where an actor is non-rectangular, you also
|
||||
need to implement a <function>pick()</function> 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 <function>pick()</function>.</para>
|
||||
|
||||
</listitem>
|
||||
|
||||
</itemizedlist>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user