diff -r 1d4b6d6474d5 -r 0896f36b9d57 src/FingersDance.GestureControl/GestureControl.cs --- 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 _Gestures = new List(); + + /// + /// List of pattern readed in the patterns.xml + /// + public List Pattern = new List(); + 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 + /// + /// return a String with the recognized pattern, "None" if no pattern + /// + /// + public String GetPattern(List gestures) + { + int found = 0; + List tmp = new List(); + 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"; + } + + /// + /// Load know patterns from the Resources/Patterns.xml file + /// + 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 childs = new List(); + 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 subNodes = new List(); + 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 } }