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