Skip to content

Commit 1789ba1

Browse files
Selection reimplementation (#253)
* Flyout menu for selecting/deselecting * Selection Button * BaseSelection as BaseTool parameter * Tools respects selection * Selection button visibility condition changed
1 parent 0d75d91 commit 1789ba1

22 files changed

+224
-83
lines changed

Pixed.Application/Controls/ExtendedControl.cs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ public ExtendedControl()
1818
{
1919
_menuItemRegistry = Provider.Get<IMenuItemRegistry>();
2020
var serviceProvider = this.GetServiceProvider();
21-
this.DataContext = serviceProvider.Get<T>();
21+
22+
var viewModel = serviceProvider.Get<T>();
23+
24+
if(viewModel is ExtendedViewModel extended)
25+
{
26+
extended.Initialize(this);
27+
}
28+
29+
this.DataContext = viewModel;
2230
}
2331

2432
public TResult Get<TResult>()

Pixed.Application/Controls/ExtendedViewModel.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
using Pixed.Common.DependencyInjection;
1+
using Avalonia.Controls;
2+
using Pixed.Common.DependencyInjection;
23
using Pixed.Core;
34

45
namespace Pixed.Application.Controls;
56
internal abstract class ExtendedViewModel : PropertyChangedBase
67
{
8+
public Control? View { get; private set; }
79
public IPixedServiceProvider Provider => App.ServiceProvider;
810
public virtual void RegisterMenuItems()
911
{
@@ -14,4 +16,9 @@ public virtual void OnLoaded()
1416
{
1517

1618
}
19+
20+
public void Initialize(Control view)
21+
{
22+
View = view;
23+
}
1724
}

Pixed.Application/Controls/ExtendedWindow.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ public ExtendedWindow()
1818
{
1919
_menuItemRegistry = Provider.Get<IMenuItemRegistry>();
2020
var serviceProvider = this.GetServiceProvider();
21-
this.DataContext = serviceProvider.Get<T>();
21+
var viewModel = serviceProvider.Get<T>();
22+
23+
if (viewModel is ExtendedViewModel extended)
24+
{
25+
extended.Initialize(this);
26+
}
27+
28+
this.DataContext = viewModel;
2229
Unloaded += PixedWindow_Unloaded;
2330
Loaded += PixedWindow_Loaded;
2431
}

Pixed.Application/Controls/PaintCanvas.axaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
</Border>
3434
</Border>
3535
</ScrollViewer>
36+
<Button Width="32" Height="32" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0 2 0 0" Theme="{StaticResource FlyingButton}" IsVisible="{Binding IsSelectionButtonVisible}" Command="{Binding OpenSelectionMenu}" CommandParameter="{Binding $self}">
37+
<Image Source="{SvgImage avares://Pixed.Application/Resources/fluent-icons/ic_fluent_square_hint_48_regular.svg}" Width="16" Height="16"/>
38+
</Button>
3639
<Button Width="32" Height="64" HorizontalAlignment="Left" VerticalAlignment="Center" Theme="{StaticResource FlyingButton}" IsVisible="{Binding !IsFramesViewButtonVisible}" Command="{Binding OpenFramesView}">
3740
<Image Source="{SvgImage avares://Pixed.Application/Resources/fluent-icons/ic_fluent_panel_left_expand_28_regular.svg}" Width="16" Height="16"/>
3841
</Button>

Pixed.Application/Controls/PixedPage.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,14 @@ public PixedPage()
1818
{
1919
_menuItemRegistry = Provider.Get<IMenuItemRegistry>();
2020
var serviceProvider = this.GetServiceProvider();
21-
this.DataContext = serviceProvider.Get<T>();
21+
var viewModel = serviceProvider.Get<T>();
22+
23+
if (viewModel is ExtendedViewModel extended)
24+
{
25+
extended.Initialize(this);
26+
}
27+
28+
this.DataContext = viewModel;
2229
Unloaded += PixedPage_Unloaded;
2330
Loaded += PixedPage_Loaded;
2431
}

Pixed.Application/DependencyInjection/ApplicationDependencyRegister.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,5 +43,6 @@ public void Register(ref IServiceCollection collection)
4343
collection.AddSingleton<IClipboardHandle, ClipboardHandle>();
4444
collection.AddSingleton<IStorageProviderHandle, StorageProviderHandle>();
4545
collection.AddSingleton<DialogUtils>();
46+
collection.AddSingleton<SelectionMenu>();
4647
}
4748
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using Avalonia.Controls;
2+
using Pixed.Common.Tools;
3+
using Pixed.Core;
4+
5+
namespace Pixed.Application.Menu;
6+
7+
public class SelectionMenu(SelectionManager selectionManager)
8+
{
9+
private readonly SelectionManager _selectionManager = selectionManager;
10+
public MenuFlyout GetMenu()
11+
{
12+
return new MenuFlyout()
13+
{
14+
Items =
15+
{
16+
new Avalonia.Controls.MenuItem(){ Header = "Select All", Command = new ActionCommand(SelectAllAction)},
17+
new Avalonia.Controls.MenuItem(){ Header = "Deselect", Command = new ActionCommand(DeselectAction) }
18+
}
19+
};
20+
}
21+
22+
private void DeselectAction()
23+
{
24+
_selectionManager.Clear();
25+
}
26+
27+
private void SelectAllAction()
28+
{
29+
_selectionManager.SelectAll();
30+
}
31+
}

Pixed.Application/ViewModels/PaintCanvasViewModel.cs

Lines changed: 48 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
1-
using Avalonia.Media;
1+
using Avalonia.Controls;
2+
using Avalonia.Media;
23
using Avalonia.Platform;
34
using Pixed.Application.Controls;
45
using Pixed.Application.Input;
6+
using Pixed.Application.Menu;
57
using Pixed.Application.Models;
68
using Pixed.Application.Zoom;
79
using Pixed.Common;
810
using Pixed.Common.Services.Keyboard;
911
using Pixed.Common.Tools;
12+
using Pixed.Common.Tools.Selection;
1013
using Pixed.Core;
1114
using Pixed.Core.Models;
1215
using Pixed.Core.Utils;
@@ -21,6 +24,8 @@ internal class PaintCanvasViewModel : ExtendedViewModel, IDisposable
2124
{
2225
private readonly ApplicationData _applicationData;
2326
private readonly ToolsManager _toolSelector;
27+
private readonly SelectionMenu _selectionMenu;
28+
private readonly SelectionManager _selectionManager;
2429
private RenderModel _renderModel;
2530
private SKBitmap? _overlay;
2631
private ImageBrush _transparentBrush;
@@ -43,6 +48,7 @@ internal class PaintCanvasViewModel : ExtendedViewModel, IDisposable
4348
private double _zoomValue = 1;
4449
private bool _isFramesViewButtonVisible;
4550
private bool _isPropertiesViewButtonVisible;
51+
private bool _isSelectionButtonVisible = false;
4652

4753
private readonly IDisposable _projectModified;
4854
private readonly IDisposable _projectChanged;
@@ -81,6 +87,7 @@ internal class PaintCanvasViewModel : ExtendedViewModel, IDisposable
8187
public ActionCommand CloseFramesView { get; }
8288
public ActionCommand OpenPropertiesView { get; }
8389
public ActionCommand ClosePropertiesView { get; }
90+
public ActionCommand<Control> OpenSelectionMenu { get; }
8491

8592
public int ToolSize
8693
{
@@ -169,6 +176,16 @@ public double ZoomValue
169176
OnPropertyChanged(nameof(ScaledGridHeight));
170177
}
171178
}
179+
180+
public bool IsSelectionButtonVisible
181+
{
182+
get => _isSelectionButtonVisible;
183+
set
184+
{
185+
_isSelectionButtonVisible = value;
186+
OnPropertyChanged();
187+
}
188+
}
172189
public double ZoomOffsetX { get; set; }
173190
public double ZoomOffsetY { get; set; }
174191

@@ -217,10 +234,13 @@ public bool IsPropertiesViewButtonVisible
217234
}
218235
}
219236

220-
public PaintCanvasViewModel(ApplicationData applicationData, ToolsManager toolSelector, ToolMoveCanvas toolMoveCanvas, SelectionManager selectionManager, FramesSectionViewModel framesSectionViewModel, PropertiesSectionViewModel propertiesSectionViewModel)
237+
public PaintCanvasViewModel(ApplicationData applicationData, ToolsManager toolSelector, ToolMoveCanvas toolMoveCanvas, SelectionManager selectionManager,
238+
FramesSectionViewModel framesSectionViewModel, PropertiesSectionViewModel propertiesSectionViewModel, SelectionMenu selectionMenu)
221239
{
222240
_applicationData = applicationData;
223241
_toolSelector = toolSelector;
242+
_selectionMenu = selectionMenu;
243+
_selectionManager = selectionManager;
224244
_frame = new Frame(32, 32);
225245
_renderModel = new RenderModel
226246
{
@@ -329,6 +349,8 @@ public PaintCanvasViewModel(ApplicationData applicationData, ToolsManager toolSe
329349
SelectionOverlay.UpdateSelection(null);
330350
SelectionOverlay.DrawLines = false;
331351
}
352+
353+
IsSelectionButtonVisible = false;
332354
});
333355

334356
_selectionCreated = Subjects.SelectionCreated.Subscribe(selection =>
@@ -338,6 +360,7 @@ public PaintCanvasViewModel(ApplicationData applicationData, ToolsManager toolSe
338360
SelectionOverlay.DrawLines = true;
339361
SelectionOverlay.UpdateSelection(selection);
340362
Subjects.OverlayModified.OnNext(null);
363+
IsSelectionButtonVisible = true;
341364
}
342365
});
343366

@@ -364,6 +387,13 @@ public PaintCanvasViewModel(ApplicationData applicationData, ToolsManager toolSe
364387
CloseFramesView = new ActionCommand(() => framesSectionViewModel.IsVisible = false);
365388
OpenPropertiesView = new ActionCommand(() => propertiesSectionViewModel.IsVisible = true);
366389
ClosePropertiesView = new ActionCommand(() => propertiesSectionViewModel.IsVisible = false);
390+
OpenSelectionMenu = new ActionCommand<Control>(obj =>
391+
{
392+
var menu = _selectionMenu.GetMenu();
393+
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
394+
menu.PlacementAnchor = Avalonia.Controls.Primitives.PopupPositioning.PopupAnchor.TopLeft;
395+
menu.ShowAt(obj);
396+
});
367397
}
368398
public void RecalculateFactor(Point windowSize)
369399
{
@@ -450,7 +480,7 @@ private void LeftMouseDownAction(MouseEvent mouseEvent)
450480
}
451481

452482
_leftPressed = true;
453-
_toolSelector.SelectedTool?.ApplyTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState);
483+
_toolSelector.SelectedTool?.ApplyTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
454484
UpdateRenderModel();
455485
Subjects.FrameModified.OnNext(_frame);
456486
}
@@ -463,7 +493,7 @@ private void LeftMouseUpAction(MouseEvent mouseEvent)
463493
}
464494

465495
_leftPressed = false;
466-
_toolSelector.SelectedTool?.ReleaseTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState);
496+
_toolSelector.SelectedTool?.ReleaseTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
467497
UpdateRenderModel();
468498

469499
if (_toolSelector.SelectedTool != null && _toolSelector.SelectedTool.AddToHistory)
@@ -484,7 +514,16 @@ private void RightMouseDownAction(MouseEvent mouseEvent)
484514
}
485515

486516
_rightPressed = true;
487-
_toolSelector.SelectedTool?.ApplyTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState);
517+
518+
if (_toolSelector.SelectedTool is ToolSelectBase selection)
519+
{
520+
var flyout = _selectionMenu.GetMenu();
521+
flyout.ShowAt(View, true);
522+
}
523+
else if (_toolSelector.SelectedTool is BaseTool tool)
524+
{
525+
tool.ApplyTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
526+
}
488527
UpdateRenderModel();
489528
}
490529

@@ -496,7 +535,7 @@ private void RightMouseUpAction(MouseEvent mouseEvent)
496535
}
497536

498537
_rightPressed = false;
499-
_toolSelector.SelectedTool?.ReleaseTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState);
538+
_toolSelector.SelectedTool?.ReleaseTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
500539
UpdateRenderModel();
501540

502541
if (_toolSelector.SelectedTool != null && _toolSelector.SelectedTool.AddToHistory)
@@ -525,12 +564,12 @@ private void MouseMoveAction(MouseEvent mouseEvent)
525564

526565
if (_leftPressed || _rightPressed)
527566
{
528-
_toolSelector.SelectedTool.MoveTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState);
567+
_toolSelector.SelectedTool.MoveTool(mouseEvent.Point, _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
529568
UpdateRenderModel();
530569
}
531570
else
532571
{
533-
_toolSelector.SelectedTool.UpdateHighlightedPixel(mouseEvent.Point, _frame, ref _overlay);
572+
_toolSelector.SelectedTool.UpdateHighlightedPixel(mouseEvent.Point, _frame, ref _overlay, _selectionManager.Selection);
534573
UpdateRenderModel();
535574
}
536575

@@ -541,7 +580,7 @@ private void MouseLeaveAction()
541580
{
542581
if (_rightPressed || _leftPressed)
543582
{
544-
_toolSelector.SelectedTool?.ReleaseTool(new Point(), _frame, ref _overlay, _currentKeyState);
583+
_toolSelector.SelectedTool?.ReleaseTool(new Point(), _frame, ref _overlay, _currentKeyState, _selectionManager.Selection);
545584
UpdateRenderModel();
546585
}
547586
_rightPressed = false;

Pixed.Common/Tools/BaseTool.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Pixed.Common.Services.Keyboard;
44
using Pixed.Core;
55
using Pixed.Core.Models;
6+
using Pixed.Core.Selection;
67
using Pixed.Core.Utils;
78
using SkiaSharp;
89
using System.Collections.Generic;
@@ -36,29 +37,29 @@ public virtual UniColor GetToolColor()
3637
return _applicationData.PrimaryColor;
3738
}
3839

39-
protected void ApplyToolBase(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState)
40+
protected void ApplyToolBase(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState, BaseSelection? selection)
4041
{
4142
_toolColor ??= GetToolColor();
4243
}
4344

44-
public virtual void ApplyTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState)
45+
public virtual void ApplyTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState, BaseSelection? selection)
4546
{
46-
ApplyToolBase(point, frame, ref overlay, keyState);
47+
ApplyToolBase(point, frame, ref overlay, keyState, selection);
4748
}
4849

49-
public virtual void MoveTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState)
50+
public virtual void MoveTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState, BaseSelection? selection)
5051
{
5152

5253
}
5354

54-
protected void ReleaseToolBase(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState)
55+
protected void ReleaseToolBase(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState, BaseSelection? selection)
5556
{
5657
_toolColor = null;
5758
}
5859

59-
public virtual void ReleaseTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState)
60+
public virtual void ReleaseTool(Point point, Frame frame, ref SKBitmap overlay, KeyState keyState, BaseSelection? selection)
6061
{
61-
ReleaseToolBase(point, frame, ref overlay, keyState);
62+
ReleaseToolBase(point, frame, ref overlay, keyState, selection);
6263
}
6364

6465
public virtual void Reset()
@@ -71,7 +72,7 @@ public virtual void Initialize()
7172

7273
}
7374

74-
public virtual void UpdateHighlightedPixel(Point point, Frame frame, ref SKBitmap overlay)
75+
public virtual void UpdateHighlightedPixel(Point point, Frame frame, ref SKBitmap overlay, BaseSelection? selection)
7576
{
7677
overlay ??= new SKBitmap(frame.Width, frame.Height, true);
7778

0 commit comments

Comments
 (0)