Add tools
This commit is contained in:
Родитель
493bce219c
Коммит
029fc5ab82
|
@ -1,65 +1,43 @@
|
|||
using Avalonia;
|
||||
using System.Collections.ObjectModel;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using VectorPaint.ViewModels;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
using VectorPaint.ViewModels.Tools;
|
||||
|
||||
namespace VectorPaint.Controls;
|
||||
|
||||
public class VectorCanvas : Control
|
||||
{
|
||||
private Drawable? _drawable;
|
||||
private Point _start;
|
||||
public ObservableCollection<Tool> Tools { get; set; }
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
public Tool? CurrentTool { get; set; }
|
||||
|
||||
public VectorCanvas()
|
||||
{
|
||||
if (DataContext is MainWindowViewModel mainWindowViewModel)
|
||||
Tools = new ObservableCollection<Tool>()
|
||||
{
|
||||
context.DrawRectangle(Brushes.WhiteSmoke, null, Bounds);
|
||||
new SelectionTool()
|
||||
};
|
||||
|
||||
foreach (var drawable in mainWindowViewModel.Drawables)
|
||||
{
|
||||
drawable.Draw(context);
|
||||
}
|
||||
}
|
||||
|
||||
base.Render(context);
|
||||
CurrentTool = Tools[0];
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
if (DataContext is MainWindowViewModel mainWindowViewModel)
|
||||
if (DataContext is IDrawing drawing)
|
||||
{
|
||||
var point = e.GetCurrentPoint(this).Position;
|
||||
|
||||
_start = point;
|
||||
|
||||
foreach (var drawable in mainWindowViewModel.Drawables)
|
||||
{
|
||||
var contains = drawable.HitTest(point);
|
||||
if (contains)
|
||||
{
|
||||
_drawable = drawable;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (_drawable is { })
|
||||
{
|
||||
e.Pointer.Capture(this);
|
||||
}
|
||||
CurrentTool?.OnPointerPressed(drawing, e);
|
||||
}
|
||||
|
||||
|
||||
base.OnPointerPressed(e);
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
if (_drawable is { })
|
||||
if (DataContext is IDrawing drawing)
|
||||
{
|
||||
e.Pointer.Capture(null);
|
||||
_drawable = null;
|
||||
CurrentTool?.OnPointerReleased(drawing, e);
|
||||
}
|
||||
|
||||
base.OnPointerReleased(e);
|
||||
|
@ -67,17 +45,21 @@ public class VectorCanvas : Control
|
|||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
if (_drawable is { })
|
||||
if (DataContext is IDrawing drawing)
|
||||
{
|
||||
var point = e.GetCurrentPoint(this).Position;
|
||||
|
||||
_drawable.Move(point - _start);
|
||||
|
||||
_start = point;
|
||||
|
||||
InvalidateVisual();
|
||||
CurrentTool?.OnPointerMoved(drawing, e);
|
||||
}
|
||||
|
||||
base.OnPointerMoved(e);
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
if (DataContext is IDrawing drawing)
|
||||
{
|
||||
drawing.Draw(context, Bounds);
|
||||
}
|
||||
|
||||
base.Render(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -49,7 +49,7 @@ public class RectangleDrawable : GeometryDrawable
|
|||
new Point(_topLeft.X, _topLeft.Y),
|
||||
new Point(_bottomRight.X, _bottomRight.Y));
|
||||
}
|
||||
|
||||
|
||||
protected sealed override Geometry? CreateGeometry()
|
||||
{
|
||||
if (_topLeft is null || _bottomRight is null)
|
||||
|
|
|
@ -1,21 +1,37 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using Avalonia;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.VisualTree;
|
||||
using ReactiveUI;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels;
|
||||
|
||||
public class MainWindowViewModel : ViewModelBase
|
||||
public interface IDrawing
|
||||
{
|
||||
public ObservableCollection<Drawable> _drawables;
|
||||
|
||||
ObservableCollection<Drawable> Drawables { get; set; }
|
||||
Drawable? HitTest(Point point);
|
||||
void Draw(DrawingContext context, Rect bounds);
|
||||
void Invalidate();
|
||||
IVisual? Canvas { get; set; }
|
||||
IInputElement? Input { get; set; }
|
||||
}
|
||||
|
||||
public class MainWindowViewModel : ViewModelBase, IDrawing
|
||||
{
|
||||
private ObservableCollection<Drawable> _drawables;
|
||||
|
||||
public ObservableCollection<Drawable> Drawables
|
||||
{
|
||||
get => _drawables;
|
||||
set => this.RaiseAndSetIfChanged(ref _drawables, value);
|
||||
}
|
||||
|
||||
|
||||
public IVisual? Canvas { get; set; }
|
||||
|
||||
public IInputElement? Input { get; set; }
|
||||
|
||||
public MainWindowViewModel()
|
||||
{
|
||||
_drawables = new ObservableCollection<Drawable>();
|
||||
|
@ -27,6 +43,13 @@ public class MainWindowViewModel : ViewModelBase
|
|||
};
|
||||
_drawables.Add(line0);
|
||||
|
||||
var ellipse0 = new EllipseDrawable()
|
||||
{
|
||||
TopLeft = new PointDrawable(30, 210),
|
||||
BottomRight = new PointDrawable(90, 270)
|
||||
};
|
||||
_drawables.Add(ellipse0);
|
||||
|
||||
var rect0 = new RectangleDrawable()
|
||||
{
|
||||
TopLeft = new PointDrawable(210, 30),
|
||||
|
@ -56,11 +79,32 @@ public class MainWindowViewModel : ViewModelBase
|
|||
}
|
||||
}
|
||||
|
||||
public void Draw(DrawingContext context)
|
||||
public Drawable? HitTest(Point point)
|
||||
{
|
||||
for (var i = _drawables.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var drawable = _drawables[i];
|
||||
if (drawable.HitTest(point))
|
||||
{
|
||||
return drawable;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void Draw(DrawingContext context, Rect bounds)
|
||||
{
|
||||
context.DrawRectangle(Brushes.WhiteSmoke, null, bounds);
|
||||
|
||||
foreach (var drawable in _drawables)
|
||||
{
|
||||
drawable.Draw(context);
|
||||
}
|
||||
}
|
||||
|
||||
public void Invalidate()
|
||||
{
|
||||
Canvas?.InvalidateVisual();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Input;
|
||||
using VectorPaint.ViewModels.Drawables;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
||||
public class SelectionTool : Tool
|
||||
{
|
||||
private Drawable? _drawable;
|
||||
private Point _start;
|
||||
|
||||
public override void OnPointerPressed(IDrawing drawing, PointerPressedEventArgs e)
|
||||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
var drawable = drawing.HitTest(point);
|
||||
if (drawable is { })
|
||||
{
|
||||
_drawable = drawable;
|
||||
_start = point;
|
||||
e.Pointer.Capture(drawing.Input);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerReleased(IDrawing drawing, PointerReleasedEventArgs e)
|
||||
{
|
||||
if (_drawable is { })
|
||||
{
|
||||
e.Pointer.Capture(null);
|
||||
_drawable = null;
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnPointerMoved(IDrawing drawing, PointerEventArgs e)
|
||||
{
|
||||
if (_drawable is { })
|
||||
{
|
||||
var point = e.GetCurrentPoint(drawing.Input).Position;
|
||||
|
||||
_drawable.Move(point - _start);
|
||||
_start = point;
|
||||
|
||||
drawing.Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
using Avalonia.Input;
|
||||
|
||||
namespace VectorPaint.ViewModels.Tools;
|
||||
|
||||
public abstract class Tool
|
||||
{
|
||||
public abstract void OnPointerPressed(IDrawing drawing, PointerPressedEventArgs e);
|
||||
|
||||
public abstract void OnPointerReleased(IDrawing drawing, PointerReleasedEventArgs e);
|
||||
|
||||
public abstract void OnPointerMoved(IDrawing drawing, PointerEventArgs e);
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
<vm:MainWindowViewModel />
|
||||
</Design.DataContext>
|
||||
|
||||
<c:VectorCanvas />
|
||||
<c:VectorCanvas Name="VectorCanvas" />
|
||||
|
||||
</UserControl>
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using VectorPaint.Controls;
|
||||
using VectorPaint.ViewModels;
|
||||
|
||||
namespace VectorPaint.Views;
|
||||
|
||||
|
@ -14,5 +17,20 @@ public class MainView : UserControl
|
|||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (DataContext is IDrawing drawing)
|
||||
{
|
||||
var vectorCanvas = this.FindControl<VectorCanvas>("VectorCanvas");
|
||||
if (vectorCanvas is { })
|
||||
{
|
||||
drawing.Canvas = vectorCanvas;
|
||||
drawing.Input = vectorCanvas;
|
||||
}
|
||||
}
|
||||
|
||||
base.OnAttachedToVisualTree(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче