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;
21 using Tizen.Internals;
26 /// The GestureLayer is used to detect gestures.
29 /// <since_tizen> preview </since_tizen>
30 public class GestureLayer : Widget
32 private readonly Interop.Elementary.GestureEventCallback _gestureCallback;
34 // Important: don't remove items from _handlers list
35 // The list can grow up to (number of GestureType) * (number of GestureState)
36 // but all gestures share the callback and you don't want to desynchronize mapping
37 private readonly List<NativeCallback> _handlers = new List<NativeCallback>();
40 /// Creates and initializes a new instance of the GestureLayer class.
42 /// <param name="parent">The parent is a given container which will be attached by the GestureLayer as a child. It's the <see cref="EvasObject"/> type.</param>
43 /// <since_tizen> preview </since_tizen>
44 public GestureLayer(EvasObject parent) : base(parent)
46 _gestureCallback = new Interop.Elementary.GestureEventCallback(GestureCallbackHandler);
50 /// Enumeration for the supported gesture types.
52 /// <since_tizen> preview </since_tizen>
53 public enum GestureType
56 /// N fingers single taps.
61 /// N fingers single long-taps.
66 /// N fingers double-single taps.
71 /// N fingers triple-single taps.
76 /// Reports momentum in the direction of the move.
81 /// N fingers line gesture.
86 /// N fingers flick gesture.
102 /// Enumeration for the gesture states.
104 /// <since_tizen> preview </since_tizen>
105 public enum GestureState
108 /// Gesture not started.
118 /// Gesture is ongoing.
123 /// Gesture completed.
128 /// Ongoing gesture is aborted.
136 /// Sets or gets the repeat-events setting.
138 /// <since_tizen> preview </since_tizen>
139 public bool HoldEvents
143 return Interop.Elementary.elm_gesture_layer_hold_events_get(Handle);
147 Interop.Elementary.elm_gesture_layer_hold_events_set(Handle, value);
152 /// Sets or gets the gesture layer to continue enable of an object.
154 /// <since_tizen> preview </since_tizen>
155 public bool Continues
159 return Interop.Elementary.elm_gesture_layer_continues_enable_get(Handle);
163 Interop.Elementary.elm_gesture_layer_continues_enable_set(Handle, value);
168 /// Sets or gets the gesture layer finger-size for taps.
170 /// <since_tizen> preview </since_tizen>
171 public int TapFingerSize
175 return Interop.Elementary.elm_gesture_layer_tap_finger_size_get(Handle);
179 Interop.Elementary.elm_gesture_layer_tap_finger_size_set(Handle, value);
184 /// Sets or gets the gesture layer long tap start timeout of an object.
186 /// <since_tizen> preview </since_tizen>
187 public double LongTapTimeout
191 return Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_get(Handle);
195 Interop.Elementary.elm_gesture_layer_long_tap_start_timeout_set(Handle, value);
200 /// Sets or gets the gesture layer double tap timeout of an object.
202 /// <since_tizen> preview </since_tizen>
203 public double DoubleTapTimeout
207 return Interop.Elementary.elm_gesture_layer_double_tap_timeout_get(Handle);
211 Interop.Elementary.elm_gesture_layer_double_tap_timeout_set(Handle, value);
216 /// Sets or gets the gesture layer flick time limit (in ms) of an object.
218 /// <since_tizen> preview </since_tizen>
219 public int FlickTimeLimit
223 return (int)Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_get(Handle);
227 Interop.Elementary.elm_gesture_layer_flick_time_limit_ms_set(Handle, (UInt32)value);
232 /// Sets or gets the gesture layer line minimum length of an object.
234 /// <since_tizen> preview </since_tizen>
235 public int MinimumLineLength
239 return Interop.Elementary.elm_gesture_layer_line_min_length_get(Handle);
243 Interop.Elementary.elm_gesture_layer_line_min_length_set(Handle, value);
248 /// Sets or gets the gesture layer line angular tolerance of an object.
250 /// <since_tizen> preview </since_tizen>
251 public double LineAngularTolerance
255 return Interop.Elementary.elm_gesture_layer_line_angular_tolerance_get(Handle);
259 Interop.Elementary.elm_gesture_layer_line_angular_tolerance_set(Handle, value);
264 /// Sets or gets the gesture layer line distance tolerance of an object.
266 /// <since_tizen> preview </since_tizen>
267 public int LineDistanceTolerance
271 return Interop.Elementary.elm_gesture_layer_line_distance_tolerance_get(Handle);
275 Interop.Elementary.elm_gesture_layer_line_distance_tolerance_set(Handle, value);
280 /// Sets or gets the step-value for the rotate action.
282 /// <since_tizen> preview </since_tizen>
283 public double RotateStep
287 return Interop.Elementary.elm_gesture_layer_rotate_step_get(Handle);
291 Interop.Elementary.elm_gesture_layer_rotate_step_set(Handle, value);
296 /// Sets or gets the gesture layer rotate angular tolerance of an object.
298 /// <since_tizen> preview </since_tizen>
299 public double RotateAngularTolerance
303 return Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_get(Handle);
307 Interop.Elementary.elm_gesture_layer_rotate_angular_tolerance_set(Handle, value);
312 /// Sets or gets the control step value for the zoom action.
314 /// <since_tizen> preview </since_tizen>
315 public double ZoomStep
319 return Interop.Elementary.elm_gesture_layer_zoom_step_get(Handle);
323 Interop.Elementary.elm_gesture_layer_zoom_step_set(Handle, value);
328 /// Sets or gets the gesture layer zoom distance tolerance of an object.
330 /// <since_tizen> preview </since_tizen>
331 public int ZoomDistanceTolerance
335 return Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_get(Handle);
339 Interop.Elementary.elm_gesture_layer_zoom_distance_tolerance_set(Handle, value);
344 /// Sets or gets the gesture layer zoom finger factor of an object.
346 /// <since_tizen> preview </since_tizen>
347 public double ZoomFingerFactor
351 return Interop.Elementary.elm_gesture_layer_zoom_finger_factor_get(Handle);
355 Interop.Elementary.elm_gesture_layer_zoom_finger_factor_set(Handle, value);
360 /// Sets or gets the gesture layer zoom wheel factor of an object.
362 /// <since_tizen> preview </since_tizen>
363 public double ZoomWheelFactor
367 return Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_get(Handle);
371 Interop.Elementary.elm_gesture_layer_zoom_wheel_factor_set(Handle, value);
375 #endregion Properties
378 /// Attaches a gesture layer widget to an Evas object (setting the widget's target).
379 /// A gesture layer's target may be any Evas object. This object will be used to listen to mouse and key events.
381 /// <param name="target">The object to attach.</param>
382 /// <since_tizen> preview </since_tizen>
383 public void Attach(EvasObject target)
385 Interop.Elementary.elm_gesture_layer_attach(Handle, target.Handle);
389 /// Sets the gesture state change callback.
390 /// When all callbacks for the gesture are set to null, it means this gesture is disabled.
392 /// <param name="type">The gesture you want to track state of.</param>
393 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
394 /// <param name="action">The callback itself.</param>
395 /// <since_tizen> preview </since_tizen>
396 public void SetGestureCallback(GestureType type, GestureState state, Action<object> action)
402 // if this (type, state) already exists in _handlers, we will reuse it
403 foreach (var handler in _handlers)
405 if (handler.Type == type && handler.State == state)
414 // if we are changing null -> not-null, or not-null -> null, then inform the EFL
415 if (_handlers[i].Action == null ^ action == null)
416 Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, action == null ? null : _gestureCallback, new IntPtr(i));
417 // overwrite previous action
418 _handlers[i].Action = action;
424 // ignore unsetting a handler for event which was not registered yet?
427 // (type, state) was not found, so we are adding a new entry and registering the callback
428 _handlers.Add(new NativeCallback(type, state, action));
429 // callback is always the same, the event is recognised by the index in _handler list (the index is passed as data)
430 Interop.Elementary.elm_gesture_layer_cb_set(Handle, type, state, _gestureCallback, new IntPtr(i));
436 /// Clears the gesture state change callback.
438 /// <since_tizen> preview </since_tizen>
439 public void ClearCallbacks()
444 foreach (var handler in _handlers)
446 if (handler.Action != null)
448 Interop.Elementary.elm_gesture_layer_cb_set(Handle, handler.Type, handler.State, null, new IntPtr(i));
449 handler.Action = null;
456 #region Typed callback setting methods
458 // Following methods have been added for convenience, so the user will not have to convert Info structures himself
460 /// Sets the tap callback.
462 /// <param name="type">The gesture you want to track state of.</param>
463 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
464 /// <param name="action">The callback itself.</param>
465 /// <since_tizen> preview </since_tizen>
466 public void SetTapCallback(GestureType type, GestureState state, Action<TapData> action)
468 SetCallback(type, state, action);
472 /// Sets the gesture state change callback with momentum gesture type.
474 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
475 /// <param name="action">The callback itself.</param>
476 /// <since_tizen> preview </since_tizen>
477 public void SetMomentumCallback(GestureState state, Action<MomentumData> action)
479 SetCallback(GestureType.Momentum, state, action);
483 /// Sets the gesture state change callback with line gesture type.
485 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
486 /// <param name="action">The callback itself.</param>
487 /// <since_tizen> preview </since_tizen>
488 public void SetLineCallback(GestureState state, Action<LineData> action)
490 SetCallback(GestureType.Line, state, action);
494 /// Sets the gesture state change callback with flick gesture type.
496 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
497 /// <param name="action">The callback itself.</param>
498 /// <since_tizen> preview </since_tizen>
499 public void SetFlickCallback(GestureState state, Action<LineData> action)
501 SetCallback(GestureType.Flick, state, action);
505 /// Sets the gesture state change callback with zoom gesture type.
507 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
508 /// <param name="action">The callback itself.</param>
509 /// <since_tizen> preview </since_tizen>
510 public void SetZoomCallback(GestureState state, Action<ZoomData> action)
512 SetCallback(GestureType.Zoom, state, action);
516 /// Sets the gesture state change callback with rotate gesture type.
518 /// <param name="state">The event the callback tracks (START, MOVE, END, ABORT).</param>
519 /// <param name="action">The callback itself.</param>
520 /// <since_tizen> preview </since_tizen>
521 public void SetRotateCallback(GestureState state, Action<RotateData> action)
523 SetCallback(GestureType.Rotate, state, action);
526 #endregion Typed callback setting methods
529 /// Calls this function to construct a new gesture-layer object.
531 /// <param name="parent">The gesture layer's parent widget.</param>
532 /// <returns></returns>
533 /// <since_tizen> preview </since_tizen>
534 protected override IntPtr CreateHandle(EvasObject parent)
536 return Interop.Elementary.elm_gesture_layer_add(parent.Handle);
540 /// Clears the gesture state change callback.
542 /// <since_tizen> preview </since_tizen>
543 protected override void OnUnrealize()
549 private void SetCallback<T>(GestureType type, GestureState state, Action<T> action)
552 SetGestureCallback(type, state, null);
554 SetGestureCallback(type, state, new Action<object>((info) => action((T)info)));
557 private int GestureCallbackHandler(IntPtr data, IntPtr event_info)
559 // so EFL called our callback, lets use data to find the right Action to call
560 var handlerIndex = (int)data;
561 // thanks to the fact that we never remove item from _handlers, we don't need a lock here
562 if (handlerIndex < 0 || handlerIndex >= _handlers.Count)
565 var currentHandler = _handlers[handlerIndex];
566 Action<object> action = currentHandler.Action;
570 // the interpretation of the event_info struct pointer depends on the GestureType
571 switch (currentHandler.Type)
573 case GestureType.Tap:
574 case GestureType.LongTap:
575 case GestureType.DoubleTap:
576 case GestureType.TripleTap:
577 action(Marshal.PtrToStructure<TapData>(event_info));
580 case GestureType.Momentum:
581 action(Marshal.PtrToStructure<MomentumData>(event_info));
584 case GestureType.Line:
585 case GestureType.Flick:
586 action(Marshal.PtrToStructure<LineData>(event_info));
589 case GestureType.Zoom:
590 action(Marshal.PtrToStructure<ZoomData>(event_info));
593 case GestureType.Rotate:
594 action(Marshal.PtrToStructure<RotateData>(event_info));
600 #region Info structures
603 /// The struct of TapData.
605 /// <since_tizen> preview </since_tizen>
606 [NativeStruct("Elm_Gesture_Taps_Info", Include="Elementary.h", PkgConfig="elementary")]
607 [StructLayout(LayoutKind.Sequential)]
608 public struct TapData
611 /// The X coordinate of the center point.
613 /// <since_tizen> preview </since_tizen>
617 /// The Y coordinate of the center point.
619 /// <since_tizen> preview </since_tizen>
622 #pragma warning disable 3003
625 /// The number of fingers tapped.
627 /// <since_tizen> preview </since_tizen>
628 public UInt32 FingersCount;
633 /// <since_tizen> preview </since_tizen>
634 public UInt32 Timestamp;
636 #pragma warning restore 3003
640 /// The struct of MomentumData.
642 /// <since_tizen> preview </since_tizen>
643 [NativeStruct("Elm_Gesture_Momentum_Info", Include="Elementary.h", PkgConfig="elementary")]
644 [StructLayout(LayoutKind.Sequential)]
645 public struct MomentumData
648 /// Final-swipe direction starting point on X.
650 /// <since_tizen> preview </since_tizen>
654 /// Final-swipe direction starting point on Y.
656 /// <since_tizen> preview </since_tizen>
660 /// Final-swipe direction ending point on X.
662 /// <since_tizen> preview </since_tizen>
666 /// Final-swipe direction ending point on Y.
668 /// <since_tizen> preview </since_tizen>
671 #pragma warning disable 3003
674 /// Timestamp of start of final X-swipe.
676 /// <since_tizen> preview </since_tizen>
677 public UInt32 HorizontalSwipeTimestamp;
680 /// Timestamp of start of final Y-swipe.
682 /// <since_tizen> preview </since_tizen>
683 public UInt32 VerticalSwipeTimestamp;
688 /// <since_tizen> preview </since_tizen>
689 public Int32 HorizontalMomentum;
694 /// <since_tizen> preview </since_tizen>
695 public Int32 VerticalMomentum;
698 /// Number of fingers.
700 /// <since_tizen> preview </since_tizen>
701 public UInt32 FingersCount;
703 #pragma warning restore 3003
707 /// The struct of LineData.
709 /// <since_tizen> preview </since_tizen>
710 [NativeStruct("Elm_Gesture_Line_Info", Include="Elementary.h", PkgConfig="elementary")]
711 [StructLayout(LayoutKind.Sequential)]
712 public struct LineData
715 /// Final-swipe direction starting point on X.
717 /// <since_tizen> preview </since_tizen>
721 /// Final-swipe direction starting point on Y.
723 /// <since_tizen> preview </since_tizen>
727 /// Final-swipe direction ending point on X.
729 /// <since_tizen> preview </since_tizen>
733 /// Final-swipe direction ending point on Y.
735 /// <since_tizen> preview </since_tizen>
738 #pragma warning disable 3003
741 /// Timestamp of start of final X-swipe.
743 /// <since_tizen> preview </since_tizen>
744 public UInt32 HorizontalSwipeTimestamp;
747 /// Timestamp of start of final Y-swipe.
749 /// <since_tizen> preview </since_tizen>
750 public UInt32 VerticalSwipeTimestamp;
755 /// <since_tizen> preview </since_tizen>
756 public Int32 HorizontalMomentum;
761 /// <since_tizen> preview </since_tizen>
762 public Int32 VerticalMomentum;
765 /// Number of fingers.
767 /// <since_tizen> preview </since_tizen>
768 public UInt32 FingersCount;
770 #pragma warning restore 3003
773 /// Angle (direction) of lines.
775 /// <since_tizen> preview </since_tizen>
780 /// The struct of ZoomData.
782 /// <since_tizen> preview </since_tizen>
783 [NativeStruct("Elm_Gesture_Zoom_Info", Include="Elementary.h", PkgConfig="elementary")]
784 [StructLayout(LayoutKind.Sequential)]
785 public struct ZoomData
788 /// The X coordinate of zoom center point reported to the user.
790 /// <since_tizen> preview </since_tizen>
794 /// The Y coordinate of zoom center point reported to the user.
796 /// <since_tizen> preview </since_tizen>
800 /// The radius (distance) between fingers reported to user.
802 /// <since_tizen> preview </since_tizen>
806 /// The zoom value. 1.0 means no zoom.
808 /// <since_tizen> preview </since_tizen>
812 /// Zoom momentum: zoom growth per second (NOT YET SUPPORTED).
814 private double Momentum;
818 /// The struct of RotateData.
820 /// <since_tizen> preview </since_tizen>
821 [NativeStruct("Elm_Gesture_Rotate_Info", Include="Elementary.h", PkgConfig="elementary")]
822 [StructLayout(LayoutKind.Sequential)]
823 public struct RotateData
826 /// The X coordinate of rotation center point reported to the user.
828 /// <since_tizen> preview </since_tizen>
832 /// The Y coordinate of rotation center point reported to the user.
834 /// <since_tizen> preview </since_tizen>
838 /// The radius (distance) between fingers reported to user.
840 /// <since_tizen> preview </since_tizen>
846 /// <since_tizen> preview </since_tizen>
847 public double BaseAngle;
850 /// The rotation value. 0.0 means no rotation.
852 /// <since_tizen> preview </since_tizen>
856 /// Rotation momentum: rotation done per second (NOT YET SUPPORTED).
858 private double Momentum;
861 #endregion Info structures
864 /// Config is a static class, it provides gestureLayer's timeout information.
866 /// <since_tizen> preview </since_tizen>
867 public static class Config
870 /// Sets or gets the duration for occurring long tap event of gesture layer.
872 /// <since_tizen> preview </since_tizen>
873 public static double DefaultLongTapTimeout
877 return Interop.Elementary.elm_config_glayer_long_tap_start_timeout_get();
881 Interop.Elementary.elm_config_glayer_long_tap_start_timeout_set(value);
886 /// Sets or gets the duration for occurring double tap event of gesture layer.
888 /// <since_tizen> preview </since_tizen>
889 public static double DefaultDoubleTapTimeout
893 return Interop.Elementary.elm_config_glayer_double_tap_timeout_get();
897 Interop.Elementary.elm_config_glayer_double_tap_timeout_set(value);
902 private class NativeCallback
904 public readonly GestureType Type;
905 public readonly GestureState State;
906 public Action<object> Action;
908 public NativeCallback(GestureType type, GestureState state, Action<object> action)