9 Commits e24cc22479 ... 23ac7af994

Author SHA1 Message Date
  Vincenz Mechler 23ac7af994 excluded svg parsing tests from AppVeyor execution as they depend on filesystem access and the [DeploymentItem] attribute 5 years ago
  Vincenz Mechler 9e858f3e38 moved FileImporter test class to UITest.cs, adapted relative file paths 5 years ago
  Vincenz Mechler fb30fd704e merged develop into userstory2 in preperation for backward merging 5 years ago
  Vincenz Mechler e9ad799202 added comments to FileImporter tests 5 years ago
  chooga e6f3cbdba9 Update userstory6.md 5 years ago
  Martin Edlund 9988b5b6e0 Optimized InternalLine 5 years ago
  Vincenz Mechler c2b20ea890 finished basic tests for svg importer and added a .testsettings file 5 years ago
  Martin Edlund 46a6fe9e8e Hotfix + Cleaned up Project Folder 5 years ago
  m-edlund 28eaf0e7d2 Userstory16 (#11) 5 years ago
54 changed files with 2313 additions and 1952 deletions
  1. 13 1
      .appveyor.yml
  2. 2 2
      Finished Userstories/userstory6.md
  3. 15 14
      SketchAssistant/SketchAssistant.Tests/UnitTest1.cs
  4. 10 10
      SketchAssistant/SketchAssistant.sln
  5. 0 14
      SketchAssistant/SketchAssistant/App.config
  6. 0 304
      SketchAssistant/SketchAssistant/Form1.Designer.cs
  7. 0 330
      SketchAssistant/SketchAssistant/Form1.cs
  8. 0 217
      SketchAssistant/SketchAssistant/Form1.resx
  9. 0 152
      SketchAssistant/SketchAssistant/Line.cs
  10. 0 71
      SketchAssistant/SketchAssistant/MVP_View.cs
  11. 0 22
      SketchAssistant/SketchAssistant/Program.cs
  12. 0 36
      SketchAssistant/SketchAssistant/Properties/AssemblyInfo.cs
  13. 0 7
      SketchAssistant/SketchAssistant/Properties/Settings.settings
  14. 0 251
      SketchAssistant/SketchAssistant/RedrawAssistant.cs
  15. 0 6
      SketchAssistant/SketchAssistant/packages.config
  16. 14 4
      SketchAssistant/SketchAssistantWPF/ActionHistory.cs
  17. 6 0
      SketchAssistant/SketchAssistantWPF/App.config
  18. 9 0
      SketchAssistant/SketchAssistantWPF/App.xaml
  19. 17 0
      SketchAssistant/SketchAssistantWPF/App.xaml.cs
  20. 18 0
      SketchAssistant/SketchAssistantWPF/CustomCanvas.cs
  21. 11 0
      SketchAssistant/SketchAssistantWPF/DebugData.cs
  22. 119 108
      SketchAssistant/SketchAssistantWPF/FileImporter.cs
  23. 3 3
      SketchAssistant/SketchAssistantWPF/FileImporterException.cs
  24. 16 11
      SketchAssistant/SketchAssistantWPF/GeometryCalculator.cs
  25. 27 0
      SketchAssistant/SketchAssistantWPF/ImageDimension.cs
  26. 166 0
      SketchAssistant/SketchAssistantWPF/InternalLine.cs
  27. 118 229
      SketchAssistant/SketchAssistantWPF/MVP_Model.cs
  28. 171 55
      SketchAssistant/SketchAssistantWPF/MVP_Presenter.cs
  29. 123 0
      SketchAssistant/SketchAssistantWPF/MVP_View.cs
  30. 194 0
      SketchAssistant/SketchAssistantWPF/MainWindow.xaml
  31. 578 0
      SketchAssistant/SketchAssistantWPF/MainWindow.xaml.cs
  32. 55 0
      SketchAssistant/SketchAssistantWPF/Properties/AssemblyInfo.cs
  33. 20 28
      SketchAssistant/SketchAssistantWPF/Properties/Resources.Designer.cs
  34. 10 7
      SketchAssistant/SketchAssistantWPF/Properties/Resources.resx
  35. 2 2
      SketchAssistant/SketchAssistantWPF/Properties/Settings.Designer.cs
  36. 7 0
      SketchAssistant/SketchAssistantWPF/Properties/Settings.settings
  37. 1 1
      SketchAssistant/SketchAssistantWPF/SketchAction.cs
  38. 55 46
      SketchAssistant/SketchAssistantWPF/SketchAssistantWPF.csproj
  39. 4 4
      SketchAssistant/WhiteTests/Properties/AssemblyInfo.cs
  40. 312 0
      SketchAssistant/WhiteTests/UITest.cs
  41. 22 14
      SketchAssistant/WhiteTests/WhiteTests.csproj
  42. 2 2
      SketchAssistant/WhiteTests/app.config
  43. 2 1
      SketchAssistant/WhiteTests/packages.config
  44. 10 0
      SketchAssistant/WhiteTests/test.runsettings
  45. 30 0
      SketchAssistant/WhiteTests/test_input_files/blacklisted/all_no_size_def_in_header.svg
  46. 29 0
      SketchAssistant/WhiteTests/test_input_files/blacklisted/all_unclosed.svg
  47. 30 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/all.svg
  48. 14 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/circle_ellipse.svg
  49. 10 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/line.svg
  50. 21 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/path.svg
  51. 10 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/polygon.svg
  52. 11 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/polyline.svg
  53. 13 0
      SketchAssistant/WhiteTests/test_input_files/whitelisted/rect.svg
  54. 13 0
      userstory16.md

+ 13 - 1
.appveyor.yml

@@ -5,4 +5,16 @@ install:
  - "nuget install TestStack.White"
  - "nuget install MSTest.TestAdapter"
  - "nuget install MSTest.TestFramework"
- - "nuget restore SketchAssistant/SketchAssistant.sln"
+ - "nuget restore SketchAssistant/SketchAssistant.sln"
+ 
+#artifacts:
+#  - path: SketchAssistant/WhiteTests/test_input_files/whitelisted/*.svg
+#    name: whitelisted svg files for testing
+#  - path: SketchAssistant/WhiteTests/test_input_files/blacklisted/*.svg
+#    name: blacklisted svg files for testing
+
+test:
+    #don't run tests depending on [DeploymentItem] and filesystem access
+    categories:
+        except:
+            - FileIO

+ 2 - 2
Finished Userstories/userstory6.md

@@ -4,10 +4,10 @@
 |-|-|
 |**Name**|Löschfunktionalität|
 |**Beschreibung**|Man kann einen Knopf in der UI drücken um in den Löschmodus zu kommen, und um wieder aus dem Löschmodus rauszukommen. Wenn man im Löschmodus ist, kann man auf einer Leinwand im rechten Bereich gezeichnete Elemente löschen indem man auf sie klickt.|
-|**Akzeptanzkriterium**|Der Knopf für den Löschmodus kann nur gedrückt werden, wenn im rechten Bereich eine Zeichennleinwand vorhanden ist. Wenn man den Knopf drückt ohne im Löschmodus zu sein, verändert sich der Knopf erkennbar und man kommt in den Löschmodus. Drückt man den Knopf, während man im Löschmodus ist, wird der Löschmodus beendet und der Knopf bekommt wieder sein urspüngliches Aussehen. Während man im Löschmodus ist, kann man auf der Leinwand im rechten Bereich Elemente löschen, wenn der Mauszeiger sie berührt während man die Maustaste gedrückt hält. Die Elemente die man löscht verschwinden. Drückt man den Löschknopf während man in einem anderen Modus ist (z.B. Zeichenmodus) wird der andere Modus beendet und man ist im Löschmodus.|
+|**Akzeptanzkriterium**|Der Knopf für den Löschmodus kann nur gedrückt werden, wenn im rechten Bereich eine Zeichennleinwand vorhanden ist. Wenn man den Knopf drückt ohne im Löschmodus zu sein, verändert sich der Knopf erkennbar und man kommt in den Löschmodus. Drückt man den Knopf, während man im Löschmodus ist, bleibt der Knopf gleich und man ist immer noch im Löschmodus. Während man im Löschmodus ist, kann man auf der Leinwand im rechten Bereich Elemente löschen, wenn der Mauszeiger sie berührt während man die Maustaste gedrückt hält. Die Elemente die man löscht verschwinden. Drückt man den Löschknopf während man in einem anderen Modus ist (z.B. Zeichenmodus) wird der andere Modus beendet und man ist im Löschmodus.|
 |Geschätzter Aufwand (Story Points)|16|
 |Entwickler|Martin Edlund, Tim Reischl|
 |Umgesetzt in Iteration|3|
 |Tatsächlicher Aufwand (Std.)|14,5|
 |Velocity (Std./Story Point)|0,90625|
-|Bemerkungen|Keine|
+|Bemerkungen|Keine|

+ 15 - 14
SketchAssistant/SketchAssistant.Tests/UnitTest1.cs

@@ -272,8 +272,9 @@ namespace Tests
             Assert.AreEqual(message, lastActionLabel);
         }
     }
-    
+
     [TestClass]
+    [DeploymentItem(@"SketchAssistant.Tests\test_input_files\")]
     public class FileImporterTests
     { 
 
@@ -391,41 +392,43 @@ namespace Tests
         }
         */
 
+        /// <summary>
+        /// parses all whitelisted files and ensures no exceptions are thrown (parsing abortion, e.g. due to corrupted input files, are realized by throwing a FileImporterException)
+        /// </summary>
         [TestMethod]
-        [DeploymentItem(@"test_input_files")]
         public void parseSVGInputNoErrorForWhitelistedFilesTest()
         {
             FileImporter uut = new FileImporter();
 
-            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory, " *.svg", SearchOption.AllDirectories);
-            foreach(string s in files) //parse each of the whitelisted files
+            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory + @"\test_input_files\whitelisted", "*.svg", SearchOption.AllDirectories);
+            Assert.IsTrue(files.Length > 0);
+
+            foreach (string s in files) //parse each of the whitelisted files
             {
                 bool noExceptionThrown = true;
                 try
                 {
                     uut.ParseSVGInputFile(s, 10000, 10000);
                 }
-                catch (FileImporterException e)
-                {
-                    noExceptionThrown = false;
-                }
                 catch (Exception e)
                 {
                     noExceptionThrown = false;
                 }
                 Assert.IsTrue(noExceptionThrown);
             }
-            Assert.IsTrue(files.Length > 0);
         }
 
+        /// <summary>
+        /// parses all blacklisted files and ensures an instance of FileIporterException is thrown for each file, but no other exceptions occur
+        /// </summary>
         [TestMethod]
-        [DeploymentItem(@"test_input_files")]
         public void parseSVGInputNoErrorForBlacklistedFilesTest()
         {
             FileImporter uut = new FileImporter();
 
-            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory, " *.svg", SearchOption.AllDirectories);
-            foreach (string s in files) //parse each of the whitelisted files
+            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory + @"\test_input_files\blacklisted", "*.svg", SearchOption.AllDirectories);
+            Assert.IsTrue(files.Length > 0);
+            foreach (string s in files) //parse each of the blacklisted files
             {
                 bool correctExceptionThrown = false;
                 try
@@ -438,11 +441,9 @@ namespace Tests
                 }
                 catch(Exception e)
                 {
-
                 }
                 Assert.IsTrue(correctExceptionThrown);
             }
-            Assert.IsTrue(files.Length > 0);
         }
     }
 

+ 10 - 10
SketchAssistant/SketchAssistant.sln

@@ -3,9 +3,9 @@ Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
 VisualStudioVersion = 15.0.28010.2050
 MinimumVisualStudioVersion = 10.0.40219.1
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SketchAssistant", "SketchAssistant\SketchAssistant.csproj", "{0336F628-A2F7-4170-8B2E-9277C23118D4}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SketchAssistantWPF", "SketchAssistantWPF\SketchAssistantWPF.csproj", "{EE53AE79-2AA0-4F43-9638-1789B189D5C3}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SketchAssistant.Tests", "SketchAssistant.Tests\SketchAssistant.Tests.csproj", "{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WhiteTests", "WhiteTests\WhiteTests.csproj", "{EB09C624-91F2-465F-825B-559BF7A7D5CB}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -13,14 +13,14 @@ Global
 		Release|Any CPU = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(ProjectConfigurationPlatforms) = postSolution
-		{0336F628-A2F7-4170-8B2E-9277C23118D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{0336F628-A2F7-4170-8B2E-9277C23118D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{0336F628-A2F7-4170-8B2E-9277C23118D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{0336F628-A2F7-4170-8B2E-9277C23118D4}.Release|Any CPU.Build.0 = Release|Any CPU
-		{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
-		{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}.Debug|Any CPU.Build.0 = Debug|Any CPU
-		{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}.Release|Any CPU.ActiveCfg = Release|Any CPU
-		{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EE53AE79-2AA0-4F43-9638-1789B189D5C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EE53AE79-2AA0-4F43-9638-1789B189D5C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EE53AE79-2AA0-4F43-9638-1789B189D5C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EE53AE79-2AA0-4F43-9638-1789B189D5C3}.Release|Any CPU.Build.0 = Release|Any CPU
+		{EB09C624-91F2-465F-825B-559BF7A7D5CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{EB09C624-91F2-465F-825B-559BF7A7D5CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{EB09C624-91F2-465F-825B-559BF7A7D5CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{EB09C624-91F2-465F-825B-559BF7A7D5CB}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE

+ 0 - 14
SketchAssistant/SketchAssistant/App.config

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<configuration>
-    <startup> 
-        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
-    </startup>
-  <runtime>
-    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
-      <dependentAssembly>
-        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
-      </dependentAssembly>
-    </assemblyBinding>
-  </runtime>
-</configuration>

+ 0 - 304
SketchAssistant/SketchAssistant/Form1.Designer.cs

@@ -1,304 +0,0 @@
-namespace SketchAssistant
-{
-    partial class Form1
-    {
-        /// <summary>
-        /// Required designer variable.
-        /// </summary>
-        private System.ComponentModel.IContainer components = null;
-
-        /// <summary>
-        /// Clean up any resources being used.
-        /// </summary>
-        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
-        protected override void Dispose(bool disposing)
-        {
-            if (disposing && (components != null))
-            {
-                components.Dispose();
-            }
-            base.Dispose(disposing);
-        }
-
-        #region Windows Form Designer generated code
-
-        /// <summary>
-        /// Required method for Designer support - do not modify
-        /// the contents of this method with the code editor.
-        /// </summary>
-        private void InitializeComponent()
-        {
-            this.components = new System.ComponentModel.Container();
-            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1));
-            this.backgroundWorker1 = new System.ComponentModel.BackgroundWorker();
-            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
-            this.pictureBoxRight = new System.Windows.Forms.PictureBox();
-            this.pictureBoxLeft = new System.Windows.Forms.PictureBox();
-            this.menuStrip1 = new System.Windows.Forms.MenuStrip();
-            this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.importToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.examplePictureToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.toolStrip1 = new System.Windows.Forms.ToolStrip();
-            this.canvasButton = new System.Windows.Forms.ToolStripButton();
-            this.drawButton = new System.Windows.Forms.ToolStripButton();
-            this.deleteButton = new System.Windows.Forms.ToolStripButton();
-            this.undoButton = new System.Windows.Forms.ToolStripButton();
-            this.redoButton = new System.Windows.Forms.ToolStripButton();
-            this.statusStrip1 = new System.Windows.Forms.StatusStrip();
-            this.toolStripLoadStatus = new System.Windows.Forms.ToolStripStatusLabel();
-            this.lastActionTakenLabel = new System.Windows.Forms.ToolStripStatusLabel();
-            this.backgroundWorker2 = new System.ComponentModel.BackgroundWorker();
-            this.mouseTimer = new System.Windows.Forms.Timer(this.components);
-            this.sVGDrawingToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.tableLayoutPanel1.SuspendLayout();
-            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxRight)).BeginInit();
-            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLeft)).BeginInit();
-            this.menuStrip1.SuspendLayout();
-            this.toolStrip1.SuspendLayout();
-            this.statusStrip1.SuspendLayout();
-            this.SuspendLayout();
-            // 
-            // tableLayoutPanel1
-            // 
-            this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) 
-            | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.tableLayoutPanel1.BackColor = System.Drawing.SystemColors.InactiveCaption;
-            this.tableLayoutPanel1.CellBorderStyle = System.Windows.Forms.TableLayoutPanelCellBorderStyle.OutsetDouble;
-            this.tableLayoutPanel1.ColumnCount = 2;
-            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
-            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
-            this.tableLayoutPanel1.Controls.Add(this.pictureBoxRight, 1, 0);
-            this.tableLayoutPanel1.Controls.Add(this.pictureBoxLeft, 0, 0);
-            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 52);
-            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
-            this.tableLayoutPanel1.RowCount = 1;
-            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
-            this.tableLayoutPanel1.Size = new System.Drawing.Size(696, 440);
-            this.tableLayoutPanel1.TabIndex = 1;
-            // 
-            // pictureBoxRight
-            // 
-            this.pictureBoxRight.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.pictureBoxRight.Location = new System.Drawing.Point(349, 3);
-            this.pictureBoxRight.Margin = new System.Windows.Forms.Padding(0);
-            this.pictureBoxRight.Name = "pictureBoxRight";
-            this.pictureBoxRight.Size = new System.Drawing.Size(344, 434);
-            this.pictureBoxRight.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
-            this.pictureBoxRight.TabIndex = 6;
-            this.pictureBoxRight.TabStop = false;
-            this.pictureBoxRight.Click += new System.EventHandler(this.pictureBoxRight_Click);
-            this.pictureBoxRight.MouseDown += new System.Windows.Forms.MouseEventHandler(this.pictureBoxRight_MouseDown);
-            this.pictureBoxRight.MouseMove += new System.Windows.Forms.MouseEventHandler(this.pictureBoxRight_MouseMove);
-            this.pictureBoxRight.MouseUp += new System.Windows.Forms.MouseEventHandler(this.pictureBoxRight_MouseUp);
-            // 
-            // pictureBoxLeft
-            // 
-            this.pictureBoxLeft.BackColor = System.Drawing.SystemColors.InactiveCaption;
-            this.pictureBoxLeft.Dock = System.Windows.Forms.DockStyle.Fill;
-            this.pictureBoxLeft.Location = new System.Drawing.Point(3, 3);
-            this.pictureBoxLeft.Margin = new System.Windows.Forms.Padding(0);
-            this.pictureBoxLeft.Name = "pictureBoxLeft";
-            this.pictureBoxLeft.Size = new System.Drawing.Size(343, 434);
-            this.pictureBoxLeft.SizeMode = System.Windows.Forms.PictureBoxSizeMode.Zoom;
-            this.pictureBoxLeft.TabIndex = 5;
-            this.pictureBoxLeft.TabStop = false;
-            // 
-            // menuStrip1
-            // 
-            this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.fileToolStripMenuItem});
-            this.menuStrip1.Location = new System.Drawing.Point(0, 0);
-            this.menuStrip1.MaximumSize = new System.Drawing.Size(1000, 0);
-            this.menuStrip1.Name = "menuStrip1";
-            this.menuStrip1.Size = new System.Drawing.Size(696, 24);
-            this.menuStrip1.TabIndex = 2;
-            this.menuStrip1.Text = "menuStrip1";
-            // 
-            // fileToolStripMenuItem
-            // 
-            this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.importToolStripMenuItem});
-            this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
-            this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
-            this.fileToolStripMenuItem.Text = "File";
-            // 
-            // importToolStripMenuItem
-            // 
-            this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.examplePictureToolStripMenuItem,
-            this.sVGDrawingToolStripMenuItem});
-            this.importToolStripMenuItem.Name = "importToolStripMenuItem";
-            this.importToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
-            this.importToolStripMenuItem.Text = "Import...";
-            // 
-            // examplePictureToolStripMenuItem
-            // 
-            this.examplePictureToolStripMenuItem.Name = "examplePictureToolStripMenuItem";
-            this.examplePictureToolStripMenuItem.Size = new System.Drawing.Size(158, 22);
-            this.examplePictureToolStripMenuItem.Text = "Example picture";
-            this.examplePictureToolStripMenuItem.Click += new System.EventHandler(this.examplePictureToolStripMenuItem_Click);
-            // 
-            // toolStrip1
-            // 
-            this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.canvasButton,
-            this.drawButton,
-            this.deleteButton,
-            this.undoButton,
-            this.redoButton});
-            this.toolStrip1.Location = new System.Drawing.Point(0, 24);
-            this.toolStrip1.Name = "toolStrip1";
-            this.toolStrip1.Size = new System.Drawing.Size(696, 25);
-            this.toolStrip1.TabIndex = 3;
-            this.toolStrip1.Text = "toolStrip1";
-            // 
-            // canvasButton
-            // 
-            this.canvasButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.canvasButton.Image = ((System.Drawing.Image)(resources.GetObject("canvasButton.Image")));
-            this.canvasButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.canvasButton.Name = "canvasButton";
-            this.canvasButton.Size = new System.Drawing.Size(76, 22);
-            this.canvasButton.Text = "New Canvas";
-            this.canvasButton.Click += new System.EventHandler(this.canvasButton_Click);
-            // 
-            // drawButton
-            // 
-            this.drawButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.drawButton.Enabled = false;
-            this.drawButton.Image = ((System.Drawing.Image)(resources.GetObject("drawButton.Image")));
-            this.drawButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.drawButton.Name = "drawButton";
-            this.drawButton.Size = new System.Drawing.Size(38, 22);
-            this.drawButton.Text = "Draw";
-            this.drawButton.Click += new System.EventHandler(this.drawButton_Click);
-            // 
-            // deleteButton
-            // 
-            this.deleteButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.deleteButton.Enabled = false;
-            this.deleteButton.Image = ((System.Drawing.Image)(resources.GetObject("deleteButton.Image")));
-            this.deleteButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.deleteButton.Name = "deleteButton";
-            this.deleteButton.Size = new System.Drawing.Size(44, 22);
-            this.deleteButton.Text = "Delete";
-            this.deleteButton.Click += new System.EventHandler(this.deleteButton_Click);
-            // 
-            // undoButton
-            // 
-            this.undoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.undoButton.Enabled = false;
-            this.undoButton.Image = ((System.Drawing.Image)(resources.GetObject("undoButton.Image")));
-            this.undoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.undoButton.Name = "undoButton";
-            this.undoButton.Size = new System.Drawing.Size(40, 22);
-            this.undoButton.Text = "Undo";
-            this.undoButton.Click += new System.EventHandler(this.undoButton_Click);
-            // 
-            // redoButton
-            // 
-            this.redoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            this.redoButton.Enabled = false;
-            this.redoButton.Image = ((System.Drawing.Image)(resources.GetObject("redoButton.Image")));
-            this.redoButton.ImageTransparentColor = System.Drawing.Color.Magenta;
-            this.redoButton.Name = "redoButton";
-            this.redoButton.Size = new System.Drawing.Size(38, 22);
-            this.redoButton.Text = "Redo";
-            this.redoButton.Click += new System.EventHandler(this.redoButton_Click);
-            // 
-            // statusStrip1
-            // 
-            this.statusStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.toolStripLoadStatus,
-            this.lastActionTakenLabel});
-            this.statusStrip1.Location = new System.Drawing.Point(0, 491);
-            this.statusStrip1.Name = "statusStrip1";
-            this.statusStrip1.Size = new System.Drawing.Size(696, 24);
-            this.statusStrip1.TabIndex = 4;
-            this.statusStrip1.Text = "statusStrip1";
-            // 
-            // toolStripLoadStatus
-            // 
-            this.toolStripLoadStatus.Name = "toolStripLoadStatus";
-            this.toolStripLoadStatus.Size = new System.Drawing.Size(40, 19);
-            this.toolStripLoadStatus.Text = "no file";
-            // 
-            // lastActionTakenLabel
-            // 
-            this.lastActionTakenLabel.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Left;
-            this.lastActionTakenLabel.Name = "lastActionTakenLabel";
-            this.lastActionTakenLabel.Size = new System.Drawing.Size(38, 19);
-            this.lastActionTakenLabel.Text = "none";
-            this.lastActionTakenLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
-            // 
-            // mouseTimer
-            // 
-            this.mouseTimer.Interval = 1;
-            this.mouseTimer.Tick += new System.EventHandler(this.mouseTimer_Tick);
-            // 
-            // sVGDrawingToolStripMenuItem
-            // 
-            this.sVGDrawingToolStripMenuItem.Name = "sVGDrawingToolStripMenuItem";
-            this.sVGDrawingToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
-            this.sVGDrawingToolStripMenuItem.Text = "SVG drawing";
-            this.sVGDrawingToolStripMenuItem.Click += new System.EventHandler(this.SVGDrawingToolStripMenuItem_Click);
-            // 
-            // Form1
-            // 
-            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
-            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.BackColor = System.Drawing.SystemColors.MenuBar;
-            this.ClientSize = new System.Drawing.Size(696, 515);
-            this.Controls.Add(this.statusStrip1);
-            this.Controls.Add(this.toolStrip1);
-            this.Controls.Add(this.tableLayoutPanel1);
-            this.Controls.Add(this.menuStrip1);
-            this.KeyPreview = true;
-            this.MainMenuStrip = this.menuStrip1;
-            this.Margin = new System.Windows.Forms.Padding(2);
-            this.Name = "Form1";
-            this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
-            this.Text = "Sketch Assistant";
-            this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
-            this.Load += new System.EventHandler(this.Form1_Load);
-            this.SizeChanged += new System.EventHandler(this.Form1_Resize);
-            this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
-            this.tableLayoutPanel1.ResumeLayout(false);
-            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxRight)).EndInit();
-            ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLeft)).EndInit();
-            this.menuStrip1.ResumeLayout(false);
-            this.menuStrip1.PerformLayout();
-            this.toolStrip1.ResumeLayout(false);
-            this.toolStrip1.PerformLayout();
-            this.statusStrip1.ResumeLayout(false);
-            this.statusStrip1.PerformLayout();
-            this.ResumeLayout(false);
-            this.PerformLayout();
-
-        }
-
-        #endregion
-        private System.ComponentModel.BackgroundWorker backgroundWorker1;
-        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
-        private System.Windows.Forms.MenuStrip menuStrip1;
-        private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
-        private System.Windows.Forms.ToolStrip toolStrip1;
-        private System.Windows.Forms.StatusStrip statusStrip1;
-        private System.Windows.Forms.ToolStripStatusLabel toolStripLoadStatus;
-        private System.ComponentModel.BackgroundWorker backgroundWorker2;
-        private System.Windows.Forms.PictureBox pictureBoxRight;
-        private System.Windows.Forms.PictureBox pictureBoxLeft;
-        private System.Windows.Forms.Timer mouseTimer;
-        private System.Windows.Forms.ToolStripButton canvasButton;
-        private System.Windows.Forms.ToolStripButton drawButton;
-        private System.Windows.Forms.ToolStripButton deleteButton;
-        private System.Windows.Forms.ToolStripMenuItem importToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem examplePictureToolStripMenuItem;
-        private System.Windows.Forms.ToolStripStatusLabel lastActionTakenLabel;
-        private System.Windows.Forms.ToolStripButton undoButton;
-        private System.Windows.Forms.ToolStripButton redoButton;
-        private System.Windows.Forms.ToolStripMenuItem sVGDrawingToolStripMenuItem;
-    }
-}
-

