Bläddra i källkod

Userstory19 (#9)

* Started Userstory 19
- Cleaned up code
- Split up Program into Model, View and Presenter
- Created MVP_View interface
- Removed unneccessary code
m-edlund 5 år sedan
förälder
incheckning
7737c197f0

+ 13 - 0
Finished Userstories/userstory19.md

@@ -0,0 +1,13 @@
+# Userstory 19  
+ 
+|**ID**|19|  
+|-|-|
+|**Name**|Verbesserung der Struktur des Programms|
+|**Beschreibung**|Strukturierung des Programms zu einem Model-View-Controller Modell.|
+|**Akzeptanzkriterium**|Aufteilung der Form Datei in drei Klassen: Eine View Klasse, welche Aufgaben bezüglich Anzeigen im Form übernimmt. Eine Controller Klasse, welche Eingaben vom Form empfängt und verarbeitet. Sowie eine Model Klasse, welche den Status des Programms darstellt, und vom Controller manipuliert wird und selbst den View anpasst.|
+|Geschätzter Aufwand (Story Points)|20|
+|Entwickler|Martin Edlund|
+|Umgesetzt in Iteration|6|
+|Tatsächlicher Aufwand (Std.)|8,5|
+|Velocity (Std./Story Point)|0,425|
+|Bemerkungen|Keine|

+ 4 - 324
SketchAssistant/SketchAssistant.Tests/UnitTest1.cs

@@ -205,11 +205,10 @@ namespace Tests
     [TestClass]
     public class ActionHistoryTests
     {
-        ToolStripStatusLabel testLabel = new ToolStripStatusLabel();
 
         private ActionHistory GetActionHistory()
         {
-            return new ActionHistory(testLabel);
+            return new ActionHistory();
         }
 
         [DataTestMethod]
@@ -267,329 +266,10 @@ namespace Tests
             Assert.AreEqual(true, testHistory.CanUndo());
             testHistory.MoveAction(true);
             Assert.AreEqual(true, testHistory.CanRedo());
-            testHistory.MoveAction(false);
+            var lastActionLabel = testHistory.MoveAction(false);
             Assert.AreEqual(actionType, testHistory.GetCurrentAction().GetActionType());
-            String currLabel = testLabel.Text;
-            Assert.AreEqual(currLabel, message);
-        }
-    }
-
-    [TestClass]
-    public class FileImporterTests
-    {
-        [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)
-        {
-            Form1 program = new Form1();
-            FileImporter uut = new SketchAssistant.FileImporter(program);
-
-            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");
-
-            (int, int, List<Line>) values = uut.ParseISADInputForTesting(file.ToArray());
-            program.CreateCanvasAndSetPictureForTesting(values.Item1, values.Item2, values.Item3);
-
-            Line[] drawing = GetLeftImage(program).ToArray();
-
-            Assert.AreEqual(xCoordinates.Length / 3, drawing.Length);
-            for (int i = 0; i < xCoordinates.Length - 2; i += 3)
-            {
-                Point[] currentLine = drawing[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]);
-                }
-            }
-        }
-
-        [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 exceptionThrown = false;
-            Form1 program = new Form1();
-            FileImporter uut = new SketchAssistant.FileImporter(program);
-            //check that left image initially is uninitialized
-            Assert.IsNull(GetLeftImage(program));
-            //initialize left image with a valid isad drawing
-            (int, int, List<Line>) values = uut.ParseISADInputForTesting(new string[] { "drawing", "300x205", "line", "40;40", "140;140", "endline", "enddrawing" });
-            program.CreateCanvasAndSetPictureForTesting(values.Item1, values.Item2, values.Item3);
-            //save left image for later comparison
-            List<Line> oldLeftImage = GetLeftImage(program);
-            try
-            {
-                //try to initialize the left image with an invalid isad drawing
-                (int, int, List<Line>) values1 = uut.ParseISADInputForTesting(file);
-                program.CreateCanvasAndSetPictureForTesting(values1.Item1, values1.Item2, values1.Item3);
-            }
-            catch(FileImporterException)
-            {
-                //save the occurence of an exception
-                exceptionThrown = true;
-            }
-            //check that an exception has been thrown
-            Assert.IsTrue(exceptionThrown);
-            //check that the left image has not been changed by the failed image import
-            Assert.AreEqual(oldLeftImage, GetLeftImage(program));
-        }
-
-        /// <summary>
-        /// local helper method retrieving the left image from a Form1 instance
-        /// </summary>
-        /// <returns>the left image of the given Form1 instance</returns>
-        private List<Line> GetLeftImage(Form1 program)
-        {
-            //cast is save as long as Form1#GetAllVariables() is conform to its contract
-            return (List<Line>)program.GetAllVariables().Find(x => x.Item1.Equals("leftLineList")).Item2;
-        }
-    }
-
-    [TestClass]
-    public class RedrawAssistantTests
-    {
-        private RedrawAssistant GetAssistant(List<Line> input)
-        {
-            if(input.Count == 0)
-            {
-                return new RedrawAssistant();
-            }
-            else
-            {
-                return new RedrawAssistant(input);
-            }
-        }
-
-        [DataTestMethod]
-        [DataRow(17, 20, new int[] { 54, 43, 57, 11, 145, 34, 113, 299, 0 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, true)]
-        [DataRow(-50, 30, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, false)]
-        [DataRow(-70, -20, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 54, 43, 57, 11, 145, 34, 113, 199, 0 }, true)]
-        public void InactiveRedrawAssistantTest(int x, int y, int[] xCoords, int[] yCoords, bool lineActive)
-        {
-            RedrawAssistant testAssistant = GetAssistant(new List<Line>());
-            List<Point> testPoints = new List<Point>();
-            for (int i = 0; i < xCoords.Length; i++)
-            {
-                testPoints.Add(new Point(xCoords[i], yCoords[i]));
-            }
-            List<Tuple<bool, Line>> testLines = new List<Tuple<bool, Line>> { new Tuple<bool, Line>(lineActive, new Line(testPoints, 0)) };
-            List<HashSet<Point>> result = testAssistant.Tick(new Point(1, 1), testLines, -1, false);
-            Assert.AreEqual(0, result.Count);
-        }
-
-        [DataTestMethod]
-        [DataRow(17, 20, new int[] { 54, 43, 57, 11, 145, 34, 113, 299, 0 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, 1)]
-        [DataRow(-50, 30, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, 1)]
-        [DataRow(33, 54, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 54, 43, 57, 11, 145, 34, 113, 199, 0 }, 2)]
-        public void ActiveRedrawAssistantTestStartedDrawing(int x, int y, int[] xCoords, int[] yCoords, int resultingCount)
-        {
-            List<Point> testPoints = new List<Point>();
-            for (int i = 0; i < xCoords.Length; i++)
-            {
-                testPoints.Add(new Point(xCoords[i], yCoords[i]));
-            }
-            List<Tuple<bool, Line>> testInputLines = new List<Tuple<bool, Line>>();
-            List<Line> testRedrawLines = new List<Line> { new Line(testPoints, 0) };
-            RedrawAssistant testAssistant = GetAssistant(testRedrawLines);
-            //Setting Marker Radius to 1 so that only the functionality of the RedrawAssistant is checked 
-            //and not the functionality of the Circle algorithm.
-            testAssistant.SetMarkerRadius(1);
-            List<HashSet<Point>> tickResult = testAssistant.Tick(new Point(x, y), testInputLines, -1, false);
-
-
-            Assert.AreEqual(resultingCount, tickResult.Count);
-            if(resultingCount == 1)
-            {
-                foreach(Point p in tickResult[0])
-                {
-                    Assert.AreEqual(testPoints[0], p);
-                }
-            }
-            if(resultingCount == 2)
-            {
-                foreach (Point p in tickResult[0])
-                {
-                    Assert.AreEqual(testPoints[0], p);
-                }
-                foreach (Point p in tickResult[1])
-                {
-                    Assert.AreEqual(testPoints[testPoints.Count-1], p);
-                }
-            }
-        }
-
-        [DataTestMethod]
-        [DataRow(17, 20, new int[] { 54, 43, 57, 11, 145, 34, 113, 299, 0 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 },
-             new int[] { 77, 20, 3, 74, 28 }, new int[] { 40, 50, 20, 77, 28}, 2, false)]
-        [DataRow(33, 33, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 },
-             new int[] { 42, 140, 30, 30, 30 }, new int[] { 11, 145, 34, 113, 28 }, 2, true)]
-        [DataRow(33, 54, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 54, 43, 57, 11, 145, 34, 113, 199, 0 },
-             new int[] { 43, 57, 11, 145 }, new int[] { 33, 42, 140, 30 }, 2, true)]
-        public void ActiveRedrawAssistantTestMultipleLinesRedrawn(
-            int x, int y, int[] xCoords_one, int[] yCoords_one, int[] xCoords_two, int[] yCoords_two, int resultingCount, bool showingStartAndEnd)
-        {
-            List<Point> testPoints1 = new List<Point>();
-            for (int i = 0; i < xCoords_one.Length; i++)
-            {
-                testPoints1.Add(new Point(xCoords_one[i], yCoords_one[i]));
-            }
-            List<Point> testPoints2 = new List<Point>();
-            for (int i = 0; i < xCoords_two.Length; i++)
-            {
-                testPoints2.Add(new Point(xCoords_two[i], yCoords_two[i]));
-            }
-            List<Tuple<bool, Line>> testInputLines = new List<Tuple<bool, Line>>();
-
-            List<Line> testRedrawLines = new List<Line> { new Line(testPoints1, 0) , new Line(testPoints2, 1) };
-            RedrawAssistant testAssistant = GetAssistant(testRedrawLines);
-            //Setting Marker Radius to 1 so that only the functionality of the RedrawAssistant is checked 
-            //and not the functionality of the Circle algorithm.
-            testAssistant.SetMarkerRadius(1);
-
-            List<HashSet<Point>> tickResult = testAssistant.Tick(new Point(x, y), testInputLines, -1, false);
-
-            Assert.AreEqual(resultingCount, tickResult.Count);
-            if (showingStartAndEnd)
-            {
-                foreach (Point p in tickResult[0])
-                {
-                    Assert.AreEqual(testPoints1[0], p);
-                }
-                foreach (Point p in tickResult[1])
-                {
-                    Assert.AreEqual(testPoints1[testPoints1.Count - 1], p);
-                }
-            }
-            else
-            {
-                foreach (Point p in tickResult[0])
-                {
-                    Assert.AreEqual(testPoints1[0], p);
-                }
-                foreach (Point p in tickResult[1])
-                {
-                    Assert.AreEqual(testPoints2[0], p);
-                }
-            }
-        }
-
-        [DataTestMethod]
-        [DataRow(17, 20, 17, 20, -1 ,false, new int[] { 54, 43, 57, 11, 145, 34, 113, 299, 0 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 },
-     new int[] { 77, 20, 3, 74, 28 }, new int[] { 40, 50, 20, 77, 28 }, 2, 2, false, false)]
-
-        [DataRow(33, 33, 2, 2, 0, true, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 },
-     new int[] { 42, 140, 30, 30, 30 }, new int[] { 11, 145, 34, 113, 28 }, 2, 1, true, false)]
-
-        [DataRow(33, 54, 17, 0, 0, true, new int[] { 33, 42, 140, 30, 30, 30, 32, 145, 2 }, new int[] { 54, 43, 57, 11, 145, 34, 113, 199, 0 },
-     new int[] { 43, 57, 11, 145 }, new int[] { 33, 42, 140, 30 }, 2, 2, true, false)]
-        public void ActiveRedrawAssistantTestLineFinished(
-            int x_one, int y_one, int x_two, int y_two, int lineID, bool finishedDrawing, int[] xCoords_one, int[] yCoords_one, int[] xCoords_two, int[] yCoords_two, 
-            int count_one, int count_two, bool showingSE_one, bool showingSE_two)
-        {
-            List<Point> testPoints1 = new List<Point>();
-            for (int i = 0; i < xCoords_one.Length; i++)
-            {
-                testPoints1.Add(new Point(xCoords_one[i], yCoords_one[i]));
-            }
-            List<Point> testPoints2 = new List<Point>();
-            for (int i = 0; i < xCoords_two.Length; i++)
-            {
-                testPoints2.Add(new Point(xCoords_two[i], yCoords_two[i]));
-            }
-            List<Tuple<bool, Line>> testInputLines = new List<Tuple<bool, Line>>();
-
-            List<Line> testRedrawLines = new List<Line> { new Line(testPoints1, 0), new Line(testPoints2, 1) };
-            RedrawAssistant testAssistant = GetAssistant(testRedrawLines);
-            //Setting Marker Radius to 1 so that only the functionality of the RedrawAssistant is checked 
-            //and not the functionality of the Circle algorithm.
-            testAssistant.SetMarkerRadius(1);
-
-            List<HashSet<Point>> tickResult1 = testAssistant.Tick(new Point(x_one, y_one), testInputLines, lineID, false);
-            List<HashSet<Point>> tickResult2 = testAssistant.Tick(new Point(x_two, y_two), testInputLines, lineID, finishedDrawing);
-
-            Assert.AreEqual(count_one, tickResult1.Count);
-            if (showingSE_one)
-            {
-                foreach(Point p in tickResult1[0])
-                {
-                    Assert.AreEqual(testPoints1[0], p);
-                }
-                foreach (Point p in tickResult1[1])
-                {
-                    Assert.AreEqual(testPoints1[testPoints1.Count - 1], p);
-                }
-            }
-            else
-            {
-                foreach (Point p in tickResult1[0])
-                {
-                    Assert.AreEqual(testPoints1[0], p);
-                }
-                foreach (Point p in tickResult1[1])
-                {
-                    Assert.AreEqual(testPoints2[0], p);
-                }
-            }
-
-            Assert.AreEqual(count_two, tickResult2.Count);
-            if(count_two == 2)
-            {
-                if (showingSE_two)
-                {
-                    foreach (Point p in tickResult2[0])
-                    {
-                        Assert.AreEqual(testPoints1[0], p);
-                    }
-                    foreach (Point p in tickResult2[1])
-                    {
-                        Assert.AreEqual(testPoints1[testPoints1.Count - 1], p);
-                    }
-                }
-                else
-                {
-                    foreach (Point p in tickResult2[0])
-                    {
-                        Assert.AreEqual(testPoints1[0], p);
-                    }
-                    foreach (Point p in tickResult2[1])
-                    {
-                        Assert.AreEqual(testPoints2[0], p);
-                    }
-                }
-            }
-            if(count_two == 1)
-            {
-                foreach (Point p in tickResult2[0])
-                {
-                    Assert.AreEqual(testPoints2[0], p);
-                }
-            }
+            Assert.AreEqual(message, lastActionLabel);
         }
     }
