Browse Source

Hotfix (#15)

* cleaned up GUI and attempted to fix phantom line error

* Cleaned up code and a user experience upgrade:
By passing the strokes directly to the model drawing with stylus and
touch should feel much more responsive

* Fixed target CPU error

* Direct input tests

* Changed svg load test
m-edlund 5 years ago
parent
commit
aee756b8f8

+ 4 - 4
.appveyor.yml

@@ -20,8 +20,8 @@ artifacts:
 before_test:
  - ps: "SketchAssistant/GenerateCoverageReport.bat"
 
-test:
+#test:
     #don't run tests depending on [DeploymentItem] and filesystem access
-    categories:
-        except:
-            - FileIO
+    #categories:
+    #    except:
+    #        - FileIO

+ 3 - 1
SketchAssistant/.gitignore

@@ -1 +1,3 @@
-/GeneratedReports/
+/GeneratedReports/
+!*.ico
+!*.svg

+ 0 - 18
SketchAssistant/SketchAssistantWPF/CustomCanvas.cs

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

+ 1 - 1
SketchAssistant/SketchAssistantWPF/DebugData.cs

@@ -78,7 +78,7 @@ namespace SketchAssistantWPF
 
             for (int i = 0; i < len; i++)
             {
-                int opX = rnd.Next(0, 2); int opY = rnd.Next(0, 1);
+                int opX = rnd.Next(0, 2); int opY = rnd.Next(0, 2);
                 int changeX = rnd.Next(0, 50); int changeY = rnd.Next(0, 50);
                 if (opX == 0) prevX = prevX - changeX;
                 else prevX = prevX + changeX;

+ 0 - 10
SketchAssistant/SketchAssistantWPF/InternalLine.cs

@@ -80,16 +80,6 @@ namespace SketchAssistantWPF
             }
         }
 
-        public Point GetStartPoint()
-        {
-            return linePoints.First();
-        }
-
-        public Point GetEndPoint()
-        {
-            return linePoints.Last();
-        }
-
         public List<Point> GetPoints()
         {
             return linePoints;

+ 20 - 63
SketchAssistant/SketchAssistantWPF/MVP_Model.cs

@@ -39,10 +39,6 @@ namespace SketchAssistantWPF
         /// </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;
@@ -63,10 +59,6 @@ namespace SketchAssistantWPF
         /// </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;
@@ -99,8 +91,6 @@ namespace SketchAssistantWPF
         /// </summary>
         private bool mouseDown;
 
-        Image rightImageWithoutOverlay;
-
         List<InternalLine> leftLineList;
         
         List<Tuple<bool, InternalLine>> rightLineList;
@@ -233,25 +223,7 @@ namespace SketchAssistantWPF
             leftLineList = listOfLines;
             graphicLoaded = true;
             programPresenter.UpdateLeftLines(leftLineList);
-            //programPresenter.ClearRightLines(); //TODO check if right position for this method call
             CanvasActivated();
-            /*
-            var workingCanvas = GetEmptyCanvas(width, height);
-            var workingGraph = Graphics.FromImage(workingCanvas);
-            leftLineList = listOfLines;
-            //redrawAss = new RedrawAssistant(leftLineList);
-            //overlayItems = redrawAss.Initialize(markerRadius);
-            //Lines
-            foreach (InternalLine 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, InternalLine>>();
-            */
         }
 
         /// <summary>
@@ -286,7 +258,6 @@ namespace SketchAssistantWPF
                     default:
                         break;
                 }
-                //TODO: For the person implementing overlay: Add check if overlay needs to be added
                 programPresenter.UpdateRightLines(rightLineList);
             }
             RepopulateDeletionMatrixes();
@@ -372,10 +343,8 @@ namespace SketchAssistantWPF
                     rightLineList.Add(new Tuple<bool, InternalLine>(true, newLine));
                     newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
                     programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID())));
-                    //TODO: For the person implementing overlay: Add check if overlay needs to be added
                     programPresenter.UpdateRightLines(rightLineList);
                     currentLine.Clear();
-                    //programPresenter.UpdateCurrentLine(currentLine)
                 }
             }
             else
@@ -385,6 +354,26 @@ namespace SketchAssistantWPF
             UpdateUI();
         }
 
+        /// <summary>
+        /// Finish the current Line, when the pressed Mouse is released.
+        /// Overload that is used to pass a list of points to be used when one is available.
+        /// </summary>
+        /// <param name="p">The list of points</param>
+        public void MouseUp(List<Point> p)
+        {
+            mouseDown = false;
+            if (inDrawingMode && currentLine.Count > 0)
+            {
+                InternalLine newLine = new InternalLine(p, rightLineList.Count);
+                rightLineList.Add(new Tuple<bool, InternalLine>(true, newLine));
+                newLine.PopulateMatrixes(isFilledMatrix, linesMatrix);
+                programPresenter.PassLastActionTaken(historyOfActions.AddNewAction(new SketchAction(SketchAction.ActionType.Draw, newLine.GetID())));
+                programPresenter.UpdateRightLines(rightLineList);
+                currentLine.Clear();
+            }
+            UpdateUI();
+        }
+
         /// <summary>
         /// Method to be called every tick. Updates the current Line, or checks for Lines to delete, depending on the drawing mode.
         /// </summary>
