Browse Source

Started Refactoring program into mvp-model.

Martin Edlund 5 years ago
parent
commit
d4397ed118

+ 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();
         }
     }
 }

+ 7 - 3
SketchAssistant/SketchAssistant/Form1.Designer.cs

@@ -126,7 +126,7 @@ namespace SketchAssistant
             // loadToolStripMenuItem
             // 
             this.loadToolStripMenuItem.Name = "loadToolStripMenuItem";
-            this.loadToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
+            this.loadToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.loadToolStripMenuItem.Text = "Load...";
             this.loadToolStripMenuItem.Click += new System.EventHandler(this.loadToolStripMenuItem_Click);
             // 
@@ -135,13 +135,13 @@ namespace SketchAssistant
             this.importToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
             this.examplePictureToolStripMenuItem});
             this.importToolStripMenuItem.Name = "importToolStripMenuItem";
-            this.importToolStripMenuItem.Size = new System.Drawing.Size(119, 22);
+            this.importToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.importToolStripMenuItem.Text = "Import...";
             // 
             // examplePictureToolStripMenuItem
             // 
             this.examplePictureToolStripMenuItem.Name = "examplePictureToolStripMenuItem";
-            this.examplePictureToolStripMenuItem.Size = new System.Drawing.Size(158, 22);
+            this.examplePictureToolStripMenuItem.Size = new System.Drawing.Size(180, 22);
             this.examplePictureToolStripMenuItem.Text = "Example picture";
             this.examplePictureToolStripMenuItem.Click += new System.EventHandler(this.examplePictureToolStripMenuItem_Click);
             // 
@@ -172,6 +172,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 +183,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";
@@ -192,6 +194,7 @@ namespace SketchAssistant
             // 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";
@@ -202,6 +205,7 @@ namespace SketchAssistant
             // 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";

+ 131 - 94
SketchAssistant/SketchAssistant/Form1.cs

@@ -21,7 +21,7 @@ namespace SketchAssistant
         {
             InitializeComponent();
             ProgramPresenter = new MVP_Presenter(this);
-            fileImporter = new FileImporter(this);
+            fileImporter = new FileImporter();
         }
 
         /**********************************/
@@ -137,11 +137,12 @@ namespace SketchAssistant
 
         private void Form1_Load(object sender, EventArgs e)
         {
-            currentState = ProgramState.Idle;
             this.DoubleBuffered = true;
+            /*
+            currentState = ProgramState.Idle;
             historyOfActions = new ActionHistory(null);
             redrawAss = new RedrawAssistant();
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
 
         /// <summary>
@@ -151,16 +152,16 @@ namespace SketchAssistant
         {
             ProgramPresenter.Resize(new Tuple<int, int>(pictureBoxLeft.Width, pictureBoxLeft.Height), 
                 new Tuple<int, int>(pictureBoxRight.Width, pictureBoxRight.Height));
-            ///
+            /*
             this.Refresh();
-            UpdateSizes();
+            UpdateSizes();*/
         }
         
         //Load button, will open an OpenFileDialog
         private void loadToolStripMenuItem_Click(object sender, EventArgs e)
         {
             ProgramPresenter.LoadToolStripMenuItemClick();
-            ///
+            /*
             openFileDialog.Filter = "Image|*.jpg;*.png;*.jpeg";
             if(openFileDialog.ShowDialog() == DialogResult.OK)
             {
@@ -171,6 +172,7 @@ namespace SketchAssistant
                 this.Refresh();
             }
             UpdateButtonStatus();
+            */
         }
 
         /// <summary>
@@ -179,7 +181,7 @@ namespace SketchAssistant
         private void examplePictureToolStripMenuItem_Click(object sender, EventArgs e)
         {
             ProgramPresenter.ExamplePictureToolStripMenuItemClick();
-            ///
+            /*
             if (CheckSavedStatus())
             {
                 openFileDialog.Filter = "Interactive Sketch-Assistant Drawing|*.isad";
@@ -212,6 +214,7 @@ namespace SketchAssistant
                 }
             }
             UpdateButtonStatus();
+            */
         }
 
         /// <summary>
