New initial commit with .svn directories and their contents ignored.

This commit is contained in:
ellen.spertus
2013-10-30 14:46:03 -07:00
commit a8acffd81c
754 changed files with 85941 additions and 0 deletions

99
blocks/colour.js Normal file
View File

@@ -0,0 +1,99 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Colour blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.colour');
goog.require('Blockly.Blocks');
Blockly.Blocks['colour_picker'] = {
// Colour picker.
init: function() {
this.setHelpUrl(Blockly.Msg.COLOUR_PICKER_HELPURL);
this.setColour(20);
this.appendDummyInput()
.appendTitle(new Blockly.FieldColour('#ff0000'), 'COLOUR');
this.setOutput(true, 'Colour');
this.setTooltip(Blockly.Msg.COLOUR_PICKER_TOOLTIP);
}
};
Blockly.Blocks['colour_random'] = {
// Random colour.
init: function() {
this.setHelpUrl(Blockly.Msg.COLOUR_RANDOM_HELPURL);
this.setColour(20);
this.appendDummyInput()
.appendTitle(Blockly.Msg.COLOUR_RANDOM_TITLE);
this.setOutput(true, 'Colour');
this.setTooltip(Blockly.Msg.COLOUR_RANDOM_TOOLTIP);
}
};
Blockly.Blocks['colour_rgb'] = {
// Compose a colour from RGB components.
init: function() {
this.setHelpUrl(Blockly.Msg.COLOUR_RGB_HELPURL);
this.setColour(20);
this.appendValueInput('RED')
.setCheck('Number')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_RGB_TITLE)
.appendTitle(Blockly.Msg.COLOUR_RGB_RED);
this.appendValueInput('GREEN')
.setCheck('Number')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_RGB_GREEN);
this.appendValueInput('BLUE')
.setCheck('Number')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_RGB_BLUE);
this.setOutput(true, 'Colour');
this.setTooltip(Blockly.Msg.COLOUR_RGB_TOOLTIP);
}
};
Blockly.Blocks['colour_blend'] = {
// Blend two colours together.
init: function() {
this.setHelpUrl(Blockly.Msg.COLOUR_BLEND_HELPURL);
this.setColour(20);
this.appendValueInput('COLOUR1')
.setCheck('Colour')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_BLEND_TITLE)
.appendTitle(Blockly.Msg.COLOUR_BLEND_COLOUR1);
this.appendValueInput('COLOUR2')
.setCheck('Colour')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_BLEND_COLOUR2);
this.appendValueInput('RATIO')
.setCheck('Number')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.COLOUR_BLEND_RATIO);
this.setOutput(true, 'Colour');
this.setTooltip(Blockly.Msg.COLOUR_BLEND_TOOLTIP);
}
};

499
blocks/lists.js Normal file
View File

