Forráskód Böngészése

Update traversing API to support a NoFurther traversing operation

CPKreuz 2 hete
szülő
commit
1089a0c3c2

+ 2 - 1
src/PixiEditor/Models/DocumentModels/DocumentStructureHelper.cs

@@ -8,6 +8,7 @@ using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.Models.Handlers;
 using PixiEditor.Models.Layers;
 using PixiEditor.UI.Common.Localization;
+using PixiEditor.ViewModels.Nodes;
 
 namespace PixiEditor.Models.DocumentModels;
 #nullable enable
@@ -34,7 +35,7 @@ internal class DocumentStructureHelper
                     count++;
             }
 
-            return true;
+            return Traverse.Further;
         });
         return $"{name} {count}";
     }

+ 3 - 2
src/PixiEditor/Models/DocumentModels/Public/DocumentOperationsModule.cs

@@ -21,6 +21,7 @@ using PixiEditor.Models.Position;
 using PixiEditor.Models.Tools;
 using Drawie.Numerics;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
+using PixiEditor.ViewModels.Nodes;
 
 namespace PixiEditor.Models.DocumentModels.Public;
 #nullable enable
@@ -617,10 +618,10 @@ internal class DocumentOperationsModule : IDocumentOperations
             if (!members.Contains(traversedNode.Id))
             {
                 parent = traversedNode;
-                return false;
+                return Traverse.Exit;
             }
 
-            return true;
+            return Traverse.Further;
         });
 
         if (parent is null)

+ 16 - 15
src/PixiEditor/Models/DocumentModels/Public/DocumentStructureModule.cs

@@ -1,5 +1,6 @@
 using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
 using PixiEditor.Models.Handlers;
+using PixiEditor.ViewModels.Nodes;
 
 namespace PixiEditor.Models.DocumentModels.Public;
 #nullable enable
@@ -45,10 +46,10 @@ internal class DocumentStructureModule
             if (!guids.Contains(traversedNode.Id) && traversedNode is IStructureMemberHandler)
             {
                 parent = traversedNode;
-                return false;
+                return Traverse.Exit;
             }
 
-            return true;
+            return Traverse.Further;
         });
 
         if (parent is null)
@@ -62,10 +63,10 @@ internal class DocumentStructureModule
                 if (!guids.Contains(traversedNode.Id) && traversedNode is IStructureMemberHandler)
                 {
                     parent = traversedNode;
-                    return false;
+                    return Traverse.Exit;
                 }
 
-                return true;
+                return Traverse.Further;
             });
         }
 
@@ -110,7 +111,7 @@ internal class DocumentStructureModule
         {
             if (node is IStructureMemberHandler parent && input is { PropertyName: FolderNode.ContentInternalName })
                 parents.Add(parent);
-            return true;
+            return Traverse.Further;
         });
 
         return parents;
@@ -187,7 +188,7 @@ internal class DocumentStructureModule
                 toFill.Add(strNode);
             }
 
-            return true;
+            return Traverse.Further;
         });
     }
 
@@ -197,10 +198,10 @@ internal class DocumentStructureModule
         startNode.TraverseForwards(node =>
         {
             if (node == startNode)
-                return true;
+                return Traverse.Further;
 
             result = node;
-            return false;
+            return Traverse.Exit;
         });
 
         return result;
@@ -218,13 +219,13 @@ internal class DocumentStructureModule
             if (node != member && node is IStructureMemberHandler structureMemberNode)
             {
                 if (node is IFolderHandler && !includeFolders)
-                    return true;
+                    return Traverse.Further;
 
                 result = structureMemberNode;
-                return false;
+                return Traverse.Exit;
             }
 
-            return true;
+            return Traverse.Further;
         });
 
         return result;
@@ -242,13 +243,13 @@ internal class DocumentStructureModule
             if (node != member && node is IStructureMemberHandler structureMemberNode)
             {
                 if (node is IFolderHandler && !includeFolders)
-                    return true;
+                    return Traverse.Further;
 
                 result = structureMemberNode;
-                return false;
+                return Traverse.Exit;
             }
 
-            return true;
+            return Traverse.Further;
         });
 
         return result;
@@ -268,7 +269,7 @@ internal class DocumentStructureModule
             if (node is IStructureMemberHandler structureMemberNode)
                 children.Add(structureMemberNode);
 
-            return true;
+            return Traverse.Further;
         });
 
         return children;

+ 7 - 7
src/PixiEditor/Models/Handlers/INodeHandler.cs

@@ -27,13 +27,13 @@ public interface INodeHandler : INotifyPropertyChanged, IDisposable
     public Rect UiSize { get; set; }
     public bool IsNodeSelected { get; set; }
     public string Icon { get; }
