Browse Source

The most wicked drawing and displaying images is working

Krzysztof Krysiński 1 year ago
parent
commit
8a79419637
19 changed files with 192 additions and 170 deletions
  1. 0 10
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Exceptions/DependencyNotFoundException.cs
  2. 64 57
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/ServiceCollectionHelpers.cs
  3. 2 2
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/Controllers/InputDevice/MouseInputFilter.cs
  4. 4 4
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/ChangeExecutionController.cs
  5. 2 2
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/DocumentInternalParts.cs
  6. 5 12
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/UpdateableChangeExecutors/UpdateableChangeExecutor.cs
  7. 13 3
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/DockDocumentViewModel.cs
  8. 0 1
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/DockFactory.cs
  9. 6 5
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/PixiEditorDocumentDock.cs
  10. 2 2
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentViewModel.cs
  11. 2 1
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ColorsViewModel.cs
  12. 0 1
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ViewportWindowViewModel.cs
  13. 9 8
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml
  14. 6 3
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml.cs
  15. 2 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml
  16. 16 4
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs
  17. 1 0
      src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainWindow.axaml.cs
  18. 2 2
      src/PixiEditor.Zoombox/Zoombox.axaml.cs
  19. 56 53
      src/PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs

+ 0 - 10
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Exceptions/DependencyNotFoundException.cs

@@ -1,10 +0,0 @@
-namespace PixiEditor.AvaloniaUI.Exceptions;
-
-public class DependencyNotFoundException : Exception
-{
-    public DependencyNotFoundException(Type dependencyType) : base($"Dependency of type {dependencyType} not found.") { }
-
-    public DependencyNotFoundException(string message) : base(message) { }
-
-    public DependencyNotFoundException(string message, Exception innerException) : base(message, innerException) { }
-}

+ 64 - 57
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Helpers/ServiceCollectionHelpers.cs

@@ -1,9 +1,11 @@
-using Microsoft.Extensions.DependencyInjection;
+using System.Linq;
+using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.AvaloniaUI.Models.AppExtensions;
 using PixiEditor.AvaloniaUI.Models.AppExtensions;
 using PixiEditor.AvaloniaUI.Models.AppExtensions.Services;
 using PixiEditor.AvaloniaUI.Models.AppExtensions.Services;
 using PixiEditor.AvaloniaUI.Models.Commands;
 using PixiEditor.AvaloniaUI.Models.Commands;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Handlers;
 using PixiEditor.AvaloniaUI.Models.Handlers;
+using PixiEditor.AvaloniaUI.Models.Handlers.Tools;
 using PixiEditor.AvaloniaUI.Models.IO.PaletteParsers;
 using PixiEditor.AvaloniaUI.Models.IO.PaletteParsers;
 using PixiEditor.AvaloniaUI.Models.IO.PaletteParsers.JascPalFile;
 using PixiEditor.AvaloniaUI.Models.IO.PaletteParsers.JascPalFile;
 using PixiEditor.AvaloniaUI.Models.Localization;
 using PixiEditor.AvaloniaUI.Models.Localization;
@@ -29,63 +31,68 @@ internal static class ServiceCollectionHelpers
     /// Adds all the services required to fully run PixiEditor's MainWindow
     /// Adds all the services required to fully run PixiEditor's MainWindow
     /// </summary>
     /// </summary>
     public static IServiceCollection
     public static IServiceCollection
