Browse Source

Implement delete layer/folder, fix a bunch of bugs, replace interactivity with behaviors everywhere

Equbuxu 3 years ago
parent
commit
54a359235b
40 changed files with 259 additions and 263 deletions
  1. 0 2
      src/PixiEditor.Zoombox/Operations/MoveDragOperation.cs
  2. 0 2
      src/PixiEditor.Zoombox/Operations/RotateDragOperation.cs
  3. 0 2
      src/PixiEditor.Zoombox/Operations/ZoomDragOperation.cs
  4. 0 2
      src/PixiEditor.Zoombox/Zoombox.xaml.cs
  5. 1 1
      src/PixiEditor/Helpers/Behaviours/ClearFocusOnClickBehavior.cs
  6. 1 1
      src/PixiEditor/Helpers/Behaviours/GlobalShortcutFocusBehavior.cs
  7. 1 1
      src/PixiEditor/Helpers/Behaviours/MouseBehavior.cs
  8. 1 1
      src/PixiEditor/Helpers/Behaviours/TextBoxFocusBehavior.cs
  9. 21 2
      src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs
  10. 28 121
      src/PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs
  11. 9 17
      src/PixiEditor/ViewModels/SubViewModels/Main/StylusViewModel.cs
  12. 1 1
      src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/ColorSetting.cs
  13. 1 1
      src/PixiEditor/Views/Dialogs/ConfirmationPopup.xaml
  14. 1 1
      src/PixiEditor/Views/Dialogs/ExportFilePopup.xaml
  15. 1 1
      src/PixiEditor/Views/Dialogs/ImportFilePopup.xaml
  16. 1 1
      src/PixiEditor/Views/Dialogs/NewFilePopup.xaml
  17. 1 1
      src/PixiEditor/Views/Dialogs/NoticePopup.xaml
  18. 1 1
      src/PixiEditor/Views/Dialogs/ResizeCanvasPopup.xaml
  19. 1 1
      src/PixiEditor/Views/Dialogs/ResizeDocumentPopup.xaml
  20. 1 1
      src/PixiEditor/Views/Dialogs/SettingsWindow.xaml
  21. 31 48
      src/PixiEditor/Views/MainWindow.xaml
  22. 1 1
      src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControl.xaml
  23. 8 9
      src/PixiEditor/Views/UserControls/DrawingViewPort.xaml
  24. 3 1
      src/PixiEditor/Views/UserControls/EditableTextBlock.xaml
  25. 6 7
      src/PixiEditor/Views/UserControls/EditableTextBlock.xaml.cs
  26. 5 9
      src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml
  27. 5 0
      src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml.cs
  28. 7 11
      src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml
  29. 5 0
      src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml.cs
  30. 24 6
      src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml.cs
  31. 1 1
      src/PixiEditor/Views/UserControls/Layers/ReferenceLayer.xaml
  32. 1 1
      src/PixiEditor/Views/UserControls/NumberInput.xaml
  33. 1 1
      src/PixiEditor/Views/UserControls/Palettes/ColorReplacer.xaml
  34. 3 1
      src/PixiEditor/Views/UserControls/Palettes/CompactPaletteViewer.xaml
  35. 1 1
      src/PixiEditor/Views/UserControls/SizeInput.xaml
  36. 1 1
      src/PixiEditor/Views/UserControls/SizePicker.xaml
  37. 1 1
      src/PixiEditor/Views/UserControls/SmallColorPicker.xaml
  38. 1 1
      src/PixiEditor/Views/UserControls/SwatchesView.xaml
  39. 21 2
      src/PixiEditor/Views/UserControls/Viewport.xaml
  40. 62 0
      src/PixiEditor/Views/UserControls/Viewport.xaml.cs

+ 0 - 2
src/PixiEditor.Zoombox/Operations/MoveDragOperation.cs

@@ -16,7 +16,6 @@ internal class MoveDragOperation : IDragOperation
     public void Start(MouseButtonEventArgs e)
     {
         prevMousePos = Zoombox.ToVecD(e.GetPosition(parent.mainCanvas));
-        parent.mainCanvas.CaptureMouse();
     }
 
     public void Update(MouseEventArgs e)
@@ -28,6 +27,5 @@ internal class MoveDragOperation : IDragOperation
 
     public void Terminate()
     {
-        parent.mainCanvas.ReleaseMouseCapture();
     }
 }

+ 0 - 2
src/PixiEditor.Zoombox/Operations/RotateDragOperation.cs

@@ -22,7 +22,6 @@ internal class RotateDragOperation : IDragOperation
         initialClickAngle = GetAngle(new(pointCur.X, pointCur.Y));
         initialZoomboxAngle = owner.Angle;
         rotationProcess = new LockingRotationProcess(initialZoomboxAngle);
-        owner.mainCanvas.CaptureMouse();
     }
 
     private double GetAngle(VecD point)
@@ -48,6 +47,5 @@ internal class RotateDragOperation : IDragOperation
 
     public void Terminate()
     {
-        owner.mainCanvas.ReleaseMouseCapture();
     }
 }

+ 0 - 2
src/PixiEditor.Zoombox/Operations/ZoomDragOperation.cs

@@ -23,7 +23,6 @@ internal class ZoomDragOperation : IDragOperation
         screenScaleOrigin = Zoombox.ToVecD(e.GetPosition(parent.mainCanvas));
         scaleOrigin = parent.ToZoomboxSpace(screenScaleOrigin);
         originalScale = parent.Scale;
-        parent.mainCanvas.CaptureMouse();
     }
 
     public void Update(MouseEventArgs e)
@@ -40,6 +39,5 @@ internal class ZoomDragOperation : IDragOperation
 
     public void Terminate()
     {
-        parent.mainCanvas.ReleaseMouseCapture();
     }
 }

+ 0 - 2
src/PixiEditor.Zoombox/Zoombox.xaml.cs

@@ -326,8 +326,6 @@ public partial class Zoombox : ContentControl, INotifyPropertyChanged
         activeMouseDownEventArgs = e;
         activeMouseDownPos = ToVecD(e.GetPosition(mainCanvas));
         Keyboard.Focus(this);
-        if (ZoomMode != ZoomboxMode.Normal)
-            e.Handled = true;
     }
 
     private void InitiateDrag(MouseButtonEventArgs e)

+ 1 - 1
src/PixiEditor/Helpers/Behaviours/ClearFocusOnClickBehavior.cs

@@ -1,5 +1,5 @@
 using System.Windows;
-using System.Windows.Interactivity;
+using Microsoft.Xaml.Behaviors;
 using PixiEditor.Models.Controllers;
 
 namespace PixiEditor.Helpers.Behaviours;

