diff options
author | Adam Spiers <git@adamspiers.org> | 2015-01-11 13:08:35 +0000 |
---|---|---|
committer | Adam Spiers <git@adamspiers.org> | 2015-01-11 13:25:46 +0000 |
commit | 9ac7713b5037710f2b1db82a63343e2f20ae775c (patch) | |
tree | d48473735eab3fd2b60ff8adee094bff2a5fb57a /html/js/git-deps-layout.coffee | |
parent | 1caef36fdeae554d5cc8bef3ca2734755bd70f08 (diff) | |
download | git-deps-9ac7713b5037710f2b1db82a63343e2f20ae775c.tar.gz |
switch to CoffeeScript!
Diffstat (limited to 'html/js/git-deps-layout.coffee')
-rw-r--r-- | html/js/git-deps-layout.coffee | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/html/js/git-deps-layout.coffee b/html/js/git-deps-layout.coffee new file mode 100644 index 0000000..8e88dde --- /dev/null +++ b/html/js/git-deps-layout.coffee @@ -0,0 +1,116 @@ +$ = require "jquery" +dagre = require "dagre" + +gdd = require "./git-deps-data.coffee" + +# The list of constraints to feed into WebCola. +constraints = [] + +# Group nodes by row, as assigned by the y coordinates returned from +# dagre's layout(). This will map a y coordinate onto all nodes +# within that row. +row_groups = {} + +# Expose a container for externally accessible objects. We can't +# directly expose the objects themselves because the references +# change each time they're constructed. However we don't need this +# trick for the constraints arrays since we can easily empty that by +# setting length to 0. +externs = {} + +dagre_layout = -> + g = new dagre.graphlib.Graph() + externs.graph = g + + # Set an object for the graph label + g.setGraph {} + + # Default to assigning a new object as a label for each new edge. + g.setDefaultEdgeLabel -> {} + + $.each gdd.nodes, (i, node) -> + g.setNode node.sha1, + label: node.name + width: node.rect_width or 70 + height: node.rect_height or 30 + + $.each gdd.deps, (parent_sha1, children) -> + $.each children, (child_sha1, bool) -> + g.setEdge parent_sha1, child_sha1 + + dagre.layout g + return g + +dagre_row_groups = -> + g = dagre_layout() + row_groups = {} + externs.row_groups = row_groups + g.nodes().forEach (sha1) -> + x = g.node(sha1).x + y = g.node(sha1).y + row_groups[y] = [] unless y of row_groups + row_groups[y].push + sha1: sha1 + x: x + return row_groups + +build_constraints = -> + row_groups = dagre_row_groups() + + constraints.length = 0 # FIXME: only rebuild constraints which changed + + # We want alignment constraints between all nodes which dagre + # assigned the same y value. + for y of row_groups + row_nodes = row_groups[y] + + # No point having an alignment group with only one node in. + if row_nodes.length > 1 + constraints.push build_alignment_constraint(row_nodes) + + # We also need separation constraints ensuring that the + # top-to-bottom ordering assigned by dagre is preserved. Since + # all nodes within a single row are already constrained to the + # same y coordinate from above, it should be enough to only + # have separation between a single node in adjacent rows. + row_y_coords = Object.keys(row_groups).sort() + + i = 0 + while i < row_y_coords.length - 1 + upper_y = row_y_coords[i] + lower_y = row_y_coords[i + 1] + upper_node = row_groups[upper_y][0] + lower_node = row_groups[lower_y][0] + constraints.push + gap: 30 + axis: "y" + left: gdd.node_index[upper_node.sha1] + right: gdd.node_index[lower_node.sha1] + + i++ + +build_alignment_constraint = (row_nodes) -> + constraint = + axis: "y" + type: "alignment" + offsets: [] + + for i of row_nodes + node = row_nodes[i] + constraint.offsets.push + node: gdd.node_index[node.sha1] + offset: 0 + + return constraint + +node = (sha1) -> + externs.graph.node sha1 + +module.exports = + # Variables + constraints: constraints + g: externs + + # Functions + build_constraints: build_constraints + node: node |