This commit is contained in:
Wiesław Šoltés 2023-04-13 19:54:15 +02:00
Родитель 6381d49021
Коммит a98177e2b7
398 изменённых файлов: 20682 добавлений и 21825 удалений

Просмотреть файл

@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<AvaloniaVersion>11.0.0-preview4</AvaloniaVersion>
<AvaloniaVersion>11.0.0-preview6</AvaloniaVersion>
<SkiaSharpVersion>2.88.3</SkiaSharpVersion>
</PropertyGroup>
</Project>

Просмотреть файл

@ -1,13 +1,13 @@
<Application x:Class="Draw2D.App"
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Draw2D">
xmlns:local="clr-namespace:Draw2D"
RequestedThemeVariant="Dark">
<Application.DataTemplates>
<local:ViewLocator />
</Application.DataTemplates>
<Application.Styles>
<StyleInclude Source="avares://Avalonia.Themes.Fluent/FluentDark.xaml" />
<StyleInclude Source="avares://Avalonia.Themes.Fluent/DensityStyles/Compact.xaml" />
<FluentTheme DensityStyle="Compact" />
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Fluent.xaml" />
<Style Selector="Border.default">
<Setter Property="Padding" Value="0" />

Просмотреть файл

@ -11,222 +11,221 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Tools;
using Draw2D.Views;
namespace Draw2D
namespace Draw2D;
public static class EditorToolContextBuilder
{
public static class EditorToolContextBuilder
public static void UseSkia(this IEditorToolContext editorToolContext)
{
public static void UseSkia(this IEditorToolContext editorToolContext)
{
editorToolContext.PathConverter = new SkiaPathConverter();
editorToolContext.AvaloniaXamlConverter = new AvaloniaXamlConverter();
editorToolContext.ContainerImporter = new SkiaContainerImporter();
editorToolContext.ContainerExporter = new SkiaContainerExporter();
editorToolContext.SvgConverter = new SkiaSvgConverter();
}
editorToolContext.PathConverter = new SkiaPathConverter();
editorToolContext.AvaloniaXamlConverter = new AvaloniaXamlConverter();
editorToolContext.ContainerImporter = new SkiaContainerImporter();
editorToolContext.ContainerExporter = new SkiaContainerExporter();
editorToolContext.SvgConverter = new SkiaSvgConverter();
}
}
public class App : Application
public class App : Application
{
public static string DocumentPath { get; set; }
public static string EditorPath { get; set; }
public static string WindowPath { get; set; }
public static IContainerFactory ContainerFactory { get; set; }
public static IStyleLibrary StyleLibrary { get; set; }
public static IGroupLibrary GroupLibrary { get; set; }
public static IToolContext ToolContext { get; set; }
public static WindowSettings WindowSettings { get; set; }
static App()
{
public static string DocumentPath { get; set; }
public static string EditorPath { get; set; }
public static string WindowPath { get; set; }
public static IContainerFactory ContainerFactory { get; set; }
public static IStyleLibrary StyleLibrary { get; set; }
public static IGroupLibrary GroupLibrary { get; set; }
public static IToolContext ToolContext { get; set; }
public static WindowSettings WindowSettings { get; set; }
DocumentPath = "document.json";
EditorPath = "editor.json";
WindowPath = "window.json";
static App()
ContainerFactory = new DefaultContainerFactory();
if (Design.IsDesignMode)
{
DocumentPath = "document.json";
EditorPath = "editor.json";
WindowPath = "window.json";
ContainerFactory = new DefaultContainerFactory();
if (Design.IsDesignMode)
{
StyleLibrary = ContainerFactory.CreateStyleLibrary();
GroupLibrary = ContainerFactory.CreateGroupLibrary();
ToolContext = ContainerFactory.CreateToolContext();
ToolContext.DocumentContainer.StyleLibrary = StyleLibrary;
ToolContext.DocumentContainer.GroupLibrary = GroupLibrary;
if (ToolContext is IEditorToolContext editorToolContext)
{
editorToolContext.ContainerFactory = ContainerFactory;
editorToolContext.UseSkia();
editorToolContext.NewContainerView("View");
editorToolContext.CurrentDirectory = Directory.GetCurrentDirectory();
editorToolContext.AddFiles(editorToolContext.CurrentDirectory);
}
}
}
public static void SetWindowSettings(Window window)
{
if (!double.IsNaN(WindowSettings.Width))
{
window.Width = WindowSettings.Width;
}
if (!double.IsNaN(WindowSettings.Height))
{
window.Height = WindowSettings.Height;
}
if (!double.IsNaN(WindowSettings.X) && !double.IsNaN(WindowSettings.Y))
{
window.Position = new PixelPoint((int)WindowSettings.X, (int)WindowSettings.Y);
window.WindowStartupLocation = WindowStartupLocation.Manual;
}
else
{
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
window.WindowState = WindowSettings.WindowState;
}
public static void GetWindowSettings(Window window)
{
WindowSettings.Width = window.Width;
WindowSettings.Height = window.Height;
WindowSettings.X = window.Position.X;
WindowSettings.Y = window.Position.Y;
WindowSettings.WindowState = window.WindowState;
}
public static void Load()
{
if (File.Exists(EditorPath))
{
ToolContext = JsonSerializer.FromJsonFile<IToolContext>(EditorPath);
}
if (ToolContext == null)
{
ToolContext = ContainerFactory.CreateToolContext();
}
bool isNewDocument;
if (File.Exists(DocumentPath))
{
ToolContext.DocumentContainer = JsonSerializer.FromJsonFile<IDocumentContainer>(DocumentPath);
isNewDocument = false;
}
else
{
ToolContext.DocumentContainer = ContainerFactory.CreateDocumentContainer("document");
ToolContext.DocumentContainer.StyleLibrary = ContainerFactory.CreateStyleLibrary();
ToolContext.DocumentContainer.GroupLibrary = ContainerFactory.CreateGroupLibrary();
isNewDocument = true;
}
StyleLibrary = ContainerFactory.CreateStyleLibrary();
GroupLibrary = ContainerFactory.CreateGroupLibrary();
ToolContext = ContainerFactory.CreateToolContext();
ToolContext.DocumentContainer.StyleLibrary = StyleLibrary;
ToolContext.DocumentContainer.GroupLibrary = GroupLibrary;
if (ToolContext is IEditorToolContext editorToolContext)
{
editorToolContext.ContainerFactory = ContainerFactory;
editorToolContext.UseSkia();
editorToolContext.NewContainerView("View");
if (editorToolContext.CurrentDirectory == null)
{
editorToolContext.CurrentDirectory = Directory.GetCurrentDirectory();
editorToolContext.AddFiles(editorToolContext.CurrentDirectory);
}
if (isNewDocument)
{
editorToolContext.NewContainerView("View");
}
else
{
foreach (var containerView in editorToolContext.DocumentContainer.ContainerViews)
{
editorToolContext.InitContainerView(containerView);
}
}
editorToolContext.CurrentDirectory = Directory.GetCurrentDirectory();
editorToolContext.AddFiles(editorToolContext.CurrentDirectory);
}
if (File.Exists(WindowPath))
{
WindowSettings = JsonSerializer.FromJsonFile<WindowSettings>(WindowPath);
}
if (WindowSettings == null)
{
WindowSettings = new WindowSettings()
{
Width = 1320,
Height = 690,
X = double.NaN,
Y = double.NaN,
WindowState = WindowState.Normal
};
}
}
public static void Save()
{
JsonSerializer.ToJsonFile(DocumentPath, ToolContext.DocumentContainer);
JsonSerializer.ToJsonFile(EditorPath, ToolContext);
JsonSerializer.ToJsonFile(WindowPath, WindowSettings);
WindowSettings = null;
ToolContext.Dispose();
ToolContext = null;
StyleLibrary = null;
GroupLibrary = null;
ContainerFactory = null;
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
{
App.Load();
var window = new MainWindow
{
DataContext = App.ToolContext
};
App.SetWindowSettings(window);
window.Closing += (sender, e) =>
{
App.GetWindowSettings(window);
};
desktopLifetime.MainWindow = window;
desktopLifetime.Exit += (sennder, e) =>
{
App.Save();
};
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
{
App.Load();
var view = new MainView
{
DataContext = App.ToolContext
};
view.Initialized += (sennder, e) =>
{
};
singleViewLifetime.MainView = view;
}
base.OnFrameworkInitializationCompleted();
}
}
public static void SetWindowSettings(Window window)
{
if (!double.IsNaN(WindowSettings.Width))
{
window.Width = WindowSettings.Width;
}
if (!double.IsNaN(WindowSettings.Height))
{
window.Height = WindowSettings.Height;
}
if (!double.IsNaN(WindowSettings.X) && !double.IsNaN(WindowSettings.Y))
{
window.Position = new PixelPoint((int)WindowSettings.X, (int)WindowSettings.Y);
window.WindowStartupLocation = WindowStartupLocation.Manual;
}
else
{
window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
}
window.WindowState = WindowSettings.WindowState;
}
public static void GetWindowSettings(Window window)
{
WindowSettings.Width = window.Width;
WindowSettings.Height = window.Height;
WindowSettings.X = window.Position.X;
WindowSettings.Y = window.Position.Y;
WindowSettings.WindowState = window.WindowState;
}
public static void Load()
{
if (File.Exists(EditorPath))
{
ToolContext = JsonSerializer.FromJsonFile<IToolContext>(EditorPath);
}
if (ToolContext == null)
{
ToolContext = ContainerFactory.CreateToolContext();
}
bool isNewDocument;
if (File.Exists(DocumentPath))
{
ToolContext.DocumentContainer = JsonSerializer.FromJsonFile<IDocumentContainer>(DocumentPath);
isNewDocument = false;
}
else
{
ToolContext.DocumentContainer = ContainerFactory.CreateDocumentContainer("document");
ToolContext.DocumentContainer.StyleLibrary = ContainerFactory.CreateStyleLibrary();
ToolContext.DocumentContainer.GroupLibrary = ContainerFactory.CreateGroupLibrary();
isNewDocument = true;
}
if (ToolContext is IEditorToolContext editorToolContext)
{
editorToolContext.ContainerFactory = ContainerFactory;
editorToolContext.UseSkia();
if (editorToolContext.CurrentDirectory == null)
{
editorToolContext.CurrentDirectory = Directory.GetCurrentDirectory();
editorToolContext.AddFiles(editorToolContext.CurrentDirectory);
}
if (isNewDocument)
{
editorToolContext.NewContainerView("View");
}
else
{
foreach (var containerView in editorToolContext.DocumentContainer.ContainerViews)
{
editorToolContext.InitContainerView(containerView);
}
}
}
if (File.Exists(WindowPath))
{
WindowSettings = JsonSerializer.FromJsonFile<WindowSettings>(WindowPath);
}
if (WindowSettings == null)
{
WindowSettings = new WindowSettings()
{
Width = 1320,
Height = 690,
X = double.NaN,
Y = double.NaN,
WindowState = WindowState.Normal
};
}
}
public static void Save()
{
JsonSerializer.ToJsonFile(DocumentPath, ToolContext.DocumentContainer);
JsonSerializer.ToJsonFile(EditorPath, ToolContext);
JsonSerializer.ToJsonFile(WindowPath, WindowSettings);
WindowSettings = null;
ToolContext.Dispose();
ToolContext = null;
StyleLibrary = null;
GroupLibrary = null;
ContainerFactory = null;
}
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
{
App.Load();
var window = new MainWindow
{
DataContext = App.ToolContext
};
App.SetWindowSettings(window);
window.Closing += (sender, e) =>
{
App.GetWindowSettings(window);
};
desktopLifetime.MainWindow = window;
desktopLifetime.Exit += (sennder, e) =>
{
App.Save();
};
}
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
{
App.Load();
var view = new MainView
{
DataContext = App.ToolContext
};
view.Initialized += (sennder, e) =>
{
};
singleViewLifetime.MainView = view;
}
base.OnFrameworkInitializationCompleted();
}
}

Просмотреть файл

@ -5,17 +5,16 @@ using Avalonia;
using Avalonia.Data.Converters;
using Draw2D.ViewModels.Containers;
namespace Draw2D.Converters
namespace Draw2D.Converters;
public class GroupIdToGroupConverter : IMultiValueConverter
{
public class GroupIdToGroupConverter : IMultiValueConverter
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
if (values?.Count == 2 && values[0] is string groupId && values[1] is IGroupLibrary groupLibrary)
{
if (values?.Count == 2 && values[0] is string groupId && values[1] is IGroupLibrary groupLibrary)
{
return groupLibrary.Get(groupId);
}
return AvaloniaProperty.UnsetValue;
return groupLibrary.Get(groupId);
}
return AvaloniaProperty.UnsetValue;
}
}
}

Просмотреть файл

@ -2,22 +2,21 @@
using System.Globalization;
using Avalonia.Data.Converters;
namespace Draw2D.Converters
{
public class IsEqualStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string str1 && parameter is string str2)
{
return str1 == str2;
}
return false;
}
namespace Draw2D.Converters;
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
public class IsEqualStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is string str1 && parameter is string str2)
{
throw new NotImplementedException();
return str1 == str2;
}
return false;
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}

Просмотреть файл

@ -5,17 +5,16 @@ using Avalonia;
using Avalonia.Data.Converters;
using Draw2D.ViewModels.Containers;
namespace Draw2D.Converters
namespace Draw2D.Converters;
public class StyleIdToStyleConverter : IMultiValueConverter
{
public class StyleIdToStyleConverter : IMultiValueConverter
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
{
public object Convert(IList<object> values, Type targetType, object parameter, CultureInfo culture)
if (values?.Count == 2 && values[0] is string styleId && values[1] is IStyleLibrary styleLibrary)
{
if (values?.Count == 2 && values[0] is string styleId && values[1] is IStyleLibrary styleLibrary)
{
return styleLibrary.Get(styleId);
}
return AvaloniaProperty.UnsetValue;
return styleLibrary.Get(styleId);
}
return AvaloniaProperty.UnsetValue;
}
}
}

Просмотреть файл

@ -2,6 +2,7 @@
using System.Collections.Generic;
using Avalonia;
using Avalonia.OpenGL;
using Avalonia.Win32;
namespace Draw2D;
@ -37,8 +38,7 @@ internal class Program
{
return new Win32PlatformOptions
{
AllowEglInitialization = true,
UseDeferredRendering = true
AllowEglInitialization = true
};
}
@ -48,8 +48,7 @@ internal class Program
{
EnableMultiTouch = true,
UseGpu = true,
UseEGL = true,
UseDeferredRendering = true
UseEGL = true
};
}
@ -58,7 +57,6 @@ internal class Program
return new AvaloniaNativePlatformOptions
{
UseGpu = true,
UseDeferredRendering = true
};
}

Просмотреть файл

@ -2,56 +2,55 @@
using Draw2D.ViewModels;
using SkiaSharp;
namespace Draw2D.Bounds
namespace Draw2D.Bounds;
public readonly struct ChildNode : IDisposable
{
public readonly struct ChildNode : IDisposable
public readonly IBaseShape Shape;
public readonly string StyleId;
public readonly double dX;
public readonly double dY;
public readonly double Scale;
public readonly SKPath Geometry;
public readonly SKRect Bounds;
public ChildNode(IBaseShape shape, string styleId, double dx, double dy, double scale, SKPath geometry)
{
public readonly IBaseShape Shape;
public readonly string StyleId;
public readonly double dX;
public readonly double dY;
public readonly double Scale;
public readonly SKPath Geometry;
public readonly SKRect Bounds;
public ChildNode(IBaseShape shape, string styleId, double dx, double dy, double scale, SKPath geometry)
{
this.Shape = shape;
this.StyleId = styleId;
this.dX = dx;
this.dY = dy;
this.Scale = scale;
this.Geometry = geometry;
geometry.GetBounds(out this.Bounds);
}
public bool Contains(float x, float y, ContainsMode mode)
{
if (mode == ContainsMode.Geometry)
{
return Geometry.Contains(x, y);
}
else if (mode == ContainsMode.Bounds)
{
return Bounds.Contains(x, y);
}
return false;
}
public bool Intersects(SKPath geometry)
{
using var result = this.Geometry.Op(geometry, SKPathOp.Intersect);
return result?.IsEmpty == false;
}
public bool Intersects(ref SKRect rect)
{
return this.Bounds.IntersectsWith(rect);
}
public void Dispose()
{
Geometry?.Dispose();
}
this.Shape = shape;
this.StyleId = styleId;
this.dX = dx;
this.dY = dy;
this.Scale = scale;
this.Geometry = geometry;
geometry.GetBounds(out this.Bounds);
}
}
public bool Contains(float x, float y, ContainsMode mode)
{
if (mode == ContainsMode.Geometry)
{
return Geometry.Contains(x, y);
}
else if (mode == ContainsMode.Bounds)
{
return Bounds.Contains(x, y);
}
return false;
}
public bool Intersects(SKPath geometry)
{
using var result = this.Geometry.Op(geometry, SKPathOp.Intersect);
return result?.IsEmpty == false;
}
public bool Intersects(ref SKRect rect)
{
return this.Bounds.IntersectsWith(rect);
}
public void Dispose()
{
Geometry?.Dispose();
}
}

Просмотреть файл

@ -1,9 +1,8 @@

namespace Draw2D.Bounds
namespace Draw2D.Bounds;
public enum ContainsMode
{
public enum ContainsMode
{
Geometry,
Bounds
}
}
Geometry,
Bounds
}

Просмотреть файл

@ -3,89 +3,88 @@ using System.Collections.Generic;
using Draw2D.ViewModels;
using SkiaSharp;
namespace Draw2D.Bounds
namespace Draw2D.Bounds;
public readonly struct RootNode : IDisposable
{
public readonly struct RootNode : IDisposable
public readonly IBaseShape Shape;
public readonly IList<ChildNode> Children;
public RootNode(IBaseShape shape)
{
public readonly IBaseShape Shape;
public readonly IList<ChildNode> Children;
this.Shape = shape;
this.Children = new List<ChildNode>();
}
public RootNode(IBaseShape shape)
public bool Contains(float x, float y, ContainsMode mode, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
{
this.Shape = shape;
this.Children = new List<ChildNode>();
}
public bool Contains(float x, float y, ContainsMode mode, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
if (mode == ContainsMode.Geometry)
{
if (mode == ContainsMode.Geometry)
{
if (Children[i].Geometry.Contains(x, y))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
else if (mode == ContainsMode.Bounds)
{
if (Children[i].Bounds.Contains(x, y))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
else
{
return false;
}
}
return false;
}
public bool Intersects(SKPath geometry, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
{
if (Children[i].Intersects(geometry))
if (Children[i].Geometry.Contains(x, y))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
return false;
}
public bool Intersects(ref SKRect rect, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
else if (mode == ContainsMode.Bounds)
{
if (Children[i].Bounds.IntersectsWith(rect))
if (Children[i].Bounds.Contains(x, y))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
return false;
}
public void Dispose()
{
for (int i = 0; i < Children?.Count; i++)
else
{
Children[i].Dispose();
return false;
}
}
return false;
}
public bool Intersects(SKPath geometry, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
{
if (Children[i].Intersects(geometry))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
return false;
}
public bool Intersects(ref SKRect rect, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < Children.Count; i++)
{
if (Children[i].Bounds.IntersectsWith(rect))
{
rootShape = this.Shape;
childShape = Children[i].Shape;
return true;
}
}
return false;
}
public void Dispose()
{
for (int i = 0; i < Children?.Count; i++)
{
Children[i].Dispose();
}
}
}
}

Просмотреть файл

@ -3,100 +3,99 @@ using Draw2D.ViewModels;
using Draw2D.ViewModels.Shapes;
using SkiaSharp;
namespace Draw2D.Bounds
namespace Draw2D.Bounds;
internal class SkiaBoundsShapeRenderer : IShapeRenderer
{
internal class SkiaBoundsShapeRenderer : IShapeRenderer
internal int _currentRootNode = -1;
internal IList<RootNode> _rootNodes;
public void DrawLine(object dc, LineShape line, string styleId, double dx, double dy, double scale)
{
internal int _currentRootNode = -1;
internal IList<RootNode> _rootNodes;
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddLine(null, line, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(line, styleId, dx, dy, scale, geometry));
}
public void DrawLine(object dc, LineShape line, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddLine(null, line, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(line, styleId, dx, dy, scale, geometry));
}
public void DrawCubicBezier(object dc, CubicBezierShape cubicBezier, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddCubic(null, cubicBezier, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(cubicBezier, styleId, dx, dy, scale, geometry));
}
public void DrawCubicBezier(object dc, CubicBezierShape cubicBezier, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddCubic(null, cubicBezier, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(cubicBezier, styleId, dx, dy, scale, geometry));
}
public void DrawQuadraticBezier(object dc, QuadraticBezierShape quadraticBezier, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddQuad(null, quadraticBezier, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(quadraticBezier, styleId, dx, dy, scale, geometry));
}
public void DrawQuadraticBezier(object dc, QuadraticBezierShape quadraticBezier, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddQuad(null, quadraticBezier, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(quadraticBezier, styleId, dx, dy, scale, geometry));
}
public void DrawConic(object dc, ConicShape conic, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddConic(null, conic, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(conic, styleId, dx, dy, scale, geometry));
}
public void DrawConic(object dc, ConicShape conic, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddConic(null, conic, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(conic, styleId, dx, dy, scale, geometry));
}
public void DrawPath(object dc, PathShape path, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SkiaUtil.ToSKPathFillType(path.FillType) };
SkiaUtil.AddPath(null, path, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(path, styleId, dx, dy, scale, geometry));
}
public void DrawPath(object dc, PathShape path, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SkiaUtil.ToSKPathFillType(path.FillType) };
SkiaUtil.AddPath(null, path, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(path, styleId, dx, dy, scale, geometry));
}
public void DrawRectangle(object dc, RectangleShape rectangle, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddRect(null, rectangle, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(rectangle, styleId, dx, dy, scale, geometry));
}
public void DrawRectangle(object dc, RectangleShape rectangle, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddRect(null, rectangle, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(rectangle, styleId, dx, dy, scale, geometry));
}
public void DrawCircle(object dc, CircleShape circle, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddCircle(null, circle, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(circle, styleId, dx, dy, scale, geometry));
}
public void DrawCircle(object dc, CircleShape circle, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddCircle(null, circle, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(circle, styleId, dx, dy, scale, geometry));
}
public void DrawArc(object dc, ArcShape arc, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddArc(null, arc, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(arc, styleId, dx, dy, scale, geometry));
}
public void DrawArc(object dc, ArcShape arc, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddArc(null, arc, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(arc, styleId, dx, dy, scale, geometry));
}
public void DrawOval(object dc, OvalShape oval, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddOval(null, oval, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(oval, styleId, dx, dy, scale, geometry));
}
public void DrawOval(object dc, OvalShape oval, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddOval(null, oval, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(oval, styleId, dx, dy, scale, geometry));
}
public void DrawText(object dc, TextShape text, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddText(null, text, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(text, styleId, dx, dy, scale, geometry));
}
public void DrawText(object dc, TextShape text, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddText(null, text, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(text, styleId, dx, dy, scale, geometry));
}
public void DrawImage(object dc, ImageShape image, string styleId, double dx, double dy, double scale)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddImage(null, image, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(image, styleId, dx, dy, scale, geometry));
}
public void DrawImage(object dc, ImageShape image, string styleId, double dx, double dy, double scale)
public void Dispose()
{
if (_rootNodes != null)
{
var geometry = new SKPath() { FillType = SKPathFillType.Winding };
SkiaUtil.AddImage(null, image, dx, dy, geometry);
_rootNodes[_currentRootNode].Children.Add(new ChildNode(image, styleId, dx, dy, scale, geometry));
}
public void Dispose()
{
if (_rootNodes != null)
for (int i = 0; i < _rootNodes.Count; i++)
{
for (int i = 0; i < _rootNodes.Count; i++)
{
_rootNodes[i].Dispose();
}
_rootNodes = null;
_rootNodes[i].Dispose();
}
_rootNodes = null;
}
}
}
}

