Skip to content

Instantly share code, notes, and snippets.

@10MINT
Last active October 11, 2020 22:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 10MINT/2c90a732ca2bc54ece8c7affb1a9422f to your computer and use it in GitHub Desktop.
Save 10MINT/2c90a732ca2bc54ece8c7affb1a9422f to your computer and use it in GitHub Desktop.
Files for adding a create class block which shares functionality with the procedures blocks
/**
* @fileoverview Class definition blocks for Blockly.
* @author 10MINT (redpandadevs@gmail.com)
*/
'use strict';
goog.provide('Blockly.Blocks.classes');
goog.require('Blockly.Blocks.procedures');
// Dummy translations
Blockly.Msg['CLASSES_DEFINITION_TITLE'] = "create class";
Blockly.Msg['CLASSES_DEFINITION_DEFAULT'] = "MyClass";
Blockly.Msg['CLASSES_DEFINITION_COMMENT'] = "Describe this class";
Blockly.Msg['CLASSES_DEFINITION_TOOLTIP'] = "Creates a new class";
Blockly.Msg['CLASSES_DEFINITION_HELPURL'] = "TODO";
Blockly.Msg['CLASSES_CALLER_HELPURL'] = "TODO";
/*
* Block for defining a class
*/
Blockly.Blocks['classes_definition'] = {
/**
* Block for defining a procedure with a return value.
* @this Blockly.Block
*/
init: function() {
var nameField = new Blockly.FieldTextInput('',
Blockly.Procedures.rename);
nameField.setSpellcheck(false);
this.appendDummyInput()
.appendField(Blockly.Msg['CLASSES_DEFINITION_TITLE'])
.appendField(nameField, 'NAME')
.appendField('', 'PARAMS');
this.setMutator(new Blockly.Mutator(['procedures_mutatorarg']));
if ((this.workspace.options.comments ||
(this.workspace.options.parentWorkspace &&
this.workspace.options.parentWorkspace.options.comments)) &&
Blockly.Msg['CLASSES_DEFINITION_COMMENT']) {
this.setCommentText(Blockly.Msg['CLASSES_DEFINITION_COMMENT']);
}
this.setStyle('procedure_blocks');
this.setTooltip(Blockly.Msg['CLASSES_DEFINITION_TOOLTIP']);
this.setHelpUrl(Blockly.Msg['CLASSES_DEFINITION_HELPURL']);
this.arguments_ = [];
this.argumentVarModels_ = [];
this.setStatements_(true);
this.statementConnection_ = null;
},
setStatements_: Blockly.Blocks['procedures_defnoreturn'].setStatements_,
updateParams_: Blockly.Blocks['procedures_defnoreturn'].updateParams_,
mutationToDom: Blockly.Blocks['procedures_defnoreturn'].mutationToDom,
domToMutation: Blockly.Blocks['procedures_defnoreturn'].domToMutation,
decompose: Blockly.Blocks['procedures_defnoreturn'].decompose,
compose: Blockly.Blocks['procedures_defnoreturn'].compose,
/**
* Return the signature of this procedure definition.
* @return {!Array} Tuple containing three elements:
* - the name of the defined procedure,
* - a list of all its arguments,
* - that it DOES have a return value.
* @this Blockly.Block
*/
getProcedureDef: function() {
return [this.getFieldValue('NAME'), this.arguments_, true];
},
getVars: Blockly.Blocks['procedures_defnoreturn'].getVars,
getVarModels: Blockly.Blocks['procedures_defnoreturn'].getVarModels,
renameVarById: Blockly.Blocks['procedures_defnoreturn'].renameVarById,
updateVarName: Blockly.Blocks['procedures_defnoreturn'].updateVarName,
displayRenamedVar_: Blockly.Blocks['procedures_defnoreturn'].displayRenamedVar_,
customContextMenu: Blockly.Blocks['procedures_defnoreturn'].customContextMenu,
callType_: 'classes_caller'
};
Blockly.Blocks['classes_caller'] = {
/**
* Block for calling a procedure with a return value.
* @this Blockly.Block
*/
init: function() {
this.appendDummyInput('TOPROW')
.appendField('', 'NAME');
this.setOutput(true, "ClassInstance");
this.setStyle('procedure_blocks');
// Tooltip is set in domToMutation.
this.setHelpUrl(Blockly.Msg['CLASSES_CALLER_HELPURL']);
this.arguments_ = [];
this.quarkConnections_ = {};
this.quarkIds_ = null;
this.previousDisabledState_ = false;
},
getProcedureCall: Blockly.Blocks['procedures_callnoreturn'].getProcedureCall,
renameProcedure: Blockly.Blocks['procedures_callnoreturn'].renameProcedure,
setProcedureParameters_:
Blockly.Blocks['procedures_callnoreturn'].setProcedureParameters_,
updateShape_: Blockly.Blocks['procedures_callnoreturn'].updateShape_,
mutationToDom: Blockly.Blocks['procedures_callnoreturn'].mutationToDom,
domToMutation: Blockly.Blocks['procedures_callnoreturn'].domToMutation,
getVarModels: Blockly.Blocks['procedures_callnoreturn'].getVarModels,
onchange: Blockly.Blocks['procedures_callnoreturn'].onchange,
customContextMenu:
Blockly.Blocks['procedures_callnoreturn'].customContextMenu,
defType_: 'classes_definition'
};
/**
* @fileoverview Generating Dart for class blocks.
* @author 10MINT (redpandadevs@gmail.com)
*/
'use strict';
// goog.provide('Blockly.Dart.procedures');
// goog.require('Blockly.Dart');
Blockly.Dart['classes_definition'] = function(block) {
// Define a class.
var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var branch = Blockly.Dart.statementToCode(block, 'STACK');
if (Blockly.Dart.STATEMENT_PREFIX) {
var id = block.id.replace(/\$/g, '$$$$'); // Issue 251.
branch = Blockly.Dart.prefixLines(
Blockly.Dart.STATEMENT_PREFIX.replace(/%1/g,
'\'' + id + '\''), Blockly.Dart.INDENT) + branch;
}
if (Blockly.Dart.INFINITE_LOOP_TRAP) {
branch = Blockly.Dart.INFINITE_LOOP_TRAP.replace(/%1/g,
'\'' + block.id + '\'') + branch;
}
var returnType = 'class';
var args = [];
for (var i = 0; i < block.arguments_.length; i++) {
args[i] = Blockly.Dart.variableDB_.getName(block.arguments_[i],
Blockly.Variables.NAME_TYPE);
}
var code = returnType + ' ' + funcName + ' {\n' +
Blockly.Dart.prefixLines(funcName + '(' + args.join(', ') + ') {\n' + branch + '}', Blockly.Dart.INDENT) +
'\n}';
code = Blockly.Dart.scrub_(block, code);
// Add % so as not to collide with helper functions in definitions list.
Blockly.Dart.definitions_['%' + funcName] = code;
return null;
};
Blockly.Dart['classes_caller'] = function(block) {
// Call a class instance
var funcName = Blockly.Dart.variableDB_.getName(block.getFieldValue('NAME'),
Blockly.Procedures.NAME_TYPE);
var args = [];
for (var i = 0; i < block.arguments_.length; i++) {
args[i] = Blockly.Dart.valueToCode(block, 'ARG' + i,
Blockly.Dart.ORDER_NONE) || 'null';
}
var code = funcName + '(' + args.join(', ') + ')';
return [code, Blockly.Dart.ORDER_UNARY_POSTFIX];
};
/**
* Construct the blocks required by the flyout for the classes category.
* @param {!Blockly.Workspace} workspace The workspace containing procedures.
* @return {!Array.<!Element>} Array of XML block elements.
*/
Blockly.Procedures.classFlyoutCategory = function(workspace) {
var xmlList = [];
if (Blockly.Blocks['classes_definition']) {
// <block type="classes_definition" gap="16">
// <field name="NAME">do something</field>
// </block>
var block = Blockly.utils.xml.createElement('block');
block.setAttribute('type', 'classes_definition');
block.setAttribute('gap', 16);
var nameField = Blockly.utils.xml.createElement('field');
nameField.setAttribute('name', 'NAME');
nameField.appendChild(Blockly.utils.xml.createTextNode(
Blockly.Msg['CLASSES_DEFINITION_DEFAULT']));
block.appendChild(nameField);
xmlList.push(block);
}
if (xmlList.length) {
// Add slightly larger gap between system blocks and user calls.
xmlList[xmlList.length - 1].setAttribute('gap', 24);
}
function populateProcedures(procedureList, templateName) {
for (var i = 0; i < procedureList.length; i++) {
var name = procedureList[i][0];
var args = procedureList[i][1];
// <block type="classes_caller" gap="16">
// <mutation name="do something">
// <arg name="x"></arg>
// </mutation>
// </block>
var block = Blockly.utils.xml.createElement('block');
block.setAttribute('type', templateName);
block.setAttribute('gap', 16);
var mutation = Blockly.utils.xml.createElement('mutation');
mutation.setAttribute('name', name);
block.appendChild(mutation);
for (var j = 0; j < args.length; j++) {
var arg = Blockly.utils.xml.createElement('arg');
arg.setAttribute('name', args[j]);
mutation.appendChild(arg);
}
xmlList.push(block);
}
}
var classesReturn = workspace.getBlocksByType('classes_definition', false).map(function(block) {
return /** @type {!Blockly.Procedures.ProcedureBlock} */ (block).getProcedureDef();
});
classesReturn.sort(Blockly.Procedures.procTupleComparator_);
populateProcedures(classesReturn, 'classes_caller');
return xmlList;
};
if (Blockly.Procedures && Blockly.Procedures.classFlyoutCategory) {
Code.workspace.registerToolboxCategoryCallback("CLASS", Blockly.Procedures.classFlyoutCategory);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment