Merge "Add ThemeOverlay() API in Elementary." into devel/dotnet
[platform/core/csapi/tizenfx.git] / src / ElmSharp / ElmSharp / GestureLayer.cs
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 using System;
18 using System.Runtime.InteropServices;
19 using System.Collections.Generic;
20
21 namespace ElmSharp
22 {
23     public class GestureLayer : EvasObject
24     {
25         private readonly Interop.Elementary.GestureEventCallback _gestureCallback;
26
27         // Important: don't remove items from _handlers list
28         // The list can grow up to (number of GestureType) * (number of GestureState)
29         // but all gestures share the callback and you don't want to desynchronize mapping
30         private readonly List<NativeCallback> _handlers = new List<NativeCallback>();
31
32         public GestureLayer(EvasObject parent) : base(parent)
33         {
34             _gestureCallback = new Interop.Elementary.GestureEventCallback(GestureCallbackHandler);
35         }
36
37         public enum GestureType
38         {
39             Tap = 1,
40             LongTap,
41             DoubleTap,
42             TripleTap,
43             Momentum,
44             Line,
45             Flick,
46             Zoom,
47             Rotate,
48         }
49
50         public enum GestureState
51         {
52             Undefined = -1,
53             Start,
54             Move,
55             End,
56             Abort,
57         }
58
59         #region Properties
60         public bool HoldEvents
61         {
62             get
63             {
64                 return Interop.Elementary.elm_gesture_layer_hold_events_get(Handle);
65             }
66             set
67             {
68                 Interop.Elementary.elm_gesture_layer_hold_events_set(Handle, value);
69             }
70         }
71
72         public bool Continues
73         {
74             get
75             {
76                 return Interop.Elementary.elm_gesture_layer_continues_enable_get(Handle);
77             }
78             set
79             {
80                 Interop.Elementary.elm_gesture_layer_continues_enable_set(Handle, value);
81             }
82         }
83
84         public int TapFingerSize
85         {
86             get
87             {
88                 return Interop.Elementary.elm_gesture_layer_tap_finger_size_get(Handle);
89             }
90             set
91             {
92                 Interop.Elementary.elm_gesture_layer_tap_finger_size_set(Handle, value);
93             }
94         }
95
96         public double LongTapTimeout
97         {
98             get
99             {
100                 return Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_get(Handle);
101             }
102             set
103             {
104                 Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_set(Handle, value);
105             }
106         }
107
108         public double DoubleTapTimeout
109         {
110             get
111             {
112                 return Interop.Elementary.elm_gesture_layer_double_tap_timeout_get(Handle);
113             }
114             set
115             {
116                 Interop.Elementary.elm_gesture_layer_double_tap_timeout_set(Handle, value);
117             }
118         }
119
120         public int FlickTimeLimit
121         {
122             get
123             {
124                 return (int)Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_get(Handle);
125             }
126             set
127             {
128                 Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_set(Handle, (UInt32)value);
129             }
130         }
131
132         public int MinimumLineLength
133         {
134             get
135             {
136                 return Interop.Elementary.elm_gesture_layer_line_min_length_get(Handle);
137             }
138             set
139             {
140                 Interop.Elementary.elm_gesture_layer_line_min_length_set(Handle, value);
141             }
142         }
143
144         public double LineAngularTolerance
145         {
146             get
147             {
148                 return Interop.Elementary.elm_gesture_layer_line_angular_tolerance_get(Handle);
149             }
150             set
151             {
152                 Interop.Elementary.elm_gesture_layer_line_angular_tolerance_set(Handle, value);
153             }
154         }
155
156         public int LineDistanceTolerance
157         {
158             get
159             {
160                 return Interop.Elementary.elm_gesture_layer_line_distance_tolerance_get(Handle);
161             }
162             set
163             {
164                 Interop.Elementary.elm_gesture_layer_line_distance_tolerance_set(Handle, value);
165             }
166         }
167
168         public double RotateStep
169         {
170             get
171             {
172                 return Interop.Elementary.elm_gesture_layer_rotate_step_get(Handle);
173             }
174             set
175             {
176                 Interop.Elementary.elm_gesture_layer_rotate_step_set(Handle, value);
177             }
178         }
179
180         public double RotateAngularTolerance
181         {
182             get
183             {
184                 return Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_get(Handle);
185             }
186             set
187             {
188                 Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_set(Handle, value);
189             }
190         }
191
192         public double ZoomStep
193         {
194             get
195             {
196                 return Interop.Elementary.elm_gesture_layer_zoom_step_get(Handle);
197             }
198             set
199             {
200                 Interop.Elementary.elm_gesture_layer_zoom_step_set(Handle, value);
201             }
202         }
203
204         public int ZoomDistanceTolerance
205         {
206             get
207             {
208                 return Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_get(Handle);
209             }
210             set
211             {
212                 Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_set(Handle, value);
213             }
214         }
215
216         public double ZoomFingerFactor
217         {
218             get
219             {
220                 return Interop.Elementary.elm_gesture_layer_zoom_finger_factor_get(Handle);
221             }
222             set
223             {
224                 Interop.Elementary.elm_gesture_layer_zoom_finger_factor_set(Handle, value);
225             }
226         }
227
228         public double ZoomWheelFactor
229         {
230             get
231             {
232                 return Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_get(Handle);
233             }
234             set
235             {
236                 Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_set(Handle, value);
237             }
238         }
239         #endregion Properties
240
241         public void Attach(EvasObject target)
242         {
243             Interop.Elementary.elm_gesture_layer_attach(Handle, target.Handle);
244         }
245
246         public void SetGestureCallback(GestureType type, GestureState state, Action<object> action)
247         {
248             lock (_handlers)
249             {
250                 bool found = false;
251                 int i = 0;
252                 // if this (type, state) already exists in _handlers, we will reuse it
253                 foreach (var handler in _handlers)
254                 {
255                     if (handler.Type == type && handler.State == state)
256                     {
257                         found = true;
258                         break;
259                     }
260                     i++;
261                 }
262                 if (found)
263                 {
264                     // if we are changing null -> not-null, or not-null -> null, then inform the EFL
265                     if (_handlers[i].Action == null ^ action == null)
266                         Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, action == null ? null : _gestureCallback, new IntPtr(i));
267                     // overwrite previous action
268                     _handlers[i].Action = action;
269                 }
270                 else
271                 {
272                     if (action == null)
273                     {
274                         // ignore unsetting a handler for event which was not registered yet?
275                         return;
276                     }
277                     // (type, state) was not found, so we are adding a new entry and registering the callback
278                     _handlers.Add(new NativeCallback(type, state, action));
279                     // callback is always the same, the event is recognised by the index in _handler list (the index is passed as data)
280                     Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, _gestureCallback, new IntPtr(i));
281                 }
282             }
283         }
284
285         public void ClearCallbacks()
286         {
287             lock (_handlers)
288             {
289                 int i = 0;
290                 foreach (var handler in _handlers)
291                 {
292                     if (handler.Action != null)
293                     {
294                         Interop.Elementary.elm_gesture_layer_cb_set(Handle, handler.Type, handler.State, null, new IntPtr(i));
295                         handler.Action = null;
296                     }
297                     i++;
298                 }
299             }
300         }
301
302         #region Typed callback setting methods
303         // Following methods have been added for convenience, so the user will not have to convert Info structures himself
304         public void SetTapCallback(GestureType type, GestureState state, Action<TapData> action)
305         {
306             SetCallback(type, state, action);
307         }
308
309         public void SetMomentumCallback(GestureState state, Action<MomentumData> action)
310         {
311             SetCallback(GestureType.Momentum, state, action);
312         }
313
314         public void SetLineCallback(GestureState state, Action<LineData> action)
315         {
316             SetCallback(GestureType.Line, state, action);
317         }
318
319         public void SetFlickCallback(GestureState state, Action<LineData> action)
320         {
321             SetCallback(GestureType.Flick, state, action);
322         }
323
324         public void SetZoomCallback(GestureState state, Action<ZoomData> action)
325         {
326             SetCallback(GestureType.Zoom, state, action);
327         }
328
329         public void SetRotateCallback(GestureState state, Action<RotateData> action)
330         {
331             SetCallback(GestureType.Rotate, state, action);
332         }
333         #endregion Typed callback setting methods
334
335         protected override IntPtr CreateHandle(EvasObject parent)
336         {
337             return Interop.Elementary.elm_gesture_layer_add(parent);
338         }
339
340         protected override void OnUnrealize()
341         {
342             ClearCallbacks();
343             base.OnUnrealize();
344         }
345
346         private void SetCallback<T>(GestureType type, GestureState state, Action<T> action)
347         {
348             if (action == null)
349                 SetGestureCallback(type, state, null);
350             else
351                 SetGestureCallback(type, state, new Action<object>((info) => action((T)info)));
352         }
353
354         private void GestureCallbackHandler(IntPtr data, IntPtr event_info)
355         {
356             // so EFL called our callback, lets use data to find the right Action to call
357             var handlerIndex = (int)data;
358             // thanks to the fact that we never remove item from _handlers, we don't need a lock here
359             if (handlerIndex < 0 || handlerIndex >= _handlers.Count)
360                 return;
361             Action<object> action = _handlers[handlerIndex].Action;
362             if (action == null)
363                 return;
364             // the interpretation of the event_info struct pointer depends on the GestureType
365             switch (_handlers[handlerIndex].Type)
366             {
367                 case GestureType.Tap:
368                 case GestureType.LongTap:
369                 case GestureType.DoubleTap:
370                 case GestureType.TripleTap:
371                     action(Marshal.PtrToStructure(event_info, typeof(TapData)));
372                     break;
373                 case GestureType.Momentum:
374                     action(Marshal.PtrToStructure(event_info, typeof(MomentumData)));
375                     break;
376                 case GestureType.Line:
377                 case GestureType.Flick:
378                     action(Marshal.PtrToStructure(event_info, typeof(LineData)));
379                     break;
380                 case GestureType.Zoom:
381                     action(Marshal.PtrToStructure(event_info, typeof(ZoomData)));
382                     break;
383                 case GestureType.Rotate:
384                     action(Marshal.PtrToStructure(event_info, typeof(RotateData)));
385                     break;
386             }
387         }
388
389         #region Info structures
390
391         [StructLayout(LayoutKind.Sequential)]
392         public struct TapData
393         {
394             /// <summary>
395             /// The x coordinate of the center point.
396             /// </summary>
397             public Int32 X;
398
399             /// <summary>
400             /// The y coordinate of the center point.
401             /// </summary>
402             public Int32 Y;
403
404             #pragma warning disable 3003
405             /// <summary>
406             /// The number of fingers tapped.
407             /// </summary>
408             public UInt32 FingersCount;
409
410             /// <summary>
411             /// The timestamp.
412             /// </summary>
413             public UInt32 Timestamp;
414             #pragma warning restore 3003
415         }
416
417         [StructLayout(LayoutKind.Sequential)]
418         public struct MomentumData
419         {
420             /// <summary>
421             /// Final-swipe direction starting point on X.
422             /// </summary>
423             public Int32 X1;
424
425             /// <summary>
426             /// Final-swipe direction starting point on Y.
427             /// </summary>
428             public Int32 Y1;
429
430             /// <summary>
431             /// Final-swipe direction ending point on X.
432             /// </summary>
433             public Int32 X2;
434
435             /// <summary>
436             /// Final-swipe direction ending point on Y
437             /// </summary>
438             public Int32 Y2;
439
440             #pragma warning disable 3003
441             /// <summary>
442             /// Timestamp of start of final x-swipe.
443             /// </summary>
444             public UInt32 HorizontalSwipeTimestamp;
445
446             /// <summary>
447             /// Timestamp of start of final y-swipe.
448             /// </summary>
449             public UInt32 VerticalSwipeTimestamp;
450
451             /// <summary>
452             /// Momentum on X.
453             /// </summary>
454             public Int32 HorizontalMomentum;
455
456             /// <summary>
457             /// Momentum on Y.
458             /// </summary>
459             public Int32 VerticalMomentum;
460
461             /// <summary>
462             /// Number of fingers.
463             /// </summary>
464             public UInt32 FingersCount;
465             #pragma warning restore 3003
466         }
467
468         [StructLayout(LayoutKind.Sequential)]
469         public struct LineData
470         {
471             /// <summary>
472             /// Final-swipe direction starting point on X.
473             /// </summary>
474             public Int32 X1;
475
476             /// <summary>
477             /// Final-swipe direction starting point on Y.
478             /// </summary>
479             public Int32 Y1;
480
481             /// <summary>
482             /// Final-swipe direction ending point on X.
483             /// </summary>
484             public Int32 X2;
485
486             /// <summary>
487             /// Final-swipe direction ending point on Y
488             /// </summary>
489             public Int32 Y2;
490
491             #pragma warning disable 3003
492             /// <summary>
493             /// Timestamp of start of final x-swipe.
494             /// </summary>
495             public UInt32 HorizontalSwipeTimestamp;
496
497             /// <summary>
498             /// Timestamp of start of final y-swipe.
499             /// </summary>
500             public UInt32 VerticalSwipeTimestamp;
501
502             /// <summary>
503             /// Momentum on X.
504             /// </summary>
505             public Int32 HorizontalMomentum;
506
507             /// <summary>
508             /// Momentum on Y.
509             /// </summary>
510             public Int32 VerticalMomentum;
511
512             /// <summary>
513             /// Number of fingers.
514             /// </summary>
515             public UInt32 FingersCount;
516             #pragma warning restore 3003
517
518             /// <summary>
519             /// Angle (direction) of lines.
520             /// </summary>
521             public double Angle;
522         }
523
524         [StructLayout(LayoutKind.Sequential)]
525         public struct ZoomData
526         {
527             /// <summary>
528             /// The x coordinate of zoom center point reported to user.
529             /// </summary>
530             public Int32 X;
531
532             /// <summary>
533             /// The y coordinate of zoom center point reported to user.
534             /// </summary>
535             public Int32 Y;
536
537             /// <summary>
538             /// The radius (distance) between fingers reported to user.
539             /// </summary>
540             public Int32 Radius;
541
542             /// <summary>
543             /// The zoom value. 1.0 means no zoom.
544             /// </summary>
545             public double Zoom;
546
547             /// <summary>
548             /// Zoom momentum: zoom growth per second (NOT YET SUPPORTED).
549             /// </summary>
550             private double Momentum;
551         }
552
553         [StructLayout(LayoutKind.Sequential)]
554         public struct RotateData
555         {
556             /// <summary>
557             /// The x coordinate of rotation center point reported to user.
558             /// </summary>
559             public Int32 X;
560
561             /// <summary>
562             /// The y coordinate of rotation center point reported to user.
563             /// </summary>
564             public Int32 Y;
565
566             /// <summary>
567             /// The radius (distance) between fingers reported to user.
568             /// </summary>
569             public Int32 Radius;
570
571             /// <summary>
572             /// The start-angle.
573             /// </summary>
574             public double BaseAngle;
575
576             /// <summary>
577             /// The rotation value. 0.0 means no rotation.
578             /// </summary>
579             public double Angle;
580
581             /// <summary>
582             /// Rotation momentum: rotation done per second (NOT YET SUPPORTED).
583             /// </summary>
584             private double Momentum;
585         }
586
587         #endregion Info structures
588
589         public static class Config
590         {
591             public static double DefaultLongTapTimeout
592             {
593                 get {
594                     return Interop.Elementary.elm_config_glayer_long_tap_start_timeout_get();
595                 }
596                 set {
597                     Interop.Elementary.elm_config_glayer_long_tap_start_timeout_set(value);
598                 }
599             }
600
601             public static double DefaultDoubleTapTimeout
602             {
603                 get {
604                     return Interop.Elementary.elm_config_glayer_double_tap_timeout_get();
605                 }
606                 set {
607                     Interop.Elementary.elm_config_glayer_double_tap_timeout_set(value);
608                 }
609             }
610         }
611
612         private class NativeCallback
613         {
614             public readonly GestureType Type;
615             public readonly GestureState State;
616             public Action<object> Action;
617
618             public NativeCallback(GestureType type, GestureState state, Action<object> action)
619             {
620                 Type = type;
621                 State = state;
622                 Action = action;
623             }
624         }
625     }
626 }