cloud-blocks
Version:
Cloud Blocks is a library for building scratch computing interfaces with Luxrobo MODI.
222 lines (200 loc) • 7.05 kB
JavaScript
/**
* @license
* Visual Blocks Editor
*
* Copyright 2017 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 Methods for dragging a block visually.
* @author Sophie
*/
'use strict';
goog.provide('Blockly.CodeSketchBlockDragger');
goog.require('Blockly.BlockAnimations');
goog.require('Blockly.Events.BlockMove');
goog.require('Blockly.Events.DragBlockOutside');
goog.require('Blockly.Events.EndBlockDrag');
goog.require('Blockly.InsertionMarkerManager');
goog.require('goog.math.Coordinate');
goog.require('goog.asserts');
/**
* Class for a block dragger. It moves blocks around the workspace when they
* are being dragged by a mouse or touch.
* @author Sophie
* @param {!Blockly.BlockSvg} block The block to drag.
* @param {!Blockly.WorkspaceSvg} workspace The workspace to drag on.
* @extends Blockly.BlockDragger
* @constructor
*/
Blockly.CodeSketchBlockDragger = function (block, workspace) {
Blockly.CodeSketchBlockDragger.superClass_.constructor.call(
this,
block,
workspace
);
/**
* is the block dragged from flyout?
* @type {!Blockly.BlockSvg}
* @author Sophie
*/
this.isFromFlyout_ = false;
};
goog.inherits(Blockly.CodeSketchBlockDragger, Blockly.BlockDragger);
/**
* Execute a step of block dragging, based on the given event. Update the
* display accordingly.
* @param {!Event} e The most recent move event.
* @param {!goog.math.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
* @package
* @return {boolean} True if the event should be propagated, false if not.
*/
Blockly.CodeSketchBlockDragger.prototype.dragBlock = function (
e,
currentDragDeltaXY
) {
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY, 'DRAG');
var newLoc = goog.math.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.moveDuringDrag(newLoc);
this.dragIcons_(delta);
this.deleteArea_ = this.workspace_.isDeleteArea(e);
var isOutside = !this.workspace_.isInsideBlocksArea(e);
this.draggedConnectionManager_.update(delta, this.deleteArea_, isOutside);
if (isOutside !== this.wasOutside_) {
this.fireDragOutsideEvent_(isOutside);
this.wasOutside_ = isOutside;
}
this.updateCursorDuringBlockDrag_(isOutside);
return isOutside;
};
/**
* Finish a block drag and put the block back on the workspace.
* @param {!Event} e The mouseup/touchend event.
* @param {!goog.math.Coordinate} currentDragDeltaXY How far the pointer has
* moved from the position at the start of the drag, in pixel units.
* @package
*/
Blockly.CodeSketchBlockDragger.prototype.endBlockDrag = function (
e,
currentDragDeltaXY
) {
// Make sure internal state is fresh.
this.dragBlock(e, currentDragDeltaXY);
this.dragIconData_ = [];
var isOutside = this.wasOutside_;
this.fireEndDragEvent_(isOutside);
this.draggingBlock_.setMouseThroughStyle(false);
Blockly.BlockAnimations.disconnectUiStop();
var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY, 'END');
var newLoc = goog.math.Coordinate.sum(this.startXY_, delta);
this.draggingBlock_.moveOffDragSurface_(newLoc);
// Scratch-specific: note possible illegal definition deletion for rollback below.
var isDeletingProcDef =
this.wouldDeleteBlock_ &&
this.draggingBlock_.type == Blockly.PROCEDURES_DEFINITION_BLOCK_TYPE;
var deleted = this.maybeDeleteBlock_();
if (!deleted) {
// These are expensive and don't need to be done if we're deleting.
this.draggingBlock_.moveConnections_(delta.x, delta.y);
this.draggingBlock_.setDragging(false);
this.fireMoveEvent_();
if (this.draggedConnectionManager_.wouldConnectBlock()) {
// Applying connections also rerenders the relevant blocks.
this.draggedConnectionManager_.applyConnections();
} else {
this.draggingBlock_.render();
}
this.draggingBlock_.scheduleSnapAndBump();
}
this.workspace_.setResizesEnabled(false); // not to move blocklyCanvas
var toolbox = this.workspace_.getToolbox();
if (toolbox) {
var style = this.draggingBlock_.isDeletable()
? 'blocklyToolboxDelete'
: 'blocklyToolboxGrab';
toolbox.removeStyle(style);
}
Blockly.Events.setGroup(false);
if (isOutside) {
var ws = this.workspace_;
// Reset a drag to outside of scratch-blocks
setTimeout(function () {
ws.undo();
});
}
// Scratch-specific: roll back deletes that create call blocks with defines.
// Have to wait for connections to be re-established, so put in setTimeout.
// Only do this if we deleted a proc def.
if (isDeletingProcDef) {
var ws = this.workspace_;
setTimeout(function () {
var allBlocks = ws.getAllBlocks();
for (var i = 0; i < allBlocks.length; i++) {
var block = allBlocks[i];
if (block.type == Blockly.PROCEDURES_CALL_BLOCK_TYPE) {
var procCode = block.getProcCode();
// Check for call blocks with no associated define block.
if (!Blockly.Procedures.getDefineBlock(procCode, ws)) {
alert(Blockly.Msg.PROCEDURE_USED);
ws.undo();
return; // There can only be one define deletion at a time.
}
}
}
// The proc deletion was valid, update the toolbox.
ws.refreshToolboxSelection_();
});
}
};
/**
* @author Tom
*/
Blockly.CodeSketchBlockDragger.prototype.pixelsToWorkspaceUnits_ = function (
pixelCoord,
eventName
) {
var videoOptions = this.getVideoOptions();
if (videoOptions && this.isFromFlyout_) {
var flyout = this.workspace_.getFlyout();
if (eventName === 'DRAG') {
pixelCoord.y += flyout.videoHeight_;
}
}
var result = new goog.math.Coordinate(
pixelCoord.x / this.workspace_.scale,
pixelCoord.y / this.workspace_.scale
);
if (this.workspace_.isMutator) {
// If we're in a mutator, its scale is always 1, purely because of some
// oddities in our rendering optimizations. The actual scale is the same as
// the scale on the parent workspace.
// Fix that for dragging.
var mainScale = this.workspace_.options.parentWorkspace.scale;
result = result.scale(1 / mainScale);
}
return result;
};
/**
* @author Tom
*/
Blockly.CodeSketchBlockDragger.prototype.getVideoOptions = function () {
var workspaceOptions = this.workspace_.options;
if (workspaceOptions) {
return workspaceOptions.videoOptions;
} else {
return undefined;
}
};