mirror of
https://github.com/brl/mutter.git
synced 2024-11-27 02:20:43 -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">
|
<section id="actors-composite-problem">
|
||||||
<title>Problem</title>
|
<title>Problem</title>
|
||||||
|
|
||||||
<para>You want to implement your own <type>ClutterActor</type>. For
|
<para>You want to implement your own <type>ClutterActor</type>;
|
||||||
example, a widget (button, scrollbar, checkbox etc.) composed of
|
for example, a very simple button widget. But you want to base it
|
||||||
several Clutter primitives.</para>
|
on existing Clutter primitives (rectangles, text) to minimise
|
||||||
|
the work required.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section id="actors-composite-solution">
|
<section id="actors-composite-solution">
|
||||||
@ -54,19 +55,25 @@
|
|||||||
|
|
||||||
<para>Implement a custom actor composed from a <type>ClutterBox</type>
|
<para>Implement a custom actor composed from a <type>ClutterBox</type>
|
||||||
packed with other <type>ClutterActors</type>. The custom actor
|
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>
|
access to their properties and behavior.</para>
|
||||||
|
|
||||||
<para>In this recipe, we make the simplest possible button widget
|
<para>In this recipe, we subclass <type>ClutterActor</type> using this
|
||||||
(<type>CbButton</type>) to demonstrate the basic principles of
|
approach to create a very simple button widget, <type>CbButton</type>.
|
||||||
implementing a <type>ClutterActor</type>. It is not a complete
|
It is not a complete button implementation: see
|
||||||
button implementation: see
|
<ulink url="http://git.clutter-project.org/mx/tree/mx/mx-button.c">
|
||||||
<ulink url="http://git.clutter-project.org/mx/tree/mx/mx-button.c"><type>MxButton</type></ulink>
|
<type>MxButton</type></ulink> for a more comprehensive example
|
||||||
for a more
|
(and the basis for this recipe). But this recipe does cover the most
|
||||||
comprehensive example (and the basis for this recipe). But
|
important parts of a <type>ClutterActor</type> implementation,
|
||||||
it does cover the most important parts of a <type>ClutterActor</type>
|
as well some useful <type>GObject</type>-related code.</para>
|
||||||
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
|
<para>The code for this solution is structured like standard GObject
|
||||||
C library code:</para>
|
C library code:</para>
|
||||||
@ -88,13 +95,19 @@
|
|||||||
|
|
||||||
<para>Each of these files is described in more detail below.</para>
|
<para>Each of these files is described in more detail below.</para>
|
||||||
|
|
||||||
<tip>
|
<note>
|
||||||
<para>As Clutter is a GObject-based library, it relies
|
<para>In a more realistic context, <type>CbButton</type> would
|
||||||
heavily on GObject concepts and idioms. If you are unfamiliar with GObject,
|
have some build infrastructure (for example, autotooling)
|
||||||
please read
|
so it could be compiled, installed, and reused in a variety of
|
||||||
<ulink url="http://library.gnome.org/devel/gobject/unstable/">the GObject
|
applications. However, for the purposes of cookbook examples,
|
||||||
Reference Manual</ulink> before proceeding.</para>
|
these issues are ignored here.</para>
|
||||||
</tip>
|
|
||||||
|
<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">
|
<example id="actors-composite-cb-button-h">
|
||||||
<title><filename>cb-button.h</filename>: header file</title>
|
<title><filename>cb-button.h</filename>: header file</title>
|
||||||
@ -115,10 +128,12 @@
|
|||||||
and GObject implementation</title>
|
and GObject implementation</title>
|
||||||
|
|
||||||
<para>This is the main C code file which implements both
|
<para>This is the main C code file which implements both
|
||||||
the GObject and Clutter parts of <type>CbButton</type>.
|
the GObject and Clutter elements of <type>CbButton</type>.
|
||||||
The example below is commented liberally, and gives some samples
|
The example below is liberally commented, and also gives some samples
|
||||||
of gtk-doc annotations to generate API docs for the
|
of annotations to generate
|
||||||
widget. The <link linkend="actors-composite-discussion">discussion
|
<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
|
section</link> comments more specifically about the Clutter-specific
|
||||||
parts of it.</para>
|
parts of it.</para>
|
||||||
|
|
||||||
@ -151,40 +166,145 @@
|
|||||||
<section id="actors-composite-discussion">
|
<section id="actors-composite-discussion">
|
||||||
<title>Discussion</title>
|
<title>Discussion</title>
|
||||||
|
|
||||||
<para>Explain about GObject a bit???</para>
|
<para>The actor implemented here is based on
|
||||||
|
simple composition: bundling several actors together and wrapping
|
||||||
<para>Note size requisition in the example application???</para>
|
their behavior and properties. In the example here, we make use of a
|
||||||
|
|
||||||
<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
|
|
||||||
<type>ClutterLayoutManager</type> to handle positioning of
|
<type>ClutterLayoutManager</type> to handle positioning of
|
||||||
the <type>ClutterText</type>; we change the background color of
|
the <type>ClutterText</type>; we change the background color of
|
||||||
the button by changing the color of the
|
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>
|
to simplify implementation of a click signal.</para>
|
||||||
|
|
||||||
<para>On the other hand, it puts some constraints on the outline of
|
<para>You may find that this approach is appropriate if you need
|
||||||
the actor: it makes it harder to use a custom outline, for
|
to implement a simple rectangular actor. However, it puts some
|
||||||
example, to round the corners of the button. This approach may
|
constraints on the outline of the actor, making it harder to
|
||||||
not be suitable where you need to do a lot of custom animation
|
use a custom outline: for example, a rectangle with rounded corners
|
||||||
and drawing.</para>
|
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
|
<para>The composition approach may also be inappropriate where
|
||||||
composition approach, you may need to do more: see the notes in
|
you need to do a lot of custom animation and drawing; and it is
|
||||||
the Clutter reference manual. Also, if you're implementing a
|
likely to be inappropriate for implementing a container
|
||||||
container, you'll need to do more.</para>
|
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
|
<itemizedlist>
|
||||||
ClutterActor subclass we are implementing; we just create
|
|
||||||
an allocation for the ClutterBox based on the allocation of its
|
<listitem>
|
||||||
parent???</para>
|
|
||||||
|
<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>
|
</section>
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user