Просмотреть файл

@ -4,117 +4,115 @@ using Draw2D.ViewModels;
using Draw2D.ViewModels.Containers;
using SkiaSharp;
namespace Draw2D.Bounds
namespace Draw2D.Bounds;
// TODO: Experimental hit-testing for TryToHover
/*
var bounds = new SkiaHitTest(context.DocumentContainer?.ContainerView?.CurrentContainer);
//if (bounds.Contains((float)target.X, (float)target.Y, ContainsMode.Bounds, out var rootShape, out var childShape))
//{
// bounds.Dispose();
// return rootShape;
//}
var rect = SKRect.Create((float)(target.X - radius), (float)(target.Y - radius), (float)(radius + radius), (float)(radius + radius));
if (bounds.Intersects(ref rect, out var rootShape, out var childShape))
{
// TODO: Experimental hit-testing for TryToHover
/*
var bounds = new SkiaHitTest(context.DocumentContainer?.ContainerView?.CurrentContainer);
//if (bounds.Contains((float)target.X, (float)target.Y, ContainsMode.Bounds, out var rootShape, out var childShape))
//{
// bounds.Dispose();
// return rootShape;
//}
var rect = SKRect.Create((float)(target.X - radius), (float)(target.Y - radius), (float)(radius + radius), (float)(radius + radius));
if (bounds.Intersects(ref rect, out var rootShape, out var childShape))
{
bounds.Dispose();
return rootShape;
}
//var rect = SKRect.Create((float)(target.X - radius), (float)(target.Y - radius), (float)(radius + radius), (float)(radius + radius));
//var geometry = new SKPath() { FillType = SKPathFillType.Winding };
//geometry.AddRect(rect);
//if (bounds.Intersects(geometry, out var rootShape, out var childShape))
//{
// bounds.Dispose();
// return rootShape;
//}
bounds.Dispose();
return rootShape;
}
return null;
//*/
//var rect = SKRect.Create((float)(target.X - radius), (float)(target.Y - radius), (float)(radius + radius), (float)(radius + radius));
//var geometry = new SKPath() { FillType = SKPathFillType.Winding };
//geometry.AddRect(rect);
//if (bounds.Intersects(geometry, out var rootShape, out var childShape))
//{
// bounds.Dispose();
// return rootShape;
//}
public class SkiaHitTest : IDisposable
bounds.Dispose();
return null;
//*/
public class SkiaHitTest : IDisposable
{
internal SkiaBoundsShapeRenderer _renderer;
public SkiaHitTest(ICanvasContainer container)
{
internal SkiaBoundsShapeRenderer _renderer;
_renderer = new SkiaBoundsShapeRenderer();
_renderer._currentRootNode = -1;
_renderer._rootNodes = new List<RootNode>();
public SkiaHitTest(ICanvasContainer container)
var points = new List<IPointShape>();
container.GetPoints(points);
foreach (var point in points)
{
_renderer = new SkiaBoundsShapeRenderer();
_renderer._currentRootNode = -1;
_renderer._rootNodes = new List<RootNode>();
var points = new List<IPointShape>();
container.GetPoints(points);
foreach (var point in points)
{
_renderer._rootNodes.Add(new RootNode(point));
_renderer._currentRootNode++;
point.Draw(null, _renderer, 0.0, 0.0, 1.0, null, null);
}
foreach (var shape in container.Shapes)
{
_renderer._rootNodes.Add(new RootNode(shape));
_renderer._currentRootNode++;
shape.Draw(null, _renderer, 0.0, 0.0, 1.0, null, null);
}
_renderer._rootNodes.Add(new RootNode(point));
_renderer._currentRootNode++;
point.Draw(null, _renderer, 0.0, 0.0, 1.0, null, null);
}
public bool Contains(float x, float y, ContainsMode mode, out IBaseShape rootShape, out IBaseShape childShape)
foreach (var shape in container.Shapes)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Contains(x, y, mode, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public bool Intersects(SKPath geometry, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Intersects(geometry, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public bool Intersects(ref SKRect rect, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Intersects(ref rect, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public void Dispose()
{
if (_renderer != null)
{
_renderer.Dispose();
_renderer = null;
}
_renderer._rootNodes.Add(new RootNode(shape));
_renderer._currentRootNode++;
shape.Draw(null, _renderer, 0.0, 0.0, 1.0, null, null);
}
}
}
public bool Contains(float x, float y, ContainsMode mode, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Contains(x, y, mode, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public bool Intersects(SKPath geometry, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Intersects(geometry, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public bool Intersects(ref SKRect rect, out IBaseShape rootShape, out IBaseShape childShape)
{
rootShape = null;
childShape = null;
for (int i = 0; i < _renderer._rootNodes.Count; i++)
{
if (_renderer._rootNodes[i].Intersects(ref rect, out rootShape, out childShape))
{
return true;
}
}
return false;
}
public void Dispose()
{
if (_renderer != null)
{
_renderer.Dispose();
_renderer = null;
}
}
}

Просмотреть файл

@ -5,155 +5,154 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Export
namespace Draw2D.Export;
public class SkiaContainerExporter : IContainerExporter
{
public class SkiaContainerExporter : IContainerExporter
internal static void ExportSvg(IToolContext context, string path, IContainerView containerView)
{
internal static void ExportSvg(IToolContext context, string path, IContainerView containerView)
using var wstream = new SKFileWStream(path);
using var canvas = SKSvgCanvas.Create(SKRect.Create(0, 0, (int)containerView.Width, (int)containerView.Height), wstream);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
internal static void ExportPdf(IToolContext context, string path, IContainerView containerView)
{
using var stream = new SKFileWStream(path);
using var pdf = SKDocument.CreatePdf(stream, SKDocument.DefaultRasterDpi);
using var canvas = pdf.BeginPage((float)containerView.Width, (float)containerView.Height);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
pdf.Close();
}
internal static void ExportXps(IToolContext context, string path, IContainerView containerView)
{
using var stream = new SKFileWStream(path);
using var xps = SKDocument.CreateXps(stream, SKDocument.DefaultRasterDpi);
using var canvas = xps.BeginPage((float)containerView.Width, (float)containerView.Height);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
xps.Close();
}
internal static void ExportSkp(IToolContext context, string path, IContainerView containerView)
{
var recorder = new SKPictureRecorder();
var rect = new SKRect(0f, 0f, (float)containerView.Width, (float)containerView.Height);
var canvas = recorder.BeginRecording(rect);
using (var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView))
{
using var wstream = new SKFileWStream(path);
using var canvas = SKSvgCanvas.Create(SKRect.Create(0, 0, (int)containerView.Width, (int)containerView.Height), wstream);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
internal static void ExportPdf(IToolContext context, string path, IContainerView containerView)
var picture = recorder.EndRecording();
var dimensions = new SKSizeI((int)containerView.Width, (int)containerView.Height);
using (var image = SKImage.FromPicture(picture, dimensions))
{
using var stream = new SKFileWStream(path);
using var pdf = SKDocument.CreatePdf(stream, SKDocument.DefaultRasterDpi);
using var canvas = pdf.BeginPage((float)containerView.Width, (float)containerView.Height);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
pdf.Close();
}
internal static void ExportXps(IToolContext context, string path, IContainerView containerView)
{
using var stream = new SKFileWStream(path);
using var xps = SKDocument.CreateXps(stream, SKDocument.DefaultRasterDpi);
using var canvas = xps.BeginPage((float)containerView.Width, (float)containerView.Height);
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
xps.Close();
}
internal static void ExportSkp(IToolContext context, string path, IContainerView containerView)
{
var recorder = new SKPictureRecorder();
var rect = new SKRect(0f, 0f, (float)containerView.Width, (float)containerView.Height);
var canvas = recorder.BeginRecording(rect);
using (var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView))
{
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
var picture = recorder.EndRecording();
var dimensions = new SKSizeI((int)containerView.Width, (int)containerView.Height);
using (var image = SKImage.FromPicture(picture, dimensions))
{
var data = image.EncodedData;
if (data != null)
{
using var stream = File.OpenWrite(path);
data.SaveTo(stream);
}
}
picture.Dispose();
}
internal static void ExportImage(IToolContext context, string path, IContainerView containerView, SKEncodedImageFormat format, int quality)
{
var info = new SKImageInfo((int)containerView.Width, (int)containerView.Height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);
using var bitmap = new SKBitmap(info);
using (var canvas = new SKCanvas(bitmap))
using (var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView))
{
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
using var image = SKImage.FromBitmap(bitmap);
using var data = image.Encode(format, quality);
var data = image.EncodedData;
if (data != null)
{
using var stream = File.OpenWrite(path);
data.SaveTo(stream);
}
}
picture.Dispose();
}
public void Export(IToolContext context, string path, IContainerView containerView)
internal static void ExportImage(IToolContext context, string path, IContainerView containerView, SKEncodedImageFormat format, int quality)
{
var info = new SKImageInfo((int)containerView.Width, (int)containerView.Height, SKImageInfo.PlatformColorType, SKAlphaType.Unpremul);
using var bitmap = new SKBitmap(info);
using (var canvas = new SKCanvas(bitmap))
using (var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView))
{
try
{
var outputExtension = Path.GetExtension(path);
if (string.Compare(outputExtension, ".svg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportSvg(context, path, containerView);
}
else if (string.Compare(outputExtension, ".pdf", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportPdf(context, path, containerView);
}
else if (string.Compare(outputExtension, ".xps", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportXps(context, path, containerView);
}
else if (string.Compare(outputExtension, ".skp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportSkp(context, path, containerView);
}
else if (string.Compare(outputExtension, ".bmp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Bmp, 100);
}
else if (string.Compare(outputExtension, ".gif", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Gif, 100);
}
else if (string.Compare(outputExtension, ".ico", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Ico, 100);
}
else if (string.Compare(outputExtension, ".jpeg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Jpeg, 100);
}
else if (string.Compare(outputExtension, ".jpg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Jpeg, 100);
}
else if (string.Compare(outputExtension, ".png", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Png, 100);
}
else if (string.Compare(outputExtension, ".wbmp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Wbmp, 100);
}
else if (string.Compare(outputExtension, ".webp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Webp, 100);
}
else if (string.Compare(outputExtension, ".pkm", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Pkm, 100);
}
else if (string.Compare(outputExtension, ".ktx", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Ktx, 100);
}
else if (string.Compare(outputExtension, ".astc", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Astc, 100);
}
else if (string.Compare(outputExtension, ".dng", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Dng, 100);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
using var image = SKImage.FromBitmap(bitmap);
using var data = image.Encode(format, quality);
if (data != null)
{
using var stream = File.OpenWrite(path);
data.SaveTo(stream);
}
}
}
public void Export(IToolContext context, string path, IContainerView containerView)
{
try
{
var outputExtension = Path.GetExtension(path);
if (string.Compare(outputExtension, ".svg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportSvg(context, path, containerView);
}
else if (string.Compare(outputExtension, ".pdf", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportPdf(context, path, containerView);
}
else if (string.Compare(outputExtension, ".xps", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportXps(context, path, containerView);
}
else if (string.Compare(outputExtension, ".skp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportSkp(context, path, containerView);
}
else if (string.Compare(outputExtension, ".bmp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Bmp, 100);
}
else if (string.Compare(outputExtension, ".gif", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Gif, 100);
}
else if (string.Compare(outputExtension, ".ico", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Ico, 100);
}
else if (string.Compare(outputExtension, ".jpeg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Jpeg, 100);
}
else if (string.Compare(outputExtension, ".jpg", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Jpeg, 100);
}
else if (string.Compare(outputExtension, ".png", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Png, 100);
}
else if (string.Compare(outputExtension, ".wbmp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Wbmp, 100);
}
else if (string.Compare(outputExtension, ".webp", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Webp, 100);
}
else if (string.Compare(outputExtension, ".pkm", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Pkm, 100);
}
else if (string.Compare(outputExtension, ".ktx", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Ktx, 100);
}
else if (string.Compare(outputExtension, ".astc", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Astc, 100);
}
else if (string.Compare(outputExtension, ".dng", StringComparison.OrdinalIgnoreCase) == 0)
{
ExportImage(context, path, containerView, SKEncodedImageFormat.Dng, 100);
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
}

Просмотреть файл

@ -5,42 +5,41 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
namespace Draw2D.Export
namespace Draw2D.Export;
public class SkiaContainerImporter : IContainerImporter
{
public class SkiaContainerImporter : IContainerImporter
public void Import(IToolContext context, string path, IContainerView containerView)
{
public void Import(IToolContext context, string path, IContainerView containerView)
try
{
try
var picture = SkiaUtil.ToSKPicture(path);
if (picture != null)
{
var picture = SkiaUtil.ToSKPicture(path);
if (picture != null)
var image = new ImageShape()
{
var image = new ImageShape()
{
Points = new ObservableCollection<IPointShape>(),
StartPoint = new PointShape(0.0, 0.0, context?.DocumentContainer?.PointTemplate),
Point = new PointShape(picture.CullRect.Width, picture.CullRect.Height, context?.DocumentContainer?.PointTemplate),
Path = path,
StretchMode = StretchMode.Center,
Text = new Text(),
StyleId = context.DocumentContainer?.StyleLibrary?.CurrentItem?.Title,
};
Points = new ObservableCollection<IPointShape>(),
StartPoint = new PointShape(0.0, 0.0, context?.DocumentContainer?.PointTemplate),
Point = new PointShape(picture.CullRect.Width, picture.CullRect.Height, context?.DocumentContainer?.PointTemplate),
Path = path,
StretchMode = StretchMode.Center,
Text = new Text(),
StyleId = context.DocumentContainer?.StyleLibrary?.CurrentItem?.Title,
};
image.StartPoint.Owner = image;
image.Point.Owner = image;
image.StartPoint.Owner = image;
image.Point.Owner = image;
picture.Dispose();
picture.Dispose();
context.DocumentContainer?.ContainerView?.CurrentContainer.Shapes.Add(image);
context.DocumentContainer?.ContainerView?.InputService?.Redraw?.Invoke();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
context.DocumentContainer?.ContainerView?.CurrentContainer.Shapes.Add(image);
context.DocumentContainer?.ContainerView?.InputService?.Redraw?.Invoke();
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
System.Diagnostics.Debug.WriteLine(ex.StackTrace);
}
}
}
}

Просмотреть файл

@ -6,223 +6,222 @@ using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Export
namespace Draw2D.Export;
public class SkiaPathConverter : IPathConverter
{
public class SkiaPathConverter : IPathConverter
private bool IsAcceptedShape(IBaseShape shape)
{
private bool IsAcceptedShape(IBaseShape shape)
return !(shape is IPointShape || shape is FigureShape);
}
private IList<IBaseShape> GetShapes(ICollection<IBaseShape> selected)
{
if (selected == null || selected.Count <= 0)
{
return !(shape is IPointShape || shape is FigureShape);
return null;
}
private IList<IBaseShape> GetShapes(ICollection<IBaseShape> selected)
var shapes = new List<IBaseShape>();
foreach (var shape in selected)
{
if (selected == null || selected.Count <= 0)
if (IsAcceptedShape(shape))
{
return null;
shapes.Add(shape);
}
var shapes = new List<IBaseShape>();
foreach (var shape in selected)
{
if (IsAcceptedShape(shape))
{
shapes.Add(shape);
}
}
return shapes;
}
private IList<SKPath> ToPaths(IToolContext context, IList<IBaseShape> shapes)
return shapes;
}
private IList<SKPath> ToPaths(IToolContext context, IList<IBaseShape> shapes)
{
if (shapes == null || shapes.Count <= 0)
{
if (shapes == null || shapes.Count <= 0)
{
return null;
}
var paths = new List<SKPath>();
for (int i = 0; i < shapes.Count; i++)
{
var fillType = SKPathFillType.Winding;
if (shapes[i] is PathShape pathShape)
{
fillType = SkiaUtil.ToSKPathFillType(pathShape.FillType);
}
var path = new SKPath() { FillType = fillType };
var result = SkiaUtil.AddShape(context, shapes[i], 0.0, 0.0, path);
if (result == true && path.IsEmpty == false)
{
paths.Add(path);
}
else
{
path.Dispose();
}
}
return paths;
return null;
}
private SKPath ToPath(IToolContext context, IBaseShape shape)
var paths = new List<SKPath>();
for (int i = 0; i < shapes.Count; i++)
{
var fillType = SKPathFillType.Winding;
if (shape is PathShape pathShape)
if (shapes[i] is PathShape pathShape)
{
fillType = SkiaUtil.ToSKPathFillType(pathShape.FillType);
}
var geometry = new SKPath() { FillType = fillType };
if (SkiaUtil.AddShape(context, shape, 0.0, 0.0, geometry) == true)
var path = new SKPath() { FillType = fillType };
var result = SkiaUtil.AddShape(context, shapes[i], 0.0, 0.0, path);
if (result == true && path.IsEmpty == false)
{
return geometry;
paths.Add(path);
}
else
{
geometry.Dispose();
path.Dispose();
}
return null;
}
public PathShape ToPathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
return SkiaUtil.ToPathShape(context, geometry, style, context?.DocumentContainer?.PointTemplate);
}
}
return null;
}
public PathShape ToStrokePathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
using var disposable = new CompositeDisposable();
var path = SkiaUtil.ToStrokePath(context, style.StrokePaint, shape.Effects, geometry, disposable.Disposables);
if (path != null)
{
disposable.Disposables.Add(path);
var union = SkiaUtil.Op(SKPathOp.Union, new[] { path, path });
if (union != null && !union.IsEmpty)
{
disposable.Disposables.Add(union);
return SkiaUtil.ToPathShape(context, union, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
}
}
}
return null;
}
public PathShape ToFillPathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
using var disposable = new CompositeDisposable();
var path = SkiaUtil.ToFillPath(context, style.FillPaint, shape.Effects, geometry, disposable.Disposables);
if (path != null)
{
disposable.Disposables.Add(path);
var union = SkiaUtil.Op(SKPathOp.Union, new[] { path, path });
if (union != null && !union.IsEmpty)
{
disposable.Disposables.Add(union);
return SkiaUtil.ToPathShape(context, union, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
}
}
}
return null;
}
public PathShape Op(IToolContext context, PathOp op, ICollection<IBaseShape> selected)
{
var path = default(PathShape);
var shapes = GetShapes(selected);
if (shapes != null && shapes.Count > 0)
{
var paths = ToPaths(context, shapes);
if (paths != null && paths.Count > 0)
{
var result = SkiaUtil.Op(SkiaUtil.ToSKPathOp(op), paths);
if (result != null)
{
if (!result.IsEmpty)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shapes[0].StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
path = SkiaUtil.ToPathShape(context, result, style, context?.DocumentContainer?.PointTemplate);
}
result.Dispose();
}
for (int i = 0; i < paths.Count; i++)
{
paths[i].Dispose();
}
}
}
return path;
}
public PathShape ToPathShape(IToolContext context, string svgPathData)
{
if (!string.IsNullOrWhiteSpace(svgPathData))
{
using var path = SkiaUtil.ToPath(svgPathData);
return SkiaUtil.ToPathShape(context, path, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
return null;
}
public string ToSvgPathData(IToolContext context, ICollection<IBaseShape> selected)
{
var sb = new StringBuilder();
var shapes = GetShapes(selected);
if (shapes != null && shapes.Count > 0)
{
foreach (var shape in shapes)
{
SkiaUtil.ToSvgPathData(context, shape, sb);
}
}
return sb.ToString();
}
public void Dispose()
{
}
return paths;
}
}
private SKPath ToPath(IToolContext context, IBaseShape shape)
{
var fillType = SKPathFillType.Winding;
if (shape is PathShape pathShape)
{
fillType = SkiaUtil.ToSKPathFillType(pathShape.FillType);
}
var geometry = new SKPath() { FillType = fillType };
if (SkiaUtil.AddShape(context, shape, 0.0, 0.0, geometry) == true)
{
return geometry;
}
else
{
geometry.Dispose();
}
return null;
}
public PathShape ToPathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
return SkiaUtil.ToPathShape(context, geometry, style, context?.DocumentContainer?.PointTemplate);
}
}
return null;
}
public PathShape ToStrokePathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
using var disposable = new CompositeDisposable();
var path = SkiaUtil.ToStrokePath(context, style.StrokePaint, shape.Effects, geometry, disposable.Disposables);
if (path != null)
{
disposable.Disposables.Add(path);
var union = SkiaUtil.Op(SKPathOp.Union, new[] { path, path });
if (union != null && !union.IsEmpty)
{
disposable.Disposables.Add(union);
return SkiaUtil.ToPathShape(context, union, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
}
}
}
return null;
}
public PathShape ToFillPathShape(IToolContext context, IBaseShape shape)
{
using (var geometry = ToPath(context, shape))
{
if (geometry != null)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
using var disposable = new CompositeDisposable();
var path = SkiaUtil.ToFillPath(context, style.FillPaint, shape.Effects, geometry, disposable.Disposables);
if (path != null)
{
disposable.Disposables.Add(path);
var union = SkiaUtil.Op(SKPathOp.Union, new[] { path, path });
if (union != null && !union.IsEmpty)
{
disposable.Disposables.Add(union);
return SkiaUtil.ToPathShape(context, union, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
}
}
}
return null;
}
public PathShape Op(IToolContext context, PathOp op, ICollection<IBaseShape> selected)
{
var path = default(PathShape);
var shapes = GetShapes(selected);
if (shapes != null && shapes.Count > 0)
{
var paths = ToPaths(context, shapes);
if (paths != null && paths.Count > 0)
{
var result = SkiaUtil.Op(SkiaUtil.ToSKPathOp(op), paths);
if (result != null)
{
if (!result.IsEmpty)
{
var style = context.DocumentContainer?.StyleLibrary?.Get(shapes[0].StyleId);
if (style == null)
{
style = context.DocumentContainer?.StyleLibrary?.CurrentItem;
}
path = SkiaUtil.ToPathShape(context, result, style, context?.DocumentContainer?.PointTemplate);
}
result.Dispose();
}
for (int i = 0; i < paths.Count; i++)
{
paths[i].Dispose();
}
}
}
return path;
}
public PathShape ToPathShape(IToolContext context, string svgPathData)
{
if (!string.IsNullOrWhiteSpace(svgPathData))
{
using var path = SkiaUtil.ToPath(svgPathData);
return SkiaUtil.ToPathShape(context, path, context.DocumentContainer?.StyleLibrary?.CurrentItem, context?.DocumentContainer?.PointTemplate);
}
return null;
}
public string ToSvgPathData(IToolContext context, ICollection<IBaseShape> selected)
{
var sb = new StringBuilder();
var shapes = GetShapes(selected);
if (shapes != null && shapes.Count > 0)
{
foreach (var shape in shapes)
{
SkiaUtil.ToSvgPathData(context, shape, sb);
}
}
return sb.ToString();
}
public void Dispose()
{
}
}

Просмотреть файл

@ -7,49 +7,48 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Export
namespace Draw2D.Export;
public class SkiaSvgConverter : ISvgConverter
{
public class SkiaSvgConverter : ISvgConverter
internal static string FormatXml(string xml)
{
internal static string FormatXml(string xml)
var sb = new StringBuilder();
var element = XElement.Parse(xml);
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = false;
settings.Indent = true;
settings.NewLineOnAttributes = false;
using (var writer = XmlWriter.Create(sb, settings))
{
var sb = new StringBuilder();
var element = XElement.Parse(xml);
var settings = new XmlWriterSettings();
settings.OmitXmlDeclaration = false;
settings.Indent = true;
settings.NewLineOnAttributes = false;
using (var writer = XmlWriter.Create(sb, settings))
{
element.Save(writer);
}
return sb.ToString();
element.Save(writer);
}
public string ConvertToSvgDocument(IToolContext context, IContainerView containerView)
{
using var stream = new MemoryStream();
using (var wstream = new SKManagedWStream(stream))
using (var canvas = SKSvgCanvas.Create(SKRect.Create(0, 0, (int)containerView.Width, (int)containerView.Height), wstream))
{
if (containerView.SelectionState?.Shapes?.Count > 0)
{
using var skiaSelectedPresenter = new SkiaExportSelectedPresenter(context, containerView);
skiaSelectedPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
else
{
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
}
stream.Position = 0;
using var reader = new StreamReader(stream, Encoding.UTF8);
var xml = reader.ReadToEnd();
return FormatXml(xml);
}
return sb.ToString();
}
}
public string ConvertToSvgDocument(IToolContext context, IContainerView containerView)
{
using var stream = new MemoryStream();
using (var wstream = new SKManagedWStream(stream))
using (var canvas = SKSvgCanvas.Create(SKRect.Create(0, 0, (int)containerView.Width, (int)containerView.Height), wstream))
{
if (containerView.SelectionState?.Shapes?.Count > 0)
{
using var skiaSelectedPresenter = new SkiaExportSelectedPresenter(context, containerView);
skiaSelectedPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
else
{
using var skiaContainerPresenter = new SkiaExportContainerPresenter(context, containerView);
skiaContainerPresenter.Draw(canvas, containerView.Width, containerView.Height, 0, 0, 1.0, 1.0, 1.0);
}
}
stream.Position = 0;
using var reader = new StreamReader(stream, Encoding.UTF8);
var xml = reader.ReadToEnd();
return FormatXml(xml);
}
}

Просмотреть файл

@ -7,319 +7,318 @@ using Draw2D.ViewModels.Style;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Presenters
namespace Draw2D.Presenters;
public class SkiaEditorContainerPresenter : IContainerPresenter
{
public class SkiaEditorContainerPresenter : IContainerPresenter
private readonly IToolContext _context;
private readonly IContainerView _view;
private SkiaShapeRenderer _skiaRenderer;
private Dictionary<IPaint, SKPaint> _paintCache;
private double _previousZX = double.NaN;
private double _previousZY = double.NaN;
private SKPicture _pictureShapesCurrent = null;
private SKPicture _pictureShapesWorking = null;
private SKPicture _pictureDecorators = null;
private SKPicture _picturePoints = null;
private bool _enablePictureCache = true;
private CompositeDisposable _disposable;
public SkiaEditorContainerPresenter(IToolContext context, IContainerView view)
{
private readonly IToolContext _context;
private readonly IContainerView _view;
private SkiaShapeRenderer _skiaRenderer;
private Dictionary<IPaint, SKPaint> _paintCache;
private double _previousZX = double.NaN;
private double _previousZY = double.NaN;
private SKPicture _pictureShapesCurrent = null;
private SKPicture _pictureShapesWorking = null;
private SKPicture _pictureDecorators = null;
private SKPicture _picturePoints = null;
private bool _enablePictureCache = true;
private CompositeDisposable _disposable;
_context = context;
_view = view;
_skiaRenderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
_paintCache = new Dictionary<IPaint, SKPaint>();
_disposable = new CompositeDisposable();
}
public SkiaEditorContainerPresenter(IToolContext context, IContainerView view)
public void Dispose()
{
_previousZX = double.NaN;
_previousZY = double.NaN;
if (_skiaRenderer != null)
{
_context = context;
_view = view;
_skiaRenderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
_paintCache = new Dictionary<IPaint, SKPaint>();
_disposable = new CompositeDisposable();
_skiaRenderer.Dispose();
}
public void Dispose()
if (_paintCache != null)
{
_previousZX = double.NaN;
_previousZY = double.NaN;
if (_skiaRenderer != null)
foreach (var cache in _paintCache)
{
_skiaRenderer.Dispose();
}
if (_paintCache != null)
{
foreach (var cache in _paintCache)
{
cache.Value.Dispose();
}
_paintCache = null;
}
if (_picturePoints != null)
{
_picturePoints.Dispose();
_picturePoints = null;
}
if (_pictureDecorators != null)
{
_pictureDecorators.Dispose();
_pictureDecorators = null;
}
if (_pictureShapesWorking != null)
{
_pictureShapesWorking.Dispose();
_pictureShapesWorking = null;
}
if (_pictureShapesCurrent != null)
{
_pictureShapesCurrent.Dispose();
_pictureShapesCurrent = null;
}
if (_disposable != null)
{
_disposable.Dispose();
_disposable = null;
cache.Value.Dispose();
}
_paintCache = null;
}
private void GetSKPaintFill(IPaint fillPaint, IPaintEffects effects, double scale, out SKPaint brush)
if (_picturePoints != null)
{
if (fillPaint.IsTreeDirty() || !_paintCache.TryGetValue(fillPaint, out var brushCached))
{
fillPaint.Invalidate();
brushCached = SkiaUtil.ToSKPaint(fillPaint, effects, scale, _disposable.Disposables);
_paintCache[fillPaint] = brushCached;
}
else
{
SkiaUtil.ToSKPaintUpdate(brushCached, fillPaint, effects, scale, _disposable.Disposables);
}
brush = brushCached;
_picturePoints.Dispose();
_picturePoints = null;
}
private void DrawShapesCurrent(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
if (_pictureDecorators != null)
{
view.CurrentContainer.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
_pictureDecorators.Dispose();
_pictureDecorators = null;
}
private void DrawShapesWorking(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
if (_pictureShapesWorking != null)
{
view.WorkingContainer.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
_pictureShapesWorking.Dispose();
_pictureShapesWorking = null;
}
private void DrawPoints(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
if (_pictureShapesCurrent != null)
{
var selected = new List<IBaseShape>(view.SelectionState.Shapes);
foreach (var shape in selected)
{
if (shape is IPointShape point)
{
double s = 1.0 / scale;
canvas.Save();
double dx = 0.0 - (point.X * s) + point.X;
double dy = 0.0 - (point.Y * s) + point.Y;
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)s);
point.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
canvas.Restore();
}
}
_pictureShapesCurrent.Dispose();
_pictureShapesCurrent = null;
}
private void DrawDecorators(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
if (_disposable != null)
{
var selected = new List<IBaseShape>(view.SelectionState.Shapes);
_disposable.Dispose();
_disposable = null;
}
}
foreach (var shape in selected)
{
shape.Decorator?.Draw(canvas, shape, renderer, view.SelectionState, 0.0, 0.0, scale);
}
private void GetSKPaintFill(IPaint fillPaint, IPaintEffects effects, double scale, out SKPaint brush)
{
if (fillPaint.IsTreeDirty() || !_paintCache.TryGetValue(fillPaint, out var brushCached))
{
fillPaint.Invalidate();
brushCached = SkiaUtil.ToSKPaint(fillPaint, effects, scale, _disposable.Disposables);
_paintCache[fillPaint] = brushCached;
}
else
{
SkiaUtil.ToSKPaintUpdate(brushCached, fillPaint, effects, scale, _disposable.Disposables);
}
private SKPicture RecordPicture(IContainerView view, IShapeRenderer renderer, double scale, Action<IContainerView, SKCanvas, IShapeRenderer, double> draw)
brush = brushCached;
}
private void DrawShapesCurrent(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
{
view.CurrentContainer.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
}
private void DrawShapesWorking(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
{
view.WorkingContainer.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
}
private void DrawPoints(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
{
var selected = new List<IBaseShape>(view.SelectionState.Shapes);
foreach (var shape in selected)
{
var recorder = new SKPictureRecorder();
var rect = new SKRect(0f, 0f, (float)view.Width, (float)view.Height);
var canvas = recorder.BeginRecording(rect);
draw(view, canvas, renderer, scale);
return recorder.EndRecording();
}
private void DrawPicture(SKCanvas canvas, SKPicture picture, double dx, double dy, double zx, double zy)
{
canvas.Save();
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
canvas.DrawPicture(picture);
canvas.Restore();
}
private void DrawGrid(SKCanvas canvas, double dx, double dy, double zx, double zy)
{
float gw = (float)_view.Width;
float gh = (float)_view.Height;
float cw = 15.0f;
float ch = 15.0f;
canvas.Save();
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
var hlattice = SKMatrix.CreateScale(cw, ch);
hlattice = hlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 0.0 / 180.0)));
var vlattice = SKMatrix.CreateScale(cw, ch);
vlattice = vlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 90.0 / 180.0)));
using (var heffect = SKPathEffect.Create2DLine((float)(1.0 / zx), hlattice))
using (var veffect = SKPathEffect.Create2DLine((float)(1.0 / zx), vlattice))
using (var hpaint = new SKPaint())
using (var vpaint = new SKPaint())
if (shape is IPointShape point)
{
hpaint.IsAntialias = false;
hpaint.Color = SKColors.LightGray;
hpaint.PathEffect = heffect;
canvas.DrawRect(SKRect.Create(0.0f, ch, gw, gh - ch), hpaint);
vpaint.IsAntialias = false;
vpaint.Color = SKColors.LightGray;
vpaint.PathEffect = veffect;
canvas.DrawRect(SKRect.Create(cw, 0.0f, gw - cw, gh), vpaint);
}
using (SKPaint strokePaint = new SKPaint())
{
strokePaint.IsAntialias = false;
strokePaint.StrokeWidth = (float)(1.0 / zx);
strokePaint.Color = SKColors.Red;
strokePaint.Style = SKPaintStyle.Stroke;
canvas.DrawRect(SKRect.Create(0.0f, 0.0f, gw, gh), strokePaint);
}
canvas.Restore();
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
bool isStyleLibraryDirty = _context.DocumentContainer.StyleLibrary.IsTreeDirty();
bool isCurrentContainerDirty = _view.CurrentContainer.IsTreeDirty();
bool isWorkingContainerDirty = _view.WorkingContainer.IsTreeDirty();
bool isPointsCurrentContainerDirty = _view.CurrentContainer.IsPointsTreeDirty();
bool isPointsWorkingContainerDirty = _view.WorkingContainer.IsPointsTreeDirty();
bool isShapesCurrentDirty = isCurrentContainerDirty == true || isPointsCurrentContainerDirty == true || _previousZX != zx || _previousZY != zy;
bool isShapesWorkingDirty = isWorkingContainerDirty == true || isPointsWorkingContainerDirty == true || _previousZX != zx || _previousZY != zy;
if (_pictureShapesCurrent == null || isShapesCurrentDirty == true || isStyleLibraryDirty == true)
{
if (_pictureShapesCurrent != null)
{
_pictureShapesCurrent.Dispose();
}
_pictureShapesCurrent = RecordPicture(_view, _skiaRenderer, zx, DrawShapesCurrent);
}
if (_pictureShapesWorking == null || isShapesWorkingDirty == true || isStyleLibraryDirty == true)
{
if (_pictureShapesWorking != null)
{
_pictureShapesWorking.Dispose();
}
_pictureShapesWorking = RecordPicture(_view, _skiaRenderer, zx, DrawShapesWorking);
}
bool isSelectionDirty = _view.SelectionState.IsTreeDirty() == true || isShapesCurrentDirty == true || isShapesWorkingDirty == true;
if (_view.SelectionState.IsTreeDirty() == true)
{
_view.SelectionState.Invalidate();
}
if (_pictureDecorators == null || isSelectionDirty == true || isStyleLibraryDirty == true)
{
if (_pictureDecorators != null)
{
_pictureDecorators.Dispose();
}
_pictureDecorators = RecordPicture(_view, _skiaRenderer, zx, DrawDecorators);
}
if (_picturePoints == null || isSelectionDirty == true || isStyleLibraryDirty == true)
{
if (_picturePoints != null)
{
_picturePoints.Dispose();
}
_picturePoints = RecordPicture(_view, _skiaRenderer, zx, DrawPoints);
}
_previousZX = zx;
_previousZY = zy;
var canvas = context as SKCanvas;
if (_view.InputBackground?.Color != null)
{
canvas.Clear(SkiaUtil.ToSKColor(_view.InputBackground.Color));
}
else
{
canvas.Clear();
}
if (_view.WorkBackground != null)
{
GetSKPaintFill(_view.WorkBackground, null, 1.0, out var brush);
double s = 1.0 / scale;
canvas.Save();
double dx = 0.0 - (point.X * s) + point.X;
double dy = 0.0 - (point.Y * s) + point.Y;
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
canvas.DrawRect(SkiaUtil.ToSKRect(0.0, 0.0, _view.Width, _view.Height), brush);
canvas.Scale((float)s);
point.Draw(canvas, renderer, 0.0, 0.0, scale, null, null);
canvas.Restore();
}
// TODO: Fix grid X and Y position.
//DrawGrid(canvas, dx, dy, zx, zy);
DrawPicture(canvas, _pictureShapesCurrent, dx, dy, zx, zy);
DrawPicture(canvas, _pictureShapesWorking, dx, dy, zx, zy);
DrawPicture(canvas, _pictureDecorators, dx, dy, zx, zy);
DrawPicture(canvas, _picturePoints, dx, dy, zx, zy);
if (_enablePictureCache == false)
{
_picturePoints.Dispose();
_picturePoints = null;
_pictureDecorators.Dispose();
_pictureDecorators = null;
_pictureShapesWorking.Dispose();
_pictureShapesWorking = null;
_pictureShapesCurrent.Dispose();
_pictureShapesCurrent = null;
}
if (isCurrentContainerDirty == true)
{
_view.CurrentContainer?.Invalidate();
}
if (isWorkingContainerDirty == true)
{
_view.WorkingContainer?.Invalidate();
}
if (isStyleLibraryDirty == true)
{
_context.DocumentContainer.StyleLibrary?.Invalidate();
}
}
}
}
private void DrawDecorators(IContainerView view, SKCanvas canvas, IShapeRenderer renderer, double scale)
{
var selected = new List<IBaseShape>(view.SelectionState.Shapes);
foreach (var shape in selected)
{
shape.Decorator?.Draw(canvas, shape, renderer, view.SelectionState, 0.0, 0.0, scale);
}
}
private SKPicture RecordPicture(IContainerView view, IShapeRenderer renderer, double scale, Action<IContainerView, SKCanvas, IShapeRenderer, double> draw)
{
var recorder = new SKPictureRecorder();
var rect = new SKRect(0f, 0f, (float)view.Width, (float)view.Height);
var canvas = recorder.BeginRecording(rect);
draw(view, canvas, renderer, scale);
return recorder.EndRecording();
}
private void DrawPicture(SKCanvas canvas, SKPicture picture, double dx, double dy, double zx, double zy)
{
canvas.Save();
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
canvas.DrawPicture(picture);
canvas.Restore();
}
private void DrawGrid(SKCanvas canvas, double dx, double dy, double zx, double zy)
{
float gw = (float)_view.Width;
float gh = (float)_view.Height;
float cw = 15.0f;
float ch = 15.0f;
canvas.Save();
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
var hlattice = SKMatrix.CreateScale(cw, ch);
hlattice = hlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 0.0 / 180.0)));
var vlattice = SKMatrix.CreateScale(cw, ch);
vlattice = vlattice.PreConcat(SKMatrix.CreateRotation((float)(Math.PI * 90.0 / 180.0)));
using (var heffect = SKPathEffect.Create2DLine((float)(1.0 / zx), hlattice))
using (var veffect = SKPathEffect.Create2DLine((float)(1.0 / zx), vlattice))
using (var hpaint = new SKPaint())
using (var vpaint = new SKPaint())
{
hpaint.IsAntialias = false;
hpaint.Color = SKColors.LightGray;
hpaint.PathEffect = heffect;
canvas.DrawRect(SKRect.Create(0.0f, ch, gw, gh - ch), hpaint);
vpaint.IsAntialias = false;
vpaint.Color = SKColors.LightGray;
vpaint.PathEffect = veffect;
canvas.DrawRect(SKRect.Create(cw, 0.0f, gw - cw, gh), vpaint);
}
using (SKPaint strokePaint = new SKPaint())
{
strokePaint.IsAntialias = false;
strokePaint.StrokeWidth = (float)(1.0 / zx);
strokePaint.Color = SKColors.Red;
strokePaint.Style = SKPaintStyle.Stroke;
canvas.DrawRect(SKRect.Create(0.0f, 0.0f, gw, gh), strokePaint);
}
canvas.Restore();
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
bool isStyleLibraryDirty = _context.DocumentContainer.StyleLibrary.IsTreeDirty();
bool isCurrentContainerDirty = _view.CurrentContainer.IsTreeDirty();
bool isWorkingContainerDirty = _view.WorkingContainer.IsTreeDirty();
bool isPointsCurrentContainerDirty = _view.CurrentContainer.IsPointsTreeDirty();
bool isPointsWorkingContainerDirty = _view.WorkingContainer.IsPointsTreeDirty();
bool isShapesCurrentDirty = isCurrentContainerDirty == true || isPointsCurrentContainerDirty == true || _previousZX != zx || _previousZY != zy;
bool isShapesWorkingDirty = isWorkingContainerDirty == true || isPointsWorkingContainerDirty == true || _previousZX != zx || _previousZY != zy;
if (_pictureShapesCurrent == null || isShapesCurrentDirty == true || isStyleLibraryDirty == true)
{
if (_pictureShapesCurrent != null)
{
_pictureShapesCurrent.Dispose();
}
_pictureShapesCurrent = RecordPicture(_view, _skiaRenderer, zx, DrawShapesCurrent);
}
if (_pictureShapesWorking == null || isShapesWorkingDirty == true || isStyleLibraryDirty == true)
{
if (_pictureShapesWorking != null)
{
_pictureShapesWorking.Dispose();
}
_pictureShapesWorking = RecordPicture(_view, _skiaRenderer, zx, DrawShapesWorking);
}
bool isSelectionDirty = _view.SelectionState.IsTreeDirty() == true || isShapesCurrentDirty == true || isShapesWorkingDirty == true;
if (_view.SelectionState.IsTreeDirty() == true)
{
_view.SelectionState.Invalidate();
}
if (_pictureDecorators == null || isSelectionDirty == true || isStyleLibraryDirty == true)
{
if (_pictureDecorators != null)
{
_pictureDecorators.Dispose();
}
_pictureDecorators = RecordPicture(_view, _skiaRenderer, zx, DrawDecorators);
}
if (_picturePoints == null || isSelectionDirty == true || isStyleLibraryDirty == true)
{
if (_picturePoints != null)
{
_picturePoints.Dispose();
}
_picturePoints = RecordPicture(_view, _skiaRenderer, zx, DrawPoints);
}
_previousZX = zx;
_previousZY = zy;
var canvas = context as SKCanvas;
if (_view.InputBackground?.Color != null)
{
canvas.Clear(SkiaUtil.ToSKColor(_view.InputBackground.Color));
}
else
{
canvas.Clear();
}
if (_view.WorkBackground != null)
{
GetSKPaintFill(_view.WorkBackground, null, 1.0, out var brush);
canvas.Save();
canvas.Translate((float)dx, (float)dy);
canvas.Scale((float)zx, (float)zy);
canvas.DrawRect(SkiaUtil.ToSKRect(0.0, 0.0, _view.Width, _view.Height), brush);
canvas.Restore();
}
// TODO: Fix grid X and Y position.
//DrawGrid(canvas, dx, dy, zx, zy);
DrawPicture(canvas, _pictureShapesCurrent, dx, dy, zx, zy);
DrawPicture(canvas, _pictureShapesWorking, dx, dy, zx, zy);
DrawPicture(canvas, _pictureDecorators, dx, dy, zx, zy);
DrawPicture(canvas, _picturePoints, dx, dy, zx, zy);
if (_enablePictureCache == false)
{
_picturePoints.Dispose();
_picturePoints = null;
_pictureDecorators.Dispose();
_pictureDecorators = null;
_pictureShapesWorking.Dispose();
_pictureShapesWorking = null;
_pictureShapesCurrent.Dispose();
_pictureShapesCurrent = null;
}
if (isCurrentContainerDirty == true)
{
_view.CurrentContainer?.Invalidate();
}
if (isWorkingContainerDirty == true)
{
_view.WorkingContainer?.Invalidate();
}
if (isStyleLibraryDirty == true)
{
_context.DocumentContainer.StyleLibrary?.Invalidate();
}
}
}

Просмотреть файл

@ -3,31 +3,30 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Presenters
namespace Draw2D.Presenters;
public class SkiaExportContainerPresenter : IContainerPresenter
{
public class SkiaExportContainerPresenter : IContainerPresenter
private readonly IToolContext _context;
private readonly IContainerView _view;
public SkiaExportContainerPresenter(IToolContext context, IContainerView view)
{
private readonly IToolContext _context;
private readonly IContainerView _view;
public SkiaExportContainerPresenter(IToolContext context, IContainerView view)
{
_context = context;
_view = view;
}
public void Dispose()
{
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
using var renderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
using var disposable = new CompositeDisposable();
using var background = SkiaUtil.ToSKPaint(_view.PrintBackground, null, zx, disposable.Disposables);
var canvas = context as SKCanvas;
canvas.DrawRect(SkiaUtil.ToSKRect(dx, dy, _view.Width + dx, _view.Height + dy), background);
_view.CurrentContainer.Draw(canvas, renderer, dx, dy, zx, null, null);
}
_context = context;
_view = view;
}
}
public void Dispose()
{
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
using var renderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
using var disposable = new CompositeDisposable();
using var background = SkiaUtil.ToSKPaint(_view.PrintBackground, null, zx, disposable.Disposables);
var canvas = context as SKCanvas;
canvas.DrawRect(SkiaUtil.ToSKRect(dx, dy, _view.Width + dx, _view.Height + dy), background);
_view.CurrentContainer.Draw(canvas, renderer, dx, dy, zx, null, null);
}
}

Просмотреть файл

@ -6,44 +6,43 @@ using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
using SkiaSharp;
namespace Draw2D.Presenters
namespace Draw2D.Presenters;
public class SkiaExportSelectedPresenter : IContainerPresenter
{
public class SkiaExportSelectedPresenter : IContainerPresenter
private readonly IToolContext _context;
private readonly IContainerView _view;
public SkiaExportSelectedPresenter(IToolContext context, IContainerView view)
{
private readonly IToolContext _context;
private readonly IContainerView _view;
_context = context;
_view = view;
}
public SkiaExportSelectedPresenter(IToolContext context, IContainerView view)
public void Dispose()
{
}
private bool IsAcceptedShape(IBaseShape shape)
{
return !(shape is IPointShape || shape is FigureShape);
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
using var renderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
using var disposable = new CompositeDisposable();
using var background = SkiaUtil.ToSKPaint(_view.PrintBackground, null, zx, disposable.Disposables);
var canvas = context as SKCanvas;
canvas.DrawRect(SkiaUtil.ToSKRect(dx, dy, _view.Width + dx, _view.Height + dy), background);
var selected = new List<IBaseShape>(_view.SelectionState?.Shapes);
foreach (var shape in selected)
{
_context = context;
_view = view;
}
public void Dispose()
{
}
private bool IsAcceptedShape(IBaseShape shape)
{
return !(shape is IPointShape || shape is FigureShape);
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
using var renderer = new SkiaShapeRenderer(_context, _view, _view.SelectionState);
using var disposable = new CompositeDisposable();
using var background = SkiaUtil.ToSKPaint(_view.PrintBackground, null, zx, disposable.Disposables);
var canvas = context as SKCanvas;
canvas.DrawRect(SkiaUtil.ToSKRect(dx, dy, _view.Width + dx, _view.Height + dy), background);
var selected = new List<IBaseShape>(_view.SelectionState?.Shapes);
foreach (var shape in selected)
if (IsAcceptedShape(shape))
{
if (IsAcceptedShape(shape))
{
shape.Draw(canvas, renderer, dx, dy, zx, null, null);
}
shape.Draw(canvas, renderer, dx, dy, zx, null, null);
}
}
}
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,24 +1,23 @@
using System;
using System.Collections.Generic;
namespace Draw2D
namespace Draw2D;
internal class CompositeDisposable : IDisposable
{
internal class CompositeDisposable : IDisposable
public IList<IDisposable> Disposables { get; private set; }
public CompositeDisposable()
{
public IList<IDisposable> Disposables { get; private set; }
public CompositeDisposable()
{
Disposables = new List<IDisposable>();
}
public void Dispose()
{
foreach (var disposable in Disposables)
{
disposable?.Dispose();
}
Disposables = null;
}
Disposables = new List<IDisposable>();
}
}
public void Dispose()
{
foreach (var disposable in Disposables)
{
disposable?.Dispose();
}
Disposables = null;
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -3,30 +3,29 @@ using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Draw2D.ViewModels;
namespace Draw2D
namespace Draw2D;
public class ViewLocator : IDataTemplate
{
public class ViewLocator : IDataTemplate
public bool SupportsRecycling => false;
public Control Build(object data)
{
public bool SupportsRecycling => false;
var name = data.GetType().FullName.Replace("ViewModel", "View");
var type = Type.GetType(name + "View");
public IControl Build(object data)
if (type != null)
{
var name = data.GetType().FullName.Replace("ViewModel", "View");
var type = Type.GetType(name + "View");
if (type != null)
{
return (Control)Activator.CreateInstance(type);
}
else
{
return new TextBlock { Text = "Not Found: " + name };
}
return (Control)Activator.CreateInstance(type);
}
public bool Match(object data)
else
{
return data is ViewModelBase;
return new TextBlock { Text = "Not Found: " + name };
}
}
public bool Match(object data)
{
return data is ViewModelBase;
}
}

Просмотреть файл

@ -4,50 +4,49 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class ArcBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class ArcBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
if (arc.StartPoint.Bounds?.TryToGetPoint(arc.StartPoint, target, radius, hitTest, modifier) != null)
{
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
if (arc.StartPoint.Bounds?.TryToGetPoint(arc.StartPoint, target, radius, hitTest, modifier) != null)
{
return arc.StartPoint;
}
if (arc.Point.Bounds?.TryToGetPoint(arc.Point, target, radius, hitTest, modifier) != null)
{
return arc.Point;
}
foreach (var point in arc.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return arc.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (arc.Point.Bounds?.TryToGetPoint(arc.Point, target, radius, hitTest, modifier) != null)
{
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
var distance = arc.StartPoint.DistanceTo(arc.Point);
return arc.StartPoint.ToRect2(distance).Contains(target) ? shape : null;
return arc.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in arc.Points)
{
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
var distance = arc.StartPoint.DistanceTo(arc.Point);
return arc.StartPoint.ToRect2(distance).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
var distance = arc.StartPoint.DistanceTo(arc.Point);
return arc.StartPoint.ToRect2(distance).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var arc = shape as ArcShape ?? throw new ArgumentNullException("shape");
var distance = arc.StartPoint.DistanceTo(arc.Point);
return arc.StartPoint.ToRect2(distance).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -4,50 +4,49 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class CircleBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class CircleBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
if (circle.StartPoint.Bounds?.TryToGetPoint(circle.StartPoint, target, radius, hitTest, modifier) != null)
{
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
if (circle.StartPoint.Bounds?.TryToGetPoint(circle.StartPoint, target, radius, hitTest, modifier) != null)
{
return circle.StartPoint;
}
if (circle.Point.Bounds?.TryToGetPoint(circle.Point, target, radius, hitTest, modifier) != null)
{
return circle.Point;
}
foreach (var point in circle.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return circle.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (circle.Point.Bounds?.TryToGetPoint(circle.Point, target, radius, hitTest, modifier) != null)
{
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
var distance = circle.StartPoint.DistanceTo(circle.Point);
return circle.StartPoint.ToRect2(distance).Contains(target) ? shape : null;
return circle.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in circle.Points)
{
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
var distance = circle.StartPoint.DistanceTo(circle.Point);
return circle.StartPoint.ToRect2(distance).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
var distance = circle.StartPoint.DistanceTo(circle.Point);
return circle.StartPoint.ToRect2(distance).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var circle = shape as CircleShape ?? throw new ArgumentNullException("shape");
var distance = circle.StartPoint.DistanceTo(circle.Point);
return circle.StartPoint.ToRect2(distance).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -5,78 +5,77 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class ConicBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class ConicBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is ConicShape conic))
{
if (!(shape is ConicShape conic))
{
throw new ArgumentNullException("shape");
}
throw new ArgumentNullException("shape");
}
if (conic.StartPoint.Bounds?.TryToGetPoint(conic.StartPoint, target, radius, hitTest, modifier) != null)
{
return conic.StartPoint;
}
if (conic.StartPoint.Bounds?.TryToGetPoint(conic.StartPoint, target, radius, hitTest, modifier) != null)
{
return conic.StartPoint;
}
if (conic.Point1.Bounds?.TryToGetPoint(conic.Point1, target, radius, hitTest, modifier) != null)
{
return conic.Point1;
}
if (conic.Point1.Bounds?.TryToGetPoint(conic.Point1, target, radius, hitTest, modifier) != null)
{
return conic.Point1;
}
if (conic.Point2.Bounds?.TryToGetPoint(conic.Point2, target, radius, hitTest, modifier) != null)
{
return conic.Point2;
}
if (conic.Point2.Bounds?.TryToGetPoint(conic.Point2, target, radius, hitTest, modifier) != null)
{
return conic.Point2;
}
foreach (var point in conic.Points)
foreach (var point in conic.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
return point;
}
}
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ConicShape conic))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
conic.GetPoints(points);
if (points.Count == 0)
{
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ConicShape conic))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
conic.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ConicShape conic))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
conic.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ConicShape conic))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
conic.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
}

Просмотреть файл

@ -5,72 +5,71 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Containers;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class ContainerBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class ContainerBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is CanvasContainer container))
{
if (!(shape is CanvasContainer container))
{
throw new ArgumentNullException("shape");
}
foreach (var containerPoint in container.Points)
{
if (containerPoint.Bounds?.TryToGetPoint(containerPoint, target, radius, hitTest, modifier) != null)
{
return containerPoint;
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var containerPoint in container.Points)
{
if (!(shape is CanvasContainer container))
if (containerPoint.Bounds?.TryToGetPoint(containerPoint, target, radius, hitTest, modifier) != null)
{
throw new ArgumentNullException("shape");
return containerPoint;
}
foreach (var containerShape in container.Shapes)
{
var result = containerShape.Bounds?.Contains(containerShape, target, radius, hitTest, modifier);
if (result != null)
{
return container;
}
}
var points = new List<IPointShape>();
container.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CanvasContainer container))
{
throw new ArgumentNullException("shape");
}
foreach (var containerShape in container.Shapes)
{
var result = containerShape.Bounds?.Overlaps(containerShape, target, radius, hitTest, modifier);
if (result != null)
{
return container;
}
}
return null;
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CanvasContainer container))
{
throw new ArgumentNullException("shape");
}
foreach (var containerShape in container.Shapes)
{
var result = containerShape.Bounds?.Contains(containerShape, target, radius, hitTest, modifier);
if (result != null)
{
return container;
}
}
var points = new List<IPointShape>();
container.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CanvasContainer container))
{
throw new ArgumentNullException("shape");
}
foreach (var containerShape in container.Shapes)
{
var result = containerShape.Bounds?.Overlaps(containerShape, target, radius, hitTest, modifier);
if (result != null)
{
return container;
}
}
return null;
}
}

Просмотреть файл

@ -5,83 +5,82 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class CubicBezierBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class CubicBezierBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is CubicBezierShape cubicBezier))
{
if (!(shape is CubicBezierShape cubicBezier))
{
throw new ArgumentNullException("shape");
}
throw new ArgumentNullException("shape");
}
if (cubicBezier.StartPoint.Bounds?.TryToGetPoint(cubicBezier.StartPoint, target, radius, hitTest, modifier) != null)
{
return cubicBezier.StartPoint;
}
if (cubicBezier.StartPoint.Bounds?.TryToGetPoint(cubicBezier.StartPoint, target, radius, hitTest, modifier) != null)
{
return cubicBezier.StartPoint;
}
if (cubicBezier.Point1.Bounds?.TryToGetPoint(cubicBezier.Point1, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point1;
}
if (cubicBezier.Point1.Bounds?.TryToGetPoint(cubicBezier.Point1, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point1;
}
if (cubicBezier.Point2.Bounds?.TryToGetPoint(cubicBezier.Point2, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point2;
}
if (cubicBezier.Point2.Bounds?.TryToGetPoint(cubicBezier.Point2, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point2;
}
if (cubicBezier.Point3.Bounds?.TryToGetPoint(cubicBezier.Point3, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point3;
}
if (cubicBezier.Point3.Bounds?.TryToGetPoint(cubicBezier.Point3, target, radius, hitTest, modifier) != null)
{
return cubicBezier.Point3;
}
foreach (var point in cubicBezier.Points)
foreach (var point in cubicBezier.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
return point;
}
}
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CubicBezierShape cubicBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
cubicBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CubicBezierShape cubicBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
cubicBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CubicBezierShape cubicBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
cubicBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is CubicBezierShape cubicBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
cubicBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
}

Просмотреть файл

@ -4,79 +4,78 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class FigureBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class FigureBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is FigureShape figure))
{
if (!(shape is FigureShape figure))
{
throw new ArgumentNullException("shape");
}
foreach (var figureShape in figure.Shapes)
{
var result = figureShape.Bounds?.TryToGetPoint(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
foreach (var figurePoint in figure.Points)
{
if (figurePoint.Bounds?.TryToGetPoint(figurePoint, target, radius, hitTest, modifier) != null)
{
return figurePoint;
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var figureShape in figure.Shapes)
{
if (!(shape is FigureShape figure))
var result = figureShape.Bounds?.TryToGetPoint(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
throw new ArgumentNullException("shape");
return result;
}
foreach (var figureShape in figure.Shapes)
{
var result = figureShape.Bounds?.Contains(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
if (modifier.HasFlag(Modifier.Shift))
{
return result;
}
else
{
return figure;
}
}
}
return null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var figurePoint in figure.Points)
{
if (!(shape is FigureShape figure))
if (figurePoint.Bounds?.TryToGetPoint(figurePoint, target, radius, hitTest, modifier) != null)
{
throw new ArgumentNullException("shape");
return figurePoint;
}
foreach (var figureShape in figure.Shapes)
{
var result = figureShape.Bounds?.Overlaps(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
return null;
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is FigureShape figure))
{
throw new ArgumentNullException("shape");
}
foreach (var figureShape in figure.Shapes)
{
var result = figureShape.Bounds?.Contains(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
if (modifier.HasFlag(Modifier.Shift))
{
return result;
}
else
{
return figure;
}
}
}
return null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is FigureShape figure))
{
throw new ArgumentNullException("shape");
}
foreach (var figureShape in figure.Shapes)
{
var result = figureShape.Bounds?.Overlaps(figureShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
return null;
}
}

Просмотреть файл

@ -6,93 +6,92 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class GroupBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class GroupBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is GroupShape group))
{
if (!(shape is GroupShape group))
{
throw new ArgumentNullException("shape");
}
if (modifier.HasFlag(Modifier.Shift))
{
foreach (var groupShape in group.Shapes.Reverse())
{
var result = groupShape.Bounds?.TryToGetPoint(groupShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
}
else
{
foreach (var groupPoint in group.Points)
{
if (groupPoint.Bounds?.TryToGetPoint(groupPoint, target, radius, hitTest, modifier) != null)
{
return groupPoint;
}
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (modifier.HasFlag(Modifier.Shift))
{
if (!(shape is GroupShape group))
{
throw new ArgumentNullException("shape");
}
foreach (var groupShape in group.Shapes.Reverse())
{
var result = groupShape.Bounds?.Contains(groupShape, target, radius, hitTest, modifier);
var result = groupShape.Bounds?.TryToGetPoint(groupShape, target, radius, hitTest, modifier);
if (result != null)
{
if (modifier.HasFlag(Modifier.Shift))
{
return result;
}
else
{
return group;
}
return result;
}
}
var points = new List<IPointShape>();
group.GetPoints(points);
if (points.Count == 0)
}
else
{
foreach (var groupPoint in group.Points)
{
return null;
if (groupPoint.Bounds?.TryToGetPoint(groupPoint, target, radius, hitTest, modifier) != null)
{
return groupPoint;
}
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is GroupShape group))
{
throw new ArgumentNullException("shape");
}
return null;
}
foreach (var groupShape in group.Shapes)
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is GroupShape group))
{
throw new ArgumentNullException("shape");
}
foreach (var groupShape in group.Shapes.Reverse())
{
var result = groupShape.Bounds?.Contains(groupShape, target, radius, hitTest, modifier);
if (result != null)
{
var result = groupShape.Bounds?.Overlaps(groupShape, target, radius, hitTest, modifier);
if (result != null)
if (modifier.HasFlag(Modifier.Shift))
{
return result;
}
else
{
return group;
}
}
}
var points = new List<IPointShape>();
group.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is GroupShape group))
{
throw new ArgumentNullException("shape");
}
foreach (var groupShape in group.Shapes)
{
var result = groupShape.Bounds?.Overlaps(groupShape, target, radius, hitTest, modifier);
if (result != null)
{
return group;
}
}
return null;
}
}

Просмотреть файл

@ -4,54 +4,53 @@ using System.Runtime.Serialization;
using Core2D.UI.Zoom.Input;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class HitTest : ViewModelBase, IHitTest
{
[DataContract(IsReference = true)]
public class HitTest : ViewModelBase, IHitTest
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, double scale, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, double scale, Modifier modifier)
{
return shape.Bounds?.TryToGetPoint(shape, target, radius / scale, this, modifier);
}
public IPointShape TryToGetPoint(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier, IPointShape exclude)
{
foreach (var shape in shapes.Reverse())
{
var result = TryToGetPoint(shape, target, radius, scale, modifier);
if (result != null && result != exclude)
{
return result;
}
}
return null;
}
public IBaseShape TryToGetShape(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier)
{
foreach (var shape in shapes.Reverse())
{
var result = shape.Bounds?.Contains(shape, target, radius / scale, this, modifier);
if (result != null)
{
return result;
}
}
return null;
}
public ISet<IBaseShape> TryToGetShapes(IEnumerable<IBaseShape> shapes, Rect2 target, double radius, double scale, Modifier modifier)
{
var selected = new HashSet<IBaseShape>();
foreach (var shape in shapes.Reverse())
{
var result = shape.Bounds?.Overlaps(shape, target, radius / scale, this, modifier);
if (result != null)
{
selected.Add(shape);
}
}
return selected.Count > 0 ? selected : null;
}
return shape.Bounds?.TryToGetPoint(shape, target, radius / scale, this, modifier);
}
}
public IPointShape TryToGetPoint(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier, IPointShape exclude)
{
foreach (var shape in shapes.Reverse())
{
var result = TryToGetPoint(shape, target, radius, scale, modifier);
if (result != null && result != exclude)
{
return result;
}
}
return null;
}
public IBaseShape TryToGetShape(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier)
{
foreach (var shape in shapes.Reverse())
{
var result = shape.Bounds?.Contains(shape, target, radius / scale, this, modifier);
if (result != null)
{
return result;
}
}
return null;
}
public ISet<IBaseShape> TryToGetShapes(IEnumerable<IBaseShape> shapes, Rect2 target, double radius, double scale, Modifier modifier)
{
var selected = new HashSet<IBaseShape>();
foreach (var shape in shapes.Reverse())
{
var result = shape.Bounds?.Overlaps(shape, target, radius / scale, this, modifier);
if (result != null)
{
selected.Add(shape);
}
}
return selected.Count > 0 ? selected : null;
}
}

Просмотреть файл

@ -4,62 +4,61 @@ using Spatial;
using Spatial.ConvexHull;
using Spatial.Sat;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
public static class HitTestHelper
{
public static class HitTestHelper
public static MonotoneChain MC => new MonotoneChain();
public static SeparatingAxisTheorem SAT => new SeparatingAxisTheorem();
public static Vector2[] ToSelection(Rect2 rect)
{
public static MonotoneChain MC => new MonotoneChain();
public static SeparatingAxisTheorem SAT => new SeparatingAxisTheorem();
public static Vector2[] ToSelection(Rect2 rect)
return new Vector2[]
{
return new Vector2[]
{
new Vector2(rect.X, rect.Y),
new Vector2(rect.X + rect.Width, rect.Y),
new Vector2(rect.X + rect.Width, rect.Y + rect.Height),
new Vector2(rect.X, rect.Y + rect.Height)
};
}
public static void ToConvexHull(IEnumerable<IPointShape> points, out int k, out Vector2[] convexHull)
{
Vector2[] vertices = new Vector2[points.Count()];
int i = 0;
foreach (var point in points)
{
vertices[i] = new Vector2(point.X, point.Y);
i++;
}
MC.ConvexHull(vertices, out convexHull, out k);
}
public static bool Contains(IEnumerable<IPointShape> points, Point2 point)
{
ToConvexHull(points, out int k, out Vector2[] convexHull);
bool contains = false;
for (int i = 0, j = k - 2; i < k - 1; j = i++)
{
if (((convexHull[i].Y > point.Y) != (convexHull[j].Y > point.Y))
&& (point.X < (convexHull[j].X - convexHull[i].X) * (point.Y - convexHull[i].Y) / (convexHull[j].Y - convexHull[i].Y) + convexHull[i].X))
{
contains = !contains;
}
}
return contains;
}
public static bool Overlap(IEnumerable<IPointShape> points, Vector2[] selectionState)
{
ToConvexHull(points, out int k, out Vector2[] convexHull);
Vector2[] vertices = convexHull.Take(k).ToArray();
return SAT.Overlap(selectionState, vertices);
}
public static bool Overlap(IEnumerable<IPointShape> points, Rect2 rect)
{
return Overlap(points, ToSelection(rect));
}
new Vector2(rect.X, rect.Y),
new Vector2(rect.X + rect.Width, rect.Y),
new Vector2(rect.X + rect.Width, rect.Y + rect.Height),
new Vector2(rect.X, rect.Y + rect.Height)
};
}
}
public static void ToConvexHull(IEnumerable<IPointShape> points, out int k, out Vector2[] convexHull)
{
Vector2[] vertices = new Vector2[points.Count()];
int i = 0;
foreach (var point in points)
{
vertices[i] = new Vector2(point.X, point.Y);
i++;
}
MC.ConvexHull(vertices, out convexHull, out k);
}
public static bool Contains(IEnumerable<IPointShape> points, Point2 point)
{
ToConvexHull(points, out int k, out Vector2[] convexHull);
bool contains = false;
for (int i = 0, j = k - 2; i < k - 1; j = i++)
{
if (((convexHull[i].Y > point.Y) != (convexHull[j].Y > point.Y))
&& (point.X < (convexHull[j].X - convexHull[i].X) * (point.Y - convexHull[i].Y) / (convexHull[j].Y - convexHull[i].Y) + convexHull[i].X))
{
contains = !contains;
}
}
return contains;
}
public static bool Overlap(IEnumerable<IPointShape> points, Vector2[] selectionState)
{
ToConvexHull(points, out int k, out Vector2[] convexHull);
Vector2[] vertices = convexHull.Take(k).ToArray();
return SAT.Overlap(selectionState, vertices);
}
public static bool Overlap(IEnumerable<IPointShape> points, Rect2 rect)
{
return Overlap(points, ToSelection(rect));
}
}