+ 0 - 330
SketchAssistant/SketchAssistant/Form1.cs

@@ -1,330 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.ComponentModel;
-using System.Data;
-using System.Drawing;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Text.RegularExpressions;
-
-// This is the code for your desktop app.
-// Press Ctrl+F5 (or go to Debug > Start Without Debugging) to run your app.
-
-namespace SketchAssistant
-{
-    public partial class Form1 : Form, MVP_View
-    {
-        public Form1()
-        {
-            InitializeComponent();
-            ProgramPresenter = new MVP_Presenter(this);
-        }
-
-        /**********************************/
-        /*** CLASS VARIABLES START HERE ***/
-        /**********************************/
-
-        public enum ButtonState
-        {
-            Enabled,
-            Disabled,
-            Active
-        }
-
-        /// <summary>
-        /// Different Program States
-        /// </summary>
-        public enum ProgramState
-        {
-            Idle,
-            Draw,
-            Delete
-        }
-
-        /// <summary>
-        /// Dialog to select a file.
-        /// </summary>
-        OpenFileDialog openFileDialog = new OpenFileDialog();
-        /// <summary>
-        /// All Lines in the current session
-        /// </summary>
-        List<Tuple<bool, Line>> rightLineList = new List<Tuple<bool, Line>>();
-        /// <summary>
-        /// Queue for the cursorPositions
-        /// </summary>
-        Queue<Point> cursorPositions = new Queue<Point>();
-        /// <summary>
-        /// The Presenter Component of the MVP-Model
-        /// </summary>
-        MVP_Presenter ProgramPresenter;
-
-        /******************************************/
-        /*** FORM SPECIFIC FUNCTIONS START HERE ***/
-        /******************************************/
-
-        private void Form1_Load(object sender, EventArgs e)
-        {
-            this.DoubleBuffered = true;
-        }
-
-        /// <summary>
-        /// Resize Function connected to the form resize event, will refresh the form when it is resized
-        /// </summary>
-        private void Form1_Resize(object sender, System.EventArgs e)
-        {
-            ProgramPresenter.Resize(new Tuple<int, int>(pictureBoxLeft.Width, pictureBoxLeft.Height), 
-                new Tuple<int, int>(pictureBoxRight.Width, pictureBoxRight.Height));
-            this.Refresh();
-        }
-
-        /// <summary>
-        /// Import example picture button, will open an OpenFileDialog
-        /// </summary>
-        private void examplePictureToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.ExamplePictureToolStripMenuItemClick();
-        }
-
-        /// <summary>
-        /// Import svg drawing button, will open an OpenFileDialog
-        /// </summary>
-        private void SVGDrawingToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.SVGToolStripMenuItemClick();
-        }
-
-        /// <summary>
-        /// Changes the state of the program to drawing
-        /// </summary>
-        private void drawButton_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.ChangeState(true);
-        }
-
-        /// <summary>
-        /// Changes the state of the program to deletion
-        /// </summary>
-        private void deleteButton_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.ChangeState(false);
-        }
-
-        /// <summary>
-        /// Undo an Action.
-        /// </summary>
-        private void undoButton_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.Undo();
-        }
-
-        /// <summary>
-        /// Redo an Action.
-        /// </summary>
-        private void redoButton_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.Redo();
-        }
-
-        /// <summary>
-        /// Detect Keyboard Shortcuts.
-        /// </summary>
-        private void Form1_KeyDown(object sender, KeyEventArgs e)
-        {
-            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
-            {
-                ProgramPresenter.Undo();
-            }
-            if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Y)
-            {
-                ProgramPresenter.Redo();
-            }
-        }
-
-        /// <summary>
-        /// The Picture box is clicked.
-        /// </summary>
-        private void pictureBoxRight_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Click);
-        }
-
-        /// <summary>
-        /// Get current Mouse positon within the right picture box.
-        /// </summary>
-        private void pictureBoxRight_MouseMove(object sender, MouseEventArgs e)
-        {
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, e);
-        }
-        
-        /// <summary>
-        /// Hold left mouse button to start drawing.
-        /// </summary>
-        private void pictureBoxRight_MouseDown(object sender, MouseEventArgs e)
-        {
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
-        }
-        
-        /// <summary>
-        /// Lift left mouse button to stop drawing and add a new Line.
-        /// </summary>
-        private void pictureBoxRight_MouseUp(object sender, MouseEventArgs e)
-        {
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
-        }
-        
-        /// <summary>
-        /// Button to create a new Canvas. Will create an empty image 
-        /// which is the size of the left image, if there is one.
-        /// If there is no image loaded the canvas will be the size of the right picture box
-        /// </summary>
-        private void canvasButton_Click(object sender, EventArgs e)
-        {
-            ProgramPresenter.NewCanvas();
-        }
-
-        /// <summary>
-        /// Add a Point on every tick to the Drawpath.
-        /// Or detect lines for deletion on every tick
-        /// </summary>
-        private void mouseTimer_Tick(object sender, EventArgs e)
-        {
-            ProgramPresenter.Tick();
-        }
-
-        /*************************/
-        /*** PRESENTER -> VIEW ***/
-        /*************************/
-
-        /// <summary>
-        /// Enables the timer of the View, which will tick the Presenter.
-        /// </summary>
-        public void EnableTimer()
-        {
-            mouseTimer.Enabled = true;
-        }
-
-        /// <summary>
-        /// A function that opens a file dialog and returns the filename.
-        /// </summary>
-        /// <param name="Filter">The filter that should be applied to the new Dialog.</param>
-        /// <returns>Returns the FileName and the SafeFileName if the user correctly selects a file, 
-        /// else returns a tuple with empty strigns</returns>
-        public Tuple<String, String> openNewDialog(String Filter)
-        {
-            openFileDialog.Filter = Filter;
-            if (openFileDialog.ShowDialog() == DialogResult.OK)
-            {
-                return new Tuple<string, string>(openFileDialog.FileName, openFileDialog.SafeFileName);
-            }
-            else
-            {
-                return new Tuple<string, string>("", "");
-            }
-        }
-
-        /// <summary>
-        /// Sets the contents of the load status indicator label.
-        /// </summary>
-        /// <param name="message">The new contents</param>
-        public void SetToolStripLoadStatus(String message)
-        {
-            toolStripLoadStatus.Text = message;
-        }
-
-        /// <summary>
-        /// Sets the contents of the last action taken indicator label.
-        /// </summary>
-        /// <param name="message">The new contents</param>
-        public void SetLastActionTakenText(String message)
-        {
-            lastActionTakenLabel.Text = message;
-        }
-
-        /// <summary>
-        /// Changes the states of a tool strip button.
-        /// </summary>
-        /// <param name="buttonName">The name of the button.</param>
-        /// <param name="state">The new state of the button.</param>
-        public void SetToolStripButtonStatus(String buttonName, ButtonState state)
-        {
-            ToolStripButton buttonToChange;
-            switch (buttonName)
-            {
-                case "canvasButton":
-                    buttonToChange = canvasButton;
-                    break;
-                case "drawButton":
-                    buttonToChange = drawButton;
-                    break;
-                case "deleteButton":
-                    buttonToChange = deleteButton;
-                    break;
-                case "undoButton":
-                    buttonToChange = undoButton;
-                    break;
-                case "redoButton":
-                    buttonToChange = redoButton;
-                    break;
-                default:
-                    Console.WriteLine("Invalid Button was given to SetToolStripButton. \nMaybe you forgot to add a case?");
-                    return;
-            }
-            switch (state)
-            {
-                case ButtonState.Active:
-                    buttonToChange.Checked = true;
-                    break;
-                case ButtonState.Disabled:
-                    buttonToChange.Checked = false;
-                    buttonToChange.Enabled = false;
-                    break;
-                case ButtonState.Enabled:
-                    buttonToChange.Checked = false;
-                    buttonToChange.Enabled = true;
-                    break;
-            }
-        }
-
-        /// <summary>
-        /// Displays an image in the left Picture box.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        public void DisplayInLeftPictureBox(Image img)
-        {
-            pictureBoxLeft.Image = img;
-            pictureBoxLeft.Refresh();
-        }
-
-        /// <summary>
-        /// Displays an image in the right Picture box.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        public void DisplayInRightPictureBox(Image img)
-        {
-            pictureBoxRight.Image = img;
-            pictureBoxRight.Refresh();
-        }
-
-        /// <summary>
-        /// shows the given info message in a popup and asks the user to aknowledge it
-        /// </summary>
-        /// <param name="message">the message to show</param>
-        public void ShowInfoMessage(String message)
-        {
-            MessageBox.Show(message);
-        }
-
-        /// <summary>
-        /// Shows a warning box with the given message (Yes/No Buttons)and returns true if the user aknowledges it.
-        /// </summary>
-        /// <param name="message">The message of the warning.</param>
-        /// <returns>True if the user confirms (Yes), negative if he doesn't (No)</returns>
-        public bool ShowWarning(String message)
-        {
-            return (MessageBox.Show(message, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
-        }
-
-    }
-}

+ 0 - 217
SketchAssistant/SketchAssistant/Form1.resx

@@ -1,217 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<root>
-  <!-- 
-    Microsoft ResX Schema 
-    
-    Version 2.0
-    
-    The primary goals of this format is to allow a simple XML format 
-    that is mostly human readable. The generation and parsing of the 
-    various data types are done through the TypeConverter classes 
-    associated with the data types.
-    
-    Example:
-    
-    ... ado.net/XML headers & schema ...
-    <resheader name="resmimetype">text/microsoft-resx</resheader>
-    <resheader name="version">2.0</resheader>
-    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
-    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
-    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
-    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
-    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
-        <value>[base64 mime encoded serialized .NET Framework object]</value>
-    </data>
-    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
-        <comment>This is a comment</comment>
-    </data>
-                
-    There are any number of "resheader" rows that contain simple 
-    name/value pairs.
-    
-    Each data row contains a name, and value. The row also contains a 
-    type or mimetype. Type corresponds to a .NET class that support 
-    text/value conversion through the TypeConverter architecture. 
-    Classes that don't support this are serialized and stored with the 
-    mimetype set.
-    
-    The mimetype is used for serialized objects, and tells the 
-    ResXResourceReader how to depersist the object. This is currently not 
-    extensible. For a given mimetype the value must be set accordingly:
-    
-    Note - application/x-microsoft.net.object.binary.base64 is the format 
-    that the ResXResourceWriter will generate, however the reader can 
-    read any of the formats listed below.
-    
-    mimetype: application/x-microsoft.net.object.binary.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
-            : and then encoded with base64 encoding.
-    
-    mimetype: application/x-microsoft.net.object.soap.base64
-    value   : The object must be serialized with 
-            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
-            : and then encoded with base64 encoding.
-
-    mimetype: application/x-microsoft.net.object.bytearray.base64
-    value   : The object must be serialized into a byte array 
-            : using a System.ComponentModel.TypeConverter
-            : and then encoded with base64 encoding.
-    -->
-  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
-    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
-    <xsd:element name="root" msdata:IsDataSet="true">
-      <xsd:complexType>
-        <xsd:choice maxOccurs="unbounded">
-          <xsd:element name="metadata">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" />
-              </xsd:sequence>
-              <xsd:attribute name="name" use="required" type="xsd:string" />
-              <xsd:attribute name="type" type="xsd:string" />
-              <xsd:attribute name="mimetype" type="xsd:string" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="assembly">
-            <xsd:complexType>
-              <xsd:attribute name="alias" type="xsd:string" />
-              <xsd:attribute name="name" type="xsd:string" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="data">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
-              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
-              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
-              <xsd:attribute ref="xml:space" />
-            </xsd:complexType>
-          </xsd:element>
-          <xsd:element name="resheader">
-            <xsd:complexType>
-              <xsd:sequence>
-                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
-              </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" use="required" />
-            </xsd:complexType>
-          </xsd:element>
-        </xsd:choice>
-      </xsd:complexType>
-    </xsd:element>
-  </xsd:schema>
-  <resheader name="resmimetype">
-    <value>text/microsoft-resx</value>
-  </resheader>
-  <resheader name="version">
-    <value>2.0</value>
-  </resheader>
-  <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
-  </resheader>
-  <metadata name="backgroundWorker1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>122, 17</value>
-  </metadata>
-  <metadata name="menuStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>286, 17</value>
-  </metadata>
-  <metadata name="toolStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>401, 17</value>
-  </metadata>
-  <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
-  <data name="canvasButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
-        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
-        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
-        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
-        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
-        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
-        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
-        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
-        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
-        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="drawButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
-        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
-        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
-        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
-        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
-        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
-        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
-        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
-        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
-        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="deleteButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
-        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
-        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
-        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
-        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
-        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
-        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
-        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
-        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
-        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="undoButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
-        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
-        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
-        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
-        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
-        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
-        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
-        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
-        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
-        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <data name="redoButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
-    <value>
-        iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
-        YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAIDSURBVDhPpZLrS5NhGMb3j4SWh0oRQVExD4gonkDpg4hG
-        YKxG6WBogkMZKgPNCEVJFBGdGETEvgwyO9DJE5syZw3PIlPEE9pgBCLZ5XvdMB8Ew8gXbl54nuf63dd9
-        0OGSnwCahxbPRNPAPMw9Xpg6ZmF46kZZ0xSKzJPIrhpDWsVnpBhGkKx3nAX8Pv7z1zg8OoY/cITdn4fw
-        bf/C0kYAN3Ma/w3gWfZL5kzTKBxjWyK2DftwI9tyMYCZKXbNHaD91bLYJrDXsYbrWfUKwJrPE9M2M1Oc
-        VzOOpHI7Jr376Hi9ogHqFIANO0/MmmmbmSmm9a8ze+I4MrNWAdjtoJgWcx+PSzg166yZZ8xM8XvXDix9
-        c4jIqFYAjoriBV9AhEPv1mH/sonogha0afbZMMZz+yreTGyhpusHwtNNCsA5U1zS4BLxzJIfg299qO32
-        Ir7UJtZfftyATqeT+8o2D8JSjQrAJblrncYL7ZJ2+bfaFnC/1S1NjL3diRat7qrO7wLRP3HjWsojBeCo
-        mDEo5mNjuweFGvjWg2EBhCbpkW78htSHHwRyNdmgAFzPEee2iFkzayy2OLXzT4gr6UdUnlXrullsxxQ+
-        kx0g8BTA3aZlButjSTyjODq/WcQcW/B/Je4OQhLvKQDnzN1mp0nnkvAhR8VuMzNrpm1mpjgkoVwB/v8D
-        TgDQASA1MVpwzwAAAABJRU5ErkJggg==
-</value>
-  </data>
-  <metadata name="statusStrip1.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>506, 17</value>
-  </metadata>
-  <metadata name="backgroundWorker2.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>622, 17</value>
-  </metadata>
-  <metadata name="mouseTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
-    <value>786, 17</value>
-  </metadata>
-  <metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
-    <value>47</value>
-  </metadata>
-</root>

+ 0 - 152
SketchAssistant/SketchAssistant/Line.cs

@@ -1,152 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Drawing;
-
-namespace SketchAssistant
-{
-    public class Line
-    {
-        /// <summary>
-        /// list saving all the points of the line in the order of the path from start to end point
-        /// </summary>
-        private List<Point> linePoints;
-        /// <summary>
-        /// unique identifier of this Line object
-        /// </summary>
-        private int identifier;
-        /// <summary>
-        /// flag showing if this is only a temporary line
-        /// </summary>
-        private bool isTemporary;
-
-        /// <summary>
-        /// The constructor for lines which are only temporary.
-        /// If you want nice lines use the other constructor.
-        /// </summary>
-        /// <param name="points">The points of the line</param>
-        public Line(List<Point> points)
-        {
-            linePoints = new List<Point>(points);
-            isTemporary = true;
-        }
-
-        /// <summary>
-        /// The constructor for lines, which will be more resource efficient 
-        /// and have the ability to populate deletion matrixes.
-        /// </summary>
-        /// <param name="points">The points of the line</param>
-        /// <param name="id">The identifier of the line</param>
-        public Line(List<Point> points, int id)
-        {
-            linePoints = new List<Point>(points);
-            identifier = id;
-            CleanPoints();
-            isTemporary = false;
-        }
-
-        public Point GetStartPoint()
-        {
-            return linePoints.First();
-        }
-
-        public Point GetEndPoint()
-        {
-            return linePoints.Last();
-        }
-
-        public List<Point> GetPoints()
-        {
-            return linePoints;
-        }
-
-        public int GetID()
-        {
-            return identifier;
-        }
-
-        /// <summary>
-        /// A function that takes a Graphics element and returns it with
-        /// the line drawn on it.
-        /// </summary>
-        /// <param name="canvas">The Graphics element on which the line shall be drawn</param>
-        /// <returns>The given Graphics element with the additional line</returns>
-        public Graphics DrawLine(Graphics canvas)
-        {
-            for(int i = 0; i < linePoints.Count - 1 ; i++)
-            {
-                canvas.DrawLine(Pens.Black, linePoints[i], linePoints[i + 1]);
-            }
-            //If there is only one point
-            if(linePoints.Count == 1){ canvas.FillRectangle(Brushes.Black, linePoints[0].X, linePoints[0].Y, 1, 1); }
-            return canvas;
-        }
-
-        /// <summary>
-        /// A function that will take to matrixes and populate the with the line data of this line object
-        /// </summary>
-        /// <param name="boolMatrix">The Matrix of booleans, in which is saved wether there is a line at this position.</param>
-        /// <param name="listMatrix">The Matrix of Lists of integers, in which is saved which lines are at this position</param>
-        public void PopulateMatrixes(bool[,] boolMatrix, HashSet<int>[,] listMatrix)
-        {
-            if(!isTemporary)
-            {
-                foreach (Point currPoint in linePoints)
-                {
-                    if (currPoint.X >= 0 && currPoint.Y >= 0 && 
-                        currPoint.X < boolMatrix.GetLength(0) && currPoint.Y < boolMatrix.GetLength(1))
-                    {
-                        boolMatrix[currPoint.X, currPoint.Y] = true;
-                        if (listMatrix[currPoint.X, currPoint.Y] == null)
-                        {
-                            listMatrix[currPoint.X, currPoint.Y] = new HashSet<int>();
-                        }
-                        listMatrix[currPoint.X, currPoint.Y].Add(identifier);
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// Removes duplicate points from the line object
-        /// </summary>
-        private void CleanPoints()
-        {
-            if (linePoints.Count > 1)
-            {
-                List<Point> newList = new List<Point>();
-                List<Point> tempList = new List<Point>();
-                //Since Point is non-nullable, we must ensure the nullPoints, 
-                //which we remove can not possibly be points of the original given line.
-                int nullValue = linePoints[0].X + 1;
-                //Fill the gaps between points
-                for (int i = 0; i < linePoints.Count - 1; i++)
-                {
-                    nullValue += linePoints[i + 1].X;
-                    List<Point> partialList = GeometryCalculator.BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
-                    tempList.AddRange(partialList);
-                }
-                Point nullPoint = new Point(nullValue, 0);
-                //Set duplicate points to the null point
-                for (int i = 1; i < tempList.Count; i++)
-                {
-                    if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
-                    {
-                        tempList[i - 1] = nullPoint;
-                    }
-                }
-                //remove the null points
-                foreach (Point tempPoint in tempList)
-                {
-                    if (tempPoint.X != nullValue)
-                    {
-                        newList.Add(tempPoint);
-                    }
-                }
-                linePoints = new List<Point>(newList);
-            }
-        }
-    }
-}

+ 0 - 71
SketchAssistant/SketchAssistant/MVP_View.cs

@@ -1,71 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Drawing;
-
-
-namespace SketchAssistant
-{
-    public interface MVP_View
-    {
-
-        /// <summary>
-        /// Enables the timer of the View, which will tick the Presenter.
-        /// </summary>
-        void EnableTimer();
-
-        /// <summary>
-        /// A function that opens a file dialog and returns the filename.
-        /// </summary>
-        /// <param name="Filter">The filter that should be applied to the new Dialog.</param>
-        /// <returns>Returns the FileName and the SafeFileName if the user correctly selects a file, 
-        /// else returns a tuple with empty strigns</returns>
-        Tuple<String, String> openNewDialog(String Filter);
-
-        /// <summary>
-        /// Sets the contents of the load status indicator label.
-        /// </summary>
-        /// <param name="message">The new contents</param>
-        void SetToolStripLoadStatus(String message);
-
-        /// <summary>
-        /// Sets the contents of the last action taken indicator label.
-        /// </summary>
-        /// <param name="message">The new contents</param>
-        void SetLastActionTakenText(String message);
-
-        /// <summary>
-        /// Changes the states of a tool strip button.
-        /// </summary>
-        /// <param name="buttonName">The name of the button.</param>
-        /// <param name="state">The new state of the button.</param>
-        void SetToolStripButtonStatus(String buttonName, Form1.ButtonState state);
-
-        /// <summary>
-        /// Displays an image in the left Picture box.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        void DisplayInLeftPictureBox(Image img);
-
-        /// <summary>
-        /// Displays an image in the right Picture box.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        void DisplayInRightPictureBox(Image img);
-
-        /// <summary>
-        /// shows the given info message in a popup and asks the user to aknowledge it
-        /// </summary>
-        /// <param name="message">the message to show</param>
-        void ShowInfoMessage(String message);
-
-        /// <summary>
-        /// Shows a warning box with the given message (Yes/No Buttons)and returns true if the user aknowledges it.
-        /// </summary>
-        /// <param name="message">The message of the warning.</param>
-        /// <returns>True if the user confirms (Yes), negative if he doesn't (No)</returns>
-        bool ShowWarning(String message);
-    }
-}

+ 0 - 22
SketchAssistant/SketchAssistant/Program.cs

@@ -1,22 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Threading.Tasks;
-using System.Windows.Forms;
-
-namespace SketchAssistant
-{
-    static class Program
-    {
-        /// <summary>
-        /// The main entry point for the application.
-        /// </summary>
-        [STAThread]
-        static void Main()
-        {
-            Application.EnableVisualStyles();
-            Application.SetCompatibleTextRenderingDefault(false);
-            Application.Run(new Form1());
-        }
-    }
-}

+ 0 - 36
SketchAssistant/SketchAssistant/Properties/AssemblyInfo.cs

@@ -1,36 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("SketchAssistant")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("SketchAssistant")]
-[assembly: AssemblyCopyright("Copyright ©  2018")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components.  If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("0336f628-a2f7-4170-8b2e-9277c23118d4")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]

+ 0 - 7
SketchAssistant/SketchAssistant/Properties/Settings.settings

@@ -1,7 +0,0 @@
-<?xml version='1.0' encoding='utf-8'?>
-<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
-  <Profiles>
-    <Profile Name="(Default)" />
-  </Profiles>
-  <Settings />
-</SettingsFile>

+ 0 - 251
SketchAssistant/SketchAssistant/RedrawAssistant.cs

@@ -1,251 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Collections;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
-using System.Drawing;
-
-namespace SketchAssistant
-{
-    public class RedrawAssistant
-    {
-        /// <summary>
-        /// The lines of the left image, with a boolean indicating if they have been redrawn
-        /// and an integer that is the same as the line id of the respective line in the right image.
-        /// </summary>
-        List<Tuple<Line, bool, int>> linesToRedraw;
-        /// <summary>
-        /// The Start and End points of all lines in linesToRedraw in the same order.
-        /// </summary>
-        List<Tuple<HashSet<Point>, HashSet<Point>>> startAndEndPoints;
-        /// <summary>
-        /// A Hashtable for quick lookup for a line id and its respective tuple in linesToRedraw
-        /// </summary>
-        Hashtable redrawnLineLookupTable;
-        /// <summary>
-        /// The position of the line currently being redrawn in the startAndEndPoints 
-        /// & linesToRedraw lists. -1 if no line is being redrawn.
-        /// </summary>
-        int lineBeingRedrawn;
-        /// <summary>
-        /// The id of the line being drawn on the right side. -1 if no line is being drawn.
-        /// </summary>
-        int currentLineID;
-        /// <summary>
-        /// Whether or not the user is currently redrawing a line.
-        /// </summary>
-        bool currentlyRedrawing;
-        /// <summary>
-        /// Whether or not the RedrawAssistant is active.
-        /// </summary>
-        bool isActive;
-        /// <summary>
-        /// The radius of the markers for redrawing.
-        /// </summary>
-        int markerRadius = 5;
-
-        /// <summary>
-        /// The Constructor for an inactive RedrawAssistant.
-        /// </summary>
-        public RedrawAssistant()
-        {
-            isActive = false;
-        }
-
-        /// <summary>
-        /// The constructor for an active RedrawAssistant
-        /// </summary>
-        /// <param name="redrawItem">The lines that shall be redrawn</param>
-        public RedrawAssistant(List<Line> redrawItem)
-        {
-            linesToRedraw = new List<Tuple<Line, bool, int>>();
-            startAndEndPoints = new List<Tuple<HashSet<Point>, HashSet<Point>>>();
-            isActive = true;
-            currentlyRedrawing = false;
-            lineBeingRedrawn = -1;
-            redrawnLineLookupTable = new Hashtable();
-            foreach (Line line in redrawItem)
-            {
-                linesToRedraw.Add(new Tuple<Line, bool, int>(line, false, -1));
-            }
-            SetMarkerRadius(5);
-        }
-
-        /// <summary>
-        /// Initialization function that returns the initial list of overlay points.
-        /// </summary>
-        /// <param name="mRad">The radius of the points.</param>
-        /// <returns>The list of overlay points.</returns>
-        public List<Tuple<bool, HashSet<Point>>> Initialize(int mRad)
-        {
-            if (isActive)
-            {
-                List<Tuple<bool, HashSet<Point>>> retList = new List<Tuple<bool, HashSet<Point>>>();
-                SetMarkerRadius(mRad);
-                foreach(Tuple<HashSet<Point>, HashSet<Point>> tup in startAndEndPoints)
-                {
-                    retList.Add(new Tuple<bool, HashSet<Point>>(false, tup.Item1));
-                    retList.Add(new Tuple<bool, HashSet<Point>>(false, tup.Item2));
-                }
-                return retList;
-            }
-            return null;
-        }
-
-        /// <summary>
-        /// The main functionality of the RedrawAssistant, which updates the Assistant according to the inputs given.
-        /// </summary>
-        /// <param name="currentPoint">The current position of the cursor, as a point</param>
-        /// <param name="rightLines">The lines on the right canvas</param>
-        /// <param name="currLineID">The id of the line currently being drawn.</param>
-        /// <param name="lineFinished">A boolean to indicate that the line is finished</param>
-        /// <param name="overlayItems">A list containing the overlay items and if they should be drawn.</param>
-        /// <returns>The updated List of overlay items, or the same list if no changes need to be done, 
-        /// along with a boolean indicating if something was changed</returns>
-        public Tuple<bool, List<Tuple<bool, HashSet<Point>>>> Tick(Point currentPoint, List<Tuple<bool, Line>> rightLines, int currLineID, bool lineFinished, 
-            List<Tuple<bool, HashSet<Point>>> overlayItems)
-        {
-            if (!isActive) { return new Tuple<bool, List<Tuple<bool, HashSet<Point>>>>(false, overlayItems); }
-
-            if (!currentlyRedrawing)
-            {
-
-            }
-            /*
-            Tuple<Line, bool, int> newLineTuple = null;
-            var returnAllStartPoints = true;
-            CheckForUndrawnLines(rightLines);
-            
-            // Checking if a startpoint is intersected
-            if (!currentlyRedrawing)
-            {
-                for (int i = 0; i < linesToRedraw.Count; i++)
-                {
-                    Tuple<Line, bool, int> tup = linesToRedraw[i];
-                    if (!tup.Item2)
-                    {
-                        if (startAndEndPoints[i].Item1.Contains(currentPoint))
-                        {
-                            currentlyRedrawing = true;
-                            lineBeingRedrawn = i;
-                            currentLineID = currLineID;
-                            returnList.Add(startAndEndPoints[i].Item1);
-                            returnList.Add(startAndEndPoints[i].Item2);
-                            returnAllStartPoints = false;
-                        }
-                    }
-                }
-            }
-            //Currently redrawing a line, but a line hasn't been finished drawing.
-            else if (!lineFinished)
-            {
-                returnList.Add(startAndEndPoints[lineBeingRedrawn].Item1);
-                returnList.Add(startAndEndPoints[lineBeingRedrawn].Item2);
-                returnAllStartPoints = false;
-            }
-            //Line is finished, check if it is in the correct endpoint
-            else if (currLineID == currentLineID && startAndEndPoints[lineBeingRedrawn].Item2.Contains(currentPoint))
-            {
-                newLineTuple = new Tuple<Line, bool, int>(linesToRedraw[lineBeingRedrawn].Item1, true, currLineID);
-                currentlyRedrawing = false;
-                lineBeingRedrawn = -1;
-                currentLineID = -1;
-            }
-            //Line is finished, but not in the correct endpoint
-            else
-            {
-                currentlyRedrawing = false;
-                lineBeingRedrawn = -1;
-                currentLineID = -1;
-            }
-
-            //Replace the changed line tuple in linesToRedraw
-            if(newLineTuple != null)
-            {
-                var newLine = newLineTuple.Item1;
-                for (int i = 0; i < linesToRedraw.Count; i++)
-                {
-                    var redrawLine = linesToRedraw[i].Item1;
-                    if (redrawLine.GetID() == newLine.GetID() 
-                        && redrawLine.GetStartPoint().Equals(newLine.GetStartPoint())
-                        && redrawLine.GetEndPoint().Equals(newLine.GetEndPoint()))
-                    {
-                        redrawnLineLookupTable.Add(currLineID, i);
-                        linesToRedraw[i] = newLineTuple;
-                    }
-                }
-            }
-
-            //Add all the startpoints to the list being returned
-            if (returnAllStartPoints)
-            {
-                for (int i = 0; i < linesToRedraw.Count; i++)
-                {
-                    if (!linesToRedraw[i].Item2)
-                    {
-                        returnList.Add(startAndEndPoints[i].Item1);
-                    }
-                }
-            }
-            return returnList;
-            */
-            return new Tuple<bool, List<Tuple<bool, HashSet<Point>>>>(false, overlayItems);
-        }
-
-        /// <summary>
-        /// A helping function which checks for lines where previously redrawn, but were removed from the image again.
-        /// </summary>
-        /// <param name="rightLines">The lines in the right image.</param>
-        private void CheckForUndrawnLines(List<Tuple<bool, Line>> rightLines)
-        {
-            for (int i = 0; i < rightLines.Count; i++)
-            {
-                if (redrawnLineLookupTable.ContainsKey(rightLines[i].Item2.GetID()))
-                {
-                    if (!rightLines[i].Item1)
-                    {
-                        int listPos = (int)redrawnLineLookupTable[rightLines[i].Item2.GetID()];
-                        var oldTup = linesToRedraw[listPos];
-                        linesToRedraw[listPos] = new Tuple<Line, bool, int>(oldTup.Item1, false, -1);
-                    }
-                    else
-                    {
-                        int listPos = (int)redrawnLineLookupTable[rightLines[i].Item2.GetID()];
-                        var oldTup = linesToRedraw[listPos];
-                        linesToRedraw[listPos] = new Tuple<Line, bool, int>(oldTup.Item1, true, rightLines[i].Item2.GetID());
-                    }
-                }
-            }
-        }
-
-        /// <summary>
-        /// A function to set the marker radius for the markers returned by the RedrawAssistant
-        /// </summary>
-        /// <param name="markerRad">The Radius of the markers.</param>
-        public void SetMarkerRadius(int markerRad)
-        {
-            markerRadius = markerRad;
-            if (isActive)
-            {
-                startAndEndPoints = new List<Tuple<HashSet<Point>, HashSet<Point>>>();
-                foreach (Tuple<Line, bool, int> tup in linesToRedraw)
-                {
-                    startAndEndPoints.Add(CalculateStartAndEnd(tup.Item1));
-                }
-            }
-        }
-
-        /// <summary>
-        /// Will calculate the start and endpoints of the given line.
-        /// </summary>
-        /// <param name="line">The given line.</param>
-        private Tuple<HashSet<Point>, HashSet<Point>> CalculateStartAndEnd(Line line)
-        {
-            var circle0 = GeometryCalculator.FilledCircleAlgorithm(line.GetStartPoint(), markerRadius);
-            var circle1 = GeometryCalculator.FilledCircleAlgorithm(line.GetEndPoint(), markerRadius);
-            var currentLineEndings = new Tuple<HashSet<Point>, HashSet<Point>>(circle0, circle1);
-            return currentLineEndings;
-        }
-    }
-}

+ 0 - 6
SketchAssistant/SketchAssistant/packages.config

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<packages>
-  <package id="OpenCover" version="4.6.519" targetFramework="net461" />
-  <package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net461" />
-  <package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net461" />
-</packages>

+ 14 - 4
SketchAssistant/SketchAssistant/ActionHistory.cs → SketchAssistant/SketchAssistantWPF/ActionHistory.cs

@@ -3,9 +3,8 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using System.Windows.Forms;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class ActionHistory
     {
@@ -21,6 +20,17 @@ namespace SketchAssistant
             AddNewAction(new SketchAction(SketchAction.ActionType.Start, -1));
         }
 
+        /// <summary>
+        /// Resets the action history to its initial state.
+        /// </summary>
+        /// <returns>The new Last Action taken.</returns>
+        public String Reset()
+        {
+            actionHistory.Clear();
+            currentAction = new Tuple<int, SketchAction>(-1, null);
+            return AddNewAction(new SketchAction(SketchAction.ActionType.Start, -1));
+        }
+
         /// <summary>
         /// Adds a new action to the action history.
         /// </summary>
@@ -45,11 +55,11 @@ namespace SketchAssistant
         /// <returns>The message to be displayed</returns>
         public String MoveAction(bool moveBack)
         {
-            if(moveBack && CanUndo())
+            if (moveBack && CanUndo())
             {
                 currentAction = new Tuple<int, SketchAction>(currentAction.Item1 - 1, actionHistory[currentAction.Item1 - 1]);
             }
-            if(!moveBack && CanRedo())
+            if (!moveBack && CanRedo())
             {
                 currentAction = new Tuple<int, SketchAction>(currentAction.Item1 + 1, actionHistory[currentAction.Item1 + 1]);
             }

+ 6 - 0
SketchAssistant/SketchAssistantWPF/App.config

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<configuration>
+    <startup> 
+        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
+    </startup>
+</configuration>

+ 9 - 0
SketchAssistant/SketchAssistantWPF/App.xaml

@@ -0,0 +1,9 @@
+<Application x:Class="SketchAssistantWPF.App"
+             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:local="clr-namespace:SketchAssistantWPF"
+             StartupUri="MainWindow.xaml">
+    <Application.Resources>
+         
+    </Application.Resources>
+</Application>

+ 17 - 0
SketchAssistant/SketchAssistantWPF/App.xaml.cs

@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace SketchAssistantWPF
+{
+    /// <summary>
+    /// Interaction logic for App.xaml
+    /// </summary>
+    public partial class App : Application
+    {
+    }
+}

+ 18 - 0
SketchAssistant/SketchAssistantWPF/CustomCanvas.cs

@@ -0,0 +1,18 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Automation.Peers;
+using System.Windows.Controls;
+
+namespace SketchAssistantWPF
+{
+    public class CustomCanvas : Canvas
+    {
+        protected override AutomationPeer OnCreateAutomationPeer()
+        {
+            return new FrameworkElementAutomationPeer(this);
+        }
+    }
+}

File diff suppressed because it is too large
+ 11 - 0
SketchAssistant/SketchAssistantWPF/DebugData.cs


+ 119 - 108
SketchAssistant/SketchAssistant/FileImporter.cs → SketchAssistant/SketchAssistantWPF/FileImporter.cs

@@ -1,13 +1,14 @@
 using System;
 using System.Collections.Generic;
-using System.Drawing;
+//using System.Drawing;
 using System.Globalization;
+using System.Windows;
 using System.Linq;
 using System.Text;
 using System.Text.RegularExpressions;
 using System.Threading.Tasks;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class FileImporter
     {
@@ -42,7 +43,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="fileName">the path of the input file</param>
         /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
-        public (int, int, List<Line>) ParseISADInputFile(String fileName)
+public Tuple<int, int, List<InternalLine>> ParseISADInputFile(String fileName)
         {
             return ParseISADInput(System.IO.File.ReadAllLines(fileName));
         }
@@ -52,7 +53,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
-        private (int, int, List<Line>) ParseISADInput(String[] allLines)
+        private Tuple<int, int, List<InternalLine>> ParseISADInput(String[] allLines)
         {
             if (allLines.Length == 0)
             {
@@ -66,9 +67,10 @@ namespace SketchAssistant
             {
                 throw new FileImporterException("unterminated drawing definition", ".isad files have to end with the 'enddrawing' token", allLines.Length);
             }
-            (int, int) dimensions = ParseISADHeader(allLines);
-            List<Line> picture = ParseISADBody(allLines, dimensions.Item1, dimensions.Item2);
-            return (dimensions.Item1, dimensions.Item2, picture);
+            Tuple<int, int> dimensions = ParseISADHeader(allLines);
+            List<InternalLine> picture = ParseISADBody(allLines, dimensions.Item1, dimensions.Item2);
+            
+            return new Tuple<int, int, List<InternalLine>>(dimensions.Item1, dimensions.Item2, picture);
         }
 
 
@@ -78,7 +80,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">the input file as an array of lines</param>
         /// <returns>the width and height of the left canvas</returns>
-        private (int, int) ParseISADHeader(String[] allLines)
+        private Tuple<int, int> ParseISADHeader(String[] allLines)
         {
             int width;
             int height;
@@ -89,7 +91,7 @@ namespace SketchAssistant
             String[] size = allLines[1].Split('x');
             width = Convert.ToInt32(size[0]);
             height = Convert.ToInt32(size[1]);
-            return (width, height);
+            return new Tuple<int, int>(width, height);
         }
 
         /// <summary>
@@ -97,11 +99,11 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">the input file as an array of lines</param>
         /// <returns>the parsed picture as a list of lines</returns>
-        private List<Line> ParseISADBody(String[] allLines, int width, int height)
+        private List<InternalLine> ParseISADBody(String[] allLines, int width, int height)
         {
             String lineStartString = "line";
             String lineEndString = "endline";
-            List<Line> drawing = new List<Line>();
+            List<InternalLine> drawing = new List<InternalLine>();
             //number of the line currently being parsed, enumeration starting at 0, body starts at the third line, therefore lin number 2
             int i = 2;
             //parse 'line' token and complete line definition
@@ -121,7 +123,7 @@ namespace SketchAssistant
                     //parse single point definition
                     if (!Regex.Match(allLines[i], @"^\d+;\d+$", RegexOptions.None).Success)
                     {
-                        throw new FileImporterException("invalid Point definition: wrong format", "format: [xCoordinate];[yCoordinate]", (i + 1) );
+                        throw new FileImporterException("invalid Point definition: wrong format", "format: [xCoordinate];[yCoordinate]", (i + 1));
                     }
                     String[] coordinates = allLines[i].Split(';');
                     //no errors possible, convertability to int already checked above
@@ -129,7 +131,7 @@ namespace SketchAssistant
                     int yCoordinate = Convert.ToInt32(coordinates[1]);
                     if (xCoordinate < 0 || yCoordinate < 0 || xCoordinate > width - 1 || yCoordinate > height - 1)
                     {
-                        throw new FileImporterException("invalid Point definition: point out of bounds", null, (i + 1) );
+                        throw new FileImporterException("invalid Point definition: point out of bounds", null, (i + 1));
                     }
                     newLine.Add(new Point(xCoordinate, yCoordinate));
                     //start parsing next line
@@ -138,12 +140,12 @@ namespace SketchAssistant
                 //"parse" 'endline' token, syntax already checked at the beginning,  and start parsing next line
                 i++;
                 //add line to drawing
-                drawing.Add(new Line(newLine));
+                drawing.Add(new InternalLine(newLine));
                 //update lineStartPointer to the presumable start of the next line
                 lineStartPointer = i;
             }
             //check if end of body is reached after there are no more line definitions
-            if(i != allLines.Length - 1)
+            if (i != allLines.Length - 1)
             {
                 throw new FileImporterException("missing or invalid line definition token", "line definitions start with the 'line' token", (i + 1));
             }
@@ -156,7 +158,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
-        public (int, int, List<Line>) ParseISADInputForTesting(String[] allLines)
+        public Tuple<int, int, List<InternalLine>> ParseISADInputForTesting(String[] allLines)
         {
             return ParseISADInput(allLines);
         }
@@ -174,7 +176,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="fileName">the path of the input file</param>
         /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
-        public (int, int, List<Line>) ParseSVGInputFile(String fileName, int windowWidth, int windowHeight)
+        public Tuple<int, int, List<InternalLine>> ParseSVGInputFile(String fileName, int windowWidth, int windowHeight)
         {
             return ParseSVGInput(System.IO.File.ReadAllLines(fileName), windowWidth, windowHeight);
         }
@@ -184,35 +186,44 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the width and height of the left canvas and the parsed picture as a list of lines</returns>
-        private (int, int, List<Line>) ParseSVGInput(String[] allLines, double windowWidth, double windowHeight)
+        private Tuple<int, int, List<InternalLine>> ParseSVGInput(String[] allLines, double windowWidth, double windowHeight)
         {
             i = 0; //reset line pointer
             if (allLines.Length == 0) //check for empty file
             {
                 throw new FileImporterException("file is empty", "", -1);
             }
-            (int, int) sizedef = ParseSVGHeader(allLines); //parse svg file header and get internal coordinate range
+            var sizedef = ParseSVGHeader(allLines); //parse svg file header and get internal coordinate range
             i++;
             int width; //width of the resulting picture in pixels
             int height; //height of the resulting picture in pixels
-            if (windowWidth / windowHeight > sizedef.Item1 / sizedef.Item2) //height dominant, width has to be smaller than drawing window to preserve xy-scale
+            if(windowWidth != 0 && windowHeight != 0)
             {
-                scale = windowHeight / sizedef.Item2;
-                height = (int)Math.Round(windowHeight);
-                width = (int) Math.Round(scale * sizedef.Item1);
+                if (windowWidth / windowHeight > sizedef.Item1 / sizedef.Item2) //height dominant, width has to be smaller than drawing window to preserve xy-scale
+                {
+                    scale = windowHeight / sizedef.Item2;
+                    height = (int)Math.Round(windowHeight);
+                    width = (int) Math.Round(scale * sizedef.Item1);
+                }
+                else //width dominant, height has to be smaller than drawing window to preserve xy-scale
+                {
+                    scale = windowWidth / sizedef.Item1;
+                    width = (int)Math.Round(windowWidth);
+                    height = (int)Math.Round(scale * sizedef.Item2);
+                }
             }
-            else //width dominant, height has to be smaller than drawing window to preserve xy-scale
+            else
             {
-                scale = windowWidth / sizedef.Item1;
-                width = (int)Math.Round(windowWidth);
-                height = (int)Math.Round(scale * sizedef.Item2);
+                scale = 1;
+                width = sizedef.Item1;
+                height = sizedef.Item2;
             }
-            for(int j=0; j < allLines.Length; j++)
+            for (int j=0; j < allLines.Length; j++)
             {
                 allLines[j] = allLines[j].Trim(whitespaces);
             }
-            List<Line> picture = ParseSVGBody(allLines); //parse whole svg drawing into list of lines
-            return (width, height, picture);
+            List<InternalLine> picture = ParseSVGBody(allLines); //parse whole svg drawing into list of lines
+            return new Tuple<int, int, List<InternalLine>>(width, height, picture);
         }
 
         /// <summary>
@@ -220,7 +231,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the internal coordinate range of this drawing</returns>
-        private (int, int) ParseSVGHeader(String[] allLines)
+        private Tuple<int, int> ParseSVGHeader(String[] allLines)
         {
             while (!allLines[i].StartsWith("<svg")) //skip non-relevant metadata at start of svg file
             {
@@ -248,7 +259,7 @@ namespace SketchAssistant
             {
                 throw new FileImporterException("missing height definition in SVG header", "the header should contain the \"height=...\" attribute", i + 1);
             }
-            return (width, height);
+            return new Tuple<int, int>(width, height);
         }
 
         /// <summary>
@@ -256,12 +267,12 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the parsed picture as a list of lines</returns>
-        private List<Line> ParseSVGBody(String[] allLines)
+        private List<InternalLine> ParseSVGBody(String[] allLines)
         {
-            List<Line> picture = new List<Line>();
+            List<InternalLine> picture = new List<InternalLine>();
             while (!allLines[i].StartsWith("</svg"))
             {
-                List<Line> element = ParseSingleSVGElement(allLines);
+                List<InternalLine> element = ParseSingleSVGElement(allLines);
                 if (element != null)
                 {
                     picture.AddRange(element);
@@ -277,7 +288,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the parsed Element as a list of lines</returns>
-        private List<Line> ParseSingleSVGElement(string[] allLines)
+        private List<InternalLine> ParseSingleSVGElement(string[] allLines)
         {
             String[] currentElement = GetCurrentElement(allLines);
             return ParseSingleLineSVGElement(currentElement);
@@ -288,10 +299,10 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the parsed element as a Line object, or null if the element is not supported</returns>
-        private List<Line> ParseSingleLineSVGElement(string[] currentElement)
+        private List<InternalLine> ParseSingleLineSVGElement(string[] currentElement)
         {
             List<Point> points= null;
-            List<Line> element = null;
+            List<InternalLine> element = null;
             switch (currentElement[0])
             {
                 case "<rect":
@@ -320,8 +331,8 @@ namespace SketchAssistant
             }
             if (element == null)
             {
-                element = new List<Line>();
-                element.Add(new Line(points));
+                element = new List<InternalLine>();
+                element.Add(new InternalLine(points));
             }
             return element;
         }
@@ -542,7 +553,7 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="currentElement">the definition of the element as whitespace seperated String[]</param>
         /// <returns>the parsed element as a List of Points</returns>
-        private List<Line> ParsePath(string[] currentElement)
+        private List<InternalLine> ParsePath(string[] currentElement)
         {
             List<String> pathElements = new List<string>();
             for (int j = 0; j < currentElement.Length; j++)
@@ -560,7 +571,7 @@ namespace SketchAssistant
                 }
             }
             NormalizePathDeclaration(pathElements); //expand path data to always explicitly have the command descriptor in front of the appropriate number of arguments and to seperate command descriptors, coordinates and other tokens always into seperate list elements (equivalent to seperation with spaces in the input file, but svg allows also for comma as a seperator, and for omitting seperators where possible without losing information (refer to svg grammer) to reduce file size
-            List<Line> element = new List<Line>();
+            List<InternalLine> element = new List<InternalLine>();
             List<Point> currentLine = new List<Point>();
             double lastBezierControlPointX= 0;
             double lastBezierControlPointY= 0;
@@ -569,9 +580,9 @@ namespace SketchAssistant
             double initialPositionX= -1;
             double initialPositionY= -1;
             bool newSubpath = true;
-            (List<Point>, double, double) valuesArc; //list of points, new values for: lastPositionX, lastPositionY
-            (List<Point>, double, double, double, double) valuesBezierCurve; //list of points, new values for: lastPositionX, lastPositionY, lastBezierControlPointX, lastBezierControlPointY
-            (Point, double, double) valuesSinglePoint = Parse_M_L(pathElements); //new point, new values for: lastPositionX, lastPositionY
+            Tuple<List<Point>, double, double> valuesArc; //list of points, new values for: lastPositionX, lastPositionY
+            Tuple<List<Point>, double, double, double, double> valuesBezierCurve; //list of points, new values for: lastPositionX, lastPositionY, lastBezierControlPointX, lastBezierControlPointY
+            var valuesSinglePoint = Parse_M_L(pathElements); //new point, new values for: lastPositionX, lastPositionY
             currentLine = new List<Point>();
             currentLine.Add(valuesSinglePoint.Item1);
             lastPositionX = valuesSinglePoint.Item2;
@@ -587,7 +598,7 @@ namespace SketchAssistant
                 currentToken = pathElements.First();
                 if (currentToken.Equals("M"))
                 {
-                    element.Add(new Line(currentLine)); //save current line
+                    element.Add(new InternalLine(currentLine)); //save current line
                     valuesSinglePoint = Parse_M_L(pathElements);
                     currentLine = new List<Point>(); //create new empty line
                     currentLine.Add(valuesSinglePoint.Item1); //add point to new line
@@ -596,7 +607,7 @@ namespace SketchAssistant
                 }
                 else if (currentToken.Equals("m"))
                 {
-                    element.Add(new Line(currentLine)); //save current line
+                    element.Add(new InternalLine(currentLine)); //save current line
                     valuesSinglePoint = Parse_m_l(pathElements, lastPositionX, lastPositionY);
                     currentLine = new List<Point>(); //create new empty line
                     currentLine.Add(valuesSinglePoint.Item1); //add point to new line
@@ -608,7 +619,7 @@ namespace SketchAssistant
                     valuesSinglePoint = Parse_Z(pathElements, initialPositionX, initialPositionY); //method call only used for uniform program structure... only real effect of method is to consume one token
                     newSubpath = true;
                     currentLine.Add(valuesSinglePoint.Item1); //add point to old line
-                    element.Add(new Line(currentLine)); //save current line
+                    element.Add(new InternalLine(currentLine)); //save current line
                     currentLine = new List<Point>(); //create new empty line
                     currentLine.Add(valuesSinglePoint.Item1); //add point to new line
                     lastPositionX = valuesSinglePoint.Item2; //save last point coordinates
@@ -749,7 +760,7 @@ namespace SketchAssistant
             }
             if (currentLine.Count > 1)
             {
-                element.Add(new Line(currentLine)); //save current line
+                element.Add(new InternalLine(currentLine)); //save current line
             }
             return element;
         }
@@ -961,10 +972,10 @@ namespace SketchAssistant
         /// <param name="initialPositionX">absolute x coordinate of the last initial point of this subpath</param>
         /// <param name="initialPositionY">absolute y coordinate of the last initial point of this subpath</param>
         /// <returns></returns>
-        private (Point, double, double) Parse_Z(List<string> pathElements, double initialPositionX, double initialPositionY)
+        private Tuple<Point, double, double> Parse_Z(List<string> pathElements, double initialPositionX, double initialPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
-            return (ScaleAndCreatePoint(initialPositionX, initialPositionY), initialPositionX, initialPositionY);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(initialPositionX, initialPositionY), initialPositionX, initialPositionY);
         }
 
         /// <summary>
@@ -972,14 +983,14 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="pathElements">a list of all not yet parsed path element tokens and values in correct order, starting with the element to be parsed</param>
         /// <returns>the point at the end of the move, close loop or line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_M_L(List<string> pathElements)
+        private Tuple<Point, double, double> Parse_M_L(List<string> pathElements)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse x coordinate
             pathElements.RemoveAt(0); //remove x coordinate token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
-            return (ScaleAndCreatePoint(x, y), x, y);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(x, y), x, y);
         }
 
         /// <summary>
@@ -989,7 +1000,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>the point at the end of the move, close loop or line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_m_l(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<Point, double, double> Parse_m_l(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse relative x coordinate
@@ -998,7 +1009,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove y coordinate token
             x = lastPositionX + x; //compute absolute x coordinate
             y = lastPositionY + y; //compute absolute y coordinate
-            return (ScaleAndCreatePoint(x, y), x, y);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(x, y), x, y);
         }
 
         /// <summary>
@@ -1007,12 +1018,12 @@ namespace SketchAssistant
         /// <param name="pathElements">a list of all not yet parsed path element tokens and values in correct order, starting with the element to be parsed</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>the point at the end of the horizontal line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_H(List<string> pathElements, double lastPositionY)
+        private Tuple<Point, double, double> Parse_H(List<string> pathElements, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse x coordinate
             pathElements.RemoveAt(0); //remove x coordinate token
-            return (ScaleAndCreatePoint(x, lastPositionY), x, lastPositionY);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(x, lastPositionY), x, lastPositionY);
         }
 
         /// <summary>
@@ -1022,13 +1033,13 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>the point at the end of the horizontal line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_h(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<Point, double, double> Parse_h(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse relative x coordinate
             pathElements.RemoveAt(0); //remove x coordinate token
             x = lastPositionX + x; //compute absolute x coordinate
-            return (ScaleAndCreatePoint(x, lastPositionY), x, lastPositionY);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(x, lastPositionY), x, lastPositionY);
         }
 
         /// <summary>
@@ -1037,12 +1048,12 @@ namespace SketchAssistant
         /// <param name="pathElements">a list of all not yet parsed path element tokens and values in correct order, starting with the element to be parsed</param>
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <returns>the point at the end of the vertical line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_V(List<string> pathElements, double lastPositionX)
+        private Tuple<Point, double, double> Parse_V(List<string> pathElements, double lastPositionX)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
-            return (ScaleAndCreatePoint(lastPositionX, y), lastPositionX, y);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(lastPositionX, y), lastPositionX, y);
         }
 
         /// <summary>
@@ -1052,13 +1063,13 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>the point at the end of the vertical line action and its exact, unscaled coordinates</returns>
-        private (Point, double, double) Parse_v(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<Point, double, double> Parse_v(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse relative y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
             y = lastPositionY + y; //compute absolute y coordinate
-            return (ScaleAndCreatePoint(lastPositionX, y), lastPositionX, y);
+            return new Tuple<Point, double, double>(ScaleAndCreatePoint(lastPositionX, y), lastPositionX, y);
         }
 
         /// <summary>
@@ -1068,7 +1079,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the second bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_C(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double, double, double> Parse_C(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x1 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse first control point x coordinate
@@ -1083,7 +1094,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove x coordinate token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse target point y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
-            return (SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
+            return new Tuple<List<Point>, double, double, double, double>(SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
         }
 
         /// <summary>
@@ -1093,7 +1104,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the second bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_c(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double, double, double> Parse_c(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x1 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse first control point x coordinate
@@ -1114,7 +1125,7 @@ namespace SketchAssistant
             y2 = lastPositionY + y2; //compute absolute y coordinate
             x = lastPositionX + x; //compute absolute x coordinate
             y = lastPositionY + y; //compute absolute y coordinate
-            return (SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
+            return new Tuple<List<Point>, double, double, double, double>(SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
         }
 
         /// <summary>
@@ -1126,7 +1137,7 @@ namespace SketchAssistant
         /// <param name="lastBezierControlPointX">absolute x coordinate of the last bezier control point of the previous bezier curve</param>
         /// <param name="lastBezierControlPointY">absolute y coordinate of the last bezier control point of the previous bezier curve</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the second bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_S(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
+        private Tuple<List<Point>, double, double, double, double> Parse_S(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x2 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse second control point x coordinate
@@ -1139,7 +1150,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove y coordinate token
             double x1 = lastPositionX + (lastPositionX - lastBezierControlPointX); //mirror last bezier control point at bezier start point to get first new bezier control point
             double y1 = lastPositionY + (lastPositionY - lastBezierControlPointY); //mirror last bezier control point at bezier start point to get first new bezier control point
-            return (SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
+            return new Tuple<List<Point>, double, double, double, double>(SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
         }
 
         /// <summary>
@@ -1151,7 +1162,7 @@ namespace SketchAssistant
         /// <param name="lastBezierControlPointX">absolute x coordinate of the last bezier control point of the previous bezier curve</param>
         /// <param name="lastBezierControlPointY">absolute y coordinate of the last bezier control point of the previous bezier curve</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the second bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_s(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
+        private Tuple<List<Point>, double, double, double, double> Parse_s(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x2 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse second control point x coordinate
@@ -1168,7 +1179,7 @@ namespace SketchAssistant
             y2 = lastPositionY + y2; //compute absolute y coordinate
             x = lastPositionX + x; //compute absolute x coordinate
             y = lastPositionY + y; //compute absolute y coordinate
-            return (SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
+            return new Tuple<List<Point>, double, double, double, double>(SampleCubicBezier(lastPositionX, lastPositionY, x1, y1, x2, y2, x, y), x, y, x2, y2);
         }
 
         /// <summary>
@@ -1178,7 +1189,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_Q(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double, double, double> Parse_Q(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x1 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse control point x coordinate
@@ -1189,7 +1200,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove x coordinate token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse target point y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
-            return (SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
+            return new Tuple<List<Point>, double, double, double, double>(SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
         }
 
         /// <summary>
@@ -1199,7 +1210,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_q(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double, double, double> Parse_q(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x1 = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse control point x coordinate
@@ -1214,7 +1225,7 @@ namespace SketchAssistant
             y1 = lastPositionY + y1; //compute absolute y coordinate
             x = lastPositionX + x; //compute absolute x coordinate
             y = lastPositionY + y; //compute absolute y coordinate
-            return (SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
+            return new Tuple<List<Point>, double, double, double, double>(SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
         }
 
         /// <summary>
@@ -1226,7 +1237,7 @@ namespace SketchAssistant
         /// <param name="lastBezierControlPointX">absolute x coordinate of the last bezier control point of the previous bezier curve</param>
         /// <param name="lastBezierControlPointY">absolute y coordinate of the last bezier control point of the previous bezier curve</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_T(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
+        private Tuple<List<Point>, double, double, double, double> Parse_T(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse target point x coordinate
@@ -1235,7 +1246,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove y coordinate token
             double x1 = lastPositionX + (lastPositionX - lastBezierControlPointX); //mirror last bezier control point at bezier start point to get first new bezier control point
             double y1 = lastPositionY + (lastPositionY - lastBezierControlPointY); //mirror last bezier control point at bezier start point to get first new bezier control point
-            return (SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
+            return new Tuple<List<Point>, double, double, double, double>(SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
         }
 
         /// <summary>
@@ -1247,7 +1258,7 @@ namespace SketchAssistant
         /// <param name="lastBezierControlPointX">absolute x coordinate of the last bezier control point of the previous bezier curve</param>
         /// <param name="lastBezierControlPointY">absolute y coordinate of the last bezier control point of the previous bezier curve</param>
         /// <returns>a List of Points containing all sampled points on the bezier curve, aswell as the unscaled x and y coordinates of the last point of the curve and of the bezier control point</returns>
-        private (List<Point>, double, double, double, double) Parse_t(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
+        private Tuple<List<Point>, double, double, double, double> Parse_t(List<string> pathElements, double lastPositionX, double lastPositionY, double lastBezierControlPointX, double lastBezierControlPointY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double x = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse target point x coordinate
@@ -1258,7 +1269,7 @@ namespace SketchAssistant
             y = lastPositionY + y; //compute absolute y coordinate
             double x1 = lastPositionX + (lastPositionX - lastBezierControlPointX); //mirror last bezier control point at bezier start point to get first new bezier control point
             double y1 = lastPositionY + (lastPositionY - lastBezierControlPointY); //mirror last bezier control point at bezier start point to get first new bezier control point
-            return (SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
+            return new Tuple<List<Point>, double, double, double, double>(SampleQuadraticBezier(lastPositionX, lastPositionY, x1, y1, x, y), x, y, x1, y1);
         }
 
         /// <summary>
@@ -1268,7 +1279,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the elliptic arc, aswell as the unscaled x and y coordinates of the last point of the arc<returns>
-        private (List<Point>, double, double) Parse_A(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double> Parse_A(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double rx = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse x radius
@@ -1287,7 +1298,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove y coordinate token
             x = x - lastPositionX; //compute relative x coordinate
             y = y - lastPositionY; //compute relative y coordinate
-            return (SampleArc(lastPositionX, lastPositionY, rx, ry, x, y, thetha, largeArcFlag, sweepFlag), x, y);
+            return new Tuple<List<Point>, double, double>(SampleArc(lastPositionX, lastPositionY, rx, ry, x, y, thetha, largeArcFlag, sweepFlag), x, y);
         }
 
         /// <summary>
@@ -1297,7 +1308,7 @@ namespace SketchAssistant
         /// <param name="lastPositionX">absolute x coordinate of the last active point</param>
         /// <param name="lastPositionY">absolute y coordinate of the last active point</param>
         /// <returns>a List of Points containing all sampled points on the elliptic arc, aswell as the unscaled x and y coordinates of the last point of the arc</returns>
-        private (List<Point>, double, double) Parse_a(List<string> pathElements, double lastPositionX, double lastPositionY)
+        private Tuple<List<Point>, double, double> Parse_a(List<string> pathElements, double lastPositionX, double lastPositionY)
         {
             pathElements.RemoveAt(0); //remove element descriptor token
             double rx = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse x radius
@@ -1314,7 +1325,7 @@ namespace SketchAssistant
             pathElements.RemoveAt(0); //remove x coordinate token
             double y = Convert.ToDouble(pathElements.First(), CultureInfo.InvariantCulture); //parse target point y coordinate
             pathElements.RemoveAt(0); //remove y coordinate token
-            return (SampleArc(lastPositionX, lastPositionY, rx, ry, x, y, thetha, largeArcFlag, sweepFlag), x, y);
+            return new Tuple<List<Point>, double, double>(SampleArc(lastPositionX, lastPositionY, rx, ry, x, y, thetha, largeArcFlag, sweepFlag), x, y);
         }
 
         /// <summary>
@@ -1336,7 +1347,7 @@ namespace SketchAssistant
             double sin = Math.Sin(thetha / 180 * Math.PI);
             double targetXTransformed = cos * nextPositionXRelative - sin * nextPositionYRelative; //rotate target point counterclockwise around the start point by [thetha] degrees, thereby practically rotating an intermediate coordinate system, which has its origin in the start point, clockwise by the same amount
             double targetYTransformed = sin * nextPositionXRelative + cos * nextPositionYRelative;
-            (double[], double[]) values = SampleEllipticArcBiasedNoRotation(rx, ry, targetXTransformed, targetYTransformed, largeArcFlag, sweepFlag);
+            var values = SampleEllipticArcBiasedNoRotation(rx, ry, targetXTransformed, targetYTransformed, largeArcFlag, sweepFlag);
             List<Point> result = new List<Point>();
             for (int j = 0; j < values.Item1.Length; j++)
             {
@@ -1359,10 +1370,10 @@ namespace SketchAssistant
         /// <param name="largeArcFlag">flag determining if the large or the small arc is to be drawn</param>
         /// <param name="sweepFlag">flag determining in which direction the arc is to be drawn (false = ccw, true = cw)</param>
         /// <returns></returns>
-        private (double[], double[]) SampleEllipticArcBiasedNoRotation(double rx, double ry, double targetXTransformed, double targetYTransformed, bool largeArcFlag, bool sweepFlag)
+        private Tuple<double[], double[]> SampleEllipticArcBiasedNoRotation(double rx, double ry, double targetXTransformed, double targetYTransformed, bool largeArcFlag, bool sweepFlag)
         {
             double xStretchFactor = rx / ry; //get rx to ry ratio
-            (double[], double[]) values = SampleCircleArcBiasedNoRotation(ry, targetXTransformed / xStretchFactor, targetYTransformed, largeArcFlag, sweepFlag); //get a circular arc with radius ry
+            var values = SampleCircleArcBiasedNoRotation(ry, targetXTransformed / xStretchFactor, targetYTransformed, largeArcFlag, sweepFlag); //get a circular arc with radius ry
             for (int j = 0; j < values.Item1.Length; j++)
             {
                 values.Item1[j] = values.Item1[j] * xStretchFactor; //correct x coordinates to get an elliptical arc from a circular one
@@ -1379,7 +1390,7 @@ namespace SketchAssistant
         /// <param name="largeArcFlag">flag determining if the large or the small arc is to be drawn</param>
         /// <param name="sweepFlag">flag determining in which direction the arc is to be drawn (false = ccw, true = cw)</param>
         /// <returns></returns>
-        private (double[], double[]) SampleCircleArcBiasedNoRotation(double r, double nextPositionXRelative, double nextPositionYRelative, bool largeArcFlag, bool sweepFlag)
+        private Tuple<double[], double[]> SampleCircleArcBiasedNoRotation(double r, double nextPositionXRelative, double nextPositionYRelative, bool largeArcFlag, bool sweepFlag)
         {
             // code for center computation adapted from https://stackoverflow.com/a/36211852
             double radsq = r * r;
@@ -1415,7 +1426,7 @@ namespace SketchAssistant
             else xC = x3 - Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((nextPositionYRelative) / q);
             if (yPlusFlag) yC = y3 + Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((nextPositionXRelative) / q); //y3 + Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((x2-x1) / q);
             else yC = y3 - Math.Sqrt(radsq - ((q / 2) * (q / 2))) * ((nextPositionXRelative) / q);
-            (double[], double[]) values = SampleCircleArcBiasedAroundCenter(-xC, -yC, nextPositionXRelative - xC, nextPositionYRelative - yC, r, largeArcFlag, sweepFlag);
+            var values = SampleCircleArcBiasedAroundCenter(-xC, -yC, nextPositionXRelative - xC, nextPositionYRelative - yC, r, largeArcFlag, sweepFlag);
             for (int j = 0; j < values.Item1.Length; j++)
             {
                 values.Item1[j] = values.Item1[j] + xC; //correct center point coordinate bias
@@ -1434,7 +1445,7 @@ namespace SketchAssistant
         /// <param name="r">radius</param>
         /// <param name="clockwise">direction</param>
         /// <returns></returns>
-        private (double[], double[]) SampleCircleArcBiasedAroundCenter(double xStartPoint, double yStartPoint, double xFinalPoint, double yFinalPoint, double r, bool largeArcFlag, bool clockwise)
+        private Tuple<double[], double[]> SampleCircleArcBiasedAroundCenter(double xStartPoint, double yStartPoint, double xFinalPoint, double yFinalPoint, double r, bool largeArcFlag, bool clockwise)
         {
             double phiEnd = Math.Atan2(yFinalPoint, xFinalPoint); // angles between points and origin and the positive x Axis
             double phiStart = Math.Atan2(yStartPoint, xStartPoint);
@@ -1462,7 +1473,7 @@ namespace SketchAssistant
             }
             xValues[numberOfPoints - 1] = xFinalPoint; //(last segment always has an angle of less than or exactly 'angle')
             yValues[numberOfPoints - 1] = yFinalPoint;
-            return (xValues, yValues);
+            return new Tuple<double[], double[]>(xValues, yValues);
         }
 
         /// <summary>
@@ -1479,12 +1490,12 @@ namespace SketchAssistant
         /// <returns>a List of Points containing all sampled points</returns>
         private List<Point> SampleCubicBezier(double lastPositionX, double lastPositionY, double controlPoint1X, double controlPoint1Y, double controlPoint2X, double controlPoint2Y, double nextPositionX, double nextPositionY)
         {
-            (double[], double[]) line1 = CreateDiscreteLine(lastPositionX, lastPositionY, controlPoint1X, controlPoint1Y);
-            (double[], double[]) line2 = CreateDiscreteLine(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y);
-            (double[], double[]) line3 = CreateDiscreteLine(controlPoint2X, controlPoint2Y, nextPositionX, nextPositionY);
-            (double[], double[]) quadraticBezier1 = ComputeBezierStep(line1.Item1, line1.Item2, line2.Item1, line2.Item2);
-            (double[], double[]) quadraticBezier2 = ComputeBezierStep(line2.Item1, line2.Item2, line3.Item1, line3.Item2);
-            (double[], double[]) values = ComputeBezierStep(quadraticBezier1.Item1, quadraticBezier1.Item2, quadraticBezier2.Item1, quadraticBezier2.Item2);
+            var line1 = CreateDiscreteLine(lastPositionX, lastPositionY, controlPoint1X, controlPoint1Y);
+            var line2 = CreateDiscreteLine(controlPoint1X, controlPoint1Y, controlPoint2X, controlPoint2Y);
+            var line3 = CreateDiscreteLine(controlPoint2X, controlPoint2Y, nextPositionX, nextPositionY);
+            var quadraticBezier1 = ComputeBezierStep(line1.Item1, line1.Item2, line2.Item1, line2.Item2);
+            var quadraticBezier2 = ComputeBezierStep(line2.Item1, line2.Item2, line3.Item1, line3.Item2);
+            var values = ComputeBezierStep(quadraticBezier1.Item1, quadraticBezier1.Item2, quadraticBezier2.Item1, quadraticBezier2.Item2);
             List<Point> result = new List<Point>();
             for (int j = 0; j < samplingRateBezier; j++)
             {
@@ -1505,9 +1516,9 @@ namespace SketchAssistant
         /// <returns>a List of Points containing all sampled points</returns>
         private List<Point> SampleQuadraticBezier(double lastPositionX, double lastPositionY, double controlPointX, double controlPointY, double nextPositionX, double nextPositionY)
         {
-            (double[], double[]) line1 = CreateDiscreteLine(lastPositionX, lastPositionY, controlPointX, controlPointY);
-            (double[], double[]) line2 = CreateDiscreteLine(controlPointX, controlPointY, nextPositionX, nextPositionY);
-            (double[], double[]) values = ComputeBezierStep(line1.Item1, line1.Item2, line2.Item1, line2.Item2);
+            var line1 = CreateDiscreteLine(lastPositionX, lastPositionY, controlPointX, controlPointY);
+            var line2 = CreateDiscreteLine(controlPointX, controlPointY, nextPositionX, nextPositionY);
+            var values = ComputeBezierStep(line1.Item1, line1.Item2, line2.Item1, line2.Item2);
             List<Point> result = new List<Point>();
             for (int j = 0; j < samplingRateBezier; j++)
             {
@@ -1524,17 +1535,17 @@ namespace SketchAssistant
         /// <param name="point2X">x coordinate of point 2</param>
         /// <param name="point2Y">y coordinate of point 2</param>
         /// <returns>the discrete line as arrays of x and y coordinates</returns>
-        private (double[], double[]) CreateDiscreteLine(double point1X, double point1Y, double point2X, double point2Y)
+        private Tuple<double[], double[]> CreateDiscreteLine(double point1X, double point1Y, double point2X, double point2Y)
         {
             double[] resultX = new double[samplingRateBezier];
             double[] resultY = new double[samplingRateBezier];
             for (int j = 0; j < samplingRateBezier; j++)
             {
-                (double, double) pointResult = LinearInterpolationForBezier(point1X, point1Y, point2X, point2Y, j);
+                var pointResult = LinearInterpolationForBezier(point1X, point1Y, point2X, point2Y, j);
                 resultX[j] = pointResult.Item1;
                 resultY[j] = pointResult.Item2;
             }
-            return (resultX, resultY);
+            return new Tuple<double[], double[]>(resultX, resultY);
         }
 
         /// <summary>
@@ -1545,17 +1556,17 @@ namespace SketchAssistant
         /// <param name="line2X">x coordinates of all points in line 2</param>
         /// <param name="line2Y">y coordinates of all points in line 2</param>
         /// <returns>the discrete bezier curve</returns>
-        private (double[], double[]) ComputeBezierStep(double[] line1X, double[] line1Y, double[] line2X, double[] line2Y)
+        private Tuple<double[], double[]> ComputeBezierStep(double[] line1X, double[] line1Y, double[] line2X, double[] line2Y)
         {
             double[] resultX = new double[samplingRateBezier];
             double[] resultY = new double[samplingRateBezier];
             for (int j = 0; j < samplingRateBezier; j++)
             {
-                (double, double) pointResult = LinearInterpolationForBezier(line1X[j], line1Y[j], line2X[j], line2Y[j], j);
+                var pointResult = LinearInterpolationForBezier(line1X[j], line1Y[j], line2X[j], line2Y[j], j);
                 resultX[j] = pointResult.Item1;
                 resultY[j] = pointResult.Item2;
             }
-            return (resultX, resultY);
+            return new Tuple<double[], double[]>(resultX, resultY);
         }
 
         /// <summary>
@@ -1567,12 +1578,12 @@ namespace SketchAssistant
         /// <param name="point2Y">y coordinate of point 2</param>
         /// <param name="j">number of point to be interpolated, at a total number of [samplingRateBezier] points</param>
         /// <returns>the linearly interpolated point</returns>
-        private (double, double) LinearInterpolationForBezier(double point1X, double point1Y, double point2X, double point2Y, int j)
+        private Tuple<double, double> LinearInterpolationForBezier(double point1X, double point1Y, double point2X, double point2Y, int j)
         {
             double factor = ((double)1 / (double)(samplingRateBezier - 1)) * (double)j; //factor for linear interpolation
             double x = point1X + ((point2X - point1X) * factor);
             double y = point1Y + ((point2Y - point1Y) * factor);
-            return (x, y);
+            return new Tuple<double, double>(x, y);
         }
 
         /// <summary>
@@ -1581,7 +1592,7 @@ namespace SketchAssistant
         /// <param name="currentElement">the definition of the top level element as whitespace seperated String[]</param>
         /// <param name="allLines">an array holding all lines of the input file</param>
         /// <returns>the parsed element as a Line object, or null if the element is not supported</returns>
-        private List<Line> ParseMultiLineSVGElement(string[] currentElement, string[] allLines)
+        private List<InternalLine> ParseMultiLineSVGElement(string[] currentElement, string[] allLines)
         {
             throw new NotImplementedException();
         }

+ 3 - 3
SketchAssistant/SketchAssistant/FileImporterException.cs → SketchAssistant/SketchAssistantWPF/FileImporterException.cs

@@ -4,7 +4,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class FileImporterException : Exception
     {
@@ -13,9 +13,9 @@ namespace SketchAssistant
         /// </summary>
         String showMessage;
 
-        public FileImporterException(String message, String hint, int lineNumber) : base (message)
+        public FileImporterException(String message, String hint, int lineNumber) : base(message)
         {
-            showMessage = "Could not import file:\n\n" + message + (hint == null ? "" : "\n(Hint: " + hint + ")") + (lineNumber == -1 ? "" : "\n\n-line: " + lineNumber );
+            showMessage = "Could not import file:\n\n" + message + (hint == null ? "" : "\n(Hint: " + hint + ")") + (lineNumber == -1 ? "" : "\n\n-line: " + lineNumber);
         }
 
         public override string ToString()

+ 16 - 11
SketchAssistant/SketchAssistant/GeometryCalculator.cs → SketchAssistant/SketchAssistantWPF/GeometryCalculator.cs

@@ -1,11 +1,11 @@
 using System;
 using System.Collections.Generic;
+using System.Windows;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using System.Drawing;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     /// <summary>
     /// A class that contains all algorithms related to geometry.
@@ -23,7 +23,7 @@ namespace SketchAssistant
         /// <returns>The HashSet containing all Points on the circle.</returns>
         public static HashSet<Point> BresenhamCircleAlgorithm(Point center, int radius)
         {
-            if(radius <= 0) { return new HashSet<Point> { center }; }
+            if (radius <= 0) { return new HashSet<Point> { center }; }
 
             int x = radius - 1;
             int y = 0;
@@ -31,7 +31,7 @@ namespace SketchAssistant
             int dy = 1;
             int err = dx - (radius * 2);
             HashSet<Point> returnSet = new HashSet<Point>();
-            
+
             while (x >= y)
             {
                 returnSet.Add(new Point(center.X + x, center.Y + y));
@@ -76,7 +76,7 @@ namespace SketchAssistant
                 for (int y = 0; y < radius; y++)
                 {
                     //Check if point is on or in the circle
-                    if((x*x + y*y - radius * radius) <= 0)
+                    if ((x * x + y * y - radius * radius) <= 0)
                     {
                         returnSet.Add(new Point(center.X + x, center.Y + y));
                         returnSet.Add(new Point(center.X - x, center.Y + y));
@@ -98,32 +98,37 @@ namespace SketchAssistant
         /// <returns>All points between p0 and p1 (including p0 and p1)</returns>
         public static List<Point> BresenhamLineAlgorithm(Point p0, Point p1)
         {
-            int deltaX = p1.X - p0.X;
-            int deltaY = p1.Y - p0.Y;
+            int p1x = (int)p1.X;
+            int p1y = (int)p1.Y;
+            int p0x = (int)p0.X;
+            int p0y = (int)p0.Y;
+
+            int deltaX = p1x - p0x;
+            int deltaY = p1y - p0y;
             List<Point> returnList;
 
             if (Math.Abs(deltaY) < Math.Abs(deltaX))
             {
                 if (p0.X > p1.X)
                 {
-                    returnList = GetLineLow(p1.X, p1.Y, p0.X, p0.Y);
+                    returnList = GetLineLow(p1x, p1y, p0x, p0y);
                     returnList.Reverse();
                 }
                 else
                 {
-                    returnList = GetLineLow(p0.X, p0.Y, p1.X, p1.Y);
+                    returnList = GetLineLow(p0x, p0y, p1x, p1y);
                 }
             }
             else
             {
                 if (p0.Y > p1.Y)
                 {
-                    returnList = GetLineHigh(p1.X, p1.Y, p0.X, p0.Y);
+                    returnList = GetLineHigh(p1x, p1y, p0x, p0y);
                     returnList.Reverse();
                 }
                 else
                 {
-                    returnList = GetLineHigh(p0.X, p0.Y, p1.X, p1.Y);
+                    returnList = GetLineHigh(p0x, p0y, p1x, p1y);
                 }
             }
             return returnList;

+ 27 - 0
SketchAssistant/SketchAssistantWPF/ImageDimension.cs

@@ -0,0 +1,27 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace SketchAssistantWPF
+{
+    public class ImageDimension
+    {
+        public int Width { get; set; }
+
+        public int Height { get; set; }
+
+        public ImageDimension(int width, int height)
+        {
+            Width = width;
+            Height = height;
+        }
+
+        public void ChangeDimension(int width, int height)
+        {
+            Width = width;
+            Height = height;
+        }
+    }
+}

+ 166 - 0
SketchAssistant/SketchAssistantWPF/InternalLine.cs

@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using System.Windows;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media;
+
+namespace SketchAssistantWPF
+{
+    public class InternalLine
+    {
+        /// <summary>
+        /// list saving all the points of the line in the order of the path from start to end point
+        /// </summary>
+        private List<Point> linePoints;
+        /// <summary>
+        /// unique identifier of this Line object
+        /// </summary>
+        private int identifier;
+        /// <summary>
+        /// flag showing if this is only a temporary line
+        /// </summary>
+        private bool isTemporary;
+        /// <summary>
+        /// A collection of the original Points defining the line.
+        /// </summary>
+        private PointCollection pointColl;
+        /// <summary>
+        /// Indicates if this is a single point.
+        /// </summary>
+        public bool isPoint { get; private set; }
+        /// <summary>
+        /// The location of the point, if this is a point
+        /// </summary>
+        public Point point { get; private set; }
+
+        /// <summary>
+        /// The constructor for lines which are only temporary.
+        /// If you want nice lines use the other constructor.
+        /// </summary>
+        /// <param name="points">The points of the line</param>
+        public InternalLine(List<Point> points)
+        {
+            linePoints = new List<Point>(points);
+            pointColl = new PointCollection(linePoints);
+            isTemporary = true;
+        }
+
+        /// <summary>
+        /// The constructor for lines, which will be more resource efficient 
+        /// and have the ability to populate deletion matrixes.
+        /// </summary>
+        /// <param name="points">The points of the line</param>
+        /// <param name="id">The identifier of the line</param>
+        public InternalLine(List<Point> points, int id)
+        {
+            linePoints = new List<Point>(points);
+            pointColl = new PointCollection(linePoints);
+            identifier = id;
+            CleanPoints();
+            isTemporary = false;
+        }
+
+        public Point GetStartPoint()
+        {
+            return linePoints.First();
+        }
+
+        public Point GetEndPoint()
+        {
+            return linePoints.Last();
+        }
+
+        public List<Point> GetPoints()
+        {
+            return linePoints;
+        }
+
+        public int GetID()
+        {
+            return identifier;
+        }
+
+        public PointCollection GetPointCollection()
+        {
+            return pointColl;
+        }
+
+        /// <summary>
+        /// A function that will take two matrixes and populate them with the line data of this line object
+        /// </summary>
+        /// <param name="boolMatrix">The Matrix of booleans, in which is saved wether there is a line at this position.</param>
+        /// <param name="listMatrix">The Matrix of Lists of integers, in which is saved which lines are at this position</param>
+        public void PopulateMatrixes(bool[,] boolMatrix, HashSet<int>[,] listMatrix)
+        {
+            if (!isTemporary)
+            {
+                foreach (Point currPoint in linePoints)
+                {
+                    if (currPoint.X >= 0 && currPoint.Y >= 0 &&
+                        currPoint.X < boolMatrix.GetLength(0) && currPoint.Y < boolMatrix.GetLength(1))
+                    {
+                        boolMatrix[(int) currPoint.X, (int) currPoint.Y] = true;
+                        if (listMatrix[(int) currPoint.X, (int) currPoint.Y] == null)
+                        {
+                            listMatrix[(int) currPoint.X, (int) currPoint.Y] = new HashSet<int>();
+                        }
+                        listMatrix[(int) currPoint.X, (int) currPoint.Y].Add(identifier);
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// Removes duplicate points from the line object
+        /// </summary>
+        private void CleanPoints()
+        {
+            if (linePoints.Any())
+            {
+                //check if its a point
+                var localIsPoint = linePoints.All(o => o.X == linePoints.First().X && o.Y == linePoints.First().Y);
+                if (!localIsPoint) {
+                    List<Point> newList = new List<Point>();
+                    List<Point> tempList = new List<Point>();
+                    //Since Point is non-nullable, we must ensure the nullPoints, 
+                    //which we remove can not possibly be points of the original given line.
+                    int nullValue = (int) linePoints[0].X + 1;
+                    //Fill the gaps between points
+                    for (int i = 0; i < linePoints.Count - 1; i++)
+                    {
+                        nullValue += (int) linePoints[i + 1].X;
+                        List<Point> partialList = GeometryCalculator.BresenhamLineAlgorithm(linePoints[i], linePoints[i + 1]);
+                        tempList.AddRange(partialList);
+                    }
+                    Point nullPoint = new Point(nullValue, 0);
+                    //Set duplicate points to the null point
+                    for (int i = 1; i < tempList.Count; i++)
+                    {
+                        if ((tempList[i].X == tempList[i - 1].X) && (tempList[i].Y == tempList[i - 1].Y))
+                        {
+                            tempList[i - 1] = nullPoint;
+                        }
+                    }
+                    //remove the null points
+                    foreach (Point tempPoint in tempList)
+                    {
+                        if (tempPoint.X != nullValue)
+                        {
+                            newList.Add(tempPoint);
+                        }
+                    }
+                    linePoints = new List<Point>(newList);
+                }
+                else
+                {
+                    isPoint = true;
+                    point = linePoints.First();
+                    linePoints.Clear();
+                    linePoints.Add(point);
+                }
+            }
+        }
+    }
+}

+ 118 - 229
SketchAssistant/SketchAssistant/MVP_Model.cs → SketchAssistant/SketchAssistantWPF/MVP_Model.cs

@@ -1,11 +1,14 @@
 using System;
 using System.Collections.Generic;
+using System.Windows;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using System.Drawing;
+using System.Windows.Controls;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class MVP_Model
     {
@@ -20,11 +23,8 @@ namespace SketchAssistant
         /// <summary>
         /// The assistant responsible for the redraw mode
         /// </summary>
-        RedrawAssistant redrawAss;
+        //RedrawAssistant redrawAss;
 
-        /*******************/
-        /*** ENUMERATORS ***/
-        /*******************/
 
         /***********************/
         /*** CLASS VARIABLES ***/
@@ -35,10 +35,6 @@ namespace SketchAssistant
         /// </summary>
         bool inDrawingMode;
         /// <summary>
-        /// If the mouse is currently pressed or not.
-        /// </summary>
-        bool mousePressed;
-        /// <summary>
         /// Size of deletion area
         /// </summary>
         int deletionRadius = 5;
@@ -87,18 +83,29 @@ namespace SketchAssistant
         /// </summary>
         public int rightImageBoxHeight;
 
-        //Images
-        Image leftImage;
+        public ImageDimension leftImageSize { get; private set; }
 
-        List<Line> leftLineList;
+        public ImageDimension rightImageSize { get; private set; }
+        /// <summary>
+        /// Indicates whether or not the canvas on the right side is active.
+        /// </summary>
+        public bool canvasActive {get; set;}
+        /// <summary>
+        /// Indicates if there is a graphic loaded in the left canvas.
+        /// </summary>
+        public bool graphicLoaded { get; set; }
+        /// <summary>
+        /// Whether or not the mouse is pressed.
+        /// </summary>
+        private bool mouseDown;
 
         Image rightImageWithoutOverlay;
 
-        Image rightImageWithOverlay;
-
-        List<Tuple<bool, Line>> rightLineList;
+        List<InternalLine> leftLineList;
+        
+        List<Tuple<bool, InternalLine>> rightLineList;
 
-        List<Point> currentLine;
+        List<Point> currentLine = new List<Point>();
 
 
 
@@ -106,112 +113,20 @@ namespace SketchAssistant
         {
             programPresenter = presenter;
             historyOfActions = new ActionHistory();
-            redrawAss = new RedrawAssistant();
-            rightLineList = new List<Tuple<bool, Line>>();
-            overlayItems = new List<Tuple<bool, HashSet<Point>>>();
+            //redrawAss = new RedrawAssistant();
+            //overlayItems = new List<Tuple<bool, HashSet<Point>>>();
+            rightLineList = new List<Tuple<bool, InternalLine>>();
+            canvasActive = false;
+            UpdateUI();
+            rightImageSize = new ImageDimension(0, 0);
+            leftImageSize = new ImageDimension(0, 0);
         }
 
         /**************************/
         /*** INTERNAL FUNCTIONS ***/
         /**************************/
 
-        /// <summary>
-        /// A function that returns a white canvas for a given width and height.
-        /// </summary>
-        /// <param name="width">The width of the canvas in pixels</param>
-        /// <param name="height">The height of the canvas in pixels</param>
-        /// <returns>The new canvas</returns>
-        private Image GetEmptyCanvas(int width, int height)
-        {
-            Image image;
-            try
-            {
-                image = new Bitmap(width, height);
-            }
-            catch (ArgumentException e)
-            {
-                programPresenter.PassMessageToView("The requested canvas size caused an error: \n" 
-                    + e.ToString() + "\n The Canvas will be set to match your window.");
-                image = new Bitmap(leftImageBoxWidth, leftImageBoxHeight);
-            }
-            Graphics graph = Graphics.FromImage(image);
-            graph.FillRectangle(Brushes.White, 0, 0, width + 10, height + 10);
-            return image;
-        }
-        
-
-        /// <summary>
-        /// Creates an empty Canvas on the left
-        /// </summary>
-        /// <param name="width"> width of the new canvas in pixels </param>
-        /// <param name="height"> height of the new canvas in pixels </param>
-        private void DrawEmptyCanvasLeft(int width, int height)
-        {
-            if (width == 0)
-            {
-                leftImage = GetEmptyCanvas(leftImageBoxWidth, leftImageBoxHeight);
-            }
-            else
-            {
-                leftImage = GetEmptyCanvas(width, height);
-            }
-            programPresenter.UpdateLeftImage(leftImage);
-        }
-
-        /// <summary>
-        /// Redraws all lines in rightLineList, for which their associated boolean value equals true and calls RedrawRightOverlay.
-        /// </summary>
-        private void RedrawRightImage()
-        {
-            var workingCanvas = GetEmptyCanvas(rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height);
-            var workingGraph = Graphics.FromImage(workingCanvas);
-            //Lines
-            foreach (Tuple<bool, Line> lineBoolTuple in rightLineList)
-            {
-                if (lineBoolTuple.Item1)
-                {
-                    lineBoolTuple.Item2.DrawLine(workingGraph);
-                }
-            }
-            //The Line being currently drawn
-            if (currentLine != null && currentLine.Count > 0 && inDrawingMode && mousePressed)
-            {
-                var currLine = new Line(currentLine);
-                currLine.DrawLine(workingGraph);
-            }
-            rightImageWithoutOverlay = workingCanvas;
-            //Redraw the Overlay if needed
-            if (leftImage != null)
-            {
-                RedrawRightOverlay();
-            }
-            else
-            {
-                programPresenter.UpdateRightImage(rightImageWithoutOverlay);
-            }
-        }
 
-        /// <summary>
-        /// Redraws all elements in the overlay items for which the respective boolean value is true.
-        /// </summary>
-        private void RedrawRightOverlay()
-        {
-            var workingCanvas = rightImageWithoutOverlay;
-            var workingGraph = Graphics.FromImage(workingCanvas);
-            foreach (Tuple<bool, HashSet<Point>> tup in overlayItems)
-            {
-                if (tup.Item1)
-                {
-                    foreach (Point p in tup.Item2)
-                    {
-                        workingGraph.FillRectangle(Brushes.Green, p.X, p.Y, 1, 1);
-                    }
-                }
-            }
-            rightImageWithOverlay = workingCanvas;
-            programPresenter.UpdateRightImage(rightImageWithOverlay);
-        }
-        
         /// <summary>
         /// Change the status of whether or not the lines are shown.
         /// </summary>
@@ -219,28 +134,25 @@ namespace SketchAssistant
         /// <param name="shown">True if the lines should be shown, false if they should be hidden.</param>
         private void ChangeLines(HashSet<int> lines, bool shown)
         {
-            var changed = false;
             foreach (int lineId in lines)
             {
                 if (lineId <= rightLineList.Count - 1 && lineId >= 0)
                 {
-                    rightLineList[lineId] = new Tuple<bool, Line>(shown, rightLineList[lineId].Item2);
-                    changed = true;
+                    rightLineList[lineId] = new Tuple<bool, InternalLine>(shown, rightLineList[lineId].Item2);
                 }
             }
-            if (changed) { RedrawRightImage(); }
         }
-        
+
         /// <summary>
         /// A function that populates the matrixes needed for deletion detection with line data.
         /// </summary>
         private void RepopulateDeletionMatrixes()
         {
-            if (rightImageWithoutOverlay != null)
+            if (canvasActive)
             {
-                isFilledMatrix = new bool[rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height];
-                linesMatrix = new HashSet<int>[rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height];
-                foreach (Tuple<bool, Line> lineTuple in rightLineList)
+                isFilledMatrix = new bool[rightImageSize.Width, rightImageSize.Height];
+                linesMatrix = new HashSet<int>[rightImageSize.Width, rightImageSize.Height];
+                foreach (Tuple<bool, InternalLine> lineTuple in rightLineList)
                 {
                     if (lineTuple.Item1)
                     {
@@ -250,6 +162,14 @@ namespace SketchAssistant
             }
         }
 
+        /// <summary>
+        /// Tells the Presenter to Update the UI
+        /// </summary>
+        private void UpdateUI()
+        {
+            programPresenter.UpdateUIState(inDrawingMode, historyOfActions.CanUndo(), historyOfActions.CanRedo(), canvasActive, graphicLoaded);
+        }
+
         /// <summary>
         /// A function that checks the deletion matrixes at a certain point 
         /// and returns all Line ids at that point and in a square around it in a certain range.
@@ -263,63 +183,42 @@ namespace SketchAssistant
 
             foreach (Point pnt in GeometryCalculator.FilledCircleAlgorithm(p, (int)range))
             {
-                if (pnt.X >= 0 && pnt.Y >= 0 && pnt.X < rightImageWithoutOverlay.Width && pnt.Y < rightImageWithoutOverlay.Height)
+                if (pnt.X >= 0 && pnt.Y >= 0 && pnt.X < rightImageSize.Width && pnt.Y < rightImageSize.Height)
                 {
-                    if (isFilledMatrix[pnt.X, pnt.Y])
+                    if (isFilledMatrix[(int)pnt.X, (int)pnt.Y])
                     {
-                        returnSet.UnionWith(linesMatrix[pnt.X, pnt.Y]);
+                        returnSet.UnionWith(linesMatrix[(int)pnt.X, (int)pnt.Y]);
                     }
                 }
             }
             return returnSet;
         }
 
-        /*
-        /// <summary>
-        /// Will calculate the start and endpoints of the given line on the right canvas.
-        /// </summary>
-        /// <param name="line">The line.</param>
-        /// <param name="size">The size of the circle with which the endpoints of the line are marked.</param>
-        private Tuple<HashSet<Point>, HashSet<Point>> CalculateStartAndEnd(Line line, int size)
-        {
-            var circle0 = GeometryCalculator.FilledCircleAlgorithm(line.GetStartPoint(), size);
-            var circle1 = GeometryCalculator.FilledCircleAlgorithm(line.GetEndPoint(), size);
-            var currentLineEndings = new Tuple<HashSet<Point>, HashSet<Point>>(circle0, circle1);
-            return currentLineEndings;
-        }
-        */
-
-
+        /********************************************/
+        /*** FUNCTIONS TO INTERACT WITH PRESENTER ***/
+        /********************************************/
 
         /// <summary>
-        /// Tells the Presenter to Update the UI
+        /// A function to update the dimensions of the left and right canvas when the window is resized.
         /// </summary>
-        private void UpdateUI()
+        /// <param name="LeftCanvas">The size of the left canvas.</param>
+        /// <param name="RightCanvas">The size of the right canvas.</param>
+        public void ResizeEvent(ImageDimension LeftCanvas, ImageDimension RightCanvas)
         {
-            programPresenter.UpdateUIState(inDrawingMode, historyOfActions.CanUndo(), historyOfActions.CanRedo(), (rightImageWithoutOverlay != null));
+            if(LeftCanvas.Height >= 0 && LeftCanvas.Width>= 0) { leftImageSize = LeftCanvas; }
+            if(RightCanvas.Height >= 0 && RightCanvas.Width >= 0) { rightImageSize = RightCanvas; }
+          
+            RepopulateDeletionMatrixes();
         }
 
-
-        /********************************************/
-        /*** FUNCTIONS TO INTERACT WITH PRESENTER ***/
-        /********************************************/
-
         /// <summary>
-        /// Creates an empty Canvas
+        /// A function to reset the right image.
         /// </summary>
-        public void DrawEmptyCanvasRight()
+        public void ResetRightImage()
         {
-            if (leftImage == null)
-            {
-                rightImageWithoutOverlay = GetEmptyCanvas(leftImageBoxWidth, leftImageBoxHeight);
-            }
-            else
-            {
-                rightImageWithoutOverlay = GetEmptyCanvas(leftImage.Width, leftImage.Height);
-            }
-            RepopulateDeletionMatrixes();
-            rightImageWithOverlay = rightImageWithoutOverlay;
-            programPresenter.UpdateRightImage(rightImageWithOverlay);
+            rightLineList.Clear();
+            programPresenter.PassLastActionTaken(historyOfActions.Reset());
+            programPresenter.ClearRightLines();
         }
 
         /// <summary>
@@ -328,15 +227,23 @@ namespace SketchAssistant
         /// <param name="width">The width of the left image.</param>
         /// <param name="height">The height of the left image.</param>
         /// <param name="listOfLines">The List of Lines to be displayed in the left image.</param>
-        public void SetLeftLineList(int width, int height, List<Line> listOfLines)
+        public void SetLeftLineList(int width, int height, List<InternalLine> listOfLines)
         {
-            var workingCanvas = GetEmptyCanvas(width,height);
+            leftImageSize = new ImageDimension(width, height);
+            rightImageSize = new ImageDimension(width, height);
+            leftLineList = listOfLines;
+            graphicLoaded = true;
+            programPresenter.UpdateLeftLines(leftLineList);
+            //programPresenter.ClearRightLines(); //TODO check if right position for this method call
+            CanvasActivated();
+            /*
+            var workingCanvas = GetEmptyCanvas(width, height);
             var workingGraph = Graphics.FromImage(workingCanvas);
             leftLineList = listOfLines;
-            redrawAss = new RedrawAssistant(leftLineList);
-            overlayItems = redrawAss.Initialize(markerRadius);
+            //redrawAss = new RedrawAssistant(leftLineList);
+            //overlayItems = redrawAss.Initialize(markerRadius);
             //Lines
-            foreach (Line line in leftLineList)
+            foreach (InternalLine line in leftLineList)
             {
                 line.DrawLine(workingGraph);
             }
@@ -344,7 +251,18 @@ namespace SketchAssistant
             programPresenter.UpdateLeftImage(leftImage);
             //Set right image to same size as left image and delete linelist
             DrawEmptyCanvasRight();
-            rightLineList = new List<Tuple<bool, Line>>();
+            rightLineList = new List<Tuple<bool, InternalLine>>();
+            */
+        }
+
+        /// <summary>
+        /// A function to tell the model a new canvas was activated.
+        /// </summary>
+        public void CanvasActivated()
+        {
+            canvasActive = true;
+            RepopulateDeletionMatrixes();
+            UpdateUI();
         }
 
         /// <summary>
@@ -369,11 +287,8 @@ namespace SketchAssistant
                     default:
                         break;
                 }
-                if(leftImage != null)
-                {
-                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                }
-                RedrawRightImage();
+                //TODO: For the person implementing overlay: Add check if overlay needs to be added
+                programPresenter.UpdateRightLines(rightLineList);
             }
             RepopulateDeletionMatrixes();
             programPresenter.PassLastActionTaken(historyOfActions.MoveAction(true));
@@ -403,11 +318,8 @@ namespace SketchAssistant
                     default:
                         break;
                 }
-                if (leftImage != null)
-                {
-                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                }
-                RedrawRightImage();
+                //TODO: For the person implementing overlay: Add check if overlay needs to be added
+                programPresenter.UpdateRightLines(rightLineList);
                 RepopulateDeletionMatrixes();
             }
             UpdateUI();
@@ -422,23 +334,7 @@ namespace SketchAssistant
             inDrawingMode = nowDrawing;
             UpdateUI();
         }
-
-        /// <summary>
-        /// A method to get the dimensions of the right image.
-        /// </summary>
-        /// <returns>A tuple containing the width and height of the right image.</returns>
-        public Tuple<int, int> GetRightImageDimensions()
-        {
-            if (rightImageWithoutOverlay != null)
-            {
-                return new Tuple<int, int>(rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height);
-            }
-            else
-            {
-                return new Tuple<int, int>(0, 0);
-            }
-        }
-
+        
         /// <summary>
         /// Updates the current cursor position of the model.
         /// </summary>
@@ -446,6 +342,7 @@ namespace SketchAssistant
         public void SetCurrentCursorPosition(Point p)
         {
             currentCursorPosition = p;
+            mouseDown = programPresenter.IsMousePressed();
         }
 
         /// <summary>
@@ -453,10 +350,11 @@ namespace SketchAssistant
         /// </summary>
         public void MouseDown()
         {
-            mousePressed = true;
-            if (inDrawingMode)
+            mouseDown = true;
+            if (inDrawingMode && mouseDown)
             {
-                currentLine = new List<Point>();
+                currentLine.Clear();
+                currentLine.Add(currentCursorPosition);
             }
         }
 
@@ -465,19 +363,17 @@ namespace SketchAssistant
         /// </summary>
         public void MouseUp()
         {
-            mousePressed = false;
+            mouseDown = false;
             if (inDrawingMode && currentLine.Count > 0)
             {
-                Line newLine = new Line(currentLine, rightLineList.Count);
-                rightLineList.Add(new Tuple<bool, Line>(true, newLine));
+                InternalLine newLine = new InternalLine(currentLine, rightLineList.Count);
+                rightLineList.Add(new Tuple<bool, InternalLine>(true, newLine));
                 newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
                 programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID())));
-                if(leftImage != null)
-                {
-                    //Execute a RedrawAssistant tick with the currently finished Line
-                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, newLine.GetID(), true);
-                }
-                RedrawRightImage();
+                //TODO: For the person implementing overlay: Add check if overlay needs to be added
+                programPresenter.UpdateRightLines(rightLineList);
+                currentLine.Clear();
+                programPresenter.UpdateCurrentLine(currentLine);
             }
             UpdateUI();
         }
@@ -491,16 +387,13 @@ namespace SketchAssistant
             else { previousCursorPosition = currentCursorPosition; }
             cursorPositions.Enqueue(currentCursorPosition);
             //Drawing
-            if (inDrawingMode && mousePressed)
+            if (inDrawingMode && programPresenter.IsMousePressed())
             {
-                var rightGraph = Graphics.FromImage(rightImageWithoutOverlay);
                 currentLine.Add(currentCursorPosition);
-                Line drawline = new Line(currentLine);
-                drawline.DrawLine(rightGraph);
-                RedrawRightOverlay();
+                programPresenter.UpdateCurrentLine(currentLine);
             }
             //Deleting
-            if (!inDrawingMode && mousePressed)
+            if (!inDrawingMode && programPresenter.IsMousePressed())
             {
                 List<Point> uncheckedPoints = GeometryCalculator.BresenhamLineAlgorithm(previousCursorPosition, currentCursorPosition);
                 foreach (Point currPoint in uncheckedPoints)
@@ -511,15 +404,11 @@ namespace SketchAssistant
                         programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Delete, linesToDelete)));
                         foreach (int lineID in linesToDelete)
                         {
-                            rightLineList[lineID] = new Tuple<bool, Line>(false, rightLineList[lineID].Item2);
+                            rightLineList[lineID] = new Tuple<bool, InternalLine>(false, rightLineList[lineID].Item2);
                         }
                         RepopulateDeletionMatrixes();
-                        if(leftImage != null)
-                        {
-                            //Redraw overlay gets ticked
-                            //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                        }
-                        RedrawRightImage();
+                        //TODO: For the person implementing overlay: Add check if overlay needs to be added
+                        programPresenter.UpdateRightLines(rightLineList);
                     }
                 }
             }
@@ -528,14 +417,15 @@ namespace SketchAssistant
         /// <summary>
         /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
         /// </summary>
-        public void UpdateSizes()
+        /// <param name="CanvasSize">The size of the canvas</param>
+        public void UpdateSizes(ImageDimension CanvasSize)
         {
             if (rightImageWithoutOverlay != null)
             {
-                int widthImage = rightImageWithoutOverlay.Width;
-                int heightImage = rightImageWithoutOverlay.Height;
-                int widthBox = rightImageBoxWidth;
-                int heightBox = rightImageBoxHeight;
+                int widthImage = rightImageSize.Width;
+                int heightImage = rightImageSize.Height;
+                int widthBox = CanvasSize.Width;
+                int heightBox = CanvasSize.Height;
 
                 float imageRatio = (float)widthImage / (float)heightImage;
                 float containerRatio = (float)widthBox / (float)heightBox;
@@ -551,7 +441,6 @@ namespace SketchAssistant
                     zoomFactor = (float)heightImage / (float)heightBox;
                 }
                 markerRadius = (int)(10 * zoomFactor);
-                redrawAss.SetMarkerRadius(markerRadius);
                 deletionRadius = (int)(5 * zoomFactor);
             }
         }

+ 171 - 55
SketchAssistant/SketchAssistant/MVP_Presenter.cs → SketchAssistant/SketchAssistantWPF/MVP_Presenter.cs

@@ -3,10 +3,13 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
-using System.Windows.Forms;
-using System.Drawing;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Shapes;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class MVP_Presenter
     {
@@ -18,6 +21,18 @@ namespace SketchAssistant
         /// The Model of the MVP-Model.
         /// </summary>
         MVP_Model programModel;
+        /// <summary>
+        /// A dictionary connecting the id of an InternalLine with the respective Polyline in the right canvas.
+        /// </summary>
+        Dictionary<int, Shape> rightPolyLines;
+
+        ImageDimension CanvasSizeLeft = new ImageDimension(0,0);
+
+        ImageDimension CanvasSizeRight = new ImageDimension(0, 0);
+
+        ImageDimension ImageSizeLeft = new ImageDimension(0, 0);
+
+        ImageDimension ImageSizeRight = new ImageDimension(0, 0);
 
         /*******************/
         /*** ENUMERATORS ***/
@@ -58,13 +73,12 @@ namespace SketchAssistant
         /// </summary>
         /// <param name="leftPBS">The new size of the left picture box.</param>
         /// <param name="rightPBS">The new size of the left picture box.</param>
-        public void Resize(Tuple<int, int> leftPBS,Tuple<int, int> rightPBS)
+        public void Resize(Tuple<int, int> leftPBS, Tuple<int, int> rightPBS)
         {
-            programModel.leftImageBoxWidth = leftPBS.Item1;
-            programModel.leftImageBoxHeight = leftPBS.Item2;
-            programModel.rightImageBoxWidth = rightPBS.Item1;
-            programModel.rightImageBoxHeight = rightPBS.Item2;
-            programModel.UpdateSizes();
+            CanvasSizeLeft.ChangeDimension(leftPBS.Item1, leftPBS.Item2);
+            CanvasSizeRight.ChangeDimension(rightPBS.Item1, rightPBS.Item2);
+            programModel.UpdateSizes(CanvasSizeRight);
+            programModel.ResizeEvent(CanvasSizeLeft, CanvasSizeRight);
         }
 
         /// <summary>
@@ -83,10 +97,14 @@ namespace SketchAssistant
                 if (!fileNameTup.Item1.Equals("") && !fileNameTup.Item2.Equals(""))
                 {
                     programView.SetToolStripLoadStatus(fileNameTup.Item2);
-                    (int, int, List<Line>) values = fileImporter.ParseISADInputFile(fileNameTup.Item1);
+                    Tuple<int, int, List<InternalLine>> values = fileImporter.ParseISADInputFile(fileNameTup.Item1);
                     programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
+
+                    programModel.ResetRightImage();
+                    programModel.CanvasActivated();
                     programModel.ChangeState(true);
                     programView.EnableTimer();
+                    ClearRightLines();
                 }
             }
         }
@@ -106,10 +124,13 @@ namespace SketchAssistant
                     programView.SetToolStripLoadStatus(fileNameTup.Item2);
                     try
                     {
-                        (int, int, List<Line>) values = fileImporter.ParseSVGInputFile(fileNameTup.Item1, programModel.leftImageBoxWidth, programModel.leftImageBoxHeight);
+                        Tuple<int, int, List<InternalLine>> values = fileImporter.ParseSVGInputFile(fileNameTup.Item1, programModel.leftImageBoxWidth, programModel.leftImageBoxHeight);
                         programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
+                        programModel.ResetRightImage();
+                        programModel.CanvasActivated();
                         programModel.ChangeState(true);
                         programView.EnableTimer();
+                        ClearRightLines();
                     }
                     catch (FileImporterException ex)
                     {
@@ -148,6 +169,14 @@ namespace SketchAssistant
             programModel.Redo();
         }
 
+        /// <summary>
+        /// Pass-trough function for ticking the model.
+        /// </summary>
+        public void Tick()
+        {
+            programModel.Tick();
+        }
+
         /// <summary>
         /// Checks if there is unsaved progress, and promts the model to generate a new canvas if not.
         /// </summary>
@@ -160,31 +189,26 @@ namespace SketchAssistant
             }
             if (okToContinue)
             {
-                programModel.DrawEmptyCanvasRight();
+                programModel.ResizeEvent(CanvasSizeLeft, CanvasSizeRight);
+                programModel.ResetRightImage();
+                programModel.CanvasActivated();
                 programModel.ChangeState(true);
                 programView.EnableTimer();
+                ClearRightLines();
             }
         }
 
-        /// <summary>
-        /// Pass-trough function for ticking the model.
-        /// </summary>
-        public void Tick()
-        {
-            programModel.Tick();
-        }
-
         /// <summary>
         /// Pass-trough when the mouse is moved.
         /// </summary>
         /// <param name="mouseAction">The action which is sent by the View.</param>
         /// <param name="e">The Mouse event arguments.</param>
-        public void MouseEvent(MouseAction mouseAction, MouseEventArgs e)
+        public void MouseEvent(MouseAction mouseAction, Point position)
         {
             switch (mouseAction)
             {
                 case MouseAction.Move:
-                    programModel.SetCurrentCursorPosition(ConvertCoordinates(new Point(e.X, e.Y)));
+                    programModel.SetCurrentCursorPosition(position);
                     break;
                 default:
                     break;
@@ -220,6 +244,84 @@ namespace SketchAssistant
         /*** FUNCTIONS MODEL -> PRESENTER ***/
         /************************************/
 
+        /// <summary>
+        /// Return the position of the cursor
+        /// </summary>
+        /// <returns>The position of the cursor</returns>
+        public Point GetCursorPosition()
+        {
+            return programView.GetCursorPosition();
+        }
+
+        /// <summary>
+        /// Updates the currentline
+        /// </summary>
+        /// <param name="linepoints">The points of the current line.</param>
+        public void UpdateCurrentLine(List<Point> linepoints)
+        {
+            Polyline currentLine = new Polyline();
+            currentLine.Stroke = Brushes.Black;
+            currentLine.Points = new PointCollection(linepoints);
+            programView.DisplayCurrLine(currentLine);
+        }
+
+        /// <summary>
+        /// Clears all Lines in the right canvas.
+        /// </summary>
+        public void ClearRightLines()
+        {
+            programView.RemoveAllRightLines();
+            rightPolyLines = new Dictionary<int, Shape>();
+        }
+
+        /// <summary>
+        /// A function to update the displayed lines in the right canvas.
+        /// </summary>
+        public void UpdateRightLines(List<Tuple<bool, InternalLine>> lines)
+        {
+            foreach(Tuple<bool, InternalLine> tup in lines)
+            {
+                var status = tup.Item1;
+                var line = tup.Item2;
+                if (!rightPolyLines.ContainsKey(line.GetID()))
+                {
+                    if (!line.isPoint)
+                    {
+                        Polyline newLine = new Polyline();
+                        newLine.Points = line.GetPointCollection();
+                        rightPolyLines.Add(line.GetID(), newLine);
+                        programView.AddNewLineRight(newLine);
+                    }
+                    else
+                    {
+                        Ellipse newPoint = new Ellipse();
+                        newPoint.SetValue(Canvas.LeftProperty, line.point.X);
+                        newPoint.SetValue(Canvas.TopProperty, line.point.Y);
+                        rightPolyLines.Add(line.GetID(), newPoint);
+                        programView.AddNewPointRight(newPoint);
+                    }
+                }
+                SetVisibility(rightPolyLines[line.GetID()], status);
+            }
+        }
+
+        /// <summary>
+        /// A function to update the displayed lines in the left canvas.
+        /// </summary>
+        public void UpdateLeftLines(List<InternalLine> lines)
+        {
+            programView.RemoveAllLeftLines();
+            foreach (InternalLine line in lines)
+            {
+                Polyline newLine = new Polyline();
+                newLine.Stroke = Brushes.Black;
+                newLine.Points = line.GetPointCollection();
+                programView.AddNewLineLeft(newLine);
+            }
+            programView.SetCanvasState("LeftCanvas", true);
+            programView.SetCanvasState("RightCanvas", true);
+        }
+
         /// <summary>
         /// Called by the model when the state of the Program changes. 
         /// Changes the look of the UI according to the current state of the model.
@@ -227,51 +329,37 @@ namespace SketchAssistant
         /// <param name="inDrawingMode">If the model is in Drawing Mode</param>
         /// <param name="canUndo">If actions in the model can be undone</param>
         /// <param name="canRedo">If actions in the model can be redone</param>
-        /// <param name="imageLoaded">If an image is loaded in the model</param>
-        public void UpdateUIState(bool inDrawingMode, bool canUndo, bool canRedo, bool imageLoaded)
+        /// <param name="canvasActive">If the right canvas is active</param>
+        /// <param name="graphicLoaded">If an image is loaded in the model</param>
+        public void UpdateUIState(bool inDrawingMode, bool canUndo, bool canRedo, bool canvasActive, bool graphicLoaded)
         {
-            Dictionary<String, Form1.ButtonState> dict = new Dictionary<String, Form1.ButtonState> {
-                {"canvasButton", Form1.ButtonState.Enabled }, {"drawButton", Form1.ButtonState.Disabled}, {"deleteButton",Form1.ButtonState.Disabled },
-                {"undoButton", Form1.ButtonState.Disabled },{"redoButton",  Form1.ButtonState.Disabled}};
+            Dictionary<String, MainWindow.ButtonState> dict = new Dictionary<String, MainWindow.ButtonState> {
+                {"canvasButton", MainWindow.ButtonState.Enabled }, {"drawButton", MainWindow.ButtonState.Disabled}, {"deleteButton",MainWindow.ButtonState.Disabled },
+                {"undoButton", MainWindow.ButtonState.Disabled },{"redoButton",  MainWindow.ButtonState.Disabled}};
 
-            if (imageLoaded)
+            if (canvasActive)
             {
                 if (inDrawingMode)
                 {
-                    dict["drawButton"] = Form1.ButtonState.Active;
-                    dict["deleteButton"] = Form1.ButtonState.Enabled;
+                    dict["drawButton"] = MainWindow.ButtonState.Active;
+                    dict["deleteButton"] = MainWindow.ButtonState.Enabled;
                 }
                 else
                 {
-                    dict["drawButton"] = Form1.ButtonState.Enabled;
-                    dict["deleteButton"] = Form1.ButtonState.Active;
+                    dict["drawButton"] = MainWindow.ButtonState.Enabled;
+                    dict["deleteButton"] = MainWindow.ButtonState.Active;
                 }
-                if (canUndo){dict["undoButton"] = Form1.ButtonState.Enabled;}
-                if (canRedo){dict["redoButton"] = Form1.ButtonState.Enabled;}
+                if (canUndo) { dict["undoButton"] = MainWindow.ButtonState.Enabled; }
+                if (canRedo) { dict["redoButton"] = MainWindow.ButtonState.Enabled; }
             }
-            foreach(KeyValuePair<String, Form1.ButtonState> entry in dict)
+            foreach (KeyValuePair<String, MainWindow.ButtonState> entry in dict)
             {
                 programView.SetToolStripButtonStatus(entry.Key, entry.Value);
             }
+            programView.SetCanvasState("RightCanvas", canvasActive);
+            programView.SetCanvasState("LeftCanvas", graphicLoaded);
         }
 
-        /// <summary>
-        /// Is called by the model when the left image is changed.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        public void UpdateLeftImage(Image img)
-        {
-            programView.DisplayInLeftPictureBox(img);
-        }
-
-        /// <summary>
-        /// Is called by the model when the right image is changed.
-        /// </summary>
-        /// <param name="img">The new image.</param>
-        public void UpdateRightImage(Image img)
-        {
-            programView.DisplayInRightPictureBox(img);
-        }
 
         /// <summary>
         /// Pass-trough function to display an info message in the view.
@@ -291,10 +379,36 @@ namespace SketchAssistant
             programView.SetLastActionTakenText(msg);
         }
 
+        /// <summary>
+        /// Passes whether or not the mouse is pressed.
+        /// </summary>
+        /// <returns>Whether or not the mouse is pressed</returns>
+        public bool IsMousePressed()
+        {
+            return programView.IsMousePressed();
+        }
+
         /*************************/
         /*** HELPING FUNCTIONS ***/
         /*************************/
 
+        /// <summary>
+        /// Sets the visibility of a polyline.
+        /// </summary>
+        /// <param name="line">The polyline</param>
+        /// <param name="visible">Whether or not it should be visible.</param>
+        private void SetVisibility(Shape line, bool visible)
+        {
+            if (!visible)
+            {
+                line.Opacity = 0.00001;
+            }
+            else
+            {
+                line.Opacity = 1;
+            }
+        }
+
         /// <summary>
         /// A function that calculates the coordinates of a point on a zoomed in image.
         /// </summary>
@@ -302,11 +416,13 @@ namespace SketchAssistant
         /// <returns>The real coordinates of the mouse cursor on the image</returns>
         private Point ConvertCoordinates(Point cursorPosition)
         {
-            var rightImageDimensions = programModel.GetRightImageDimensions();
+            if (!programModel.canvasActive) { return cursorPosition; }
+            if (programModel.canvasActive && !programModel.graphicLoaded) { return cursorPosition; }
+            ImageDimension rightImageDimensions = programModel.rightImageSize;
             Point realCoordinates = new Point(0, 0);
 
-            int widthImage = rightImageDimensions.Item1;
-            int heightImage = rightImageDimensions.Item2;
+            int widthImage = rightImageDimensions.Width;
+            int heightImage = rightImageDimensions.Height;
             int widthBox = programModel.rightImageBoxWidth;
             int heightBox = programModel.rightImageBoxHeight;
 

+ 123 - 0
SketchAssistant/SketchAssistantWPF/MVP_View.cs

@@ -0,0 +1,123 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Shapes;
+
+namespace SketchAssistantWPF
+{
+    public interface MVP_View
+    {
+        /// <summary>
+        /// Updates the colour of a canvas.
+        /// </summary>
+        /// <param name="canvasName">The name of the canvas to be updated.</param>
+        /// <param name="active">Whether or not the canvas is active.</param>
+        void SetCanvasState(string canvasName, bool active);
+
+        /// <summary>
+        /// Remove the current line.
+        /// </summary>
+        void RemoveCurrLine();
+
+        /// <summary>
+        /// Display the current line.
+        /// </summary>
+        /// <param name="line">The current line to display</param>
+        void DisplayCurrLine(Polyline line);
+
+        /// <summary>
+        /// Removes all Lines from the left canvas.
+        /// </summary>
+        void RemoveAllLeftLines();
+
+        /// <summary>
+        /// Removes all lines in the right canvas.
+        /// </summary>
+        void RemoveAllRightLines();
+
+        /// <summary>
+        /// Adds another Line that will be displayed in the left display.
+        /// </summary>
+        /// <param name="newLine">The new Polyline to be added displayed.</param>
+        void AddNewLineLeft(Polyline newLine);
+
+        /// <summary>
+        /// Adds another Line that will be displayed in the right display.
+        /// </summary>
+        /// <param name="newLine">The new Polyline to be added displayed.</param>
+        void AddNewLineRight(Polyline newLine);
+
+        /// <summary>
+        /// Enables the timer of the View, which will tick the Presenter.
+        /// </summary>
+        void EnableTimer();
+
+        /// <summary>
+        /// A function that opens a file dialog and returns the filename.
+        /// </summary>
+        /// <param name="Filter">The filter that should be applied to the new Dialog.</param>
+        /// <returns>Returns the FileName and the SafeFileName if the user correctly selects a file, 
+        /// else returns a tuple with empty strigns</returns>
+        Tuple<String, String> openNewDialog(String Filter);
+
+        /// <summary>
+        /// Sets the contents of the load status indicator label.
+        /// </summary>
+        /// <param name="message">The new contents</param>
+        void SetToolStripLoadStatus(String message);
+
+        /// <summary>
+        /// Sets the contents of the last action taken indicator label.
+        /// </summary>
+        /// <param name="message">The new contents</param>
+        void SetLastActionTakenText(String message);
+
+        /// <summary>
+        /// Changes the states of a tool strip button.
+        /// </summary>
+        /// <param name="buttonName">The name of the button.</param>
+        /// <param name="state">The new state of the button.</param>
+        void SetToolStripButtonStatus(String buttonName, MainWindow.ButtonState state);
+
+        /// <summary>
+        /// shows the given info message in a popup and asks the user to aknowledge it
+        /// </summary>
+        /// <param name="message">the message to show</param>
+        void ShowInfoMessage(String message);
+
+        /// <summary>
+        /// Shows a warning box with the given message (Yes/No Buttons)and returns true if the user aknowledges it.
+        /// </summary>
+        /// <param name="message">The message of the warning.</param>
+        /// <returns>True if the user confirms (Yes), negative if he doesn't (No)</returns>
+        bool ShowWarning(String message);
+
+        /// <summary>
+        /// If the mouse is pressed or not.
+        /// </summary>
+        /// <returns>Whether or not the mouse is pressed.</returns>
+        bool IsMousePressed();
+
+        /// <summary>
+        /// Adds a point to the right canvas
+        /// </summary>
+        /// <param name="newPoint">The point</param>
+        void AddNewPointRight(Ellipse newPoint);
+
+        /// <summary>
+        /// Adds a point to the left canvas
+        /// </summary>
+        /// <param name="newPoint">The point</param>
+        void AddNewPointLeft(Ellipse newPoint);
+
+        /// <summary>
+        /// Returns the cursor position.
+        /// </summary>
+        /// <returns>The cursor Position</returns>
+        Point GetCursorPosition();
+    }
+}

+ 194 - 0
SketchAssistant/SketchAssistantWPF/MainWindow.xaml

@@ -0,0 +1,194 @@
+<Window x:Class="SketchAssistantWPF.MainWindow"
+        xmlns:local="clr-namespace:SketchAssistantWPF"
+        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
+        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+        mc:Ignorable="d"
+        Title="Sketch Assistant" Height="612" Width="914" SizeChanged="Window_SizeChanged">
+    <Grid>
+        <Grid.ColumnDefinitions>
+            <ColumnDefinition Width="auto"/>
+            <ColumnDefinition Width="auto"/>
+            <ColumnDefinition Width="170*"/>
+            <ColumnDefinition Width="55*"/>
+            <ColumnDefinition Width="225*"/>
+            <ColumnDefinition Width="5"/>
+            <ColumnDefinition Width="226*"/>
+            <ColumnDefinition Width="225*"/>
+            <ColumnDefinition Width="auto"/>
+            <ColumnDefinition Width="auto"/>
+        </Grid.ColumnDefinitions>
+        <Grid.RowDefinitions>
+            <RowDefinition Height="auto"/>
+            <RowDefinition Height="*"/>
+            <RowDefinition Height="auto"/>
+        </Grid.RowDefinitions>
+        <ToolBar x:Name="MenuToolbar" Grid.Column="0" Grid.ColumnSpan="5" Grid.Row="0" Background="LightGray">
+            <Menu Background="LightGray">
+                <MenuItem x:Name="LoadMenuButton" Header="Load">
+                    <MenuItem x:Name="ISADMenuButton" Header="Load .isad Drawing" Click="ISADMenuItem_Click"/>
+                    <MenuItem x:Name="SVGMenuButton" Header="Import SVG File" Click="SVGMenuItem_Click"/>
+                </MenuItem>
+                <MenuItem x:Name="EditMenuButton" Header="Edit">
+                    <MenuItem x:Name="CanvasMenuButton" Header="New Canvas" Click="CanvasButton_Click"/>
+                    <MenuItem x:Name="UndoMenuButton" Header="Undo" Click="UndoButton_Click"/>
+                    <MenuItem x:Name="RedoMenuButton" Header="Redo" Click="RedoButton_Click"/>
+                    <MenuItem x:Name="DebugMode" Header="Debug Input">
+                        <MenuItem x:Name="DebugOne" Header="Debug 1" Click="DebugOne_Click"/>
+                        <MenuItem x:Name="DebugTwo" Header="Debug 2" Click="DebugTwo_Click"/>
+                        <MenuItem x:Name="DebugThree" Header="Debug 3" Click="DebugThree_Click"/>
+                    </MenuItem>
+                </MenuItem>
+            </Menu>
+        </ToolBar>
+        <!-- All Icons in the Toolbar taken from openclipart.org -->
+        <ToolBar x:Name="DrawingToolBar" Grid.Column="6" Grid.Row="0" Grid.ColumnSpan="2" Background="LightGray">
+            <Button x:Name="CanvasButton" ToolTip="Create a new Canvas" Click="CanvasButton_Click">
+                <Rectangle Width="30" Height="30">
+                    <Rectangle.Fill>
+                        <DrawingBrush>
+                            <DrawingBrush.Drawing>
+                                <DrawingGroup ClipGeometry="M0,0 V60 H60 V0 H0 Z">
+                                    <DrawingGroup Transform="1.0513,0,0,1.0513,-1.5376,-1.5376">
+                                        <GeometryDrawing Geometry="F1 M60,60z M0,0z M11.75,54.375L11.75,5.625 39.438,5.625 48.25,14.438 48.25,54.375 11.75,54.375z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FFFFFFFF" Thickness="7.1343" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                        <GeometryDrawing Brush="#FFFFFFFF" Geometry="F1 M60,60z M0,0z M11.75,54.375L11.75,5.625 39.438,5.625 48.25,14.438 48.25,54.375 11.75,54.375z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FF000000" Thickness="2.3781" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                        <GeometryDrawing Brush="#FF000000" Geometry="F1 M60,60z M0,0z M39.437,14.438L39.437,5.625 48.25,14.438 39.437,14.438z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FF000000" Thickness="2.3781" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                    </DrawingGroup>
+                                </DrawingGroup>
+                            </DrawingBrush.Drawing>
+                        </DrawingBrush>
+                    </Rectangle.Fill>
+                </Rectangle>
+            </Button>
+            <ToggleButton x:Name="DrawButton" ToolTip="Enter Drawing Mode" Click="DrawButton_Click">
+                <Rectangle Width="30" Height="30">
+                    <Rectangle.Fill>
+                        <DrawingBrush>
+                            <DrawingBrush.Drawing>
+                                <DrawingGroup ClipGeometry="M0,0 V100 H100 V0 H0 Z">
+                                    <GeometryDrawing Brush="#FF000000" Geometry="F1 M100,100z M0,0z M69.172,11.265C68.981,11.073,68.67,11.073,68.477,11.265L11.639,68.029C11.447,68.22,11.447,68.53,11.639,68.721L30.846,87.905C30.942,88 31.068,88.048 31.194,88.048 31.319,88.048 31.445,88 31.541,87.905L88.38,31.14C88.473,31.048 88.525,30.924 88.525,30.793 88.525,30.662 88.473,30.538 88.38,30.446L69.172,11.265z" />
+                                    <GeometryDrawing Brush="#FF000000" Geometry="F1 M100,100z M0,0z M96.846,9.12L90.527,2.809C88.713,0.997999999999999 86.301,-8.88178419700125E-16 83.735,-8.88178419700125E-16 81.171,-8.88178419700125E-16 78.758,0.997999999999999 76.945,2.809L70.626,9.12C70.533,9.212 70.481,9.336 70.481,9.467 70.481,9.597 70.533,9.721 70.626,9.813L89.833,28.995C89.925,29.087 90.051,29.139 90.181,29.139 90.312,29.139 90.436,29.087 90.527,28.995L96.846,22.684C98.66,20.872 99.659,18.464 99.659,15.901 99.659,13.34 98.66,10.932 96.846,9.12z" />
+                                    <GeometryDrawing Brush="#FF000000" Geometry="F1 M100,100z M0,0z M10.358,69.967C10.236,69.846 10.062,69.795 9.894,69.838 9.727,69.878 9.594,70.003 9.543,70.168L0.363,99.363C0.308,99.541 0.357,99.732 0.49,99.861 0.584,99.952 0.707,100 0.832,100 0.886,100 0.942,99.989 0.996,99.971L29.383,89.959C29.542,89.903 29.661,89.771 29.698,89.605 29.735,89.441 29.686,89.268 29.566,89.15L10.358,69.967z" />
+                                </DrawingGroup>
+                            </DrawingBrush.Drawing>
+                        </DrawingBrush>
+                    </Rectangle.Fill>
+                </Rectangle>
+            </ToggleButton>
+            <ToggleButton x:Name="DeleteButton" ToolTip="Enter Deletion Mode" Click="DeleteButton_Click">
+                <Rectangle Width="30" Height="30">
+                    <Rectangle.Fill>
+                        <DrawingBrush>
+                            <DrawingBrush.Drawing>
+                                <DrawingGroup ClipGeometry="M0,0 V60 H60 V0 H0 Z">
+                                    <DrawingGroup>
+                                        <GeometryDrawing Geometry="F1 M60,60z M0,0z M41.312,11.031L6.438,32.5C5.407,33.151,4.6875,34.249,4.6875,35.562L4.6875,45.281C4.6875,47.32,6.3367,48.969,8.375,48.969L24.656,48.969C25.444,48.969,26.121,48.669,26.719,48.25L54.312,26.719 55.312,11.094 41.312,11.031z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FFFFFFFF" Thickness="8.125" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                        <DrawingGroup Transform="0.99664,0,0,0.99664,-0.3563,-0.39594">
+                                            <GeometryDrawing Brush="#FF000000" Geometry="F0 M60,60z M0,0z M27.173,48.89L54.852,27.221 55.857,11.533 27.522,33.19 27.173,48.89z">
+                                                <GeometryDrawing.Pen>
+                                                    <Pen Brush="#FF000000" Thickness="3.1356" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                                </GeometryDrawing.Pen>
+                                            </GeometryDrawing>
+                                            <GeometryDrawing Brush="#FFFFFFFF" Geometry="F0 M60,60z M0,0z M6.6373,32.995L41.8073,11.464 55.8573,11.533 27.5223,33.19 6.63729999999999,32.995z">
+                                                <GeometryDrawing.Pen>
+                                                    <Pen Brush="#FF000000" Thickness="3.1356" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                                </GeometryDrawing.Pen>
+                                            </GeometryDrawing>
+                                            <GeometryDrawing>
+                                                <GeometryDrawing.Brush>
+                                                    <SolidColorBrush Color="#FFFFFFFF" Opacity="1" Transform="1.8458,0,0,1.8458,-121.06,-6.2579" />
+                                                </GeometryDrawing.Brush>
+                                                <GeometryDrawing.Pen>
+                                                    <Pen Brush="#FF000000" Thickness="1.6987" StartLineCap="Flat" EndLineCap="Flat" LineJoin="Round" />
+                                                </GeometryDrawing.Pen>
+                                                <GeometryDrawing.Geometry>
+                                                    <PathGeometry FillRule="EvenOdd" Transform="1.8458,0,0,1.8458,-121.06,-6.2579" Figures="M60,60z M0,0z M70.328,20.937C69.22,20.937,68.328,21.829,68.328,22.937L68.328,28.226C68.328,29.334,69.22,30.226,70.328,30.226L79.18,30.226C80.288,30.226,81.18,29.334,81.18,28.226L81.18,22.937C81.18,21.829,80.288,20.937,79.18,20.937L70.328,20.937z" />
+                                                </GeometryDrawing.Geometry>
+                                            </GeometryDrawing>
+                                        </DrawingGroup>
+                                    </DrawingGroup>
+                                </DrawingGroup>
+                            </DrawingBrush.Drawing>
+                        </DrawingBrush>
+                    </Rectangle.Fill>
+                </Rectangle>
+            </ToggleButton>
+            <Button x:Name="UndoButton" ToolTip="Undo the last action" Click="UndoButton_Click">
+                <Rectangle Width="30" Height="30">
+                    <Rectangle.Fill>
+                        <DrawingBrush>
+                            <DrawingBrush.Drawing>
+                                <DrawingGroup ClipGeometry="M0,0 V60 H60 V0 H0 Z">
+                                    <GeometryDrawing Geometry="F1 M60,60z M0,0z M25.063,4.6882L9.445,20.1632 25.063,35.6012 25.063,25.9792C25.442,25.9292 25.778,25.7632 26.176,25.7632 33.176,25.7632 38.85,31.4742 38.85,38.4732 38.85,41.7872 37.521,44.7602 35.439,47.0182L43.733,55.3122C47.934,50.9322 50.555,45.0212 50.555,38.4732 50.555,25.0092 39.64,14.0592 26.176,14.0592 25.797,14.0592 25.437,14.1452 25.063,14.1672L25.063,4.68840000000001z">
+                                        <GeometryDrawing.Pen>
+                                            <Pen Brush="#FFFFFFFF" Thickness="8.125" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                        </GeometryDrawing.Pen>
+                                    </GeometryDrawing>
+                                    <GeometryDrawing Brush="#FF000000" Geometry="F0 M60,60z M0,0z M25.063,4.6882L9.445,20.1632 25.063,35.6012 25.063,25.9792C25.442,25.9292 25.778,25.7632 26.176,25.7632 33.176,25.7632 38.85,31.4742 38.85,38.4732 38.85,41.7872 37.521,44.7602 35.439,47.0182L43.733,55.3122C47.934,50.9322 50.555,45.0212 50.555,38.4732 50.555,25.0092 39.64,14.0592 26.176,14.0592 25.797,14.0592 25.437,14.1452 25.063,14.1672L25.063,4.68840000000001z">
+                                        <GeometryDrawing.Pen>
+                                            <Pen Brush="#FF000000" Thickness="3.125" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                        </GeometryDrawing.Pen>
+                                    </GeometryDrawing>
+                                </DrawingGroup>
+                            </DrawingBrush.Drawing>
+                        </DrawingBrush>
+                    </Rectangle.Fill>
+                </Rectangle>
+            </Button>
+            <Button x:Name="RedoButton" ToolTip="Redo the last undone action" Click="RedoButton_Click">
+                <Rectangle Width="30" Height="30">
+                    <Rectangle.Fill>
+                        <DrawingBrush>
+                            <DrawingBrush.Drawing>
+                                <DrawingGroup ClipGeometry="M0,0 V60 H60 V0 H0 Z">
+                                    <DrawingGroup Transform="-1,0,0,1,60,0">
+                                        <GeometryDrawing Geometry="F1 M60,60z M0,0z M25.063,4.6882L9.445,20.1632 25.063,35.6012 25.063,25.9792C25.442,25.9292 25.778,25.7632 26.176,25.7632 33.176,25.7632 38.85,31.4742 38.85,38.4732 38.85,41.7872 37.521,44.7602 35.439,47.0182L43.733,55.3122C47.934,50.9322 50.555,45.0212 50.555,38.4732 50.555,25.0092 39.64,14.0592 26.176,14.0592 25.797,14.0592 25.437,14.1452 25.063,14.1672L25.063,4.68840000000001z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FFFFFFFF" Thickness="8.125" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                        <GeometryDrawing Brush="#FF000000" Geometry="F0 M60,60z M0,0z M25.063,4.6882L9.445,20.1632 25.063,35.6012 25.063,25.9792C25.442,25.9292 25.778,25.7632 26.176,25.7632 33.176,25.7632 38.85,31.4742 38.85,38.4732 38.85,41.7872 37.521,44.7602 35.439,47.0182L43.733,55.3122C47.934,50.9322 50.555,45.0212 50.555,38.4732 50.555,25.0092 39.64,14.0592 26.176,14.0592 25.797,14.0592 25.437,14.1452 25.063,14.1672L25.063,4.68840000000001z">
+                                            <GeometryDrawing.Pen>
+                                                <Pen Brush="#FF000000" Thickness="3.125" StartLineCap="Round" EndLineCap="Round" LineJoin="Round" />
+                                            </GeometryDrawing.Pen>
+                                        </GeometryDrawing>
+                                    </DrawingGroup>
+                                </DrawingGroup>
+                            </DrawingBrush.Drawing>
+                        </DrawingBrush>
+                    </Rectangle.Fill>
+                </Rectangle>
+            </Button>
+        </ToolBar>
+        <local:CustomCanvas x:Name="LeftCanvas" Background="SlateGray" Grid.Column="2" Grid.Row="1" Height="auto" Grid.ColumnSpan="3"/>
+        <Canvas Name="CanvasSeperator" Grid.Column="5" Grid.Row="1" Background="LightGray"/>
+        <local:CustomCanvas x:Name="RightCanvas" Background="SlateGray" Grid.Column="6" Grid.Row="1" Height="auto"
+            MouseDown="RightCanvas_MouseDown" MouseUp="RightCanvas_MouseUp" MouseMove="RightCanvas_MouseMove" Grid.ColumnSpan="2" MouseLeave="RightCanvas_MouseLeave" MouseEnter="RightCanvas_MouseEnter" TouchEnter="RightCanvas_TouchEnter" TouchLeave="RightCanvas_TouchLeave"/>
+
+
+        <DockPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="8">
+            <StatusBar DockPanel.Dock="Bottom" Name="StatusBar"  Background="LightGray">
+                <TextBox Name="LoadStatusBox" Text="nothing loaded" Background="LightGray"/>
+                <Separator/>
+                <TextBox Name="LastActionBox" Text="none" Background="LightGray"/>
+            </StatusBar>
+        </DockPanel>
+    </Grid>
+</Window>

+ 578 - 0
SketchAssistant/SketchAssistantWPF/MainWindow.xaml.cs

@@ -0,0 +1,578 @@
+using Microsoft.Win32;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using System.Timers;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Controls.Primitives;
+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 System.Windows.Threading;
+
+namespace SketchAssistantWPF
+{
+    /// <summary>
+    /// Interaction logic for MainWindow.xaml
+    /// </summary>
+    public partial class MainWindow : Window, MVP_View
+    {
+        public MainWindow()
+        {
+            bool InDebugMode = false;
+            String[] commArgs = Environment.GetCommandLineArgs();
+            InitializeComponent();
+            if (commArgs.Length > 1)
+            {
+                if (commArgs[1].Equals("-debug"))
+                {
+                    InDebugMode = true;
+                }
+            }
+            if(!InDebugMode)
+            {
+                DebugMode.Visibility = Visibility.Collapsed;
+            }
+            ProgramPresenter = new MVP_Presenter(this);
+            //  DispatcherTimer setup
+            dispatcherTimer = new DispatcherTimer(DispatcherPriority.Render);
+            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
+            dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 10);
+            ProgramPresenter.Resize(new Tuple<int, int>((int)LeftCanvas.Width, (int)LeftCanvas.Height),
+                new Tuple<int, int>((int)RightCanvas.Width, (int)RightCanvas.Height));
+        }
+
+        public enum ButtonState
+        {
+            Enabled,
+            Disabled,
+            Active
+        }
+
+        DispatcherTimer dispatcherTimer;
+        /// <summary>
+        /// Dialog to select a file.
+        /// </summary>
+        OpenFileDialog openFileDialog = new OpenFileDialog();
+        /// <summary>
+        /// All Lines in the current session
+        /// </summary>
+        List<Tuple<bool, InternalLine>> rightLineList = new List<Tuple<bool, InternalLine>>();
+        /// <summary>
+        /// Queue for the cursorPositions
+        /// </summary>
+        Queue<Point> cursorPositions = new Queue<Point>();
+        /// <summary>
+        /// The Presenter Component of the MVP-Model
+        /// </summary>
+        MVP_Presenter ProgramPresenter;
+        /// <summary>
+        /// The line currently being drawn
+        /// </summary>
+        Polyline currentLine;
+        /// <summary>
+        /// If the debug function is running.
+        /// </summary>
+        bool debugRunning = false;
+        /// <summary>
+        /// Point collections for debugging.
+        /// </summary>
+        DebugData debugDat = new DebugData();
+
+        /********************************************/
+        /*** WINDOW SPECIFIC FUNCTIONS START HERE ***/
+        /********************************************/
+
+        /// <summary>
+        /// Resize Function connected to the form resize event, will refresh the form when it is resized
+        /// </summary>
+        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
+        {
+            ProgramPresenter.Resize(new Tuple<int, int>((int)LeftCanvas.ActualWidth, (int)LeftCanvas.ActualHeight),
+                new Tuple<int, int>((int)RightCanvas.ActualWidth, (int)RightCanvas.ActualHeight));
+        }
+
+        /// <summary>
+        /// Redo an Action.
+        /// </summary>
+        private void RedoButton_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.Redo();
+        }
+
+        /// <summary>
+        /// Undo an Action.
+        /// </summary>
+        private void UndoButton_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.Undo();
+        }
+
+        /// <summary>
+        /// Changes the state of the program to deletion
+        /// </summary>
+        private void DeleteButton_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.ChangeState(false);
+        }
+
+        /// <summary>
+        /// Changes the state of the program to drawing
+        /// </summary>
+        private void DrawButton_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.ChangeState(true);
+        }
+
+        /// <summary>
+        /// Hold left mouse button to start drawing.
+        /// </summary>
+        private void RightCanvas_MouseDown(object sender, MouseButtonEventArgs e)
+        {
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
+            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);");
+        }
+
+        /// <summary>
+        /// Lift left mouse button to stop drawing and add a new Line.
+        /// </summary>
+        private void RightCanvas_MouseUp(object sender, MouseButtonEventArgs e)
+        {
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
+            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);");
+        }
+
+        /// <summary>
+        /// If the mouse leaves the canvas, it is treated as if the mouse was released.
+        /// </summary>
+        private void RightCanvas_MouseLeave(object sender, MouseEventArgs e)
+        {
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
+        }
+
+        /// <summary>
+        /// If the cursor enters the canvas, it is treated as if the cursor was just pressed if the cursor is pressed.
+        /// </summary>
+        private void RightCanvas_MouseEnter(object sender, MouseEventArgs e)
+        {
+            if (IsMousePressed())
+            {
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, Mouse.GetPosition(RightCanvas));
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
+            }
+        }
+
+        /// <summary>
+        /// If the finger enters the canvas, it is treated as if the finger was just pressed if the finger is pressed.
+        /// </summary>
+        private void RightCanvas_TouchEnter(object sender, TouchEventArgs e)
+        {
+            if (IsMousePressed())
+            {
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, Mouse.GetPosition(RightCanvas));
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
+            }
+        }
+
+        /// <summary>
+        /// If the finger leaves the canvas, it is treated as if the finger was released.
+        /// </summary>
+        private void RightCanvas_TouchLeave(object sender, TouchEventArgs e)
+        {
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
+        }
+
+        /// <summary>
+        /// Get current Mouse positon within the right picture box.
+        /// </summary>
+        private void RightCanvas_MouseMove(object sender, MouseEventArgs e)
+        {
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, e.GetPosition(RightCanvas));
+            //System.Diagnostics.Debug.WriteLine("new Point(" + ((int)e.GetPosition(RightCanvas).X).ToString() + "," + ((int)e.GetPosition(RightCanvas).Y).ToString() + "), ");
+        }
+
+        /// <summary>
+        /// Button to create a new Canvas. Will create an empty image 
+        /// which is the size of the left image, if there is one.
+        /// If there is no image loaded the canvas will be the size of the right picture box
+        /// </summary>
+        private void CanvasButton_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.NewCanvas();
+        }
+
+        /// <summary>
+        /// Sends inputs to the presenter simulating drawing, used for testing and debugging.
+        /// Takes 7000ms
+        /// </summary>
+        private void DebugOne_Click(object sender, RoutedEventArgs e)
+        {
+            Debug(1);
+        }
+
+        /// <summary>
+        /// Sends inputs to the presenter simulating drawing, used for testing and debugging.
+        /// Takes 24000ms
+        /// </summary>
+        private void DebugTwo_Click(object sender, RoutedEventArgs e)
+        {
+            Debug(2);
+        }
+
+        /// <summary>
+        /// Sends inputs to the presenter simulating drawing, used for testing and debugging.
+        /// Takes 7000ms
+        /// </summary>
+        private void DebugThree_Click(object sender, RoutedEventArgs e)
+        {
+            Debug(3);
+        }
+
+        /// <summary>
+        /// Ticks the Presenter.
+        /// </summary>
+        private void dispatcherTimer_Tick(object sender, EventArgs e)
+        {
+            ProgramPresenter.Tick();
+            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.Tick();");
+        }
+
+        /// <summary>
+        /// Import button for .isad drawing, will open an OpenFileDialog
+        /// </summary>
+        private void ISADMenuItem_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.ExamplePictureToolStripMenuItemClick();
+        }
+
+        /// <summary>
+        /// Import button for .svg file, will open an OpenFileDialog
+        /// </summary>
+        private void SVGMenuItem_Click(object sender, RoutedEventArgs e)
+        {
+            ProgramPresenter.SVGToolStripMenuItemClick();
+        }
+
+        /*************************/
+        /*** PRESENTER -> VIEW ***/
+        /*************************/
+
+        /// <summary>
+        /// Returns the cursor position.
+        /// </summary>
+        /// <returns>The cursor Position</returns>
+        public Point GetCursorPosition()
+        {
+            return Mouse.GetPosition(RightCanvas);
+        }
+
+        /// <summary>
+        /// If the mouse is pressed or not.
+        /// </summary>
+        /// <returns>Whether or not the mouse is pressed.</returns>
+        public bool IsMousePressed()
+        {
+            if (!debugRunning) {
+                return (Mouse.LeftButton.Equals(MouseButtonState.Pressed) || Mouse.RightButton.Equals(MouseButtonState.Pressed)); }
+            else return true;
+        }
+
+        /// <summary>
+        /// Remove the current line.
+        /// </summary>
+        public void RemoveCurrLine()
+        {
+            RightCanvas.Children.Remove(currentLine);
+        }
+
+        /// <summary>
+        /// Display the current line.
+        /// </summary>
+        /// <param name="line">The current line to display</param>
+        public void DisplayCurrLine(Polyline line)
+        {
+            if (RightCanvas.Children.Contains(currentLine))
+            {
+                RemoveCurrLine();
+            }
+            RightCanvas.Children.Add(line);
+            currentLine = line;
+        }
+
+        /// <summary>
+        /// Removes all Lines from the left canvas.
+        /// </summary>
+        public void RemoveAllLeftLines()
+        {
+            LeftCanvas.Children.Clear();
+        }
+
+        /// <summary>
+        /// Removes all lines in the right canvas.
+        /// </summary>
+        public void RemoveAllRightLines()
+        {
+            RightCanvas.Children.Clear();
+        }
+
+        /// <summary>
+        /// Adds another Line that will be displayed in the left display.
+        /// </summary>
+        /// <param name="newLine">The new Polyline to be added displayed.</param>
+        public void AddNewLineLeft(Polyline newLine)
+        {
+            newLine.Stroke = Brushes.Black;
+            newLine.StrokeThickness = 2;
+            LeftCanvas.Children.Add(newLine);
+        }
+
+        /// <summary>
+        /// Adds another Line that will be displayed in the right display.
+        /// </summary>
+        /// <param name="newLine">The new Polyline to be added displayed.</param>
+        public void AddNewLineRight(Polyline newLine)
+        {
+            newLine.Stroke = Brushes.Black;
+            newLine.StrokeThickness = 2;
+            RightCanvas.Children.Add(newLine);
+        }
+
+        /// <summary>
+        /// Adds a point to the right canvas
+        /// </summary>
+        /// <param name="newPoint">The point</param>
+        public void AddNewPointRight(Ellipse newPoint)
+        {
+            newPoint.Height = 3; newPoint.Width = 3;
+            newPoint.Fill = Brushes.Black;
+            RightCanvas.Children.Add(newPoint);
+        }
+
+        /// <summary>
+        /// Adds a point to the left canvas
+        /// </summary>
+        /// <param name="newPoint">The point</param>
+        public void AddNewPointLeft(Ellipse newPoint)
+        {
+            newPoint.Height = 3; newPoint.Width = 3;
+            newPoint.Fill = Brushes.Black;
+            LeftCanvas.Children.Add(newPoint);
+        }
+
+        /// <summary>
+        /// Enables the timer of the View, which will tick the Presenter.
+        /// </summary>
+        public void EnableTimer()
+        {
+            dispatcherTimer.Start();
+        }
+
+        /// <summary>
+        /// A function that opens a file dialog and returns the filename.
+        /// </summary>
+        /// <param name="Filter">The filter that should be applied to the new Dialog.</param>
+        /// <returns>Returns the FileName and the SafeFileName if the user correctly selects a file, 
+        /// else returns a tuple with empty strigns</returns>
+        public Tuple<string, string> openNewDialog(string Filter)
+        {
+            openFileDialog.Filter = Filter;
+            if (openFileDialog.ShowDialog() == true)
+            {
+                return new Tuple<string, string>(openFileDialog.FileName, openFileDialog.SafeFileName);
+            }
+            else
+            {
+                return new Tuple<string, string>("", "");
+            }
+        }
+
+        /// <summary>
+        /// Sets the contents of the last action taken indicator label.
+        /// </summary>
+        /// <param name="message">The new contents</param>
+        public void SetLastActionTakenText(string message)
+        {
+            LastActionBox.Text = message;
+        }
+
+        /// <summary>
+        /// Changes the states of a tool strip button.
+        /// </summary>
+        /// <param name="buttonName">The name of the button.</param>
+        /// <param name="state">The new state of the button.</param>
+        public void SetToolStripButtonStatus(string buttonName, MainWindow.ButtonState state)
+        {
+            ButtonBase buttonToChange;
+            bool isToggleable = false;
+            switch (buttonName)
+            {
+                case "canvasButton":
+                    buttonToChange = CanvasButton;
+                    break;
+                case "drawButton":
+                    buttonToChange = DrawButton;
+                    isToggleable = true;
+                    break;
+                case "deleteButton":
+                    buttonToChange = DeleteButton;
+                    isToggleable = true;
+                    break;
+                case "undoButton":
+                    buttonToChange = UndoButton;
+                    break;
+                case "redoButton":
+                    buttonToChange = RedoButton;
+                    break;
+                default:
+                    Console.WriteLine("Invalid Button was given to SetToolStripButton. \nMaybe you forgot to add a case?");
+                    return;
+            }
+            if (isToggleable)
+            {
+                switch (state)
+                {
+                    case ButtonState.Active:
+                        ((ToggleButton)buttonToChange).IsEnabled = true;
+                        ((ToggleButton)buttonToChange).IsChecked = true;
+                        ((ToggleButton)buttonToChange).Opacity = 1;
+                        ((ToggleButton)buttonToChange).Background = Brushes.SkyBlue;
+                        break;
+                    case ButtonState.Disabled:
+                        ((ToggleButton)buttonToChange).IsEnabled = false;
+                        ((ToggleButton)buttonToChange).IsChecked = false;
+                        ((ToggleButton)buttonToChange).Opacity = 0.5;
+                        ((ToggleButton)buttonToChange).Background = Brushes.LightGray;
+                        break;
+                    case ButtonState.Enabled:
+                        ((ToggleButton)buttonToChange).IsEnabled = true;
+                        ((ToggleButton)buttonToChange).IsChecked = false;
+                        ((ToggleButton)buttonToChange).Opacity = 1;
+                        ((ToggleButton)buttonToChange).Background = Brushes.LightGray;
+                        break;
+                }
+            }
+            else
+            {
+                switch (state)
+                {
+                    case ButtonState.Disabled:
+                        ((Button)buttonToChange).IsEnabled = false;
+                        ((Button)buttonToChange).Opacity = 0.5;
+                        break;
+                    default:
+                        ((Button)buttonToChange).IsEnabled = true;
+                        ((Button)buttonToChange).Opacity = 1;
+                        break;
+                }
+            }
+        }
+
+        /// <summary>
+        /// Sets the contents of the load status indicator label.
+        /// </summary>
+        /// <param name="message">The new contents</param>
+        public void SetToolStripLoadStatus(string message)
+        {
+            LoadStatusBox.Text = message;
+        }
+
+        /// <summary>
+        /// shows the given info message in a popup and asks the user to aknowledge it
+        /// </summary>
+        /// <param name="message">the message to show</param>
+        public void ShowInfoMessage(string message)
+        {
+            MessageBox.Show(message);
+        }
+
+        /// <summary>
+        /// Shows a warning box with the given message (Yes/No Buttons)and returns true if the user aknowledges it.
+        /// </summary>
+        /// <param name="message">The message of the warning.</param>
+        /// <returns>True if the user confirms (Yes), negative if he doesn't (No)</returns>
+        public bool ShowWarning(string message)
+        {
+            MessageBoxResult result = MessageBox.Show(message, "Warning", MessageBoxButton.YesNo, MessageBoxImage.Warning);
+            return (result.Equals(MessageBoxResult.Yes));
+        }
+
+        /// <summary>
+        /// Updates the colour of a canvas.
+        /// </summary>
+        /// <param name="canvasName">The name of the canvas to be updated.</param>
+        /// <param name="active">Whether or not the canvas is active.</param>
+        public void SetCanvasState(string canvasName, bool active)
+        {
+            Canvas canvas;
+            switch (canvasName){
+                case ("LeftCanvas"):
+                    canvas = LeftCanvas;
+                    break;
+                case ("RightCanvas"):
+                    canvas = RightCanvas;
+                    break;
+                default:
+                    throw new InvalidOperationException("Unknown canvas name, Check that the canvas passed is either LeftCanvas or RightCanvas");
+            }
+            if (active)
+            {
+                canvas.Background = Brushes.White;
+            }
+            else
+            {
+                canvas.Background = Brushes.SlateGray;
+            }
+        }
+
+        /************************/
+        /*** HELPING FUNCTION ***/
+        /************************/
+
+        /// <summary>
+        /// A function which simulates canvas input for debugging.
+        /// </summary>
+        /// <param name="option"></param>
+        private async void Debug(int option)
+        {
+            Point[] points;
+            switch (option)
+            {
+                case 1:
+                    points = debugDat.debugPoints1;
+                    break;
+                case 2:
+                    points = debugDat.debugPoints2;
+                    break;
+                default:
+                    return;
+            }
+            dispatcherTimer.Stop();
+            debugRunning = true;
+            ProgramPresenter.Tick(); await Task.Delay(10);
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, new Point(50, 50));
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down); await Task.Delay(10);
+            for (int x = 0; x < points.Length; x++)
+            {
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, points[x]);
+                await Task.Delay(1);
+                if (x % 5 == 0)
+                {
+                    ProgramPresenter.Tick();
+                    await Task.Delay(1);
+                }
+            }
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up); await Task.Delay(1);
+            debugRunning = false;
+            dispatcherTimer.Start();
+        }
+    }
+}

+ 55 - 0
SketchAssistant/SketchAssistantWPF/Properties/AssemblyInfo.cs

@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SketchAssistantWPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SketchAssistantWPF")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components.  If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
+//inside a <PropertyGroup>.  For example, if you are using US english
+//in your source files, set the <UICulture> to en-US.  Then uncomment
+//the NeutralResourceLanguage attribute below.  Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+    ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+                                     //(used if a resource is not found in the page,
+                                     // or application resource dictionaries)
+    ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+                                              //(used if a resource is not found in the page,
+                                              // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+//      Major Version
+//      Minor Version
+//      Build Number
+//      Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 20 - 28
SketchAssistant/SketchAssistant/Properties/Resources.Designer.cs → SketchAssistant/SketchAssistantWPF/Properties/Resources.Designer.cs

@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
 //     Runtime Version:4.0.30319.42000
@@ -8,10 +8,10 @@
 // </auto-generated>
 //------------------------------------------------------------------------------
 
-namespace SketchAssistant.Properties
-{
-
-
+namespace SketchAssistantWPF.Properties {
+    using System;
+    
+    
     /// <summary>
     ///   A strongly-typed resource class, for looking up localized strings, etc.
     /// </summary>
@@ -19,51 +19,43 @@ namespace SketchAssistant.Properties
     // class via a tool like ResGen or Visual Studio.
     // To add or remove a member, edit your .ResX file then rerun ResGen
     // with the /str option, or rebuild your VS project.
-    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+    [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
     [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
-    internal class Resources
-    {
-
+    internal class Resources {
+        
         private static global::System.Resources.ResourceManager resourceMan;
-
+        
         private static global::System.Globalization.CultureInfo resourceCulture;
-
+        
         [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
-        internal Resources()
-        {
+        internal Resources() {
         }
-
+        
         /// <summary>
         ///   Returns the cached ResourceManager instance used by this class.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Resources.ResourceManager ResourceManager
-        {
-            get
-            {
-                if ((resourceMan == null))
-                {
-                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SketchAssistant.Properties.Resources", typeof(Resources).Assembly);
+        internal static global::System.Resources.ResourceManager ResourceManager {
+            get {
+                if (object.ReferenceEquals(resourceMan, null)) {
+                    global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SketchAssistantWPF.Properties.Resources", typeof(Resources).Assembly);
                     resourceMan = temp;
                 }
                 return resourceMan;
             }
         }
-
+        
         /// <summary>
         ///   Overrides the current thread's CurrentUICulture property for all
         ///   resource lookups using this strongly typed resource class.
         /// </summary>
         [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
-        internal static global::System.Globalization.CultureInfo Culture
-        {
-            get
-            {
+        internal static global::System.Globalization.CultureInfo Culture {
+            get {
                 return resourceCulture;
             }
-            set
-            {
+            set {
                 resourceCulture = value;
             }
         }

+ 10 - 7
SketchAssistant/SketchAssistant/Properties/Resources.resx → SketchAssistant/SketchAssistantWPF/Properties/Resources.resx

@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8"?>
+<?xml version="1.0" encoding="utf-8"?>
 <root>
   <!-- 
     Microsoft ResX Schema 
@@ -46,7 +46,7 @@
     
     mimetype: application/x-microsoft.net.object.binary.base64
     value   : The object must be serialized with 
-            : System.Serialization.Formatters.Binary.BinaryFormatter
+            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
             : and then encoded with base64 encoding.
     
     mimetype: application/x-microsoft.net.object.soap.base64
@@ -60,6 +60,7 @@
             : and then encoded with base64 encoding.
     -->
   <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
     <xsd:element name="root" msdata:IsDataSet="true">
       <xsd:complexType>
         <xsd:choice maxOccurs="unbounded">
@@ -68,9 +69,10 @@
               <xsd:sequence>
                 <xsd:element name="value" type="xsd:string" minOccurs="0" />
               </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" />
+              <xsd:attribute name="name" use="required" type="xsd:string" />
               <xsd:attribute name="type" type="xsd:string" />
               <xsd:attribute name="mimetype" type="xsd:string" />
+              <xsd:attribute ref="xml:space" />
             </xsd:complexType>
           </xsd:element>
           <xsd:element name="assembly">
@@ -85,9 +87,10 @@
                 <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                 <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
               </xsd:sequence>
-              <xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
+              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
               <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
               <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+              <xsd:attribute ref="xml:space" />
             </xsd:complexType>
           </xsd:element>
           <xsd:element name="resheader">
@@ -109,9 +112,9 @@
     <value>2.0</value>
   </resheader>
   <resheader name="reader">
-    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
   <resheader name="writer">
-    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-</root>
+</root>

+ 2 - 2
SketchAssistant/SketchAssistant/Properties/Settings.Designer.cs → SketchAssistant/SketchAssistantWPF/Properties/Settings.Designer.cs

@@ -1,4 +1,4 @@
-//------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 // <auto-generated>
 //     This code was generated by a tool.
 //     Runtime Version:4.0.30319.42000
@@ -8,7 +8,7 @@
 // </auto-generated>
 //------------------------------------------------------------------------------
 
-namespace SketchAssistant.Properties
+namespace SketchAssistantWPF.Properties
 {
 
 

+ 7 - 0
SketchAssistant/SketchAssistantWPF/Properties/Settings.settings

@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8'?>
+<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
+  <Profiles>
+    <Profile Name="(Default)" />
+  </Profiles>
+  <Settings />
+</SettingsFile>

+ 1 - 1
SketchAssistant/SketchAssistant/SketchAction.cs → SketchAssistant/SketchAssistantWPF/SketchAction.cs

@@ -4,7 +4,7 @@ using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
 
-namespace SketchAssistant
+namespace SketchAssistantWPF
 {
     public class SketchAction
     {

+ 55 - 46
SketchAssistant/SketchAssistant/SketchAssistant.csproj → SketchAssistant/SketchAssistantWPF/SketchAssistantWPF.csproj

@@ -4,13 +4,18 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{0336F628-A2F7-4170-8B2E-9277C23118D4}</ProjectGuid>
+    <ProjectGuid>{EE53AE79-2AA0-4F43-9638-1789B189D5C3}</ProjectGuid>
     <OutputType>WinExe</OutputType>
-    <RootNamespace>SketchAssistant</RootNamespace>
-    <AssemblyName>SketchAssistant</AssemblyName>
+    <RootNamespace>SketchAssistantWPF</RootNamespace>
+    <AssemblyName>SketchAssistantWPF</AssemblyName>
     <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
+    <ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+    <WarningLevel>4</WarningLevel>
     <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
+    <Deterministic>true</Deterministic>
+    <NuGetPackageImportStamp>
+    </NuGetPackageImportStamp>
     <PublishUrl>publish\</PublishUrl>
     <Install>true</Install>
     <InstallFrom>Disk</InstallFrom>
@@ -26,8 +31,6 @@
     <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
-    <NuGetPackageImportStamp>
-    </NuGetPackageImportStamp>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
     <PlatformTarget>AnyCPU</PlatformTarget>
@@ -50,70 +53,76 @@
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
-    <Reference Include="System.Configuration" />
+    <Reference Include="System.Data" />
+    <Reference Include="System.Drawing" />
+    <Reference Include="System.Xml" />
+    <Reference Include="Microsoft.CSharp" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
-    </Reference>
-    <Reference Include="System.Threading.Tasks.Extensions, Version=4.2.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll</HintPath>
-    </Reference>
     <Reference Include="System.Xml.Linq" />
     <Reference Include="System.Data.DataSetExtensions" />
-    <Reference Include="Microsoft.CSharp" />
-    <Reference Include="System.Data" />
-    <Reference Include="System.Deployment" />
-    <Reference Include="System.Drawing" />
     <Reference Include="System.Net.Http" />
-    <Reference Include="System.Windows.Forms" />
-    <Reference Include="System.Xml" />
+    <Reference Include="System.Xaml">
+      <RequiredTargetFramework>4.0</RequiredTargetFramework>
+    </Reference>
+    <Reference Include="WindowsBase" />
+    <Reference Include="PresentationCore" />
+    <Reference Include="PresentationFramework" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="MVP_View.cs" />
-    <Compile Include="MVP_Presenter.cs" />
-    <Compile Include="MVP_Model.cs" />
-    <Compile Include="RedrawAssistant.cs" />
+    <ApplicationDefinition Include="App.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </ApplicationDefinition>
+    <Compile Include="ActionHistory.cs" />
+    <Compile Include="CustomCanvas.cs" />
+    <Compile Include="DebugData.cs" />
     <Compile Include="FileImporter.cs" />
     <Compile Include="FileImporterException.cs" />
     <Compile Include="GeometryCalculator.cs" />
+    <Compile Include="ImageDimension.cs" />
     <Compile Include="SketchAction.cs" />
-    <Compile Include="ActionHistory.cs" />
-    <Compile Include="Line.cs" />
-    <Compile Include="Form1.cs">
-      <SubType>Form</SubType>
+    <Page Include="MainWindow.xaml">
+      <Generator>MSBuild:Compile</Generator>
+      <SubType>Designer</SubType>
+    </Page>
+    <Compile Include="App.xaml.cs">
+      <DependentUpon>App.xaml</DependentUpon>
+      <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Form1.Designer.cs">
-      <DependentUpon>Form1.cs</DependentUpon>
+    <Compile Include="InternalLine.cs" />
+    <Compile Include="MainWindow.xaml.cs">
+      <DependentUpon>MainWindow.xaml</DependentUpon>
+      <SubType>Code</SubType>
+    </Compile>
+  </ItemGroup>
+  <ItemGroup>
+    <Compile Include="MVP_Model.cs" />
+    <Compile Include="MVP_Presenter.cs" />
+    <Compile Include="MVP_View.cs" />
+    <Compile Include="Properties\AssemblyInfo.cs">
+      <SubType>Code</SubType>
     </Compile>
-    <Compile Include="Program.cs" />
-    <Compile Include="Properties\AssemblyInfo.cs" />
-    <EmbeddedResource Include="Form1.resx">
-      <DependentUpon>Form1.cs</DependentUpon>
-    </EmbeddedResource>
-    <EmbeddedResource Include="Properties\Resources.resx">
-      <Generator>ResXFileCodeGenerator</Generator>
-      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
-      <SubType>Designer</SubType>
-    </EmbeddedResource>
     <Compile Include="Properties\Resources.Designer.cs">
       <AutoGen>True</AutoGen>
+      <DesignTime>True</DesignTime>
       <DependentUpon>Resources.resx</DependentUpon>
     </Compile>
-    <None Include="packages.config" />
-    <None Include="Properties\Settings.settings">
-      <Generator>SettingsSingleFileGenerator</Generator>
-      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
-    </None>
     <Compile Include="Properties\Settings.Designer.cs">
       <AutoGen>True</AutoGen>
       <DependentUpon>Settings.settings</DependentUpon>
       <DesignTimeSharedInput>True</DesignTimeSharedInput>
     </Compile>
+    <EmbeddedResource Include="Properties\Resources.resx">
+      <Generator>ResXFileCodeGenerator</Generator>
+      <LastGenOutput>Resources.Designer.cs</LastGenOutput>
+    </EmbeddedResource>
+    <None Include="Properties\Settings.settings">
+      <Generator>SettingsSingleFileGenerator</Generator>
+      <LastGenOutput>Settings.Designer.cs</LastGenOutput>
+    </None>
   </ItemGroup>
   <ItemGroup>
-    <None Include="App.config">
-      <SubType>Designer</SubType>
-    </None>
+    <None Include="App.config" />
   </ItemGroup>
   <ItemGroup>
     <BootstrapperPackage Include=".NETFramework,Version=v4.6.1">

+ 4 - 4
SketchAssistant/SketchAssistant.Tests/Properties/AssemblyInfo.cs → SketchAssistant/WhiteTests/Properties/AssemblyInfo.cs

@@ -2,18 +2,18 @@ using System.Reflection;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 
-[assembly: AssemblyTitle("SketchAssistant.Tests")]
+[assembly: AssemblyTitle("WhiteTests")]
 [assembly: AssemblyDescription("")]
 [assembly: AssemblyConfiguration("")]
 [assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("SketchAssistant.Tests")]
-[assembly: AssemblyCopyright("Copyright ©  2018")]
+[assembly: AssemblyProduct("WhiteTests")]
+[assembly: AssemblyCopyright("Copyright ©  2019")]
 [assembly: AssemblyTrademark("")]
 [assembly: AssemblyCulture("")]
 
 [assembly: ComVisible(false)]
 
-[assembly: Guid("7dcdc31a-8291-4b05-93d6-dcc5de27a4a0")]
+[assembly: Guid("eb09c624-91f2-465f-825b-559bf7a7d5cb")]
 
 // [assembly: AssemblyVersion("1.0.*")]
 [assembly: AssemblyVersion("1.0.0.0")]

+ 312 - 0
SketchAssistant/WhiteTests/UITest.cs

@@ -0,0 +1,312 @@
+using System;
+using System.IO;
+using System.Reflection;
+using Microsoft.VisualStudio.TestTools.UnitTesting;
+using TestStack.White;
+using TestStack.White.UIItems;
+using TestStack.White.UIItems.WindowItems;
+using TestStack.White.UIItems.Finders;
+using System.Threading;
+using SketchAssistantWPF;
+using System.Windows;
+using System.Diagnostics;
+using TestStack.White.UIItems.WindowStripControls;
+using TestStack.White.UIItems.MenuItems;
+using System.Collections.Generic;
+
+namespace WhiteTests
+{
+    [TestClass]
+    public class UITest
+    {
+        private TestStack.White.Application application;
+
+        public Window setupapp()
+        {
+            string outputDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+            string editedDir = outputDir.Replace("WhiteTests", "SketchAssistantWPF");
+            string app_path = editedDir + @"\SketchAssistantWPF.exe";
+            ProcessStartInfo processStart = new ProcessStartInfo(app_path, "-debug");
+            application = Application.Launch(processStart);
+            return application.GetWindow("Sketch Assistant");
+        }
+
+        [TestMethod]
+        public void CreateCanvasTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        public void DrawLineTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugOne")).Click();
+            Thread.Sleep(7000);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        /*[TestMethod]
+         public void DeleteLineTest()
+         {
+             Window mainWindow = setupapp();
+             Thread.Sleep(20);
+             Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+             mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+             Thread.Sleep(20);
+             Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+             Thread.Sleep(20);
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+             Thread.Sleep(20);
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugOne")).Click();
+             Thread.Sleep(7000);
+             Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+             Thread.Sleep(20);
+             mainWindow.Get<Button>(SearchCriteria.ByAutomationId("DeleteButton")).Click();
+             Thread.Sleep(20);
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+             Thread.Sleep(20);
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+             Thread.Sleep(20);
+             mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugThree")).Click();
+             Thread.Sleep(24000);
+             Assert.AreEqual("Last Action: Line number 0 was deleted", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+             mainWindow.Close();
+         }*/
+
+        [TestMethod]
+        public void UndoTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugOne")).Click();
+            Thread.Sleep(7000);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("UndoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        public void RedoTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugOne")).Click();
+            Thread.Sleep(7000);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("UndoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("RedoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+    }
+
+    [TestClass]
+    [DeploymentItem(@"WhiteTests\test_input_files\")]
+    public class FileImporterTests
+    {
+
+        /// <summary>
+        /// instance of TestContext to be able to access deployed files
+        /// </summary>
+        private TestContext testContextInstance;
+        /// <summary>
+        ///Gets or sets the test context which provides
+        ///information about and functionality for the current test run.
+        ///</summary>
+        public TestContext TestContext
+        {
+            get
+            {
+                return testContextInstance;
+            }
+            set
+            {
+                testContextInstance = value;
+            }
+        }
+
+        /// <summary>
+        /// creates a valid .isad file from the given sets of coordinates (number divisible by 3) by creating a line for every three consecutive points, parses the file and verifies that all lines and their points have been parsed correctly
+        /// </summary>
+        /// <param name="xCoordinates">an array containing the x coordinates of the points that will be created (length divisible by 3)</param>
+        /// <param name="yCoordinates">an array containing the y coordinates of the points that will be created (length divisible by 3)</param>
+        [DataTestMethod]
+        [DataRow(new int[] { 54, 43, 57, 11, 145, 34, 113, 299, 0 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 })]
+        [DataRow(new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 })]
+        [DataRow(new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 54, 43, 57, 11, 145, 34, 113, 199, 0 })]
+        public void ParseISADInputSuccessfulTest(int[] xCoordinates, int[] yCoordinates)
+        {
+            FileImporter uut = new FileImporter();
+
+            List<String> file = new List<string>();
+            file.Add("drawing");
+            file.Add("300x200");
+            for (int i = 0; i < xCoordinates.Length - 2; i += 3)
+            {
+                file.Add("line");
+                file.Add(xCoordinates[i] + ";" + yCoordinates[i]);
+                file.Add(xCoordinates[i + 1] + ";" + yCoordinates[i + 1]);
+                file.Add(xCoordinates[i + 2] + ";" + yCoordinates[i + 2]);
+                file.Add("endline");
+            }
+            file.Add("enddrawing");
+
+            Tuple<int, int, List<InternalLine>> values = uut.ParseISADInputForTesting(file.ToArray());
+
+            Assert.AreEqual(xCoordinates.Length / 3, values.Item3.Count);
+            InternalLine[] lines = values.Item3.ToArray();
+            for (int i = 0; i < xCoordinates.Length - 2; i += 3)
+            {
+                Point[] currentLine = lines[i / 3].GetPoints().ToArray();
+                Assert.AreEqual(3, currentLine.Length);
+                for (int j = 0; j < 3; j++)
+                {
+                    Assert.IsTrue(currentLine[j].X == xCoordinates[i + j] && currentLine[j].Y == yCoordinates[i + j]);
+                }
+            }
+        }
+
+        /// <summary>
+        /// parses teh given invalid .isad files and verifies that a FileImporterException is thrown, but no other exception
+        /// </summary>
+        /// <param name="file">the input file represented as an array of lines</param>
+        [DataTestMethod]
+        [DataRow(new String[] {})]
+        [DataRow(new String[] { "begindrawing", "300x300", "line", "50;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300;300", "line", "50;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "30.5x300", "line", "50;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "line", "50;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "beginline", "50;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "500;50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50x50", "100;50", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50", "100", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50;50", "line", "endline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50;50", "100;50", "stopline", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50;50", "100;50", "enddrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50;50", "100;50", "endline", "endrawing" })]
+        [DataRow(new String[] { "drawing", "300x300", "line", "50;50", "100;50", "endline" })]
+        public void ParseISADInputExceptionTest(String[] file)
+        {
+            bool correctExceptionThrown = false;
+
+            FileImporter uut = new FileImporter();
+
+            try
+            {
+                //try to initialize the left image with an invalid isad drawing
+                Tuple<int, int, List<InternalLine>> values1 = uut.ParseISADInputForTesting(file);
+            }
+            catch (FileImporterException)
+            {
+                //save the occurence of an exception
+                correctExceptionThrown = true;
+            }
+            catch (Exception e)
+            {
+                //don't set success flag
+            }
+            //check that an exception has been thrown
+            Assert.IsTrue(correctExceptionThrown);
+        }
+
+        /// <summary>
+        /// parses all whitelisted files and ensures no exceptions are thrown (parsing abortion, e.g. due to corrupted input files, are realized by throwing a FileImporterException)
+        /// </summary>
+        [TestMethod]
+        [TestCategory("FileIO")]
+        public void ParseSVGInputNoErrorForWhitelistedFilesTest()
+        {
+            FileImporter uut = new FileImporter();
+
+            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory + @"\test_input_files\whitelisted", "*.svg", SearchOption.AllDirectories);
+            
+            Assert.IsTrue(files.Length > 0);
+
+            foreach (string s in files) //parse each of the whitelisted files
+            {
+                Console.WriteLine(s);
+                bool noExceptionThrown = true;
+                try
+                {
+                    uut.ParseSVGInputFile(s, 10000, 10000);
+                }
+                catch (Exception e)
+                {
+                    noExceptionThrown = false;
+                }
+                Assert.IsTrue(noExceptionThrown);
+            }
+        }
+
+        /// <summary>
+        /// parses all blacklisted files and ensures an instance of FileIporterException is thrown for each file, but no other exceptions occur
+        /// </summary>
+        [TestMethod]
+        [TestCategory("FileIO")]
+        public void ParseSVGInputNoErrorForBlacklistedFilesTest()
+        {
+            FileImporter uut = new FileImporter();
+
+            string[] files = Directory.GetFiles(TestContext.DeploymentDirectory + @"\test_input_files\blacklisted", "*.svg", SearchOption.AllDirectories);
+            Assert.IsTrue(files.Length > 0);
+            foreach (string s in files) //parse each of the blacklisted files
+            {
+                bool correctExceptionThrown = false;
+                try
+                {
+                    uut.ParseSVGInputFile(s, 10000, 10000);
+                }
+                catch (FileImporterException e)
+                {
+                    correctExceptionThrown = true;
+                }
+                catch (Exception e)
+                {
+                }
+                Assert.IsTrue(correctExceptionThrown);
+            }
+        }
+    }
+}

+ 22 - 14
SketchAssistant/SketchAssistant.Tests/SketchAssistant.Tests.csproj → SketchAssistant/WhiteTests/WhiteTests.csproj

@@ -5,11 +5,11 @@
   <PropertyGroup>
     <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
     <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
-    <ProjectGuid>{7DCDC31A-8291-4B05-93D6-DCC5DE27A4A0}</ProjectGuid>
+    <ProjectGuid>{EB09C624-91F2-465F-825B-559BF7A7D5CB}</ProjectGuid>
     <OutputType>Library</OutputType>
     <AppDesignerFolder>Properties</AppDesignerFolder>
-    <RootNamespace>SketchAssistant.Tests</RootNamespace>
-    <AssemblyName>SketchAssistant.Tests</AssemblyName>
+    <RootNamespace>WhiteTests</RootNamespace>
+    <AssemblyName>WhiteTests</AssemblyName>
     <TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
     <FileAlignment>512</FileAlignment>
     <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
@@ -39,6 +39,9 @@
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
   <ItemGroup>
+    <Reference Include="Castle.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=407dd0808d44fbdc, processorArchitecture=MSIL">
+      <HintPath>..\packages\Castle.Core.4.3.1\lib\net45\Castle.Core.dll</HintPath>
+    </Reference>
     <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll</HintPath>
     </Reference>
@@ -46,15 +49,15 @@
       <HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
     </Reference>
     <Reference Include="System" />
+    <Reference Include="System.Configuration" />
     <Reference Include="System.Core" />
-    <Reference Include="System.Drawing" />
-    <Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
-      <HintPath>..\packages\System.ValueTuple.4.5.0\lib\net461\System.ValueTuple.dll</HintPath>
+    <Reference Include="TestStack.White, Version=0.13.0.0, Culture=neutral, PublicKeyToken=2672efbf3e161801, processorArchitecture=MSIL">
+      <HintPath>..\packages\TestStack.White.0.13.3\lib\net40\TestStack.White.dll</HintPath>
     </Reference>
-    <Reference Include="System.Windows.Forms" />
+    <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
-    <Compile Include="UnitTest1.cs" />
+    <Compile Include="UITest.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
   </ItemGroup>
   <ItemGroup>
@@ -62,15 +65,19 @@
     <None Include="packages.config" />
   </ItemGroup>
   <ItemGroup>
-    <ProjectReference Include="..\SketchAssistant\SketchAssistant.csproj">
-      <Project>{0336f628-a2f7-4170-8b2e-9277c23118d4}</Project>
-      <Name>SketchAssistant</Name>
+    <ProjectReference Include="..\SketchAssistantWPF\SketchAssistantWPF.csproj">
+      <Project>{ee53ae79-2aa0-4f43-9638-1789b189d5c3}</Project>
+      <Name>SketchAssistantWPF</Name>
     </ProjectReference>
   </ItemGroup>
+  <ItemGroup />
   <ItemGroup>
-    <Folder Include="test_input_files\blacklisted\" />
-  </ItemGroup>
-  <ItemGroup>
+    <Content Include="test_input_files\blacklisted\all_no_size_def_in_header.svg">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
+    <Content Include="test_input_files\blacklisted\all_unclosed.svg">
+      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+    </Content>
     <Content Include="test_input_files\whitelisted\all.svg">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
@@ -92,6 +99,7 @@
     <Content Include="test_input_files\whitelisted\rect.svg">
       <CopyToOutputDirectory>Always</CopyToOutputDirectory>
     </Content>
+    <None Include="test.runsettings" />
   </ItemGroup>
   <Import Project="$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets" Condition="Exists('$(VSToolsPath)\TeamTest\Microsoft.TestTools.targets')" />
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

+ 2 - 2
SketchAssistant/SketchAssistant.Tests/app.config → SketchAssistant/WhiteTests/app.config

@@ -3,8 +3,8 @@
   <runtime>
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
       <dependentAssembly>
-        <assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
-        <bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
+        <assemblyIdentity name="Castle.Core" publicKeyToken="407dd0808d44fbdc" culture="neutral" />
+        <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
       </dependentAssembly>
     </assemblyBinding>
   </runtime>

+ 2 - 1
SketchAssistant/SketchAssistant.Tests/packages.config → SketchAssistant/WhiteTests/packages.config

@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
+  <package id="Castle.Core" version="4.3.1" targetFramework="net461" />
   <package id="MSTest.TestAdapter" version="1.4.0" targetFramework="net461" />
   <package id="MSTest.TestFramework" version="1.4.0" targetFramework="net461" />
-  <package id="System.ValueTuple" version="4.5.0" targetFramework="net461" />
+  <package id="TestStack.White" version="0.13.3" targetFramework="net461" />
 </packages>

+ 10 - 0
SketchAssistant/WhiteTests/test.runsettings

@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8" ?>
+<RunSettings>
+  <!-- MSTest adapter -->
+  <MSTest>
+    <MapInconclusiveToFailed>True</MapInconclusiveToFailed>
+    <DeleteDeploymentDirectoryAfterTestRunIsComplete>False</DeleteDeploymentDirectoryAfterTestRunIsComplete>
+    <DeploymentEnabled>False</DeploymentEnabled>
+  </MSTest>
+
+</RunSettings>

+ 30 - 0
SketchAssistant/WhiteTests/test_input_files/blacklisted/all_no_size_def_in_header.svg

@@ -0,0 +1,30 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg>
+  <polygon points="220,10 300,210 170,250 123,234" style="fill:lime;stroke:purple;stroke-width:1" />
+  <polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
+  style="fill:none;stroke:black;stroke-width:3" />
+    <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
+  <rect x="50" y="20" width="150" height="150"
+  style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
+  <rect x="352.324" y="311.765" fill="#5486F7" width="4" height="128"/>
+  <rect x="478.871" y="266.351" fill="#FFFFFF" width="12" height="12"/>
+  <ellipse cx="250" cy="250" rx="100" ry="50"
+  style="fill:yellow;stroke:purple;stroke-width:2" />
+  <ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple" />
+  <ellipse cx="220" cy="70" rx="190" ry="20" style="fill:lime" />
+  <ellipse cx="210" cy="45" rx="170" ry="15" style="fill:yellow" />
+  <path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path id="lineBC" d="M 250 50 l 150 300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path d="M 175 200 l 150 0" stroke="green" stroke-width="3"
+  fill="none" />
+  <path d="M 100 350 q 150 -300 300 0" stroke="blue"
+  stroke-width="5" fill="none" />
+</svg>

+ 29 - 0
SketchAssistant/WhiteTests/test_input_files/blacklisted/all_unclosed.svg

@@ -0,0 +1,29 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <polygon points="220,10 300,210 170,250 123,234" style="fill:lime;stroke:purple;stroke-width:1" />
+  <polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
+  style="fill:none;stroke:black;stroke-width:3" />
+    <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
+  <rect x="50" y="20" width="150" height="150"
+  style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
+  <rect x="352.324" y="311.765" fill="#5486F7" width="4" height="128"/>
+  <rect x="478.871" y="266.351" fill="#FFFFFF" width="12" height="12"/>
+  <ellipse cx="250" cy="250" rx="100" ry="50"
+  style="fill:yellow;stroke:purple;stroke-width:2" />
+  <ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple" />
+  <ellipse cx="220" cy="70" rx="190" ry="20" style="fill:lime" />
+  <ellipse cx="210" cy="45" rx="170" ry="15" style="fill:yellow" />
+  <path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path id="lineBC" d="M 250 50 l 150 300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path d="M 175 200 l 150 0" stroke="green" stroke-width="3"
+  fill="none" />
+  <path d="M 100 350 q 150 -300 300 0" stroke="blue"
+  stroke-width="5" fill="none" />

+ 30 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/all.svg

@@ -0,0 +1,30 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <polygon points="220,10 300,210 170,250 123,234" style="fill:lime;stroke:purple;stroke-width:1" />
+  <polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
+  style="fill:none;stroke:black;stroke-width:3" />
+    <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
+  <rect x="50" y="20" width="150" height="150"
+  style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
+  <rect x="352.324" y="311.765" fill="#5486F7" width="4" height="128"/>
+  <rect x="478.871" y="266.351" fill="#FFFFFF" width="12" height="12"/>
+  <ellipse cx="250" cy="250" rx="100" ry="50"
+  style="fill:yellow;stroke:purple;stroke-width:2" />
+  <ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple" />
+  <ellipse cx="220" cy="70" rx="190" ry="20" style="fill:lime" />
+  <ellipse cx="210" cy="45" rx="170" ry="15" style="fill:yellow" />
+  <path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path id="lineBC" d="M 250 50 l 150 300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path d="M 175 200 l 150 0" stroke="green" stroke-width="3"
+  fill="none" />
+  <path d="M 100 350 q 150 -300 300 0" stroke="blue"
+  stroke-width="5" fill="none" />
+</svg>

+ 14 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/circle_ellipse.svg

@@ -0,0 +1,14 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="5000" width="5000">
+  <ellipse cx="2500" cy="2500" rx="1000" ry="500"
+  style="fill:yellow;stroke:purple;stroke-width:2" />
+  <ellipse cx="2400" cy="1000" rx="2200" ry="300" style="fill:purple" />
+  <ellipse cx="2200" cy="700" rx="1900" ry="200" style="fill:lime" />
+  <ellipse cx="2100" cy="450" rx="1700" ry="150" style="fill:yellow" />
+</svg>

+ 10 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/line.svg

@@ -0,0 +1,10 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <line x1="0" y1="0" x2="200" y2="200" style="stroke:rgb(255,0,0);stroke-width:2" />
+</svg>

+ 21 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/path.svg

@@ -0,0 +1,21 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="600" width="1200">
+  <path id="lineAB" d="M 100 350 l 150 -300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path id="lineBC" d="M 250 50 l 150 300" stroke="red"
+  stroke-width="3" fill="none" />
+  <path d="M 100 350 q 150 -300 300 0 z M 175 200 l 150 0" stroke="blue"
+  stroke-width="5" fill="none" />
+  <path d="M 100 100 a 60 60 0 0 0 100 0 Z"
+      fill="yellow" stroke="blue" stroke-width="5" />
+  <path d="M 100 200 a 150 120 45 1 0 100 100"
+      fill="yellow" stroke="blue" stroke-width="5" />
+  <path d="M200,300 Q400,50 600,300 T1000,300"
+        fill="none" stroke="red" stroke-width="5"  />
+</svg>

+ 10 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/polygon.svg

@@ -0,0 +1,10 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <polygon points="220,10 300,210 170,250 123,234" style="fill:lime;stroke:purple;stroke-width:1" />
+</svg>

+ 11 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/polyline.svg

@@ -0,0 +1,11 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <polyline points="20,20 40,25 60,40 80,120 120,140 200,180"
+  style="fill:none;stroke:black;stroke-width:3" />
+</svg>

+ 13 - 0
SketchAssistant/WhiteTests/test_input_files/whitelisted/rect.svg

@@ -0,0 +1,13 @@
+fsfwefafaefcSC
+F
+S
+FSFewFAHBfAg
+<DSFVSF>
+<GSG FS02MAFfm="Fmseikf" />
+source: https://www.w3schools.com/
+<svg height="500" width="500">
+  <rect x="50" y="20" width="150" height="150"
+  style="fill:blue;stroke:pink;stroke-width:5;fill-opacity:0.1;stroke-opacity:0.9" />
+  <rect x="352.324" y="311.765" fill="#5486F7" width="4" height="128"/>
+  <rect x="478.871" y="266.351" fill="#FFFFFF" width="12" height="12"/>
+</svg>

+ 13 - 0
userstory16.md

@@ -0,0 +1,13 @@
+# Userstory 16  
+ 
+|**ID**|16|  
+|-|-|
+|**Name**|Änderung der Nutzeroberfläche & wpf|
+|**Beschreibung**|Die Nutzeroberfläche wird an die neuen Anforderungen des Auftraggebers angepasst.|
+|**Akzeptanzkriterium**|Die Userstory ist akzeptiert, wenn die UI eine Zeichenfläche enthält und eine Fläche zum Anzeigen von Grafiken, sowie alle vorherig verfügbare Knöpfe. Zusätzlich ist erforderlich, dass die UI statt auf WinForms auf WPF basiert. Auch sollen die Knöpfe in der Toolbar durch Symbole, statt durch Text markiert sein, und es einen Edit Button gibt in welchem zusätzlich die Funktionen vorhanden sind.|
+|Geschätzter Aufwand (Story Points)|10|
+|Entwickler|Martin Edlund|
+|Umgesetzt in Iteration|keine|
+|Tatsächlicher Aufwand (Std.)|keine|
+|Velocity (Std./Story Point)|keine|
+|Bemerkungen|Keine|

Some files were not shown because too many files changed in this diff