private void CreateReplacementEdge(INode sourceNode, INode targetNode, IEdge edge)
 {
     if ((AggregateGraph.IsAggregationItem(sourceNode) || AggregateGraph.IsAggregationItem(targetNode)) &&
         AggregateGraph.GetEdge(sourceNode, targetNode) == null &&
         AggregateGraph.GetEdge(targetNode, sourceNode) == null)
     {
         AggregateGraph.CreateEdge(sourceNode, targetNode, edge.Style);
     }
 }
        /// <summary>
        /// Separates an aggregated aggregation node and replaces it by a new aggregation node.
        /// </summary>
        /// <remarks>
        /// Creates hierarchy edges between the new aggregation node and its children.
        /// </remarks>
        /// <param name="node">The node.</param>
        /// <returns>The nodes affected by this operation. The created aggregation node is always the first item.</returns>
        public IListEnumerable <INode> Separate(INode node)
        {
            var aggregationInfo = (AggregationNodeInfo)node.Tag;
            var aggregate       = aggregationInfo.Aggregate;
            var aggregatedItems = AggregateGraph.GetAggregatedItems(node)
                                  .Where(n => n != aggregate.Node)
                                  .Cast <INode>().ToList();

            AggregateGraph.Separate(node);

            var nodesToAggregate = aggregate.Node != null
          ? new ListEnumerable <INode>(new List <INode> {
                aggregate.Node
            })
          : ListEnumerable <INode> .Empty;
            var aggregationNode = AggregateGraph.Aggregate(nodesToAggregate, node.Layout.ToRectD(), AggregationNodeStyle);

            foreach (var child in aggregatedItems)
            {
                AggregateGraph.CreateEdge(aggregationNode, child, HierarchyEdgeStyle, true);
                AggregateGraph.SetNodeLayout(child,
                                             RectD.FromCenter(aggregationNode.Layout.GetCenter(), child.Layout.ToSizeD()));
                ReplaceEdges(child);
            }

            aggregationInfo.IsAggregated = false;
            aggregateToNode[aggregate]   = aggregationNode;
            aggregationNode.Tag          = aggregationInfo;

            var affectedNodes = new List <INode> {
                aggregationNode
            };

            affectedNodes.AddRange(aggregatedItems);

            if (aggregate.Parent != null && aggregateToNode.TryGetValue(aggregate.Parent, out var parentNode))
            {
                AggregateGraph.CreateEdge(parentNode, aggregationNode, HierarchyEdgeStyle, true);
                affectedNodes.Add(parentNode);
            }

            if (aggregate.Node != null)
            {
                placeholderMap[aggregate.Node] = aggregationNode;
                CopyLabels(aggregate.Node, aggregationNode);
                ReplaceEdges(aggregationNode);
            }

            return(new ListEnumerable <INode>(affectedNodes));
        }
        /// <summary>
        /// Replaces a separated node and its hierarchy children with a new aggregation node.
        /// </summary>
        /// <param name="node">The node.</param>
        /// <returns>The nodes affected by this operation. The created aggregation node is always the first item.</returns>
        public IListEnumerable <INode> Aggregate(INode node)
        {
            var aggregationInfo = (AggregationNodeInfo)node.Tag;
            var aggregate       = aggregationInfo.Aggregate;
            var aggregationNode = AggregateRecursively(aggregate);

            var affectedNodes = new List <INode> {
                aggregationNode
            };

            if (aggregate.Parent != null && aggregateToNode.TryGetValue(aggregate.Parent, out var parentNode))
            {
                AggregateGraph.CreateEdge(parentNode, aggregationNode, HierarchyEdgeStyle, true);
                affectedNodes.Add(parentNode);
            }

            if (aggregate.Node != null)
            {
                ReplaceEdges(aggregationNode);
            }

            return(new ListEnumerable <INode>(affectedNodes));
        }