Просмотреть файл

@ -4,56 +4,55 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class ImageBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class ImageBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
if (image.StartPoint.Bounds?.TryToGetPoint(image.StartPoint, target, radius, hitTest, modifier) != null)
{
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
if (image.StartPoint.Bounds?.TryToGetPoint(image.StartPoint, target, radius, hitTest, modifier) != null)
{
return image.StartPoint;
}
if (image.Point.Bounds?.TryToGetPoint(image.Point, target, radius, hitTest, modifier) != null)
{
return image.Point;
}
foreach (var point in image.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return image.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (image.Point.Bounds?.TryToGetPoint(image.Point, target, radius, hitTest, modifier) != null)
{
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
image.StartPoint.X,
image.StartPoint.Y,
image.Point.X,
image.Point.Y).Contains(target) ? shape : null;
return image.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in image.Points)
{
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
image.StartPoint.X,
image.StartPoint.Y,
image.Point.X,
image.Point.Y).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
image.StartPoint.X,
image.StartPoint.Y,
image.Point.X,
image.Point.Y).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var image = shape as ImageShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
image.StartPoint.X,
image.StartPoint.Y,
image.Point.X,
image.Point.Y).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -4,63 +4,62 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class LineBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class LineBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is LineShape line))
{
if (!(shape is LineShape line))
{
throw new ArgumentNullException("shape");
}
if (line.StartPoint.Bounds?.TryToGetPoint(line.StartPoint, target, radius, hitTest, modifier) != null)
{
return line.StartPoint;
}
if (line.Point.Bounds?.TryToGetPoint(line.Point, target, radius, hitTest, modifier) != null)
{
return line.Point;
}
foreach (var point in line.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (line.StartPoint.Bounds?.TryToGetPoint(line.StartPoint, target, radius, hitTest, modifier) != null)
{
if (!(shape is LineShape line))
{
throw new ArgumentNullException("shape");
}
var a = new Point2(line.StartPoint.X, line.StartPoint.Y);
var b = new Point2(line.Point.X, line.Point.Y);
var nearest = target.NearestOnLine(a, b);
double distance = target.DistanceTo(nearest);
return distance < radius ? shape : null;
return line.StartPoint;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
if (line.Point.Bounds?.TryToGetPoint(line.Point, target, radius, hitTest, modifier) != null)
{
if (!(shape is LineShape line))
{
throw new ArgumentNullException("shape");
}
var a = new Point2(line.StartPoint.X, line.StartPoint.Y);
var b = new Point2(line.Point.X, line.Point.Y);
return Line2.LineIntersectsWithRect(a, b, target, out _, out _, out _, out _) ? shape : null;
return line.Point;
}
foreach (var point in line.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is LineShape line))
{
throw new ArgumentNullException("shape");
}
var a = new Point2(line.StartPoint.X, line.StartPoint.Y);
var b = new Point2(line.Point.X, line.Point.Y);
var nearest = target.NearestOnLine(a, b);
double distance = target.DistanceTo(nearest);
return distance < radius ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is LineShape line))
{
throw new ArgumentNullException("shape");
}
var a = new Point2(line.StartPoint.X, line.StartPoint.Y);
var b = new Point2(line.Point.X, line.Point.Y);
return Line2.LineIntersectsWithRect(a, b, target, out _, out _, out _, out _) ? shape : null;
}
}

