using System;
using System.Collections.Generic;
using System.Linq;
using System.Diagnostics;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Media.Animation;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Surface;
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
{
public class GestureControl : ContentControl
{
public double time;
double start = -1;
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); }
set { SetValue(GestureControl.GestureProperty, value); }
}
#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 event GestureRoutedEventHandler GestureEvent
{
add { AddHandler(gestureEvent, value); }
remove { RemoveHandler(gestureEvent, value); }
}
public delegate void RaiseGestureEventCallBack(Gesture gesture);
public void RaiseGestureEvent(Gesture gesture)
{
if (this.Dispatcher.CheckAccess())
{
try
{
GestureRoutedEventArgs newEventArgs = new GestureRoutedEventArgs(GestureControl.gestureEvent, gesture);
RaiseEvent(newEventArgs);
}
catch (Exception e) { }
}
else
{
this.Dispatcher.BeginInvoke(new RaiseGestureEventCallBack(RaiseGestureEvent), gesture);
}
}
#endregion
static GestureControl()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(GestureControl), new FrameworkPropertyMetadata(typeof(GestureControl)));
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");
}
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
this.InitializeControl();
}
protected void InitializeControl()
{
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)
{
if (start == -1)
start = time;
ContactEventArgs c = (ContactEventArgs)e;
this.angle = c.Contact.GetOrientation(this) - 270;
}
protected void AreaStrokeCollected(object source, RoutedEventArgs e)
{
try
{
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
Matrix rot = Matrix.Identity;
rot.Rotate(-this.angle);
Stroke s = tmp.Stroke;
s.Transform(rot, true);
// Get a list of point from a Bezier curve
StylusPointCollection tmp2 = s.GetBezierStylusPoints();
// Generate a list of SurfaceGesturePoint, just X and Y but can be improve
List<SurfaceGesturePoint> pointList = new List<SurfaceGesturePoint>();
foreach (StylusPoint p in s.StylusPoints)
pointList.Add(new SurfaceGesturePoint { X = p.X, Y = p.Y });
// 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
_Gestures.Add(gesture);
SurfaceInkCanvas ink = e.OriginalSource as SurfaceInkCanvas;
ink.Strokes.Clear();
}
catch { }
}
void RunCapture()
{
try
{
Thread.Sleep(1000);
CommonPattern();
string gesture = GetPattern(_Gestures);
if (gesture != "None")
{
this.RaiseGestureEvent(new Gesture{Start=start, End=time, Name=gesture});
}
_Gestures.Clear();
start = -1;
inProgess = null;
}
catch (Exception)
{
inProgess = null;
}
}
#region Pattern
/// <summary>
/// return a String with the recognized pattern, "None" if no pattern
/// </summary>
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;
case "TAP":
p.Add(new SurfaceGestureVector() { Direction = SurfaceGestureVectorDirection.TAP });
break;
default:
break;
}
}
item.Add(p);
}
this.Pattern.Add(item);
}
#endregion
}
catch
{
throw new Exception("Error loading Patterns.xml");
}
}
#endregion
}
}