@@ -420,38 +409,6 @@ namespace SketchAssistantWPF
                 }
             }
         }
-        /*
-        /// <summary>
-        /// A helper Function that updates the markerRadius & deletionRadius, considering the size of the canvas.
-        /// </summary>
-        /// <param name="CanvasSize">The size of the canvas</param>
-        public void UpdateSizes(ImageDimension CanvasSize)
-        {
-            if (rightImageWithoutOverlay != null)
-            {
-                int widthImage = rightImageSize.Width;
-                int heightImage = rightImageSize.Height;
-                int widthBox = CanvasSize.Width;
-                int heightBox = CanvasSize.Height;
-
-                float imageRatio = (float)widthImage / (float)heightImage;
-                float containerRatio = (float)widthBox / (float)heightBox;
-                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);
-                deletionRadius = (int)(5 * zoomFactor);
-            }
-        }
-        */
 
         /// <summary>
         /// If there is unsaved progress.

+ 16 - 52
SketchAssistant/SketchAssistantWPF/MVP_Presenter.cs

@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Ink;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Shapes;
@@ -44,7 +45,6 @@ namespace SketchAssistantWPF
 
         public enum MouseAction
         {
-            Click,
             Down,
             Up,
             Up_Invalid,
@@ -86,49 +86,6 @@ namespace SketchAssistantWPF
             programModel.ResizeEvent(CanvasSizeLeft, CanvasSizeRight);
         }
 
-        /// <summary>
-        /// Display a new FileDialog to load a collection of lines.
-        /// </summary>
-        /// <returns>True if loading was a success</returns>
-        public bool ExamplePictureToolStripMenuItemClick()
-        {
-            var okToContinue = true; bool returnval = false;
-            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);
-                    try
-                    {
-                        Tuple<int, int, List<InternalLine>> values = fileImporter.ParseISADInputFile(fileNameTup.Item1);
-                        values.Item3.ForEach(line => line.MakePermanent(0)); //Make all lines permanent
-                        programModel.SetLeftLineList(values.Item1, values.Item2, values.Item3);
-
-                        programModel.ResetRightImage();
-                        programModel.CanvasActivated();
-                        programModel.ChangeState(true);
-                        programView.EnableTimer();
-                        ClearRightLines();
-                        returnval = true;
-                    }
-                    catch (FileImporterException ex)
-                    {
-                        programView.ShowInfoMessage(ex.ToString());
-                    }
-                    catch (Exception ex)
-                    {
-                        programView.ShowInfoMessage("exception occured while trying to load interactive sketch-assistant drawing file:\n\n" + ex.ToString() + "\n\n" + ex.StackTrace);
-                    }
-                }
-            }
-            return returnval;
-        }
-
         /// <summary>
         /// Display a new FileDialog to a svg drawing.
         /// </summary>
@@ -246,21 +203,28 @@ namespace SketchAssistantWPF
         /// 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)
