Release 4.0.0-preview1-00051
[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     /// <summary>
24     /// The GestureLayer is used to detect gestures.
25     /// Inherits Widget
26     /// </summary>
27     public class GestureLayer : Widget
28     {
29         private readonly Interop.Elementary.GestureEventCallback _gestureCallback;
30
31         // Important: don't remove items from _handlers list
32         // The list can grow up to (number of GestureType) * (number of GestureState)
33         // but all gestures share the callback and you don't want to desynchronize mapping
34         private readonly List<NativeCallback> _handlers = new List<NativeCallback>();
35
36         /// <summary>
37         /// Creates and initializes a new instance of GestureLayer class.
38         /// </summary>
39         /// <param name="parent">The parent is a given container which will be attached by GestureLayer as a child. It's <see cref="EvasObject"/> type.</param>
40         public GestureLayer(EvasObject parent) : base(parent)
41         {
42             _gestureCallback = new Interop.Elementary.GestureEventCallback(GestureCallbackHandler);
43         }
44
45         /// <summary>
46         /// Enumeration for supported gesture types.
47         /// </summary>
48         public enum GestureType
49         {
50             /// <summary>
51             /// N fingers single taps
52             /// </summary>
53             Tap = 1,
54
55             /// <summary>
56             /// N fingers single long-taps
57             /// </summary>
58             LongTap,
59
60             /// <summary>
61             /// N fingers double-single taps
62             /// </summary>
63             DoubleTap,
64
65             /// <summary>
66             /// N fingers triple-single taps
67             /// </summary>
68             TripleTap,
69
70             /// <summary>
71             /// Reports momentum in the direction of move
72             /// </summary>
73             Momentum,
74
75             /// <summary>
76             /// N fingers line gesture
77             /// </summary>
78             Line,
79
80             /// <summary>
81             /// N fingers flick gesture
82             /// </summary>
83             Flick,
84
85             /// <summary>
86             /// Zoom
87             /// </summary>
88             Zoom,
89
90             /// <summary>
91             /// Rotate
92             /// </summary>
93             Rotate,
94         }
95
96         /// <summary>
97         /// Enumeration for gesture states.
98         /// </summary>
99         public enum GestureState
100         {
101             /// <summary>
102             /// Gesture not started
103             /// </summary>
104             Undefined = -1,
105
106             /// <summary>
107             /// Gesture started
108             /// </summary>
109             Start,
110
111             /// <summary>
112             /// Gesture is ongoing
113             /// </summary>
114             Move,
115
116             /// <summary>
117             /// Gesture completed
118             /// </summary>
119             End,
120
121             /// <summary>
122             /// Ongoing gesture is aborted
123             /// </summary>
124             Abort,
125         }
126
127         #region Properties
128
129         /// <summary>
130         /// Sets or gets the repeat-events setting.
131         /// </summary>
132         public bool HoldEvents
133         {
134             get
135             {
136                 return Interop.Elementary.elm_gesture_layer_hold_events_get(Handle);
137             }
138             set
139             {
140                 Interop.Elementary.elm_gesture_layer_hold_events_set(Handle, value);
141             }
142         }
143
144         /// <summary>
145         /// Sets or gets the gesture layer continues enable of an object
146         /// </summary>
147         public bool Continues
148         {
149             get
150             {
151                 return Interop.Elementary.elm_gesture_layer_continues_enable_get(Handle);
152             }
153             set
154             {
155                 Interop.Elementary.elm_gesture_layer_continues_enable_set(Handle, value);
156             }
157         }
158
159         /// <summary>
160         /// Sets or gets the gesture layer finger-size for taps.
161         /// </summary>
162         public int TapFingerSize
163         {
164             get
165             {
166                 return Interop.Elementary.elm_gesture_layer_tap_finger_size_get(Handle);
167             }
168             set
169             {
170                 Interop.Elementary.elm_gesture_layer_tap_finger_size_set(Handle, value);
171             }
172         }
173
174         /// <summary>
175         /// Sets or gets the gesture layer long tap start timeout of an object
176         /// </summary>
177         public double LongTapTimeout
178         {
179             get
180             {
181                 return Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_get(Handle);
182             }
183             set
184             {
185                 Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_set(Handle, value);
186             }
187         }
188
189         /// <summary>
190         /// Sets or gets the gesture layer double tap timeout of an object
191         /// </summary>
192         public double DoubleTapTimeout
193         {
194             get
195             {
196                 return Interop.Elementary.elm_gesture_layer_double_tap_timeout_get(Handle);
197             }
198             set
199             {
200                 Interop.Elementary.elm_gesture_layer_double_tap_timeout_set(Handle, value);
201             }
202         }
203
204         /// <summary>
205         /// Sets or gets the gesture layer flick time limit (in ms) of an object
206         /// </summary>
207         public int FlickTimeLimit
208         {
209             get
210             {
211                 return (int)Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_get(Handle);
212             }
213             set
214             {
215                 Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_set(Handle, (UInt32)value);
216             }
217         }
218
219         /// <summary>
220         /// Sets or gets the gesture layer line min length of an object
221         /// </summary>
222         public int MinimumLineLength
223         {
224             get
225             {
226                 return Interop.Elementary.elm_gesture_layer_line_min_length_get(Handle);
227             }
228             set
229             {
230                 Interop.Elementary.elm_gesture_layer_line_min_length_set(Handle, value);
231             }
232         }
233
234         /// <summary>
235         /// Sets or gets  the gesture layer line angular tolerance of an object
236         /// </summary>
237         public double LineAngularTolerance
238         {
239             get
240             {
241                 return Interop.Elementary.elm_gesture_layer_line_angular_tolerance_get(Handle);
242             }
243             set
244             {
245                 Interop.Elementary.elm_gesture_layer_line_angular_tolerance_set(Handle, value);
246             }
247         }
248
249         /// <summary>
250         /// Sets or gets the gesture layer line distance tolerance of an object
251         /// </summary>
252         public int LineDistanceTolerance
253         {
254             get
255             {
256                 return Interop.Elementary.elm_gesture_layer_line_distance_tolerance_get(Handle);
257             }
258             set
259             {
260                 Interop.Elementary.elm_gesture_layer_line_distance_tolerance_set(Handle, value);
261             }
262         }
263
264         /// <summary>
265         /// Sets or gets step-value for rotate action.
266         /// </summary>
267         public double RotateStep
268         {
269             get
270             {
271                 return Interop.Elementary.elm_gesture_layer_rotate_step_get(Handle);
272             }
273             set
274             {
275                 Interop.Elementary.elm_gesture_layer_rotate_step_set(Handle, value);
276             }
277         }
278
279         /// <summary>
280         /// Sets or gets the gesture layer rotate angular tolerance of an object
281         /// </summary>
282         public double RotateAngularTolerance
283         {
284             get
285             {
286                 return Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_get(Handle);
287             }
288             set
289             {
290                 Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_set(Handle, value);
291             }
292         }
293
294         /// <summary>
295         /// Sets or gets control step value for zoom action.
296         /// </summary>
297         public double ZoomStep
298         {
299             get
300             {
301                 return Interop.Elementary.elm_gesture_layer_zoom_step_get(Handle);
302             }
303             set
304             {
305                 Interop.Elementary.elm_gesture_layer_zoom_step_set(Handle, value);
306             }
307         }
308
309         /// <summary>
310         /// Sets or gets the gesture layer zoom distance tolerance of an object
311         /// </summary>
312         public int ZoomDistanceTolerance
313         {
314             get
315             {
316                 return Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_get(Handle);
317             }
318             set
319             {
320                 Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_set(Handle, value);
321             }
322         }
323
324         /// <summary>
325         /// Sets or gets the gesture layer zoom finger factor of an object
326         /// </summary>
327         public double ZoomFingerFactor
328         {
329             get
330             {
331                 return Interop.Elementary.elm_gesture_layer_zoom_finger_factor_get(Handle);
332             }
333             set
334             {
335                 Interop.Elementary.elm_gesture_layer_zoom_finger_factor_set(Handle, value);
336             }
337         }
338
339         /// <summary>
340         /// Sets or gets the gesture layer zoom wheel factor of an object
341         /// </summary>
342         public double ZoomWheelFactor
343         {
344             get
345             {
346                 return Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_get(Handle);
347             }
348             set
349             {
350                 Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_set(Handle, value);
351             }
352         }
353
354         #endregion Properties
355
356         /// <summary>
357         /// Attach a gesture layer widget to an Evas object (setting the widget's target).
358         /// A gesture layer's target may be any Evas object. This object will be used to listen to mouse and key events.
359         /// </summary>
360         /// <param name="target">The object to attach.</param>
361         public void Attach(EvasObject target)
362         {
363             Interop.Elementary.elm_gesture_layer_attach(Handle, target.Handle);
364         }
365
366         /// <summary>
367         /// Set the gesture state change callback.
368         /// When all callbacks for the gesture are set to null, it means this gesture is disabled.
369         /// </summary>
370         /// <param name="type">The gesture you want to track state of.</param>
371         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
372         /// <param name="action">The callback itself.</param>
373         public void SetGestureCallback(GestureType type, GestureState state, Action<object> action)
374         {
375             lock (_handlers)
376             {
377                 bool found = false;
378                 int i = 0;
379                 // if this (type, state) already exists in _handlers, we will reuse it
380                 foreach (var handler in _handlers)
381                 {
382                     if (handler.Type == type && handler.State == state)
383                     {
384                         found = true;
385                         break;
386                     }
387                     i++;
388                 }
389                 if (found)
390                 {
391                     // if we are changing null -> not-null, or not-null -> null, then inform the EFL
392                     if (_handlers[i].Action == null ^ action == null)
393                         Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, action == null ? null : _gestureCallback, new IntPtr(i));
394                     // overwrite previous action
395                     _handlers[i].Action = action;
396                 }
397                 else
398                 {
399                     if (action == null)
400                     {
401                         // ignore unsetting a handler for event which was not registered yet?
402                         return;
403                     }
404                     // (type, state) was not found, so we are adding a new entry and registering the callback
405                     _handlers.Add(new NativeCallback(type, state, action));
406                     // callback is always the same, the event is recognised by the index in _handler list (the index is passed as data)
407                     Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, _gestureCallback, new IntPtr(i));
408                 }
409             }
410         }
411
412         /// <summary>
413         /// clear the gesture state change callback.
414         /// </summary>
415         public void ClearCallbacks()
416         {
417             lock (_handlers)
418             {
419                 int i = 0;
420                 foreach (var handler in _handlers)
421                 {
422                     if (handler.Action != null)
423                     {
424                         Interop.Elementary.elm_gesture_layer_cb_set(Handle, handler.Type, handler.State, null, new IntPtr(i));
425                         handler.Action = null;
426                     }
427                     i++;
428                 }
429             }
430         }
431
432         #region Typed callback setting methods
433
434         // Following methods have been added for convenience, so the user will not have to convert Info structures himself
435         /// <summary>
436         /// Set the tap callback.
437         /// </summary>
438         /// <param name="type">The gesture you want to track state of.</param>
439         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
440         /// <param name="action">The callback itself.</param>
441         public void SetTapCallback(GestureType type, GestureState state, Action<TapData> action)
442         {
443             SetCallback(type, state, action);
444         }
445
446         /// <summary>
447         /// Set the gesture state change callback with Momentum Gesture Type
448         /// </summary>
449         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
450         /// <param name="action">The callback itself.</param>
451         public void SetMomentumCallback(GestureState state, Action<MomentumData> action)
452         {
453             SetCallback(GestureType.Momentum, state, action);
454         }
455
456         /// <summary>
457         /// Set the gesture state change callback with Line Gesture Type
458         /// </summary>
459         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
460         /// <param name="action">The callback itself.</param>
461         public void SetLineCallback(GestureState state, Action<LineData> action)
462         {
463             SetCallback(GestureType.Line, state, action);
464         }
465
466         /// <summary>
467         /// Set the gesture state change callback with Flick Gesture Type
468         /// </summary>
469         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
470         /// <param name="action">The callback itself.</param>
471         public void SetFlickCallback(GestureState state, Action<LineData> action)
472         {
473             SetCallback(GestureType.Flick, state, action);
474         }
475
476         /// <summary>
477         /// Set the gesture state change callback with Zoom Gesture Type
478         /// </summary>
479         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
480         /// <param name="action">The callback itself.</param>
481         public void SetZoomCallback(GestureState state, Action<ZoomData> action)
482         {
483             SetCallback(GestureType.Zoom, state, action);
484         }
485
486         /// <summary>
487         /// Set the gesture state change callback with Rotate Gesture Type
488         /// </summary>
489         /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
490         /// <param name="action">The callback itself.</param>
491         public void SetRotateCallback(GestureState state, Action<RotateData> action)
492         {
493             SetCallback(GestureType.Rotate, state, action);
494         }
495
496         #endregion Typed callback setting methods
497
498         /// <summary>
499         /// Call this function to construct a new gesture-layer object.
500         /// </summary>
501         /// <param name="parent">The gesture layer's parent widget.</param>
502         /// <returns></returns>
503         protected override IntPtr CreateHandle(EvasObject parent)
504         {
505             return Interop.Elementary.elm_gesture_layer_add(parent);
506         }
507
508         /// <summary>
509         /// clear the gesture state change callback.
510         /// </summary>
511         protected override void OnUnrealize()
512         {
513             ClearCallbacks();
514             base.OnUnrealize();
515         }
516
517         private void SetCallback<T>(GestureType type, GestureState state, Action<T> action)
518         {
519             if (action == null)
520                 SetGestureCallback(type, state, null);
521             else
522                 SetGestureCallback(type, state, new Action<object>((info) => action((T)info)));
523         }
524
525         private void GestureCallbackHandler(IntPtr data, IntPtr event_info)
526         {
527             // so EFL called our callback, lets use data to find the right Action to call
528             var handlerIndex = (int)data;
529             // thanks to the fact that we never remove item from _handlers, we don't need a lock here
530             if (handlerIndex < 0 || handlerIndex >= _handlers.Count)
531                 return;
532             Action<object> action = _handlers[handlerIndex].Action;
533             if (action == null)
534                 return;
535             // the interpretation of the event_info struct pointer depends on the GestureType
536             switch (_handlers[handlerIndex].Type)
537             {
538                 case GestureType.Tap:
539                 case GestureType.LongTap:
540                 case GestureType.DoubleTap:
541                 case GestureType.TripleTap:
542                     action(Marshal.PtrToStructure<TapData>(event_info));
543                     break;
544
545                 case GestureType.Momentum:
546                     action(Marshal.PtrToStructure<MomentumData>(event_info));
547                     break;
548
549                 case GestureType.Line:
550                 case GestureType.Flick:
551                     action(Marshal.PtrToStructure<LineData>(event_info));
552                     break;
553
554                 case GestureType.Zoom:
555                     action(Marshal.PtrToStructure<ZoomData>(event_info));
556                     break;
557
558                 case GestureType.Rotate:
559                     action(Marshal.PtrToStructure<RotateData>(event_info));
560                     break;
561             }
562         }
563
564         #region Info structures
565
566         /// <summary>
567         /// The struct of TapData
568         /// </summary>
569         [StructLayout(LayoutKind.Sequential)]
570         public struct TapData
571         {
572             /// <summary>
573             /// The x coordinate of the center point.
574             /// </summary>
575             public Int32 X;
576
577             /// <summary>
578             /// The y coordinate of the center point.
579             /// </summary>
580             public Int32 Y;
581
582 #pragma warning disable 3003
583
584             /// <summary>
585             /// The number of fingers tapped.
586             /// </summary>
587             public UInt32 FingersCount;
588
589             /// <summary>
590             /// The timestamp.
591             /// </summary>
592             public UInt32 Timestamp;
593
594 #pragma warning restore 3003
595         }
596
597         /// <summary>
598         /// The struct of MomentumData
599         /// </summary>
600         [StructLayout(LayoutKind.Sequential)]
601         public struct MomentumData
602         {
603             /// <summary>
604             /// Final-swipe direction starting point on X.
605             /// </summary>
606             public Int32 X1;
607
608             /// <summary>
609             /// Final-swipe direction starting point on Y.
610             /// </summary>
611             public Int32 Y1;
612
613             /// <summary>
614             /// Final-swipe direction ending point on X.
615             /// </summary>
616             public Int32 X2;
617
618             /// <summary>
619             /// Final-swipe direction ending point on Y
620             /// </summary>
621             public Int32 Y2;
622
623 #pragma warning disable 3003
624
625             /// <summary>
626             /// Timestamp of start of final x-swipe.
627             /// </summary>
628             public UInt32 HorizontalSwipeTimestamp;
629
630             /// <summary>
631             /// Timestamp of start of final y-swipe.
632             /// </summary>
633             public UInt32 VerticalSwipeTimestamp;
634
635             /// <summary>
636             /// Momentum on X.
637             /// </summary>
638             public Int32 HorizontalMomentum;
639
640             /// <summary>
641             /// Momentum on Y.
642             /// </summary>
643             public Int32 VerticalMomentum;
644
645             /// <summary>
646             /// Number of fingers.
647             /// </summary>
648             public UInt32 FingersCount;
649
650 #pragma warning restore 3003
651         }
652
653         /// <summary>
654         /// The struct of LineData
655         /// </summary>
656         [StructLayout(LayoutKind.Sequential)]
657         public struct LineData
658         {
659             /// <summary>
660             /// Final-swipe direction starting point on X.
661             /// </summary>
662             public Int32 X1;
663
664             /// <summary>
665             /// Final-swipe direction starting point on Y.
666             /// </summary>
667             public Int32 Y1;
668
669             /// <summary>
670             /// Final-swipe direction ending point on X.
671             /// </summary>
672             public Int32 X2;
673
674             /// <summary>
675             /// Final-swipe direction ending point on Y
676             /// </summary>
677             public Int32 Y2;
678
679 #pragma warning disable 3003
680
681             /// <summary>
682             /// Timestamp of start of final x-swipe.
683             /// </summary>
684             public UInt32 HorizontalSwipeTimestamp;
685
686             /// <summary>
687             /// Timestamp of start of final y-swipe.
688             /// </summary>
689             public UInt32 VerticalSwipeTimestamp;
690
691             /// <summary>
692             /// Momentum on X.
693             /// </summary>
694             public Int32 HorizontalMomentum;
695
696             /// <summary>
697             /// Momentum on Y.
698             /// </summary>
699             public Int32 VerticalMomentum;
700
701             /// <summary>
702             /// Number of fingers.
703             /// </summary>
704             public UInt32 FingersCount;
705
706 #pragma warning restore 3003
707
708             /// <summary>
709             /// Angle (direction) of lines.
710             /// </summary>
711             public double Angle;
712         }
713
714         /// <summary>
715         /// The struct of ZoomData
716         /// </summary>
717         [StructLayout(LayoutKind.Sequential)]
718         public struct ZoomData
719         {
720             /// <summary>
721             /// The x coordinate of zoom center point reported to user.
722             /// </summary>
723             public Int32 X;
724
725             /// <summary>
726             /// The y coordinate of zoom center point reported to user.
727             /// </summary>
728             public Int32 Y;
729
730             /// <summary>
731             /// The radius (distance) between fingers reported to user.
732             /// </summary>
733             public Int32 Radius;
734
735             /// <summary>
736             /// The zoom value. 1.0 means no zoom.
737             /// </summary>
738             public double Zoom;
739
740             /// <summary>
741             /// Zoom momentum: zoom growth per second (NOT YET SUPPORTED).
742             /// </summary>
743             private double Momentum;
744         }
745
746         /// <summary>
747         /// The struct of RotateData
748         /// </summary>
749         [StructLayout(LayoutKind.Sequential)]
750         public struct RotateData
751         {
752             /// <summary>
753             /// The x coordinate of rotation center point reported to user.
754             /// </summary>
755             public Int32 X;
756
757             /// <summary>
758             /// The y coordinate of rotation center point reported to user.
759             /// </summary>
760             public Int32 Y;
761
762             /// <summary>
763             /// The radius (distance) between fingers reported to user.
764             /// </summary>
765             public Int32 Radius;
766
767             /// <summary>
768             /// The start-angle.
769             /// </summary>
770             public double BaseAngle;
771
772             /// <summary>
773             /// The rotation value. 0.0 means no rotation.
774             /// </summary>
775             public double Angle;
776
777             /// <summary>
778             /// Rotation momentum: rotation done per second (NOT YET SUPPORTED).
779             /// </summary>
780             private double Momentum;
781         }
782
783         #endregion Info structures
784
785         /// <summary>
786         /// Config is a static class, it provides gestureLayer's timeout information.
787         /// </summary>
788         public static class Config
789         {
790             /// <summary>
791             /// Sets or gets the duration for occurring long tap event of gesture layer.
792             /// </summary>
793             public static double DefaultLongTapTimeout
794             {
795                 get
796                 {
797                     return Interop.Elementary.elm_config_glayer_long_tap_start_timeout_get();
798                 }
799                 set
800                 {
801                     Interop.Elementary.elm_config_glayer_long_tap_start_timeout_set(value);
802                 }
803             }
804
805             /// <summary>
806             /// Sets or gets the duration for occurring double tap event of gesture layer.
807             /// </summary>
808             public static double DefaultDoubleTapTimeout
809             {
810                 get
811                 {
812                     return Interop.Elementary.elm_config_glayer_double_tap_timeout_get();
813                 }
814                 set
815                 {
816                     Interop.Elementary.elm_config_glayer_double_tap_timeout_set(value);
817                 }
818             }
819         }
820
821         private class NativeCallback
822         {
823             public readonly GestureType Type;
824             public readonly GestureState State;
825             public Action<object> Action;
826
827             public NativeCallback(GestureType type, GestureState state, Action<object> action)
828             {
829                 Type = type;
830                 State = state;
831                 Action = action;
832             }
833         }
834     }
835 }