Update
This commit is contained in:
Родитель
6381d49021
Коммит
a98177e2b7
|
@ -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();
|
||||
}
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче