ClutterBinLayout

ClutterBinLayout — A simple layout manager

Synopsis

enum                ClutterBinAlignment;
struct              ClutterBinLayout;
struct              ClutterBinLayoutClass;
ClutterLayoutManager * clutter_bin_layout_new           (ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);
void                clutter_bin_layout_set_alignment    (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);
void                clutter_bin_layout_get_alignment    (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment *x_align,
                                                         ClutterBinAlignment *y_align);
void                clutter_bin_layout_add              (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);

Object Hierarchy

  GObject
   +----GInitiallyUnowned
         +----ClutterLayoutManager
               +----ClutterBinLayout

Properties

  "x-align"                  ClutterBinAlignment   : Read / Write
  "y-align"                  ClutterBinAlignment   : Read / Write

Description

ClutterBinLayout is a layout manager which implements the following policy:

  • the preferred size is the maximum preferred size between all the children of the container using the layout;
  • each child is allocated in "layers", on on top of the other;
  • for each layer there are horizontal and vertical alignment policies.

Figure 4. Bin layout

The image shows a ClutterBinLayout with three layers: a background ClutterCairoTexture, set to fill on both the X and Y axis; a ClutterTexture, set to center on both the X and Y axis; and a ClutterRectangle, set to CLUTTER_BIN_ALIGNMENT_END on both the X and Y axis.

Bin layout


Example 4. How to pack actors inside a BinLayout

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
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
#include <stdlib.h>
#include <cairo.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <clutter/clutter.h>

static const ClutterColor bg_color = { 0xcc, 0xcc, 0xcc, 0x99 };

static gboolean is_expanded = FALSE;

static gboolean
on_canvas_draw (ClutterCanvas *canvas,
                cairo_t      *cr,
                gint          width,
                gint          height)
{
  cairo_pattern_t *pat;
  gfloat x, y;

  g_print (G_STRLOC ": Painting at %d x %d\n", width, height);

  cairo_save (cr);
  cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
  cairo_paint (cr);
  cairo_restore (cr);

#define BG_ROUND_RADIUS         12

  x = y = 0;

  cairo_move_to (cr, BG_ROUND_RADIUS, y);
  cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
  cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
  cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
  cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
  cairo_line_to (cr, BG_ROUND_RADIUS, height);
  cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
  cairo_line_to (cr, x, BG_ROUND_RADIUS);
  cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);

  cairo_close_path (cr);

  clutter_cairo_set_source_color (cr, &bg_color);
  cairo_stroke (cr);

  x += 4;
  y += 4;
  width -= 4;
  height -= 4;

  cairo_move_to (cr, BG_ROUND_RADIUS, y);
  cairo_line_to (cr, width - BG_ROUND_RADIUS, y);
  cairo_curve_to (cr, width, y, width, y, width, BG_ROUND_RADIUS);
  cairo_line_to (cr, width, height - BG_ROUND_RADIUS);
  cairo_curve_to (cr, width, height, width, height, width - BG_ROUND_RADIUS, height);
  cairo_line_to (cr, BG_ROUND_RADIUS, height);
  cairo_curve_to (cr, x, height, x, height, x, height - BG_ROUND_RADIUS);
  cairo_line_to (cr, x, BG_ROUND_RADIUS);
  cairo_curve_to (cr, x, y, x, y, BG_ROUND_RADIUS, y);

  cairo_close_path (cr);

  pat = cairo_pattern_create_linear (0, 0, 0, height);
  cairo_pattern_add_color_stop_rgba (pat, 1, .85, .85, .85, 1);
  cairo_pattern_add_color_stop_rgba (pat, .95, 1, 1, 1, 1);
  cairo_pattern_add_color_stop_rgba (pat, .05, 1, 1, 1, 1);
  cairo_pattern_add_color_stop_rgba (pat, 0, .85, .85, .85, 1);

  cairo_set_source (cr, pat);
  cairo_fill (cr);

  cairo_pattern_destroy (pat);

#undef BG_ROUND_RADIUS

  return TRUE;
}

static gboolean
on_box_enter (ClutterActor *box,
              ClutterEvent *event,
              ClutterActor *emblem)
{
  /* we ease the opacity linearly */
  clutter_actor_save_easing_state (emblem);
  clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR);
  clutter_actor_set_opacity (emblem, 255);
  clutter_actor_restore_easing_state (emblem);

  return CLUTTER_EVENT_STOP;
}

