Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 85 additions & 0 deletions pxtblocks/plugins/newVariableField/fieldVariable.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import * as Blockly from "blockly";
import { showEditorMixin } from "./fieldDropdownMixin";
import { EXPORTED_VARIABLE_TYPE, IMPORTED_VARIABLE_TYPE } from "../../blocksProgram";

import svg = pxt.svgUtil;

const ICON_WIDTH = 20;
const ICON_PADDING = 8;
const TEXT_ARROW_PADDING = 15; // Extra padding between text end and arrow

/**
* This is the same as the Blockly variable field but with the addition
Expand Down Expand Up @@ -58,6 +65,17 @@ export class FieldVariable extends Blockly.FieldVariable {
private svgRootBinding: Blockly.browserEvents.Data | null = null;
private fieldRootBinding: Blockly.browserEvents.Data | null = null;
private clickTargetRect: SVGRectElement;
private globeIcon: svg.Text;

/**
* Check if the current variable is a global variable (exported or imported)
*/
protected isGlobalVariable(): boolean {
const variable = this.getVariable();
if (!variable) return false;
const varType = variable.getType();
return varType === EXPORTED_VARIABLE_TYPE || varType === IMPORTED_VARIABLE_TYPE;
}

override initView() {
super.initView();
Expand All @@ -75,6 +93,15 @@ export class FieldVariable extends Blockly.FieldVariable {
// Make sure to unset the border rect so that it isn't included in size
// calculations
this.borderRect_ = undefined;

// Add globe icon only for global variables
if (this.isGlobalVariable()) {
this.globeIcon = new svg.Text("\uf0ac")
.setClass("semanticIcon")
.setAttribute("alignment-baseline", "middle")
.anchor("middle");
this.fieldGroup_.appendChild(this.globeIcon.el);
}
}

override shouldAddBorderRect_() {
Expand Down Expand Up @@ -150,6 +177,17 @@ export class FieldVariable extends Blockly.FieldVariable {
}
}

protected override updateSize_(margin?: number): void {
// Let parent calculate the base size first
super.updateSize_(margin);

// Then add extra width for the icon if we're rendering it
if (this.globeIcon && !this.shouldAddBorderRect_()) {
// Add space for: icon + padding between icon and text + extra padding after text for arrow
this.size_.width += ICON_WIDTH + ICON_PADDING + TEXT_ARROW_PADDING;
}
}

protected override positionBorderRect_() {
super.positionBorderRect_();

Expand All @@ -167,6 +205,53 @@ export class FieldVariable extends Blockly.FieldVariable {
'ry',
String(this.getConstants()!.FIELD_BORDER_RECT_RADIUS),
);

// Position globe icon
if (this.globeIcon) {
this.globeIcon.at(ICON_WIDTH / 2, this.size_.height / 2);
}
}

protected override render_() {
super.render_();

// After parent renders, shift all children (except the icon) to make room for icon
if (this.globeIcon && !this.shouldAddBorderRect_() && this.fieldGroup_) {
const children = this.fieldGroup_.children;
for (let i = 0; i < children.length; i++) {
const child = children[i] as SVGElement;

// Skip the globe icon itself
if (child === this.globeIcon.el) {
continue;
}

// Shift elements with x attribute (like text)
if (child.hasAttribute('x')) {
const currentX = parseFloat(child.getAttribute('x') || '0');
child.setAttribute('x', String(currentX + ICON_WIDTH + ICON_PADDING));
}

// Shift elements with transform attribute (like arrow)
const transform = child.getAttribute('transform');
if (transform) {
const match = transform.match(/translate\(([-\d.]+),\s*([-\d.]+)\)/);
if (match) {
const x = parseFloat(match[1]);
const y = parseFloat(match[2]);
child.setAttribute('transform', `translate(${x + ICON_WIDTH + ICON_PADDING}, ${y})`);
}
}
}

// Update the width to account for the icon and shifted elements
this.size_.width += ICON_WIDTH + ICON_PADDING;

// Update the click target rect to cover the new width
if (this.clickTargetRect) {
this.clickTargetRect.setAttribute('width', String(this.size_.width));
}
}
}

protected showEditor_(e?: MouseEvent): void {
Expand Down