-    public void TraverseBackwards(Func<INodeHandler, bool> func);
-    public void TraverseBackwards(Func<INodeHandler, INodeHandler, bool> func);
-    public void TraverseBackwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, bool> func);
-    public void TraverseForwards(Func<INodeHandler, bool> func);
-    public void TraverseForwards(Func<INodeHandler, INodeHandler, bool> func);
-    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, bool> func);
-    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, INodePropertyHandler, bool> func);
+    public void TraverseBackwards(Func<INodeHandler, Traverse> func);
+    public void TraverseBackwards(Func<INodeHandler, INodeHandler, Traverse> func);
+    public void TraverseBackwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, Traverse> func);
+    public void TraverseForwards(Func<INodeHandler, Traverse> func);
+    public void TraverseForwards(Func<INodeHandler, INodeHandler, Traverse> func);
+    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, Traverse> func);
+    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, INodePropertyHandler, Traverse> func);
     public HashSet<NodeFrameViewModelBase> Frames { get; }
     public IReadOnlyDictionary<string, INodePropertyHandler> InputPropertyMap { get; }
     public IReadOnlyDictionary<string, INodePropertyHandler> OutputPropertyMap { get; }

+ 4 - 3
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -8,6 +8,7 @@ using PixiEditor.Helpers;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Handlers;
 using Drawie.Numerics;
+using PixiEditor.ViewModels.Nodes;
 
 namespace PixiEditor.Models.Rendering;
 
@@ -265,16 +266,16 @@ internal class MemberPreviewUpdater
         nodeVm.TraverseForwards(next =>
         {
             if (next is not INodeHandler nextVm)
-                return true;
+                return Traverse.Further;
 
             var nextNode = allNodes.FirstOrDefault(x => x.Id == next.Id);
 
             if (nextNode is null || actualRepaintedNodes.Contains(next.Id))
-                return true;
+                return Traverse.Further;
 
             RequestRepaintNode(nextNode, nextVm);
             actualRepaintedNodes.Add(next.Id);
-            return true;
+            return Traverse.Further;
         });
     }
 

+ 6 - 6
src/PixiEditor/ViewModels/Document/NodeGraphViewModel.cs

@@ -156,15 +156,15 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposabl
         node.TraverseBackwards(x =>
         {
             if (x is IPairNodeEndViewModel)
-                return false;
+                return Traverse.NoFurther;
 
             if (x is not IPairNodeStartViewModel)
-                return true;
+                return Traverse.Further;
 
             var zone = startLookup[x];
             currentlyPartOf.Add(zone);
 
-            return true;
+            return Traverse.Further;
         });
 
         foreach (var frame in currentlyPartOf)
@@ -203,14 +203,14 @@ internal class NodeGraphViewModel : ViewModelBase, INodeGraphHandler, IDisposabl
                      .SelectMany(x => x.ConnectedInputs)
                      .Select(x => x.Node))
         {
-            node.TraverseForwards((x, _, _) =>
+            node.TraverseForwards((x) =>
             {
                 if (x is IPairNodeEndViewModel)
-                    return false;
+                    return Traverse.NoFurther;
 
                 currentlyPartOf.Add(x);
 
-                return true;
+                return Traverse.Further;
             });
         }
 

+ 2 - 2
src/PixiEditor/ViewModels/Document/Nodes/StructureMemberViewModel.cs

@@ -60,10 +60,10 @@ internal abstract class StructureMemberViewModel<T> : NodeViewModel<T>, IStructu
                 if (node is IFolderHandler parent && input is { PropertyName: FolderNode.ContentInternalName })
                 {
                     visible = parent.IsVisibleBindable;
-                    return visible;
+                    return visible ? Traverse.Further : Traverse.Exit;
                 }
 
-                return true;
+                return Traverse.Further;
             });
 
             return visible;

+ 2 - 1
src/PixiEditor/ViewModels/Document/StructureTree.cs

@@ -1,5 +1,6 @@
 using System.Collections.ObjectModel;
 using PixiEditor.Models.Handlers;
+using PixiEditor.ViewModels.Nodes;
 
 namespace PixiEditor.ViewModels.Document;
 
@@ -60,7 +61,7 @@ internal class StructureTree
 
             _memberMap.TryAdd(node, lastRoot);
 
-            return true;
+            return Traverse.Further;
         });
 
         List<IStructureMemberHandler> toRemove = new();

+ 91 - 24
src/PixiEditor/ViewModels/Nodes/NodeViewModel.cs

@@ -1,6 +1,7 @@
 using System.Collections.ObjectModel;
 using System.Collections.Specialized;
 using System.ComponentModel;
+using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using Avalonia;
 using Avalonia.Media;
@@ -225,7 +226,11 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
 
     public string Icon => icon ??= GetType().GetCustomAttribute<NodeViewModelAttribute>().Icon;
 
-    public void TraverseBackwards(Func<INodeHandler, bool> func)
+    [DoesNotReturn]
+    private void ThrowInvalidTraverseResult(Traverse traverse) =>
+        throw new IndexOutOfRangeException($"Invalid Traverse Option '{traverse}'");
+
+    public void TraverseBackwards(Func<INodeHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<INodeHandler>();
@@ -240,9 +245,18 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
                 continue;
             }
 
-            if (!func(node))
+            var result = func(node);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var inputProperty in node.Inputs)
@@ -255,7 +269,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
         }
     }
 
-    public void TraverseBackwards(Func<INodeHandler, INodeHandler, bool> func)
+    public void TraverseBackwards(Func<INodeHandler, INodeHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<(INodeHandler, INodeHandler)>();
@@ -270,9 +284,18 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
                 continue;
             }
 
-            if (!func(node.Item1, node.Item2))
+            var result = func(node.Item1, node.Item2);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var inputProperty in node.Item1.Inputs)
@@ -285,7 +308,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
         }
     }
 
-    public void TraverseBackwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, bool> func)
+    public void TraverseBackwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<(INodeHandler, INodeHandler, INodePropertyHandler)>();
@@ -299,10 +322,18 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
             {
                 continue;
             }
-
-            if (!func(node.Item1, node.Item2, node.Item3))
+            var result = func(node.Item1, node.Item2, node.Item3);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var inputProperty in node.Item1.Inputs)
@@ -315,7 +346,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
         }
     }
 
-    public void TraverseForwards(Func<INodeHandler, bool> func)
+    public void TraverseForwards(Func<INodeHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<INodeHandler>();
@@ -329,10 +360,19 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
             {
                 continue;
             }
-
-            if (!func(node))
+            
+            var result = func(node);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var outputProperty in node.Outputs)
@@ -345,7 +385,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
         }
     }
 
-    public void TraverseForwards(Func<INodeHandler, INodeHandler, bool> func)
+    public void TraverseForwards(Func<INodeHandler, INodeHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<(INodeHandler, INodeHandler)>();
@@ -359,10 +399,19 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
             {
                 continue;
             }
-
-            if (!func(node.Item1, node.Item2))
+            
+            var result = func(node.Item1, node.Item2);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var outputProperty in node.Item1.Outputs)
@@ -375,7 +424,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
         }
     }
 
-    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, bool> func)
+    public void TraverseForwards(Func<INodeHandler, INodeHandler, INodePropertyHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<(INodeHandler, INodeHandler, INodePropertyHandler)>();
@@ -390,9 +439,18 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
                 continue;
             }
 
-            if (!func(node.Item1, node.Item2, node.Item3))
+            var result = func(node.Item1, node.Item2, node.Item3);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var outputProperty in node.Item1.Outputs)
@@ -406,7 +464,7 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
     }
 
     public void TraverseForwards(
-        Func<INodeHandler, INodeHandler, INodePropertyHandler, INodePropertyHandler, bool> func)
+        Func<INodeHandler, INodeHandler, INodePropertyHandler, INodePropertyHandler, Traverse> func)
     {
         var visited = new HashSet<INodeHandler>();
         var queueNodes = new Queue<(INodeHandler, INodeHandler, INodePropertyHandler, INodePropertyHandler)>();
@@ -421,9 +479,18 @@ internal abstract class NodeViewModel : ObservableObject, INodeHandler
                 continue;
             }
 
-            if (!func(node.Item1, node.Item2, node.Item3, node.Item4))
+            var result = func(node.Item1, node.Item2, node.Item3, node.Item4);
+            switch (result)
             {
-                return;
+                case Traverse.NoFurther:
+                    continue;
+                case Traverse.Exit:
+                    return;
+                case Traverse.Further:
+                    break;
+                default:
+                    ThrowInvalidTraverseResult(result);
+                    break;
             }
 
             foreach (var outputProperty in node.Item1.Outputs)

+ 19 - 0
src/PixiEditor/ViewModels/Nodes/Traverse.cs

@@ -0,0 +1,19 @@
+namespace PixiEditor.ViewModels.Nodes;
+
+public enum Traverse
+{
+    /// <summary>
+    /// Go further in this direction, meaning any further child connections will not be enqueued.
+    /// </summary>
+    Further,
+    
+    /// <summary>
+    /// Don't go further in this direction, meaning all further child connections will be enqueued.
+    /// </summary>
+    NoFurther,
+    
+    /// <summary>
+    /// Completely stop traversing in any direction, meaning this will drop all enqueued child connections.
+    /// </summary>
+    Exit
+}