+    
 }

+ 10 - 13
SketchAssistant/SketchAssistant/ActionHistory.cs

@@ -13,12 +13,9 @@ namespace SketchAssistant
         List<SketchAction> actionHistory;
         //The current position in the actionHistory
         Tuple<int, SketchAction> currentAction;
-        //The label in which the current action is displayed
-        ToolStripStatusLabel displayLabel;
 
-        public ActionHistory(ToolStripStatusLabel displayPosition)
+        public ActionHistory()
         {
-            displayLabel = displayPosition;
             actionHistory = new List<SketchAction>();
             currentAction = new Tuple<int, SketchAction>(-1, null);
             AddNewAction(new SketchAction(SketchAction.ActionType.Start, -1));
@@ -28,7 +25,8 @@ namespace SketchAssistant
         /// Adds a new action to the action history.
         /// </summary>
         /// <param name="newAction">The newly added action.</param>
-        public void AddNewAction(SketchAction newAction)
+        /// <returns>The message to be displayed</returns>
+        public String AddNewAction(SketchAction newAction)
         {
             //The current Action is before the last action taken, delete everything after the current action.
             if (currentAction.Item1 < actionHistory.Count - 1)
@@ -37,14 +35,15 @@ namespace SketchAssistant
             }
             actionHistory.Add(newAction);
             currentAction = new Tuple<int, SketchAction>(actionHistory.Count - 1, newAction);
-            UpdateStatusLabel();
+            return UpdateStatusLabel();
         }
 
         /// <summary>
         /// Changes the currentAction.
         /// </summary>
         /// <param name="moveBack">If True, moves the current action back one slot, if False, moves it forward.</param>
-        public void MoveAction(bool moveBack)
+        /// <returns>The message to be displayed</returns>
+        public String MoveAction(bool moveBack)
         {
             if(moveBack && CanUndo())
             {
@@ -54,7 +53,7 @@ namespace SketchAssistant
             {
                 currentAction = new Tuple<int, SketchAction>(currentAction.Item1 + 1, actionHistory[currentAction.Item1 + 1]);
             }
-            UpdateStatusLabel();
+            return UpdateStatusLabel();
         }
 
         /// <summary>
@@ -99,12 +98,10 @@ namespace SketchAssistant
         /// <summary>
         /// Updates the status label if there is one given.
         /// </summary>
-        private void UpdateStatusLabel()
+        /// <returns>The message to be displayed</returns>
+        private String UpdateStatusLabel()
         {
-            if (displayLabel != null)
-            {
-                displayLabel.Text = "Last Action: " + currentAction.Item2.GetActionInformation();
-            }
+            return "Last Action: " + currentAction.Item2.GetActionInformation();
         }
     }
 }

+ 0 - 11
SketchAssistant/SketchAssistant/FileImporter.cs

