mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2025-03-14 01:09:51 -04:00
switch from rejectReporters
flag to acceptReporters
Also add more extensive documentation around extension menu definitions, including some considerations to think about before making a menu accept reporters.
This commit is contained in:
parent
e7bf49c8df
commit
3fbed88a95
2 changed files with 127 additions and 10 deletions
|
@ -120,6 +120,123 @@ class SomeBlocks {
|
|||
}
|
||||
```
|
||||
|
||||
### Defining a Menu
|
||||
|
||||
To display a drop-down menu for a block argument, specify the `menu` property of that argument and a matching item in
|
||||
the `menus` section of your extension's definition:
|
||||
|
||||
```js
|
||||
return {
|
||||
// ...
|
||||
blocks: [
|
||||
{
|
||||
// ...
|
||||
arguments: {
|
||||
FOO: {
|
||||
type: ArgumentType.NUMBER,
|
||||
menu: 'fooMenu'
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
menus: {
|
||||
fooMenu: {
|
||||
items: ['a', 'b', 'c']
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The items in a menu may be specified with an array or with the name of a function which returns an array. The two
|
||||
simplest forms for menu definitions are:
|
||||
|
||||
```js
|
||||
getInfo () {
|
||||
return {
|
||||
menus: {
|
||||
staticMenu: ['static 1', 'static 2', 'static 3'],
|
||||
dynamicMenu: 'getDynamicMenuItems'
|
||||
}
|
||||
};
|
||||
}
|
||||
// this member function will be called each time the menu opens
|
||||
getDynamicMenuItems () {
|
||||
return ['dynamic 1', 'dynamic 2', 'dynamic 3'];
|
||||
}
|
||||
```
|
||||
|
||||
The examples above are shorthand for these equivalent definitions:
|
||||
|
||||
```js
|
||||
getInfo () {
|
||||
return {
|
||||
menus: {
|
||||
staticMenu: {
|
||||
items: ['static 1', 'static 2', 'static 3']
|
||||
},
|
||||
dynamicMenu: {
|
||||
items: 'getDynamicMenuItems'
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
// this member function will be called each time the menu opens
|
||||
getDynamicMenuItems () {
|
||||
return ['dynamic 1', 'dynamic 2', 'dynamic 3'];
|
||||
}
|
||||
```
|
||||
|
||||
If a menu item needs a label that doesn't match its value -- for example, if the label needs to be displayed in the
|
||||
user's language but the value needs to stay constant -- the menu item may be an object instead of a string. This works
|
||||
for both static and dynamic menu items:
|
||||
|
||||
```js
|
||||
menus: {
|
||||
staticMenu: [
|
||||
{
|
||||
text: formatMessage(/* ... */),
|
||||
value: 42
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
#### Accepting reporters ("droppable" menus)
|
||||
|
||||
By default it is not possible to specify the value of a dropdown menu by inserting a reporter block. While we
|
||||
encourage extension authors to make their menus accept reporters when possible, doing so requires careful
|
||||
consideration to avoid confusion and frustration on the part of those using the extension.
|
||||
|
||||
A few of these considerations include:
|
||||
|
||||
* The valid values for the menu should not change when the user changes the Scratch language setting.
|
||||
* In particular, changing languages should never break a working project.
|
||||
* The average Scratch user should be able to figure out the valid values for this input without referring to extension
|
||||
documentation.
|
||||
* One way to ensure this is to make an item's text match or include the item's value.
|
||||
* The block should accept any value as input, even "invalid" values.
|
||||
* Scratch has no concept of a runtime error!
|
||||
* For a command block, sometimes the best option is to do nothing.
|
||||
* For a reporter, returning zero or the empty string might make sense.
|
||||
* The block should be forgiving in its interpretation of inputs.
|
||||
* For example, if the block expects a string and receives a number it may make sense to interpret the number as a
|
||||
string instead of treating it as invalid input.
|
||||
|
||||
The `acceptReporters` flag indicates that the user can drop a reporter onto the menu input:
|
||||
|
||||
```js
|
||||
menus: {
|
||||
staticMenu: {
|
||||
acceptReporters: true,
|
||||
items: [/*...*/]
|
||||
},
|
||||
dynamicMenu: {
|
||||
acceptReporters: true,
|
||||
items: 'getDynamicMenuItems'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Annotated Example
|
||||
|
||||
```js
|
||||
|
@ -315,8 +432,8 @@ class SomeBlocks {
|
|||
|
||||
// The examples above are shorthand for setting only the `items` property in this full form:
|
||||
menuC: {
|
||||
// This flag makes a "non-droppable" menu: the menu will not accept reporters.
|
||||
rejectReporters: true,
|
||||
// This flag makes a "droppable" menu: the menu will allow dropping a reporter in for the input.
|
||||
acceptReporters: true,
|
||||
|
||||
// The `item` property may be an array or function name as in previous menu examples.
|
||||
items: [/*...*/] || 'getItemsForMenuC'
|
||||
|
|
|
@ -894,7 +894,7 @@ class Runtime extends EventEmitter {
|
|||
* @param {string} menuName - the name of the menu
|
||||
* @param {object} menuInfo - a description of this menu and its items
|
||||
* @property {*} items - an array of menu items or a function to retrieve such an array
|
||||
* @property {boolean} [rejectReporters] - if true, prevent dropping reporters onto this menu
|
||||
* @property {boolean} [acceptReporters] - if true, allow dropping reporters onto this menu
|
||||
* @param {CategoryInfo} categoryInfo - the category for this block
|
||||
* @returns {object} - a JSON-esque object ready for scratch-blocks' consumption
|
||||
* @private
|
||||
|
@ -927,8 +927,8 @@ class Runtime extends EventEmitter {
|
|||
colour: categoryInfo.color1,
|
||||
colourSecondary: categoryInfo.color2,
|
||||
colourTertiary: categoryInfo.color3,
|
||||
outputShape: menuInfo.rejectReporters ?
|
||||
ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE : ScratchBlocksConstants.OUTPUT_SHAPE_ROUND,
|
||||
outputShape: menuInfo.acceptReporters ?
|
||||
ScratchBlocksConstants.OUTPUT_SHAPE_ROUND : ScratchBlocksConstants.OUTPUT_SHAPE_SQUARE,
|
||||
args0: [
|
||||
{
|
||||
type: 'field_dropdown',
|
||||
|
@ -1235,16 +1235,16 @@ class Runtime extends EventEmitter {
|
|||
let fieldName;
|
||||
if (argInfo.menu) {
|
||||
const menuInfo = argInfo.menu && context.categoryInfo.menuInfo[argInfo.menu];
|
||||
if (menuInfo.rejectReporters) {
|
||||
if (menuInfo.acceptReporters) {
|
||||
valueName = placeholder;
|
||||
shadowType = this._makeExtensionMenuId(argInfo.menu, context.categoryInfo.id);
|
||||
fieldName = argInfo.menu;
|
||||
} else {
|
||||
argJSON.type = 'field_dropdown';
|
||||
argJSON.options = menuInfo.items;
|
||||
valueName = null;
|
||||
shadowType = null;
|
||||
fieldName = placeholder;
|
||||
} else {
|
||||
valueName = placeholder;
|
||||
shadowType = this._makeExtensionMenuId(argInfo.menu, context.categoryInfo.id);
|
||||
fieldName = argInfo.menu;
|
||||
}
|
||||
} else {
|
||||
valueName = placeholder;
|
||||
|
|
Loading…
Reference in a new issue