diff --git a/core/bubble.js b/core/bubble.js index 8e8023b03..92dc28894 100644 --- a/core/bubble.js +++ b/core/bubble.js @@ -162,14 +162,15 @@ Blockly.Bubble.bubbleMouseUp_ = function(/*e*/) { Blockly.Bubble.prototype.rendered_ = false; /** - * Absolute coordinate of anchor point. + * Absolute coordinate of anchor point, in workspace coordinates. * @type {goog.math.Coordinate} * @private */ Blockly.Bubble.prototype.anchorXY_ = null; /** - * Relative X coordinate of bubble with respect to the anchor's centre. + * Relative X coordinate of bubble with respect to the anchor's centre, + * in workspace units. * In RTL mode the initial value is negated. * @private */ @@ -273,6 +274,14 @@ Blockly.Bubble.prototype.createDom_ = function(content, hasResize) { return this.bubbleGroup_; }; +/** + * Return the root node of the bubble's SVG group. + * @return {Element} The root SVG node of the bubble's group. + */ +Blockly.Bubble.prototype.getSvgRoot = function() { + return this.bubbleGroup_; +}; + /** * Handle a mouse-down on bubble's border. * @param {!Event} e Mouse down event. @@ -413,16 +422,16 @@ Blockly.Bubble.prototype.positionBubble_ = function() { left += this.relativeLeft_; } var top = this.relativeTop_ + this.anchorXY_.y; - this.moveTo_(left, top); + this.moveTo(left, top); }; /** * Move the bubble group to the specified location in workspace coordinates. * @param {number} x The x position to move to. - * @param {nubmer} y The y position to move to. - * @private + * @param {number} y The y position to move to. + * @package */ -Blockly.Bubble.prototype.moveTo_ = function(x, y) { +Blockly.Bubble.prototype.moveTo = function(x, y) { this.bubbleGroup_.setAttribute('transform', 'translate(' + x + ',' + y + ')'); }; @@ -574,53 +583,48 @@ Blockly.Bubble.prototype.dispose = function() { }; /** - * - * @package - */ -Blockly.Bubble.prototype.moveToDragSurface = function(dragSurface) { - this.autoLayout_ = false; - if (dragSurface) { - // TODO: check RTL. - var x = this.anchorXY_.x + this.relativeLeft_; - var y = this.anchorXY_.y + this.relativeTop_; - this.moveTo_(0, 0); - dragSurface.translateSurface(x, y); - // Execute the move on the top-level SVG component. - dragSurface.setBlocksAndShow(this.bubbleGroup_); - } -}; - -/** - * + * Move this bubble during a drag, taking into account whether or not there is + * a drag surface. + * @param {?Blockly.BlockDragSurfaceSvg} dragSurface The surface that carries + * rendered items during a drag, or null if no drag surface is in use. + * @param {!goog.math.Coordinate} newLoc The location to translate to, in + * workspace coordinates. * @package */ Blockly.Bubble.prototype.moveDuringDrag = function(dragSurface, newLoc) { if (dragSurface) { dragSurface.translateSurface(newLoc.x, newLoc.y); } else { - this.moveTo_(newLoc.x, newLoc.y); + this.moveTo(newLoc.x, newLoc.y); } - this.relativeLeft_ = - this.anchorXY_.x + newLoc.x; - this.relativeTop_ = - this.anchorXY_.y + newLoc.y; + if (this.workspace_.RTL) { + this.relativeLeft_ = this.anchorXY_.x - newLoc.x - this.width_; + } else { + this.relativeLeft_ = newLoc.x - this.anchorXY_.x; + } + this.relativeTop_ = newLoc.y - this.anchorXY_.y; this.renderArrow_(); }; /** - * - * @package + * Return the coordinates of the top-left corner of this bubble's body relative + * to the drawing surface's origin (0,0), in workspace units. + * @return {!goog.math.Coordinate} Object with .x and .y properties. */ -Blockly.Bubble.prototype.moveOffDragSurface = function(dragSurface, newXY) { - this.moveTo_(newXY.x, newXY.y); - if (dragSurface) { - dragSurface.clearAndHide(this.workspace_.getBubbleCanvas()); - } +Blockly.Bubble.prototype.getRelativeToSurfaceXY = function() { + return new goog.math.Coordinate( + this.anchorXY_.x + this.relativeLeft_, + this.anchorXY_.y + this.relativeTop_); }; /** - * + * Set whether auto-layout of this bubble is enabled. The first time a bubble + * is shown it positions itself to not cover any blocks. Once a user has + * dragged it to reposition, it renders where the user put it. + * @param {boolean} enable True if auto-layout should be enabled, false + * otherwise. * @package */ -Blockly.Bubble.prototype.getRelativeToSurfaceXY = function() { - return new goog.math.Coordinate(this.anchorXY_.x + this.relativeLeft_, - this.anchorXY_.y + this.relativeTop_); +Blockly.Bubble.prototype.setAutoLayout = function(enable) { + this.autoLayout_ = enable; }; diff --git a/core/bubble_dragger.js b/core/bubble_dragger.js index c801233f3..e0dc03eda 100644 --- a/core/bubble_dragger.js +++ b/core/bubble_dragger.js @@ -53,17 +53,22 @@ Blockly.BubbleDragger = function(bubble, workspace) { this.workspace_ = workspace; /** - * The location of the top left corner of the dragging bubble at the beginning - * of the drag in workspace coordinates. + * The location of the top left corner of the dragging bubble's body at the + * beginning of the drag, in workspace coordinates. * @type {!goog.math.Coordinate} * @private */ this.startXY_ = this.draggingBubble_.getRelativeToSurfaceXY(); - // TODO: validate, getters, etc. + /** + * The drag surface to move bubbles to during a drag, or null if none should + * be used. Block dragging and bubble dragging use the same surface. + * @type {?Blockly.BlockDragSurfaceSvg} + * @private + */ this.dragSurface_ = - Blockly.utils.is3dSupported() && !!workspace.blockDragSurface_ ? - workspace.blockDragSurface_ : null; + Blockly.utils.is3dSupported() && !!workspace.getBlockDragSurface() ? + workspace.getBlockDragSurface() : null; }; /** @@ -73,11 +78,11 @@ Blockly.BubbleDragger = function(bubble, workspace) { Blockly.BubbleDragger.prototype.dispose = function() { this.draggingBubble_ = null; this.workspace_ = null; - this.startWorkspace_ = null; + this.dragSurface_ = null; }; /** - * Start dragging a block. This includes moving it to the drag surface. + * Start dragging a bubble. This includes moving it to the drag surface. * @package */ Blockly.BubbleDragger.prototype.startBubbleDrag = function() { @@ -86,11 +91,14 @@ Blockly.BubbleDragger.prototype.startBubbleDrag = function() { } this.workspace_.setResizesEnabled(false); - this.draggingBubble_.moveToDragSurface(this.dragSurface_); + this.draggingBubble_.setAutoLayout(false); + if (this.dragSurface_) { + this.moveToDragSurface_(); + } }; /** - * Execute a step of block dragging, based on the given event. Update the + * Execute a step of bubble 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 @@ -107,19 +115,26 @@ Blockly.BubbleDragger.prototype.dragBubble = function(e, currentDragDeltaXY) { }; /** - * Finish a block drag and put the block back on the workspace. + * Finish a bubble drag and put the bubble 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.BubbleDragger.prototype.endBubbleDrag = function(e, currentDragDeltaXY) { +Blockly.BubbleDragger.prototype.endBubbleDrag = function( + e, currentDragDeltaXY) { // Make sure internal state is fresh. this.dragBubble(e, currentDragDeltaXY); var delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); var newLoc = goog.math.Coordinate.sum(this.startXY_, delta); - this.draggingBubble_.moveOffDragSurface(this.dragSurface_, newLoc); + + // Move the bubble to its final location. + this.draggingBubble_.moveTo(newLoc.x, newLoc.y); + // Put everything back onto the bubble canvas. + if (this.dragSurface_) { + this.dragSurface_.clearAndHide(this.workspace_.getBubbleCanvas()); + } this.fireMoveEvent_(); this.workspace_.setResizesEnabled(true); @@ -128,11 +143,11 @@ Blockly.BubbleDragger.prototype.endBubbleDrag = function(e, currentDragDeltaXY) }; /** - * Fire a move event at the end of a block drag. + * Fire a move event at the end of a bubble drag. * @private */ Blockly.BubbleDragger.prototype.fireMoveEvent_ = function() { - // TODO: move events for comments. + // TODO (fenichel): move events for comments. return; }; @@ -160,3 +175,14 @@ Blockly.BubbleDragger.prototype.pixelsToWorkspaceUnits_ = function(pixelCoord) { } return result; }; +/** + * Move the bubble onto the drag surface at the beginning of a drag. Move the + * drag surface to preserve the apparent location of the bubble. + * @private + */ +Blockly.BubbleDragger.prototype.moveToDragSurface_ = function() { + this.draggingBubble_.moveTo(0, 0); + this.dragSurface_.translateSurface(this.startXY_.x, this.startXY_.y); + // Execute the move on the top-level SVG component. + this.dragSurface_.setBlocksAndShow(this.draggingBubble_.getSvgRoot()); +}; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 2f78a1663..53b600ae8 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -754,6 +754,15 @@ Blockly.WorkspaceSvg.prototype.setupDragSurface = function() { this.workspaceDragSurface_.translateSurface(coord.x, coord.y); }; +/** + * @return {?Blockly.BlockDragSurfaceSvg} This workspace's block drag surface, + * if one is in use. + * @package + */ +Blockly.WorkspaceSvg.prototype.getBlockDragSurface = function() { + return this.blockDragSurface_; +}; + /** * Returns the horizontal offset of the workspace. * Intended for LTR/RTL compatibility in XML.