@@ -0,0 +1,499 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview List blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.lists');
goog.require('Blockly.Blocks');
Blockly.Blocks['lists_create_empty'] = {
// Create an empty list.
init: function() {
this.setHelpUrl(Blockly.Msg.LISTS_CREATE_EMPTY_HELPURL);
this.setColour(260);
this.setOutput(true, 'Array');
this.appendDummyInput()
.appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
this.setTooltip(Blockly.Msg.LISTS_CREATE_EMPTY_TOOLTIP);
}
};
Blockly.Blocks['lists_create_with'] = {
// Create a list with any number of elements of any type.
init: function() {
this.setColour(260);
this.appendValueInput('ADD0')
.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);
this.appendValueInput('ADD1');
this.appendValueInput('ADD2');
this.setOutput(true, 'Array');
this.setMutator(new Blockly.Mutator(['lists_create_with_item']));
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_TOOLTIP);
this.itemCount_ = 3;
},
mutationToDom: function(workspace) {
var container = document.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(container) {
for (var x = 0; x < this.itemCount_; x++) {
this.removeInput('ADD' + x);
}
this.itemCount_ = parseInt(container.getAttribute('items'), 10);
for (var x = 0; x < this.itemCount_; x++) {
var input = this.appendValueInput('ADD' + x);
if (x == 0) {
input.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);
}
}
if (this.itemCount_ == 0) {
this.appendDummyInput('EMPTY')
.appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
}
},
decompose: function(workspace) {
var containerBlock = new Blockly.Block(workspace,
'lists_create_with_container');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 0; x < this.itemCount_; x++) {
var itemBlock = new Blockly.Block(workspace, 'lists_create_with_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
return containerBlock;
},
compose: function(containerBlock) {
// Disconnect all input blocks and remove all inputs.
if (this.itemCount_ == 0) {
this.removeInput('EMPTY');
} else {
for (var x = this.itemCount_ - 1; x >= 0; x--) {
this.removeInput('ADD' + x);
}
}
this.itemCount_ = 0;
// Rebuild the block's inputs.
var itemBlock = containerBlock.getInputTargetBlock('STACK');
while (itemBlock) {
var input = this.appendValueInput('ADD' + this.itemCount_);
if (this.itemCount_ == 0) {
input.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_INPUT_WITH);
}
// Reconnect any child blocks.
if (itemBlock.valueConnection_) {
input.connection.connect(itemBlock.valueConnection_);
}
this.itemCount_++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
if (this.itemCount_ == 0) {
this.appendDummyInput('EMPTY')
.appendTitle(Blockly.Msg.LISTS_CREATE_EMPTY_TITLE);
}
},
saveConnections: function(containerBlock) {
// Store a pointer to any connected child blocks.
var itemBlock = containerBlock.getInputTargetBlock('STACK');
var x = 0;
while (itemBlock) {
var input = this.getInput('ADD' + x);
itemBlock.valueConnection_ = input && input.connection.targetConnection;
x++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['lists_create_with_container'] = {
// Container.
init: function() {
this.setColour(260);
this.appendDummyInput()
.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TITLE_ADD);
this.appendStatementInput('STACK');
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_CONTAINER_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['lists_create_with_item'] = {
// Add items.
init: function() {
this.setColour(260);
this.appendDummyInput()
.appendTitle(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TITLE);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.LISTS_CREATE_WITH_ITEM_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['lists_repeat'] = {
// Create a list with one element repeated.
init: function() {
this.setHelpUrl(Blockly.Msg.LISTS_REPEAT_HELPURL);
this.setColour(260);
this.setOutput(true, 'Array');
this.interpolateMsg(Blockly.Msg.LISTS_REPEAT_TITLE,
['ITEM', null, Blockly.ALIGN_RIGHT],
['NUM', 'Number', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setTooltip(Blockly.Msg.LISTS_REPEAT_TOOLTIP);
}
};
Blockly.Blocks['lists_length'] = {
// List length.
init: function() {
this.setHelpUrl(Blockly.Msg.LISTS_LENGTH_HELPURL);
this.setColour(260);
this.interpolateMsg(Blockly.Msg.LISTS_LENGTH_TITLE,
['VALUE', ['Array', 'String'], Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setOutput(true, 'Number');
this.setTooltip(Blockly.Msg.LISTS_LENGTH_TOOLTIP);
}
};
Blockly.Blocks['lists_isEmpty'] = {
// Is the list empty?
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)
this.setInputsInline(true);
this.setOutput(true, 'Boolean');
this.setTooltip(Blockly.Msg.LISTS_TOOLTIP);
}
};
Blockly.Blocks['lists_indexOf'] = {
// Find an item in the list.
init: function() {
var OPERATORS =
[[Blockly.Msg.LISTS_INDEX_OF_FIRST, 'FIRST'],
[Blockly.Msg.LISTS_INDEX_OF_LAST, 'LAST']];
this.setHelpUrl(Blockly.Msg.LISTS_INDEX_OF_HELPURL);
this.setColour(260);
this.setOutput(true, 'Number');
this.appendValueInput('VALUE')
.setCheck('Array')
.appendTitle(Blockly.Msg.LISTS_INDEX_OF_INPUT_IN_LIST);
this.appendValueInput('FIND')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'END');
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.LISTS_INDEX_OF_TOOLTIP);
}
};
Blockly.Blocks['lists_getIndex'] = {
// Get element at index.
init: function() {
var MODE =
[[Blockly.Msg.LISTS_GET_INDEX_GET, 'GET'],
[Blockly.Msg.LISTS_GET_INDEX_GET_REMOVE, 'GET_REMOVE'],
[Blockly.Msg.LISTS_GET_INDEX_REMOVE, 'REMOVE']];
this.WHERE_OPTIONS =
[[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],
[Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],
[Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],
[Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],
[Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']];
this.setHelpUrl(Blockly.Msg.LISTS_GET_INDEX_HELPURL);
this.setColour(260);
var modeMenu = new Blockly.FieldDropdown(MODE, function(value) {
var isStatement = (value == 'REMOVE');
this.sourceBlock_.updateStatement(isStatement);
});
this.appendValueInput('VALUE')
.setCheck('Array')
.appendTitle(Blockly.Msg.LISTS_GET_INDEX_INPUT_IN_LIST);
this.appendDummyInput()
.appendTitle(modeMenu, 'MODE')
.appendTitle('', 'SPACE');
this.appendDummyInput('AT');
if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {
this.appendDummyInput('TAIL')
.appendTitle(Blockly.Msg.LISTS_GET_INDEX_TAIL);
}
this.setInputsInline(true);
this.setOutput(true);
this.updateAt(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var combo = thisBlock.getTitleValue('MODE') + '_' +
thisBlock.getTitleValue('WHERE');
return Blockly.Msg['LISTS_GET_INDEX_TOOLTIP_' + combo];
});
},
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);
var isAt = this.getInput('AT').type == Blockly.INPUT_VALUE;
container.setAttribute('at', isAt);
return container;
},
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);
var isAt = (xmlElement.getAttribute('at') != 'false');
this.updateAt(isAt);
},
updateStatement: function(newStatement) {
// Switch between a value block and a statement block.
var oldStatement = !this.outputConnection;
if (newStatement != oldStatement) {
this.unplug(true, true);
if (newStatement) {
this.setOutput(false);
this.setPreviousStatement(true);
this.setNextStatement(true);
} else {
this.setPreviousStatement(false);
this.setNextStatement(false);
this.setOutput(true);
}
}
},
updateAt: function(isAt) {
// Create or delete an input for the numeric index.
// Destroy old 'AT' and 'ORDINAL' inputs.
this.removeInput('AT');
this.removeInput('ORDINAL', true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
this.appendValueInput('AT').setCheck('Number');
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
this.appendDummyInput('ORDINAL')
.appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT');
}
var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt(newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setTitleValue(value, 'WHERE');
return null;
}
return undefined;
});
this.getInput('AT').appendTitle(menu, 'WHERE');
if (Blockly.Msg.LISTS_GET_INDEX_TAIL) {
this.moveInputBefore('TAIL', null);
}
}
};
Blockly.Blocks['lists_setIndex'] = {
// Set element at index.
init: function() {
var MODE =
[[Blockly.Msg.LISTS_SET_INDEX_SET, 'SET'],
[Blockly.Msg.LISTS_SET_INDEX_INSERT, 'INSERT']];
this.WHERE_OPTIONS =
[[Blockly.Msg.LISTS_GET_INDEX_FROM_START, 'FROM_START'],
[Blockly.Msg.LISTS_GET_INDEX_FROM_END, 'FROM_END'],
[Blockly.Msg.LISTS_GET_INDEX_FIRST, 'FIRST'],
[Blockly.Msg.LISTS_GET_INDEX_LAST, 'LAST'],
[Blockly.Msg.LISTS_GET_INDEX_RANDOM, 'RANDOM']];
this.setHelpUrl(Blockly.Msg.LISTS_SET_INDEX_HELPURL);
this.setColour(260);
this.appendValueInput('LIST')
.setCheck('Array')
.appendTitle(Blockly.Msg.LISTS_SET_INDEX_INPUT_IN_LIST);
this.appendDummyInput()
.appendTitle(new Blockly.FieldDropdown(MODE), 'MODE')
.appendTitle('', 'SPACE');
this.appendDummyInput('AT');
this.appendValueInput('TO')
.appendTitle(Blockly.Msg.LISTS_SET_INDEX_INPUT_TO);
this.setInputsInline(true);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.LISTS_SET_INDEX_TOOLTIP);
this.updateAt(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var combo = thisBlock.getTitleValue('MODE') + '_' +
thisBlock.getTitleValue('WHERE');
return Blockly.Msg['LISTS_SET_INDEX_TOOLTIP_' + combo];
});
},
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;
},
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);
},
updateAt: function(isAt) {
// Create or delete an input for the numeric index.
// Destroy old 'AT' and 'ORDINAL' input.
this.removeInput('AT');
this.removeInput('ORDINAL', true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
this.appendValueInput('AT').setCheck('Number');
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
this.appendDummyInput('ORDINAL')
.appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT');
}
var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt(newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setTitleValue(value, 'WHERE');
return null;
}
return undefined;
});
this.moveInputBefore('AT', 'TO');
if (this.getInput('ORDINAL')) {
this.moveInputBefore('ORDINAL', 'TO');
}
this.getInput('AT').appendTitle(menu, 'WHERE');
}
};
Blockly.Blocks['lists_getSublist'] = {
// Get sublist.
init: function() {
this.WHERE_OPTIONS_1 =
[[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_START, 'FROM_START'],
[Blockly.Msg.LISTS_GET_SUBLIST_START_FROM_END, 'FROM_END'],
[Blockly.Msg.LISTS_GET_SUBLIST_START_FIRST, 'FIRST']];
this.WHERE_OPTIONS_2 =
[[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_START, 'FROM_START'],
[Blockly.Msg.LISTS_GET_SUBLIST_END_FROM_END, 'FROM_END'],
[Blockly.Msg.LISTS_GET_SUBLIST_END_LAST, 'LAST']];
this.setHelpUrl(Blockly.Msg.LISTS_GET_SUBLIST_HELPURL);
this.setColour(260);
this.appendValueInput('LIST')
.setCheck('Array')
.appendTitle(Blockly.Msg.LISTS_GET_SUBLIST_INPUT_IN_LIST);
this.appendDummyInput('AT1');
this.appendDummyInput('AT2');
if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {
this.appendDummyInput('TAIL')
.appendTitle(Blockly.Msg.LISTS_GET_SUBLIST_TAIL);
}
this.setInputsInline(true);
this.setOutput(true, 'Array');
this.updateAt(1, true);
this.updateAt(2, true);
this.setTooltip(Blockly.Msg.LISTS_GET_SUBLIST_TOOLTIP);
},
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);
var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE;
container.setAttribute('at2', isAt2);
return container;
},
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);
},
updateAt: function(n, isAt) {
// Create or delete an input for the numeric index.
// Destroy old 'AT' and 'ORDINAL' inputs.
this.removeInput('AT' + n);
this.removeInput('ORDINAL' + n, true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
this.appendValueInput('AT' + n).setCheck('Number');
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
this.appendDummyInput('ORDINAL' + n)
.appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT' + n);
}
var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n],
function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt(n, newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setTitleValue(value, 'WHERE' + n);
return null;
}
return undefined;
});
this.getInput('AT' + n)
.appendTitle(menu, 'WHERE' + n);
if (n == 1) {
this.moveInputBefore('AT1', 'AT2');
if (this.getInput('ORDINAL1')) {
this.moveInputBefore('ORDINAL1', 'AT2');
}
}
if (Blockly.Msg.LISTS_GET_SUBLIST_TAIL) {
this.moveInputBefore('TAIL', null);
}
}
};

350
blocks/logic.js Normal file
View File

@@ -0,0 +1,350 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Logic blocks for Blockly.
* @author q.neutron@gmail.com (Quynh Neutron)
*/
'use strict';
goog.provide('Blockly.Blocks.logic');
goog.require('Blockly.Blocks');
Blockly.Blocks['controls_if'] = {
// If/elseif/else condition.
init: function() {
this.setHelpUrl(Blockly.Msg.CONTROLS_IF_HELPURL);
this.setColour(210);
this.appendValueInput('IF0')
.setCheck('Boolean')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_IF);
this.appendStatementInput('DO0')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setMutator(new Blockly.Mutator(['controls_if_elseif',
'controls_if_else']));
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
if (!thisBlock.elseifCount_ && !thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_1;
} else if (!thisBlock.elseifCount_ && thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_2;
} else if (thisBlock.elseifCount_ && !thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_3;
} else if (thisBlock.elseifCount_ && thisBlock.elseCount_) {
return Blockly.Msg.CONTROLS_IF_TOOLTIP_4;
}
return '';
});
this.elseifCount_ = 0;
this.elseCount_ = 0;
},
mutationToDom: function() {
if (!this.elseifCount_ && !this.elseCount_) {
return null;
}
var container = document.createElement('mutation');
if (this.elseifCount_) {
container.setAttribute('elseif', this.elseifCount_);
}
if (this.elseCount_) {
container.setAttribute('else', 1);
}
return container;
},
domToMutation: function(xmlElement) {
this.elseifCount_ = parseInt(xmlElement.getAttribute('elseif'), 10);
this.elseCount_ = parseInt(xmlElement.getAttribute('else'), 10);
for (var x = 1; x <= this.elseifCount_; x++) {
this.appendValueInput('IF' + x)
.setCheck('Boolean')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);
this.appendStatementInput('DO' + x)
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN);
}
if (this.elseCount_) {
this.appendStatementInput('ELSE')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSE);
}
},
decompose: function(workspace) {
var containerBlock = new Blockly.Block(workspace, 'controls_if_if');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 1; x <= this.elseifCount_; x++) {
var elseifBlock = new Blockly.Block(workspace, 'controls_if_elseif');
elseifBlock.initSvg();
connection.connect(elseifBlock.previousConnection);
connection = elseifBlock.nextConnection;
}
if (this.elseCount_) {
var elseBlock = new Blockly.Block(workspace, 'controls_if_else');
elseBlock.initSvg();
connection.connect(elseBlock.previousConnection);
}
return containerBlock;
},
compose: function(containerBlock) {
// Disconnect the else input blocks and remove the inputs.
if (this.elseCount_) {
this.removeInput('ELSE');
}
this.elseCount_ = 0;
// Disconnect all the elseif input blocks and remove the inputs.
for (var x = this.elseifCount_; x > 0; x--) {
this.removeInput('IF' + x);
this.removeInput('DO' + x);
}
this.elseifCount_ = 0;
// Rebuild the block's optional inputs.
var clauseBlock = containerBlock.getInputTargetBlock('STACK');
while (clauseBlock) {
switch (clauseBlock.type) {
case 'controls_if_elseif':
this.elseifCount_++;
var ifInput = this.appendValueInput('IF' + this.elseifCount_)
.setCheck('Boolean')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSEIF);
var doInput = this.appendStatementInput('DO' + this.elseifCount_);
doInput.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_THEN);
// Reconnect any child blocks.
if (clauseBlock.valueConnection_) {
ifInput.connection.connect(clauseBlock.valueConnection_);
}
if (clauseBlock.statementConnection_) {
doInput.connection.connect(clauseBlock.statementConnection_);
}
break;
case 'controls_if_else':
this.elseCount_++;
var elseInput = this.appendStatementInput('ELSE');
elseInput.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_ELSE);
// Reconnect any child blocks.
if (clauseBlock.statementConnection_) {
elseInput.connection.connect(clauseBlock.statementConnection_);
}
break;
default:
throw 'Unknown block type.';
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
},
saveConnections: function(containerBlock) {
// Store a pointer to any connected child blocks.
var clauseBlock = containerBlock.getInputTargetBlock('STACK');
var x = 1;
while (clauseBlock) {
switch (clauseBlock.type) {
case 'controls_if_elseif':
var inputIf = this.getInput('IF' + x);
var inputDo = this.getInput('DO' + x);
clauseBlock.valueConnection_ =
inputIf && inputIf.connection.targetConnection;
clauseBlock.statementConnection_ =
inputDo && inputDo.connection.targetConnection;
x++;
break;
case 'controls_if_else':
var inputDo = this.getInput('ELSE');
clauseBlock.statementConnection_ =
inputDo && inputDo.connection.targetConnection;
break;
default:
throw 'Unknown block type.';
}
clauseBlock = clauseBlock.nextConnection &&
clauseBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['controls_if_if'] = {
// If condition.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_IF_IF_TITLE_IF);
this.appendStatementInput('STACK');
this.setTooltip(Blockly.Msg.CONTROLS_IF_IF_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['controls_if_elseif'] = {
// Else-If condition.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_IF_ELSEIF_TITLE_ELSEIF);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSEIF_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['controls_if_else'] = {
// Else condition.
init: function() {
this.setColour(210);
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_IF_ELSE_TITLE_ELSE);
this.setPreviousStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_IF_ELSE_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['logic_compare'] = {
// Comparison operator.
init: function() {
if (Blockly.RTL) {
var OPERATORS = [
['=', 'EQ'],
['\u2260', 'NEQ'],
['>', 'LT'],
['\u2265', 'LTE'],
['<', 'GT'],
['\u2264', 'GTE']
];
} else {
var OPERATORS = [
['=', 'EQ'],
['\u2260', 'NEQ'],
['<', 'LT'],
['\u2264', 'LTE'],
['>', 'GT'],
['\u2265', 'GTE']
];
}
this.setHelpUrl(Blockly.Msg.LOGIC_COMPARE_HELPURL);
this.setColour(210);
this.setOutput(true, 'Boolean');
this.appendValueInput('A');
this.appendValueInput('B')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
this.setInputsInline(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var op = thisBlock.getTitleValue('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
};
return TOOLTIPS[op];
});
}
};
Blockly.Blocks['logic_operation'] = {
// Logical operations: 'and', 'or'.
init: function() {
var OPERATORS =
[[Blockly.Msg.LOGIC_OPERATION_AND, 'AND'],
[Blockly.Msg.LOGIC_OPERATION_OR, 'OR']];
this.setHelpUrl(Blockly.Msg.LOGIC_OPERATION_HELPURL);
this.setColour(210);
this.setOutput(true, 'Boolean');
this.appendValueInput('A')
.setCheck('Boolean');
this.appendValueInput('B')
.setCheck('Boolean')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
this.setInputsInline(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var op = thisBlock.getTitleValue('OP');
var TOOLTIPS = {
AND: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_AND,
OR: Blockly.Msg.LOGIC_OPERATION_TOOLTIP_OR
};
return thisBlock.TOOLTIPS[op];
});
}
};
Blockly.Blocks['logic_negate'] = {
// Negation.
init: function() {
this.setHelpUrl(Blockly.Msg.LOGIC_NEGATE_HELPURL);
this.setColour(210);
this.setOutput(true, 'Boolean');
this.interpolateMsg(Blockly.Msg.LOGIC_NEGATE_TITLE,
['BOOL', 'Boolean', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT)
this.setTooltip(Blockly.Msg.LOGIC_NEGATE_TOOLTIP);
}
};
Blockly.Blocks['logic_boolean'] = {
// Boolean data type: true and false.
init: function() {
var BOOLEANS =
[[Blockly.Msg.LOGIC_BOOLEAN_TRUE, 'TRUE'],
[Blockly.Msg.LOGIC_BOOLEAN_FALSE, 'FALSE']];
this.setHelpUrl(Blockly.Msg.LOGIC_BOOLEAN_HELPURL);
this.setColour(210);
this.setOutput(true, 'Boolean');
this.appendDummyInput()
.appendTitle(new Blockly.FieldDropdown(BOOLEANS), 'BOOL');
this.setTooltip(Blockly.Msg.LOGIC_BOOLEAN_TOOLTIP);
}
};
Blockly.Blocks['logic_null'] = {
// Null data type.
init: function() {
this.setHelpUrl(Blockly.Msg.LOGIC_NULL_HELPURL);
this.setColour(210);
this.setOutput(true);
this.appendDummyInput()
.appendTitle(Blockly.Msg.LOGIC_NULL);
this.setTooltip(Blockly.Msg.LOGIC_NULL_TOOLTIP);
}
};
Blockly.Blocks['logic_ternary'] = {
// Ternary operator.
init: function() {
this.setHelpUrl(Blockly.Msg.LOGIC_TERNARY_HELPURL);
this.setColour(210);
this.appendValueInput('IF')
.setCheck('Boolean')
.appendTitle(Blockly.Msg.LOGIC_TERNARY_CONDITION);
this.appendValueInput('THEN')
.appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_TRUE);
this.appendValueInput('ELSE')
.appendTitle(Blockly.Msg.LOGIC_TERNARY_IF_FALSE);
this.setOutput(true);
this.setTooltip(Blockly.Msg.LOGIC_TERNARY_TOOLTIP);
}
};

224
blocks/loops.js Normal file
View File

@@ -0,0 +1,224 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Loop blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.loops');
goog.require('Blockly.Blocks');
Blockly.Blocks['controls_repeat'] = {
// Repeat n times (internal number).
init: function() {
this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);
this.setColour(120);
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_REPEAT_TITLE_REPEAT)
.appendTitle(new Blockly.FieldTextInput('10',
Blockly.FieldTextInput.nonnegativeIntegerValidator), 'TIMES')
.appendTitle(Blockly.Msg.CONTROLS_REPEAT_TITLE_TIMES);
this.appendStatementInput('DO')
.appendTitle(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP);
}
};
Blockly.Blocks['controls_repeat_ext'] = {
// Repeat n times (external number).
init: function() {
this.setHelpUrl(Blockly.Msg.CONTROLS_REPEAT_HELPURL);
this.setColour(120);
this.interpolateMsg(Blockly.Msg.CONTROLS_REPEAT_TITLE,
['TIMES', 'Number', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.appendStatementInput('DO')
.appendTitle(Blockly.Msg.CONTROLS_REPEAT_INPUT_DO);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.CONTROLS_REPEAT_TOOLTIP);
}
};
Blockly.Blocks['controls_whileUntil'] = {
// Do while/until loop.
init: function() {
var OPERATORS =
[[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_WHILE, 'WHILE'],
[Blockly.Msg.CONTROLS_WHILEUNTIL_OPERATOR_UNTIL, 'UNTIL']];
this.setHelpUrl(Blockly.Msg.CONTROLS_WHILEUNTIL_HELPURL);
this.setColour(120);
this.appendValueInput('BOOL')
.setCheck('Boolean')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'MODE');
this.appendStatementInput('DO')
.appendTitle(Blockly.Msg.CONTROLS_WHILEUNTIL_INPUT_DO);
this.setPreviousStatement(true);
this.setNextStatement(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var op = thisBlock.getTitleValue('MODE');
var TOOLTIPS = {
WHILE: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_WHILE,
UNTIL: Blockly.Msg.CONTROLS_WHILEUNTIL_TOOLTIP_UNTIL
};
return TOOLTIPS[op];
});
}
};
Blockly.Blocks['controls_for'] = {
// For loop.
init: function() {
this.setHelpUrl(Blockly.Msg.CONTROLS_FOR_HELPURL);
this.setColour(120);
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_FOR_INPUT_WITH)
.appendTitle(new Blockly.FieldVariable(null), 'VAR');
this.interpolateMsg(Blockly.Msg.CONTROLS_FOR_INPUT_FROM_TO_BY,
['FROM', 'Number', Blockly.ALIGN_RIGHT],
['TO', 'Number', Blockly.ALIGN_RIGHT],
['BY', 'Number', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.appendStatementInput('DO')
.appendTitle(Blockly.Msg.CONTROLS_FOR_INPUT_DO);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setInputsInline(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return Blockly.Msg.CONTROLS_FOR_TOOLTIP.replace('%1',
thisBlock.getTitleValue('VAR'));
});
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
},
customContextMenu: function(options) {
var option = {enabled: true};
var name = this.getTitleValue('VAR');
option.text = Blockly.Msg.VARIABLES_SET_CREATE_GET.replace('%1', name);
var xmlTitle = goog.dom.createDom('title', null, name);
xmlTitle.setAttribute('name', 'VAR');
var xmlBlock = goog.dom.createDom('block', null, xmlTitle);
xmlBlock.setAttribute('type', 'variables_get');
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
options.push(option);
}
};
Blockly.Blocks['controls_forEach'] = {
// For each loop.
init: function() {
this.setHelpUrl(Blockly.Msg.CONTROLS_FOREACH_HELPURL);
this.setColour(120);
this.appendValueInput('LIST')
.setCheck('Array')
.appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_ITEM)
.appendTitle(new Blockly.FieldVariable(null), 'VAR')
.appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST);
if (Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL) {
this.appendDummyInput()
.appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_INLIST_TAIL);
this.setInputsInline(true);
}
this.appendStatementInput('DO')
.appendTitle(Blockly.Msg.CONTROLS_FOREACH_INPUT_DO);
this.setPreviousStatement(true);
this.setNextStatement(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return Blockly.Msg.CONTROLS_FOREACH_TOOLTIP.replace('%1',
thisBlock.getTitleValue('VAR'));
});
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
},
customContextMenu: Blockly.Blocks['controls_for'].customContextMenu
};
Blockly.Blocks['controls_flow_statements'] = {
// Flow statements: continue, break.
init: function() {
var OPERATORS =
[[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_BREAK, 'BREAK'],
[Blockly.Msg.CONTROLS_FLOW_STATEMENTS_OPERATOR_CONTINUE, 'CONTINUE']];
this.setHelpUrl(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_HELPURL);
this.setColour(120);
this.appendDummyInput()
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'FLOW');
this.setPreviousStatement(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var op = thisBlock.getTitleValue('FLOW');
var TOOLTIPS = {
BREAK: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_BREAK,
CONTINUE: Blockly.Msg.CONTROLS_FLOW_STATEMENTS_TOOLTIP_CONTINUE
};
return thisBlock.TOOLTIPS[op];
});
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
var legal = false;
// Is the block nested in a control statement?
var block = this;
do {
if (block.type == 'controls_repeat' ||
block.type == 'controls_repeat_ext' ||
block.type == 'controls_forEach' ||
block.type == 'controls_for' ||
block.type == 'controls_whileUntil') {
legal = true;
break;
}
block = block.getSurroundParent();
} while (block);
if (legal) {
this.setWarningText(null);
} else {
this.setWarningText(Blockly.Msg.CONTROLS_FLOW_STATEMENTS_WARNING);
}
}
};

