Create WorkspaceViewport class (#1291)

* Create WorkspaceViewport class

* Update comments

* Move workspace viewport functions back to the workspace for now

* whitespace
This commit is contained in:
Rachel Fenichel
2017-08-24 15:51:31 -07:00
committed by GitHub
parent 8e8b6b27af
commit 6c00d77c9e

View File

@@ -1415,6 +1415,7 @@ Blockly.WorkspaceSvg.prototype.zoom = function(x, y, amount) {
.translate(x * (1 - scaleChange), y * (1 - scaleChange))
.scale(scaleChange);
// newScale and matrix.a should be identical (within a rounding error).
// ScrollX and scrollY are in pixels.
this.scrollX = matrix.e - metrics.absoluteLeft;
this.scrollY = matrix.f - metrics.absoluteTop;
}
@@ -1504,6 +1505,118 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
}
};
/**
* Get the dimensions of the given workspace component, in pixels.
* @param {Blockly.Toolbox|Blockly.Flyout} elem The element to get the
* dimensions of, or null. It should be a toolbox or flyout, and should
* implement getWidth() and getHeight().
* @return {!Object} An object containing width and height attributes, which
* will both be zero if elem did not exist.
* @private
*/
Blockly.WorkspaceSvg.getDimensionsPx_ = function(elem) {
var width = 0;
var height = 0;
if (elem) {
width = elem.getWidth();
height = elem.getHeight();
}
return {
width: width,
height: height
};
};
/**
* Get the content dimensions of the given workspace, taking into account
* whether or not it is scrollable and what size the workspace div is on screen.
* @param {!Blockly.WorkspaceSvg} ws The workspace to measure.
* @param {!Object} svgSize An object containing height and width attributes in
* CSS pixels. Together they specify the size of the visible workspace, not
* including areas covered up by the toolbox.
* @return {!Object} The dimensions of the contents of the given workspace, as
* an object containing at least
* - height and width in pixels
* - left and top in pixels relative to the workspace origin.
* @private
*/
Blockly.WorkspaceSvg.getContentDimensions_ = function(ws, svgSize) {
if (ws.scrollbar) {
return Blockly.WorkspaceSvg.getContentDimensionsBounded_(ws, svgSize);
} else {
return Blockly.WorkspaceSvg.getContentDimensionsExact_(ws);
}
};
/**
* Get the bounding box for all workspace contents, in pixels.
* @param {!Blockly.WorkspaceSvg} ws The workspace to inspect.
* @return {!Object} The dimensions of the contents of the given workspace, as
* an object containing
* - height and width in pixels
* - left, right, top and bottom in pixels relative to the workspace origin.
* @private
*/
Blockly.WorkspaceSvg.getContentDimensionsExact_ = function(ws) {
// Block bounding box is in workspace coordinates.
var blockBox = ws.getBlocksBoundingBox();
var scale = ws.scale;
// Convert to pixels.
var width = blockBox.width * scale;
var height = blockBox.height * scale;
var left = blockBox.x * scale;
var top = blockBox.y * scale;
return {
left: left,
top: top,
right: left + width,
bottom: top + height,
width: width,
height: height
};
};
/**
* Calculate the size of a scrollable workspace, which should include room for a
* half screen border around the workspace contents.
* @param {!Blockly.WorkspaceSvg} ws The workspace to measure.
* @param {!Object} svgSize An object containing height and width attributes in
* CSS pixels. Together they specify the size of the visible workspace, not
* including areas covered up by the toolbox.
* @return {!Object} The dimensions of the contents of the given workspace, as
* an object containing
* - height and width in pixels
* - left and top in pixels relative to the workspace origin.
* @private
*/
Blockly.WorkspaceSvg.getContentDimensionsBounded_ = function(ws, svgSize) {
var content = Blockly.WorkspaceSvg.getContentDimensionsExact_(ws);
// View height and width are both in pixels, and are the same as the svg size.
var viewWidth = svgSize.width;
var viewHeight = svgSize.height;
var halfWidth = viewWidth / 2;
var halfHeight = viewHeight / 2;
// Add a border around the content that is at least half a screenful wide.
// Ensure border is wide enough that blocks can scroll over entire screen.
var left = Math.min(content.left - halfWidth, content.right - viewWidth);
var right = Math.max(content.right + halfWidth, content.left + viewWidth);
var top = Math.min(content.top - halfHeight, content.bottom - viewHeight);
var bottom = Math.max(content.bottom + halfHeight, content.top + viewHeight);
var dimensions = {
left: left,
top: top,
height: bottom - top,
width: right - left
};
return dimensions;
};
/**
* Return an object with all the metrics required to size scrollbars for a
* top level workspace. The following properties are computed:
@@ -1529,70 +1642,59 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
* @this Blockly.WorkspaceSvg
*/
Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_ = function() {
var toolboxDimensions =
Blockly.WorkspaceSvg.getDimensionsPx_(this.toolbox_);
var flyoutDimensions =
Blockly.WorkspaceSvg.getDimensionsPx_(this.flyout_);
// Contains height and width in CSS pixels.
// svgSize is equivalent to the size of the injectionDiv at this point.
var svgSize = Blockly.svgSize(this.getParentSvg());
if (this.toolbox_) {
if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP ||
this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) {
svgSize.height -= this.toolbox_.getHeight();
svgSize.height -= toolboxDimensions.height;
} else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT ||
this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) {
svgSize.width -= this.toolbox_.getWidth();
svgSize.width -= toolboxDimensions.width;
}
}
// Set the margin to match the flyout's margin so that the workspace does
// not jump as blocks are added.
var MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS - 1;
var viewWidth = svgSize.width - MARGIN;
var viewHeight = svgSize.height - MARGIN;
var blockBox = this.getBlocksBoundingBox();
// svgSize is now the space taken up by the Blockly workspace, not including
// the toolbox.
var contentDimensions =
Blockly.WorkspaceSvg.getContentDimensions_(this, svgSize);
// Fix scale.
var contentWidth = blockBox.width * this.scale;
var contentHeight = blockBox.height * this.scale;
var contentX = blockBox.x * this.scale;
var contentY = blockBox.y * this.scale;
if (this.scrollbar) {
// Add a border around the content that is at least half a screenful wide.
// Ensure border is wide enough that blocks can scroll over entire screen.
var leftEdge = Math.min(contentX - viewWidth / 2,
contentX + contentWidth - viewWidth);
var rightEdge = Math.max(contentX + contentWidth + viewWidth / 2,
contentX + viewWidth);
var topEdge = Math.min(contentY - viewHeight / 2,
contentY + contentHeight - viewHeight);
var bottomEdge = Math.max(contentY + contentHeight + viewHeight / 2,
contentY + viewHeight);
} else {
var leftEdge = blockBox.x;
var rightEdge = leftEdge + blockBox.width;
var topEdge = blockBox.y;
var bottomEdge = topEdge + blockBox.height;
}
var absoluteLeft = 0;
if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) {
absoluteLeft = this.toolbox_.getWidth();
absoluteLeft = toolboxDimensions.width;
}
var absoluteTop = 0;
if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) {
absoluteTop = this.toolbox_.getHeight();
absoluteTop = toolboxDimensions.height;
}
var metrics = {
contentHeight: contentDimensions.height,
contentWidth: contentDimensions.width,
contentTop: contentDimensions.top,
contentLeft: contentDimensions.left,
viewHeight: svgSize.height,
viewWidth: svgSize.width,
contentHeight: bottomEdge - topEdge,
contentWidth: rightEdge - leftEdge,
viewTop: -this.scrollY,
viewLeft: -this.scrollX,
contentTop: topEdge,
contentLeft: leftEdge,
viewTop: -this.scrollY, // Must be in pixels, somehow.
viewLeft: -this.scrollX, // Must be in pixels, somehow.
absoluteTop: absoluteTop,
absoluteLeft: absoluteLeft,
toolboxWidth: this.toolbox_ ? this.toolbox_.getWidth() : 0,
toolboxHeight: this.toolbox_ ? this.toolbox_.getHeight() : 0,
flyoutWidth: this.flyout_ ? this.flyout_.getWidth() : 0,
flyoutHeight: this.flyout_ ? this.flyout_.getHeight() : 0,
toolboxWidth: toolboxDimensions.width,
toolboxHeight: toolboxDimensions.height,
flyoutWidth: flyoutDimensions.width,
flyoutHeight: flyoutDimensions.height,
toolboxPosition: this.toolboxPosition
};
return metrics;