1 #include <stdlib.h>
2 #include <clutter/clutter.h>
3
4 #define TARGET_SIZE 200
5 #define HANDLE_SIZE 128
6
7 static ClutterActor *stage = NULL;
8 static ClutterActor *target1 = NULL;
9 static ClutterActor *target2 = NULL;
10 static ClutterActor *drag = NULL;
11
12 static gboolean drop_successful = FALSE;
13
14 static void add_drag_object (ClutterActor *target);
15
16 static void
on_drag_end(ClutterDragAction * action,ClutterActor * actor,gfloat event_x,gfloat event_y,ClutterModifierType modifiers)17 on_drag_end (ClutterDragAction *action,
18 ClutterActor *actor,
19 gfloat event_x,
20 gfloat event_y,
21 ClutterModifierType modifiers)
22 {
23 ClutterActor *handle = clutter_drag_action_get_drag_handle (action);
24
25 g_print ("Drag ended at: %.0f, %.0f\n",
26 event_x, event_y);
27
28 clutter_actor_save_easing_state (actor);
29 clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
30 clutter_actor_set_opacity (actor, 255);
31 clutter_actor_restore_easing_state (actor);
32
33 clutter_actor_save_easing_state (handle);
34
35 if (!drop_successful)
36 {
37 ClutterActor *parent = clutter_actor_get_parent (actor);
38 gfloat x_pos, y_pos;
39
40 clutter_actor_save_easing_state (parent);
41 clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR);
42 clutter_actor_set_opacity (parent, 255);
43 clutter_actor_restore_easing_state (parent);
44
45 clutter_actor_get_transformed_position (actor, &x_pos, &y_pos);
46
47 clutter_actor_set_easing_mode (handle, CLUTTER_EASE_OUT_BOUNCE);
48 clutter_actor_set_position (handle, x_pos, y_pos);
49 clutter_actor_set_opacity (handle, 0);
50
51 }
52 else
53 {
54 clutter_actor_set_easing_mode (handle, CLUTTER_LINEAR);
55 clutter_actor_set_opacity (handle, 0);
56 }
57
58 clutter_actor_restore_easing_state (handle);
59
60 g_signal_connect (handle, "transitions-completed",
61 G_CALLBACK (clutter_actor_destroy),
62 NULL);
63 }
64
65 static void
on_drag_begin(ClutterDragAction * action,ClutterActor * actor,gfloat event_x,gfloat event_y,ClutterModifierType modifiers)66 on_drag_begin (ClutterDragAction *action,
67 ClutterActor *actor,
68 gfloat event_x,
69 gfloat event_y,
70 ClutterModifierType modifiers)
71 {
72 ClutterActor *handle;
73 gfloat x_pos, y_pos;
74
75 clutter_actor_get_position (actor, &x_pos, &y_pos);
76
77 handle = clutter_actor_new ();
78 clutter_actor_set_background_color (handle, CLUTTER_COLOR_DarkSkyBlue);
79 clutter_actor_set_size (handle, 128, 128);
80 clutter_actor_set_position (handle, event_x - x_pos, event_y - y_pos);
81 clutter_actor_add_child (stage, handle);
82
83 clutter_drag_action_set_drag_handle (action, handle);
84
85 clutter_actor_save_easing_state (actor);
86 clutter_actor_set_easing_mode (actor, CLUTTER_LINEAR);
87 clutter_actor_set_opacity (actor, 128);
88 clutter_actor_restore_easing_state (actor);
89
90 drop_successful = FALSE;
91 }
92
93 static void
add_drag_object(ClutterActor * target)94 add_drag_object (ClutterActor *target)
95 {
96 ClutterActor *parent;
97
98 if (drag == NULL)
99 {
100 ClutterAction *action;
101
102 drag = clutter_actor_new ();
103 clutter_actor_set_background_color (drag, CLUTTER_COLOR_LightSkyBlue);
104 clutter_actor_set_size (drag, HANDLE_SIZE, HANDLE_SIZE);
105 clutter_actor_set_position (drag,
106 (TARGET_SIZE - HANDLE_SIZE) / 2.0,
107 (TARGET_SIZE - HANDLE_SIZE) / 2.0);
108 clutter_actor_set_reactive (drag, TRUE);
109
110 action = clutter_drag_action_new ();
111 g_signal_connect (action, "drag-begin", G_CALLBACK (on_drag_begin), NULL);
112 g_signal_connect (action, "drag-end", G_CALLBACK (on_drag_end), NULL);
113
114 clutter_actor_add_action (drag, action);
115 }
116
117 parent = clutter_actor_get_parent (drag);
118 if (parent == target)
119 {
120 clutter_actor_save_easing_state (target);
121 clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
122 clutter_actor_set_opacity (target, 255);
123 clutter_actor_restore_easing_state (target);
124 return;
125 }
126
127 g_object_ref (drag);
128 if (parent != NULL && parent != stage)
129 {
130 clutter_actor_remove_child (parent, drag);
131
132 clutter_actor_save_easing_state (parent);
133 clutter_actor_set_easing_mode (parent, CLUTTER_LINEAR);
134 clutter_actor_set_opacity (parent, 64);
135 clutter_actor_restore_easing_state (parent);
136 }
137
138 clutter_actor_add_child (target, drag);
139
140 clutter_actor_save_easing_state (target);
141 clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
142 clutter_actor_set_opacity (target, 255);
143 clutter_actor_restore_easing_state (target);
144
145 g_object_unref (drag);
146 }
147
148 static void
on_target_over(ClutterDropAction * action,ClutterActor * actor,gpointer _data)149 on_target_over (ClutterDropAction *action,
150 ClutterActor *actor,
151 gpointer _data)
152 {
153 gboolean is_over = GPOINTER_TO_UINT (_data);
154 guint8 final_opacity = is_over ? 128 : 64;
155 ClutterActor *target;
156
157 target = clutter_actor_meta_get_actor (CLUTTER_ACTOR_META (action));
158
159 clutter_actor_save_easing_state (target);
160 clutter_actor_set_easing_mode (target, CLUTTER_LINEAR);
161 clutter_actor_set_opacity (target, final_opacity);
162 clutter_actor_restore_easing_state (target);
163 }
164
165 static void
on_target_drop(ClutterDropAction * action,ClutterActor * actor,gfloat event_x,gfloat event_y)166 on_target_drop (ClutterDropAction *action,
167 ClutterActor *actor,
168 gfloat event_x,
169 gfloat event_y)
170 {
171 gfloat actor_x, actor_y;
172
173 actor_x = actor_y = 0.0f;
174
175 clutter_actor_transform_stage_point (actor, event_x, event_y,
176 &actor_x,
177 &actor_y);
178
179 g_print ("Dropped at %.0f, %.0f (screen: %.0f, %.0f)\n",
180 actor_x, actor_y,
181 event_x, event_y);
182
183 drop_successful = TRUE;
184 add_drag_object (actor);
185 }
186
187 int
main(int argc,char * argv[])188 main (int argc, char *argv[])
189 {
190 ClutterActor *dummy;
191
192 if (clutter_init (&argc, &argv) != CLUTTER_INIT_SUCCESS)
193 return EXIT_FAILURE;
194
195 stage = clutter_stage_new ();
196 clutter_stage_set_title (CLUTTER_STAGE (stage), "Drop Action");
197 g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
198
199 target1 = clutter_actor_new ();
200 clutter_actor_set_background_color (target1, CLUTTER_COLOR_LightScarletRed);
201 clutter_actor_set_size (target1, TARGET_SIZE, TARGET_SIZE);
202 clutter_actor_set_opacity (target1, 64);
203 clutter_actor_add_constraint (target1, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
204 clutter_actor_set_x (target1, 10);
205 clutter_actor_set_reactive (target1, TRUE);
206
207 clutter_actor_add_action_with_name (target1, "drop", clutter_drop_action_new ());
208 g_signal_connect (clutter_actor_get_action (target1, "drop"),
209 "over-in",
210 G_CALLBACK (on_target_over),
211 GUINT_TO_POINTER (TRUE));
212 g_signal_connect (clutter_actor_get_action (target1, "drop"),
213 "over-out",
214 G_CALLBACK (on_target_over),
215 GUINT_TO_POINTER (FALSE));
216 g_signal_connect (clutter_actor_get_action (target1, "drop"),
217 "drop",
218 G_CALLBACK (on_target_drop),
219 NULL);
220
221 dummy = clutter_actor_new ();
222 clutter_actor_set_background_color (dummy, CLUTTER_COLOR_DarkOrange);
223 clutter_actor_set_size (dummy,
224 640 - (2 * 10) - (2 * (TARGET_SIZE + 10)),
225 TARGET_SIZE);
226 clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_X_AXIS, 0.5));
227 clutter_actor_add_constraint (dummy, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
228 clutter_actor_set_reactive (dummy, TRUE);
229
230 target2 = clutter_actor_new ();
231 clutter_actor_set_background_color (target2, CLUTTER_COLOR_LightChameleon);
232 clutter_actor_set_size (target2, TARGET_SIZE, TARGET_SIZE);
233 clutter_actor_set_opacity (target2, 64);
234 clutter_actor_add_constraint (target2, clutter_align_constraint_new (stage, CLUTTER_ALIGN_Y_AXIS, 0.5));
235 clutter_actor_set_x (target2, 640 - TARGET_SIZE - 10);
236 clutter_actor_set_reactive (target2, TRUE);
237
238 clutter_actor_add_action_with_name (target2, "drop", clutter_drop_action_new ());
239 g_signal_connect (clutter_actor_get_action (target2, "drop"),
240 "over-in",
241 G_CALLBACK (on_target_over),
242 GUINT_TO_POINTER (TRUE));
243 g_signal_connect (clutter_actor_get_action (target2, "drop"),
244 "over-out",
245 G_CALLBACK (on_target_over),
246 GUINT_TO_POINTER (FALSE));
247 g_signal_connect (clutter_actor_get_action (target2, "drop"),
248 "drop",
249 G_CALLBACK (on_target_drop),
250 NULL);
251
252 clutter_actor_add_child (stage, target1);
253 clutter_actor_add_child (stage, dummy);
254 clutter_actor_add_child (stage, target2);
255
256 add_drag_object (target1);
257
258 clutter_actor_show (stage);
259
260 clutter_main ();
261
262 return EXIT_SUCCESS;
263 }
264