public virtual bool Arrange(FlowChart chart) { chart.UndoManager.onStartLayout("Grid layout"); // Build the graph FCGraph graph = new FCGraph(chart, _keepGroupLayout); // Find the root adapter Layout.INode rootNode = null; if (_root != null) { foreach (FCNode node in graph.Nodes) { if (node.Node == _root) { rootNode = node; break; } } } // Split graph to subgraphs Layout.IGraph[] subgraphs = null; if (_splitGraph) { subgraphs = Layout.GraphSplitter.Split( graph, new FCGraphBuilder(chart, false)); } else { subgraphs = new Layout.IGraph[] { graph }; } // Create the layouter Layout.GridLayout layout = new Layout.GridLayout(); Layout.LayoutProgress progress = null; if (_progress != null) progress = new Layout.LayoutProgress(this.OnLayoutProgress); Layout.GridLayoutInfo info = new Layout.GridLayoutInfo(); info.GridSize = this.GridSize; info.Iterations = this.Iterations; info.XGap = this.XGap; info.YGap = this.YGap; info.RndSeed = this.RndSeed; float xOffset = XGap; foreach (FCGraph subgraph in subgraphs) { // If a root node is specified and the subgraph // does not contain that node, do not arrange // the subgraph if (rootNode != null) { if (!subgraph.Nodes.Contains(rootNode)) continue; } // Set the start and end nodes info.StartNode = null; info.EndNode = null; foreach (FCNode node in subgraph.Nodes) { if (node.Node == _startNode) info.StartNode = node; if (node.Node == _endNode) info.EndNode = node; } // Ensure both start and end nodes are set if (info.StartNode == null || info.EndNode == null) { info.StartNode = null; info.EndNode = null; } layout.Arrange(subgraph, info, progress); // Translate the whole subgraph RectangleF graphBounds = subgraph.GetBounds(false); float xToMove = xOffset - graphBounds.X; float yToMove = info.YGap - graphBounds.Y; foreach (FCNode node in subgraph.Nodes) { RectangleF nodeBounds = node.Bounds; RectangleF oldBounds = node.Node.BoundingRect; nodeBounds.X += xToMove; nodeBounds.Y += yToMove; node.Bounds = nodeBounds; if (_layoutNode != null) _layoutNode(node.Node, oldBounds); } xOffset += graphBounds.Width + info.GridSize; // Update arrows foreach (FCLink link in subgraph.Links) { if (link.Arrow.IgnoreLayout) continue; link.Arrow.arrangePoints(_anchoring); if (_layoutLink != null) _layoutLink(link.Arrow); } } chart.RouteAllArrows(); chart.Invalidate(); chart.UndoManager.onEndLayout(); return true; }