Skip to content

Commit 23a42c7

Browse files
authored
operators.js -- expandable math block
1 parent de4d667 commit 23a42c7

File tree

1 file changed

+134
-4
lines changed

1 file changed

+134
-4
lines changed

blocks_vertical/operators.js

Lines changed: 134 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,136 @@ Blockly.Blocks['operator_divide'] = {
124124
}
125125
};
126126

127+
Blockly.Blocks['operator_expandableMath'] = {
128+
/**
129+
* pm: Block for performing multiple math operations (determined by user)
130+
* @this Blockly.Block
131+
*/
132+
init: function () {
133+
this.jsonInit({
134+
"message0": '%1 %2',
135+
"args0": [
136+
{
137+
"type": "field_expandable_remove",
138+
"name": "REMOVE"
139+
},
140+
{
141+
"type": "field_expandable_add",
142+
"name": "ADD"
143+
}
144+
],
145+
"category": Blockly.Categories.operators,
146+
"extensions": ["colours_operators", "output_number"]
147+
});
148+
149+
this.inputs_ = 2;
150+
if (this.isInFlyout) {
151+
const input1 = this.appendValueInput("NUM1");
152+
this.fillInBlock(input1.connection, 0);
153+
const input2 = this.appendValueInput("NUM2");
154+
input2.appendField(this.menuGenerator());
155+
this.fillInBlock(input2.connection, 1);
156+
}
157+
},
158+
159+
menuGenerator: function() {
160+
const dropdown = new Blockly.FieldDropdown(function () {
161+
return [
162+
["+", "+"], ["-", "-"],
163+
["*", "*"], ["/", "/"],
164+
["^", "^"],
165+
];
166+
});
167+
const ogSetValue = dropdown.setValue;
168+
dropdown.setValue = function (value, omitMutation) {
169+
const srcBlock = this.sourceBlock_;
170+
let oldMutation;
171+
if (!omitMutation) oldMutation = Blockly.Xml.domToText(srcBlock.mutationToDom());
172+
173+
ogSetValue.call(this, value);
174+
if (!omitMutation) {
175+
const newMutation = Blockly.Xml.domToText(srcBlock.mutationToDom());
176+
Blockly.Events.fire(new Blockly.Events.BlockChange(
177+
srcBlock, 'mutation', null, oldMutation, newMutation
178+
));
179+
}
180+
}
181+
return dropdown;
182+
},
183+
fillInBlock: function (connection, index) {
184+
if (connection.sourceBlock_.isInsertionMarker_) return;
185+
const block = this.workspace.newBlock('math_number');
186+
block.setShadow(true);
187+
block.initSvg();
188+
block.render(false);
189+
block.outputConnection.connect(connection);
190+
},
191+
192+
mutationToDom: function () {
193+
// on save
194+
const container = document.createElement("mutation");
195+
let number = Number(this.inputs_);
196+
if (isNaN(number)) number = 1;
197+
container.setAttribute("inputcount", String(number));
198+
let orderedOperations = "";
199+
for (var i = 1; i < this.inputList.length; i++) {
200+
const input = this.inputList[i];
201+
if (input.fieldRow[0]) orderedOperations += input.fieldRow[0].getValue();
202+
}
203+
container.setAttribute("menuvalues", orderedOperations);
204+
return container;
205+
},
206+
207+
domToMutation: function (xmlElement) {
208+
// on load
209+
const inputCount = Number(xmlElement.getAttribute("inputcount"));
210+
const menuValues = String(xmlElement.getAttribute("menuvalues"));
211+
this.inputs_ = isNaN(inputCount) ? 0 : inputCount;
212+
for (let i = 0; i < this.inputs_; i++) {
213+
const input = this.appendValueInput(`NUM${i + 1}`);
214+
if (i > 0) {
215+
const menu = input.appendField(this.menuGenerator());
216+
menu.fieldRow[0].setValue(menuValues[i - 1] ? menuValues[i - 1] : "+", true);
217+
}
218+
this.fillInBlock(input.connection, i);
219+
}
220+
queueMicrotask(() => {
221+
const connections = this.getConnections_();
222+
for (let i = 1; i < connections.length; i++) {
223+
const block = connections[i].targetBlock();
224+
if (!block) continue;
225+
if (!block.category_ && !block.isShadow()) block.dispose();
226+
}
227+
});
228+
},
229+
230+
onExpandableButtonClicked_: function (isAdding) {
231+
// Create an event group to keep field value and mutator in sync
232+
// Return null at the end because setValue is called here already.
233+
Blockly.Events.setGroup(true);
234+
var oldMutation = Blockly.Xml.domToText(this.mutationToDom());
235+
if (isAdding) {
236+
this.inputs_++;
237+
const number = this.inputs_;
238+
const newInput = this.appendValueInput(`NUM${number}`);
239+
newInput.appendField(this.menuGenerator());
240+
this.fillInBlock(newInput.connection, number - 1);
241+
} else if (this.inputs_ > 1) {
242+
const number = this.inputs_;
243+
this.removeInput(`NUM${number}`);
244+
this.inputs_--;
245+
}
246+
this.initSvg();
247+
if (this.rendered) this.render();
248+
249+
const newMutation = Blockly.Xml.domToText(this.mutationToDom());
250+
Blockly.Events.fire(new Blockly.Events.BlockChange(
251+
this, 'mutation', null, oldMutation, newMutation
252+
));
253+
Blockly.Events.setGroup(false);
254+
}
255+
};
256+
127257
Blockly.Blocks['operator_random'] = {
128258
/**
129259
* Block for picking a random number.
@@ -518,7 +648,6 @@ Blockly.Blocks['operator_join3'] = {
518648
}
519649
};
520650

521-
522651
Blockly.Blocks['operators_expandablejoininputs'] = {
523652
/**
524653
* pm: Block for joining strings together (determined by user)
@@ -558,7 +687,7 @@ Blockly.Blocks['operators_expandablejoininputs'] = {
558687
block.setFieldValue(text ? text : "...", "TEXT");
559688
block.setShadow(true);
560689
block.initSvg();
561-
block.render(true);
690+
block.render(false);
562691
block.outputConnection.connect(connection);
563692
},
564693

@@ -608,8 +737,9 @@ Blockly.Blocks['operators_expandablejoininputs'] = {
608737
if (this.rendered) this.render();
609738

610739
var newMutation = Blockly.Xml.domToText(this.mutationToDom());
611-
Blockly.Events.fire(new Blockly.Events.BlockChange(this,
612-
'mutation', null, oldMutation, newMutation));
740+
Blockly.Events.fire(new Blockly.Events.BlockChange(
741+
this, 'mutation', null, oldMutation, newMutation
742+
));
613743
Blockly.Events.setGroup(false);
614744
}
615745
};

0 commit comments

Comments
 (0)