using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
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.Navigation;
using System.Windows.Shapes;
using Tango.Editors;
using Tango.PMR;
using Tango.PMR.Embroidery;
namespace Tango.EmbroideryUI
{
///
/// Interaction logic for EmbroideryFileEditor.xaml
///
public partial class EmbroideryFileEditor : UserControl
{
[DllImport("Tango.Embroidery.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "AnalyzeEmbroideryFile")]
public static extern int AnalyzeEmbroideryFile(IntPtr data, int size, ref IntPtr output);
private Thickness _currentMargins;
#region Properties
public ObservableCollection Paths
{
get { return (ObservableCollection)GetValue(PathsProperty); }
set { SetValue(PathsProperty, value); }
}
public static readonly DependencyProperty PathsProperty =
DependencyProperty.Register("Paths", typeof(ObservableCollection), typeof(EmbroideryFileEditor), new PropertyMetadata(null, (d, e) => (d as EmbroideryFileEditor).OnPathsChanged()));
public EmbroideryFile EmbroideryFile
{
get { return (EmbroideryFile)GetValue(EmbroideryFileProperty); }
set { SetValue(EmbroideryFileProperty, value); }
}
public static readonly DependencyProperty EmbroideryFileProperty =
DependencyProperty.Register("EmbroideryFile", typeof(EmbroideryFile), typeof(EmbroideryFileEditor), new PropertyMetadata(null));
public String FileName
{
get { return (String)GetValue(FileNameProperty); }
set { SetValue(FileNameProperty, value); }
}
public static readonly DependencyProperty FileNameProperty =
DependencyProperty.Register("FileName", typeof(String), typeof(EmbroideryFileEditor), new PropertyMetadata(null, (d, e) => (d as EmbroideryFileEditor).OnFileNameChanged()));
public double ScaleFactor
{
get { return (double)GetValue(ScaleFactorProperty); }
set { SetValue(ScaleFactorProperty, value); }
}
public static readonly DependencyProperty ScaleFactorProperty =
DependencyProperty.Register("ScaleFactor", typeof(double), typeof(EmbroideryFileEditor), new PropertyMetadata(1.0, (d, e) => (d as EmbroideryFileEditor).OnScaleFactorChanged()));
public EmbroideryPath SelectedPath
{
get { return (EmbroideryPath)GetValue(SelectedPathProperty); }
set { SetValue(SelectedPathProperty, value); }
}
public static readonly DependencyProperty SelectedPathProperty =
DependencyProperty.Register("SelectedPath", typeof(EmbroideryPath), typeof(EmbroideryFileEditor), new PropertyMetadata(null));
#endregion
#region Constructors
public EmbroideryFileEditor()
{
Paths = new ObservableCollection();
InitializeComponent();
MouseWheel += EmbroideryFileEditor_MouseWheel;
}
#endregion
#region Virtual Methods
protected virtual void OnFileNameChanged()
{
if (!File.Exists(FileName)) return;
AnalyzeInput input = new AnalyzeInput();
input.FilePath = FileName;
NativePMR nativePMR = new NativePMR(AnalyzeEmbroideryFile);
AnalyzeOutput output = nativePMR.Invoke(input);
EmbroideryFile = output.EmbroideryFile;
DrawFile();
ScaleToFit();
}
protected virtual void OnPathsChanged()
{
if (Paths != null)
{
Paths.CollectionChanged -= Paths_CollectionChanged;
Paths.CollectionChanged += Paths_CollectionChanged;
RegisterPathsEvents();
}
}
protected virtual void OnScaleFactorChanged()
{
if (EmbroideryFile != null)
{
DrawFile();
}
}
#endregion
#region Event Handlers
private void EmbroideryFileEditor_MouseWheel(object sender, MouseWheelEventArgs e)
{
double factor = e.Delta > 0 ? 0.5 : -0.5;
Paths.Clear();
ScaleFactor += factor;
DrawFile();
}
private void Paths_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
RegisterPathsEvents();
}
private void Path_MouseDown(object sender, MouseButtonEventArgs e)
{
EmbroideryPath path = sender as EmbroideryPath;
path.IsSelected = !path.IsSelected;
SelectedPath = path;
Paths.Where(x => x != path).ToList().ForEach(x => x.IsSelected = false);
}
private void OnThumbDragging(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
list.Margin = new Thickness(_currentMargins.Left + e.HorizontalChange, _currentMargins.Top + e.VerticalChange, 0, 0);
this.Cursor = Cursors.SizeAll;
}
private void OnThumbDragStarted(object sender, System.Windows.Controls.Primitives.DragStartedEventArgs e)
{
_currentMargins = list.Margin;
}
private void OnDragCompleted(object sender, System.Windows.Controls.Primitives.DragCompletedEventArgs e)
{
this.Cursor = Cursors.Arrow;
}
#endregion
#region Private Methods
private void RegisterPathsEvents()
{
foreach (var path in Paths)
{
path.MouseDown -= Path_MouseDown;
path.MouseDown += Path_MouseDown;
}
}
public void DrawFile()
{
if (EmbroideryFile == null) return;
Point _currentPoint = new Point();
Point _lastPoint = new Point();
Stitch _lastStitch = new Stitch();
StitchFlag _mode = StitchFlag.Jump;
if (Paths == null)
{
Paths = new ObservableCollection();
}
Paths.Clear();
Color color = ConvertStitchColorToColor(EmbroideryFile.Colors[0]);
var path = CreatePathFigure(color, _currentPoint);
foreach (var stitch in EmbroideryFile.Stitches)
{
_currentPoint = new Point(stitch.XX * ScaleFactor, stitch.YY * -1 * ScaleFactor);
switch (stitch.Flag)
{
case StitchFlag.Jump:
path = CreatePathFigure(color, _currentPoint);
_mode = StitchFlag.Jump;
break;
case StitchFlag.Stop:
color = ConvertStitchColorToColor(EmbroideryFile.Colors[stitch.ColorIndex]);
break;
case StitchFlag.Normal:
if (_mode == StitchFlag.Normal)
{
path.PathFigure.Segments.Add(new LineSegment(new Point(_currentPoint.X, _currentPoint.Y), true));
path.Length += Math.Abs(GetDistance(_lastStitch.XX, _lastStitch.YY, stitch.XX, stitch.YY));
path.StitchCount++;
}
_mode = StitchFlag.Normal;
break;
}
_lastStitch = stitch;
_lastPoint = _currentPoint;
}
}
private Color ConvertStitchColorToColor(StitchColor stitchColor)
{
return Color.FromRgb((byte)stitchColor.Red, (byte)stitchColor.Green, (byte)stitchColor.Blue);
}
private EmbroideryPath CreatePathFigure(Color color, Point startPoint)
{
PathFigure figure = new PathFigure();
figure.StartPoint = startPoint;
figure.IsClosed = false;
EmbroideryPath path = new EmbroideryPath(new PathGeometry(new PathFigureCollection() { figure }));
path.PathFigure = figure;
path.StrokeThickness = 1;
path.Brush = new SolidColorBrush(color);
Paths.Add(path);
return path;
}
private static double GetDistance(double x1, double y1, double x2, double y2)
{
return Math.Sqrt(Math.Pow((x2 - x1), 2) + Math.Pow((y2 - y1), 2));
}
#endregion
#region Public Methods
public void ScaleToFit()
{
double minX = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Left).Min();
double minY = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Top).Min();
double maxX = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Right).Max();
double maxY = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Bottom).Max();
Rect embRect = new Rect(minX, minY, maxX - minX, maxY - minY);
Rect editorRect = new Rect(0, 0, ActualWidth, ActualHeight);
double embRectArea = embRect.Width * embRect.Height;
double editorRectArea = editorRect.Width * editorRect.Height;
double factor = (editorRect.Width / embRect.Width) / 2d;
if (embRect.Height > embRect.Width)
{
factor = (editorRect.Height / embRect.Height) / 2d;
}
ScaleFactor = factor;
minY = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Top).Min();
minX = Paths.Select(x => x.Path.GetFlattenedPathGeometry().Bounds.Left).Min();
list.Margin = new Thickness(minX / 2, -minY / 2, 0, 0);
}
#endregion
}
}