├── SimpleCADTest
├── Resources
│ ├── axis.png
│ ├── disk.png
│ ├── grid.png
│ ├── snap.png
│ ├── zoom.png
│ ├── angle.png
│ ├── cross.png
│ ├── folder.png
│ ├── arrow_all.png
│ ├── coordinates.png
│ ├── page_white.png
│ ├── shape_copy.png
│ ├── shape_scale.png
│ ├── disk_multiple.png
│ ├── shape_flip_horizontal.png
│ ├── shape_move_backwards.png
│ └── shape_rotate_clockwise.png
├── App.config
├── Properties
│ ├── Settings.settings
│ ├── Settings.Designer.cs
│ └── AssemblyInfo.cs
├── Program.cs
└── SimpleCADTest.csproj
├── README.md
├── SimpleCAD
├── Document
│ ├── IPersistable.cs
│ ├── Enums.cs
│ ├── LayerDictionary.cs
│ ├── TextStyleDictionary.cs
│ ├── CompositeDictionary.cs
│ ├── IDict.cs
│ ├── SettingsProperties.tt
│ ├── Layer.cs
│ ├── TextStyle.cs
│ ├── PersistableDictionaryWithDefault.cs
│ ├── DocumentWriter.cs
│ ├── PersistableDictionary.cs
│ ├── DocumentReader.cs
│ ├── Model.cs
│ ├── SettingsProperties.cs
│ ├── Settings.cs
│ └── CADDocument.cs
├── Commands
│ ├── Command.cs
│ ├── Command_Selection.cs
│ ├── Command_Edit.cs
│ ├── Command_Composite.cs
│ ├── Command_Document.cs
│ └── Command_View.cs
├── Editor
│ ├── InitArgs.cs
│ ├── InputArgs.cs
│ ├── TextGetter.cs
│ ├── EditorEvents.cs
│ ├── SnapPoint.cs
│ ├── ControlPoint.cs
│ ├── PointGetter.cs
│ ├── OpenFilenameGetter.cs
│ ├── SaveFilenameGetter.cs
│ ├── IntGetter.cs
│ ├── CornerGetter.cs
│ ├── FloatGetter.cs
│ ├── AngleGetter.cs
│ ├── DistanceGetter.cs
│ ├── InputResult.cs
│ ├── CPSelectionSet.cs
│ ├── SnapPointCollection.cs
│ ├── SelectionGetter.cs
│ ├── SelectionSet.cs
│ └── CPSelectionGetter.cs
├── Drawables
│ ├── Polygon.cs
│ ├── Hatch.cs
│ ├── Drawable.cs
│ ├── Point.cs
│ ├── DrawableList.cs
│ ├── DrawableDictionary.cs
│ ├── CompositeReference.cs
│ ├── Curve.cs
│ ├── Rectangle.cs
│ ├── Composite.cs
│ ├── Circle.cs
│ └── Line.cs
├── View
│ ├── Axes.cs
│ ├── ViewEvents.cs
│ ├── SelectionWindow.cs
│ ├── Camera.cs
│ ├── Grid.cs
│ └── Cursor.cs
├── CADWindow.Designer.cs
├── Properties
│ └── AssemblyInfo.cs
├── Geometry
│ ├── Point2DConverter.cs
│ ├── Vector2DConverter.cs
│ ├── Segment2DConverter.cs
│ ├── Segment2D.cs
│ ├── Point2D.cs
│ ├── Extents2D.cs
│ ├── Point2DCollection.cs
│ ├── Vector2D.cs
│ └── Matrix2D.cs
├── Graphics
│ ├── Style.cs
│ └── ColorConverter.cs
├── CADWindow.cs
├── MathF.cs
└── CADWindow.resx
├── SimpleCAD.sln
└── .gitignore
/SimpleCADTest/Resources/axis.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/axis.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/disk.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/disk.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/grid.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/grid.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/snap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/snap.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/zoom.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/zoom.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/angle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/angle.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/cross.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/cross.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/folder.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/arrow_all.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/arrow_all.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/coordinates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/coordinates.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/page_white.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/page_white.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/shape_copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/shape_copy.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/shape_scale.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/shape_scale.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/disk_multiple.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/disk_multiple.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/shape_flip_horizontal.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/shape_flip_horizontal.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/shape_move_backwards.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/shape_move_backwards.png
--------------------------------------------------------------------------------
/SimpleCADTest/Resources/shape_rotate_clockwise.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oozcitak/SimpleCad/HEAD/SimpleCADTest/Resources/shape_rotate_clockwise.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SimpleCad
2 | A basic CAD-like control surface for winforms (WIP).
3 |
4 | 
5 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/IPersistable.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | public interface IPersistable
4 | {
5 | void Load(DocumentReader reader);
6 | void Save(DocumentWriter writer);
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/SimpleCADTest/App.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/Enums.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | public enum AngleMode
4 | {
5 | Radians,
6 | Degrees,
7 | Grads,
8 | DegreesMinutesSeconds,
9 | Surveyor,
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/LayerDictionary.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | public class LayerDictionary : PersistableDictionaryWithDefault
4 | {
5 | public LayerDictionary() : base("0", Layer.Default)
6 | {
7 | ;
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/TextStyleDictionary.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | public class TextStyleDictionary : PersistableDictionaryWithDefault
4 | {
5 | public TextStyleDictionary() : base("0", TextStyle.Default)
6 | {
7 | ;
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/SimpleCADTest/Properties/Settings.settings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/CompositeDictionary.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 |
3 | namespace SimpleCAD
4 | {
5 | public class CompositeDictionary : PersistableDictionary
6 | {
7 | public CompositeDictionary() : base()
8 | {
9 | ;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/SimpleCAD/Commands/Command.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace SimpleCAD
4 | {
5 | public abstract class Command
6 | {
7 | public abstract string RegisteredName { get; }
8 | public abstract string Name { get; }
9 |
10 | public virtual Task Apply(CADDocument doc, params string[] args)
11 | {
12 | return Task.FromResult(default(object));
13 | }
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/IDict.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 |
3 | namespace SimpleCAD
4 | {
5 | public interface IDict : IEnumerable
6 | {
7 | int Count { get; }
8 | TValue this[string key] { get; set; }
9 |
10 | void Add(string key, TValue value);
11 | void Clear();
12 | bool ContainsKey(string key);
13 | bool Remove(string key);
14 | bool TryGetValue(string key, out TValue value);
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/InitArgs.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | internal class InitArgs
4 | {
5 | public TValue Value;
6 | public string ErrorMessage;
7 | public bool InputValid;
8 | public bool ContinueAsync;
9 |
10 | public InitArgs()
11 | {
12 | Value = default(TValue);
13 | InputValid = true;
14 | ContinueAsync = true;
15 | ErrorMessage = "*Invalid input*";
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/SimpleCADTest/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Windows.Forms;
3 |
4 | namespace SimpleCADTest
5 | {
6 | static class Program
7 | {
8 | ///
9 | /// The main entry point for the application.
10 | ///
11 | [STAThread]
12 | static void Main()
13 | {
14 | Application.EnableVisualStyles();
15 | Application.SetCompatibleTextRenderingDefault(false);
16 | Application.Run(new MainForm());
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/SimpleCAD/Commands/Command_Selection.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace SimpleCAD.Commands
4 | {
5 | public class SelectionClear : Command
6 | {
7 | public override string RegisteredName => "Selection.Clear";
8 | public override string Name => "Clear Selection";
9 |
10 | public override Task Apply(CADDocument doc, params string[] args)
11 | {
12 | doc.Editor.CurrentSelection.Clear();
13 | return Task.FromResult(default(object));
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/SimpleCAD/Drawables/Polygon.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using System.ComponentModel;
3 | using System.Drawing;
4 |
5 | namespace SimpleCAD.Drawables
6 | {
7 | public class Polygon : Polyline
8 | {
9 | [Browsable(false)]
10 | public override bool Closed => true;
11 |
12 | public Polygon() : base() { }
13 | public Polygon(Point2DCollection pts) : base(pts) { }
14 | public Polygon(params Point2D[] pts) : base(pts) { }
15 | public Polygon(PointF[] pts) : base(pts) { }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/InputArgs.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | internal class InputArgs
4 | {
5 | public readonly TInput Input;
6 | public TValue Value;
7 | public string ErrorMessage;
8 | public bool InputValid;
9 | public bool InputCompleted;
10 |
11 | public InputArgs(TInput input)
12 | {
13 | Input = input;
14 | Value = default(TValue);
15 | InputValid = true;
16 | InputCompleted = true;
17 | ErrorMessage = "*Invalid input*";
18 | }
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/SettingsProperties.tt:
--------------------------------------------------------------------------------
1 | <#@ template debug="false" hostspecific="false" language="C#" #>
2 | <#@ output extension=".cs" #>
3 | <#@ assembly name="$(TargetPath)" #>
4 | <#@ import namespace="SimpleCAD" #>
5 |
6 | namespace SimpleCAD
7 | {
8 | public partial class Settings
9 | {
10 | <#
11 | foreach(var pair in SimpleCAD.Settings.Defaults)
12 | {
13 | string name = pair.Key;
14 | string type = pair.Value.GetType().FullName;
15 | #>
16 | public <#= type #> <#= name #>
17 | {
18 | get => Get<<#= type #>>("<#= name#>");
19 | set => Set("<#= name #>", value);
20 | }
21 | <#
22 | }
23 | #>
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/TextGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 |
3 | namespace SimpleCAD
4 | {
5 | internal class TextGetter : EditorGetter
6 | {
7 | public TextGetter()
8 | {
9 | SpaceAccepts = false;
10 | }
11 |
12 | protected override void TextChanged(string text)
13 | {
14 | SetCursorText(text);
15 |
16 | Options.Jig(text);
17 | }
18 |
19 | protected override void AcceptCoordsInput(InputArgs args) =>
20 | args.InputValid = false;
21 |
22 | protected override void AcceptTextInput(InputArgs args) =>
23 | args.Value = args.Input;
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/SimpleCAD/Drawables/Hatch.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 | using System.Drawing;
4 |
5 | namespace SimpleCAD.Drawables
6 | {
7 | public class Hatch : Polygon
8 | {
9 | public Hatch() : base()
10 | {
11 | ;
12 | }
13 |
14 | public Hatch(Point2DCollection pts) : base(pts)
15 | {
16 | ;
17 | }
18 |
19 | public Hatch(params Point2D[] pts) : base(pts)
20 | {
21 | ;
22 | }
23 |
24 | public Hatch(PointF[] pts) : base(pts)
25 | {
26 | ;
27 | }
28 |
29 | public override void Draw(Renderer renderer)
30 | {
31 | renderer.FillPolygon(Style.ApplyLayer(Layer), Points);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/EditorEvents.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SimpleCAD
4 | {
5 | public delegate void EditorPromptEventHandler(object sender, EditorPromptEventArgs e);
6 | public delegate void EditorErrorEventHandler(object sender, EditorErrorEventArgs e);
7 |
8 | public class EditorPromptEventArgs : EventArgs
9 | {
10 | public string Status { get; private set; }
11 |
12 | public EditorPromptEventArgs() : this("")
13 | {
14 | ;
15 | }
16 |
17 | public EditorPromptEventArgs(string status) : base()
18 | {
19 | Status = status;
20 | }
21 | }
22 |
23 | public class EditorErrorEventArgs : EventArgs
24 | {
25 | public Exception Error { get; private set; }
26 |
27 | public EditorErrorEventArgs(Exception error) : base()
28 | {
29 | Error = error;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/SimpleCAD/View/Axes.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 |
4 | namespace SimpleCAD.View
5 | {
6 | internal class Axes : Drawable
7 | {
8 | public override void Draw(Renderer renderer)
9 | {
10 | var view = renderer.View;
11 | var doc = view.Document;
12 |
13 | Extents2D bounds = view.GetViewport();
14 | Color axisColor = doc.Settings.AxisColor;
15 |
16 | renderer.DrawLine(new Style(axisColor), new Point2D(0, bounds.Ymin), new Point2D(0, bounds.Ymax));
17 | renderer.DrawLine(new Style(axisColor), new Point2D(bounds.Xmin, 0), new Point2D(bounds.Xmax, 0));
18 | }
19 |
20 | public override Extents2D GetExtents()
21 | {
22 | return Extents2D.Empty;
23 | }
24 |
25 | public override void TransformBy(Matrix2D transformation)
26 | {
27 | ;
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SimpleCAD/Commands/Command_Edit.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Threading.Tasks;
3 |
4 | namespace SimpleCAD.Commands
5 | {
6 | public class EditDelete : Command
7 | {
8 | public override string RegisteredName => "Edit.Delete";
9 | public override string Name => "Delete";
10 |
11 | public override async Task Apply(CADDocument doc, params string[] args)
12 | {
13 | Editor ed = doc.Editor;
14 |
15 | var s = await ed.GetSelection("Select objects: ");
16 | if (s.Result != ResultMode.OK || s.Value.Count == 0) return;
17 | List toDelete = new List();
18 | foreach (Drawable item in s.Value)
19 | {
20 | toDelete.Add(item);
21 | }
22 | foreach(Drawable item in toDelete )
23 | {
24 | doc.Model.Remove(item);
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/SnapPoint.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using System;
3 |
4 | namespace SimpleCAD
5 | {
6 | [Flags]
7 | public enum SnapPointType
8 | {
9 | None = 0,
10 | End = 1,
11 | Middle = 2,
12 | Center = 4,
13 | Quadrant = 8,
14 | Point = 16,
15 | All = End | Middle | Center | Quadrant | Point
16 | }
17 |
18 | public class SnapPoint
19 | {
20 | public string Name { get; private set; }
21 | public SnapPointType Type { get; private set; }
22 | public Point2D Location { get; private set; }
23 |
24 | public SnapPoint(string name, Point2D location) : this(name, SnapPointType.End, location)
25 | {
26 | ;
27 | }
28 |
29 | public SnapPoint(string name, SnapPointType type, Point2D location)
30 | {
31 | Name = name;
32 | Type = type;
33 | Location = location;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/ControlPoint.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 |
3 | namespace SimpleCAD
4 | {
5 | public enum ControlPointType
6 | {
7 | Point,
8 | Angle,
9 | Distance
10 | }
11 |
12 | public class ControlPoint
13 | {
14 | public string Name { get; private set; }
15 | public ControlPointType Type { get; private set; }
16 | public Point2D BasePoint { get; private set; }
17 | public Point2D Location { get; private set; }
18 | internal int Index;
19 |
20 | public ControlPoint(string name, Point2D basePoint)
21 | : this(name, ControlPointType.Point, basePoint, basePoint)
22 | {
23 | ;
24 | }
25 |
26 | public ControlPoint(string name, ControlPointType type, Point2D basePoint, Point2D location)
27 | {
28 | Name = name;
29 | Type = type;
30 | BasePoint = basePoint;
31 | Location = location;
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/PointGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 | using SimpleCAD.Geometry;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class PointGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | if (Options.HasBasePoint)
11 | Jigged = new Line(Options.BasePoint, Options.BasePoint);
12 | }
13 |
14 | protected override void CoordsChanged(Point2D pt)
15 | {
16 | SetCursorText(pt.ToString(Editor.Document.Settings.NumberFormat));
17 |
18 | if (Options.HasBasePoint)
19 | (Jigged as Line).EndPoint = pt;
20 |
21 | Options.Jig(pt);
22 | }
23 |
24 | protected override void AcceptCoordsInput(InputArgs args) =>
25 | args.Value = args.Input;
26 |
27 | protected override void AcceptTextInput(InputArgs args) =>
28 | args.InputValid = Point2D.TryParse(args.Input, out args.Value);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/SimpleCAD/View/ViewEvents.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using System;
3 | using System.Windows.Forms;
4 |
5 | namespace SimpleCAD
6 | {
7 | public delegate void CursorEventHandler(object sender, CursorEventArgs e);
8 |
9 | public class CursorEventArgs : EventArgs
10 | {
11 | public MouseButtons Button { get; private set; }
12 | public Point2D Location { get; private set; }
13 | public int Clicks { get; private set; }
14 | public int Delta { get; private set; }
15 |
16 | public float X { get { return Location.X; } }
17 | public float Y { get { return Location.Y; } }
18 |
19 | public CursorEventArgs(MouseButtons button, int clicks, Point2D location, int delta)
20 | {
21 | Button = button;
22 | Location = location;
23 | Clicks = clicks;
24 | Delta = delta;
25 | }
26 |
27 | public CursorEventArgs(MouseButtons button, int clicks, float x, float y, int delta)
28 | : this(button, clicks, new Point2D(x, y), delta)
29 | {
30 | ;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/OpenFilenameGetter.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Windows.Forms;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class OpenFilenameGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | OpenFileDialog ofd = new OpenFileDialog();
11 | ofd.Title = Options.Message;
12 | ofd.Filter = Options.Filter;
13 | ofd.DefaultExt = "scf";
14 | string filename = "";
15 | string path = "";
16 | if (File.Exists(Options.FileName))
17 | {
18 | filename = Path.GetFileName(Options.FileName);
19 | path = Path.GetDirectoryName(Options.FileName);
20 | }
21 | if (!string.IsNullOrEmpty(filename)) ofd.FileName = filename;
22 | if (!string.IsNullOrEmpty(path)) ofd.InitialDirectory = path;
23 |
24 | if (ofd.ShowDialog() == DialogResult.OK)
25 | args.Value = ofd.FileName;
26 | else
27 | args.InputValid = false;
28 |
29 | args.ContinueAsync = false;
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/SimpleCADTest/Properties/Settings.Designer.cs:
--------------------------------------------------------------------------------
1 | //------------------------------------------------------------------------------
2 | //
3 | // This code was generated by a tool.
4 | // Runtime Version:4.0.30319.42000
5 | //
6 | // Changes to this file may cause incorrect behavior and will be lost if
7 | // the code is regenerated.
8 | //
9 | //------------------------------------------------------------------------------
10 |
11 | namespace SimpleCADTest.Properties
12 | {
13 |
14 |
15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")]
17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
18 |
19 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
20 |
21 | public static Settings Default {
22 | get {
23 | return defaultInstance;
24 | }
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/Layer.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Graphics;
2 | using System.ComponentModel;
3 |
4 | namespace SimpleCAD
5 | {
6 | [TypeConverter(typeof(ExpandableObjectConverter))]
7 | public class Layer : IPersistable
8 | {
9 | public static Layer Default => new Layer("0", new Style(Color.White));
10 |
11 | public string Name { get; private set; }
12 | public Style Style { get; set; } = new Style(Color.White, 0, DashStyle.Solid);
13 | public bool Visible { get; set; } = true;
14 |
15 | public Layer()
16 | {
17 | ;
18 | }
19 |
20 | public Layer(string name, Style style)
21 | {
22 | Name = name;
23 | Style = style;
24 | }
25 |
26 | public void Load(DocumentReader reader)
27 | {
28 | Name = reader.ReadString();
29 | Style = new Style();
30 | Style.Load(reader);
31 | Visible = reader.ReadBoolean();
32 | }
33 |
34 | public void Save(DocumentWriter writer)
35 | {
36 | writer.Write(Name);
37 | Style.Save(writer);
38 | writer.Write(Visible);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/SaveFilenameGetter.cs:
--------------------------------------------------------------------------------
1 | using System.IO;
2 | using System.Windows.Forms;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class SaveFilenameGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | SaveFileDialog sfd = new SaveFileDialog();
11 | sfd.Title = Options.Message;
12 | sfd.Filter = Options.Filter;
13 | sfd.DefaultExt = "scf";
14 | string filename = "";
15 | string path = "";
16 | try
17 | {
18 | filename = Path.GetFileName(Options.FileName);
19 | path = Path.GetDirectoryName(Options.FileName);
20 | }
21 | catch
22 | {
23 | ;
24 | }
25 | if (!string.IsNullOrEmpty(filename)) sfd.FileName = filename;
26 | if (!string.IsNullOrEmpty(path)) sfd.InitialDirectory = path;
27 |
28 | if (sfd.ShowDialog() == DialogResult.OK)
29 | args.Value = sfd.FileName;
30 | else
31 | args.InputValid = false;
32 |
33 | args.ContinueAsync = false;
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/TextStyle.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Graphics;
2 | using System.ComponentModel;
3 |
4 | namespace SimpleCAD
5 | {
6 | [TypeConverter(typeof(ExpandableObjectConverter))]
7 | public class TextStyle : IPersistable
8 | {
9 | public static TextStyle Default => new TextStyle("0", "Calibri Light", FontStyle.Regular);
10 |
11 | public string Name { get; private set; }
12 | public string FontFamily { get; set; }
13 | public FontStyle FontStyle { get; set; }
14 |
15 | public TextStyle()
16 | {
17 | ;
18 | }
19 |
20 | public TextStyle(string name, string fontFamily, FontStyle fontStyle)
21 | {
22 | Name = name;
23 | FontFamily = fontFamily;
24 | FontStyle = fontStyle;
25 | }
26 |
27 | public void Load(DocumentReader reader)
28 | {
29 | Name = reader.ReadString();
30 | FontFamily = reader.ReadString();
31 | FontStyle = (FontStyle)reader.ReadInt();
32 | }
33 |
34 | public void Save(DocumentWriter writer)
35 | {
36 | writer.Write(Name);
37 | writer.Write(FontFamily);
38 | writer.Write((int)FontStyle);
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/PersistableDictionaryWithDefault.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace SimpleCAD
4 | {
5 | public abstract class PersistableDictionaryWithDefault : PersistableDictionary where TValue : IPersistable, new()
6 | {
7 | public string DefaultKey { get; private set; }
8 | public TValue Default { get => dict[DefaultKey]; }
9 |
10 | public PersistableDictionaryWithDefault(string defaultKey, TValue defaultValue) : base()
11 | {
12 | DefaultKey = defaultKey;
13 | dict.Add(defaultKey, defaultValue);
14 | }
15 |
16 | public TValue GetOrDefault(string key)
17 | {
18 | if (dict.TryGetValue(key, out var value))
19 | return value;
20 | else
21 | return Default;
22 | }
23 |
24 | public override void Clear()
25 | {
26 | TValue defaultValue = dict[DefaultKey];
27 | dict.Clear();
28 | dict.Add(DefaultKey, defaultValue);
29 | }
30 |
31 | public override bool Remove(string key)
32 | {
33 | if(dict.Comparer.Equals(key, DefaultKey))
34 | return false;
35 | else
36 | return dict.Remove(key);
37 | }
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/IntGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 |
3 | namespace SimpleCAD
4 | {
5 | internal class IntGetter : EditorGetter
6 | {
7 | protected override void AcceptCoordsInput(InputArgs args) =>
8 | args.InputValid = false;
9 |
10 | protected override void AcceptTextInput(InputArgs args)
11 | {
12 | if (int.TryParse(args.Input, out args.Value))
13 | {
14 | if (!Options.AllowNegative && args.Value < 0)
15 | {
16 | args.ErrorMessage = "*Negative numbers are not allowed*";
17 | args.InputValid = false;
18 | }
19 | else if (!Options.AllowPositive && args.Value > 0)
20 | {
21 | args.ErrorMessage = "*Positive numbers are not allowed*";
22 | args.InputValid = false;
23 | }
24 | else if (!Options.AllowZero && args.Value == 0)
25 | {
26 | args.ErrorMessage = "*Zero is not allowed*";
27 | args.InputValid = false;
28 | }
29 | }
30 | else
31 | {
32 | args.InputValid = false;
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/CornerGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 | using SimpleCAD.Geometry;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class CornerGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | Jigged = new Polygon(Options.BasePoint, Options.BasePoint, Options.BasePoint, Options.BasePoint);
11 | }
12 |
13 | protected override void CoordsChanged(Point2D pt)
14 | {
15 | SetCursorText(pt.ToString(Editor.Document.Settings.NumberFormat));
16 |
17 | Polygon poly = Jigged as Polygon;
18 | Point2D pc1 = poly.Points[0];
19 | Point2D pc2 = new Point2D(pt.X, pc1.Y);
20 | Point2D pc3 = pt;
21 | Point2D pc4 = new Point2D(pc1.X, pt.Y);
22 | poly.Points[0] = pc1;
23 | poly.Points[1] = pc2;
24 | poly.Points[2] = pc3;
25 | poly.Points[3] = pc4;
26 |
27 | Options.Jig(pt);
28 | }
29 |
30 | protected override void AcceptCoordsInput(InputArgs args) =>
31 | args.Value = args.Input;
32 |
33 | protected override void AcceptTextInput(InputArgs args) =>
34 | args.InputValid = Point2D.TryParse(args.Input, out args.Value);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/FloatGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 |
3 | namespace SimpleCAD
4 | {
5 | internal class FloatGetter : EditorGetter
6 | {
7 | protected override void AcceptCoordsInput(InputArgs args) =>
8 | args.InputValid = false;
9 |
10 | protected override void AcceptTextInput(InputArgs args)
11 | {
12 | if (float.TryParse(args.Input, out args.Value))
13 | {
14 | if (!Options.AllowNegative && args.Value < 0)
15 | {
16 | args.ErrorMessage = "*Negative numbers are not allowed*";
17 | args.InputValid = false;
18 | }
19 | else if (!Options.AllowPositive && args.Value > 0)
20 | {
21 | args.ErrorMessage = "*Positive numbers are not allowed*";
22 | args.InputValid = false;
23 | }
24 | else if (!Options.AllowZero && args.Value == 0)
25 | {
26 | args.ErrorMessage = "*Zero is not allowed*";
27 | args.InputValid = false;
28 | }
29 | }
30 | else
31 | {
32 | args.InputValid = false;
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/AngleGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 | using SimpleCAD.Geometry;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class AngleGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | Jigged = new Line(Options.BasePoint, Options.BasePoint);
11 | }
12 |
13 | protected override void CoordsChanged(Point2D pt)
14 | {
15 | float angle = (pt - Options.BasePoint).Angle;
16 | SetCursorText(Editor.AngleToString(angle));
17 |
18 | (Jigged as Line).EndPoint = pt;
19 |
20 | Options.Jig(angle);
21 | }
22 |
23 | protected override void AcceptCoordsInput(InputArgs args) =>
24 | args.Value = (args.Input - Options.BasePoint).Angle;
25 |
26 | protected override void AcceptTextInput(InputArgs args)
27 | {
28 | if (Editor.TryAngleFromString(args.Input, out float angle))
29 | {
30 | args.Value = angle;
31 | }
32 | else if (Vector2D.TryParse(args.Input, out Vector2D vec))
33 | {
34 | args.Value = vec.Angle;
35 | }
36 | else
37 | {
38 | args.InputValid = false;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/DistanceGetter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 | using SimpleCAD.Geometry;
3 |
4 | namespace SimpleCAD
5 | {
6 | internal class DistanceGetter : EditorGetter
7 | {
8 | protected override void Init(InitArgs args)
9 | {
10 | Jigged = new Line(Options.BasePoint, Options.BasePoint);
11 | }
12 |
13 | protected override void CoordsChanged(Point2D pt)
14 | {
15 | float dist = (pt - Options.BasePoint).Length;
16 | SetCursorText(dist.ToString(Editor.Document.Settings.NumberFormat));
17 |
18 | (Jigged as Line).EndPoint = pt;
19 |
20 | Options.Jig(dist);
21 | }
22 |
23 | protected override void AcceptCoordsInput(InputArgs args) =>
24 | args.Value = (args.Input - Options.BasePoint).Length;
25 |
26 | protected override void AcceptTextInput(InputArgs args)
27 | {
28 | if (Vector2D.TryParse(args.Input, out Vector2D vec))
29 | {
30 | args.Value = vec.Length;
31 | }
32 | else if (float.TryParse(args.Input, out args.Value))
33 | {
34 | ;
35 | }
36 | else
37 | {
38 | args.InputValid = false;
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/SimpleCAD/View/SelectionWindow.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 |
4 | namespace SimpleCAD.View
5 | {
6 | internal class SelectionWindow : Drawable
7 | {
8 | public Point2D P1 { get; set; }
9 | public Point2D P2 { get; set; }
10 |
11 | public bool WindowSelection => P2.X > P1.X;
12 |
13 | public SelectionWindow(Point2D p1, Point2D p2)
14 | {
15 | P1 = p1;
16 | P2 = p2;
17 | }
18 |
19 | public override void Draw(Renderer renderer)
20 | {
21 | var doc = renderer.View.Document;
22 |
23 | Style fillStyle = (WindowSelection ? new Style(doc.Settings.SelectionWindowColor) : new Style(doc.Settings.ReverseSelectionWindowColor));
24 | Style outlineStyle = (WindowSelection ? new Style(doc.Settings.SelectionWindowBorderColor) : new Style(doc.Settings.SelectionWindowBorderColor, 0, DashStyle.Dash));
25 |
26 | renderer.FillRectangle(fillStyle, P1, P2);
27 | renderer.DrawRectangle(outlineStyle, P1, P2);
28 | }
29 |
30 | public override Extents2D GetExtents()
31 | {
32 | Extents2D ex = new Extents2D();
33 | ex.Add(P1);
34 | ex.Add(P2);
35 | return ex;
36 | }
37 |
38 | public override void TransformBy(Matrix2D transformation)
39 | {
40 | ;
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/SimpleCADTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("SimpleCADTest")]
8 | [assembly: AssemblyDescription("")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("SimpleCADTest")]
12 | [assembly: AssemblyCopyright("Copyright © 2018")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("7c00350a-2fa9-4eb1-9475-76732dc9eeb6")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/SimpleCAD/CADWindow.Designer.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | partial class CADWindow
4 | {
5 | ///
6 | /// Required designer variable.
7 | ///
8 | private System.ComponentModel.IContainer components = null;
9 |
10 | ///
11 | /// Clean up any resources being used.
12 | ///
13 | /// true if managed resources should be disposed; otherwise, false.
14 | protected override void Dispose(bool disposing)
15 | {
16 | if (disposing && (components != null))
17 | {
18 | components.Dispose();
19 | }
20 | base.Dispose(disposing);
21 | }
22 |
23 | #region Component Designer generated code
24 |
25 | ///
26 | /// Required method for Designer support - do not modify
27 | /// the contents of this method with the code editor.
28 | ///
29 | private void InitializeComponent()
30 | {
31 | this.SuspendLayout();
32 | //
33 | // CADWindow
34 | //
35 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
36 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
37 | this.Name = "CADWindow";
38 | this.Size = new System.Drawing.Size(683, 424);
39 | this.ResumeLayout(false);
40 |
41 | }
42 |
43 | #endregion
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/SimpleCAD/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.InteropServices;
3 |
4 | // General Information about an assembly is controlled through the following
5 | // set of attributes. Change these attribute values to modify the information
6 | // associated with an assembly.
7 | [assembly: AssemblyTitle("SimpleCAD")]
8 | [assembly: AssemblyDescription("A basic CAD-like control surface for winforms.")]
9 | [assembly: AssemblyConfiguration("")]
10 | [assembly: AssemblyCompany("")]
11 | [assembly: AssemblyProduct("SimpleCAD")]
12 | [assembly: AssemblyCopyright("")]
13 | [assembly: AssemblyTrademark("")]
14 | [assembly: AssemblyCulture("")]
15 |
16 | // Setting ComVisible to false makes the types in this assembly not visible
17 | // to COM components. If you need to access a type in this assembly from
18 | // COM, set the ComVisible attribute to true on that type.
19 | [assembly: ComVisible(false)]
20 |
21 | // The following GUID is for the ID of the typelib if this project is exposed to COM
22 | [assembly: Guid("09d0c2a2-1aa1-49d6-b3c7-1e7d4da31a18")]
23 |
24 | // Version information for an assembly consists of the following four values:
25 | //
26 | // Major Version
27 | // Minor Version
28 | // Build Number
29 | // Revision
30 | //
31 | // You can specify all the values or you can default the Build and Revision Numbers
32 | // by using the '*' as shown below:
33 | // [assembly: AssemblyVersion("1.0.*")]
34 | [assembly: AssemblyVersion("1.0.1.0")]
35 | [assembly: AssemblyFileVersion("1.0.1.0")]
36 |
--------------------------------------------------------------------------------
/SimpleCAD.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 15
4 | VisualStudioVersion = 15.0.27130.2027
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleCAD", "SimpleCAD\SimpleCAD.csproj", "{473B4BE8-4019-4A0C-8B73-59A2A07ED028}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SimpleCADTest", "SimpleCADTest\SimpleCADTest.csproj", "{7C00350A-2FA9-4EB1-9475-76732DC9EEB6}"
9 | EndProject
10 | Global
11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
12 | Debug|Any CPU = Debug|Any CPU
13 | Release|Any CPU = Release|Any CPU
14 | EndGlobalSection
15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 | {473B4BE8-4019-4A0C-8B73-59A2A07ED028}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
17 | {473B4BE8-4019-4A0C-8B73-59A2A07ED028}.Debug|Any CPU.Build.0 = Debug|Any CPU
18 | {473B4BE8-4019-4A0C-8B73-59A2A07ED028}.Release|Any CPU.ActiveCfg = Release|Any CPU
19 | {473B4BE8-4019-4A0C-8B73-59A2A07ED028}.Release|Any CPU.Build.0 = Release|Any CPU
20 | {7C00350A-2FA9-4EB1-9475-76732DC9EEB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
21 | {7C00350A-2FA9-4EB1-9475-76732DC9EEB6}.Debug|Any CPU.Build.0 = Debug|Any CPU
22 | {7C00350A-2FA9-4EB1-9475-76732DC9EEB6}.Release|Any CPU.ActiveCfg = Release|Any CPU
23 | {7C00350A-2FA9-4EB1-9475-76732DC9EEB6}.Release|Any CPU.Build.0 = Release|Any CPU
24 | EndGlobalSection
25 | GlobalSection(SolutionProperties) = preSolution
26 | HideSolutionNode = FALSE
27 | EndGlobalSection
28 | GlobalSection(ExtensibilityGlobals) = postSolution
29 | SolutionGuid = {D8E32F36-44D8-4531-8406-EF5032B95559}
30 | EndGlobalSection
31 | EndGlobal
32 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/InputResult.cs:
--------------------------------------------------------------------------------
1 | namespace SimpleCAD
2 | {
3 | public enum ResultMode
4 | {
5 | OK,
6 | Keyword,
7 | Cancel
8 | }
9 |
10 | internal enum AcceptReason
11 | {
12 | None,
13 | Init,
14 | Coords,
15 | Text,
16 | Keyword
17 | }
18 |
19 | internal enum CancelReason
20 | {
21 | None,
22 | Init,
23 | Escape,
24 | Space,
25 | Enter
26 | }
27 |
28 | public class InputResult
29 | {
30 | public ResultMode Result { get; private set; }
31 | public TInput Value { get; private set; }
32 | public string Keyword { get; private set; }
33 | internal AcceptReason AcceptReason { get; private set; }
34 | internal CancelReason CancelReason { get; private set; }
35 |
36 | internal static InputResult CancelResult(CancelReason cancelReason) => new InputResult(ResultMode.Cancel, default(TInput), "", AcceptReason.None, cancelReason);
37 | internal static InputResult KeywordResult(string keyword) => new InputResult(ResultMode.Keyword, default(TInput), keyword, AcceptReason.Keyword, CancelReason.None);
38 | internal static InputResult AcceptResult(TInput value, AcceptReason acceptReason) => new InputResult(ResultMode.OK, value, "", acceptReason, CancelReason.None);
39 |
40 | private InputResult(ResultMode result, TInput value, string keyword, AcceptReason acceptReason, CancelReason cancelReason)
41 | {
42 | Result = result;
43 | Value = value;
44 | Keyword = keyword;
45 | AcceptReason = acceptReason;
46 | CancelReason = cancelReason;
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/SimpleCAD/Commands/Command_Composite.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Drawables;
2 | using SimpleCAD.Geometry;
3 | using System.Collections.Generic;
4 | using System.Threading.Tasks;
5 |
6 | namespace SimpleCAD.Commands
7 | {
8 | public class CompositeCreate : Command
9 | {
10 | public override string RegisteredName => "Composite.Create";
11 | public override string Name => "Create Composite";
12 |
13 | public override async Task Apply(CADDocument doc, params string[] args)
14 | {
15 | Editor ed = doc.Editor;
16 |
17 | var s = await ed.GetSelection("Select objects: ");
18 | if (s.Result != ResultMode.OK || s.Value.Count == 0) return;
19 | var p = await ed.GetPoint("Base point: ");
20 | if (p.Result != ResultMode.OK) return;
21 | var t = await ed.GetText("Name: ");
22 | if (t.Result != ResultMode.OK || string.IsNullOrEmpty(t.Value)) return;
23 |
24 | Composite composite = new Composite();
25 | composite.Name = t.Value;
26 |
27 | Matrix2D matrix = Matrix2D.Translation(-1 * p.Value.AsVector2D());
28 | List toDelete = new List();
29 | foreach (Drawable item in s.Value)
30 | {
31 | item.TransformBy(matrix);
32 | toDelete.Add(item);
33 | composite.Add(item);
34 | }
35 |
36 | doc.Composites.Add(composite.Name, composite);
37 |
38 | foreach (Drawable item in toDelete)
39 | {
40 | doc.Model.Remove(item);
41 | }
42 |
43 | CompositeReference compRef = new CompositeReference();
44 | compRef.Composite = composite;
45 | compRef.Location = p.Value;
46 | doc.Model.Add(compRef);
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/SimpleCAD/Editor/CPSelectionSet.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using System.Linq;
3 |
4 | namespace SimpleCAD
5 | {
6 | public sealed class CPSelectionSet
7 | {
8 | Dictionary> items = new Dictionary>();
9 |
10 | public static CPSelectionSet Empty => new CPSelectionSet();
11 |
12 | public int[] this[Drawable item] => items[item].ToArray();
13 |
14 | public CPSelectionSet()
15 | {
16 | ;
17 | }
18 |
19 | public bool Add(Drawable item, int index)
20 | {
21 | if (items.TryGetValue(item, out var indices))
22 | {
23 | return indices.Add(index);
24 | }
25 | else
26 | {
27 | items.Add(item, new HashSet() { index });
28 | return true;
29 | }
30 | }
31 |
32 | public void Add(Drawable item, IEnumerable indices)
33 | {
34 | foreach (int index in indices)
35 | {
36 | Add(item, index);
37 | }
38 | }
39 |
40 | public void Clear()
41 | {
42 | items.Clear();
43 | }
44 |
45 | public int Count { get { return items.Count; } }
46 |
47 | public IEnumerator>> GetEnumerator()
48 | {
49 | return items.GetEnumerator();
50 | }
51 |
52 | public void UnionWith(CPSelectionSet other)
53 | {
54 | foreach (var item in other)
55 | {
56 | foreach (int index in item.Value)
57 | {
58 | Add(item.Key, index);
59 | }
60 | }
61 | }
62 |
63 | public SelectionSet ToSelectionSet()
64 | {
65 | SelectionSet ss = new SelectionSet();
66 | foreach (var pair in items)
67 | {
68 | ss.Add(pair.Key);
69 | }
70 | return ss;
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/SimpleCAD/View/Camera.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using System.ComponentModel;
3 |
4 | namespace SimpleCAD
5 | {
6 | public class Camera
7 | {
8 | private Point2D position;
9 | private float zoom;
10 |
11 | [Category("Appearance"), DefaultValue(5f / 3f), Description("Determines the zoom factor of the view.")]
12 | public float Zoom
13 | {
14 | get
15 | {
16 | return zoom;
17 | }
18 | set
19 | {
20 | zoom = value;
21 |
22 | if (float.IsNaN(zoom) || float.IsNegativeInfinity(zoom) || float.IsPositiveInfinity(zoom) ||
23 | zoom < float.Epsilon * 1000.0f || zoom > float.MaxValue / 1000.0f)
24 | {
25 | zoom = 1;
26 | }
27 | }
28 | }
29 |
30 | [Category("Appearance"), DefaultValue(typeof(System.Drawing.PointF), "0,0"), Description("Determines the location of the camera.")]
31 | public Point2D Position
32 | {
33 | get
34 | {
35 | return position;
36 | }
37 | set
38 | {
39 | position = value;
40 | float x = position.X;
41 | float y = position.Y;
42 | if (float.IsNaN(x) || float.IsNegativeInfinity(x) || float.IsPositiveInfinity(x) ||
43 | x < float.MinValue / 1000.0f || x > float.MaxValue / 1000.0f)
44 | {
45 | x = 0;
46 | }
47 | if (float.IsNaN(y) || float.IsNegativeInfinity(y) || float.IsPositiveInfinity(y) ||
48 | y < float.MinValue / 1000.0f || y > float.MaxValue / 1000.0f)
49 | {
50 | y = 0;
51 | }
52 | position = new Point2D(x, y);
53 | }
54 | }
55 |
56 | public Camera(Point2D position, float zoom)
57 | {
58 | this.position = position;
59 | this.zoom = zoom;
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/DocumentWriter.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 | using System;
4 | using System.IO;
5 |
6 | namespace SimpleCAD
7 | {
8 | public sealed class DocumentWriter : IDisposable
9 | {
10 | BinaryWriter writer;
11 |
12 | public CADDocument Document { get; private set; }
13 |
14 | public DocumentWriter(CADDocument document, Stream stream)
15 | {
16 | Document = document;
17 | writer = new BinaryWriter(stream);
18 | }
19 |
20 | public void Write(bool value)
21 | {
22 | writer.Write(value);
23 | }
24 |
25 | public void Write(float value)
26 | {
27 | writer.Write(value);
28 | }
29 |
30 | public void Write(int value)
31 | {
32 | writer.Write(value);
33 | }
34 |
35 | public void Write(uint value)
36 | {
37 | writer.Write(value);
38 | }
39 |
40 | public void Write(string value)
41 | {
42 | writer.Write(value);
43 | }
44 |
45 | public void Write(Point2D value)
46 | {
47 | Write(value.X);
48 | Write(value.Y);
49 | }
50 |
51 | public void Write(Point2DCollection value)
52 | {
53 | Write(value.Count);
54 | foreach (Point2D point in value)
55 | Write(point);
56 | }
57 |
58 | public void Write(Vector2D value)
59 | {
60 | Write(value.X);
61 | Write(value.Y);
62 | }
63 |
64 | public void Write(Color value)
65 | {
66 | Write(value.IsByLayer);
67 | Write(value.Argb);
68 | }
69 |
70 | public void Write(Camera value)
71 | {
72 | Write(value.Position);
73 | Write(value.Zoom);
74 | }
75 |
76 | public void Write(IPersistable item)
77 | {
78 | Write(item.GetType().FullName);
79 | item.Save(this);
80 | }
81 |
82 | public void Dispose()
83 | {
84 | writer.Dispose();
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
2 | [Bb]in/
3 | [Oo]bj/
4 | [Ww]in32/
5 | [Xx]64/
6 |
7 | # mstest test results
8 | TestResults
9 |
10 | ## Ignore Visual Studio temporary files, build results, and
11 | ## files generated by popular Visual Studio add-ons.
12 |
13 | # User-specific files
14 | *.suo
15 | # *.user
16 | *.sln.docstates
17 |
18 | # Build results
19 | [Dd]ebug/
20 | [Rr]elease/
21 | x64/
22 | *_i.c
23 | *_i.h
24 | *_p.c
25 | *.ilk
26 | *.meta
27 | *.obj
28 | *.pch
29 | *.pdb
30 | *.pgc
31 | *.pgd
32 | *.rsp
33 | *.sbr
34 | *.tlb
35 | *.tli
36 | *.tlh
37 | *.tmp
38 | *.vspscc
39 | *.vssscc
40 | .builds
41 | *.msi
42 | *.msm
43 |
44 | # Visual Studio 2015/2017 cache/options directory
45 | .vs/
46 |
47 | # Visual C++ cache files
48 | ipch/
49 | *.aps
50 | *.ncb
51 | *.opensdf
52 | *.sdf
53 |
54 | # Visual Studio profiler
55 | *.psess
56 | *.vsp
57 |
58 | # Guidance Automation Toolkit
59 | *.gpState
60 |
61 | # ReSharper is a .NET coding add-in
62 | _ReSharper*
63 |
64 | # NCrunch
65 | *.ncrunch*
66 | .*crunch*.local.xml
67 |
68 | # Installshield output folder
69 | [Ee]xpress
70 |
71 | # DocProject is a documentation generator add-in
72 | DocProject/buildhelp/
73 | DocProject/Help/*.HxT
74 | DocProject/Help/*.HxC
75 | DocProject/Help/*.hhc
76 | DocProject/Help/*.hhk
77 | DocProject/Help/*.hhp
78 | DocProject/Help/Html2
79 | DocProject/Help/html
80 |
81 | # Click-Once directory
82 | publish
83 |
84 | # Publish Web Output
85 | *.Publish.xml
86 |
87 | # Others
88 | [Bb]in
89 | [Oo]bj
90 | sql
91 | TestResults
92 | [Tt]est[Rr]esult*
93 | *.Cache
94 | ClientBin
95 | [Ss]tyle[Cc]op.*
96 | ~$*
97 | *.dbmdl
98 | Generated_Code #added for RIA/Silverlight projects
99 |
100 | # Backup & report files from converting an old project file to a newer
101 | # Visual Studio version. Backup files are not needed, because we have git ;-)
102 | _UpgradeReport_Files/
103 | Backup*/
104 | UpgradeLog*.XML
105 |
106 | # Compiled Object files
107 | *.slo
108 | *.lo
109 | *.o
110 |
111 | # Compiled Dynamic libraries
112 | *.so
113 |
114 | # Compiled Static libraries
115 | *.lai
116 | *.la
117 | *.a
118 | *.opendb
119 | *.db
120 |
--------------------------------------------------------------------------------
/SimpleCAD/Document/PersistableDictionary.cs:
--------------------------------------------------------------------------------
1 | using System.Collections;
2 | using System.Collections.Generic;
3 |
4 | namespace SimpleCAD
5 | {
6 | public abstract class PersistableDictionary : IPersistable, IDict where TValue : IPersistable, new()
7 | {
8 | protected Dictionary dict = new Dictionary();
9 |
10 | public virtual TValue this[string key] { get => dict[key]; set => dict[key] = value; }
11 |
12 | public virtual int Count => dict.Count;
13 |
14 | public virtual void Load(DocumentReader reader)
15 | {
16 | dict = new Dictionary();
17 | int count = reader.ReadInt();
18 | for (int i = 0; i < count; i++)
19 | {
20 | string key = reader.ReadString();
21 | TValue value = reader.ReadPersistable();
22 | dict.Add(key, value);
23 | }
24 | }
25 |
26 | public virtual void Save(DocumentWriter writer)
27 | {
28 | writer.Write(dict.Count);
29 | foreach (var pair in dict)
30 | {
31 | writer.Write(pair.Key);
32 | writer.Write(pair.Value);
33 | }
34 | }
35 |
36 | public virtual void Add(string key, TValue value)
37 | {
38 | dict.Add(key, value);
39 | }
40 |
41 | public virtual void Clear()
42 | {
43 | dict.Clear();
44 | }
45 |
46 | public virtual bool ContainsKey(string key)
47 | {
48 | return dict.ContainsKey(key);
49 | }
50 |
51 | public virtual IEnumerator GetEnumerator()
52 | {
53 | foreach (TValue value in dict.Values)
54 | yield return value;
55 | }
56 |
57 | public virtual bool Remove(string key)
58 | {
59 | return dict.Remove(key);
60 | }
61 |
62 | public virtual bool TryGetValue(string key, out TValue value)
63 | {
64 | return dict.TryGetValue(key, out value);
65 | }
66 |
67 | IEnumerator IEnumerable.GetEnumerator()
68 | {
69 | return GetEnumerator();
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/SimpleCAD/Geometry/Point2DConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace SimpleCAD.Geometry
5 | {
6 | public class Point2DConverter : ExpandableObjectConverter
7 | {
8 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
9 | {
10 | return sourceType == typeof(string);
11 | }
12 |
13 | public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
14 | {
15 | return destinationType == typeof(string);
16 | }
17 |
18 | public override bool IsValid(ITypeDescriptorContext context, object value)
19 | {
20 | string str = value as string;
21 |
22 | if (str == null) return false;
23 |
24 | string[] parts = str.Replace(" ", "").Split(';', ',');
25 | if (parts.Length != 2) return false;
26 | foreach (string part in parts)
27 | {
28 | if (!float.TryParse(part, out _))
29 | return false;
30 | }
31 |
32 | return true;
33 | }
34 |
35 | public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
36 | {
37 | string str = value as string;
38 |
39 | if (str != null)
40 | {
41 | string[] parts = str.Replace(" ", "").Split(';', ',');
42 | if (parts.Length == 2)
43 | {
44 | float x = float.Parse(parts[0]);
45 | float y = float.Parse(parts[1]);
46 | return new Point2D(x, y);
47 | }
48 | }
49 |
50 | return base.ConvertFrom(context, culture, value);
51 | }
52 |
53 | public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
54 | {
55 | if (destinationType == typeof(string) && value is Point2D)
56 | {
57 | Point2D pt = (Point2D)value;
58 | return pt.X.ToString("F2") + "; " + pt.Y.ToString("F2");
59 | }
60 |
61 | return base.ConvertTo(context, culture, value, destinationType);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/SimpleCAD/Geometry/Vector2DConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.ComponentModel;
3 |
4 | namespace SimpleCAD.Geometry
5 | {
6 | public class Vector2DConverter : ExpandableObjectConverter
7 | {
8 | public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
9 | {
10 | return sourceType == typeof(string);
11 | }
12 |
13 | public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
14 | {
15 | return destinationType == typeof(string);
16 | }
17 |
18 | public override bool IsValid(ITypeDescriptorContext context, object value)
19 | {
20 | string str = value as string;
21 |
22 | if (str == null) return false;
23 |
24 | string[] parts = str.Replace(" ", "").Split(';', ',');
25 | if (parts.Length != 2) return false;
26 | foreach (string part in parts)
27 | {
28 | if (!float.TryParse(part, out _))
29 | return false;
30 | }
31 |
32 | return true;
33 | }
34 |
35 | public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
36 | {
37 | string str = value as string;
38 |
39 | if (str != null)
40 | {
41 | string[] parts = str.Replace(" ", "").Split(';', ',');
42 | if (parts.Length == 2)
43 | {
44 | float x = float.Parse(parts[0]);
45 | float y = float.Parse(parts[1]);
46 | return new Vector2D(x, y);
47 | }
48 | }
49 |
50 | return base.ConvertFrom(context, culture, value);
51 | }
52 |
53 | public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
54 | {
55 | if (destinationType == typeof(string) && value is Vector2D)
56 | {
57 | Vector2D vec = (Vector2D)value;
58 | return vec.X.ToString("F2") + "; " + vec.Y.ToString("F2");
59 | }
60 |
61 | return base.ConvertTo(context, culture, value, destinationType);
62 | }
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/SimpleCAD/Graphics/Style.cs:
--------------------------------------------------------------------------------
1 | using System.ComponentModel;
2 |
3 | namespace SimpleCAD.Graphics
4 | {
5 | public enum DashStyle
6 | {
7 | ByLayer = -1,
8 | Solid = 0,
9 | Dash = 1,
10 | Dot = 2,
11 | DashDot = 3,
12 | DashDotDot = 4,
13 | }
14 |
15 | [TypeConverter(typeof(ExpandableObjectConverter))]
16 | public class Style : IPersistable
17 | {
18 | public static Style Default => new Style(Color.ByLayer, ByLayer, DashStyle.ByLayer);
19 |
20 | public const float ByLayer = -1;
21 |
22 | public Color Color { get; set; }
23 | public float LineWeight { get; set; }
24 | public DashStyle DashStyle { get; set; }
25 |
26 | public Style(Color color, float lineWeight, DashStyle dashStyle)
27 | {
28 | Color = color;
29 | LineWeight = lineWeight;
30 | DashStyle = dashStyle;
31 | }
32 |
33 | public Style(Color color, float lineWeight)
34 | : this(color, lineWeight, DashStyle.Solid)
35 | {
36 | ;
37 | }
38 |
39 | public Style(Color color)
40 | : this(color, 0, DashStyle.Solid)
41 | {
42 | ;
43 | }
44 |
45 | public Style()
46 | : this(Color.ByLayer, ByLayer, DashStyle.ByLayer)
47 | {
48 | ;
49 | }
50 |
51 | public Style ApplyLayer(Layer layer)
52 | {
53 | Style style = new Style(Color, LineWeight, DashStyle);
54 | if (layer != null)
55 | {
56 | if (Color.IsByLayer) style.Color = layer.Style.Color;
57 | if (LineWeight == ByLayer) style.LineWeight = layer.Style.LineWeight;
58 | if (DashStyle == DashStyle.ByLayer) style.DashStyle = layer.Style.DashStyle;
59 | }
60 | return style;
61 | }
62 |
63 | public void Load(DocumentReader reader)
64 | {
65 | Color = reader.ReadColor();
66 | LineWeight = reader.ReadFloat();
67 | DashStyle = (DashStyle)reader.ReadInt();
68 | }
69 |
70 | public void Save(DocumentWriter writer)
71 | {
72 | writer.Write(Color);
73 | writer.Write(LineWeight);
74 | writer.Write((int)DashStyle);
75 | }
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/SimpleCAD/View/Grid.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 |
4 | namespace SimpleCAD.View
5 | {
6 | internal class Grid : Drawable
7 | {
8 | public override void Draw(Renderer renderer)
9 | {
10 | var view = renderer.View;
11 | var doc = view.Document;
12 |
13 | float spacing = 1;
14 | // Dynamic grid spacing
15 | while (view.WorldToScreen(new Vector2D(spacing, 0)).X > 12)
16 | spacing /= 10;
17 |
18 | while (view.WorldToScreen(new Vector2D(spacing, 0)).X < 4)
19 | spacing *= 10;
20 |
21 | Extents2D bounds = view.GetViewport();
22 | Style majorStyle = new Style(doc.Settings.MajorGridColor);
23 | Style minorStyle = new Style(doc.Settings.MinorGridColor);
24 |
25 | int k = 0;
26 | for (float i = 0; i > bounds.Xmin; i -= spacing)
27 | {
28 | Style style = (k == 0 ? majorStyle : minorStyle);
29 | k = (k + 1) % 10;
30 | renderer.DrawLine(style, new Point2D(i, bounds.Ymax), new Point2D(i, bounds.Ymin));
31 | }
32 | k = 0;
33 | for (float i = 0; i < bounds.Xmax; i += spacing)
34 | {
35 | Style style = (k == 0 ? majorStyle : minorStyle);
36 | k = (k + 1) % 10;
37 | renderer.DrawLine(style, new Point2D(i, bounds.Ymax), new Point2D(i, bounds.Ymin));
38 | }
39 | k = 0;
40 | for (float i = 0; i < bounds.Ymax; i += spacing)
41 | {
42 | Style style = (k == 0 ? majorStyle : minorStyle);
43 | k = (k + 1) % 10;
44 | renderer.DrawLine(style, new Point2D(bounds.Xmin, i), new Point2D(bounds.Xmax, i));
45 | }
46 | k = 0;
47 | for (float i = 0; i > bounds.Ymin; i -= spacing)
48 | {
49 | Style style = (k == 0 ? majorStyle : minorStyle);
50 | k = (k + 1) % 10;
51 | renderer.DrawLine(style, new Point2D(bounds.Xmin, i), new Point2D(bounds.Xmax, i));
52 | }
53 | }
54 |
55 | public override Extents2D GetExtents()
56 | {
57 | return Extents2D.Infinity;
58 | }
59 |
60 | public override void TransformBy(Matrix2D transformation)
61 | {
62 | ;
63 | }
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/SimpleCAD/Commands/Command_Document.cs:
--------------------------------------------------------------------------------
1 | using System.Threading.Tasks;
2 |
3 | namespace SimpleCAD.Commands
4 | {
5 | public class DocumentNew : Command
6 | {
7 | public override string RegisteredName => "Document.New";
8 | public override string Name => "New";
9 |
10 | public override Task Apply(CADDocument doc, params string[] args)
11 | {
12 | doc.New();
13 | return Task.FromResult(default(object));
14 | }
15 | }
16 |
17 | public class DocumentOpen : Command
18 | {
19 | public override string RegisteredName => "Document.Open";
20 | public override string Name => "Open";
21 |
22 | public override async Task Apply(CADDocument doc, params string[] args)
23 | {
24 | Editor ed = doc.Editor;
25 | ed.PickedSelection.Clear();
26 |
27 | var res = await ed.GetOpenFilename("Open file");
28 | if (res.Result == ResultMode.OK)
29 | {
30 | doc.Open(res.Value);
31 | }
32 | }
33 | }
34 |
35 | public class DocumentSave : Command
36 | {
37 | public override string RegisteredName => "Document.Save";
38 | public override string Name => "Save";
39 |
40 | public override async Task Apply(CADDocument doc, params string[] args)
41 | {
42 | Editor ed = doc.Editor;
43 | ed.PickedSelection.Clear();
44 |
45 | string filename = doc.FileName;
46 | if (string.IsNullOrEmpty(filename))
47 | {
48 | var res = await ed.GetSaveFilename("Save file");
49 | if (res.Result == ResultMode.OK)
50 | filename = res.Value;
51 | else
52 | return;
53 | }
54 | doc.Save(filename);
55 | }
56 | }
57 |
58 | public class DocumentSaveAs : Command
59 | {
60 | public override string RegisteredName => "Document.SaveAs";
61 | public override string Name => "Save As";
62 |
63 | public override async Task Apply(CADDocument doc, params string[] args)
64 | {
65 | Editor ed = doc.Editor;
66 | ed.PickedSelection.Clear();
67 |
68 | var res = await ed.GetSaveFilename("Save file");
69 | if (res.Result == ResultMode.OK)
70 | {
71 | doc.Save(res.Value);
72 | }
73 | }
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/SimpleCAD/Drawables/Drawable.cs:
--------------------------------------------------------------------------------
1 | using SimpleCAD.Geometry;
2 | using SimpleCAD.Graphics;
3 | using System;
4 | using System.ComponentModel;
5 | using System.Runtime.CompilerServices;
6 |
7 | namespace SimpleCAD
8 | {
9 | public abstract class Drawable : INotifyPropertyChanged, IPersistable
10 | {
11 | public Lazy layerRef = new Lazy(() => Layer.Default);
12 |
13 | public Style Style { get; set; } = Style.Default;
14 | public Layer Layer { get => layerRef.Value; set => layerRef = new Lazy(() => value); }
15 | public bool Visible { get; set; } = true;
16 | internal bool InModel { get; set; } = false;
17 |
18 | public event PropertyChangedEventHandler PropertyChanged;
19 |
20 | public abstract void Draw(Renderer renderer);
21 | public abstract Extents2D GetExtents();
22 | public virtual bool Contains(Point2D pt, float pickBoxSize) { return GetExtents().Contains(pt); }
23 | public abstract void TransformBy(Matrix2D transformation);
24 | public virtual ControlPoint[] GetControlPoints() { return new ControlPoint[0]; }
25 | public virtual ControlPoint[] GetStretchPoints() { return GetControlPoints(); }
26 | public virtual SnapPoint[] GetSnapPoints() { return new SnapPoint[0]; }
27 | public virtual void TransformControlPoints(int[] indices, Matrix2D transformation) { }
28 | public virtual void TransformStretchPoints(int[] indices, Matrix2D transformation) { TransformControlPoints(indices, transformation); }
29 |
30 | public virtual Drawable Clone() { return (Drawable)MemberwiseClone(); }
31 |
32 | protected Drawable() { }
33 |
34 | protected void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
35 | {
36 | PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
37 | }
38 |
39 | public virtual void Load(DocumentReader reader)
40 | {
41 | var doc = reader.Document;
42 | string layerName = reader.ReadString();
43 | layerRef = new Lazy(() => doc.Layers[layerName]);
44 | Style = reader.ReadPersistable