+        /// <param name="strokes">The Strokes.</param>
+        public void MouseEvent(MouseAction mouseAction, StrokeCollection strokes)
         {
+
             switch (mouseAction)
             {
-                case MouseAction.Click:
-                    programModel.MouseDown();
-                    programModel.Tick();
-                    programModel.MouseUp(true);
-                    break;
                 case MouseAction.Down:
                     programModel.MouseDown();
                     break;
                 case MouseAction.Up:
-                    programModel.MouseUp(true);
+                    if(strokes.Count > 0)
+                    {
+                        StylusPointCollection sPoints = strokes.First().StylusPoints;
+                        List<Point> points = new List<Point>();
+                        foreach(StylusPoint p in sPoints)
+                            points.Add(new Point(p.X, p.Y));
+                        programModel.MouseUp(points);
+                    }
+                    else
+                    {
+                        programModel.MouseUp(true);
+                    }
                     break;
                 case MouseAction.Up_Invalid:
                     programModel.MouseUp(false);

+ 1 - 0
SketchAssistant/SketchAssistantWPF/MVP_View.cs

@@ -5,6 +5,7 @@ using System.Text;
 using System.Threading.Tasks;
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Ink;
 using System.Windows.Shapes;
 
 namespace SketchAssistantWPF

+ 22 - 25
SketchAssistant/SketchAssistantWPF/MainWindow.xaml

@@ -8,26 +8,20 @@
         Title="Sketch Assistant" Height="612" Width="914" SizeChanged="Window_SizeChanged">
     <Grid>
         <Grid.ColumnDefinitions>
-            <ColumnDefinition Width="auto"/>
-            <ColumnDefinition Width="auto"/>
-            <ColumnDefinition Width="170*"/>
-            <ColumnDefinition Width="55*"/>
-            <ColumnDefinition Width="225*"/>
             <ColumnDefinition Width="5"/>
-            <ColumnDefinition Width="226*"/>
-            <ColumnDefinition Width="225*"/>
-            <ColumnDefinition Width="auto"/>
-            <ColumnDefinition Width="auto"/>
+            <ColumnDefinition Width="*"/>
+            <ColumnDefinition Width="5"/>
+            <ColumnDefinition Width="*"/>
+            <ColumnDefinition Width="5"/>
         </Grid.ColumnDefinitions>
         <Grid.RowDefinitions>
             <RowDefinition Height="auto"/>
             <RowDefinition Height="*"/>
             <RowDefinition Height="auto"/>
         </Grid.RowDefinitions>
-        <ToolBar x:Name="MenuToolbar" Grid.Column="0" Grid.ColumnSpan="5" Grid.Row="0" Background="LightGray">
-            <Menu Background="LightGray">
+        <StackPanel Orientation="Horizontal" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Background="LightGray">
+            <Menu Background="LightGray"   VerticalAlignment="Center" Padding="5,0,0,0">
                 <MenuItem x:Name="LoadMenuButton" Header="Load">
-                    <MenuItem x:Name="ISADMenuButton" Header="Load .isad Drawing" Click="ISADMenuItem_Click"/>
                     <MenuItem x:Name="SVGMenuButton" Header="Import SVG File" Click="SVGMenuItem_Click"/>
                 </MenuItem>
                 <MenuItem x:Name="EditMenuButton" Header="Edit">
@@ -42,10 +36,11 @@
                     </MenuItem>
                 </MenuItem>
             </Menu>
-        </ToolBar>
-        <!-- All Icons in the Toolbar taken from openclipart.org -->
-        <ToolBar x:Name="DrawingToolBar" Grid.Column="6" Grid.Row="0" Grid.ColumnSpan="2" Background="LightGray">
-            <Button x:Name="CanvasButton" ToolTip="Create a new Canvas" Click="CanvasButton_Click">
+        </StackPanel>
+        <StackPanel Orientation="Horizontal" Grid.Column="2" Grid.Row="0" Grid.ColumnSpan="3" Background="LightGray">
+            <Canvas Name="ToolbarSpacer" Width="5" Background="LightGray" />
+            <!-- All Icons in the StackPanel taken from openclipart.org -->
+            <Button x:Name="CanvasButton" ToolTip="Create a new Canvas" Click="CanvasButton_Click" BorderThickness="0">
                 <Rectangle Width="30" Height="30">
                     <Rectangle.Fill>
                         <DrawingBrush>
@@ -74,7 +69,7 @@
                     </Rectangle.Fill>
                 </Rectangle>
             </Button>
-            <ToggleButton x:Name="DrawButton" ToolTip="Enter Drawing Mode" Click="DrawButton_Click">
+            <ToggleButton x:Name="DrawButton" ToolTip="Enter Drawing Mode" Click="DrawButton_Click" BorderThickness="0">
                 <Rectangle Width="30" Height="30">
                     <Rectangle.Fill>
                         <DrawingBrush>
@@ -89,7 +84,7 @@
                     </Rectangle.Fill>
                 </Rectangle>
             </ToggleButton>
-            <ToggleButton x:Name="DeleteButton" ToolTip="Enter Deletion Mode" Click="DeleteButton_Click">
+            <ToggleButton x:Name="DeleteButton" ToolTip="Enter Deletion Mode" Click="DeleteButton_Click" BorderThickness="0">
                 <Rectangle Width="30" Height="30">
                     <Rectangle.Fill>
                         <DrawingBrush>
@@ -131,7 +126,7 @@
                     </Rectangle.Fill>
                 </Rectangle>
             </ToggleButton>
-            <Button x:Name="UndoButton" ToolTip="Undo the last action" Click="UndoButton_Click">
+            <Button x:Name="UndoButton" ToolTip="Undo the last action" Click="UndoButton_Click" BorderThickness="0">
                 <Rectangle Width="30" Height="30">
                     <Rectangle.Fill>
                         <DrawingBrush>
@@ -153,7 +148,7 @@
                     </Rectangle.Fill>
                 </Rectangle>
             </Button>
-            <Button x:Name="RedoButton" ToolTip="Redo the last undone action" Click="RedoButton_Click">
+            <Button x:Name="RedoButton" ToolTip="Redo the last undone action" Click="RedoButton_Click" BorderThickness="0">
                 <Rectangle Width="30" Height="30">
                     <Rectangle.Fill>
                         <DrawingBrush>
@@ -177,13 +172,15 @@
                     </Rectangle.Fill>
                 </Rectangle>
             </Button>
-        </ToolBar>
-        <local:CustomCanvas x:Name="LeftCanvas" Background="SlateGray" Grid.Column="2" Grid.Row="1" Height="auto" Grid.ColumnSpan="3"/>
-        <Canvas Name="CanvasSeperator" Grid.Column="5" Grid.Row="1" Background="LightGray" />
-        <InkCanvas x:Name="RightCanvas" Background="SlateGray" Grid.Column="6" Grid.Row="1" Height="auto"
+        </StackPanel>
+        <Canvas Name="CanvasLeftEdge" Grid.Column="0" Grid.Row="1" Background="LightGray" />
+        <Canvas x:Name="LeftCanvas" Background="SlateGray" Grid.Column="1" Grid.Row="1" Height="auto" Grid.ColumnSpan="1"/>
+        <Canvas Name="CanvasSeperator" Grid.Column="2" Grid.Row="1" Background="LightGray" />
+        <InkCanvas x:Name="RightCanvas" Background="SlateGray" Grid.Column="3" Grid.Row="1" Height="auto"
             PreviewMouseDown="RightCanvas_MouseDown" MouseUp="RightCanvas_MouseUp" MouseMove="RightCanvas_MouseMove" Grid.ColumnSpan="2" 
-                    StrokeCollected="RightCanvas_StrokeCollection" EditingMode="None"/>
+                    StrokeCollected="RightCanvas_StrokeCollection" EditingMode="None" IsStylusCapturedChanged="RightCanvas_IsStylusCapturedChanged"/>
 
+        <Canvas Name="CanvasRightEdge" Grid.Column="4" Grid.Row="1" Background="LightGray" />
 
         <DockPanel Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="8">
             <StatusBar DockPanel.Dock="Bottom" Name="StatusBar"  Background="LightGray">

+ 34 - 23
SketchAssistant/SketchAssistantWPF/MainWindow.xaml.cs

@@ -91,7 +91,11 @@ namespace SketchAssistantWPF
         /// <summary>
         /// Stores Lines drawn on RightCanvas.
         /// </summary>
-        StrokeCollection strokeCollection = new StrokeCollection();
+        public StrokeCollection strokeCollection = new StrokeCollection();
+        /// <summary>
+        /// Size of areas marking endpoints of lines in the redraw mode.
+        /// </summary>
+        int markerRadius = 10;
 
         /********************************************/
         /*** WINDOW SPECIFIC FUNCTIONS START HERE ***/
@@ -112,7 +116,6 @@ namespace SketchAssistantWPF
         public void RightCanvas_StrokeCollection(object sender, InkCanvasStrokeCollectedEventArgs e)
         {
             strokeCollection.Add(e.Stroke);
-            //System.Diagnostics.Debug.WriteLine(strokeCollection.Count);
         }
 
         /// <summary>
@@ -120,7 +123,7 @@ namespace SketchAssistantWPF
         /// </summary>
         private void RedoButton_Click(object sender, RoutedEventArgs e)
         {
-            ProgramPresenter.Redo();
+            if (!IsMousePressed()) ProgramPresenter.Redo();
         }
 
         /// <summary>
@@ -128,7 +131,7 @@ namespace SketchAssistantWPF
         /// </summary>
         private void UndoButton_Click(object sender, RoutedEventArgs e)
         {
-            ProgramPresenter.Undo();
+            if(!IsMousePressed()) ProgramPresenter.Undo();
         }
 
         /// <summary>
@@ -154,8 +157,7 @@ namespace SketchAssistantWPF
         /// </summary>
         private void RightCanvas_MouseDown(object sender, MouseButtonEventArgs e)
         {
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);
-            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down);");
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down, strokeCollection);
         }
 
         /// <summary>
