aboutsummaryrefslogtreecommitdiffstats
path: root/src/layout.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/layout.js')
-rw-r--r--src/layout.js116
1 files changed, 116 insertions, 0 deletions
diff --git a/src/layout.js b/src/layout.js
new file mode 100644
index 0000000..4762f4a
--- /dev/null
+++ b/src/layout.js
@@ -0,0 +1,116 @@
+import Viz from './viz.es';
+
+const graphviz = new Viz({ workerURL: 'lib/lite.render.js' });
+
+export const init = () => {
+ return 'digraph { node [shape="rectangle"];\n';
+}
+
+export const addNode = (dot, node) => {
+ const id = node.data.id;
+ dot += ` "${id}" [fixedsize=true; width=${node.width / 72}; height=${node.height / 72}];\n`;
+
+ for (const replyId of node.data.replies || [])
+ dot += ` "${id}" -> "${replyId}";\n`;
+
+ return dot;
+};
+
+const toNumber = (i) => Number(i);
+
+export const render = async (dot, canvas, setPosition, setSize) => {
+ dot += '}';
+
+ console.log(dot);
+
+ const info = await graphviz.renderJSONObject(dot, { format: 'json0' });
+ window.info = info;
+
+ const [_x, _y, width, height] = info.bb.split(',').map(toNumber);
+
+ setSize(width, height);
+
+ for (const object of info.objects) {
+ const [x, y] = object.pos.split(',').map(toNumber);
+ setPosition(object.name, x, height - y);
+ }
+
+ const ctx = canvas.getContext('2d');
+ ctx.lineWidth = 4;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+ ctx.strokeStyle = '#696969';
+
+ for (const edge of info.edges) {
+ const pos = edge.pos.slice(2);
+ const points = pos.split(' ').map(p => {
+ const [x, y] = p.split(',');
+ return [toNumber(x), height - toNumber(y)];
+ });
+
+ ctx.beginPath();
+ ctx.moveTo(...points[1]);
+ for (let i = 4; i < points.length; i += 3) {
+ const [ax, ay] = points[i - 2];
+ const [bx, by] = points[i - 1];
+ const [x, y] = points[i];
+ ctx.bezierCurveTo(ax, ay, bx, by, x, y);
+ }
+ ctx.lineTo(...points[0]);
+ ctx.stroke();
+ }
+}
+
+/*
+import * as dagre from 'dagre';
+
+export const init = () => {
+ const graph = new dagre.graphlib.Graph();
+
+ graph.setGraph({
+ rankSep: 20,
+ nodeSep: 40,
+ });
+ graph.setDefaultEdgeLabel(() => ({}));
+
+ return graph;
+};
+
+export const addNode = (graph, node) => {
+ graph.setNode(node.data.id, node);
+
+ for (const reply of node.data.replies || []) {
+ graph.setEdge(node.data.id, reply);
+ }
+
+ return graph;
+};
+
+export const render = (graph, canvas, setPosition, setSize) => {
+ dagre.layout(graph);
+ const info = graph.graph();
+
+ setSize(info.width, info.height);
+
+ for (const id of graph.nodes()) {
+ const node = graph.node(id);
+ setPosition(node, node.x, node.y);
+ }
+
+ const ctx = canvas.getContext('2d');
+ ctx.lineWidth = 4;
+ ctx.lineCap = 'round';
+ ctx.lineJoin = 'round';
+ ctx.strokeStyle = '#696969';
+
+ for (const eo of graph.edges()) {
+ const edge = graph.edge(eo);
+
+ ctx.beginPath();
+ ctx.moveTo(edge.points[0].x, edge.points[0].y);
+ for (const p of edge.points.slice(1))
+ ctx.lineTo(p.x, p.y);
+ ctx.stroke();
+ }
+};
+*/