title: Draw Shapes and Strings with undo and redo feature
body: <p>Is there a way to drawstring and then remove it?</p>
  
  <p>I've used following classes to Undo/Redo Rectangle, Circle, Line, Arrow type shapes but cant figure how i can remove drawn string.</p>
  
  <p><a href="https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/UndoRedo.cs" rel="noreferrer">https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/UndoRedo.cs</a></p>
  
  <p><a href="https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/Shape.cs" rel="noreferrer">https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/Shape.cs</a></p>
  
  <p><a href="https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/ShapesTypes.cs" rel="noreferrer">https://github.com/Muhammad-Khalifa/Free-Snipping-Tool/blob/master/Free%20Snipping%20Tool/Operations/ShapesTypes.cs</a></p>
  
  <p>Here is how i'm adding Rectangle in shape list: This works well when i undo or redo from the list.</p>
  
  <p><strong>DrawString</strong></p>
  
  <pre><code>Shape shape = new Shape();
  shape.shape = ShapesTypes.ShapeTypes.Rectangle;
  shape.CopyTuplePoints(points);
  shape.X = StartPoint.X;
  shape.Y = StartPoint.Y;
  shape.Width = EndPoint.X;
  shape.Height = EndPoint.Y;
  
  Pen pen = new Pen(new SolidBrush(penColor), 2);
  shape.pen = pen;
  undoactions.AddShape(shape);
  </code></pre>
  
  <p>This is how i'm drawing text:</p>
  
  <pre><code>var fontFamily = new FontFamily("Calibri");
  var font = new Font(fontFamily, 12, FontStyle.Regular, GraphicsUnit.Point);
  
  Size proposedSize = new Size(int.MaxValue, int.MaxValue);
  TextFormatFlags flags = TextFormatFlags.WordEllipsis | TextFormatFlags.NoPadding | TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.WordBreak;
  
  Size size = TextRenderer.MeasureText(e.Graphics, textAreaValue, font, proposedSize, flags);
  
  Shape shape = new Shape();
  shape.shape = ShapesTypes.ShapeTypes.Text;
  shape.X = ta.Location.X;
  shape.Y = ta.Location.Y;
  shape.Width = size.Width;
  shape.Height = size.Height;
  shape.Value = textAreaValue;
  
  Pen pen = new Pen(new SolidBrush(penColor), 2);
  shape.pen = pen;
  undoactions.AddShape(shape);
  </code></pre>
  
  <p>But this does not work with undo-redo list. Maybe problem is with <strong>pen</strong> and <strong>font-size</strong> but i cant figure it out how to use pen with DrawString.</p>
  
  <p><strong>Edit:</strong>
  Here's how i'm drawing in paint event</p>
  
  <pre><code>protected override void OnPaint(PaintEventArgs e)
  {
      e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
  
      foreach (var item in undoactions.lstShape)
      {
          if (item.shape == ShapesTypes.ShapeTypes.Line)
          {
              e.Graphics.DrawLine(item.pen, item.X, item.Y, item.Width, item.Height);
          }
          else if (item.shape == ShapesTypes.ShapeTypes.Pen)
          {
              if (item.Points.Count &gt; 1)
              {
                  e.Graphics.DrawCurve(item.pen, item.Points.ToArray());
              }
          }
  
          else if (item.shape == ShapesTypes.ShapeTypes.Text)
          {
              var fontFamily = new FontFamily("Calibri");
              var font = new Font(fontFamily, 12, FontStyle.Regular, GraphicsUnit.Point);
  
              e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
              e.Graphics.DrawString(item.Value, font, new SolidBrush(item.pen.Color), new PointF(item.X, item.Y));
          }
      }
  }
  </code></pre>
  
  <p><strong>Shape.cs</strong></p>
  
  <pre><code>using System;
  using System.Collections.Generic;
  using System.Drawing;
  using System.Linq;
  using System.Text;
  using System.Threading.Tasks;
  
  namespace Drawing
  {
      public class Shape : ICloneable
      {
          public ShapesTypes.ShapeTypes shape { get; set; }
          public List&lt;Point&gt; Points { get; }
          public int X { get; set; }
          public int Y { get; set; }
          public int Width { get; set; }
          public int Height { get; set; }
          public Pen pen { get; set; }
  
          public String Value { get; set; }
  
          public Shape()
          {
              Points = new List&lt;Point&gt;();
          }
  
          public void CopyPoints(List&lt;Point&gt; points)
          {
              for (int i = 0; i &lt; points.Count; i++)
              {
                  Point p = new Point();
                  p.X = points[i].X;
                  p.Y = points[i].Y;
  
                  Points.Add(p);
              }
          }
  
          public void CopyCopyPoints(List&lt;List&lt;Point&gt;&gt; points)
          {
              for (int j = 0; j &lt; points.Count; j++)
              {
                  List&lt;Point&gt; current = points[j];
  
                  for (int i = 0; i &lt; current.Count; i++)
                  {
                      Point p = new Point();
                      p.X = current[i].X;
                      p.Y = current[i].Y;
  
                      Points.Add(p);
                  }
              }
          }
  
          public void CopyTuplePoints(List&lt;Tuple&lt;Point, Point&gt;&gt; points)
          {
              foreach (var line in points)
              {
                  Point p = new Point();
                  p.X = line.Item1.X;
                  p.Y = line.Item1.Y;
                  Points.Add(p);
  
                  p.X = line.Item2.X;
                  p.Y = line.Item2.Y;
                  Points.Add(p);
              }
          }
  
  
          public object Clone()
          {
              Shape shp = new Shape();
              shp.X = X;
              shp.Y = Y;
              shp.Width = Width;
              shp.Height = Height;
              shp.pen = pen;
              shp.shape = shape;
              shp.Value = Value;
  
              for (int i = 0; i &lt; Points.Count; i++)
              {
                  shp.Points.Add(new Point(Points[i].X, Points[i].Y));
              }
  
              return shp;
          }
      }
  }
  </code></pre>
  
  <p><strong>DrawCircle</strong></p>
  
  <pre><code>if (currentshape == ShapesTypes.ShapeTypes.Circle)
  {
      Shape shape = new Shape();
      shape.shape = ShapesTypes.ShapeTypes.Circle;
      shape.CopyTuplePoints(cLines);
      shape.X = StartPoint.X;
      shape.Y = StartPoint.Y;
      shape.Width = EndPoint.X;
      shape.Height = EndPoint.Y;
  
      Pen pen = new Pen(new SolidBrush(penColor), 2);
      shape.pen = pen;
      undoactions.AddShape(shape);
  }
  </code></pre>
  
  <p><strong>Undo</strong></p>
  
  <pre><code>if (currentshape != ShapesTypes.ShapeTypes.Undo)
  {
      oldshape = currentshape;
      currentshape = ShapesTypes.ShapeTypes.Undo;
  }
  if (undoactions.lstShape.Count &gt; 0)
  {
      undoactions.Undo();
      this.Invalidate();
  }
  if (undoactions.redoShape.Count &gt; 0)
  {
      btnRedo.Enabled = true;
  }
  </code></pre>
  
  <p><strong>UndoRedo</strong></p>
  
  <pre><code>public class UndoRedo
  {
      public List&lt;Shape&gt; lstShape = new List&lt;Shape&gt;();
      public List&lt;Shape&gt; redoShape = new List&lt;Shape&gt;();
  
      public void AddShape(Shape shape)
      {
          lstShape.Add(shape);
      }
  
      public void Undo()
      {
          redoShape.Add((Shape)lstShape[lstShape.Count - 1].Clone());
          lstShape.RemoveAt(lstShape.Count - 1);
      }
  
      public void Redo()
      {
          lstShape.Add((Shape)redoShape[redoShape.Count - 1].Clone());
          redoShape.RemoveAt(redoShape.Count - 1);
      }
  }
  </code></pre>