mirror of
https://github.com/google/blockly.git
synced 2026-01-11 02:47:09 +01:00
Blockly Factory: Shadow Block Validation in Workspace Factory (#563)
* Added more shadow block validation and cascading when adding shadow blocks * Rebased and small bug fix in add category * Removed warning text in addShadow * Broke long if statement into inlined function
This commit is contained in:
committed by
picklesrus
parent
204e28f63f
commit
00c04688da
@@ -117,6 +117,8 @@ WorkspaceFactoryController.prototype.addCategory = function() {
|
||||
this.view.setCategoryTabSelection(id, true);
|
||||
// Allow user to use the default options for injecting with categories.
|
||||
this.allowToSetDefaultOptions();
|
||||
// Update preview here in case exit early.
|
||||
this.updatePreview();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,12 +862,62 @@ WorkspaceFactoryController.prototype.addShadow = function() {
|
||||
if (!Blockly.selected) {
|
||||
return;
|
||||
}
|
||||
this.view.markShadowBlock(Blockly.selected);
|
||||
this.model.addShadowBlock(Blockly.selected.id);
|
||||
// Clear any previous warnings on the block (would only have warnings on
|
||||
// a non-shadow block if it was nested inside another shadow block).
|
||||
Blockly.selected.setWarningText(null);
|
||||
// Set selected block and all children as shadow blocks.
|
||||
this.addShadowForBlockAndChildren_(Blockly.selected);
|
||||
|
||||
// Save and update the preview.
|
||||
this.saveStateFromWorkspace();
|
||||
this.updatePreview();
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets a block and all of its children to be user-generated shadow blocks,
|
||||
* both in the model and view.
|
||||
* @private
|
||||
*
|
||||
* @param {!Blockly.Block} block The block to be converted to a user-generated
|
||||
* shadow block.
|
||||
*/
|
||||
WorkspaceFactoryController.prototype.addShadowForBlockAndChildren_ =
|
||||
function(block) {
|
||||
// Convert to shadow block.
|
||||
this.view.markShadowBlock(block);
|
||||
this.model.addShadowBlock(block.id);
|
||||
|
||||
if (this.hasVariableField(block)) {
|
||||
block.setWarningText('Cannot make variable blocks shadow blocks.');
|
||||
}
|
||||
|
||||
// Convert all children to shadow blocks recursively.
|
||||
var children = block.getChildren();
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
this.addShadowForBlockAndChildren_(children[i]);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if a block has a variable field. Blocks with variable fields cannot
|
||||
* be shadow blocks.
|
||||
*
|
||||
* @param {Blockly.Block} block The block to check if a variable field exists.
|
||||
* @return {boolean} True if the block has a variable field, false otherwise.
|
||||
*/
|
||||
WorkspaceFactoryController.prototype.hasVariableField = function(block) {
|
||||
if (!block) {
|
||||
return false;
|
||||
}
|
||||
for (var i = 0; i < block.inputList.length; i++) {
|
||||
if (block.inputList[i].fieldRow.length > 0 &&
|
||||
block.inputList[i].fieldRow[0].name == 'VAR') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* If the currently selected block is a user-generated shadow block, this
|
||||
* function makes it a normal block again, removing it from the list of
|
||||
@@ -879,6 +931,10 @@ WorkspaceFactoryController.prototype.removeShadow = function() {
|
||||
}
|
||||
this.model.removeShadowBlock(Blockly.selected.id);
|
||||
this.view.unmarkShadowBlock(Blockly.selected);
|
||||
|
||||
// If turning invalid shadow block back to normal block, remove warning.
|
||||
Blockly.selected.setWarningText(null);
|
||||
|
||||
this.saveStateFromWorkspace();
|
||||
this.updatePreview();
|
||||
};
|
||||
|
||||
@@ -339,9 +339,8 @@ document.getElementById('button_import').addEventListener
|
||||
controller.removeShadow();
|
||||
document.getElementById('dropdownDiv_editShadowRemove').classList.
|
||||
remove("show");
|
||||
// If turning invalid shadow block back to normal block, remove
|
||||
// warning and disable block editing privileges.
|
||||
Blockly.selected.setWarningText(null);
|
||||
// Disable shadow editing button if turning invalid shadow block back
|
||||
// to normal block.
|
||||
if (!Blockly.selected.getSurroundParent()) {
|
||||
document.getElementById('button_editShadow').disabled = true;
|
||||
}
|
||||
@@ -374,6 +373,16 @@ WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
|
||||
}
|
||||
});
|
||||
|
||||
// Determines if a block breaks shadow block placement rules.
|
||||
// Breaks rules if (1) a shadow block no longer has a valid
|
||||
// parent, or (2) a normal block is inside of a shadow block.
|
||||
var isInvalidBlockPlacement = function(block) {
|
||||
return ((controller.isUserGenShadowBlock(block.id) &&
|
||||
!block.getSurroundParent()) ||
|
||||
(!controller.isUserGenShadowBlock(block.id) && block.getSurroundParent()
|
||||
&& controller.isUserGenShadowBlock(block.getSurroundParent().id)));
|
||||
}
|
||||
|
||||
// Add change listeners for toolbox workspace in workspace factory.
|
||||
controller.toolboxWorkspace.addChangeListener(function(e) {
|
||||
// Listen for Blockly move and delete events to update preview.
|
||||
@@ -394,24 +403,48 @@ WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
|
||||
e.element == 'selected')) {
|
||||
var selected = Blockly.selected;
|
||||
|
||||
if (selected != null && selected.getSurroundParent() != null) {
|
||||
if (selected != null && selected.getSurroundParent() != null &&
|
||||
!controller.isUserGenShadowBlock(selected.getSurroundParent().id)) {
|
||||
// Selected block is a valid shadow block or could be a valid shadow
|
||||
// block.
|
||||
|
||||
// A valid shadow block is selected. Enable block editing and remove
|
||||
// warnings.
|
||||
// Enable block editing and remove warnings if the block is not a
|
||||
// variable user-generated shadow block.
|
||||
document.getElementById('button_editShadow').disabled = false;
|
||||
Blockly.selected.setWarningText(null);
|
||||
if (!controller.hasVariableField(selected)) {
|
||||
selected.setWarningText(null);
|
||||
}
|
||||
} else {
|
||||
if (selected != null && controller.isUserGenShadowBlock(selected.id)) {
|
||||
// Selected block cannot be a valid shadow block.
|
||||
|
||||
// Provide warning if shadow block is moved and is no longer a valid
|
||||
// shadow block.
|
||||
Blockly.selected.setWarningText('Shadow blocks must be nested' +
|
||||
' inside other blocks to be displayed.');
|
||||
if (selected != null && isInvalidBlockPlacement(selected)) {
|
||||
// Selected block breaks shadow block rules.
|
||||
// Invalid shadow block if (1) a shadow block no longer has a valid
|
||||
// parent, or (2) a normal block is inside of a shadow block.
|
||||
|
||||
if (!controller.isUserGenShadowBlock(selected.id)) {
|
||||
// Warn if a non-shadow block is nested inside a shadow block.
|
||||
selected.setWarningText('Only shadow blocks can be nested inside '
|
||||
+ 'other shadow blocks.');
|
||||
} else if (!controller.hasVariableField(selected)) {
|
||||
// Warn if a shadow block is invalid only if not replacing
|
||||
// warning for variables.
|
||||
selected.setWarningText('Shadow blocks must be nested inside other'
|
||||
+ ' blocks.')
|
||||
}
|
||||
|
||||
// Give editing options so that the user can make an invalid shadow
|
||||
// block a normal block.
|
||||
document.getElementById('button_editShadow').disabled = false;
|
||||
} else {
|
||||
// Selected block does not break any shadow block rules, but cannot
|
||||
// be a shadow block.
|
||||
|
||||
// Remove possible 'invalid shadow block placement' warning.
|
||||
if (selected != null && (!controller.hasVariableField(selected) ||
|
||||
!controller.isUserGenShadowBlock(selected.id))) {
|
||||
selected.setWarningText(null);
|
||||
}
|
||||
|
||||
// No block selected that is a shadow block or could be a valid shadow
|
||||
// block. Disable block editing.
|
||||
|
||||
Reference in New Issue
Block a user