@@ -10,17 +10,6 @@ namespace SketchAssistant
 {
     public class FileImporter
     {
-
-        /// <summary>
-        /// pointer to the running instance of main program
-        /// </summary>
-        Form1 program;
-
-        public FileImporter(Form1 newProgram)
-        {
-            program = newProgram;
-        }
-
         /// <summary>
         /// parses a drawing consisting of line objects, given as a file in the application specific .isad format
         /// </summary>

+ 33 - 38
SketchAssistant/SketchAssistant/Form1.Designer.cs

@@ -36,20 +36,19 @@ namespace SketchAssistant
             this.pictureBoxLeft = new System.Windows.Forms.PictureBox();
             this.menuStrip1 = new System.Windows.Forms.MenuStrip();
             this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
-            this.loadToolStripMenuItem = 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.lastActionTakenLabel = new System.Windows.Forms.ToolStripStatusLabel();
-            this.undoButton = new System.Windows.Forms.ToolStripButton();
-            this.redoButton = new System.Windows.Forms.ToolStripButton();
             this.tableLayoutPanel1.SuspendLayout();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxRight)).BeginInit();
             ((System.ComponentModel.ISupportInitialize)(this.pictureBoxLeft)).BeginInit();
@@ -87,6 +86,7 @@ namespace SketchAssistant
             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);
@@ -117,31 +117,23 @@ namespace SketchAssistant
             // fileToolStripMenuItem
             // 
             this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
-            this.loadToolStripMenuItem,
             this.importToolStripMenuItem});
             this.fileToolStripMenuItem.Name = "fileToolStripMenuItem";
             this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20);
             this.fileToolStripMenuItem.Text = "File";
             // 
-            // loadToolStripMenuItem
-            // 
-            this.loadToolStripMenuItem.Name = "loadToolStripMenuItem";
-            this.loadToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
-            this.loadToolStripMenuItem.Text = "Load...";
-            this.loadToolStripMenuItem.Click += new System.EventHandler(this.loadToolStripMenuItem_Click);
-            // 
             // importToolStripMenuItem
             // 
             this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.examplePictureToolStripMenuItem});
             this.importToolStripMenuItem.Name = "importToolStripMenuItem";
-            this.importToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
+            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(180, 22);
+            this.examplePictureToolStripMenuItem.Size = new System.Drawing.Size(158, 22);
             this.examplePictureToolStripMenuItem.Text = "Example picture";
             this.examplePictureToolStripMenuItem.Click += new System.EventHandler(this.examplePictureToolStripMenuItem_Click);
             // 
@@ -172,6 +164,7 @@ namespace SketchAssistant
             // 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";
@@ -182,6 +175,7 @@ namespace SketchAssistant
             // 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";
@@ -189,6 +183,28 @@ namespace SketchAssistant
             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[] {
@@ -206,11 +222,6 @@ namespace SketchAssistant
             this.toolStripLoadStatus.Size = new System.Drawing.Size(40, 19);
             this.toolStripLoadStatus.Text = "no file";
             // 
-            // mouseTimer
-            // 
-            this.mouseTimer.Interval = 1;
-            this.mouseTimer.Tick += new System.EventHandler(this.mouseTimer_Tick);
-            // 
             // lastActionTakenLabel
             // 
             this.lastActionTakenLabel.BorderSides = System.Windows.Forms.ToolStripStatusLabelBorderSides.Left;
@@ -219,25 +230,10 @@ namespace SketchAssistant
             this.lastActionTakenLabel.Text = "none";
             this.lastActionTakenLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
             // 
-            // undoButton
-            // 
-            this.undoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            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
+            // mouseTimer
             // 
-            this.redoButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
-            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);
+            this.mouseTimer.Interval = 1;
+            this.mouseTimer.Tick += new System.EventHandler(this.mouseTimer_Tick);
             // 
             // Form1
             // 
@@ -278,7 +274,6 @@ namespace SketchAssistant
         private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;
         private System.Windows.Forms.MenuStrip menuStrip1;
         private System.Windows.Forms.ToolStripMenuItem fileToolStripMenuItem;
-        private System.Windows.Forms.ToolStripMenuItem loadToolStripMenuItem;
         private System.Windows.Forms.ToolStrip toolStrip1;
         private System.Windows.Forms.StatusStrip statusStrip1;
         private System.Windows.Forms.ToolStripStatusLabel toolStripLoadStatus;

+ 102 - 581
SketchAssistant/SketchAssistant/Form1.cs

@@ -9,18 +9,17 @@ 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
+    public partial class Form1 : Form, MVP_View
     {
         public Form1()
         {
             InitializeComponent();
-            fileImporter = new FileImporter(this);
+            ProgramPresenter = new MVP_Presenter(this);
         }
 
         /**********************************/
@@ -29,6 +28,13 @@ namespace SketchAssistant
 
         //important: add new variables only at the end of the list to keep the order of definition consistent with the order in which they are returned by GetAllVariables()
 
+        public enum ButtonState
+        {
+            Enabled,
+            Disabled,
+            Active
+        }
+
         /// <summary>
         /// Different Program States
         /// </summary>
@@ -39,85 +45,21 @@ namespace SketchAssistant
             Delete
         }
         /// <summary>
-        /// Current Program State
-        /// </summary>
-        private ProgramState currentState;
-        /// <summary>
-        /// instance of FileImporter to handle drawing imports
-        /// </summary>
-        private FileImporter fileImporter;
-        /// <summary>
         /// Dialog to select a file.
         /// </summary>
         OpenFileDialog openFileDialog = new OpenFileDialog();
         /// <summary>
-        /// Image loaded on the left
-        /// </summary>
-        private Image leftImage = null;
-        /// <summary>
-        /// the graphic shown in the left window, represented as a list of polylines
-        /// </summary>
-        private List<Line> leftLineList;
-        /// <summary>
-        /// Image on the right
-        /// </summary>
-        Image rightImage = null;
-        /// <summary>
-        /// Current Line being Drawn
-        /// </summary>
-        List<Point> currentLine;
-        /// <summary>
         /// All Lines in the current session
         /// </summary>
         List<Tuple<bool,Line>> rightLineList = new List<Tuple<bool, Line>>();
         /// <summary>
-        /// Whether the Mouse is currently pressed in the rightPictureBox
-        /// </summary>
-        bool mousePressed = false;
-        /// <summary>
-        /// The Position of the Cursor in the right picture box
-        /// </summary>
-        Point currentCursorPosition;
-        /// <summary>
-        /// The Previous Cursor Position in the right picture box
-        /// </summary>
-        Point previousCursorPosition;
-        /// <summary>
         /// Queue for the cursorPositions
         /// </summary>
         Queue<Point> cursorPositions = new Queue<Point>();
         /// <summary>
-        /// The graphic representation of the right image
-        /// </summary>
-        Graphics rightGraph = null;
-        /// <summary>
-        /// Lookup Matrix for checking postions of lines in the image
-        /// </summary>
-        bool[,] isFilledMatrix;
-        /// <summary>
-        /// Lookup Matrix for getting line ids at a certain postions of the image
-        /// </summary>
-        HashSet<int>[,] linesMatrix;
-        /// <summary>
-        /// Size of deletion area
-        /// </summary>
-        int deletionRadius = 2;
-        /// <summary>
-        /// History of Actions
-        /// </summary>
-        ActionHistory historyOfActions;
-        /// <summary>
-        /// List of items which will be overlayed over the right canvas.
+        /// The Presenter Component of the MVP-Model
         /// </summary>
-        List<HashSet<Point>> overlayItems;
-        /// <summary>
-        /// The assistant responsible for the redraw mode
-        /// </summary>
-        RedrawAssistant redrawAss;
-        /// <summary>
-        /// Size of areas marking endpoints of lines in the redraw mode.
-        /// </summary>
-        int markerRadius = 10;
+        MVP_Presenter ProgramPresenter;
 
         /******************************************/
         /*** FORM SPECIFIC FUNCTIONS START HERE ***/
@@ -125,11 +67,7 @@ namespace SketchAssistant
 
         private void Form1_Load(object sender, EventArgs e)
         {
-            currentState = ProgramState.Idle;
             this.DoubleBuffered = true;
-            historyOfActions = new ActionHistory(null);
-            redrawAss = new RedrawAssistant();
-            UpdateButtonStatus();
         }
 
         /// <summary>
@@ -137,23 +75,9 @@ namespace SketchAssistant
         /// </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();
-            UpdateSizes();
-        }
-        
-        //Load button, will open an OpenFileDialog
-        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
-        {
-            openFileDialog.Filter = "Image|*.jpg;*.png;*.jpeg";
-            if(openFileDialog.ShowDialog() == DialogResult.OK)
-            {
-                toolStripLoadStatus.Text = openFileDialog.SafeFileName;
-                leftImage = Image.FromFile(openFileDialog.FileName);
-                pictureBoxLeft.Image = leftImage;
-                //Refresh the left image box when the content is changed
-                this.Refresh();
-            }
-            UpdateButtonStatus();
         }
 
         /// <summary>