364
blocks/math.js Normal file
View File

@@ -0,0 +1,364 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Math blocks for Blockly.
* @author q.neutron@gmail.com (Quynh Neutron)
*/
'use strict';
goog.provide('Blockly.Blocks.math');
goog.require('Blockly.Blocks');
Blockly.Blocks['math_number'] = {
// Numeric value.
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_NUMBER_HELPURL);
this.setColour(230);
this.appendDummyInput()
.appendTitle(new Blockly.FieldTextInput('0',
Blockly.FieldTextInput.numberValidator), 'NUM');
this.setOutput(true, 'Number');
this.setTooltip(Blockly.Msg.MATH_NUMBER_TOOLTIP);
}
};
Blockly.Blocks['math_arithmetic'] = {
// Basic arithmetic operator.
init: function() {
var OPERATORS =
[[Blockly.Msg.MATH_ADDITION_SYMBOL, 'ADD'],
[Blockly.Msg.MATH_SUBTRACTION_SYMBOL, 'MINUS'],
[Blockly.Msg.MATH_MULTIPLICATION_SYMBOL, 'MULTIPLY'],
[Blockly.Msg.MATH_DIVISION_SYMBOL, 'DIVIDE'],
[Blockly.Msg.MATH_POWER_SYMBOL, 'POWER']];
this.setHelpUrl(Blockly.Msg.MATH_ARITHMETIC_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendValueInput('A')
.setCheck('Number');
this.appendValueInput('B')
.setCheck('Number')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
this.setInputsInline(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var mode = thisBlock.getTitleValue('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
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_single'] = {
// Advanced math operators with single operand.
init: function() {
var OPERATORS =
[[Blockly.Msg.MATH_SINGLE_OP_ROOT, 'ROOT'],
[Blockly.Msg.MATH_SINGLE_OP_ABSOLUTE, 'ABS'],
['-', 'NEG'],
['ln', 'LN'],
['log10', 'LOG10'],
['e^', 'EXP'],
['10^', 'POW10']];
this.setHelpUrl(Blockly.Msg.MATH_SINGLE_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendValueInput('NUM')
.setCheck('Number')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var mode = thisBlock.getTitleValue('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
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_trig'] = {
// Trigonometry operators.
init: function() {
var OPERATORS =
[[Blockly.Msg.MATH_TRIG_SIN, 'SIN'],
[Blockly.Msg.MATH_TRIG_COS, 'COS'],
[Blockly.Msg.MATH_TRIG_TAN, 'TAN'],
[Blockly.Msg.MATH_TRIG_ASIN, 'ASIN'],
[Blockly.Msg.MATH_TRIG_ACOS, 'ACOS'],
[Blockly.Msg.MATH_TRIG_ATAN, 'ATAN']];
this.setHelpUrl(Blockly.Msg.MATH_TRIG_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendValueInput('NUM')
.setCheck('Number')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
var mode = thisBlock.getTitleValue('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
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_constant'] = {
// Constants: PI, E, the Golden Ratio, sqrt(2), 1/sqrt(2), INFINITY.
init: function() {
var CONSTANTS =
[['\u03c0', 'PI'],
['e', 'E'],
['\u03c6', 'GOLDEN_RATIO'],
['sqrt(2)', 'SQRT2'],
['sqrt(\u00bd)', 'SQRT1_2'],
['\u221e', 'INFINITY']];
this.setHelpUrl(Blockly.Msg.MATH_CONSTANT_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendDummyInput()
.appendTitle(new Blockly.FieldDropdown(CONSTANTS), 'CONSTANT');
this.setTooltip(Blockly.Msg.MATH_CONSTANT_TOOLTIP);
}
};
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.
init: function() {
var PROPERTIES =
[[Blockly.Msg.MATH_IS_EVEN, 'EVEN'],
[Blockly.Msg.MATH_IS_ODD, 'ODD'],
[Blockly.Msg.MATH_IS_PRIME, 'PRIME'],
[Blockly.Msg.MATH_IS_WHOLE, 'WHOLE'],
[Blockly.Msg.MATH_IS_POSITIVE, 'POSITIVE'],
[Blockly.Msg.MATH_IS_NEGATIVE, 'NEGATIVE'],
[Blockly.Msg.MATH_IS_DIVISIBLE_BY, 'DIVISIBLE_BY']];
this.setColour(230);
this.appendValueInput('NUMBER_TO_CHECK')
.setCheck('Number');
var dropdown = new Blockly.FieldDropdown(PROPERTIES, function(option) {
var divisorInput = (option == 'DIVISIBLE_BY');
this.sourceBlock_.updateShape(divisorInput);
});
this.appendDummyInput()
.appendTitle(dropdown, 'PROPERTY');
this.setInputsInline(true);
this.setOutput(true, 'Boolean');
this.setTooltip(Blockly.Msg.MATH_IS_TOOLTIP);
},
mutationToDom: function() {
// Save whether the 'divisorInput' should be true of false (present or not).
var container = document.createElement('mutation');
var divisorInput = (this.getTitleValue('PROPERTY') == 'DIVISIBLE_BY');
container.setAttribute('divisor_input', divisorInput);
return container;
},
domToMutation: function(xmlElement) {
// Restore the 'divisorInput'.
var divisorInput = (xmlElement.getAttribute('divisor_input') == 'true');
this.updateShape(divisorInput);
},
updateShape: function(divisorInput) {
// Add or remove a Value Input.
var inputExists = this.getInput('DIVISOR');
if (divisorInput) {
if (!inputExists) {
this.appendValueInput('DIVISOR')
.setCheck('Number');
}
} else if (inputExists) {
this.removeInput('DIVISOR');
}
}
};
Blockly.Blocks['math_change'] = {
// Add to a variable in place.
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_CHANGE_HELPURL);
this.setColour(230);
this.appendValueInput('DELTA')
.setCheck('Number')
.appendTitle(Blockly.Msg.MATH_CHANGE_TITLE_CHANGE)
.appendTitle(new Blockly.FieldVariable(
Blockly.Msg.MATH_CHANGE_TITLE_ITEM), 'VAR')
.appendTitle(Blockly.Msg.MATH_CHANGE_INPUT_BY);
this.setPreviousStatement(true);
this.setNextStatement(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return Blockly.Msg.MATH_CHANGE_TOOLTIP.replace('%1',
thisBlock.getTitleValue('VAR'));
});
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
}
};
Blockly.Blocks['math_round'] = {
// Rounding functions.
init: function() {
var OPERATORS =
[[Blockly.Msg.MATH_ROUND_OPERATOR_ROUND, 'ROUND'],
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDUP, 'ROUNDUP'],
[Blockly.Msg.MATH_ROUND_OPERATOR_ROUNDDOWN, 'ROUNDDOWN']];
this.setHelpUrl(Blockly.Msg.MATH_ROUND_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendValueInput('NUM')
.setCheck('Number')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'OP');
this.setTooltip(Blockly.Msg.MATH_ROUND_TOOLTIP);
}
};
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).
init: function() {
var OPERATORS =
[[Blockly.Msg.MATH_ONLIST_OPERATOR_SUM, 'SUM'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MIN, 'MIN'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MAX, 'MAX'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_AVERAGE, 'AVERAGE'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MEDIAN, 'MEDIAN'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_MODE, 'MODE'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_STD_DEV, 'STD_DEV'],
[Blockly.Msg.MATH_ONLIST_OPERATOR_RANDOM, 'RANDOM']];
// Assign 'this' to a variable for use in the closure below.
var thisBlock = this;
this.setHelpUrl(Blockly.Msg.MATH_ONLIST_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
var dropdown = new Blockly.FieldDropdown(OPERATORS, function(newOp) {
if (newOp == 'MODE') {
thisBlock.outputConnection.setCheck('Array');
} else {
thisBlock.outputConnection.setCheck('Number');
}
});
this.appendValueInput('LIST')
.setCheck('Array')
.appendTitle(dropdown, 'OP');
this.setTooltip(function() {
var mode = thisBlock.getTitleValue('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
};
return TOOLTIPS[mode];
});
}
};
Blockly.Blocks['math_modulo'] = {
// Remainder of a division.
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_MODULO_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.interpolateMsg(Blockly.Msg.MATH_MODULO_TITLE,
['DIVIDEND', 'Number', Blockly.ALIGN_RIGHT],
['DIVISOR', 'Number', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.MATH_MODULO_TOOLTIP);
}
};
Blockly.Blocks['math_constrain'] = {
// Constrain a number between two limits.
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_CONSTRAIN_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.interpolateMsg(Blockly.Msg.MATH_CONSTRAIN_TITLE,
['VALUE', 'Number', Blockly.ALIGN_RIGHT],
['LOW', 'Number', Blockly.ALIGN_RIGHT],
['HIGH', 'Number', 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].
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_RANDOM_INT_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.interpolateMsg(Blockly.Msg.MATH_RANDOM_INT_TITLE,
['FROM', 'Number', Blockly.ALIGN_RIGHT],
['TO', 'Number', Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.MATH_RANDOM_INT_TOOLTIP);
}
};
Blockly.Blocks['math_random_float'] = {
// Random fraction between 0 and 1.
init: function() {
this.setHelpUrl(Blockly.Msg.MATH_RANDOM_FLOAT_HELPURL);
this.setColour(230);
this.setOutput(true, 'Number');
this.appendDummyInput()
.appendTitle(Blockly.Msg.MATH_RANDOM_FLOAT_TITLE_RANDOM);
this.setTooltip(Blockly.Msg.MATH_RANDOM_FLOAT_TOOLTIP);
}
};

517
blocks/procedures.js Normal file
View File

@@ -0,0 +1,517 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Procedure blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.procedures');
goog.require('Blockly.Blocks');
Blockly.Blocks['procedures_defnoreturn'] = {
// Define a procedure with no return value.
init: function() {
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFNORETURN_HELPURL);
this.setColour(290);
var name = Blockly.Procedures.findLegalName(
Blockly.Msg.PROCEDURES_DEFNORETURN_PROCEDURE, this);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_DEFNORETURN_TITLE)
.appendTitle(new Blockly.FieldTextInput(name,
Blockly.Procedures.rename), 'NAME')
.appendTitle('', 'PARAMS');
this.appendStatementInput('STACK')
.appendTitle(Blockly.Msg.PROCEDURES_DEFNORETURN_DO);
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
this.setTooltip(Blockly.Msg.PROCEDURES_DEFNORETURN_TOOLTIP);
this.arguments_ = [];
},
updateParams_: function() {
// Check for duplicated arguments.
var badArg = false;
var hash = {};
for (var x = 0; x < this.arguments_.length; x++) {
if (hash['arg_' + this.arguments_[x].toLowerCase()]) {
badArg = true;
break;
}
hash['arg_' + this.arguments_[x].toLowerCase()] = true;
}
if (badArg) {
this.setWarningText(Blockly.Msg.PROCEDURES_DEF_DUPLICATE_WARNING);
} else {
this.setWarningText(null);
}
// Merge the arguments into a human-readable list.
var paramString = '';
if (this.arguments_.length) {
paramString = Blockly.Msg.PROCEDURES_BEFORE_PARAMS +
' ' + this.arguments_.join(', ');
}
this.setTitleValue(paramString, 'PARAMS');
},
mutationToDom: function() {
var container = document.createElement('mutation');
for (var x = 0; x < this.arguments_.length; x++) {
var parameter = document.createElement('arg');
parameter.setAttribute('name', this.arguments_[x]);
container.appendChild(parameter);
}
return container;
},
domToMutation: function(xmlElement) {
this.arguments_ = [];
for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) {
if (childNode.nodeName.toLowerCase() == 'arg') {
this.arguments_.push(childNode.getAttribute('name'));
}
}
this.updateParams_();
},
decompose: function(workspace) {
var containerBlock = new Blockly.Block(workspace,
'procedures_mutatorcontainer');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 0; x < this.arguments_.length; x++) {
var paramBlock = new Blockly.Block(workspace, 'procedures_mutatorarg');
paramBlock.initSvg();
paramBlock.setTitleValue(this.arguments_[x], 'NAME');
// Store the old location.
paramBlock.oldLocation = x;
connection.connect(paramBlock.previousConnection);
connection = paramBlock.nextConnection;
}
// Initialize procedure's callers with blank IDs.
Blockly.Procedures.mutateCallers(this.getTitleValue('NAME'),
this.workspace, this.arguments_, null);
return containerBlock;
},
compose: function(containerBlock) {
this.arguments_ = [];
this.paramIds_ = [];
var paramBlock = containerBlock.getInputTargetBlock('STACK');
while (paramBlock) {
this.arguments_.push(paramBlock.getTitleValue('NAME'));
this.paramIds_.push(paramBlock.id);
paramBlock = paramBlock.nextConnection &&
paramBlock.nextConnection.targetBlock();
}
this.updateParams_();
Blockly.Procedures.mutateCallers(this.getTitleValue('NAME'),
this.workspace, this.arguments_, this.paramIds_);
},
dispose: function() {
// Dispose of any callers.
var name = this.getTitleValue('NAME');
Blockly.Procedures.disposeCallers(name, this.workspace);
// Call parent's destructor.
Blockly.Block.prototype.dispose.apply(this, arguments);
},
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.getTitleValue('NAME'), this.arguments_, false];
},
getVars: function() {
return this.arguments_;
},
renameVar: function(oldName, newName) {
var change = false;
for (var x = 0; x < this.arguments_.length; x++) {
if (Blockly.Names.equals(oldName, this.arguments_[x])) {
this.arguments_[x] = newName;
change = true;
}
}
if (change) {
this.updateParams_();
// Update the mutator's variables if the mutator is open.
if (this.mutator.isVisible_()) {
var blocks = this.mutator.workspace_.getAllBlocks();
for (var x = 0, block; block = blocks[x]; x++) {
if (block.type == 'procedures_mutatorarg' &&
Blockly.Names.equals(oldName, block.getTitleValue('NAME'))) {
block.setTitleValue(newName, 'NAME');
}
}
}
}
},
customContextMenu: function(options) {
// Add option to create caller.
var option = {enabled: true};
var name = this.getTitleValue('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++) {
var xmlArg = goog.dom.createDom('arg');
xmlArg.setAttribute('name', this.arguments_[x]);
xmlMutation.appendChild(xmlArg);
}
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 xmlTitle = goog.dom.createDom('title', null, name);
xmlTitle.setAttribute('name', 'VAR');
var xmlBlock = goog.dom.createDom('block', null, xmlTitle);
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.
init: function() {
this.setHelpUrl(Blockly.Msg.PROCEDURES_DEFRETURN_HELPURL);
this.setColour(290);
var name = Blockly.Procedures.findLegalName(
Blockly.Msg.PROCEDURES_DEFRETURN_PROCEDURE, this);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_TITLE)
.appendTitle(new Blockly.FieldTextInput(name,
Blockly.Procedures.rename), 'NAME')
.appendTitle('', 'PARAMS');
this.appendStatementInput('STACK')
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_DO);
this.appendValueInput('RETURN')
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
this.setTooltip(Blockly.Msg.PROCEDURES_DEFRETURN_TOOLTIP);
this.arguments_ = [];
},
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,
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.getTitleValue('NAME'), this.arguments_, true];
},
getVars: Blockly.Blocks['procedures_defnoreturn'].getVars,
renameVar: Blockly.Blocks['procedures_defnoreturn'].renameVar,
customContextMenu: Blockly.Blocks['procedures_defnoreturn'].customContextMenu,
callType_: 'procedures_callreturn'
};
Blockly.Blocks['procedures_mutatorcontainer'] = {
// Procedure container (for mutator dialog).
init: function() {
this.setColour(290);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_MUTATORCONTAINER_TITLE);
this.appendStatementInput('STACK');
this.setTooltip('');
this.contextMenu = false;
}
};
Blockly.Blocks['procedures_mutatorarg'] = {
// Procedure argument (for mutator dialog).
init: function() {
this.setColour(290);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_MUTATORARG_TITLE)
.appendTitle(new Blockly.FieldTextInput('x', this.validator), 'NAME');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip('');
this.contextMenu = false;
},
validator: function(newVar) {
// Merge runs of whitespace. Strip leading and trailing whitespace.
// Beyond this, all names are legal.
newVar = newVar.replace(/[\s\xa0]+/g, ' ').replace(/^ | $/g, '');
return newVar || null;
}
};
Blockly.Blocks['procedures_callnoreturn'] = {
// Call a procedure with no return value.
init: function() {
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLNORETURN_HELPURL);
this.setColour(290);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_CALLNORETURN_CALL)
.appendTitle('', 'NAME');
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP);
this.arguments_ = [];
this.quarkConnections_ = null;
this.quarkArguments_ = null;
},
getProcedureCall: function() {
return this.getTitleValue('NAME');
},
renameProcedure: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('NAME'))) {
this.setTitleValue(newName, 'NAME');
this.setTooltip(
(this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP
: Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP)
.replace('%1', newName));
}
},
setProcedureParameters: function(paramNames, paramIds) {
// Data structures for parameters on each call block:
// 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_']
// Existing param IDs.
// Note that quarkConnections_ may include IDs that no longer exist, but
// which might reappear if a param is reattached in the mutator.
if (!paramIds) {
// Reset the quarks (a mutator is about to open).
this.quarkConnections_ = {};
this.quarkArguments_ = null;
return;
}
if (paramIds.length != paramNames.length) {
throw 'Error: paramNames and paramIds must be the same length.';
}
if (!this.quarkArguments_) {
// Initialize tracking for this block.
this.quarkConnections_ = {};
if (paramNames.join('\n') == this.arguments_.join('\n')) {
// No change to the parameters, allow quarkConnections_ to be
// populated with the existing connections.
this.quarkArguments_ = paramIds;
} else {
this.quarkArguments_ = [];
}
}
// Switch off rendering while the block is rebuilt.
var savedRendered = this.rendered;
this.rendered = false;
// Update the quarkConnections_ with existing connections.
for (var x = this.arguments_.length - 1; x >= 0; x--) {
var input = this.getInput('ARG' + x);
if (input) {
var connection = input.connection.targetConnection;
this.quarkConnections_[this.quarkArguments_[x]] = connection;
// Disconnect all argument blocks and remove all inputs.
this.removeInput('ARG' + x);
}
}
// Rebuild the block's arguments.
this.arguments_ = [].concat(paramNames);
this.quarkArguments_ = paramIds;
for (var x = 0; x < this.arguments_.length; x++) {
var input = this.appendValueInput('ARG' + x)
.setAlign(Blockly.ALIGN_RIGHT)
.appendTitle(this.arguments_[x]);
if (this.quarkArguments_) {
// Reconnect any child blocks.
var quarkName = this.quarkArguments_[x];
if (quarkName in this.quarkConnections_) {
var connection = this.quarkConnections_[quarkName];
if (!connection || connection.targetConnection ||
connection.sourceBlock_.workspace != this.workspace) {
// Block no longer exists or has been attached elsewhere.
delete this.quarkConnections_[quarkName];
} else {
input.connection.connect(connection);
}
}
}
}
// Restore rendering and show the changes.
this.rendered = savedRendered;
if (this.rendered) {
this.render();
}
},
mutationToDom: function() {
// Save the name and arguments (none of which are editable).
var container = document.createElement('mutation');
container.setAttribute('name', this.getTitleValue('NAME'));
for (var x = 0; x < this.arguments_.length; x++) {
var parameter = document.createElement('arg');
parameter.setAttribute('name', this.arguments_[x]);
container.appendChild(parameter);
}
return container;
},
domToMutation: function(xmlElement) {
// Restore the name and parameters.
var name = xmlElement.getAttribute('name');
this.setTitleValue(name, 'NAME');
this.setTooltip(
(this.outputConnection ? Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP
: Blockly.Msg.PROCEDURES_CALLNORETURN_TOOLTIP).replace('%1', name));
var def = Blockly.Procedures.getDefinition(name, this.workspace);
if (def && def.mutator.isVisible()) {
// Initialize caller with the mutator's IDs.
this.setProcedureParameters(def.arguments_, def.paramIds_);
} else {
this.arguments_ = [];
for (var x = 0, childNode; childNode = xmlElement.childNodes[x]; x++) {
if (childNode.nodeName.toLowerCase() == 'arg') {
this.arguments_.push(childNode.getAttribute('name'));
}
}
// For the second argument (paramIds) use the arguments list as a dummy
// list.
this.setProcedureParameters(this.arguments_, this.arguments_);
}
},
renameVar: function(oldName, newName) {
for (var x = 0; x < this.arguments_.length; x++) {
if (Blockly.Names.equals(oldName, this.arguments_[x])) {
this.arguments_[x] = newName;
this.getInput('ARG' + x).titleRow[0].setText(newName);
}
}
},
customContextMenu: function(options) {
// Add option to find caller.
var option = {enabled: true};
option.text = Blockly.Msg.PROCEDURES_HIGHLIGHT_DEF;
var name = this.getTitleValue('NAME');
var workspace = this.workspace;
option.callback = function() {
var def = Blockly.Procedures.getDefinition(name, workspace);
def && def.select();
};
options.push(option);
}
};
Blockly.Blocks['procedures_callreturn'] = {
// Call a procedure with a return value.
init: function() {
this.setHelpUrl(Blockly.Msg.PROCEDURES_CALLRETURN_HELPURL);
this.setColour(290);
this.appendDummyInput()
.appendTitle(Blockly.Msg.PROCEDURES_CALLRETURN_CALL)
.appendTitle('', 'NAME');
this.setOutput(true);
this.setTooltip(Blockly.Msg.PROCEDURES_CALLRETURN_TOOLTIP);
this.arguments_ = [];
this.quarkConnections_ = null;
this.quarkArguments_ = null;
},
getProcedureCall: Blockly.Blocks['procedures_callnoreturn'].getProcedureCall,
renameProcedure: Blockly.Blocks['procedures_callnoreturn'].renameProcedure,
setProcedureParameters:
Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters,
mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom,
domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation,
renameVar: Blockly.Blocks['procedures_callnoreturn'].renameVar,
customContextMenu: Blockly.Blocks['procedures_callnoreturn'].customContextMenu
};
Blockly.Blocks['procedures_ifreturn'] = {
// Conditionally return value from a procedure.
init: function() {
this.setHelpUrl('http://c2.com/cgi/wiki?GuardClause');
this.setColour(290);
this.appendValueInput('CONDITION')
.setCheck('Boolean')
.appendTitle(Blockly.Msg.CONTROLS_IF_MSG_IF);
this.appendValueInput('VALUE')
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
this.setInputsInline(true);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.PROCEDURES_IFRETURN_TOOLTIP);
this.hasReturnValue_ = true;
},
mutationToDom: function() {
// Save whether this block has a return value.
var container = document.createElement('mutation');
container.setAttribute('value', Number(this.hasReturnValue_));
return container;
},
domToMutation: function(xmlElement) {
// Restore whether this block has a return value.
var value = xmlElement.getAttribute('value');
this.hasReturnValue_ = (value == 1);
if (!this.hasReturnValue_) {
this.removeInput('VALUE');
this.appendDummyInput('VALUE')
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
}
},
onchange: function() {
if (!this.workspace) {
// Block has been deleted.
return;
}
var legal = false;
// Is the block nested in a procedure?
var block = this;
do {
if (block.type == 'procedures_defnoreturn' ||
block.type == 'procedures_defreturn') {
legal = true;
break;
}
block = block.getSurroundParent();
} while (block);
if (legal) {
// If needed, toggle whether this block has a return value.
if (block.type == 'procedures_defnoreturn' && this.hasReturnValue_) {
this.removeInput('VALUE');
this.appendDummyInput('VALUE')
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
this.hasReturnValue_ = false;
} else if (block.type == 'procedures_defreturn' &&
!this.hasReturnValue_) {
this.removeInput('VALUE');
this.appendValueInput('VALUE')
.appendTitle(Blockly.Msg.PROCEDURES_DEFRETURN_RETURN);
this.hasReturnValue_ = true;
}
this.setWarningText(null);
} else {
this.setWarningText(Blockly.Msg.PROCEDURES_IFRETURN_WARNING);
}
}
};

