/// <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; }