Skip to content

Commit 59e8f24

Browse files
committed
can now toggle local and global
1 parent 9779d93 commit 59e8f24

File tree

2 files changed

+88
-0
lines changed

2 files changed

+88
-0
lines changed

pxtblocks/builtins/variables.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ export function initVariables() {
149149
msg.DELETE_VARIABLE_CONFIRMATION = lf("Delete %1 uses of the \"%2\" variable?");
150150
msg.NEW_VARIABLE_DROPDOWN = lf("New variable...");
151151
msg.NEW_GLOBAL_VARIABLE_DROPDOWN = lf("New global variable...");
152+
msg.MAKE_VARIABLE_GLOBAL = lf("Make variable \"%1\" global");
153+
msg.MAKE_VARIABLE_LOCAL = lf("Make variable \"%1\" local");
154+
msg.CANNOT_MAKE_VARIABLE_LOCAL = lf("Cannot make variable \"%1\" local because it is referenced in another file.");
152155

153156
// builtin variables_set
154157
const variablesSetId = "variables_set";

pxtblocks/plugins/newVariableField/fieldVariable.ts

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as Blockly from "blockly";
22
import { showEditorMixin } from "./fieldDropdownMixin";
33
import { EXPORTED_VARIABLE_TYPE, IMPORTED_VARIABLE_TYPE } from "../../blocksProgram";
4+
import { getGlobalProgram } from "../../external";
45

56
import svg = pxt.svgUtil;
67

@@ -15,6 +16,7 @@ const TEXT_ARROW_PADDING = 15; // Extra padding between text end and arrow
1516
export 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

Comments
 (0)