-        AddPixiEditor(this IServiceCollection collection, ExtensionLoader extensionLoader) => collection
-        .AddSingleton<ViewModelMain>()
-        .AddSingleton<IPreferences, PreferencesSettings>()
-        .AddSingleton<ILocalizationProvider, LocalizationProvider>(x => new LocalizationProvider(extensionLoader))
+        AddPixiEditor(this IServiceCollection collection, ExtensionLoader extensionLoader)
+    {
+        return collection
+            .AddSingleton<ViewModelMain>()
+            .AddSingleton<IPreferences, PreferencesSettings>()
+            .AddSingleton<ILocalizationProvider, LocalizationProvider>(x => new LocalizationProvider(extensionLoader))
 
 
-        // View Models
-        .AddSingleton<ToolsViewModel>()
-        .AddSingleton<IToolsHandler, ToolsViewModel>()
-        .AddSingleton<StylusViewModel>()
-        .AddSingleton<WindowViewModel>()
-        .AddSingleton<FileViewModel>()
-        .AddSingleton<UpdateViewModel>()
-        .AddSingleton<IoViewModel>()
-        .AddSingleton<LayersViewModel>()
-        .AddSingleton<ClipboardViewModel>()
-        .AddSingleton<UndoViewModel>()
-        .AddSingleton<SelectionViewModel>()
-        .AddSingleton<ViewOptionsViewModel>()
-        .AddSingleton<ColorsViewModel>()
-        .AddSingleton<RegistryViewModel>()
-        .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
-        .AddSingleton<DebugViewModel>()
-        .AddSingleton<ISearchHandler, SearchViewModel>()
-        .AddSingleton<SearchViewModel>()
-        .AddSingleton<AdditionalContentViewModel>()
-        .AddSingleton<LayoutDockViewModel>()
-        .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModelMain>(), extensionLoader))
-        // Controllers
-        .AddSingleton<ShortcutController>()
-        .AddSingleton<CommandController>()
-        .AddSingleton<DocumentManagerViewModel>()
-        // Tools
-        .AddSingleton<IToolHandler, MoveViewportToolViewModel>()
-        .AddSingleton<IToolHandler, RotateViewportToolViewModel>()
-        .AddSingleton<IToolHandler, MoveToolViewModel>()
-        .AddSingleton<IToolHandler, PenToolViewModel>()
-        .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<IToolHandler, ZoomToolViewModel>()
-        // Palette Parsers
-        .AddSingleton<PaletteFileParser, JascFileParser>()
-        .AddSingleton<PaletteFileParser, ClsFileParser>()
-        .AddSingleton<PaletteFileParser, PngPaletteParser>()
-        .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
-        .AddSingleton<PaletteFileParser, HexPaletteParser>()
-        .AddSingleton<PaletteFileParser, GimpGplParser>()
-        .AddSingleton<PaletteFileParser, PixiPaletteParser>()
-        // Palette data sources
-        .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>();
+            // View Models
+            .AddSingleton<ToolsViewModel>()
+            .AddSingleton<IToolsHandler, ToolsViewModel>()
+            .AddSingleton<IColorsHandler, ColorsViewModel>()
+            .AddSingleton<StylusViewModel>()
+            .AddSingleton<WindowViewModel>()
+            .AddSingleton<FileViewModel>()
+            .AddSingleton<UpdateViewModel>()
+            .AddSingleton<IoViewModel>()
+            .AddSingleton<LayersViewModel>()
+            .AddSingleton<ClipboardViewModel>()
+            .AddSingleton<UndoViewModel>()
+            .AddSingleton<SelectionViewModel>()
+            .AddSingleton<ViewOptionsViewModel>()
+            .AddSingleton<ColorsViewModel>()
+            .AddSingleton<RegistryViewModel>()
+            .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
+            .AddSingleton<DebugViewModel>()
+            .AddSingleton<ISearchHandler, SearchViewModel>()
+            .AddSingleton<SearchViewModel>()
+            .AddSingleton<AdditionalContentViewModel>()
+            .AddSingleton<LayoutDockViewModel>()
+            .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModelMain>(), extensionLoader))
+            // Controllers
+            .AddSingleton<ShortcutController>()
+            .AddSingleton<CommandController>()
+            .AddSingleton<DocumentManagerViewModel>()
+            // 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<IToolHandler, ZoomToolViewModel>()
+            // Palette Parsers
+            .AddSingleton<PaletteFileParser, JascFileParser>()
+            .AddSingleton<PaletteFileParser, ClsFileParser>()
+            .AddSingleton<PaletteFileParser, PngPaletteParser>()
+            .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
+            .AddSingleton<PaletteFileParser, HexPaletteParser>()
+            .AddSingleton<PaletteFileParser, GimpGplParser>()
+            .AddSingleton<PaletteFileParser, PixiPaletteParser>()
+            // Palette data sources
+            .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>();
+    }
 
 
     public static IServiceCollection AddExtensionServices(this IServiceCollection collection) =>
     public static IServiceCollection AddExtensionServices(this IServiceCollection collection) =>
         collection.AddSingleton<IWindowProvider, WindowProvider>()
         collection.AddSingleton<IWindowProvider, WindowProvider>()

+ 2 - 2
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/Controllers/InputDevice/MouseInputFilter.cs

@@ -33,9 +33,9 @@ internal class MouseInputFilter
         OnMouseDown?.Invoke(this, args);
         OnMouseDown?.Invoke(this, args);
     }
     }
 
 
