Bläddra i källkod

Layers multiple selection

Equbuxu 3 år sedan
förälder
incheckning
e78dbae1ad

+ 17 - 2
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -94,12 +94,27 @@ internal class DocumentUpdater
             case AddSoftSelectedMember_PassthroughAction info:
                 ProcessAddSoftSelectedMember(info);
                 break;
+            case RemoveSoftSelectedMember_PassthroughAction info:
+                ProcessRemoveSoftSelectedMember(info);
+                break;
             case ClearSoftSelectedMembers_PassthroughAction info:
                 ProcessClearSoftSelectedMembers(info);
                 break;
         }
     }
 
+    private void ProcessRemoveSoftSelectedMember(RemoveSoftSelectedMember_PassthroughAction info)
+    {
+        StructureMemberViewModel? member = helper.StructureHelper.Find(info.GuidValue);
+        if (member is null || member.Selection == StructureMemberSelectionType.Hard)
+            return;
+        if (member.Selection != StructureMemberSelectionType.Soft)
+            return;
+        member.Selection = StructureMemberSelectionType.None;
+        member.RaisePropertyChanged(nameof(member.Selection));
+        doc.InternalRemoveSoftSelectedMember(member);
+    }
+
     private void ProcessClearSoftSelectedMembers(ClearSoftSelectedMembers_PassthroughAction info)
     {
         foreach (StructureMemberViewModel? oldMember in doc.SoftSelectedStructureMembers)
@@ -114,8 +129,8 @@ internal class DocumentUpdater
 
     private void ProcessAddSoftSelectedMember(AddSoftSelectedMember_PassthroughAction info)
     {
-        StructureMemberViewModel? member = helper.StructureHelper.FindOrThrow(info.GuidValue);
-        if (member.Selection == StructureMemberSelectionType.Hard)
+        StructureMemberViewModel? member = helper.StructureHelper.Find(info.GuidValue);
+        if (member is null || member.Selection == StructureMemberSelectionType.Hard)
             return;
         member.Selection = StructureMemberSelectionType.Soft;
         member.RaisePropertyChanged(nameof(member.Selection));

+ 5 - 0
src/PixiEditor/Models/DocumentPassthroughActions/RemoveSoftSelectedMember_PassthroughAction.cs

@@ -0,0 +1,5 @@
+using PixiEditor.ChangeableDocument.Actions;
+using PixiEditor.ChangeableDocument.ChangeInfos;
+
+namespace PixiEditor.Models.DocumentPassthroughActions;
+internal record class RemoveSoftSelectedMember_PassthroughAction(Guid GuidValue) : IAction, IChangeInfo;

+ 3 - 0
src/PixiEditor/ViewModels/SubViewModels/Document/DocumentViewModel.cs

@@ -207,6 +207,7 @@ internal class DocumentViewModel : NotifyableObject
     public void InternalClearSoftSelectedMembers() => softSelectedStructureMembers.Clear();
 
     public void InternalAddSoftSelectedMember(StructureMemberViewModel member) => softSelectedStructureMembers.Add(member);
+    public void InternalRemoveSoftSelectedMember(StructureMemberViewModel member) => softSelectedStructureMembers.Remove(member);
 
     #endregion
 
@@ -243,6 +244,8 @@ internal class DocumentViewModel : NotifyableObject
 
     public void AddSoftSelectedMember(Guid memberGuid) => Helpers.ActionAccumulator.AddActions(new AddSoftSelectedMember_PassthroughAction(memberGuid));
 
+    public void RemoveSoftSelectedMember(Guid memberGuid) => Helpers.ActionAccumulator.AddActions(new RemoveSoftSelectedMember_PassthroughAction(memberGuid));
+
     public void ClearSoftSelectedMembers() => Helpers.ActionAccumulator.AddActions(new ClearSoftSelectedMembers_PassthroughAction());
 
     public void UseOpacitySlider() => Helpers.ChangeController.TryStartUpdateableChange<StructureMemberOpacityExecutor>();

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

@@ -19,7 +19,7 @@
     <UserControl.Resources>
         <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter" />
     </UserControl.Resources>
-    <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True" Tag="{Binding ElementName=folderControl}" MouseDown="Border_MouseDown">
+    <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True" Tag="{Binding ElementName=folderControl}">
         <Border.Background>
             <Binding ElementName="folderControl" Path="Folder.Selection">
                 <Binding.Converter>

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

@@ -1,6 +1,5 @@
 using System.Windows;
 using System.Windows.Controls;
-using System.Windows.Input;
 using System.Windows.Media;
 using PixiEditor.Models.Enums;
 using PixiEditor.ViewModels.SubViewModels.Document;
@@ -77,11 +76,6 @@ internal partial class FolderControl : UserControl
         HandleDrop(e.Data, StructureMemberPlacement.Below);
     }
 
-    private void Border_MouseDown(object sender, MouseButtonEventArgs e)
-    {
-        Folder?.Document.SetSelectedMember(Folder.GuidValue);
-    }
-
     private void FolderControl_DragEnter(object sender, DragEventArgs e)
     {
         middleDropGrid.Visibility = Visibility.Visible;

+ 3 - 2
src/PixiEditor/Views/UserControls/Layers/LayerControl.xaml

@@ -10,10 +10,11 @@
              xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
              xmlns:behaviors="clr-namespace:PixiEditor.Helpers.Behaviours"
              xmlns:helpers="clr-namespace:PixiEditor.Helpers.UI"
-             mc:Ignorable="d" Focusable="True"
+             mc:Ignorable="d" 
+             Focusable="True"
              d:DesignHeight="60" d:DesignWidth="250" Name="uc"
              MouseLeave="LayerItem_OnMouseLeave" MouseEnter="LayerItem_OnMouseEnter">
-    <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True" MouseDown="Border_MouseDown">
+    <Border BorderThickness="0 0 0 0.5" BorderBrush="Gray" MinWidth="60" Focusable="True">
         <Border.Background>
             <Binding ElementName="uc" Path="Layer.Selection">
                 <Binding.Converter>

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

@@ -131,9 +131,4 @@ internal partial class LayerControl : UserControl
         RemoveDragEffect((Grid)sender);
         HandleDrop(e.Data, StructureMemberPlacement.BelowOutsideFolder);
     }
-
-    private void Border_MouseDown(object sender, MouseButtonEventArgs e)
-    {
-        Layer?.Document.SetSelectedMember(Layer.GuidValue);
-    }
 }

+ 4 - 0
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml

@@ -125,14 +125,18 @@
                     </Style>
                 </TreeView.ItemContainerStyle>
                 <TreeView.Resources>
+                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Transparent"/>
+                    <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}" Color="Transparent" />
                     <HierarchicalDataTemplate DataType="{x:Type docVm:FolderViewModel}" ItemsSource="{Binding Children}">
                         <layerUserControls:FolderControl
                             Folder="{Binding}"
+                            MouseDown="FolderControl_MouseDown"
                             MouseMove="LayerGroup_MouseMove"/>
                     </HierarchicalDataTemplate>
                     <DataTemplate DataType="{x:Type docVm:LayerViewModel}">
                         <layerUserControls:LayerControl
                             Layer="{Binding}"
+                            MouseDown="LayerControl_MouseDown"
                             MouseMove="LayerStructureItemContainer_MouseMove"/>
                     </DataTemplate>
                 </TreeView.Resources>

+ 78 - 0
src/PixiEditor/Views/UserControls/Layers/LayersManager.xaml.cs

@@ -1,5 +1,6 @@
 using System.Windows;
 using System.Windows.Controls;
+using System.Windows.Input;
 using System.Windows.Media;
 using PixiEditor.Models.Controllers;
 using PixiEditor.Models.Enums;
@@ -76,4 +77,81 @@ internal partial class LayersManager : UserControl
     {
         ((Border)sender).BorderBrush = Brushes.Transparent;
     }
+
+    private static int TraverseRange(Guid bound1, Guid bound2, FolderViewModel root, Action<StructureMemberViewModel> action, int matches = 0)
+    {
+        if (matches == 2)
+            return 2;
+        foreach (StructureMemberViewModel child in root.Children)
+        {
+            if (child is FolderViewModel innerFolder)
+            {
+                matches = TraverseRange(bound1, bound2, innerFolder, action, matches);
+            }
+            if (matches == 1)
+                action(child);
+            if (matches == 2)
+                return 2;
+            if (child.GuidValue == bound1 || child.GuidValue == bound2)
+            {
+                matches++;
+                if (matches == 1)
+                    action(child);
+                if (matches == 2)
+                    return 2;
+            }
+        }
+        return matches;
+    }
+
+    private void HandleMouseDown(StructureMemberViewModel memberVM)
+    {
+        if (ActiveDocument is null)
+            return;
+        if (Keyboard.IsKeyDown(Key.LeftCtrl) || Keyboard.IsKeyDown(Key.RightCtrl))
+        {
+            if (memberVM.Selection == StructureMemberSelectionType.Hard)
+                return;
+            else if (memberVM.Selection == StructureMemberSelectionType.Soft)
+                ActiveDocument.RemoveSoftSelectedMember(memberVM.GuidValue);
+            else if (memberVM.Selection == StructureMemberSelectionType.None)
+                ActiveDocument.AddSoftSelectedMember(memberVM.GuidValue);
+        }
+        else if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
+        {
+            if (ActiveDocument.SelectedStructureMember is null || ActiveDocument.SelectedStructureMember.GuidValue == memberVM.GuidValue)
+                return;
+            ActiveDocument.ClearSoftSelectedMembers();
+            TraverseRange(
+                ActiveDocument.SelectedStructureMember.GuidValue,
+                memberVM.GuidValue,
+                ActiveDocument.StructureRoot,
+                static member =>
+                {
+                    if (member.Selection == StructureMemberSelectionType.None)
+                        member.Document.AddSoftSelectedMember(member.GuidValue);
+                });
+        }
+        else
+        {
+            ActiveDocument.SetSelectedMember(memberVM.GuidValue);
+            ActiveDocument.ClearSoftSelectedMembers();
+        }
+    }
+
+    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);
+    }
+
+    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);
+    }
 }