+ 1 - 1
src/PixiEditor/Helpers/Behaviours/GlobalShortcutFocusBehavior.cs

@@ -1,5 +1,5 @@
 using System.Windows;
-using System.Windows.Interactivity;
+using Microsoft.Xaml.Behaviors;
 using PixiEditor.Models.Controllers;
 
 namespace PixiEditor.Helpers.Behaviours;

+ 1 - 1
src/PixiEditor/Helpers/Behaviours/MouseBehavior.cs

@@ -1,6 +1,6 @@
 using System.Windows;
 using System.Windows.Input;
-using System.Windows.Interactivity;
+using Microsoft.Xaml.Behaviors;
 
 namespace PixiEditor.Helpers.Behaviours
 {

+ 1 - 1
src/PixiEditor/Helpers/Behaviours/TextBoxFocusBehavior.cs

@@ -1,7 +1,7 @@
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
-using System.Windows.Interactivity;
+using Microsoft.Xaml.Behaviors;
 using PixiEditor.Views;
 
 namespace PixiEditor.Helpers.Behaviours;

+ 21 - 2
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -90,7 +90,7 @@ internal class DocumentViewModel : NotifyableObject
         }
     }
 
-    private string coordinatesString;
+    private string coordinatesString = "";
     public string CoordinatesString
     {
         get => coordinatesString;
@@ -232,7 +232,26 @@ internal class DocumentViewModel : NotifyableObject
 
     public void RemoveViewport(Guid viewportGuid) => Helpers.ActionAccumulator.AddActions(new RemoveViewport_PassthroughAction(viewportGuid));
 
-    public void CreateStructureMember(StructureMemberType type) => Helpers.StructureHelper.CreateNewStructureMember(type);
+    public void CreateStructureMember(StructureMemberType type)
+    {
+        if (Helpers.ChangeController.IsChangeActive)
+            return;
+        Helpers.StructureHelper.CreateNewStructureMember(type);
+    }
+
+    public void DeleteStructureMember(Guid guidValue)
+    {
+        if (Helpers.ChangeController.IsChangeActive)
+            return;
+        Helpers.ActionAccumulator.AddFinishedActions(new DeleteStructureMember_Action(guidValue));
+    }
+
+    public void DeleteStructureMembers(IReadOnlyList<Guid> guids)
+    {
+        if (Helpers.ChangeController.IsChangeActive)
+            return;
+        Helpers.ActionAccumulator.AddFinishedActions(guids.Select(static guid => new DeleteStructureMember_Action(guid)).ToArray());
+    }
 
     public void ResizeCanvas(VecI newSize, ResizeAnchor anchor)
     {

+ 28 - 121
src/PixiEditor/ViewModels/SubViewModels/Main/LayersViewModel.cs

@@ -8,42 +8,10 @@ namespace PixiEditor.ViewModels.SubViewModels.Main;
 [Command.Group("PixiEditor.Layer", "Image")]
 internal class LayersViewModel : SubViewModel<ViewModelMain>
 {
-    public RelayCommand CreateGroupFromActiveLayersCommand { get; set; }
-
-    public RelayCommand DeleteGroupCommand { get; set; }
-
-    public RelayCommand DeleteLayersCommand { get; set; }
-
-    public RelayCommand DuplicateLayerCommand { get; set; }
-
-    public RelayCommand RenameLayerCommand { get; set; }
-
-    public RelayCommand RenameGroupCommand { get; set; }
-
-    public RelayCommand MoveToBackCommand { get; set; }
-
-    public RelayCommand MoveToFrontCommand { get; set; }
-
-    public RelayCommand MergeSelectedCommand { get; set; }
-
-    public RelayCommand MergeWithAboveCommand { get; set; }
-
-    public RelayCommand MergeWithBelowCommand { get; set; }
 
     public LayersViewModel(ViewModelMain owner)
         : base(owner)
     {
-        CreateGroupFromActiveLayersCommand = new RelayCommand(CreateGroupFromActiveLayers, CanCreateGroupFromSelected);
-        DeleteLayersCommand = new RelayCommand(DeleteActiveLayers, CanDeleteActiveLayers);
-        DuplicateLayerCommand = new RelayCommand(DuplicateLayer, CanDuplicateLayer);
-        MoveToBackCommand = new RelayCommand(MoveLayerToBack, CanMoveToBack);
-        MoveToFrontCommand = new RelayCommand(MoveLayerToFront, CanMoveToFront);
-        RenameLayerCommand = new RelayCommand(RenameLayer);
-        MergeSelectedCommand = new RelayCommand(MergeSelected, CanMergeSelected);
-        MergeWithAboveCommand = new RelayCommand(MergeWithAbove, CanMergeWithAbove);
-        MergeWithBelowCommand = new RelayCommand(MergeWithBelow, CanMergeWithBelow);
-        RenameGroupCommand = new RelayCommand(RenameGroup);
-        DeleteGroupCommand = new RelayCommand(DeleteGroup, CanDeleteGroup);
     }
 
     public void CreateGroupFromActiveLayers(object parameter)
@@ -54,67 +22,41 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     [Evaluator.CanExecute("PixiEditor.Layer.CanDeleteSelected")]
     public bool CanDeleteSelected(object parameter)
     {
-        /*
-        bool paramIsLayerOrGroup = parameter is not null and (Layer or LayerGroup);
-        bool activeLayerExists = Owner.BitmapManager?.ActiveDocument?.ActiveLayer != null;
-        bool activeDocumentExists = Owner.BitmapManager.ActiveDocument != null;
-        bool allGood = (paramIsLayerOrGroup || activeLayerExists) && activeDocumentExists;
-        if (!allGood)
+        var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
+        if (member is null)
             return false;
-
-        if (parameter is Layer or LayerStructureItemContainer)
-        {
-            return CanDeleteActiveLayers(null);
-        }
-        else if (parameter is LayerGroup group)
-        {
-            return CanDeleteGroup(group.GuidValue);
-        }
-        else if (parameter is LayerGroupControl groupControl)
-        {
-            return CanDeleteGroup(groupControl.GroupGuid);
-        }
-        else if (Owner.BitmapManager.ActiveDocument.ActiveLayer != null)
-        {
-            return CanDeleteActiveLayers(null);
-        }*/
-        return false;
+        return true;
     }
 
-    [Command.Basic("PixiEditor.Layer.DeleteSelected", "Delete selected layer/folder", "", CanExecute = "PixiEditor.Layer.CanDeleteSelected")]
+    [Command.Basic("PixiEditor.Layer.DeleteSelected", "Delete active layer/folder", "", CanExecute = "PixiEditor.Layer.CanDeleteSelected")]
     public void DeleteSelected(object parameter)
     {
-        /*
-        if (parameter is Layer or LayerStructureItemContainer)
-        {
-            DeleteActiveLayers(null);
-        }
-        else if (parameter is LayerGroup group)
-        {
-            DeleteGroup(group.GuidValue);
-        }
-        else if (parameter is LayerGroupControl groupControl)
-        {
-            DeleteGroup(groupControl.GroupGuid);
-        }
-        else if (Owner.BitmapManager.ActiveDocument.ActiveLayer != null)
-        {
-            DeleteActiveLayers(null);
-        }*/
-    }
-
-    public bool CanDeleteGroup(object parameter)
-    {
-        return false;
+        var member = Owner.DocumentManagerSubViewModel.ActiveDocument?.SelectedStructureMember;
+        if (member is null)
+            return;
+        member.Document.DeleteStructureMember(member.GuidValue);
     }
 
-    public void DeleteGroup(object parameter)
+    [Evaluator.CanExecute("PixiEditor.Layer.CanDeleteAllSelected")]
+    public bool CanDeleteAllSelected(object parameter)
     {
-
+        var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
+        if (doc is null)
+            return false;
+        return doc.SelectedStructureMember is not null || doc.SoftSelectedStructureMembers.Count > 0;
     }
 
-    public void RenameGroup(object parameter)
+    [Command.Basic("PixiEditor.Layer.DeleteAllSelected", "Delete all selected layers/folders", "", CanExecute = "PixiEditor.Layer.CanDeleteAllSelected")]
+    public void DeleteAllSelected(object parameter)
     {
+        var doc = Owner.DocumentManagerSubViewModel.ActiveDocument;
+        if (doc is null)
+            return;
+        List<Guid> membersToDelete = new();
+        if (doc.SelectedStructureMember is not null)
+            membersToDelete.Add(doc.SelectedStructureMember.GuidValue);
+        membersToDelete.AddRange(doc.SoftSelectedStructureMembers.Select(static member => member.GuidValue));
+        doc.DeleteStructureMembers(membersToDelete);
     }
 
     [Command.Basic("PixiEditor.Layer.NewFolder", "New Folder", "Create new folder", CanExecute = "PixiEditor.Layer.CanCreateNewMember")]
@@ -150,61 +92,26 @@ internal class LayersViewModel : SubViewModel<ViewModelMain>
     }
 
     [Command.Internal("PixiEditor.Layer.OpacitySliderDragStarted")]
-    public void OpacitySliderDragStarted(object paramenter)
+    public void OpacitySliderDragStarted(object parameter)
     {
         Owner.DocumentManagerSubViewModel.ActiveDocument?.UseOpacitySlider();
         Owner.DocumentManagerSubViewModel.ActiveDocument?.OnOpacitySliderDragStarted();
     }
 
     [Command.Internal("PixiEditor.Layer.OpacitySliderDragged")]
-    public void OpacitySliderDragged(object paramenter)
+    public void OpacitySliderDragged(object parameter)
     {
-        if (paramenter is not double value)
+        if (parameter is not double value)
             return;
         Owner.DocumentManagerSubViewModel.ActiveDocument?.OnOpacitySliderDragged((float)value);
     }
 
     [Command.Internal("PixiEditor.Layer.OpacitySliderDragEnded")]
-    public void OpacitySliderDragEnded(object paramenter)
+    public void OpacitySliderDragEnded(object parameter)
     {
         Owner.DocumentManagerSubViewModel.ActiveDocument?.OnOpacitySliderDragEnded();
     }
 
-    public void SetActiveLayer(object parameter)
-    {
-        //int index = (int)parameter;
-
-        //var doc = Owner.BitmapManager.ActiveDocument;
-
-        /*if (doc.Layers[index].IsActive && Mouse.RightButton == MouseButtonState.Pressed)
-        {
-            return;
-        }*/
-
-        if (Keyboard.IsKeyDown(Key.LeftCtrl))
-        {
-            //doc.ToggleLayer(index);
-        }
-        //else if (Keyboard.IsKeyDown(Key.LeftShift) && Owner.BitmapManager.ActiveDocument.Layers.Any(x => x.IsActive))
-        {
-            //doc.SelectLayersRange(index);
-        }
-        //else
-        {
-            //doc.SetMainActiveLayer(index);
-        }
-    }
-
-    public void DeleteActiveLayers(object unusedParameter)
-    {
-
-    }
-
-    public bool CanDeleteActiveLayers(object unusedParam)
-    {
-        return false;
-    }
-
     public void DuplicateLayer(object parameter)
     {
 

+ 9 - 17
src/PixiEditor/ViewModels/SubViewModels/Main/StylusViewModel.cs

@@ -8,6 +8,7 @@ using PixiEditor.ViewModels.SubViewModels.Tools.Tools;
 
 namespace PixiEditor.ViewModels.SubViewModels.Main;
 
+[Command.Group("PixiEditor.Stylus", "Stylus")]
 internal class StylusViewModel : SubViewModel<ViewModelMain>
 {
     private bool isPenModeEnabled;
@@ -39,22 +40,9 @@ internal class StylusViewModel : SubViewModel<ViewModelMain>
 
     private ToolViewModel PreviousTool { get; set; }
 
-    public RelayCommand<StylusButtonEventArgs> StylusDownCommand { get; }
-
-    public RelayCommand<StylusButtonEventArgs> StylusUpCommand { get; }
-
-    public RelayCommand<StylusEventArgs> StylusOutOfRangeCommand { get; }
-
-    public RelayCommand<StylusSystemGestureEventArgs> StylusGestureCommand { get; }
-
     public StylusViewModel(ViewModelMain owner)
         : base(owner)
     {
-        StylusDownCommand = new(StylusDown);
-        StylusUpCommand = new(StylusUp);
-        StylusOutOfRangeCommand = new(StylusOutOfRange);
-        StylusGestureCommand = new(StylusSystemGesture);
-
         isPenModeEnabled = IPreferences.Current.GetLocalPreference<bool>(nameof(IsPenModeEnabled));
         Owner.ToolsSubViewModel.AddPropertyChangedCallback(nameof(ToolsViewModel.ActiveTool), UpdateUseTouchGesture);
 
@@ -79,12 +67,14 @@ internal class StylusViewModel : SubViewModel<ViewModelMain>
         }
     }
 
-    private void StylusOutOfRange(StylusEventArgs e)
+    [Command.Internal("PixiEditor.Stylus.StylusOutOfRange")]
+    public void StylusOutOfRange(StylusEventArgs e)
     {
         //Owner.BitmapManager.UpdateHighlightIfNecessary(true);
     }
 
-    private void StylusSystemGesture(StylusSystemGestureEventArgs e)
+    [Command.Internal("PixiEditor.Stylus.StylusSystemGesture")]
+    public void StylusSystemGesture(StylusSystemGestureEventArgs e)
     {
         if (e.SystemGesture == SystemGesture.Drag || e.SystemGesture == SystemGesture.Tap)
         {
@@ -94,7 +84,8 @@ internal class StylusViewModel : SubViewModel<ViewModelMain>
         e.Handled = true;
     }
 
-    private void StylusDown(StylusButtonEventArgs e)
+    [Command.Internal("PixiEditor.Stylus.StylusDown")]
+    public void StylusDown(StylusButtonEventArgs e)
     {
         e.Handled = true;
 
@@ -106,7 +97,8 @@ internal class StylusViewModel : SubViewModel<ViewModelMain>
         }
     }
 
-    private void StylusUp(StylusButtonEventArgs e)
+    [Command.Internal("PixiEditor.Stylus.StylusUp")]
+    public void StylusUp(StylusButtonEventArgs e)
     {
         e.Handled = true;
 

+ 1 - 1
src/PixiEditor/ViewModels/SubViewModels/Tools/ToolSettings/Settings/ColorSetting.cs

@@ -1,8 +1,8 @@
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
-using System.Windows.Interactivity;
 using System.Windows.Media;
+using Microsoft.Xaml.Behaviors;
 using PixiEditor.Helpers.Behaviours;
 using PixiEditor.Views.UserControls;
 

+ 1 - 1
src/PixiEditor/Views/Dialogs/ConfirmationPopup.xaml

@@ -6,7 +6,7 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:system="clr-namespace:System;assembly=System.Runtime" 
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         mc:Ignorable="d" d:Title="Unsaved changes"
         Name="popup" WindowStartupLocation="CenterScreen" 

+ 1 - 1
src/PixiEditor/Views/Dialogs/ExportFilePopup.xaml

@@ -5,7 +5,7 @@
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:PixiEditor.Views"
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"

+ 1 - 1
src/PixiEditor/Views/Dialogs/ImportFilePopup.xaml

@@ -8,7 +8,7 @@
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         xmlns:vm="clr-namespace:PixiEditor.ViewModels"
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"
         mc:Ignorable="d" BorderBrush="Black" BorderThickness="1"
         Title="ImportFilePopup" ShowInTaskbar="False" 

+ 1 - 1
src/PixiEditor/Views/Dialogs/NewFilePopup.xaml

@@ -6,7 +6,7 @@
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:local="clr-namespace:PixiEditor.Views"
         xmlns:vm="clr-namespace:PixiEditor.ViewModels"
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"
         mc:Ignorable="d"

+ 1 - 1
src/PixiEditor/Views/Dialogs/NoticePopup.xaml

@@ -6,7 +6,7 @@
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:system="clr-namespace:System;assembly=System.Runtime" 
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         mc:Ignorable="d" WindowStyle="None"
         d:Title="Notice" Height="180" Width="400" MinHeight="180" MinWidth="400"

+ 1 - 1
src/PixiEditor/Views/Dialogs/ResizeCanvasPopup.xaml

@@ -5,7 +5,7 @@
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
         xmlns:local="clr-namespace:PixiEditor.Views"
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"
         xmlns:base="clr-namespace:PixiEditor.Views"

+ 1 - 1
src/PixiEditor/Views/Dialogs/ResizeDocumentPopup.xaml

@@ -4,7 +4,7 @@
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
         xmlns:local="clr-namespace:PixiEditor.Views" 
         xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"

+ 1 - 1
src/PixiEditor/Views/Dialogs/SettingsWindow.xaml

@@ -9,7 +9,7 @@
         xmlns:viewmodels="clr-namespace:PixiEditor.ViewModels" 
         xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters" 
         xmlns:views="clr-namespace:PixiEditor.Views" 
-        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
+        xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
         xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours" 
         xmlns:usercontrols="clr-namespace:PixiEditor.Views.UserControls"
         xmlns:dial="clr-namespace:PixiEditor.Views.Dialogs"

+ 31 - 48
src/PixiEditor/Views/MainWindow.xaml

@@ -13,7 +13,6 @@
     xmlns:doc="clr-namespace:PixiEditor.ViewModels.SubViewModels.Document"
     xmlns:dataHolders="clr-namespace:PixiEditor.Models.DataHolders"
     xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
-    xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
     xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
     xmlns:ui="clr-namespace:PixiEditor.Helpers.UI"
     xmlns:cmd="http://www.galasoft.ch/mvvmlight"
@@ -88,19 +87,19 @@
             Executed="CommandBinding_Executed_Restore" />
     </Window.CommandBindings>
 
-    <i:Interaction.Triggers>
-        <i:EventTrigger
+    <b:Interaction.Triggers>
+        <b:EventTrigger
             EventName="ContentRendered">
-            <i:InvokeCommandAction
+            <b:InvokeCommandAction
                 Command="{Binding OnStartupCommand}" />
-        </i:EventTrigger>
-        <i:EventTrigger
+        </b:EventTrigger>
+        <b:EventTrigger
             EventName="Closing">
-            <cmd:EventToCommand
+            <b:InvokeCommandAction
                 Command="{Binding CloseWindowCommand}"
                 PassEventArgsToCommand="True" />
-        </i:EventTrigger>
-    </i:Interaction.Triggers>
+        </b:EventTrigger>
+    </b:Interaction.Triggers>
     <Grid>
         <Grid
             Name="mainGrid"
@@ -122,9 +121,9 @@
                 <RowDefinition
                     Height="30" />
             </Grid.RowDefinitions>
-            <i:Interaction.Behaviors>
+            <b:Interaction.Behaviors>
                 <behaviours:ClearFocusOnClickBehavior />
-            </i:Interaction.Behaviors>
+            </b:Interaction.Behaviors>
             <DockPanel
                 Grid.Row="0"
                 Grid.Column="0"
@@ -359,13 +358,13 @@
                             </Style.Triggers>
                         </Style>
                     </Border.Style>
-                    <i:Interaction.Triggers>
-                        <i:EventTrigger
+                    <b:Interaction.Triggers>
+                        <b:EventTrigger
                             EventName="MouseDown">
-                            <cmd:EventToCommand
+                            <b:InvokeCommandAction
                                 Command="{cmds:Command PixiEditor.Search.Toggle}"/>
-                        </i:EventTrigger>
-                    </i:Interaction.Triggers>
+                        </b:EventTrigger>
+                    </b:Interaction.Triggers>
                     <Grid Margin="5,0" VerticalAlignment="Center">
                         <TextBlock Foreground="White">Search...</TextBlock>
                         <TextBlock Text="{cmds:ShortcutBinding PixiEditor.Search.Toggle}"
@@ -508,36 +507,20 @@
                                             MouseDownCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseDownCommand}"
                                             MouseMoveCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseMoveCommand}"
                                             MouseUpCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.MouseUpCommand}"
+                                            MiddleMouseClickedCommand="{Binding ElementName=mainWindow, Path=DataContext.IoSubViewModel.PreviewMouseMiddleButtonCommand}"
                                             Cursor="{Binding ElementName=mainWindow, Path=DataContext.ToolsSubViewModel.ToolCursor}"
                                             GridLinesVisible="{Binding ElementName=mainWindow, Path=DataContext.ViewportSubViewModel.GridLinesEnabled}"
                                             ZoomMode="{Binding ElementName=mainWindow, Path=DataContext.ToolsSubViewModel.ActiveTool, Converter={converters:ActiveToolToZoomModeConverter}}"
                                             ZoomOutOnClick="{Binding ElementName=mainWindow, Path=DataContext.ToolsSubViewModel.ZoomTool.ZoomOutOnClick}"
-                                            Document="{Binding}"/>
-                                        <!--<usercontrols:DrawingViewPort
-                                        CenterViewportTrigger="{Binding CenterViewportTrigger}"
-                                        ZoomViewportTrigger="{Binding ZoomViewportTrigger}"
-                                        GridLinesVisible="{Binding XamlAccesibleViewModel.ViewportSubViewModel.GridLinesEnabled}"
-                                        Cursor="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ToolCursor}"
-                                        MiddleMouseClickedCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.PreviewMouseMiddleButtonCommand}"
-                                        MouseMoveCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseMoveCommand}"
-                                        MouseDownCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseDownCommand}"
-                                        MouseUpCommand="{Binding XamlAccesibleViewModel.IoSubViewModel.MouseUpCommand}"
-                                        MouseXOnCanvas="{Binding MouseXOnCanvas, Mode=TwoWay}"
-                                        MouseYOnCanvas="{Binding MouseYOnCanvas, Mode=TwoWay}"
-                                        StylusButtonDownCommand="{Binding XamlAccesibleViewModel.StylusSubViewModel.StylusDownCommand}"
-                                        StylusButtonUpCommand="{Binding XamlAccesibleViewModel.StylusSubViewModel.StylusUpCommand}"
-                                        StylusGestureCommand="{Binding XamlAccesibleViewModel.StylusSubViewModel.StylusGestureCommand}"
-                                        StylusOutOfRangeCommand="{Binding XamlAccesibleViewModel.StylusSubViewModel.StylusOutOfRangeCommand}"
-                                        UseTouchGestures="{Binding XamlAccesibleViewModel.StylusSubViewModel.UseTouchGestures}"
-                                        IsUsingZoomTool="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ActiveTool, Converter={converters:IsSpecifiedTypeConverter SpecifiedType={x:Type tools:ZoomTool}}}"
-                                        IsUsingMoveViewportTool="{Binding XamlAccesibleViewModel.ToolsSubViewModel.ActiveTool, Converter={converters:IsSpecifiedTypeConverter SpecifiedType={x:Type tools:MoveViewportTool}}}"
-                                        Stylus.IsTapFeedbackEnabled="False" Stylus.IsTouchFeedbackEnabled="False">
-                                            <i:Interaction.Triggers>
-                                                <i:EventTrigger EventName="PreviewMouseDown">
-                                                    <i:InvokeCommandAction Command="{Binding SetAsActiveOnClickCommand}"/>
-                                                </i:EventTrigger>
-                                            </i:Interaction.Triggers>
-                                            <usercontrols:DrawingViewPort.ContextMenu>
+                                            UseTouchGestures="{Binding ElementName=mainWindow, Path=DataContext.StylusSubViewModel.UseTouchGestures}"
+                                            StylusButtonDownCommand="{cmds:Command PixiEditor.Stylus.StylusDown, UseProvided=True}"
+                                            StylusButtonUpCommand="{cmds:Command PixiEditor.Stylus.StylusUp, UseProvided=True}"
+                                            StylusGestureCommand="{cmds:Command PixiEditor.Stylus.StylusSystemGesture, UseProvided=True}"
+                                            StylusOutOfRangeCommand="{cmds:Command PixiEditor.Stylus.StylusOutOfRange, UseProvided=True}"
+                                            Stylus.IsTapFeedbackEnabled="False" 
+                                            Stylus.IsTouchFeedbackEnabled="False"
+                                            Document="{Binding}">
+                                            <usercontrols:Viewport.ContextMenu>
                                                 <ContextMenu DataContext="{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
                                                     <ContextMenu.Template>
                                                         <ControlTemplate>