-    public void MouseMoveInlet(object args) => OnMouseMove?.Invoke(this, (VecD)args);
+    public void MouseMoveInlet(object args) => OnMouseMove?.Invoke(this, ((MouseOnCanvasEventArgs)args).PositionOnCanvas);
 
 
-    public void MouseUpInlet(object args) => MouseUpInlet((MouseButton)args);
+    public void MouseUpInlet(object args) => MouseUpInlet(((MouseOnCanvasEventArgs)args).Button);
     public void MouseUpInlet(object? sender, Point p, MouseButton button) => MouseUpInlet(button);
     public void MouseUpInlet(object? sender, Point p, MouseButton button) => MouseUpInlet(button);
     public void MouseUpInlet(MouseButton button)
     public void MouseUpInlet(MouseButton button)
     {
     {

+ 4 - 4
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/ChangeExecutionController.cs

@@ -19,7 +19,7 @@ internal class ChangeExecutionController
     public bool IsChangeActive => currentSession is not null;
     public bool IsChangeActive => currentSession is not null;
 
 
     private readonly IDocument document;
     private readonly IDocument document;
-    private readonly List<IHandler> handlers = new();
+    private readonly IServiceProvider services;
     private readonly DocumentInternalParts internals;
     private readonly DocumentInternalParts internals;
 
 
     private VecI lastPixelPos;
     private VecI lastPixelPos;
@@ -29,11 +29,11 @@ internal class ChangeExecutionController
     
     
     private UpdateableChangeExecutor? _queuedExecutor = null;
     private UpdateableChangeExecutor? _queuedExecutor = null;
 
 
-    public ChangeExecutionController(IDocument document, DocumentInternalParts internals, List<IHandler> handlers)
+    public ChangeExecutionController(IDocument document, DocumentInternalParts internals, IServiceProvider services)
     {
     {
         this.document = document;
         this.document = document;
         this.internals = internals;
         this.internals = internals;
-        this.handlers = handlers;
+        this.services = services;
     }
     }
 
 
     public ExecutorType GetCurrentExecutorType()
     public ExecutorType GetCurrentExecutorType()
@@ -72,7 +72,7 @@ internal class ChangeExecutionController
 
 
     private bool TryStartExecutorInternal(UpdateableChangeExecutor executor)
     private bool TryStartExecutorInternal(UpdateableChangeExecutor executor)
     {
     {
-        executor.Initialize(document, internals, handlers, this, EndExecutor);
+        executor.Initialize(document, internals, services, this, EndExecutor);
 
 
         if (executor.StartMode == ExecutorStartMode.OnMouseLeftButtonDown)
         if (executor.StartMode == ExecutorStartMode.OnMouseLeftButtonDown)
         {
         {

+ 2 - 2
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/DocumentInternalParts.cs

@@ -6,14 +6,14 @@ namespace PixiEditor.AvaloniaUI.Models.DocumentModels;
 #nullable enable
 #nullable enable
 internal class DocumentInternalParts
 internal class DocumentInternalParts
 {
 {
-    public DocumentInternalParts(IDocument doc, List<IHandler> handlers)
+    public DocumentInternalParts(IDocument doc, IServiceProvider services)
     {
     {
         Tracker = new DocumentChangeTracker();
         Tracker = new DocumentChangeTracker();
         StructureHelper = new DocumentStructureHelper(doc, this);
         StructureHelper = new DocumentStructureHelper(doc, this);
         Updater = new DocumentUpdater(doc, this);
         Updater = new DocumentUpdater(doc, this);
         ActionAccumulator = new ActionAccumulator(doc, this);
         ActionAccumulator = new ActionAccumulator(doc, this);
         State = new DocumentState();
         State = new DocumentState();
-        ChangeController = new ChangeExecutionController(doc, this, handlers);
+        ChangeController = new ChangeExecutionController(doc, this, services);
     }
     }
     public ActionAccumulator ActionAccumulator { get; }
     public ActionAccumulator ActionAccumulator { get; }
     public DocumentChangeTracker Tracker { get; }
     public DocumentChangeTracker Tracker { get; }

+ 5 - 12
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Models/DocumentModels/UpdateableChangeExecutors/UpdateableChangeExecutor.cs

@@ -1,6 +1,7 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using Avalonia.Input;
 using Avalonia.Input;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
+using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.AvaloniaUI.Exceptions;
 using PixiEditor.AvaloniaUI.Exceptions;
 using PixiEditor.AvaloniaUI.Models.Handlers;
 using PixiEditor.AvaloniaUI.Models.Handlers;
 using PixiEditor.AvaloniaUI.Models.Position;
 using PixiEditor.AvaloniaUI.Models.Position;
@@ -15,14 +16,14 @@ internal abstract class UpdateableChangeExecutor
     protected IDocument? document;
     protected IDocument? document;
     protected DocumentInternalParts? internals;
     protected DocumentInternalParts? internals;
     protected ChangeExecutionController? controller;
     protected ChangeExecutionController? controller;
-    protected IReadOnlyCollection<IHandler> handlers;
+    protected IServiceProvider services;
     private bool initialized = false;
     private bool initialized = false;
 
 
     protected Action<UpdateableChangeExecutor>? onEnded;
     protected Action<UpdateableChangeExecutor>? onEnded;
     public virtual ExecutorType Type => ExecutorType.Regular;
     public virtual ExecutorType Type => ExecutorType.Regular;
     public virtual ExecutorStartMode StartMode => ExecutorStartMode.RightAway;
     public virtual ExecutorStartMode StartMode => ExecutorStartMode.RightAway;
 
 
-    public void Initialize(IDocument document, DocumentInternalParts internals, List<IHandler> list,
+    public void Initialize(IDocument document, DocumentInternalParts internals, IServiceProvider services,
         ChangeExecutionController controller, Action<UpdateableChangeExecutor> onEnded)
         ChangeExecutionController controller, Action<UpdateableChangeExecutor> onEnded)
     {
     {
         if (initialized)
         if (initialized)
@@ -32,22 +33,14 @@ internal abstract class UpdateableChangeExecutor
         this.document = document;
         this.document = document;
         this.internals = internals;
         this.internals = internals;
         this.controller = controller;
         this.controller = controller;
-        handlers = list;
+        this.services = services;
         this.onEnded = onEnded;
         this.onEnded = onEnded;
     }
     }
 
 
     protected T GetHandler<T>()
     protected T GetHandler<T>()
         where T : IHandler
         where T : IHandler
     {
     {
-        foreach (var handler in handlers)
-        {
-            if (handler is T t)
-            {
-                return t;
-            }
-        }
-
-        throw new DependencyNotFoundException(typeof(T));
+        return services.GetRequiredService<T>();
     }
     }
 
 
     public abstract ExecutionState Start();
     public abstract ExecutionState Start();

+ 13 - 3
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/DockDocumentViewModel.cs

@@ -1,11 +1,21 @@
-using PixiEditor.AvaloniaUI.ViewModels.Document;
+using Avalonia;
+using PixiEditor.AvaloniaUI.ViewModels.Document;
+using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 
 
 namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
 namespace PixiEditor.AvaloniaUI.ViewModels.Dock;
 
 
 internal class DockDocumentViewModel : global::Dock.Model.Avalonia.Controls.Document
 internal class DockDocumentViewModel : global::Dock.Model.Avalonia.Controls.Document
 {
 {
-    public DockDocumentViewModel(DocumentViewModel documentViewModel)
+    public static readonly StyledProperty<ViewportWindowViewModel> ViewModelProperty =
+        AvaloniaProperty.Register<DockDocumentViewModel, ViewportWindowViewModel>(nameof(ViewModel));
+
+    public ViewportWindowViewModel ViewModel
+    {
+        get { return (ViewportWindowViewModel)GetValue(ViewModelProperty); }
+        set { SetValue(ViewModelProperty, value); }
+    }
+    public DockDocumentViewModel(ViewportWindowViewModel viewportViewModel)
     {
     {
-        DataContext = documentViewModel;
+        ViewModel = viewportViewModel;
     }
     }
 }
 }

+ 0 - 1
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/DockFactory.cs

@@ -129,7 +129,6 @@ internal class DockFactory : Factory
         ContextLocator = new Dictionary<string, Func<object?>>()
         ContextLocator = new Dictionary<string, Func<object?>>()
         {
         {
             { "MainLayout", () => layout },
             { "MainLayout", () => layout },
-            { "DocumentsPane", () => layout },
             { "ToolsPane", () => layout },
             { "ToolsPane", () => layout },
         };
         };
 
 

+ 6 - 5
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Dock/PixiEditorDocumentDock.cs

@@ -1,4 +1,5 @@
 using System.Collections.Specialized;
 using System.Collections.Specialized;
+using System.Linq;
 using CommunityToolkit.Mvvm.Input;
 using CommunityToolkit.Mvvm.Input;
 using Dock.Model.Avalonia.Controls;
 using Dock.Model.Avalonia.Controls;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
 using PixiEditor.AvaloniaUI.ViewModels.Document;
@@ -13,14 +14,14 @@ internal class PixiEditorDocumentDock : DocumentDock
     public PixiEditorDocumentDock(FileViewModel manager)
     public PixiEditorDocumentDock(FileViewModel manager)
     {
     {
         this.manager = manager;
         this.manager = manager;
-        manager.Owner.DocumentManagerSubViewModel.Documents.CollectionChanged += Documents_CollectionChanged;
+        manager.Owner.WindowSubViewModel.Viewports.CollectionChanged += Viewports_CollectionChanged;
         CreateDocument = new RelayCommand(CreateDockDocument);
         CreateDocument = new RelayCommand(CreateDockDocument);
     }
     }
 
 
-    private void Documents_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
+    private void Viewports_CollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
     {
     {
-        DocumentViewModel documentVm = e.NewItems[^1] as DocumentViewModel;
-        var document = new DockDocumentViewModel(documentVm) { Title = documentVm.FileName };
+        ViewportWindowViewModel viewportVm = e.NewItems[^1] as ViewportWindowViewModel;
+        var document = new DockDocumentViewModel(viewportVm) { Title = viewportVm.Document.FileName };
 
 
         Factory?.AddDockable(this, document);
         Factory?.AddDockable(this, document);
         Factory?.SetActiveDockable(document);
         Factory?.SetActiveDockable(document);
@@ -38,7 +39,7 @@ internal class PixiEditorDocumentDock : DocumentDock
         {
         {
             b.WithSize(new VecI(64, 64));
             b.WithSize(new VecI(64, 64));
         });
         });
-        var document = new DockDocumentViewModel(doc) { Title = "hello" };
+        var document = new DockDocumentViewModel(manager.Owner.WindowSubViewModel.Viewports[^1]) { Title = "hello" };
 
 
         Factory?.AddDockable(this, document);
         Factory?.AddDockable(this, document);
         Factory?.SetActiveDockable(document);
         Factory?.SetActiveDockable(document);

+ 2 - 2
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/Document/DocumentViewModel.cs

@@ -165,8 +165,8 @@ internal partial class DocumentViewModel : ObservableObject, IDocument
 
 
     private DocumentViewModel()
     private DocumentViewModel()
     {
     {
-        var allHandlers = ViewModelMain.Current.Services.GetServices<IHandler>().ToList();
-        Internals = new DocumentInternalParts(this, allHandlers);
+        var serviceProvider = ViewModelMain.Current.Services;
+        Internals = new DocumentInternalParts(this, serviceProvider);
         Tools = new DocumentToolsModule(this, Internals);
         Tools = new DocumentToolsModule(this, Internals);
         StructureHelper = new DocumentStructureModule(this);
         StructureHelper = new DocumentStructureModule(this);
         EventInlet = new DocumentEventsModule(this, Internals);
         EventInlet = new DocumentEventsModule(this, Internals);

+ 2 - 1
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ColorsViewModel.cs

@@ -15,6 +15,7 @@ using PixiEditor.AvaloniaUI.Models.Commands.XAML;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Controllers;
 using PixiEditor.AvaloniaUI.Models.Dialogs;
 using PixiEditor.AvaloniaUI.Models.Dialogs;
 using PixiEditor.AvaloniaUI.Models.ExternalServices;
 using PixiEditor.AvaloniaUI.Models.ExternalServices;
+using PixiEditor.AvaloniaUI.Models.Handlers;
 using PixiEditor.AvaloniaUI.Models.Palettes;
 using PixiEditor.AvaloniaUI.Models.Palettes;
 using PixiEditor.AvaloniaUI.Models.Structures;
 using PixiEditor.AvaloniaUI.Models.Structures;
 using PixiEditor.AvaloniaUI.Views.Dialogs;
 using PixiEditor.AvaloniaUI.Views.Dialogs;
@@ -29,7 +30,7 @@ using Command = PixiEditor.AvaloniaUI.Models.Commands.Attributes.Commands.Comman
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 
 
 [Command.Group("PixiEditor.Colors", "PALETTE_COLORS")]
 [Command.Group("PixiEditor.Colors", "PALETTE_COLORS")]
-internal class ColorsViewModel : SubViewModel<ViewModelMain>
+internal class ColorsViewModel : SubViewModel<ViewModelMain>, IColorsHandler
 {
 {
     public AsyncRelayCommand<List<PaletteColor>> ImportPaletteCommand { get; set; }
     public AsyncRelayCommand<List<PaletteColor>> ImportPaletteCommand { get; set; }
     private PaletteProvider paletteProvider;
     private PaletteProvider paletteProvider;

+ 0 - 1
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/ViewModels/SubViewModels/ViewportWindowViewModel.cs

@@ -8,7 +8,6 @@ namespace PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 internal class ViewportWindowViewModel : SubViewModel<WindowViewModel>
 internal class ViewportWindowViewModel : SubViewModel<WindowViewModel>
 {
 {
     public DocumentViewModel Document { get; }
     public DocumentViewModel Document { get; }
-
     public ExecutionTrigger<VecI> CenterViewportTrigger { get; } = new ExecutionTrigger<VecI>();
     public ExecutionTrigger<VecI> CenterViewportTrigger { get; } = new ExecutionTrigger<VecI>();
     public ExecutionTrigger<double> ZoomViewportTrigger { get; } = new ExecutionTrigger<double>();
     public ExecutionTrigger<double> ZoomViewportTrigger { get; } = new ExecutionTrigger<double>();
 
 

+ 9 - 8
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml

@@ -10,24 +10,25 @@
              xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:document="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Document"
              xmlns:document="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.Document"
              xmlns:viewModels1="clr-namespace:PixiEditor.AvaloniaUI.ViewModels"
              xmlns:viewModels1="clr-namespace:PixiEditor.AvaloniaUI.ViewModels"
+             xmlns:subViewModels="clr-namespace:PixiEditor.AvaloniaUI.ViewModels.SubViewModels"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
              x:Class="PixiEditor.AvaloniaUI.Views.Dock.DocumentTemplate">
              x:Class="PixiEditor.AvaloniaUI.Views.Dock.DocumentTemplate">
     <userControls:Viewport
     <userControls:Viewport
-                                             CenterViewportTrigger="{Binding CenterViewportTrigger}"
-                                            ZoomViewportTrigger="{Binding ZoomViewportTrigger}"
-                                            MouseDownCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseDownCommand}"
-                                            MouseMoveCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseMoveCommand}"
-                                            MouseUpCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseUpCommand}"
+                                             CenterViewportTrigger="{Binding ViewModel.DockCenterViewportTrigger}"
+                                            ZoomViewportTrigger="{Binding ViewModel.ZoomViewportTrigger}"
+                                            MouseDownCommand="{Binding Path=IoSubViewModel.MouseDownCommand, Source={viewModels1:MainVM}}"
+                                            MouseMoveCommand="{Binding Path=IoSubViewModel.MouseMoveCommand, Source={viewModels1:MainVM}}"
+                                            MouseUpCommand="{Binding Path=IoSubViewModel.MouseUpCommand, Source={viewModels1:MainVM}}"
                                             MiddleMouseClickedCommand="{Binding IoSubViewModel.PreviewMouseMiddleButtonCommand, Source={viewModels1:MainVM}}"
                                             MiddleMouseClickedCommand="{Binding IoSubViewModel.PreviewMouseMiddleButtonCommand, Source={viewModels1:MainVM}}"
                                             Cursor="{Binding ToolsSubViewModel.ToolCursor, Source={viewModels1:MainVM}}"
                                             Cursor="{Binding ToolsSubViewModel.ToolCursor, Source={viewModels1:MainVM}}"
                                             GridLinesVisible="{Binding ViewportSubViewModel.GridLinesEnabled, Source={viewModels1:MainVM}}"
                                             GridLinesVisible="{Binding ViewportSubViewModel.GridLinesEnabled, Source={viewModels1:MainVM}}"
                                             ZoomMode="{Binding ToolsSubViewModel.ActiveTool, Source={viewModels1:MainVM}, Converter={converters:ActiveToolToZoomModeConverter}}"
                                             ZoomMode="{Binding ToolsSubViewModel.ActiveTool, Source={viewModels1:MainVM}, Converter={converters:ActiveToolToZoomModeConverter}}"
                                             ZoomOutOnClick="{Binding ToolsSubViewModel.ZoomTool.ZoomOutOnClick, Source={viewModels1:MainVM}}"
                                             ZoomOutOnClick="{Binding ToolsSubViewModel.ZoomTool.ZoomOutOnClick, Source={viewModels1:MainVM}}"
                                             UseTouchGestures="{Binding StylusSubViewModel.UseTouchGestures, Source={viewModels1:MainVM}}"
                                             UseTouchGestures="{Binding StylusSubViewModel.UseTouchGestures, Source={viewModels1:MainVM}}"
-                                            FlipX="{Binding FlipX, Mode=TwoWay}"
-                                            FlipY="{Binding FlipY, Mode=TwoWay}"
+                                            FlipX="{Binding ViewModel.FlipX, Mode=TwoWay}"
+                                            FlipY="{Binding ViewModel.FlipY, Mode=TwoWay}"
                                             ContextRequested="Viewport_OnContextMenuOpening"
                                             ContextRequested="Viewport_OnContextMenuOpening"
-                                            Document="{Binding Document}">
+                                            Document="{Binding ViewModel.Document}">
                                             <userControls:Viewport.ContextMenu>
                                             <userControls:Viewport.ContextMenu>
                                                 <ContextMenu DataContext="{Binding PlacementTarget.Document, RelativeSource={RelativeSource Self}}">
                                                 <ContextMenu DataContext="{Binding PlacementTarget.Document, RelativeSource={RelativeSource Self}}">
                                                     <ContextMenu.Template>
                                                     <ContextMenu.Template>

+ 6 - 3
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Dock/DocumentTemplate.axaml.cs

@@ -3,6 +3,9 @@ using Avalonia.Controls;
 using Avalonia.Markup.Xaml;
 using Avalonia.Markup.Xaml;
 using PixiEditor.AvaloniaUI.Models.Preferences;
 using PixiEditor.AvaloniaUI.Models.Preferences;
 using PixiEditor.AvaloniaUI.ViewModels;
 using PixiEditor.AvaloniaUI.ViewModels;
+using PixiEditor.AvaloniaUI.ViewModels.Dock;
+using PixiEditor.AvaloniaUI.ViewModels.Document;
+using PixiEditor.AvaloniaUI.ViewModels.SubViewModels;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.Tools;
 using PixiEditor.AvaloniaUI.ViewModels.Tools.Tools;
 
 
 namespace PixiEditor.AvaloniaUI.Views.Dock;
 namespace PixiEditor.AvaloniaUI.Views.Dock;
@@ -16,8 +19,8 @@ public partial class DocumentTemplate : UserControl
 
 
     private void Viewport_OnContextMenuOpening(object? sender, ContextRequestedEventArgs e)
     private void Viewport_OnContextMenuOpening(object? sender, ContextRequestedEventArgs e)
     {
     {
-        ViewModelMain vm = (ViewModelMain)DataContext;
-        var tools = vm.ToolsSubViewModel;
+        ViewportWindowViewModel vm = ((DockDocumentViewModel)DataContext).ViewModel;
+        var tools = vm.Owner.Owner.ToolsSubViewModel;
 
 
         var superSpecialBrightnessTool = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool is BrightnessToolViewModel;
         var superSpecialBrightnessTool = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool is BrightnessToolViewModel;
         var superSpecialColorPicker = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool is ColorPickerToolViewModel;
         var superSpecialColorPicker = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool is ColorPickerToolViewModel;
@@ -28,7 +31,7 @@ public partial class DocumentTemplate : UserControl
             return;
             return;
         }
         }
 
 
-        var useContextMenu = vm.ToolsSubViewModel.RightClickMode == RightClickMode.ContextMenu;
+        var useContextMenu = vm.Owner.Owner.ToolsSubViewModel.RightClickMode == RightClickMode.ContextMenu;
         var usesErase = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool.IsErasable;
         var usesErase = tools.RightClickMode == RightClickMode.Erase && tools.ActiveTool.IsErasable;
         var usesSecondaryColor = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool.UsesColor;
         var usesSecondaryColor = tools.RightClickMode == RightClickMode.SecondaryColor && tools.ActiveTool.UsesColor;
 
 

+ 2 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml

@@ -130,6 +130,8 @@
                 d:Height="64"
                 d:Height="64"
                 HorizontalAlignment="Center"
                 HorizontalAlignment="Center"
                 VerticalAlignment="Center"
                 VerticalAlignment="Center"
+                Width="64"
+                Height="64"
                 DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}}"
                 DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}}"
                 RenderOptions.BitmapInterpolationMode="None">
                 RenderOptions.BitmapInterpolationMode="None">
                 <Border.Background>
                 <Border.Background>

+ 16 - 4
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/Main/Viewport.axaml.cs

@@ -397,16 +397,28 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         Point pos = e.GetPosition(MainImage);
         Point pos = e.GetPosition(MainImage);
         VecD conv = new VecD(pos.X, pos.Y);
         VecD conv = new VecD(pos.X, pos.Y);
 
 
-        if (MouseMoveCommand.CanExecute(conv))
-            MouseMoveCommand.Execute(conv);
+        MouseButton mouseButton = e.GetCurrentPoint(this).Properties.PointerUpdateKind switch
+        {
+            PointerUpdateKind.LeftButtonPressed => MouseButton.Left,
+            PointerUpdateKind.RightButtonPressed => MouseButton.Right,
+            _ => MouseButton.Middle
+        };
+
+        MouseOnCanvasEventArgs parameter = new(mouseButton, conv);
+
+        if (MouseMoveCommand.CanExecute(parameter))
+            MouseMoveCommand.Execute(parameter);
     }
     }
 
 
     private void Image_MouseUp(object? sender, PointerReleasedEventArgs e)
     private void Image_MouseUp(object? sender, PointerReleasedEventArgs e)
     {
     {
         if (MouseUpCommand is null)
         if (MouseUpCommand is null)
             return;
             return;
-        if (MouseUpCommand.CanExecute(e.InitialPressMouseButton))
-            MouseUpCommand.Execute(e.InitialPressMouseButton);
+
+        Point pos = e.GetPosition(MainImage);
+        MouseOnCanvasEventArgs parameter = new(e.InitialPressMouseButton, new VecD(pos.X, pos.Y));
+        if (MouseUpCommand.CanExecute(parameter))
+            MouseUpCommand.Execute(parameter);
     }
     }
 
 
     private void CenterZoomboxContent(object? sender, VecI args)
     private void CenterZoomboxContent(object? sender, VecI args)

+ 1 - 0
src/PixiEditor.Avalonia/PixiEditor.AvaloniaUI/Views/MainWindow.axaml.cs

@@ -5,6 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
 using Microsoft.Extensions.DependencyInjection;
 using Microsoft.Extensions.DependencyInjection;
 using PixiEditor.AvaloniaUI.Helpers;
 using PixiEditor.AvaloniaUI.Helpers;
 using PixiEditor.AvaloniaUI.Models.AppExtensions;
 using PixiEditor.AvaloniaUI.Models.AppExtensions;
+using PixiEditor.AvaloniaUI.Models.Services;
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Skia;
 using PixiEditor.DrawingApi.Skia;
 using PixiEditor.Extensions.Common.UserPreferences;
 using PixiEditor.Extensions.Common.UserPreferences;

+ 2 - 2
src/PixiEditor.Zoombox/Zoombox.axaml.cs

@@ -405,10 +405,10 @@ public partial class Zoombox : UserControl, INotifyPropertyChanged
 
 
     private void OnScroll(object sender, PointerWheelEventArgs e)
     private void OnScroll(object sender, PointerWheelEventArgs e)
     {
     {
-        double abs = Math.Abs(-e.Delta.Y / 100.0);
+        double abs = Math.Abs(e.Delta.Y / 100.0);
         for (int i = 0; i < abs; i++)
         for (int i = 0; i < abs; i++)
         {
         {
-            ZoomInto(ToVecD(e.GetPosition(uc)), -e.Delta.Y / 100.0);
+            ZoomInto(ToVecD(e.GetPosition(uc)), e.Delta.Y / 100.0);
         }
         }
     }
     }
 
 

+ 56 - 53
src/PixiEditor/Helpers/Extensions/ServiceCollectionHelpers.cs

@@ -29,59 +29,62 @@ internal static class ServiceCollectionHelpers
     /// <summary>
     /// <summary>
     /// Adds all the services required to fully run PixiEditor's MainWindow
     /// Adds all the services required to fully run PixiEditor's MainWindow
     /// </summary>
     /// </summary>
-    public static IServiceCollection AddPixiEditor(this IServiceCollection collection, ExtensionLoader extensionLoader) => collection
-        .AddSingleton<ViewModelMain>()
-        .AddSingleton<IPreferences, PreferencesSettings>()
-        .AddSingleton<ILocalizationProvider, LocalizationProvider>(x => new LocalizationProvider(extensionLoader))
-        // View Models
-        .AddSingleton<StylusViewModel>()
-        .AddSingleton<WindowViewModel>()
-        .AddSingleton<ToolsViewModel>()
-        .AddSingleton<FileViewModel>()
-        .AddSingleton<UpdateViewModel>()
-        .AddSingleton<IoViewModel>()
-        .AddSingleton<LayersViewModel>()
-        .AddSingleton<ClipboardViewModel>()
-        .AddSingleton<UndoViewModel>()
-        .AddSingleton<SelectionViewModel>()
-        .AddSingleton<ViewOptionsViewModel>()
-        .AddSingleton<ColorsViewModel>()
-        .AddSingleton<RegistryViewModel>()
-        .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
-        .AddSingleton<DebugViewModel>()
-        .AddSingleton<SearchViewModel>()
-        .AddSingleton<AdditionalContentViewModel>()
-        .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModelMain>(), extensionLoader))
-        // Controllers
-        .AddSingleton<ShortcutController>()
-        .AddSingleton<CommandController>()
-        .AddSingleton<DocumentManagerViewModel>()
-        // Tools
-        .AddSingleton<ToolViewModel, MoveViewportToolViewModel>()
-        .AddSingleton<ToolViewModel, RotateViewportToolViewModel>()
-        .AddSingleton<ToolViewModel, MoveToolViewModel>()
-        .AddSingleton<ToolViewModel, PenToolViewModel>()
-        .AddSingleton<ToolViewModel, SelectToolViewModel>()
-        .AddSingleton<ToolViewModel, MagicWandToolViewModel>()
-        .AddSingleton<ToolViewModel, LassoToolViewModel>()
-        .AddSingleton<ToolViewModel, FloodFillToolViewModel>()
-        .AddSingleton<ToolViewModel, LineToolViewModel>()
-        .AddSingleton<ToolViewModel, EllipseToolViewModel>()
-        .AddSingleton<ToolViewModel, RectangleToolViewModel>()
-        .AddSingleton<ToolViewModel, EraserToolViewModel>()
-        .AddSingleton<ToolViewModel, ColorPickerToolViewModel>()
-        .AddSingleton<ToolViewModel, BrightnessToolViewModel>()
-        .AddSingleton<ToolViewModel, ZoomToolViewModel>()
-        // Palette Parsers
-        .AddSingleton<PaletteFileParser, JascFileParser>()
-        .AddSingleton<PaletteFileParser, ClsFileParser>()
-        .AddSingleton<PaletteFileParser, PngPaletteParser>()
-        .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
-        .AddSingleton<PaletteFileParser, HexPaletteParser>()
-        .AddSingleton<PaletteFileParser, GimpGplParser>()
-        .AddSingleton<PaletteFileParser, PixiPaletteParser>()
-        // Palette data sources
-        .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>();
+    public static IServiceCollection AddPixiEditor(this IServiceCollection collection, ExtensionLoader extensionLoader)
+    {
+        return collection
+            .AddSingleton<ViewModelMain>()
+            .AddSingleton<IPreferences, PreferencesSettings>()
+            .AddSingleton<ILocalizationProvider, LocalizationProvider>(x => new LocalizationProvider(extensionLoader))
+            // View Models
+            .AddSingleton<StylusViewModel>()
+            .AddSingleton<WindowViewModel>()
+            .AddSingleton<ToolsViewModel>()
+            .AddSingleton<FileViewModel>()
+            .AddSingleton<UpdateViewModel>()
+            .AddSingleton<IoViewModel>()
+            .AddSingleton<LayersViewModel>()
+            .AddSingleton<ClipboardViewModel>()
+            .AddSingleton<UndoViewModel>()
+            .AddSingleton<SelectionViewModel>()
+            .AddSingleton<ViewOptionsViewModel>()
+            .AddSingleton<ColorsViewModel>()
+            .AddSingleton<RegistryViewModel>()
+            .AddSingleton(static x => new DiscordViewModel(x.GetService<ViewModelMain>(), "764168193685979138"))
+            .AddSingleton<DebugViewModel>()
+            .AddSingleton<SearchViewModel>()
+            .AddSingleton<AdditionalContentViewModel>()
+            .AddSingleton(x => new ExtensionsViewModel(x.GetService<ViewModelMain>(), extensionLoader))
+            // Controllers
+            .AddSingleton<ShortcutController>()
+            .AddSingleton<CommandController>()
+            .AddSingleton<DocumentManagerViewModel>()
+            // Tools
+            .AddSingleton<ToolViewModel, MoveViewportToolViewModel>()
+            .AddSingleton<ToolViewModel, RotateViewportToolViewModel>()
+            .AddSingleton<ToolViewModel, MoveToolViewModel>()
+            .AddSingleton<ToolViewModel, PenToolViewModel>()
+            .AddSingleton<ToolViewModel, SelectToolViewModel>()
+            .AddSingleton<ToolViewModel, MagicWandToolViewModel>()
+            .AddSingleton<ToolViewModel, LassoToolViewModel>()
+            .AddSingleton<ToolViewModel, FloodFillToolViewModel>()
+            .AddSingleton<ToolViewModel, LineToolViewModel>()
+            .AddSingleton<ToolViewModel, EllipseToolViewModel>()
+            .AddSingleton<ToolViewModel, RectangleToolViewModel>()
+            .AddSingleton<ToolViewModel, EraserToolViewModel>()
+            .AddSingleton<ToolViewModel, ColorPickerToolViewModel>()
+            .AddSingleton<ToolViewModel, BrightnessToolViewModel>()
+            .AddSingleton<ToolViewModel, ZoomToolViewModel>()
+            // Palette Parsers
+            .AddSingleton<PaletteFileParser, JascFileParser>()
+            .AddSingleton<PaletteFileParser, ClsFileParser>()
+            .AddSingleton<PaletteFileParser, PngPaletteParser>()
+            .AddSingleton<PaletteFileParser, PaintNetTxtParser>()
+            .AddSingleton<PaletteFileParser, HexPaletteParser>()
+            .AddSingleton<PaletteFileParser, GimpGplParser>()
+            .AddSingleton<PaletteFileParser, PixiPaletteParser>()
+            // Palette data sources
+            .AddSingleton<PaletteListDataSource, LocalPalettesFetcher>();
+    }
 
 
     public static IServiceCollection AddExtensionServices(this IServiceCollection collection) =>
     public static IServiceCollection AddExtensionServices(this IServiceCollection collection) =>
         collection.AddSingleton<IWindowProvider, WindowProvider>()
         collection.AddSingleton<IWindowProvider, WindowProvider>()