@@ -161,38 +85,7 @@ namespace SketchAssistant
         /// </summary>
         private void examplePictureToolStripMenuItem_Click(object sender, EventArgs e)
         {
-            if (CheckSavedStatus())
-            {
-                openFileDialog.Filter = "Interactive Sketch-Assistant Drawing|*.isad";
-                if (openFileDialog.ShowDialog() == DialogResult.OK)
-                {
-                    toolStripLoadStatus.Text = openFileDialog.SafeFileName;
-                    try
-                    {
-                        (int, int, List<Line>) values = fileImporter.ParseISADInputFile(openFileDialog.FileName);
-                        DrawEmptyCanvasLeft(values.Item1, values.Item2);
-                        BindAndDrawLeftImage(values.Item3);
-
-                        //Match The right canvas to the left
-                        historyOfActions = new ActionHistory(lastActionTakenLabel);
-                        DrawEmptyCanvasRight();
-                        isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
-                        linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
-                        rightLineList = new List<Tuple<bool, Line>>();
-                        //Start the redraw mode
-                        redrawAss = new RedrawAssistant(leftLineList);
-                        UpdateSizes();
-                        overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                        RedrawRightImage();
-                        this.Refresh();
-                    }
-                    catch (FileImporterException ex)
-                    {
-                        ShowInfoMessage(ex.ToString());
-                    }
-                }
-            }
-            UpdateButtonStatus();
+            ProgramPresenter.ExamplePictureToolStripMenuItemClick();
         }
 
         /// <summary>
@@ -200,18 +93,7 @@ namespace SketchAssistant
         /// </summary>
         private void drawButton_Click(object sender, EventArgs e)
         {
-            if(rightImage != null)
-            {
-                if (currentState.Equals(ProgramState.Draw))
-                {
-                    ChangeState(ProgramState.Idle);
-                }
-                else
-                {
-                    ChangeState(ProgramState.Draw);
-                }
-            }
-            UpdateButtonStatus();
+            ProgramPresenter.ChangeState(true);
         }
 
         /// <summary>
@@ -219,18 +101,7 @@ namespace SketchAssistant
         /// </summary>
         private void deleteButton_Click(object sender, EventArgs e)
         {
-            if (rightImage != null)
-            {
-                if (currentState.Equals(ProgramState.Delete))
-                {
-                    ChangeState(ProgramState.Idle);
-                }
-                else
-                {
-                    ChangeState(ProgramState.Delete);
-                }
-            }
-            UpdateButtonStatus();
+            ProgramPresenter.ChangeState(false);
         }
 
         /// <summary>
@@ -238,28 +109,7 @@ namespace SketchAssistant
         /// </summary>
         private void undoButton_Click(object sender, EventArgs e)
         {
-            if (historyOfActions.CanUndo())
-            {
-                HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
-                SketchAction.ActionType  undoAction = historyOfActions.GetCurrentAction().GetActionType();
-                switch (undoAction)
-                {
-                    case SketchAction.ActionType.Delete:
-                        //Deleted Lines need to be shown
-                        ChangeLines(affectedLines, true);
-                        break;
-                    case SketchAction.ActionType.Draw:
-                        //Drawn lines need to be hidden
-                        ChangeLines(affectedLines, false);
-                        break;
-                    default:
-                        break;
-                }
-                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                RedrawRightImage();
-            }
-            historyOfActions.MoveAction(true);
-            UpdateButtonStatus();
+            ProgramPresenter.Undo();
         }
 
         /// <summary>
@@ -267,28 +117,7 @@ namespace SketchAssistant
         /// </summary>
         private void redoButton_Click(object sender, EventArgs e)
         {
-            if (historyOfActions.CanRedo())
-            {
-                historyOfActions.MoveAction(false);
-                HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
-                SketchAction.ActionType redoAction = historyOfActions.GetCurrentAction().GetActionType();
-                switch (redoAction)
-                {
-                    case SketchAction.ActionType.Delete:
-                        //Deleted Lines need to be redeleted
-                        ChangeLines(affectedLines, false);
-                        break;
-                    case SketchAction.ActionType.Draw:
-                        //Drawn lines need to be redrawn
-                        ChangeLines(affectedLines, true);
-                        break;
-                    default:
-                        break;
-                }
-                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                RedrawRightImage();
-            }
-            UpdateButtonStatus();
+            ProgramPresenter.Redo();
         }
 
         /// <summary>
@@ -298,20 +127,28 @@ namespace SketchAssistant
         {
             if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
             {
-                undoButton_Click(sender, e);
+                ProgramPresenter.Undo();
             }
             if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Y)
             {
-                redoButton_Click(sender, e);
+                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)
         {
-            currentCursorPosition = ConvertCoordinates(new Point(e.X, e.Y));
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, e);
         }
         
         /// <summary>
@@ -319,11 +156,7 @@ namespace SketchAssistant
         /// </summary>
         private void pictureBoxRight_MouseDown(object sender, MouseEventArgs e)
         {
-            mousePressed = true;
-            if (currentState.Equals(ProgramState.Draw))
-            {
-                currentLine = new List<Point>();
-            }
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
         }
         
         /// <summary>
@@ -331,18 +164,7 @@ namespace SketchAssistant
         /// </summary>
         private void pictureBoxRight_MouseUp(object sender, MouseEventArgs e)
         {
-            mousePressed = false;
-            if (currentState.Equals(ProgramState.Draw) && currentLine.Count > 0)
-            {
-                Line newLine = new Line(currentLine, rightLineList.Count);
-                rightLineList.Add(new Tuple<bool, Line>(true, newLine));
-                newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
-                historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID()));
-                //Execute a RedrawAssistant tick with the currently finished Line
-                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, newLine.GetID(), true);
-                RedrawRightImage();
-            }
-            UpdateButtonStatus();
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
         }
         
         /// <summary>
@@ -352,25 +174,7 @@ namespace SketchAssistant
         /// </summary>
         private void canvasButton_Click(object sender, EventArgs e)
         {
-            if (CheckSavedStatus())
-            {
-                historyOfActions = new ActionHistory(lastActionTakenLabel);
-                DrawEmptyCanvasRight();
-                //The following lines cannot be in DrawEmptyCanvas()
-                isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
-                linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
-                rightLineList = new List<Tuple<bool, Line>>();
-                //Reinitialise the Redraw Assistant.
-                if(leftLineList != null)
-                {
-                    redrawAss = new RedrawAssistant(leftLineList);
-                    UpdateSizes();
-                    overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                    RedrawRightImage();
-                }
-            }
-            UpdateButtonStatus();
-            UpdateSizes();
+            ProgramPresenter.NewCanvas();
         }
 
         /// <summary>
@@ -379,424 +183,141 @@ namespace SketchAssistant
         /// </summary>
         private void mouseTimer_Tick(object sender, EventArgs e)
         {
-            if(cursorPositions.Count > 0) { previousCursorPosition = cursorPositions.Dequeue(); }
-            else { previousCursorPosition = currentCursorPosition; }
-            cursorPositions.Enqueue(currentCursorPosition);
-            //Drawing
-            if (currentState.Equals(ProgramState.Draw) && mousePressed)
-            {
-                rightGraph = Graphics.FromImage(rightImage);
-                currentLine.Add(currentCursorPosition);
-                Line drawline = new Line(currentLine);
-                drawline.DrawLine(rightGraph);
-                pictureBoxRight.Image = rightImage;
-                //Redraw overlay gets ticked
-                overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, rightLineList.Count, false);
-                RedrawRightImage();
-            }
-            //Deleting
-            if (currentState.Equals(ProgramState.Delete) && mousePressed)
-            {
-                List<Point> uncheckedPoints = GeometryCalculator.BresenhamLineAlgorithm(previousCursorPosition, currentCursorPosition);
-                foreach (Point currPoint in uncheckedPoints)
-                {
-                    HashSet<int> linesToDelete = CheckDeletionMatrixesAroundPoint(currPoint, deletionRadius);
-                    if (linesToDelete.Count > 0)
-                    {
-                        historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Delete, linesToDelete));
-                        foreach (int lineID in linesToDelete)
-                        {
-                            rightLineList[lineID] = new Tuple<bool, Line>(false, rightLineList[lineID].Item2);
-                        }
-                        RepopulateDeletionMatrixes();
-                        //Redraw overlay gets ticked
-                        overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
-                        RedrawRightImage();
-                    }
-                }
-            }
+            ProgramPresenter.Tick();
         }
 
-        /***********************************/
-        /*** HELPER FUNCTIONS START HERE ***/
-        /***********************************/
+        /*************************/
+        /*** PRESENTER -> VIEW ***/
+        /*************************/
 
         /// <summary>
-        /// A function that returns a white canvas for a given width and height.
+        /// Enables the timer of the View, which will tick the Presenter.
         /// </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)
+        public void EnableTimer()
         {
-            Image image;
-            try
-            {
-                image = new Bitmap(width, height);
-            }
-            catch(ArgumentException e)
-            {
-                ShowInfoMessage("The requested canvas size caused an error: \n" + e.ToString() + "\n The Canvas will be set to match your window.");
-                image = new Bitmap(pictureBoxLeft.Width, pictureBoxLeft.Height);
-            }
-            Graphics graph = Graphics.FromImage(image);
-            graph.FillRectangle(Brushes.White, 0, 0, width + 10, height + 10);
-            return image;
+            mouseTimer.Enabled = true;
         }
 
         /// <summary>
