Skip to content

Commit 8395ffe

Browse files
committed
Popper stuff for REX works mostly
1 parent ee36052 commit 8395ffe

File tree

4 files changed

+125
-36
lines changed

4 files changed

+125
-36
lines changed

src/algorithms/controllers/MSDRadixSort.js

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import MaskTracer from '../../components/DataStructures/Mask/MaskTracer'
33
import {
44
areExpanded,
55
} from './collapseChunkPlugin';
6+
import { createPopper } from '@popperjs/core';
67

78
// see stackFrameColour in Array1DRenderer/index.js to find corresponding function mapping to css
89
const STACK_FRAME_COLOR = {
@@ -239,10 +240,11 @@ export default {
239240
} else {
240241
if (prev_j !== undefined && prev_j !== cur_i)
241242
unhighlight(vis, prev_j);
242-
if (cur_j !== undefined) // might have fallen off array
243+
if (cur_j !== undefined) { // might have fallen off array
243244
highlight(vis, cur_j);
244-
if (arr && cur_j)
245+
// XXX probably best avoid updateBinary at swap
245246
updateBinary(vis, arr[cur_j])
247+
}
246248
}
247249
if (left < A.length)
248250
assignVariable(vis, VIS_VARIABLE_STRINGS.left, left);
@@ -348,12 +350,19 @@ depth, arr, mask)
348350
[arr[n1], arr[n2]] = [arr[n2], arr[n1]]
349351

350352
chunker.add(bookmark,
351-
(vis, _n1, _n2, cur_real_stack, cur_finished_stack_frames, cur_i, cur_j, cur_depth) => {
353+
(vis, _n1, _n2, cur_real_stack, cur_finished_stack_frames, cur_i, cur_j, cur_depth, A) => {
352354

353355
vis.array.swapElements(_n1, _n2);
354-
refreshStack(vis, cur_real_stack, cur_finished_stack_frames, cur_i, cur_j, prev_i, prev_j, left, right, cur_depth, false, undefined, arr, mask)
356+
refreshStack(vis, cur_real_stack, cur_finished_stack_frames, cur_i, cur_j, prev_i, prev_j, left, right, cur_depth, false, undefined, A, mask)
357+
// XXX redo poppers: swapping the elements keeps the
358+
// contents of the poppers correct but the position needs
359+
// to change (the documentation suggests update()
360+
// should work and it does partially but it also screws up
361+
// sometimes)
362+
// vis.array.poppers[_n1].update();
363+
// vis.array.poppers[_n2].update();
355364
},
356-
[n1, n2, real_stack, finished_stack_frames, i, j, depth],
365+
[n1, n2, real_stack, finished_stack_frames, i, j, depth, arr],
357366
depth);
358367
}
359368

@@ -463,6 +472,28 @@ depth, arr, mask)
463472
vis.mask.setMaxBits(mask + 1)
464473
updateMask(vis, mask)
465474
updateBinary(vis, A[maxIndex])
475+
let floatingBoxes = new Array(n); // List of all popper instances
476+
for (let idx = 0; idx < A.length; idx++) {
477+
const popper = document.getElementById('float_box_' + idx);
478+
const slot = document.getElementById('chain_' + idx);
479+
// vis.array.setPopper(idx, createPopper(slot, popper, {
480+
floatingBoxes[idx] = createPopper(slot, popper, {
481+
placement: "right-start",
482+
strategy: "fixed",
483+
modifiers: [
484+
{
485+
name: 'preventOverflow',
486+
options: {
487+
// popper_boundary not defined for 1D
488+
// array - maybe it should be??
489+
// boundary: document.getElementById('popper_boundary'),
490+
},
491+
},
492+
]
493+
});
494+
popper.innerHTML = A[idx].toString(2).padStart(mask + 1, "0");
495+
}
496+
vis.array.setPoppers(floatingBoxes);
466497
},
467498
[maxIndex, mask, A],
468499
0

src/components/DataStructures/Array/Array1DRenderer/index.js

Lines changed: 67 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ import Array2DRenderer from '../Array2DRenderer/index';
2626
import styles from './Array1DRenderer.module.scss';
2727
import { classes } from '../../common/util';
2828
import { mode } from '../../../top/Settings';
29+
// Add your algo to this if you want to use the float box/popper
30+
const ALGOS_USING_FLOAT_BOX = ["MSDRadixSort"];
2931

