Răsfoiți Sursa

Fix discord rich presence, fully delete Document

Equbuxu 3 ani în urmă
părinte
comite
2de908cd60

+ 4 - 5
src/PixiEditor/Helpers/Extensions/ParserHelpers.cs

@@ -1,14 +1,13 @@
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.DataHolders.Document;
 using PixiEditor.Parser;
 
 namespace PixiEditor.Helpers.Extensions;
 
 internal static class ParserHelpers
 {
-    public static Document ToDocument(this SerializableDocument serializableDocument)
+    /*public static Document ToDocument(this SerializableDocument serializableDocument)
     {
-        /*
+        
         Document document = new Document(serializableDocument.Width, serializableDocument.Height)
         {
             Layers = serializableDocument.ToLayers(),
@@ -24,9 +23,9 @@ internal static class ParserHelpers
         }
         document.Renderer.ForceRerender();
 
-        return document;*/
+        return document;
         throw new NotImplementedException();
-    }
+    }*/
     /*
     public static WpfObservableRangeCollection<Layer> ToLayers(this SerializableDocument document)
     {

+ 0 - 1
src/PixiEditor/Helpers/UI/PanelsStyleSelector.cs

@@ -1,7 +1,6 @@
 using System.Windows;
 using System.Windows.Controls;
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.DataHolders.Document;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Helpers.UI;

+ 6 - 6
src/PixiEditor/Models/Controllers/ClipboardController.cs

@@ -3,8 +3,8 @@ using System.Runtime.InteropServices;
 using System.Windows;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.DataHolders.Document;
 using PixiEditor.Models.IO;
+using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Models.Controllers;
 
@@ -14,21 +14,21 @@ internal static class ClipboardController
         Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
         "PixiEditor",
         "Copied.png");
-
+    /*
     /// <summary>
     /// Copies the selection to clipboard in PNG, Bitmap and DIB formats. <para/>
     /// Also serailizes the <paramref name="document"/> in the PIXI format and copies it to the clipboard.
     /// </summary>
     public static void CopyToClipboard(Document document)
     {
-        /*CopyToClipboard(
+        CopyToClipboard(
             document.Layers.Where(x => document.GetFinalLayerIsVisible(x) && x.IsActive).ToArray(),
             document.ActiveSelection.SelectionLayer,
             document.LayerStructure,
             document.Width,
             document.Height,
-            null/*document.ToSerializable());*/
-    }
+            null/*document.ToSerializable());
+    }*/
     /*
     private static Surface CreateMaskedCombinedSurface(Layer[] layers, LayerStructure structure, Layer selLayer)
     {
@@ -98,7 +98,7 @@ internal static class ClipboardController
     /// <summary>
     ///     Pastes image from clipboard into new layer.
     /// </summary>
-    public static void PasteFromClipboard(Document document)
+    public static void PasteFromClipboard(DocumentViewModel document)
     {
         /*
         Layer[] layers;

+ 3 - 2
src/PixiEditor/Models/DataHolders/CrashReport.cs

@@ -4,6 +4,7 @@ using System.IO.Compression;
 using System.Reflection;
 using System.Text;
 using PixiEditor.Helpers;
+using PixiEditor.ViewModels.SubViewModels.Document;
 
 namespace PixiEditor.Models.DataHolders;
 
@@ -85,9 +86,9 @@ internal class CrashReport : IDisposable
 
     public int GetDocumentCount() => ZipFile.Entries.Where(x => x.FullName.EndsWith(".pixi")).Count();
 
-    public List<Document.Document> RecoverDocuments()
+    public List<DocumentViewModel> RecoverDocuments()
     {
-        return new List<Document.Document>();
+        return new List<DocumentViewModel>();
         /*
         List<Document> documents = new();
         foreach (ZipArchiveEntry entry in ZipFile.Entries.Where(x => x.FullName.EndsWith(".pixi")))

+ 0 - 21
src/PixiEditor/Models/DataHolders/Document/Document.Commands.cs

@@ -1,21 +0,0 @@
-using PixiEditor.Helpers;
-
-namespace PixiEditor.Models.DataHolders.Document;
-
-internal partial class Document
-{
-    public RelayCommand RequestCloseDocumentCommand { get; set; }
-
-    public RelayCommand SetAsActiveOnClickCommand { get; set; }
-
-    private void SetRelayCommands()
-    {
-        RequestCloseDocumentCommand = new RelayCommand(RequestCloseDocument);
-        //SetAsActiveOnClickCommand = new RelayCommand(SetAsActiveOnClick);
-    }
-
-    private void RequestCloseDocument(object obj)
-    {
-        
-    }
-}

+ 0 - 11
src/PixiEditor/Models/DataHolders/Document/Document.Discord.cs

@@ -1,11 +0,0 @@
-namespace PixiEditor.Models.DataHolders.Document;
-
-internal partial class Document
-{
-    private readonly DateTime openedUtc = DateTime.UtcNow;
-
-    public DateTime OpenedUTC
-    {
-        get => openedUtc;
-    }
-}

+ 4 - 0
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -8,6 +8,7 @@ using PixiEditor.ChangeableDocument.ChangeInfos.Properties;
 using PixiEditor.ChangeableDocument.ChangeInfos.Root;
 using PixiEditor.ChangeableDocument.ChangeInfos.Structure;
 using PixiEditor.ChangeableDocument.Enums;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DocumentPassthroughActions;
 using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Document;
@@ -358,6 +359,7 @@ internal class DocumentUpdater
             doc.RaisePropertyChanged(nameof(doc.SelectedStructureMember));
             doc.RaisePropertyChanged(nameof(memberVM.Selection));
         }
+        doc.InternalRaiseLayersChanged(new LayersChangedEventArgs(info.GuidValue, LayerAction.Add));
     }
 
     private void ProcessDeleteStructureMember(DeleteStructureMember_ChangeInfo info)
@@ -367,6 +369,7 @@ internal class DocumentUpdater
         if (doc.SelectedStructureMember == memberVM)
             doc.InternalSetSelectedMember(null);
         doc.InternalClearSoftSelectedMembers();
+        doc.InternalRaiseLayersChanged(new LayersChangedEventArgs(info.GuidValue, LayerAction.Remove));
     }
 
     private void ProcessUpdateStructureMemberIsVisible(StructureMemberIsVisible_ChangeInfo info)
@@ -395,5 +398,6 @@ internal class DocumentUpdater
 
         curFolderVM.Children.Remove(memberVM);
         targetFolderVM.Children.Insert(info.NewIndex, memberVM);
+        doc.InternalRaiseLayersChanged(new LayersChangedEventArgs(info.GuidValue, LayerAction.Move));
     }
 }

+ 2 - 3
src/PixiEditor/Models/Enums/LayerAction.cs

@@ -4,6 +4,5 @@ public enum LayerAction
 {
     Add,
     Remove,
-    Move,
-    SetActive
-}
+    Move
+}

+ 3 - 3
src/PixiEditor/Models/IO/Exporter.cs

@@ -6,9 +6,9 @@ using System.Windows.Media.Imaging;
 using Microsoft.Win32;
 using PixiEditor.Helpers;
 using PixiEditor.Models.DataHolders;
-using PixiEditor.Models.DataHolders.Document;
 using PixiEditor.Models.Dialogs;
 using PixiEditor.Models.Enums;
+using PixiEditor.ViewModels.SubViewModels.Document;
 using SkiaSharp;
 
 namespace PixiEditor.Models.IO;
@@ -20,7 +20,7 @@ internal class Exporter
     /// </summary>
     /// <param name="document">Document to save.</param>
     /// <param name="path">Path where file was saved.</param>
-    public static bool SaveAsEditableFileWithDialog(Document document, out string path)
+    public static bool SaveAsEditableFileWithDialog(DocumentViewModel document, out string path)
     {
         SaveFileDialog dialog = new SaveFileDialog
         {
@@ -46,7 +46,7 @@ internal class Exporter
     /// <param name="document">Document to be saved.</param>
     /// <param name="path">Path where to save file.</param>
     /// <returns>Path.</returns>
-    public static string SaveAsEditableFile(Document document, string path, FileType requestedType = FileType.Unset)
+    public static string SaveAsEditableFile(DocumentViewModel document, string path, FileType requestedType = FileType.Unset)
     {
         return path;
         /*

+ 8 - 1
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -10,6 +10,7 @@ using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.Helpers;
+using PixiEditor.Models.Controllers;
 using PixiEditor.Models.DataHolders;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.DocumentModels.UpdateableChangeExecutors;
@@ -22,6 +23,8 @@ namespace PixiEditor.ViewModels.SubViewModels.Document;
 #nullable enable
 internal class DocumentViewModel : NotifyableObject
 {
+    public event EventHandler<LayersChangedEventArgs> LayersChanged;
+
     private bool busy = false;
     public bool Busy
     {
@@ -60,6 +63,8 @@ internal class DocumentViewModel : NotifyableObject
         }
     }
 
+    public DateTime OpenedUTC { get; } = DateTime.UtcNow;
+
     private bool horizontalSymmetryAxisEnabled;
     public bool HorizontalSymmetryAxisEnabledBindable
     {
@@ -161,6 +166,9 @@ internal class DocumentViewModel : NotifyableObject
 
     #region Internal Methods
     // these are intended to only be called from DocumentUpdater
+
+    public void InternalRaiseLayersChanged(LayersChangedEventArgs args) => LayersChanged?.Invoke(this, args);
+
     public void InternalSetVerticalSymmetryAxisEnabled(bool verticalSymmetryAxisEnabled)
     {
         this.verticalSymmetryAxisEnabled = verticalSymmetryAxisEnabled;
@@ -379,7 +387,6 @@ internal class DocumentViewModel : NotifyableObject
         }
     }
 
-
     #region Events
     public void OnKeyDown(Key args) => Helpers.ChangeController.OnKeyDown(args);
     public void OnKeyUp(Key args) => Helpers.ChangeController.OnKeyUp(args);

+ 30 - 14
src/PixiEditor/ViewModels/SubViewModels/Main/DiscordViewModel.cs

@@ -1,4 +1,7 @@
-using DiscordRPC;
+using System.ComponentModel;
+using DiscordRPC;
+using PixiEditor.Models.Controllers;
+using PixiEditor.Models.Events;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.ViewModels.SubViewModels.Document;
 
@@ -77,7 +80,7 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
     public DiscordViewModel(ViewModelMain owner, string clientId)
         : base(owner)
     {
-        //Owner.BitmapManager.DocumentChanged += DocumentChanged;
+        Owner.DocumentManagerSubViewModel.ActiveDocumentChanged += DocumentChanged;
         this.clientId = clientId;
 
         Enabled = IPreferences.Current.GetPreference("EnableRichPresence", true);
@@ -102,9 +105,8 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
         client = null;
     }
 
-    public void UpdatePresence(DocumentViewModel document)
+    public void UpdatePresence(DocumentViewModel? document)
     {
-        /*
         if (client == null)
         {
             return;
@@ -116,7 +118,7 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
         {
             richPresence.WithTimestamps(new Timestamps(document.OpenedUTC));
 
-            richPresence.Details = ShowDocumentName ? $"Editing {document.Name}".Limit(128) : "Editing an image";
+            richPresence.Details = ShowDocumentName ? $"Editing {document.FileName}".Limit(128) : "Editing an image";
 
             string state = string.Empty;
 
@@ -132,14 +134,27 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
 
             if (ShowLayerCount)
             {
-                state += document.Layers.Count == 1 ? "1 Layer" : $"{document.Layers.Count} Layers";
+                int count = CountLayers(document.StructureRoot);
+                state += count == 1 ? "1 Layer" : $"{count} Layers";
             }
 
             richPresence.State = state;
         }
 
         client.SetPresence(richPresence);
-        */
+    }
+
+    private int CountLayers(FolderViewModel folder)
+    {
+        int counter = 0;
+        foreach (var child in folder.Children)
+        {
+            if (child is LayerViewModel)
+                counter++;
+            else if (child is FolderViewModel innerFolder)
+                counter += CountLayers(innerFolder);
+        }
+        return counter;
     }
 
     public void Dispose()