@@ -595,8 +578,8 @@
                                                         </ControlTemplate>
                                                     </ContextMenu.Template>
                                                 </ContextMenu>
-                                            </usercontrols:DrawingViewPort.ContextMenu>
-                                            </usercontrols:DrawingViewPort> -->
+                                            </usercontrols:Viewport.ContextMenu>
+                                        </usercontrols:Viewport>
                                     </DataTemplate>
                                 </ui:DocumentsTemplateSelector.DocumentsViewTemplate>
                             </ui:DocumentsTemplateSelector>
@@ -613,9 +596,9 @@
                                             <usercontrols:SmallColorPicker SelectedColor="{Binding ColorsSubViewModel.PrimaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}"
                                                                          SecondaryColor="{Binding ColorsSubViewModel.SecondaryColor, Mode=TwoWay, Converter={StaticResource SKColorToMediaColorConverter}}" 
                                                                          Style="{StaticResource DefaultColorPickerStyle}" x:Name="mainColorPicker">
-                                                <i:Interaction.Behaviors>
+                                                <b:Interaction.Behaviors>
                                                     <behaviours:GlobalShortcutFocusBehavior/>
-                                                </i:Interaction.Behaviors>
+                                                </b:Interaction.Behaviors>
                                             </usercontrols:SmallColorPicker>
                                         </LayoutAnchorable>
                                         <LayoutAnchorable ContentId="colorSliders" Title="Color Sliders" CanHide="False"