@@ -220,7 +223,7 @@ namespace SketchAssistant
         private void drawButton_Click(object sender, EventArgs e)
         {
             ProgramPresenter.ChangeState(true);
-            ///
+            /*
             if(rightImage != null)
             {
                 if (currentState.Equals(ProgramState.Draw))
@@ -232,7 +235,7 @@ namespace SketchAssistant
                     ChangeState(ProgramState.Draw);
                 }
             }
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
 
         /// <summary>
@@ -241,7 +244,7 @@ namespace SketchAssistant
         private void deleteButton_Click(object sender, EventArgs e)
         {
             ProgramPresenter.ChangeState(false);
-            ///
+            /*
             if (rightImage != null)
             {
                 if (currentState.Equals(ProgramState.Delete))
@@ -253,7 +256,7 @@ namespace SketchAssistant
                     ChangeState(ProgramState.Delete);
                 }
             }
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
 
         /// <summary>
@@ -262,7 +265,7 @@ namespace SketchAssistant
         private void undoButton_Click(object sender, EventArgs e)
         {
             ProgramPresenter.Undo();
-            ///
+            /*
             if (historyOfActions.CanUndo())
             {
                 HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
@@ -284,7 +287,7 @@ namespace SketchAssistant
                 RedrawRightImage();
             }
             historyOfActions.MoveAction(true);
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
 
         /// <summary>
@@ -293,7 +296,7 @@ namespace SketchAssistant
         private void redoButton_Click(object sender, EventArgs e)
         {
             ProgramPresenter.Redo();
-            ///
+            /*
             if (historyOfActions.CanRedo())
             {
                 historyOfActions.MoveAction(false);
@@ -315,7 +318,7 @@ namespace SketchAssistant
                 overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
                 RedrawRightImage();
             }
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
 
         /// <summary>
@@ -339,8 +342,8 @@ namespace SketchAssistant
         private void pictureBoxRight_MouseMove(object sender, MouseEventArgs e)
         {
             ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, e);
-            ///
-            currentCursorPosition = ConvertCoordinates(new Point(e.X, e.Y));
+            
+            //currentCursorPosition = ConvertCoordinates(new Point(e.X, e.Y));
         }
         
         /// <summary>
@@ -349,12 +352,12 @@ namespace SketchAssistant
         private void pictureBoxRight_MouseDown(object sender, MouseEventArgs e)
         {
             ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down, e);
-            ///
+            /*
             mousePressed = true;
             if (currentState.Equals(ProgramState.Draw))
             {
                 currentLine = new List<Point>();
-            }
+            }*/
         }
         
         /// <summary>
@@ -363,7 +366,7 @@ namespace SketchAssistant
         private void pictureBoxRight_MouseUp(object sender, MouseEventArgs e)
         {
             ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up, e);
-            ///
+            /*
             mousePressed = false;
             if (currentState.Equals(ProgramState.Draw) && currentLine.Count > 0)
             {
@@ -375,7 +378,7 @@ namespace SketchAssistant
                 overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, newLine.GetID(), true);
                 RedrawRightImage();
             }
-            UpdateButtonStatus();
+            UpdateButtonStatus();*/
         }
         
         /// <summary>
@@ -386,7 +389,7 @@ namespace SketchAssistant
         private void canvasButton_Click(object sender, EventArgs e)
         {
             ProgramPresenter.NewCanvas();
-            ///
+            /*
             if (CheckSavedStatus())
             {
                 historyOfActions = new ActionHistory(lastActionTakenLabel);
@@ -405,7 +408,7 @@ namespace SketchAssistant
                 }
             }
             UpdateButtonStatus();
-            UpdateSizes();
+            UpdateSizes();*/
         }
 
         /// <summary>
