diff options
Diffstat (limited to 'blockly/demos/blocklyfactory/block_exporter_controller.js')
-rw-r--r-- | blockly/demos/blocklyfactory/block_exporter_controller.js | 335 |
1 files changed, 335 insertions, 0 deletions
diff --git a/blockly/demos/blocklyfactory/block_exporter_controller.js b/blockly/demos/blocklyfactory/block_exporter_controller.js new file mode 100644 index 0000000..e0c192f --- /dev/null +++ b/blockly/demos/blocklyfactory/block_exporter_controller.js @@ -0,0 +1,335 @@ +/** + * @license + * Visual Blocks Editor + * + * Copyright 2016 Google Inc. + * https://developers.google.com/blockly/ + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * You may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * @fileoverview Javascript for the Block Exporter Controller class. Allows + * users to export block definitions and generator stubs of their saved blocks + * easily using a visual interface. Depends on Block Exporter View and Block + * Exporter Tools classes. Interacts with Export Settings in the index.html. + * + * @author quachtina96 (Tina Quach) + */ + +'use strict'; + +goog.provide('BlockExporterController'); + +goog.require('FactoryUtils'); +goog.require('StandardCategories'); +goog.require('BlockExporterView'); +goog.require('BlockExporterTools'); +goog.require('goog.dom.xml'); + +/** + * BlockExporter Controller Class + * @constructor + * + * @param {!BlockLibrary.Storage} blockLibStorage - Block Library Storage. + */ +BlockExporterController = function(blockLibStorage) { + // BlockLibrary.Storage object containing user's saved blocks. + this.blockLibStorage = blockLibStorage; + // Utils for generating code to export. + this.tools = new BlockExporterTools(); + // The ID of the block selector, a div element that will be populated with the + // block options. + this.selectorID = 'blockSelector'; + // Map of block types stored in block library to their corresponding Block + // Option objects. + this.blockOptions = this.tools.createBlockSelectorFromLib( + this.blockLibStorage, this.selectorID); + // View provides the block selector and export settings UI. + this.view = new BlockExporterView(this.blockOptions); +}; + +/** + * Set the block library storage object from which exporter exports. + * + * @param {!BlockLibraryStorage} blockLibStorage - Block Library Storage object + * that stores the blocks. + */ +BlockExporterController.prototype.setBlockLibraryStorage = + function(blockLibStorage) { + this.blockLibStorage = blockLibStorage; +}; + +/** + * Get the block library storage object from which exporter exports. + * + * @return {!BlockLibraryStorage} blockLibStorage - Block Library Storage object + * that stores the blocks. + */ +BlockExporterController.prototype.getBlockLibraryStorage = + function(blockLibStorage) { + return this.blockLibStorage; +}; + +/** + * Get selected blocks from block selector, pulls info from the Export + * Settings form in Block Exporter, and downloads code accordingly. + */ +BlockExporterController.prototype.export = function() { + // Get selected blocks' information. + var blockTypes = this.view.getSelectedBlockTypes(); + var blockXmlMap = this.blockLibStorage.getBlockXmlMap(blockTypes); + + // Pull block definition(s) settings from the Export Settings form. + var wantBlockDef = document.getElementById('blockDefCheck').checked; + var definitionFormat = document.getElementById('exportFormat').value; + var blockDef_filename = document.getElementById('blockDef_filename').value; + + // Pull block generator stub(s) settings from the Export Settings form. + var wantGenStub = document.getElementById('genStubCheck').checked; + var language = document.getElementById('exportLanguage').value; + var generatorStub_filename = document.getElementById( + 'generatorStub_filename').value; + + if (wantBlockDef) { + // User wants to export selected blocks' definitions. + if (!blockDef_filename) { + // User needs to enter filename. + alert('Please enter a filename for your block definition(s) download.'); + } else { + // Get block definition code in the selected format for the blocks. + var blockDefs = this.tools.getBlockDefinitions(blockXmlMap, + definitionFormat); + // Download the file, using .js file ending for JSON or Javascript. + FactoryUtils.createAndDownloadFile( + blockDefs, blockDef_filename, 'javascript'); + } + } + + if (wantGenStub) { + // User wants to export selected blocks' generator stubs. + if (!generatorStub_filename) { + // User needs to enter filename. + alert('Please enter a filename for your generator stub(s) download.'); + } else { + // Get generator stub code in the selected language for the blocks. + var genStubs = this.tools.getGeneratorCode(blockXmlMap, + language); + // Get the correct file extension. + if (language == 'JavaScript') { + var fileType = 'javascript'; + } else { + var fileType = 'plain'; + } + // Download the file. + FactoryUtils.createAndDownloadFile( + genStubs, generatorStub_filename, fileType); + } + } + +}; + +/** + * Update the Exporter's block selector with block options generated from blocks + * stored in block library. + */ +BlockExporterController.prototype.updateSelector = function() { + // Get previously selected block types. + var oldSelectedTypes = this.view.getSelectedBlockTypes(); + + // Generate options from block library and assign to view. + this.blockOptions = this.tools.createBlockSelectorFromLib( + this.blockLibStorage, this.selectorID); + this.addBlockOptionSelectHandlers(); + this.view.setBlockOptions(this.blockOptions); + + // Select all previously selected blocks. + for (var i = 0, blockType; blockType = oldSelectedTypes[i]; i++) { + if (this.blockOptions[blockType]) { + this.view.select(blockType); + } + } + + this.view.listSelectedBlocks(); +}; + +/** + * Tied to the 'Clear Selected Blocks' button in the Block Exporter. + * Deselects all blocks in the selector and updates text accordingly. + */ +BlockExporterController.prototype.clearSelectedBlocks = function() { + this.view.deselectAllBlocks(); + this.view.listSelectedBlocks(); +}; + +/** + * Tied to the 'All Stored' button in the Block Exporter 'Select' dropdown. + * Selects all blocks stored in block library for export. + */ +BlockExporterController.prototype.selectAllBlocks = function() { + var allBlockTypes = this.blockLibStorage.getBlockTypes(); + for (var i = 0, blockType; blockType = allBlockTypes[i]; i++) { + this.view.select(blockType); + } + this.view.listSelectedBlocks(); +}; + +/** + * Returns the category xml containing all blocks in the block library. + * + * @return {Element} Xml for a category to be used in toolbox. + */ +BlockExporterController.prototype.getBlockLibraryCategory = function() { + return this.tools.generateCategoryFromBlockLib(this.blockLibStorage); +}; + +/** + * Add select handlers to each block option to update the view and the selected + * blocks accordingly. + */ +BlockExporterController.prototype.addBlockOptionSelectHandlers = function() { + var self = this; + + // Click handler for a block option. Toggles whether or not it's selected and + // updates helper text accordingly. + var updateSelectedBlockTypes_ = function(blockOption) { + // Toggle selected. + blockOption.setSelected(!blockOption.isSelected()); + + // Show currently selected blocks in helper text. + self.view.listSelectedBlocks(); + }; + + // Returns a block option select handler. + var makeBlockOptionSelectHandler_ = function(blockOption) { + return function() { + updateSelectedBlockTypes_(blockOption); + self.updatePreview(); + }; + }; + + // Assign a click handler to each block option. + for (var blockType in this.blockOptions) { + var blockOption = this.blockOptions[blockType]; + // Use an additional closure to correctly assign the tab callback. + blockOption.dom.addEventListener( + 'click', makeBlockOptionSelectHandler_(blockOption)); + } +}; + +/** + * Tied to the 'All Used' button in the Block Exporter's 'Select' button. + * Selects all blocks stored in block library and used in workspace factory. + */ +BlockExporterController.prototype.selectUsedBlocks = function() { + // Deselect all blocks. + this.view.deselectAllBlocks(); + + // Get list of block types that are in block library and used in workspace + // factory. + var storedBlockTypes = this.blockLibStorage.getBlockTypes(); + var sharedBlockTypes = []; + // Keep list of custom block types used but not in library. + var unstoredCustomBlockTypes = []; + + for (var i = 0, blockType; blockType = this.usedBlockTypes[i]; i++) { + if (storedBlockTypes.indexOf(blockType) != -1) { + sharedBlockTypes.push(blockType); + } else if (StandardCategories.coreBlockTypes.indexOf(blockType) == -1) { + unstoredCustomBlockTypes.push(blockType); + } + } + + // Select each shared block type. + for (var i = 0, blockType; blockType = sharedBlockTypes[i]; i++) { + this.view.select(blockType); + } + this.view.listSelectedBlocks(); + + if (unstoredCustomBlockTypes.length > 0){ + // Warn user to import block defifnitions and generator code for blocks + // not in their Block Library nor Blockly's standard library. + var blockTypesText = unstoredCustomBlockTypes.join(', '); + var customWarning = 'Custom blocks used in workspace factory but not ' + + 'stored in block library:\n ' + blockTypesText + + '\n\nDon\'t forget to include block definitions and generator code ' + + 'for these blocks.'; + alert(customWarning); + } +}; + +/** + * Set the array that holds the block types used in workspace factory. + * + * @param {!Array.<!string>} usedBlockTypes - Block types used in + */ +BlockExporterController.prototype.setUsedBlockTypes = + function(usedBlockTypes) { + this.usedBlockTypes = usedBlockTypes; +}; + +/** + * Updates preview code (block definitions and generator stubs) in the exporter + * preview to reflect selected blocks. + */ +BlockExporterController.prototype.updatePreview = function() { + // Generate preview code for selected blocks. + var blockDefs = this.getBlockDefinitionsOfSelected(); + var genStubs = this.getGeneratorStubsOfSelected(); + + // Update the text areas containing the code. + FactoryUtils.injectCode(blockDefs, 'blockDefs_textArea'); + FactoryUtils.injectCode(genStubs, 'genStubs_textArea'); +}; + +/** + * Returns a map of each selected block's type to its corresponding xml. + * + * @return {!Object} a map of each selected block's type (a string) to its + * corresponding xml element. + */ +BlockExporterController.prototype.getSelectedBlockXmlMap = function() { + var blockTypes = this.view.getSelectedBlockTypes(); + return this.blockLibStorage.getBlockXmlMap(blockTypes); +}; + +/** + * Get block definition code in the selected format for selected blocks. + * + * @return {!string} The concatenation of each selected block's language code + * in the format specified in export settings. + */ +BlockExporterController.prototype.getBlockDefinitionsOfSelected = function() { + // Get selected blocks' information. + var blockXmlMap = this.getSelectedBlockXmlMap(); + + // Get block definition code in the selected format for the blocks. + var definitionFormat = document.getElementById('exportFormat').value; + return this.tools.getBlockDefinitions(blockXmlMap, definitionFormat); +}; + +/** + * Get generator stubs in the selected language for selected blocks. + * + * @return {!string} The concatenation of each selected block's generator stub + * in the language specified in export settings. + */ +BlockExporterController.prototype.getGeneratorStubsOfSelected = function() { + // Get selected blocks' information. + var blockXmlMap = this.getSelectedBlockXmlMap(); + + // Get generator stub code in the selected language for the blocks. + var language = document.getElementById('exportLanguage').value; + return this.tools.getGeneratorCode(blockXmlMap, language); +}; + |