Form1.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Drawing.Imaging;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using System.Windows.Forms;
  11. using System.Text.RegularExpressions;
  12. using System.IO;
  13. using System.Text;
  14. // This is the code for your desktop app.
  15. // Press Ctrl+F5 (or go to Debug > Start Without Debugging) to run your app.
  16. namespace SketchAssistant
  17. {
  18. public partial class Form1 : Form
  19. {
  20. public Form1()
  21. {
  22. InitializeComponent();
  23. fileImporter = new FileImporter(this);
  24. }
  25. /**********************************/
  26. /*** CLASS VARIABLES START HERE ***/
  27. /**********************************/
  28. //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()
  29. /// <summary>
  30. /// Different Program States
  31. /// </summary>
  32. public enum ProgramState
  33. {
  34. Idle,
  35. Draw,
  36. Delete
  37. }
  38. /// <summary>
  39. /// Current Program State
  40. /// </summary>
  41. private ProgramState currentState;
  42. /// <summary>
  43. /// instance of FileImporter to handle drawing imports
  44. /// </summary>
  45. private FileImporter fileImporter;
  46. /// <summary>
  47. /// Dialog to select a file.
  48. /// </summary>
  49. OpenFileDialog openFileDialog = new OpenFileDialog();
  50. /// <summary>
  51. /// Image loaded on the left
  52. /// </summary>
  53. private Image leftImage = null;
  54. /// <summary>
  55. /// the graphic shown in the left window, represented as a list of polylines
  56. /// </summary>
  57. private List<Line> leftLineList;
  58. /// <summary>
  59. /// Image on the right
  60. /// </summary>
  61. Image rightImage = null;
  62. /// <summary>
  63. /// Current Line being Drawn
  64. /// </summary>
  65. List<Point> currentLine;
  66. /// <summary>
  67. /// All Lines in the current session
  68. /// </summary>
  69. List<Tuple<bool,Line>> rightLineList = new List<Tuple<bool, Line>>();
  70. /// <summary>
  71. /// Whether the Mouse is currently pressed in the rightPictureBox
  72. /// </summary>
  73. bool mousePressed = false;
  74. /// <summary>
  75. /// The Position of the Cursor in the right picture box
  76. /// </summary>
  77. Point currentCursorPosition;
  78. /// <summary>
  79. /// The Previous Cursor Position in the right picture box
  80. /// </summary>
  81. Point previousCursorPosition;
  82. /// <summary>
  83. /// Queue for the cursorPositions
  84. /// </summary>
  85. Queue<Point> cursorPositions = new Queue<Point>();
  86. /// <summary>
  87. /// The graphic representation of the right image
  88. /// </summary>
  89. Graphics rightGraph = null;
  90. /// <summary>
  91. /// Deletion Matrixes for checking postions of lines in the image
  92. /// </summary>
  93. bool[,] isFilledMatrix;
  94. HashSet<int>[,] linesMatrix;
  95. /// <summary>
  96. /// Size of deletion area
  97. /// </summary>
  98. uint deletionSize = 2;
  99. /// <summary>
  100. /// History of Actions
  101. /// </summary>
  102. ActionHistory historyOfActions;
  103. /// <summary>
  104. ///Dialog to save a file
  105. /// </summary>
  106. SaveFileDialog saveFileDialogRight = new SaveFileDialog();
  107. /******************************************/
  108. /*** FORM SPECIFIC FUNCTIONS START HERE ***/
  109. /******************************************/
  110. private void Form1_Load(object sender, EventArgs e)
  111. {
  112. currentState = ProgramState.Idle;
  113. this.DoubleBuffered = true;
  114. historyOfActions = new ActionHistory(null);
  115. UpdateButtonStatus();
  116. }
  117. //Resize Function connected to the form resize event, will refresh the form when it is resized
  118. private void Form1_Resize(object sender, System.EventArgs e)
  119. {
  120. this.Refresh();
  121. }
  122. //Load button, will open an OpenFileDialog
  123. private void loadToolStripMenuItem_Click(object sender, EventArgs e)
  124. {
  125. openFileDialog.Filter = "Image|*.jpg;*.png;*.jpeg";
  126. if(openFileDialog.ShowDialog() == DialogResult.OK)
  127. {
  128. toolStripLoadStatus.Text = openFileDialog.SafeFileName;
  129. leftImage = Image.FromFile(openFileDialog.FileName);
  130. pictureBoxLeft.Image = leftImage;
  131. //Refresh the left image box when the content is changed
  132. this.Refresh();
  133. }
  134. UpdateButtonStatus();
  135. }
  136. /// <summary>
  137. /// Import button, will open an OpenFileDialog
  138. /// </summary>
  139. private void examplePictureToolStripMenuItem_Click(object sender, EventArgs e)
  140. {
  141. openFileDialog.Filter = "Interactive Sketch-Assistant Drawing|*.isad";
  142. if (openFileDialog.ShowDialog() == DialogResult.OK)
  143. {
  144. toolStripLoadStatus.Text = openFileDialog.SafeFileName;
  145. try
  146. {
  147. (int, int, List<Line>) values = fileImporter.ParseISADInputFile(openFileDialog.FileName);
  148. DrawEmptyCanvasLeft(values.Item1, values.Item2);
  149. BindAndDrawLeftImage(values.Item3);
  150. this.Refresh();
  151. }
  152. catch(FileImporterException ex)
  153. {
  154. ShowInfoMessage(ex.ToString());
  155. }
  156. }
  157. }
  158. //Changes the state of the program to drawing
  159. private void drawButton_Click(object sender, EventArgs e)
  160. {
  161. if(rightImage != null)
  162. {
  163. if (currentState.Equals(ProgramState.Draw))
  164. {
  165. ChangeState(ProgramState.Idle);
  166. }
  167. else
  168. {
  169. ChangeState(ProgramState.Draw);
  170. }
  171. }
  172. UpdateButtonStatus();
  173. }
  174. //Changes the state of the program to deletion
  175. private void deleteButton_Click(object sender, EventArgs e)
  176. {
  177. if (rightImage != null)
  178. {
  179. if (currentState.Equals(ProgramState.Delete))
  180. {
  181. ChangeState(ProgramState.Idle);
  182. }
  183. else
  184. {
  185. ChangeState(ProgramState.Delete);
  186. }
  187. }
  188. UpdateButtonStatus();
  189. }
  190. //Undo an action
  191. private void undoButton_Click(object sender, EventArgs e)
  192. {
  193. if (historyOfActions.CanUndo())
  194. {
  195. HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
  196. SketchAction.ActionType undoAction = historyOfActions.GetCurrentAction().GetActionType();
  197. switch (undoAction)
  198. {
  199. case SketchAction.ActionType.Delete:
  200. //Deleted Lines need to be shown
  201. ChangeLines(affectedLines, true);
  202. break;
  203. case SketchAction.ActionType.Draw:
  204. //Drawn lines need to be hidden
  205. ChangeLines(affectedLines, false);
  206. break;
  207. default:
  208. break;
  209. }
  210. }
  211. historyOfActions.MoveAction(true);
  212. UpdateButtonStatus();
  213. }
  214. //Redo an action
  215. private void redoButton_Click(object sender, EventArgs e)
  216. {
  217. if (historyOfActions.CanRedo())
  218. {
  219. historyOfActions.MoveAction(false);
  220. HashSet<int> affectedLines = historyOfActions.GetCurrentAction().GetLineIDs();
  221. SketchAction.ActionType redoAction = historyOfActions.GetCurrentAction().GetActionType();
  222. switch (redoAction)
  223. {
  224. case SketchAction.ActionType.Delete:
  225. //Deleted Lines need to be redeleted
  226. ChangeLines(affectedLines, false);
  227. break;
  228. case SketchAction.ActionType.Draw:
  229. //Drawn lines need to be redrawn
  230. ChangeLines(affectedLines, true);
  231. break;
  232. default:
  233. break;
  234. }
  235. }
  236. UpdateButtonStatus();
  237. }
  238. //Detect Keyboard Shortcuts
  239. private void Form1_KeyDown(object sender, KeyEventArgs e)
  240. {
  241. if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Z)
  242. {
  243. undoButton_Click(sender, e);
  244. }
  245. if (e.Modifiers == Keys.Control && e.KeyCode == Keys.Y)
  246. {
  247. redoButton_Click(sender, e);
  248. }
  249. }
  250. //get current Mouse positon within the right picture box
  251. private void pictureBoxRight_MouseMove(object sender, MouseEventArgs e)
  252. {
  253. currentCursorPosition = ConvertCoordinates(new Point(e.X, e.Y));
  254. }
  255. //hold left mouse button to draw.
  256. private void pictureBoxRight_MouseDown(object sender, MouseEventArgs e)
  257. {
  258. mousePressed = true;
  259. if (currentState.Equals(ProgramState.Draw))
  260. {
  261. currentLine = new List<Point>();
  262. }
  263. }
  264. //Lift left mouse button to stop drawing and add a new Line.
  265. private void pictureBoxRight_MouseUp(object sender, MouseEventArgs e)
  266. {
  267. mousePressed = false;
  268. if (currentState.Equals(ProgramState.Draw) && currentLine.Count > 0)
  269. {
  270. Line newLine = new Line(currentLine, rightLineList.Count);
  271. rightLineList.Add(new Tuple<bool, Line>(true, newLine));
  272. newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
  273. historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID()));
  274. }
  275. UpdateButtonStatus();
  276. }
  277. //Button to create a new Canvas. Will create an empty image
  278. //which is the size of the left image, if there is one.
  279. //If there is no image loaded the canvas will be the size of the right picture box
  280. private void canvasButton_Click(object sender, EventArgs e)
  281. {
  282. if (!historyOfActions.IsEmpty())
  283. {
  284. if (MessageBox.Show("You have unsaved changes, creating a new canvas will discard these.",
  285. "Attention", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
  286. {
  287. historyOfActions = new ActionHistory(lastActionTakenLabel);
  288. DrawEmptyCanvasRight();
  289. //The following lines cannot be in DrawEmptyCanvas()
  290. isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
  291. linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
  292. rightLineList = new List<Tuple<bool, Line>>();
  293. }
  294. }
  295. else
  296. {
  297. historyOfActions = new ActionHistory(lastActionTakenLabel);
  298. DrawEmptyCanvasRight();
  299. //The following lines cannot be in DrawEmptyCanvas()
  300. isFilledMatrix = new bool[rightImage.Width, rightImage.Height];
  301. linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
  302. rightLineList = new List<Tuple<bool, Line>>();
  303. }
  304. UpdateButtonStatus();
  305. }
  306. //add a Point on every tick to the Drawpath
  307. private void mouseTimer_Tick(object sender, EventArgs e)
  308. {
  309. cursorPositions.Enqueue(currentCursorPosition);
  310. previousCursorPosition = cursorPositions.Dequeue();
  311. if (currentState.Equals(ProgramState.Draw) && mousePressed)
  312. {
  313. currentLine.Add(currentCursorPosition);
  314. Line drawline = new Line(currentLine);
  315. drawline.DrawLine(rightGraph);
  316. pictureBoxRight.Image = rightImage;
  317. }
  318. if (currentState.Equals(ProgramState.Delete) && mousePressed)
  319. {
  320. List<Point> uncheckedPoints = Line.BresenhamLineAlgorithm(previousCursorPosition, currentCursorPosition);
  321. foreach (Point currPoint in uncheckedPoints)
  322. {
  323. HashSet<int> linesToDelete = CheckDeletionMatrixesAroundPoint(currPoint, deletionSize);
  324. if (linesToDelete.Count > 0)
  325. {
  326. historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Delete, linesToDelete));
  327. foreach (int lineID in linesToDelete)
  328. {
  329. rightLineList[lineID] = new Tuple<bool, Line>(false, rightLineList[lineID].Item2);
  330. }
  331. RepopulateDeletionMatrixes();
  332. RedrawRightImage();
  333. }
  334. }
  335. }
  336. }
  337. //Save button, will open an SaveFileDialog
  338. private void saveToolStripMenuItem_Click_1(object sender, EventArgs e)
  339. {
  340. if (rightImage != null)
  341. {
  342. saveFileDialogRight.Filter = "Image|*.jpg;*.png;*.jpeg|" + "Vector Graphics|*.svg|" + "All files (*.*)|*.*";
  343. ImageFormat format = ImageFormat.Jpeg;
  344. if (saveFileDialogRight.ShowDialog() == DialogResult.OK)
  345. {
  346. switch (saveFileDialogRight.Filter)
  347. {
  348. case ".svg":
  349. String newReturnString = createSvgTxt();
  350. using (StreamWriter sw = new StreamWriter(File.Create(saveFileDialogRight.FileName)))
  351. {
  352. sw.Write("test");
  353. }
  354. break;
  355. case ".png":
  356. format = ImageFormat.Png;
  357. pictureBoxRight.Image.Save(saveFileDialogRight.FileName, format);
  358. break;
  359. case ".bmp":
  360. format = ImageFormat.Bmp;
  361. pictureBoxRight.Image.Save(saveFileDialogRight.FileName, format);
  362. break;
  363. default:
  364. pictureBoxRight.Image.Save(saveFileDialogRight.FileName, format);
  365. break;
  366. }
  367. }
  368. }
  369. else
  370. {
  371. MessageBox.Show("The right picture box can't be empty");
  372. }
  373. }
  374. /***********************************/
  375. /*** HELPER FUNCTIONS START HERE ***/
  376. /***********************************/
  377. /// <summary>
  378. /// Creates an empty Canvas
  379. /// </summary>
  380. private void DrawEmptyCanvasRight()
  381. {
  382. if (leftImage == null)
  383. {
  384. rightImage = new Bitmap(pictureBoxRight.Width, pictureBoxRight.Height);
  385. rightGraph = Graphics.FromImage(rightImage);
  386. rightGraph.FillRectangle(Brushes.White, 0, 0, pictureBoxRight.Width + 10, pictureBoxRight.Height + 10);
  387. pictureBoxRight.Image = rightImage;
  388. }
  389. else
  390. {
  391. rightImage = new Bitmap(leftImage.Width, leftImage.Height);
  392. rightGraph = Graphics.FromImage(rightImage);
  393. rightGraph.FillRectangle(Brushes.White, 0, 0, leftImage.Width + 10, leftImage.Height + 10);
  394. pictureBoxRight.Image = rightImage;
  395. }
  396. this.Refresh();
  397. pictureBoxRight.Refresh();
  398. }
  399. /// <summary>
  400. /// Creates an empty Canvas on the left
  401. /// </summary>
  402. /// <param name="width"> width of the new canvas in pixels </param>
  403. /// <param name="height"> height of the new canvas in pixels </param>
  404. private void DrawEmptyCanvasLeft(int width, int height)
  405. {
  406. if (width == 0)
  407. {
  408. leftImage = new Bitmap(pictureBoxLeft.Width, pictureBoxLeft.Height);
  409. }
  410. else
  411. {
  412. leftImage = new Bitmap(width, height);
  413. }
  414. Graphics.FromImage(leftImage).FillRectangle(Brushes.White, 0, 0, pictureBoxLeft.Width + 10, pictureBoxLeft.Height + 10);
  415. pictureBoxLeft.Image = leftImage;
  416. this.Refresh();
  417. pictureBoxLeft.Refresh();
  418. }
  419. /// <summary>
  420. /// Redraws all lines in lineList, for which their associated boolean value equals true.
  421. /// </summary>
  422. private void RedrawRightImage()
  423. {
  424. DrawEmptyCanvasRight();
  425. foreach (Tuple<bool, Line> lineBoolTuple in rightLineList)
  426. {
  427. if (lineBoolTuple.Item1)
  428. {
  429. lineBoolTuple.Item2.DrawLine(rightGraph);
  430. }
  431. }
  432. pictureBoxRight.Refresh();
  433. }
  434. /// <summary>
  435. /// Change the status of whether or not the lines are shown.
  436. /// </summary>
  437. /// <param name="lines">The HashSet containing the affected Line IDs.</param>
  438. /// <param name="shown">True if the lines should be shown, false if they should be hidden.</param>
  439. private void ChangeLines(HashSet<int> lines, bool shown)
  440. {
  441. foreach (int lineId in lines)
  442. {
  443. if (lineId <= rightLineList.Count - 1 && lineId >= 0)
  444. {
  445. rightLineList[lineId] = new Tuple<bool, Line>(shown, rightLineList[lineId].Item2);
  446. }
  447. }
  448. RedrawRightImage();
  449. }
  450. /// <summary>
  451. /// Updates the active status of buttons. Currently draw, delete, undo and redo button.
  452. /// </summary>
  453. private void UpdateButtonStatus()
  454. {
  455. undoButton.Enabled = historyOfActions.CanUndo();
  456. redoButton.Enabled = historyOfActions.CanRedo();
  457. drawButton.Enabled = (rightImage != null);
  458. deleteButton.Enabled = (rightImage != null);
  459. }
  460. /// <summary>
  461. /// A helper function which handles tasks associated witch changing states,
  462. /// such as checking and unchecking buttons and changing the state.
  463. /// </summary>
  464. /// <param name="newState">The new state of the program</param>
  465. private void ChangeState(ProgramState newState)
  466. {
  467. switch (currentState)
  468. {
  469. case ProgramState.Draw:
  470. drawButton.CheckState = CheckState.Unchecked;
  471. mouseTimer.Enabled = false;
  472. break;
  473. case ProgramState.Delete:
  474. deleteButton.CheckState = CheckState.Unchecked;
  475. mouseTimer.Enabled = false;
  476. break;
  477. default:
  478. break;
  479. }
  480. switch (newState)
  481. {
  482. case ProgramState.Draw:
  483. drawButton.CheckState = CheckState.Checked;
  484. mouseTimer.Enabled = true;
  485. break;
  486. case ProgramState.Delete:
  487. deleteButton.CheckState = CheckState.Checked;
  488. mouseTimer.Enabled = true;
  489. break;
  490. default:
  491. break;
  492. }
  493. currentState = newState;
  494. pictureBoxRight.Refresh();
  495. }
  496. /// <summary>
  497. /// A function that calculates the coordinates of a point on a zoomed in image.
  498. /// </summary>
  499. /// <param name="">The position of the mouse cursor</param>
  500. /// <returns>The real coordinates of the mouse cursor on the image</returns>
  501. private Point ConvertCoordinates(Point cursorPosition)
  502. {
  503. Point realCoordinates = new Point(5,3);
  504. if(pictureBoxRight.Image == null)
  505. {
  506. return cursorPosition;
  507. }
  508. int widthImage = pictureBoxRight.Image.Width;
  509. int heightImage = pictureBoxRight.Image.Height;
  510. int widthBox = pictureBoxRight.Width;
  511. int heightBox = pictureBoxRight.Height;
  512. float imageRatio = (float)widthImage / (float)heightImage;
  513. float containerRatio = (float)widthBox / (float)heightBox;
  514. if (imageRatio >= containerRatio)
  515. {
  516. //Image is wider than it is high
  517. float zoomFactor = (float)widthImage / (float)widthBox;
  518. float scaledHeight = heightImage / zoomFactor;
  519. float filler = (heightBox - scaledHeight) / 2;
  520. realCoordinates.X = (int)(cursorPosition.X * zoomFactor);
  521. realCoordinates.Y = (int)((cursorPosition.Y - filler) * zoomFactor);
  522. }
  523. else
  524. {
  525. //Image is higher than it is wide
  526. float zoomFactor = (float)heightImage / (float)heightBox;
  527. float scaledWidth = widthImage / zoomFactor;
  528. float filler = (widthBox - scaledWidth) / 2;
  529. realCoordinates.X = (int)((cursorPosition.X - filler) * zoomFactor);
  530. realCoordinates.Y = (int)(cursorPosition.Y * zoomFactor);
  531. }
  532. return realCoordinates;
  533. }
  534. /// <summary>
  535. /// A function that populates the matrixes needed for deletion detection with line data.
  536. /// </summary>
  537. private void RepopulateDeletionMatrixes()
  538. {
  539. if(rightImage != null)
  540. {
  541. isFilledMatrix = new bool[rightImage.Width,rightImage.Height];
  542. linesMatrix = new HashSet<int>[rightImage.Width, rightImage.Height];
  543. foreach(Tuple<bool,Line> lineTuple in rightLineList)
  544. {
  545. if (lineTuple.Item1)
  546. {
  547. lineTuple.Item2.PopulateMatrixes(isFilledMatrix, linesMatrix);
  548. }
  549. }
  550. }
  551. }
  552. /// <summary>
  553. /// A function that checks the deletion matrixes at a certain point
  554. /// and returns all Line ids at that point and in a square around it in a certain range.
  555. /// </summary>
  556. /// <param name="p">The point around which to check.</param>
  557. /// <param name="range">The range around the point. If range is 0, only the point is checked.</param>
  558. /// <returns>A List of all lines.</returns>
  559. private HashSet<int> CheckDeletionMatrixesAroundPoint(Point p, uint range)
  560. {
  561. HashSet<int> returnSet = new HashSet<int>();
  562. if (p.X >= 0 && p.Y >= 0 && p.X < rightImage.Width && p.Y < rightImage.Height)
  563. {
  564. if (isFilledMatrix[p.X, p.Y])
  565. {
  566. returnSet.UnionWith(linesMatrix[p.X, p.Y]);
  567. }
  568. }
  569. for (int x_mod = (int)range*(-1); x_mod < range; x_mod++)
  570. {
  571. for (int y_mod = (int)range * (-1); y_mod < range; y_mod++)
  572. {
  573. if (p.X + x_mod >= 0 && p.Y + y_mod >= 0 && p.X + x_mod < rightImage.Width && p.Y + y_mod < rightImage.Height)
  574. {
  575. if (isFilledMatrix[p.X + x_mod, p.Y + y_mod])
  576. {
  577. returnSet.UnionWith(linesMatrix[p.X + x_mod, p.Y + y_mod]);
  578. }
  579. }
  580. }
  581. }
  582. return returnSet;
  583. }
  584. /// <summary>
  585. /// binds the given picture to templatePicture and draws it
  586. /// </summary>
  587. /// <param name="newTemplatePicture"> the new template picture, represented as a list of polylines </param>
  588. /// <returns></returns>
  589. private void BindAndDrawLeftImage(List<Line> newTemplatePicture)
  590. {
  591. leftLineList = newTemplatePicture;
  592. foreach(Line l in leftLineList)
  593. {
  594. l.DrawLine(Graphics.FromImage(leftImage));
  595. }
  596. }
  597. /// <summary>
  598. /// shows the given info message in a popup and asks the user to aknowledge it
  599. /// </summary>
  600. /// <param name="message">the message to show</param>
  601. private void ShowInfoMessage(String message)
  602. {
  603. MessageBox.Show(message);
  604. }
  605. /// <summary>
  606. /// returns all instance variables in the order of their definition for testing
  607. /// </summary>
  608. /// <returns>all instance variables in the order of their definition</returns>
  609. public Object[]/*(ProgramState, FileImporter, OpenFileDialog, Image, List<Line>, Image, List<Point>, List<Tuple<bool, Line>>, bool, Point, Point, Queue<Point>, Graphics, bool[,], HashSet<int>[,], uint, ActionHistory)*/ GetAllVariables()
  610. {
  611. return new Object[] { currentState, fileImporter, openFileDialog, leftImage, leftLineList, rightImage, currentLine, rightLineList, mousePressed, currentCursorPosition, previousCursorPosition, cursorPositions, rightGraph, isFilledMatrix, linesMatrix, deletionSize, historyOfActions };
  612. }
  613. /// <summary>
  614. /// public method wrapper for testing purposes, invoking DrawEmptyCanvas(...) and BindAndDrawLeftImage(...)
  615. /// </summary>
  616. /// <param name="width">width of the parsed image</param>
  617. /// <param name="height">height of the parsed image</param>
  618. /// <param name="newImage">the parsed image</param>
  619. public void CreateCanvasAndSetPictureForTesting(int width, int height, List<Line> newImage)
  620. {
  621. DrawEmptyCanvasLeft(width, height);
  622. BindAndDrawLeftImage(newImage);
  623. }
  624. private String createSvgTxt()
  625. {
  626. String newString = String.Format("<svg viewBox = \"0 0 {0} {1}\" xmlns = \"http://www.w3.org/2000/svg\">", rightImage.Width, rightImage.Height);
  627. foreach (Tuple<bool, Line> lineTuple in rightLineList)
  628. {
  629. if (lineTuple.Item1 == true)
  630. {
  631. String nextLine = String.Format("\n" + "<line x1 = \"{0}\" y1 = \"{1}\" x2 = \"{2}\" y2 = \"{3}\" stroke = \"black\">",
  632. lineTuple.Item2.GetStartPoint().X, lineTuple.Item2.GetStartPoint().Y, lineTuple.Item2.GetEndPoint().X, lineTuple.Item2.GetEndPoint().X);
  633. newString += nextLine;
  634. }
  635. }
  636. return newString;
  637. }
  638. }
  639. }