File: clutter-constraint.c

package info (click to toggle)
clutter-1.0 1.10.8-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 32,560 kB
  • sloc: ansic: 120,145; sh: 12,144; xml: 10,355; makefile: 2,013; perl: 169; ruby: 149; sed: 16
file content (203 lines) | stat: -rw-r--r-- 9,630 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
/**
 * SECTION:clutter-constraint
 * @Title: ClutterConstraint
 * @Short_Description: Abstract class for constraints on position or size
 * @See_Also: #ClutterAction
 *
 * #ClutterConstraint is a base abstract class for modifiers of a #ClutterActor
 * position or size.
 *
 * A #ClutterConstraint sub-class should contain the logic for modifying
 * the position or size of the #ClutterActor to which it is applied, by
 * updating the actor's allocation. Each #ClutterConstraint can change the
 * allocation of the actor to which they are applied by overriding the
 * <function>update_allocation()</function> virtual function.
 *
 * <refsect2 id="ClutterConstraint-usage">
 *   <title>Using Constraints</title>
 *   <para>Constraints can be used with fixed layout managers, like
 *   #ClutterFixedLayout, or with actors implicitly using a fixed layout
 *   manager, like #ClutterGroup and #ClutterStage.</para>
 *   <para>Constraints provide a way to build user interfaces by using
 *   relations between #ClutterActor<!-- -->s, without explicit fixed
 *   positioning and sizing, similarly to how fluid layout managers like
 *   #ClutterBoxLayout and #ClutterTableLayout lay out their children.</para>
 *   <para>Constraints are attached to a #ClutterActor, and are available
 *   for inspection using clutter_actor_get_constraints().</para>
 *   <para>Clutter provides different implementation of the #ClutterConstraint
 *   abstract class, for instance:</para>
 *   <variablelist>
 *     <varlistentry>
 *       <term>#ClutterAlignConstraint</term>
 *       <listitem><simpara>this constraint can be used to align an actor
 *       to another one, on either the horizontal or the vertical axis; the
 *       #ClutterAlignConstraint uses a normalized offset between 0.0 (the
 *       top or the left of the source actor, depending on the axis) and
 *       1.0 (the bottom or the right of the source actor, depending on the
 *       axis).</simpara></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term>#ClutterBindConstraint</term>
 *       <listitem><simpara>this constraint binds the X, Y, width or height
 *       of an actor to the corresponding position or size of a source
 *       actor; it can also apply an offset.</simpara></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term>#ClutterSnapConstraint</term>
 *       <listitem><simpara>this constraint "snaps" together the edges of
 *       two #ClutterActor<!-- -->s; if an actor uses two constraints on
 *       both its horizontal or vertical edges then it can also expand to
 *       fit the empty space.</simpara></listitem>
 *     </varlistentry>
 *   </variablelist>
 *   <example id="ClutterConstraint-usage-example">
 *     <title>Usage of constraints</title>
 *     <para>The example below uses various #ClutterConstraint<!-- -->s to
 *     lay out three actors on a resizable stage. Only the central actor has
 *     an explicit size, and no actor has an explicit position.</para>
 *     <orderedlist>
 *       <listitem><simpara>The #ClutterRectangle with #ClutterActor:name
 *       <emphasis>layerA</emphasis> is explicitly sized to 100 pixels by 25
 *       pixels, and it's added to the #ClutterStage;</simpara></listitem>
 *       <listitem><simpara>two #ClutterAlignConstraint<!-- -->s are used
 *       to anchor <emphasis>layerA</emphasis> to the center of the stage,
 *       by using 0.5 as the alignment #ClutterAlignConstraint:factor on
 *       both the X and Y axis.</simpara></listitem>
 *       <listitem><simpara>the #ClutterRectangle with #ClutterActor:name
 *       <emphasis>layerB</emphasis> is added to the #ClutterStage with
 *       no explicit size;</simpara></listitem>
 *       <listitem><simpara>the #ClutterActor:x and #ClutterActor:width
 *       of <emphasis>layerB</emphasis> are bound to the same properties
 *       of <emphasis>layerA</emphasis> using two #ClutterBindConstraint
 *       objects, thus keeping <emphasis>layerB</emphasis> aligned to
 *       <emphasis>layerA</emphasis>;</simpara></listitem>
 *       <listitem><simpara>the top edge of <emphasis>layerB</emphasis> is
 *       snapped together with the bottom edge of <emphasis>layerA</emphasis>;
 *       the bottom edge of <emphasis>layerB</emphasis> is also snapped
 *       together with the bottom edge of the #ClutterStage; an offset is
 *       given to the two #ClutterSnapConstraint<!-- -->s to allow for some
 *       padding; since <emphasis>layerB</emphasis> is snapped between two
 *       different #ClutterActor<!-- -->s, its height is stretched to match
 *       the gap;</simpara></listitem>
 *       <listitem><simpara>the #ClutterRectangle with #ClutterActor:name
 *       <emphasis>layerC</emphasis> mirrors <emphasis>layerB</emphasis>,
 *       snapping the top edge of the #ClutterStage to the top edge of
 *       <emphasis>layerC</emphasis> and the top edge of
 *       <emphasis>layerA</emphasis> to the bottom edge of
 *       <emphasis>layerC</emphasis>;</simpara></listitem>
 *     </orderedlist>
 *     <figure id="constraints-example">
 *       <title>Constraints</title>
 *       <graphic fileref="constraints-example.png" format="PNG"/>
 *     </figure>
 *     <programlisting>
 *<xi:include xmlns:xi="http://www.w3.org/2001/XInclude" href="../../../../tests/interactive/test-snap-constraint.c" parse="text"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include>
 *     </programlisting>
 *     <para>You can try resizing interactively the #ClutterStage and verify
 *     that the three #ClutterActor<!-- -->s maintain the same position and
 *     size relative to each other, and to the #ClutterStage.</para>
 *   </example>
 *   <warning><para>It's important to note that Clutter does not avoid loops
 *   or competing constraints; if two or more #ClutterConstraint<!-- -->s
 *   are operating on the same positional or dimensional attributes of an
 *   actor, or if the constraints on two different actors depend on each
 *   other, then the behavior is undefined.</para></warning>
 * </refsect2>
 *
 * <refsect2 id="ClutterConstraint-implementation">
 *   <title>Implementing a ClutterConstraint</title>
 *   <para>Creating a sub-class of #ClutterConstraint requires the
 *   implementation of the <function>update_allocation()</function>
 *   virtual function.</para>
 *   <para>The <function>update_allocation()</function> virtual function
 *   is called during the allocation sequence of a #ClutterActor, and
 *   allows any #ClutterConstraint attached to that actor to modify the
 *   allocation before it is passed to the <function>allocate()</function>
 *   implementation.</para>
 *   <para>The #ClutterActorBox passed to the
 *   <function>update_allocation()</function> implementation contains the
 *   original allocation of the #ClutterActor, plus the eventual modifications
 *   applied by the other #ClutterConstraint<!-- -->s.</para>
 *   <note><para>Constraints are queried in the same order as they were
 *   applied using clutter_actor_add_constraint() or
 *   clutter_actor_add_constraint_with_name().</para></note>
 *   <para>It is not necessary for a #ClutterConstraint sub-class to chain
 *   up to the parent's implementation.</para>
 *   <para>If a #ClutterConstraint is parametrized - i.e. if it contains
 *   properties that affect the way the constraint is implemented - it should
 *   call clutter_actor_queue_relayout() on the actor to which it is attached
 *   to whenever any parameter is changed. The actor to which it is attached
 *   can be recovered at any point using clutter_actor_meta_get_actor().</para>
 * </refsect2>
 *
 * #ClutterConstraint is available since Clutter 1.4
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>

#include "clutter-constraint.h"

#include "clutter-actor.h"
#include "clutter-actor-meta-private.h"
#include "clutter-private.h"

G_DEFINE_ABSTRACT_TYPE (ClutterConstraint,
                        clutter_constraint,
                        CLUTTER_TYPE_ACTOR_META);

static void
constraint_update_allocation (ClutterConstraint *constraint,
                              ClutterActor      *actor,
                              ClutterActorBox   *allocation)
{
}

static void
clutter_constraint_notify (GObject    *gobject,
                           GParamSpec *pspec)
{
  if (strcmp (pspec->name, "enabled") == 0)
    {
      ClutterActorMeta *meta = CLUTTER_ACTOR_META (gobject);
      ClutterActor *actor = clutter_actor_meta_get_actor (meta);

      if (actor != NULL)
        clutter_actor_queue_relayout (actor);
    }

  if (G_OBJECT_CLASS (clutter_constraint_parent_class)->notify != NULL)
    G_OBJECT_CLASS (clutter_constraint_parent_class)->notify (gobject, pspec);
}

static void
clutter_constraint_class_init (ClutterConstraintClass *klass)
{
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);

  gobject_class->notify = clutter_constraint_notify;

  klass->update_allocation = constraint_update_allocation;
}

static void
clutter_constraint_init (ClutterConstraint *self)
{
}

void
_clutter_constraint_update_allocation (ClutterConstraint *constraint,
                                       ClutterActor      *actor,
                                       ClutterActorBox   *allocation)
{
  g_return_if_fail (CLUTTER_IS_CONSTRAINT (constraint));
  g_return_if_fail (CLUTTER_IS_ACTOR (actor));
  g_return_if_fail (allocation != NULL);

  CLUTTER_CONSTRAINT_GET_CLASS (constraint)->update_allocation (constraint,
                                                                actor,
                                                                allocation);
}