aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.EmbroideryUI/EmbroideryFileEditor.xaml.cs
blob: 6b86c68cbbe28a6606287fbff3b6aed697f7d378 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# generated from CMake
n213' href='#n213'>213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
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
{
    /// <summary>
    /// Interaction logic for EmbroideryFileEditor.xaml
    /// </summary>
    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<EmbroideryPath> Paths
        {
            get { return (ObservableCollection<EmbroideryPath>)GetValue(PathsProperty); }
            set { SetValue(PathsProperty, value); }
        }
        public static readonly DependencyProperty PathsProperty =
            DependencyProperty.Register("Paths", typeof(ObservableCollection<EmbroideryPath>), 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<EmbroideryPath>();
            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<AnalyzeInput, AnalyzeOutput> nativePMR = new NativePMR<AnalyzeInput, AnalyzeOutput>(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<EmbroideryPath>();
            }

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