484
blocks/text.js Normal file
View File

@@ -0,0 +1,484 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Text blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.text');
goog.require('Blockly.Blocks');
Blockly.Blocks['text'] = {
// Text value.
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_TEXT_HELPURL);
this.setColour(160);
this.appendDummyInput()
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote0.png', 12, 12))
.appendTitle(new Blockly.FieldTextInput(''), 'TEXT')
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote1.png', 12, 12));
this.setOutput(true, 'String');
this.setTooltip(Blockly.Msg.TEXT_TEXT_TOOLTIP);
}
};
Blockly.Blocks['text_join'] = {
// Create a string made up of any number of elements of any type.
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_JOIN_HELPURL);
this.setColour(160);
this.appendValueInput('ADD0')
.appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH);
this.appendValueInput('ADD1');
this.setOutput(true, 'String');
this.setMutator(new Blockly.Mutator(['text_create_join_item']));
this.setTooltip(Blockly.Msg.TEXT_JOIN_TOOLTIP);
this.itemCount_ = 2;
},
mutationToDom: function() {
var container = document.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(xmlElement) {
for (var x = 0; x < this.itemCount_; x++) {
this.removeInput('ADD' + x);
}
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
for (var x = 0; x < this.itemCount_; x++) {
var input = this.appendValueInput('ADD' + x);
if (x == 0) {
input.appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH);
}
}
if (this.itemCount_ == 0) {
this.appendDummyInput('EMPTY')
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote0.png', 12, 12))
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote1.png', 12, 12));
}
},
decompose: function(workspace) {
var containerBlock = new Blockly.Block(workspace,
'text_create_join_container');
containerBlock.initSvg();
var connection = containerBlock.getInput('STACK').connection;
for (var x = 0; x < this.itemCount_; x++) {
var itemBlock = new Blockly.Block(workspace, 'text_create_join_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
return containerBlock;
},
compose: function(containerBlock) {
// Disconnect all input blocks and remove all inputs.
if (this.itemCount_ == 0) {
this.removeInput('EMPTY');
} else {
for (var x = this.itemCount_ - 1; x >= 0; x--) {
this.removeInput('ADD' + x);
}
}
this.itemCount_ = 0;
// Rebuild the block's inputs.
var itemBlock = containerBlock.getInputTargetBlock('STACK');
while (itemBlock) {
var input = this.appendValueInput('ADD' + this.itemCount_);
if (this.itemCount_ == 0) {
input.appendTitle(Blockly.Msg.TEXT_JOIN_TITLE_CREATEWITH);
}
// Reconnect any child blocks.
if (itemBlock.valueConnection_) {
input.connection.connect(itemBlock.valueConnection_);
}
this.itemCount_++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
if (this.itemCount_ == 0) {
this.appendDummyInput('EMPTY')
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote0.png', 12, 12))
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote1.png', 12, 12));
}
},
saveConnections: function(containerBlock) {
// Store a pointer to any connected child blocks.
var itemBlock = containerBlock.getInputTargetBlock('STACK');
var x = 0;
while (itemBlock) {
var input = this.getInput('ADD' + x);
itemBlock.valueConnection_ = input && input.connection.targetConnection;
x++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
}
};
Blockly.Blocks['text_create_join_container'] = {
// Container.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendTitle(Blockly.Msg.TEXT_CREATE_JOIN_TITLE_JOIN);
this.appendStatementInput('STACK');
this.setTooltip(Blockly.Msg.TEXT_CREATE_JOIN_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['text_create_join_item'] = {
// Add items.
init: function() {
this.setColour(160);
this.appendDummyInput()
.appendTitle(Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TITLE_ITEM);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.TEXT_CREATE_JOIN_ITEM_TOOLTIP);
this.contextMenu = false;
}
};
Blockly.Blocks['text_append'] = {
// Append to a variable in place.
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_APPEND_HELPURL);
this.setColour(160);
this.appendValueInput('TEXT')
.appendTitle(Blockly.Msg.TEXT_APPEND_TO)
.appendTitle(new Blockly.FieldVariable(
Blockly.Msg.TEXT_APPEND_VARIABLE), 'VAR')
.appendTitle(Blockly.Msg.TEXT_APPEND_APPENDTEXT);
this.setPreviousStatement(true);
this.setNextStatement(true);
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return Blockly.Msg.TEXT_APPEND_TOOLTIP.replace('%1',
thisBlock.getTitleValue('VAR'));
});
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
}
};
Blockly.Blocks['text_length'] = {
// String length.
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_LENGTH_HELPURL);
this.setColour(160);
this.interpolateMsg(Blockly.Msg.TEXT_LENGTH_TITLE,
['VALUE', ['String', 'Array'], Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setOutput(true, 'Number');
this.setTooltip(Blockly.Msg.TEXT_LENGTH_TOOLTIP);
}
};
Blockly.Blocks['text_isEmpty'] = {
// Is the string null?
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_ISEMPTY_HELPURL);
this.setColour(160);
this.interpolateMsg(Blockly.Msg.TEXT_ISEMPTY_TITLE,
['VALUE', ['String', 'Array'], Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setOutput(true, 'Boolean');
this.setTooltip(Blockly.Msg.TEXT_ISEMPTY_TOOLTIP);
}
};
Blockly.Blocks['text_indexOf'] = {
// Find a substring in the text.
init: function() {
var OPERATORS =
[[Blockly.Msg.TEXT_INDEXOF_OPERATOR_FIRST, 'FIRST'],
[Blockly.Msg.TEXT_INDEXOF_OPERATOR_LAST, 'LAST']];
this.setHelpUrl(Blockly.Msg.TEXT_INDEXOF_HELPURL);
this.setColour(160);
this.setOutput(true, 'Number');
this.appendValueInput('VALUE')
.setCheck('String')
.appendTitle(Blockly.Msg.TEXT_INDEXOF_INPUT_INTEXT);
this.appendValueInput('FIND')
.setCheck('String')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'END');
if (Blockly.Msg.TEXT_INDEXOF_TAIL) {
this.appendDummyInput().appendTitle(Blockly.Msg.TEXT_INDEXOF_TAIL);
}
this.setInputsInline(true);
this.setTooltip(Blockly.Msg.TEXT_INDEXOF_TOOLTIP);
}
};
Blockly.Blocks['text_charAt'] = {
// Get a character from the string.
init: function() {
this.WHERE_OPTIONS =
[[Blockly.Msg.TEXT_CHARAT_FROM_START, 'FROM_START'],
[Blockly.Msg.TEXT_CHARAT_FROM_END, 'FROM_END'],
[Blockly.Msg.TEXT_CHARAT_FIRST, 'FIRST'],
[Blockly.Msg.TEXT_CHARAT_LAST, 'LAST'],
[Blockly.Msg.TEXT_CHARAT_RANDOM, 'RANDOM']];
this.setHelpUrl(Blockly.Msg.TEXT_CHARAT_HELPURL);
this.setColour(160);
this.setOutput(true, 'String');
this.appendValueInput('VALUE')
.setCheck('String')
.appendTitle(Blockly.Msg.TEXT_CHARAT_INPUT_INTEXT);
this.appendDummyInput('AT');
this.setInputsInline(true);
this.updateAt(true);
this.setTooltip(Blockly.Msg.TEXT_CHARAT_TOOLTIP);
},
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;
},
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);
},
updateAt: function(isAt) {
// Create or delete an input for the numeric index.
// Destroy old 'AT' and 'ORDINAL' inputs.
this.removeInput('AT');
this.removeInput('ORDINAL', true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
this.appendValueInput('AT').setCheck('Number');
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
this.appendDummyInput('ORDINAL')
.appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT');
}
if (Blockly.Msg.TEXT_CHARAT_TAIL) {
this.removeInput('TAIL', true);
this.appendDummyInput('TAIL')
.appendTitle(Blockly.Msg.TEXT_CHARAT_TAIL);
}
var menu = new Blockly.FieldDropdown(this.WHERE_OPTIONS, function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt(newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setTitleValue(value, 'WHERE');
return null;
}
return undefined;
});
this.getInput('AT').appendTitle(menu, 'WHERE');
}
};
Blockly.Blocks['text_getSubstring'] = {
// Get substring.
init: function() {
this.WHERE_OPTIONS_1 =
[[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_START, 'FROM_START'],
[Blockly.Msg.TEXT_GET_SUBSTRING_START_FROM_END, 'FROM_END'],
[Blockly.Msg.TEXT_GET_SUBSTRING_START_FIRST, 'FIRST']];
this.WHERE_OPTIONS_2 =
[[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_START, 'FROM_START'],
[Blockly.Msg.TEXT_GET_SUBSTRING_END_FROM_END, 'FROM_END'],
[Blockly.Msg.TEXT_GET_SUBSTRING_END_LAST, 'LAST']];
this.setHelpUrl(Blockly.Msg.TEXT_GET_SUBSTRING_HELPURL);
this.setColour(160);
this.appendValueInput('STRING')
.setCheck('String')
.appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_INPUT_IN_TEXT);
this.appendDummyInput('AT1');
this.appendDummyInput('AT2');
if (Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) {
this.appendDummyInput('TAIL')
.appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL);
}
this.setInputsInline(true);
this.setOutput(true, 'String');
this.updateAt(1, true);
this.updateAt(2, true);
this.setTooltip(Blockly.Msg.TEXT_GET_SUBSTRING_TOOLTIP);
},
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);
var isAt2 = this.getInput('AT2').type == Blockly.INPUT_VALUE;
container.setAttribute('at2', isAt2);
return container;
},
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);
},
updateAt: function(n, isAt) {
// Create or delete an input for the numeric index.
// Destroy old 'AT' and 'ORDINAL' inputs.
this.removeInput('AT' + n);
this.removeInput('ORDINAL' + n, true);
// Create either a value 'AT' input or a dummy input.
if (isAt) {
this.appendValueInput('AT' + n).setCheck('Number');
if (Blockly.Msg.ORDINAL_NUMBER_SUFFIX) {
this.appendDummyInput('ORDINAL' + n)
.appendTitle(Blockly.Msg.ORDINAL_NUMBER_SUFFIX);
}
} else {
this.appendDummyInput('AT' + n);
}
// Move tail, if present, to end of block.
if (n == 2 && Blockly.Msg.TEXT_GET_SUBSTRING_TAIL) {
this.removeInput('TAIL', true);
this.appendDummyInput('TAIL')
.appendTitle(Blockly.Msg.TEXT_GET_SUBSTRING_TAIL);
}
var menu = new Blockly.FieldDropdown(this['WHERE_OPTIONS_' + n],
function(value) {
var newAt = (value == 'FROM_START') || (value == 'FROM_END');
// The 'isAt' variable is available due to this function being a closure.
if (newAt != isAt) {
var block = this.sourceBlock_;
block.updateAt(n, newAt);
// This menu has been destroyed and replaced. Update the replacement.
block.setTitleValue(value, 'WHERE' + n);
return null;
}
return undefined;
});
this.getInput('AT' + n)
.appendTitle(menu, 'WHERE' + n);
if (n == 1) {
this.moveInputBefore('AT1', 'AT2');
}
}
};
Blockly.Blocks['text_changeCase'] = {
// Change capitalization.
init: function() {
var OPERATORS =
[[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_UPPERCASE, 'UPPERCASE'],
[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_LOWERCASE, 'LOWERCASE'],
[Blockly.Msg.TEXT_CHANGECASE_OPERATOR_TITLECASE, 'TITLECASE']];
this.setHelpUrl(Blockly.Msg.TEXT_CHANGECASE_HELPURL);
this.setColour(160);
this.appendValueInput('TEXT')
.setCheck('String')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'CASE');
this.setOutput(true, 'String');
this.setTooltip(Blockly.Msg.TEXT_CHANGECASE_TOOLTIP);
}
};
Blockly.Blocks['text_trim'] = {
// Trim spaces.
init: function() {
var OPERATORS =
[[Blockly.Msg.TEXT_TRIM_OPERATOR_BOTH, 'BOTH'],
[Blockly.Msg.TEXT_TRIM_OPERATOR_LEFT, 'LEFT'],
[Blockly.Msg.TEXT_TRIM_OPERATOR_RIGHT, 'RIGHT']];
this.setHelpUrl(Blockly.Msg.TEXT_TRIM_HELPURL);
this.setColour(160);
this.appendValueInput('TEXT')
.setCheck('String')
.appendTitle(new Blockly.FieldDropdown(OPERATORS), 'MODE');
this.setOutput(true, 'String');
this.setTooltip(Blockly.Msg.TEXT_TRIM_TOOLTIP);
}
};
Blockly.Blocks['text_print'] = {
// Print statement.
init: function() {
this.setHelpUrl(Blockly.Msg.TEXT_PRINT_HELPURL);
this.setColour(160);
this.interpolateMsg(Blockly.Msg.TEXT_PRINT_TITLE,
['TEXT', null, Blockly.ALIGN_RIGHT],
Blockly.ALIGN_RIGHT);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.TEXT_PRINT_TOOLTIP);
}
};
Blockly.Blocks['text_prompt'] = {
// Prompt function.
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.outputConnection.setCheck('Number');
} else {
thisBlock.outputConnection.setCheck('String');
}
});
this.appendDummyInput()
.appendTitle(dropdown, 'TYPE')
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote0.png', 12, 12))
.appendTitle(new Blockly.FieldTextInput(''), 'TEXT')
.appendTitle(new Blockly.FieldImage(Blockly.pathToBlockly +
'media/quote1.png', 12, 12));
this.setOutput(true, 'String');
// Assign 'this' to a variable for use in the tooltip closure below.
var thisBlock = this;
this.setTooltip(function() {
return (thisBlock.getTitleValue('TYPE') == 'TEXT') ?
Blockly.Msg.TEXT_PROMPT_TOOLTIP_TEXT :
Blockly.Msg.TEXT_PROMPT_TOOLTIP_NUMBER;
});
}
};

