@@ -673,6 +673,189 @@ class Activity {
673673 }
674674 } ;
675675
676+ /**
677+ * Ensures blocks stay within canvas boundaries when resized.
678+ * Ensures that music blocks are responsive to horizontal resizing.
679+ * Ensures that overall integrity of blocks isn't hampered with.
680+ */
681+ function repositionBlocks ( activity ) {
682+
683+ const canvasWidth = window . innerWidth ;
684+ const processedBlocks = new Set ( ) ;
685+
686+ //Array for storing individual dragGroups (the chunks of code linked together which are not connected)
687+ const dragGroups = [ ] ;
688+
689+ // Identifying individual dragGroups
690+ Object . values ( activity . blocks . blockList ) . forEach ( block => {
691+ if ( ! processedBlocks . has ( block . id ) ) {
692+
693+ activity . blocks . findDragGroup ( block . id ) ;
694+
695+ if ( activity . blocks . dragGroup . length > 0 ) {
696+ dragGroups . push ( [ ...activity . blocks . dragGroup ] ) ; // Store the group into dragGroups
697+ activity . blocks . dragGroup . forEach ( id => processedBlocks . add ( id ) ) ; // Process individual groups
698+ }
699+ }
700+ } ) ;
701+
702+ // Repositioning of dragGroups according to horizontal resizing
703+ dragGroups . forEach ( group => {
704+ let referenceBlock = activity . blocks . blockList [ group [ 0 ] ] ;
705+
706+ // Store initial positions
707+ if ( ! referenceBlock . initialPosition ) {
708+ referenceBlock . initialPosition = { x : referenceBlock . container . x , y : referenceBlock . container . y } ;
709+ }
710+
711+ if ( canvasWidth < 768 && ! referenceBlock . beforeMobilePosition ) {
712+ referenceBlock . beforeMobilePosition = { x : referenceBlock . container . x , y : referenceBlock . container . y } ;
713+ }
714+
715+ if ( canvasWidth >= 768 && referenceBlock . beforeMobilePosition ) {
716+ let dx = referenceBlock . beforeMobilePosition . x - referenceBlock . container . x ;
717+ let dy = referenceBlock . beforeMobilePosition . y - referenceBlock . container . y ;
718+ group . forEach ( blockId => {
719+ let block = activity . blocks . blockList [ blockId ] ;
720+ block . container . x += dx ;
721+ block . container . y += dy ;
722+ } ) ;
723+ referenceBlock . beforeMobilePosition = null ; // Clear stored position
724+ //this prevents old groups from affecting new calculations.
725+ }
726+
727+ if ( canvasWidth < 600 && ! referenceBlock . before600pxPosition ) {
728+ referenceBlock . before600pxPosition = { x : referenceBlock . container . x , y : referenceBlock . container . y } ;
729+ }
730+
731+ if ( canvasWidth >= 600 && referenceBlock . before600pxPosition ) {
732+ let dx = referenceBlock . before600pxPosition . x - referenceBlock . container . x ;
733+ let dy = referenceBlock . before600pxPosition . y - referenceBlock . container . y ;
734+
735+ group . forEach ( blockId => {
736+ let block = activity . blocks . blockList [ blockId ] ;
737+ block . container . x += dx ;
738+ block . container . y += dy ;
739+ } ) ;
740+ referenceBlock . before600pxPosition = null ;
741+ }
742+
743+ // Ensure blocks stay within horizontal boundary
744+ let rightmostX = Math . max ( ...group . map ( id => activity . blocks . blockList [ id ] . container . x + activity . blocks . blockList [ id ] . width ) ) ;
745+
746+ if ( rightmostX > canvasWidth ) {
747+ let shiftX = Math . max ( 10 , canvasWidth - rightmostX - 10 ) ;
748+
749+ group . forEach ( blockId => {
750+ activity . blocks . blockList [ blockId ] . container . x += shiftX ;
751+ } ) ;
752+ }
753+
754+ // Ensures that blocks do not go hide behind the search for blocks div
755+ let leftmostX = Math . min ( ...group . map ( id => activity . blocks . blockList [ id ] . container . x ) ) ;
756+ if ( leftmostX < 0 ) {
757+ let shiftX = 100 - leftmostX ;
758+
759+ group . forEach ( blockId => {
760+ activity . blocks . blockList [ blockId ] . container . x += shiftX ;
761+ } ) ;
762+ }
763+
764+ } ) ;
765+
766+ activity . _findBlocks ( ) ;
767+ }
768+
769+ //if any window resize event occurs:
770+ window . addEventListener ( "resize" , ( ) => repositionBlocks ( this ) ) ;
771+
772+ /**
773+ * Finds and organizes blocks within the workspace.
774+ * Arranges blocks in grid format on wide screens and vertically on narrow screens.
775+ */
776+ this . _findBlocks = ( ) => {
777+ if ( ! this . blocks . visible ) {
778+ this . _changeBlockVisibility ( ) ;
779+ }
780+
781+ this . blocks . activeBlock = null ;
782+ hideDOMLabel ( ) ;
783+ this . blocks . showBlocks ( ) ;
784+ this . blocksContainer . x = 0 ;
785+ this . blocksContainer . y = 0 ;
786+
787+ const screenWidth = window . innerWidth ;
788+ const isNarrowScreen = screenWidth < 600 ;
789+ const minColumnWidth = 400 ;
790+ let numColumns = isNarrowScreen ? 1 : Math . floor ( screenWidth / minColumnWidth ) ;
791+
792+ let toppos = this . auxToolbar . style . display === "block" ? 90 + this . toolbarHeight : 90 ;
793+ let x = isNarrowScreen ? Math . floor ( screenWidth / 2 ) : Math . floor ( this . canvas . width / 4 ) ;
794+ let y = Math . floor ( toppos * this . turtleBlocksScale ) ;
795+ let verticalSpacing = Math . floor ( 40 * this . turtleBlocksScale ) ;
796+
797+ const columnSpacing = ( screenWidth / numColumns ) * 1.2 ;
798+ const columnXPositions = Array . from ( { length : numColumns } , ( _ , i ) =>
799+ Math . floor ( i * columnSpacing + columnSpacing / 2 )
800+ ) ;
801+ const columnYPositions = Array ( numColumns ) . fill ( y ) ;
802+
803+ for ( const blk in this . blocks . blockList ) {
804+ if ( ! this . blocks . blockList [ blk ] . trash ) {
805+ const myBlock = this . blocks . blockList [ blk ] ;
806+
807+ // Store original position only once
808+ if ( ! myBlock . originalPosition ) {
809+ myBlock . originalPosition = { x : myBlock . container . x , y : myBlock . container . y } ;
810+ }
811+
812+ if ( myBlock . connections [ 0 ] === null ) {
813+ if ( isNarrowScreen ) {
814+ const dx = x - myBlock . container . x ;
815+ const dy = y - myBlock . container . y ;
816+ this . blocks . moveBlockRelative ( blk , dx , dy ) ;
817+ y += myBlock . height + verticalSpacing ;
818+ } else {
819+ let minYIndex = columnYPositions . indexOf ( Math . min ( ...columnYPositions ) ) ;
820+ const dx = columnXPositions [ minYIndex ] - myBlock . container . x ;
821+ const dy = columnYPositions [ minYIndex ] - myBlock . container . y ;
822+ this . blocks . moveBlockRelative ( blk , dx , dy ) ;
823+ columnYPositions [ minYIndex ] += myBlock . height + verticalSpacing ;
824+ }
825+ }
826+
827+ // Making code to make sure that
828+ if ( myBlock . connections . length > 0 ) {
829+ myBlock . connections . forEach ( conn => {
830+ if ( conn !== null ) {
831+ let innerBlock = this . blocks . blockList [ conn ] ;
832+ if ( innerBlock ) {
833+
834+ innerBlock . container . x = myBlock . container . x + innerBlock . relativeX ;
835+ innerBlock . container . y = myBlock . container . y + innerBlock . relativeY ;
836+ }
837+
838+ }
839+
840+ } ) ;
841+ }
842+ }
843+ }
844+
845+ repositionBlocks ( this ) ;
846+ this . setHomeContainers ( false ) ;
847+ this . boundary . hide ( ) ;
848+
849+ for ( let turtle = 0 ; turtle < this . turtles . turtleList . length ; turtle ++ ) {
850+ const savedPenState = this . turtles . turtleList [ turtle ] . painter . penState ;
851+ this . turtles . turtleList [ turtle ] . painter . penState = false ;
852+ this . turtles . turtleList [ turtle ] . painter . doSetXY ( 0 , 0 ) ;
853+ this . turtles . turtleList [ turtle ] . painter . doSetHeading ( 0 ) ;
854+ this . turtles . turtleList [ turtle ] . painter . penState = savedPenState ;
855+ }
856+ } ;
857+
858+
676859 /**
677860 * Finds and organizes blocks within the workspace.
678861 * Blocks are positioned based on their connections and availability within the canvas area.
@@ -801,7 +984,7 @@ class Activity {
801984 */
802985
803986 const screenWidth = window . innerWidth ;
804- const minColumnWidth = 400 ;
987+ const minColumnWidth = 320 ;
805988 let numColumns = screenWidth <= 320 ? 1 : Math . floor ( screenWidth / minColumnWidth ) ;
806989
807990 const baseColumnSpacing = screenWidth / numColumns ;
0 commit comments