mirror of
https://github.com/scratchfoundation/scratch-blocks.git
synced 2025-08-28 22:10:31 -04:00
Remove setProcedureParameters from API (use domToMutation instead).
This commit is contained in:
parent
d086634394
commit
39fbd24659
6 changed files with 101 additions and 76 deletions
|
@ -119,6 +119,13 @@ Blockly.Blocks['lists_create_with'] = {
|
|||
itemBlock = itemBlock.nextConnection &&
|
||||
itemBlock.nextConnection.targetBlock();
|
||||
}
|
||||
// Disconnect any children that don't belong.
|
||||
for (var i = 0; i < this.itemCount_; i++) {
|
||||
var connection = this.getInput('ADD' + i).connection.targetConnection;
|
||||
if (connection && connections.indexOf(connection) == -1) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
this.itemCount_ = connections.length;
|
||||
this.updateShape_();
|
||||
// Reconnect any child blocks.
|
||||
|
|
|
@ -117,18 +117,30 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
|||
paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS +
|
||||
' ' + this.arguments_.join(', ');
|
||||
}
|
||||
// The params field is deterministic based on the mutation,
|
||||
// no need to fire a change event.
|
||||
Blockly.Events.disable();
|
||||
this.setFieldValue(paramString, 'PARAMS');
|
||||
Blockly.Events.enable();
|
||||
},
|
||||
/**
|
||||
* Create XML to represent the argument inputs.
|
||||
* @param {=boolean} opt_paramIds If true include the IDs of the parameter
|
||||
* quarks. Used by Blockly.Procedures.mutateCallers for reconnection.
|
||||
* @return {!Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
mutationToDom: function(opt_paramIds) {
|
||||
var container = document.createElement('mutation');
|
||||
if (opt_paramIds) {
|
||||
container.setAttribute('name', this.getFieldValue('NAME'));
|
||||
}
|
||||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
var parameter = document.createElement('arg');
|
||||
parameter.setAttribute('name', this.arguments_[i]);
|
||||
if (opt_paramIds && this.paramIds_) {
|
||||
parameter.setAttribute('paramId', this.paramIds_[i]);
|
||||
}
|
||||
container.appendChild(parameter);
|
||||
}
|
||||
|
||||
|
@ -151,6 +163,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
|||
}
|
||||
}
|
||||
this.updateParams_();
|
||||
Blockly.Procedures.mutateCallers(this);
|
||||
|
||||
// Show or hide the statement input.
|
||||
this.setStatements_(xmlElement.getAttribute('statements') !== 'false');
|
||||
|
@ -185,8 +198,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
|||
connection = paramBlock.nextConnection;
|
||||
}
|
||||
// Initialize procedure's callers with blank IDs.
|
||||
Blockly.Procedures.mutateCallers(this.getFieldValue('NAME'),
|
||||
this.workspace, this.arguments_, null);
|
||||
Blockly.Procedures.mutateCallers(this);
|
||||
return containerBlock;
|
||||
},
|
||||
/**
|
||||
|
@ -206,8 +218,7 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
|||
paramBlock.nextConnection.targetBlock();
|
||||
}
|
||||
this.updateParams_();
|
||||
Blockly.Procedures.mutateCallers(this.getFieldValue('NAME'),
|
||||
this.workspace, this.arguments_, this.paramIds_);
|
||||
Blockly.Procedures.mutateCallers(this);
|
||||
|
||||
// Show/hide the statement input.
|
||||
var hasStatements = containerBlock.getFieldValue('STATEMENTS');
|
||||
|
@ -439,15 +450,15 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
|||
*/
|
||||
init: function() {
|
||||
this.appendDummyInput('TOPROW')
|
||||
.appendField('', 'NAME');
|
||||
.appendField(this.id, 'NAME');
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setColour(Blockly.Blocks.procedures.HUE);
|
||||
// Tooltip is set in domToMutation.
|
||||
// Tooltip is set in renameProcedure.
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);
|
||||
this.arguments_ = [];
|
||||
this.quarkConnections_ = {};
|
||||
this.quarkArguments_ = null;
|
||||
this.quarkIds_ = null;
|
||||
},
|
||||
/**
|
||||
* Returns the name of the procedure this block calls.
|
||||
|
@ -480,63 +491,69 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
|||
* @param {!Array.<string>} paramIds IDs of params (consistent for each
|
||||
* parameter through the life of a mutator, regardless of param renaming),
|
||||
* e.g. ['piua', 'f8b_', 'oi.o'].
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
setProcedureParameters: function(paramNames, paramIds) {
|
||||
setProcedureParameters_: function(paramNames, paramIds) {
|
||||
// Data structures:
|
||||
// this.arguments = ['x', 'y']
|
||||
// Existing param names.
|
||||
// this.quarkConnections_ {piua: null, f8b_: Blockly.Connection}
|
||||
// Look-up of paramIds to connections plugged into the call block.
|
||||
// this.quarkArguments_ = ['piua', 'f8b_']
|
||||
// this.quarkIds_ = ['piua', 'f8b_']
|
||||
// Existing param IDs.
|
||||
// Note that quarkConnections_ may include IDs that no longer exist, but
|
||||
// which might reappear if a param is reattached in the mutator.
|
||||
if (!paramIds) {
|
||||
// Reset the quarks (a mutator is about to open).
|
||||
this.quarkConnections_ = {};
|
||||
this.quarkArguments_ = null;
|
||||
this.quarkIds_ = null;
|
||||
return;
|
||||
}
|
||||
if (goog.array.equals(this.arguments_, paramNames)) {
|
||||
// No change.
|
||||
this.quarkArguments_ = paramIds;
|
||||
this.quarkIds_ = paramIds;
|
||||
return;
|
||||
}
|
||||
if (paramIds.length != paramNames.length) {
|
||||
throw 'Error: paramNames and paramIds must be the same length.';
|
||||
}
|
||||
this.setCollapsed(false);
|
||||
if (!this.quarkArguments_) {
|
||||
if (!this.quarkIds_) {
|
||||
// Initialize tracking for this block.
|
||||
this.quarkConnections_ = {};
|
||||
if (paramNames.join('\n') == this.arguments_.join('\n')) {
|
||||
// No change to the parameters, allow quarkConnections_ to be
|
||||
// populated with the existing connections.
|
||||
this.quarkArguments_ = paramIds;
|
||||
this.quarkIds_ = paramIds;
|
||||
} else {
|
||||
this.quarkArguments_ = [];
|
||||
this.quarkIds_ = [];
|
||||
}
|
||||
}
|
||||
// Switch off rendering while the block is rebuilt.
|
||||
var savedRendered = this.rendered;
|
||||
this.rendered = false;
|
||||
// Update the quarkConnections_ with existing connections.
|
||||
for (var i = this.arguments_.length - 1; i >= 0; i--) {
|
||||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
var input = this.getInput('ARG' + i);
|
||||
if (input) {
|
||||
var connection = input.connection.targetConnection;
|
||||
this.quarkConnections_[this.quarkArguments_[i]] = connection;
|
||||
this.quarkConnections_[this.quarkIds_[i]] = connection;
|
||||
if (connection && paramIds.indexOf(this.quarkIds_[i]) == -1) {
|
||||
// This connection should no longer be attached to this block.
|
||||
connection.disconnect();
|
||||
connection.getSourceBlock().bumpNeighbours_();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rebuild the block's arguments.
|
||||
this.arguments_ = [].concat(paramNames);
|
||||
this.updateShape_();
|
||||
this.quarkArguments_ = paramIds;
|
||||
this.quarkIds_ = paramIds;
|
||||
// Reconnect any child blocks.
|
||||
if (this.quarkArguments_) {
|
||||
if (this.quarkIds_) {
|
||||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
var quarkId = this.quarkArguments_[i];
|
||||
var quarkId = this.quarkIds_[i];
|
||||
if (quarkId in this.quarkConnections_) {
|
||||
var connection = this.quarkConnections_[quarkId];
|
||||
if (!Blockly.Mutator.reconnect(connection, this, 'ARG' + i)) {
|
||||
|
@ -558,12 +575,21 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
|||
* @this Blockly.Block
|
||||
*/
|
||||
updateShape_: function() {
|
||||
// Add new inputs.
|
||||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
if (!this.getInput('ARG' + i)) {
|
||||
var field = this.getField('ARGNAME' + i);
|
||||
if (field) {
|
||||
// Ensure argument name is up to date.
|
||||
// The argument name field is deterministic based on the mutation,
|
||||
// no need to fire a change event.
|
||||
Blockly.Events.disable();
|
||||
field.setValue(this.arguments_[i]);
|
||||
Blockly.Events.enable();
|
||||
} else {
|
||||
// Add new input.
|
||||
field = new Blockly.FieldLabel(this.arguments_[i]);
|
||||
var input = this.appendValueInput('ARG' + i)
|
||||
.setAlign(Blockly.ALIGN_RIGHT)
|
||||
.appendField(this.arguments_[i]);
|
||||
.appendField(field, 'ARGNAME' + i);
|
||||
input.init();
|
||||
}
|
||||
}
|
||||
|
@ -609,25 +635,16 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
|||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
var name = xmlElement.getAttribute('name');
|
||||
this.setFieldValue(name, 'NAME');
|
||||
this.setTooltip(
|
||||
(this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP :
|
||||
Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace('%1', name));
|
||||
var def = Blockly.Procedures.getDefinition(name, this.workspace);
|
||||
if (def && def.mutator && def.mutator.isVisible()) {
|
||||
// Initialize caller with the mutator's IDs.
|
||||
this.setProcedureParameters(def.arguments_, def.paramIds_);
|
||||
} else {
|
||||
var args = [];
|
||||
for (var i = 0, childNode; childNode = xmlElement.childNodes[i]; i++) {
|
||||
if (childNode.nodeName.toLowerCase() == 'arg') {
|
||||
args.push(childNode.getAttribute('name'));
|
||||
}
|
||||
this.renameProcedure(this.getProcedureCall(), name);
|
||||
var args = [];
|
||||
var paramIds = [];
|
||||
for (var i = 0, childNode; childNode = xmlElement.childNodes[i]; i++) {
|
||||
if (childNode.nodeName.toLowerCase() == 'arg') {
|
||||
args.push(childNode.getAttribute('name'));
|
||||
paramIds.push(childNode.getAttribute('paramId'));
|
||||
}
|
||||
// For the second argument (paramIds) use the arguments list as a dummy
|
||||
// list.
|
||||
this.setProcedureParameters(args, args);
|
||||
}
|
||||
this.setProcedureParameters_(args, paramIds);
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
|
@ -640,7 +657,7 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
|||
for (var i = 0; i < this.arguments_.length; i++) {
|
||||
if (Blockly.Names.equals(oldName, this.arguments_[i])) {
|
||||
this.arguments_[i] = newName;
|
||||
this.getInput('ARG' + i).fieldRow[0].setValue(newName);
|
||||
this.getField('ARGNAME' + i).setValue(newName);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -676,12 +693,12 @@ Blockly.Blocks['procedures_callreturn'] = {
|
|||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);
|
||||
this.arguments_ = [];
|
||||
this.quarkConnections_ = {};
|
||||
this.quarkArguments_ = null;
|
||||
this.quarkIds_ = null;
|
||||
},
|
||||
getProcedureCall: Blockly.Blocks['procedures_callnoreturn'].getProcedureCall,
|
||||
renameProcedure: Blockly.Blocks['procedures_callnoreturn'].renameProcedure,
|
||||
setProcedureParameters:
|
||||
Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters,
|
||||
setProcedureParameters_:
|
||||
Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters_,
|
||||
updateShape_: Blockly.Blocks['procedures_callnoreturn'].updateShape_,
|
||||
mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom,
|
||||
domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation,
|
||||
|
|
|
@ -137,6 +137,13 @@ Blockly.Blocks['text_join'] = {
|
|||
itemBlock = itemBlock.nextConnection &&
|
||||
itemBlock.nextConnection.targetBlock();
|
||||
}
|
||||
// Disconnect any children that don't belong.
|
||||
for (var i = 0; i < this.itemCount_; i++) {
|
||||
var connection = this.getInput('ADD' + i).connection.targetConnection;
|
||||
if (connection && connections.indexOf(connection) == -1) {
|
||||
connection.disconnect();
|
||||
}
|
||||
}
|
||||
this.itemCount_ = connections.length;
|
||||
this.updateShape_();
|
||||
// Reconnect any child blocks.
|
||||
|
|
|
@ -251,16 +251,28 @@ Blockly.Procedures.disposeCallers = function(name, workspace) {
|
|||
/**
|
||||
* When a procedure definition changes its parameters, find and edit all its
|
||||
* callers.
|
||||
* @param {string} name Name of edited procedure definition.
|
||||
* @param {!Blockly.Workspace} workspace The workspace to delete callers from.
|
||||
* @param {!Array.<string>} paramNames Array of new parameter names.
|
||||
* @param {!Array.<string>} paramIds Array of unique parameter IDs.
|
||||
* @param {!Blockly.Block} defBlock Procedure definition block.
|
||||
*/
|
||||
Blockly.Procedures.mutateCallers = function(name, workspace,
|
||||
paramNames, paramIds) {
|
||||
var callers = Blockly.Procedures.getCallers(name, workspace);
|
||||
for (var i = 0; i < callers.length; i++) {
|
||||
callers[i].setProcedureParameters(paramNames, paramIds);
|
||||
Blockly.Procedures.mutateCallers = function(defBlock) {
|
||||
var oldRecordUndo = Blockly.Events.recordUndo;
|
||||
var name = defBlock.getProcedureDef()[0];
|
||||
var xmlElement = defBlock.mutationToDom(true);
|
||||
var callers = Blockly.Procedures.getCallers(name, defBlock.workspace);
|
||||
for (var i = 0, caller; caller = callers[i]; i++) {
|
||||
var oldMutationDom = caller.mutationToDom();
|
||||
var oldMutation = oldMutationDom && Blockly.Xml.domToText(oldMutationDom);
|
||||
caller.domToMutation(xmlElement);
|
||||
var newMutationDom = caller.mutationToDom();
|
||||
var newMutation = newMutationDom && Blockly.Xml.domToText(newMutationDom);
|
||||
if (oldMutation != newMutation) {
|
||||
// Fire a mutation on every caller block. But don't record this as an
|
||||
// undo action since it is deterministically tied to the procedure's
|
||||
// definition mutation.
|
||||
Blockly.Events.recordUndo = false;
|
||||
Blockly.Events.fire(new Blockly.Events.Change(
|
||||
caller, 'mutation', null, oldMutation, newMutation));
|
||||
Blockly.Events.recordUndo = oldRecordUndo;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -558,30 +558,12 @@ Blockly.genUid = function() {
|
|||
var length = 20;
|
||||
var soupLength = Blockly.genUid.soup_.length;
|
||||
var id = [];
|
||||
if (Blockly.genUid.crypto_) {
|
||||
// Cryptographically strong randomness is supported.
|
||||
var array = new Uint32Array(length);
|
||||
Blockly.genUid.crypto_.getRandomValues(array);
|
||||
for (var i = 0; i < length; i++) {
|
||||
id[i] = Blockly.genUid.soup_.charAt(array[i] % soupLength);
|
||||
}
|
||||
} else {
|
||||
// Fall back to Math.random for IE 10.
|
||||
for (var i = 0; i < length; i++) {
|
||||
id[i] = Blockly.genUid.soup_.charAt(Math.random() * soupLength);
|
||||
}
|
||||
for (var i = 0; i < length; i++) {
|
||||
id[i] = Blockly.genUid.soup_.charAt(Math.random() * soupLength);
|
||||
}
|
||||
return id.join('');
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine if window.crypto or global.crypto exists.
|
||||
* @this {Object}
|
||||
* @type {=RandomSource}
|
||||
* @private
|
||||
*/
|
||||
Blockly.genUid.crypto_ = this.crypto;
|
||||
|
||||
/**
|
||||
* Legal characters for the unique ID.
|
||||
* Should be all on a US keyboard. No XML special characters or control codes.
|
||||
|
|
|
@ -98,17 +98,17 @@ Blockly.ZoomControls.prototype.createDom = function() {
|
|||
<clippath id="blocklyZoomoutClipPath837493">
|
||||
<rect width="32" height="32" y="77"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-64" y="-15" xlink:href="media/sprites.png">
|
||||
<image width="96" height="124" x="-64" y="-15" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomoutClipPath837493)"></image>
|
||||
<clippath id="blocklyZoominClipPath837493">
|
||||
<rect width="32" height="32" y="43"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" x="-32" y="-49" xlink:href="media/sprites.png">
|
||||
<image width="96" height="124" x="-32" y="-49" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoominClipPath837493)"></image>
|
||||
<clippath id="blocklyZoomresetClipPath837493">
|
||||
<rect width="32" height="32"></rect>
|
||||
</clippath>
|
||||
<image width="96" height="124" y="-92" xlink:href="media/sprites.png">
|
||||
<image width="96" height="124" y="-92" xlink:href="media/sprites.png"
|
||||
clip-path="url(#blocklyZoomresetClipPath837493)"></image>
|
||||
</g>
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue