protected override bool Apply(Subgraph subgraph, NodeGraph fullGraph)
            {
                var rootNode = fullGraph.Nodes.GetOrDefaultFromReadOnly(_rootNodeKey);

                if (rootNode == null)
                {
                    return(false);
                }

                if ((rootNode as TypeNode)?.Project is not {
                } project)
                {
                    return(false);
                }

                var modified = false;

                foreach (var kvp in fullGraph.Nodes)
                {
                    if (project.Equals((kvp.Value as TypeNode)?.Project))
                    {
                        modified |= subgraph.AddPinnedNode(kvp.Key, fullGraph);
                    }
                }

                return(modified);
            }
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var currentAdditionals = subgraph.AdditionalNodes;
                var nodes = fullGraph.Nodes;

                var newAdditionals = (nodes.ContainsKey(_selected), _includeConnectionsAsWell) switch
                {
                    (false, _) => ArrayUtils.GetEmpty <NodeKey>(),
                    (_, false) => new[] { _selected },
                    (_, true) => nodes[_selected].AllLinkKeys(includeThis: true)
                };

                var(isDifferent, addedNodes, removedNodes) = newAdditionals.GetUnorderedDiff(currentAdditionals);

                var modified = false;

                if (isDifferent)
                {
                    foreach (var removed in removedNodes)
                    {
                        modified |= subgraph.RemoveNode(removed);
                    }
                    foreach (var added in addedNodes)
                    {
                        modified |= subgraph.AddAdditionalNode(added, fullGraph);
                    }
                }

                modified |= subgraph.SetSelectedNode(_selected);

                return(Task.FromResult(modified));
            }
            protected override bool Apply(Subgraph subgraph, NodeGraph fullGraph)
            {
                var modified = false;

                foreach (var kvp in fullGraph.Nodes)
                {
                    modified |= subgraph.AddPinnedNode(kvp.Key, fullGraph);
                }
                return(modified);
            }
            public override async Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = false;

                foreach (var op in _operations)
                {
                    modified |= await op.Apply(subgraph, fullGraph, ct);
                }

                return(modified);
            }
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = false;

                foreach (var key in subgraph.AllNodes)
                {
                    if (!fullGraph.Nodes.ContainsKey(key))
                    {
                        modified |= subgraph.RemoveNode(key);
                    }
                }

                return(Task.FromResult(modified));
            }
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = false;

                foreach (var node in _nodeKeys)
                {
                    if (fullGraph.Nodes.ContainsKey(node))
                    {
                        modified |= subgraph.AddPinnedNode(node, fullGraph);
                    }
                }

                return(Task.FromResult(modified));
            }
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = false;

                var nodes      = fullGraph.Nodes;
                var nodesToPin = nodes.ContainsKey(_targetNode) ?
                                 nodes[_targetNode].AllLinkKeys(includeThis: true) :
                                 ArrayUtils.GetEmpty <NodeKey>();

                foreach (var node in nodesToPin)
                {
                    modified |= subgraph.AddPinnedNode(node, fullGraph);
                }

                return(Task.FromResult(modified));
            }
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = false;

                foreach (var node in _nodeKeys)
                {
                    if (_dontRemoveSelected && Equals(subgraph._selectedNode, node))
                    {
                        modified |= subgraph.TogglePinned(node, setPinned: false);
                    }
                    else
                    {
                        modified |= subgraph.RemoveNode(node);
                    }
                }

                return(Task.FromResult(modified));
            }
            protected override bool Apply(Subgraph subgraph, NodeGraph fullGraph)
            {
                if (fullGraph.Nodes.GetOrDefaultFromReadOnly(_rootNodeKey) is not {
                } rootNode)
                {
                    return(false);
                }

                var modified       = false;
                var nodesSeen      = new HashSet <Node>();
                var nodesToExplore = new Queue <Node>();

                void TryEnqueue(Node toEnqueue)
                {
                    if (nodesSeen.Add(toEnqueue))
                    {
                        nodesToExplore.Enqueue(toEnqueue);
                    }
                }

                TryEnqueue(rootNode);
                var lp = new LoopProtection();

                while (nodesToExplore.Count > 0)
                {
                    lp.Iterate();
                    var current = nodesToExplore.Dequeue();
                    var links   = _isDependent ? current.BackLinks : current.ForwardLinks;
                    foreach (var dependency in links)
                    {
                        if (dependency.LinkType.HasFlagPartially(_dependencyRelationship))
                        {
                            TryEnqueue(_isDependent ? dependency.Dependent : dependency.Dependency);
                        }
                    }
                }

                foreach (var found in nodesSeen)
                {
                    modified |= subgraph.AddPinnedNode(found.Key, fullGraph);
                }

                return(modified);
            }
            protected override bool Apply(Subgraph subgraph, NodeGraph fullGraph)
            {
                if (fullGraph.Nodes.GetOrDefaultFromReadOnly(_rootNodeKey) is not {
                } rootNode)
                {
                    return(false);
                }

                var modified = subgraph.AddPinnedNode(_rootNodeKey, fullGraph);

                var links = _isDependent ? rootNode.BackLinks : rootNode.ForwardLinks;

                foreach (var link in links)
                {
                    if (link.LinkType.HasFlagPartially(_dependencyRelationship))
                    {
                        var node = _isDependent ? link.Dependent : link.Dependency;
                        modified |= subgraph.AddPinnedNode(node.Key, fullGraph);
                    }
                }
                return(modified);
            }
 protected abstract bool Apply(Subgraph subgraph, NodeGraph fullGraph);
            public sealed override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = Apply(subgraph, fullGraph);

                return(Task.FromResult(modified));
            }
 public abstract Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct);            // TODO: there's no longer a compelling reason for this to be asynchronous
            public override Task <bool> Apply(Subgraph subgraph, NodeGraph fullGraph, CancellationToken ct)
            {
                var modified = subgraph.ClearAdditional();

                return(Task.FromResult(modified));
            }