-        /// Creates an empty Canvas
+        /// A function that opens a file dialog and returns the filename.
         /// </summary>
-        private void DrawEmptyCanvasRight()
+        /// <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)
         {
-            if (leftImage == null)
+            openFileDialog.Filter = Filter;
+            if (openFileDialog.ShowDialog() == DialogResult.OK)
             {
-                SetAndRefreshRightImage(GetEmptyCanvas(pictureBoxRight.Width, pictureBoxRight.Height));
+                return new Tuple<string, string>(openFileDialog.FileName, openFileDialog.SafeFileName);
             }
             else
             {
-                SetAndRefreshRightImage(GetEmptyCanvas(leftImage.Width, leftImage.Height));
+                return new Tuple<string, string>("", "");
             }
         }
 
         /// <summary>
-        /// Creates an empty Canvas on the left
+        /// Sets the contents of the load status indicator label.
         /// </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)
+        /// <param name="message">The new contents</param>
+        public void SetToolStripLoadStatus(String message)
         {
-            if (width == 0)
-            {
-                SetAndRefreshLeftImage(GetEmptyCanvas(pictureBoxLeft.Width, pictureBoxLeft.Height));
-            }
-            else
-            {
-                SetAndRefreshLeftImage(GetEmptyCanvas(width, height));
-            }
+            toolStripLoadStatus.Text = message;
         }
 
         /// <summary>
-        /// Redraws all lines in lineList, for which their associated boolean value equals true.
+        /// Sets the contents of the last action taken indicator label.
         /// </summary>
-        private void RedrawRightImage()
+        /// <param name="message">The new contents</param>
+        public void SetLastActionTakenText(String message)
         {
-            var workingCanvas = GetEmptyCanvas(rightImage.Width, rightImage.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 && currentState.Equals(ProgramState.Draw) && mousePressed)
-            {
-                var currLine = new Line(currentLine);
-                currLine.DrawLine(workingGraph);
-            }
-            //Overlay Items
-            foreach (HashSet<Point> item in overlayItems)
-            {
-                foreach(Point p in item)
-                {
-                    workingGraph.FillRectangle(Brushes.Green, p.X, p.Y, 1, 1);
-                }
-            }
-            SetAndRefreshRightImage(workingCanvas);
+            lastActionTakenLabel.Text = message;
         }
 
         /// <summary>
-        /// A function to set rightImage and to refresh the respective PictureBox with it.
+        /// Changes the states of a tool strip button.
         /// </summary>
