|
@@ -1,5 +1,6 @@
|
|
|
using System.Collections.Generic;
|
|
|
using System.Collections.ObjectModel;
|
|
|
+using System.ComponentModel;
|
|
|
using System.Linq;
|
|
|
using Avalonia.Input;
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
@@ -58,6 +59,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
}
|
|
|
|
|
|
private Cursor? toolCursor;
|
|
|
+
|
|
|
public Cursor? ToolCursor
|
|
|
{
|
|
|
get => toolCursor;
|
|
@@ -70,6 +72,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
}
|
|
|
|
|
|
private IToolHandler? activeTool;
|
|
|
+
|
|
|
public IToolHandler? ActiveTool
|
|
|
{
|
|
|
get => activeTool;
|
|
@@ -87,7 +90,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
}
|
|
|
|
|
|
ICollection<IToolSetHandler> IToolsHandler.AllToolSets => AllToolSets;
|
|
|
-
|
|
|
+
|
|
|
public ObservableCollection<IToolSetHandler> AllToolSets { get; } = new();
|
|
|
|
|
|
public event EventHandler<SelectedToolEventArgs>? SelectedToolChanged;
|
|
@@ -97,26 +100,27 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
private bool altIsDown;
|
|
|
|
|
|
private ToolViewModel _preTransientTool;
|
|
|
-
|
|
|
+
|
|
|
private List<IToolHandler> allTools = new();
|
|
|
private IToolSetHandler? _activeToolSet;
|
|
|
|
|
|
public ToolsViewModel(ViewModelMain owner)
|
|
|
: base(owner)
|
|
|
{
|
|
|
+ owner.DocumentManagerSubViewModel.ActiveDocumentChanged += ActiveDocumentChanged;
|
|
|
}
|
|
|
|
|
|
public void SetupTools(IServiceProvider services, ToolSetsConfig toolSetConfig)
|
|
|
{
|
|
|
allTools = services.GetServices<IToolHandler>().ToList();
|
|
|
-
|
|
|
+
|
|
|
ToolSetConfig activeToolSetConfig = toolSetConfig.FirstOrDefault();
|
|
|
-
|
|
|
+
|
|
|
if (activeToolSetConfig is null)
|
|
|
{
|
|
|
throw new InvalidOperationException("No tool set configuration found.");
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
AllToolSets.Clear();
|
|
|
AddToolSets(toolSetConfig);
|
|
|
SetActiveToolSet(AllToolSets.First());
|
|
@@ -125,6 +129,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
public void SetActiveToolSet(IToolSetHandler toolSetHandler)
|
|
|
{
|
|
|
ActiveToolSet = toolSetHandler;
|
|
|
+ UpdateEnabledState();
|
|
|
}
|
|
|
|
|
|
public void SetupToolsTooltipShortcuts(IServiceProvider services)
|
|
@@ -157,20 +162,28 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
return;
|
|
|
doc.EventInlet.OnApplyTransform();
|
|
|
}
|
|
|
-
|
|
|
- [Command.Internal("PixiEditor.Tools.SwitchToolSet", AnalyticsTrack = true, CanExecute = "PixiEditor.HasNextToolSet")]
|
|
|
- [Command.Basic("PixiEditor.Tools.NextToolSet", true, "NEXT_TOOL_SET", "NEXT_TOOL_SET", Modifiers = KeyModifiers.Shift,
|
|
|
+
|
|
|
+ [Command.Internal("PixiEditor.Tools.SwitchToolSet", AnalyticsTrack = true,
|
|
|
+ CanExecute = "PixiEditor.HasNextToolSet")]
|
|
|
+ [Command.Basic("PixiEditor.Tools.NextToolSet", true, "NEXT_TOOL_SET", "NEXT_TOOL_SET",
|
|
|
+ Modifiers = KeyModifiers.Shift,
|
|
|
Key = Key.E, AnalyticsTrack = true)]
|
|
|
- [Command.Basic("PixiEditor.Tools.PreviousToolSet", false, "PREVIOUS_TOOL_SET", "PREVIOUS_TOOL_SET", Modifiers = KeyModifiers.Shift,
|
|
|
+ [Command.Basic("PixiEditor.Tools.PreviousToolSet", false, "PREVIOUS_TOOL_SET", "PREVIOUS_TOOL_SET",
|
|
|
+ Modifiers = KeyModifiers.Shift,
|
|
|
Key = Key.Q, AnalyticsTrack = true)]
|
|
|
public void SwitchToolSet(bool forward)
|
|
|
{
|
|
|
int currentIndex = AllToolSets.IndexOf(ActiveToolSet);
|
|
|
int nextIndex = currentIndex + (forward ? 1 : -1);
|
|
|
- if (nextIndex >= AllToolSets.Count || nextIndex < 0)
|
|
|
+ if (nextIndex >= AllToolSets.Count)
|
|
|
{
|
|
|
nextIndex = 0;
|
|
|
}
|
|
|
+
|
|
|
+ if (nextIndex < 0)
|
|
|
+ {
|
|
|
+ nextIndex = AllToolSets.Count - 1;
|
|
|
+ }
|
|
|
|
|
|
SetActiveToolSet(AllToolSets.ElementAt(nextIndex));
|
|
|
}
|
|
@@ -186,7 +199,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
}
|
|
|
|
|
|
return AllToolSets.ElementAt(nextIndex) != ActiveToolSet;
|
|
|
- }
|
|
|
+ }
|
|
|
|
|
|
[Command.Internal("PixiEditor.Tools.SelectTool", CanExecute = "PixiEditor.HasDocument")]
|
|
|
public void SetActiveTool(ToolViewModel tool)
|
|
@@ -198,7 +211,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
|
|
|
public void SetActiveTool(IToolHandler tool, bool transient, ICommandExecutionSourceInfo? sourceInfo)
|
|
|
{
|
|
|
- if(Owner.DocumentManagerSubViewModel.ActiveDocument is { PointerDragChangeInProgress: true }) return;
|
|
|
+ if (Owner.DocumentManagerSubViewModel.ActiveDocument is { PointerDragChangeInProgress: true }) return;
|
|
|
|
|
|
if (ActiveTool == tool)
|
|
|
{
|
|
@@ -223,7 +236,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
|
|
|
LastActionTool = ActiveTool;
|
|
|
ActiveTool = tool;
|
|
|
-
|
|
|
+
|
|
|
ActiveTool.Toolbar.SettingChanged += ToolbarSettingChanged;
|
|
|
|
|
|
if (shareToolbar)
|
|
@@ -264,7 +277,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
source = context.SourceInfo;
|
|
|
parameter = context.Parameter;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (parameter is Type type)
|
|
|
{
|
|
|
SetActiveTool(type, false, source);
|
|
@@ -275,8 +288,10 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
SetActiveTool(tool.GetType(), false, source);
|
|
|
}
|
|
|
|
|
|
- [Command.Basic("PixiEditor.Tools.IncreaseSize", 1, "INCREASE_TOOL_SIZE", "INCREASE_TOOL_SIZE", CanExecute = "PixiEditor.Tools.CanChangeToolSize", Key = Key.OemCloseBrackets, AnalyticsTrack = true)]
|
|
|
- [Command.Basic("PixiEditor.Tools.DecreaseSize", -1, "DECREASE_TOOL_SIZE", "DECREASE_TOOL_SIZE", CanExecute = "PixiEditor.Tools.CanChangeToolSize", Key = Key.OemOpenBrackets, AnalyticsTrack = true)]
|
|
|
+ [Command.Basic("PixiEditor.Tools.IncreaseSize", 1, "INCREASE_TOOL_SIZE", "INCREASE_TOOL_SIZE",
|
|
|
+ CanExecute = "PixiEditor.Tools.CanChangeToolSize", Key = Key.OemCloseBrackets, AnalyticsTrack = true)]
|
|
|
+ [Command.Basic("PixiEditor.Tools.DecreaseSize", -1, "DECREASE_TOOL_SIZE", "DECREASE_TOOL_SIZE",
|
|
|
+ CanExecute = "PixiEditor.Tools.CanChangeToolSize", Key = Key.OemOpenBrackets, AnalyticsTrack = true)]
|
|
|
public void ChangeToolSize(int increment)
|
|
|
{
|
|
|
if (ActiveTool?.Toolbar is not BasicToolbar toolbar)
|
|
@@ -298,11 +313,11 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
if (!typeof(ToolViewModel).IsAssignableFrom(toolType))
|
|
|
throw new ArgumentException($"'{toolType}' does not inherit from {typeof(ToolViewModel)}");
|
|
|
IToolHandler foundTool = ActiveToolSet!.Tools.FirstOrDefault(x => x.GetType().IsAssignableFrom(toolType));
|
|
|
- if (foundTool == null) return;
|
|
|
-
|
|
|
+ if (foundTool == null || !foundTool.CanBeUsed) return;
|
|
|
+
|
|
|
SetActiveTool(foundTool, transient, sourceInfo);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public void RestorePreviousTool()
|
|
|
{
|
|
|
if (LastActionTool != null)
|
|
@@ -329,17 +344,17 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
|
|
|
public void HandleToolRepeatShortcutDown()
|
|
|
{
|
|
|
- if(ActiveTool == null) return;
|
|
|
+ if (ActiveTool == null) return;
|
|
|
if (ActiveTool is null or { IsTransient: false })
|
|
|
{
|
|
|
ShortcutController.BlockShortcutExecution("ShortcutDown");
|
|
|
ActiveTool.IsTransient = true;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
public void HandleToolShortcutUp()
|
|
|
{
|
|
|
- if(ActiveTool == null) return;
|
|
|
+ if (ActiveTool == null) return;
|
|
|
if (ActiveTool.IsTransient && LastActionTool is { } tool)
|
|
|
SetActiveTool(tool, false);
|
|
|
ShortcutController.UnblockShortcutExecution("ShortcutDown");
|
|
@@ -347,7 +362,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
|
|
|
public void UseToolEventInlet(VecD canvasPos, MouseButton button)
|
|
|
{
|
|
|
- if (ActiveTool == null) return;
|
|
|
+ if (ActiveTool is not { CanBeUsed: true }) return;
|
|
|
|
|
|
ActiveTool.UsedWith = button;
|
|
|
if (ActiveTool.StopsLinkedToolOnUse)
|
|
@@ -367,38 +382,81 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
|
|
|
{
|
|
|
ActiveTool?.ModifierKeyChanged(args.IsCtrlDown, args.IsShiftDown, args.IsAltDown);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private void ToolbarSettingChanged(string settingName, object value)
|
|
|
{
|
|
|
var document = Owner.DocumentManagerSubViewModel.ActiveDocument;
|
|
|
if (document is null)
|
|
|
return;
|
|
|
-
|
|
|
+
|
|
|
document.EventInlet.SettingsChanged(settingName, value);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
private void AddToolSets(ToolSetsConfig toolSetConfig)
|
|
|
{
|
|
|
foreach (ToolSetConfig toolSet in toolSetConfig)
|
|
|
{
|
|
|
List<IToolHandler> tools = new List<IToolHandler>();
|
|
|
-
|
|
|
+
|
|
|
foreach (string toolName in toolSet.Tools)
|
|
|
{
|
|
|
IToolHandler? tool = allTools.FirstOrDefault(tool => tool.ToolName == toolName);
|
|
|
if (tool is null)
|
|
|
{
|
|
|
- #if DEBUG
|
|
|
+#if DEBUG
|
|
|
throw new InvalidOperationException($"Tool '{toolName}' not found.");
|
|
|
- #endif
|
|
|
-
|
|
|
+#endif
|
|
|
+
|
|
|
continue;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
tools.Add(tool);
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
AllToolSets.Add(new ToolSetViewModel(toolSet.Name, tools));
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ private void ActiveDocumentChanged(object? sender, DocumentChangedEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.OldDocument is not null)
|
|
|
+ {
|
|
|
+ e.OldDocument.PropertyChanged -= DocumentOnPropertyChanged;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (e.NewDocument is not null)
|
|
|
+ {
|
|
|
+ e.NewDocument.PropertyChanged += DocumentOnPropertyChanged;
|
|
|
+ UpdateEnabledState();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void DocumentOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
|
|
|
+ {
|
|
|
+ if (e.PropertyName == nameof(DocumentViewModel.SelectedStructureMember))
|
|
|
+ {
|
|
|
+ UpdateEnabledState();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void UpdateEnabledState()
|
|
|
+ {
|
|
|
+ var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
|
|
|
+ if (doc is null)
|
|
|
+ return;
|
|
|
+
|
|
|
+ foreach (var toolHandler in ActiveToolSet.Tools)
|
|
|
+ {
|
|
|
+ if (toolHandler is ToolViewModel tool)
|
|
|
+ {
|
|
|
+ List<IStructureMemberHandler> selectedLayers = new List<IStructureMemberHandler>
|
|
|
+ {
|
|
|
+ doc.SelectedStructureMember
|
|
|
+ };
|
|
|
+
|
|
|
+ selectedLayers.AddRange(doc.SoftSelectedStructureMembers);
|
|
|
+ tool.SelectedLayersChanged(selectedLayers.ToArray());
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|