Skip to content
This repository was archived by the owner on Sep 9, 2025. It is now read-only.

Commit 338484c

Browse files
author
Hendrik van Antwerpen
committed
Add help menu
1 parent e89b103 commit 338484c

4 files changed

Lines changed: 199 additions & 40 deletions

File tree

‎stack-graphs/src/visualization.css‎

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@
230230

231231
#sg-tooltip {
232232
position: absolute;
233+
top: 0px;
234+
left: 0px;
233235
visibility: hidden;
234236
pointer-events: none;
235237
border: 0px;
@@ -322,3 +324,79 @@
322324
display: inline-block;
323325
margin: 0px 1px;
324326
}
327+
328+
/* ------------------------------------------------------------------------------------------------
329+
* Help
330+
*/
331+
332+
#sg-help-toggle {
333+
visibility: hidden;
334+
position: absolute;
335+
left: 10px;
336+
bottom: 10px;
337+
z-index: 3;
338+
}
339+
340+
.sg-help-label {
341+
position: absolute;
342+
left: 10px;
343+
bottom: 10px;
344+
background-color: #bbbbbb;
345+
padding: 0px;
346+
border-radius: 6px;
347+
z-index: 2;
348+
width: 30px;
349+
height: 30px;
350+
line-height: 30px;
351+
text-align: center;
352+
margin: 0px;
353+
font-size: 18px;
354+
}
355+
356+
.sg-help-content {
357+
visibility: hidden;
358+
position: absolute;
359+
left: 10px;
360+
bottom: 10px;
361+
background-color: #bbbbbb;
362+
padding: 6px;
363+
border-radius: 6px;
364+
z-index: 1;
365+
min-height: 18px;
366+
min-width: 18px;
367+
max-width: 300px;
368+
margin: 0px;
369+
}
370+
371+
#sg-help-toggle:checked ~ .sg-help-content {
372+
visibility: visible;
373+
}
374+
375+
.sg-help-content h1 {
376+
font-size: inherit;
377+
}
378+
379+
.sg-help-content kbd {
380+
font-family: monospace;
381+
display: inline-block;
382+
border-radius: 3px;
383+
padding: 0px 4px;
384+
box-shadow: 1px 1px 1px #777;
385+
margin: 2px;
386+
font-size: small;
387+
vertical-align: text-bottom;
388+
background: #eee;
389+
font-variant: small-caps;
390+
}
391+
392+
.sg-help-meta {
393+
font-style: italic;
394+
}
395+
396+
.sg-help-byline {
397+
line-height: 20px;
398+
font-style: italic;
399+
width: 100%;
400+
margin-left: 24px;
401+
text-align: left;
402+
}

‎stack-graphs/src/visualization.html‎

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,9 @@
11
<!DOCTYPE html>
2-
<html lang="en">
2+
<html lang="en" class=""sg-container">
33

44
<head>
55
<meta charset="utf-8">
66
<title>Stack Graph Visualization</title>
7-
<style>
8-
html,
9-
body,
10-
#container {
11-
width: 100%;
12-
height: 100%;
13-
margin: 0;
14-
}
15-
</style>
167
<link href="visualization.css" type="text/css" rel="stylesheet"></link>
178
<script src="https://d3js.org/d3.v7.js"></script>
189
<script src="https://unpkg.com/d3-dag@0.10.0"></script>
@@ -1021,14 +1012,29 @@
10211012
]
10221013
;
10231014
</script>
1015+
<style>
1016+
html, body, #container {
1017+
width: 100%;
1018+
height: 100%;
1019+
margin: 0;
1020+
overflow: hidden;
1021+
}
1022+
</style>
10241023
</head>
10251024

10261025
<body>
1026+
<div id="controls">
1027+
<input type="checkbox" id="show_all_node_labels" />
1028+
<label for="show_all_node_labels">show all node labels</label>
1029+
</div>
10271030
<div id="container">
10281031
</div>
10291032
<script type="text/javascript">
10301033
let container = d3.select("\#container");
1031-
new StackGraph(container, graph, paths);
1034+
const sg = new StackGraph(container, graph, paths, { version: "tree-sitter-stack-graph dev" });
1035+
document.getElementById("show_all_node_labels").addEventListener("click", function (ev) {{
1036+
sg.set_show_all_node_labels(ev.target.checked)
1037+
}});
10321038
</script>
10331039
</body>
10341040