-        /// <param name="image">The new Image</param>
-        private void SetAndRefreshRightImage(Image image)
+        /// <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)
         {
-            rightImage = image;
-            pictureBoxRight.Image = rightImage;
-            pictureBoxRight.Refresh();
-        }
-
-        /// <summary>
-        /// A function to set leftImage and to refresh the respective PictureBox with it.
-        /// </summary>
-        /// <param name="image">The new Image</param>
-        private void SetAndRefreshLeftImage(Image image)
-        {
-            leftImage = image;
-            pictureBoxLeft.Image = leftImage;
-            pictureBoxLeft.Refresh();
-        }
-
-        /// <summary>
-        /// Change the status of whether or not the lines are shown.
-        /// </summary>
-        /// <param name="lines">The HashSet containing the affected Line IDs.</param>
-        /// <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)
-        {
-            foreach (int lineId in lines)
-            {
-                if (lineId <= rightLineList.Count - 1 && lineId >= 0)
-                {
-                    rightLineList[lineId] = new Tuple<bool, Line>(shown, rightLineList[lineId].Item2);
-                }
-            }
-            RedrawRightImage();
-        }
-
-        /// <summary>
-        /// Updates the active status of buttons. Currently draw, delete, undo and redo button.
-        /// </summary>
-        private void UpdateButtonStatus()
-        {
-            undoButton.Enabled = historyOfActions.CanUndo();
-            redoButton.Enabled = historyOfActions.CanRedo();
-            drawButton.Enabled = (rightImage != null);
-            deleteButton.Enabled = (rightImage != null);
-        }
-
-        /// <summary>
-        /// A helper function which handles tasks associated witch changing states, 
-        /// such as checking and unchecking buttons and changing the state.
-        /// </summary>
-        /// <param name="newState">The new state of the program</param>
-        private void ChangeState(ProgramState newState)
-        {
-            switch (currentState)
+            ToolStripButton buttonToChange;
+            switch (buttonName)
             {
-                case ProgramState.Draw:
-                    drawButton.CheckState = CheckState.Unchecked;
-                    mouseTimer.Enabled = false;
+                case "canvasButton":
+                    buttonToChange = canvasButton;
                     break;
-                case ProgramState.Delete:
-                    deleteButton.CheckState = CheckState.Unchecked;
-                    mouseTimer.Enabled = false;
+                case "drawButton":
+                    buttonToChange = drawButton;
                     break;
-                default:
+                case "deleteButton":
+                    buttonToChange = deleteButton;
                     break;
-            }
-            switch (newState)
-            {
-                case ProgramState.Draw:
-                    drawButton.CheckState = CheckState.Checked;
-                    mouseTimer.Enabled = true;
+                case "undoButton":
+                    buttonToChange = undoButton;
                     break;
-                case ProgramState.Delete:
-                    deleteButton.CheckState = CheckState.Checked;
-                    mouseTimer.Enabled = true;
+                case "redoButton":
+                    buttonToChange = redoButton;
                     break;
                 default:
-                    break;
+                    Console.WriteLine("Invalid Button was given to SetToolStripButton. \nMaybe you forgot to add a case?");
+                    return;
             }
-            currentState = newState;
-            pictureBoxRight.Refresh();
-        }
-
-        /// <summary>
-        /// A function that calculates the coordinates of a point on a zoomed in image.
-        /// </summary>
-        /// <param name="">The position of the mouse cursor</param>
-        /// <returns>The real coordinates of the mouse cursor on the image</returns>
-        private Point ConvertCoordinates(Point cursorPosition)
-        {
-            Point realCoordinates = new Point(5,3);
-            if(pictureBoxRight.Image == null)
+            switch (state)
             {
-                return cursorPosition;
-            }
-
-            int widthImage = pictureBoxRight.Image.Width;
-            int heightImage = pictureBoxRight.Image.Height;
-            int widthBox = pictureBoxRight.Width;
-            int heightBox = pictureBoxRight.Height;
-
-            float imageRatio = (float)widthImage / (float)heightImage;
-            float containerRatio = (float)widthBox / (float)heightBox;
-
-            if (imageRatio >= containerRatio)
-            {
-                //Image is wider than it is high
-                float zoomFactor = (float)widthImage / (float)widthBox;
-                float scaledHeight = heightImage / zoomFactor;
-                float filler = (heightBox - scaledHeight) / 2;
-                realCoordinates.X = (int)(cursorPosition.X * zoomFactor);
-                realCoordinates.Y = (int)((cursorPosition.Y - filler) * zoomFactor);
-            }
-            else
-            {
-                //Image is higher than it is wide
-                float zoomFactor = (float)heightImage / (float)heightBox;
-                float scaledWidth = widthImage / zoomFactor;
-                float filler = (widthBox - scaledWidth) / 2;
-                realCoordinates.X = (int)((cursorPosition.X - filler) * zoomFactor);
-                realCoordinates.Y = (int)(cursorPosition.Y * zoomFactor);
-            }
-            return realCoordinates;
-        }
-
-        /// <summary>
-        /// A function that populates the matrixes needed for deletion detection with line data.
-        /// </summary>
-        private void RepopulateDeletionMatrixes()
-        {
-            if(rightImage != null)
-            {
-                isFilledMatrix = new bool[rightImage.Width,rightImage.Height];
-                linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
-                foreach(Tuple<bool,Line> lineTuple in rightLineList)
-                {
-                    if (lineTuple.Item1)
-                    {
-                        lineTuple.Item2.PopulateMatrixes(isFilledMatrix, linesMatrix);
-                    }
-                }
+                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>
-        /// 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.
+        /// Displays an image in the left Picture box.
         /// </summary>
-        /// <param name="p">The point around which to check.</param>
-        /// <param name="range">The range around the point. If range is 0, only the point is checked.</param>
-        /// <returns>A List of all lines.</returns>
-        private HashSet<int> CheckDeletionMatrixesAroundPoint(Point p, int range)
+        /// <param name="img">The new image.</param>
+        public void DisplayInLeftPictureBox(Image img)
         {
-            HashSet<int> returnSet = new HashSet<int>();
-
-            foreach(Point pnt in GeometryCalculator.FilledCircleAlgorithm(p, (int)range))
-            {
-                if(pnt.X >= 0 && pnt.Y >= 0 && pnt.X < rightImage.Width && pnt.Y < rightImage.Height)
-                {
-                    if (isFilledMatrix[pnt.X, pnt.Y])
-                    {
-                        returnSet.UnionWith(linesMatrix[pnt.X, pnt.Y]);
-                    }
-                }
-            }
-            return returnSet;
+            pictureBoxLeft.Image = img;
+            pictureBoxLeft.Refresh();
         }
 
         /// <summary>
-        /// binds the given picture to templatePicture and draws it
+        /// Displays an image in the right Picture box.
         /// </summary>
-        /// <param name="newTemplatePicture"> the new template picture, represented as a list of polylines </param>
-        /// <returns></returns>
-        private void BindAndDrawLeftImage(List<Line> newTemplatePicture)
+        /// <param name="img">The new image.</param>
+        public void DisplayInRightPictureBox(Image img)
         {
-            leftLineList = newTemplatePicture;
-            foreach(Line l in leftLineList)
-            {
-                l.DrawLine(Graphics.FromImage(leftImage));
-            }
+            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>
-        private void ShowInfoMessage(String message)
+        public void ShowInfoMessage(String message)
         {
             MessageBox.Show(message);
         }
-        
-        /// <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;
-        }
 
         /// <summary>
-        /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
+        /// Shows a warning box with the given message (Yes/No Buttons)and returns true if the user aknowledges it.
         /// </summary>
-        private void UpdateSizes()
+        /// <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)
         {
-            if (rightImage != null)
-            {
-                int widthImage = pictureBoxRight.Image.Width;
-                int heightImage = pictureBoxRight.Image.Height;
-                int widthBox = pictureBoxRight.Width;
-                int heightBox = pictureBoxRight.Height;
-                
-                float imageRatio = (float)widthImage / (float)heightImage;
-                float containerRatio = (float)widthBox / (float)heightBox;
-                float zoomFactor = 0;
-                if (imageRatio >= containerRatio)
-                {
-                    //Image is wider than it is high
-                    zoomFactor = (float)widthImage / (float)widthBox;
-                }
-                else
-                {
-                    //Image is higher than it is wide
-                    zoomFactor = (float)heightImage / (float)heightBox;
-                }
-                markerRadius = (int)(10 * zoomFactor);
-                redrawAss.SetMarkerRadius(markerRadius);
-                deletionRadius = (int)(5 * zoomFactor);
-            }
-        }
-
-        /// <summary>
-        /// Checks if there is unsaved progess, and warns the user. Returns True if it safe to continue.
-        /// </summary>
-        /// <returns>true if there is none, or the user wishes to continue without saving.
-        /// false if there is progress, and the user doesn't wish to continue.</returns>
-        private bool CheckSavedStatus()
-        {
-            if (!historyOfActions.IsEmpty())
-            {
-                return (MessageBox.Show("You have unsaved changes, do you wish to continue?",
-                    "Attention", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
-            }
-            return true;
-        }
-
-        /********************************************/
-        /*** TESTING RELATED FUNCTIONS START HERE ***/
-        /********************************************/
-
-        /// <summary>
-        /// returns all instance variables in the order of their definition for testing
-        /// </summary>
-        /// <returns>A list of tuples containing names of variables and the variable themselves. 
-        /// Cast according to the Type definitions in the class variable section.</returns>
-        public List<Tuple<String, Object>>GetAllVariables()
-        {
-            var objArr = new (String, object)[] { ("currentState", currentState), ("fileImporter", fileImporter), ("openFileDialog", openFileDialog),
-                ("leftImage", leftImage), ("leftLineList", leftLineList), ("rightImage", rightImage), ("currentLine", currentLine),
-                ("rightLineList", rightLineList), ("mousePressed", mousePressed), ("currentCursorPosition", currentCursorPosition),
-                ("previousCursorPosition", previousCursorPosition), ("cursorPositions", cursorPositions), ("rightGraph", rightGraph),
-                ("isFilledMatrix", isFilledMatrix), ("linesMatrix", linesMatrix), ("deletionRadius", deletionRadius),
-                ("historyOfActions", historyOfActions), ("overlayItems", overlayItems), ("redrawAss", redrawAss), ("markerRadius", markerRadius) };
-            var varArr = new List<Tuple<String, Object>>();
-            foreach((String, object) obj in objArr)
-            {
-                varArr.Add(new Tuple<string, object>(obj.Item1, obj.Item2));
-            }
-            return varArr;
+            return (MessageBox.Show(message, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
         }
 
-        /// <summary>
-        /// public method wrapper for testing purposes, invoking DrawEmptyCanvas(...) and BindAndDrawLeftImage(...)
-        /// </summary>
-        /// <param name="width">width of the parsed image</param>
-        /// <param name="height">height of the parsed image</param>
-        /// <param name="newImage">the parsed image</param>
-        public void CreateCanvasAndSetPictureForTesting(int width, int height, List<Line> newImage)
-        {
-            DrawEmptyCanvasLeft(width, height);
-            BindAndDrawLeftImage(newImage);
-        }
     }
 }

+ 9 - 9
SketchAssistant/SketchAssistant/Form1.resx

@@ -172,15 +172,6 @@
         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>
   <data name="undoButton.Image" type="System.Drawing.Bitmap, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
         iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8
@@ -211,6 +202,15 @@
         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>

+ 568 - 0
SketchAssistant/SketchAssistant/MVP_Model.cs

@@ -0,0 +1,568 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Drawing;
+
+namespace SketchAssistant
+{
+    public class MVP_Model
+    {
+        /// <summary>
+        /// The Presenter of the MVP-Model.
+        /// </summary>
+        MVP_Presenter programPresenter;
+        /// <summary>
+        /// History of Actions
+        /// </summary>
+        ActionHistory historyOfActions;
+        /// <summary>
+        /// The assistant responsible for the redraw mode
+        /// </summary>
+        RedrawAssistant redrawAss;
+
+        /*******************/
+        /*** ENUMERATORS ***/
+        /*******************/
+
+        /***********************/
+        /*** CLASS VARIABLES ***/
+        /***********************/
+
+        /// <summary>
+        /// If the program is in drawing mode.
+        /// </summary>
+        bool inDrawingMode;
+        /// <summary>
+        /// If the mouse is currently pressed or not.
+        /// </summary>
+        bool mousePressed;
+        /// <summary>
+        /// Size of deletion area
+        /// </summary>
+        int deletionRadius = 5;
+        /// <summary>
+        /// Size of areas marking endpoints of lines in the redraw mode.
+        /// </summary>
+        int markerRadius = 10;
+        /// <summary>
+        /// The Position of the Cursor in the right picture box
+        /// </summary>
+        Point currentCursorPosition;
+        /// <summary>
+        /// The Previous Cursor Position in the right picture box
+        /// </summary>
+        Point previousCursorPosition;
+        /// <summary>
+        /// Queue for the cursorPositions
+        /// </summary>
+        Queue<Point> cursorPositions = new Queue<Point>();
+        /// <summary>
+        /// Lookup Matrix for checking postions of lines in the image
+        /// </summary>
+        bool[,] isFilledMatrix;
+        /// <summary>
+        /// Lookup Matrix for getting line ids at a certain postions of the image
+        /// </summary>
+        HashSet<int>[,] linesMatrix;
+        /// <summary>
+        /// List of items which will be overlayed over the right canvas.
+        /// </summary>
+        List<Tuple<bool, HashSet<Point>>> overlayItems;
+        /// <summary>
+        /// Width of the LeftImageBox.
+        /// </summary>
+        public int leftImageBoxWidth;
+        /// <summary>
+        /// Height of the LeftImageBox.
+        /// </summary>
+        public int leftImageBoxHeight;
+        /// <summary>
+        /// Width of the RightImageBox.
+        /// </summary>
+        public int rightImageBoxWidth;
+        /// <summary>
+        /// Height of the RightImageBox.
+        /// </summary>
+        public int rightImageBoxHeight;
+
+        //Images
+        Image leftImage;
+
+        List<Line> leftLineList;
+
+        Image rightImageWithoutOverlay;
+
+        Image rightImageWithOverlay;
+
+        List<Tuple<bool, Line>> rightLineList;
+
+        List<Point> currentLine;
+
+
+
+        public MVP_Model(MVP_Presenter presenter)
+        {
+            programPresenter = presenter;
+            historyOfActions = new ActionHistory();
+            redrawAss = new RedrawAssistant();
+            rightLineList = new List<Tuple<bool, Line>>();
+            overlayItems = new List<Tuple<bool, HashSet<Point>>>();
+        }
+
+        /**************************/
+        /*** 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>
+        /// <param name="lines">The HashSet containing the affected Line IDs.</param>
+        /// <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;
+                }
+            }
+            if (changed) { RedrawRightImage(); }
+        }
+        
+        /// <summary>
+        /// A function that populates the matrixes needed for deletion detection with line data.
+        /// </summary>
+        private void RepopulateDeletionMatrixes()
+        {
+            if (rightImageWithoutOverlay != null)
+            {
+                isFilledMatrix = new bool[rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height];
+                linesMatrix = new HashSet<int>[rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height];
+                foreach (Tuple<bool, Line> lineTuple in rightLineList)
+                {
+                    if (lineTuple.Item1)
+                    {
+                        lineTuple.Item2.PopulateMatrixes(isFilledMatrix, linesMatrix);
+                    }
+                }
+            }
+        }
+
+        /// <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.
+        /// </summary>
+        /// <param name="p">The point around which to check.</param>
+        /// <param name="range">The range around the point. If range is 0, only the point is checked.</param>
+        /// <returns>A List of all lines.</returns>
+        private HashSet<int> CheckDeletionMatrixesAroundPoint(Point p, int range)
+        {
+            HashSet<int> returnSet = new HashSet<int>();
+
+            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 (isFilledMatrix[pnt.X, pnt.Y])
+                    {
+                        returnSet.UnionWith(linesMatrix[pnt.X, 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;
+        }
+        */
+
+
+
+        /// <summary>
+        /// Tells the Presenter to Update the UI
+        /// </summary>
+        private void UpdateUI()
+        {
+            programPresenter.UpdateUIState(inDrawingMode, historyOfActions.CanUndo(), historyOfActions.CanRedo(), (rightImageWithoutOverlay != null));
+        }
+
+
+        /********************************************/
+        /*** FUNCTIONS TO INTERACT WITH PRESENTER ***/
+        /********************************************/
+
+        /// <summary>
+        /// Creates an empty Canvas
+        /// </summary>
+        public void DrawEmptyCanvasRight()
+        {
+            if (leftImage == null)
+            {
+                rightImageWithoutOverlay = GetEmptyCanvas(leftImageBoxWidth, leftImageBoxHeight);
+            }
+            else
+            {
+                rightImageWithoutOverlay = GetEmptyCanvas(leftImage.Width, leftImage.Height);
+            }
+            RepopulateDeletionMatrixes();
+            rightImageWithOverlay = rightImageWithoutOverlay;
+            programPresenter.UpdateRightImage(rightImageWithOverlay);
+        }
+
+        /// <summary>
+        /// The function to set the left image.
+        /// </summary>
+        /// <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)
+        {
+            var workingCanvas = GetEmptyCanvas(width,height);
+            var workingGraph = Graphics.FromImage(workingCanvas);
+            leftLineList = listOfLines;
+            redrawAss = new RedrawAssistant(leftLineList);
+            overlayItems = redrawAss.Initialize(markerRadius);
+            //Lines
+            foreach (Line line in leftLineList)
+            {
+                line.DrawLine(workingGraph);
+            }
+            leftImage = workingCanvas;
+            programPresenter.UpdateLeftImage(leftImage);
+            //Set right image to same size as left image and delete linelist
+            DrawEmptyCanvasRight();
+            rightLineList = new List<Tuple<bool, Line>>();
+        }
+
+        /// <summary>
+        /// Will undo the last action taken, if the action history allows it.
+        /// </summary>
+        public void Undo()
+        {
+            if (historyOfActions.CanUndo())
+            {
+                HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
+                SketchAction.ActionType undoAction = historyOfActions.GetCurrentAction().GetActionType();
+                switch (undoAction)
+                {
+                    case SketchAction.ActionType.Delete:
+                        //Deleted Lines need to be shown
+                        ChangeLines(affectedLines, true);
+                        break;
+                    case SketchAction.ActionType.Draw:
+                        //Drawn lines need to be hidden
+                        ChangeLines(affectedLines, false);
+                        break;
+                    default:
+                        break;
+                }
+                if(leftImage != null)
+                {
+                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
+                }
+                RedrawRightImage();
+            }
+            RepopulateDeletionMatrixes();
+            programPresenter.PassLastActionTaken(historyOfActions.MoveAction(true));
+            UpdateUI();
+        }
+
+        /// <summary>
+        /// Will redo the last action undone, if the action history allows it.
+        /// </summary>
+        public void Redo()
+        {
+            if (historyOfActions.CanRedo())
+            {
+                programPresenter.PassLastActionTaken(historyOfActions.MoveAction(false));
+                HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
+                SketchAction.ActionType redoAction = historyOfActions.GetCurrentAction().GetActionType();
+                switch (redoAction)
+                {
+                    case SketchAction.ActionType.Delete:
+                        //Deleted Lines need to be redeleted
+                        ChangeLines(affectedLines, false);
+                        break;
+                    case SketchAction.ActionType.Draw:
+                        //Drawn lines need to be redrawn
+                        ChangeLines(affectedLines, true);
+                        break;
+                    default:
+                        break;
+                }
+                if (leftImage != null)
+                {
+                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
+                }
+                RedrawRightImage();
+                RepopulateDeletionMatrixes();
+            }
+            UpdateUI();
+        }
+
+        /// <summary>
+        /// The function called by the Presenter to change the drawing state of the program.
+        /// </summary>
+        /// <param name="nowDrawing">The new drawingstate of the program</param>
+        public void ChangeState(bool nowDrawing)
+        {
+            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>
+        /// <param name="p">The new cursor position</param>
+        public void SetCurrentCursorPosition(Point p)
+        {
+            currentCursorPosition = p;
+        }
+
+        /// <summary>
+        /// Start a new Line, when the Mouse is pressed down.
+        /// </summary>
+        public void MouseDown()
+        {
+            mousePressed = true;
+            if (inDrawingMode)
+            {
+                currentLine = new List<Point>();
+            }
+        }
+
+        /// <summary>
+        /// Finish the current Line, when the pressed Mouse is released.
+        /// </summary>
+        public void MouseUp()
+        {
+            mousePressed = false;
+            if (inDrawingMode && currentLine.Count > 0)
+            {
+                Line newLine = new Line(currentLine, rightLineList.Count);
+                rightLineList.Add(new Tuple<bool, Line>(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();
+            }
+            UpdateUI();
+        }
+
+        /// <summary>
+        /// Method to be called every tick. Updates the current Line, or checks for Lines to delete, depending on the drawing mode.
+        /// </summary>
+        public void Tick()
+        {
+            if (cursorPositions.Count > 0) { previousCursorPosition = cursorPositions.Dequeue(); }
+            else { previousCursorPosition = currentCursorPosition; }
+            cursorPositions.Enqueue(currentCursorPosition);
+            //Drawing
+            if (inDrawingMode && mousePressed)
+            {
+                var rightGraph = Graphics.FromImage(rightImageWithoutOverlay);
+                currentLine.Add(currentCursorPosition);
+                Line drawline = new Line(currentLine);
+                drawline.DrawLine(rightGraph);
+                RedrawRightOverlay();
+            }
+            //Deleting
+            if (!inDrawingMode && mousePressed)
+            {
+                List<Point> uncheckedPoints = GeometryCalculator.BresenhamLineAlgorithm(previousCursorPosition, currentCursorPosition);
+                foreach (Point currPoint in uncheckedPoints)
+                {
+                    HashSet<int> linesToDelete = CheckDeletionMatrixesAroundPoint(currPoint, deletionRadius);
+                    if (linesToDelete.Count > 0)
+                    {
+                        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);
+                        }
+                        RepopulateDeletionMatrixes();
+                        if(leftImage != null)
+                        {
+                            //Redraw overlay gets ticked
+                            //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
+                        }
+                        RedrawRightImage();
+                    }
+                }
+            }
+        }
+
+        /// <summary>
+        /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
+        /// </summary>
+        public void UpdateSizes()
+        {
+            if (rightImageWithoutOverlay != null)
+            {
+                int widthImage = rightImageWithoutOverlay.Width;
+                int heightImage = rightImageWithoutOverlay.Height;
+                int widthBox = rightImageBoxWidth;
+                int heightBox = rightImageBoxHeight;
+
+                float imageRatio = (float)widthImage / (float)heightImage;
+                float containerRatio = (float)widthBox / (float)heightBox;
+                float zoomFactor = 0;
+                if (imageRatio >= containerRatio)
+                {
+                    //Image is wider than it is high
+                    zoomFactor = (float)widthImage / (float)widthBox;
+                }
+                else
+                {
+                    //Image is higher than it is wide
+                    zoomFactor = (float)heightImage / (float)heightBox;
+                }
+                markerRadius = (int)(10 * zoomFactor);
+                redrawAss.SetMarkerRadius(markerRadius);
+                deletionRadius = (int)(5 * zoomFactor);
+            }
+        }
+
+        /// <summary>
+        /// If there is unsaved progress.
+        /// </summary>
+        /// <returns>True if there is progress that has not been saved.</returns>
+        public bool HasUnsavedProgress()
+        {
+            return !historyOfActions.IsEmpty();
+        }
+    }
+}

+ 310 - 0
SketchAssistant/SketchAssistant/MVP_Presenter.cs

@@ -0,0 +1,310 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Forms;
+using System.Drawing;
+
+namespace SketchAssistant
+{
+    public class MVP_Presenter
+    {
+        /// <summary>
+        /// The View of the MVP-Model, in this case Form1.
+        /// </summary>
+        MVP_View programView;
+        /// <summary>
+        /// The Model of the MVP-Model.
+        /// </summary>
+        MVP_Model programModel;
+
+        /*******************/
+        /*** ENUMERATORS ***/
+        /*******************/
+
+        public enum MouseAction
+        {
+            Click,
+            Down,
+            Up,
+            Move
+        }
+
+        /***********************/
+        /*** CLASS VARIABLES ***/
+        /***********************/
+
+        /// <summary>
+        /// Instance of FileImporter to handle drawing imports.
+        /// </summary>
+        private FileImporter fileImporter;
+
+
+        public MVP_Presenter(MVP_View form)
+        {
+            programView = form;
+            programModel = new MVP_Model(this);
+            //Initialize Class Variables
+            fileImporter = new FileImporter();
+        }
+
+        /***********************************/
+        /*** FUNCTIONS VIEW -> PRESENTER ***/
+        /***********************************/
+
+        /// <summary>
+        /// Pass-trough function to update the appropriate information of the model, when the window is resized.
+        /// </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)
+        {
+            programModel.leftImageBoxWidth = leftPBS.Item1;
+            programModel.leftImageBoxHeight = leftPBS.Item2;
+            programModel.rightImageBoxWidth = rightPBS.Item1;
+            programModel.rightImageBoxHeight = rightPBS.Item2;
+            programModel.UpdateSizes();
+        }
+
+        /// <summary>
+        /// Display a new FileDialog to load a collection of lines.
+        /// </summary>
+        public void ExamplePictureToolStripMenuItemClick()
+        {
+            var okToContinue = true;
+            if (programModel.HasUnsavedProgress())
+            {
+                okToContinue = programView.ShowWarning("You have unsaved progress. Continue?");
+            }
+            if (okToContinue)
+            {
+                var fileNameTup = programView.openNewDialog("Interactive Sketch-Assistant Drawing|*.isad");
+                if (!fileNameTup.Item1.Equals("") && !fileNameTup.Item2.Equals(""))
+                {
+                    programView.SetToolStripLoadStatus(fileNameTup.Item2);
+                    (int, int, List<Line>) values = fileImporter.ParseISADInputFile(fileNameTup.Item1);
+                    programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
+                    programModel.ChangeState(true);
+                    programView.EnableTimer();
+                }
+            }
+        }
+
+        /// <summary>
+        /// Pass-trough function to change the drawing state of the model.
+        /// </summary>
+        /// <param name="NowDrawing">Indicates if the program is in drawing (true) or deletion (false) mode.</param>
+        public void ChangeState(bool NowDrawing)
+        {
+            programModel.ChangeState(NowDrawing);
+        }
+
+        /// <summary>
+        /// Pass-trough function to undo an action.
+        /// </summary>
+        public void Undo()
+        {
+            programModel.Undo();
+        }
+
+        /// <summary>
+        /// Pass-trough function to redo an action.
+        /// </summary>
+        public void Redo()
+        {
+            programModel.Redo();
+        }
+
+        /// <summary>
+        /// Checks if there is unsaved progress, and promts the model to generate a new canvas if not.
+        /// </summary>
+        public void NewCanvas()
+        {
+            var okToContinue = true;
+            if (programModel.HasUnsavedProgress())
+            {
+                okToContinue = programView.ShowWarning("You have unsaved progress. Continue?");
+            }
+            if (okToContinue)
+            {
+                programModel.DrawEmptyCanvasRight();
+                programModel.ChangeState(true);
+                programView.EnableTimer();
+            }
+        }
+
+        /// <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)
+        {
+            switch (mouseAction)
+            {
+                case MouseAction.Move:
+                    programModel.SetCurrentCursorPosition(ConvertCoordinates(new Point(e.X, e.Y)));
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        /// <summary>
+        /// Pass-trough function that calls the correct Mouse event of the model, when the mouse is clicked.
+        /// </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)
+        {
+            switch (mouseAction)
+            {
+                case MouseAction.Click:
+                    programModel.MouseDown();
+                    programModel.Tick();
+                    programModel.MouseUp();
+                    break;
+                case MouseAction.Down:
+                    programModel.MouseDown();
+                    break;
+                case MouseAction.Up:
+                    programModel.MouseUp();
+                    break;
+                default:
+                    break;
+            }
+        }
+
+        /************************************/
+        /*** FUNCTIONS MODEL -> PRESENTER ***/
+        /************************************/
+
+        /// <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.
+        /// </summary>
+        /// <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)
+        {
+            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}};
+
+            if (imageLoaded)
+            {
+                if (inDrawingMode)
+                {
+                    dict["drawButton"] = Form1.ButtonState.Active;
+                    dict["deleteButton"] = Form1.ButtonState.Enabled;
+                }
+                else
+                {
+                    dict["drawButton"] = Form1.ButtonState.Enabled;
+                    dict["deleteButton"] = Form1.ButtonState.Active;
+                }
+                if (canUndo){dict["undoButton"] = Form1.ButtonState.Enabled;}
+                if (canRedo){dict["redoButton"] = Form1.ButtonState.Enabled;}
+            }
+            foreach(KeyValuePair<String, Form1.ButtonState> entry in dict)
+            {
+                programView.SetToolStripButtonStatus(entry.Key, entry.Value);
+            }
+        }
+
+        /// <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.
+        /// </summary>
+        /// <param name="msg">The message.</param>
+        public void PassMessageToView(String msg)
+        {
+            programView.ShowInfoMessage(msg);
+        }
+
+        /// <summary>
+        /// Pass-trough function to update the display of the last action taken.
+        /// </summary>
+        /// <param name="msg">The new last action taken.</param>
+        public void PassLastActionTaken(String msg)
+        {
+            programView.SetLastActionTakenText(msg);
+        }
+
+        /*************************/
+        /*** HELPING FUNCTIONS ***/
+        /*************************/
+
+        /// <summary>
+        /// A function that calculates the coordinates of a point on a zoomed in image.
+        /// </summary>
+        /// <param name="">The position of the mouse cursor</param>
+        /// <returns>The real coordinates of the mouse cursor on the image</returns>
+        private Point ConvertCoordinates(Point cursorPosition)
+        {
+            var rightImageDimensions = programModel.GetRightImageDimensions();
+            Point realCoordinates = new Point(0, 0);
+
+            int widthImage = rightImageDimensions.Item1;
+            int heightImage = rightImageDimensions.Item2;
+            int widthBox = programModel.rightImageBoxWidth;
+            int heightBox = programModel.rightImageBoxHeight;
+
+            if (heightImage == 0 && widthImage == 0)
+            {
+                return cursorPosition;
+            }
+
+            float imageRatio = (float)widthImage / (float)heightImage;
+            float containerRatio = (float)widthBox / (float)heightBox;
+
+            if (imageRatio >= containerRatio)
+            {
+                //Image is wider than it is high
+                float zoomFactor = (float)widthImage / (float)widthBox;
+                float scaledHeight = heightImage / zoomFactor;
+                float filler = (heightBox - scaledHeight) / 2;
+                realCoordinates.X = (int)(cursorPosition.X * zoomFactor);
+                realCoordinates.Y = (int)((cursorPosition.Y - filler) * zoomFactor);
+            }
+            else
+            {
+                //Image is higher than it is wide
+                float zoomFactor = (float)heightImage / (float)heightBox;
+                float scaledWidth = widthImage / zoomFactor;
+                float filler = (widthBox - scaledWidth) / 2;
+                realCoordinates.X = (int)((cursorPosition.X - filler) * zoomFactor);
+                realCoordinates.Y = (int)(cursorPosition.Y * zoomFactor);
+            }
+            return realCoordinates;
+        }
+    }
+}

+ 71 - 0
SketchAssistant/SketchAssistant/MVP_View.cs

@@ -0,0 +1,71 @@
+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);
+    }
+}

+ 36 - 6
SketchAssistant/SketchAssistant/RedrawAssistant.cs

@@ -72,6 +72,27 @@ namespace SketchAssistant
             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>
@@ -79,15 +100,23 @@ namespace SketchAssistant
         /// <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>
-        /// <returns>A List of HashSets of Points, which are markers for the user to redraw lines.</returns>
-        public List<HashSet<Point>> Tick(Point currentPoint, List<Tuple<bool, Line>> rightLines, int currLineID, bool lineFinished)
+        /// <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)
         {
-            List<HashSet<Point>> returnList = new List<HashSet<Point>>();
-            if (!isActive) { return returnList; }
+            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)
             {
@@ -159,8 +188,9 @@ namespace SketchAssistant
                     }
                 }
             }
-
             return returnList;
+            */
+            return new Tuple<bool, List<Tuple<bool, HashSet<Point>>>>(false, overlayItems);
         }
 
         /// <summary>

+ 3 - 0
SketchAssistant/SketchAssistant/SketchAssistant.csproj

@@ -69,6 +69,9 @@
     <Reference Include="System.Xml" />
   </ItemGroup>
   <ItemGroup>
+    <Compile Include="MVP_View.cs" />
+    <Compile Include="MVP_Presenter.cs" />
+    <Compile Include="MVP_Model.cs" />
     <Compile Include="RedrawAssistant.cs" />
     <Compile Include="FileImporter.cs" />
     <Compile Include="FileImporterException.cs" />