File: test-scrolling.c

package info (click to toggle)
clutter-1.0 1.26.4%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 34,352 kB
  • sloc: ansic: 128,533; sh: 5,580; xml: 1,641; makefile: 1,613; ruby: 149; perl: 142; sed: 16
file content (134 lines) | stat: -rw-r--r-- 4,250 bytes parent folder | download | duplicates (13)
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
#include <stdlib.h>
#include <math.h>
#include <gmodule.h>
#include <clutter/clutter.h>

#define RECT_WIDTH      400
#define RECT_HEIGHT     300
#define N_RECTS         7

static const gchar *rect_color[N_RECTS] = {
  "#edd400",
  "#f57900",
  "#c17d11",
  "#73d216",
  "#3465a4",
  "#75507b",
  "#cc0000"
};

static ClutterActor *rectangle[N_RECTS]; 
static ClutterActor *viewport = NULL;

static void
on_drag_end (ClutterDragAction   *action,
             ClutterActor        *actor,
             gfloat               event_x,
             gfloat               event_y,
             ClutterModifierType  modifiers)
{
  gfloat viewport_x = clutter_actor_get_x (viewport);
  gfloat offset_x;
  gint child_visible;

  /* check if we're at the viewport edges */
  if (viewport_x > 0)
    {
      clutter_actor_save_easing_state (viewport);
      clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE);
      clutter_actor_set_x (viewport, 0);
      clutter_actor_restore_easing_state (viewport);
      return;
    }

  if (viewport_x < (-1.0f * (RECT_WIDTH * (N_RECTS - 1))))
    {
      clutter_actor_save_easing_state (viewport);
      clutter_actor_set_easing_mode (viewport, CLUTTER_EASE_OUT_BOUNCE);
      clutter_actor_set_x (viewport, -1.0f * (RECT_WIDTH * (N_RECTS - 1)));
      clutter_actor_restore_easing_state (viewport);
      return;
    }

  /* animate the viewport to fully show the child once we pass
   * a certain threshold with the dragging action
   */
  offset_x = fabsf (viewport_x) / RECT_WIDTH + 0.5f;
  if (offset_x > (RECT_WIDTH * 0.33))
    child_visible = (int) offset_x + 1;
  else
    child_visible = (int) offset_x;

  /* sanity check on the children number */
  child_visible = CLAMP (child_visible, 0, N_RECTS);

  clutter_actor_save_easing_state (viewport);
  clutter_actor_set_x (viewport, -1.0f * RECT_WIDTH * child_visible);
  clutter_actor_restore_easing_state (viewport);
}

G_MODULE_EXPORT int
test_scrolling_main (int argc, char *argv[])
{
  ClutterActor *stage;
  ClutterActor *scroll;
  ClutterAction *action;
  gint i;

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

  stage = clutter_stage_new ();
  clutter_stage_set_title (CLUTTER_STAGE (stage), "Scrolling");
  clutter_actor_set_size (stage, 800, 600);
  g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

  /* scroll: the group that contains the scrolling viewport; we set its
   * size to be the same as one rectangle, position it in the middle of
   * the stage and set it to clip its contents to the allocated size
   */
  scroll = clutter_actor_new ();
  clutter_actor_add_child (stage, scroll);
  clutter_actor_set_size (scroll, RECT_WIDTH, RECT_HEIGHT);
  clutter_actor_add_constraint (scroll, clutter_align_constraint_new (stage, CLUTTER_ALIGN_BOTH, 0.5));
  clutter_actor_set_clip_to_allocation (scroll, TRUE);

  /* viewport: the actual container for the children; we scroll it using
   * the Drag action constrained to the horizontal axis, and every time
   * the dragging ends we check whether we're dragging past the end of
   * the viewport
   */
  viewport = clutter_actor_new ();
  clutter_actor_set_layout_manager (viewport, clutter_box_layout_new ());
  clutter_actor_add_child (scroll, viewport);

  /* add dragging capabilities to the viewport; the heavy lifting is
   * all done by the DragAction itself, plus the ::drag-end signal
   * handler in our code
   */
  action = clutter_drag_action_new ();
  clutter_actor_add_action (viewport, action);
  clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action),
                                     CLUTTER_DRAG_X_AXIS);
  g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
  clutter_actor_set_reactive (viewport, TRUE);

  /* children of the viewport */
  for (i = 0; i < N_RECTS; i++)
    {
      ClutterColor color;

      clutter_color_from_string (&color, rect_color[i]);

      rectangle[i] = clutter_actor_new ();
      clutter_actor_set_background_color (rectangle[i], &color);
      clutter_actor_add_child (viewport, rectangle[i]);
      clutter_actor_set_size (rectangle[i], RECT_WIDTH, RECT_HEIGHT);
    }

  clutter_actor_show (stage);

  clutter_main ();

  return EXIT_SUCCESS;
}