@@ -415,7 +418,7 @@ namespace SketchAssistant
         private void mouseTimer_Tick(object sender, EventArgs e)
         {
             ProgramPresenter.Tick();
-            ///
+            /*
             if(cursorPositions.Count > 0) { previousCursorPosition = cursorPositions.Dequeue(); }
             else { previousCursorPosition = currentCursorPosition; }
             cursorPositions.Enqueue(currentCursorPosition);
@@ -451,7 +454,111 @@ namespace SketchAssistant
                         RedrawRightImage();
                     }
                 }
+            }*/
+        }
+
+        /*************************/
+        /*** PRESENTER -> VIEW ***/
+        /*************************/
+
+        public void EnableTimer()
+        {
+            mouseTimer.Enabled = true;
+        }
+
+        /// <summary>
+        /// A function that opens a file dialog and returns the filename.
+        /// </summary>
+        /// <param name="Filter">The filter that should be applied to the new Dialog.</param>
+        /// <returns>Returns the FileName and the SafeFileName if the user correctly selects a file, 
+        /// else returns a tuple with empty strigns</returns>
+        public Tuple<String, String> openNewDialog(String Filter)
+        {
+            openFileDialog.Filter = Filter;
+            if (openFileDialog.ShowDialog() == DialogResult.OK)
+            {
+                return new Tuple<string, string>(openFileDialog.FileName, openFileDialog.SafeFileName);
             }
+            else
+            {
+                return new Tuple<string, string>("", "");
+            }
+        }
+
+        public void SetToolStripLoadStatus(String message)
+        {
+            toolStripLoadStatus.Text = message;
+        }
+
+        public void SetLastActionTakenText(String message)
+        {
+            lastActionTakenLabel.Text = message;
+        }
+
+        public void SetToolStripButtonStatus(String buttonName, ButtonState state)
+        {
+            ToolStripButton buttonToChange;
+            switch (buttonName)
+            {
+                case "canvasButton":
+                    buttonToChange = canvasButton;
+                    break;
+                case "drawButton":
+                    buttonToChange = drawButton;
+                    break;
+                case "deleteButton":
+                    buttonToChange = deleteButton;
+                    break;
+                case "undoButton":
+                    buttonToChange = undoButton;
+                    break;
+                case "redoButton":
+                    buttonToChange = redoButton;
+                    break;
+                default:
+                    Console.WriteLine("Invalid Button was given to SetToolStripButton. \nMaybe you forgot to add a case?");
+                    return;
+            }
+            switch (state)
+            {
+                case ButtonState.Active:
+                    buttonToChange.Checked = true;
+                    break;
+                case ButtonState.Disabled:
+                    buttonToChange.Checked = false;
+                    buttonToChange.Enabled = false;
+                    break;
+                case ButtonState.Enabled:
+                    buttonToChange.Checked = false;
+                    buttonToChange.Enabled = true;
+                    break;
+            }
+        }
+
+        public void DisplayInLeftPictureBox(Image img)
+        {
+            pictureBoxLeft.Image = img;
+            pictureBoxLeft.Refresh();
+        }
+
+        public void DisplayInRightPictureBox(Image img)
+        {
+            pictureBoxRight.Image = img;
+            pictureBoxRight.Refresh();
+        }
+
+        /// <summary>
+        /// shows the given info message in a popup and asks the user to aknowledge it
+        /// </summary>
+        /// <param name="message">the message to show</param>
+        public void ShowInfoMessage(String message)
+        {
+            MessageBox.Show(message);
+        }
+
+        public bool ShowWarning(String message)
+        {
+            return (MessageBox.Show(message, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
         }
 
         /***********************************/
@@ -790,76 +897,6 @@ namespace SketchAssistant
             return true;
         }
 
-        /************************************************/
-        /*** FUNCTIONS FOR MANIPULATING THE FORM HERE ***/
-        /************************************************/
-
-        public void SetToolStripLoadStatus(String message)
-        {
-            toolStripLoadStatus.Text = message;
-        }
-
-        public void SetToolStripButtonStatus(String buttonName, ButtonState state)
-        {
-            ToolStripButton buttonToChange;
-            switch (buttonName)
-            {
-                case "canvasButton":
-                    buttonToChange = canvasButton;
-                    break;
-                case "drawButton":
-                    buttonToChange = drawButton;
-                    break;
-                case "deleteButton":
-                    buttonToChange = deleteButton;
-                    break;
-                case "undoButton":
-                    buttonToChange = undoButton;
-                    break;
-                case "redoButton":
-                    buttonToChange = redoButton;
-                    break;
-                default:
-                    Console.WriteLine("Invalid Button was given to SetToolStripButton. \nMaybe you forgot to add a case?");
-                    return;
-            }
-            switch (state)
-            {
-                case ButtonState.Active:
-                    buttonToChange.Checked = true;
-                    break;
-                case ButtonState.Disabled:
-                    buttonToChange.Checked = false;
-                    buttonToChange.Enabled = false;
-                    break;
-                case ButtonState.Enabled:
-                    buttonToChange.Checked = false;
-                    buttonToChange.Enabled = true;
-                    break;
-            }
-        }
-
-        public void DisplayInLeftPictureBox(Image img)
-        {
-            pictureBoxLeft.Image = img;
-            this.Refresh();
-        }
-
-        public void DisplayInRightPictureBox(Image img)
-        {
-            pictureBoxRight.Image = img;
-            this.Refresh();
-        }
-
-        /// <summary>
-        /// shows the given info message in a popup and asks the user to aknowledge it
-        /// </summary>
-        /// <param name="message">the message to show</param>
-        public void ShowInfoMessage(String message)
-        {
-            MessageBox.Show(message);
-        }
-
         /********************************************/
         /*** TESTING RELATED FUNCTIONS START HERE ***/
         /********************************************/

+ 255 - 89
SketchAssistant/SketchAssistant/MVP_Model.cs

@@ -30,8 +30,13 @@ namespace SketchAssistant
         /*** 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
@@ -100,14 +105,15 @@ namespace SketchAssistant
         public MVP_Model(MVP_Presenter presenter)
         {
             programPresenter = presenter;
-            historyOfActions = new ActionHistory(null);
+            historyOfActions = new ActionHistory();
             redrawAss = new RedrawAssistant();
+            rightLineList = new List<Tuple<bool, Line>>();
+            overlayItems = new List<Tuple<bool, HashSet<Point>>>();
         }
-        
-        public void Undo()
-        {
 
-        }
+        /**************************/
+        /*** INTERNAL FUNCTIONS ***/
+        /**************************/
 
         /// <summary>
         /// A function that returns a white canvas for a given width and height.
@@ -133,21 +139,6 @@ namespace SketchAssistant
             return image;
         }
         
