[Contribution] Horizontal graph auto-layout code
See original GitHub issueAltought this code is specific for the model of my project (w/ InPorts & OutPorts) I’ve made a recursive method to organize the graph layout horizontally. Example: Before auto layout call & After layout call
In case this helps someone integration I’ll drop the code here.
The function itself:
//NodeData is the custom NodeModel implementation
public delegate void SearchAction(NodeData node, int depthLevel, int branchesOffset);
public int DFS_SearchGraph(SearchAction searchAction, NodeData currentNode, int depthLevel, int maxBranchesPrevChilds)
{
var maxBranchesCurrent = 0;
int maxBranchesPrevChild = 0;
for (int i = 0; i < currentNode.OutPort.connectedNodes.Count; i++)
{
maxBranchesPrevChild = DFS_SearchGraph(searchAction, currentNode.OutPort.connectedNodes[i], depthLevel + 1, maxBranchesPrevChilds + maxBranchesCurrent);
if (i < currentNode.OutPort.connectedNodes.Count-1) //Has next branch
maxBranchesCurrent += maxBranchesPrevChild + 1;
else
maxBranchesCurrent += maxBranchesPrevChild;
}
searchAction(currentNode, depthLevel, maxBranchesPrevChilds);
return maxBranchesCurrent;
}
The delegate implementation & function call:
public void OrganizeLayout()
{
const int marginX = 400;
const int marginY = 120;
var rootNode = FindRootNode();
if (rootNode is null) return;
Dictionary<int, (double?, double?)> nodesPos = new();
foreach (NodeData node in diagram.Nodes)
nodesPos.Add(node.DataId, (null, null));
SearchAction organizeLayoutAction = (n, l, m) =>
{
var xFromCurrent = l * marginX;
var yFromCurrent = m * marginY;
if (nodesPos[n.DataId].Item1.HasValue) //If node already visited
{
var xSet = nodesPos[n.DataId].Item1.Value;
var ySet = nodesPos[n.DataId].Item2.Value;
nodesPos[n.DataId] = (xFromCurrent > xSet ? xFromCurrent : xSet, yFromCurrent < ySet ? yFromCurrent : ySet);
}
else
{
nodesPos[n.DataId] = (xFromCurrent, yFromCurrent);
}
};
DFS_SearchGraph(organizeLayoutAction, rootNode, 0, 0);
foreach (var nodePos in nodesPos)
{
var test = nodePos;
var node = diagram.Nodes.Where(x => ((NodeData)x).DataId == nodePos.Key).FirstOrDefault();
node?.SetPosition(nodePos.Value.Item1.Value, nodePos.Value.Item2.Value);
}
diagram.Refresh();
}
public NodeData FindRootNode()
{
foreach (var node in diagram.Nodes)
if (((NodeData)node).InPort.IsPortEmpty())
return (NodeData)node;
return null;
}
Issue Analytics
- State:
- Created 2 years ago
- Reactions:4
- Comments:8
Top Results From Across the Web
How to setup layout constraints for a horizontal alignment ...
Try the following steps 1) first select all of them and add constraint EQUAL WIDTH to images 2) set the leading space between...
Read more >The why, what, and how of Swift Auto-Layout
It calculates the size and position on your behalf as long as the rules you set (the constraints) result in one sound outcome....
Read more >Throwing Auto Layout Out the Window
The black horizontal line is 16 milliseconds and you can see that for a feed item using UIStackView , it would take 46...
Read more >ConstraintLayout vs Auto Layout: How Do They Compare?
With Auto Layout, each view needs to have enough constraints to determine its vertical and horizontal position and size. For some Views, their ......
Read more >Manual: Auto Layout
The auto layout system provides ways to place elements in nested layout groups such as horizontal groups, vertical groups, or grids.
Read more >
Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free
Top Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
The graph search algorithm is based on DFS but the rest was made by head w/ some trial and error, if that makes sense? To have multiple directions/orientations I’m guessing: You can probably just alter the marginX & marginY values to negative and invert the flow direction. Or use depthLevel for Y position & branchesOffset for X position to make it flow vertically. But never tried it out tho
Hi @glinkot , would you mind sharing your implementation?