@@ -299,21 +299,6 @@ export default {
299
299
STACK_FRAME_COLOR . Current_stackFrameR ,
300
300
) ;
301
301
}
302
-
303
- if ( cur_depth === undefined ) {
304
- return stack_vis ;
305
- }
306
-
307
- if ( ! isPartitionExpanded ( ) ) { return stack_vis ; }
308
-
309
- // if (cur_i >= 0 && cur_i < n) {
310
- // stack_vis[cur_depth][cur_i].extra.push(STACK_FRAME_COLOR.I_color);
311
- // }
312
-
313
- // if (cur_j >= 0 && cur_j < n) {
314
- // stack_vis[cur_depth][cur_j].extra.push(STACK_FRAME_COLOR.J_color);
315
- // }
316
-
317
302
return stack_vis ;
318
303
}
319
304
@@ -333,13 +318,14 @@ export default {
333
318
let j ; // the recursive calls; XX best rename - "i" too generic
334
319
let prev_i ; // for unhighlighting
335
320
let prev_j ; // for unhighlighting
321
+ let floatingBoxes = new Array ( n ) ; // XXX popper instances (rename)
322
+
336
323
const partition = ( arr , left , right , mask , depth ) => {
337
324
i = left
338
325
j = right
339
326
340
327
const partitionChunkerWrapper = ( bookmark ) => {
341
- partitionChunker ( bookmark , i , j , prev_i , prev_j , left , right ,
342
- depth , arr , mask )
328
+ partitionChunker ( bookmark , i , j , prev_i , prev_j , left , right , depth , arr , mask )
343
329
}
344
330
345
331
function swapAction ( bookmark , n1 , n2 ) {
@@ -350,19 +336,28 @@ depth, arr, mask)
350
336
[ arr [ n1 ] , arr [ n2 ] ] = [ arr [ n2 ] , arr [ n1 ] ]
351
337
352
338
chunker . add ( bookmark ,
353
- ( vis , _n1 , _n2 , cur_real_stack , cur_finished_stack_frames , cur_i , cur_j , cur_depth , A ) => {
339
+ ( vis , _n1 , _n2 , cur_real_stack , cur_finished_stack_frames ,
340
+ cur_i , cur_j , cur_depth , A ) => {
354
341
355
342
vis . array . swapElements ( _n1 , _n2 ) ;
356
343
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
344
+ // redo poppers: swapping the elements keeps the
358
345
// contents of the poppers correct but the position needs
359
- // to change (the documentation suggests update()
346
+ // to change. The documentation suggests update()
360
347
// 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();
348
+ // the position sometimes, particularly for _n1; it
349
+ // returns a promise but we can't use await here. The
350
+ // contents also gets screwed up sometimes stepping
351
+ // backwards (stepping backwards again seems to help). The
352
+ // wonders of asynchronous programming...
353
+ // The solution we use here is to schedule a forceUpdate()
354
+ // after a bit of a delay - seems to work ok on some
355
+ // devices at least...
356
+ setTimeout ( ( ) => floatingBoxes [ _n1 ] . forceUpdate ( ) , 900 ) ;
357
+ setTimeout ( ( ) => floatingBoxes [ _n2 ] . forceUpdate ( ) , 900 ) ;
364
358
} ,
365
- [ n1 , n2 , real_stack , finished_stack_frames , i , j , depth , arr ] ,
359
+ [ n1 , n2 , real_stack , finished_stack_frames , i , j , depth ,
360
+ arr ] ,
366
361
depth ) ;
367
362
}
368
363
@@ -411,19 +406,6 @@ depth, arr, mask)
411
406
// Base case: If the array has 1 or fewer elements or mask is less than 0, stop
412
407
partitionChunker ( MSD_BOOKMARKS . rec_function , undefined , undefined , undefined , undefined , left , right , depth , arr , mask )
413
408
maxIndex = undefined ; // defined only for top level call
414
- /*
415
- chunker.add(MSD_BOOKMARKS.rec_function, (vis, left, right) => {
416
- if (left < n)
417
- assignVariable(vis, VIS_VARIABLE_STRINGS.left, left);
418
- if (right >= 0)
419
- assignVariable(vis, VIS_VARIABLE_STRINGS.right, right);
420
- updateMask(vis, mask)
421
-
422
- for (let i = 0; i < n; i++) {
423
- unhighlight(vis, i);
424
- }
425
- }, [left, right], depth)
426
- */
427
409
chunker . add ( MSD_BOOKMARKS . base_case , ( vis ) => { } , [ ] , depth )
428
410
429
411
if ( left < right && mask >= 0 ) {
@@ -451,12 +433,33 @@ depth, arr, mask)
451
433
finished_stack_frames . push ( real_stack . pop ( ) ) ;
452
434
}
453
435
436
+ // XXX probably should rename to something like poppers
437
+ // Handling is rather tricky. We have the global array of poppers
438
+ // which is initially all null. When the second chunk is executed,
439
+ // poppers are created and when later chunks are executed things
440
+ // can move around. When we step backwards, we go back and execute
441
+ // from the first chunk, so the first chunk cleans up and destroys
442
+ // all the existing poppers and later chunks re-create them. To
443
+ // make things more complicated, its all asynchronous, so we put
444
+ // delays in to (hopefully) stop it screwing up.
445
+ floatingBoxes . fill ( null ) ;
446
+
454
447
// Initialise the array on start
455
448
chunker . add ( MSD_BOOKMARKS . start ,
456
449
( vis , array ) => {
457
450
vis . array . set ( array , 'MSDRadixSort' )
458
451
vis . array . setSize ( 5 ) ; // more space for array
459
452
vis . array . setZoom ( 0.90 ) ;
453
+ // destroy existing poppers, replace with null
454
+ floatingBoxes . forEach ( ( p ) => {
455
+ if ( p !== null ) {
456
+ console . log ( 'popper gone' ) ;
457
+ p . state . elements . popper . innerHTML = "" ; // reset HTML
458
+ p . forceUpdate ( ) ;
459
+ p . destroy ( ) ; // remove popper
460
+ return null ; // array el. = null
461
+ }
462
+ } ) ;
460
463
} ,
461
464
[ nodes ] ,
462
465
0
@@ -472,43 +475,54 @@ depth, arr, mask)
472
475
vis . mask . setMaxBits ( mask + 1 )
473
476
updateMask ( vis , mask )
474
477
updateBinary ( vis , A [ maxIndex ] )
475
- let floatingBoxes = new Array ( n ) ; // List of all popper instances
476
- for ( let idx = 0 ; idx < A . length ; idx ++ ) {
478
+ // set up poppers
479
+ // A bit of a nightmare due to asynchronous programming. If
480
+ // we have stepped backwards the poppers have been reset and
481
+ // destroyed but if we immediately create new poppers some
482
+ // of the old state persists. If we wait a while then create
483
+ // them it seems to work on some devices at least...
484
+ // XXX do popper.innerHTML = immediately; use setTimeout for createPopper
485
+ // XXX have array for the popper.innerHTML stuff?,
486
+ setTimeout ( ( ) => {
487
+ for ( let idx = 0 ; idx < A . length ; idx ++ ) {
477
488
const popper = document . getElementById ( 'float_box_' + idx ) ;
478
489
const slot = document . getElementById ( 'chain_' + idx ) ;
479
- // vis.array.setPopper(idx, createPopper(slot, popper, {
480
- floatingBoxes [ idx ] = createPopper ( slot , popper , {
490
+ floatingBoxes [ idx ] = createPopper ( slot , popper , {
481
491
placement : "right-start" ,
482
492
strategy : "fixed" ,
483
493
modifiers : [
484
494
{
495
+ removeOnDestroy : true , // doesn't work well?
485
496
name : 'preventOverflow' ,
486
497
options : {
487
- // popper_boundary not defined for 1D
498
+ // XXX popper_boundary not defined for 1D
488
499
// array - maybe it should be??
489
- // boundary: document.getElementById('popper_boundary'),
500
+ boundary : document . getElementById ( 'popper_boundary' ) ,
490
501
} ,
491
502
} ,
492
503
]
493
504
} ) ;
494
505
popper . innerHTML = A [ idx ] . toString ( 2 ) . padStart ( mask + 1 , "0" ) ;
495
506
}
496
- vis . array . setPoppers ( floatingBoxes ) ;
507
+ } , 1000 ) ;
508
+ /*
509
+ console.log(floatingBoxes);
510
+ setTimeout( () => {
511
+ console.log(floatingBoxes);
512
+ floatingBoxes.forEach((p) => {
513
+ if (p !== null) {
514
+ p.setOptions({placement: "right-start"});
515
+ p.forceUpdate()
516
+ }
517
+ })
518
+ }, 2000);
519
+ */
497
520
} ,
498
521
[ maxIndex , mask , A ] ,
499
522
0
500
523
)
501
- /*
502
- chunker.add(MSD_BOOKMARKS.rec_function,
503
- (vis, maxIndex) => {
504
- unhighlight(vis, maxIndex)
505
- }, [maxIndex],
506
- 0
507
- )
508
- */
509
524
msdRadixSortRecursive ( A , 0 , n - 1 , mask , 0 ) ;
510
525
511
-
512
526
chunker . add ( MSD_BOOKMARKS . done ,
513
527
vis => {
514
528
vis . array . setStackDepth ( 0 )
0 commit comments