92
blocks/variables.js Normal file
View File

@@ -0,0 +1,92 @@
/**
* Visual Blocks Editor
*
* Copyright 2012 Google Inc.
* http://blockly.googlecode.com/
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @fileoverview Variable blocks for Blockly.
* @author fraser@google.com (Neil Fraser)
*/
'use strict';
goog.provide('Blockly.Blocks.variables');
goog.require('Blockly.Blocks');
Blockly.Blocks['variables_get'] = {
// Variable getter.
init: function() {
this.setHelpUrl(Blockly.Msg.VARIABLES_GET_HELPURL);
this.setColour(330);
this.appendDummyInput()
.appendTitle(Blockly.Msg.VARIABLES_GET_TITLE)
.appendTitle(new Blockly.FieldVariable(
Blockly.Msg.VARIABLES_GET_ITEM), 'VAR')
.appendTitle(Blockly.Msg.VARIABLES_GET_TAIL);
this.setOutput(true);
this.setTooltip(Blockly.Msg.VARIABLES_GET_TOOLTIP);
this.contextMenuMsg_ = Blockly.Msg.VARIABLES_GET_CREATE_SET;
this.contextMenuType_ = 'variables_set';
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
},
customContextMenu: function(options) {
var option = {enabled: true};
var name = this.getTitleValue('VAR');
option.text = this.contextMenuMsg_.replace('%1', name);
var xmlTitle = goog.dom.createDom('title', null, name);
xmlTitle.setAttribute('name', 'VAR');
var xmlBlock = goog.dom.createDom('block', null, xmlTitle);
xmlBlock.setAttribute('type', this.contextMenuType_);
option.callback = Blockly.ContextMenu.callbackFactory(this, xmlBlock);
options.push(option);
}
};
Blockly.Blocks['variables_set'] = {
// Variable setter.
init: function() {
this.setHelpUrl(Blockly.Msg.VARIABLES_SET_HELPURL);
this.setColour(330);
this.appendValueInput('VALUE')
.appendTitle(Blockly.Msg.VARIABLES_SET_TITLE)
.appendTitle(new Blockly.FieldVariable(
Blockly.Msg.VARIABLES_SET_ITEM), 'VAR')
.appendTitle(Blockly.Msg.VARIABLES_SET_TAIL);
this.setPreviousStatement(true);
this.setNextStatement(true);
this.setTooltip(Blockly.Msg.VARIABLES_SET_TOOLTIP);
this.contextMenuMsg_ = Blockly.Msg.VARIABLES_SET_CREATE_GET;
this.contextMenuType_ = 'variables_get';
},
getVars: function() {
return [this.getTitleValue('VAR')];
},
renameVar: function(oldName, newName) {
if (Blockly.Names.equals(oldName, this.getTitleValue('VAR'))) {
this.setTitleValue(newName, 'VAR');
}
},
customContextMenu: Blockly.Blocks['variables_get'].customContextMenu
};