Extensões são funções executadas em cada bloco de um determinado tipo, à medida que o bloco criados. Eles geralmente adicionam uma configuração ou comportamento personalizado a um bloco.
Um mutador é um tipo especial de extensão que adiciona serialização personalizada. às vezes interface, para um bloco.
Extensões
Extensões são funções executadas em cada bloco de um determinado tipo, à medida que o bloco criados. Ele pode adicionar uma configuração personalizada (por exemplo, definir a dica do bloco) ou comportamento personalizado (por exemplo, adicionar uma escuta de evento ao bloco).
// This extension sets the block's tooltip to be a function which displays
// the parent block's tooltip (if it exists).
Blockly.Extensions.register(
'parent_tooltip_extension',
function() { // this refers to the block that the extension is being run on
var thisBlock = this;
this.setTooltip(function() {
var parent = thisBlock.getParent();
return (parent && parent.getInputsInline() && parent.tooltip) ||
Blockly.Msg.MATH_NUMBER_TOOLTIP;
});
});
As extensões precisam ser "registradas" para que possam ser associados a uma string
de dados. Em seguida, você pode atribuir essa chave de string à propriedade extensions
do
do tipo de bloco JSON
definição para aplicar a
extensão ao bloco.
{
//...,
"extensions": ["parent_tooltip_extension",]
}
Você também pode adicionar várias extensões de uma vez. Observe que o extensions
deve ser uma matriz, mesmo que você esteja aplicando apenas uma extensão.
{
//...,
"extensions": ["parent_tooltip_extension", "break_warning_extension"],
}
Mixins
O Blockly também oferece um método conveniente para situações em que você deseja adicionar algumas propriedades/funções auxiliares em um bloco, mas não executá-las imediatamente. Isso permite que você registre um mixin Objeto que contém todas as propriedades/métodos adicionais. O objeto mixin é então envolvido em uma função que aplica a mistura sempre que uma instância de o tipo de bloco fornecido é criado.
Blockly.Extensions.registerMixin('my_mixin', {
someProperty: 'a cool value',
someMethod: function() {
// Do something cool!
}
))`
Chaves de string associadas a mixins podem ser referenciadas em JSON, assim como qualquer outra .
{
//...,
"extensions": ["my_mixin"],
}
Mutadores
Um mutador é um tipo especial de extensão que adiciona serialização adicional
que é salvo e carregado) em um bloco. Por exemplo, o gerenciador
Os blocos controls_if
e list_create_with
precisam de serialização extra para que
elas podem economizar a quantidade de entradas que têm.
Alterar a forma do bloco não significa necessariamente que você precise
com serialização extra. Por exemplo, o bloco math_number_property
muda
forma, mas faz isso com base em um campo suspenso, cujo valor já é
serializados. Assim, ele pode usar apenas um campo
validador e não
precisa de um mutador.
Consulte a serialização página para mais informações sobre quando você precisa e quando não precisa de um mutador.
Os mutadores também oferecem uma IU integrada para que os usuários mudem as formas dos blocos se você fornece alguns métodos opcionais.
Hooks de serialização
Os mutadores têm dois pares de hooks de serialização com os quais trabalham. Um par de ganchos funciona com o novo sistema de serialização JSON, e o outro par funciona com a antigo sistema de serialização XML. Você precisa fornecer pelo menos um desses pares.
saveExtraState e loadExtraState
saveExtraState
e loadExtraState
são hooks de serialização que funcionam com a
novo sistema de serialização JSON. saveExtraState
retorna um JSON serializável
um valor que representa o estado extra do bloco, e loadExtraState
aceita esse mesmo valor serializável do JSON e o aplica ao bloco.
// These are the serialization hooks for the lists_create_with block.
saveExtraState: function() {
return {
'itemCount': this.itemCount_,
};
},
loadExtraState: function(state) {
this.itemCount_ = state['itemCount'];
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
O JSON resultante será semelhante a este:
{
"type": "lists_create_with",
"extraState": {
"itemCount": 3 // or whatever the count is
}
}
Sem estado
Se o bloco estiver no estado padrão quando for serializado, então seu
O método saveExtraState
pode retornar null
para indicar isso. Se as
O método saveExtraState
retorna null
, e nenhuma propriedade extraState
é adicionada a
no JSON. Isso mantém o tamanho do arquivo salvo pequeno.
Serialização completa e dados de backup
saveExtraState
também recebe um parâmetro doFullSerialization
opcional. Isso
é usado por blocos que fazem referência ao estado serializado por uma
serializer (como modelos de dados de apoio). O parâmetro indica que
o estado referenciado não estará disponível quando o bloco for desserializado, então o
deve serializar todo o estado de apoio. Por exemplo,
verdadeiro quando um bloco individual é serializado ou quando um bloco é copiado e colado.
Dois casos de uso comuns para isso são:
- Quando um bloco individual é carregado em um espaço de trabalho em que os dados de apoio não existe, ele tem informações suficientes em seu próprio estado para criar um novo modelo de dados.
- Quando um bloco é copiado e colado, ele sempre cria um novo apoio modelo de dados em vez de referenciar um que já existe.
Alguns blocos que usam isso são
Blocos @blockly/block-shareable-procedures. Normalmente
eles serializam uma referência a um modelo de dados de apoio, que armazena seu estado.
No entanto, se o parâmetro doFullSerialization
for verdadeiro, eles serializam todos os
o estado delas. Os blocos de procedimento compartilhável usam isso para garantir que, quando
são copiados e colados eles criam um novo modelo de dados de apoio, em vez de referenciar um
modelo atual.
mutateToDom e domToMutation
mutationToDom
e domToMutation
são hooks de serialização que funcionam com a
antigo sistema de serialização XML. Use esses ganchos apenas se precisar (por exemplo,
trabalhando em uma base de código antiga que ainda não foi migrada), use
saveExtraState
e loadExtraState
.
mutationToDom
retorna um nó XML que representa o estado extra da
bloco, e domToMutation
aceita o mesmo nó XML e aplica o estado a
do bloco.
// These are the old XML serialization hooks for the lists_create_with block.
mutationToDom: function() {
// You *must* create a <mutation></mutation> element.
// This element can have children.
var container = Blockly.utils.xml.createElement('mutation');
container.setAttribute('items', this.itemCount_);
return container;
},
domToMutation: function(xmlElement) {
this.itemCount_ = parseInt(xmlElement.getAttribute('items'), 10);
// This is a helper function which adds or removes inputs from the block.
this.updateShape_();
},
O XML resultante será semelhante a este:
<block type="lists_create_with">
<mutation items="3"></mutation>
</block>
Se a função mutationToDom
retornar nulo, nenhum elemento extra será
adicionados ao XML.
Ganchos da interface
Se você fornecer certas funções como parte do mutador, o Blockly adicionará um "mutator" padrão interface ao seu bloco.
Você não precisa usar essa interface se quiser adicionar serialização extra. Você pode usar uma interface personalizada, como o bloco blocos-mais-menos plug-in fornece, ou você pode não usar nenhuma interface.
compor e decompor
A interface padrão depende das funções compose
e decompose
.
decompose
"explode" o bloco em subblocos menores que podem ser movidos
adicionados e excluídos. Essa função deve retornar um "bloco superior" que é
no bloco principal no espaço de trabalho do mutator ao qual os subblocos se conectam.
Em seguida, compose
interpreta a configuração dos subblocos e os usa para
modificar o bloco principal. Essa função precisa aceitar o bloco superior que era
retornados por decompose
como um parâmetro.
Essas funções são "misturadas" ao bloco sendo "mutado" então this
pode ser usada para se referir a esse bloco.
// These are the decompose and compose functions for the lists_create_with block.
decompose: function(workspace) {
// This is a special sub-block that only gets created in the mutator UI.
// It acts as our "top block"
var topBlock = workspace.newBlock('lists_create_with_container');
topBlock.initSvg();
// Then we add one sub-block for each item in the list.
var connection = topBlock.getInput('STACK').connection;
for (var i = 0; i < this.itemCount_; i++) {
var itemBlock = workspace.newBlock('lists_create_with_item');
itemBlock.initSvg();
connection.connect(itemBlock.previousConnection);
connection = itemBlock.nextConnection;
}
// And finally we have to return the top-block.
return topBlock;
},
// The container block is the top-block returned by decompose.
compose: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we collect up all of the connections of on our main block that are
// referenced by our sub-blocks.
// This relates to the saveConnections hook (explained below).
var connections = [];
while (itemBlock && !itemBlock.isInsertionMarker()) { // Ignore insertion markers!
connections.push(itemBlock.valueConnection_);
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
// Then we disconnect any children where the sub-block associated with that
// child has been deleted/removed from the stack.
for (var i = 0; i < this.itemCount_; i++) {
var connection = this.getInput('ADD' + i).connection.targetConnection;
if (connection && connections.indexOf(connection) == -1) {
connection.disconnect();
}
}
// Then we update the shape of our block (removing or adding iputs as necessary).
// `this` refers to the main block.
this.itemCount_ = connections.length;
this.updateShape_();
// And finally we reconnect any child blocks.
for (var i = 0; i < this.itemCount_; i++) {
connections[i].reconnect(this, 'ADD' + i);
}
},
saveConnections
Também é possível definir uma função saveConnections
que funcione com
à interface padrão. Essa função dá a você a chance de associar filhos de
bloco principal (que existe no espaço de trabalho principal) com subblocos que existem no
seu espaço de trabalho mutador. Você pode usar esses dados para garantir que o compose
funciona reconecta adequadamente os filhos do bloco principal quando seus
sub-blocos são reorganizados.
saveConnections
precisa aceitar o "bloco superior" retornado por decompose
como parâmetro. Se a função saveConnections
estiver definida, o Blockly
o chamará antes de chamar compose
.
saveConnections: function(topBlock) {
// First we get the first sub-block (which represents an input on our main block).
var itemBlock = topBlock.getInputTargetBlock('STACK');
// Then we go through and assign references to connections on our main block
// (input.connection.targetConnection) to properties on our sub blocks
// (itemBlock.valueConnection_).
var i = 0;
while (itemBlock) {
// `this` refers to the main block (which is being "mutated").
var input = this.getInput('ADD' + i);
// This is the important line of this function!
itemBlock.valueConnection_ = input && input.connection.targetConnection;
i++;
itemBlock = itemBlock.nextConnection &&
itemBlock.nextConnection.targetBlock();
}
},
Registrando
Os mutadores são apenas um tipo especial de extensão, então eles também precisam ser registradas antes de serem usadas no JSON do tipo de bloco definição.
// Function signature.
Blockly.Extensions.registerMutator(name, mixinObj, opt_helperFn, opt_blockList);
// Example call.
Blockly.Extensions.registerMutator(
'controls_if_mutator',
{ /* mutator methods */ },
undefined,
['controls_if_elseif', 'controls_if_else']);
name
: uma string a ser associada ao mutador para que você possa usá-lo em JSON.mixinObj
: um objeto que contém os vários métodos de mutação. Por exemplo:saveExtraState
eloadExtraState
.opt_helperFn
: uma função auxiliar opcional que será ser executada no bloco depois que o mixin for misturado.opt_blockList
: uma matriz opcional de tipos de bloco (como strings) que serão adicionado ao menu suspenso na interface do mutator padrão, se os métodos da interface também estiverem definido.
Ao contrário das extensões, cada tipo de bloqueio só pode ter um mutador.
{
//...
"mutator": "controls_if_mutator"
}
Função auxiliar
Junto com o mixin, um mutador pode registrar uma função auxiliar. Essa função é executada em cada bloco do tipo especificado depois que ele é criado e o mixinObj é adicionados. Ela pode ser usada para adicionar outros gatilhos ou efeitos a uma mutação.
Por exemplo, você pode adicionar um assistente ao seu bloco tipo lista que define o Número inicial de itens:
var helper = function() {
this.itemCount_ = 5;
this.updateShape();
}