11import * as Blockly from "blockly" ;
22import { showEditorMixin } from "./fieldDropdownMixin" ;
33import { EXPORTED_VARIABLE_TYPE , IMPORTED_VARIABLE_TYPE } from "../../blocksProgram" ;
4+ import { getGlobalProgram } from "../../external" ;
45
56import svg = pxt . svgUtil ;
67
@@ -15,6 +16,7 @@ const TEXT_ARROW_PADDING = 15; // Extra padding between text end and arrow
1516export class FieldVariable extends Blockly . FieldVariable {
1617 static CREATE_VARIABLE_ID = "CREATE_VARIABLE" ;
1718 static CREATE_GLOBAL_VARIABLE_ID = "CREATE_GLOBAL_VARIABLE" ;
19+ static TOGGLE_VARIABLE_SCOPE_ID = "TOGGLE_VARIABLE_SCOPE" ;
1820
1921 static dropdownCreate ( this : FieldVariable ) : Blockly . MenuOption [ ] {
2022 const options = Blockly . FieldVariable . dropdownCreate . call ( this ) as Blockly . MenuOption [ ] ;
@@ -34,6 +36,30 @@ export class FieldVariable extends Blockly.FieldVariable {
3436 [ Blockly . Msg [ 'NEW_GLOBAL_VARIABLE_DROPDOWN' ] , FieldVariable . CREATE_GLOBAL_VARIABLE_ID ]
3537 ) ;
3638
39+ // Add "Make variable global/local" option next to rename/delete
40+ const variable = this . getVariable ( ) ;
41+ if ( variable ) {
42+ const varName = variable . getName ( ) ;
43+ const varType = variable . getType ( ) ;
44+ const isGlobal = varType === EXPORTED_VARIABLE_TYPE ;
45+ const isImported = varType === IMPORTED_VARIABLE_TYPE ;
46+
47+ // Only show toggle for local or exported variables (not for imported ones)
48+ if ( ! isImported ) {
49+ const toggleLabel = isGlobal
50+ ? Blockly . Msg [ 'MAKE_VARIABLE_LOCAL' ] . replace ( '%1' , varName )
51+ : Blockly . Msg [ 'MAKE_VARIABLE_GLOBAL' ] . replace ( '%1' , varName ) ;
52+
53+ // Insert after rename, grouped with the other universal variable options
54+ const renameIndex = options . findIndex ( e => e [ 1 ] === "RENAME_VARIABLE_ID" ) ;
55+ options . splice (
56+ renameIndex + 1 ,
57+ 0 ,
58+ [ toggleLabel , FieldVariable . TOGGLE_VARIABLE_SCOPE_ID ]
59+ ) ;
60+ }
61+ }
62+
3763 return options ;
3864 }
3965
@@ -66,11 +92,70 @@ export class FieldVariable extends Blockly.FieldVariable {
6692 } , variableType ) ;
6793 return ;
6894 }
95+
96+ // Handle toggling variable scope (global <-> local)
97+ if ( id === FieldVariable . TOGGLE_VARIABLE_SCOPE_ID ) {
98+ this . toggleVariableScope ( ) ;
99+ return ;
100+ }
69101 }
70102
71103 super . onItemSelected_ ( menu , menuItem ) ;
72104 }
73105
106+ protected toggleVariableScope ( ) : void {
107+ const variable = this . getVariable ( ) ;
108+ if ( ! variable ) return ;
109+
110+ const workspace = this . sourceBlock_ . workspace ;
111+ const varName = variable . getName ( ) ;
112+ const varId = variable . getId ( ) ;
113+ const isGlobal = variable . getType ( ) === EXPORTED_VARIABLE_TYPE ;
114+ console . log ( "this is the variable type" ) ;
115+ console . log ( variable . getType ( ) ) ;
116+
117+ if ( isGlobal ) {
118+ // Check if the variable is referenced in other workspaces
119+ const program = getGlobalProgram ( ) ;
120+ if ( program ) {
121+ const allWorkspaces = program . getAllWorkspaces ( ) ;
122+ for ( const ws of allWorkspaces ) {
123+ if ( ws === workspace ) continue ;
124+
125+ const importedVar = ws . getVariableMap ( ) . getVariableById ( varId ) ;
126+ if ( importedVar ) {
127+ const uses = Blockly . Variables . getVariableUsesById ( ws , varId ) ;
128+ if ( uses . length > 0 ) {
129+ Blockly . dialog . alert (
130+ Blockly . Msg [ 'CANNOT_MAKE_VARIABLE_LOCAL' ] . replace ( '%1' , varName )
131+ ) ;
132+ return ;
133+ }
134+ }
135+ }
136+ }
137+
138+ variable . setType ( '' ) ;
139+ } else {
140+ variable . setType ( EXPORTED_VARIABLE_TYPE ) ;
141+ }
142+
143+ // Re-render all blocks that reference this variable so the globe icon updates
144+ const uses = Blockly . Variables . getVariableUsesById ( workspace , varId ) ;
145+ for ( const block of uses ) {
146+ const field = block . getField ( "VAR" ) ;
147+ if ( field ) {
148+ field . forceRerender ( ) ;
149+ }
150+ }
151+
152+ // Propagate changes across workspaces
153+ const program = getGlobalProgram ( ) ;
154+ if ( program ) {
155+ program . refreshSymbols ?.( ) ;
156+ }
157+ }
158+
74159 // Everything in this class below this line is duplicated in pxtblocks/fields/field_dropown
75160 // and should be kept in sync with FieldDropdown in that file
76161 private svgRootBinding : Blockly . browserEvents . Data | null = null ;
0 commit comments