-        /// <summary>
-        /// Creates an empty Canvas
-        /// </summary>
-        private void DrawEmptyCanvasRight()
-        {
-            if (leftImage == null)
-            {
-                rightImageWithoutOverlay = GetEmptyCanvas(leftImageBoxWidth, leftImageBoxHeight);
-            }
-            else
-            {
-                rightImageWithoutOverlay = GetEmptyCanvas(leftImage.Width, leftImage.Height);
-            }
-            RefreshRightImage();
-        }
 
         /// <summary>
         /// Creates an empty Canvas on the left
@@ -164,29 +155,11 @@ namespace SketchAssistant
             {
                 leftImage = GetEmptyCanvas(width, height);
             }
-            RefreshLeftImage();
-        }
-
-        /// <summary>
-        /// A function to refresh the image being displayed in the right picture box, with the current rightImageWithOverlay.
-        /// </summary>
-        /// <param name="image">The new Image</param>
-        private void RefreshRightImage()
-        {
-            programPresenter.UpdateRightImage(rightImageWithOverlay);
-        }
-
-        /// <summary>
-        /// A function to refresh the image being displayed in the left picture box, with the current leftImage.
-        /// </summary>
-        /// <param name="image">The new Image</param>
-        private void RefreshLeftImage()
-        {
             programPresenter.UpdateLeftImage(leftImage);
         }
 
         /// <summary>
-        /// Redraws all lines in lineList, for which their associated boolean value equals true and calls RedrawRightOverlay.
+        /// Redraws all lines in rightLineList, for which their associated boolean value equals true and calls RedrawRightOverlay.
         /// </summary>
         private void RedrawRightImage()
         {
@@ -207,9 +180,15 @@ namespace SketchAssistant
                 currLine.DrawLine(workingGraph);
             }
             rightImageWithoutOverlay = workingCanvas;
-            //Redraw the Overlay
-            RedrawRightOverlay();
-            RefreshRightImage();
+            //Redraw the Overlay if needed
+            if (leftImage != null)
+            {
+                RedrawRightOverlay();
+            }
+            else
+            {
+                programPresenter.UpdateRightImage(rightImageWithoutOverlay);
+            }
         }
 
         /// <summary>
@@ -230,17 +209,7 @@ namespace SketchAssistant
                 }
             }
             rightImageWithOverlay = workingCanvas;
-            RefreshRightImage();
-        }
-        
-        /// <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();
+            programPresenter.UpdateRightImage(rightImageWithOverlay);
         }
         
         /// <summary>
@@ -280,7 +249,7 @@ namespace SketchAssistant
                 }
             }
         }
-        /*
+
         /// <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.
@@ -294,7 +263,7 @@ namespace SketchAssistant
 
             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 (pnt.X >= 0 && pnt.Y >= 0 && pnt.X < rightImageWithoutOverlay.Width && pnt.Y < rightImageWithoutOverlay.Height)
                 {
                     if (isFilledMatrix[pnt.X, pnt.Y])
                     {
@@ -305,6 +274,7 @@ namespace SketchAssistant
             return returnSet;
         }
 
+        /*
         /// <summary>
         /// binds the given picture to templatePicture and draws it
         /// </summary>
@@ -332,44 +302,148 @@ namespace SketchAssistant
             return currentLineEndings;
         }
         */
