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
{
///
/// The View of the MVP-Model, in this case Form1.
///
MVP_View programView;
///
/// The Model of the MVP-Model.
///
MVP_Model programModel;
/*******************/
/*** ENUMERATORS ***/
/*******************/
public enum MouseAction
{
Click,
Down,
Up,
Move
}
/***********************/
/*** CLASS VARIABLES ***/
/***********************/
///
/// Instance of FileImporter to handle drawing imports.
///
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 ***/
/***********************************/
///
/// Pass-trough function to update the appropriate information of the model, when the window is resized.
///
/// The new size of the left picture box.
/// The new size of the left picture box.
public void Resize(Tuple leftPBS,Tuple rightPBS)
{
programModel.leftImageBoxWidth = leftPBS.Item1;
programModel.leftImageBoxHeight = leftPBS.Item2;
programModel.rightImageBoxWidth = rightPBS.Item1;
programModel.rightImageBoxHeight = rightPBS.Item2;
programModel.UpdateSizes();
}
///
/// Display a new FileDialog to load a collection of lines.
///
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);
Tuple> values = fileImporter.ParseISADInputFile(fileNameTup.Item1);
programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
programModel.ChangeState(true);
programView.EnableTimer();
}
}
}
public void SVGToolStripMenuItemClick()
{
var okToContinue = true;
if (programModel.HasUnsavedProgress())
{
okToContinue = programView.ShowWarning("You have unsaved progress. Continue?");
}
if (okToContinue)
{
var fileNameTup = programView.openNewDialog("Scalable Vector Graphics|*.svg");
if (!fileNameTup.Item1.Equals("") && !fileNameTup.Item2.Equals(""))
{
programView.SetToolStripLoadStatus(fileNameTup.Item2);
try
{
Tuple> values = fileImporter.ParseSVGInputFile(fileNameTup.Item1, programModel.leftImageBoxWidth, programModel.leftImageBoxHeight);
programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
programModel.ChangeState(true);
programView.EnableTimer();
}
catch (FileImporterException ex)
{
programView.ShowInfoMessage(ex.ToString());
}
catch (Exception ex)
{
programView.ShowInfoMessage("exception occured while trying to parse svg file:\n\n" + ex.ToString() + "\n\n" + ex.StackTrace);
}
}
}
}
///
/// Pass-trough function to change the drawing state of the model.
///
/// Indicates if the program is in drawing (true) or deletion (false) mode.
public void ChangeState(bool NowDrawing)
{
programModel.ChangeState(NowDrawing);
}
///
/// Pass-trough function to undo an action.
///
public void Undo()
{
programModel.Undo();
}
///
/// Pass-trough function to redo an action.
///
public void Redo()
{
programModel.Redo();
}
///
/// Checks if there is unsaved progress, and promts the model to generate a new canvas if not.
///
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();
}
}
///
/// Pass-trough function for ticking the model.
///
public void Tick()
{
programModel.Tick();
}
///
/// Pass-trough when the mouse is moved.
///
/// The action which is sent by the View.
/// The Mouse event arguments.
public void MouseEvent(MouseAction mouseAction, MouseEventArgs e)
{
switch (mouseAction)
{
case MouseAction.Move:
programModel.SetCurrentCursorPosition(ConvertCoordinates(new Point(e.X, e.Y)));
break;
default:
break;
}
}
///
/// Pass-trough function that calls the correct Mouse event of the model, when the mouse is clicked.
///
/// The action which is sent by the View.
/// The Mouse event arguments.
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 ***/
/************************************/
///
/// 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.
///
/// If the model is in Drawing Mode
/// If actions in the model can be undone
/// If actions in the model can be redone
/// If an image is loaded in the model
public void UpdateUIState(bool inDrawingMode, bool canUndo, bool canRedo, bool imageLoaded)
{
Dictionary dict = new Dictionary {
{"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 entry in dict)
{
programView.SetToolStripButtonStatus(entry.Key, entry.Value);
}
}
///
/// Is called by the model when the left image is changed.
///
/// The new image.
public void UpdateLeftImage(Image img)
{
programView.DisplayInLeftPictureBox(img);
}
///
/// Is called by the model when the right image is changed.
///
/// The new image.
public void UpdateRightImage(Image img)
{
programView.DisplayInRightPictureBox(img);
}
///
/// Pass-trough function to display an info message in the view.
///
/// The message.
public void PassMessageToView(String msg)
{
programView.ShowInfoMessage(msg);
}
///
/// Pass-trough function to update the display of the last action taken.
///
/// The new last action taken.
public void PassLastActionTaken(String msg)
{
programView.SetLastActionTakenText(msg);
}
/*************************/
/*** HELPING FUNCTIONS ***/
/*************************/
///
/// A function that calculates the coordinates of a point on a zoomed in image.
///
/// The position of the mouse cursor
/// The real coordinates of the mouse cursor on the image
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;
}
}
}