private void AutoFormatConnectedNodes(List <XNode.Node> nodes, Rect boundingBox) { if (nodes.Count <= 1) { return; } // Assumes that all nodes are connected // Storing extra data for each node var graphNodes = nodes.ToDictionary(n => n, n => new FormattedNode() { Node = n }); // Find rightmost nodes (nodes that don't have any of our nodes to the right) var endNodes = graphNodes.Values .Where(n => !n.Node.Outputs.SelectMany(o => o.GetConnections()).Any(c => graphNodes.ContainsKey(c.node))) .OrderBy(n => n.Node.position.y) // Keep the order of the endNodes .ToList(); var endNode = new FormattedNode() { Layer = -1, ChildNodes = endNodes }; // Sorted child nodes, as a tree SetChildNodes(graphNodes, endNode); // Longest path layering int maxLayer = SetLayers(graphNodes, endNode); // Set offsets int maxOffset = SetOffsets(endNode, maxLayer); Vector2 topRightPosition = endNodes.First().Node.position; // TODO: Better node spacing (figure out how much space the biggest node in this row takes up and make the row a bit bigger than that) foreach (var n in graphNodes) { n.Key.position.x = (-n.Value.Layer) * 250 + topRightPosition.x; } foreach (var n in graphNodes) { n.Key.position.y = n.Value.Offset * 250 + topRightPosition.y; } }
private static int SetOffsets(FormattedNode endNode, int maxLayer) { int maxOffset = 0; int[] offsets = new int[maxLayer + 1]; // TODO: Replace with iterative version? /*var nodeStack = new Stack<Tuple<FormattedNode, FormattedNode>>(); * nodeStack.Push(Tuple.Create(endNode, endNode)); * while(nodeStack.Count > 0) * { * * }*/ void SetOffsets(FormattedNode node, FormattedNode straightParent) { if (node.Layer >= 0 && offsets[node.Layer] > node.Offset) { straightParent.SubtreeOffset = Math.Max(straightParent.SubtreeOffset, offsets[node.Layer] - node.Offset); } int childOffset = node.Offset; bool firstIteration = true; foreach (var childNode in node.ChildNodes) { childNode.Offset = childOffset; SetOffsets(childNode, firstIteration ? straightParent : childNode); childOffset = childNode.Offset + 1; firstIteration = false; } if (node.Layer >= 0) { node.Offset += straightParent.SubtreeOffset; maxOffset = Math.Max(maxOffset, node.Offset); offsets[node.Layer] = node.Offset + 1; } } SetOffsets(endNode, endNode); return(maxOffset); }
protected override MarkdownNode VisitFormatted(FormattedNode formatted) { var(tagOpen, tagClose) = formatted.Formatting switch { TextFormatting.Bold => ("<strong>", "</strong>"), TextFormatting.Italic => ("<em>", "</em>"), TextFormatting.Underline => ("<u>", "</u>"), TextFormatting.Strikethrough => ("<s>", "</s>"), TextFormatting.Spoiler => ( "<span class=\"spoiler spoiler--hidden\" onclick=\"showSpoiler(event, this)\"><span class=\"spoiler-text\">", "</span></span>"), TextFormatting.Quote => ("<div class=\"quote\">", "</div>"), _ => throw new ArgumentOutOfRangeException(nameof(formatted.Formatting)) }; _buffer.Append(tagOpen); var result = base.VisitFormatted(formatted); _buffer.Append(tagClose); return(result); }
public virtual MarkdownNode VisitFormatted(FormattedNode formatted) { Visit(formatted.Children); return(formatted); }
private static int SetLayers(Dictionary <XNode.Node, FormattedNode> graphNodes, FormattedNode endNode) { int maxLayer = 0; var nodesStack = new Stack <XNode.Node>(endNode.ChildNodes.Select(c => c.Node)); while (nodesStack.Count > 0) { var node = nodesStack.Pop(); int layer = graphNodes[node].Layer; foreach (var input in node.Inputs) { if (input.Connection != null && graphNodes.TryGetValue(input.Connection.node, out var inputGraphNode)) { inputGraphNode.Layer = Math.Max(inputGraphNode.Layer, layer + 1); maxLayer = Math.Max(maxLayer, inputGraphNode.Layer); nodesStack.Push(input.Connection.node); } } } return(maxLayer); }
private void SetChildNodes(Dictionary <XNode.Node, FormattedNode> graphNodes, FormattedNode endNode) { var nodesStack = new Stack <FormattedNode>(); nodesStack.Push(endNode); var visitedChildNodes = new HashSet <FormattedNode>(); while (nodesStack.Count > 0) { var node = nodesStack.Pop(); if (node.ChildNodes == null) { node.ChildNodes = Sort(node.Node.Inputs) .SelectMany(input => input.GetConnections()) .Select(c => graphNodes.TryGetValue(c.node, out FormattedNode n) ? n : null) .Where(n => n != null && !visitedChildNodes.Contains(n)) .ToList(); } for (int i = node.ChildNodes.Count - 1; i >= 0; i--) { visitedChildNodes.Add(node.ChildNodes[i]); nodesStack.Push(node.ChildNodes[i]); } } }