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 } }