@@ -523,39 +523,49 @@ export class LineCursor extends Marker {
523523 return curNode ;
524524 }
525525 const newNode = new ASTNode ( ASTNode . types . BLOCK , selected ) ;
526- super . setCurNode ( newNode ) ;
527- this . updateFocusIndication ( curNode , newNode ) ;
526+ this . setCurNode ( newNode ) ;
528527 return newNode ;
529528 }
530529
531530 /**
532531 * Set the location of the cursor and draw it.
533532 *
534- * Overrides drawing logic to call `setSelected` if the location is
535- * a block, or `addSelect` if it's a shadow block (since shadow
536- * blocks can't be selected).
537- *
538- * TODO(#142): The selection and fake-selection code was originally
539- * a hack added for testing on October 28 2024, because the default
540- * drawer behaviour was to draw a box around the block and all
541- * attached child blocks, which was confusing when navigating
542- * stacks.
543- *
544- * Since then we have decided that we probably _do_ in most cases
545- * want navigating to a block to select the block, but more
546- * particularly that we want navigation to move _focus_. Replace
547- * this selection hack with non-hacky changing of focus once that's
548- * possible.
533+ * Overrides normal Marker setCurNode logic to call
534+ * this.drawMarker() instead of this.drawer.draw() directly.
549535 *
550536 * @param newNode The new location of the cursor.
551537 */
552538 override setCurNode ( newNode : ASTNode ) {
553- const oldNode = this . getCurNode ( ) ;
539+ const oldNode = super . getCurNode ( ) ;
540+ // Kludge: we can't set this.curNode directly, so we have to call
541+ // super.setCurNode(...) to do it for us - but that would call
542+ // this.drawer.draw(...), so prevent that by temporarily setting
543+ // this.drawer to null (which we also can't do directly!)
544+ const drawer = this . getDrawer ( ) ;
545+ this . setDrawer ( null as any ) ; // Cast required since param is not nullable.
554546 super . setCurNode ( newNode ) ;
547+ this . setDrawer ( drawer ) ;
548+ // Draw this marker the way we want to.
549+ this . drawMarker ( oldNode , newNode ) ;
550+ // Try to scroll cursor into view.
555551 if ( newNode ?. getType ( ) === ASTNode . types . BLOCK ) {
556552 this . scrollBlockIntoView ( newNode . getLocation ( ) as Blockly . BlockSvg ) ;
557553 }
558- this . updateFocusIndication ( oldNode , newNode ) ;
554+ }
555+
556+ /**
557+ * Redraw the current marker.
558+ *
559+ * Overrides normal Marker drawing logic to use this.drawMarker()
560+ * instead of this.drawer.draw() directly.
561+ *
562+ * This hooks the method used by the renderer to draw the marker,
563+ * preventing the marker drawer from showing a marker if we don't
564+ * want it to.
565+ */
566+ override draw ( ) {
567+ const curNode = super . getCurNode ( ) ;
568+ this . drawMarker ( curNode , curNode ) ;
559569 }
560570
561571 /**
@@ -610,20 +620,30 @@ export class LineCursor extends Marker {
610620 }
611621
612622 /**
613- * Implements fake selection of shadow blocks as described in
614- * documentation for setCurNode.
623+ * Draw this cursor's marker.
624+ *
625+ * This is a wrapper around this.drawer.draw (usually implemented by
626+ * MarkerSvg.prototype.draw) that will, if newNode is a BLOCK node,
627+ * instead call `setSelected` to select it (if it's a regular block)
628+ * or `addSelect` (if it's a shadow block, since shadow blocks can't
629+ * be selected) instead of using the normal drawer logic.
630+ *
631+ * TODO(#142): The selection and fake-selection code was originally
632+ * a hack added for testing on October 28 2024, because the default
633+ * drawer (MarkerSvg) behaviour in Zelos was to draw a box around
634+ * the block and all attached child blocks, which was confusing when
635+ * navigating stacks.
636+ *
637+ * Since then we have decided that we probably _do_ in most cases
638+ * want navigating to a block to select the block, but more
639+ * particularly that we want navigation to move _focus_. Replace
640+ * this selection hack with non-hacky changing of focus once that's
641+ * possible.
615642 *
616643 * @param oldNode The previous node.
617- * @param newNode The newly-selected node.
644+ * @param curNode The current node.
618645 */
619- private updateFocusIndication ( oldNode : ASTNode , newNode : ASTNode ) {
620- const drawer = this . getDrawer ( ) ;
621-
622- if ( ! drawer ) {
623- console . error ( 'could not find a drawer' ) ;
624- return ;
625- }
626-
646+ private drawMarker ( oldNode : ASTNode , curNode : ASTNode ) {
627647 // If old node was a block, unselect it or remove fake selection.
628648 if ( oldNode ?. getType ( ) === ASTNode . types . BLOCK ) {
629649 const block = oldNode . getLocation ( ) as Blockly . BlockSvg ;
@@ -634,19 +654,25 @@ export class LineCursor extends Marker {
634654 }
635655 }
636656
637- // If new node is a block, select it or make it look selected.
638- if ( newNode ?. getType ( ) === ASTNode . types . BLOCK ) {
639- drawer . hide ( ) ;
640- const block = newNode . getLocation ( ) as Blockly . BlockSvg ;
641- if ( ! block . isShadow ( ) ) {
642- Blockly . common . setSelected ( block ) ;
643- } else {
644- block . addSelect ( ) ;
645- }
657+ // If curNode node is not block, just use the drawer.
658+ if ( curNode ?. getType ( ) !== ASTNode . types . BLOCK ) {
659+ this . getDrawer ( ) ?. draw ( oldNode , curNode ) ;
646660 return ;
647661 }
648662
649- drawer . draw ( oldNode , newNode ) ;
663+ // curNode is a block. Hide any visible marker SVG and instead
664+ // select the block or make it look selected.
665+ super . hide ( ) ; // Calls this.drawer?.hide().
666+ const block = curNode . getLocation ( ) as Blockly . BlockSvg ;
667+ if ( ! block . isShadow ( ) ) {
668+ Blockly . common . setSelected ( block ) ;
669+ } else {
670+ block . addSelect ( ) ;
671+ }
672+
673+ // Call MarkerSvg.prototype.fireMarkerEvent like
674+ // MarkerSvg.prototype.draw would (even though it's private).
675+ ( this . getDrawer ( ) as any ) ?. fireMarkerEvent ?.( oldNode , curNode ) ;
650676 }
651677
652678 /**
0 commit comments