mirror of
https://github.com/google/blockly.git
synced 2026-01-09 01:50:11 +01:00
Use the same math for dragging blocks out of horizontal and vertical flyouts. (#1215)
* Use the same math for dragging blocks out of horizontal and vertical flyouts. * Update flyout_base.js
This commit is contained in:
@@ -752,3 +752,62 @@ Blockly.Flyout.prototype.reflow = function() {
|
||||
Blockly.Flyout.prototype.isScrollable = function() {
|
||||
return this.scrollbar_ ? this.scrollbar_.isVisible() : false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a block from the flyout to the workspace and position it correctly.
|
||||
* @param {!Blockly.Block} oldBlock The flyout block to copy.
|
||||
* @return {!Blockly.Block} The new block in the main workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Flyout.prototype.placeNewBlock_ = function(oldBlock) {
|
||||
var targetWorkspace = this.targetWorkspace_;
|
||||
var svgRootOld = oldBlock.getSvgRoot();
|
||||
if (!svgRootOld) {
|
||||
throw 'oldBlock is not rendered.';
|
||||
}
|
||||
|
||||
// Create the new block by cloning the block in the flyout (via XML).
|
||||
var xml = Blockly.Xml.blockToDom(oldBlock);
|
||||
// The target workspace would normally resize during domToBlock, which will
|
||||
// lead to weird jumps. Save it for terminateDrag.
|
||||
targetWorkspace.setResizesEnabled(false);
|
||||
|
||||
// Using domToBlock instead of domToWorkspace means that the new block will be
|
||||
// placed at position (0, 0) in main workspace units.
|
||||
var block = Blockly.Xml.domToBlock(xml, targetWorkspace);
|
||||
var svgRootNew = block.getSvgRoot();
|
||||
if (!svgRootNew) {
|
||||
throw 'block is not rendered.';
|
||||
}
|
||||
|
||||
// The offset in pixels between the main workspace's origin and the upper left
|
||||
// corner of the injection div.
|
||||
var mainOffsetPixels = targetWorkspace.getOriginOffsetInPixels();
|
||||
|
||||
// The offset in pixels between the flyout workspace's origin and the upper
|
||||
// left corner of the injection div.
|
||||
var flyoutOffsetPixels = this.workspace_.getOriginOffsetInPixels();
|
||||
|
||||
// The position of the old block in flyout workspace coordinates.
|
||||
var oldBlockPosWs = oldBlock.getRelativeToSurfaceXY();
|
||||
|
||||
// The position of the old block in pixels relative to the flyout
|
||||
// workspace's origin.
|
||||
var oldBlockPosPixels = oldBlockPosWs.scale(this.workspace_.scale);
|
||||
|
||||
// The position of the old block in pixels relative to the upper left corner
|
||||
// of the injection div.
|
||||
var oldBlockOffsetPixels = goog.math.Coordinate.sum(flyoutOffsetPixels,
|
||||
oldBlockPosPixels);
|
||||
|
||||
// The position of the old block in pixels relative to the origin of the
|
||||
// main workspace.
|
||||
var finalOffsetPixels = goog.math.Coordinate.difference(oldBlockOffsetPixels,
|
||||
mainOffsetPixels);
|
||||
|
||||
// The position of the old block in main workspace coordinates.
|
||||
var finalOffsetMainWs = finalOffsetPixels.scale(1 / targetWorkspace.scale);
|
||||
|
||||
block.moveBy(finalOffsetMainWs.x, finalOffsetMainWs.y);
|
||||
return block;
|
||||
};
|
||||
|
||||
@@ -322,82 +322,6 @@ Blockly.HorizontalFlyout.prototype.isDragTowardWorkspace = function(
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a block from the flyout to the workspace and position it correctly.
|
||||
* @param {!Blockly.Block} originBlock The flyout block to copy..
|
||||
* @return {!Blockly.Block} The new block in the main workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.placeNewBlock_ = function(originBlock) {
|
||||
var targetWorkspace = this.targetWorkspace_;
|
||||
var svgRootOld = originBlock.getSvgRoot();
|
||||
if (!svgRootOld) {
|
||||
throw 'originBlock is not rendered.';
|
||||
}
|
||||
// Figure out where the original block is on the screen, relative to the upper
|
||||
// left corner of the main workspace.
|
||||
if (targetWorkspace.isMutator) {
|
||||
var xyOld = this.workspace_.getSvgXY(/** @type {!Element} */ (svgRootOld));
|
||||
} else {
|
||||
var xyOld = Blockly.utils.getInjectionDivXY_(svgRootOld);
|
||||
}
|
||||
|
||||
// Take into account that the flyout might have been scrolled horizontally
|
||||
// (separately from the main workspace).
|
||||
// Generally a no-op in vertical mode but likely to happen in horizontal
|
||||
// mode.
|
||||
var scrollX = this.workspace_.scrollX;
|
||||
var scale = this.workspace_.scale;
|
||||
xyOld.x += scrollX / scale - scrollX;
|
||||
|
||||
// Take into account that the flyout might have been scrolled vertically
|
||||
// (separately from the main workspace).
|
||||
// Generally a no-op in horizontal mode but likely to happen in vertical
|
||||
// mode.
|
||||
var scrollY = this.workspace_.scrollY;
|
||||
scale = this.workspace_.scale;
|
||||
xyOld.y += scrollY / scale - scrollY;
|
||||
// If the flyout is on the bottom, (0, 0) in the flyout is offset to be below
|
||||
// (0, 0) in the main workspace. Add an offset to take that into account.
|
||||
if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) {
|
||||
scrollY = targetWorkspace.getMetrics().viewHeight - this.height_;
|
||||
scale = targetWorkspace.scale;
|
||||
xyOld.y += scrollY / scale - scrollY;
|
||||
}
|
||||
|
||||
// Create the new block by cloning the block in the flyout (via XML).
|
||||
var xml = Blockly.Xml.blockToDom(originBlock);
|
||||
var block = Blockly.Xml.domToBlock(xml, targetWorkspace);
|
||||
var svgRootNew = block.getSvgRoot();
|
||||
if (!svgRootNew) {
|
||||
throw 'block is not rendered.';
|
||||
}
|
||||
// Figure out where the new block got placed on the screen, relative to the
|
||||
// upper left corner of the workspace. This may not be the same as the
|
||||
// original block because the flyout's origin may not be the same as the
|
||||
// main workspace's origin.
|
||||
if (targetWorkspace.isMutator) {
|
||||
var xyNew = targetWorkspace.getSvgXY(/* @type {!Element} */(svgRootNew));
|
||||
} else {
|
||||
var xyNew = Blockly.utils.getInjectionDivXY_(svgRootNew);
|
||||
}
|
||||
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
xyNew.x +=
|
||||
targetWorkspace.scrollX / targetWorkspace.scale - targetWorkspace.scrollX;
|
||||
xyNew.y +=
|
||||
targetWorkspace.scrollY / targetWorkspace.scale - targetWorkspace.scrollY;
|
||||
// If the flyout is collapsible and the workspace can't be scrolled.
|
||||
if (targetWorkspace.toolbox_ && !targetWorkspace.scrollbar) {
|
||||
xyNew.x += targetWorkspace.toolbox_.getWidth() / targetWorkspace.scale;
|
||||
xyNew.y += targetWorkspace.toolbox_.getHeight() / targetWorkspace.scale;
|
||||
}
|
||||
|
||||
// Move the new block to where the old block is.
|
||||
block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);
|
||||
return block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the deletion rectangle for this flyout in viewport coordinates.
|
||||
* @return {goog.math.Rect} Rectangle in which to delete.
|
||||
|
||||
@@ -300,88 +300,6 @@ Blockly.VerticalFlyout.prototype.isDragTowardWorkspace = function(
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Copy a block from the flyout to the workspace and position it correctly.
|
||||
* @param {!Blockly.Block} originBlock The flyout block to copy.
|
||||
* @return {!Blockly.Block} The new block in the main workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.placeNewBlock_ = function(originBlock) {
|
||||
var targetWorkspace = this.targetWorkspace_;
|
||||
var svgRootOld = originBlock.getSvgRoot();
|
||||
if (!svgRootOld) {
|
||||
throw 'originBlock is not rendered.';
|
||||
}
|
||||
// Figure out where the original block is on the screen, relative to the upper
|
||||
// left corner of the main workspace.
|
||||
if (targetWorkspace.isMutator) {
|
||||
var xyOld = this.workspace_.getSvgXY(/** @type {!Element} */ (svgRootOld));
|
||||
} else {
|
||||
var xyOld = Blockly.utils.getInjectionDivXY_(svgRootOld);
|
||||
}
|
||||
|
||||
// Take into account that the flyout might have been scrolled horizontally
|
||||
// (separately from the main workspace).
|
||||
// Generally a no-op in vertical mode but likely to happen in horizontal
|
||||
// mode.
|
||||
var scrollX = this.workspace_.scrollX;
|
||||
var scale = this.workspace_.scale;
|
||||
xyOld.x += scrollX / scale - scrollX;
|
||||
|
||||
var targetMetrics = targetWorkspace.getMetrics();
|
||||
|
||||
// If the flyout is on the right side, (0, 0) in the flyout is offset to
|
||||
// the right of (0, 0) in the main workspace. Add an offset to take that
|
||||
// into account.
|
||||
var scrollX = 0;
|
||||
if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) {
|
||||
scrollX = targetMetrics.viewWidth - this.width_;
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
xyOld.x += scrollX / scale - scrollX;
|
||||
}
|
||||
|
||||
// Take into account that the flyout might have been scrolled vertically
|
||||
// (separately from the main workspace).
|
||||
// Generally a no-op in horizontal mode but likely to happen in vertical
|
||||
// mode.
|
||||
var scrollY = this.workspace_.scrollY;
|
||||
scale = this.workspace_.scale;
|
||||
xyOld.y += scrollY / scale - scrollY;
|
||||
|
||||
// Create the new block by cloning the block in the flyout (via XML).
|
||||
var xml = Blockly.Xml.blockToDom(originBlock);
|
||||
var block = Blockly.Xml.domToBlock(xml, targetWorkspace);
|
||||
var svgRootNew = block.getSvgRoot();
|
||||
if (!svgRootNew) {
|
||||
throw 'block is not rendered.';
|
||||
}
|
||||
// Figure out where the new block got placed on the screen, relative to the
|
||||
// upper left corner of the workspace. This may not be the same as the
|
||||
// original block because the flyout's origin may not be the same as the
|
||||
// main workspace's origin.
|
||||
if (targetWorkspace.isMutator) {
|
||||
var xyNew = targetWorkspace.getSvgXY(/* @type {!Element} */(svgRootNew));
|
||||
} else {
|
||||
var xyNew = Blockly.utils.getInjectionDivXY_(svgRootNew);
|
||||
}
|
||||
|
||||
// Scale the scroll (getSvgXY_ did not do this).
|
||||
xyNew.x +=
|
||||
targetWorkspace.scrollX / targetWorkspace.scale - targetWorkspace.scrollX;
|
||||
xyNew.y +=
|
||||
targetWorkspace.scrollY / targetWorkspace.scale - targetWorkspace.scrollY;
|
||||
|
||||
// If the flyout is collapsible and the workspace can't be scrolled.
|
||||
if (targetWorkspace.toolbox_ && !targetWorkspace.scrollbar) {
|
||||
xyNew.x += targetWorkspace.toolbox_.getWidth() / targetWorkspace.scale;
|
||||
xyNew.y += targetWorkspace.toolbox_.getHeight() / targetWorkspace.scale;
|
||||
}
|
||||
|
||||
// Move the new block to where the old block is.
|
||||
block.moveBy(xyOld.x - xyNew.x, xyOld.y - xyNew.y);
|
||||
return block;
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the deletion rectangle for this flyout in viewport coordinates.
|
||||
* @return {goog.math.Rect} Rectangle in which to delete.
|
||||
|
||||
@@ -315,6 +315,18 @@ Blockly.WorkspaceSvg.prototype.getSvgXY = function(element) {
|
||||
return new goog.math.Coordinate(x, y);
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the position of the workspace origin relative to the injection div
|
||||
* origin in pixels.
|
||||
* The workspace origin is where a block would render at position (0, 0).
|
||||
* It is not the upper left corner of the workspace SVG.
|
||||
* @return {!goog.math.Coordinate} Offset in pixels.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.getOriginOffsetInPixels = function() {
|
||||
return Blockly.utils.getInjectionDivXY_(this.svgBlockCanvas_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Save resize handler data so we can delete it later in dispose.
|
||||
* @param {!Array.<!Array>} handler Data that can be passed to unbindEvent_.
|
||||
|
||||
Reference in New Issue
Block a user