mirror of
https://github.com/google/blockly.git
synced 2026-01-08 09:30:06 +01:00
Update to latest version.
This commit is contained in:
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['colour_picker'] = {
|
||||
// Colour picker.
|
||||
/**
|
||||
* Block for colour picker.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.COLOUR_PICKER_HELPURL);
|
||||
this.setColour(20);
|
||||
@@ -42,7 +45,10 @@ Blockly.Blocks['colour_picker'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['colour_random'] = {
|
||||
// Random colour.
|
||||
/**
|
||||
* Block for random colour.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.COLOUR_RANDOM_HELPURL);
|
||||
this.setColour(20);
|
||||
@@ -54,7 +60,10 @@ Blockly.Blocks['colour_random'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['colour_rgb'] = {
|
||||
// Compose a colour from RGB components.
|
||||
/**
|
||||
* Block for composing a colour from RGB components.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.COLOUR_RGB_HELPURL);
|
||||
this.setColour(20);
|
||||
@@ -77,7 +86,10 @@ Blockly.Blocks['colour_rgb'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['colour_blend'] = {
|
||||
// Blend two colours together.
|
||||
/**
|
||||
* Block for blending two colours together.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.COLOUR_BLEND_HELPURL);
|
||||
this.setColour(20);
|
||||
|
||||
192
blocks/lists.js
192
blocks/lists.js
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['lists_create_empty'] = {
|
||||
// Create an empty list.
|
||||
/**
|
||||
* Block for creating an empty list.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL);
|
||||
this.setColour(260);
|
||||
@@ -42,7 +45,10 @@ Blockly.Blocks['lists_create_empty'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_create_with'] = {
|
||||
// Create a list with any number of elements of any type.
|
||||
/**
|
||||
* Block for creating a list with any number of elements of any type.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(260);
|
||||
this.appendValueInput('ADD0')
|
||||
@@ -54,16 +60,26 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);
|
||||
this.itemCount_ = 3;
|
||||
},
|
||||
mutationToDom: function(workspace) {
|
||||
/**
|
||||
* Create XML to represent list inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
var container = document.createElement('mutation');
|
||||
container.setAttribute('items', this.itemCount_);
|
||||
return container;
|
||||
},
|
||||
domToMutation: function(container) {
|
||||
/**
|
||||
* Parse XML to restore the list inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
for (var x = 0; x < this.itemCount_; x++) {
|
||||
this.removeInput('ADD' + x);
|
||||
}
|
||||
this.itemCount_ = parseInt(container.getAttribute('items'), 10);
|
||||
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
|
||||
for (var x = 0; x < this.itemCount_; x++) {
|
||||
var input = this.appendValueInput('ADD' + x);
|
||||
if (x == 0) {
|
||||
@@ -75,6 +91,12 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
.appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Populate the mutator's dialog with this block's components.
|
||||
* @param {!Blockly.Workspace} workspace Mutator's workspace.
|
||||
* @return {!Blockly.Block} Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
decompose: function(workspace) {
|
||||
var containerBlock =
|
||||
Blockly.Block.obtain(workspace, 'lists_create_with_container');
|
||||
@@ -88,6 +110,11 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
}
|
||||
return containerBlock;
|
||||
},
|
||||
/**
|
||||
* Reconfigure this block based on the mutator dialog's components.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
compose: function(containerBlock) {
|
||||
// Disconnect all input blocks and remove all inputs.
|
||||
if (this.itemCount_ == 0) {
|
||||
@@ -118,8 +145,12 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
.appendField(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Store pointers to any connected child blocks.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
saveConnections: function(containerBlock) {
|
||||
// Store a pointer to any connected child blocks.
|
||||
var itemBlock = containerBlock.getInputTargetBlock('STACK');
|
||||
var x = 0;
|
||||
while (itemBlock) {
|
||||
@@ -133,7 +164,10 @@ Blockly.Blocks['lists_create_with'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_create_with_container'] = {
|
||||
// Container.
|
||||
/**
|
||||
* Mutator block for list container.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(260);
|
||||
this.appendDummyInput()
|
||||
@@ -145,7 +179,10 @@ Blockly.Blocks['lists_create_with_container'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_create_with_item'] = {
|
||||
// Add items.
|
||||
/**
|
||||
* Mutator bolck for adding items.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(260);
|
||||
this.appendDummyInput()
|
||||
@@ -158,7 +195,10 @@ Blockly.Blocks['lists_create_with_item'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_repeat'] = {
|
||||
// Create a list with one element repeated.
|
||||
/**
|
||||
* Block for creating a list with one element repeated.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_REPEAT_HELPURL);
|
||||
this.setColour(260);
|
||||
@@ -172,7 +212,10 @@ Blockly.Blocks['lists_repeat'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_length'] = {
|
||||
// List length.
|
||||
/**
|
||||
* Block for list length.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_LENGTH_HELPURL);
|
||||
this.setColour(260);
|
||||
@@ -185,13 +228,16 @@ Blockly.Blocks['lists_length'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_isEmpty'] = {
|
||||
// Is the list empty?
|
||||
/**
|
||||
* Block for is the list empty?
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LISTS_IS_EMPTY_HELPURL);
|
||||
this.setColour(260);
|
||||
this.interpolateMsg(Blockly.Msg.LISTS_IS_EMPTY_TITLE,
|
||||
['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT],
|
||||
Blockly.ALIGN_RIGHT)
|
||||
Blockly.ALIGN_RIGHT);
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'Boolean');
|
||||
this.setTooltip(Blockly.Msg.LISTS_TOOLTIP);
|
||||
@@ -199,7 +245,10 @@ Blockly.Blocks['lists_isEmpty'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_indexOf'] = {
|
||||
// Find an item in the list.
|
||||
/**
|
||||
* Block for finding an item in the list.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.LISTS_INDEX_OF_FIRST, 'FIRST'],
|
||||
@@ -218,7 +267,10 @@ Blockly.Blocks['lists_indexOf'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_getIndex'] = {
|
||||
// Get element at index.
|
||||
/**
|
||||
* Block for getting element at index.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var MODE =
|
||||
[[Blockly.Msg.LISTS_GET_INDEX_GET, 'GET'],
|
||||
@@ -234,7 +286,7 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
this.setColour(260);
|
||||
var modeMenu = new Blockly.FieldDropdown(MODE, function(value) {
|
||||
var isStatement = (value == 'REMOVE');
|
||||
this.sourceBlock_.updateStatement(isStatement);
|
||||
this.sourceBlock_.updateStatement_(isStatement);
|
||||
});
|
||||
this.appendValueInput('VALUE')
|
||||
.setCheck('Array')
|
||||
@@ -249,7 +301,7 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true);
|
||||
this.updateAt(true);
|
||||
this.updateAt_(true);
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
@@ -258,9 +310,13 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
return Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_' + combo];
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether the block is a statement or a value.
|
||||
* Also represent whether there is an 'AT' input.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether the block is a statement or a value.
|
||||
// Save whether there is an 'AT' input.
|
||||
var container = document.createElement('mutation');
|
||||
var isStatement = !this.outputConnection;
|
||||
container.setAttribute('statement', isStatement);
|
||||
@@ -268,17 +324,27 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
container.setAttribute('at', isAt);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'AT' input.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the block shape.
|
||||
// Note: Until January 2013 this block did not have mutations,
|
||||
// so 'statement' defaults to false and 'at' defaults to true.
|
||||
var isStatement = (xmlElement.getAttribute('statement') == 'true');
|
||||
this.updateStatement(isStatement);
|
||||
this.updateStatement_(isStatement);
|
||||
var isAt = (xmlElement.getAttribute('at') != 'false');
|
||||
this.updateAt(isAt);
|
||||
this.updateAt_(isAt);
|
||||
},
|
||||
updateStatement: function(newStatement) {
|
||||
// Switch between a value block and a statement block.
|
||||
/**
|
||||
* Switch between a value block and a statement block.
|
||||
* @param {boolean} newStatement True if the block should be a statement.
|
||||
* False if the block should be a value.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateStatement_: function(newStatement) {
|
||||
var oldStatement = !this.outputConnection;
|
||||
if (newStatement != oldStatement) {
|
||||
this.unplug(true, true);
|
||||
@@ -293,8 +359,13 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
updateAt: function(isAt) {
|
||||
// Create or delete an input for the numeric index.
|
||||
/**
|
||||
* Create or delete an input for the numeric index.
|
||||
* @param {boolean} isAt True if the input should exist.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateAt_: function(isAt) {
|
||||
// Destroy old 'AT' and 'ORDINAL' inputs.
|
||||
this.removeInput('AT');
|
||||
this.removeInput('ORDINAL', true);
|
||||
@@ -313,7 +384,7 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
// The 'isAt' variable is available due to this function being a closure.
|
||||
if (newAt != isAt) {
|
||||
var block = this.sourceBlock_;
|
||||
block.updateAt(newAt);
|
||||
block.updateAt_(newAt);
|
||||
// This menu has been destroyed and replaced. Update the replacement.
|
||||
block.setFieldValue(value, 'WHERE');
|
||||
return null;
|
||||
@@ -328,7 +399,10 @@ Blockly.Blocks['lists_getIndex'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_setIndex'] = {
|
||||
// Set element at index.
|
||||
/**
|
||||
* Block for setting the element at index.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var MODE =
|
||||
[[Blockly.Msg.LISTS_SET_INDEX_SET, 'SET'],
|
||||
@@ -354,7 +428,7 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);
|
||||
this.updateAt(true);
|
||||
this.updateAt_(true);
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
@@ -363,22 +437,35 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
return Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_' + combo];
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there is an 'AT' input.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether there is an 'AT' input.
|
||||
var container = document.createElement('mutation');
|
||||
var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE;
|
||||
container.setAttribute('at', isAt);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'AT' input.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the block shape.
|
||||
// Note: Until January 2013 this block did not have mutations,
|
||||
// so 'at' defaults to true.
|
||||
var isAt = (xmlElement.getAttribute('at') != 'false');
|
||||
this.updateAt(isAt);
|
||||
this.updateAt_(isAt);
|
||||
},
|
||||
updateAt: function(isAt) {
|
||||
// Create or delete an input for the numeric index.
|
||||
/**
|
||||
* Create or delete an input for the numeric index.
|
||||
* @param {boolean} isAt True if the input should exist.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateAt_: function(isAt) {
|
||||
// Destroy old 'AT' and 'ORDINAL' input.
|
||||
this.removeInput('AT');
|
||||
this.removeInput('ORDINAL', true);
|
||||
@@ -397,7 +484,7 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
// The 'isAt' variable is available due to this function being a closure.
|
||||
if (newAt != isAt) {
|
||||
var block = this.sourceBlock_;
|
||||
block.updateAt(newAt);
|
||||
block.updateAt_(newAt);
|
||||
// This menu has been destroyed and replaced. Update the replacement.
|
||||
block.setFieldValue(value, 'WHERE');
|
||||
return null;
|
||||
@@ -414,7 +501,10 @@ Blockly.Blocks['lists_setIndex'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['lists_getSublist'] = {
|
||||
// Get sublist.
|
||||
/**
|
||||
* Block for getting sublist.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.WHERE_OPTIONS_1 =
|
||||
[[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START, 'FROM_START'],
|
||||
@@ -437,12 +527,16 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'Array');
|
||||
this.updateAt(1, true);
|
||||
this.updateAt(2, true);
|
||||
this.updateAt_(1, true);
|
||||
this.updateAt_(2, true);
|
||||
this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there are 'AT' inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether there are 'AT' inputs.
|
||||
var container = document.createElement('mutation');
|
||||
var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE;
|
||||
container.setAttribute('at1', isAt1);
|
||||
@@ -450,14 +544,26 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
container.setAttribute('at2', isAt2);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'AT' inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the block shape.
|
||||
var isAt1 = (xmlElement.getAttribute('at1') == 'true');
|
||||
var isAt2 = (xmlElement.getAttribute('at2') == 'true');
|
||||
this.updateAt(1, isAt1);
|
||||
this.updateAt(2, isAt2);
|
||||
this.updateAt_(1, isAt1);
|
||||
this.updateAt_(2, isAt2);
|
||||
},
|
||||
updateAt: function(n, isAt) {
|
||||
/**
|
||||
* Create or delete an input for a numeric index.
|
||||
* This block has two such inputs, independant of each other.
|
||||
* @param {number} n Specify first or second input (1 or 2).
|
||||
* @param {boolean} isAt True if the input should exist.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateAt_: function(n, isAt) {
|
||||
// Create or delete an input for the numeric index.
|
||||
// Destroy old 'AT' and 'ORDINAL' inputs.
|
||||
this.removeInput('AT' + n);
|
||||
@@ -478,7 +584,7 @@ Blockly.Blocks['lists_getSublist'] = {
|
||||
// The 'isAt' variable is available due to this function being a closure.
|
||||
if (newAt != isAt) {
|
||||
var block = this.sourceBlock_;
|
||||
block.updateAt(n, newAt);
|
||||
block.updateAt_(n, newAt);
|
||||
// This menu has been destroyed and replaced. Update the replacement.
|
||||
block.setFieldValue(value, 'WHERE' + n);
|
||||
return null;
|
||||
|
||||
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['controls_if'] = {
|
||||
// If/elseif/else condition.
|
||||
/**
|
||||
* Block for if/elseif/else condition.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL);
|
||||
this.setColour(210);
|
||||
@@ -60,6 +63,11 @@ Blockly.Blocks['controls_if'] = {
|
||||
this.elseifCount_ = 0;
|
||||
this.elseCount_ = 0;
|
||||
},
|
||||
/**
|
||||
* Create XML to represent the number of else-if and else inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
if (!this.elseifCount_ && !this.elseCount_) {
|
||||
return null;
|
||||
@@ -73,6 +81,11 @@ Blockly.Blocks['controls_if'] = {
|
||||
}
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the else-if and else inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10);
|
||||
this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10);
|
||||
@@ -88,6 +101,12 @@ Blockly.Blocks['controls_if'] = {
|
||||
.appendField(Blockly.Msg.CONTROLS_IF_MSG_ELSE);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Populate the mutator's dialog with this block's components.
|
||||
* @param {!Blockly.Workspace} workspace Mutator's workspace.
|
||||
* @return {!Blockly.Block} Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
decompose: function(workspace) {
|
||||
var containerBlock = Blockly.Block.obtain(workspace, 'controls_if_if');
|
||||
containerBlock.initSvg();
|
||||
@@ -105,6 +124,11 @@ Blockly.Blocks['controls_if'] = {
|
||||
}
|
||||
return containerBlock;
|
||||
},
|
||||
/**
|
||||
* Reconfigure this block based on the mutator dialog's components.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
compose: function(containerBlock) {
|
||||
// Disconnect the else input blocks and remove the inputs.
|
||||
if (this.elseCount_) {
|
||||
@@ -152,8 +176,12 @@ Blockly.Blocks['controls_if'] = {
|
||||
clauseBlock.nextConnection.targetBlock();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Store pointers to any connected child blocks.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
saveConnections: function(containerBlock) {
|
||||
// Store a pointer to any connected child blocks.
|
||||
var clauseBlock = containerBlock.getInputTargetBlock('STACK');
|
||||
var x = 1;
|
||||
while (clauseBlock) {
|
||||
@@ -182,7 +210,10 @@ Blockly.Blocks['controls_if'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_if_if'] = {
|
||||
// If condition.
|
||||
/**
|
||||
* Mutator block for if container.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(210);
|
||||
this.appendDummyInput()
|
||||
@@ -194,7 +225,10 @@ Blockly.Blocks['controls_if_if'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_if_elseif'] = {
|
||||
// Else-If condition.
|
||||
/**
|
||||
* Mutator bolck for else-if condition.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(210);
|
||||
this.appendDummyInput()
|
||||
@@ -207,7 +241,10 @@ Blockly.Blocks['controls_if_elseif'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_if_else'] = {
|
||||
// Else condition.
|
||||
/**
|
||||
* Mutator block for else condition.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(210);
|
||||
this.appendDummyInput()
|
||||
@@ -219,7 +256,10 @@ Blockly.Blocks['controls_if_else'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['logic_compare'] = {
|
||||
// Comparison operator.
|
||||
/**
|
||||
* Block for comparison operator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS = Blockly.RTL ? [
|
||||
['=', 'EQ'],
|
||||
@@ -248,12 +288,12 @@ Blockly.Blocks['logic_compare'] = {
|
||||
this.setTooltip(function() {
|
||||
var op = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
EQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,
|
||||
NEQ: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,
|
||||
LT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,
|
||||
LTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,
|
||||
GT: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,
|
||||
GTE: Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE
|
||||
'EQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_EQ,
|
||||
'NEQ': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_NEQ,
|
||||
'LT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LT,
|
||||
'LTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_LTE,
|
||||
'GT': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GT,
|
||||
'GTE': Blockly.Msg.LOGIC_COMPARE_TOOLTIP_GTE
|
||||
};
|
||||
return TOOLTIPS[op];
|
||||
});
|
||||
@@ -261,7 +301,10 @@ Blockly.Blocks['logic_compare'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['logic_operation'] = {
|
||||
// Logical operations: 'and', 'or'.
|
||||
/**
|
||||
* Block for logical operations: 'and', 'or'.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.LOGIC_OPERATION_AND, 'AND'],
|
||||
@@ -280,17 +323,19 @@ Blockly.Blocks['logic_operation'] = {
|
||||
this.setTooltip(function() {
|
||||
var op = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
AND: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND,
|
||||
OR: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR
|
||||
'AND': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND,
|
||||
'OR': Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR
|
||||
};
|
||||
return TOOLTIPS[op];
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Blockly.Blocks['logic_negate'] = {
|
||||
// Negation.
|
||||
/**
|
||||
* Block for negation.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL);
|
||||
this.setColour(210);
|
||||
@@ -303,7 +348,10 @@ Blockly.Blocks['logic_negate'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['logic_boolean'] = {
|
||||
// Boolean data type: true and false.
|
||||
/**
|
||||
* Block for boolean data type: true and false.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var BOOLEANS =
|
||||
[[Blockly.Msg.LOGIC_BOOLEAN_TRUE, 'TRUE'],
|
||||
@@ -318,7 +366,10 @@ Blockly.Blocks['logic_boolean'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['logic_null'] = {
|
||||
// Null data type.
|
||||
/**
|
||||
* Block for null data type.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL);
|
||||
this.setColour(210);
|
||||
@@ -330,7 +381,10 @@ Blockly.Blocks['logic_null'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['logic_ternary'] = {
|
||||
// Ternary operator.
|
||||
/**
|
||||
* Block for ternary operator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL);
|
||||
this.setColour(210);
|
||||
|
||||
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['controls_repeat'] = {
|
||||
// Repeat n times (internal number).
|
||||
/**
|
||||
* Block for repeat n times (internal number).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);
|
||||
this.setColour(120);
|
||||
@@ -48,7 +51,10 @@ Blockly.Blocks['controls_repeat'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_repeat_ext'] = {
|
||||
// Repeat n times (external number).
|
||||
/**
|
||||
* Block for repeat n times (external number).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);
|
||||
this.setColour(120);
|
||||
@@ -65,7 +71,10 @@ Blockly.Blocks['controls_repeat_ext'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_whileUntil'] = {
|
||||
// Do while/until loop.
|
||||
/**
|
||||
* Block for 'do while/until' loop.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'],
|
||||
@@ -84,8 +93,8 @@ Blockly.Blocks['controls_whileUntil'] = {
|
||||
this.setTooltip(function() {
|
||||
var op = thisBlock.getFieldValue('MODE');
|
||||
var TOOLTIPS = {
|
||||
WHILE: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE,
|
||||
UNTIL: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL
|
||||
'WHILE': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE,
|
||||
'UNTIL': Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL
|
||||
};
|
||||
return TOOLTIPS[op];
|
||||
});
|
||||
@@ -93,7 +102,10 @@ Blockly.Blocks['controls_whileUntil'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_for'] = {
|
||||
// For loop.
|
||||
/**
|
||||
* Block for 'for' loop.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.CONTROLS_FOR_HELPURL);
|
||||
this.setColour(120);
|
||||
@@ -117,29 +129,51 @@ Blockly.Blocks['controls_for'] = {
|
||||
thisBlock.getFieldValue('VAR'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add menu option to create getter block for loop variable.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
var option = {enabled: true};
|
||||
var name = this.getFieldValue('VAR');
|
||||
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
|
||||
var xmlField = goog.dom.createDom('field', null, name);
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
if (!this.isCollapsed()) {
|
||||
var option = {enabled: true};
|
||||
var name = this.getFieldValue('VAR');
|
||||
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
|
||||
var xmlField = goog.dom.createDom('field', null, name);
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_forEach'] = {
|
||||
// For each loop.
|
||||
/**
|
||||
* Block for 'for each' loop.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.CONTROLS_FOREACH_HELPURL);
|
||||
this.setColour(120);
|
||||
@@ -164,9 +198,21 @@ Blockly.Blocks['controls_forEach'] = {
|
||||
thisBlock.getFieldValue('VAR'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
@@ -176,7 +222,10 @@ Blockly.Blocks['controls_forEach'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['controls_flow_statements'] = {
|
||||
// Flow statements: continue, break.
|
||||
/**
|
||||
* Block for flow statements: continue, break.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'],
|
||||
@@ -191,12 +240,17 @@ Blockly.Blocks['controls_flow_statements'] = {
|
||||
this.setTooltip(function() {
|
||||
var op = thisBlock.getFieldValue('FLOW');
|
||||
var TOOLTIPS = {
|
||||
BREAK: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK,
|
||||
CONTINUE: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE
|
||||
'BREAK': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK,
|
||||
'CONTINUE': Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE
|
||||
};
|
||||
return thisBlock.TOOLTIPS[op];
|
||||
return TOOLTIPS[op];
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Called whenever anything on the workspace changes.
|
||||
* Add warning if this flow block is not nested inside a loop.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
onchange: function() {
|
||||
if (!this.workspace) {
|
||||
// Block has been deleted.
|
||||
|
||||
161
blocks/math.js
161
blocks/math.js
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['math_number'] = {
|
||||
// Numeric value.
|
||||
/**
|
||||
* Block for numeric value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
|
||||
this.setColour(230);
|
||||
@@ -43,7 +46,10 @@ Blockly.Blocks['math_number'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_arithmetic'] = {
|
||||
// Basic arithmetic operator.
|
||||
/**
|
||||
* Block for basic arithmetic operator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'],
|
||||
@@ -65,11 +71,11 @@ Blockly.Blocks['math_arithmetic'] = {
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
ADD: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
|
||||
MINUS: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
|
||||
MULTIPLY: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
|
||||
DIVIDE: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
|
||||
POWER: Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
|
||||
'ADD': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_ADD,
|
||||
'MINUS': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MINUS,
|
||||
'MULTIPLY': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_MULTIPLY,
|
||||
'DIVIDE': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_DIVIDE,
|
||||
'POWER': Blockly.Msg.MATH_ARITHMETIC_TOOLTIP_POWER
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
@@ -77,7 +83,10 @@ Blockly.Blocks['math_arithmetic'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_single'] = {
|
||||
// Advanced math operators with single operand.
|
||||
/**
|
||||
* Block for advanced math operators with single operand.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'],
|
||||
@@ -99,13 +108,13 @@ Blockly.Blocks['math_single'] = {
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
ROOT: Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,
|
||||
ABS: Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,
|
||||
NEG: Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,
|
||||
LN: Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,
|
||||
LOG10: Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,
|
||||
EXP: Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,
|
||||
POW10: Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10
|
||||
'ROOT': Blockly.Msg.MATH_SINGLE_TOOLTIP_ROOT,
|
||||
'ABS': Blockly.Msg.MATH_SINGLE_TOOLTIP_ABS,
|
||||
'NEG': Blockly.Msg.MATH_SINGLE_TOOLTIP_NEG,
|
||||
'LN': Blockly.Msg.MATH_SINGLE_TOOLTIP_LN,
|
||||
'LOG10': Blockly.Msg.MATH_SINGLE_TOOLTIP_LOG10,
|
||||
'EXP': Blockly.Msg.MATH_SINGLE_TOOLTIP_EXP,
|
||||
'POW10': Blockly.Msg.MATH_SINGLE_TOOLTIP_POW10
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
@@ -113,7 +122,10 @@ Blockly.Blocks['math_single'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_trig'] = {
|
||||
// Trigonometry operators.
|
||||
/**
|
||||
* Block for trigonometry operators.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_TRIG_SIN, 'SIN'],
|
||||
@@ -133,12 +145,12 @@ Blockly.Blocks['math_trig'] = {
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
SIN: Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,
|
||||
COS: Blockly.Msg.MATH_TRIG_TOOLTIP_COS,
|
||||
TAN: Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,
|
||||
ASIN: Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,
|
||||
ACOS: Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,
|
||||
ATAN: Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN
|
||||
'SIN': Blockly.Msg.MATH_TRIG_TOOLTIP_SIN,
|
||||
'COS': Blockly.Msg.MATH_TRIG_TOOLTIP_COS,
|
||||
'TAN': Blockly.Msg.MATH_TRIG_TOOLTIP_TAN,
|
||||
'ASIN': Blockly.Msg.MATH_TRIG_TOOLTIP_ASIN,
|
||||
'ACOS': Blockly.Msg.MATH_TRIG_TOOLTIP_ACOS,
|
||||
'ATAN': Blockly.Msg.MATH_TRIG_TOOLTIP_ATAN
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
@@ -146,7 +158,10 @@ Blockly.Blocks['math_trig'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_constant'] = {
|
||||
// Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
|
||||
/**
|
||||
* Block for constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var CONSTANTS =
|
||||
[['\u03c0', 'PI'],
|
||||
@@ -165,8 +180,11 @@ Blockly.Blocks['math_constant'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_number_property'] = {
|
||||
// Check if a number is even, odd, prime, whole, positive, or negative
|
||||
// or if it is divisible by certain number. Returns true or false.
|
||||
/**
|
||||
* Block for checking if a number is even, odd, prime, whole, positive,
|
||||
* negative or if it is divisible by certain number.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var PROPERTIES =
|
||||
[[Blockly.Msg.MATH_IS_EVEN, 'EVEN'],
|
||||
@@ -181,7 +199,7 @@ Blockly.Blocks['math_number_property'] = {
|
||||
.setCheck('Number');
|
||||
var dropdown = new Blockly.FieldDropdown(PROPERTIES, function(option) {
|
||||
var divisorInput = (option == 'DIVISIBLE_BY');
|
||||
this.sourceBlock_.updateShape(divisorInput);
|
||||
this.sourceBlock_.updateShape_(divisorInput);
|
||||
});
|
||||
this.appendDummyInput()
|
||||
.appendField(dropdown, 'PROPERTY');
|
||||
@@ -189,25 +207,39 @@ Blockly.Blocks['math_number_property'] = {
|
||||
this.setOutput(true, 'Boolean');
|
||||
this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether the 'divisorInput' should be present.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether the 'divisorInput' should be true of false (present or not).
|
||||
var container = document.createElement('mutation');
|
||||
var divisorInput = (this.getFieldValue('PROPERTY') == 'DIVISIBLE_BY');
|
||||
container.setAttribute('divisor_input', divisorInput);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'divisorInput'.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the 'divisorInput'.
|
||||
var divisorInput = (xmlElement.getAttribute('divisor_input') == 'true');
|
||||
this.updateShape(divisorInput);
|
||||
this.updateShape_(divisorInput);
|
||||
},
|
||||
updateShape: function(divisorInput) {
|
||||
/**
|
||||
* Modify this block to have (or not have) an input for 'is divisible by'.
|
||||
* @param {boolean} divisorInput True if this block has a divisor input.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateShape_: function(divisorInput) {
|
||||
// Add or remove a Value Input.
|
||||
var inputExists = this.getInput('DIVISOR');
|
||||
if (divisorInput) {
|
||||
if (!inputExists) {
|
||||
this.appendValueInput('DIVISOR')
|
||||
.setCheck('Number');
|
||||
.setCheck('Number');
|
||||
}
|
||||
} else if (inputExists) {
|
||||
this.removeInput('DIVISOR');
|
||||
@@ -216,7 +248,10 @@ Blockly.Blocks['math_number_property'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_change'] = {
|
||||
// Add to a variable in place.
|
||||
/**
|
||||
* Block for adding to a variable in place.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_CHANGE_HELPURL);
|
||||
this.setColour(230);
|
||||
@@ -236,9 +271,21 @@ Blockly.Blocks['math_change'] = {
|
||||
thisBlock.getFieldValue('VAR'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
@@ -247,7 +294,10 @@ Blockly.Blocks['math_change'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_round'] = {
|
||||
// Rounding functions.
|
||||
/**
|
||||
* Block for rounding functions.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'],
|
||||
@@ -264,8 +314,11 @@ Blockly.Blocks['math_round'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_on_list'] = {
|
||||
// Evaluate a list of numbers to return sum, average, min, max, etc.
|
||||
// Some functions also work on text (min, max, mode, median).
|
||||
/**
|
||||
* Block for evaluating a list of numbers to return sum, average, min, max,
|
||||
* etc. Some functions also work on text (min, max, mode, median).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'],
|
||||
@@ -294,14 +347,14 @@ Blockly.Blocks['math_on_list'] = {
|
||||
this.setTooltip(function() {
|
||||
var mode = thisBlock.getFieldValue('OP');
|
||||
var TOOLTIPS = {
|
||||
SUM: Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,
|
||||
MIN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,
|
||||
MAX: Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,
|
||||
AVERAGE: Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,
|
||||
MEDIAN: Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,
|
||||
MODE: Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,
|
||||
STD_DEV: Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,
|
||||
RANDOM: Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM
|
||||
'SUM': Blockly.Msg.MATH_ONLIST_TOOLTIP_SUM,
|
||||
'MIN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MIN,
|
||||
'MAX': Blockly.Msg.MATH_ONLIST_TOOLTIP_MAX,
|
||||
'AVERAGE': Blockly.Msg.MATH_ONLIST_TOOLTIP_AVERAGE,
|
||||
'MEDIAN': Blockly.Msg.MATH_ONLIST_TOOLTIP_MEDIAN,
|
||||
'MODE': Blockly.Msg.MATH_ONLIST_TOOLTIP_MODE,
|
||||
'STD_DEV': Blockly.Msg.MATH_ONLIST_TOOLTIP_STD_DEV,
|
||||
'RANDOM': Blockly.Msg.MATH_ONLIST_TOOLTIP_RANDOM
|
||||
};
|
||||
return TOOLTIPS[mode];
|
||||
});
|
||||
@@ -309,7 +362,10 @@ Blockly.Blocks['math_on_list'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_modulo'] = {
|
||||
// Remainder of a division.
|
||||
/**
|
||||
* Block for remainder of a division.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_MODULO_HELPURL);
|
||||
this.setColour(230);
|
||||
@@ -324,7 +380,10 @@ Blockly.Blocks['math_modulo'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_constrain'] = {
|
||||
// Constrain a number between two limits.
|
||||
/**
|
||||
* Block for constraining a number between two limits.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_CONSTRAIN_HELPURL);
|
||||
this.setColour(230);
|
||||
@@ -333,14 +392,17 @@ Blockly.Blocks['math_constrain'] = {
|
||||
['VALUE', 'Number', Blockly.ALIGN_RIGHT],
|
||||
['LOW', 'Number', Blockly.ALIGN_RIGHT],
|
||||
['HIGH', 'Number', Blockly.ALIGN_RIGHT],
|
||||
Blockly.ALIGN_RIGHT)
|
||||
Blockly.ALIGN_RIGHT);
|
||||
this.setInputsInline(true);
|
||||
this.setTooltip(Blockly.Msg.MATH_CONSTRAIN_TOOLTIP);
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_random_int'] = {
|
||||
// Random integer between [X] and [Y].
|
||||
/**
|
||||
* Block for random integer between [X] and [Y].
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_RANDOM_INT_HELPURL);
|
||||
this.setColour(230);
|
||||
@@ -355,7 +417,10 @@ Blockly.Blocks['math_random_int'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['math_random_float'] = {
|
||||
// Random fraction between 0 and 1.
|
||||
/**
|
||||
* Block for random fraction between 0 and 1.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL);
|
||||
this.setColour(230);
|
||||
|
||||
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
// Define a procedure with no return value.
|
||||
/**
|
||||
* Block for defining a procedure with no return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);
|
||||
this.setColour(290);
|
||||
@@ -41,12 +44,38 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
.appendField(new Blockly.FieldTextInput(name,
|
||||
Blockly.Procedures.rename), 'NAME')
|
||||
.appendField('', 'PARAMS');
|
||||
this.appendStatementInput('STACK')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);
|
||||
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);
|
||||
this.arguments_ = [];
|
||||
this.setStatements_(true);
|
||||
this.statementConnection_ = null;
|
||||
},
|
||||
/**
|
||||
* Add or remove the statement block from this function definition.
|
||||
* @param {boolean} hasStatements True if a statement block is needed.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
setStatements_: function(hasStatements) {
|
||||
if (this.hasStatements_ === hasStatements) {
|
||||
return;
|
||||
}
|
||||
if (hasStatements) {
|
||||
this.appendStatementInput('STACK')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);
|
||||
if (this.getInput('RETURN')) {
|
||||
this.moveInputBefore('STACK', 'RETURN');
|
||||
}
|
||||
} else {
|
||||
this.removeInput('STACK', true);
|
||||
}
|
||||
this.hasStatements_ = hasStatements;
|
||||
},
|
||||
/**
|
||||
* Update the display of parameters for this procedure definition block.
|
||||
* Display a warning if there are duplicately named parameters.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateParams_: function() {
|
||||
// Check for duplicated arguments.
|
||||
var badArg = false;
|
||||
@@ -71,6 +100,11 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
}
|
||||
this.setFieldValue(paramString, 'PARAMS');
|
||||
},
|
||||
/**
|
||||
* Create XML to represent the argument inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
var container = document.createElement('mutation');
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
@@ -78,8 +112,18 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
parameter.setAttribute('name', this.arguments_[x]);
|
||||
container.appendChild(parameter);
|
||||
}
|
||||
|
||||
// Save whether the statement input is visible.
|
||||
if (!this.hasStatements_) {
|
||||
container.setAttribute('statements', 'false');
|
||||
}
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the argument inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
this.arguments_ = [];
|
||||
for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) {
|
||||
@@ -88,11 +132,30 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
}
|
||||
}
|
||||
this.updateParams_();
|
||||
|
||||
// Show or hide the statement input.
|
||||
this.setStatements_(xmlElement.getAttribute('statements') !== 'false');
|
||||
},
|
||||
/**
|
||||
* Populate the mutator's dialog with this block's components.
|
||||
* @param {!Blockly.Workspace} workspace Mutator's workspace.
|
||||
* @return {!Blockly.Block} Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
decompose: function(workspace) {
|
||||
var containerBlock = Blockly.Block.obtain(workspace,
|
||||
'procedures_mutatorcontainer');
|
||||
'procedures_mutatorcontainer');
|
||||
containerBlock.initSvg();
|
||||
|
||||
// Check/uncheck the allow statement box.
|
||||
if (this.getInput('RETURN')) {
|
||||
containerBlock.setFieldValue(this.hasStatements_ ? 'TRUE' : 'FALSE',
|
||||
'STATEMENTS');
|
||||
} else {
|
||||
containerBlock.getInput('STATEMENT_INPUT').setVisible(false);
|
||||
}
|
||||
|
||||
// Parameter list.
|
||||
var connection = containerBlock.getInput('STACK').connection;
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
var paramBlock = Blockly.Block.obtain(workspace, 'procedures_mutatorarg');
|
||||
@@ -108,7 +171,13 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
this.workspace, this.arguments_, null);
|
||||
return containerBlock;
|
||||
},
|
||||
/**
|
||||
* Reconfigure this block based on the mutator dialog's components.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
compose: function(containerBlock) {
|
||||
// Parameter list.
|
||||
this.arguments_ = [];
|
||||
this.paramIds_ = [];
|
||||
var paramBlock = containerBlock.getInputTargetBlock('STACK');
|
||||
@@ -121,23 +190,76 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
this.updateParams_();
|
||||
Blockly.Procedures.mutateCallers(this.getFieldValue('NAME'),
|
||||
this.workspace, this.arguments_, this.paramIds_);
|
||||
|
||||
// Show/hide the statement input.
|
||||
var hasStatements = containerBlock.getFieldValue('STATEMENTS');
|
||||
if (hasStatements !== null) {
|
||||
hasStatements = hasStatements == 'TRUE';
|
||||
if (this.hasStatements_ != hasStatements) {
|
||||
if (hasStatements) {
|
||||
this.setStatements_(true);
|
||||
// Restore the stack, if one was saved.
|
||||
var stackConnection = this.getInput('STACK').connection;
|
||||
if (stackConnection.targetConnection ||
|
||||
!this.statementConnection_ ||
|
||||
this.statementConnection_.targetConnection ||
|
||||
this.statementConnection_.sourceBlock_.workspace !=
|
||||
this.workspace) {
|
||||
// Block no longer exists or has been attached elsewhere.
|
||||
this.statementConnection_ = null;
|
||||
} else {
|
||||
stackConnection.connect(this.statementConnection_);
|
||||
}
|
||||
} else {
|
||||
// Save the stack, then disconnect it.
|
||||
var stackConnection = this.getInput('STACK').connection;
|
||||
this.statementConnection_ = stackConnection.targetConnection;
|
||||
if (this.statementConnection_) {
|
||||
var stackBlock = stackConnection.targetBlock();
|
||||
stackBlock.setParent(null);
|
||||
stackBlock.bumpNeighbours_();
|
||||
}
|
||||
this.setStatements_(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Dispose of any callers.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
dispose: function() {
|
||||
// Dispose of any callers.
|
||||
var name = this.getFieldValue('NAME');
|
||||
Blockly.Procedures.disposeCallers(name, this.workspace);
|
||||
// Call parent's destructor.
|
||||
Blockly.Block.prototype.dispose.apply(this, arguments);
|
||||
},
|
||||
/**
|
||||
* Return the signature of this procedure definition.
|
||||
* @return {!Array} Tuple containing three elements:
|
||||
* - the name of the defined procedure,
|
||||
* - a list of all its arguments,
|
||||
* - that it DOES NOT have a return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getProcedureDef: function() {
|
||||
// Return the name of the defined procedure,
|
||||
// a list of all its arguments,
|
||||
// and that it DOES NOT have a return value.
|
||||
return [this.getFieldValue('NAME'), this.arguments_, false];
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return this.arguments_;
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
var change = false;
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
@@ -160,12 +282,16 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add custom menu options to this block's context menu.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
// Add option to create caller.
|
||||
var option = {enabled: true};
|
||||
var name = this.getFieldValue('NAME');
|
||||
option.text = Blockly.Msg.PROCEDURES_CREATE_DO.replace('%1', name);
|
||||
|
||||
var xmlMutation = goog.dom.createDom('mutation');
|
||||
xmlMutation.setAttribute('name', name);
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
@@ -176,26 +302,31 @@ Blockly.Blocks['procedures_defnoreturn'] = {
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlMutation);
|
||||
xmlBlock.setAttribute('type', this.callType_);
|
||||
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
|
||||
|
||||
options.push(option);
|
||||
|
||||
// Add options to create getters for each parameter.
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
var option = {enabled: true};
|
||||
var name = this.arguments_[x];
|
||||
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
|
||||
var xmlField = goog.dom.createDom('field', null, name);
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
if (!this.isCollapsed()) {
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
var option = {enabled: true};
|
||||
var name = this.arguments_[x];
|
||||
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
|
||||
var xmlField = goog.dom.createDom('field', null, name);
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
var xmlBlock = goog.dom.createDom('block', null, xmlField);
|
||||
xmlBlock.setAttribute('type', 'variables_get');
|
||||
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
}
|
||||
}
|
||||
},
|
||||
callType_: 'procedures_callnoreturn'
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_defreturn'] = {
|
||||
// Define a procedure with a return value.
|
||||
/**
|
||||
* Block for defining a procedure with a return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);
|
||||
this.setColour(290);
|
||||
@@ -206,25 +337,31 @@ Blockly.Blocks['procedures_defreturn'] = {
|
||||
.appendField(new Blockly.FieldTextInput(name,
|
||||
Blockly.Procedures.rename), 'NAME')
|
||||
.appendField('', 'PARAMS');
|
||||
this.appendStatementInput('STACK')
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_DO);
|
||||
this.appendValueInput('RETURN')
|
||||
.setAlign(Blockly.ALIGN_RIGHT)
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);
|
||||
this.arguments_ = [];
|
||||
this.setStatements_(true);
|
||||
this.statementConnection_ = null;
|
||||
},
|
||||
setStatements_: Blockly.Blocks['procedures_defnoreturn'].setStatements_,
|
||||
updateParams_: Blockly.Blocks['procedures_defnoreturn'].updateParams_,
|
||||
mutationToDom: Blockly.Blocks['procedures_defnoreturn'].mutationToDom,
|
||||
domToMutation: Blockly.Blocks['procedures_defnoreturn'].domToMutation,
|
||||
decompose: Blockly.Blocks['procedures_defnoreturn'].decompose,
|
||||
compose: Blockly.Blocks['procedures_defnoreturn'].compose,
|
||||
dispose: Blockly.Blocks['procedures_defnoreturn'].dispose,
|
||||
/**
|
||||
* Return the signature of this procedure definition.
|
||||
* @return {!Array} Tuple containing three elements:
|
||||
* - the name of the defined procedure,
|
||||
* - a list of all its arguments,
|
||||
* - that it DOES have a return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getProcedureDef: function() {
|
||||
// Return the name of the defined procedure,
|
||||
// a list of all its arguments,
|
||||
// and that it DOES have a return value.
|
||||
return [this.getFieldValue('NAME'), this.arguments_, true];
|
||||
},
|
||||
getVars: Blockly.Blocks['procedures_defnoreturn'].getVars,
|
||||
@@ -234,73 +371,109 @@ Blockly.Blocks['procedures_defreturn'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_mutatorcontainer'] = {
|
||||
// Procedure container (for mutator dialog).
|
||||
/**
|
||||
* Mutator block for procedure container.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(290);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);
|
||||
this.appendStatementInput('STACK');
|
||||
this.setTooltip('');
|
||||
this.appendDummyInput('STATEMENT_INPUT')
|
||||
.appendField(Blockly.Msg.PROCEDURES_ALLOW_STATEMENTS)
|
||||
.appendField(new Blockly.FieldCheckbox('TRUE'), 'STATEMENTS');
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TOOLTIP);
|
||||
this.contextMenu = false;
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_mutatorarg'] = {
|
||||
// Procedure argument (for mutator dialog).
|
||||
/**
|
||||
* Mutator block for procedure argument.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(290);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE)
|
||||
.appendField(new Blockly.FieldTextInput('x', this.validator), 'NAME');
|
||||
.appendField(new Blockly.FieldTextInput('x', this.validator_), 'NAME');
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setTooltip('');
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_MUTATORARG_TOOLTIP);
|
||||
this.contextMenu = false;
|
||||
},
|
||||
validator: function(newVar) {
|
||||
// Merge runs of whitespace. Strip leading and trailing whitespace.
|
||||
// Beyond this, all names are legal.
|
||||
/**
|
||||
* Obtain a valid name for the procedure.
|
||||
* Merge runs of whitespace. Strip leading and trailing whitespace.
|
||||
* Beyond this, all names are legal.
|
||||
* @param {string} newVar User-supplied name.
|
||||
* @return {?string} Valid name, or null if a name was not specified.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
validator_: function(newVar) {
|
||||
newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
|
||||
return newVar || null;
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
// Call a procedure with no return value.
|
||||
/**
|
||||
* Block for calling a procedure with no return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);
|
||||
this.setColour(290);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_CALLNORETURN_CALL)
|
||||
.appendField('', 'NAME');
|
||||
.appendField('', 'NAME')
|
||||
.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS, 'WITH');
|
||||
this.setPreviousStatement(true);
|
||||
this.setNextStatement(true);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP);
|
||||
// Tooltip is set in domToMutation.
|
||||
this.arguments_ = [];
|
||||
this.quarkConnections_ = null;
|
||||
this.quarkArguments_ = null;
|
||||
},
|
||||
/**
|
||||
* Returns the name of the procedure this block calls.
|
||||
* @return {string} Procedure name.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getProcedureCall: function() {
|
||||
return this.getFieldValue('NAME');
|
||||
// The NAME field is guaranteed to exist, null will never be returned.
|
||||
return /** @type {string} */ (this.getFieldValue('NAME'));
|
||||
},
|
||||
/**
|
||||
* Notification that a procedure is renaming.
|
||||
* If the name matches this block's procedure, rename it.
|
||||
* @param {string} oldName Previous name of procedure.
|
||||
* @param {string} newName Renamed procedure.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameProcedure: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('NAME'))) {
|
||||
if (Blockly.Names.equals(oldName, this.getProcedureCall())) {
|
||||
this.setFieldValue(newName, 'NAME');
|
||||
this.setTooltip(
|
||||
(this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP
|
||||
: Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP)
|
||||
(this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP :
|
||||
Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP)
|
||||
.replace('%1', newName));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Notification that the procedure's parameters have changed.
|
||||
* @param {!Array.<string>} paramNames New param names, e.g. ['x', 'y', 'z'].
|
||||
* @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'].
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
setProcedureParameters: function(paramNames, paramIds) {
|
||||
// Data structures for parameters on each call block:
|
||||
// Data structures:
|
||||
// this.arguments = ['x', 'y']
|
||||
// Existing param names.
|
||||
// paramNames = ['x', 'y', 'z']
|
||||
// New param names.
|
||||
// paramIds = ['piua', 'f8b_', 'oi.o']
|
||||
// IDs of params (consistent for each parameter through the life of a
|
||||
// mutator, regardless of param renaming).
|
||||
// this.quarkConnections_ {piua: null, f8b_: Blockly.Connection}
|
||||
// Look-up of paramIds to connections plugged into the call block.
|
||||
// this.quarkArguments_ = ['piua', 'f8b_']
|
||||
@@ -362,16 +535,22 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
}
|
||||
}
|
||||
}
|
||||
// Add 'with:' if there are parameters.
|
||||
this.getField_('WITH').setVisible(!!this.arguments_.length);
|
||||
// Restore rendering and show the changes.
|
||||
this.rendered = savedRendered;
|
||||
if (this.rendered) {
|
||||
this.render();
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Create XML to represent the (non-editable) name and arguments.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save the name and arguments (none of which are editable).
|
||||
var container = document.createElement('mutation');
|
||||
container.setAttribute('name', this.getFieldValue('NAME'));
|
||||
container.setAttribute('name', this.getProcedureCall());
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
var parameter = document.createElement('arg');
|
||||
parameter.setAttribute('name', this.arguments_[x]);
|
||||
@@ -379,13 +558,17 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
}
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the (non-editable) name and parameters.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the name and parameters.
|
||||
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));
|
||||
(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.isVisible()) {
|
||||
// Initialize caller with the mutator's IDs.
|
||||
@@ -402,6 +585,13 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
this.setProcedureParameters(this.arguments_, this.arguments_);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
for (var x = 0; x < this.arguments_.length; x++) {
|
||||
if (Blockly.Names.equals(oldName, this.arguments_[x])) {
|
||||
@@ -410,11 +600,15 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
}
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add menu option to find the definition block for this call.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
// Add option to find caller.
|
||||
var option = {enabled: true};
|
||||
option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;
|
||||
var name = this.getFieldValue('NAME');
|
||||
var name = this.getProcedureCall();
|
||||
var workspace = this.workspace;
|
||||
option.callback = function() {
|
||||
var def = Blockly.Procedures.getDefinition(name, workspace);
|
||||
@@ -425,15 +619,19 @@ Blockly.Blocks['procedures_callnoreturn'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_callreturn'] = {
|
||||
// Call a procedure with a return value.
|
||||
/**
|
||||
* Block for calling a procedure with a return value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);
|
||||
this.setColour(290);
|
||||
this.appendDummyInput()
|
||||
.appendField(Blockly.Msg.PROCEDURES_CALLRETURN_CALL)
|
||||
.appendField('', 'NAME');
|
||||
.appendField('', 'NAME')
|
||||
.appendField(Blockly.Msg.PROCEDURES_CALL_BEFORE_PARAMS, 'WITH');
|
||||
this.setOutput(true);
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP);
|
||||
// Tooltip is set in domToMutation.
|
||||
this.arguments_ = [];
|
||||
this.quarkConnections_ = null;
|
||||
this.quarkArguments_ = null;
|
||||
@@ -449,7 +647,10 @@ Blockly.Blocks['procedures_callreturn'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['procedures_ifreturn'] = {
|
||||
// Conditionally return value from a procedure.
|
||||
/**
|
||||
* Block for conditionally returning a value from a procedure.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl('http://c2.com/cgi/wiki?GuardClause');
|
||||
this.setColour(290);
|
||||
@@ -464,14 +665,22 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);
|
||||
this.hasReturnValue_ = true;
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether this block has a return value.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether this block has a return value.
|
||||
var container = document.createElement('mutation');
|
||||
container.setAttribute('value', Number(this.hasReturnValue_));
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore whether this block has a return value.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore whether this block has a return value.
|
||||
var value = xmlElement.getAttribute('value');
|
||||
this.hasReturnValue_ = (value == 1);
|
||||
if (!this.hasReturnValue_) {
|
||||
@@ -480,6 +689,11 @@ Blockly.Blocks['procedures_ifreturn'] = {
|
||||
.appendField(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Called whenever anything on the workspace changes.
|
||||
* Add warning if this flow block is not nested inside a loop.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
onchange: function() {
|
||||
if (!this.workspace) {
|
||||
// Block has been deleted.
|
||||
|
||||
229
blocks/text.js
229
blocks/text.js
@@ -30,23 +30,42 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['text'] = {
|
||||
// Text value.
|
||||
/**
|
||||
* Block for text value.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL);
|
||||
this.setColour(160);
|
||||
this.appendDummyInput()
|
||||
.appendField(new Blockly.FieldImage(Blockly.pathToBlockly +
|
||||
'media/quote0.png', 12, 12, '"'))
|
||||
.appendField(this.newQuote_(true))
|
||||
.appendField(new Blockly.FieldTextInput(''), 'TEXT')
|
||||
.appendField(new Blockly.FieldImage(Blockly.pathToBlockly +
|
||||
'media/quote1.png', 12, 12, '"'));
|
||||
.appendField(this.newQuote_(false));
|
||||
this.setOutput(true, 'String');
|
||||
this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP);
|
||||
},
|
||||
/**
|
||||
* Create an image of an open or closed quote.
|
||||
* @param {boolean} open True if open quote, false if closed.
|
||||
* @return {!Blockly.FieldImage} The field image of the quote.
|
||||
* @private
|
||||
*/
|
||||
newQuote_: function(open) {
|
||||
if (open == Blockly.RTL) {
|
||||
var file = 'quote1.png';
|
||||
} else {
|
||||
var file = 'quote0.png';
|
||||
}
|
||||
return new Blockly.FieldImage(Blockly.pathToBlockly + 'media/' + file,
|
||||
12, 12, '"');
|
||||
}
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_join'] = {
|
||||
// Create a string made up of any number of elements of any type.
|
||||
/**
|
||||
* Block for creating a string made up of any number of elements of any type.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_JOIN_HELPURL);
|
||||
this.setColour(160);
|
||||
@@ -58,11 +77,21 @@ Blockly.Blocks['text_join'] = {
|
||||
this.setTooltip(Blockly.Msg.TEXT_JOIN_TOOLTIP);
|
||||
this.itemCount_ = 2;
|
||||
},
|
||||
/**
|
||||
* Create XML to represent number of text inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
var container = document.createElement('mutation');
|
||||
container.setAttribute('items', this.itemCount_);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the text inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
for (var x = 0; x < this.itemCount_; x++) {
|
||||
this.removeInput('ADD' + x);
|
||||
@@ -82,6 +111,12 @@ Blockly.Blocks['text_join'] = {
|
||||
'media/quote1.png', 12, 12, '"'));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Populate the mutator's dialog with this block's components.
|
||||
* @param {!Blockly.Workspace} workspace Mutator's workspace.
|
||||
* @return {!Blockly.Block} Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
decompose: function(workspace) {
|
||||
var containerBlock = Blockly.Block.obtain(workspace,
|
||||
'text_create_join_container');
|
||||
@@ -95,6 +130,11 @@ Blockly.Blocks['text_join'] = {
|
||||
}
|
||||
return containerBlock;
|
||||
},
|
||||
/**
|
||||
* Reconfigure this block based on the mutator dialog's components.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
compose: function(containerBlock) {
|
||||
// Disconnect all input blocks and remove all inputs.
|
||||
if (this.itemCount_ == 0) {
|
||||
@@ -128,8 +168,12 @@ Blockly.Blocks['text_join'] = {
|
||||
'media/quote1.png', 12, 12, '"'));
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Store pointers to any connected child blocks.
|
||||
* @param {!Blockly.Block} containerBlock Root block in mutator.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
saveConnections: function(containerBlock) {
|
||||
// Store a pointer to any connected child blocks.
|
||||
var itemBlock = containerBlock.getInputTargetBlock('STACK');
|
||||
var x = 0;
|
||||
while (itemBlock) {
|
||||
@@ -143,7 +187,10 @@ Blockly.Blocks['text_join'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_create_join_container'] = {
|
||||
// Container.
|
||||
/**
|
||||
* Mutator block for container.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(160);
|
||||
this.appendDummyInput()
|
||||
@@ -155,7 +202,10 @@ Blockly.Blocks['text_create_join_container'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_create_join_item'] = {
|
||||
// Add items.
|
||||
/**
|
||||
* Mutator block for add items.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setColour(160);
|
||||
this.appendDummyInput()
|
||||
@@ -168,7 +218,10 @@ Blockly.Blocks['text_create_join_item'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_append'] = {
|
||||
// Append to a variable in place.
|
||||
/**
|
||||
* Block for appending to a variable in place.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_APPEND_HELPURL);
|
||||
this.setColour(160);
|
||||
@@ -186,9 +239,21 @@ Blockly.Blocks['text_append'] = {
|
||||
thisBlock.getFieldValue('VAR'));
|
||||
});
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
@@ -197,7 +262,10 @@ Blockly.Blocks['text_append'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_length'] = {
|
||||
// String length.
|
||||
/**
|
||||
* Block for string length.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_LENGTH_HELPURL);
|
||||
this.setColour(160);
|
||||
@@ -210,7 +278,10 @@ Blockly.Blocks['text_length'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_isEmpty'] = {
|
||||
// Is the string null?
|
||||
/**
|
||||
* Block for is the string null?
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_ISEMPTY_HELPURL);
|
||||
this.setColour(160);
|
||||
@@ -223,7 +294,10 @@ Blockly.Blocks['text_isEmpty'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_indexOf'] = {
|
||||
// Find a substring in the text.
|
||||
/**
|
||||
* Block for finding a substring in the text.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST, 'FIRST'],
|
||||
@@ -246,7 +320,10 @@ Blockly.Blocks['text_indexOf'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_charAt'] = {
|
||||
// Get a character from the string.
|
||||
/**
|
||||
* Block for getting a character from the string.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.WHERE_OPTIONS =
|
||||
[[Blockly.Msg.TEXT_CHARAT_FROM_START, 'FROM_START'],
|
||||
@@ -262,25 +339,38 @@ Blockly.Blocks['text_charAt'] = {
|
||||
.appendField(Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT);
|
||||
this.appendDummyInput('AT');
|
||||
this.setInputsInline(true);
|
||||
this.updateAt(true);
|
||||
this.updateAt_(true);
|
||||
this.setTooltip(Blockly.Msg.TEXT_CHARAT_TOOLTIP);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there is an 'AT' input.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether there is an 'AT' input.
|
||||
var container = document.createElement('mutation');
|
||||
var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE;
|
||||
container.setAttribute('at', isAt);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'AT' input.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the 'AT' input.
|
||||
// Note: Until January 2013 this block did not have mutations,
|
||||
// so 'at' defaults to true.
|
||||
var isAt = (xmlElement.getAttribute('at') != 'false');
|
||||
this.updateAt(isAt);
|
||||
this.updateAt_(isAt);
|
||||
},
|
||||
updateAt: function(isAt) {
|
||||
// Create or delete an input for the numeric index.
|
||||
/**
|
||||
* Create or delete an input for the numeric index.
|
||||
* @param {boolean} isAt True if the input should exist.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateAt_: function(isAt) {
|
||||
// Destroy old 'AT' and 'ORDINAL' inputs.
|
||||
this.removeInput('AT');
|
||||
this.removeInput('ORDINAL', true);
|
||||
@@ -304,7 +394,7 @@ Blockly.Blocks['text_charAt'] = {
|
||||
// The 'isAt' variable is available due to this function being a closure.
|
||||
if (newAt != isAt) {
|
||||
var block = this.sourceBlock_;
|
||||
block.updateAt(newAt);
|
||||
block.updateAt_(newAt);
|
||||
// This menu has been destroyed and replaced. Update the replacement.
|
||||
block.setFieldValue(value, 'WHERE');
|
||||
return null;
|
||||
@@ -316,7 +406,10 @@ Blockly.Blocks['text_charAt'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_getSubstring'] = {
|
||||
// Get substring.
|
||||
/**
|
||||
* Block for getting substring.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.WHERE_OPTIONS_1 =
|
||||
[[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START, 'FROM_START'],
|
||||
@@ -339,12 +432,16 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
}
|
||||
this.setInputsInline(true);
|
||||
this.setOutput(true, 'String');
|
||||
this.updateAt(1, true);
|
||||
this.updateAt(2, true);
|
||||
this.updateAt_(1, true);
|
||||
this.updateAt_(2, true);
|
||||
this.setTooltip(Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP);
|
||||
},
|
||||
/**
|
||||
* Create XML to represent whether there are 'AT' inputs.
|
||||
* @return {Element} XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
mutationToDom: function() {
|
||||
// Save whether there are 'AT' inputs.
|
||||
var container = document.createElement('mutation');
|
||||
var isAt1 = this.getInput('AT1').type == Blockly.INPUT_VALUE;
|
||||
container.setAttribute('at1', isAt1);
|
||||
@@ -352,14 +449,26 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
container.setAttribute('at2', isAt2);
|
||||
return container;
|
||||
},
|
||||
/**
|
||||
* Parse XML to restore the 'AT' inputs.
|
||||
* @param {!Element} xmlElement XML storage element.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
domToMutation: function(xmlElement) {
|
||||
// Restore the block shape.
|
||||
var isAt1 = (xmlElement.getAttribute('at1') == 'true');
|
||||
var isAt2 = (xmlElement.getAttribute('at2') == 'true');
|
||||
this.updateAt(1, isAt1);
|
||||
this.updateAt(2, isAt2);
|
||||
this.updateAt_(1, isAt1);
|
||||
this.updateAt_(2, isAt2);
|
||||
},
|
||||
updateAt: function(n, isAt) {
|
||||
/**
|
||||
* Create or delete an input for a numeric index.
|
||||
* This block has two such inputs, independant of each other.
|
||||
* @param {number} n Specify first or second input (1 or 2).
|
||||
* @param {boolean} isAt True if the input should exist.
|
||||
* @private
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
updateAt_: function(n, isAt) {
|
||||
// Create or delete an input for the numeric index.
|
||||
// Destroy old 'AT' and 'ORDINAL' inputs.
|
||||
this.removeInput('AT' + n);
|
||||
@@ -386,7 +495,7 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
// The 'isAt' variable is available due to this function being a closure.
|
||||
if (newAt != isAt) {
|
||||
var block = this.sourceBlock_;
|
||||
block.updateAt(n, newAt);
|
||||
block.updateAt_(n, newAt);
|
||||
// This menu has been destroyed and replaced. Update the replacement.
|
||||
block.setFieldValue(value, 'WHERE' + n);
|
||||
return null;
|
||||
@@ -402,7 +511,10 @@ Blockly.Blocks['text_getSubstring'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_changeCase'] = {
|
||||
// Change capitalization.
|
||||
/**
|
||||
* Block for changing capitalization.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE, 'UPPERCASE'],
|
||||
@@ -419,7 +531,10 @@ Blockly.Blocks['text_changeCase'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_trim'] = {
|
||||
// Trim spaces.
|
||||
/**
|
||||
* Block for trimming spaces.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var OPERATORS =
|
||||
[[Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH, 'BOTH'],
|
||||
@@ -436,7 +551,10 @@ Blockly.Blocks['text_trim'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_print'] = {
|
||||
// Print statement.
|
||||
/**
|
||||
* Block for print statement.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_PRINT_HELPURL);
|
||||
this.setColour(160);
|
||||
@@ -450,7 +568,10 @@ Blockly.Blocks['text_print'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_prompt'] = {
|
||||
// Prompt function.
|
||||
/**
|
||||
* Block for prompt function (internal message).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var TYPES =
|
||||
[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'],
|
||||
@@ -468,11 +589,43 @@ Blockly.Blocks['text_prompt'] = {
|
||||
});
|
||||
this.appendDummyInput()
|
||||
.appendField(dropdown, 'TYPE')
|
||||
.appendField(new Blockly.FieldImage(Blockly.pathToBlockly +
|
||||
'media/quote0.png', 12, 12, '"'))
|
||||
.appendField(this.newQuote_(true))
|
||||
.appendField(new Blockly.FieldTextInput(''), 'TEXT')
|
||||
.appendField(new Blockly.FieldImage(Blockly.pathToBlockly +
|
||||
'media/quote1.png', 12, 12, '"'));
|
||||
.appendField(this.newQuote_(false));
|
||||
this.setOutput(true, 'String');
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
this.setTooltip(function() {
|
||||
return (thisBlock.getFieldValue('TYPE') == 'TEXT') ?
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT :
|
||||
Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER;
|
||||
});
|
||||
},
|
||||
newQuote_: Blockly.Blocks['text'].newQuote_
|
||||
};
|
||||
|
||||
Blockly.Blocks['text_prompt_ext'] = {
|
||||
/**
|
||||
* Block for prompt function (external message).
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
var TYPES =
|
||||
[[Blockly.Msg.TEXT_PROMPT_TYPE_TEXT, 'TEXT'],
|
||||
[Blockly.Msg.TEXT_PROMPT_TYPE_NUMBER, 'NUMBER']];
|
||||
// Assign 'this' to a variable for use in the closure below.
|
||||
var thisBlock = this;
|
||||
this.setHelpUrl(Blockly.Msg.TEXT_PROMPT_HELPURL);
|
||||
this.setColour(160);
|
||||
var dropdown = new Blockly.FieldDropdown(TYPES, function(newOp) {
|
||||
if (newOp == 'NUMBER') {
|
||||
thisBlock.changeOutput('Number');
|
||||
} else {
|
||||
thisBlock.changeOutput('String');
|
||||
}
|
||||
});
|
||||
this.appendValueInput('TEXT')
|
||||
.appendField(dropdown, 'TYPE');
|
||||
this.setOutput(true, 'String');
|
||||
// Assign 'this' to a variable for use in the tooltip closure below.
|
||||
var thisBlock = this;
|
||||
|
||||
@@ -30,7 +30,10 @@ goog.require('Blockly.Blocks');
|
||||
|
||||
|
||||
Blockly.Blocks['variables_get'] = {
|
||||
// Variable getter.
|
||||
/**
|
||||
* Block for variable getter.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
|
||||
this.setColour(330);
|
||||
@@ -44,14 +47,31 @@ Blockly.Blocks['variables_get'] = {
|
||||
this.contextMenuMsg_ = Blockly.Msg.VARIABLES_GET_CREATE_SET;
|
||||
this.contextMenuType_ = 'variables_set';
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Add menu option to create getter/setter block for this setter/getter.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
var option = {enabled: true};
|
||||
var name = this.getFieldValue('VAR');
|
||||
@@ -66,7 +86,10 @@ Blockly.Blocks['variables_get'] = {
|
||||
};
|
||||
|
||||
Blockly.Blocks['variables_set'] = {
|
||||
// Variable setter.
|
||||
/**
|
||||
* Block for variable setter.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
init: function() {
|
||||
this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);
|
||||
this.setColour(330);
|
||||
@@ -83,9 +106,21 @@ Blockly.Blocks['variables_set'] = {
|
||||
this.contextMenuMsg_ = Blockly.Msg.VARIABLES_SET_CREATE_GET;
|
||||
this.contextMenuType_ = 'variables_get';
|
||||
},
|
||||
/**
|
||||
* Return all variables referenced by this block.
|
||||
* @return {!Array.<string>} List of variable names.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
getVars: function() {
|
||||
return [this.getFieldValue('VAR')];
|
||||
},
|
||||
/**
|
||||
* Notification that a variable is renaming.
|
||||
* If the name matches one of this block's variables, rename it.
|
||||
* @param {string} oldName Previous name of variable.
|
||||
* @param {string} newName Renamed variable.
|
||||
* @this Blockly.Block
|
||||
*/
|
||||
renameVar: function(oldName, newName) {
|
||||
if (Blockly.Names.equals(oldName, this.getFieldValue('VAR'))) {
|
||||
this.setFieldValue(newName, 'VAR');
|
||||
|
||||
Reference in New Issue
Block a user