/// <summary>
        /// Aggregates all nodes of the original graph by the selector and runs the layout.
        /// </summary>
        /// <remarks>
        /// Before aggregating the nodes, all existing aggregations are
        /// <see cref="AggregateGraphWrapper.SeparateAll">separated</see>.
        /// </remarks>
        private void AggregateAll <TKey>(Func <INode, TKey> selector, Func <TKey, INodeStyle> styleFactory)
        {
            AggregateGraph.SeparateAll();

            foreach (var grouping in Graph.Nodes.GroupBy(selector).ToList())
            {
                Aggregate(grouping.ToList(), grouping.Key, styleFactory);
            }

            RunLayout();
        }
        /// <summary>
        /// Fills the context menu with menu items based on the clicked node.
        /// </summary>
        private void OnPopulateItemContextMenu(object sender, PopulateItemContextMenuEventArgs <IModelItem> e)
        {
            // first update the selection
            INode node = e.Item as INode;

            // if the cursor is over a node select it, else clear selection
            UpdateSelection(node);

            // Create the context menu items
            var selectedNodes = graphControl.Selection.SelectedNodes;

            if (selectedNodes.Count > 0)
            {
                // only allow aggregation operations on nodes that are not aggregation nodes already
                var aggregateAllowed = selectedNodes.Any(n => !AggregateGraph.IsAggregationItem(n));

                var aggregateByShape =
                    new ToolStripMenuItem("Aggregate Nodes with Same Shape")
                {
                    Enabled = aggregateAllowed
                };
                aggregateByShape.Click += (o, args) => AggregateSame(selectedNodes.ToList(), ShapeSelector,
                                                                     ShapeStyle);
                e.Menu.Items.Add(aggregateByShape);

                var aggregateByColor =
                    new ToolStripMenuItem("Aggregate Nodes with Same Color")
                {
                    Enabled = aggregateAllowed
                };
                aggregateByColor.Click += (o, args) => AggregateSame(selectedNodes.ToList(), ColorSelector, ColorStyle);
                e.Menu.Items.Add(aggregateByColor);

                var aggregateByShapeAndColor =
                    new ToolStripMenuItem("Aggregate Nodes with Same Shape and Color")
                {
                    Enabled = aggregateAllowed
                };
                aggregateByShapeAndColor.Click += (o, args) =>
                                                  AggregateSame(selectedNodes.ToList(), ShapeAndColorSelector, ShapeAndColorStyle);
                e.Menu.Items.Add(aggregateByShapeAndColor);

                var separateAllowed = selectedNodes.Any(n => AggregateGraph.IsAggregationItem(n));
                var separate        = new ToolStripMenuItem("Separate")
                {
                    Enabled = separateAllowed
                };
                separate.Click += (o, args) => Separate(selectedNodes.ToList());
                e.Menu.Items.Add(separate);
            }
            else
            {
                var aggregateByShape = new ToolStripMenuItem("Aggregate All Nodes by Shape");
                aggregateByShape.Click += (o, args) => AggregateAll(ShapeSelector, ShapeStyle);
                e.Menu.Items.Add(aggregateByShape);

                var aggregateByColor = new ToolStripMenuItem("Aggregate All Nodes by Color");
                aggregateByColor.Click += (o, args) => AggregateAll(ColorSelector, ColorStyle);
                e.Menu.Items.Add(aggregateByColor);

                var aggregateByShapeAndColor = new ToolStripMenuItem("Aggregate All Nodes by Shape and Color");
                aggregateByShapeAndColor.Click += (o, args) => AggregateAll(ShapeAndColorSelector, ShapeAndColorStyle);
                e.Menu.Items.Add(aggregateByShapeAndColor);

                var separateAllowed = Graph.Nodes.Any(n => AggregateGraph.IsAggregationItem(n));
                var separateAll     = new ToolStripMenuItem("Separate All")
                {
                    Enabled = separateAllowed
                };
                separateAll.Click += (o, args) => {
                    AggregateGraph.SeparateAll();
                    RunLayout();
                };
                e.Menu.Items.Add(separateAll);
            }

            e.ShowMenu = true;
            e.Handled  = true;
        }