‎stack-graphs/src/visualization.js‎

Lines changed: 70 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,9 @@ class StackGraph {
1313
static distx = 15;
1414
static disty = 15;
1515

16-
constructor(container, graph, paths) {
16+
constructor(container, graph, paths, metadata) {
17+
this.metadata = metadata;
18+
1719
this.graph = graph;
1820
this.paths = paths;
1921
this.compute_data();
@@ -116,8 +118,8 @@ class StackGraph {
116118
}
117119

118120
set_show_all_node_labels(yn) {
119-
this.show_all_node_labels = yn;
120-
this.render();
121+
this.show_all_node_labels = yn;
122+
this.render();
121123
}
122124

123125
render() {
@@ -215,6 +217,9 @@ class StackGraph {
215217
.attr('id', 'sg-tooltip')
216218
.classed(this.tooltip_orient_class(), true);
217219

220+
// help
221+
this.render_help();
222+
218223
// mouse events
219224
nodes
220225
.on("mouseover", (e, d) => {
@@ -260,6 +265,7 @@ class StackGraph {
260265
d3.select(window).on("keyup", (e) => {
261266
this.paths_keypress(e);
262267
this.tooltip_keypress(e);
268+
this.help_keypress(e);
263269
})
264270
}
265271

@@ -309,16 +315,15 @@ class StackGraph {
309315
break;
310316
case "scope":
311317
if (this.show_all_node_labels) {
312-
console.log(node);
313318
let v = '';
314319
let l = '';
315320
for (let i = 0; i < node.debug_info.length; i++) {
316-
let info = node.debug_info[i];
317-
if (info.key == "tsg_variable") {
318-
v = info.value;
319-
} else if (info.key == "tsg_location") {
320-
l = info.value
321-
}
321+
let info = node.debug_info[i];
322+
if (info.key == "tsg_variable") {
323+
v = info.value;
324+
} else if (info.key == "tsg_location") {
325+
l = info.value
326+
}
322327
}
323328
this.render_symbol_node(g, v + " " + l);
324329
g.classed('plain_labeled_node', true);
@@ -509,7 +514,7 @@ class StackGraph {
509514

510515
tooltip_keypress(e) {
511516
const old_class = this.tooltip_orient_class();
512-
switch(e.keyCode) {
517+
switch (e.keyCode) {
513518
case 87: // w
514519
this.current_orient.y = "north";
515520
break;
@@ -684,7 +689,7 @@ class StackGraph {
684689
tooltip.add_row("end node", `${this.node_id_to_str(path.end_node)}`);
685690

686691
const node_id = (this.current_node && this.node_to_id_str(this.current_node))
687-
|| (this.current_edge && this.node_id_to_str(this.current_edge.source) );
692+
|| (this.current_edge && this.node_id_to_str(this.current_edge.source));
688693
const node_data = path.derived.nodes[node_id];
689694
tooltip.add_row("symbol stack", this.symbol_stack_to_array(node_data.symbol_stack));
690695
tooltip.add_row("scope stack", this.scope_stack_to_array(node_data.scope_stack));
@@ -696,6 +701,59 @@ class StackGraph {
696701
|| (this.current_edge !== null && path.derived.edges.hasOwnProperty(this.edge_to_id_str(this.current_edge)));
697702
}
698703

704+
// ------------------------------------------------------------------------------------------------
705+
// Help
706+
//
707+
708+
render_help() {
709+
const help = d3.select('body').append('div');
710+
help.append('label')
711+
.attr('for', 'sg-help-toggle')
712+
.attr('class', 'sg-help-label')
713+
.text("ⓘ");
714+
this.help_toggle = help.append('input')
715+
.attr('id', 'sg-help-toggle')
716+
.attr('type', 'checkbox');
717+
const help_content = help.append('div')
718+
.attr('class', 'sg-help-content');
719+
720+
help_content.append("h1").text("Pan & Zoom");
721+
help_content.append("p").html(`
722+
Pan by dragging the background with the mouse.
723+
Zoom using the scroll wheel.
724+
`);
725+
726+
help_content.append("h1").text("Tooltip");
727+
help_content.append("p").html(`
728+
Hover over nodes and edges to get a tooltip with detailed information.
729+
Change the tooltip orientation using the keys <kbd>w</kbd> for above, <kbd>a</kbd> for left of, <kbd>s</kbd> for below, or <kbd>d</kbd> for right of the pointer.
730+
`);
731+
732+
help_content.append("h1").text("Path Selection");
733+
help_content.append("p").html(`
734+
Cycle through individual paths by clicking on a node with outgoing paths.
735+
While a path is selected, clicks to other nodes than the source node have no effect.
736+
Cycle through selected paths using the key <kbd>n</kbd>.
737+
Path selection ends after cycling through all paths by clicking the node, or by pressing the <kbd>esc</kbd> key.
738+
`);
739+
740+
help_content.append("p").attr("class", "sg-help-meta").html(`
741+
Toggle visibility of this help anytime by pressing <kbd>h</kbd>.
742+
`);
743+
744+
const byline = help_content.append('div')
745+
.attr("class", "sg-help-byline");
746+
if (this.metadata?.version) {
747+
byline.text(this.metadata.version);
748+
}
749+
}
750+
751+
help_keypress(e) {
752+
if (e.keyCode === 72) {
753+
this.help_toggle.property("checked", !this.help_toggle.property("checked"));
754+
}
755+
}
756+
699757
// ------------------------------------------------------------------------------------------------
700758
// Node & Edge IDs
701759
//

‎stack-graphs/src/visualization.rs‎

Lines changed: 34 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ static D3: &'static str = include_str!("d3.v7.min.js");
1616
static D3_DAG: &'static str = include_str!("d3-dag.v0.10.0.min.js");
1717
static JS: &'static str = include_str!("visualization.js");
1818

19+
static PKG: &'static str = env!("CARGO_PKG_NAME");
20+
static VERSION: &'static str = env!("CARGO_PKG_VERSION");
21+
1922
//-----------------------------------------------------------------------------
2023
// StackGraph
2124

@@ -29,33 +32,48 @@ impl StackGraph {
2932
r#"
3033
<!DOCTYPE html>
3134
<html lang="en">
35+
3236
<head>
37+
3338
<meta charset="utf-8">
34-
<title>{}</title>
39+
<title>{title}</title>
40+
41+
<!-- <link href="visualization.css" type="text/css" rel="stylesheet"></link> -->
3542
<style>
36-
{}
37-
</style>
38-
<style>
39-
html, body, #container {{
40-
width: 100%;
41-
height: 100%;
42-
margin: 0;
43-
}}
43+
{CSS}
4444
</style>
45+
46+
<!-- <script type="text/javascript" src="d3.v7.min.js"></script> -->
4547
<script type="text/javascript">
46-
{}
48+
{D3}
4749
</script>
50+
51+
<!-- <script type="text/javascript" src="d3-dag.v0.10.0.min.js"></script> -->
4852
<script type="text/javascript">
49-
{}
53+
{D3_DAG}
5054
</script>
55+
56+
<!-- <script type="text/javascript" src="visualization.js"></script> -->
5157
<script charset="utf-8">
52-
{}
58+
{JS}
5359
</script>
60+
5461
<script type="text/javascript">
55-
let graph = {};
56-
let paths = {};
62+
let graph = {graph};
63+
let paths = {paths};
5764
</script>
65+
66+
<style>
67+
html, body, #container {{
68+
width: 100%;
69+
height: 100%;
70+
margin: 0;
71+
overflow: hidden;
72+
}}
73+
</style>
74+
5875
</head>
76+
5977
<body>
6078
<div id="controls">
6179
<input type="checkbox" id="show_all_node_labels" />
@@ -65,15 +83,14 @@ impl StackGraph {
6583
</div>
6684
<script type="text/javascript">
6785
let container = d3.select("\#container");
68-
let sg = new StackGraph(container, graph, paths);
86+
let sg = new StackGraph(container, graph, paths, {{ version: "{PKG} {VERSION}" }});
6987
document.getElementById("show_all_node_labels").addEventListener("click", function (ev) {{
7088
sg.set_show_all_node_labels(ev.target.checked)
7189
}});
7290
</script>
7391
</body>
7492
</html>
75-
"#,
76-
title, CSS, D3, D3_DAG, JS, graph, paths
93+
"#
7794
);
7895
Ok(html)
7996
}

0 commit comments

Comments
 (0)