@@ -623,9 +606,9 @@
                                                       CanDockAsTabbedDocument="False" CanFloat="True">
                                             <colorpicker:ColorSliders Style="{StaticResource DefaultColorPickerStyle}" 
                                                                   ColorState="{Binding ElementName=mainColorPicker, Path=ColorState, Delay=10, Mode=TwoWay}">
-                                                <i:Interaction.Behaviors>
+                                                <b:Interaction.Behaviors>
                                                     <behaviours:GlobalShortcutFocusBehavior/>
-                                                </i:Interaction.Behaviors>
+                                                </b:Interaction.Behaviors>
                                             </colorpicker:ColorSliders>
                                         </LayoutAnchorable>
                                         <avalondock:LayoutAnchorable ContentId="palette" Title="Palette" CanHide="False"

+ 1 - 1
src/PixiEditor/Views/UserControls/CommandSearch/CommandSearchControl.xaml

@@ -7,7 +7,7 @@
              xmlns:local="clr-namespace:PixiEditor.Views.UserControls.CommandSearch"
              xmlns:behaves="clr-namespace:PixiEditor.Helpers.Behaviours"
              xmlns:cmdssearch="clr-namespace:PixiEditor.Models.Commands.Search"
-             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              mc:Ignorable="d"
              Foreground="White"
              d:DesignHeight="450" d:DesignWidth="600"

