src/FingersDance.GestureControl/GestureControl.cs
changeset 176 0896f36b9d57
parent 174 45c9e55fcf23
child 178 56041bd3761e
--- a/src/FingersDance.GestureControl/GestureControl.cs	Mon Oct 26 16:03:34 2009 +0100
+++ b/src/FingersDance.GestureControl/GestureControl.cs	Tue Oct 27 01:59:56 2009 +0100
@@ -17,6 +17,11 @@
 using Microsoft.Surface.Presentation;
 using Microsoft.Surface.Presentation.Controls;
 using System.Windows.Ink;
+using System.Threading;
+using System.IO;
+using System.Xml;
+using System.Reflection;
+using System.Xml.Linq;
 
 namespace GestureControl
 {
@@ -24,6 +29,14 @@
     {
         private double angle = 0;
         public static readonly DependencyProperty GestureProperty;
+        Thread inProgess;
+        List<SurfaceGesture> _Gestures = new List<SurfaceGesture>();
+
+        /// <summary>
+        /// List of pattern readed in the patterns.xml
+        /// </summary>
+        public List<SurfaceGesturePattern> Pattern = new List<SurfaceGesturePattern>();
+
         public String Gesture
         {
             get { return (String)GetValue(GestureControl.GestureProperty); }
@@ -31,24 +44,36 @@
         }
 
         #region GestureEvent
+
         public delegate void GestureRoutedEventHandler(object sender, GestureRoutedEventArgs e);
-        public static readonly RoutedEvent gestureEvent = EventManager.RegisterRoutedEvent(
-            "GestureEvent", RoutingStrategy.Bubble, typeof(GestureRoutedEventHandler), typeof(GestureControl));
+
+        public static readonly RoutedEvent gestureEvent = EventManager.RegisterRoutedEvent("GestureEvent", RoutingStrategy.Bubble, typeof(GestureRoutedEventHandler), typeof(GestureControl));
 
         public event GestureRoutedEventHandler GestureEvent
         {
             add { AddHandler(gestureEvent, value); }
             remove { RemoveHandler(gestureEvent, value); }
         }
-        protected virtual void RaiseGestureEvent(String gesture)
+
+        public delegate void RaiseGestureEventCallBack(string gesture);
+
+        public void RaiseGestureEvent(string gesture)
         {
-            try
+            if (this.Dispatcher.CheckAccess())
             {
-                GestureRoutedEventArgs newEventArgs = new GestureRoutedEventArgs(GestureControl.gestureEvent, gesture);
-                RaiseEvent(newEventArgs);
+                try
+                {
+                    GestureRoutedEventArgs newEventArgs = new GestureRoutedEventArgs(GestureControl.gestureEvent, gesture);
+                    RaiseEvent(newEventArgs);
+                }
+                catch (Exception e) { }
             }
-            catch (Exception e) { }
+            else
+            {
+                this.Dispatcher.BeginInvoke(new RaiseGestureEventCallBack(RaiseGestureEvent), gesture);
+            }
         }
+
         #endregion
 
         static GestureControl()
@@ -58,6 +83,7 @@
             GestureControl.GestureProperty = DependencyProperty.Register("Gesture", typeof(String), typeof(GestureControl),
                     new FrameworkPropertyMetadata("None", new PropertyChangedCallback(OnGestureChanged)));
         }
+
         private static void OnGestureChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
         {
             //Debug.WriteLine("changed", "Gesture");
@@ -68,11 +94,13 @@
             base.OnInitialized(e);
             this.InitializeControl();
         }
+
         protected void InitializeControl()
         {
-           base.AddHandler(SurfaceControl.PreviewContactDownEvent, new RoutedEventHandler(AreaDown));
-           base.AddHandler(SurfaceInkCanvas.StrokeCollectedEvent, new RoutedEventHandler(AreaStrokeCollected));
+            base.AddHandler(SurfaceControl.PreviewContactDownEvent, new RoutedEventHandler(AreaDown));
+            base.AddHandler(SurfaceInkCanvas.StrokeCollectedEvent, new RoutedEventHandler(AreaStrokeCollected));
         }
+
         // get angle from the first contact of the stroke
         protected void AreaDown(object source, RoutedEventArgs e)
         {
@@ -82,6 +110,18 @@
 
         protected void AreaStrokeCollected(object source, RoutedEventArgs e)
         {
+            if (inProgess == null)
+            {
+                inProgess = new Thread(RunCapture);
+                inProgess.Start();
+            }
+            else
+            {
+                inProgess.Abort();
+                inProgess = null;
+                inProgess = new Thread(RunCapture);
+                inProgess.Start();
+            }
             Debug.WriteLine("collected", "Stroke");
             System.Windows.Controls.InkCanvasStrokeCollectedEventArgs tmp = e as System.Windows.Controls.InkCanvasStrokeCollectedEventArgs;
             // Apply a rotation with the angle of the first contact
@@ -98,14 +138,154 @@
             // create the gesture analyser and set the list
             SurfaceGesture gesture = new SurfaceGesture(pointList, 1);
             // try to get a pattern from the list, if one, raise a event
-            this.Gesture = gesture.GetPattern();
-            if (this.Gesture != "None")
-            {
-                this.RaiseGestureEvent(this.Gesture);
-            }
-            // clear the stroke
+            _Gestures.Add(gesture);
             SurfaceInkCanvas ink = e.OriginalSource as SurfaceInkCanvas;
             ink.Strokes.Clear();
         }
+
+        void RunCapture()
+        {
+            try
+            {
+                Thread.Sleep(1000);
+                CommonPattern();
+                string gesture = GetPattern(_Gestures);
+                if (gesture != "None")
+                {
+                    this.RaiseGestureEvent(gesture);
+                }
+                _Gestures.Clear();
+                inProgess = null;
+            }
+            catch (Exception)
+            {
+                inProgess = null;
+            }
+        }
+
+        #region Pattern
+        /// <ary>
+        /// return a String with the recognized pattern, "None" if no pattern
+        /// </summary>
+        /// <returns></returns>
+        public String GetPattern(List<SurfaceGesture> gestures)
+        {            
+            int found = 0;
+            List<SurfaceGesture> tmp = new List<SurfaceGesture>();
+            foreach (SurfaceGesturePattern p in Pattern)
+            {
+                if (p.Count == gestures.Count)
+                {
+                    int index = 0;
+                    for (index = 0; index < p.Count; index++)
+                    {
+                        if (p[index].Count == gestures[index].Count)
+                        {
+                            int i;
+                            for (i = 0; i < p[index].Count; i++)
+                            {
+                                if (gestures[index][i].Direction != p[index][i].Direction)
+                                    i = p[index].Count + 1;
+                            }
+                            if (i == p[index].Count)
+                                found++;
+
+                        }
+                    }
+                    if (found == p.Count)
+                        return p.Name;
+                }
+            }
+
+            return "None";
+        }
+
+        /// <summary>
+        /// Load know patterns from the Resources/Patterns.xml file
+        /// </summary>
+        private void CommonPattern()
+        {
+            try
+            {
+                #region Load Patterns
+                Pattern.Clear();
+                System.IO.Stream file = Assembly.GetExecutingAssembly().GetManifestResourceStream("GestureControl.Resources.Patterns.xml");
+                XmlDocument xml = new XmlDocument();
+                xml.Load(file);
+                XmlElement root = xml.DocumentElement;
+                XmlNodeList nodes = root.SelectNodes("//Pattern");
+                SurfaceGesturePattern item;
+                foreach (XmlNode nod in nodes)
+                {
+                    string name = nod["Name"].InnerText;
+                    if (nod.ChildNodes.Count < 2)
+                        continue;
+                    item = new SurfaceGesturePattern() { Name = name };
+                    List<XmlNode> childs = new List<XmlNode>();
+                    foreach (XmlNode elt in nod.ChildNodes)
+                        if (elt.Name.Equals("Childs"))
+                            foreach (XmlNode c in elt.ChildNodes)
+                                childs.Add(c);
+
+                    SurfaceGesturePatternItem p;
+                    int j = 0;
+                    foreach (XmlNode node in childs)
+                    {
+                        string childname = node["Name"].InnerText;
+                        List<XmlNode> subNodes = new List<XmlNode>();
+                        foreach (XmlNode elt in node.ChildNodes)
+                            if (elt.Name.Equals("Directions"))
+                                foreach (XmlNode c in elt.ChildNodes)
+                                    subNodes.Add(c);
+                        if (subNodes.Count == 0)
+                            continue;
+
+                        p = new SurfaceGesturePatternItem() { Name = childname };
+
+                        foreach (XmlNode subNode in subNodes)
+                        {
+                            switch (subNode.InnerText)
+                            {
+                                case "Up":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UP });
+                                    break;
+                                case "Down":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWN });
+                                    break;
+                                case "Left":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.LEFT });
+                                    break;
+                                case "Right":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.RIGHT });
+                                    break;
+                                case "DownRight":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNRIGHT });
+                                    break;
+                                case "DownLeft":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.DOWNLEFT });
+                                    break;
+                                case "UpRight":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPRIGHT });
+                                    break;
+                                case "UpLeft":
+                                    p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.UPLEFT });
+                                    break;
+                                default:
+                                    break;
+                            }
+                        }
+                        item.Add(p);
+                    }
+                    this.Pattern.Add(item);
+                }
+                #endregion
+            }
+            catch
+            {
+                throw new Exception("Error loading Patterns.xml");
+            }
+        }
+
+        #endregion
     }
 }