private void RegisterAggregationCallbacks()
        {
            Graph.NodeCreated += (sender, args) => {
                if (AggregateGraph.IsAggregationItem(args.Item))
                {
                    // add a label with the number of aggregated items to the new aggregation node
                    Graph.AddLabel(args.Item, AggregateGraph.GetAggregatedItems(args.Item).Count.ToString());
                }
            };

            Graph.EdgeCreated += (sender, args) => {
                var edge = args.Item;
                if (!AggregateGraph.IsAggregationItem(edge))
                {
                    return;
                }

                // add a label with the number of all original aggregated edges represented by the new aggregation edge
                var aggregatedEdgesCount = AggregateGraph.GetAllAggregatedOriginalItems(edge).Count;
                if (aggregatedEdgesCount > 1)
                {
                    Graph.AddLabel(edge, aggregatedEdgesCount.ToString());
                }

                // set the thickness to the number of aggregated edges
                Graph.SetStyle(edge,
                               new PolylineEdgeStyle {
                    Pen = new Pen(Brushes.Gray, 1 + aggregatedEdgesCount)
                });
            };
        }
        /// <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));
        }