From 5c79d2f36f8d22b464e0279d251e839666a50586 Mon Sep 17 00:00:00 2001 From: Sean Lip Date: Tue, 22 Nov 2016 15:53:45 -0800 Subject: [PATCH] When the workspace is empty, make it easy for the user to add a new group of blocks to it. --- accessible/sidebar.component.js | 58 +---------- accessible/toolbox-modal.service.js | 151 ++++++++++++++++++++-------- accessible/workspace.component.js | 22 +++- demos/accessible/index.html | 2 +- 4 files changed, 131 insertions(+), 102 deletions(-) diff --git a/accessible/sidebar.component.js b/accessible/sidebar.component.js index 70fc806e5..52901867b 100644 --- a/accessible/sidebar.component.js +++ b/accessible/sidebar.component.js @@ -98,63 +98,9 @@ blocklyApp.SidebarComponent = ng.core.Component({ return this.utilsService.isWorkspaceEmpty(); }, showToolboxModalForAttachToMarkedSpot: function() { - var that = this; - this.toolboxModalService.showModal(function(opt_block) { - if (!opt_block) { - return; - } - - var block = opt_block; - var blockDescription = that.utilsService.getBlockDescription(block); - - // Clean up the active desc for the destination tree. - var oldDestinationTreeId = that.treeService.getTreeIdForBlock( - that.clipboardService.getMarkedConnectionBlock().id); - that.treeService.clearActiveDesc(oldDestinationTreeId); - var newBlockId = that.clipboardService.pasteToMarkedConnection(block); - - // Invoke a digest cycle, so that the DOM settles. - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - - var newDestinationTreeId = that.treeService.getTreeIdForBlock( - newBlockId); - if (newDestinationTreeId != oldDestinationTreeId) { - // It is possible for the tree ID for the pasted block to change - // after the paste operation, e.g. when inserting a block between two - // existing blocks that are joined together. In this case, we need to - // also reset the active desc for the old destination tree. - that.treeService.initActiveDesc(oldDestinationTreeId); - } - - that.notificationsService.setStatusMessage( - blockDescription + ' connected. ' + - 'Now on copied block in workspace.'); - }); - }, function(block) { - return that.clipboardService.canBeCopiedToMarkedConnection(block); - }); + this.toolboxModalService.showToolboxModalForAttachToMarkedSpot(); }, showToolboxModalForCreateNewGroup: function() { - var that = this; - this.toolboxModalService.showModal(function(opt_block) { - if (!opt_block) { - return; - } - - var block = opt_block; - var blockDescription = that.utilsService.getBlockDescription(block); - var xml = Blockly.Xml.blockToDom(block); - var newBlockId = Blockly.Xml.domToBlock(blocklyApp.workspace, xml).id; - - setTimeout(function() { - that.treeService.focusOnBlock(newBlockId); - that.notificationsService.setStatusMessage( - blockDescription + ' added to workspace. ' + - 'Now on added block in workspace.'); - }); - }, function(block) { - return true; - }); + this.toolboxModalService.showToolboxModalForCreateNewGroup(); } }); diff --git a/accessible/toolbox-modal.service.js b/accessible/toolbox-modal.service.js index ec52899f2..87e233b9d 100644 --- a/accessible/toolbox-modal.service.js +++ b/accessible/toolbox-modal.service.js @@ -24,50 +24,61 @@ */ blocklyApp.ToolboxModalService = ng.core.Class({ - constructor: [function() { - this.modalIsShown = false; - this.onHideCallback = null; - this.isBlockAvailable = null; - this.preShowHook = function() { - throw Error( - 'A pre-show hook must be defined for the toolbox modal before it ' + - 'can be shown.'); - }; - this.toolboxCategories = []; + constructor: [ + blocklyApp.TreeService, blocklyApp.UtilsService, + blocklyApp.NotificationsService, blocklyApp.ClipboardService, + function( + _treeService, _utilsService, + _notificationsService, _clipboardService) { + this.treeService = _treeService; + this.utilsService = _utilsService; + this.notificationsService = _notificationsService; + this.clipboardService = _clipboardService; - // Populate the toolbox categories. - var toolboxXmlElt = document.getElementById('blockly-toolbox-xml'); - var toolboxCategoryElts = toolboxXmlElt.getElementsByTagName('category'); - if (toolboxCategoryElts.length) { - this.toolboxCategories = Array.from(toolboxCategoryElts).map( - function(categoryElt) { + this.modalIsShown = false; + this.onHideCallback = null; + this.isBlockAvailable = null; + this.preShowHook = function() { + throw Error( + 'A pre-show hook must be defined for the toolbox modal before it ' + + 'can be shown.'); + }; + this.toolboxCategories = []; + + // Populate the toolbox categories. + var toolboxXmlElt = document.getElementById('blockly-toolbox-xml'); + var toolboxCategoryElts = toolboxXmlElt.getElementsByTagName('category'); + if (toolboxCategoryElts.length) { + this.toolboxCategories = Array.from(toolboxCategoryElts).map( + function(categoryElt) { + var workspace = new Blockly.Workspace(); + Blockly.Xml.domToWorkspace(categoryElt, workspace); + return { + categoryName: categoryElt.attributes.name.value, + blocks: workspace.topBlocks_ + }; + } + ); + } else { + // A timeout seems to be needed in order for the .children accessor to + // work correctly. + var that = this; + setTimeout(function() { + // If there are no top-level categories, we create a single category + // containing all the top-level blocks. var workspace = new Blockly.Workspace(); - Blockly.Xml.domToWorkspace(categoryElt, workspace); - return { - categoryName: categoryElt.attributes.name.value, - blocks: workspace.topBlocks_ - }; - } - ); - } else { - // A timeout seems to be needed in order for the .children accessor to - // work correctly. - var that = this; - setTimeout(function() { - // If there are no top-level categories, we create a single category - // containing all the top-level blocks. - var workspace = new Blockly.Workspace(); - Array.from(toolboxXmlElt.children).forEach(function(topLevelNode) { - Blockly.Xml.domToBlock(workspace, topLevelNode); - }); + Array.from(toolboxXmlElt.children).forEach(function(topLevelNode) { + Blockly.Xml.domToBlock(workspace, topLevelNode); + }); - that.toolboxCategories = [{ - categoryName: 'Available Blocks', - blocks: workspace.topBlocks_ - }]; - }); + that.toolboxCategories = [{ + categoryName: 'Available Blocks', + blocks: workspace.topBlocks_ + }]; + }); + } } - }], + ], registerPreShowHook: function(preShowHook) { this.preShowHook = function() { preShowHook(this.toolboxCategories, this.isBlockAvailable); @@ -85,5 +96,65 @@ blocklyApp.ToolboxModalService = ng.core.Class({ hideModal: function(opt_block) { this.modalIsShown = false; this.onHideCallback(opt_block); + }, + showToolboxModalForAttachToMarkedSpot: function() { + var that = this; + this.showModal(function(opt_block) { + if (!opt_block) { + return; + } + + var block = opt_block; + var blockDescription = that.utilsService.getBlockDescription(block); + + // Clean up the active desc for the destination tree. + var oldDestinationTreeId = that.treeService.getTreeIdForBlock( + that.clipboardService.getMarkedConnectionBlock().id); + that.treeService.clearActiveDesc(oldDestinationTreeId); + var newBlockId = that.clipboardService.pasteToMarkedConnection(block); + + // Invoke a digest cycle, so that the DOM settles. + setTimeout(function() { + that.treeService.focusOnBlock(newBlockId); + + var newDestinationTreeId = that.treeService.getTreeIdForBlock( + newBlockId); + if (newDestinationTreeId != oldDestinationTreeId) { + // It is possible for the tree ID for the pasted block to change + // after the paste operation, e.g. when inserting a block between two + // existing blocks that are joined together. In this case, we need to + // also reset the active desc for the old destination tree. + that.treeService.initActiveDesc(oldDestinationTreeId); + } + + that.notificationsService.setStatusMessage( + blockDescription + ' connected. ' + + 'Now on copied block in workspace.'); + }); + }, function(block) { + return that.clipboardService.canBeCopiedToMarkedConnection(block); + }); + }, + showToolboxModalForCreateNewGroup: function() { + var that = this; + this.showModal(function(opt_block) { + if (!opt_block) { + return; + } + + var block = opt_block; + var blockDescription = that.utilsService.getBlockDescription(block); + var xml = Blockly.Xml.blockToDom(block); + var newBlockId = Blockly.Xml.domToBlock(blocklyApp.workspace, xml).id; + + setTimeout(function() { + that.treeService.focusOnBlock(newBlockId); + that.notificationsService.setStatusMessage( + blockDescription + ' added to workspace. ' + + 'Now on added block in workspace.'); + }); + }, function(block) { + return true; + }); } }); diff --git a/accessible/workspace.component.js b/accessible/workspace.component.js index f9160c99e..014a33824 100644 --- a/accessible/workspace.component.js +++ b/accessible/workspace.component.js @@ -41,7 +41,12 @@ blocklyApp.WorkspaceComponent = ng.core.Component({ - Workspace is empty. +

+ There are no blocks in the workspace. + +

@@ -50,14 +55,21 @@ blocklyApp.WorkspaceComponent = ng.core.Component({ pipes: [blocklyApp.TranslatePipe] }) .Class({ - constructor: [blocklyApp.TreeService, function(_treeService) { - this.treeService = _treeService; - this.workspace = blocklyApp.workspace; - }], + constructor: [ + blocklyApp.TreeService, blocklyApp.ToolboxModalService, + function(_treeService, _toolboxModalService) { + this.treeService = _treeService; + this.toolboxModalService = _toolboxModalService; + this.workspace = blocklyApp.workspace; + } + ], getActiveDescId: function(treeId) { return this.treeService.getActiveDescId(treeId); }, onKeypress: function(e, tree) { this.treeService.onKeypress(e, tree); + }, + showToolboxModalForCreateNewGroup: function() { + this.toolboxModalService.showToolboxModalForCreateNewGroup(); } }); diff --git a/demos/accessible/index.html b/demos/accessible/index.html index 4e7205fda..6a3294bf4 100644 --- a/demos/accessible/index.html +++ b/demos/accessible/index.html @@ -21,11 +21,11 @@ - +