@@ -165,16 +167,36 @@ namespace SketchAssistantWPF
         {
             if(strokeCollection.Count == 0)
             {
-                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up_Invalid);
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up_Invalid, strokeCollection);
             }
             else
             {
-                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);
+                ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up, strokeCollection);
                 RightCanvas.Strokes.RemoveAt(0);
                 strokeCollection.RemoveAt(0);
-                //System.Diagnostics.Debug.WriteLine(strokeCollection.Count);
             }
-            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up);");
+        }
+
+        /// <summary>
+        /// Is called when a stylus is lifted, which has the same effect as releasing the mouse.
+        /// Lifting the finger when using touch also toggles this, therfore this function is sufficient.
+        /// </summary>
+        private void RightCanvas_IsStylusCapturedChanged(object sender, DependencyPropertyChangedEventArgs e)
+        {
+            System.Diagnostics.Debug.WriteLine("Stylus Capture is now: {0}", RightCanvas.IsStylusCaptured);
+            if (!RightCanvas.IsStylusCaptured)
+            {
+                if (strokeCollection.Count == 0)
+                {
+                    ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up_Invalid,strokeCollection);
+                }
+                else
+                {
+                    ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up, strokeCollection);
+                    RightCanvas.Strokes.RemoveAt(0);
+                    strokeCollection.RemoveAt(0);
+                }
+            }
         }
 
         /// <summary>