Просмотреть файл

@ -4,56 +4,55 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class OvalBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class OvalBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
if (oval.StartPoint.Bounds?.TryToGetPoint(oval.StartPoint, target, radius, hitTest, modifier) != null)
{
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
if (oval.StartPoint.Bounds?.TryToGetPoint(oval.StartPoint, target, radius, hitTest, modifier) != null)
{
return oval.StartPoint;
}
if (oval.Point.Bounds?.TryToGetPoint(oval.Point, target, radius, hitTest, modifier) != null)
{
return oval.Point;
}
foreach (var point in oval.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return oval.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (oval.Point.Bounds?.TryToGetPoint(oval.Point, target, radius, hitTest, modifier) != null)
{
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
oval.StartPoint.X,
oval.StartPoint.Y,
oval.Point.X,
oval.Point.Y).Contains(target) ? shape : null;
return oval.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in oval.Points)
{
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
oval.StartPoint.X,
oval.StartPoint.Y,
oval.Point.X,
oval.Point.Y).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
oval.StartPoint.X,
oval.StartPoint.Y,
oval.Point.X,
oval.Point.Y).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var oval = shape as OvalShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
oval.StartPoint.X,
oval.StartPoint.Y,
oval.Point.X,
oval.Point.Y).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -6,130 +6,129 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class PathBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class PathBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is PathShape path))
{
if (!(shape is PathShape path))
{
throw new ArgumentNullException("shape");
}
foreach (var pathShape in path.Shapes.Reverse())
{
var result = pathShape.Bounds?.TryToGetPoint(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
foreach (var pathPoint in path.Points)
{
if (pathPoint.Bounds?.TryToGetPoint(pathPoint, target, radius, hitTest, modifier) != null)
{
return pathPoint;
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var pathShape in path.Shapes.Reverse())
{
if (!(shape is PathShape path))
var result = pathShape.Bounds?.TryToGetPoint(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
throw new ArgumentNullException("shape");
return result;
}
}
if (modifier.HasFlag(Modifier.Shift))
foreach (var pathPoint in path.Points)
{
if (pathPoint.Bounds?.TryToGetPoint(pathPoint, target, radius, hitTest, modifier) != null)
{
if (path.Shapes.Count >= 1)
{
foreach (var pathShape in path.Shapes.Reverse())
{
var pathShapePoints = new List<IPointShape>();
pathShape.GetPoints(pathShapePoints);
if (pathShapePoints.Count == 0)
{
continue;
}
if (HitTestHelper.Contains(pathShapePoints, target))
{
if (modifier.HasFlag(Modifier.Alt))
{
var result = pathShape.Bounds?.Contains(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
return pathShape;
}
}
}
return pathPoint;
}
else
}
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is PathShape path))
{
throw new ArgumentNullException("shape");
}
if (modifier.HasFlag(Modifier.Shift))
{
if (path.Shapes.Count >= 1)
{
foreach (var pathShape in path.Shapes.Reverse())
{
var result = pathShape.Bounds?.Contains(pathShape, target, radius, hitTest, modifier);
if (result != null)
var pathShapePoints = new List<IPointShape>();
pathShape.GetPoints(pathShapePoints);
if (pathShapePoints.Count == 0)
{
continue;
}
if (HitTestHelper.Contains(pathShapePoints, target))
{
if (modifier.HasFlag(Modifier.Alt))
{
var subResult = result.Bounds?.Contains(result, target, radius, hitTest, Modifier.Shift);
if (subResult != null)
var result = pathShape.Bounds?.Contains(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
return subResult;
return result;
}
}
return path;
return pathShape;
}
}
}
var points = new List<IPointShape>();
path.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
else
{
if (!(shape is PathShape path))
foreach (var pathShape in path.Shapes.Reverse())
{
throw new ArgumentNullException("shape");
}
foreach (var pathShape in path.Shapes)
{
var result = pathShape.Bounds?.Overlaps(pathShape, target, radius, hitTest, modifier);
var result = pathShape.Bounds?.Contains(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
if (modifier.HasFlag(Modifier.Alt))
{
var subResult = result.Bounds?.Contains(result, target, radius, hitTest, Modifier.Shift);
if (subResult != null)
{
return subResult;
}
}
return path;
}
}
var points = new List<IPointShape>();
path.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
var points = new List<IPointShape>();
path.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is PathShape path))
{
throw new ArgumentNullException("shape");
}
foreach (var pathShape in path.Shapes)
{
var result = pathShape.Bounds?.Overlaps(pathShape, target, radius, hitTest, modifier);
if (result != null)
{
return result;
}
}
var points = new List<IPointShape>();
path.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
}

Просмотреть файл

@ -3,44 +3,43 @@ using System.Runtime.Serialization;
using Core2D.UI.Zoom.Input;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class PointBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class PointBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is IPointShape point))
{
if (!(shape is IPointShape point))
{
throw new ArgumentNullException("shape");
}
if (Point2.FromXY(point.X, point.Y).ExpandToRect(radius).Contains(target.X, target.Y))
{
return point;
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (Point2.FromXY(point.X, point.Y).ExpandToRect(radius).Contains(target.X, target.Y))
{
if (!(shape is IPointShape point))
{
throw new ArgumentNullException("shape");
}
return Point2.FromXY(point.X, point.Y).ExpandToRect(radius).Contains(target.X, target.Y) ? shape : null;
return point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is IPointShape point))
{
throw new ArgumentNullException("shape");
}
return Point2.FromXY(point.X, point.Y).ExpandToRect(radius).IntersectsWith(target) ? shape : null;
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is IPointShape point))
{
throw new ArgumentNullException("shape");
}
return Point2.FromXY(point.X, point.Y).ExpandToRect(radius).Contains(target.X, target.Y) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is IPointShape point))
{
throw new ArgumentNullException("shape");
}
return Point2.FromXY(point.X, point.Y).ExpandToRect(radius).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -5,78 +5,77 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class QuadraticBezierBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class QuadraticBezierBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is QuadraticBezierShape quadraticBezier))
{
if (!(shape is QuadraticBezierShape quadraticBezier))
{
throw new ArgumentNullException("shape");
}
throw new ArgumentNullException("shape");
}
if (quadraticBezier.StartPoint.Bounds?.TryToGetPoint(quadraticBezier.StartPoint, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.StartPoint;
}
if (quadraticBezier.StartPoint.Bounds?.TryToGetPoint(quadraticBezier.StartPoint, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.StartPoint;
}
if (quadraticBezier.Point1.Bounds?.TryToGetPoint(quadraticBezier.Point1, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.Point1;
}
if (quadraticBezier.Point1.Bounds?.TryToGetPoint(quadraticBezier.Point1, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.Point1;
}
if (quadraticBezier.Point2.Bounds?.TryToGetPoint(quadraticBezier.Point2, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.Point2;
}
if (quadraticBezier.Point2.Bounds?.TryToGetPoint(quadraticBezier.Point2, target, radius, hitTest, modifier) != null)
{
return quadraticBezier.Point2;
}
foreach (var point in quadraticBezier.Points)
foreach (var point in quadraticBezier.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
return point;
}
}
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is QuadraticBezierShape quadraticBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
quadraticBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is QuadraticBezierShape quadraticBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
quadraticBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is QuadraticBezierShape quadraticBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
quadraticBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
return HitTestHelper.Contains(points, target) ? shape : null;
}
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is QuadraticBezierShape quadraticBezier))
{
throw new ArgumentNullException("shape");
}
var points = new List<IPointShape>();
quadraticBezier.GetPoints(points);
if (points.Count == 0)
{
return null;
}
return HitTestHelper.Overlap(points, target) ? shape : null;
}
}