+
+
+
         /// <summary>
-        /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
+        /// Tells the Presenter to Update the UI
         /// </summary>
-        public void UpdateSizes()
+        private void UpdateUI()
         {
-            if (rightImageWithoutOverlay != null)
+            programPresenter.UpdateUIState(inDrawingMode, historyOfActions.CanUndo(), historyOfActions.CanRedo(), (rightImageWithoutOverlay != null));
+        }
+
+
+        /*
+        /// <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())
             {
-                int widthImage = rightImageWithoutOverlay.Width;
-                int heightImage = rightImageWithoutOverlay.Height;
-                int widthBox = rightImageBoxWidth;
-                int heightBox = rightImageBoxHeight;
+                return (MessageBox.Show("You have unsaved changes, do you wish to continue?",
+                    "Attention", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
+            }
+            return true;
+        }
+        */
 
-                float imageRatio = (float)widthImage / (float)heightImage;
-                float containerRatio = (float)widthBox / (float)heightBox;
-                float zoomFactor = 0;
-                if (imageRatio >= containerRatio)
+        /********************************************/
+        /*** 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;
+            //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>>();
+        }
+
+        public void Undo()
+        {
+            if (historyOfActions.CanUndo())
+            {
+                HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
+                SketchAction.ActionType undoAction = historyOfActions.GetCurrentAction().GetActionType();
+                switch (undoAction)
                 {
-                    //Image is wider than it is high
-                    zoomFactor = (float)widthImage / (float)widthBox;
+                    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;
                 }
-                else
+                if(leftImage != null)
                 {
-                    //Image is higher than it is wide
-                    zoomFactor = (float)heightImage / (float)heightBox;
+                    //overlayItems = redrawAss.Tick(currentCursorPosition, rightLineList, -1, false);
                 }
-                markerRadius = (int)(10 * zoomFactor);
-                redrawAss.SetMarkerRadius(markerRadius);
-                deletionRadius = (int)(5 * zoomFactor);
+                RedrawRightImage();
             }
+            RepopulateDeletionMatrixes();
+            programPresenter.PassLastActionTaken(historyOfActions.MoveAction(true));
+            UpdateUI();
         }
 
+        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>
-        /// Tells the Presenter to Update the UI
+        /// The function called by the Presenter to change the drawing state of the program.
         /// </summary>
-        private void UpdateUI()
+        /// <param name="nowDrawing">The new drawingstate of the program</param>
+        public void ChangeState(bool nowDrawing)
         {
-            programPresenter.UpdateUIState(inDrawingMode, historyOfActions.CanUndo(), historyOfActions.CanRedo(), (rightImageWithoutOverlay != null));
+            inDrawingMode = nowDrawing;
+            UpdateUI();
         }
 
         /// <summary>
@@ -378,7 +452,7 @@ namespace SketchAssistant
         /// <returns>A tuple containing the width and height of the right image.</returns>
         public Tuple<int, int> GetRightImageDimensions()
         {
-            if(rightImageWithoutOverlay != null)
+            if (rightImageWithoutOverlay != null)
             {
                 return new Tuple<int, int>(rightImageWithoutOverlay.Width, rightImageWithoutOverlay.Height);
             }
@@ -390,23 +464,115 @@ namespace SketchAssistant
 
         public void SetCurrentCursorPosition(Point p)
         {
+            currentCursorPosition = p;
+        }
 
+        public void MouseDown()
+        {
+            mousePressed = true;
+            if (inDrawingMode)
+            {
+                currentLine = new List<Point>();
+            }
         }
-        /*
+
+        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();
+        }
+
+        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>
-        /// Checks if there is unsaved progess, and warns the user. Returns True if it safe to continue.
+        /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
         /// </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()
+        public void UpdateSizes()
         {
-            if (!historyOfActions.IsEmpty())
+            if (rightImageWithoutOverlay != null)
             {
-                return (MessageBox.Show("You have unsaved changes, do you wish to continue?",
-                    "Attention", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes);
+                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);
             }
-            return true;
         }
-        */
+
+        /// <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();
+        }
     }
 }

+ 39 - 48
SketchAssistant/SketchAssistant/MVP_Presenter.cs

@@ -35,10 +35,6 @@ namespace SketchAssistant
         /*** CLASS VARIABLES ***/
         /***********************/
 
