--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/0d750c9e-6f7d-47ef-a240-6923114c6730%40googlegroups.com.
This would probably be best served with a focus group, because I can see arguments for both directions.
Second, which backend API will be better for developers creating blocks?
To unsubscribe from this group and stop receiving emails from it, send an email to blo...@googlegroups.com.
Hi Adam!Thank you for the detailed response :D
This would probably be best served with a focus group, because I can see arguments for both directions.Good idea! Sadly I don't have a focus group at my disposal :( But I'll try to contact the the OpenRoberta people and see if they've done anything like that.
mutationToDom and domToMutation remain the same, because this is purely a UI change.
The only things I've added are two fields, a plus field and a minus field. On construction each field takes in an arbitrary data object (which can be undefined). The data object is passed to the callback (sourceBlock.plus() for plus and sourceBlock.minus() for minus) when the field is clicked.So here's an example of the UI for the 'if and 'if else' blocks (they use the same mutator).
And here's an example for the procedures. You can see how in this case the minus is passed an argId which is later used to remove that specific arg.
So what do you think of that API? Is there any way it could be abstracted or made easier to use?Thank you again for the feed back :D--Beka
Where do you define which values get a - button and which don't?
First of all, I much more prefer the +/- system over the classic mutator menu, that's also feedback I got from young users.
a "-" for each row of elseif and the final else, otherwise it gets really hard to manipulate this block
For texts and lists, I don't believe it is a necessity and I would prefer a single "-" that removes the last element.
We almost finished implementing these changes, I can share a demo when it's done if that helps anyhow.
As for the API, I actually think I like the more ambitious API better! I think it would be easier to bundle it into an object, which is useful when this exists as an extension, and not part of core.
I think how AppInventor handles their mutator API might be a good place to look. All of their mutators are "list" type mutators. The block author has to provide a block to use in composition, an addInput() function and an addEmptyInput() function. Everything else (composition, decomposition, serialization, saving connections) is handled automatically.
I don't think it would be hard to create some sort of PlusMinusListMutator() object which acts similarly. The other functions you mentioned could be added easily as well. Then once setMutator is fixed (so that you can pass more than just icons) it could be applied using that.
More "preset" mutators could be added in the same fasion.
How would you feel about that? Basically take that same idea, a simplified API for list mutators, but bundle it into an object?
If we decide to go with a minus for each individual element, do you think that would be bad for users? Or just unnecessary?
It does answer my question, but I can't say I LIKE the answer. This doesn't really provide a way to put - buttons on an else-if, because you can't cleanly predefine all of the "do" inputs as not needing them.
addPart_: function() {
this.elseIfCount_++;
var minus = new FieldMinus(/* pass something here */);
this.appendValueInput('IF' + this.elseIfCount_)
.setCheck('Boolean')
.appendField(minus, 'MINUS'/* + some id */)
.appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']);
this.appendStatementInput('DO' + this.elseIfCount_)
.appendField(Blockly.Msg['CONTROLS_IF_MSG_THEN']);
// Handle if-elseif-else block.
if (this.getInput('ELSE')) {
this.moveInputBefore('ELSE', /* put at end */ null);
}
},
I like it better too, but when I say it's more ambitious, that means it's going to require changes to the core, because the uniqueness constraint on inputs gets broken. I like the idea of making it an extension; I'm just not sure it CAN be.
MutatorObject.getInput = function(index) {
var id = this.inputIds[index];
return this.sourceBlock.getInput(id);
}
The generator needs an easy, clean way to iterate over the values while keeping them in order and appropriately linked together
generator = function (block) {
// Add initial code
for (var i = 0, input; input = block.mutator.getInput(i); i++) {
// Add input code.
}
return code;
}
We decided to go in the same way makecode did, which is the following - there is only one "+" button, that adds "else" when it's not there already, and "elseif" otherwise.
I really appreciate the first 3 block types. It seems very intuitive for me as a user. I also think that one minus mutator for each parameter is to much.
Hello again,It does answer my question, but I can't say I LIKE the answer. This doesn't really provide a way to put - buttons on an else-if, because you can't cleanly predefine all of the "do" inputs as not needing them.Adding minuses to the non-do inputs would be possible. We'd just have to redefine addPart_ to look like this:
I'll admit it doesn't really look like an 'API' though.
I like it better too, but when I say it's more ambitious, that means it's going to require changes to the core, because the uniqueness constraint on inputs gets broken. I like the idea of making it an extension; I'm just not sure it CAN be.I think we could figure out a way to allow you to interact with things using an index without editting the core. My first instinct would be to have the (theoretical) mutator object keep a list of UUIDs for the inputs. Maybe getInput would look something like:
MutatorObject.getInput = function(index) {
var id = this.inputIds[index];
return this.sourceBlock.getInput(id);
}So you would call: block.mutator.getInput(index) instead of block.getInput(name).
There would have to be work done to get it to work with multiple types of inputs (i.e. if & do). But my point is that I think your idea is definitely achievable in an extension format. Even if under-the-hood doesn't look so nice, I think a good facade could be built.
The generator needs an easy, clean way to iterate over the values while keeping them in order and appropriately linked togetherTotally getcha, there definitely needs to be a way to handle generators cleanly.If we went with an ID array we could always allow the developer to loop over every input via the mutator:
I think that's similar enough to how generators are now that it could work. And it doesn't seem like too much boilerplate.
We decided to go in the same way makecode did, which is the following - there is only one "+" button, that adds "else" when it's not there already, and "elseif" otherwise.Thanks for mentioning that MakeCode uses +/- mutators Léo! I had no clue! I do like the MakeCode version of the if-else block. Definitely more intuitive than I thought it'd be (like you said)! My only problem with it is how you have to keep chasing the + button to add statements. You could move the + to the top, but that might make the plus less intuitive... I'm still not sure how I want to handle these blocks hehe.I'll try and contact the make code people and see if they have anything to add to this discussion :D
To summarize; it feels like currently we're leaning towards:- A minus on each input for the if - else if and if - else if - else blocks.- How to handle elses is still undecided.- Only a single minus on join text and create list.- A minus on each parameter for procedures.
rather than trying to have a single block that can do all of these behaviours in one go, you could make different blocks for different intended use cases
rather than trying to have a single block that can do all of these behaviours in one go, you could make different blocks for different intended use casesI like this idea! What kinds of different blocks would you suggest creating?
> However, nested if/else blocks is a terrible experience for everyone involved. It WORKS, certainly, and for the least-experienced beginner it might be a step more intuitive, but anyone who's built nontrivial logic in any language that can't express else-if without extra visual nesting can attest that it's hard to read and a terrible waste of screen space. So even though this is the hardest use case to accommodate, I think it's also the most important one.This is very much an audience question. If the goal is to build nontrivial logic, and your users already know what they want to build, then nested if/else is bad. It gets in the way of expressing an idea and is really frustrating.But if the goal is to get young users started fast, it's less bad (in my opinion). They eventually get annoyed by it, as the scratch forums attest, but the ease of use for beginners can be worth the trade-off.
Part of the reason our mutators look the way they do is because we aimed to make them more capable rather than more understandable. (We also really didn't intend for everyone to assume that they're our suggested implementation, but that's a messaging issue.)
> I like this idea! What kinds of different blocks would you suggest creating?At minimum, I would split into two use cases:- input reordering is required- input reordering is not required
I think I would split apart function blocks from the rest of the problem, because of the connection between mutating a definition and mutating a caller.
And I would split if/else blocks into a set for beginnings and a set for advanced users, which matches what we've already done in Blockly. Maybe the beginners only get +/-, and the advanced users get chevrons as well.
My question is: Do you think each individual input should have a plus and a minus? Just a minus and not a plus? Or do you think the current design is good?
At minimum, I would split into two use cases:- input reordering is required- input reordering is not required
...that block can, internally, be an if/elseif/else block without any elseifs attached.
I think I would split apart function blocks from the rest of the problem, because of the connection between mutating a definition and mutating a caller.I think this isn't necessarily a problem; as long as the callbacks are sufficiently robust it shouldn't need special-cased implementation. On the other hand, I don't see a problem with leaving function blocks with their existing implementation while we focus on the other use cases.
And I would split if/else blocks into a set for beginnings and a set for advanced users, which matches what we've already done in Blockly. Maybe the beginners only get +/-, and the advanced users get chevrons as well.If we do implement reordering in the same extension instead of having it be an additional extension, that would be a trivial toggle. I guess it'd be something you'd want to save in the mutator DOM.
I prefer one plus per block and one minus per input. In general I think +/- is easier for learners then the current mutator system, so I'm happy that you are exploring this. One downside is that +/- buttons add more visual elements to the already busy workspace. Maybe show them only if the block is selected or hovered over?
Adams system sounds good as well.
...that block can, internally, be an if/elseif/else block without any elseifs attached.This isn't a response to the point you were making Adam, but I just wanted to note that I actually had to move to this method. Adding a mutator to the controls_ifelse block doesn't work because then the developer can't switch from +/- back to default.
I think I would split apart function blocks from the rest of the problem, because of the connection between mutating a definition and mutating a caller.I think this isn't necessarily a problem; as long as the callbacks are sufficiently robust it shouldn't need special-cased implementation. On the other hand, I don't see a problem with leaving function blocks with their existing implementation while we focus on the other use cases.There are actually some things with callers that need to be cleaned up before moving inputs can be implemented. That might have been why Rachel said to set them aside for now.
And I would split if/else blocks into a set for beginnings and a set for advanced users, which matches what we've already done in Blockly. Maybe the beginners only get +/-, and the advanced users get chevrons as well.If we do implement reordering in the same extension instead of having it be an additional extension, that would be a trivial toggle. I guess it'd be something you'd want to save in the mutator DOM.I'm not sure how you'd want to handle that, because I think adding it to the XML would make it hard to "upgrade" a user to the new blocks. I think we'd have to see how developers would want to use it before making any decisions.
I prefer one plus per block and one minus per input. In general I think +/- is easier for learners then the current mutator system, so I'm happy that you are exploring this. One downside is that +/- buttons add more visual elements to the already busy workspace. Maybe show them only if the block is selected or hovered over?Thank you for your input! I'm not sure about hiding them unless the block is selected, because I think that might hurt discoverability. For now I'm going to leave them visible by default. Clutter is definitely a thing though! So I think this is a good idea to keep in mind.
Adams system sounds good as well.A note about Adam's system: I also think it sounds really good! But I know that he could definitely do it better than I could, so I think I'm going to leave that to him if he wants to implement it hehe.
Also I really like your suggested "dragged over" block. I think that pretty much solves the reordering issue! Nice suggestion!
On Sat, Mar 28, 2020 at 8:17 PM Beka Westberg <bekawe...@gmail.com> wrote:I think I would split apart function blocks from the rest of the problem, because of the connection between mutating a definition and mutating a caller.I think this isn't necessarily a problem; as long as the callbacks are sufficiently robust it shouldn't need special-cased implementation. On the other hand, I don't see a problem with leaving function blocks with their existing implementation while we focus on the other use cases.There are actually some things with callers that need to be cleaned up before moving inputs can be implemented. That might have been why Rachel said to set them aside for now.I wasn't talking about moving inputs, though. Do those things prevent using +/- instead of the existing mutator UI?
On Sunday, March 29, 2020 at 6:57:14 AM UTC-7, Coda Highland wrote:
On Sat, Mar 28, 2020 at 8:17 PM Beka Westberg <bekawe...@gmail.com> wrote:
...that block can, internally, be an if/elseif/else block without any elseifs attached.This isn't a response to the point you were making Adam, but I just wanted to note that I actually had to move to this method. Adding a mutator to the controls_ifelse block doesn't work because then the developer can't switch from +/- back to default.Why not? It should just be a property on the mutator.
Sorry I didn't explain this very well. The default controls_ifelse block doesn't have a mutator. So if we give it a mutator via the +/- mutators extension thing, and allow the user to mutate the block, default blockly won't be able to de-serialize those mutations. For this extension I wanted to make sure developers could switch back and forth between the mutator UIs, so the mutator on the controls_ifelse block had to go.But the same functionality can be achieved with the controls_if block alone, so it's all good :D
--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blockly+u...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/blockly/52f62197-2afe-4273-8124-ce3fc3ab4e57%40googlegroups.com.
Thank you for sharing Léo!I like how you decided to move the +/- buttons for lists from the end of the block to the front. That avoids the annoying chasing I always hate haha.One thing I never asked: How did you implement your buttons? Are they: icons, an image field subclass, just image fields (i.e. using constructor params), or something else? After some discussion we decided to just use an image field for the plugin (which I think works well!). I'm just curious how you guys decided to tackle this.P.S. I love your app! Especially that matrix block. Forcing it to be square is a really clever, elegant approach! I kinda really want one now lolThank you again I enjoyed getting to take a look :D--Beka
On Thu, Apr 23, 2020 at 4:43 AM Léo Briand <leobr...@gmail.com> wrote:
As promised earlier, here is a link to how we implemented the +/- in Vittascience platform: https://fr.vittascience.com/python/?link=5ea17ed78d2c8Feel free to tell me your opinion on this!Best,
Léo--
You received this message because you are subscribed to the Google Groups "Blockly" group.
To unsubscribe from this group and stop receiving emails from it, send an email to blo...@googlegroups.com.
{ |
"type": "text_join", |
"output": "String", |
"outputShape": Blockly.OUTPUT_SHAPE_ROUND, |
"style": "text_blocks", |
"helpUrl": "%{BKY_TEXT_JOIN_HELPURL}", |
"tooltip": "%{BKY_TEXT_JOIN_TOOLTIP}", |
"extensions": [ |
"block_buttons_plus_minus", |
"text_join_init" |
], |
"mutator": "text_join_mutator" |
// Block for joining text items I would be happy to share more if you tell me what you would like to see. Best, Léo |