Skip to content

Commit 0d8f841

Browse files
committed
feat(wip): add rough cut at result text to vis
The trouble is that most results are going to be both variable-width and likely to require multiple context-dependent visualizations. The main benefit of seeing the upcoming results, i.e. before they have a chance to be computed, and therefore before we can know their width(s), is to help the person "wayfind" in program-space, and so they get a sense for what's coming up next. We might: 1. Move the computed results to a different part of the view, so the stream of operations is its own linear context, 2. Add an "on-deck" or "minimap" kind of view to help localize without necessarily needing to draw every upcoming operation, 3. Re-flow the layout after we've computed a particular result (in addition being hard with SVGs, that also has the side effect of making the view very "jumpy"), 4. Define a maximum size (good) and always size our view to that (bad)
1 parent 3bd8a4b commit 0d8f841

File tree

1 file changed

+40
-15
lines changed

1 file changed

+40
-15
lines changed

pages/index.astro

+40-15
Original file line numberDiff line numberDiff line change
@@ -1363,11 +1363,11 @@ const vis = {
13631363
label: '%2',
13641364
kind: 'alu',
13651365
values: function* () {
1366-
let base = 0x1000000000000;
1366+
let addr = 0x1000000000000;
13671367
while (true) {
1368-
const last = base;
1369-
base += 4;
1370-
yield `0x${last.toString(16)}`;
1368+
const r = `0x${addr.toString(16)}`;
1369+
addr += 4;
1370+
yield r;
13711371
}
13721372
},
13731373
},
@@ -1387,11 +1387,13 @@ const vis = {
13871387
label: '%4',
13881388
kind: 'alu',
13891389
values: function* () {
1390-
let base = 0x2000000000000;
1390+
const base = 0x2000000000000;
1391+
let offset = 0;
13911392
while (true) {
1392-
const last = base;
1393-
base += 4;
1394-
yield `0x${last.toString(16)}`;
1393+
const last = offset;
1394+
offset += 4;
1395+
// yield `0x${last.toString(16)}`;
1396+
yield `0x20..${last.toString(16).padStart(2, '0')}`;
13951397
}
13961398
},
13971399
},
@@ -1479,7 +1481,10 @@ const vis = {
14791481
reject('el not found');
14801482
});
14811483

1482-
// TODO: we should hoist state into the DOM and update it instead of react-style re-rendering, but...
1484+
// TODO: we should hoist state into the DOM and update it instead of react-style re-rendering
1485+
// but:
1486+
// 1. where do we put `gen` (the current state for the value generator)? That's assuming it's even worth keeping
1487+
// 2. for wip purposes, it's convenient to have a thing that knows how to render any state, and oh look I accidentally a react.
14831488
function updateModule() {
14841489
if (state.cur >= ops.length) return;
14851490
if (!state.gen) state.gen = ops[state.cur]!.values();
@@ -1491,11 +1496,18 @@ const vis = {
14911496
// TODO we really want something like this for a `<text>`, don't we?
14921497
// or maybe for every result to be its own `g` so we can add a child?
14931498
// el.insertAdjacentElement()
1494-
1495-
// TODO oh of course (?) this blows up with:
1496-
// Uncaught HierarchyRequestError: Failed to execute 'appendChild' on 'Node': Nodes of type 'title' may not be inserted inside nodes of type 'rect'.
14971499
const titleEl = el.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'title'));
14981500
titleEl.textContent = state.gen.next().value || 'uh oh'; // TODO
1501+
1502+
// seems like there's a few problems to solve:
1503+
// 1. how wide does this result need to be now (we lose fixed width)
1504+
// -> do we need to "re-flow" everything to the right?
1505+
// -> should we be using SVG for this at all, then, if we're gonna be doing that?
1506+
// 2. where do we put the <text> ? we can center it on the result's center,
1507+
// as long as we know we'll fit (see above)
1508+
// 3. how do we make the label accessible, without needing to supply an ID for every
1509+
// sub-result (or do we just generate one based on the indexes?)
1510+
// cf. https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html
14991511
}
15001512
}
15011513

@@ -1539,6 +1551,7 @@ const vis = {
15391551
const gEl = opSvg.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'g'));
15401552
gEl.classList.add('results');
15411553

1554+
const gen = op.values();
15421555
// <rect width="20" height="20" x="20" y="80 + ..." class="result dispatched completed"></rect>
15431556
for (var i = 0; i < parseInt(svgEl.dataset.lanes || ''); i++) {
15441557
const resEl = gEl.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'rect'));
@@ -1547,9 +1560,21 @@ const vis = {
15471560
resEl.setAttribute('width', '20');
15481561
resEl.setAttribute('height', '20');
15491562
resEl.classList.add('result');
1550-
if (idx < state.cur || (idx == state.cur && state.last[i] == 'completed'))
1551-
resEl.classList.add('completed');
15521563
if (idx <= state.cur) resEl.classList.add('dispatched');
1564+
if (idx < state.cur || (idx == state.cur && state.last[i] == 'completed')) {
1565+
resEl.classList.add('completed');
1566+
const titleEl = resEl.appendChild(
1567+
document.createElementNS('http://www.w3.org/2000/svg', 'title')
1568+
);
1569+
titleEl.textContent = gen.next().value || 'oh no, generator ran out of values';
1570+
const textEl = gEl.appendChild(document.createElementNS('http://www.w3.org/2000/svg', 'text'));
1571+
1572+
textEl.setAttribute('x', '30');
1573+
textEl.setAttribute('y', `${80 + 30 * i + 10}px`);
1574+
textEl.setAttribute('dominant-baseline', 'middle');
1575+
textEl.setAttribute('text-anchor', 'middle');
1576+
textEl.textContent = titleEl.textContent;
1577+
}
15531578
}
15541579

15551580
return opSvg;
@@ -1575,7 +1600,7 @@ const vis = {
15751600

15761601
transform-box: fill-box;
15771602
transform-origin: center;
1578-
transform: rotate(45deg);
1603+
/* transform: rotate(45deg); */
15791604
}
15801605

15811606
circle {

0 commit comments

Comments
 (0)