summaryrefslogtreecommitdiff
path: root/blockly/accessible/clipboard.service.js
diff options
context:
space:
mode:
Diffstat (limited to 'blockly/accessible/clipboard.service.js')
-rw-r--r--blockly/accessible/clipboard.service.js172
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;
+ }
+ });