Просмотреть файл

@ -4,56 +4,55 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class RectangleBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class RectangleBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
if (rectangle.StartPoint.Bounds?.TryToGetPoint(rectangle.StartPoint, target, radius, hitTest, modifier) != null)
{
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
if (rectangle.StartPoint.Bounds?.TryToGetPoint(rectangle.StartPoint, target, radius, hitTest, modifier) != null)
{
return rectangle.StartPoint;
}
if (rectangle.Point.Bounds?.TryToGetPoint(rectangle.Point, target, radius, hitTest, modifier) != null)
{
return rectangle.Point;
}
foreach (var point in rectangle.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return rectangle.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (rectangle.Point.Bounds?.TryToGetPoint(rectangle.Point, target, radius, hitTest, modifier) != null)
{
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
rectangle.StartPoint.X,
rectangle.StartPoint.Y,
rectangle.Point.X,
rectangle.Point.Y).Contains(target) ? shape : null;
return rectangle.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in rectangle.Points)
{
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
rectangle.StartPoint.X,
rectangle.StartPoint.Y,
rectangle.Point.X,
rectangle.Point.Y).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
rectangle.StartPoint.X,
rectangle.StartPoint.Y,
rectangle.Point.X,
rectangle.Point.Y).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var rectangle = shape as RectangleShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
rectangle.StartPoint.X,
rectangle.StartPoint.Y,
rectangle.Point.X,
rectangle.Point.Y).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -4,67 +4,66 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class ReferenceBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class ReferenceBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (!(shape is ReferenceShape reference))
{
if (!(shape is ReferenceShape reference))
{
throw new ArgumentNullException("shape");
}
foreach (var point in reference.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
throw new ArgumentNullException("shape");
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in reference.Points)
{
if (!(shape is ReferenceShape reference))
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
throw new ArgumentNullException("shape");
return point;
}
if (reference.Template?.Bounds != null)
{
var adjustedTarget = new Point2(target.X - reference.X, target.Y - reference.Y);
var result = reference.Template.Bounds.Contains(reference.Template, adjustedTarget, radius, hitTest, modifier);
if (result != null)
{
return reference;
}
}
return null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ReferenceShape reference))
{
throw new ArgumentNullException("shape");
}
if (reference.Template?.Bounds != null)
{
var adjustedTarget = new Rect2(target.X - reference.X, target.Y - reference.Y, target.Width, target.Height);
var result = reference.Template.Bounds.Overlaps(reference.Template, adjustedTarget, radius, hitTest, modifier);
if (result != null)
{
return reference;
}
}
return null;
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ReferenceShape reference))
{
throw new ArgumentNullException("shape");
}
if (reference.Template?.Bounds != null)
{
var adjustedTarget = new Point2(target.X - reference.X, target.Y - reference.Y);
var result = reference.Template.Bounds.Contains(reference.Template, adjustedTarget, radius, hitTest, modifier);
if (result != null)
{
return reference;
}
}
return null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
if (!(shape is ReferenceShape reference))
{
throw new ArgumentNullException("shape");
}
if (reference.Template?.Bounds != null)
{
var adjustedTarget = new Rect2(target.X - reference.X, target.Y - reference.Y, target.Width, target.Height);
var result = reference.Template.Bounds.Overlaps(reference.Template, adjustedTarget, radius, hitTest, modifier);
if (result != null)
{
return reference;
}
}
return null;
}
}

Просмотреть файл

@ -4,56 +4,55 @@ using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Shapes;
using Spatial;
namespace Draw2D.ViewModels.Bounds
namespace Draw2D.ViewModels.Bounds;
[DataContract(IsReference = true)]
public class TextBounds : ViewModelBase, IBounds
{
[DataContract(IsReference = true)]
public class TextBounds : ViewModelBase, IBounds
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
public IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
if (text.StartPoint.Bounds?.TryToGetPoint(text.StartPoint, target, radius, hitTest, modifier) != null)
{
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
if (text.StartPoint.Bounds?.TryToGetPoint(text.StartPoint, target, radius, hitTest, modifier) != null)
{
return text.StartPoint;
}
if (text.Point.Bounds?.TryToGetPoint(text.Point, target, radius, hitTest, modifier) != null)
{
return text.Point;
}
foreach (var point in text.Points)
{
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
return text.StartPoint;
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
if (text.Point.Bounds?.TryToGetPoint(text.Point, target, radius, hitTest, modifier) != null)
{
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
text.StartPoint.X,
text.StartPoint.Y,
text.Point.X,
text.Point.Y).Contains(target) ? shape : null;
return text.Point;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
foreach (var point in text.Points)
{
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
text.StartPoint.X,
text.StartPoint.Y,
text.Point.X,
text.Point.Y).IntersectsWith(target) ? shape : null;
if (point.Bounds?.TryToGetPoint(point, target, radius, hitTest, modifier) != null)
{
return point;
}
}
return null;
}
}
public IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
text.StartPoint.X,
text.StartPoint.Y,
text.Point.X,
text.Point.Y).Contains(target) ? shape : null;
}
public IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier)
{
var text = shape as TextShape ?? throw new ArgumentNullException("shape");
return Rect2.FromPoints(
text.StartPoint.X,
text.StartPoint.Y,
text.Point.X,
text.Point.Y).IntersectsWith(target) ? shape : null;
}
}

Просмотреть файл

@ -5,55 +5,54 @@ using Draw2D.ViewModels.Bounds;
using Draw2D.ViewModels.Decorators;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class CanvasContainer : GroupShape, ICanvasContainer
{
[DataContract(IsReference = true)]
public class CanvasContainer : GroupShape, ICanvasContainer
internal static new IBounds s_bounds = new ContainerBounds();
internal static new IShapeDecorator s_decorator = new ContainerDecorator();
[IgnoreDataMember]
public override IBounds Bounds { get; } = s_bounds;
[IgnoreDataMember]
public override IShapeDecorator Decorator { get; } = s_decorator;
public CanvasContainer()
{
internal static new IBounds s_bounds = new ContainerBounds();
internal static new IShapeDecorator s_decorator = new ContainerDecorator();
}
[IgnoreDataMember]
public override IBounds Bounds { get; } = s_bounds;
[IgnoreDataMember]
public override IShapeDecorator Decorator { get; } = s_decorator;
public CanvasContainer()
public override object Copy(Dictionary<object, object> shared)
{
var copy = new CanvasContainer()
{
}
Name = this.Name,
Title = this.Title + "_copy",
Points = new ObservableCollection<IPointShape>(),
Shapes = new ObservableCollection<IBaseShape>(),
StyleId = this.StyleId
};
public override object Copy(Dictionary<object, object> shared)
if (shared != null)
{
var copy = new CanvasContainer()
foreach (var point in this.Points)
{
Name = this.Name,
Title = this.Title + "_copy",
Points = new ObservableCollection<IPointShape>(),
Shapes = new ObservableCollection<IBaseShape>(),
StyleId = this.StyleId
};
if (shared != null)
{
foreach (var point in this.Points)
{
copy.Points.Add((IPointShape)shared[point]);
}
foreach (var shape in this.Shapes)
{
if (shape is ICopyable copyable)
{
copy.Shapes.Add((IBaseShape)(copyable.Copy(shared)));
}
}
shared[this] = copy;
shared[copy] = this;
copy.Points.Add((IPointShape)shared[point]);
}
return copy;
foreach (var shape in this.Shapes)
{
if (shape is ICopyable copyable)
{
copy.Shapes.Add((IBaseShape)(copyable.Copy(shared)));
}
}
shared[this] = copy;
shared[copy] = this;
}
return copy;
}
}
}

Просмотреть файл