3032
let modename;
3133
function switchmode(modetype = mode()) {
@@ -110,35 +112,71 @@ class Array1DRenderer extends Array2DRenderer {
110112
justifyContent: 'center',
111113
}}
112114
>
113-
{row.map((col) => (
114-
<motion.div
115-
layout
116-
transition={{ duration: 0.6 }}
117-
style={{
118-
height: `${this.toString(scaleY(col.value))}vh`,
119-
display: 'flex',
120-
}}
121-
/* eslint-disable-next-line react/jsx-props-no-multi-spaces */
122-
className={classes(
123-
styles.col,
124-
col.faded && styles.faded,
125-
col.selected && styles.selected,
126-
col.patched && styles.patched,
127-
col.sorted && styles.sorted,
128-
col.style && col.style.backgroundStyle,
129-
)}
115+
{row.map((col, j) => (
116+
<td className={classes(styles.col, styles.index)}
130117
key={col.key}
131-
>
132-
<motion.span
133-
layout="position"
134-
className={classes(
135-
styles.value,
136-
col.style && col.style.textStyle,
137-
)}
138-
>
139-
{this.toString(col.value)}
140-
</motion.span>
141-
</motion.div>
118+
onMouseEnter={(e) => {
119+
let element = e.target.children[1];
120+
if (element && element.innerHTML !== "") {
121+
element.style.display = 'block'
122+
}
123+
}}
124+
onMouseLeave={(e) => {
125+
let element = e.target.children[1];
126+
if (element && element.innerHTML !== "") {
127+
element.style.display = 'none'
128+
}
129+
}}
130+
>
131+
<div
132+
id={'chain_' + parseInt(j)}
133+
>
134+
<motion.div
135+
layout
136+
transition={{ duration: 0.6 }}
137+
style={{
138+
height: `${this.toString(scaleY(col.value))}vh`,
139+
display: 'flex',
140+
}}
141+
/* eslint-disable-next-line react/jsx-props-no-multi-spaces */
142+
className={classes(
143+
styles.col,
144+
col.faded && styles.faded,
145+
col.selected && styles.selected,
146+
col.patched && styles.patched,
147+
col.sorted && styles.sorted,
148+
col.style && col.style.backgroundStyle,
149+
)}
150+
>
151+
<motion.span
152+
layout="position"
153+
className={classes(
154+
styles.value,
155+
col.style && col.style.textStyle,
156+
)}
157+
>
158+
{this.toString(col.value)}
159+
</motion.span>
160+
{ (ALGOS_USING_FLOAT_BOX.includes(algo) && (
161+
<div
162+
id={"float_box_" + parseInt(j)}
163+
role="tooltip"
164+
style={{
165+
background: '#333',
166+
color: "#FFFFFF",
167+
fontWeight: "bold",
168+
padding: "4px 8px",
169+
fontSize: "13px",
170+
borderRadius: "4px",
171+
display: "none",
172+
}}
173+
>
174+
</div>
175+
))
176+
}
177+
</motion.div>
178+
</div>
179+
</td>
142180
))}
143181
</div>
144182
))}
@@ -215,7 +253,7 @@ class Array1DRenderer extends Array2DRenderer {
215253
</div>
216254
</motion.div>
217255
</tbody>
218-
{ // XXX I've given up trying to avoid this warning:(
256+
{ // XXX I've given up trying to avoid this warning...
219257
// "Whitespace text nodes cannot appear as a child of <table>. Make
220258
// sure you don't have any extra whitespace between tags on each
221259
// line of your source code." Similariy div inside tbody.

src/components/DataStructures/Array/Array1DTracer.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class Array1DTracer extends Array2DTracer {
2020
init() {
2121
super.init();
2222
this.chartTracer = null;
23+
this.poppers = [];
2324
}
2425

2526
set(array1d = [], algo) {
@@ -141,6 +142,23 @@ class Array1DTracer extends Array2DTracer {
141142
this.stackDepth = depth;
142143
}
143144

145+
// XXX move to super
146+
// XXX should kill existing poppers
147+
setPoppers(poppers) {
148+
this.poppers = poppers;
149+
}
150+
151+
setPopper(i, popper) {
152+
this.poppers[i] = popper;
153+
}
154+
155+
// NQR and not currently used
156+
/*
157+
setPopperHTML(i, HTML) {
158+
this.poppers[i].innerHTML = HTML;
159+
}
160+
*/
161+
144162
// default is to compute largestColumnValue but we can set it
145163
// explicitly so we can make two arrays look the same when moving
146164
// elements between them and avoid re-scaling

src/components/DataStructures/Array/Array2DRenderer/index.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ import { classes } from '../../common/util';
2828
import { mode } from '../../../top/Settings';
2929
import PropTypes from 'prop-types';
3030

31-
const ALGOS_USING_FLOAT_BOX = ["HashingCH"]; // Add your algo to this if you want to use the float box
32-
const ALGOS_WITH_FIRST_COL_AS_HEADERS = ["HashingCH", "HashingLP", "HashingDH"]; // Add your algo to this if your algo has the first column as the headers
31+
// Add your algo to this if you want to use the float box/popper
32+
const ALGOS_USING_FLOAT_BOX = ["HashingCH"];
33+
// Add your algo to this if your algo has the first column as the headers
34+
const ALGOS_WITH_FIRST_COL_AS_HEADERS = ["HashingCH", "HashingLP", "HashingDH"];
3335

3436
let modename;
3537
export function switchmode(modetype = mode()) {

0 commit comments

Comments
 (0)