@@ -183,7 +205,6 @@ namespace SketchAssistantWPF
         private void RightCanvas_MouseMove(object sender, MouseEventArgs e)
         {
             ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, e.GetPosition(RightCanvas));
-            //System.Diagnostics.Debug.WriteLine("new Point(" + ((int)e.GetPosition(RightCanvas).X).ToString() + "," + ((int)e.GetPosition(RightCanvas).Y).ToString() + "), ");
         }
 
         /// <summary>
@@ -204,16 +225,6 @@ namespace SketchAssistantWPF
         private void dispatcherTimer_Tick(object sender, EventArgs e)
         {
             ProgramPresenter.Tick();
-            //System.Diagnostics.Debug.WriteLine("ProgramPresenter.Tick();");
-        }
-
-        /// <summary>
-        /// Import button for .isad drawing, will open an OpenFileDialog
-        /// </summary>
-        private void ISADMenuItem_Click(object sender, RoutedEventArgs e)
-        {
-            if(ProgramPresenter.ExamplePictureToolStripMenuItemClick())
-                RightCanvas.EditingMode = InkCanvasEditingMode.Ink;
         }
 
         /// <summary>
@@ -587,7 +598,7 @@ namespace SketchAssistantWPF
             debugRunning = true;
             ProgramPresenter.Tick(); await Task.Delay(10);
             ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, start);
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down); await Task.Delay(10);
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Down, strokeCollection); await Task.Delay(10);
             for (int x = 0; x < points.Length; x++)
             {
                 ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Move, points[x]);
@@ -598,7 +609,7 @@ namespace SketchAssistantWPF
                     await Task.Delay(1);
                 }
             }
-            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up); await Task.Delay(1);
+            ProgramPresenter.MouseEvent(MVP_Presenter.MouseAction.Up, strokeCollection); await Task.Delay(1);
             debugRunning = false;
             dispatcherTimer.Start();
         }

+ 1 - 4
SketchAssistant/SketchAssistantWPF/SketchAction.cs

@@ -72,7 +72,7 @@ namespace SketchAssistantWPF
         /// <returns>A String describing what happend at this action.</returns>
         public String GetActionInformation()
         {
-            String returnString;
+            String returnString = "";
             switch (thisAction)
             {
                 case ActionType.Start:
@@ -88,9 +88,6 @@ namespace SketchAssistantWPF
                         returnString = "Several Lines were deleted.";
                     }
                     break;
-                default:
-                    returnString = "There is no information available for this action.";
-                    break;
             }
             return returnString;
         }

+ 7 - 2
SketchAssistant/SketchAssistantWPF/SketchAssistantWPF.csproj

@@ -17,6 +17,7 @@
     <Deterministic>true</Deterministic>
     <NuGetPackageImportStamp>
     </NuGetPackageImportStamp>
+    <IsWebBootstrapper>false</IsWebBootstrapper>
     <PublishUrl>publish\</PublishUrl>
     <Install>true</Install>
     <InstallFrom>Disk</InstallFrom>
@@ -29,7 +30,6 @@
     <MapFileExtensions>true</MapFileExtensions>
     <ApplicationRevision>0</ApplicationRevision>
     <ApplicationVersion>1.0.0.%2a</ApplicationVersion>
-    <IsWebBootstrapper>false</IsWebBootstrapper>
     <UseApplicationTrust>false</UseApplicationTrust>
     <BootstrapperEnabled>true</BootstrapperEnabled>
   </PropertyGroup>
@@ -52,6 +52,9 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
   </PropertyGroup>
+  <PropertyGroup>
+    <ApplicationIcon>nicubunu-Quill.ico</ApplicationIcon>
+  </PropertyGroup>
   <ItemGroup>
     <Reference Include="System" />
     <Reference Include="System.Data" />
@@ -75,7 +78,6 @@
       <SubType>Designer</SubType>
     </ApplicationDefinition>
     <Compile Include="ActionHistory.cs" />
-    <Compile Include="CustomCanvas.cs" />
     <Compile Include="DebugData.cs" />
     <Compile Include="FileImporter.cs" />
     <Compile Include="FileImporterException.cs" />
@@ -138,6 +140,9 @@
       <Install>false</Install>
     </BootstrapperPackage>
   </ItemGroup>
+  <ItemGroup>
+    <Resource Include="nicubunu-Quill.ico" />
+  </ItemGroup>
   <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
   <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
     <PropertyGroup>

BIN
SketchAssistant/SketchAssistantWPF/nicubunu-Quill.ico


+ 312 - 25
SketchAssistant/WhiteTests/UITest.cs