@@ -168,8 +183,8 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
             }
         };
     }
-    /*
-    private void DocumentChanged(object sender, Models.Events.DocumentChangedEventArgs e)
+    
+    private void DocumentChanged(object sender, DocumentChangedEventArgs e)
     {
         if (currentDocument != null)
         {
@@ -186,16 +201,17 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
             currentDocument.LayersChanged += DocumentLayerChanged;
         }
     }
-    */
 
-    private void DocumentLayerChanged(object sender, Models.Controllers.LayersChangedEventArgs e)
+    private void DocumentLayerChanged(object sender, LayersChangedEventArgs e)
     {
         UpdatePresence(currentDocument);
     }
 
-    private void DocumentPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
+    private void DocumentPropertyChanged(object sender, PropertyChangedEventArgs e)
     {
-        if (e.PropertyName == "Name" || e.PropertyName == "Width" || e.PropertyName == "Height")
+        if (e.PropertyName == nameof(currentDocument.FileName)
+            || e.PropertyName == nameof(currentDocument.Width)
+            || e.PropertyName == nameof(currentDocument.Height))
         {
             UpdatePresence(currentDocument);
         }
@@ -203,7 +219,7 @@ internal class DiscordViewModel : SubViewModel<ViewModelMain>, IDisposable
 
     private void OnReady(object sender, DiscordRPC.Message.ReadyMessage args)
     {
-        //UpdatePresence(Owner.BitmapManager.ActiveDocument);
+        UpdatePresence(Owner.DocumentManagerSubViewModel.ActiveDocument);
     }
 
     ~DiscordViewModel()

+ 1 - 2
src/PixiEditor/Views/MainWindow.xaml.cs

@@ -4,7 +4,6 @@ using System.Windows.Input;
 using System.Windows.Interop;
 using System.Windows.Media.Imaging;
 using Microsoft.Extensions.DependencyInjection;
-using PixiEditor.Models.DataHolders.Document;
 using PixiEditor.Models.IO;
 using PixiEditor.Models.UserPreferences;
 using PixiEditor.ViewModels.SubViewModels.Document;
@@ -54,7 +53,7 @@ internal partial class MainWindow : Window
         });
     }
 
