Update canvas
This commit is contained in:
Родитель
996684464f
Коммит
43b7376466
|
@ -0,0 +1,111 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace VectorPaint.Controls;
|
||||
|
||||
public sealed class GridLines : Control
|
||||
{
|
||||
public static readonly StyledProperty<int> CellWidthProperty =
|
||||
AvaloniaProperty.Register<GridLines, int>(nameof(CellWidth), 10);
|
||||
|
||||
public static readonly StyledProperty<int> CellHeightProperty =
|
||||
AvaloniaProperty.Register<GridLines, int>(nameof(CellHeight), 10);
|
||||
|
||||
public static readonly StyledProperty<int> BoldSeparatorHorizontalSpacingProperty =
|
||||
AvaloniaProperty.Register<GridLines, int>(nameof(BoldSeparatorHorizontalSpacing), 10);
|
||||
|
||||
public static readonly StyledProperty<int> BoldSeparatorVerticalSpacingProperty =
|
||||
AvaloniaProperty.Register<GridLines, int>(nameof(BoldSeparatorVerticalSpacing), 10);
|
||||
|
||||
public static readonly StyledProperty<bool> IsGridEnabledProperty =
|
||||
AvaloniaProperty.Register<GridLines, bool>(nameof(IsGridEnabled), true);
|
||||
|
||||
private readonly Pen _pen;
|
||||
private readonly Pen _penBold;
|
||||
|
||||
public int CellWidth
|
||||
{
|
||||
get => GetValue(CellWidthProperty);
|
||||
set => SetValue(CellWidthProperty, value);
|
||||
}
|
||||
|
||||
public int CellHeight
|
||||
{
|
||||
get => GetValue(CellHeightProperty);
|
||||
set => SetValue(CellHeightProperty, value);
|
||||
}
|
||||
|
||||
public int BoldSeparatorHorizontalSpacing
|
||||
{
|
||||
get => GetValue(BoldSeparatorHorizontalSpacingProperty);
|
||||
set => SetValue(BoldSeparatorHorizontalSpacingProperty, value);
|
||||
}
|
||||
|
||||
public int BoldSeparatorVerticalSpacing
|
||||
{
|
||||
get => GetValue(BoldSeparatorVerticalSpacingProperty);
|
||||
set => SetValue(BoldSeparatorVerticalSpacingProperty, value);
|
||||
}
|
||||
|
||||
public bool IsGridEnabled
|
||||
{
|
||||
get => GetValue(IsGridEnabledProperty);
|
||||
set => SetValue(IsGridEnabledProperty, value);
|
||||
}
|
||||
|
||||
public GridLines()
|
||||
{
|
||||
_pen = new Pen(new SolidColorBrush(Color.FromArgb((byte)(255.0 * 0.1), 14, 94, 253)));
|
||||
_penBold = new Pen(new SolidColorBrush(Color.FromArgb((byte)(255.0 * 0.3), 14, 94, 253)));
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == CellWidthProperty
|
||||
|| change.Property == CellHeightProperty
|
||||
|| change.Property == BoldSeparatorHorizontalSpacingProperty
|
||||
|| change.Property == BoldSeparatorVerticalSpacingProperty
|
||||
|| change.Property == IsGridEnabledProperty)
|
||||
{
|
||||
InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
|
||||
if (!IsGridEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var cellWidth = CellWidth;
|
||||
var cellHeight = CellHeight;
|
||||
var boldSeparatorHorizontalSpacing = BoldSeparatorHorizontalSpacing;
|
||||
var boldSeparatorVerticalSpacing = BoldSeparatorVerticalSpacing;
|
||||
var width = Bounds.Width;
|
||||
var height = Bounds.Height;
|
||||
|
||||
for(var i = 1; i < height / cellHeight; i++)
|
||||
{
|
||||
var pen = i % boldSeparatorVerticalSpacing == 0 ? _penBold : _pen;
|
||||
context.DrawLine(
|
||||
pen,
|
||||
new Point(0 + 0.5, i * cellHeight + 0.5),
|
||||
new Point(width + 0.5, i * cellHeight + 0.5));
|
||||
}
|
||||
|
||||
for (var i = 1; i < width / cellWidth; i++)
|
||||
{
|
||||
var pen = i % boldSeparatorHorizontalSpacing == 0 ? _penBold : _pen;
|
||||
context.DrawLine(
|
||||
pen,
|
||||
new Point(i * cellWidth + 0.5, 0 + 0.5),
|
||||
new Point(i * cellWidth + 0.5, height + 0.5));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -72,7 +72,8 @@ public class Drawing : ReactiveObject, IDrawing
|
|||
|
||||
public void Draw(DrawingContext context, Rect bounds)
|
||||
{
|
||||
context.DrawRectangle(Brushes.WhiteSmoke, null, bounds);
|
||||
// context.DrawRectangle(Brushes.WhiteSmoke, null, bounds);
|
||||
context.DrawRectangle(Brushes.Transparent, null, bounds);
|
||||
|
||||
if (_drawables is { })
|
||||
{
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
using Avalonia;
|
||||
|
||||
namespace VectorPaint.ViewModels.Core;
|
||||
|
||||
public static class SnapHelper
|
||||
{
|
||||
public static double SnapValue(double value, double snap)
|
||||
{
|
||||
if (snap == 0.0)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
var c = value % snap;
|
||||
var r = c >= snap / 2.0 ? value + snap - c : value - c;
|
||||
return r;
|
||||
}
|
||||
|
||||
public static Point SnapPoint(Point point, double snapX = 5, double snapY = 5, bool enabled = true)
|
||||
{
|
||||
if (enabled)
|
||||
{
|
||||
var pointX = SnapValue(point.X, snapX);
|
||||
var pointY = SnapValue(point.Y, snapY);
|
||||
return new Point(pointX, pointY);
|
||||
}
|
||||
|
||||
return point;
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia.Input;
|
||||
using VectorPaint.ViewModels.Core;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
@ -17,6 +18,8 @@ public class EllipseTool : Tool
|
|||
}
|
||||
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_ellipse = new EllipseDrawable()
|
||||
{
|
||||
|
@ -57,6 +60,8 @@ public class EllipseTool : Tool
|
|||
if (_ellipse?.BottomRight is { })
|
||||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_ellipse.BottomRight.X = point.X;
|
||||
_ellipse.BottomRight.Y = point.Y;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia.Input;
|
||||
using VectorPaint.ViewModels.Core;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
@ -18,6 +19,8 @@ public class LineTool : Tool
|
|||
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_line = new LineDrawable()
|
||||
{
|
||||
Fill = null,
|
||||
|
@ -57,7 +60,9 @@ public class LineTool : Tool
|
|||
if (_line?.End is { })
|
||||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_line.End.X = point.X;
|
||||
_line.End.Y = point.Y;
|
||||
_line.Invalidate();
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia.Input;
|
||||
using VectorPaint.ViewModels.Core;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
@ -17,6 +18,8 @@ public class RectangleTool : Tool
|
|||
}
|
||||
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_rectangle = new RectangleDrawable()
|
||||
{
|
||||
|
@ -58,6 +61,8 @@ public class RectangleTool : Tool
|
|||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
_rectangle.BottomRight.X = point.X;
|
||||
_rectangle.BottomRight.Y = point.Y;
|
||||
_rectangle.Invalidate();
|
||||
|
|
|
@ -4,6 +4,7 @@ using Avalonia;
|
|||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Immutable;
|
||||
using VectorPaint.ViewModels.Core;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
@ -79,7 +80,7 @@ public class SelectionTool : Tool
|
|||
if (!_moving)
|
||||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
|
||||
var rect = new Rect(_start, point);
|
||||
|
||||
var selected = drawing.HitTest(rect).ToList();
|
||||
|
@ -110,13 +111,15 @@ public class SelectionTool : Tool
|
|||
}
|
||||
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
|
||||
if (_moving)
|
||||
{
|
||||
if (_selected.Count > 0)
|
||||
{
|
||||
foreach (var drawable in _selected)
|
||||
{
|
||||
point = SnapHelper.SnapPoint(point);
|
||||
|
||||
drawable.Move(point - _start);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,8 @@ public class MainWindowViewModel : ViewModelBase
|
|||
{
|
||||
Drawing = new Drawing
|
||||
{
|
||||
DefaultFill = new ImmutableSolidColorBrush(Colors.Yellow),
|
||||
DefaultStroke = new ImmutablePen(new ImmutableSolidColorBrush(Colors.Red), 2, null, PenLineCap.Round),
|
||||
DefaultFill = new ImmutableSolidColorBrush(Colors.Transparent),
|
||||
DefaultStroke = new ImmutablePen(new ImmutableSolidColorBrush(Colors.Black), 10, null, PenLineCap.Round),
|
||||
Drawables = new ObservableCollection<Drawable>(),
|
||||
OverlayDrawables = new ObservableCollection<Drawable>()
|
||||
};
|
||||
|
@ -37,7 +37,7 @@ public class MainWindowViewModel : ViewModelBase
|
|||
|
||||
Editor.CurrentTool = Editor.Tools[0];
|
||||
|
||||
Demo(Drawing);
|
||||
// Demo(Drawing);
|
||||
}
|
||||
|
||||
private void Demo(IDrawing drawing)
|
||||
|
|
|
@ -30,12 +30,24 @@
|
|||
<Button Content="NonZero" Command="{Binding GroupNonZeroCommand}" />
|
||||
</DockPanel>
|
||||
|
||||
<c:VectorCanvas Name="VectorCanvas"
|
||||
Drawing="{Binding Drawing}"
|
||||
Tools="{Binding Editor.Tools}"
|
||||
CurrentTool="{Binding Editor.CurrentTool}"
|
||||
ClipToBounds="True" />
|
||||
|
||||
<Border BoxShadow="4 11 30 1 #3F000000"
|
||||
Background="White"
|
||||
Width="600"
|
||||
Height="600"
|
||||
ZIndex="-1">
|
||||
<Panel>
|
||||
<c:GridLines CellWidth="10"
|
||||
CellHeight="10"
|
||||
BoldSeparatorHorizontalSpacing="10"
|
||||
BoldSeparatorVerticalSpacing="10"
|
||||
IsGridEnabled="True" />
|
||||
<c:VectorCanvas Name="VectorCanvas"
|
||||
Drawing="{Binding Drawing}"
|
||||
Tools="{Binding Editor.Tools}"
|
||||
CurrentTool="{Binding Editor.CurrentTool}"
|
||||
ClipToBounds="True" />
|
||||
</Panel>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
|
||||
</UserControl>
|
||||
|
|
|
@ -8,6 +8,6 @@
|
|||
Icon="/Assets/avalonia-logo.ico"
|
||||
Title="VectorPaint"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Width="800" Height="600">
|
||||
Width="1000" Height="800">
|
||||
<views:MainView />
|
||||
</Window>
|
||||
|
|
Загрузка…
Ссылка в новой задаче