Geometry Touch / Gesture Event
authorjoogab.yun <joogab.yun@samsung.com>
Tue, 12 Nov 2024 02:29:06 +0000 (11:29 +0900)
committerSeoyeon2Kim <34738918+Seoyeon2Kim@users.noreply.github.com>
Tue, 19 Nov 2024 06:39:04 +0000 (15:39 +0900)
src/Tizen.NUI/src/internal/Interop/Interop.Application.cs
src/Tizen.NUI/src/internal/Interop/Interop.GestureDetector.cs
src/Tizen.NUI/src/public/Application/NUIApplication.cs
src/Tizen.NUI/src/public/BaseComponents/ViewEvent.cs
src/Tizen.NUI/src/public/Events/GestureDetector.cs
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedGestureSample.cs [new file with mode: 0755]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSample.cs [new file with mode: 0755]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSampleVertical.cs [new file with mode: 0755]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndLongPressGestureSample.cs [new file with mode: 0755]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndPanGestureSample.cs [new file with mode: 0755]
test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/GeometryTouchEvent.cs [new file with mode: 0755]

index a9654c41a84394fe6ac521320c74d6b690cc6244..a52f199384fadcd699aad6bde70691477a17b7d0 100755 (executable)
@@ -96,6 +96,13 @@ namespace Tizen.NUI
 
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_GetScreenSize")]
             public static extern global::System.IntPtr GetScreenSize();
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_SetGeometryHittestEnabled")]
+            public static extern void SetGeometryHittestEnabled(bool enable);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_IsGeometryHittestEnabled")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool IsGeometryHittestEnabled();
         }
     }
 }
index d17e752739d407a6aa2e39ad2d72c956cd22b37c..998d426f79f254720617ac0c26729596fdc490a8 100755 (executable)
@@ -48,6 +48,14 @@ namespace Tizen.NUI
 
             [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_GestureDetector_GetAttachedActor")]
             public static extern global::System.IntPtr GetAttachedActor(global::System.Runtime.InteropServices.HandleRef jarg1, uint jarg2);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_GestureDetector_HandleEvent")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool HandleEvent(global::System.Runtime.InteropServices.HandleRef jarg1, global::System.Runtime.InteropServices.HandleRef jarg2, global::System.Runtime.InteropServices.HandleRef jarg3);
+
+            [global::System.Runtime.InteropServices.DllImport(NDalicPINVOKE.Lib, EntryPoint = "CSharp_Dali_GestureDetector_CancelAllOtherGestureDetectors")]
+            [return: global::System.Runtime.InteropServices.MarshalAs(global::System.Runtime.InteropServices.UnmanagedType.U1)]
+            public static extern bool CancelAllOtherGestureDetectors(global::System.Runtime.InteropServices.HandleRef jarg1);
         }
     }
 }
index e7fb82753b1d109c3899d6048fc00bc6b5101174..ac178056c5faf762821a934a3587dbb97d47bb91 100755 (executable)
@@ -34,7 +34,7 @@ namespace Tizen.NUI
     public class NUIApplication : CoreApplication
     {
         /// <summary>
-        /// Set to true if XAML is used. 
+        /// Set to true if XAML is used.
         /// This must be called before or immediately after the NUIApplication constructor is called.
         /// The default value is true.
         /// </summary>
@@ -592,6 +592,30 @@ namespace Tizen.NUI
             return ret;
         }
 
+        /// <summary>
+        /// Sets the geometry hit-testing enabled or disabled for the application.
+        /// </summary>
+        /// <param name="enable">True to enable geometry hit-testing, false otherwise.</param>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        static public void SetGeometryHittestEnabled(bool enable)
+        {
+            Interop.Application.SetGeometryHittestEnabled(enable);
+            NDalicPINVOKE.ThrowExceptionIfExists();
+        }
+
+        /// <summary>
+        /// Checks whether geometry hit-testing is enabled for the application.
+        /// </summary>
+        /// <returns>True if geometry hit-testing is enabled, false otherwise.</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        static public bool IsGeometryHittestEnabled()
+        {
+            bool ret = Interop.Application.IsGeometryHittestEnabled();
+            NDalicPINVOKE.ThrowExceptionIfExists();
+            return ret;
+        }
+
+
         /// <summary>
         /// The OnLocaleChanged method is called when the system locale settings have changed.
         /// Overrides this method if you want to handle behavior.
index e9c32177f118aaa24e4d533025b92e506105d4d1..a8f254e671c28c58e66242eeb407f965ec07daaf 100755 (executable)
@@ -898,7 +898,19 @@ namespace Tizen.NUI.BaseComponents
 
             if (interceptTouchDataEventHandler != null)
             {
-                consumed = interceptTouchDataEventHandler(this, e);
+                if(NUIApplication.IsGeometryHittestEnabled())
+                {
+                    Delegate[] delegateList = interceptTouchDataEventHandler.GetInvocationList();
+                    // Oring the result of each callback.
+                    foreach (EventHandlerWithReturnType<object, TouchEventArgs, bool> del in delegateList)
+                    {
+                        consumed |= del(this, e);
+                    }
+                }
+                else
+                {
+                    consumed = interceptTouchDataEventHandler(this, e);
+                }
             }
 
             return consumed;
@@ -926,7 +938,19 @@ namespace Tizen.NUI.BaseComponents
 
             if (touchDataEventHandler != null)
             {
-                consumed = touchDataEventHandler(this, e);
+                if(NUIApplication.IsGeometryHittestEnabled())
+                {
+                    Delegate[] delegateList = touchDataEventHandler.GetInvocationList();
+                    // Oring the result of each callback.
+                    foreach (EventHandlerWithReturnType<object, TouchEventArgs, bool> del in delegateList)
+                    {
+                        consumed |= del(this, e);
+                    }
+                }
+                else
+                {
+                    consumed = touchDataEventHandler(this, e);
+                }
             }
 
             if (enableControlState && !consumed)
index fa15c6fe0ca0ba43e5c4dc6d7d3ca8355cd187d1..d9cdbf8eaed6c28e8bde20c13d91b7dcc3b938df 100755 (executable)
@@ -121,6 +121,32 @@ namespace Tizen.NUI
             return ret;
         }
 