-    public static MainWindow CreateWithDocuments(IEnumerable<Document> documents)
+    public static MainWindow CreateWithDocuments(IEnumerable<DocumentViewModel> documents)
     {
         /*
         MainWindow window = new();

+ 0 - 138
src/PixiEditor/Views/UserControls/DrawingViewPort.xaml

@@ -1,138 +0,0 @@
-<UserControl
-    x:ClassModifier="internal"
-    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-    xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
-    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
-    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-    xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
-    xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
-    xmlns:dataholders="clr-namespace:PixiEditor.Models.DataHolders"
-    xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
-    xmlns:sys="clr-namespace:System;assembly=System.Runtime"
-    xmlns:document="clr-namespace:PixiEditor.Models.DataHolders.Document"
-    x:Class="PixiEditor.Views.UserControls.DrawingViewPort"
-    mc:Ignorable="d"
-    d:DesignHeight="450" d:DesignWidth="800" x:Name="uc">
-    <UserControl.Resources>
-        <converters:BoolToIntConverter x:Key="BoolToIntConverter" />
-        <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
-        <converters:IntToViewportRectConverter x:Key="IntToViewportRectConverter" />
-        <converters:ZoomToViewportConverter x:Key="ZoomToViewportConverter" />
-    </UserControl.Resources>
-
-    <local:Zoombox x:Name="zoombox" ClipToBounds="True" d:DataContext="{d:DesignInstance document:Document}"
-                   UseTouchGestures="{Binding UseTouchGestures, ElementName=uc}">
-        <i:Interaction.Triggers>
-            <i:EventTrigger EventName="MouseMove">
-                <i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=uc}" PassEventArgsToCommand="True" />
-            </i:EventTrigger>
-            <i:EventTrigger EventName="MouseDown">
-                <i:InvokeCommandAction Command="{Binding MouseDownCommand, ElementName=uc}" PassEventArgsToCommand="True" />
-            </i:EventTrigger>
-            <i:EventTrigger EventName="MouseUp">
-                <i:InvokeCommandAction Command="{Binding MouseUpCommand, ElementName=uc}" PassEventArgsToCommand="True" />
-            </i:EventTrigger>
-            <i:EventTrigger EventName="PreviewMouseDown">
-                <i:InvokeCommandAction Command="{Binding PreviewMouseDownCommand, ElementName=uc}"/>
-            </i:EventTrigger>
-            <i:EventTrigger EventName="StylusButtonDown">
-                <i:InvokeCommandAction Command="{Binding StylusButtonDownCommand, ElementName=uc}"
-                                        PassEventArgsToCommand="True"/>
-            </i:EventTrigger>
-            <i:EventTrigger EventName="StylusButtonUp">
-                <i:InvokeCommandAction Command="{Binding StylusButtonUpCommand, ElementName=uc}"
-                                        PassEventArgsToCommand="True"/>
-            </i:EventTrigger>
-            <i:EventTrigger EventName="StylusSystemGesture">
-                <i:InvokeCommandAction Command="{Binding StylusGestureCommand, ElementName=uc}"
-                                        PassEventArgsToCommand="True"/>
-            </i:EventTrigger>
-            <i:EventTrigger EventName="StylusOutOfRange">
-                <i:InvokeCommandAction Command="{Binding StylusOutOfRangeCommand, ElementName=uc}"
-                                        PassEventArgsToCommand="True"/>
-            </i:EventTrigger>
-        </i:Interaction.Triggers>
-        <i:Interaction.Behaviors>
-            <behaviors:MouseBehavior RelativeTo="{Binding ElementName=zoombox, Path=AdditionalContent}"
-                                     MouseX="{Binding MouseXOnCanvas, Mode=TwoWay, ElementName=uc}"
-                                     MouseY="{Binding MouseYOnCanvas, Mode=TwoWay, ElementName=uc}" />
-        </i:Interaction.Behaviors>
-
-        <local:Zoombox.AdditionalContent>
-            <Canvas Width="{Binding Width}" Height="{Binding Height}"
-                    d:Width="400" d:Height="400"
-                    Loaded="OnCanvasLoaded"
-                    VerticalAlignment="Center" HorizontalAlignment="Center"
-                    RenderOptions.BitmapScalingMode="NearestNeighbor">
-                <Canvas.Background>
-                    <ImageBrush ImageSource="/Images/CheckerTile.png" TileMode="Tile" ViewportUnits="Absolute">
-                        <ImageBrush.Viewport>
-                            <Binding Path="Zoom" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:Zoombox}}" Converter="{StaticResource ZoomToViewportConverter}">
-                                <Binding.ConverterParameter>
-                                    <sys:Double>16</sys:Double>
-                                </Binding.ConverterParameter>
-                            </Binding>
-                        </ImageBrush.Viewport>
-                    </ImageBrush>
-                </Canvas.Background>
-
-                <local:ReferenceLayerView ShowReferenceLayer="{Binding ReferenceLayer.IsVisible}"
-                                          HideReferenceLayer="{Binding XamlAccesibleViewModel.BitmapManager.HideReferenceLayer}"
-                                          Width="{Binding Width}" Height="{Binding Height}"
-                                          RenderOptions.BitmapScalingMode="NearestNeighbor"/>
-
-                <Image Source="{Binding PreviewLayerRenderer.FinalBitmap}" Panel.ZIndex="2"
-                       RenderOptions.BitmapScalingMode="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Zoombox}}, Path=Zoom, Converter={converters:ZoomLevelToBitmapScalingModeConverter}}" 
-                       Stretch="Uniform"
-                       Width="{Binding Width}" Height="{Binding Height}"/>
-
-
-                <Image VerticalAlignment="Top" HorizontalAlignment="Left" Source="{Binding Renderer.FinalBitmap}"
-                       RenderOptions.BitmapScalingMode="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:Zoombox}}, Path=Zoom, Converter={converters:ZoomLevelToBitmapScalingModeConverter}}" 
-                       Stretch="Uniform" 
-                       Visibility="{Binding XamlAccesibleViewModel.BitmapManager.OnlyReferenceLayer, Converter={InverseBoolToVisibilityConverter}}"/>
-
-                <Grid ShowGridLines="True" Width="{Binding Width}" Height="{Binding Height}" Panel.ZIndex="10" 
-                      Visibility="{Binding GridLinesVisible, Converter={StaticResource BoolToVisibilityConverter}, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:DrawingViewPort}}}">
-                    <Rectangle Focusable="False">
-                        <Rectangle.Fill>
-                            <VisualBrush Viewport="{Binding Height, Converter={StaticResource IntToViewportRectConverter}}" ViewboxUnits="Absolute" TileMode="Tile" >
-                                <VisualBrush.Visual>
-                                    <Line  X1="0" Y1="0" X2="1" Y2="0" Stroke="Black" StrokeThickness="0.01"/>
-                                </VisualBrush.Visual>
-                            </VisualBrush>
-                        </Rectangle.Fill>
-                    </Rectangle>
-                    <Rectangle Focusable="False">
-                        <Rectangle.Fill>
-                            <VisualBrush Viewport="{Binding Width, Converter={StaticResource IntToViewportRectConverter}, ConverterParameter=vertical}" ViewboxUnits="Absolute" TileMode="Tile" >
-                                <VisualBrush.Visual>
-                                    <Line  X1="0" Y1="0" X2="0" Y2="1" Stroke="Black" StrokeThickness="0.01"/>
-                                </VisualBrush.Visual>
-                            </VisualBrush>
-                        </Rectangle.Fill>
-                    </Rectangle>
-                    <Rectangle Focusable="False">
-                        <Rectangle.Fill>
-                            <VisualBrush Viewport="{Binding Height, Converter={StaticResource IntToViewportRectConverter}}" ViewboxUnits="Absolute" TileMode="Tile" >
-                                <VisualBrush.Visual>
-                                    <Line  X1="0" Y1="0" X2="1" Y2="0" Stroke="White" StrokeThickness="0.02"/>
-                                </VisualBrush.Visual>
-                            </VisualBrush>
-                        </Rectangle.Fill>
-                    </Rectangle>
-                    <Rectangle Focusable="False">
-                        <Rectangle.Fill>
-                            <VisualBrush Viewport="{Binding Width, Converter={StaticResource IntToViewportRectConverter}, ConverterParameter=vertical}" ViewboxUnits="Absolute" TileMode="Tile" >
-                                <VisualBrush.Visual>
-                                    <Line  X1="0" Y1="0" X2="0" Y2="1" Stroke="White" StrokeThickness="0.02"/>
-                                </VisualBrush.Visual>
-                            </VisualBrush>
-                        </Rectangle.Fill>
-                    </Rectangle>
-                </Grid>
-            </Canvas>
-        </local:Zoombox.AdditionalContent>
-    </local:Zoombox>
-</UserControl>

+ 0 - 216
src/PixiEditor/Views/UserControls/DrawingViewPort.xaml.cs

@@ -1,216 +0,0 @@
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using PixiEditor.Helpers;
-
-namespace PixiEditor.Views.UserControls;
-
-/// <summary>
-/// Interaction logic for DrawingViewPort.xaml.
-/// </summary>
-internal partial class DrawingViewPort : UserControl
-{
-    public static readonly DependencyProperty MiddleMouseClickedCommandProperty =
-        DependencyProperty.Register(nameof(MiddleMouseClickedCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty MouseMoveCommandProperty =
-        DependencyProperty.Register(nameof(MouseMoveCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty MouseDownCommandProperty =
-        DependencyProperty.Register(nameof(MouseDownCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty MouseUpCommandProperty =
-        DependencyProperty.Register(nameof(MouseUpCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty StylusButtonDownCommandProperty =
-        DependencyProperty.Register(nameof(StylusButtonDownCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty StylusGestureCommandProperty =
-        DependencyProperty.Register(nameof(StylusGestureCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty StylusButtonUpCommandProperty =
-        DependencyProperty.Register(nameof(StylusButtonUpCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty StylusOutOfRangeCommandProperty =
-        DependencyProperty.Register(nameof(StylusOutOfRangeCommand), typeof(ICommand), typeof(DrawingViewPort), new PropertyMetadata(default(ICommand)));
-
-    public static readonly DependencyProperty MouseXOnCanvasProperty =
-        DependencyProperty.Register(nameof(MouseXOnCanvas), typeof(double), typeof(DrawingViewPort), new PropertyMetadata(0.0));
-
-    public static readonly DependencyProperty MouseYOnCanvasProperty =
-        DependencyProperty.Register(nameof(MouseYOnCanvas), typeof(double), typeof(DrawingViewPort), new PropertyMetadata(0.0));
-
-    public static readonly DependencyProperty GridLinesVisibleProperty =
-        DependencyProperty.Register(nameof(GridLinesVisible), typeof(bool), typeof(DrawingViewPort), new PropertyMetadata(false));
-
-    public static readonly DependencyProperty IsUsingZoomToolProperty =
-        DependencyProperty.Register(nameof(IsUsingZoomTool), typeof(bool), typeof(DrawingViewPort), new PropertyMetadata(false, ToolChanged));
-
-    public static readonly DependencyProperty IsUsingMoveViewportToolProperty =
-        DependencyProperty.Register(nameof(IsUsingMoveViewportTool), typeof(bool), typeof(DrawingViewPort), new PropertyMetadata(false, ToolChanged));
-
-    public static readonly DependencyProperty CenterViewportTriggerProperty =
-        DependencyProperty.Register(nameof(CenterViewportTrigger), typeof(ExecutionTrigger<Size>), typeof(DrawingViewPort),
-            new PropertyMetadata(default(ExecutionTrigger<Size>), CenterViewportTriggerChanged));
-
-    public static readonly DependencyProperty ZoomViewportTriggerProperty =
-        DependencyProperty.Register(nameof(ZoomViewportTrigger), typeof(ExecutionTrigger<double>), typeof(DrawingViewPort),
-            new PropertyMetadata(default(ExecutionTrigger<double>), ZoomViewportTriggerChanged));
-
-    public static readonly DependencyProperty UseTouchGesturesProperty =
-        DependencyProperty.Register(nameof(UseTouchGestures), typeof(bool), typeof(DrawingViewPort));
-
-    public ICommand MiddleMouseClickedCommand
-    {
-        get => (ICommand)GetValue(MiddleMouseClickedCommandProperty);
-        set => SetValue(MiddleMouseClickedCommandProperty, value);
-    }
-
-    public ICommand MouseMoveCommand
-    {
-        get => (ICommand)GetValue(MouseMoveCommandProperty);
-        set => SetValue(MouseMoveCommandProperty, value);
-    }
-
-    public ICommand MouseDownCommand
-    {
-        get => (ICommand)GetValue(MouseDownCommandProperty);
-        set => SetValue(MouseDownCommandProperty, value);
-    }
-
-    public ICommand MouseUpCommand
-    {
-        get => (ICommand)GetValue(MouseUpCommandProperty);
-        set => SetValue(MouseUpCommandProperty, value);
-    }
-
-    public ICommand StylusButtonDownCommand
-    {
-        get => (ICommand)GetValue(StylusButtonDownCommandProperty);
-        set => SetValue(StylusButtonDownCommandProperty, value);
-    }
-
-    public ICommand StylusButtonUpCommand
-    {
-        get => (ICommand)GetValue(StylusButtonUpCommandProperty);
-        set => SetValue(StylusButtonUpCommandProperty, value);
-    }
-
-    public ICommand StylusGestureCommand
-    {
-        get => (ICommand)GetValue(StylusGestureCommandProperty);
-        set => SetValue(StylusGestureCommandProperty, value);
-    }
-
-    public ICommand StylusOutOfRangeCommand
-    {
-        get => (ICommand)GetValue(StylusOutOfRangeCommandProperty);
-        set => SetValue(StylusOutOfRangeCommandProperty, value);
-    }
-
-    public double MouseXOnCanvas
-    {
-        get => (double)GetValue(MouseXOnCanvasProperty);
-        set => SetValue(MouseXOnCanvasProperty, value);
-    }
-
-    public double MouseYOnCanvas
-    {
-        get => (double)GetValue(MouseYOnCanvasProperty);
-        set => SetValue(MouseYOnCanvasProperty, value);
-    }
-
-    public bool GridLinesVisible
-    {
-        get => (bool)GetValue(GridLinesVisibleProperty);
-        set => SetValue(GridLinesVisibleProperty, value);
-    }
-
-    public bool IsUsingZoomTool
-    {
-        get => (bool)GetValue(IsUsingZoomToolProperty);
-        set => SetValue(IsUsingZoomToolProperty, value);
-    }
-
-    public bool IsUsingMoveViewportTool
-    {
-        get => (bool)GetValue(IsUsingMoveViewportToolProperty);
-        set => SetValue(IsUsingMoveViewportToolProperty, value);
-    }
-    public bool UseTouchGestures
-    {
-        get => (bool)GetValue(UseTouchGesturesProperty);
-        set => SetValue(UseTouchGesturesProperty, value);
-    }
-
-    public ExecutionTrigger<Size> CenterViewportTrigger
-    {
-        get => (ExecutionTrigger<Size>)GetValue(CenterViewportTriggerProperty);
-        set => SetValue(CenterViewportTriggerProperty, value);
-    }
-
-    public ExecutionTrigger<double> ZoomViewportTrigger
-    {
-        get => (ExecutionTrigger<double>)GetValue(ZoomViewportTriggerProperty);
-        set => SetValue(ZoomViewportTriggerProperty, value);
-    }
-
-    public RelayCommand PreviewMouseDownCommand { get; private set; }
-    private static void ToolChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
-    {
-        var panel = (DrawingViewPort)sender;
-        if (panel.IsUsingZoomTool)
-            panel.zoombox.ZoomMode = Zoombox.Mode.ZoomTool;
-        else if (panel.IsUsingMoveViewportTool)
-            panel.zoombox.ZoomMode = Zoombox.Mode.MoveTool;
-        else
-            panel.zoombox.ZoomMode = Zoombox.Mode.Normal;
-    }
-
-    private static void CenterViewportTriggerChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
-    {
-        var viewport = (DrawingViewPort)sender;
-        if (args.OldValue != null)
-            ((ExecutionTrigger<Size>)args.OldValue).Triggered -= viewport.CenterZoomboxContent;
-        ((ExecutionTrigger<Size>)args.NewValue).Triggered += viewport.CenterZoomboxContent;
-    }
-
-    private static void ZoomViewportTriggerChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args)
-    {
-        var viewport = (DrawingViewPort)sender;
-        if (args.OldValue != null)
-            ((ExecutionTrigger<double>)args.OldValue).Triggered -= viewport.ZoomZoomboxContent;
-        ((ExecutionTrigger<double>)args.NewValue).Triggered += viewport.ZoomZoomboxContent;
-    }
-
-    private bool loaded = false;
-
-    public DrawingViewPort()
-    {
-        PreviewMouseDownCommand = new RelayCommand(ProcessMouseDown);
-        InitializeComponent();
-    }
-
-    private void CenterZoomboxContent(object sender, Size args)
-    {
-        zoombox.CenterContent(args);
-    }
-    private void ZoomZoomboxContent(object sender, double args)
-    {
-        zoombox.ZoomIntoCenter(args);
-    }
-
-    private void ProcessMouseDown(object parameter)
-    {
-        if (Mouse.MiddleButton == MouseButtonState.Pressed && MiddleMouseClickedCommand.CanExecute(null))
-            MiddleMouseClickedCommand.Execute(null);
-    }
-
-    private void OnCanvasLoaded(object sender, EventArgs e)
-    {
-        if (loaded)
-            return;
-        zoombox.CenterContent();
-        loaded = true;
-    }
-}

+ 0 - 21
src/PixiEditor/Views/UserControls/Zoombox.xaml

@@ -1,21 +0,0 @@
-<ContentControl x:Class="PixiEditor.Views.UserControls.Zoombox"
-                x:ClassModifier="internal"
-                xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
-                xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
-                xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
-                xmlns:local="clr-namespace:PixiEditor.Views.UserControls"
-                mc:Ignorable="d" 
-                x:Name="uc"
-                d:DesignHeight="450" d:DesignWidth="800">
-    <Canvas MouseDown="OnMouseDown" MouseUp="OnMouseUp" MouseMove="OnMouseMove" MouseWheel="OnScroll"
-            IsManipulationEnabled="{Binding UseTouchGestures, ElementName=uc}" ManipulationDelta="OnManipulationDelta"
-            x:Name="mainCanvas" Background="Transparent">
-        <Grid x:Name="mainGrid" SizeChanged="RecalculateMinZoomLevel">
-            <Grid.LayoutTransform>
-                <ScaleTransform x:Name="scaleTransform"/>
-            </Grid.LayoutTransform>
-            <ContentPresenter Content="{Binding AdditionalContent, ElementName=uc}"/>
-        </Grid>
-    </Canvas>
-</ContentControl>

+ 0 - 317
src/PixiEditor/Views/UserControls/Zoombox.xaml.cs

@@ -1,317 +0,0 @@
-using System.ComponentModel;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Input;
-using System.Windows.Markup;
-
-namespace PixiEditor.Views.UserControls;
-
-[ContentProperty(nameof(AdditionalContent))]
-internal partial class Zoombox : ContentControl, INotifyPropertyChanged
-{
-    public enum Mode
-    {
-        Normal, MoveTool, ZoomTool
-    }
-
-    private interface IDragOperation
-    {
-        void Start(MouseButtonEventArgs e);
-
-        void Update(MouseEventArgs e);
-
-        void Terminate();
-    }
-
-    private class MoveDragOperation : IDragOperation
-    {
-        private Zoombox parent;
-        private Point prevMousePos;
-
-        public MoveDragOperation(Zoombox zoomBox)
-        {
-            parent = zoomBox;
-        }
-        public void Start(MouseButtonEventArgs e)
-        {
-            prevMousePos = e.GetPosition(parent.mainCanvas);
-            parent.mainCanvas.CaptureMouse();
-        }
-
-        public void Update(MouseEventArgs e)
-        {
-            var curMousePos = e.GetPosition(parent.mainCanvas);
-            parent.SpaceOriginPos += curMousePos - prevMousePos;
-            prevMousePos = curMousePos;
-        }
-
-        public void Terminate()
-        {
-            parent.mainCanvas.ReleaseMouseCapture();
-        }
-    }
-
-    private class ZoomDragOperation : IDragOperation
-    {
-        private Zoombox parent;
-
-        private double initZoomPower;
-        private Point initSpaceOriginPos;
-
-        private Point zoomOrigin;
-        private Point screenZoomOrigin;
-
-        public ZoomDragOperation(Zoombox zoomBox)
-        {
-            parent = zoomBox;
-        }
-        public void Start(MouseButtonEventArgs e)
-        {
-            screenZoomOrigin = e.GetPosition(parent.mainCanvas);
-            zoomOrigin = parent.ToZoomboxSpace(screenZoomOrigin);
-            initZoomPower = parent.ZoomPowerClamped;
-            initSpaceOriginPos = parent.SpaceOriginPos;
-            parent.mainCanvas.CaptureMouse();
-        }
-
-        public void Update(MouseEventArgs e)
-        {
-            var curScreenPos = e.GetPosition(parent.mainCanvas);
-            double deltaX = screenZoomOrigin.X - curScreenPos.X;
-            double deltaPower = deltaX / 10.0;
-            parent.ZoomPowerClamped = initZoomPower - deltaPower;
-
-            parent.SpaceOriginPos = initSpaceOriginPos;
-            var shiftedOriginPos = parent.ToScreenSpace(zoomOrigin);
-            var deltaOriginPos = shiftedOriginPos - screenZoomOrigin;
-            parent.SpaceOriginPos = initSpaceOriginPos - deltaOriginPos;
-        }
-
-        public void Terminate()
-        {
-            parent.mainCanvas.ReleaseMouseCapture();
-        }
-    }
-
-    public static readonly DependencyProperty AdditionalContentProperty =
-        DependencyProperty.Register(nameof(AdditionalContent), typeof(object), typeof(Zoombox),
-            new PropertyMetadata(null));
-
-    public static readonly DependencyProperty ZoomModeProperty =
-        DependencyProperty.Register(nameof(ZoomMode), typeof(Mode), typeof(Zoombox),
-            new PropertyMetadata(Mode.Normal, ZoomModeChanged));
-
-    public static readonly DependencyProperty UseTouchGesturesProperty =
-        DependencyProperty.Register(nameof(UseTouchGestures), typeof(bool), typeof(Zoombox));
-
-    private const double zoomFactor = 1.09050773267; //2^(1/8)
-    private const double maxZoom = 50;
-    private double minZoom = -28;
-    public object AdditionalContent
-    {
-        get => GetValue(AdditionalContentProperty);
-        set => SetValue(AdditionalContentProperty, value);
-    }
-    public Mode ZoomMode
-    {
-        get => (Mode)GetValue(ZoomModeProperty);
-        set => SetValue(ZoomModeProperty, value);
-    }
-
-    public bool UseTouchGestures
-    {
-        get => (bool)GetValue(UseTouchGesturesProperty);
-        set => SetValue(UseTouchGesturesProperty, value);
-    }
-
-    public double Zoom => Math.Pow(zoomFactor, zoomPower);
-
-    private Point spaceOriginPos;
-    private Point SpaceOriginPos
-    {
-        get => spaceOriginPos;
-        set
-        {
-            spaceOriginPos = value;
-            Canvas.SetLeft(mainGrid, spaceOriginPos.X);
-            Canvas.SetTop(mainGrid, spaceOriginPos.Y);
-        }
-    }
-
-    private double zoomPower;
-    private double ZoomPowerClamped
-    {
-        get => zoomPower;
-        set
-        {
-            value = Math.Clamp(value, minZoom, maxZoom);
-            if (value == zoomPower)
-                return;
-            zoomPower = value;
-            var mult = Zoom;
-            scaleTransform.ScaleX = mult;
-            scaleTransform.ScaleY = mult;
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Zoom)));
-        }
-    }
-    private double ZoomPowerTopCapped
-    {
-        get => zoomPower;
-        set
-        {
-            if (value > maxZoom)
-                value = maxZoom;
-            if (value == zoomPower)
-                return;
-            zoomPower = value;
-            var mult = Zoom;
-            scaleTransform.ScaleX = mult;
-            scaleTransform.ScaleY = mult;
-            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Zoom)));
-        }
-    }
-
-    private IDragOperation activeDragOperation = null;
-    private MouseButtonEventArgs activeMouseDownEventArgs = null;
-    private Point activeMouseDownPos;
-
-    public event PropertyChangedEventHandler PropertyChanged;
-
-    private static void ZoomModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
-    {
-        Zoombox sender = (Zoombox)d;
-        sender.activeDragOperation?.Terminate();
-        sender.activeDragOperation = null;
-        sender.activeMouseDownEventArgs = null;
-    }
-
-    public Zoombox()
-    {
-        InitializeComponent();
-    }
-
-    public void CenterContent() => CenterContent(new Size(mainGrid.ActualWidth, mainGrid.ActualHeight));
-
-    public void CenterContent(Size newSize)
-    {
-        const double marginFactor = 1.1;
-        double scaleFactor = Math.Max(
-            newSize.Width * marginFactor / mainCanvas.ActualWidth,
-            newSize.Height * marginFactor / mainCanvas.ActualHeight);
-        ZoomPowerTopCapped = -Math.Log(scaleFactor, zoomFactor);
-        SpaceOriginPos = new Point(
-            mainCanvas.ActualWidth / 2 - newSize.Width * Zoom / 2,
-            mainCanvas.ActualHeight / 2 - newSize.Height * Zoom / 2);
-    }
-
-    public void ZoomIntoCenter(double delta)
-    {
-        ZoomInto(new Point(mainCanvas.ActualWidth / 2, mainCanvas.ActualHeight / 2), delta);
-    }
-
-    public void ZoomInto(Point mousePos, double delta)
-    {
-        var oldZoomboxMousePos = ToZoomboxSpace(mousePos);
-
-        ZoomPowerClamped += delta;
-
-        if (Math.Abs(ZoomPowerClamped) < 1) ZoomPowerClamped = 0;
-
-        var shiftedMousePos = ToScreenSpace(oldZoomboxMousePos);
-        var deltaMousePos = mousePos - shiftedMousePos;
-        SpaceOriginPos = SpaceOriginPos + deltaMousePos;
-    }
-
-    private void RecalculateMinZoomLevel(object sender, SizeChangedEventArgs args)
-    {
-        double fraction = Math.Max(
-            mainCanvas.ActualWidth / mainGrid.ActualWidth,
-            mainCanvas.ActualHeight / mainGrid.ActualHeight);
-        minZoom = Math.Min(0, Math.Log(fraction / 8, zoomFactor));
-    }
-
-    private Point ToScreenSpace(Point p)
-    {
-        double zoom = Zoom;
-        p.X *= zoom;
-        p.Y *= zoom;
-        p += (Vector)SpaceOriginPos;
-        return p;
-    }
-
-    private Point ToZoomboxSpace(Point mousePos)
-    {
-        double zoom = Zoom;
-        mousePos -= (Vector)SpaceOriginPos;
-        mousePos.X /= zoom;
-        mousePos.Y /= zoom;
-        return mousePos;
-    }
-
-    private void OnMouseDown(object sender, MouseButtonEventArgs e)
-    {
-        if (e.ChangedButton == MouseButton.Right)
-            return;
-        activeMouseDownEventArgs = e;
-        activeMouseDownPos = e.GetPosition(mainCanvas);
-        Keyboard.Focus(this);
-    }
-
-    private void InitiateDrag(MouseButtonEventArgs e)
-    {
-        if (ZoomMode == Mode.Normal)
-            return;
-
-        activeDragOperation?.Terminate();
-
-        if (ZoomMode == Mode.MoveTool)
-            activeDragOperation = new MoveDragOperation(this);
-        else if (ZoomMode == Mode.ZoomTool)
-            activeDragOperation = new ZoomDragOperation(this);
-
-        activeDragOperation.Start(e);
-    }
-
-    private void OnMouseUp(object sender, MouseButtonEventArgs e)
-    {
-        if (e.ChangedButton == MouseButton.Right)
-            return;
-        if (activeDragOperation != null)
-        {
-            activeDragOperation.Terminate();
-            activeDragOperation = null;
-        }
-        else
-        {
-            if (ZoomMode == Mode.ZoomTool && e.ChangedButton == MouseButton.Left)
-                ZoomInto(e.GetPosition(mainCanvas), Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl) ? -1 : 1);
-        }
-        activeMouseDownEventArgs = null;
-    }
-
-    private void OnMouseMove(object sender, MouseEventArgs e)
-    {
-        if (activeDragOperation == null && activeMouseDownEventArgs != null)
-        {
-            var cur = e.GetPosition(mainCanvas);
-
-            if (Math.Abs(cur.X - activeMouseDownPos.X) > 3)
-                InitiateDrag(activeMouseDownEventArgs);
-        }
-        activeDragOperation?.Update(e);
-    }
-
-    private void OnScroll(object sender, MouseWheelEventArgs e)
-    {
-        ZoomInto(e.GetPosition(mainCanvas), e.Delta / 100);
-    }
-
-    private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
-    {
-        if (e.Handled = UseTouchGestures)
-        {
-            ZoomInto(e.ManipulationOrigin, e.DeltaManipulation.Expansion.X / 5.0);
-            SpaceOriginPos += e.DeltaManipulation.Translation;
-        }
-    }
-}