2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
18 using System.Runtime.InteropServices;
19 using System.Collections.Generic;
24 /// The GestureLayer is used to detect gestures.
27 public class GestureLayer : Widget
29 private readonly Interop.Elementary.GestureEventCallback _gestureCallback;
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>();
37 /// Creates and initializes a new instance of GestureLayer class.
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)
42 _gestureCallback = new Interop.Elementary.GestureEventCallback(GestureCallbackHandler);
46 /// Enumeration for supported gesture types.
48 public enum GestureType
51 /// N fingers single taps
56 /// N fingers single long-taps
61 /// N fingers double-single taps
66 /// N fingers triple-single taps
71 /// Reports momentum in the direction of move
76 /// N fingers line gesture
81 /// N fingers flick gesture
97 /// Enumeration for gesture states.
99 public enum GestureState
102 /// Gesture not started
112 /// Gesture is ongoing
117 /// Gesture completed
122 /// Ongoing gesture is aborted
130 /// Sets or gets the repeat-events setting.
132 public bool HoldEvents
136 return Interop.Elementary.elm_gesture_layer_hold_events_get(Handle);
140 Interop.Elementary.elm_gesture_layer_hold_events_set(Handle, value);
145 /// Sets or gets the gesture layer continues enable of an object
147 public bool Continues
151 return Interop.Elementary.elm_gesture_layer_continues_enable_get(Handle);
155 Interop.Elementary.elm_gesture_layer_continues_enable_set(Handle, value);
160 /// Sets or gets the gesture layer finger-size for taps.
162 public int TapFingerSize
166 return Interop.Elementary.elm_gesture_layer_tap_finger_size_get(Handle);
170 Interop.Elementary.elm_gesture_layer_tap_finger_size_set(Handle, value);
175 /// Sets or gets the gesture layer long tap start timeout of an object
177 public double LongTapTimeout
181 return Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_get(Handle);
185 Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_set(Handle, value);
190 /// Sets or gets the gesture layer double tap timeout of an object
192 public double DoubleTapTimeout
196 return Interop.Elementary.elm_gesture_layer_double_tap_timeout_get(Handle);
200 Interop.Elementary.elm_gesture_layer_double_tap_timeout_set(Handle, value);
205 /// Sets or gets the gesture layer flick time limit (in ms) of an object
207 public int FlickTimeLimit
211 return (int)Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_get(Handle);
215 Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_set(Handle, (UInt32)value);
220 /// Sets or gets the gesture layer line min length of an object
222 public int MinimumLineLength
226 return Interop.Elementary.elm_gesture_layer_line_min_length_get(Handle);
230 Interop.Elementary.elm_gesture_layer_line_min_length_set(Handle, value);
235 /// Sets or gets the gesture layer line angular tolerance of an object
237 public double LineAngularTolerance
241 return Interop.Elementary.elm_gesture_layer_line_angular_tolerance_get(Handle);
245 Interop.Elementary.elm_gesture_layer_line_angular_tolerance_set(Handle, value);
250 /// Sets or gets the gesture layer line distance tolerance of an object
252 public int LineDistanceTolerance
256 return Interop.Elementary.elm_gesture_layer_line_distance_tolerance_get(Handle);
260 Interop.Elementary.elm_gesture_layer_line_distance_tolerance_set(Handle, value);
265 /// Sets or gets step-value for rotate action.
267 public double RotateStep
271 return Interop.Elementary.elm_gesture_layer_rotate_step_get(Handle);
275 Interop.Elementary.elm_gesture_layer_rotate_step_set(Handle, value);
280 /// Sets or gets the gesture layer rotate angular tolerance of an object
282 public double RotateAngularTolerance
286 return Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_get(Handle);
290 Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_set(Handle, value);
295 /// Sets or gets control step value for zoom action.
297 public double ZoomStep
301 return Interop.Elementary.elm_gesture_layer_zoom_step_get(Handle);
305 Interop.Elementary.elm_gesture_layer_zoom_step_set(Handle, value);
310 /// Sets or gets the gesture layer zoom distance tolerance of an object
312 public int ZoomDistanceTolerance
316 return Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_get(Handle);
320 Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_set(Handle, value);
325 /// Sets or gets the gesture layer zoom finger factor of an object
327 public double ZoomFingerFactor
331 return Interop.Elementary.elm_gesture_layer_zoom_finger_factor_get(Handle);
335 Interop.Elementary.elm_gesture_layer_zoom_finger_factor_set(Handle, value);
340 /// Sets or gets the gesture layer zoom wheel factor of an object
342 public double ZoomWheelFactor
346 return Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_get(Handle);
350 Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_set(Handle, value);
354 #endregion Properties
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.
360 /// <param name="target">The object to attach.</param>
361 public void Attach(EvasObject target)
363 Interop.Elementary.elm_gesture_layer_attach(Handle, target.Handle);
367 /// Set the gesture state change callback.
368 /// When all callbacks for the gesture are set to null, it means this gesture is disabled.
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)
379 // if this (type, state) already exists in _handlers, we will reuse it
380 foreach (var handler in _handlers)
382 if (handler.Type == type && handler.State == state)
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;
401 // ignore unsetting a handler for event which was not registered yet?
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));
413 /// clear the gesture state change callback.
415 public void ClearCallbacks()
420 foreach (var handler in _handlers)
422 if (handler.Action != null)
424 Interop.Elementary.elm_gesture_layer_cb_set(Handle, handler.Type, handler.State, null, new IntPtr(i));
425 handler.Action = null;
432 #region Typed callback setting methods
434 // Following methods have been added for convenience, so the user will not have to convert Info structures himself
436 /// Set the tap callback.
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)
443 SetCallback(type, state, action);
447 /// Set the gesture state change callback with Momentum Gesture Type
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)
453 SetCallback(GestureType.Momentum, state, action);
457 /// Set the gesture state change callback with Line Gesture Type
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)
463 SetCallback(GestureType.Line, state, action);
467 /// Set the gesture state change callback with Flick Gesture Type
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)
473 SetCallback(GestureType.Flick, state, action);
477 /// Set the gesture state change callback with Zoom Gesture Type
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)
483 SetCallback(GestureType.Zoom, state, action);
487 /// Set the gesture state change callback with Rotate Gesture Type
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)
493 SetCallback(GestureType.Rotate, state, action);
496 #endregion Typed callback setting methods
499 /// Call this function to construct a new gesture-layer object.
501 /// <param name="parent">The gesture layer's parent widget.</param>
502 /// <returns></returns>
503 protected override IntPtr CreateHandle(EvasObject parent)
505 return Interop.Elementary.elm_gesture_layer_add(parent);
509 /// clear the gesture state change callback.
511 protected override void OnUnrealize()
517 private void SetCallback<T>(GestureType type, GestureState state, Action<T> action)
520 SetGestureCallback(type, state, null);
522 SetGestureCallback(type, state, new Action<object>((info) => action((T)info)));
525 private void GestureCallbackHandler(IntPtr data, IntPtr event_info)
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)
532 Action<object> action = _handlers[handlerIndex].Action;
535 // the interpretation of the event_info struct pointer depends on the GestureType
536 switch (_handlers[handlerIndex].Type)
538 case GestureType.Tap:
539 case GestureType.LongTap:
540 case GestureType.DoubleTap:
541 case GestureType.TripleTap:
542 action(Marshal.PtrToStructure<TapData>(event_info));
545 case GestureType.Momentum:
546 action(Marshal.PtrToStructure<MomentumData>(event_info));
549 case GestureType.Line:
550 case GestureType.Flick:
551 action(Marshal.PtrToStructure<LineData>(event_info));
554 case GestureType.Zoom:
555 action(Marshal.PtrToStructure<ZoomData>(event_info));
558 case GestureType.Rotate:
559 action(Marshal.PtrToStructure<RotateData>(event_info));
564 #region Info structures
567 /// The struct of TapData
569 [StructLayout(LayoutKind.Sequential)]
570 public struct TapData
573 /// The x coordinate of the center point.
578 /// The y coordinate of the center point.
582 #pragma warning disable 3003
585 /// The number of fingers tapped.
587 public UInt32 FingersCount;
592 public UInt32 Timestamp;
594 #pragma warning restore 3003
598 /// The struct of MomentumData
600 [StructLayout(LayoutKind.Sequential)]
601 public struct MomentumData
604 /// Final-swipe direction starting point on X.
609 /// Final-swipe direction starting point on Y.
614 /// Final-swipe direction ending point on X.
619 /// Final-swipe direction ending point on Y
623 #pragma warning disable 3003
626 /// Timestamp of start of final x-swipe.
628 public UInt32 HorizontalSwipeTimestamp;
631 /// Timestamp of start of final y-swipe.
633 public UInt32 VerticalSwipeTimestamp;
638 public Int32 HorizontalMomentum;
643 public Int32 VerticalMomentum;
646 /// Number of fingers.
648 public UInt32 FingersCount;
650 #pragma warning restore 3003
654 /// The struct of LineData
656 [StructLayout(LayoutKind.Sequential)]
657 public struct LineData
660 /// Final-swipe direction starting point on X.
665 /// Final-swipe direction starting point on Y.
670 /// Final-swipe direction ending point on X.
675 /// Final-swipe direction ending point on Y
679 #pragma warning disable 3003
682 /// Timestamp of start of final x-swipe.
684 public UInt32 HorizontalSwipeTimestamp;
687 /// Timestamp of start of final y-swipe.
689 public UInt32 VerticalSwipeTimestamp;
694 public Int32 HorizontalMomentum;
699 public Int32 VerticalMomentum;
702 /// Number of fingers.
704 public UInt32 FingersCount;
706 #pragma warning restore 3003
709 /// Angle (direction) of lines.
715 /// The struct of ZoomData
717 [StructLayout(LayoutKind.Sequential)]
718 public struct ZoomData
721 /// The x coordinate of zoom center point reported to user.
726 /// The y coordinate of zoom center point reported to user.
731 /// The radius (distance) between fingers reported to user.
736 /// The zoom value. 1.0 means no zoom.
741 /// Zoom momentum: zoom growth per second (NOT YET SUPPORTED).
743 private double Momentum;
747 /// The struct of RotateData
749 [StructLayout(LayoutKind.Sequential)]
750 public struct RotateData
753 /// The x coordinate of rotation center point reported to user.
758 /// The y coordinate of rotation center point reported to user.
763 /// The radius (distance) between fingers reported to user.
770 public double BaseAngle;
773 /// The rotation value. 0.0 means no rotation.
778 /// Rotation momentum: rotation done per second (NOT YET SUPPORTED).
780 private double Momentum;
783 #endregion Info structures
786 /// Config is a static class, it provides gestureLayer's timeout information.
788 public static class Config
791 /// Sets or gets the duration for occurring long tap event of gesture layer.
793 public static double DefaultLongTapTimeout
797 return Interop.Elementary.elm_config_glayer_long_tap_start_timeout_get();
801 Interop.Elementary.elm_config_glayer_long_tap_start_timeout_set(value);
806 /// Sets or gets the duration for occurring double tap event of gesture layer.
808 public static double DefaultDoubleTapTimeout
812 return Interop.Elementary.elm_config_glayer_double_tap_timeout_get();
816 Interop.Elementary.elm_config_glayer_double_tap_timeout_set(value);
821 private class NativeCallback
823 public readonly GestureType Type;
824 public readonly GestureState State;
825 public Action<object> Action;
827 public NativeCallback(GestureType type, GestureState state, Action<object> action)