openct-tasks/_common/modules/ext/scratch/fixes.js

1501 lines
50 KiB
JavaScript

Blockly.createDom_ = function(container, options) {
// Sadly browsers (Chrome vs Firefox) are currently inconsistent in laying
// out content in RTL mode. Therefore Blockly forces the use of LTR,
// then manually positions content in RTL as needed.
container.setAttribute('dir', 'LTR');
// Closure can be trusted to create HTML widgets with the proper direction.
goog.ui.Component.setDefaultRightToLeft(options.RTL);
// Load CSS.
Blockly.Css.inject(options.hasCss, options.pathToMedia);
// Build the SVG DOM.
var svg = Blockly.createSvgElement('svg', {
'xmlns': 'http://www.w3.org/2000/svg',
'xmlns:html': 'http://www.w3.org/1999/xhtml',
'xmlns:xlink': 'http://www.w3.org/1999/xlink',
'version': '1.1',
'class': 'blocklySvg'
}, container);
var defs = Blockly.createSvgElement('defs', {}, svg);
// Each filter/pattern needs a unique ID for the case of multiple Blockly
// instances on a page. Browser behaviour becomes undefined otherwise.
// https://neil.fraser.name/news/2015/11/01/
// TODO (tmickel): Look into whether block highlighting still works.
// Reference commit:
// https://github.com/google/blockly/commit/144be4d49f36fdba260a26edbd170ae75bbc37a6
var rnd = String(Math.random()).substring(2);
// Add embossFilter
var embossFilter = Blockly.createSvgElement('filter',
{'id': 'blocklyEmbossFilter' + rnd}, defs);
Blockly.createSvgElement('feGaussianBlur',
{'in': 'SourceAlpha', 'stdDeviation': 1, 'result': 'blur'}, embossFilter);
var feSpecularLighting = Blockly.createSvgElement('feSpecularLighting',
{'in': 'blur', 'surfaceScale': 1, 'specularConstant': 0.5,
'specularExponent': 10, 'lighting-color': 'white', 'result': 'specOut'},
embossFilter);
Blockly.createSvgElement('fePointLight',
{'x': -5000, 'y': -10000, 'z': 20000}, feSpecularLighting);
Blockly.createSvgElement('feComposite',
{'in': 'specOut', 'in2': 'SourceAlpha', 'operator': 'in',
'result': 'specOut'}, embossFilter);
Blockly.createSvgElement('feComposite',
{'in': 'SourceGraphic', 'in2': 'specOut', 'operator': 'arithmetic',
'k1': 0, 'k2': 1, 'k3': 1, 'k4': 0}, embossFilter);
options.embossFilterId = embossFilter.id;
// Using a dilate distorts the block shape.
// Instead use a gaussian blur, and then set all alpha to 1 with a transfer.
var stackGlowFilter = Blockly.createSvgElement('filter',
{'id': 'blocklyStackGlowFilter',
'height': '160%', 'width': '180%', y: '-30%', x: '-40%'}, defs);
options.stackGlowBlur = Blockly.createSvgElement('feGaussianBlur',
{'in': 'SourceGraphic',
'stdDeviation': Blockly.STACK_GLOW_RADIUS}, stackGlowFilter);
// Set all gaussian blur pixels to 1 opacity before applying flood
var componentTransfer = Blockly.createSvgElement('feComponentTransfer', {'result': 'outBlur'}, stackGlowFilter);
Blockly.createSvgElement('feFuncA',
{'type': 'table', 'tableValues': '0' + ' 1'.repeat(16)}, componentTransfer);
// Color the highlight
Blockly.createSvgElement('feFlood',
{'flood-color': Blockly.Colours.stackGlow,
'flood-opacity': Blockly.Colours.stackGlowOpacity, 'result': 'outColor'}, stackGlowFilter);
Blockly.createSvgElement('feComposite',
{'in': 'outColor', 'in2': 'outBlur',
'operator': 'in', 'result': 'outGlow'}, stackGlowFilter);
Blockly.createSvgElement('feComposite',
{'in': 'SourceGraphic', 'in2': 'outGlow', 'operator': 'over'}, stackGlowFilter);
// Filter for replacement marker
var replacementGlowFilter = Blockly.createSvgElement('filter',
{'id': 'blocklyReplacementGlowFilter',
'height': '160%', 'width': '180%', y: '-30%', x: '-40%'}, defs);
Blockly.createSvgElement('feGaussianBlur',
{'in': 'SourceGraphic',
'stdDeviation': Blockly.REPLACEMENT_GLOW_RADIUS}, replacementGlowFilter);
// Set all gaussian blur pixels to 1 opacity before applying flood
var componentTransfer = Blockly.createSvgElement('feComponentTransfer', {'result': 'outBlur'}, replacementGlowFilter);
Blockly.createSvgElement('feFuncA',
{'type': 'table', 'tableValues': '0' + ' 1'.repeat(16)}, componentTransfer);
// Color the highlight
Blockly.createSvgElement('feFlood',
{'flood-color': Blockly.Colours.replacementGlow,
'flood-opacity': Blockly.Colours.replacementGlowOpacity, 'result': 'outColor'}, replacementGlowFilter);
Blockly.createSvgElement('feComposite',
{'in': 'outColor', 'in2': 'outBlur',
'operator': 'in', 'result': 'outGlow'}, replacementGlowFilter);
Blockly.createSvgElement('feComposite',
{'in': 'SourceGraphic', 'in2': 'outGlow', 'operator': 'over'}, replacementGlowFilter);
var disabledPattern = Blockly.createSvgElement('pattern',
{'id': 'blocklyDisabledPattern' + rnd,
'patternUnits': 'userSpaceOnUse',
'width': 10, 'height': 10}, defs);
Blockly.createSvgElement('rect',
{'width': 10, 'height': 10, 'fill': '#aaa'}, disabledPattern);
Blockly.createSvgElement('path',
{'d': 'M 0 0 L 10 10 M 10 0 L 0 10', 'stroke': '#cc0'}, disabledPattern);
options.disabledPatternId = disabledPattern.id;
var gridPattern = Blockly.createSvgElement('pattern',
{'id': 'blocklyGridPattern' + rnd,
'patternUnits': 'userSpaceOnUse'}, defs);
if (options.gridOptions['length'] > 0 && options.gridOptions['spacing'] > 0) {
Blockly.createSvgElement('line',
{'stroke': options.gridOptions['colour']},
gridPattern);
if (options.gridOptions['length'] > 1) {
Blockly.createSvgElement('line',
{'stroke': options.gridOptions['colour']},
gridPattern);
}
// x1, y1, x1, x2 properties will be set later in updateGridPattern_.
}
options.gridPattern = gridPattern;
return svg;
};
// Fix arguments missing, possibility to silence error message
Blockly.Workspace.prototype.deleteVariable = function(name, silent) {
var workspace = this;
function doDeletion(variableUses, index) {
Blockly.Events.setGroup(true);
for (var i = 0; i < variableUses.length; i++) {
variableUses[i].dispose(true, false);
}
Blockly.Events.setGroup(false);
workspace.variableList.splice(index, 1);
}
var variableIndex = this.variableIndexOf(name);
if (variableIndex != -1) {
// Check whether this variable is a function parameter before deleting.
var uses = this.getVariableUses(name);
for (var i = 0, block; block = uses[i]; i++) {
if ((block.type == 'procedures_defnoreturn' ||
block.type == 'procedures_defreturn') && !silent) {
var procedureName = block.getFieldValue('NAME');
Blockly.alert(
Blockly.Msg.CANNOT_DELETE_VARIABLE_PROCEDURE.
replace('%1', name).
replace('%2', procedureName));
return;
}
}
if (uses.length > 1) {
// Confirm before deleting multiple blocks.
Blockly.confirm(
Blockly.Msg.DELETE_VARIABLE_CONFIRMATION.replace('%1', uses.length).
replace('%2', name),
function(ok) {
if (ok) {
doDeletion(uses, variableIndex);
}
});
} else {
// No confirmation necessary for a single block.
doDeletion(uses, variableIndex);
}
}
};
// Change gap between blocks in the toolbox
Blockly.Flyout.prototype.GAP_Y = 14;
Blockly.Block.prototype.getVariableField = function () {
for(var i=0; i<this.childBlocks_.length; i++) {
if(this.childBlocks_[i].type == 'data_variablemenu') {
return this.childBlocks_[i].getFieldValue('VARIABLE');
}
}
return null;
};
// Add a border when a block is glowing to make it more obvious
Blockly.BlockSvg.prototype.setGlowBlock = function(isGlowingBlock) {
var blockSvg = this.getSvgRoot();
for(var i=0; i<blockSvg.children.length; i++) {
if(blockSvg.children[i].classList[0] == 'blocklyPath') {
blockSvg = blockSvg.children[i];
break;
}
}
blockSvg.style.strokeWidth = isGlowingBlock ? '4px' : '';
this.isGlowingBlock_ = isGlowingBlock;
this.updateColour();
};
// Change behavior when we attach a data_variable along a data_variablemenu
Blockly.Connection.prototype.connect_ = function(childConnection) {
var parentConnection = this;
var parentBlock = parentConnection.getSourceBlock();
var childBlock = childConnection.getSourceBlock();
var isSurroundingC = false;
if (parentConnection == parentBlock.getFirstStatementConnection()) {
isSurroundingC = true;
}
// Disconnect any existing parent on the child connection.
if (childConnection.isConnected()) {
// Scratch-specific behaviour:
// If we're using a c-shaped block to surround a stack, remember where the
// stack used to be connected.
if (isSurroundingC) {
var previousParentConnection = childConnection.targetConnection;
}
childConnection.disconnect();
}
if (parentConnection.isConnected()) {
// Other connection is already connected to something.
// Disconnect it and reattach it or bump it as needed.
var orphanBlock = parentConnection.targetBlock();
if(orphanBlock.type == 'data_variablemenu' && orphanBlock.isShadow()) {
// Special behavior for variables
if(childBlock.type != 'data_variable') {
// Abort
return;
}
try {
// Set the current variable field to the new variable name
var newVarName = childBlock.getVariableField();
var oldVarField = orphanBlock.inputList[0].fieldRow[0];
oldVarField.setValue(newVarName);
// Delete the data_variable which was dragged onto here
setTimeout(function () { childBlock.dispose(); }, 0);
} catch(e) {
// Abort
}
return;
}
var shadowDom = parentConnection.getShadowDom();
// Temporarily set the shadow DOM to null so it does not respawn.
parentConnection.setShadowDom(null);
// Displaced shadow blocks dissolve rather than reattaching or bumping.
if (orphanBlock.isShadow()) {
// Save the shadow block so that field values are preserved.
shadowDom = Blockly.Xml.blockToDom(orphanBlock);
orphanBlock.dispose();
orphanBlock = null;
} else if (parentConnection.type == Blockly.NEXT_STATEMENT) {
// Statement connections.
// Statement blocks may be inserted into the middle of a stack.
// Split the stack.
if (!orphanBlock.previousConnection) {
throw 'Orphan block does not have a previous connection.';
}
// Attempt to reattach the orphan at the bottom of the newly inserted
// block. Since this block may be a stack, walk down to the end.
var newBlock = childBlock;
while (newBlock.nextConnection) {
var nextBlock = newBlock.getNextBlock();
if (nextBlock && !nextBlock.isShadow()) {
newBlock = nextBlock;
} else {
if (orphanBlock.previousConnection.checkType_(
newBlock.nextConnection)) {
newBlock.nextConnection.connect(orphanBlock.previousConnection);
orphanBlock = null;
}
break;
}
}
}
if (orphanBlock) {
// Unable to reattach orphan.
parentConnection.disconnect();
if (Blockly.Events.recordUndo) {
// Bump it off to the side after a moment.
var group = Blockly.Events.getGroup();
setTimeout(function() {
// Verify orphan hasn't been deleted or reconnected (user on meth).
if (orphanBlock.workspace && !orphanBlock.getParent()) {
Blockly.Events.setGroup(group);
if (orphanBlock.outputConnection) {
orphanBlock.outputConnection.bumpAwayFrom_(parentConnection);
} else if (orphanBlock.previousConnection) {
orphanBlock.previousConnection.bumpAwayFrom_(parentConnection);
}
Blockly.Events.setGroup(false);
}
}, Blockly.BUMP_DELAY);
}
}
// Restore the shadow DOM.
parentConnection.setShadowDom(shadowDom);
}
if (isSurroundingC && previousParentConnection) {
previousParentConnection.connect(parentBlock.previousConnection);
}
var event;
if (Blockly.Events.isEnabled()) {
event = new Blockly.Events.Move(childBlock);
}
// Establish the connections.
Blockly.Connection.connectReciprocally_(parentConnection, childConnection);
// Demote the inferior block so that one is a child of the superior one.
childBlock.setParent(parentBlock);
if (event) {
event.recordNew();
Blockly.Events.fire(event);
}
};
Blockly.Workspace.prototype.getFlyout = function () { return null; };
Blockly.Workspace.prototype.remainingCapacity = function(maxBlocks) {
if (!maxBlocks) {
maxBlocks = this.maxBlocks();
if (!maxBlocks) {
return Infinity;
}
}
// Count number of blocks
var blocks = this.getAllBlocks();
var blockCount = 0;
for (var b = 0; b < blocks.length; b++) {
var block = blocks[b];
// Counting is tricky because some blocks in Scratch don't count in Blockly
if(block.parentBlock_) {
// There's a parent (container) block
if((block.type == 'math_number' && block.parentBlock_.type == 'control_repeat') ||
(block.type == 'data_variablemenu' &&
(block.parentBlock_.type == 'data_variable' ||
block.parentBlock_.type == 'data_setvariableto' ||
block.parentBlock_.type == 'data_changevariableby'))) {
continue;
}
} else {
if(block.type == 'data_variablemenu') {
continue;
}
}
if(block.type == 'data_itemoflist' || block.type == 'data_replaceitemoflist') {
// Count one extra for these ones
blockCount += 1;
}
blockCount += 1;
}
return maxBlocks - blockCount;
};
// Pass to this.clear that we are deleting the workspace
Blockly.Workspace.prototype.dispose = function() {
this.listeners_.length = 0;
this.clear(true);
// Remove from workspace database.
delete Blockly.Workspace.WorkspaceDB_[this.id];
};
Blockly.WorkspaceSvg.prototype.clear = function(deleting) {
this.setResizesEnabled(false);
Blockly.WorkspaceSvg.superClass_.clear.call(this);
if(!deleting) { // Do not try to resize if we're deleting the workspace
this.setResizesEnabled(true);
}
};
// Prevent the workspace from shifting when we create a new block (especially
// with categories enabled)
Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox_ = Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox;
Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox = function() {
var originalBbox = Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox_.apply(this, arguments);
originalBbox.x = 0;
return originalBbox;
}
// Put the padding to 0 to avoid issues with clicks getting misplaced
Blockly.DropDownDiv.PADDING_Y = 0;
// Move the dropdown slightly higher to make its target clearer
Blockly.DropDownDiv.getPositionMetrics_ = Blockly.DropDownDiv.getPositionMetrics;
Blockly.DropDownDiv.getPositionMetrics = function () {
var originalPos = Blockly.DropDownDiv.getPositionMetrics_.apply(this, arguments);
originalPos.initialY -= 20;
originalPos.finalY -= 20;
return originalPos;
}
Blockly.WorkspaceSvg.prototype.renameVariable = function(oldName, newName) {
Blockly.WorkspaceSvg.superClass_.renameVariable.call(this, oldName, newName);
// Don't refresh the toolbox if there's a drag in progress.
if (this.toolbox_ && this.toolbox_.flyout_ && !Blockly.Flyout.startFlyout_) {
this.toolbox_.refreshSelection();
}
}
/**
* Check if 3D transforms are supported by adding an element
* and attempting to set the property.
* @return {boolean} true if 3D transforms are supported
*/
Blockly.is3dSupported = function() {
if (Blockly.cache3dSupported_ !== null) {
return Blockly.cache3dSupported_;
}
// CC-BY-SA Lorenzo Polidori
// https://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
if (!window.getComputedStyle) {
return false;
}
try {
var el = document.createElement('p'),
has3d,
transforms = {
'webkitTransform': '-webkit-transform',
'OTransform': '-o-transform',
'msTransform': '-ms-transform',
'MozTransform': '-moz-transform',
'transform': 'transform'
};
// Add it to the body to get the computed style.
document.body.insertBefore(el, null);
for (var t in transforms) {
if (el.style[t] !== undefined) {
el.style[t] = 'translate3d(1px,1px,1px)';
has3d = window.getComputedStyle(el).getPropertyValue(transforms[t]);
}
}
document.body.removeChild(el);
Blockly.cache3dSupported_ = (has3d !== undefined && has3d.length > 0 && has3d !== "none");
} catch (e) {
Blockly.cache3dSupported_ = false;
}
return Blockly.cache3dSupported_;
};
Blockly.FieldTextInput.prototype.oldShowEditor_ = Blockly.FieldTextInput.prototype.showEditor_;
Blockly.FieldTextInput.prototype.showEditor_ = function() {
var mobile =
goog.userAgent.MOBILE || goog.userAgent.ANDROID || goog.userAgent.IPAD;
if(mobile) {
// Display a prompt on mobile, as Blockly does
var newValue = prompt
var newValue = window.prompt(Blockly.Msg.CHANGE_VALUE_TITLE, this.text_);
if (this.sourceBlock_) {
newValue = this.callValidator(newValue);
}
this.setValue(newValue);
} else {
Blockly.FieldTextInput.prototype.oldShowEditor_.apply(this, arguments);
}
}
Blockly.Colours['input'] = {
'primary': '#891431',
'secondary': '#840A28',
'tertiary': '#630D23'};
Blockly.Colours['texts'] = {
'primary': '#18BC85',
'secondary': '#0DA572',
'tertiary': '#128E65'};
Blockly.Blocks['control_repeat'] = {
/**
* Block for repeat n times (external number).
* https://blockly-demo.appspot.com/static/demos/blockfactory/index.html#so57n9
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"id": "control_repeat",
"message0": Blockly.Msg.CONTROLS_REPEAT_TITLE,
"message1": "%1", // Statement
"message2": "%1", // Icon
"lastDummyAlign2": "RIGHT",
"args0": [
{
"type": "input_value",
"name": "TIMES"
}
],
"args1": [
{
"type": "input_statement",
"name": "SUBSTACK"
}
],
"args2": [
{
"type": "field_image",
"src": Blockly.mainWorkspace.options.pathToMedia + "c_arrow.svg",
"width": 16,
"height": 16,
"alt": "*",
"flip_rtl": true
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.control,
"colour": Blockly.Colours.control.primary,
"colourSecondary": Blockly.Colours.control.secondary,
"colourTertiary": Blockly.Colours.control.tertiary
});
}
};
Blockly.Blocks['control_if'] = {
/**
* Block for if-then.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"type": "control_if",
"message0": Blockly.Msg.CONTROLS_IF_MSG_IF+" %1 "+Blockly.Msg.CONTROLS_REPEAT_INPUT_DO,
"message1": "%1", // Statement
"args0": [
{
"type": "input_value",
"name": "CONDITION",
"check": "Boolean"
}
],
"args1": [
{
"type": "input_statement",
"name": "SUBSTACK"
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.control,
"colour": Blockly.Colours.control.primary,
"colourSecondary": Blockly.Colours.control.secondary,
"colourTertiary": Blockly.Colours.control.tertiary
});
}
};
Blockly.Blocks['control_if_else'] = {
/**
* Block for if-else.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"type": "control_if_else",
"message0": Blockly.Msg.CONTROLS_IF_MSG_IF+" %1 "+Blockly.Msg.CONTROLS_REPEAT_INPUT_DO,
"message1": "%1",
"message2": Blockly.Msg.CONTROLS_IF_MSG_ELSE,
"message3": "%1",
"args0": [
{
"type": "input_value",
"name": "CONDITION",
"check": "Boolean"
}
],
"args1": [
{
"type": "input_statement",
"name": "SUBSTACK"
}
],
"args3": [
{
"type": "input_statement",
"name": "SUBSTACK2"
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.control,
"colour": Blockly.Colours.control.primary,
"colourSecondary": Blockly.Colours.control.secondary,
"colourTertiary": Blockly.Colours.control.tertiary
});
}
};
Blockly.Blocks['control_repeat_until'] = {
/**
* Block for repeat until a condition becomes true.
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL+" %1",
"message1": "%1",
"message2": "%1",
"lastDummyAlign2": "RIGHT",
"args0": [
{
"type": "input_value",
"name": "CONDITION",
"check": "Boolean"
}
],
"args1": [
{
"type": "input_statement",
"name": "SUBSTACK"
}
],
"args2": [
{
"type": "field_image",
"src": Blockly.mainWorkspace.options.pathToMedia + "c_arrow.svg",
"width": 16,
"height": 16,
"alt": "*",
"flip_rtl": true
}
],
"inputsInline": true,
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.control,
"colour": Blockly.Colours.control.primary,
"colourSecondary": Blockly.Colours.control.secondary,
"colourTertiary": Blockly.Colours.control.tertiary
});
}
};
// Fix image path
Blockly.Blocks['control_forever'] = {
/**
* Block for repeat n times (external number).
* https://blockly-demo.appspot.com/static/demos/blockfactory/index.html#5eke39
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"id": "control_forever",
"message0": "forever",
"message1": "%1", // Statement
"message2": "%1", // Icon
"lastDummyAlign2": "RIGHT",
"args1": [
{
"type": "input_statement",
"name": "SUBSTACK"
}
],
"args2": [
{
"type": "field_image",
"src": Blockly.mainWorkspace.options.pathToMedia + "c_arrow.svg",
"width": 16,
"height": 16,
"alt": "*",
"flip_rtl": true
}
],
"inputsInline": true,
"previousStatement": null,
"category": Blockly.Categories.control,
"colour": Blockly.Colours.control.primary,
"colourSecondary": Blockly.Colours.control.secondary,
"colourTertiary": Blockly.Colours.control.tertiary
});
}
};
Blockly.Blocks['operator_not'] = {
/**
* Block for "not" unary boolean operator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.LOGIC_NEGATE_TITLE,
"args0": [
{
"type": "input_value",
"name": "OPERAND",
"check": "Boolean"
}
],
"inputsInline": true,
"output": "Boolean",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_HEXAGONAL
});
}
};
// Fix title
Blockly.Blocks['data_replaceitemoflist'] = {
/**
* Block to insert item to list.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.DATA_REPLACEITEMOFLIST_TITLE,
"args0": [
{
"type": "input_value",
"name": "INDEX"
},
{
"type": "field_variable",
"name": "LIST"
},
{
"type": "input_value",
"name": "ITEM"
}
],
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.data,
"colour": Blockly.Colours.data.primary,
"colourSecondary": Blockly.Colours.data.secondary,
"colourTertiary": Blockly.Colours.data.tertiary
});
}
};
// Fix title
Blockly.Blocks['data_itemoflist'] = {
init: function() {
this.jsonInit({
"message0": Blockly.Msg.DATA_ITEMOFLIST_TITLE,
"args0": [
{
"type": "input_value",
"name": "INDEX"
},
{
"type": "field_variable",
"name": "LIST"
}
],
"output": null,
"category": Blockly.Categories.data,
"colour": Blockly.Colours.data.primary,
"colourSecondary": Blockly.Colours.data.secondary,
"colourTertiary": Blockly.Colours.data.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_ROUND
});
}
};
// Create list from repetition of item
Blockly.Blocks['data_listrepeat'] = {
init: function() {
this.jsonInit({
"message0": Blockly.Msg.DATA_LISTREPEAT_TITLE,
"args0": [
{
"type": "field_variable",
"name": "LIST"
},
{
"type": "input_value",
"name": "ITEM"
},
{
"type": "input_value",
"name": "TIMES"
}
],
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.data,
"colour": Blockly.Colours.data.primary,
"colourSecondary": Blockly.Colours.data.secondary,
"colourTertiary": Blockly.Colours.data.tertiary
});
}
};
Blockly.Blocks['data_setvariableto'] = {
/**
* Block to set variable to a certain value
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.VARIABLES_SET,
"args0": [
{
"type": "input_value",
"name": "VARIABLE"
},
{
"type": "input_value",
"name": "VALUE"
}
],
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.data,
"colour": Blockly.Colours.data.primary,
"colourSecondary": Blockly.Colours.data.secondary,
"colourTertiary": Blockly.Colours.data.tertiary
});
}
};
Blockly.Blocks['data_changevariableby'] = {
/**
* Block to change variable by a certain value
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.MATH_CHANGE_TITLE,
"args0": [
{
"type": "input_value",
"name": "VARIABLE"
},
{
"type": "input_value",
"name": "VALUE"
}
],
"previousStatement": null,
"nextStatement": null,
"category": Blockly.Categories.data,
"colour": Blockly.Colours.data.primary,
"colourSecondary": Blockly.Colours.data.secondary,
"colourTertiary": Blockly.Colours.data.tertiary
});
}
};
Blockly.Blocks['operator_and'] = {
/**
* Block for "and" boolean comparator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": "%1 "+Blockly.Msg.LOGIC_OPERATION_AND+" %2",
"args0": [
{
"type": "input_value",
"name": "OPERAND1",
"check": "Boolean"
},
{
"type": "input_value",
"name": "OPERAND2",
"check": "Boolean"
}
],
"inputsInline": true,
"output": "Boolean",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_HEXAGONAL
});
}
};
Blockly.Blocks['operator_or'] = {
/**
* Block for "or" boolean comparator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": "%1 "+Blockly.Msg.LOGIC_OPERATION_OR+" %2",
"args0": [
{
"type": "input_value",
"name": "OPERAND1",
"check": "Boolean"
},
{
"type": "input_value",
"name": "OPERAND2",
"check": "Boolean"
}
],
"inputsInline": true,
"output": "Boolean",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_HEXAGONAL
});
}
};
Blockly.Blocks['operator_join'] = {
/**
* Block for string join operator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN+" %1 %2",
"args0": [
{
"type": "input_value",
"name": "STRING1"
},
{
"type": "input_value",
"name": "STRING2"
}
],
"inputsInline": true,
"output": "String",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_ROUND
});
}
};
Blockly.Blocks['operator_dividefloor'] = {
/**
* Block for getting the whole part of dividing two numbers.
* @this Blockly.Block
*/
init: function() {
this.jsonInit(
{
"message0": "%1 // %2",
"args0": [
{
"type": "input_value",
"name": "NUM1"
},
{
"type": "input_value",
"name": "NUM2"
}
],
"inputsInline": true,
"output": "Number",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_ROUND
});
}
};
Blockly.Blocks['operator_lte'] = {
/**
* Block for less than or equal comparator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": "%1 ≤ %2",
"args0": [
{
"type": "input_value",
"name": "OPERAND1"
},
{
"type": "input_value",
"name": "OPERAND2"
}
],
"inputsInline": true,
"output": "Boolean",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_HEXAGONAL
});
}
};
Blockly.Blocks['operator_gte'] = {
/**
* Block for greater than or equal comparator.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": "%1 ≥ %2",
"args0": [
{
"type": "input_value",
"name": "OPERAND1"
},
{
"type": "input_value",
"name": "OPERAND2"
}
],
"inputsInline": true,
"output": "Boolean",
"category": Blockly.Categories.operators,
"colour": Blockly.Colours.operators.primary,
"colourSecondary": Blockly.Colours.operators.secondary,
"colourTertiary": Blockly.Colours.operators.tertiary,
"outputShape": Blockly.OUTPUT_SHAPE_HEXAGONAL
});
}
};
Blockly.Blocks['text_print'] = {
/**
* Block for print statement.
* @this Blockly.Block
*/
init: function() {
this.jsonInit({
"message0": Blockly.Msg.TEXT_PRINT_TITLE,
"args0": [
{
"type": "input_value",
"name": "TEXT"
}
],
"previousStatement": null,
"nextStatement": null,
"colour": Blockly.Colours.texts.primary,
"colourSecondary": Blockly.Colours.texts.secondary,
"colourTertiary": Blockly.Colours.texts.tertiary,
"tooltip": Blockly.Msg.TEXT_PRINT_TOOLTIP,
"helpUrl": Blockly.Msg.TEXT_PRINT_HELPURL
});
}
};
Blockly.JavaScript['control_if'] = function(block) {
// If/then condition.
var n = 0;
var argument = Blockly.JavaScript.valueToCode(block, 'CONDITION',
Blockly.JavaScript.ORDER_NONE) || 'false';
var branch = Blockly.JavaScript.statementToCode(block, 'SUBSTACK');
var code = 'if (' + argument + ') {\n' + branch + '}';
return code + '\n';
};
Blockly.JavaScript['control_if_else'] = function(block) {
// If/then/else condition.
var argument = Blockly.JavaScript.valueToCode(block, 'CONDITION',
Blockly.JavaScript.ORDER_NONE) || 'false';
var branch = Blockly.JavaScript.statementToCode(block, 'SUBSTACK');
var branch2 = Blockly.JavaScript.statementToCode(block, 'SUBSTACK2');
var code = 'if (' + argument + ') {\n' + branch + '} else {\n' + branch2 + '}';
return code + '\n';
};
Blockly.JavaScript['control_repeat'] = function(block) {
// Repeat n times.
if (block.getField('TIMES')) {
// Internal number.
var repeats = String(Number(block.getFieldValue('TIMES')));
} else {
// External number.
var repeats = Blockly.JavaScript.valueToCode(block, 'TIMES',
Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
}
var branch = Blockly.JavaScript.statementToCode(block, 'SUBSTACK');
branch = Blockly.JavaScript.addLoopTrap(branch, block.id);
var code = '';
var loopVar = Blockly.JavaScript.variableDB_.getDistinctName(
'count', Blockly.Variables.NAME_TYPE);
var endVar = repeats;
if (!repeats.match(/^\w+$/) && !Blockly.isNumber(repeats)) {
var endVar = Blockly.JavaScript.variableDB_.getDistinctName(
'repeat_end', Blockly.Variables.NAME_TYPE);
code += 'var ' + endVar + ' = ' + repeats + ';\n';
}
code += 'for (var ' + loopVar + ' = 0; ' +
loopVar + ' < ' + endVar + '; ' +
loopVar + '++) {\n' +
branch + '}\n';
return code;
};
Blockly.JavaScript['control_repeat_until'] = function(block) {
// If/then/else condition.
var n = 0;
var argument = Blockly.JavaScript.valueToCode(block, 'CONDITION',
Blockly.JavaScript.ORDER_NONE) || 'false';
var branch = Blockly.JavaScript.statementToCode(block, 'SUBSTACK');
var code = 'while (!(' + argument + ')) {\n' + branch + '}';
return code + '\n';
};
Blockly.JavaScript['operator_not'] = function(block) {
var b = Blockly.JavaScript.ORDER_LOGICAL_NOT;
return["!"+ (Blockly.JavaScript.valueToCode(block,"OPERAND",b) || "true"), b]
};
Blockly.JavaScript['data_listrepeat'] = function(block) {
// Create a list with one element repeated.
Blockly.JavaScript.externalFunctions['listsRepeat'] = function(value, n) {
if(n > FioiBlockly.maxListSize) {
throw Blockly.Msg.LISTS_CREATE_WITH_TOO_LARGE.replace('%1', n).replace('%2', FioiBlockly.maxListSize);
}
var array = [];
for (var i = 0; i < n; i++) {
array[i] = value;
}
return array;
};
var element = Blockly.JavaScript.valueToCode(block, 'ITEM',
Blockly.JavaScript.ORDER_COMMA) || 'null';
var repeatCount = Blockly.JavaScript.valueToCode(block, 'TIMES',
Blockly.JavaScript.ORDER_COMMA) || '0';
var code = 'listsRepeat(' + element + ', ' + repeatCount + ')';
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var assignCode = 'var ' + varName + ' = ' + code + ';\n';
// Report value if available
var reportCode = "reportBlockValue('" + block.id + "', '" + varName + " = ' + " + varName + ");\n";
return assignCode + reportCode;
};
Blockly.JavaScript['data_itemoflist'] = function(block) {
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var at = Blockly.JavaScript.getAdjusted(block, 'INDEX');
var code = varName + '[' + at + ']';
return [code, Blockly.JavaScript.ORDER_MEMBER];
};
Blockly.JavaScript['data_replaceitemoflist'] = function(block) {
// Set element at index.
// Note: Until February 2013 this block did not have MODE or WHERE inputs.
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var value = Blockly.JavaScript.valueToCode(block, 'ITEM',
Blockly.JavaScript.ORDER_ASSIGNMENT) || 'null';
var at = Blockly.JavaScript.getAdjusted(block, 'INDEX');
code = 'if(' + at + ' > 1000000) { throw "List index > 1000000"; }\n';
code += varName + '[' + at + '] = ' + value + ';\n';
return code;
};
Blockly.JavaScript['data_variable'] = function(block) {
// Variable getter.
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
return [varName, Blockly.JavaScript.ORDER_ATOMIC];
};
Blockly.JavaScript['data_setvariableto'] = function(block) {
// Variable setter.
if (block.getField("VALUE")) {
var argument0 = String(Number(block.getFieldValue("VALUE")));
} else {
var argument0 = Blockly.JavaScript.valueToCode(block, "VALUE", Blockly.JavaScript.ORDER_ASSIGNMENT) || "0";
}
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var assignCode = 'var ' + varName + ' = ' + argument0 + ';\n';
// Report value if available
var reportCode = "reportBlockValue('" + block.id + "', '" + varName + " = ' + " + varName + ");\n";
return assignCode + reportCode;
};
Blockly.JavaScript['data_changevariableby'] = function(block) {
// Increment
var argument0 = Blockly.JavaScript.valueToCode(block, 'VALUE',
Blockly.JavaScript.ORDER_ASSIGNMENT) || '0';
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var incrCode = varName + ' += ' + argument0 + ';\n';
// Report value if available
var reportCode = "reportBlockValue('" + block.id + "', '" + varName + " = ' + " + varName + ");\n";
return incrCode + reportCode;
};
Blockly.JavaScript['operators'] = function(block) {
// Generator for all operators
var nameToOp = {
'operator_add': {op: '+', varname: 'NUM', order: Blockly.JavaScript.ORDER_ADDITION},
'operator_subtract': {op: '-', varname: 'NUM', order: Blockly.JavaScript.ORDER_SUBTRACTION},
'operator_multiply': {op: '*', varname: 'NUM', order: Blockly.JavaScript.ORDER_MULTIPLICATION},
'operator_divide': {op: '/', varname: 'NUM', order: Blockly.JavaScript.ORDER_DIVISION},
'operator_equals': {op: '==', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_EQUALITY},
'operator_gt': {op: '>', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_RELATIONAL},
'operator_gte': {op: '>=', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_RELATIONAL},
'operator_lt': {op: '<', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_RELATIONAL},
'operator_lte': {op: '<=', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_RELATIONAL},
'operator_and': {op: '&&', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_LOGICAL_AND},
'operator_or': {op: '||', varname: 'OPERAND', order: Blockly.JavaScript.ORDER_LOGICAL_OR}
};
var opInfo = nameToOp[block.type];
var argument0 = Blockly.JavaScript.valueToCode(block, opInfo.varname+'1', opInfo.order) || '0';
if(argument0 == 'NaN') { argument0 = '0'; };
var argument1 = Blockly.JavaScript.valueToCode(block, opInfo.varname+'2', opInfo.order) || '0';
if(argument1 == 'NaN') { argument1 = '0'; };
var code = argument0 + ' ' + opInfo.op + ' ' + argument1;
return [code, opInfo.order];
}
Blockly.JavaScript['operator_add'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_subtract'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_multiply'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_divide'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_equals'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_gt'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_gte'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_lt'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_lte'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_and'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_or'] = Blockly.JavaScript['operators'];
Blockly.JavaScript['operator_dividefloor'] = function(block) {
var argument0 = Blockly.JavaScript.valueToCode(block, 'NUM1', Blockly.JavaScript.ORDER_DIVISION) || '0';
if(argument0 == 'NaN') { argument0 = '0'; };
var argument1 = Blockly.JavaScript.valueToCode(block, 'NUM2', Blockly.JavaScript.ORDER_DIVISION) || '0';
if(argument1 == 'NaN') { argument1 = '0'; };
var code = 'Math.floor(' + argument0 + ' / ' + argument1 + ')';
return [code, Blockly.JavaScript.ORDER_FUNCTION_CALL];
}
Blockly.JavaScript['operator_join'] = function(block) {
var argument0 = Blockly.JavaScript.valueToCode(block, 'STRING1', Blockly.JavaScript.ORDER_NONE) || '';
if(argument0 == 'NaN') { argument0 = ''; };
var argument1 = Blockly.JavaScript.valueToCode(block, 'STRING2', Blockly.JavaScript.ORDER_NONE) || '';
if(argument1 == 'NaN') { argument1 = ''; };
var code = 'String(' + argument0 + ') + String(' + argument1 + ')';
return [code, Blockly.JavaScript.ORDER_ADDITION];
}
Blockly.JavaScript['text'] = function(block) {
// Text value. Output an integer if the content is an int, as Scratch is
// ambiguous on these fields.
var val = block.getFieldValue('TEXT');
if(val.search(/^-?\d+\.?\d*$/) < 0) {
// string
var code = Blockly.JavaScript.quote_(val);
} else {
// float
var code = val;
}
return [code, Blockly.JavaScript.ORDER_ATOMIC];
};
Blockly.Python['control_if'] = function(block) {
var argument = Blockly.Python.valueToCode(block, 'CONDITION',
Blockly.Python.ORDER_NONE) || 'False';
var branch = Blockly.Python.statementToCode(block, 'SUBSTACK') ||
Blockly.Python.PASS;
var code = 'if ' + argument + ':\n' + branch;
return code;
}
Blockly.Python['control_if_else'] = function(block) {
var argument = Blockly.Python.valueToCode(block, 'CONDITION',
Blockly.Python.ORDER_NONE) || 'False';
var branch = Blockly.Python.statementToCode(block, 'SUBSTACK') ||
Blockly.Python.PASS;
var code = 'if ' + argument + ':\n' + branch;
branch = Blockly.Python.statementToCode(block, 'SUBSTACK2') ||
Blockly.Python.PASS;
code += 'else:\n' + branch;
return code;
}
Blockly.Python['control_repeat'] = function(block) {
// Repeat n times.
if (block.getField('TIMES')) {
// Internal number.
var repeats = String(parseInt(block.getFieldValue('TIMES'), 10));
} else {
// External number.
var repeats = Blockly.Python.valueToCode(block, 'TIMES',
Blockly.Python.ORDER_NONE) || '0';
}
if (Blockly.isNumber(repeats)) {
repeats = parseInt(repeats, 10);
} else {
repeats = 'int(' + repeats + ')';
}
var branch = Blockly.Python.statementToCode(block, 'SUBSTACK');
branch = Blockly.Python.addLoopTrap(branch, block.id) ||
Blockly.Python.PASS;
var loopVar = Blockly.Python.variableDB_.getDistinctName(
'count', Blockly.Variables.NAME_TYPE);
var code = 'for ' + loopVar + ' in range(' + repeats + '):\n' + branch;
return code;
}
Blockly.Python['control_repeat_until'] = function(block) {
var argument0 = Blockly.Python.valueToCode(block, 'CONDITION',
Blockly.Python.ORDER_LOGICAL_NOT) || 'False';
var branch = Blockly.Python.statementToCode(block, 'SUBSTACK');
branch = Blockly.Python.addLoopTrap(branch, block.id) ||
Blockly.Python.PASS;
return 'while not ' + argument0 + ':\n' + branch;
}
Blockly.Python['operator_not'] = function(block) {
var b = Blockly.Python.ORDER_LOGICAL_NOT;
return["not "+ (Blockly.Python.valueToCode(block, "OPERAND", b) || "True"), b]
}
Blockly.Python['data_listrepeat'] = function(block) {
// Create a list with one element repeated.
var item = Blockly.Python.valueToCode(block, 'ITEM',
Blockly.Python.ORDER_NONE) || 'None';
var times = Blockly.Python.valueToCode(block, 'TIMES',
Blockly.Python.ORDER_MULTIPLICATIVE) || '0';
var code = '[' + item + '] * (' + times + ')';
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.JavaScript.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
return varName + ' = ' + code + '\n';
}
Blockly.Python['data_itemoflist'] = function(block) {
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.Python.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
var at = Blockly.Python.getAdjustedInt(block, 'INDEX');
var code = varName + '[' + at + ']';
return [code, Blockly.Python.ORDER_MEMBER];
}
Blockly.Python['data_replaceitemoflist'] = function(block) {
var blockVarName = block.getFieldValue('LIST');
if(blockVarName) {
var varName = Blockly.Python.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
// TODO :: make it an option
/* Blockly.Python.definitions_['lists_assignIndex'] = '' +
'def assignIndex(l, i, x):\n' +
' if i > 1000000:\n' +
' raise IndexError("list index > 1000000")\n' +
' n = len(l)\n' +
' if i >= n:\n' +
' l.extend([None]*(i-n+1))\n' +
' l[i] = x\n';*/
var value = Blockly.Python.valueToCode(block, 'ITEM',
Blockly.Python.ORDER_ASSIGNMENT) || 'null';
var at = Blockly.Python.getAdjustedInt(block, 'INDEX');
// return 'assignIndex(' + varName + ', ' + at + ', ' + value + ')\n';
return varName + '[' + at + '] = ' + value + '\n';
}
Blockly.Python['data_variable'] = function(block) {
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.Python.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
return [varName, Blockly.Python.ORDER_ATOMIC];
}
Blockly.Python['data_setvariableto'] = function(block) {
if (block.getField("VALUE")) {
var argument0 = String(Number(block.getFieldValue("VALUE")));
} else {
var argument0 = Blockly.Python.valueToCode(block, "VALUE", Blockly.Python.ORDER_ASSIGNMENT) || "0";
}
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.Python.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
return varName + ' = ' + argument0 + ';\n';
}
Blockly.Python['data_changevariableby'] = function(block) {
var argument0 = Blockly.Python.valueToCode(block, 'VALUE',
Blockly.Python.ORDER_ASSIGNMENT) || '0';
var blockVarName = block.getVariableField();
if(blockVarName) {
var varName = Blockly.Python.variableDB_.getName(blockVarName, Blockly.Variables.NAME_TYPE);
} else {
var varName = 'unnamed_variable'; // Block is still loading
}
return varName + ' += ' + argument0 + ';\n';
}
Blockly.Python['text'] = function(block) {
var val = block.getFieldValue('TEXT');
if(val.search(/^-?\d+\.?\d*$/) < 0) {
// string
var code = Blockly.Python.quote_(val);
} else {
// float
var code = val;
}
return [code, Blockly.Python.ORDER_ATOMIC];
}
Blockly.Python['operators'] = function(block) {
var nameToOp = {
'operator_add': {op: '+', varname: 'NUM', order: Blockly.Python.ORDER_ADDITIVE},
'operator_subtract': {op: '-', varname: 'NUM', order: Blockly.Python.ORDER_ADDITIVE},
'operator_multiply': {op: '*', varname: 'NUM', order: Blockly.Python.ORDER_MULTIPLICATIVE},
'operator_divide': {op: '/', varname: 'NUM', order: Blockly.Python.ORDER_MULTIPLICATIVE},
'operator_dividefloor': {op: '//', varname: 'NUM', order: Blockly.Python.ORDER_MULTIPLICATIVE},
'operator_equals': {op: '==', varname: 'OPERAND', order: Blockly.Python.ORDER_RELATIONAL},
'operator_gt': {op: '>', varname: 'OPERAND', order: Blockly.Python.ORDER_RELATIONAL},
'operator_gte': {op: '>=', varname: 'OPERAND', order: Blockly.Python.ORDER_RELATIONAL},
'operator_lt': {op: '<', varname: 'OPERAND', order: Blockly.Python.ORDER_RELATIONAL},
'operator_lte': {op: '<=', varname: 'OPERAND', order: Blockly.Python.ORDER_RELATIONAL},
'operator_and': {op: 'and', varname: 'OPERAND', order: Blockly.Python.ORDER_LOGICAL_AND},
'operator_or': {op: 'or', varname: 'OPERAND', order: Blockly.Python.ORDER_LOGICAL_OR}
};
var opInfo = nameToOp[block.type];
var argument0 = Blockly.Python.valueToCode(block, opInfo.varname+'1', opInfo.order) || '0';
if(argument0 == 'NaN') { argument0 = '0'; };
var argument1 = Blockly.Python.valueToCode(block, opInfo.varname+'2', opInfo.order) || '0';
if(argument1 == 'NaN') { argument1 = '0'; };
var code = argument0 + ' ' + opInfo.op + ' ' + argument1;
return [code, opInfo.order];
}
Blockly.Python['operator_add'] = Blockly.Python['operators'];
Blockly.Python['operator_subtract'] = Blockly.Python['operators'];
Blockly.Python['operator_multiply'] = Blockly.Python['operators'];
Blockly.Python['operator_divide'] = Blockly.Python['operators'];
Blockly.Python['operator_dividefloor'] = Blockly.Python['operators'];
Blockly.Python['operator_equals'] = Blockly.Python['operators'];
Blockly.Python['operator_gt'] = Blockly.Python['operators'];
Blockly.Python['operator_gte'] = Blockly.Python['operators'];
Blockly.Python['operator_lt'] = Blockly.Python['operators'];
Blockly.Python['operator_lte'] = Blockly.Python['operators'];
Blockly.Python['operator_and'] = Blockly.Python['operators'];
Blockly.Python['operator_or'] = Blockly.Python['operators'];
Blockly.Python['operator_join'] = function(block) {
var argument0 = Blockly.Python.valueToCode(block, 'STRING1', Blockly.Python.ORDER_NONE) || '';
if(argument0 == 'NaN') { argument0 = ''; };
var argument1 = Blockly.Python.valueToCode(block, 'STRING2', Blockly.Python.ORDER_NONE) || '';
if(argument1 == 'NaN') { argument1 = ''; };
var code = '"%s%s" % (' + argument0 + ', ' + argument1 + ')';
return [code, Blockly.Python.ORDER_MULTIPLICATIVE];
}