Skip to content

Commit

Permalink
fix: Fix blocks with mutators. (google#6440)
Browse files Browse the repository at this point in the history
* refactor: Revert the Mutator/Icon constructor API changes with a deprecation warning.

* fix: Update the block definitions to use the new Mutator constructor.
  • Loading branch information
gonfunko authored Sep 27, 2022
1 parent 9c81e75 commit ab03c65
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 57 deletions.
2 changes: 1 addition & 1 deletion blocks/lists.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ blocks['lists_create_with'] = {
this.itemCount_ = 3;
this.updateShape_();
this.setOutput(true, 'Array');
this.setMutator(new Mutator(['lists_create_with_item']));
this.setMutator(new Mutator(['lists_create_with_item'], this));
this.setTooltip(Msg['LISTS_CREATE_WITH_TOOLTIP']);
},
/**
Expand Down
4 changes: 2 additions & 2 deletions blocks/procedures.js
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ blocks['procedures_defnoreturn'] = {
.appendField(Msg['PROCEDURES_DEFNORETURN_TITLE'])
.appendField(nameField, 'NAME')
.appendField('', 'PARAMS');
this.setMutator(new Mutator(['procedures_mutatorarg']));
this.setMutator(new Mutator(['procedures_mutatorarg'], this));
if ((this.workspace.options.comments ||
(this.workspace.options.parentWorkspace &&
this.workspace.options.parentWorkspace.options.comments)) &&
Expand Down Expand Up @@ -507,7 +507,7 @@ blocks['procedures_defreturn'] = {
this.appendValueInput('RETURN')
.setAlign(Align.RIGHT)
.appendField(Msg['PROCEDURES_DEFRETURN_RETURN']);
this.setMutator(new Mutator(['procedures_mutatorarg']));
this.setMutator(new Mutator(['procedures_mutatorarg'], this));
if ((this.workspace.options.comments ||
(this.workspace.options.parentWorkspace &&
this.workspace.options.parentWorkspace.options.comments)) &&
Expand Down
2 changes: 1 addition & 1 deletion blocks/text.js
Original file line number Diff line number Diff line change
Expand Up @@ -864,7 +864,7 @@ const TEXT_JOIN_EXTENSION = function() {
this.itemCount_ = 2;
this.updateShape_();
// Configure the mutator UI.
this.setMutator(new Mutator(['text_create_join_item']));
this.setMutator(new Mutator(['text_create_join_item'], this));
};

// Update the tooltip of 'text_append' block to reference the variable.
Expand Down
21 changes: 11 additions & 10 deletions core/comment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ export class Comment extends Icon {
HTMLTextAreaElement;
const textarea = this.textarea_;
textarea.className = 'blocklyCommentTextarea';
textarea.setAttribute('dir', this.block_.RTL ? 'RTL' : 'LTR');
textarea.setAttribute('dir', this.getBlock().RTL ? 'RTL' : 'LTR');
textarea.value = this.model_.text ?? '';
this.resizeTextarea_();

Expand All @@ -167,7 +167,7 @@ export class Comment extends Icon {
function(this: Comment, _e: Event) {
if (this.cachedText_ !== this.model_.text) {
eventUtils.fire(new (eventUtils.get(eventUtils.BLOCK_CHANGE))(
this.block_, 'comment', null, this.cachedText_,
this.getBlock(), 'comment', null, this.cachedText_,
this.model_.text));
}
});
Expand Down Expand Up @@ -233,7 +233,7 @@ export class Comment extends Icon {
return;
}
eventUtils.fire(new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
this.block_, visible, 'comment'));
this.getBlock(), visible, 'comment'));
this.model_.pinned = visible;
if (visible) {
this.createBubble_();
Expand All @@ -244,7 +244,7 @@ export class Comment extends Icon {

/** Show the bubble. Handles deciding if it should be editable or not. */
private createBubble_() {
if (!this.block_.isEditable()) {
if (!this.getBlock().isEditable()) {
this.createNonEditableBubble_();
} else {
this.createEditableBubble_();
Expand All @@ -253,12 +253,13 @@ export class Comment extends Icon {

/** Show an editable bubble. */
private createEditableBubble_() {
const block = this.getBlock();
this.bubble_ = new Bubble(
this.block_.workspace, this.createEditor_(),
this.block_.pathObject.svgPath, (this.iconXY_ as Coordinate),
this.model_.size.width, this.model_.size.height);
block.workspace, this.createEditor_(), block.pathObject.svgPath,
(this.iconXY_ as Coordinate), this.model_.size.width,
this.model_.size.height);
// Expose this comment's block's ID on its top-level SVG group.
this.bubble_.setSvgId(this.block_.id);
this.bubble_.setSvgId(block.id);
this.bubble_.registerResizeEvent(this.onBubbleResize_.bind(this));
this.applyColour();
}
Expand All @@ -272,7 +273,7 @@ export class Comment extends Icon {
// TODO (#2917): It would be great if the comment could support line breaks.
this.paragraphElement_ = Bubble.textToDom(this.model_.text ?? '');
this.bubble_ = Bubble.createNonEditableBubble(
this.paragraphElement_, (this.block_), this.iconXY_ as Coordinate);
this.paragraphElement_, this.getBlock(), this.iconXY_ as Coordinate);
this.applyColour();
}

Expand Down Expand Up @@ -371,7 +372,7 @@ export class Comment extends Icon {
* should not be called directly. Instead call block.setCommentText(null);
*/
override dispose() {
this.block_.comment = null;
this.getBlock().comment = null;
super.dispose();
}
}
Expand Down
2 changes: 1 addition & 1 deletion core/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export function registerMutator(
// Sanity checks passed.
register(name, function(this: Block) {
if (hasMutatorDialog) {
this.setMutator(new Mutator(this as BlockSvg, opt_blockList || []));
this.setMutator(new Mutator(opt_blockList || [], this as BlockSvg));
}
// Mixin the object.
this.mixin(mixinObj);
Expand Down
39 changes: 28 additions & 11 deletions core/icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import * as dom from './utils/dom.js';
import {Size} from './utils/size.js';
import {Svg} from './utils/svg.js';
import * as svgMath from './utils/svg_math.js';
import * as deprecation from './utils/deprecation.js';


/**
Expand All @@ -28,7 +29,7 @@ import * as svgMath from './utils/svg_math.js';
* @alias Blockly.Icon
*/
export abstract class Icon {
protected block_: BlockSvg;
protected block_: BlockSvg|null;
/** The icon SVG group. */
iconGroup_: SVGGElement|null = null;

Expand All @@ -45,7 +46,12 @@ export abstract class Icon {
protected iconXY_: Coordinate|null = null;

/** @param block The block associated with this icon. */
constructor(block: BlockSvg) {
constructor(block: BlockSvg|null) {
if (!block) {
deprecation.warn(
'Calling the Icon constructor with a null block', 'version 9',
'version 10', 'a non-null block');
}
this.block_ = block;
}

Expand All @@ -62,12 +68,12 @@ export abstract class Icon {
*/
this.iconGroup_ =
dom.createSvgElement(Svg.G, {'class': 'blocklyIconGroup'});
if (this.block_.isInFlyout) {
if (this.getBlock().isInFlyout) {
this.iconGroup_.classList.add('blocklyIconGroupReadonly');
}
this.drawIcon_(this.iconGroup_);

this.block_.getSvgRoot().appendChild(this.iconGroup_);
this.getBlock().getSvgRoot().appendChild(this.iconGroup_);
browserEvents.conditionalBind(
this.iconGroup_, 'mouseup', this, this.iconClick_);
this.updateEditable();
Expand Down Expand Up @@ -99,19 +105,19 @@ export abstract class Icon {
* @param e Mouse click event.
*/
protected iconClick_(e: MouseEvent) {
if (this.block_.workspace.isDragging()) {
if (this.getBlock().workspace.isDragging()) {
// Drag operation is concluding. Don't open the editor.
return;
}
if (!this.block_.isInFlyout && !browserEvents.isRightButton(e)) {
if (!this.getBlock().isInFlyout && !browserEvents.isRightButton(e)) {
this.setVisible(!this.isVisible());
}
}

/** Change the colour of the associated bubble to match its block. */
applyColour() {
if (this.isVisible()) {
this.bubble_!.setColour(this.block_.style.colourPrimary);
if (this.bubble_ && this.isVisible()) {
this.bubble_.setColour(this.getBlock().style.colourPrimary);
}
}

Expand All @@ -122,8 +128,8 @@ export abstract class Icon {
*/
setIconLocation(xy: Coordinate) {
this.iconXY_ = xy;
if (this.isVisible()) {
this.bubble_!.setAnchorLocation(xy);
if (this.bubble_ && this.isVisible()) {
this.bubble_.setAnchorLocation(xy);
}
}

Expand All @@ -133,7 +139,7 @@ export abstract class Icon {
*/
computeIconLocation() {
// Find coordinates for the centre of the icon and update the arrow.
const blockXY = this.block_.getRelativeToSurfaceXY();
const blockXY = this.getBlock().getRelativeToSurfaceXY();
const iconXY = svgMath.getRelativeXY(this.iconGroup_ as SVGElement);
const newXY = new Coordinate(
blockXY.x + iconXY.x + this.SIZE / 2,
Expand Down Expand Up @@ -178,5 +184,16 @@ export abstract class Icon {
* @param _visible True if the icon should be visible.
*/
setVisible(_visible: boolean) {}

/**
* Returns the block this icon is attached to.
*/
protected getBlock(): BlockSvg {
if (!this.block_) {
throw new Error('Block is not set for this icon.');
}

return this.block_;
}
}
// No-op on base class
65 changes: 37 additions & 28 deletions core/mutator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import * as dom from './utils/dom.js';
import {Svg} from './utils/svg.js';
import * as toolbox from './utils/toolbox.js';
import * as xml from './utils/xml.js';
import * as deprecation from './utils/deprecation.js';
import type {WorkspaceSvg} from './workspace_svg.js';


Expand Down Expand Up @@ -77,8 +78,14 @@ export class Mutator extends Icon {
private updateWorkspacePid_: ReturnType<typeof setTimeout>|null = null;

/** @param quarkNames List of names of sub-blocks for flyout. */
constructor(block: BlockSvg, quarkNames: string[]) {
super(block);
constructor(quarkNames: string[], block?: BlockSvg) {
if (!block) {
deprecation.warn(
'Calling the Mutator constructor without passing the block it is attached to',
'version 9', 'version 10',
'the constructor by passing the list of subblocks and the block instance to attach the mutator to');
}
super(block ?? null);
this.quarkNames_ = quarkNames;
}

Expand Down Expand Up @@ -145,7 +152,7 @@ export class Mutator extends Icon {
* @param e Mouse click event.
*/
protected override iconClick_(e: MouseEvent) {
if (this.block_.isEditable()) {
if (this.getBlock().isEditable()) {
super.iconClick_(e);
}
}
Expand Down Expand Up @@ -175,19 +182,20 @@ export class Mutator extends Icon {
} else {
quarkXml = null;
}
const block = this.getBlock();
const workspaceOptions = new Options(({
// If you want to enable disabling, also remove the
// event filter from workspaceChanged_ .
'disable': false,
'parentWorkspace': this.block_.workspace,
'media': this.block_.workspace.options.pathToMedia,
'rtl': this.block_.RTL,
'parentWorkspace': block.workspace,
'media': block.workspace.options.pathToMedia,
'rtl': block.RTL,
'horizontalLayout': false,
'renderer': this.block_.workspace.options.renderer,
'rendererOverrides': this.block_.workspace.options.rendererOverrides,
'renderer': block.workspace.options.renderer,
'rendererOverrides': block.workspace.options.rendererOverrides,
} as BlocklyOptions));
workspaceOptions.toolboxPosition =
this.block_.RTL ? toolbox.Position.RIGHT : toolbox.Position.LEFT;
block.RTL ? toolbox.Position.RIGHT : toolbox.Position.LEFT;
const hasFlyout = !!quarkXml;
if (hasFlyout) {
workspaceOptions.languageTree = toolbox.convertToolboxDefToJson(quarkXml);
Expand Down Expand Up @@ -227,8 +235,8 @@ export class Mutator extends Icon {
/** Add or remove the UI indicating if this icon may be clicked or not. */
override updateEditable() {
super.updateEditable();
if (!this.block_.isInFlyout) {
if (this.block_.isEditable()) {
if (!this.getBlock().isInFlyout) {
if (this.getBlock().isEditable()) {
if (this.iconGroup_) {
this.iconGroup_.classList.remove('blocklyIconGroupReadonly');
}
Expand All @@ -255,7 +263,7 @@ export class Mutator extends Icon {
height = Math.max(height, flyoutScrollMetrics.height + 20);
width += flyout.getWidth();
}
if (this.block_.RTL) {
if (this.getBlock().RTL) {
width = -workspaceSize.x;
}
width += doubleBorderWidth * 3;
Expand All @@ -275,7 +283,7 @@ export class Mutator extends Icon {
this.workspaceWidth_, this.workspaceHeight_);
}

if (this.block_.RTL) {
if (this.getBlock().RTL) {
// Scroll the workspace to always left-align.
const translation = 'translate(' + this.workspaceWidth_ + ',0)';
this.workspace_!.getCanvas().setAttribute('transform', translation);
Expand All @@ -300,16 +308,16 @@ export class Mutator extends Icon {
// No change.
return;
}
const block = this.getBlock();
eventUtils.fire(new (eventUtils.get(eventUtils.BUBBLE_OPEN))(
this.block_, visible, 'mutator'));
block, visible, 'mutator'));
if (visible) {
// Create the bubble.
this.bubble_ = new Bubble(
(this.block_.workspace as WorkspaceSvg), this.createEditor_(),
this.block_.pathObject.svgPath, (this.iconXY_ as Coordinate), null,
null);
block.workspace, this.createEditor_(), block.pathObject.svgPath,
(this.iconXY_ as Coordinate), null, null);
// Expose this mutator's block's ID on its top-level SVG group.
this.bubble_.setSvgId(this.block_.id);
this.bubble_.setSvgId(block.id);
this.bubble_.registerMoveEvent(this.onBubbleMove_.bind(this));
const tree = this.workspace_!.options.languageTree;
const flyout = this.workspace_!.getFlyout();
Expand All @@ -318,7 +326,7 @@ export class Mutator extends Icon {
flyout!.show(tree);
}

this.rootBlock_ = this.block_!.decompose!(this.workspace_!)!;
this.rootBlock_ = block.decompose!(this.workspace_!)!;
const blocks = this.rootBlock_!.getDescendants(false);
for (let i = 0, child; child = blocks[i]; i++) {
child.render();
Expand All @@ -335,20 +343,21 @@ export class Mutator extends Icon {
margin = 16;
x = margin;
}
if (this.block_.RTL) {
if (block.RTL) {
x = -x;
}
this.rootBlock_!.moveBy(x, margin);
// Save the initial connections, then listen for further changes.
if (this.block_.saveConnections) {
if (block.saveConnections) {
const thisRootBlock = this.rootBlock_;
this.block_.saveConnections(thisRootBlock);
block.saveConnections(thisRootBlock);
this.sourceListener_ = () => {
if (this.block_ && this.block_.saveConnections) {
this.block_.saveConnections(thisRootBlock);
const currentBlock = this.getBlock();
if (currentBlock.saveConnections) {
currentBlock.saveConnections(thisRootBlock);
}
};
this.block_.workspace.addChangeListener(this.sourceListener_);
block.workspace.addChangeListener(this.sourceListener_);
}
this.resizeBubble_();
// When the mutator's workspace changes, update the source block.
Expand All @@ -367,7 +376,7 @@ export class Mutator extends Icon {
this.workspaceWidth_ = 0;
this.workspaceHeight_ = 0;
if (this.sourceListener_) {
this.block_.workspace.removeChangeListener(this.sourceListener_);
block.workspace.removeChangeListener(this.sourceListener_);
this.sourceListener_ = null;
}
}
Expand Down Expand Up @@ -438,7 +447,7 @@ export class Mutator extends Icon {
if (!existingGroup) {
eventUtils.setGroup(true);
}
const block = this.block_ as BlockSvg;
const block = this.getBlock();
const oldExtraState = BlockChange.getExtraBlockState_(block);

// Switch off rendering while the source block is rebuilt.
Expand Down Expand Up @@ -482,7 +491,7 @@ export class Mutator extends Icon {

/** Dispose of this mutator. */
override dispose() {
this.block_.mutator = null;
this.getBlock().mutator = null;
super.dispose();
}

Expand Down
Loading

0 comments on commit ab03c65

Please sign in to comment.