@@ -17,10 +17,13 @@ using System.Text.RegularExpressions;
 using WindowsInput;
 using WindowsInput.Native;
 using System.Threading.Tasks;
+using System.Linq;
+using Application = TestStack.White.Application;
+using Window = TestStack.White.UIItems.WindowItems.Window;
 
 namespace WhiteTests
 {
-    
+
     [TestClass]
     public class UITest
     {
@@ -92,8 +95,152 @@ namespace WhiteTests
             return application.GetWindow("Sketch Assistant");
         }
 
+        [DataTestMethod]
+        [TestCategory("FileIO")]
+        [DataRow("line")]
+        public void LoadSVGFileTest(String filename)
+        {
+            Window mainWindow = setupapp();
+            InputSimulator inputSimulator = new InputSimulator();
+            Thread.Sleep(20);
+            string[] files = Directory.GetFiles(getSketchAssistantDirectory() + @"\whitelisted", "*.svg", SearchOption.AllDirectories);
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("LoadMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("SVGMenuButton")).Click();
+            Thread.Sleep(1000);
+            inputSimulator.Keyboard.TextEntry(getSketchAssistantDirectory() + @"whitelisted\" + filename + ".svg");
+            Thread.Sleep(1000);
+            inputSimulator.Keyboard.KeyPress(VirtualKeyCode.RETURN);
+            Thread.Sleep(1000);
+            //Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DirectInput")]
+        public void DrawLineOnCanvasTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            InputSimulator inputSimulator = new InputSimulator();
+            MouseSimulator mouseSimulator = new MouseSimulator(inputSimulator);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(100,100);
+            inputSimulator.Mouse.LeftButtonDown();
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(100, 100);
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DirectInput")]
+        public void UndoLineOnCanvasTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            InputSimulator inputSimulator = new InputSimulator();
+            MouseSimulator mouseSimulator = new MouseSimulator(inputSimulator);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(0, 200);
+            inputSimulator.Mouse.LeftButtonDown();
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(500, 300);
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("UndoButton")).Click();
+            Thread.Sleep(100);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
         [TestMethod]
-        [TestCategory("bla")]
+        [TestCategory("DirectInput")]
+        public void InvalidLineTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            InputSimulator inputSimulator = new InputSimulator();
+            MouseSimulator mouseSimulator = new MouseSimulator(inputSimulator);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("DrawButton")).Click();
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonDown();
+            inputSimulator.Mouse.MoveMouseBy(0, 200);
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(500, 300);
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            inputSimulator.Mouse.MoveMouseBy(-1000, 0);
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonDown();
+            inputSimulator.Mouse.MoveMouseBy(1000, 0);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DirectInput")]
+        public void PointsOnCanvasSimilarityTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            InputSimulator inputSimulator = new InputSimulator();
+            MouseSimulator mouseSimulator = new MouseSimulator(inputSimulator);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Assert.AreEqual("-", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LineSimilarityBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            inputSimulator.Mouse.MoveMouseBy(0, 200);
+            inputSimulator.Mouse.LeftButtonDown();
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Assert.AreEqual("-", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LineSimilarityBox")).Text.ToString());
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonDown();
+            Thread.Sleep(20);
+            inputSimulator.Mouse.LeftButtonUp();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 1 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Assert.AreEqual("1", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LineSimilarityBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("UndoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Assert.AreEqual("-", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LineSimilarityBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("RedoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: Line number 1 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Assert.AreEqual("1", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LineSimilarityBox")).Text.ToString());
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DebugInput")]
         public void CreateCanvasTest()
         {
             Window mainWindow = setupapp();
@@ -106,7 +253,7 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        [TestCategory("bla")]
+        [TestCategory("DebugInput")]
         public void DrawLineTest()
         {
             Window mainWindow = setupapp();
@@ -126,6 +273,7 @@ namespace WhiteTests
         }
 
         [TestMethod]
+        [TestCategory("DebugInput")]
         public void DeleteLineTest()
         {
             Window mainWindow = setupapp();
@@ -157,7 +305,7 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        [TestCategory("bla")]
+        [TestCategory("DebugInput")]
         public void UndoTest()
         {
             Window mainWindow = setupapp();
@@ -181,7 +329,7 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        [TestCategory("bla")]
+        [TestCategory("DebugInput")]
         public void RedoTest()
         {
             Window mainWindow = setupapp();
@@ -209,7 +357,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void DrawSeveralLines()
+        [TestCategory("DebugInput")]
+        public void DrawSeveralLinesTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -237,7 +386,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void DeleteSeveralLines()
+        [TestCategory("DebugInput")]
+        public void DeleteSeveralLinesTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -276,7 +426,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void UndoSeveralLines()
+        [TestCategory("DebugInput")]
+        public void UndoSeveralLinesTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -312,7 +463,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void RedoSeveralLines()
+        [TestCategory("DebugInput")]
+        public void RedoSeveralLinesTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -356,7 +508,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void UndoAndRedoTests()
+        [TestCategory("DebugInput")]
+        public void UndoAndRedoTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -414,7 +567,80 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void PointDraw()
+        [TestCategory("DebugInput")]
+        public void UndoAndDrawTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugFour")).Click();
+            Thread.Sleep(2000);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("UndoButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugFour")).Click();
+            Thread.Sleep(2000);
+            Assert.AreEqual("Last Action: Line number 1 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DebugInput")]
+        public void DeleteSeveralLinesAtOnceTest()
+        {
+            Window mainWindow = setupapp();
+            Thread.Sleep(20);
+            Assert.AreEqual("none", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("CanvasButton")).Click();
+            Thread.Sleep(20);
+            Assert.AreEqual("Last Action: A new canvas was created.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugFour")).Click();
+            Thread.Sleep(2000);
+            Assert.AreEqual("Last Action: Line number 0 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugFour")).Click();
+            Thread.Sleep(2000);
+            Assert.AreEqual("Last Action: Line number 1 was drawn.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Get<Button>(SearchCriteria.ByAutomationId("DeleteButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("EditMenuButton")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugMode")).Click();
+            Thread.Sleep(20);
+            mainWindow.Get<Menu>(SearchCriteria.ByAutomationId("DebugFour")).Click();
+            Thread.Sleep(2000);
+            Assert.AreEqual("Last Action: Several Lines were deleted.", mainWindow.Get<TextBox>(SearchCriteria.ByAutomationId("LastActionBox")).Text.ToString());
+            Thread.Sleep(20);
+            mainWindow.Close();
+        }
+
+        [TestMethod]
+        [TestCategory("DebugInput")]
+        public void PointDrawTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -434,7 +660,8 @@ namespace WhiteTests
         }
 
         [TestMethod]
-        public void NewCanvasAfterDraw()
+        [TestCategory("DebugInput")]
+        public void NewCanvasAfterDrawTest()
         {
             Window mainWindow = setupapp();
             Thread.Sleep(20);
@@ -479,7 +706,6 @@ namespace WhiteTests
     }
 
     [TestClass]
-    //[DeploymentItem(@"WhiteTests\test_input_files\")]
     public class FileImporterTests
     {
         /// <summary>
@@ -516,7 +742,7 @@ namespace WhiteTests
             Regex rx = new Regex(@"^(.*\\SketchAssistant\\)");
             Match match = rx.Match(TestContext.DeploymentDirectory);
             String SketchAssistDir = match.Groups[1].Value;
-            if(input_file_dir == null)
+            if (input_file_dir == null)
             {
                 if (Directory.Exists(SketchAssistDir + @"\WhiteTests\test_input_files\"))
                 {
@@ -544,7 +770,7 @@ namespace WhiteTests
         /// <param name="xCoordinates">an array containing the x coordinates of the points that will be created (length divisible by 3)</param>
         /// <param name="yCoordinates">an array containing the y coordinates of the points that will be created (length divisible by 3)</param>
         [DataTestMethod]
-        [TestCategory("bla")]
+        [TestCategory("FileIO")]
         [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 })]
@@ -585,8 +811,8 @@ namespace WhiteTests
         /// </summary>
         /// <param name="file">the input file represented as an array of lines</param>
         [DataTestMethod]
-        [TestCategory("bla")]
-        [DataRow(new String[] {})]
+        [TestCategory("FileIO")]
+        [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" })]
@@ -611,10 +837,11 @@ namespace WhiteTests
                 //try to initialize the left image with an invalid isad drawing
                 Tuple<int, int, List<InternalLine>> values1 = uut.ParseISADInputForTesting(file);
             }
-            catch (FileImporterException)
+            catch (FileImporterException e)
             {
                 //save the occurence of an exception
                 correctExceptionThrown = true;
+                System.Diagnostics.Debug.WriteLine(e.ToString());
             }
             catch (Exception)
             {
@@ -633,7 +860,7 @@ namespace WhiteTests
         {
             FileImporter uut = new FileImporter();
             string[] files = Directory.GetFiles(getSketchAssistantDirectory() + @"\whitelisted", "*.svg", SearchOption.AllDirectories);
-            
+
             Assert.IsTrue(files.Length > 0);
 
             foreach (string s in files) //parse each of the whitelisted files
@@ -670,8 +897,9 @@ namespace WhiteTests
                 {
                     uut.ParseSVGInputFile(s, 10000, 10000);
                 }
-                catch (FileImporterException)
+                catch (FileImporterException e)
                 {
+                    System.Diagnostics.Debug.WriteLine(e.ToString());
                     correctExceptionThrown = true;
                 }
                 catch (Exception)
@@ -689,26 +917,28 @@ namespace WhiteTests
         /// The debug data element used to generate random lines.
         /// </summary>
         private DebugData DebugData = new DebugData();
-        
+
         /// <summary>
         /// Generates random lines and tests how similar they are. 
         /// To test the similarity score always stays between 0 and 1.
         /// </summary>
         [TestMethod]
+        [TestCategory("UnitTest")]
         public void StaysWithinParameters()
         {
-            Parallel.For(1,100,
+            Parallel.For(1, 100,
                 i =>
                 {
-                    InternalLine l0 = DebugData.GetRandomLine(1, (uint) i);
+                    InternalLine l0 = DebugData.GetRandomLine(1, (uint)i);
                     InternalLine l1 = DebugData.GetRandomLine(1, (uint)i);
                     var sim = GeometryCalculator.CalculateSimilarity(l0, l1);
                     Assert.IsTrue((sim >= 0));
                     Assert.IsTrue((sim <= 1));
-                } );
+                });
         }
 
         [TestMethod]
+        [TestCategory("UnitTest")]
         public void CorrectSimilarity()
         {
             Parallel.ForEach(DebugData.GetSimilarityTestData(),
@@ -720,6 +950,63 @@ namespace WhiteTests
                     Assert.AreEqual(tup.Item3, sim, 0.00000001);
                 });
         }
-        
+
+    }
+
+    [TestClass]
+    public class InternalLineUnitTests
+    {
+        /// <summary>
+        /// The debug data element used to generate random lines.
+        /// </summary>
+        private DebugData DebugData = new DebugData();
+
+        [TestMethod]
+        [TestCategory("UnitTest")]
+        public void MakePermanentTest()
+        {
+
+            List<Point> points = new List<Point>();
+            points.AddRange(DebugData.debugPoints4);
+            InternalLine uut = new InternalLine(points);
+            Assert.AreEqual(false, uut.isPoint);
+            uut.MakePermanent(5);
+            Assert.AreEqual(true, uut.isPoint);
+            Assert.AreEqual(5, uut.GetID());
+            Assert.AreEqual(0, uut.GetLength());
+        }
+
+        [DataTestMethod]
+        [TestCategory("UnitTest")]
+        [DataRow(new int[] { 1 ,1, 3, 3 }, new int[] { 1, 1, 2, 2, 3, 3 }, false, 2.828427125)]
+        [DataRow(new int[] { 1, 1, 3, 3 }, new int[] { 1, 1, 2, 2, 3, 3 }, true, 2.828427125)]
+        [DataRow(new int[] { 1, 1, 1, 4 ,3, 4 }, new int[] { 1, 1, 1, 2, 1, 3, 1, 4, 2, 4, 3, 4 }, false, 5)]
+        [DataRow(new int[] { 1, 1, 1, 4, 3, 4 }, new int[] { 1, 1, 1, 2, 1, 3, 1, 4, 2, 4, 3, 4 }, true, 5)]
+        public void PermanentLineTest(int[] inPoints, int[] outPoints, bool isTemp, double len)
+        {
+            List<Point> inLine = new List<Point>(); List<Point> outLine = new List<Point>();
+            for (int i = 0; i < inPoints.Length;i += 2) inLine.Add(new Point(inPoints[i], inPoints[i + 1]));
+            for (int i = 0; i < outPoints.Length; i += 2) outLine.Add(new Point(outPoints[i], outPoints[i + 1]));
+            InternalLine uut;
+            if (isTemp)
+            {
+                uut = new InternalLine(inLine);
+                var zip = inLine.Zip(uut.GetPoints(), (a,b) => new Tuple<Point, Point>(a, b));
+                foreach (Tuple < Point, Point> tup in zip)
+                {
+                    Assert.AreEqual(tup.Item1, tup.Item2);
+                }
+            }
+            else
+            {
+                uut = new InternalLine(inLine,0);
+                var zip = outLine.Zip(uut.GetPoints(), (a, b) => new Tuple<Point, Point>(a, b));
+                foreach (Tuple<Point, Point> tup in zip)
+                {
+                    Assert.AreEqual(tup.Item1, tup.Item2);
+                }
+            }
+            Assert.AreEqual(len, uut.GetLength(), 0.000001);
+        }
     }
 }

+ 2 - 0
SketchAssistant/WhiteTests/WhiteTests.csproj

@@ -52,9 +52,11 @@
     <Reference Include="Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions, Version=14.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
       <HintPath>..\packages\MSTest.TestFramework.1.4.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll</HintPath>
     </Reference>
+    <Reference Include="PresentationFramework" />
     <Reference Include="System" />
     <Reference Include="System.Configuration" />
     <Reference Include="System.Core" />
+    <Reference Include="System.Drawing" />
     <Reference Include="System.Windows" />
     <Reference Include="System.Windows.Forms" />
     <Reference Include="TestStack.White, Version=0.13.0.0, Culture=neutral, PublicKeyToken=2672efbf3e161801, processorArchitecture=MSIL">