mirror of
https://github.com/brl/mutter.git
synced 2024-12-25 20:32:16 +00:00
4fd74e71e6
DragAction is an Action sub-class that provides dragging capabilities to any actor. DragAction has: • drag-begin, drag-motion and drag-end signals, relaying the event information like coordinates, button and modifiers to user code; • drag-threshold property, for delaying the drag start by a given amount of pixels; • drag-handle property, to allow using other actors as the drag handle. • drag-axis property, to allow constraining the dragging to a specific axis. An interactive test demonstrating the various features is also provided.
190 lines
5.4 KiB
C
190 lines
5.4 KiB
C
#include <stdlib.h>
|
|
#include <gmodule.h>
|
|
#include <clutter/clutter.h>
|
|
|
|
static void
|
|
on_drag_begin (ClutterDragAction *action,
|
|
ClutterActor *actor,
|
|
gfloat event_x,
|
|
gfloat event_y,
|
|
gint button,
|
|
ClutterModifierType modifiers)
|
|
{
|
|
gboolean is_copy = (modifiers & CLUTTER_SHIFT_MASK) ? TRUE : FALSE;
|
|
ClutterActor *drag_handle = NULL;
|
|
|
|
if (is_copy)
|
|
{
|
|
ClutterActor *stage = clutter_actor_get_stage (actor);
|
|
ClutterColor handle_color;
|
|
|
|
drag_handle = clutter_rectangle_new ();
|
|
clutter_actor_set_size (drag_handle, 48, 48);
|
|
|
|
clutter_color_from_string (&handle_color, "#204a87aa");
|
|
clutter_rectangle_set_color (CLUTTER_RECTANGLE (drag_handle), &handle_color);
|
|
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), drag_handle);
|
|
clutter_actor_set_position (drag_handle, event_x, event_y);
|
|
}
|
|
else
|
|
drag_handle = actor;
|
|
|
|
clutter_drag_action_set_drag_handle (action, drag_handle);
|
|
|
|
clutter_actor_set_opacity (actor, 128);
|
|
}
|
|
|
|
static void
|
|
on_drag_motion (ClutterDragAction *action,
|
|
ClutterActor *actor,
|
|
gfloat delta_x,
|
|
gfloat delta_y,
|
|
ClutterModifierType modifiers)
|
|
{
|
|
ClutterActor *drag_handle;
|
|
|
|
drag_handle = clutter_drag_action_get_drag_handle (action);
|
|
g_assert (drag_handle != NULL);
|
|
|
|
clutter_actor_move_by (drag_handle, delta_x, delta_y);
|
|
}
|
|
|
|
static void
|
|
on_drag_end (ClutterDragAction *action,
|
|
ClutterActor *actor,
|
|
gfloat event_x,
|
|
gfloat event_y,
|
|
gint button,
|
|
ClutterModifierType modifiers)
|
|
{
|
|
ClutterActor *drag_handle;
|
|
|
|
drag_handle = clutter_drag_action_get_drag_handle (action);
|
|
if (actor != drag_handle)
|
|
{
|
|
gfloat real_x, real_y;
|
|
ClutterActor *parent;
|
|
|
|
/* if we are dragging a copy we can destroy the copy now
|
|
* and animate the real actor to the drop coordinates,
|
|
* transformed in the parent's coordinate space
|
|
*/
|
|
clutter_actor_animate (drag_handle, CLUTTER_LINEAR, 150,
|
|
"opacity", 0,
|
|
"signal-swapped-after::completed",
|
|
G_CALLBACK (clutter_actor_destroy),
|
|
drag_handle,
|
|
NULL);
|
|
|
|
parent = clutter_actor_get_parent (actor);
|
|
clutter_actor_transform_stage_point (parent, event_x, event_y,
|
|
&real_x,
|
|
&real_y);
|
|
|
|
clutter_actor_animate (actor, CLUTTER_EASE_OUT_CUBIC, 150,
|
|
"opacity", 255,
|
|
"x", real_x,
|
|
"y", real_y,
|
|
NULL);
|
|
}
|
|
else
|
|
clutter_actor_animate (actor, CLUTTER_LINEAR, 150,
|
|
"opacity", 255,
|
|
NULL);
|
|
}
|
|
|
|
static ClutterDragAxis
|
|
get_drag_axis (const gchar *str)
|
|
{
|
|
if (str == NULL || *str == '\0')
|
|
return CLUTTER_DRAG_AXIS_NONE;
|
|
|
|
if (*str == 'x' || *str == 'X')
|
|
return CLUTTER_DRAG_X_AXIS;
|
|
|
|
if (*str == 'y' || *str == 'Y')
|
|
return CLUTTER_DRAG_Y_AXIS;
|
|
|
|
g_warn_if_reached ();
|
|
|
|
return CLUTTER_DRAG_AXIS_NONE;
|
|
}
|
|
|
|
static gchar *drag_axis = NULL;
|
|
static gint drag_threshold = 0;
|
|
|
|
static GOptionEntry entries[] = {
|
|
{
|
|
"threshold", 't',
|
|
0,
|
|
G_OPTION_ARG_INT,
|
|
&drag_threshold,
|
|
"Set the drag threshold", "PIXELS"
|
|
},
|
|
{
|
|
"axis", 'a',
|
|
0,
|
|
G_OPTION_ARG_STRING,
|
|
&drag_axis,
|
|
"Set the drag axis", "AXIS"
|
|
},
|
|
|
|
{ NULL }
|
|
};
|
|
|
|
G_MODULE_EXPORT int
|
|
test_drag_main (int argc, char *argv[])
|
|
{
|
|
ClutterActor *stage, *handle;
|
|
ClutterAction *action;
|
|
ClutterColor handle_color;
|
|
GError *error;
|
|
|
|
error = NULL;
|
|
clutter_init_with_args (&argc, &argv,
|
|
"test-drag",
|
|
entries,
|
|
NULL,
|
|
&error);
|
|
if (error != NULL)
|
|
{
|
|
g_print ("Unable to run test-drag: %s\n", error->message);
|
|
g_error_free (error);
|
|
|
|
return EXIT_FAILURE;
|
|
}
|
|
|
|
stage = clutter_stage_new ();
|
|
clutter_stage_set_title (CLUTTER_STAGE (stage), "Drag Test");
|
|
clutter_actor_set_size (stage, 800, 600);
|
|
g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
|
|
|
|
clutter_color_from_string (&handle_color, "#729fcfff");
|
|
|
|
handle = clutter_rectangle_new ();
|
|
clutter_rectangle_set_color (CLUTTER_RECTANGLE (handle), &handle_color);
|
|
clutter_actor_set_size (handle, 128, 128);
|
|
clutter_actor_set_position (handle, (800 - 128) / 2, (600 - 128) / 2);
|
|
clutter_actor_set_reactive (handle, TRUE);
|
|
clutter_container_add_actor (CLUTTER_CONTAINER (stage), handle);
|
|
|
|
action = clutter_drag_action_new ();
|
|
clutter_drag_action_set_drag_threshold (CLUTTER_DRAG_ACTION (action),
|
|
drag_threshold);
|
|
clutter_drag_action_set_drag_axis (CLUTTER_DRAG_ACTION (action),
|
|
get_drag_axis (drag_axis));
|
|
|
|
g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL);
|
|
g_signal_connect (action, "drag-motion", G_CALLBACK (on_drag_motion), NULL);
|
|
g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
|
|
|
|
clutter_actor_add_action (handle, action);
|
|
|
|
clutter_actor_show (stage);
|
|
|
|
clutter_main ();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|