-        /// <summary>
-        /// A dialog responsible for opening files.
-        /// </summary>
-        OpenFileDialog openFileDialog;
         /// <summary>
         /// Instance of FileImporter to handle drawing imports.
         /// </summary>
@@ -50,7 +46,6 @@ namespace SketchAssistant
             programView = form;
             programModel = new MVP_Model(this);
             //Initialize Class Variables
-            openFileDialog = new OpenFileDialog();
             fileImporter = new FileImporter();
         }
 
@@ -69,21 +64,15 @@ namespace SketchAssistant
         }
 
         /// <summary>
-        /// Display a new FileDialog to load an image.
+        /// Display a new FileDialog to load an image of type jpg or png.
         /// </summary>
         public void LoadToolStripMenuItemClick()
         {
-            openFileDialog.Filter = "Image|*.jpg;*.png;*.jpeg";
-            if (openFileDialog.ShowDialog() == DialogResult.OK)
+            var fileNameTup = programView.openNewDialog("Image|*.jpg;*.png;*.jpeg");
+            if(!fileNameTup.Item1.Equals("") && !fileNameTup.Item2.Equals(""))
             {
-                ProgramView.SetToolStripLoadStatus(openFileDialog.SafeFileName);
-                ProgramModel
-                leftImage = Image.FromFile(openFileDialog.FileName);
-                pictureBoxLeft.Image = leftImage;
-                //Refresh the left image box when the content is changed
-                this.Refresh();
+
             }
-            UpdateButtonStatus();
         }
 
         /// <summary>
@@ -91,38 +80,23 @@ namespace SketchAssistant
         /// </summary>
         public void ExamplePictureToolStripMenuItemClick()
         {
-            if (ProgramModel.CheckSavedStatus())
+            var okToContinue = true;
+            if (programModel.HasUnsavedProgress())
+            {
+                okToContinue = programView.ShowWarning("You have unsaved progress. Continue?");
+            }
+            if (okToContinue)
             {
-                openFileDialog.Filter = "Interactive Sketch-Assistant Drawing|*.isad";
-                if (openFileDialog.ShowDialog() == DialogResult.OK)
+                var fileNameTup = programView.openNewDialog("Interactive Sketch-Assistant Drawing|*.isad");
+                if (!fileNameTup.Item1.Equals("") && !fileNameTup.Item2.Equals(""))
                 {
-                    ProgramView.SetToolStripLoadStatus(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());
-                    }
+                    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();
                 }
             }
-            UpdateButtonStatus();
         }
 
         public void ChangeState(bool NowDrawing)
@@ -132,22 +106,32 @@ namespace SketchAssistant
 
         public void Undo()
         {
-
+            programModel.Undo();
         }
 
         public void Redo()
         {
-
+            programModel.Redo();
         }
 
         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();
+            }
         }
 
         public void Tick()
         {
-
+            programModel.Tick();
         }
 
         public void MouseEvent(MouseAction mouseAction, MouseEventArgs e)
@@ -157,8 +141,10 @@ namespace SketchAssistant
                 case MouseAction.Click:
                     break;
                 case MouseAction.Down:
+                    programModel.MouseDown();
                     break;
                 case MouseAction.Up:
+                    programModel.MouseUp();
                     break;
                 case MouseAction.Move:
                     programModel.SetCurrentCursorPosition(ConvertCoordinates(new Point(e.X, e.Y)));
@@ -181,7 +167,7 @@ namespace SketchAssistant
         public void UpdateUIState(bool inDrawingMode, bool canUndo, bool canRedo, bool imageLoaded)
         {
             Dictionary<String, Form1.ButtonState> dict = new Dictionary<String, Form1.ButtonState> {
-                {"canvasButton", Form1.ButtonState.Disabled }, {"drawButton", Form1.ButtonState.Disabled}, {"deleteButton",Form1.ButtonState.Disabled }
+                {"canvasButton", Form1.ButtonState.Enabled }, {"drawButton", Form1.ButtonState.Disabled}, {"deleteButton",Form1.ButtonState.Disabled },
                 {"undoButton", Form1.ButtonState.Disabled },{"redoButton",  Form1.ButtonState.Disabled}};
 
             if (imageLoaded)
@@ -228,6 +214,11 @@ namespace SketchAssistant
             programView.ShowInfoMessage(msg);
         }
 
+        public void PassLastActionTaken(String msg)
+        {
+            programView.SetLastActionTakenText(msg);
+        }
+
         /*************************/
         /*** HELPING FUNCTIONS ***/
         /*************************/