@ -6,219 +6,218 @@ using Draw2D.ViewModels.Style;
using Draw2D.ViewModels.Tools;
using Spatial;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class ContainerView : ViewModelBase, IContainerView
{
[DataContract(IsReference = true)]
public class ContainerView : ViewModelBase, IContainerView
private double _width;
private double _height;
private IPaint _printBackground;
private IPaint _workBackground;
private IPaint _inputBackground;
private ICanvasContainer _currentContainer;
private ICanvasContainer _workingContainer;
private ISelectionState _selectionState;
private IZoomServiceState _zoomServiceState;
private IContainerPresenter _containerPresenter;
private IInputService _inputService;
private IZoomService _zoomService;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double Width
{
private double _width;
private double _height;
private IPaint _printBackground;
private IPaint _workBackground;
private IPaint _inputBackground;
private ICanvasContainer _currentContainer;
private ICanvasContainer _workingContainer;
private ISelectionState _selectionState;
private IZoomServiceState _zoomServiceState;
private IContainerPresenter _containerPresenter;
private IInputService _inputService;
private IZoomService _zoomService;
get => _width;
set => Update(ref _width, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double Width
{
get => _width;
set => Update(ref _width, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double Height
{
get => _height;
set => Update(ref _height, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double Height
{
get => _height;
set => Update(ref _height, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint PrintBackground
{
get => _printBackground;
set => Update(ref _printBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint PrintBackground
{
get => _printBackground;
set => Update(ref _printBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint WorkBackground
{
get => _workBackground;
set => Update(ref _workBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint WorkBackground
{
get => _workBackground;
set => Update(ref _workBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint InputBackground
{
get => _inputBackground;
set => Update(ref _inputBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IPaint InputBackground
{
get => _inputBackground;
set => Update(ref _inputBackground, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ICanvasContainer CurrentContainer
{
get => _currentContainer;
set => Update(ref _currentContainer, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ICanvasContainer CurrentContainer
{
get => _currentContainer;
set => Update(ref _currentContainer, value);
}
[IgnoreDataMember]
public ICanvasContainer WorkingContainer
{
get => _workingContainer;
set => Update(ref _workingContainer, value);
}
[IgnoreDataMember]
public ICanvasContainer WorkingContainer
{
get => _workingContainer;
set => Update(ref _workingContainer, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ISelectionState SelectionState
{
get => _selectionState;
set => Update(ref _selectionState, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ISelectionState SelectionState
{
get => _selectionState;
set => Update(ref _selectionState, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IZoomServiceState ZoomServiceState
{
get => _zoomServiceState;
set => Update(ref _zoomServiceState, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IZoomServiceState ZoomServiceState
{
get => _zoomServiceState;
set => Update(ref _zoomServiceState, value);
}
[IgnoreDataMember]
public IContainerPresenter ContainerPresenter
{
get => _containerPresenter;
set => Update(ref _containerPresenter, value);
}
[IgnoreDataMember]
public IContainerPresenter ContainerPresenter
{
get => _containerPresenter;
set => Update(ref _containerPresenter, value);
}
[IgnoreDataMember]
public IInputService InputService
{
get => _inputService;
set => Update(ref _inputService, value);
}
[IgnoreDataMember]
public IInputService InputService
{
get => _inputService;
set => Update(ref _inputService, value);
}
[IgnoreDataMember]
public IZoomService ZoomService
{
get => _zoomService;
set => Update(ref _zoomService, value);
}
[IgnoreDataMember]
public IZoomService ZoomService
{
get => _zoomService;
set => Update(ref _zoomService, value);
}
private bool IsAcceptedShape(IBaseShape shape)
{
return !(shape is IPointShape || shape is FigureShape);
}
private bool IsAcceptedShape(IBaseShape shape)
public virtual IPointShape GetNextPoint(IToolContext context, double x, double y, bool connect, double radius, double scale, Modifier modifier)
{
if (connect == true)
{
return !(shape is IPointShape || shape is FigureShape);
}
public virtual IPointShape GetNextPoint(IToolContext context, double x, double y, bool connect, double radius, double scale, Modifier modifier)
{
if (connect == true)
var point = context.HitTest?.TryToGetPoint(_currentContainer.Shapes, new Point2(x, y), radius, scale, modifier, null);
if (point != null)
{
var point = context.HitTest?.TryToGetPoint(_currentContainer.Shapes, new Point2(x, y), radius, scale, modifier, null);
if (point != null)
{
return point;
}
}
return new PointShape(x, y, context?.DocumentContainer?.PointTemplate);
}
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
_containerPresenter?.Draw(context, width, height, dx, dy, zx, zy, renderScaling);
}
public void Add(IBaseShape shape)
{
if (shape != null)
{
_currentContainer.Shapes.Add(shape);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
return point;
}
}
return new PointShape(x, y, context?.DocumentContainer?.PointTemplate);
}
public void Remove(IBaseShape shape)
public void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling)
{
_containerPresenter?.Draw(context, width, height, dx, dy, zx, zy, renderScaling);
}
public void Add(IBaseShape shape)
{
if (shape != null)
{
if (shape != null)
{
_currentContainer.Shapes.Remove(shape);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public void Reference(IBaseShape shape)
{
if (shape != null)
{
_selectionState?.Clear();
var title = shape is GroupShape group ? group.Title : "Reference";
var reference = new ReferenceShape(title, 0.0, 0.0, shape);
reference.Select(_selectionState);
reference.Owner = _currentContainer;
_currentContainer.Shapes.Add(reference);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public void Style(string styleId)
{
if (_selectionState?.Shapes != null && !string.IsNullOrEmpty(styleId))
{
foreach (var shape in _selectionState.Shapes)
{
if (IsAcceptedShape(shape))
{
shape.StyleId = styleId;
}
}
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public virtual object Copy(Dictionary<object, object> shared)
{
var copy = new ContainerView()
{
Name = this.Name,
Title = this.Title + "_copy",
Width = this.Width,
Height = this.Height,
PrintBackground = (IPaint)this.PrintBackground?.Copy(shared),
WorkBackground = (IPaint)this.WorkBackground?.Copy(shared),
InputBackground = (IPaint)this.InputBackground?.Copy(shared),
CurrentContainer = (ICanvasContainer)this.CurrentContainer?.Copy(shared),
WorkingContainer = null,
SelectionState = new SelectionState()
{
Hovered = null,
Selected = null,
Shapes = new HashSet<IBaseShape>()
},
ZoomServiceState = new ZoomServiceState()
{
ZoomSpeed = 1.2,
ZoomX = double.NaN,
ZoomY = double.NaN,
OffsetX = double.NaN,
OffsetY = double.NaN,
IsPanning = false,
IsZooming = false,
InitFitMode = FitMode.Center,
AutoFitMode = FitMode.None
},
ContainerPresenter = null,
InputService = null,
ZoomService = null
};
return copy;
_currentContainer.Shapes.Add(shape);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
}
public void Remove(IBaseShape shape)
{
if (shape != null)
{
_currentContainer.Shapes.Remove(shape);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public void Reference(IBaseShape shape)
{
if (shape != null)
{
_selectionState?.Clear();
var title = shape is GroupShape group ? group.Title : "Reference";
var reference = new ReferenceShape(title, 0.0, 0.0, shape);
reference.Select(_selectionState);
reference.Owner = _currentContainer;
_currentContainer.Shapes.Add(reference);
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public void Style(string styleId)
{
if (_selectionState?.Shapes != null && !string.IsNullOrEmpty(styleId))
{
foreach (var shape in _selectionState.Shapes)
{
if (IsAcceptedShape(shape))
{
shape.StyleId = styleId;
}
}
_currentContainer.MarkAsDirty(true);
_inputService?.Redraw?.Invoke();
}
}
public virtual object Copy(Dictionary<object, object> shared)
{
var copy = new ContainerView()
{
Name = this.Name,
Title = this.Title + "_copy",
Width = this.Width,
Height = this.Height,
PrintBackground = (IPaint)this.PrintBackground?.Copy(shared),
WorkBackground = (IPaint)this.WorkBackground?.Copy(shared),
InputBackground = (IPaint)this.InputBackground?.Copy(shared),
CurrentContainer = (ICanvasContainer)this.CurrentContainer?.Copy(shared),
WorkingContainer = null,
SelectionState = new SelectionState()
{
Hovered = null,
Selected = null,
Shapes = new HashSet<IBaseShape>()
},
ZoomServiceState = new ZoomServiceState()
{
ZoomSpeed = 1.2,
ZoomX = double.NaN,
ZoomY = double.NaN,
OffsetX = double.NaN,
OffsetY = double.NaN,
IsPanning = false,
IsZooming = false,
InitFitMode = FitMode.Center,
AutoFitMode = FitMode.None
},
ContainerPresenter = null,
InputService = null,
ZoomService = null
};
return copy;
}
}

Просмотреть файл

@ -1,9 +1,8 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface ICanvasContainer : IBaseShape
{
public interface ICanvasContainer : IBaseShape
{
IList<IBaseShape> Shapes { get; set; }
}
}
IList<IBaseShape> Shapes { get; set; }
}

Просмотреть файл

@ -1,24 +1,23 @@
using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Style;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IContainerView : IDrawTarget, IHitTestable, ICopyable
{
public interface IContainerView : IDrawTarget, IHitTestable, ICopyable
{
string Title { get; set; }
double Width { get; set; }
double Height { get; set; }
IPaint PrintBackground { get; set; }
IPaint WorkBackground { get; set; }
IPaint InputBackground { get; set; }
ICanvasContainer CurrentContainer { get; set; }
ICanvasContainer WorkingContainer { get; set; }
ISelectionState SelectionState { get; set; }
IZoomServiceState ZoomServiceState { get; set; }
IContainerPresenter ContainerPresenter { get; set; }
void Add(IBaseShape shape);
void Remove(IBaseShape shape);
void Reference(IBaseShape shape);
void Style(string styleId);
}
}
string Title { get; set; }
double Width { get; set; }
double Height { get; set; }
IPaint PrintBackground { get; set; }
IPaint WorkBackground { get; set; }
IPaint InputBackground { get; set; }
ICanvasContainer CurrentContainer { get; set; }
ICanvasContainer WorkingContainer { get; set; }
ISelectionState SelectionState { get; set; }
IZoomServiceState ZoomServiceState { get; set; }
IContainerPresenter ContainerPresenter { get; set; }
void Add(IBaseShape shape);
void Remove(IBaseShape shape);
void Reference(IBaseShape shape);
void Style(string styleId);
}

Просмотреть файл

@ -1,15 +1,14 @@
using System;
using System.Collections.Generic;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IDocumentContainer : ICopyable, IDisposable
{
public interface IDocumentContainer : ICopyable, IDisposable
{
string Title { get; set; }
IStyleLibrary StyleLibrary { get; set; }
IGroupLibrary GroupLibrary { get; set; }
IBaseShape PointTemplate { get; set; }
IList<IContainerView> ContainerViews { get; set; }
IContainerView ContainerView { get; set; }
}
}
string Title { get; set; }
IStyleLibrary StyleLibrary { get; set; }
IGroupLibrary GroupLibrary { get; set; }
IBaseShape PointTemplate { get; set; }
IList<IContainerView> ContainerViews { get; set; }
IContainerView ContainerView { get; set; }
}

Просмотреть файл

@ -1,8 +1,7 @@
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IGroupLibrary : ILibrary<GroupShape>
{
public interface IGroupLibrary : ILibrary<GroupShape>
{
}
}
}

Просмотреть файл

@ -1,14 +1,13 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface ILibrary<T> : IDirty where T : INode, ICopyable, IDirty
{
public interface ILibrary<T> : IDirty where T : INode, ICopyable, IDirty
{
IList<T> Items { get; set; }
T CurrentItem { get; set; }
void UpdateCache();
void Add(T value);
void Remove(T value);
T Get(string title);
}
}
IList<T> Items { get; set; }
T CurrentItem { get; set; }
void UpdateCache();
void Add(T value);
void Remove(T value);
T Get(string title);
}

Просмотреть файл

@ -1,8 +1,7 @@
using Draw2D.ViewModels.Style;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IStyleLibrary : ILibrary<IShapeStyle>
{
public interface IStyleLibrary : ILibrary<IShapeStyle>
{
}
}
}

Просмотреть файл

@ -1,139 +1,138 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public abstract class Library<T> : ViewModelBase, ILibrary<T> where T : INode, ICopyable, IDirty
{
[DataContract(IsReference = true)]
public abstract class Library<T> : ViewModelBase, ILibrary<T> where T : INode, ICopyable, IDirty
private Dictionary<string, T> _itemsCache;
private IList<T> _items;
private T _currentItem;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IList<T> Items
{
private Dictionary<string, T> _itemsCache;
private IList<T> _items;
private T _currentItem;
get => _items;
set => Update(ref _items, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IList<T> Items
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public T CurrentItem
{
get => _currentItem;
set => Update(ref _currentItem, value);
}
public override bool IsTreeDirty()
{
if (base.IsTreeDirty())
{
get => _items;
set => Update(ref _items, value);
return true;
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public T CurrentItem
if (_items != null)
{
get => _currentItem;
set => Update(ref _currentItem, value);
}
public override bool IsTreeDirty()
{
if (base.IsTreeDirty())
foreach (var item in _items)
{
return true;
}
if (_items != null)
{
foreach (var item in _items)
if (item?.IsTreeDirty() ?? false)
{
if (item?.IsTreeDirty() ?? false)
{
return true;
}
}
}
return false;
}
public override void Invalidate()
{
if (_items != null)
{
foreach (var item in _items)
{
item.Invalidate();
}
}
_currentItem?.Invalidate();
base.Invalidate();
}
public void UpdateCache()
{
if (_items != null)
{
if (_itemsCache == null)
{
_itemsCache = new Dictionary<string, T>();
}
else
{
_itemsCache.Clear();
}
foreach (var item in _items)
{
_itemsCache[item.Title] = item;
return true;
}
}
}
public void Add(T value)
return false;
}
public override void Invalidate()
{
if (_items != null)
{
if (value != null)
foreach (var item in _items)
{
_items.Add(value);
if (_itemsCache == null)
{
_itemsCache = new Dictionary<string, T>();
}
_itemsCache[value.Title] = value;
item.Invalidate();
}
}
public void Remove(T value)
{
if (value != null)
{
_items.Remove(value);
_currentItem?.Invalidate();
if (_itemsCache != null)
{
_itemsCache.Remove(value.Title);
}
base.Invalidate();
}
public void UpdateCache()
{
if (_items != null)
{
if (_itemsCache == null)
{
_itemsCache = new Dictionary<string, T>();
}
else
{
_itemsCache.Clear();
}
foreach (var item in _items)
{
_itemsCache[item.Title] = item;
}
}
}
public T Get(string title)
public void Add(T value)
{
if (value != null)
{
if (title == null)
{
return default;
}
_items.Add(value);
if (_itemsCache == null)
{
UpdateCache();
_itemsCache = new Dictionary<string, T>();
}
if (!_itemsCache.TryGetValue(title, out var value))
{
foreach (var item in _items)
{
if (item.Title == title)
{
_itemsCache[item.Title] = item;
return item;
}
}
return default;
}
return value;
_itemsCache[value.Title] = value;
}
}
}
public void Remove(T value)
{
if (value != null)
{
_items.Remove(value);
if (_itemsCache != null)
{
_itemsCache.Remove(value.Title);
}
}
}
public T Get(string title)
{
if (title == null)
{
return default;
}
if (_itemsCache == null)
{
UpdateCache();
}
if (!_itemsCache.TryGetValue(title, out var value))
{
foreach (var item in _items)
{
if (item.Title == title)
{
_itemsCache[item.Title] = item;
return item;
}
}
return default;
}
return value;
}
}

Просмотреть файл

@ -2,74 +2,73 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class DocumentContainer : ViewModelBase, IDocumentContainer
{
[DataContract(IsReference = true)]
public class DocumentContainer : ViewModelBase, IDocumentContainer
private IStyleLibrary _styleLibrary;
private IGroupLibrary _groupLibrary;
private IBaseShape _pointTemplate;
private IList<IContainerView> _containerViews;
private IContainerView _containerView;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IStyleLibrary StyleLibrary
{
private IStyleLibrary _styleLibrary;
private IGroupLibrary _groupLibrary;
private IBaseShape _pointTemplate;
private IList<IContainerView> _containerViews;
private IContainerView _containerView;
get => _styleLibrary;
set => Update(ref _styleLibrary, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IStyleLibrary StyleLibrary
{
get => _styleLibrary;
set => Update(ref _styleLibrary, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IGroupLibrary GroupLibrary
{
get => _groupLibrary;
set => Update(ref _groupLibrary, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IGroupLibrary GroupLibrary
{
get => _groupLibrary;
set => Update(ref _groupLibrary, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape PointTemplate
{
get => _pointTemplate;
set => Update(ref _pointTemplate, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape PointTemplate
{
get => _pointTemplate;
set => Update(ref _pointTemplate, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IList<IContainerView> ContainerViews
{
get => _containerViews;
set => Update(ref _containerViews, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IList<IContainerView> ContainerViews
{
get => _containerViews;
set => Update(ref _containerViews, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IContainerView ContainerView
{
get => _containerView;
set => Update(ref _containerView, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IContainerView ContainerView
public void Dispose()
{
if (_containerViews != null)
{
get => _containerView;
set => Update(ref _containerView, value);
}
public void Dispose()
{
if (_containerViews != null)
foreach (var containerView in _containerViews)
{
foreach (var containerView in _containerViews)
{
containerView.ContainerPresenter?.Dispose();
containerView.ContainerPresenter = null;
containerView.SelectionState = null;
containerView.WorkingContainer = null;
}
containerView.ContainerPresenter?.Dispose();
containerView.ContainerPresenter = null;
containerView.SelectionState = null;
containerView.WorkingContainer = null;
}
}
public virtual object Copy(Dictionary<object, object> shared)
{
var copy = new ToolContext()
{
Name = this.Name
};
return copy;
}
}
}
public virtual object Copy(Dictionary<object, object> shared)
{
var copy = new ToolContext()
{
Name = this.Name
};
return copy;
}
}

Просмотреть файл

@ -1,14 +1,13 @@
using System.Text;
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IAvaloniaXamlConverter
{
public interface IAvaloniaXamlConverter
{
void ConvertToGeometryDrawing(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToDrawingGroup(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToDrawingPresenter(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToPath(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToCanvas(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
}
}
void ConvertToGeometryDrawing(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToDrawingGroup(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToDrawingPresenter(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToPath(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
void ConvertToCanvas(IToolContext context, IContainerView containerView, StringBuilder sb, string indent);
}

Просмотреть файл

@ -1,9 +1,8 @@
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IContainerExporter
{
public interface IContainerExporter
{
void Export(IToolContext context, string path, IContainerView containerView);
}
}
void Export(IToolContext context, string path, IContainerView containerView);
}

Просмотреть файл

@ -1,9 +1,8 @@
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IContainerImporter
{
public interface IContainerImporter
{
void Import(IToolContext context, string path, IContainerView containerView);
}
}
void Import(IToolContext context, string path, IContainerView containerView);
}

Просмотреть файл

@ -1,9 +1,8 @@
using System;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IContainerPresenter : IDisposable
{
public interface IContainerPresenter : IDisposable
{
void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling);
}
}
void Draw(object context, double width, double height, double dx, double dy, double zx, double zy, double renderScaling);
}

Просмотреть файл

@ -3,15 +3,14 @@ using System.Collections.Generic;
using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface IPathConverter : IDisposable
{
public interface IPathConverter : IDisposable
{
PathShape ToPathShape(IToolContext context, IBaseShape shape);
PathShape ToStrokePathShape(IToolContext context, IBaseShape shape);
PathShape ToFillPathShape(IToolContext context, IBaseShape shape);
PathShape Op(IToolContext context, PathOp op, ICollection<IBaseShape> selected);
PathShape ToPathShape(IToolContext context, string svgPathData);
string ToSvgPathData(IToolContext context, ICollection<IBaseShape> selected);
}
}
PathShape ToPathShape(IToolContext context, IBaseShape shape);
PathShape ToStrokePathShape(IToolContext context, IBaseShape shape);
PathShape ToFillPathShape(IToolContext context, IBaseShape shape);
PathShape Op(IToolContext context, PathOp op, ICollection<IBaseShape> selected);
PathShape ToPathShape(IToolContext context, string svgPathData);
string ToSvgPathData(IToolContext context, ICollection<IBaseShape> selected);
}

Просмотреть файл

@ -1,9 +1,8 @@
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public interface ISvgConverter
{
public interface ISvgConverter
{
string ConvertToSvgDocument(IToolContext context, IContainerView containerView);
}
}
string ConvertToSvgDocument(IToolContext context, IContainerView containerView);
}

Просмотреть файл

@ -1,12 +1,11 @@

namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
public enum PathOp
{
public enum PathOp
{
Difference = 0,
Intersect = 1,
Union = 2,
Xor = 3,
ReverseDifference = 4
}
}
Difference = 0,
Intersect = 1,
Union = 2,
Xor = 3,
ReverseDifference = 4
}

Просмотреть файл

@ -3,30 +3,29 @@ using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class GroupLibrary : Library<GroupShape>, IGroupLibrary
{
[DataContract(IsReference = true)]
public class GroupLibrary : Library<GroupShape>, IGroupLibrary
public virtual object Copy(Dictionary<object, object> shared)
{
public virtual object Copy(Dictionary<object, object> shared)
var copy = new GroupLibrary()
{
var copy = new GroupLibrary()
{
Name = this.Name,
CurrentItem = (GroupShape)this.CurrentItem?.Copy(shared),
Items = new ObservableCollection<GroupShape>()
};
Name = this.Name,
CurrentItem = (GroupShape)this.CurrentItem?.Copy(shared),
Items = new ObservableCollection<GroupShape>()
};
foreach (var item in this.Items)
foreach (var item in this.Items)
{
if (item is ICopyable copyable)
{
if (item is ICopyable copyable)
{
copy.Items.Add((GroupShape)(copyable.Copy(shared)));
}
copy.Items.Add((GroupShape)(copyable.Copy(shared)));
}
return copy;
}
return copy;
}
}
}

Просмотреть файл

@ -1,96 +1,95 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class SelectionState : ViewModelBase, ISelectionState
{
[DataContract(IsReference = true)]
public class SelectionState : ViewModelBase, ISelectionState
private IBaseShape _hovered;
private IBaseShape _selected;
private ISet<IBaseShape> _shapes;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape Hovered
{
private IBaseShape _hovered;
private IBaseShape _selected;
private ISet<IBaseShape> _shapes;
get => _hovered;
set => Update(ref _hovered, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape Hovered
{
get => _hovered;
set => Update(ref _hovered, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape Selected
{
get => _selected;
set => Update(ref _selected, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public IBaseShape Selected
{
get => _selected;
set => Update(ref _selected, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ISet<IBaseShape> Shapes
{
get => _shapes;
set => Update(ref _shapes, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public ISet<IBaseShape> Shapes
public void Hover(IBaseShape shape)
{
if (shape != null)
{
get => _shapes;
set => Update(ref _shapes, value);
}
public void Hover(IBaseShape shape)
{
if (shape != null)
{
shape.Select(this);
Hovered = shape;
this.MarkAsDirty(true);
}
}
public void Dehover()
{
if (_hovered != null)
{
_hovered.Deselect(this);
Hovered = null;
this.MarkAsDirty(true);
}
}
public bool IsSelected(IBaseShape shape)
{
if (shape != null && _shapes.Contains(shape))
{
return true;
}
return false;
}
public void Select(IBaseShape shape)
{
if (shape != null)
{
if (_shapes.Count == 0)
{
Selected = shape;
}
_shapes.Add(shape);
this.MarkAsDirty(true);
}
}
public void Deselect(IBaseShape shape)
{
if (shape != null)
{
_shapes.Remove(shape);
if (_shapes.Count == 0)
{
Selected = null;
}
this.MarkAsDirty(true);
}
}
public void Clear()
{
_shapes.Clear();
Selected = null;
shape.Select(this);
Hovered = shape;
this.MarkAsDirty(true);
}
}
}
public void Dehover()
{
if (_hovered != null)
{
_hovered.Deselect(this);
Hovered = null;
this.MarkAsDirty(true);
}
}
public bool IsSelected(IBaseShape shape)
{
if (shape != null && _shapes.Contains(shape))
{
return true;
}
return false;
}
public void Select(IBaseShape shape)
{
if (shape != null)
{
if (_shapes.Count == 0)
{
Selected = shape;
}
_shapes.Add(shape);
this.MarkAsDirty(true);
}
}
public void Deselect(IBaseShape shape)
{
if (shape != null)
{
_shapes.Remove(shape);
if (_shapes.Count == 0)
{
Selected = null;
}
this.MarkAsDirty(true);
}
}
public void Clear()
{
_shapes.Clear();
Selected = null;
this.MarkAsDirty(true);
}
}

Просмотреть файл

@ -3,29 +3,28 @@ using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Draw2D.ViewModels.Style;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class StyleLibrary : Library<IShapeStyle>, IStyleLibrary
{
[DataContract(IsReference = true)]
public class StyleLibrary : Library<IShapeStyle>, IStyleLibrary
public virtual object Copy(Dictionary<object, object> shared)
{
public virtual object Copy(Dictionary<object, object> shared)
var copy = new StyleLibrary()
{
var copy = new StyleLibrary()
{
Name = this.Name,
CurrentItem = (IShapeStyle)this.CurrentItem?.Copy(shared),
Items = new ObservableCollection<IShapeStyle>()
};
Name = this.Name,
CurrentItem = (IShapeStyle)this.CurrentItem?.Copy(shared),
Items = new ObservableCollection<IShapeStyle>()
};
foreach (var item in this.Items)
foreach (var item in this.Items)
{
if (item is ICopyable copyable)
{
if (item is ICopyable copyable)
{
copy.Items.Add((IShapeStyle)(copyable.Copy(shared)));
}
copy.Items.Add((IShapeStyle)(copyable.Copy(shared)));
}
return copy;
}
return copy;
}
}
}

Просмотреть файл

@ -2,84 +2,83 @@
using System.Runtime.Serialization;
using Core2D.UI.Zoom.Input;
namespace Draw2D.ViewModels.Containers
namespace Draw2D.ViewModels.Containers;
[DataContract(IsReference = true)]
public class ZoomServiceState : ViewModelBase, IZoomServiceState
{
[DataContract(IsReference = true)]
public class ZoomServiceState : ViewModelBase, IZoomServiceState
public static FitMode[] FitModeValues { get; } = (FitMode[])Enum.GetValues(typeof(FitMode));
private double _zoomSpeed;
private double _zoomX;
private double _zoomY;
private double _offsetX;
private double _offsetY;
private bool _isPanning;
private bool _isZooming;
private FitMode _initFitMode;
private FitMode _autoFitMode;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomSpeed
{
public static FitMode[] FitModeValues { get; } = (FitMode[])Enum.GetValues(typeof(FitMode));
private double _zoomSpeed;
private double _zoomX;
private double _zoomY;
private double _offsetX;
private double _offsetY;
private bool _isPanning;
private bool _isZooming;
private FitMode _initFitMode;
private FitMode _autoFitMode;
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomSpeed
{
get => _zoomSpeed;
set => Update(ref _zoomSpeed, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomX
{
get => _zoomX;
set => Update(ref _zoomX, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomY
{
get => _zoomY;
set => Update(ref _zoomY, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double OffsetX
{
get => _offsetX;
set => Update(ref _offsetX, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double OffsetY
{
get => _offsetY;
set => Update(ref _offsetY, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public bool IsPanning
{
get => _isPanning;
set => Update(ref _isPanning, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public bool IsZooming
{
get => _isZooming;
set => Update(ref _isZooming, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public FitMode InitFitMode
{
get => _initFitMode;
set => Update(ref _initFitMode, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public FitMode AutoFitMode
{
get => _autoFitMode;
set => Update(ref _autoFitMode, value);
}
get => _zoomSpeed;
set => Update(ref _zoomSpeed, value);
}
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomX
{
get => _zoomX;
set => Update(ref _zoomX, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double ZoomY
{
get => _zoomY;
set => Update(ref _zoomY, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double OffsetX
{
get => _offsetX;
set => Update(ref _offsetX, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public double OffsetY
{
get => _offsetY;
set => Update(ref _offsetY, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public bool IsPanning
{
get => _isPanning;
set => Update(ref _isPanning, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public bool IsZooming
{
get => _isZooming;
set => Update(ref _isZooming, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public FitMode InitFitMode
{
get => _initFitMode;
set => Update(ref _initFitMode, value);
}
[DataMember(IsRequired = false, EmitDefaultValue = false)]
public FitMode AutoFitMode
{
get => _autoFitMode;
set => Update(ref _autoFitMode, value);
}
}

Просмотреть файл

@ -1,11 +1,10 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public enum HAlign
{
public enum HAlign
{
Auto = 0,
Left = 1,
Center = 2,
Right = 3
}
}
Auto = 0,
Left = 1,
Center = 2,
Right = 3
}

Просмотреть файл

@ -1,10 +1,9 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IBaseShape : INode, ICopyable, IDirty, ISelectable, IDrawable
{
public interface IBaseShape : INode, ICopyable, IDirty, ISelectable, IDrawable
{
void GetPoints(IList<IPointShape> points);
bool IsPointsTreeDirty();
}
}
void GetPoints(IList<IPointShape> points);
bool IsPointsTreeDirty();
}

Просмотреть файл

@ -1,12 +1,11 @@
using Core2D.UI.Zoom.Input;
using Spatial;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IBounds
{
public interface IBounds
{
IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier);
IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier);
IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier);
}
}
IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier);
IBaseShape Contains(IBaseShape shape, Point2 target, double radius, IHitTest hitTest, Modifier modifier);
IBaseShape Overlaps(IBaseShape shape, Rect2 target, double radius, IHitTest hitTest, Modifier modifier);
}

Просмотреть файл

@ -1,12 +1,11 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IConnectable
{
public interface IConnectable
{
IList<IPointShape> Points { get; set; }
bool Connect(IPointShape point, IPointShape target);
bool Disconnect(IPointShape point, out IPointShape result);
bool Disconnect();
}
}
IList<IPointShape> Points { get; set; }
bool Connect(IPointShape point, IPointShape target);
bool Disconnect(IPointShape point, out IPointShape result);
bool Disconnect();
}

Просмотреть файл

@ -1,9 +1,8 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface ICopyable
{
public interface ICopyable
{
object Copy(Dictionary<object, object> shared);
}
}
object Copy(Dictionary<object, object> shared);
}

Просмотреть файл

@ -1,11 +1,10 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IDirty
{
public interface IDirty
{
bool IsDirty { get; set; }
void MarkAsDirty(bool isDirty);
bool IsTreeDirty();
void Invalidate();
}
}
bool IsDirty { get; set; }
void MarkAsDirty(bool isDirty);
bool IsTreeDirty();
void Invalidate();
}

Просмотреть файл

@ -1,13 +1,12 @@
using Draw2D.ViewModels.Style;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IDrawable
{
public interface IDrawable
{
IBounds Bounds { get; }
IShapeDecorator Decorator { get; }
string StyleId { get; set; }
IPaintEffects Effects { get; set; }
void Draw(object dc, IShapeRenderer renderer, double dx, double dy, double scale, object db, object r);
}
}
IBounds Bounds { get; }
IShapeDecorator Decorator { get; }
string StyleId { get; set; }
IPaintEffects Effects { get; set; }
void Draw(object dc, IShapeRenderer renderer, double dx, double dy, double scale, object db, object r);
}

Просмотреть файл

@ -2,13 +2,12 @@
using Core2D.UI.Zoom.Input;
using Spatial;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IHitTest
{
public interface IHitTest
{
IPointShape TryToGetPoint(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier, IPointShape exclude);
IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, double scale, Modifier modifier);
IBaseShape TryToGetShape(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier);
ISet<IBaseShape> TryToGetShapes(IEnumerable<IBaseShape> shapes, Rect2 target, double radius, double scale, Modifier modifier);
}
}
IPointShape TryToGetPoint(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier, IPointShape exclude);
IPointShape TryToGetPoint(IBaseShape shape, Point2 target, double radius, double scale, Modifier modifier);
IBaseShape TryToGetShape(IEnumerable<IBaseShape> shapes, Point2 target, double radius, double scale, Modifier modifier);
ISet<IBaseShape> TryToGetShapes(IEnumerable<IBaseShape> shapes, Rect2 target, double radius, double scale, Modifier modifier);
}

Просмотреть файл

@ -1,10 +1,9 @@
using Core2D.UI.Zoom.Input;
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IHitTestable
{
public interface IHitTestable
{
IPointShape GetNextPoint(IToolContext context, double x, double y, bool connect, double radius, double scale, Modifier modifier);
}
}
IPointShape GetNextPoint(IToolContext context, double x, double y, bool connect, double radius, double scale, Modifier modifier);
}

Просмотреть файл

@ -1,11 +1,10 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface INode
{
public interface INode
{
string Id { get; set; }
string Name { get; set; }
string Title { get; set; }
object Owner { get; set; }
}
}
string Id { get; set; }
string Name { get; set; }
string Title { get; set; }
object Owner { get; set; }
}

Просмотреть файл

@ -1,12 +1,11 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IPointShape : IBaseShape
{
public interface IPointShape : IBaseShape
{
double X { get; set; }
double Y { get; set; }
HAlign HAlign { get; set; }
VAlign VAlign { get; set; }
IBaseShape Template { get; set; }
}
}
double X { get; set; }
double Y { get; set; }
HAlign HAlign { get; set; }
VAlign VAlign { get; set; }
IBaseShape Template { get; set; }
}

Просмотреть файл

@ -1,10 +1,9 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface ISelectable
{
public interface ISelectable
{
void Move(ISelectionState selectionState, double dx, double dy);
void Select(ISelectionState selectionState);
void Deselect(ISelectionState selectionState);
}
}
void Move(ISelectionState selectionState, double dx, double dy);
void Select(ISelectionState selectionState);
void Deselect(ISelectionState selectionState);
}

Просмотреть файл

@ -1,17 +1,16 @@
using System.Collections.Generic;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface ISelectionState : INode, IDirty
{
public interface ISelectionState : INode, IDirty
{
IBaseShape Hovered { get; set; }
IBaseShape Selected { get; set; }
ISet<IBaseShape> Shapes { get; set; }
void Hover(IBaseShape shape);
void Dehover();
bool IsSelected(IBaseShape shape);
void Select(IBaseShape shape);
void Deselect(IBaseShape shape);
void Clear();
}
}
IBaseShape Hovered { get; set; }
IBaseShape Selected { get; set; }
ISet<IBaseShape> Shapes { get; set; }
void Hover(IBaseShape shape);
void Dehover();
bool IsSelected(IBaseShape shape);
void Select(IBaseShape shape);
void Deselect(IBaseShape shape);
void Clear();
}

Просмотреть файл

@ -1,8 +1,7 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IShapeDecorator
{
public interface IShapeDecorator
{
void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale);
}
}
void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale);
}

Просмотреть файл

@ -1,20 +1,19 @@
using System;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public interface IShapeRenderer : IDisposable
{
public interface IShapeRenderer : IDisposable
{
void DrawLine(object dc, LineShape line, string styleId, double dx, double dy, double scale);
void DrawCubicBezier(object dc, CubicBezierShape cubicBezier, string styleId, double dx, double dy, double scale);
void DrawQuadraticBezier(object dc, QuadraticBezierShape quadraticBezier, string styleId, double dx, double dy, double scale);
void DrawConic(object dc, ConicShape conic, string styleId, double dx, double dy, double scale);
void DrawPath(object dc, PathShape path, string styleId, double dx, double dy, double scale);
void DrawRectangle(object dc, RectangleShape rectangle, string styleId, double dx, double dy, double scale);
void DrawCircle(object dc, CircleShape circle, string styleId, double dx, double dy, double scale);
void DrawArc(object dc, ArcShape arc, string styleId, double dx, double dy, double scale);
void DrawOval(object dc, OvalShape oval, string styleId, double dx, double dy, double scale);
void DrawText(object dc, TextShape text, string styleId, double dx, double dy, double scale);
void DrawImage(object dc, ImageShape image, string styleId, double dx, double dy, double scale);
}
}
void DrawLine(object dc, LineShape line, string styleId, double dx, double dy, double scale);
void DrawCubicBezier(object dc, CubicBezierShape cubicBezier, string styleId, double dx, double dy, double scale);
void DrawQuadraticBezier(object dc, QuadraticBezierShape quadraticBezier, string styleId, double dx, double dy, double scale);
void DrawConic(object dc, ConicShape conic, string styleId, double dx, double dy, double scale);
void DrawPath(object dc, PathShape path, string styleId, double dx, double dy, double scale);
void DrawRectangle(object dc, RectangleShape rectangle, string styleId, double dx, double dy, double scale);
void DrawCircle(object dc, CircleShape circle, string styleId, double dx, double dy, double scale);
void DrawArc(object dc, ArcShape arc, string styleId, double dx, double dy, double scale);
void DrawOval(object dc, OvalShape oval, string styleId, double dx, double dy, double scale);
void DrawText(object dc, TextShape text, string styleId, double dx, double dy, double scale);
void DrawImage(object dc, ImageShape image, string styleId, double dx, double dy, double scale);
}

Просмотреть файл

@ -1,11 +1,10 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public enum VAlign
{
public enum VAlign
{
Auto = 0,
Top = 1,
Center = 2,
Bottom = 3
}
}
Auto = 0,
Top = 1,
Center = 2,
Bottom = 3
}

Просмотреть файл

@ -1,24 +1,23 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
namespace Draw2D.ViewModels.Decorators;
[DataContract(IsReference = true)]
public class ArcDecorator : CommonDecorator
{
[DataContract(IsReference = true)]
public class ArcDecorator : CommonDecorator
public void Draw(object dc, IShapeRenderer renderer, ArcShape arcShape, double dx, double dy, double scale)
{
public void Draw(object dc, IShapeRenderer renderer, ArcShape arcShape, double dx, double dy, double scale)
{
var distance = arcShape.StartPoint.DistanceTo(arcShape.Point);
var distance = arcShape.StartPoint.DistanceTo(arcShape.Point);
DrawRectangle(dc, renderer, arcShape.StartPoint.X, arcShape.StartPoint.Y, distance, dx, dy, scale);
}
DrawRectangle(dc, renderer, arcShape.StartPoint.X, arcShape.StartPoint.Y, distance, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is ArcShape arcShape)
{
if (shape is ArcShape arcShape)
{
Draw(dc, renderer, arcShape, dx, dy, scale);
}
Draw(dc, renderer, arcShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,24 +1,23 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
namespace Draw2D.ViewModels.Decorators;
[DataContract(IsReference = true)]
public class CircleDecorator : CommonDecorator
{
[DataContract(IsReference = true)]
public class CircleDecorator : CommonDecorator
public void Draw(object dc, IShapeRenderer renderer, CircleShape circleShape, double dx, double dy, double scale)
{
public void Draw(object dc, IShapeRenderer renderer, CircleShape circleShape, double dx, double dy, double scale)
{
var distance = circleShape.StartPoint.DistanceTo(circleShape.Point);
var distance = circleShape.StartPoint.DistanceTo(circleShape.Point);
DrawRectangle(dc, renderer, circleShape.StartPoint.X, circleShape.StartPoint.Y, distance, dx, dy, scale);
}
DrawRectangle(dc, renderer, circleShape.StartPoint.X, circleShape.StartPoint.Y, distance, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is CircleShape circleShape)
{
if (shape is CircleShape circleShape)
{
Draw(dc, renderer, circleShape, dx, dy, scale);
}
Draw(dc, renderer, circleShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,23 +1,22 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class ConicDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ConicShape conic, double dx, double dy, double scale)
{
DrawLine(dc, renderer, conic.StartPoint, conic.Point1, dx, dy, scale);
DrawLine(dc, renderer, conic.Point1, conic.Point2, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class ConicDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ConicShape conic, double dx, double dy, double scale)
{
DrawLine(dc, renderer, conic.StartPoint, conic.Point1, dx, dy, scale);
DrawLine(dc, renderer, conic.Point1, conic.Point2, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is ConicShape conic)
{
if (shape is ConicShape conic)
{
Draw(dc, renderer, conic, dx, dy, scale);
}
Draw(dc, renderer, conic, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,25 +1,24 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Containers;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class ContainerDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ICanvasContainer container, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(container))
{
DrawBoxFromPoints(dc, renderer, container, dx, dy, scale);
}
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class ContainerDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ICanvasContainer container, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(container))
{
if (shape is ICanvasContainer container)
{
Draw(dc, renderer, container, selectionState, dx, dy, scale);
}
DrawBoxFromPoints(dc, renderer, container, dx, dy, scale);
}
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is ICanvasContainer container)
{
Draw(dc, renderer, container, selectionState, dx, dy, scale);
}
}
}

Просмотреть файл

@ -3,261 +3,260 @@ using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
namespace Draw2D.ViewModels.Decorators
namespace Draw2D.ViewModels.Decorators;
[DataContract(IsReference = true)]
public abstract class CommonDecorator : ViewModelBase, IShapeDecorator
{
[DataContract(IsReference = true)]
public abstract class CommonDecorator : ViewModelBase, IShapeDecorator
private readonly string _strokeStyleId;
private readonly string _fillStyleId;
private readonly LineShape _line;
private readonly OvalShape _oval;
private readonly RectangleShape _rectangle;
private readonly TextShape _text;
public CommonDecorator()
{
private readonly string _strokeStyleId;
private readonly string _fillStyleId;
private readonly LineShape _line;
private readonly OvalShape _oval;
private readonly RectangleShape _rectangle;
private readonly TextShape _text;
_strokeStyleId = "Decorator-Stroke";
_fillStyleId = "Decorator-Fill";
public CommonDecorator()
_line = new LineShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
_strokeStyleId = "Decorator-Stroke";
_fillStyleId = "Decorator-Fill";
Points = new ObservableCollection<IPointShape>()
};
_line.StartPoint.Owner = _line;
_line.Point.Owner = _line;
_line = new LineShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
Points = new ObservableCollection<IPointShape>()
};
_line.StartPoint.Owner = _line;
_line.Point.Owner = _line;
_oval = new OvalShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
Points = new ObservableCollection<IPointShape>(),
};
_oval.StartPoint.Owner = _oval;
_oval.Point.Owner = _oval;
_rectangle = new RectangleShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
Points = new ObservableCollection<IPointShape>(),
};
_rectangle.StartPoint.Owner = _rectangle;
_rectangle.Point.Owner = _rectangle;
_text = new TextShape(new Text(), new PointShape(0, 0, null), new PointShape(0, 0, null))
{
Points = new ObservableCollection<IPointShape>(),
};
_text.StartPoint.Owner = _text;
_text.Point.Owner = _text;
}
internal void DrawLine(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
_oval = new OvalShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
_line.StyleId = _strokeStyleId;
_line.StartPoint.X = a.X;
_line.StartPoint.Y = a.Y;
_line.Point.X = b.X;
_line.Point.Y = b.Y;
_line.Draw(dc, renderer, dx, dy, scale, null, null);
}
Points = new ObservableCollection<IPointShape>(),
};
_oval.StartPoint.Owner = _oval;
_oval.Point.Owner = _oval;
internal void DrawLine(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
_rectangle = new RectangleShape(new PointShape(0, 0, null), new PointShape(0, 0, null))
{
_line.StyleId = _strokeStyleId;
_line.StartPoint.X = ax;
_line.StartPoint.Y = ay;
_line.Point.X = bx;
_line.Point.Y = by;
_line.Draw(dc, renderer, dx, dy, scale, null, null);
}
Points = new ObservableCollection<IPointShape>(),
};
_rectangle.StartPoint.Owner = _rectangle;
_rectangle.Point.Owner = _rectangle;
internal void FillOval(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
_text = new TextShape(new Text(), new PointShape(0, 0, null), new PointShape(0, 0, null))
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = s.X - radius;
_oval.StartPoint.Y = s.Y - radius;
_oval.Point.X = s.X + radius;
_oval.Point.Y = s.Y + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = sx - radius;
_oval.StartPoint.Y = sy - radius;
_oval.Point.X = sx + radius;
_oval.Point.Y = sy + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = s.X - radius;
_oval.StartPoint.Y = s.Y - radius;
_oval.Point.X = s.X + radius;
_oval.Point.Y = s.Y + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = sx - radius;
_oval.StartPoint.Y = sy - radius;
_oval.Point.X = sx + radius;
_oval.Point.Y = sy + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = a.X;
_oval.StartPoint.Y = a.Y;
_oval.Point.X = b.X;
_oval.Point.Y = b.Y;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = ax;
_oval.StartPoint.Y = ay;
_oval.Point.X = bx;
_oval.Point.Y = by;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = a.X;
_oval.StartPoint.Y = a.Y;
_oval.Point.X = b.X;
_oval.Point.Y = b.Y;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = ax;
_oval.StartPoint.Y = ay;
_oval.Point.X = bx;
_oval.Point.Y = by;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = s.X - radius;
_rectangle.StartPoint.Y = s.Y - radius;
_rectangle.Point.X = s.X + radius;
_rectangle.Point.Y = s.Y + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = sx - radius;
_rectangle.StartPoint.Y = sy - radius;
_rectangle.Point.X = sx + radius;
_rectangle.Point.Y = sy + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = s.X - radius;
_rectangle.StartPoint.Y = s.Y - radius;
_rectangle.Point.X = s.X + radius;
_rectangle.Point.Y = s.Y + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = sx - radius;
_rectangle.StartPoint.Y = sy - radius;
_rectangle.Point.X = sx + radius;
_rectangle.Point.Y = sy + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = a.X;
_rectangle.StartPoint.Y = a.Y;
_rectangle.Point.X = b.X;
_rectangle.Point.Y = b.Y;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = ax;
_rectangle.StartPoint.Y = ay;
_rectangle.Point.X = bx;
_rectangle.Point.Y = by;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = a.X;
_rectangle.StartPoint.Y = a.Y;
_rectangle.Point.X = b.X;
_rectangle.Point.Y = b.Y;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = ax;
_rectangle.StartPoint.Y = ay;
_rectangle.Point.X = bx;
_rectangle.Point.Y = by;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawText(object dc, IShapeRenderer renderer, string text, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_text.StyleId = _strokeStyleId;
_text.StartPoint.X = a.X;
_text.StartPoint.Y = a.Y;
_text.Point.X = b.X;
_text.Point.Y = b.Y;
_text.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawText(object dc, IShapeRenderer renderer, string text, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_text.StyleId = _strokeStyleId;
_text.StartPoint.X = ax;
_text.StartPoint.Y = ay;
_text.Point.X = bx;
_text.Point.Y = by;
_text.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawBoxFromPoints(object dc, IShapeRenderer renderer, IBaseShape shape, double dx, double dy, double scale)
{
var box = new Box(shape);
if (box.points.Count >= 2)
{
DrawRectangle(dc, renderer, box.ax, box.ay, box.bx, box.by, dx, dy, scale);
}
}
public abstract void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale);
Points = new ObservableCollection<IPointShape>(),
};
_text.StartPoint.Owner = _text;
_text.Point.Owner = _text;
}
}
internal void DrawLine(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_line.StyleId = _strokeStyleId;
_line.StartPoint.X = a.X;
_line.StartPoint.Y = a.Y;
_line.Point.X = b.X;
_line.Point.Y = b.Y;
_line.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawLine(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_line.StyleId = _strokeStyleId;
_line.StartPoint.X = ax;
_line.StartPoint.Y = ay;
_line.Point.X = bx;
_line.Point.Y = by;
_line.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = s.X - radius;
_oval.StartPoint.Y = s.Y - radius;
_oval.Point.X = s.X + radius;
_oval.Point.Y = s.Y + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = sx - radius;
_oval.StartPoint.Y = sy - radius;
_oval.Point.X = sx + radius;
_oval.Point.Y = sy + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = s.X - radius;
_oval.StartPoint.Y = s.Y - radius;
_oval.Point.X = s.X + radius;
_oval.Point.Y = s.Y + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = sx - radius;
_oval.StartPoint.Y = sy - radius;
_oval.Point.X = sx + radius;
_oval.Point.Y = sy + radius;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = a.X;
_oval.StartPoint.Y = a.Y;
_oval.Point.X = b.X;
_oval.Point.Y = b.Y;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillOval(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_oval.StyleId = _fillStyleId;
_oval.StartPoint.X = ax;
_oval.StartPoint.Y = ay;
_oval.Point.X = bx;
_oval.Point.Y = by;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = a.X;
_oval.StartPoint.Y = a.Y;
_oval.Point.X = b.X;
_oval.Point.Y = b.Y;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawOval(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_oval.StyleId = _strokeStyleId;
_oval.StartPoint.X = ax;
_oval.StartPoint.Y = ay;
_oval.Point.X = bx;
_oval.Point.Y = by;
_oval.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = s.X - radius;
_rectangle.StartPoint.Y = s.Y - radius;
_rectangle.Point.X = s.X + radius;
_rectangle.Point.Y = s.Y + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = sx - radius;
_rectangle.StartPoint.Y = sy - radius;
_rectangle.Point.X = sx + radius;
_rectangle.Point.Y = sy + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, IPointShape s, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = s.X - radius;
_rectangle.StartPoint.Y = s.Y - radius;
_rectangle.Point.X = s.X + radius;
_rectangle.Point.Y = s.Y + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, double sx, double sy, double radius, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = sx - radius;
_rectangle.StartPoint.Y = sy - radius;
_rectangle.Point.X = sx + radius;
_rectangle.Point.Y = sy + radius;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = a.X;
_rectangle.StartPoint.Y = a.Y;
_rectangle.Point.X = b.X;
_rectangle.Point.Y = b.Y;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void FillRectangle(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_rectangle.StyleId = _fillStyleId;
_rectangle.StartPoint.X = ax;
_rectangle.StartPoint.Y = ay;
_rectangle.Point.X = bx;
_rectangle.Point.Y = by;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = a.X;
_rectangle.StartPoint.Y = a.Y;
_rectangle.Point.X = b.X;
_rectangle.Point.Y = b.Y;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawRectangle(object dc, IShapeRenderer renderer, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_rectangle.StyleId = _strokeStyleId;
_rectangle.StartPoint.X = ax;
_rectangle.StartPoint.Y = ay;
_rectangle.Point.X = bx;
_rectangle.Point.Y = by;
_rectangle.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawText(object dc, IShapeRenderer renderer, string text, IPointShape a, IPointShape b, double dx, double dy, double scale)
{
_text.StyleId = _strokeStyleId;
_text.StartPoint.X = a.X;
_text.StartPoint.Y = a.Y;
_text.Point.X = b.X;
_text.Point.Y = b.Y;
_text.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawText(object dc, IShapeRenderer renderer, string text, double ax, double ay, double bx, double by, double dx, double dy, double scale)
{
_text.StyleId = _strokeStyleId;
_text.StartPoint.X = ax;
_text.StartPoint.Y = ay;
_text.Point.X = bx;
_text.Point.Y = by;
_text.Draw(dc, renderer, dx, dy, scale, null, null);
}
internal void DrawBoxFromPoints(object dc, IShapeRenderer renderer, IBaseShape shape, double dx, double dy, double scale)
{
var box = new Box(shape);
if (box.points.Count >= 2)
{
DrawRectangle(dc, renderer, box.ax, box.ay, box.bx, box.by, dx, dy, scale);
}
}
public abstract void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale);
}

Просмотреть файл

@ -1,24 +1,23 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class CubicBezierDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, CubicBezierShape cubicBezier, double dx, double dy, double scale)
{
DrawLine(dc, renderer, cubicBezier.StartPoint, cubicBezier.Point1, dx, dy, scale);
DrawLine(dc, renderer, cubicBezier.Point3, cubicBezier.Point2, dx, dy, scale);
DrawLine(dc, renderer, cubicBezier.Point1, cubicBezier.Point2, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class CubicBezierDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, CubicBezierShape cubicBezier, double dx, double dy, double scale)
{
DrawLine(dc, renderer, cubicBezier.StartPoint, cubicBezier.Point1, dx, dy, scale);
DrawLine(dc, renderer, cubicBezier.Point3, cubicBezier.Point2, dx, dy, scale);
DrawLine(dc, renderer, cubicBezier.Point1, cubicBezier.Point2, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is CubicBezierShape cubicBezier)
{
if (shape is CubicBezierShape cubicBezier)
{
Draw(dc, renderer, cubicBezier, dx, dy, scale);
}
Draw(dc, renderer, cubicBezier, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,75 +1,74 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
namespace Draw2D.ViewModels.Decorators;
[DataContract(IsReference = true)]
public class FigureDecorator : CommonDecorator
{
[DataContract(IsReference = true)]
public class FigureDecorator : CommonDecorator
private readonly LineDecorator _lineDecorator;
private readonly CubicBezierDecorator _cubiceBezierDecorator;
private readonly QuadraticBezierDecorator _quadraticBezierDecorator;
private readonly ConicDecorator _conicDecorator;
public FigureDecorator()
{
private readonly LineDecorator _lineDecorator;
private readonly CubicBezierDecorator _cubiceBezierDecorator;
private readonly QuadraticBezierDecorator _quadraticBezierDecorator;
private readonly ConicDecorator _conicDecorator;
_lineDecorator = new LineDecorator();
_cubiceBezierDecorator = new CubicBezierDecorator();
_quadraticBezierDecorator = new QuadraticBezierDecorator();
_conicDecorator = new ConicDecorator();
}
public FigureDecorator()
public void DrawShape(object dc, IShapeRenderer renderer, IBaseShape shape, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is LineShape line)
{
_lineDecorator = new LineDecorator();
_cubiceBezierDecorator = new CubicBezierDecorator();
_quadraticBezierDecorator = new QuadraticBezierDecorator();
_conicDecorator = new ConicDecorator();
}
public void DrawShape(object dc, IShapeRenderer renderer, IBaseShape shape, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is LineShape line)
if (selectionState.IsSelected(line))
{
if (selectionState.IsSelected(line))
{
_lineDecorator.Draw(dc, line, renderer, selectionState, dx, dy, scale);
}
}
else if (shape is CubicBezierShape cubicBezier)
{
if (selectionState.IsSelected(cubicBezier))
{
_cubiceBezierDecorator.Draw(dc, cubicBezier, renderer, selectionState, dx, dy, scale);
}
}
else if (shape is QuadraticBezierShape quadraticBezier)
{
if (selectionState.IsSelected(quadraticBezier))
{
_quadraticBezierDecorator.Draw(dc, quadraticBezier, renderer, selectionState, dx, dy, scale);
}
}
else if (shape is ConicShape conicShape)
{
if (selectionState.IsSelected(conicShape))
{
_conicDecorator.Draw(dc, conicShape, renderer, selectionState, dx, dy, scale);
}
_lineDecorator.Draw(dc, line, renderer, selectionState, dx, dy, scale);
}
}
public void DrawFigure(object dc, IShapeRenderer renderer, FigureShape figure, ISelectionState selectionState, double dx, double dy, double scale)
else if (shape is CubicBezierShape cubicBezier)
{
if (selectionState.IsSelected(figure))
if (selectionState.IsSelected(cubicBezier))
{
DrawBoxFromPoints(dc, renderer, figure, dx, dy, scale);
}
foreach (var shape in figure.Shapes)
{
DrawShape(dc, renderer, shape, selectionState, dx, dy, scale);
_cubiceBezierDecorator.Draw(dc, cubicBezier, renderer, selectionState, dx, dy, scale);
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
else if (shape is QuadraticBezierShape quadraticBezier)
{
if (shape is FigureShape figure)
if (selectionState.IsSelected(quadraticBezier))
{
DrawFigure(dc, renderer, figure, selectionState, dx, dy, scale);
_quadraticBezierDecorator.Draw(dc, quadraticBezier, renderer, selectionState, dx, dy, scale);
}
}
else if (shape is ConicShape conicShape)
{
if (selectionState.IsSelected(conicShape))
{
_conicDecorator.Draw(dc, conicShape, renderer, selectionState, dx, dy, scale);
}
}
}
}
public void DrawFigure(object dc, IShapeRenderer renderer, FigureShape figure, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(figure))
{
DrawBoxFromPoints(dc, renderer, figure, dx, dy, scale);
}
foreach (var shape in figure.Shapes)
{
DrawShape(dc, renderer, shape, selectionState, dx, dy, scale);
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is FigureShape figure)
{
DrawFigure(dc, renderer, figure, selectionState, dx, dy, scale);
}
}
}

Просмотреть файл

@ -1,25 +1,24 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class GroupDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, GroupShape group, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(group))
{
DrawBoxFromPoints(dc, renderer, group, dx, dy, scale);
}
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class GroupDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, GroupShape group, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(group))
{
if (shape is GroupShape group)
{
Draw(dc, renderer, group, selectionState, dx, dy, scale);
}
DrawBoxFromPoints(dc, renderer, group, dx, dy, scale);
}
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is GroupShape group)
{
Draw(dc, renderer, group, selectionState, dx, dy, scale);
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class ImageDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ImageShape imageShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, imageShape.StartPoint, imageShape.Point, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class ImageDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ImageShape imageShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, imageShape.StartPoint, imageShape.Point, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is ImageShape imageShape)
{
if (shape is ImageShape imageShape)
{
Draw(dc, renderer, imageShape, dx, dy, scale);
}
Draw(dc, renderer, imageShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class LineDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, LineShape lineShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, lineShape.StartPoint, lineShape.Point, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class LineDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, LineShape lineShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, lineShape.StartPoint, lineShape.Point, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is LineShape lineShape)
{
if (shape is LineShape lineShape)
{
Draw(dc, renderer, lineShape, dx, dy, scale);
}
Draw(dc, renderer, lineShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class OvalDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, OvalShape ovalShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, ovalShape.StartPoint, ovalShape.Point, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class OvalDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, OvalShape ovalShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, ovalShape.StartPoint, ovalShape.Point, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is OvalShape ovalShape)
{
if (shape is OvalShape ovalShape)
{
Draw(dc, renderer, ovalShape, dx, dy, scale);
}
Draw(dc, renderer, ovalShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,30 +1,29 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class PathDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, PathShape path, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(path))
{
DrawBoxFromPoints(dc, renderer, path, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
foreach (var shape in path.Shapes)
{
shape.Decorator?.Draw(dc, shape, renderer, selectionState, dx, dy, scale);
}
[DataContract(IsReference = true)]
public class PathDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, PathShape path, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(path))
{
DrawBoxFromPoints(dc, renderer, path, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
foreach (var shape in path.Shapes)
{
if (shape is PathShape path)
{
Draw(dc, renderer, path, selectionState, dx, dy, scale);
}
shape.Decorator?.Draw(dc, shape, renderer, selectionState, dx, dy, scale);
}
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is PathShape path)
{
Draw(dc, renderer, path, selectionState, dx, dy, scale);
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class PointDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, IPointShape pointShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, pointShape, 10, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
// TODO:
//if (shape is IPointShape pointShape)
//{
// Draw(dc, renderer, pointShape, dx, dy, scale);
//}
}
[DataContract(IsReference = true)]
public class PointDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, IPointShape pointShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, pointShape, 10, dx, dy, scale);
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
// TODO:
//if (shape is IPointShape pointShape)
//{
// Draw(dc, renderer, pointShape, dx, dy, scale);
//}
}
}

Просмотреть файл

@ -1,23 +1,22 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class QuadraticBezierDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, QuadraticBezierShape quadraticBezier, double dx, double dy, double scale)
{
DrawLine(dc, renderer, quadraticBezier.StartPoint, quadraticBezier.Point1, dx, dy, scale);
DrawLine(dc, renderer, quadraticBezier.Point1, quadraticBezier.Point2, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class QuadraticBezierDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, QuadraticBezierShape quadraticBezier, double dx, double dy, double scale)
{
DrawLine(dc, renderer, quadraticBezier.StartPoint, quadraticBezier.Point1, dx, dy, scale);
DrawLine(dc, renderer, quadraticBezier.Point1, quadraticBezier.Point2, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is QuadraticBezierShape quadraticBezier)
{
if (shape is QuadraticBezierShape quadraticBezier)
{
Draw(dc, renderer, quadraticBezier, dx, dy, scale);
}
Draw(dc, renderer, quadraticBezier, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class RectangleDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, RectangleShape rectangleShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, rectangleShape.StartPoint, rectangleShape.Point, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class RectangleDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, RectangleShape rectangleShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, rectangleShape.StartPoint, rectangleShape.Point, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is RectangleShape rectangleShape)
{
if (shape is RectangleShape rectangleShape)
{
Draw(dc, renderer, rectangleShape, dx, dy, scale);
}
Draw(dc, renderer, rectangleShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,25 +1,24 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class ReferenceDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ReferenceShape reference, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(reference) && reference.Template != null)
{
DrawBoxFromPoints(dc, renderer, reference.Template, dx + reference.X, dy + reference.Y, scale);
}
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class ReferenceDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, ReferenceShape reference, ISelectionState selectionState, double dx, double dy, double scale)
{
if (selectionState.IsSelected(reference) && reference.Template != null)
{
if (shape is ReferenceShape reference)
{
Draw(dc, renderer, reference, selectionState, dx, dy, scale);
}
DrawBoxFromPoints(dc, renderer, reference.Template, dx + reference.X, dy + reference.Y, scale);
}
}
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is ReferenceShape reference)
{
Draw(dc, renderer, reference, selectionState, dx, dy, scale);
}
}
}

Просмотреть файл

@ -1,22 +1,21 @@
using System.Runtime.Serialization;
using Draw2D.ViewModels.Shapes;
namespace Draw2D.ViewModels.Decorators
{
[DataContract(IsReference = true)]
public class TextDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, TextShape textShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, textShape.StartPoint, textShape.Point, dx, dy, scale);
}
namespace Draw2D.ViewModels.Decorators;
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
[DataContract(IsReference = true)]
public class TextDecorator : CommonDecorator
{
public void Draw(object dc, IShapeRenderer renderer, TextShape textShape, double dx, double dy, double scale)
{
DrawRectangle(dc, renderer, textShape.StartPoint, textShape.Point, dx, dy, scale);
}
public override void Draw(object dc, IBaseShape shape, IShapeRenderer renderer, ISelectionState selectionState, double dx, double dy, double scale)
{
if (shape is TextShape textShape)
{
if (shape is TextShape textShape)
{
Draw(dc, renderer, textShape, dx, dy, scale);
}
Draw(dc, renderer, textShape, dx, dy, scale);
}
}
}
}

Просмотреть файл

@ -1,9 +1,8 @@

namespace Draw2D.ViewModels
namespace Draw2D.ViewModels;
public enum EditMode
{
public enum EditMode
{
Touch,
Mouse
}
}
Touch,
Mouse
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -6,127 +6,126 @@ using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Shapes;
using Draw2D.ViewModels.Tools;
namespace Draw2D.Export
namespace Draw2D.Export;
public class AvaloniaXamlConverter : IAvaloniaXamlConverter
{
public class AvaloniaXamlConverter : IAvaloniaXamlConverter
internal static char[] NewLine = Environment.NewLine.ToCharArray();
public void ConvertToGeometryDrawing(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
internal static char[] NewLine = Environment.NewLine.ToCharArray();
public void ConvertToGeometryDrawing(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
if (containerView.SelectionState?.Shapes != null && containerView.SelectionState?.Shapes.Count > 0)
{
if (containerView.SelectionState?.Shapes != null && containerView.SelectionState?.Shapes.Count > 0)
var shapes = new List<IBaseShape>(containerView.SelectionState?.Shapes);
foreach (var shape in shapes)
{
var shapes = new List<IBaseShape>(containerView.SelectionState?.Shapes);
foreach (var shape in shapes)
if (shape is IPointShape || shape is FigureShape)
{
if (shape is IPointShape || shape is FigureShape)
{
continue;
}
continue;
}
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
continue;
}
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
continue;
}
var geometry = context.PathConverter?.ToSvgPathData(context, new[] { shape })?.TrimEnd(NewLine);
if (geometry == null)
{
continue;
}
var geometry = context.PathConverter?.ToSvgPathData(context, new[] { shape })?.TrimEnd(NewLine);
if (geometry == null)
{
continue;
}
var stroke = style.StrokePaint;
var fill = style.FillPaint;
var stroke = style.StrokePaint;
var fill = style.FillPaint;
if (style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Brush=\"{fill.Color.ToHex()}\" Geometry=\"{geometry}\">");
sb.AppendLine($"{indent} <GeometryDrawing.Pen>");
sb.AppendLine($"{indent} <Pen Brush=\"{stroke.Color.ToHex()}\" Thickness=\"{stroke.StrokeWidth}\" LineCap=\"{stroke.StrokeCap}\" LineJoin=\"{stroke.StrokeJoin}\" MiterLimit=\"{stroke.StrokeMiter}\"/>");
sb.AppendLine($"{indent} </GeometryDrawing.Pen>");
sb.AppendLine($"{indent}</GeometryDrawing>");
}
else if (style.IsStroked && !style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Geometry=\"{geometry}\">");
sb.AppendLine($"{indent} <GeometryDrawing.Pen>");
sb.AppendLine($"{indent} <Pen Brush=\"{stroke.Color.ToHex()}\" Thickness=\"{stroke.StrokeWidth}\" LineCap=\"{stroke.StrokeCap}\" LineJoin=\"{stroke.StrokeJoin}\" MiterLimit=\"{stroke.StrokeMiter}\"/>");
sb.AppendLine($"{indent} </GeometryDrawing.Pen>");
sb.AppendLine($"{indent}</GeometryDrawing>");
}
else if (!style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Brush=\"{fill.Color.ToHex()}\" Geometry=\"{geometry}\" />");
}
if (style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Brush=\"{fill.Color.ToHex()}\" Geometry=\"{geometry}\">");
sb.AppendLine($"{indent} <GeometryDrawing.Pen>");
sb.AppendLine($"{indent} <Pen Brush=\"{stroke.Color.ToHex()}\" Thickness=\"{stroke.StrokeWidth}\" LineCap=\"{stroke.StrokeCap}\" LineJoin=\"{stroke.StrokeJoin}\" MiterLimit=\"{stroke.StrokeMiter}\"/>");
sb.AppendLine($"{indent} </GeometryDrawing.Pen>");
sb.AppendLine($"{indent}</GeometryDrawing>");
}
else if (style.IsStroked && !style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Geometry=\"{geometry}\">");
sb.AppendLine($"{indent} <GeometryDrawing.Pen>");
sb.AppendLine($"{indent} <Pen Brush=\"{stroke.Color.ToHex()}\" Thickness=\"{stroke.StrokeWidth}\" LineCap=\"{stroke.StrokeCap}\" LineJoin=\"{stroke.StrokeJoin}\" MiterLimit=\"{stroke.StrokeMiter}\"/>");
sb.AppendLine($"{indent} </GeometryDrawing.Pen>");
sb.AppendLine($"{indent}</GeometryDrawing>");
}
else if (!style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<GeometryDrawing Brush=\"{fill.Color.ToHex()}\" Geometry=\"{geometry}\" />");
}
}
}
public void ConvertToDrawingGroup(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<DrawingGroup>");
ConvertToGeometryDrawing(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</DrawingGroup>");
}
public void ConvertToDrawingPresenter(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<DrawingPresenter Width=\"{containerView.Width}\" Height=\"{containerView.Height}\" Stretch=\"Uniform\">");
ConvertToDrawingGroup(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</DrawingPresenter>");
}
public void ConvertToPath(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
if (containerView.SelectionState?.Shapes != null && containerView.SelectionState?.Shapes.Count > 0)
{
var shapes = new List<IBaseShape>(containerView.SelectionState?.Shapes);
foreach (var shape in shapes)
{
if (shape is IPointShape || shape is FigureShape)
{
continue;
}
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
continue;
}
var geometry = context.PathConverter?.ToSvgPathData(context, new[] { shape })?.TrimEnd(NewLine);
if (geometry == null)
{
continue;
}
var stroke = style.StrokePaint;
var fill = style.FillPaint;
if (style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<Path Fill=\"{fill.Color.ToHex()}\" Stroke=\"{stroke.Color.ToHex()}\" StrokeThickness=\"{stroke.StrokeWidth}\" StrokeLineCap=\"{stroke.StrokeCap}\" StrokeJoin=\"{stroke.StrokeJoin}\" Data=\"{geometry}\"/>");
}
else if (style.IsStroked && !style.IsFilled)
{
sb.AppendLine($"{indent}<Path Stroke=\"{stroke.Color.ToHex()}\" StrokeThickness=\"{stroke.StrokeWidth}\" StrokeLineCap=\"{stroke.StrokeCap}\" StrokeJoin=\"{stroke.StrokeJoin}\" Data=\"{geometry}\"/>");
}
else if (!style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<Path Fill=\"{fill.Color.ToHex()}\" Data=\"{geometry}\"/>");
}
}
}
}
public void ConvertToCanvas(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<Canvas Width=\"{containerView.Width}\" Height=\"{containerView.Height}\">");
ConvertToPath(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</Canvas>");
}
}
}
public void ConvertToDrawingGroup(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<DrawingGroup>");
ConvertToGeometryDrawing(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</DrawingGroup>");
}
public void ConvertToDrawingPresenter(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<DrawingPresenter Width=\"{containerView.Width}\" Height=\"{containerView.Height}\" Stretch=\"Uniform\">");
ConvertToDrawingGroup(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</DrawingPresenter>");
}
public void ConvertToPath(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
if (containerView.SelectionState?.Shapes != null && containerView.SelectionState?.Shapes.Count > 0)
{
var shapes = new List<IBaseShape>(containerView.SelectionState?.Shapes);
foreach (var shape in shapes)
{
if (shape is IPointShape || shape is FigureShape)
{
continue;
}
var style = context.DocumentContainer?.StyleLibrary?.Get(shape.StyleId);
if (style == null)
{
continue;
}
var geometry = context.PathConverter?.ToSvgPathData(context, new[] { shape })?.TrimEnd(NewLine);
if (geometry == null)
{
continue;
}
var stroke = style.StrokePaint;
var fill = style.FillPaint;
if (style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<Path Fill=\"{fill.Color.ToHex()}\" Stroke=\"{stroke.Color.ToHex()}\" StrokeThickness=\"{stroke.StrokeWidth}\" StrokeLineCap=\"{stroke.StrokeCap}\" StrokeJoin=\"{stroke.StrokeJoin}\" Data=\"{geometry}\"/>");
}
else if (style.IsStroked && !style.IsFilled)
{
sb.AppendLine($"{indent}<Path Stroke=\"{stroke.Color.ToHex()}\" StrokeThickness=\"{stroke.StrokeWidth}\" StrokeLineCap=\"{stroke.StrokeCap}\" StrokeJoin=\"{stroke.StrokeJoin}\" Data=\"{geometry}\"/>");
}
else if (!style.IsStroked && style.IsFilled)
{
sb.AppendLine($"{indent}<Path Fill=\"{fill.Color.ToHex()}\" Data=\"{geometry}\"/>");
}
}
}
}
public void ConvertToCanvas(IToolContext context, IContainerView containerView, StringBuilder sb, string indent)
{
sb.AppendLine($"{indent}<Canvas Width=\"{containerView.Width}\" Height=\"{containerView.Height}\">");
ConvertToPath(context, containerView, sb, indent + " ");
sb.AppendLine($"{indent}</Canvas>");
}
}

Просмотреть файл

@ -2,47 +2,46 @@
using Draw2D.ViewModels.Containers;
using Draw2D.ViewModels.Tools;
namespace Draw2D.Editor
namespace Draw2D.Editor;
public interface IEditorToolContext : IToolContext
{
public interface IEditorToolContext : IToolContext
{
IContainerFactory ContainerFactory { get; set; }
IAvaloniaXamlConverter AvaloniaXamlConverter { get; set; }
IContainerImporter ContainerImporter { get; set; }
IContainerExporter ContainerExporter { get; set; }
ISvgConverter SvgConverter { get; set; }
ISelection Selection { get; set; }
string CurrentDirectory { get; set; }
IList<string> Files { get; set; }
void InitContainerView(IContainerView containerView);
void AddContainerView(IContainerView containerView);
void CloseContainerView(IContainerView containerView);
void NewContainerView(string title);
void OpenDocument(string path);
void SaveDocument(string path);
void OpenStyles(string path);
void SaveStyles(string path);
void OpenGroups(string path);
void SaveGroups(string path);
void OpenDocumentContainer();
void SaveDocumentContainerAs();
void OpenStyleLibrary();
void SaveStyleLibraryAs();
void OpenGroupLibrary();
void SaveGroupLibraryAs();
void AddFiles(string path);
void ClearFiles();
void ImportFile();
void ExportFile();
void CopySvgDocument();
void CopySvgPathData();
void PasteSvgPathData();
void CopyGeometryDrawing();
void CopyDrawingGroup();
void CopyDrawingPresenter();
void CopyPath();
void CopyCanvas();
void PathOp(string parameter);
void Exit();
}
}
IContainerFactory ContainerFactory { get; set; }
IAvaloniaXamlConverter AvaloniaXamlConverter { get; set; }
IContainerImporter ContainerImporter { get; set; }
IContainerExporter ContainerExporter { get; set; }
ISvgConverter SvgConverter { get; set; }
ISelection Selection { get; set; }
string CurrentDirectory { get; set; }
IList<string> Files { get; set; }
void InitContainerView(IContainerView containerView);
void AddContainerView(IContainerView containerView);
void CloseContainerView(IContainerView containerView);
void NewContainerView(string title);
void OpenDocument(string path);
void SaveDocument(string path);
void OpenStyles(string path);
void SaveStyles(string path);
void OpenGroups(string path);
void SaveGroups(string path);
void OpenDocumentContainer();
void SaveDocumentContainerAs();
void OpenStyleLibrary();
void SaveStyleLibraryAs();
void OpenGroupLibrary();
void SaveGroupLibraryAs();
void AddFiles(string path);
void ClearFiles();
void ImportFile();
void ExportFile();
void CopySvgDocument();
void CopySvgPathData();
void PasteSvgPathData();
void CopyGeometryDrawing();
void CopyDrawingGroup();
void CopyDrawingPresenter();
void CopyPath();
void CopyCanvas();
void PathOp(string parameter);
void Exit();
}

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше