Browse Source

More tools work

Krzysztof Krysiński 2 years ago
parent
commit
c5a36cdb87

+ 26 - 15
src/PixiEditor.AvaloniaUI/Helpers/ServiceCollectionHelpers.cs

@@ -40,7 +40,7 @@ internal static class ServiceCollectionHelpers
 
             // View Models
             .AddSingleton<ToolsViewModel>()
-            .AddSingleton<IToolsHandler, ToolsViewModel>()
+            .AddSingleton<IToolsHandler, ToolsViewModel>(x => x.GetRequiredService<ToolsViewModel>())
             .AddSingleton<IColorsHandler, ColorsViewModel>()
             .AddSingleton<StylusViewModel>()
             .AddSingleton<WindowViewModel>()
@@ -56,8 +56,8 @@ internal static class ServiceCollectionHelpers
             .AddSingleton<RegistryViewModel>()
             .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
             .AddSingleton<DebugViewModel>()
-            .AddSingleton<ISearchHandler, SearchViewModel>()
             .AddSingleton<SearchViewModel>()
+            .AddSingleton<ISearchHandler, SearchViewModel>(x => x.GetRequiredService<SearchViewModel>())
             .AddSingleton<AdditionalContentViewModel>()
             .AddSingleton<LayoutDockViewModel>()
             .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModelMain>(), extensionLoader))
@@ -68,19 +68,30 @@ internal static class ServiceCollectionHelpers
             // Tools
             .AddSingleton<IToolHandler, MoveViewportToolViewModel>()
             .AddSingleton<IToolHandler, RotateViewportToolViewModel>()
-            .AddSingleton<IToolHandler, MoveToolViewModel>()
-            .AddSingleton<IToolHandler, PenToolViewModel>()
-            .AddSingleton<IPenToolHandler, PenToolViewModel>(x => x.GetServices<IToolHandler>().OfType<PenToolViewModel>().First())
-            .AddSingleton<IToolHandler, SelectToolViewModel>()
-            .AddSingleton<IToolHandler, MagicWandToolViewModel>()
-            .AddSingleton<IToolHandler, LassoToolViewModel>()
-            .AddSingleton<IToolHandler, FloodFillToolViewModel>()
-            .AddSingleton<IToolHandler, LineToolViewModel>()
-            .AddSingleton<IToolHandler, EllipseToolViewModel>()
-            .AddSingleton<IToolHandler, RectangleToolViewModel>()
-            .AddSingleton<IToolHandler, EraserToolViewModel>()
-            .AddSingleton<IToolHandler, ColorPickerToolViewModel>()
-            .AddSingleton<IToolHandler, BrightnessToolViewModel>()
+            .AddSingleton<IMoveToolHandler, MoveToolViewModel>()
+            .AddSingleton<IToolHandler, MoveToolViewModel>(x => (MoveToolViewModel)x.GetService<IMoveToolHandler>())
+            .AddSingleton<IPenToolHandler, PenToolViewModel>()
+            .AddSingleton<IToolHandler, PenToolViewModel>(x => (PenToolViewModel)x.GetService<IPenToolHandler>())
+            .AddSingleton<ISelectToolHandler, SelectToolViewModel>()
+            .AddSingleton<IToolHandler, SelectToolViewModel>(x => (SelectToolViewModel)x.GetService<ISelectToolHandler>())
+            .AddSingleton<IMagicWandToolHandler, MagicWandToolViewModel>()
+            .AddSingleton<IToolHandler, MagicWandToolViewModel>(x => (MagicWandToolViewModel)x.GetService<IMagicWandToolHandler>())
+            .AddSingleton<ILassoToolHandler, LassoToolViewModel>()
+            .AddSingleton<IToolHandler, LassoToolViewModel>(x => (LassoToolViewModel)x.GetService<ILassoToolHandler>())
+            .AddSingleton<IFloodFillToolHandler, FloodFillToolViewModel>()
+            .AddSingleton<IToolHandler, FloodFillToolViewModel>(x => (FloodFillToolViewModel)x.GetService<IFloodFillToolHandler>())
+            .AddSingleton<ILineToolHandler, LineToolViewModel>()
+            .AddSingleton<IToolHandler, LineToolViewModel>(x => (LineToolViewModel)x.GetService<ILineToolHandler>())
+            .AddSingleton<IEllipseToolHandler, EllipseToolViewModel>()
+            .AddSingleton<IToolHandler, EllipseToolViewModel>(x => (EllipseToolViewModel)x.GetService<IEllipseToolHandler>())
+            .AddSingleton<IRectangleToolHandler, RectangleToolViewModel>()
+            .AddSingleton<IToolHandler, RectangleToolViewModel>(x => (RectangleToolViewModel)x.GetService<IRectangleToolHandler>())
+            .AddSingleton<IEraserToolHandler, EraserToolViewModel>()
+            .AddSingleton<IToolHandler, EraserToolViewModel>(x => (EraserToolViewModel)x.GetService<IEraserToolHandler>())
+            .AddSingleton<IColorPickerHandler, ColorPickerToolViewModel>()
+            .AddSingleton<IToolHandler, ColorPickerToolViewModel>(x => (ColorPickerToolViewModel)x.GetService<IColorPickerHandler>())
+            .AddSingleton<IBrightnessToolHandler, BrightnessToolViewModel>()
+            .AddSingleton<IToolHandler, BrightnessToolViewModel>(x => (BrightnessToolViewModel)x.GetService<IBrightnessToolHandler>())
             .AddSingleton<IToolHandler, ZoomToolViewModel>()
             // Palette Parsers
             .AddSingleton<PaletteFileParser, JascFileParser>()

+ 24 - 1
src/PixiEditor.AvaloniaUI/Models/Handlers/IToolsHandler.cs

@@ -1,7 +1,30 @@
-namespace PixiEditor.AvaloniaUI.Models.Handlers;
+using System.Collections.Generic;
+using Avalonia.Input;
+using PixiEditor.AvaloniaUI.Models.Events;
+using PixiEditor.AvaloniaUI.Models.Preferences;
+using PixiEditor.AvaloniaUI.ViewModels.Tools;
+using PixiEditor.DrawingApi.Core.Numerics;
+
+namespace PixiEditor.AvaloniaUI.Models.Handlers;
 
 internal interface IToolsHandler : IHandler
 {
     public void SetTool(object parameter);
     public void RestorePreviousTool();
+    public IToolHandler ActiveTool { get; }
+    public List<IToolHandler> ToolSet { get; }
+    public RightClickMode RightClickMode { get; set; }
+    public bool EnableSharedToolbar { get; set; }
+    public event EventHandler<SelectedToolEventArgs> SelectedToolChanged;
+    public void SetupTools(IServiceProvider services);
+    public void SetupToolsTooltipShortcuts(IServiceProvider services);
+    public void SetActiveTool<T>(bool transient) where T : IToolHandler;
+    public void SetActiveTool(Type toolType, bool transient);
+    public void ConvertedKeyDownInlet(FilteredKeyEventArgs args);
+    public void ConvertedKeyUpInlet(FilteredKeyEventArgs args);
+    public void HandleToolRepeatShortcutDown();
+    public void HandleToolShortcutUp();
+    public void UseToolEventInlet(VecD argsPositionOnCanvas, MouseButton argsButton);
+    public T GetTool<T>() where T : IToolHandler;
+    public void AddPropertyChangedCallback(string propertyName, Action callback);
 }

+ 17 - 15
src/PixiEditor.AvaloniaUI/ViewModels/Dock/PixiEditorDocumentDock.cs

@@ -1,5 +1,6 @@
 using System.Collections.Specialized;
 using System.Linq;
+using System.Threading.Tasks;
 using CommunityToolkit.Mvvm.Input;
 using Dock.Model.Avalonia.Controls;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
@@ -14,35 +15,36 @@ internal class PixiEditorDocumentDock : DocumentDock
     public PixiEditorDocumentDock(FileViewModel manager)
     {
         this.manager = manager;
-        manager.Owner.WindowSubViewModel.Viewports.CollectionChanged += Viewports_CollectionChanged;
-        CreateDocument = new RelayCommand(CreateDockDocument);
+        manager.Owner.WindowSubViewModel.ViewportAdded += AddNewViewport;
+        manager.Owner.WindowSubViewModel.ViewportClosed += RemoveViewport;
+        CreateDocument = new AsyncRelayCommand(CreateDockDocument);
     }
 
-    private void Viewports_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+    private void AddNewViewport(ViewportWindowViewModel e)
     {
-        ViewportWindowViewModel viewportVm = e.NewItems[^1] as ViewportWindowViewModel;
-        var document = new DockDocumentViewModel(viewportVm) { Title = viewportVm.Document.FileName };
+        var document = new DockDocumentViewModel(e) { Title = e.Document.FileName };
 
         Factory?.AddDockable(this, document);
         Factory?.SetActiveDockable(document);
         Factory?.SetFocusedDockable(this, document);
     }
 