+ 8 - 9
src/PixiEditor/Views/UserControls/DrawingViewPort.xaml

@@ -1,11 +1,10 @@
 <UserControl
     x:ClassModifier="internal"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
-    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+    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:cmd="http://www.galasoft.ch/mvvmlight"
     xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
     xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
     xmlns:dataholders="clr-namespace:PixiEditor.Models.DataHolders"
@@ -26,31 +25,31 @@
                    UseTouchGestures="{Binding UseTouchGestures, ElementName=uc}">
         <i:Interaction.Triggers>
             <i:EventTrigger EventName="MouseMove">
-                <cmd:EventToCommand Command="{Binding MouseMoveCommand, ElementName=uc}" PassEventArgsToCommand="True" />
+                <i:InvokeCommandAction Command="{Binding MouseMoveCommand, ElementName=uc}" PassEventArgsToCommand="True" />
             </i:EventTrigger>
             <i:EventTrigger EventName="MouseDown">
-                <cmd:EventToCommand Command="{Binding MouseDownCommand, ElementName=uc}" PassEventArgsToCommand="True" />
+                <i:InvokeCommandAction Command="{Binding MouseDownCommand, ElementName=uc}" PassEventArgsToCommand="True" />
             </i:EventTrigger>
             <i:EventTrigger EventName="MouseUp">
