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:
Emma Dauterman
2016-08-18 15:37:19 -07:00
committed by picklesrus
parent 204e28f63f
commit 00c04688da
2 changed files with 103 additions and 14 deletions

View File

@@ -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();
};

View File

@@ -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.