-    private void CreateDockDocument()
+    private void RemoveViewport(ViewportWindowViewModel e)
     {
-        if (!CanCreateDocument)
+        var document = VisibleDockables?.OfType<DockDocumentViewModel>().FirstOrDefault(x => x.ViewModel == e);
+        if (document != null)
         {
-            return;
+            Factory?.RemoveDockable(this, true);
         }
+    }
 
-        var doc = manager.NewDocument(b =>
+    private async Task CreateDockDocument()
+    {
+        if (!CanCreateDocument)
         {
-            b.WithSize(new VecI(64, 64));
-        });
-        var document = new DockDocumentViewModel(manager.Owner.WindowSubViewModel.Viewports[^1]) { Title = "hello" };
+            return;
+        }
 
-        Factory?.AddDockable(this, document);
-        Factory?.SetActiveDockable(document);
-        Factory?.SetFocusedDockable(this, document);
+        await manager.CreateFromNewFileDialog();
     }
 }

+ 4 - 3
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/IoViewModel.cs

@@ -8,6 +8,7 @@ using PixiEditor.AvaloniaUI.Models.Commands.Commands;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Controllers.InputDevice;
 using PixiEditor.AvaloniaUI.Models.Events;
+using PixiEditor.AvaloniaUI.Models.Handlers;
 using PixiEditor.AvaloniaUI.Models.Input;
 using PixiEditor.AvaloniaUI.Models.Preferences;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
@@ -187,7 +188,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         }
     }
 
-    private void HandleRightMouseEraseDown(ToolsViewModel tools)
+    private void HandleRightMouseEraseDown(IToolsHandler tools)
     {
         var currentToolSize = tools.ActiveTool.Toolbar.Settings.FirstOrDefault(x => x.Name == "ToolSize");
         hadSharedToolbar = tools.EnableSharedToolbar;
@@ -246,7 +247,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         hadSwapped = false;
     }
 
-    private void HandleRightMouseUp(MouseButton button, ToolsViewModel tools)
+    private void HandleRightMouseUp(MouseButton button, IToolsHandler tools)
     {
         switch (button)
         {
@@ -266,7 +267,7 @@ internal class IoViewModel : SubViewModel<ViewModelMain>
         }
     }
 
-    private void HandleRightMouseEraseUp(ToolsViewModel tools)
+    private void HandleRightMouseEraseUp(IToolsHandler tools)
     {
         if (startedWithEraser)
         {

+ 1 - 1
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/SearchViewModel.cs

@@ -34,7 +34,7 @@ internal class SearchViewModel : SubViewModel<ViewModelMain>, ISearchHandler
     { }
 
     [Evaluator.CanExecute("PixiEditor.Search.CanOpenSearchWindow")]
-    public bool CanToggleSeachWindow() => !ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Busy ?? true;
+    public bool CanToggleSearchWindow() => !ViewModelMain.Current?.DocumentManagerSubViewModel.ActiveDocument?.Busy ?? true;
 
     [Command.Basic("PixiEditor.Search.Toggle", "", "COMMAND_SEARCH", "OPEN_COMMAND_SEARCH", Key = Key.K, Modifiers = KeyModifiers.Control, CanExecute = "PixiEditor.Search.CanOpenSearchWindow")]
     public void ToggleSearchWindow(string searchTerm)

+ 3 - 3
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ToolsViewModel.cs

@@ -106,13 +106,13 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     }
 
     public T? GetTool<T>()
-        where T : ToolViewModel
+        where T : IToolHandler
     {
         return (T?)ToolSet?.Where(static tool => tool is T).FirstOrDefault();
     }
 
     public void SetActiveTool<T>(bool transient)
-        where T : ToolViewModel
+        where T : IToolHandler
     {
         SetActiveTool(typeof(T), transient);
     }
@@ -215,7 +215,7 @@ internal class ToolsViewModel : SubViewModel<ViewModelMain>, IToolsHandler
     {
         if (!typeof(ToolViewModel).IsAssignableFrom(toolType))
             throw new ArgumentException($"'{toolType}' does not inherit from {typeof(ToolViewModel)}");
-        IToolHandler foundTool = ToolSet!.First(x => x.GetType() == toolType);
+        IToolHandler foundTool = ToolSet!.First(x => x.GetType().IsAssignableFrom(toolType));
         SetActiveTool(foundTool, transient);
     }
     

+ 10 - 1
src/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/WindowViewModel.cs

@@ -5,6 +5,7 @@ using CommunityToolkit.Mvvm.Input;
 using PixiEditor.AvaloniaUI.Models.Commands;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
 using PixiEditor.AvaloniaUI.Views.Windows;
+using PixiEditor.Views.UserControls;
 using Command = PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands.Command;
 using SettingsWindow = PixiEditor.AvaloniaUI.Views.Settings.SettingsWindow;
 
@@ -20,6 +21,8 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
     public RelayCommand<string> ShowAvalonDockWindowCommand { get; set; }
     public ObservableCollection<ViewportWindowViewModel> Viewports { get; } = new();
     public event EventHandler<ViewportWindowViewModel>? ActiveViewportChanged;
+    public event Action<ViewportWindowViewModel> ViewportAdded;
+    public event Action<ViewportWindowViewModel> ViewportClosed;
 
     private object? activeWindow;
     public object? ActiveWindow
@@ -79,11 +82,14 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
 
     public void CreateNewViewport(DocumentViewModel doc)
     {
-        Viewports.Add(new ViewportWindowViewModel(this, doc));
+        ViewportWindowViewModel newViewport = new ViewportWindowViewModel(this, doc);
+        Viewports.Add(newViewport);
         foreach (var viewport in Viewports.Where(vp => vp.Document == doc))
         {
             viewport.IndexChanged();
         }
+
+        ViewportAdded?.Invoke(newViewport);
     }
 
     public void MakeDocumentViewportActive(DocumentViewModel? doc)
@@ -119,6 +125,8 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
             {
                 sibling.IndexChanged();
             }
+
+            ViewportClosed?.Invoke(viewport);
         }
     }
 
@@ -128,6 +136,7 @@ internal class WindowViewModel : SubViewModel<ViewModelMain>
         foreach (ViewportWindowViewModel viewport in viewports)
         {
             Viewports.Remove(viewport);
+            ViewportClosed?.Invoke(viewport);
         }
     }
 

+ 0 - 2
src/PixiEditor.AvaloniaUI/ViewModels/Tools/Tools/BrightnessToolViewModel.cs

@@ -24,8 +24,6 @@ internal class BrightnessToolViewModel : ToolViewModel, IBrightnessToolHandler
     }
 
     public override bool IsErasable => true;
-
-    public IToolbar Toolbar { get; set; }
     public override LocalizedString Tooltip => new LocalizedString("BRIGHTNESS_TOOL_TOOLTIP", Shortcut);
 
     public override BrushShape BrushShape => BrushShape.Circle;

+ 0 - 1
src/PixiEditor.AvaloniaUI/ViewModels/Tools/Tools/RectangleToolViewModel.cs

@@ -17,7 +17,6 @@ internal class RectangleToolViewModel : ShapeTool, IRectangleToolHandler
     }
 
     public override string ToolNameLocalizationKey => "RECTANGLE_TOOL";
-    public IToolbar Toolbar { get; set; }
     public override LocalizedString Tooltip => new LocalizedString("RECTANGLE_TOOL_TOOLTIP", Shortcut);
 
     public bool Filled { get; set; } = false;

+ 2 - 2
src/PixiEditor.AvaloniaUI/ViewModels/ViewModelMain.cs

@@ -31,7 +31,7 @@ internal partial class ViewModelMain : ViewModelBase, ICommandsHandler
 
     public UpdateViewModel UpdateSubViewModel { get; set; }
 
-    public ToolsViewModel ToolsSubViewModel { get; set; }
+    public IToolsHandler ToolsSubViewModel { get; set; }
 
     public IoViewModel IoSubViewModel { get; set; }
 
@@ -118,7 +118,7 @@ internal partial class ViewModelMain : ViewModelBase, ICommandsHandler
         SelectionSubViewModel = services.GetService<SelectionViewModel>();
 
         FileSubViewModel = services.GetService<FileViewModel>();
-        ToolsSubViewModel = services.GetService<ToolsViewModel>();
+        ToolsSubViewModel = services.GetService<IToolsHandler>();
         ToolsSubViewModel.SelectedToolChanged += ToolsSubViewModel_SelectedToolChanged;
 
         IoSubViewModel = services.GetService<IoViewModel>();

+ 1 - 0
src/PixiEditor.Zoombox/Zoombox.axaml.cs

@@ -403,6 +403,7 @@ public partial class Zoombox : UserControl, INotifyPropertyChanged
         activeDragOperation?.Update(e);
     }
 
+    //TODO: Scroll is imprecise
     private void OnScroll(object sender, PointerWheelEventArgs e)
     {
         double abs = Math.Abs(e.Delta.Y / 100.0);