-                <cmd:EventToCommand Command="{Binding MouseUpCommand, ElementName=uc}" PassEventArgsToCommand="True" />
+                <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">
-                <cmd:EventToCommand Command="{Binding StylusButtonDownCommand, ElementName=uc}"
+                <i:InvokeCommandAction Command="{Binding StylusButtonDownCommand, ElementName=uc}"
                                         PassEventArgsToCommand="True"/>
             </i:EventTrigger>
             <i:EventTrigger EventName="StylusButtonUp">
-                <cmd:EventToCommand Command="{Binding StylusButtonUpCommand, ElementName=uc}"
+                <i:InvokeCommandAction Command="{Binding StylusButtonUpCommand, ElementName=uc}"
                                         PassEventArgsToCommand="True"/>
             </i:EventTrigger>
             <i:EventTrigger EventName="StylusSystemGesture">
-                <cmd:EventToCommand Command="{Binding StylusGestureCommand, ElementName=uc}"
+                <i:InvokeCommandAction Command="{Binding StylusGestureCommand, ElementName=uc}"
                                         PassEventArgsToCommand="True"/>
             </i:EventTrigger>
             <i:EventTrigger EventName="StylusOutOfRange">
-                <cmd:EventToCommand Command="{Binding StylusOutOfRangeCommand, ElementName=uc}"
+                <i:InvokeCommandAction Command="{Binding StylusOutOfRangeCommand, ElementName=uc}"
                                         PassEventArgsToCommand="True"/>
             </i:EventTrigger>
         </i:Interaction.Triggers>

+ 3 - 1
src/PixiEditor/Views/UserControls/EditableTextBlock.xaml

@@ -4,7 +4,9 @@
              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:converters="clr-namespace:PixiEditor.Helpers.Converters" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters" 
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
+             xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
              mc:Ignorable="d"
              d:DesignHeight="60" d:DesignWidth="100" Focusable="True">
     <Grid>

+ 6 - 7
src/PixiEditor/Views/UserControls/EditableTextBlock.xaml.cs

@@ -6,28 +6,27 @@ using PixiEditor.Models.Controllers;
 
 namespace PixiEditor.Views.UserControls;
 
-/// <summary>
-///     Interaction logic for EditableTextBlock.xaml.
-/// </summary>
 internal partial class EditableTextBlock : UserControl
 {
-
     public static readonly DependencyProperty TextBlockVisibilityProperty =
-        DependencyProperty.Register(nameof(TextBlockVisibility),
+        DependencyProperty.Register(
+            nameof(TextBlockVisibility),
             typeof(Visibility),
             typeof(EditableTextBlock),
             new PropertyMetadata(Visibility.Visible));
 
 
     public static readonly DependencyProperty TextProperty =
-        DependencyProperty.Register(nameof(Text),
+        DependencyProperty.Register(
+            nameof(Text),
             typeof(string),
             typeof(EditableTextBlock),
             new PropertyMetadata(default(string)));
 
 
     public static readonly DependencyProperty EnableEditingProperty =
-        DependencyProperty.Register(nameof(IsEditing),
+        DependencyProperty.Register(
+            nameof(IsEditing),
             typeof(bool),
             typeof(EditableTextBlock),
             new PropertyMetadata(OnIsEditingChanged));

+ 5 - 9
src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml

@@ -4,10 +4,11 @@
              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:i="http://schemas.microsoft.com/expression/2010/interactivity" 
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
              xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:userControls="clr-namespace:PixiEditor.Views" 
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters" xmlns:helpers="clr-namespace:PixiEditor.Helpers.UI"
              xmlns:userControls1="clr-namespace:PixiEditor.Views.UserControls"
+             xmlns:cmds="clr-namespace:PixiEditor.Models.Commands.XAML"
              mc:Ignorable="d" 
              Focusable="True"
              d:DesignHeight="60" 
@@ -67,6 +68,7 @@
                             </Image>
                         </Border>
                         <userControls1:EditableTextBlock
+                            x:Name="editableTextBlock"
                             FontSize="15"
                             VerticalAlignment="Center"
                             Text="{Binding Folder.NameBindable, ElementName=folderControl, Mode=TwoWay}" />
@@ -81,14 +83,8 @@
         </Grid>
         <Border.ContextMenu>
             <ContextMenu>
-                <MenuItem Header="Rename"
-                                     Command="{Binding PlacementTarget.Tag.LayersViewModel.RenameGroupCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.GroupGuid, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                </MenuItem>
-                <MenuItem Header="Delete"
-                                     Command="{Binding PlacementTarget.Tag.LayersViewModel.DeleteGroupCommand, 
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.GroupGuid, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                </MenuItem>
+                <MenuItem Header="Rename" Click="RenameMenuItem_Click"/>
+                <MenuItem Header="Delete" Command="{cmds:Command PixiEditor.Layer.DeleteAllSelected}"/>
             </ContextMenu>
         </Border.ContextMenu>
     </Border>

+ 5 - 0
src/PixiEditor/Views/UserControls/Layers/FolderControl.xaml.cs

@@ -85,4 +85,9 @@ internal partial class FolderControl : UserControl
     {
         middleDropGrid.Visibility = Visibility.Collapsed;
     }
+
+    private void RenameMenuItem_Click(object sender, RoutedEventArgs e)
+    {
+        editableTextBlock.EnableEditing();
+    }
 }

+ 7 - 11
src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml

@@ -7,9 +7,10 @@
              xmlns:local="clr-namespace:PixiEditor.Views"
              xmlns:conv="clr-namespace:PixiEditor.Helpers.Converters"
              xmlns:controls="clr-namespace:PixiEditor.Views.UserControls"
-             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
              xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
              xmlns:helpers="clr-namespace:PixiEditor.Helpers.UI"
+             xmlns:cmds="clr-namespace:PixiEditor.Models.Commands.XAML"
              mc:Ignorable="d" 
              Focusable="True"
              d:DesignHeight="60" d:DesignWidth="250" Name="uc"
@@ -53,6 +54,7 @@
                     </Border>
 
                     <controls:EditableTextBlock
+                        x:Name="editableTextBlock"
                         FontSize="15"
                         VerticalAlignment="Center"
                         Text="{Binding Layer.NameBindable, ElementName=uc, Mode=TwoWay}" />
@@ -67,18 +69,12 @@
             <ContextMenu>
                 <MenuItem Header="Duplicate"
                                          Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.DuplicateLayerCommand,
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" 
-                          CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                </MenuItem>
-                <MenuItem Header="Delete"
-                                         Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.DeleteLayersCommand,
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" 
+                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}"
                           CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
                 </MenuItem>
-                <MenuItem Header="Rename"
-                                     Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.RenameLayerCommand,
-                                            RelativeSource={RelativeSource AncestorType=ContextMenu}}" CommandParameter="{Binding PlacementTarget.Tag.ContainerIndex, RelativeSource={RelativeSource AncestorType=ContextMenu}}">
-                </MenuItem>
+                <MenuItem Header="Delete" Command="{cmds:Command PixiEditor.Layer.DeleteAllSelected}"/>
+                <MenuItem Header="Rename" Click="RenameMenuItem_Click"/>
+
                 <MenuItem Header="Move to front"
                                      Command="{Binding PlacementTarget.Tag.LayerCommandsViewModel.MoveToFrontCommand,
                                             RelativeSource={RelativeSource AncestorType=ContextMenu}}"

+ 5 - 0
src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml.cs

@@ -131,4 +131,9 @@ internal partial class LayerControl : UserControl
         RemoveDragEffect((Grid)sender);
         HandleDrop(e.Data, StructureMemberPlacement.BelowOutsideFolder);
     }
+
+    private void RenameMenuItem_Click(object sender, RoutedEventArgs e)
+    {
+        editableTextBlock.EnableEditing();
+    }
 }

+ 24 - 6
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml.cs

@@ -141,17 +141,35 @@ internal partial class LayersManager : UserControl
 
     private void FolderControl_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
     {
-        if (e.ChangedButton is not MouseButton.Left)
-            return;
         FolderControl control = (FolderControl)sender;
-        HandleMouseDown(control.Folder);
+        if (e.ChangedButton == MouseButton.Left)
+        {
+            HandleMouseDown(control.Folder);
+        }
+        else
+        {
+            if (control.Folder is not null && control.Folder.Selection == StructureMemberSelectionType.None)
+            {
+                control.Folder.Document.SetSelectedMember(control.Folder.GuidValue);
+                control.Folder.Document.ClearSoftSelectedMembers();
+            }
+        }
     }
 
     private void LayerControl_MouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
     {
-        if (e.ChangedButton is not MouseButton.Left)
-            return;
         LayerControl? control = (LayerControl)sender;
-        HandleMouseDown(control.Layer);
+        if (e.ChangedButton == MouseButton.Left)
+        {
+            HandleMouseDown(control.Layer);
+        }
+        else
+        {
+            if (control.Layer is not null && control.Layer.Selection == StructureMemberSelectionType.None)
+            {
+                control.Layer.Document.SetSelectedMember(control.Layer.GuidValue);
+                control.Layer.Document.ClearSoftSelectedMembers();
+            }
+        }
     }
 }

+ 1 - 1
src/PixiEditor/Views/UserControls/Layers/ReferenceLayer.xaml

@@ -4,7 +4,7 @@
              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.Layers" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:local1="clr-namespace:PixiEditor.Views.UserControls" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Layers" xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours" xmlns:i="http://schemas.microsoft.com/xaml/behaviors" xmlns:local1="clr-namespace:PixiEditor.Views.UserControls" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d" 
              d:DesignHeight="60" d:DesignWidth="350" VerticalAlignment="Center" Name="uc">
     <Border BorderBrush="{StaticResource DarkerAccentColor}" BorderThickness="0 2 0 0" MinWidth="60" Focusable="True">

+ 1 - 1
src/PixiEditor/Views/UserControls/NumberInput.xaml

@@ -4,7 +4,7 @@
              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:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
              mc:Ignorable="d"
              d:DesignHeight="20" d:DesignWidth="40" x:Name="numberInput" Focusable="True" FocusVisualStyle="{x:Null}">

+ 1 - 1
src/PixiEditor/Views/UserControls/Palettes/ColorReplacer.xaml

@@ -7,7 +7,7 @@
              xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:userControls="clr-namespace:PixiEditor.Views.UserControls"
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
-             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              xmlns:behaviours="clr-namespace:PixiEditor.Helpers.Behaviours"
              xmlns:colorPicker="clr-namespace:ColorPicker;assembly=ColorPicker"
              mc:Ignorable="d" Name="uc"

+ 3 - 1
src/PixiEditor/Views/UserControls/Palettes/CompactPaletteViewer.xaml

@@ -4,7 +4,9 @@
              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.Palettes" xmlns:b="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
+             xmlns:local="clr-namespace:PixiEditor.Views.UserControls.Palettes" 
+             xmlns:b="http://schemas.microsoft.com/xaml/behaviors" 
+             xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d"  Name="compactPaletteViewer"
              d:DesignHeight="900" d:DesignWidth="30">
     <Grid Background="{StaticResource AccentColor}">

+ 1 - 1
src/PixiEditor/Views/UserControls/SizeInput.xaml

@@ -4,7 +4,7 @@
              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:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              mc:Ignorable="d" Foreground="White" Focusable="True"

+ 1 - 1
src/PixiEditor/Views/UserControls/SizePicker.xaml