static gboolean
on_box_leave (ClutterActor *box,
              ClutterEvent *event,
              ClutterActor *emblem)
{
  clutter_actor_save_easing_state (emblem);
  clutter_actor_set_easing_mode (emblem, CLUTTER_LINEAR);
  clutter_actor_set_opacity (emblem, 0);
  clutter_actor_restore_easing_state (emblem);

  return CLUTTER_EVENT_STOP;
}

static void
on_emblem_clicked (ClutterClickAction *action,
                   ClutterActor       *emblem,
                   ClutterActor       *box)
{
  /* we add a little bounce to the resizing of the box */
  clutter_actor_save_easing_state (box);
  clutter_actor_set_easing_mode (box, CLUTTER_EASE_OUT_BOUNCE);
  clutter_actor_set_easing_duration (box, 500);

  if (!is_expanded)
    clutter_actor_set_size (box, 400, 400);
  else
    clutter_actor_set_size (box, 200, 200);

  clutter_actor_restore_easing_state (box);

  is_expanded = !is_expanded;
}

static gboolean
on_emblem_long_press (ClutterClickAction    *action,
                      ClutterActor          *emblem,
                      ClutterLongPressState  state,
                      ClutterActor          *box)
{
  switch (state)
    {
    case CLUTTER_LONG_PRESS_QUERY:
      g_print ("*** long press: query ***\n");
      return is_expanded;

    case CLUTTER_LONG_PRESS_CANCEL:
      g_print ("*** long press: cancel ***\n");
      break;

    case CLUTTER_LONG_PRESS_ACTIVATE:
      g_print ("*** long press: activate ***\n");
      break;
    }

  return TRUE;
}

static void
redraw_canvas (ClutterActor  *actor,
               ClutterCanvas *canvas)
{
  /* we want to invalidate the canvas and redraw its contents
   * only when the size changes at the end of the animation,
   * to avoid drawing all the states inbetween
   */
  clutter_canvas_set_size (canvas,
                           clutter_actor_get_width (actor),
                           clutter_actor_get_height (actor));
}

