Added plate support
This commit is contained in:
Родитель
ddcb10c4da
Коммит
8cac594725
|
@ -40,6 +40,8 @@ namespace SpiroNet.Wpf
|
|||
private int _hitShapePointIndex = -1;
|
||||
private double _width = 600;
|
||||
private double _height = 600;
|
||||
private bool _isStroked = true;
|
||||
private bool _isFilled = false;
|
||||
private bool _isClosed = false;
|
||||
private bool _isTagged = false;
|
||||
private SpiroPointType _pointType = SpiroPointType.G4;
|
||||
|
@ -88,6 +90,18 @@ namespace SpiroNet.Wpf
|
|||
set { Update(ref _height, value); }
|
||||
}
|
||||
|
||||
public bool IsStroked
|
||||
{
|
||||
get { return _isStroked; }
|
||||
set { Update(ref _isStroked, value); }
|
||||
}
|
||||
|
||||
public bool IsFilled
|
||||
{
|
||||
get { return _isFilled; }
|
||||
set { Update(ref _isFilled, value); }
|
||||
}
|
||||
|
||||
public bool IsClosed
|
||||
{
|
||||
get { return _isClosed; }
|
||||
|
@ -128,6 +142,10 @@ namespace SpiroNet.Wpf
|
|||
|
||||
public ICommand ExitCommand { get; set; }
|
||||
|
||||
public ICommand IsStrokedCommand { get; set; }
|
||||
|
||||
public ICommand IsFilledCommand { get; set; }
|
||||
|
||||
public ICommand IsClosedCommand { get; set; }
|
||||
|
||||
public ICommand IsTaggedCommand { get; set; }
|
||||
|
@ -138,6 +156,26 @@ namespace SpiroNet.Wpf
|
|||
|
||||
public Action Invalidate { get; set; }
|
||||
|
||||
public void ToggleIsStroked()
|
||||
{
|
||||
IsStroked = !IsStroked;
|
||||
if (_shape != null)
|
||||
{
|
||||
_shape.IsStroked = IsStroked;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleIsFilled()
|
||||
{
|
||||
IsFilled = !IsFilled;
|
||||
if (_shape != null)
|
||||
{
|
||||
_shape.IsFilled = IsFilled;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
public void ToggleIsClosed()
|
||||
{
|
||||
IsClosed = !IsClosed;
|
||||
|
@ -172,6 +210,8 @@ namespace SpiroNet.Wpf
|
|||
private void NewShape()
|
||||
{
|
||||
_shape = new PathShape();
|
||||
_shape.IsStroked = IsStroked;
|
||||
_shape.IsFilled = IsFilled;
|
||||
_shape.IsClosed = IsClosed;
|
||||
_shape.IsTagged = IsTagged;
|
||||
_shape.Points = new ObservableCollection<SpiroControlPoint>();
|
||||
|
@ -396,17 +436,17 @@ namespace SpiroNet.Wpf
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
public void Open(string path)
|
||||
public void OpenDrawing(string path)
|
||||
{
|
||||
using (var f = System.IO.File.OpenText(path))
|
||||
{
|
||||
var json = f.ReadToEnd();
|
||||
var drawing = JsonSerializer.Deserialize<PathDrawing>(json);
|
||||
Open(drawing);
|
||||
OpenDrawing(drawing);
|
||||
}
|
||||
}
|
||||
|
||||
public void Open(PathDrawing drawing)
|
||||
public void OpenDrawing(PathDrawing drawing)
|
||||
{
|
||||
Width = drawing.Width;
|
||||
Height = drawing.Height;
|
||||
|
@ -421,7 +461,7 @@ namespace SpiroNet.Wpf
|
|||
Invalidate();
|
||||
}
|
||||
|
||||
public void SaveAs(string path)
|
||||
public void SaveAsDrawing(string path)
|
||||
{
|
||||
using (var f = System.IO.File.CreateText(path))
|
||||
{
|
||||
|
@ -436,6 +476,77 @@ namespace SpiroNet.Wpf
|
|||
}
|
||||
}
|
||||
|
||||
public void OpenPlate(string path)
|
||||
{
|
||||
using (var f = System.IO.File.OpenText(path))
|
||||
{
|
||||
var plate = f.ReadToEnd();
|
||||
ExecuteScript(plate);
|
||||
}
|
||||
}
|
||||
|
||||
public void SaveAsPlate(string path)
|
||||
{
|
||||
using (var f = System.IO.File.CreateText(path))
|
||||
{
|
||||
var plate = ToPlate(Shapes);
|
||||
f.Write(plate);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Format(double value)
|
||||
{
|
||||
return value.ToString(CultureInfo.GetCultureInfo("en-GB"));
|
||||
}
|
||||
|
||||
public static string ToPlate(IList<PathShape> shapes)
|
||||
{
|
||||
var sb = new StringBuilder();
|
||||
|
||||
sb.AppendLine("(plate");
|
||||
|
||||
foreach (var shape in shapes)
|
||||
{
|
||||
foreach (var point in shape.Points)
|
||||
{
|
||||
switch (point.Type)
|
||||
{
|
||||
case SpiroPointType.Corner:
|
||||
sb.AppendLine(string.Format(" (v {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.G4:
|
||||
sb.AppendLine(string.Format(" (o {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.G2:
|
||||
sb.AppendLine(string.Format(" (c {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.Left:
|
||||
sb.AppendLine(string.Format(" ([ {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.Right:
|
||||
sb.AppendLine(string.Format(" (] {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.End:
|
||||
sb.AppendLine(" (z)");
|
||||
break;
|
||||
case SpiroPointType.OpenContour:
|
||||
sb.AppendLine(string.Format(" ({ {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
case SpiroPointType.EndOpenContour:
|
||||
sb.AppendLine(string.Format(" (} {0} {1})", Format(point.X), Format(point.Y)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (shape.IsClosed && !shape.IsTagged)
|
||||
sb.AppendLine(" (z)");
|
||||
}
|
||||
|
||||
sb.AppendLine(")");
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void ExportAsSvg(string path)
|
||||
{
|
||||
using (var f = System.IO.File.CreateText(path))
|
||||
|
@ -444,15 +555,23 @@ namespace SpiroNet.Wpf
|
|||
var suffix = Environment.NewLine + " ";
|
||||
|
||||
sb.AppendLine("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>");
|
||||
sb.AppendLine(string.Format("<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"{1}\" height=\"{0}\">", Width, Height));
|
||||
sb.AppendLine(
|
||||
string.Format(
|
||||
"<svg xmlns=\"http://www.w3.org/2000/svg\" version=\"1.1\" width=\"{0}\" height=\"{1}\">",
|
||||
Width,
|
||||
Height));
|
||||
|
||||
foreach (var shape in Shapes)
|
||||
{
|
||||
sb.AppendLine(string.Format(" <path {0}",
|
||||
shape.IsClosed ?
|
||||
"style=\"fill-rule:nonzero;stroke:#000000;stroke-opacity:1;stroke-width:2;fill:#808080;fill-opacity:0.5\"" :
|
||||
"style=\"fill-rule:nonzero;stroke:#000000;stroke-opacity:1;stroke-width:2;fill:none\""));
|
||||
sb.AppendLine(string.Format(" d=\"{0}\"/>", Data[shape].Replace(Environment.NewLine, suffix)));
|
||||
sb.AppendLine(
|
||||
string.Format(
|
||||
" <path style=\"{0};{1}\"",
|
||||
shape.IsStroked ? "stroke:#000000;stroke-opacity:1;stroke-width:2" : "stroke:none",
|
||||
shape.IsFilled ? "fill:#808080;fill-opacity:0.5" : "fill:none"));
|
||||
sb.AppendLine(
|
||||
string.Format(
|
||||
" d=\"{0}\"/>",
|
||||
Data[shape].Replace(Environment.NewLine, suffix)));
|
||||
}
|
||||
|
||||
sb.AppendLine("</svg>");
|
||||
|
@ -465,13 +584,15 @@ namespace SpiroNet.Wpf
|
|||
{
|
||||
return new PathShape()
|
||||
{
|
||||
IsStroked = true,
|
||||
IsFilled = false,
|
||||
IsClosed = false,
|
||||
IsTagged = true,
|
||||
Points = new ObservableCollection<SpiroControlPoint>()
|
||||
};
|
||||
}
|
||||
|
||||
private SpiroControlPoint ToPoint(SpiroPointType type, string x, string y)
|
||||
private static SpiroControlPoint ToPoint(SpiroPointType type, string x, string y)
|
||||
{
|
||||
var point = new SpiroControlPoint();
|
||||
point.X = double.Parse(x, CultureInfo.GetCultureInfo("en-GB").NumberFormat);
|
||||
|
@ -487,13 +608,17 @@ namespace SpiroNet.Wpf
|
|||
|
||||
var newLine = Environment.NewLine.ToCharArray();
|
||||
var separator = new char[] { ' ', '\t' };
|
||||
var trim = new char[] { '(', ')' };
|
||||
var options = StringSplitOptions.RemoveEmptyEntries;
|
||||
var lines = script.Split(newLine, options).Select(x => x.Trim().Split(separator, options));
|
||||
var lines = script.Split(newLine, options).Select(x => x.Trim().Trim(trim).Split(separator, options));
|
||||
|
||||
PathShape shape = null;
|
||||
|
||||
foreach (var line in lines)
|
||||
{
|
||||
if (line.Length == 0 || line[0] == "plate")
|
||||
continue;
|
||||
|
||||
switch (line[0][0])
|
||||
{
|
||||
case 'v':
|
||||
|
|
|
@ -96,7 +96,10 @@ namespace SpiroNet.Wpf
|
|||
if (Context.Data.TryGetValue(shape, out data) && !string.IsNullOrEmpty(data))
|
||||
{
|
||||
var geometry = Geometry.Parse(data);
|
||||
dc.DrawGeometry(shape.IsClosed ? _geometryBrush : null, _geometryPen, geometry);
|
||||
dc.DrawGeometry(
|
||||
shape.IsFilled ? _geometryBrush : null,
|
||||
shape.IsStroked ? _geometryPen : null,
|
||||
geometry);
|
||||
}
|
||||
|
||||
if (shape.Points != null)
|
||||
|
|
|
@ -116,7 +116,9 @@
|
|||
Focusable="True"
|
||||
FocusVisualStyle="{x:Null}">
|
||||
<local:SpiroCanvas.InputBindings>
|
||||
<KeyBinding Command="{Binding IsClosedCommand}" Key="S" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding IsStrokedCommand}" Key="K" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding IsFilledCommand}" Key="F" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding IsClosedCommand}" Key="D" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding IsTaggedCommand}" Key="T" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding PointTypeCommand}" CommandParameter="Corner" Key="V" Modifiers=""/>
|
||||
<KeyBinding Command="{Binding PointTypeCommand}" CommandParameter="G4" Key="O" Modifiers=""/>
|
||||
|
@ -141,7 +143,30 @@
|
|||
</GroupBox>
|
||||
<GroupBox Header="New Shape" Margin="4,2,4,2">
|
||||
<StackPanel>
|
||||
<CheckBox IsChecked="{Binding IsClosed}" VerticalContentAlignment="Center" Content="Is Closed 's'" Margin="1">
|
||||
<CheckBox IsChecked="{Binding IsStroked}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Is Stroked k"
|
||||
Margin="1">
|
||||
<CheckBox.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Is stroked path shape" FontWeight="Bold"/>
|
||||
</StackPanel>
|
||||
</CheckBox.ToolTip>
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding IsFilled}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Is Filled f"
|
||||
Margin="1">
|
||||
<CheckBox.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Is filled path shape" FontWeight="Bold"/>
|
||||
</StackPanel>
|
||||
</CheckBox.ToolTip>
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding IsClosed}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Is Closed d"
|
||||
Margin="1">
|
||||
<CheckBox.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Is closed spiro shape" FontWeight="Bold"/>
|
||||
|
@ -149,7 +174,10 @@
|
|||
</StackPanel>
|
||||
</CheckBox.ToolTip>
|
||||
</CheckBox>
|
||||
<CheckBox IsChecked="{Binding IsTagged}" VerticalContentAlignment="Center" Content="Is Tagged 't'" Margin="1">
|
||||
<CheckBox IsChecked="{Binding IsTagged}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Is Tagged t"
|
||||
Margin="1">
|
||||
<CheckBox.ToolTip>
|
||||
<StackPanel>
|
||||
<TextBlock Text="Is tagged spiro shape" FontWeight="Bold"/>
|
||||
|
@ -165,7 +193,7 @@
|
|||
<StackPanel>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.Corner}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Corner 'v'"
|
||||
Content="Corner v"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -176,7 +204,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.G4}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="G4 'o'"
|
||||
Content="G4 o"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -187,7 +215,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.G2}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="G2 'c'"
|
||||
Content="G2 c"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -198,7 +226,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.Left}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Left '['"
|
||||
Content="Left ["
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -209,7 +237,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.Right}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="Right ']'"
|
||||
Content="Right ]"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -221,7 +249,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.End}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="End 'z'"
|
||||
Content="End z"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -232,7 +260,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.OpenContour}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="OpenContour '{'"
|
||||
Content="OpenContour {"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -243,7 +271,7 @@
|
|||
</RadioButton>
|
||||
<RadioButton IsChecked="{Binding Path=PointType, Converter={StaticResource EnumToBooleanConverterKey}, ConverterParameter={x:Static spiro:SpiroPointType.EndOpenContour}}"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="EndOpenContour '}'"
|
||||
Content="EndOpenContour }"
|
||||
Margin="1">
|
||||
<RadioButton.ToolTip>
|
||||
<StackPanel>
|
||||
|
@ -257,17 +285,20 @@
|
|||
<TextBlock Text="Mouse:" TextAlignment="Left" Foreground="Gray" Margin="4,0,4,0"/>
|
||||
<TextBlock Text="Left -> Add Point" TextAlignment="Left" Foreground="Gray" Margin="4,0,4,0"/>
|
||||
<TextBlock Text="Right -> Finish Shape" TextAlignment="Left" Foreground="Gray" Margin="4,0,4,0"/>
|
||||
<TextBlock Text="Script:" TextAlignment="Left" Foreground="Black" Margin="4,4,4,0"/>
|
||||
<TextBlock Text="Script/plate:" TextAlignment="Left" Foreground="Black" Margin="4,4,4,0"/>
|
||||
<TextBox x:Name="scriptTextBox"
|
||||
AcceptsReturn="True"
|
||||
AcceptsTab="True"
|
||||
IsReadOnly="False"
|
||||
Height="240"
|
||||
Height="180"
|
||||
VerticalScrollBarVisibility="Auto"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
Margin="4,0,4,0">
|
||||
</TextBox>
|
||||
<Button Content="Run" Command="{Binding ExecuteScriptCommand}" CommandParameter="{Binding ElementName=scriptTextBox, Path=Text}" Margin="4,4,4,0"/>
|
||||
<Button Content="Run" Command="{Binding ExecuteScriptCommand}"
|
||||
CommandParameter="{Binding ElementName=scriptTextBox, Path=Text}"
|
||||
Margin="4,4,4,0">
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -63,6 +63,8 @@ namespace SpiroNet.Wpf
|
|||
{
|
||||
Width = 600,
|
||||
Height = 600,
|
||||
IsStroked = true,
|
||||
IsFilled = false,
|
||||
IsClosed = false,
|
||||
IsTagged = false,
|
||||
PointType = SpiroPointType.G4,
|
||||
|
@ -77,6 +79,8 @@ namespace SpiroNet.Wpf
|
|||
_context.SaveAsCommand = Command.Create(SaveAs);
|
||||
_context.ExportAsSvgCommand = Command.Create(ExportAsSvg);
|
||||
_context.ExitCommand = Command.Create(Exit);
|
||||
_context.IsStrokedCommand = Command.Create(_context.ToggleIsStroked);
|
||||
_context.IsFilledCommand = Command.Create(_context.ToggleIsFilled);
|
||||
_context.IsClosedCommand = Command.Create(_context.ToggleIsClosed);
|
||||
_context.IsTaggedCommand = Command.Create(_context.ToggleIsTagged);
|
||||
_context.PointTypeCommand = Command<string>.Create(_context.TogglePointType);
|
||||
|
@ -118,25 +122,47 @@ namespace SpiroNet.Wpf
|
|||
private void Open()
|
||||
{
|
||||
var dlg = new Microsoft.Win32.OpenFileDialog();
|
||||
dlg.Filter = "Spiro Files (*.spiro)|*.spiro|All Files (*.*)|*.*";
|
||||
dlg.Filter = "Spiro Files (*.spiro)|*.spiro|Plate Files (*.plate)|*.plate|All Files (*.*)|*.*";
|
||||
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
{
|
||||
_context.Open(dlg.FileName);
|
||||
switch (dlg.FilterIndex)
|
||||
{
|
||||
case 1:
|
||||
_context.OpenDrawing(dlg.FileName);
|
||||
break;
|
||||
case 2:
|
||||
_context.OpenPlate(dlg.FileName);
|
||||
break;
|
||||
default:
|
||||
_context.OpenDrawing(dlg.FileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SaveAs()
|
||||
{
|
||||
var dlg = new Microsoft.Win32.SaveFileDialog();
|
||||
dlg.Filter = "Spiro Files (*.spiro)|*.spiro|All Files (*.*)|*.*";
|
||||
dlg.Filter = "Spiro Files (*.spiro)|*.spiro|Plate Files (*.plate)|*.plate|All Files (*.*)|*.*";
|
||||
dlg.FileName = "drawing.spiro";
|
||||
|
||||
var result = dlg.ShowDialog();
|
||||
if (result == true)
|
||||
{
|
||||
_context.SaveAs(dlg.FileName);
|
||||
switch (dlg.FilterIndex)
|
||||
{
|
||||
case 1:
|
||||
_context.SaveAsDrawing(dlg.FileName);
|
||||
break;
|
||||
case 2:
|
||||
_context.SaveAsPlate(dlg.FileName);
|
||||
break;
|
||||
default:
|
||||
_context.SaveAsDrawing(dlg.FileName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,30 @@ namespace SpiroNet.Wpf
|
|||
/// </summary>
|
||||
public class PathShape : ObservableObject
|
||||
{
|
||||
private bool _isStroked;
|
||||
private bool _isFilled;
|
||||
private bool _isClosed;
|
||||
private bool _isTagged;
|
||||
private IList<SpiroControlPoint> _points;
|
||||
|
||||
/// <summary>
|
||||
/// Is stroked path shape.
|
||||
/// </summary>
|
||||
public bool IsStroked
|
||||
{
|
||||
get { return _isStroked; }
|
||||
set { Update(ref _isStroked, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is filled path shape.
|
||||
/// </summary>
|
||||
public bool IsFilled
|
||||
{
|
||||
get { return _isFilled; }
|
||||
set { Update(ref _isFilled, value); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is closed spiro shape.
|
||||
/// Whether points describe a closed (True) or open (False) contour.
|
||||
|
|
Загрузка…
Ссылка в новой задаче