mutter/doc/cookbook/examples/events-mouse-scroll.c

130 lines
3.6 KiB
C
Raw Normal View History

#include <clutter/clutter.h>
#define STAGE_HEIGHT 300
#define STAGE_WIDTH STAGE_HEIGHT
#define SCROLL_AMOUNT STAGE_HEIGHT * 0.125
static gboolean
_scroll_event_cb (ClutterActor *viewport,
ClutterEvent *event,
gpointer user_data)
{
ClutterActor *scrollable = CLUTTER_ACTOR (user_data);
gfloat viewport_height = clutter_actor_get_height (viewport);
gfloat scrollable_height = clutter_actor_get_height (scrollable);
gfloat y;
ClutterScrollDirection direction;
/* no need to scroll if the scrollable is shorter than the viewport */
if (scrollable_height < viewport_height)
return TRUE;
y = clutter_actor_get_y (scrollable);
direction = clutter_event_get_scroll_direction (event);
switch (direction)
{
case CLUTTER_SCROLL_UP:
y -= SCROLL_AMOUNT;
break;
case CLUTTER_SCROLL_DOWN:
y += SCROLL_AMOUNT;
break;
/* we're only interested in up and down */
case CLUTTER_SCROLL_LEFT:
case CLUTTER_SCROLL_RIGHT:
break;
}
/*
* the CLAMP macro returns a value for the first argument
* that falls within the range specified by the second and
* third arguments
*
* we allow the scrollable's y position to be decremented to the point
* where its base is aligned with the base of the viewport
*/
y = CLAMP (y,
viewport_height - scrollable_height,
0.0);
/* animate the change to the scrollable's y coordinate */
clutter_actor_animate (scrollable,
CLUTTER_EASE_OUT_CUBIC,
300,
"y", y,
NULL);
return TRUE;
}
int
main (int argc, char *argv[])
{
ClutterActor *stage;
ClutterActor *viewport;
ClutterActor *texture;
gchar *image_file_path = TESTS_DATA_DIR "/redhand.png";
if (argc > 1)
{
image_file_path = argv[1];
}
if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
return 1;
stage = clutter_stage_new ();
clutter_actor_set_size (stage, STAGE_WIDTH, STAGE_HEIGHT);
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
/* the scrollable actor */
texture = clutter_texture_new ();
clutter_texture_set_keep_aspect_ratio (CLUTTER_TEXTURE (texture),
TRUE);
/* set the texture's height so it's as tall as the stage */
clutter_actor_set_request_mode (texture, CLUTTER_REQUEST_WIDTH_FOR_HEIGHT);
clutter_actor_set_height (texture, STAGE_HEIGHT);
clutter_texture_set_from_file (CLUTTER_TEXTURE (texture),
image_file_path,
NULL);
/* the viewport which the box is scrolled within */
viewport = clutter_group_new ();
/* viewport is shorter than the stage */
clutter_actor_set_size (viewport, STAGE_WIDTH, STAGE_HEIGHT * 0.5);
/* align the viewport to the center of the stage's y axis */
clutter_actor_add_constraint (viewport, clutter_align_constraint_new (stage, CLUTTER_BIND_Y, 0.5));
/* viewport needs to respond to scroll events */
clutter_actor_set_reactive (viewport, TRUE);
/* clip all actors inside the viewport to that group's allocation */
clutter_actor_set_clip_to_allocation (viewport, TRUE);
/* put the texture inside the viewport */
clutter_container_add_actor (CLUTTER_CONTAINER (viewport), texture);
/* add the viewport to the stage */
clutter_container_add_actor (CLUTTER_CONTAINER (stage), viewport);
g_signal_connect (viewport,
"scroll-event",
G_CALLBACK (_scroll_event_cb),
texture);
clutter_actor_show (stage);
clutter_main ();
return 0;
}