@@ -4,7 +4,7 @@
              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:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              xmlns:local="clr-namespace:PixiEditor.Views"
              xmlns:converters="clr-namespace:PixiEditor.Helpers.Converters"
              xmlns:enums="clr-namespace:PixiEditor.Models.Enums"

+ 1 - 1
src/PixiEditor/Views/UserControls/SmallColorPicker.xaml

@@ -4,7 +4,7 @@
                                    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:i="http://schemas.microsoft.com/expression/2010/interactivity"
+                                   xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
                                    xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
                                    xmlns:vws="clr-namespace:PixiEditor.Views"
                                    xmlns:local="clr-namespace:PixiEditor.Views.UserControls"

+ 1 - 1
src/PixiEditor/Views/UserControls/SwatchesView.xaml

@@ -5,7 +5,7 @@
              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" 
-             xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
+             xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
              xmlns:conv="clr-namespace:PixiEditor.Helpers.Converters" 
              xmlns:palettes="clr-namespace:PixiEditor.Views.UserControls.Palettes"
              xmlns:cmds="clr-namespace:PixiEditor.Models.Commands.XAML"

+ 21 - 2
src/PixiEditor/Views/UserControls/Viewport.xaml

@@ -20,10 +20,29 @@
     <Grid 
         MouseDown="Image_MouseDown"
         MouseMove="Image_MouseMove"
-        MouseUp="Image_MouseUp">
+        MouseUp="Image_MouseUp"
+        PreviewMouseDown="Grid_PreviewMouseDown">
+        <i:Interaction.Triggers>
+            <i:EventTrigger EventName="StylusButtonDown">
+                <i:InvokeCommandAction Command="{Binding StylusButtonDownCommand, ElementName=vpUc}"
+                                        PassEventArgsToCommand="True"/>
+            </i:EventTrigger>
+            <i:EventTrigger EventName="StylusButtonUp">
+                <i:InvokeCommandAction Command="{Binding StylusButtonUpCommand, ElementName=vpUc}"
+                                        PassEventArgsToCommand="True"/>
+            </i:EventTrigger>
+            <i:EventTrigger EventName="StylusSystemGesture">
+                <i:InvokeCommandAction Command="{Binding StylusGestureCommand, ElementName=vpUc}"
+                                        PassEventArgsToCommand="True"/>
+            </i:EventTrigger>
+            <i:EventTrigger EventName="StylusOutOfRange">
+                <i:InvokeCommandAction Command="{Binding StylusOutOfRangeCommand, ElementName=vpUc}"
+                                        PassEventArgsToCommand="True"/>
+            </i:EventTrigger>
+        </i:Interaction.Triggers>
         <zoombox:Zoombox
             x:Name="zoombox"
-            UseTouchGestures="True"
+            UseTouchGestures="{Binding UseTouchGestures, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=OneWayToSource}"
             Scale="{Binding ZoomboxScale, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=OneWayToSource}"
             Center="{Binding Center, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=OneWayToSource}"
             Angle="{Binding Angle, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=local:Viewport}, Mode=OneWayToSource}"

+ 62 - 0
src/PixiEditor/Views/UserControls/Viewport.xaml.cs

@@ -57,6 +57,60 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
     public static readonly DependencyProperty CenterViewportTriggerProperty =
         DependencyProperty.Register(nameof(CenterViewportTrigger), typeof(ExecutionTrigger<VecI>), typeof(Viewport), new(null, CenterViewportTriggerChanged));
 
+    public static readonly DependencyProperty UseTouchGesturesProperty =
+        DependencyProperty.Register(nameof(UseTouchGestures), typeof(bool), typeof(Viewport), new(false));
+
+    public static readonly DependencyProperty StylusButtonDownCommandProperty =
+        DependencyProperty.Register(nameof(StylusButtonDownCommand), typeof(ICommand), typeof(Viewport), new(null));
+
+    public static readonly DependencyProperty StylusButtonUpCommandProperty =
+        DependencyProperty.Register(nameof(StylusButtonUpCommand), typeof(ICommand), typeof(Viewport), new(null));
+
+    public static readonly DependencyProperty StylusGestureCommandProperty =
+        DependencyProperty.Register(nameof(StylusGestureCommand), typeof(ICommand), typeof(Viewport), new(null));
+
+    public static readonly DependencyProperty StylusOutOfRangeCommandProperty =
+        DependencyProperty.Register(nameof(StylusOutOfRangeCommand), typeof(ICommand), typeof(Viewport), new(null));
+
+    public static readonly DependencyProperty MiddleMouseClickedCommandProperty =
+        DependencyProperty.Register(nameof(MiddleMouseClickedCommand), typeof(ICommand), typeof(Viewport), new(null));
+
+    public ICommand? MiddleMouseClickedCommand
+    {
+        get => (ICommand?)GetValue(MiddleMouseClickedCommandProperty);
+        set => SetValue(MiddleMouseClickedCommandProperty, value);
+    }
+
+    public ICommand? StylusOutOfRangeCommand
+    {
+        get => (ICommand?)GetValue(StylusOutOfRangeCommandProperty);
+        set => SetValue(StylusOutOfRangeCommandProperty, value);
+    }
+
+    public ICommand? StylusGestureCommand
+    {
+        get => (ICommand?)GetValue(StylusGestureCommandProperty);
+        set => SetValue(StylusGestureCommandProperty, value);
+    }
+
+    public ICommand? StylusButtonUpCommand
+    {
+        get => (ICommand?)GetValue(StylusButtonUpCommandProperty);
+        set => SetValue(StylusButtonUpCommandProperty, value);
+    }
+
+    public ICommand? StylusButtonDownCommand
+    {
+        get => (ICommand?)GetValue(StylusButtonDownCommandProperty);
+        set => SetValue(StylusButtonDownCommandProperty, value);
+    }
+
+    public bool UseTouchGestures
+    {
+        get => (bool)GetValue(UseTouchGesturesProperty);
+        set => SetValue(UseTouchGesturesProperty, value);
+    }
+
     public ExecutionTrigger<VecI>? CenterViewportTrigger
     {
         get => (ExecutionTrigger<VecI>)GetValue(CenterViewportTriggerProperty);
@@ -356,4 +410,12 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         if (args.NewValue != null)
             ((ExecutionTrigger<double>)args.NewValue).Triggered += viewport.ZoomZoomboxContent;
     }
+
+    private void Grid_PreviewMouseDown(object sender, MouseButtonEventArgs e)
+    {
+        if (MiddleMouseClickedCommand is null)
+            return;
+        if (Mouse.MiddleButton == MouseButtonState.Pressed && MiddleMouseClickedCommand.CanExecute(null))
+            MiddleMouseClickedCommand.Execute(null);
+    }
 }