diff --git a/demos/blocklyfactory/app_controller.js b/demos/blocklyfactory/app_controller.js
index 3c729c32d..8a6ba8374 100644
--- a/demos/blocklyfactory/app_controller.js
+++ b/demos/blocklyfactory/app_controller.js
@@ -330,13 +330,15 @@ AppController.prototype.onTab = function() {
FactoryUtils.hide('workspaceFactoryContent');
} else if (this.selectedTab == AppController.WORKSPACE_FACTORY) {
- // Update block library category.
- var categoryXml = this.exporter.getBlockLibraryCategory();
- this.workspaceFactoryController.setBlockLibraryCategory(categoryXml);
// Hide container of exporter.
FactoryUtils.hide('blockLibraryExporter');
// Show workspace factory container.
FactoryUtils.show('workspaceFactoryContent');
+ // Update block library category.
+ var categoryXml = this.exporter.getBlockLibraryCategory();
+ var blockTypes = this.blockLibraryController.getStoredBlockTypes();
+ this.workspaceFactoryController.setBlockLibCategory(categoryXml,
+ blockTypes);
}
// Resize to render workspaces' toolboxes correctly for all tabs.
diff --git a/demos/blocklyfactory/block_library_controller.js b/demos/blocklyfactory/block_library_controller.js
index a6d82c872..1df8121a7 100644
--- a/demos/blocklyfactory/block_library_controller.js
+++ b/demos/blocklyfactory/block_library_controller.js
@@ -228,3 +228,12 @@ BlockLibraryController.prototype.getBlockLibraryStorage = function() {
BlockLibraryController.prototype.hasEmptyBlockLibrary = function() {
return this.storage.isEmpty();
};
+
+/**
+ * Get all block types stored in block library.
+ *
+ * @return {!Array} Array of block types.
+ */
+BlockLibraryController.prototype.getStoredBlockTypes = function() {
+ return this.storage.getBlockTypes();
+};
diff --git a/demos/blocklyfactory/workspacefactory/wfactory_controller.js b/demos/blocklyfactory/workspacefactory/wfactory_controller.js
index 94ce31773..d3fb168be 100644
--- a/demos/blocklyfactory/workspacefactory/wfactory_controller.js
+++ b/demos/blocklyfactory/workspacefactory/wfactory_controller.js
@@ -302,9 +302,7 @@ WorkspaceFactoryController.prototype.clearAndLoadElement = function(id) {
// Selects the next tab.
this.view.setCategoryTabSelection(id, true);
- // Mark all shadow blocks laoded and order blocks as if shown in a flyout.
- this.view.markShadowBlocks(this.model.getShadowBlocksInWorkspace
- (this.toolboxWorkspace.getAllBlocks()));
+ // Order blocks as shown in flyout.
this.toolboxWorkspace.cleanUp();
// Update category editing buttons.
@@ -1023,6 +1021,7 @@ WorkspaceFactoryController.prototype.clearAndLoadXml_ = function(xml) {
Blockly.Xml.domToWorkspace(xml, this.toolboxWorkspace);
this.view.markShadowBlocks(this.model.getShadowBlocksInWorkspace
(this.toolboxWorkspace.getAllBlocks()));
+ this.warnForUndefinedBlocks_();
};
/**
@@ -1156,6 +1155,10 @@ WorkspaceFactoryController.prototype.importBlocks =
categoryXml.setAttribute('colour', randomColor);
controller.toolbox.appendChild(categoryXml);
controller.toolboxWorkspace.updateToolbox(controller.toolbox);
+ // Update imported block types.
+ this.model.addImportedBlocks(blockTypes);
+ // Reload current category to possibly reflect any newly defined blocks.
+ this.clearAndLoadXml_(Blockly.Xml.workspaceToDom(this.toolboxWorkspace));
} catch (e) {
alert('Cannot read blocks from file.');
window.console.log(e);
@@ -1170,9 +1173,11 @@ WorkspaceFactoryController.prototype.importBlocks =
* Updates the block library category in the toolbox workspace toolbox.
*
* @param {!Element} categoryXml XML for the block library category.
+ * @param {!Array} libBlockTypes Array of block types from the block
+ * library.
*/
-WorkspaceFactoryController.prototype.setBlockLibraryCategory =
- function(categoryXml) {
+WorkspaceFactoryController.prototype.setBlockLibCategory =
+ function(categoryXml, libBlockTypes) {
var blockLibCategory = document.getElementById('blockLibCategory');
// Set category id so that it can be easily replaced, and set a standard,
@@ -1183,6 +1188,13 @@ WorkspaceFactoryController.prototype.setBlockLibraryCategory =
// Update the toolbox and toolboxWorkspace.
this.toolbox.replaceChild(categoryXml, blockLibCategory);
this.toolboxWorkspace.updateToolbox(this.toolbox);
+
+ // Update the block library types.
+ this.model.updateLibBlockTypes(libBlockTypes);
+
+ // Reload XML on page to account for blocks now defined or undefined in block
+ // library.
+ this.clearAndLoadXml_(Blockly.Xml.workspaceToDom(this.toolboxWorkspace));
};
/**
@@ -1194,3 +1206,28 @@ WorkspaceFactoryController.prototype.setBlockLibraryCategory =
WorkspaceFactoryController.prototype.getAllUsedBlockTypes = function() {
return this.model.getAllUsedBlockTypes();
};
+
+/**
+ * Determines if a block loaded in the workspace has a definition (if it
+ * is a standard block, is defined in the block library, or has a definition
+ * imported).
+ *
+ * @param {!Blockly.Block} block The block to examine.
+ */
+WorkspaceFactoryController.prototype.isDefinedBlock = function(block) {
+ return this.model.isDefinedBlockType(block.type);
+};
+
+/**
+ * Sets a warning on blocks loaded to the workspace that are not defined.
+ * @private
+ */
+WorkspaceFactoryController.prototype.warnForUndefinedBlocks_ = function() {
+ var blocks = this.toolboxWorkspace.getAllBlocks();
+ for (var i = 0, block; block = blocks[i]; i++) {
+ if (!this.isDefinedBlock(block)) {
+ block.setWarningText(block.type + ' is not defined (it is not a standard '
+ + 'block, \nin your block library, or an imported block)');
+ }
+ }
+};
diff --git a/demos/blocklyfactory/workspacefactory/wfactory_init.js b/demos/blocklyfactory/workspacefactory/wfactory_init.js
index d306222a9..4e286da84 100644
--- a/demos/blocklyfactory/workspacefactory/wfactory_init.js
+++ b/demos/blocklyfactory/workspacefactory/wfactory_init.js
@@ -443,7 +443,8 @@ WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
// Enable block editing and remove warnings if the block is not a
// variable user-generated shadow block.
document.getElementById('button_editShadow').disabled = false;
- if (!controller.hasVariableField(selected)) {
+ if (!controller.hasVariableField(selected) &&
+ controller.isDefinedBlock(selected)) {
selected.setWarningText(null);
}
} else {
@@ -473,7 +474,8 @@ WorkspaceFactoryInit.addWorkspaceFactoryEventListeners_ = function(controller) {
// be a shadow block.
// Remove possible 'invalid shadow block placement' warning.
- if (selected != null && (!controller.hasVariableField(selected) ||
+ if (selected != null && controller.isDefinedBlock(selected) &&
+ (!controller.hasVariableField(selected) ||
!controller.isUserGenShadowBlock(selected.id))) {
selected.setWarningText(null);
}
diff --git a/demos/blocklyfactory/workspacefactory/wfactory_model.js b/demos/blocklyfactory/workspacefactory/wfactory_model.js
index 0a5f3f33d..8e552d838 100644
--- a/demos/blocklyfactory/workspacefactory/wfactory_model.js
+++ b/demos/blocklyfactory/workspacefactory/wfactory_model.js
@@ -53,6 +53,11 @@ WorkspaceFactoryModel = function() {
this.preloadXml = Blockly.Xml.textToDom('');
// Options object to be configured for Blockly inject call.
this.options = new Object(null);
+ // Block Library block types.
+ this.libBlockTypes = [];
+ // Imported block types.
+ this.importedBlockTypes = [];
+ //
};
/**
@@ -300,7 +305,7 @@ WorkspaceFactoryModel.prototype.getCategoryIdByName = function(name) {
WorkspaceFactoryModel.prototype.clearToolboxList = function() {
this.toolboxList = [];
this.hasVariableCategory = false;
- this.hasVariableCategory = false;
+ this.hasProcedureCategory = false;
this.shadowBlocks = [];
this.selected.xml = Blockly.Xml.textToDom('');
};
@@ -469,6 +474,39 @@ WorkspaceFactoryModel.prototype.getAllUsedBlockTypes = function() {
return blockTypeList;
};
+/**
+ * Adds new imported block types to the list of current imported block types.
+ *
+ * @param {!Array} blockTypes Array of block types imported.
+ */
+WorkspaceFactoryModel.prototype.addImportedBlockTypes = function(blockTypes) {
+ this.importedBlockTypes = this.importedBlockTypes.concat(blockTypes);
+};
+
+/**
+ * Updates block types in block library.
+ *
+ * @param {!Array} blockTypes Array of block types in block library.
+ */
+WorkspaceFactoryModel.prototype.updateLibBlockTypes = function(blockTypes) {
+ this.libBlockTypes = blockTypes;
+};
+
+/**
+ * Determines if a block type is defined as a standard block, in the block
+ * library, or as an imported block.
+ *
+ * @param {!string} blockType Block type to check.
+ * @return {boolean} True if blockType is defined, false otherwise.
+ */
+WorkspaceFactoryModel.prototype.isDefinedBlockType = function(blockType) {
+ var isStandardBlock = StandardCategories.coreBlockTypes.indexOf(blockType)
+ != -1;
+ var isLibBlock = this.libBlockTypes.indexOf(blockType) != -1;
+ var isImportedBlock = this.importedBlockTypes.indexOf(blockType) != -1;
+ return (isStandardBlock || isLibBlock || isImportedBlock);
+}
+
/**
* Class for a ListElement.
* @constructor