diff options
Diffstat (limited to 'blockly/accessible/clipboard.service.js')
-rw-r--r-- | blockly/accessible/clipboard.service.js | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/blockly/accessible/clipboard.service.js b/blockly/accessible/clipboard.service.js new file mode 100644 index 0000000..05b0afe --- /dev/null +++ b/blockly/accessible/clipboard.service.js @@ -0,0 +1,172 @@ +/** + * AccessibleBlockly + * + * 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 Angular2 Service that handles the clipboard and marked spots. + * @author madeeha@google.com (Madeeha Ghori) + */ + +blocklyApp.ClipboardService = ng.core + .Class({ + constructor: [ + blocklyApp.NotificationsService, blocklyApp.UtilsService, + blocklyApp.AudioService, + function(_notificationsService, _utilsService, _audioService) { + this.clipboardBlockXml_ = null; + this.clipboardBlockPreviousConnection_ = null; + this.clipboardBlockNextConnection_ = null; + this.clipboardBlockOutputConnection_ = null; + this.markedConnection_ = null; + this.notificationsService = _notificationsService; + this.utilsService = _utilsService; + this.audioService = _audioService; + }], + areConnectionsCompatible_: function(blockConnection, connection) { + // Check that both connections exist, that it's the right kind of + // connection, and that the types match. + return Boolean( + connection && blockConnection && + Blockly.OPPOSITE_TYPE[blockConnection.type] == connection.type && + connection.checkType_(blockConnection)); + }, + isCompatibleWithClipboard: function(connection) { + var previousConnection = this.clipboardBlockPreviousConnection_; + var nextConnection = this.clipboardBlockNextConnection_; + var outputConnection = this.clipboardBlockOutputConnection_; + return Boolean( + this.areConnectionsCompatible_(connection, previousConnection) || + this.areConnectionsCompatible_(connection, nextConnection) || + this.areConnectionsCompatible_(connection, outputConnection)); + }, + getMarkedConnectionBlock: function() { + if (!this.markedConnection_) { + return null; + } else { + return this.markedConnection_.getSourceBlock(); + } + }, + isMovableToMarkedConnection: function(block) { + // It should not be possible to move any ancestor of the block containing + // the marked spot to the marked spot. + if (!this.markedConnection_) { + return false; + } + + var markedSpotAncestorBlock = this.getMarkedConnectionBlock(); + while (markedSpotAncestorBlock) { + if (markedSpotAncestorBlock.id == block.id) { + return false; + } + markedSpotAncestorBlock = markedSpotAncestorBlock.getParent(); + } + + return this.canBeCopiedToMarkedConnection(block); + }, + canBeCopiedToMarkedConnection: function(block) { + if (!this.markedConnection_ || + !this.markedConnection_.getSourceBlock().workspace) { + return false; + } + + var potentialConnections = [ + block.outputConnection, + block.previousConnection, + block.nextConnection + ]; + + var that = this; + return potentialConnections.some(function(connection) { + return that.areConnectionsCompatible_( + connection, that.markedConnection_); + }); + }, + markConnection: function(connection) { + this.markedConnection_ = connection; + this.notificationsService.setStatusMessage(Blockly.Msg.MARKED_SPOT_MSG); + }, + cut: function(block) { + this.copy(block); + block.dispose(true); + }, + copy: function(block) { + this.clipboardBlockXml_ = Blockly.Xml.blockToDom(block); + this.clipboardBlockPreviousConnection_ = block.previousConnection; + this.clipboardBlockNextConnection_ = block.nextConnection; + this.clipboardBlockOutputConnection_ = block.outputConnection; + }, + pasteFromClipboard: function(inputConnection) { + var connection = inputConnection; + // If the connection is a 'previousConnection' and that connection is + // already joined to something, use the 'nextConnection' of the + // previous block instead in order to do an insertion. + if (inputConnection.type == Blockly.PREVIOUS_STATEMENT && + inputConnection.isConnected()) { + connection = inputConnection.targetConnection; + } + + var reconstitutedBlock = Blockly.Xml.domToBlock(blocklyApp.workspace, + this.clipboardBlockXml_); + switch (connection.type) { + case Blockly.NEXT_STATEMENT: + connection.connect(reconstitutedBlock.previousConnection); + break; + case Blockly.PREVIOUS_STATEMENT: + connection.connect(reconstitutedBlock.nextConnection); + break; + default: + connection.connect(reconstitutedBlock.outputConnection); + } + this.audioService.playConnectSound(); + this.notificationsService.setStatusMessage( + this.utilsService.getBlockDescription(reconstitutedBlock) + ' ' + + Blockly.Msg.PASTED_BLOCK_FROM_CLIPBOARD_MSG); + return reconstitutedBlock.id; + }, + pasteToMarkedConnection: function(block) { + var xml = Blockly.Xml.blockToDom(block); + var reconstitutedBlock = Blockly.Xml.domToBlock( + blocklyApp.workspace, xml); + + var potentialConnections = [ + reconstitutedBlock.outputConnection, + reconstitutedBlock.previousConnection, + reconstitutedBlock.nextConnection + ]; + + var connectionSuccessful = false; + for (var i = 0; i < potentialConnections.length; i++) { + if (this.areConnectionsCompatible_( + this.markedConnection_, potentialConnections[i])) { + this.markedConnection_.connect(potentialConnections[i]); + this.audioService.playConnectSound(); + connectionSuccessful = true; + break; + } + } + + if (!connectionSuccessful) { + console.error('ERROR: Could not connect block to marked spot.'); + return; + } + + this.markedConnection_ = null; + + return reconstitutedBlock.id; + } + }); |