+        /// <summary>
+        /// Handles the event for a given view and touch input.
+        /// This method should only be called when SetGeometryHittestEnabled is set to true.
+        /// It processes the touch input and attempts to recognize gestures based on the provided view and touch data.
+        /// </summary>
+        /// <param name="view">The view associated with the gesture detector.</param>
+        /// <param name="touch">The touch input data to analyze for gestures.</param>
+        /// <returns>True if the event was handled successfully, otherwise false.</returns>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public bool HandleEvent(View view, Touch touch)
+        {
+            bool ret = Interop.GestureDetector.HandleEvent(SwigCPtr, View.getCPtr(view), Touch.getCPtr(touch));
+            NDalicPINVOKE.ThrowExceptionIfExists();
+            return ret;
+        }
+
+        /// <summary>
+        /// Cancels all other gesture detectors that are currently recognizing gestures by HandleEvent(View view, Touch touch) api
+        /// </summary>
+        [EditorBrowsable(EditorBrowsableState.Never)]
+        public void CancelAllOtherGestureDetectors()
+        {
+            Interop.GestureDetector.CancelAllOtherGestureDetectors(SwigCPtr);
+            NDalicPINVOKE.ThrowExceptionIfExists();
+        }
+
         internal GestureDetector Assign(GestureDetector rhs)
         {
             GestureDetector ret = new GestureDetector(Interop.GestureDetector.Assign(SwigCPtr, GestureDetector.getCPtr(rhs)), false);
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedGestureSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedGestureSample.cs
new file mode 100755 (executable)
index 0000000..1f2438f
--- /dev/null
@@ -0,0 +1,450 @@
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class FeedGestureSample : IExample
+    {
+        private View rootView;
+
+        private PanGestureDetector panGestureDetectorOne;
+        private PanGestureDetector panGestureDetectorTwo;
+        private PanGestureDetector panGestureDetectorThree;
+
+
+        private LongPressGestureDetector longPressGestureDetectorOne;
+        private LongPressGestureDetector longPressGestureDetectorTwo;
+        private LongPressGestureDetector longPressGestureDetectorThree;
+
+        private TapGestureDetector tapGestureDetectorOne;
+        private TapGestureDetector tapGestureDetectorTwo;
+        private TapGestureDetector tapGestureDetectorThree;
+
+        private Vector3 startingScale = new Vector3(1.0f, 1.0f, 1.0f);
+        private float startingOrientation;
+        private PinchGestureDetector pinchGestureDetector;
+        private RotationGestureDetector rotationGestureDetector;
+
+        public void Activate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(true);
+
+            rootView = new View
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+            };
+
+            CreateViewUseOneDetector();
+            CreateViewUseTwoDetector();
+        }
+
+        private void CreateViewUseOneDetector()
+        {
+            Window window = NUIApplication.GetDefaultWindow();
+            var redView = new View
+            {
+                Size = new Size(500, 500),
+                Position = new Position(150, 170),
+                BackgroundColor = new Color(1.0f, 0.0f, 0.0f, 1.0f),
+                ClippingMode = ClippingModeType.ClipToBoundingBox,
+            };
+
+            var blueView = new View
+            {
+                Size2D = new Size2D(300, 700),
+                Position = new Position(100, 100),
+                BackgroundColor = Color.Blue,
+            };
+
+            var textField = new TextField()
+            {
+                Text = "Input",
+                Size2D = new Size2D(300, 100),
+                BackgroundColor = Color.Orange
+            };
+            redView.Add(blueView);
+            rootView.Add(redView);
+
+            var textLabel = new TextLabel
+            {
+                Text = "Use One Detector",
+                Size2D = new Size2D(300, 300),
+                Position = new Position(150, 550),
+            };
+
+            rootView.Add(textLabel);
+            window.Add(rootView);
+
+            var tempView = new View()
+            {
+                Size2D = new Size2D(300, 100),
+                Position = new Position(0, 600),
+                BackgroundColor = Color.Black,
+            };
+            blueView.Add(tempView);
+            tempView.TouchEvent += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $"tempView.TouchEvent\n");
+                return false;
+            };
+
+
+            TapOne(redView, blueView);
+            PanOne(redView, blueView);
+            LongPressOne(redView, blueView);
+        }
+
+        private void TapOne(View redView, View blueView)
+        {
+            tapGestureDetectorOne = new TapGestureDetector();
+            tapGestureDetectorOne.Detected += (s, e) =>
+            {
+                if(e.TapGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Yellow;
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                 if(e.Touch.GetState(0) == PointStateType.Down || e.Touch.GetState(0) == PointStateType.Interrupted)
+                 {
+                    redView.BackgroundColor = Color.Red;
+                 }
+                return tapGestureDetectorOne.HandleEvent(s as View, e.Touch);
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                 if(e.Touch.GetState(0) == PointStateType.Down || e.Touch.GetState(0) == PointStateType.Interrupted)
+                 {
+                    blueView.BackgroundColor = Color.Blue;
+                 }
+                return tapGestureDetectorOne.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private void PanOne(View redView, View blueView)
+        {
+            panGestureDetectorOne = new PanGestureDetector();
+            panGestureDetectorOne.SetMaximumTouchesRequired(2);
+            panGestureDetectorOne.Detected += (s, e) =>
+            {
+                if(e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    e.View.Position += new Position(e.PanGesture.ScreenDisplacement.X, e.PanGesture.ScreenDisplacement.Y);
+                }
+                // e.Handled = false;
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                return panGestureDetectorOne.HandleEvent(s as View, e.Touch);;
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                return panGestureDetectorOne.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private void LongPressOne(View redView, View blueView)
+        {
+            longPressGestureDetectorOne = new LongPressGestureDetector();
+            longPressGestureDetectorOne.Detected += (s, e) =>
+            {
+                if(e.LongPressGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Aqua;
+                }
+                else if (e.LongPressGesture.State == Gesture.StateType.Finished || e.LongPressGesture.State == Gesture.StateType.Cancelled)
+                {
+                    if(e.View == redView)
+                    {
+                        e.View.BackgroundColor = Color.Red;
+                    }
+                    if(e.View == blueView)
+                    {
+                        e.View.BackgroundColor = Color.Blue;
+                    }
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                return longPressGestureDetectorOne.HandleEvent(s as View, e.Touch);
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                return longPressGestureDetectorOne.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private void CreateViewUseTwoDetector()
+        {
+            Window window = NUIApplication.GetDefaultWindow();
+            var redView = new View
+            {
+                Size = new Size(500, 500),
+                Position = new Position(750, 170),
+                BackgroundColor = new Color(1.0f, 0.0f, 0.0f, 1.0f),
+                ClippingMode = ClippingModeType.ClipToBoundingBox,
+            };
+
+            var blueView = new View
+            {
+                Size2D = new Size2D(300, 300),
+                Position = new Position(100, 100),
+                BackgroundColor = Color.Blue,
+            };
+
+            var textField = new TextField()
+            {
+                Text = "Input",
+                Size2D = new Size2D(300, 100),
+                BackgroundColor = Color.Orange
+            };
+            blueView.Add(textField);
+
+            redView.Add(blueView);
+            rootView.Add(redView);
+
+            var textLabel = new TextLabel
+            {
+                Text = "Use Two Detector",
+                Size2D = new Size2D(300, 300),
+                Position = new Position(750, 550),
+            };
+
+            var blockView = new View
+            {
+                Size2D = new Size2D(300, 100),
+                Position = new Position(200, 100),
+                BackgroundColor = Color.BurlyWood,
+            };
+            blockView.TouchEvent += (s, e) =>
+            {
+                return true;
+            };
+
+            rootView.Add(textLabel);
+            redView.Add(blockView);
+            window.Add(rootView);
+
+
+            // TapTwo(redView, blueView);
+            PanTwo(redView, blueView);
+            LongPressTwo(redView, blueView);
+            // Pinch(redView, blueView);
+            // Rotation(redView, blueView);
+        }
+
+        private void Rotation(View redView, View blueView)
+        {
+            rotationGestureDetector = new RotationGestureDetector();
+            rotationGestureDetector.Detected += (s, e) =>
+            {
+                if (e.RotationGesture.State == Gesture.StateType.Started)
+                {
+                    startingOrientation = e.RotationGesture.Rotation;
+                }
+                else if (e.RotationGesture.State != Gesture.StateType.Cancelled)
+                {
+                    Tizen.Log.Error("NUI", $"Rotation startingOrientation {startingOrientation}, { e.RotationGesture.Rotation}\n");
+                    e.View.RotateBy(new Radian(e.RotationGesture.Rotation), Vector3.ZAxis);
+                }
+            };
+
+            // redView.TouchEvent += (s, e) =>
+            // {
+            //     return rotationGestureDetector.HandleEvent(s as View, e.Touch);
+            // };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                // blueView.Orientation = new Rotation(new Radian(0.01f), Vector3.ZAxis);
+                // blueView.RotateBy(new Radian(0.01f), Vector3.ZAxis);
+                // return true;
+                return rotationGestureDetector.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private void Pinch(View redView, View blueView)
+        {
+            pinchGestureDetector = new PinchGestureDetector();
+            pinchGestureDetector.Detected += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $"Pinch state {e.PinchGesture.State}\n");
+                if (e.PinchGesture.State == Gesture.StateType.Started)
+                {
+                    startingScale = (Vector3)e.View.Scale.Clone();
+                }
+                else if (e.PinchGesture.State != Gesture.StateType.Cancelled)
+                {
+                    e.View.Scale = startingScale * e.PinchGesture.Scale;
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                return pinchGestureDetector.HandleEvent(s as View, e.Touch);
+            };
+
+            // blueView.TouchEvent += (s, e) =>
+            // {
+            //     return pinchGestureDetector.HandleEvent(s as View, e.Touch);
+            // };
+        }
+
+        private void TapTwo(View redView, View blueView)
+        {
+            tapGestureDetectorTwo = new TapGestureDetector();
+            tapGestureDetectorTwo.Detected += (s, e) =>
+            {
+                if(e.TapGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Yellow;
+                }
+            };
+
+            tapGestureDetectorThree = new TapGestureDetector();
+            tapGestureDetectorThree.Detected += (s, e) =>
+            {
+                if(e.TapGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Yellow;
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                 if(e.Touch.GetState(0) == PointStateType.Down || e.Touch.GetState(0) == PointStateType.Interrupted)
+                 {
+                    redView.BackgroundColor = Color.Red;
+                 }
+                return tapGestureDetectorThree.HandleEvent(s as View, e.Touch);
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                 if(e.Touch.GetState(0) == PointStateType.Down || e.Touch.GetState(0) == PointStateType.Interrupted)
+                 {
+                    blueView.BackgroundColor = Color.Blue;
+                 }
+                return tapGestureDetectorTwo.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private void PanTwo(View redView, View blueView)
+        {
+            panGestureDetectorTwo = new PanGestureDetector();
+            panGestureDetectorTwo.SetMaximumTouchesRequired(2);
+            panGestureDetectorTwo.Detected += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $" pan {e.PanGesture.State }\n");
+                if(e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    e.View.Position += new Position(e.PanGesture.ScreenDisplacement.X, e.PanGesture.ScreenDisplacement.Y);
+                }
+            };
+
+            panGestureDetectorThree = new PanGestureDetector();
+            panGestureDetectorThree.SetMaximumTouchesRequired(2);
+            panGestureDetectorThree.Detected += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $" pan {e.PanGesture.State }\n");
+                if(e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    e.View.Position += new Position(e.PanGesture.ScreenDisplacement.X, e.PanGesture.ScreenDisplacement.Y);
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                bool ret = panGestureDetectorThree.HandleEvent(s as View, e.Touch);;
+                return ret;
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                bool ret = panGestureDetectorTwo.HandleEvent(s as View, e.Touch);
+                if(ret) panGestureDetectorTwo.CancelAllOtherGestureDetectors();
+                return ret;
+            };
+        }
+
+        private void LongPressTwo(View redView, View blueView)
+        {
+            longPressGestureDetectorTwo = new LongPressGestureDetector();
+            longPressGestureDetectorTwo.Detected += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $" long {e.LongPressGesture.State }\n");
+                if(e.LongPressGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Aqua;
+                }
+                else if (e.LongPressGesture.State == Gesture.StateType.Finished || e.LongPressGesture.State == Gesture.StateType.Cancelled)
+                {
+                    if(e.View == redView)
+                    {
+                        e.View.BackgroundColor = Color.Red;
+                    }
+                    if(e.View == blueView)
+                    {
+                        e.View.BackgroundColor = Color.Blue;
+                    }
+                }
+            };
+
+            longPressGestureDetectorThree = new LongPressGestureDetector();
+            longPressGestureDetectorThree.Detected += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $" long {e.LongPressGesture.State }\n");
+                if(e.LongPressGesture.State == Gesture.StateType.Started)
+                {
+                    e.View.BackgroundColor = Color.Coral;
+                }
+                else if (e.LongPressGesture.State == Gesture.StateType.Finished || e.LongPressGesture.State == Gesture.StateType.Cancelled)
+                {
+                    if(e.View == redView)
+                    {
+                        e.View.BackgroundColor = Color.Red;
+                    }
+                    if(e.View == blueView)
+                    {
+                        e.View.BackgroundColor = Color.Blue;
+                    }
+                }
+            };
+
+            redView.TouchEvent += (s, e) =>
+            {
+                bool ret = longPressGestureDetectorThree.HandleEvent(s as View, e.Touch);
+                // Tizen.Log.Error("NUI", $"redView long {ret}\n");
+                return ret;
+            };
+
+            blueView.TouchEvent += (s, e) =>
+            {
+                bool ret = longPressGestureDetectorTwo.HandleEvent(s as View, e.Touch);
+                // Tizen.Log.Error("NUI", $"blueView long {ret}\n");
+                return ret;
+            };
+        }
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (rootView != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(rootView);
+                rootView.Dispose();
+            }
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSample.cs
new file mode 100755 (executable)
index 0000000..f168b79
--- /dev/null
@@ -0,0 +1,260 @@
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class FeedNestedPanGestureSample : IExample
+    {
+        private View root;
+
+        public class MyScrollView : View {
+            public enum Direction
+            {
+                Horizontal,
+                Vertical
+            }
+            public View ContentContainer { get; set; }
+
+            private PanGestureDetector mPanGestureDetector;
+            private Direction mScrollDirection = Direction.Vertical;
+            private float maxScrollDistance;
+            private float childTargetPosition = 0.0f;
+
+            public MyScrollView() : base()
+            {
+                Tizen.Log.Error("NUI", $"MyScrollView\n");
+                ClippingMode = ClippingModeType.ClipToBoundingBox;
+                base.Layout = new AbsoluteLayout();
+                ContentContainer = new View()
+                {
+                    BackgroundColor = Color.Grey,
+                };
+
+                ContentContainer.Relayout += OnScrollingChildRelayout;
+                base.Add(ContentContainer);
+                base.Relayout += OnScrollingChildRelayout;
+                this.TouchEvent += OnTouchEvent;
+                mPanGestureDetector = new PanGestureDetector();
+                mPanGestureDetector.SetMaximumTouchesRequired(10);
+                // mPanGestureDetector.Attach(this);
+                mPanGestureDetector.Detected += OnPanGestureDetected;
+            }
+
+            public override void Add(View view)
+            {
+                ContentContainer.Add(view);
+            }
+
+            public void SetDirection(Direction direction)
+            {
+                mScrollDirection = direction;
+                mPanGestureDetector.ClearAngles();
+                mPanGestureDetector.AddDirection(direction == Direction.Horizontal ?
+                        PanGestureDetector.DirectionHorizontal : PanGestureDetector.DirectionVertical);
+            }
+
+            private bool OnInterceptTouchEvent(object source, View.TouchEventArgs e)
+            {
+                Tizen.Log.Error("NUI", $"OnInterceptTouchEvent\n");
+                return true;
+            }
+
+            private bool OnTouchEvent(object source, View.TouchEventArgs e)
+            {
+                Tizen.Log.Error("NUI", $"OnTouchEvent {e.Touch.GetState(0)}\n");
+                bool ret = mPanGestureDetector.HandleEvent(source as View, e.Touch);
+                return ret;
+                // return true;
+            }
+
+            private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
+            {
+                if(e.PanGesture.State == Gesture.StateType.Started)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected Started {mScrollDirection}\n");
+                    e.View.InterceptTouchEvent += OnInterceptTouchEvent;
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    if(mScrollDirection == Direction.Horizontal)
+                    {
+                        ScrollBy(e.PanGesture.Displacement.X);
+                    }
+                    else
+                    {
+                        ScrollBy(e.PanGesture.Displacement.Y);
+                    }
+
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Finished || e.PanGesture.State == Gesture.StateType.Cancelled)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected {e.PanGesture.State}\n");
+                    e.View.InterceptTouchEvent -= OnInterceptTouchEvent;
+                }
+            }
+
+            private void OnScrollingChildRelayout(object source, EventArgs args)
+            {
+                maxScrollDistance = CalculateMaximumScrollDistance();
+            }
+
+            private float CalculateMaximumScrollDistance()
+            {
+                float scrollingChildLength = 0;
+                float scrollerLength = 0;
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    scrollingChildLength = ContentContainer.Size.Width;
+                    scrollerLength = Size.Width;
+                }
+                else
+                {
+                    scrollingChildLength = ContentContainer.Size.Height;
+                    scrollerLength = Size.Height;
+                }
+                return Math.Max(scrollingChildLength - scrollerLength, 0);
+            }
+
+            private void ScrollBy(float displacement)
+            {
+                float childCurrentPosition = (mScrollDirection == Direction.Horizontal) ? ContentContainer.PositionX : ContentContainer.PositionY;
+                childTargetPosition = childCurrentPosition + displacement;
+                float finalTargetPosition = BoundScrollPosition(childTargetPosition);
+
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    ContentContainer.PositionX = finalTargetPosition;
+                }
+                else
+                {
+                    ContentContainer.PositionY = finalTargetPosition;
+                }
+            }
+
+            private float BoundScrollPosition(float targetPosition)
+            {
+                targetPosition = Math.Min(0, targetPosition);
+                targetPosition = Math.Max(-maxScrollDistance, targetPosition);
+                return targetPosition;
+            }
+
+        }
+
+        private TapGestureDetector mItemTapDetector;
+        private LongPressGestureDetector mItemLongPressDetector;
+
+        public void Activate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(true);
+            Window window = NUIApplication.GetDefaultWindow();
+            root = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+            };
+
+            var myScrollView01 = new MyScrollView()
+            {
+                Size2D = new Size2D(1000,1000),
+            };
+            myScrollView01.ContentContainer.Size2D = new Size2D(1000, 2000);
+            myScrollView01.SetDirection(MyScrollView.Direction.Vertical);
+            myScrollView01.ContentContainer.Layout = new LinearLayout
+            {
+                LinearOrientation = LinearLayout.Orientation.Vertical,
+                CellPadding = new Size2D(20, 20),
+            };
+
+
+            mItemTapDetector = new TapGestureDetector();
+            mItemTapDetector.Detected += OnTapGestureDetected;
+
+            mItemLongPressDetector = new LongPressGestureDetector();
+            mItemLongPressDetector.Detected += OnLongPressGestureDetected;
+
+            myScrollView01.Add(GetNewScrollView(Color.Orange));
+            myScrollView01.Add(GetNewScrollView(Color.Blue));
+            myScrollView01.Add(GetNewScrollView(Color.Red));
+            myScrollView01.Add(GetNewScrollView(Color.Cyan));
+            myScrollView01.Add(GetNewScrollView(Color.DarkOrange));
+            myScrollView01.Add(GetNewScrollView(Color.DarkBlue));
+
+
+            root.Add(myScrollView01);
+
+            window.Add(root);
+        }
+
+
+        public View GetNewScrollView(Color color)
+        {
+            var scrollView = new MyScrollView()
+            {
+                Size2D = new Size2D(1000, 300),
+            };
+            scrollView.ContentContainer.Size2D = new Size2D(2000, 300);
+            scrollView.ContentContainer.BackgroundColor = color;
+            scrollView.SetDirection(MyScrollView.Direction.Horizontal);
+            scrollView.ContentContainer.Layout = new LinearLayout
+            {
+                LinearOrientation = LinearLayout.Orientation.Horizontal,
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+                CellPadding = new Size2D(50, 50),
+            };
+
+            for (int i=0; i<20; i++)
+            {
+                var item = new View()
+                {
+                    Size2D = new Size2D(100, 100),
+                    BackgroundColor = Color.DarkBlue,
+                };
+                item.TouchEvent += (s, e) =>
+                {
+                    bool ret = mItemTapDetector.HandleEvent(s as View, e.Touch);
+                    ret |= mItemLongPressDetector.HandleEvent(s as View, e.Touch);
+                    return ret;
+                    // return true;
+                };
+                scrollView.Add(item);
+            }
+            return scrollView;
+        }
+
+        private void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
+        {
+             Tizen.Log.Error("NUI", $"OnTapGestureDetected {e.TapGesture.State}\n");
+             e.View.BackgroundColor = Color.White;
+        }
+
+        private void OnLongPressGestureDetected(object source, LongPressGestureDetector.DetectedEventArgs e)
+        {
+            Tizen.Log.Error("NUI", $"OnLongPressGestureDetected {e.LongPressGesture.State}\n");
+            if(e.LongPressGesture.State == Gesture.StateType.Started)
+            {
+                e.View.BackgroundColor = Color.Yellow;
+            }
+            else if (e.LongPressGesture.State == Gesture.StateType.Finished || e.LongPressGesture.State == Gesture.StateType.Cancelled)
+            {
+                e.View.BackgroundColor = Color.DarkBlue;
+            }
+        }
+
+
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (root != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(root);
+                root.Dispose();
+            }
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSampleVertical.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedNestedPanGestureSampleVertical.cs
new file mode 100755 (executable)
index 0000000..19a5b51
--- /dev/null
@@ -0,0 +1,222 @@
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class FeedNestedPanGestureSampleVertical : IExample
+    {
+        private View root;
+
+        public class MyScrollView : View {
+            public enum Direction
+            {
+                Horizontal,
+                Vertical
+            }
+            public View ContentContainer { get; set; }
+
+            private PanGestureDetector mPanGestureDetector;
+            private Direction mScrollDirection = Direction.Vertical;
+            private float maxScrollDistance;
+            private float childTargetPosition = 0.0f;
+
+            public MyScrollView() : base()
+            {
+                Tizen.Log.Error("NUI", $"MyScrollView\n");
+                ClippingMode = ClippingModeType.ClipToBoundingBox;
+                base.Layout = new AbsoluteLayout();
+                ContentContainer = new View()
+                {
+                    BackgroundColor = Color.Grey,
+                };
+
+                ContentContainer.Relayout += OnScrollingChildRelayout;
+                base.Add(ContentContainer);
+                base.Relayout += OnScrollingChildRelayout;
+                this.TouchEvent += OnTouchEvent;
+                mPanGestureDetector = new PanGestureDetector();
+                mPanGestureDetector.Detected += OnPanGestureDetected;
+            }
+
+            public override void Add(View view)
+            {
+                ContentContainer.Add(view);
+            }
+
+            public void SetDirection(Direction direction)
+            {
+                mScrollDirection = direction;
+                mPanGestureDetector.ClearAngles();
+                mPanGestureDetector.AddDirection(direction == Direction.Horizontal ?
+                        PanGestureDetector.DirectionHorizontal : PanGestureDetector.DirectionVertical);
+            }
+
+            private bool OnTouchEvent(object source, View.TouchEventArgs e)
+            {
+                bool ret = mPanGestureDetector.HandleEvent(source as View, e.Touch);
+                Tizen.Log.Error("NUI", $"OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            }
+
+            private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
+            {
+                if(e.PanGesture.State == Gesture.StateType.Started)
+                {
+                    var checkDisplacement = (mScrollDirection == Direction.Horizontal) ? e.PanGesture.Displacement.X : e.PanGesture.Displacement.Y;
+                    var checkChildCurrentPosition = (mScrollDirection == Direction.Horizontal) ? ContentContainer.PositionX : ContentContainer.PositionY;
+                    var checkChildTargetPosition = checkChildCurrentPosition + checkDisplacement;
+                    var checkFinalTargetPosition = BoundScrollPosition(checkChildTargetPosition);
+                    bool handled = !((int)checkFinalTargetPosition == 0 || -(int)checkFinalTargetPosition == (int)maxScrollDistance);
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected Started {checkFinalTargetPosition} {maxScrollDistance} {handled}\n");
+                    // If you propagate a gesture event, return;
+                    if (!handled)
+                    {
+                        e.Handled = handled;
+                        return;
+                    }
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected mScrollDirection : {mScrollDirection} \n");
+                    if(mScrollDirection == Direction.Horizontal)
+                    {
+                        ScrollBy(e.PanGesture.Displacement.X);
+                    }
+                    else
+                    {
+                        ScrollBy(e.PanGesture.Displacement.Y);
+                    }
+
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Finished || e.PanGesture.State == Gesture.StateType.Cancelled)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected Finished or Cancelled\n");
+                }
+            }
+
+            private void OnScrollingChildRelayout(object source, EventArgs args)
+            {
+                maxScrollDistance = CalculateMaximumScrollDistance();
+            }
+
+            private float CalculateMaximumScrollDistance()
+            {
+                float scrollingChildLength = 0;
+                float scrollerLength = 0;
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    scrollingChildLength = ContentContainer.Size.Width;
+                    scrollerLength = Size.Width;
+                }
+                else
+                {
+                    scrollingChildLength = ContentContainer.Size.Height;
+                    scrollerLength = Size.Height;
+                }
+                return Math.Max(scrollingChildLength - scrollerLength, 0);
+            }
+
+            private void ScrollBy(float displacement)
+            {
+                float childCurrentPosition = (mScrollDirection == Direction.Horizontal) ? ContentContainer.PositionX : ContentContainer.PositionY;
+                childTargetPosition = childCurrentPosition + displacement;
+                float finalTargetPosition = BoundScrollPosition(childTargetPosition);
+
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    ContentContainer.PositionX = finalTargetPosition;
+                }
+                else
+                {
+                    ContentContainer.PositionY = finalTargetPosition;
+                }
+            }
+
+            private float BoundScrollPosition(float targetPosition)
+            {
+                targetPosition = Math.Min(0, targetPosition);
+                targetPosition = Math.Max(-maxScrollDistance, targetPosition);
+                return targetPosition;
+            }
+
+        }
+        public void Activate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(true);
+            Window window = NUIApplication.GetDefaultWindow();
+            root = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+            };
+
+            var myScrollView01 = new MyScrollView()
+            {
+                Size2D = new Size2D(1000,1000),
+            };
+            myScrollView01.ContentContainer.Size2D = new Size2D(1000, 2000);
+            myScrollView01.SetDirection(MyScrollView.Direction.Vertical);
+            myScrollView01.ContentContainer.Layout = new LinearLayout
+            {
+                LinearOrientation = LinearLayout.Orientation.Vertical,
+                CellPadding = new Size2D(20, 20),
+            };
+
+
+            myScrollView01.Add(GetNewScrollView(Color.Orange));
+            myScrollView01.Add(GetNewScrollView(Color.Blue));
+            myScrollView01.Add(GetNewScrollView(Color.Red));
+            myScrollView01.Add(GetNewScrollView(Color.Cyan));
+            myScrollView01.Add(GetNewScrollView(Color.DarkOrange));
+            myScrollView01.Add(GetNewScrollView(Color.DarkBlue));
+
+
+            root.Add(myScrollView01);
+
+            window.Add(root);
+        }
+
+        public View GetNewScrollView(Color color)
+        {
+            var scrollView = new MyScrollView()
+            {
+                Size2D = new Size2D(900, 500),
+            };
+            scrollView.ContentContainer.Size2D = new Size2D(900, 1000);
+            scrollView.ContentContainer.BackgroundColor = color;
+            scrollView.SetDirection(MyScrollView.Direction.Vertical);
+            scrollView.ContentContainer.Layout = new LinearLayout
+            {
+                LinearOrientation = LinearLayout.Orientation.Vertical,
+                HorizontalAlignment = HorizontalAlignment.Center,
+                // VerticalAlignment = VerticalAlignment.Center,
+                CellPadding = new Size2D(50, 50),
+            };
+            for (int i=0; i<20; i++)
+            {
+                var item = new View()
+                {
+                    Size2D = new Size2D(100, 100),
+                    BackgroundColor = Color.DarkBlue,
+                };
+                scrollView.Add(item);
+            }
+            return scrollView;
+        }
+
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (root != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(root);
+                root.Dispose();
+            }
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndLongPressGestureSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndLongPressGestureSample.cs
new file mode 100755 (executable)
index 0000000..59be671
--- /dev/null
@@ -0,0 +1,138 @@
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class FeedTapAndLongPressGestureSample : IExample
+    {
+        private View root;
+        private TapGestureDetector mTapGestureDetector;
+        private LongPressGestureDetector mLongPressGestureDetector;
+        private int view1TapCount = 0;
+        private int view1LongCount = 0;
+        private int view2TapCount = 0;
+        private int view3TapCount = 0;
+        private TextLabel view1;
+        private TextLabel view2;
+        private TextLabel view3;
+        public void Activate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(true);
+            Window window = NUIApplication.GetDefaultWindow();
+            root = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+            };
+
+            view1 = new TextLabel()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+                BackgroundColor = Color.Orange,
+                Text = "Long and Tap"
+            };
+
+            mTapGestureDetector = new TapGestureDetector();
+            mTapGestureDetector.Detected += OnTapGestureDetected;
+
+            mLongPressGestureDetector = new LongPressGestureDetector();
+            mLongPressGestureDetector.Detected += OnLongPressGestureDetected;
+            view1.TouchEvent += (s, e) =>
+            {
+                bool ret = mTapGestureDetector.HandleEvent(s as View, e.Touch);
+                // ret |= mLongPressGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view1 OnTouchEvent Tap {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            };
+
+            view1.TouchEvent += (s, e) =>
+            {
+                bool ret = mLongPressGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view1 OnTouchEvent Long {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            };
+
+            view2 = new TextLabel()
+            {
+                ParentOrigin = ParentOrigin.Center,
+                PivotPoint = PivotPoint.Center,
+                PositionUsesPivotPoint = true,
+                Size2D = new Size2D(500, 300),
+                BackgroundColor = Color.Aqua,
+                Text = "Tap"
+            };
+            view2.TouchEvent += (s, e) =>
+            {
+                bool ret = mTapGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view2 OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            };
+
+
+            view3 = new TextLabel()
+            {
+                ParentOrigin = ParentOrigin.Center,
+                PivotPoint = PivotPoint.Center,
+                PositionUsesPivotPoint = true,
+                Size2D = new Size2D(300, 200),
+                BackgroundColor = Color.Red,
+                Text = "Tap"
+            };
+            view3.TouchEvent += (s, e) =>
+            {
+                bool ret = mTapGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view3 OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return false;
+            };
+
+
+            view1.Add(view2);
+            view2.Add(view3);
+            root.Add(view1);
+
+            window.Add(root);
+        }
+
+        private void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
+        {
+            Tizen.Log.Error("NUI", $"OnTapGestureDetected\n");
+            if(e.View == view1)
+            {
+                view1.Text = "view1 Long count "+view1LongCount +" Tap count "+(++view1TapCount);
+            }
+            else if (e.View == view2)
+            {
+                view2.Text = "view2 tap count "+(++view2TapCount);
+            }
+            else if (e.View == view3)
+            {
+                view3.Text = "view3 tap count "+(++view3TapCount);
+            }
+        }
+
+        private void OnLongPressGestureDetected(object source, LongPressGestureDetector.DetectedEventArgs e)
+        {
+            Tizen.Log.Error("NUI", $"OnLongPressGestureDetected {e.LongPressGesture.State}\n");
+            if(e.LongPressGesture.State == Gesture.StateType.Started)
+            {
+                view1.Text = "view1 Long count "+(++view1LongCount) +" Tap count "+view1TapCount;
+            }
+        }
+
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (root != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(root);
+                root.Dispose();
+            }
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndPanGestureSample.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/FeedTapAndPanGestureSample.cs
new file mode 100755 (executable)
index 0000000..d1c105f
--- /dev/null
@@ -0,0 +1,248 @@
+using System;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class FeedTapAndPanGestureSample : IExample
+    {
+        private View root;
+
+        public class MyScrollView : View {
+            public enum Direction
+            {
+                Horizontal,
+                Vertical
+            }
+            public View ContentContainer { get; set; }
+
+            private PanGestureDetector mPanGestureDetector;
+            private Direction mScrollDirection = Direction.Vertical;
+            private float maxScrollDistance;
+            private float childTargetPosition = 0.0f;
+
+            public MyScrollView() : base()
+            {
+                Tizen.Log.Error("NUI", $"MyScrollView\n");
+                ClippingMode = ClippingModeType.ClipToBoundingBox;
+                base.Layout = new AbsoluteLayout();
+                ContentContainer = new View()
+                {
+                    BackgroundColor = Color.Grey,
+                };
+
+                ContentContainer.Relayout += OnScrollingChildRelayout;
+                base.Add(ContentContainer);
+                base.Relayout += OnScrollingChildRelayout;
+                this.TouchEvent += OnTouchEvent;
+                mPanGestureDetector = new PanGestureDetector();
+                mPanGestureDetector.Detected += OnPanGestureDetected;
+            }
+
+            public override void Add(View view)
+            {
+                ContentContainer.Add(view);
+            }
+
+            public void SetDirection(Direction direction)
+            {
+                mScrollDirection = direction;
+                mPanGestureDetector.ClearAngles();
+                mPanGestureDetector.AddDirection(direction == Direction.Horizontal ?
+                        PanGestureDetector.DirectionHorizontal : PanGestureDetector.DirectionVertical);
+            }
+
+            private bool OnTouchEvent(object source, View.TouchEventArgs e)
+            {
+                bool ret = mPanGestureDetector.HandleEvent(source as View, e.Touch);
+                Tizen.Log.Error("NUI", $"OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            }
+
+            private void OnPanGestureDetected(object source, PanGestureDetector.DetectedEventArgs e)
+            {
+                if(e.PanGesture.State == Gesture.StateType.Started)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected Started\n");
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Continuing)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected mScrollDirection : {mScrollDirection} \n");
+                    if(mScrollDirection == Direction.Horizontal)
+                    {
+                        ScrollBy(e.PanGesture.Displacement.X);
+                    }
+                    else
+                    {
+                        ScrollBy(e.PanGesture.Displacement.Y);
+                    }
+
+                }
+                else if (e.PanGesture.State == Gesture.StateType.Finished || e.PanGesture.State == Gesture.StateType.Cancelled)
+                {
+                    Tizen.Log.Error("NUI", $"OnPanGestureDetected Finished or Cancelled\n");
+                }
+            }
+
+            private void OnScrollingChildRelayout(object source, EventArgs args)
+            {
+                maxScrollDistance = CalculateMaximumScrollDistance();
+            }
+
+            private float CalculateMaximumScrollDistance()
+            {
+                float scrollingChildLength = 0;
+                float scrollerLength = 0;
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    scrollingChildLength = ContentContainer.Size.Width;
+                    scrollerLength = Size.Width;
+                }
+                else
+                {
+                    scrollingChildLength = ContentContainer.Size.Height;
+                    scrollerLength = Size.Height;
+                }
+                return Math.Max(scrollingChildLength - scrollerLength, 0);
+            }
+
+            private void ScrollBy(float displacement)
+            {
+                float childCurrentPosition = (mScrollDirection == Direction.Horizontal) ? ContentContainer.PositionX : ContentContainer.PositionY;
+                childTargetPosition = childCurrentPosition + displacement;
+                float finalTargetPosition = BoundScrollPosition(childTargetPosition);
+
+                if (mScrollDirection == Direction.Horizontal)
+                {
+                    ContentContainer.PositionX = finalTargetPosition;
+                }
+                else
+                {
+                    ContentContainer.PositionY = finalTargetPosition;
+                }
+            }
+
+            private float BoundScrollPosition(float targetPosition)
+            {
+                targetPosition = Math.Min(0, targetPosition);
+                targetPosition = Math.Max(-maxScrollDistance, targetPosition);
+                return targetPosition;
+            }
+
+        }
+
+        private TapGestureDetector mTapGestureDetector;
+        private int view1TapCount = 0;
+        private int view3TapCount = 0;
+        private TextLabel view1;
+        private TextLabel view3;
+        public void Activate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(true);
+            Window window = NUIApplication.GetDefaultWindow();
+            root = new View()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+            };
+
+            view1 = new TextLabel()
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+                BackgroundColor = Color.Orange,
+            };
+
+            mTapGestureDetector = new TapGestureDetector();
+            mTapGestureDetector.Detected += OnTapGestureDetected;
+            view1.TouchEvent += (s, e) =>
+            {
+                bool ret = mTapGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view1 OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            };
+
+            var view2 = new View()
+            {
+                Position2D = new Position2D(100, 100),
+                Size2D = new Size2D(1000,300),
+                BackgroundColor = Color.Aqua,
+            };
+            view2.Add(GetNewScrollView(Color.Azure));
+
+            view3 = new TextLabel()
+            {
+                Position2D = new Position2D(500, 500),
+                Size2D = new Size2D(300,300),
+                BackgroundColor = Color.Red,
+            };
+            view3.TouchEvent += (s, e) =>
+            {
+                bool ret = mTapGestureDetector.HandleEvent(s as View, e.Touch);
+                Tizen.Log.Error("NUI", $"view3 OnTouchEvent {e.Touch.GetState(0)} : {ret}\n");
+                return ret;
+            };
+
+            view1.Add(view2);
+            view1.Add(view3);
+            root.Add(view1);
+
+            window.Add(root);
+        }
+
+        public View GetNewScrollView(Color color)
+        {
+            var scrollView = new MyScrollView()
+            {
+                Size2D = new Size2D(1000, 300),
+            };
+            scrollView.ContentContainer.Size2D = new Size2D(2000, 300);
+            scrollView.ContentContainer.BackgroundColor = color;
+            scrollView.SetDirection(MyScrollView.Direction.Horizontal);
+            scrollView.ContentContainer.Layout = new LinearLayout
+            {
+                LinearOrientation = LinearLayout.Orientation.Horizontal,
+                HorizontalAlignment = HorizontalAlignment.Begin,
+                VerticalAlignment = VerticalAlignment.Center,
+                CellPadding = new Size2D(50, 50),
+            };
+            for (int i=0; i<20; i++)
+            {
+                var item = new View()
+                {
+                    Size2D = new Size2D(100, 100),
+                    BackgroundColor = Color.DarkBlue,
+                };
+                scrollView.Add(item);
+            }
+            return scrollView;
+        }
+
+        private void OnTapGestureDetected(object source, TapGestureDetector.DetectedEventArgs e)
+        {
+            Tizen.Log.Error("NUI", $"OnTapGestureDetected\n");
+            if(e.View == view1)
+            {
+                view1.Text = "view1 tap count "+(++view1TapCount);
+            }
+            else if (e.View == view3)
+            {
+                view3.Text = "view3 tap count "+(++view3TapCount);
+            }
+        }
+
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (root != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(root);
+                root.Dispose();
+            }
+        }
+    }
+}
diff --git a/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/GeometryTouchEvent.cs b/test/Tizen.NUI.Samples/Tizen.NUI.Samples/Samples/GeometryTouchEvent.cs
new file mode 100755 (executable)
index 0000000..8977f12
--- /dev/null
@@ -0,0 +1,866 @@
+using System;
+using System.Collections.Generic;
+using Tizen.NUI;
+using Tizen.NUI.BaseComponents;
+using Tizen.NUI.Components;
+using Tizen.NUI.Events;
+
+
+namespace Tizen.NUI.Samples
+{
+    public class GeometryTouchEvent : IExample
+    {
+        class LogOutput : ScrollableBase
+        {
+            public LogOutput() : base()
+            {
+                SizeWidth = 500;
+                BackgroundColor = Color.AntiqueWhite;
+                // WidthSpecification = LayoutParamPolicies.MatchParent;
+                HeightSpecification = LayoutParamPolicies.MatchParent;
+                // HideScrollbar = false;
+                ScrollingDirection = ScrollableBase.Direction.Vertical;
+
+                ContentContainer.Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    VerticalAlignment = VerticalAlignment.Top,
+                };
+            }
+
+            public void AddLog(string log)
+            {
+                Console.WriteLine($"{log}\n");
+                var txt = new TextLabel
+                {
+                    Text = log
+                };
+
+                ContentContainer.Add(txt);
+                if (ContentContainer.Children.Count > 30)
+                {
+                    var remove = ContentContainer.Children.GetRange(0, 10);
+                    foreach (var child in remove)
+                    {
+                        ContentContainer.Remove(child);
+                    }
+                }
+                ElmSharp.EcoreMainloop.Post(() =>
+                {
+                    ScrollTo((ContentContainer.Children.Count) * (txt.NaturalSize.Height), true);
+                });
+            }
+            public override View GetNextFocusableView(View currentFocusedView, View.FocusDirection direction, bool loopEnabled)
+            {
+                return null;
+            }
+        }
+
+
+        private TapGestureDetector[] tapGestureDetector = new TapGestureDetector[4];
+        private PanGestureDetector[] panGestureDetector = new PanGestureDetector[4];
+        private LongPressGestureDetector[] longPressGestureDetector = new LongPressGestureDetector[4];
+        private List<GestureDetector>[] gestureDetector = new List<GestureDetector>[4];
+        private Color backgroundColor = Color.White;
+
+
+        private PanGestureDetector tempPanGestureDetector;
+
+        private Window window;
+        private View blueView;
+        private View yellowView;
+        private View redView;
+        private View orangeView;
+        private LogOutput log;
+        private View root;
+
+        public void Activate()
+        {
+            Tizen.Log.Error("NUI", $"NUIApplication.SetGeometryTouchGesture(true);!!!!!!!!!!!!!!!\n");
+            NUIApplication.SetGeometryHittestEnabled(true);
+            window = NUIApplication.GetDefaultWindow();
+            window.BackgroundColor = Color.Grey;
+
+            // var tempWindow = new Window("subwin1", null, new Rectangle(20, 20, 800, 800), false);
+
+            root = new View
+            {
+                WidthResizePolicy = ResizePolicyType.FillToParent,
+                HeightResizePolicy = ResizePolicyType.FillToParent,
+
+            };
+            root.Name = "root";
+
+            // default hittest, do not parent-child
+            blueView = new View
+            {
+                Name = "blueView",
+                Size2D = new Size2D(700, 500),
+                Position2D = new Position2D(500, 10),
+                BackgroundColor = Color.Blue,
+            };
+            var blueTxt = new TextLabel
+            {
+                Text = "Blue",
+            };
+            blueView.Add(blueTxt);
+
+            yellowView = new View
+            {
+                Name = "yellowView",
+                Size2D = new Size2D(600, 350),
+                Position2D = new Position2D(550, 60),
+                BackgroundColor = Color.Yellow,
+            };
+            var yellowTxt = new TextLabel
+            {
+                Text = "Yellow",
+            };
+            yellowView.Add(yellowTxt);
+
+
+            redView = new View
+            {
+                Name = "redView",
+                Size2D = new Size2D(300, 150),
+                Position2D = new Position2D(590, 120),
+                BackgroundColor = Color.Red,
+                // ClippingMode = ClippingModeType.ClipChildren,
+            };
+            var redTxt = new TextLabel
+            {
+                Text = "Red",
+            };
+            redView.Add(redTxt);
+
+
+            orangeView = new View
+            {
+                Name = "orangeView",
+                Size2D = new Size2D(700, 100),
+                Position2D = new Position2D(50, 30),
+                BackgroundColor = Color.Orange,
+            };
+            var orangeTxt = new TextLabel
+            {
+                Text = "Orange",
+            };
+            orangeView.Add(orangeTxt);
+
+            var tempView = new View
+            {
+                 Name = "orangeView",
+                Size2D = new Size2D(700, 100),
+                Position2D = new Position2D(50, 30),
+                BackgroundColor = Color.AntiqueWhite,
+            };
+            var tempTxt = new TextLabel
+            {
+                Text = "Temp",
+            };
+            tempView.HoverEvent += (s, e) =>
+            {
+                Tizen.Log.Error("NUI", $"TempView Hover {e.Hover.GetState(0)}\n");
+                log.AddLog($" ->Temp Hover {e.Hover.GetState(0)}\n");
+                return false;
+            };
+            tempView.Add(tempTxt);
+            orangeView.Add(tempView);
+
+
+            log = new LogOutput();
+
+            redView.Add(orangeView);
+            root.Add(blueView);
+            root.Add(yellowView);
+            root.Add(redView);
+            window.Add(root);
+            window.Add(log);
+
+            //test code
+            // for(int i = 0; i<2000; i++)
+            // {
+            //     var testView = new View()
+            //     {
+            //         Size2D = new Size2D (500, 500),
+            //         Position2D = new Position2D(595, 125),
+            //         BackgroundColor = new Vector4(0.5f, 1.0f, 0.5f, 0.5f),
+            //     };
+            //     window.Add(testView);
+            // }
+
+            for(int i =0; i<4; i++)
+            {
+                string name = GetName(i);
+                tapGestureDetector[i] = new TapGestureDetector();
+                tapGestureDetector[i].Detected += (s, e) =>
+                {
+                    Tizen.Log.Error("NUI", $"{name} tapGestureDetectorn");
+                    log.AddLog($" ->{name} OnTap {e.TapGesture.State}\n");
+                };
+                panGestureDetector[i] = new PanGestureDetector();
+                panGestureDetector[i].Detected += (s, e) =>
+                {
+                    Tizen.Log.Error("NUI", $"{name} panGestureDetector");
+                    log.AddLog($" ->{name} OnPan {e.PanGesture.State}\n");
+                };
+                longPressGestureDetector[i] = new LongPressGestureDetector();
+                longPressGestureDetector[i].Detected += (s, e) =>
+                {
+                    Tizen.Log.Error("NUI", $"{name} longPressGestureDetector");
+                    log.AddLog($" ->{name} OnLong {e.LongPressGesture.State} {s}\n");
+
+                    var senderView = e.View;
+                    if(e.LongPressGesture.State == Gesture.StateType.Started)
+                    {
+                        backgroundColor = new Color(senderView.BackgroundColor);
+                        senderView.BackgroundColor = senderView.BackgroundColor * 0.7f;
+                    }
+
+                    if(e.LongPressGesture.State == Gesture.StateType.Finished || e.LongPressGesture.State == Gesture.StateType.Cancelled)
+                     {
+                        senderView.BackgroundColor = backgroundColor;
+                     }
+                };
+                gestureDetector[i] = new List<GestureDetector>();
+            }
+
+            // MakeInterceptTouchList();
+            // MakeTouchList();
+            // MakeGestureList();
+            // MakeHoverList();
+
+            LongPanGestureTest();
+        }
+
+        public void LongPanGestureTest()
+        {
+
+            orangeView.TouchEvent += (s, e) =>
+            {
+                log.AddLog($" ->orangeView touch11 {e.Touch.GetState(0)}\n");
+                longPressGestureDetector[3].HandleEvent(s as View, e.Touch);
+                return false;
+            };
+
+
+            tempPanGestureDetector = new PanGestureDetector();
+            Color tempColor = yellowView.BackgroundColor * 0.7f;;
+            tempPanGestureDetector.Detected += (s, e) =>
+            {
+                if(e.View == orangeView)
+                {
+                    log.AddLog($" -> tempPanGestureDetector orangeView OnPan {e.PanGesture.State}\n");
+                }
+                else if (e.View == yellowView)
+                {
+                    log.AddLog($" -> tempPanGestureDetector yellowView OnPan {e.PanGesture.State}\n");
+                }
+                if(e.PanGesture.State == Gesture.StateType.Finished || e.PanGesture.State == Gesture.StateType.Cancelled)
+                {
+                    yellowView.BackgroundColor = Color.Yellow;
+                }
+                else
+                {
+                    yellowView.BackgroundColor = tempColor;
+                }
+            };
+
+            yellowView.InterceptTouchEvent += (s, e) =>
+            {
+                return tempPanGestureDetector.HandleEvent(s as View, e.Touch);
+            };
+
+            yellowView.TouchEvent += (s, e) =>
+            {
+                return tempPanGestureDetector.HandleEvent(s as View, e.Touch);
+            };
+        }
+
+        private bool blueInterceptConsumed = false;
+        private bool yellowInterceptConsumed = false;
+        private bool redInterceptConsumed = false;
+        private bool orangeInterceptConsumed = false;
+        public void MakeInterceptTouchEvent(View list, View targetView, string name, Tizen.NUI.EventHandlerWithReturnType<object, Tizen.NUI.BaseComponents.View.TouchEventArgs, bool> interceptEvent)
+        {
+            var interceptButtonList = new View()
+            {
+                Size2D = new Size2D(300, 70),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                },
+            };
+            var checkBox = new CheckBox
+            {
+                Text = name
+            };
+            checkBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected == true)
+                {
+                    targetView.InterceptTouchEvent += interceptEvent;
+                }
+                else
+                {
+                    targetView.InterceptTouchEvent -= interceptEvent;
+                }
+            };
+            var consumedCheck = new CheckBox
+            {
+                Text = "Consumed"
+            };
+            if(name == "Blue")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    blueInterceptConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Yellow")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    yellowInterceptConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Red")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    redInterceptConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Orange")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    orangeInterceptConsumed = args.IsSelected;
+                };
+            }
+            interceptButtonList.Add(checkBox);
+            interceptButtonList.Add(consumedCheck);
+            list.Add(interceptButtonList);
+        }
+
+        public void MakeInterceptTouchList()
+        {
+            var buttonLayer = new View()
+            {
+                Size2D = new Size2D(700, 400),
+                Position2D = new Position2D(500, 560),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    VerticalAlignment = VerticalAlignment.Top,
+                },
+            };
+
+            var interceptText = new TextLabel()
+            {
+                Text = "InterceptTouch"
+            };
+            buttonLayer.Add(interceptText);
+
+            MakeInterceptTouchEvent(buttonLayer, blueView, "Blue", BlueInterceptTouched);
+            MakeInterceptTouchEvent(buttonLayer, yellowView, "Yellow", YellowInterceptTouched);
+            MakeInterceptTouchEvent(buttonLayer, redView, "Red", RedInterceptTouched);
+            MakeInterceptTouchEvent(buttonLayer, orangeView, "Orange", OrangeInterceptTouched);
+            window.Add(buttonLayer);
+        }
+
+        private bool blueConsumed = false;
+        private bool yellowConsumed = false;
+        private bool redConsumed = false;
+        private bool orangeConsumed = false;
+        public void MakeTouchEvent(View list, View targetView, string name, Tizen.NUI.EventHandlerWithReturnType<object, Tizen.NUI.BaseComponents.View.TouchEventArgs, bool> touchEvent)
+        {
+            var buttonList = new View()
+            {
+                Size2D = new Size2D(300, 70),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                },
+            };
+            var checkBox = new CheckBox
+            {
+                Text = name
+            };
+            checkBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected == true)
+                {
+                    targetView.TouchEvent += touchEvent;
+                }
+                else
+                {
+                    targetView.TouchEvent -= touchEvent;
+                }
+            };
+            var consumedCheck = new CheckBox
+            {
+                Text = "Consumed"
+            };
+            if(name == "Blue")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    blueConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Yellow")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    yellowConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Red")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    redConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Orange")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    orangeConsumed = args.IsSelected;
+                };
+            }
+            buttonList.Add(checkBox);
+            buttonList.Add(consumedCheck);
+            list.Add(buttonList);
+        }
+        public void MakeTouchList()
+        {
+            var buttonLayer = new View()
+            {
+                Size2D = new Size2D(700, 400),
+                Position2D = new Position2D(850, 560),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    VerticalAlignment = VerticalAlignment.Top,
+                },
+            };
+
+            var title = new TextLabel()
+            {
+                Text = "Touch"
+            };
+            buttonLayer.Add(title);
+
+            MakeTouchEvent(buttonLayer, blueView, "Blue", BlueTouched);
+            MakeTouchEvent(buttonLayer, yellowView, "Yellow", YellowTouched);
+            MakeTouchEvent(buttonLayer, redView, "Red", RedTouched);
+            MakeTouchEvent(buttonLayer, orangeView, "Orange", OrangeTouched);
+            window.Add(buttonLayer);
+        }
+
+        private bool blueHoverConsumed = false;
+        private bool yellowHoverConsumed = false;
+        private bool redHoverConsumed = false;
+        private bool orangeHoverConsumed = false;
+        public void MakeHoverEvent(View list, View targetView, string name, Tizen.NUI.EventHandlerWithReturnType<object, Tizen.NUI.BaseComponents.View.HoverEventArgs, bool> hoverEvent)
+        {
+            var buttonList = new View()
+            {
+                Size2D = new Size2D(300, 70),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                },
+            };
+            var checkBox = new CheckBox
+            {
+                Text = name
+            };
+            checkBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected == true)
+                {
+                    targetView.HoverEvent += hoverEvent;
+                }
+                else
+                {
+                    targetView.HoverEvent -= hoverEvent;
+                }
+            };
+            var consumedCheck = new CheckBox
+            {
+                Text = "Consumed"
+            };
+            if(name == "Blue")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    blueHoverConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Yellow")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    yellowHoverConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Red")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    redHoverConsumed = args.IsSelected;
+                };
+            }
+            else if(name == "Orange")
+            {
+                consumedCheck.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+                {
+                    orangeHoverConsumed = args.IsSelected;
+                };
+            }
+            buttonList.Add(checkBox);
+            buttonList.Add(consumedCheck);
+            list.Add(buttonList);
+        }
+        public void MakeHoverList()
+        {
+            var buttonLayer = new View()
+            {
+                Size2D = new Size2D(700, 400),
+                Position2D = new Position2D(550, 560),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    VerticalAlignment = VerticalAlignment.Top,
+                },
+            };
+
+            var title = new TextLabel()
+            {
+                Text = "Hover"
+            };
+            buttonLayer.Add(title);
+
+            MakeHoverEvent(buttonLayer, blueView, "Blue", BlueHover);
+            MakeHoverEvent(buttonLayer, yellowView, "Yellow", YellowHover);
+            MakeHoverEvent(buttonLayer, redView, "Red", RedHover);
+            MakeHoverEvent(buttonLayer, orangeView, "Orange", OrangeHover);
+            window.Add(buttonLayer);
+        }
+
+        public int GetIndex(string name)
+        {
+            if(name == "Blue")
+            {
+                return 0;
+            }
+            else if(name == "Yellow")
+            {
+                return 1;
+            }
+            else if(name == "Red")
+            {
+                return 2;
+            }
+            else if(name == "Orange")
+            {
+                return 3;
+            }
+            return -1;
+        }
+
+        public string GetName(int index)
+        {
+            switch(index)
+            {
+                case 0 :
+                    return "Blue";
+                case 1 :
+                    return "Yellow";
+                case 2 :
+                    return "Red";
+                case 3 :
+                    return "Orange";
+                default :
+                    return "Unknown";
+            }
+        }
+
+        public void MakeGestureEvent(View list, View targetView, string name)
+        {
+            var buttonList = new View()
+            {
+                Size2D = new Size2D(300, 70),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Horizontal,
+                    VerticalAlignment = VerticalAlignment.Center,
+                },
+            };
+            // var viewText = new TextLabel
+            // {
+            //     Text = name+" : "
+            // };
+            // buttonList.Add(viewText);
+
+            var tapCheckBox = new CheckBox
+            {
+                Text = "Tap"
+            };
+
+            tapCheckBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected)
+                {
+                    gestureDetector[GetIndex(name)].Add(tapGestureDetector[GetIndex(name)]);
+                }
+                else
+                {
+                    gestureDetector[GetIndex(name)].Remove(tapGestureDetector[GetIndex(name)]);
+                }
+            };
+
+            var longCheckBox = new CheckBox
+            {
+                Text = "LongPress"
+            };
+            longCheckBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected)
+                {
+                    gestureDetector[GetIndex(name)].Add(longPressGestureDetector[GetIndex(name)]);
+                }
+                else
+                {
+                    gestureDetector[GetIndex(name)].Remove(longPressGestureDetector[GetIndex(name)]);
+                }
+            };
+
+            var panCheckBox = new CheckBox
+            {
+                Text = "Pan"
+            };
+            panCheckBox.SelectedChanged += (object sender, SelectedChangedEventArgs args) =>
+            {
+                if(args.IsSelected)
+                {
+                    gestureDetector[GetIndex(name)].Add(panGestureDetector[GetIndex(name)]);
+                }
+                else
+                {
+                    gestureDetector[GetIndex(name)].Remove(panGestureDetector[GetIndex(name)]);
+                }
+            };
+
+            buttonList.Add(tapCheckBox);
+            buttonList.Add(longCheckBox);
+            buttonList.Add(panCheckBox);
+            list.Add(buttonList);
+        }
+
+        public void MakeGestureList()
+        {
+            var buttonLayer = new View()
+            {
+                Size2D = new Size2D(700, 400),
+                Position2D = new Position2D(1200, 560),
+                Layout = new LinearLayout
+                {
+                    LinearOrientation = LinearLayout.Orientation.Vertical,
+                    VerticalAlignment = VerticalAlignment.Top,
+                },
+            };
+            var title = new TextLabel()
+            {
+                Text = "Gesture"
+            };
+            buttonLayer.Add(title);
+            MakeGestureEvent(buttonLayer, blueView, "Blue");
+            MakeGestureEvent(buttonLayer, yellowView, "Yellow");
+            MakeGestureEvent(buttonLayer, redView, "Red");
+            MakeGestureEvent(buttonLayer, orangeView, "Orange");
+            window.Add(buttonLayer);
+        }
+
+        private bool BlueInterceptTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"blueView InterceptTouchEvent {args.Touch.GetState(0)} return {blueInterceptConsumed}\n");
+            log.AddLog($" ->InterceptBlue View {args.Touch.GetState(0)} return {blueInterceptConsumed}\n");
+            return blueInterceptConsumed;
+        }
+
+        private bool YellowInterceptTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"yellowView InterceptTouchEvent {args.Touch.GetState(0)} return {yellowInterceptConsumed}\n");
+            log.AddLog($" ->InterceptYellow View {args.Touch.GetState(0)} return {yellowInterceptConsumed}\n");
+            return yellowInterceptConsumed;
+        }
+
+
+        private bool RedInterceptTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"redView InterceptTouchEvent {args.Touch.GetState(0)} return {redInterceptConsumed}\n");
+            log.AddLog($" ->InterceptRed View {args.Touch.GetState(0)} return {redInterceptConsumed}\n");
+            return redInterceptConsumed;
+        }
+
+
+        private bool OrangeInterceptTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"orangeView InterceptTouchEvent {args.Touch.GetState(0)} return {orangeInterceptConsumed}\n");
+            log.AddLog($" ->InterceptOrange View {args.Touch.GetState(0)} return {orangeInterceptConsumed}\n");
+            return orangeInterceptConsumed;
+        }
+
+        private bool BlueTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"blueView TouchEvent {args.Touch.GetState(0)}\n");
+            log.AddLog($" ->Blue View {args.Touch.GetState(0)}\n");
+            bool ret = false;
+            foreach(var detector in gestureDetector[0])
+            {
+                ret |= detector.HandleEvent(sender as View, args.Touch);
+            }
+            return blueConsumed | ret;
+        }
+
+        private bool YellowTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"yellowView TouchEvent {args.Touch.GetState(0)}\n");
+            log.AddLog($" ->Yellow View {args.Touch.GetState(0)}\n");
+            bool ret = false;
+            foreach(var detector in gestureDetector[1])
+            {
+                ret |= detector.HandleEvent(sender as View, args.Touch);
+            }
+            return yellowConsumed | ret;
+        }
+
+
+        private bool RedTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"redView TouchEvent {args.Touch.GetState(0)}\n");
+            log.AddLog($" ->Red View {args.Touch.GetState(0)}\n");
+            bool ret = false;
+            foreach(var detector in gestureDetector[2])
+            {
+                ret |= detector.HandleEvent(sender as View, args.Touch);
+            }
+            return redConsumed | ret;
+        }
+
+
+        private bool OrangeTouched(object sender, View.TouchEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"orangeView TouchEvent {args.Touch.GetState(0)}\n");
+            log.AddLog($" ->Orange View {args.Touch.GetState(0)}\n");
+            bool ret = false;
+            foreach(var detector in gestureDetector[3])
+            {
+                ret |= detector.HandleEvent(sender as View, args.Touch);
+            }
+            return orangeConsumed | ret;
+        }
+
+        //// hover
+        private bool BlueHover(object sender, View.HoverEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"blueView Hover {args.Hover.GetState(0)}\n");
+            log.AddLog($" ->Blue Hover {args.Hover.GetState(0)}\n");
+            return blueHoverConsumed;
+        }
+
+        private bool YellowHover(object sender, View.HoverEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"yellowView Hover {args.Hover.GetState(0)}\n");
+            log.AddLog($" ->Yellow Hover {args.Hover.GetState(0)}\n");
+            return yellowHoverConsumed;
+        }
+
+
+        private bool RedHover(object sender, View.HoverEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"redView Hover {args.Hover.GetState(0)}\n");
+            log.AddLog($" ->Red Hover {args.Hover.GetState(0)}\n");
+            return redHoverConsumed;
+        }
+
+
+        private bool OrangeHover(object sender, View.HoverEventArgs args)
+        {
+            Tizen.Log.Error("NUI", $"orangeView Hover {args.Hover.GetState(0)}\n");
+            log.AddLog($" ->Orange Hover {args.Hover.GetState(0)}\n");
+            return orangeHoverConsumed;
+        }
+        ///
+
+
+        static View CreateButton(int index)
+        {
+            var rnd = new Random();
+
+            var btn = new Button
+            {
+                Focusable = true,
+                FocusableInTouch = true,
+                Text = $"Item {index}",
+                LeaveRequired = true,
+                BackgroundColor = Color.DarkOrange,
+            };
+            btn.HoverEvent += (s, e) =>
+            {
+                if(e.Hover.GetState(0) == PointStateType.Started)
+                {
+                    btn.BackgroundColor = Color.Red;
+                }
+                else if (e.Hover.GetState(0) == PointStateType.Leave)
+                {
+                    btn.BackgroundColor = Color.DarkOrange;
+                }
+                return true;
+            };
+
+            var item = Wrapping(btn);
+            item.SizeWidth = 200;
+            item.SizeHeight = 90;
+
+            item.Position = new Position(200, 100 * (index / 3) );
+
+            if (item is Button button)
+            {
+                button.Text = $"[{button.Text}]";
+            }
+
+            return item;
+        }
+
+        static View Wrapping(View view)
+        {
+            int cnt = new Random().Next(0, 4);
+
+            for (int i = 0; i < cnt; i++)
+            {
+                var wrapper = new View();
+                view.WidthSpecification = LayoutParamPolicies.MatchParent;
+                view.HeightSpecification = LayoutParamPolicies.MatchParent;
+                wrapper.Add(view);
+                view = wrapper;
+            }
+
+            return view;
+        }
+
+        public void Deactivate()
+        {
+            NUIApplication.SetGeometryHittestEnabled(false);
+            if (root != null)
+            {
+                NUIApplication.GetDefaultWindow().Remove(root);
+                root.Dispose();
+            }
+        }
+    }
+}