int
main (int argc, char *argv[])
{
  ClutterActor *stage, *box, *bg, *icon, *emblem, *label;
  ClutterLayoutManager *layout;
  ClutterContent *canvas, *image;
  ClutterColor *color;
  ClutterAction *action;
  GdkPixbuf *pixbuf;

  if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
    return 1;

  /* prepare the stage */
  stage = clutter_stage_new ();
  clutter_stage_set_title (CLUTTER_STAGE (stage), "BinLayout");
  clutter_actor_set_background_color (stage, CLUTTER_COLOR_Aluminium2);
  clutter_actor_set_size (stage, 640, 480);
  clutter_actor_show (stage);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  /* this is our BinLayout, with its default alignments */
  layout = clutter_bin_layout_new (CLUTTER_BIN_ALIGNMENT_CENTER,
                                   CLUTTER_BIN_ALIGNMENT_CENTER);

  /* the main container; this actor will use the BinLayout to lay
   * out its children; we use the anchor point to keep it centered
   * on the same position even when we change its size
   */
  box = clutter_actor_new ();
  clutter_actor_set_layout_manager (box, layout);
  clutter_actor_add_constraint (box, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
  clutter_actor_set_position (box, 320, 240);
  clutter_actor_set_reactive (box, TRUE);
  clutter_actor_set_name (box, "box");
  clutter_actor_add_child (stage, box);

  /* the background is drawn using a canvas content */
  canvas = clutter_canvas_new ();
  g_signal_connect (canvas, "draw", G_CALLBACK (on_canvas_draw), NULL);
  clutter_canvas_set_size (CLUTTER_CANVAS (canvas), 200, 200);

  /* this is the background actor; we want it to fill the whole
   * of the allocation given to it by its parent
   */
  bg = clutter_actor_new ();
  clutter_actor_set_name (bg, "background");
  clutter_actor_set_size (bg, 200, 200);
  clutter_actor_set_content (bg, canvas);
  clutter_actor_set_x_expand (bg, TRUE);
  clutter_actor_set_y_expand (bg, TRUE);
  clutter_actor_set_x_align (bg, CLUTTER_ACTOR_ALIGN_FILL);
  clutter_actor_set_y_align (bg, CLUTTER_ACTOR_ALIGN_FILL);
  clutter_actor_add_child (box, bg);
  /* we use the ::transitions-completed signal to get notification
   * of the end of the sizing animation; this allows us to redraw
   * the canvas only once the animation has stopped
   */
  g_signal_connect (box, "transitions-completed",
                    G_CALLBACK (redraw_canvas),
                    canvas);

  /* we use GdkPixbuf to load an image from our data directory */
  pixbuf = gdk_pixbuf_new_from_file (TESTS_DATADIR G_DIR_SEPARATOR_S "redhand.png", NULL);
  image = clutter_image_new ();
  clutter_image_set_data (CLUTTER_IMAGE (image),
                          gdk_pixbuf_get_pixels (pixbuf),
                          gdk_pixbuf_get_has_alpha (pixbuf)
                            ? COGL_PIXEL_FORMAT_RGBA_8888
                            : COGL_PIXEL_FORMAT_RGB_888,
                          gdk_pixbuf_get_width (pixbuf),
                          gdk_pixbuf_get_height (pixbuf),
                          gdk_pixbuf_get_rowstride (pixbuf),
                          NULL);
  g_object_unref (pixbuf);

  /* this is the icon; it's going to be centered inside the box actor.
   * we use the content gravity to keep the aspect ratio of the image,
   * and the scaling filters to get a better result when scaling the
   * image down.
   */
  icon = clutter_actor_new ();
  clutter_actor_set_name (icon, "icon");
  clutter_actor_set_size (icon, 196, 196);
  clutter_actor_set_x_expand (icon, TRUE);
  clutter_actor_set_y_expand (icon, TRUE);
  clutter_actor_set_x_align (icon, CLUTTER_ACTOR_ALIGN_CENTER);
  clutter_actor_set_y_align (icon, CLUTTER_ACTOR_ALIGN_CENTER);
  clutter_actor_set_content_gravity (icon, CLUTTER_CONTENT_GRAVITY_RESIZE_ASPECT);
  clutter_actor_set_content_scaling_filters (icon,
                                             CLUTTER_SCALING_FILTER_TRILINEAR,
                                             CLUTTER_SCALING_FILTER_LINEAR);
  clutter_actor_set_content (icon, image);
  clutter_actor_add_child (box, icon);

  color = clutter_color_new (g_random_int_range (0, 255),
                             g_random_int_range (0, 255),
                             g_random_int_range (0, 255),
                             224);

  /* this is the emblem: a small rectangle with a random color, that we
   * want to put in the bottom right corner
   */
  emblem = clutter_actor_new ();
  clutter_actor_set_name (emblem, "emblem");
  clutter_actor_set_size (emblem, 48, 48);
  clutter_actor_set_background_color (emblem, color);
  clutter_actor_set_x_expand (emblem, TRUE);
  clutter_actor_set_y_expand (emblem, TRUE);
  clutter_actor_set_x_align (emblem, CLUTTER_ACTOR_ALIGN_END);
  clutter_actor_set_y_align (emblem, CLUTTER_ACTOR_ALIGN_END);
  clutter_actor_set_reactive (emblem, TRUE);
  clutter_actor_set_opacity (emblem, 0);
  clutter_actor_add_child (box, emblem);
  clutter_color_free (color);

  /* when clicking on the emblem, we want to perform an action */
  action = clutter_click_action_new ();
  clutter_actor_add_action (emblem, action);
  g_signal_connect (action, "clicked", G_CALLBACK (on_emblem_clicked), box);
  g_signal_connect (action, "long-press", G_CALLBACK (on_emblem_long_press), box);

  /* whenever the pointer enters the box, we show the emblem; we hide
   * the emblem when the pointer leaves the box
   */
  g_signal_connect (box,
                    "enter-event", G_CALLBACK (on_box_enter),
                    emblem);
  g_signal_connect (box,
                    "leave-event", G_CALLBACK (on_box_leave),
                    emblem);

  /* a label, that we want to position at the top and center of the box */
  label = clutter_text_new ();
  clutter_actor_set_name (label, "text");
  clutter_text_set_text (CLUTTER_TEXT (label), "A simple test");
  clutter_actor_set_x_expand (label, TRUE);
  clutter_actor_set_x_align (label, CLUTTER_ACTOR_ALIGN_CENTER);
  clutter_actor_set_y_expand (label, TRUE);
  clutter_actor_set_y_align (label, CLUTTER_ACTOR_ALIGN_START);
  clutter_actor_add_child (box, label);

  clutter_main ();

  return EXIT_SUCCESS;
}


ClutterBinLayout is available since Clutter 1.2

Details

enum ClutterBinAlignment

typedef enum {
  CLUTTER_BIN_ALIGNMENT_FIXED,
  CLUTTER_BIN_ALIGNMENT_FILL,
  CLUTTER_BIN_ALIGNMENT_START,
  CLUTTER_BIN_ALIGNMENT_END,
  CLUTTER_BIN_ALIGNMENT_CENTER
} ClutterBinAlignment;

Warning

ClutterBinAlignment has been deprecated since version 1.12 and should not be used in newly-written code. Use ClutterActorAlign and the ClutterActor API instead

The alignment policies available on each axis for ClutterBinLayout

CLUTTER_BIN_ALIGNMENT_FIXED

Fixed position alignment; the ClutterBinLayout will honour the fixed position provided by the actors themselves when allocating them

CLUTTER_BIN_ALIGNMENT_FILL

Fill the allocation size

CLUTTER_BIN_ALIGNMENT_START

Position the actors at the top or left side of the container, depending on the axis

CLUTTER_BIN_ALIGNMENT_END

Position the actors at the bottom or right side of the container, depending on the axis

CLUTTER_BIN_ALIGNMENT_CENTER

Position the actors at the center of the container, depending on the axis

Since 1.2


struct ClutterBinLayout

struct ClutterBinLayout;

The ClutterBinLayout structure contains only private data and should be accessed using the provided API

Since 1.2


struct ClutterBinLayoutClass

struct ClutterBinLayoutClass {
};

The ClutterBinLayoutClass structure contains only private data and should be accessed using the provided API

Since 1.2


clutter_bin_layout_new ()

ClutterLayoutManager * clutter_bin_layout_new           (ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);

Creates a new ClutterBinLayout layout manager

x_align :

the default alignment policy to be used on the horizontal axis

y_align :

the default alignment policy to be used on the vertical axis

Returns :

the newly created layout manager

Since 1.2


clutter_bin_layout_set_alignment ()

void                clutter_bin_layout_set_alignment    (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);

Warning

clutter_bin_layout_set_alignment has been deprecated since version 1.12 and should not be used in newly-written code. Use the "x-align" and "y-align" properties of ClutterActor instead.

Sets the horizontal and vertical alignment policies to be applied to a child of self

If child is NULL then the x_align and y_align values will be set as the default alignment policies

self :

a ClutterBinLayout

child :

a child of container. [allow-none]

x_align :

the horizontal alignment policy to be used for the child inside container

y_align :

the vertical aligment policy to be used on the child inside container

Since 1.2


clutter_bin_layout_get_alignment ()

void                clutter_bin_layout_get_alignment    (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment *x_align,
                                                         ClutterBinAlignment *y_align);

Warning

clutter_bin_layout_get_alignment has been deprecated since version 1.12 and should not be used in newly-written code. Use the "x-align" and the "y-align" properties of ClutterActor instead.

Retrieves the horizontal and vertical alignment policies for a child of self

If child is NULL the default alignment policies will be returned instead

self :

a ClutterBinLayout

child :

a child of container. [allow-none]

x_align :

return location for the horizontal alignment policy. [out][allow-none]

y_align :

return location for the vertical alignment policy. [out][allow-none]

Since 1.2


clutter_bin_layout_add ()

void                clutter_bin_layout_add              (ClutterBinLayout *self,
                                                         ClutterActor *child,
                                                         ClutterBinAlignment x_align,
                                                         ClutterBinAlignment y_align);

Warning

clutter_bin_layout_add has been deprecated since version 1.12 and should not be used in newly-written code. Use clutter_actor_add_child() instead.

Adds a ClutterActor to the container using self and sets the alignment policies for it

This function is equivalent to clutter_container_add_actor() and clutter_layout_manager_child_set_property() but it does not require a pointer to the ClutterContainer associated to the ClutterBinLayout

self :

a ClutterBinLayout

child :

a ClutterActor

x_align :

horizontal alignment policy for child

y_align :

vertical alignment policy for child

Since 1.2

Property Details

The "x-align" property

  "x-align"                  ClutterBinAlignment   : Read / Write

Warning

ClutterBinLayout:x-align has been deprecated since version 1.12 and should not be used in newly-written code. Use the "x-expand" and the "x-align" properties on ClutterActor instead.

The default horizontal alignment policy for actors managed by the ClutterBinLayout

Default value: CLUTTER_BIN_ALIGNMENT_CENTER

Since 1.2


The "y-align" property

  "y-align"                  ClutterBinAlignment   : Read / Write

Warning

ClutterBinLayout:y-align has been deprecated since version 1.12 and should not be used in newly-written code. Use the "y-expand" and the "y-align" properties on ClutterActor instead.

The default vertical alignment policy for actors managed by the ClutterBinLayout

Default value: CLUTTER_BIN_ALIGNMENT_CENTER

Since 1.2