mirror of
https://github.com/google/blockly.git
synced 2026-01-07 00:50:27 +01:00
Updating bump logic to support single-direction scrollbars (#4652)
* Updating bump logic to support single-direction scrollbars
This commit is contained in:
@@ -200,11 +200,22 @@ Blockly.Events.COMMENT_MOVE = 'comment_move';
|
||||
Blockly.Events.FINISHED_LOADING = 'finished_loading';
|
||||
|
||||
/**
|
||||
* List of events that cause objects to be bumped back into the visible
|
||||
* portion of the workspace (only used for non-movable workspaces).
|
||||
* Type of events that cause objects to be bumped back into the visible
|
||||
* portion of the workspace.
|
||||
*
|
||||
* Not to be confused with bumping so that disconnected connections to do
|
||||
* not appear connected.
|
||||
* Not to be confused with bumping so that disconnected connections do not
|
||||
* appear connected.
|
||||
* @typedef {!Blockly.Events.BlockCreate|!Blockly.Events.BlockMove|
|
||||
* !Blockly.Events.CommentCreate|!Blockly.Events.CommentMove}
|
||||
*/
|
||||
Blockly.Events.BumpEvent;
|
||||
|
||||
/**
|
||||
* List of events that cause objects to be bumped back into the visible
|
||||
* portion of the workspace.
|
||||
*
|
||||
* Not to be confused with bumping so that disconnected connections do not
|
||||
* appear connected.
|
||||
* @const
|
||||
*/
|
||||
Blockly.Events.BUMP_EVENTS = [
|
||||
|
||||
@@ -48,11 +48,15 @@ Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);
|
||||
* .viewWidth: Width of the visible rectangle,
|
||||
* .contentHeight: Height of the contents,
|
||||
* .contentWidth: Width of the contents,
|
||||
* .scrollHeight: Height of the scroll area,
|
||||
* .scrollWidth: Width of the scroll area,
|
||||
* .viewTop: Offset of top edge of visible rectangle from parent,
|
||||
* .contentTop: Offset of the top-most content from the y=0 coordinate,
|
||||
* .scrollTop: Offset of the scroll area top from the y=0 coordinate,
|
||||
* .absoluteTop: Top-edge of view.
|
||||
* .viewLeft: Offset of the left edge of visible rectangle from parent,
|
||||
* .contentLeft: Offset of the left-most content from the x=0 coordinate,
|
||||
* .scrollLeft: Offset of the scroll area left from the x=0 coordinate,
|
||||
* .absoluteLeft: Left-edge of view.
|
||||
* @return {Blockly.utils.Metrics} Contains size and position metrics of the
|
||||
* flyout.
|
||||
@@ -83,11 +87,16 @@ Blockly.HorizontalFlyout.prototype.getMetrics_ = function() {
|
||||
var viewWidth = this.width_ - 2 * this.SCROLLBAR_PADDING;
|
||||
|
||||
var metrics = {
|
||||
contentHeight: (optionBox.height + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
contentWidth: (optionBox.width + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
contentHeight: optionBox.height * this.workspace_.scale,
|
||||
contentWidth: optionBox.width * this.workspace_.scale,
|
||||
contentTop: 0,
|
||||
contentLeft: 0,
|
||||
|
||||
scrollHeight: (optionBox.height + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
scrollWidth: (optionBox.width + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
scrollTop: 0,
|
||||
scrollLeft: 0,
|
||||
|
||||
viewHeight: viewHeight,
|
||||
viewWidth: viewWidth,
|
||||
viewTop: -this.workspace_.scrollY,
|
||||
@@ -115,8 +124,8 @@ Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
|
||||
if (typeof xyRatio.x == 'number') {
|
||||
this.workspace_.scrollX =
|
||||
-(metrics.contentLeft +
|
||||
(metrics.contentWidth - metrics.viewWidth) * xyRatio.x);
|
||||
-(metrics.scrollLeft +
|
||||
(metrics.scrollWidth - metrics.viewWidth) * xyRatio.x);
|
||||
}
|
||||
|
||||
this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
|
||||
@@ -267,7 +276,7 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
if (delta) {
|
||||
var metrics = this.getMetrics_();
|
||||
var pos = metrics.viewLeft + delta;
|
||||
var limit = metrics.contentWidth - metrics.viewWidth;
|
||||
var limit = metrics.scrollWidth - metrics.viewWidth;
|
||||
pos = Math.min(pos, limit);
|
||||
pos = Math.max(pos, 0);
|
||||
this.workspace_.scrollbar.setX(pos);
|
||||
|
||||
@@ -55,9 +55,11 @@ Blockly.VerticalFlyout.registryName = 'verticalFlyout';
|
||||
* .contentWidth: Width of the contents,
|
||||
* .viewTop: Offset of top edge of visible rectangle from parent,
|
||||
* .contentTop: Offset of the top-most content from the y=0 coordinate,
|
||||
* .scrollTop: Offset of the scroll area top from the y=0 coordinate,
|
||||
* .absoluteTop: Top-edge of view.
|
||||
* .viewLeft: Offset of the left edge of visible rectangle from parent,
|
||||
* .contentLeft: Offset of the left-most content from the x=0 coordinate,
|
||||
* .scrollLeft: Offset of the scroll area left from the x=0 coordinate,
|
||||
* .absoluteLeft: Left-edge of view.
|
||||
* @return {Blockly.utils.Metrics} Contains size and position metrics of the
|
||||
* flyout.
|
||||
@@ -87,10 +89,15 @@ Blockly.VerticalFlyout.prototype.getMetrics_ = function() {
|
||||
}
|
||||
|
||||
var metrics = {
|
||||
contentHeight: optionBox.height * this.workspace_.scale + 2 * this.MARGIN,
|
||||
contentWidth: optionBox.width * this.workspace_.scale + 2 * this.MARGIN,
|
||||
contentTop: optionBox.y - this.MARGIN,
|
||||
contentLeft: optionBox.x - this.MARGIN,
|
||||
contentHeight: optionBox.height * this.workspace_.scale,
|
||||
contentWidth: optionBox.width * this.workspace_.scale,
|
||||
contentTop: optionBox.y,
|
||||
contentLeft: optionBox.x,
|
||||
|
||||
scrollHeight: (optionBox.height + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
scrollWidth: (optionBox.width + 2 * this.MARGIN) * this.workspace_.scale,
|
||||
scrollTop: optionBox.y - this.MARGIN,
|
||||
scrollLeft: optionBox.x - this.MARGIN,
|
||||
|
||||
viewHeight: viewHeight,
|
||||
viewWidth: viewWidth,
|
||||
@@ -118,8 +125,8 @@ Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
}
|
||||
if (typeof xyRatio.y == 'number') {
|
||||
this.workspace_.scrollY =
|
||||
-(metrics.contentTop +
|
||||
(metrics.contentHeight - metrics.viewHeight) * xyRatio.y);
|
||||
-(metrics.scrollTop +
|
||||
(metrics.scrollHeight - metrics.viewHeight) * xyRatio.y);
|
||||
}
|
||||
this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
|
||||
this.workspace_.scrollY + metrics.absoluteTop);
|
||||
@@ -258,8 +265,8 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
|
||||
if (scrollDelta.y) {
|
||||
var metrics = this.getMetrics_();
|
||||
var pos = (metrics.viewTop - metrics.contentTop) + scrollDelta.y;
|
||||
var limit = metrics.contentHeight - metrics.viewHeight;
|
||||
var pos = (metrics.viewTop - metrics.scrollTop) + scrollDelta.y;
|
||||
var limit = metrics.scrollHeight - metrics.viewHeight;
|
||||
pos = Math.min(pos, limit);
|
||||
pos = Math.max(pos, 0);
|
||||
this.workspace_.scrollbar.setY(pos);
|
||||
|
||||
279
core/inject.js
279
core/inject.js
@@ -181,147 +181,7 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
|
||||
// A null translation will also apply the correct initial scale.
|
||||
mainWorkspace.translate(0, 0);
|
||||
|
||||
if (!wsOptions.readOnly && !mainWorkspace.isMovable()) {
|
||||
// Helper function for the workspaceChanged callback.
|
||||
// TODO (#2300): Move metrics math back to the WorkspaceSvg.
|
||||
var getWorkspaceMetrics = function() {
|
||||
var workspaceMetrics = Object.create(null);
|
||||
var defaultMetrics = mainWorkspace.getMetrics();
|
||||
var scale = mainWorkspace.scale;
|
||||
|
||||
workspaceMetrics.RTL = mainWorkspace.RTL;
|
||||
|
||||
// Get the view metrics in workspace units.
|
||||
workspaceMetrics.viewLeft = defaultMetrics.viewLeft / scale;
|
||||
workspaceMetrics.viewTop = defaultMetrics.viewTop / scale;
|
||||
workspaceMetrics.viewRight =
|
||||
(defaultMetrics.viewLeft + defaultMetrics.viewWidth) / scale;
|
||||
workspaceMetrics.viewBottom =
|
||||
(defaultMetrics.viewTop + defaultMetrics.viewHeight) / scale;
|
||||
|
||||
// Get the exact content metrics (in workspace units), even if the
|
||||
// content is bounded.
|
||||
if (mainWorkspace.isContentBounded()) {
|
||||
// Already in workspace units, no need to divide by scale.
|
||||
var blocksBoundingBox = mainWorkspace.getBlocksBoundingBox();
|
||||
workspaceMetrics.contentLeft = blocksBoundingBox.left;
|
||||
workspaceMetrics.contentTop = blocksBoundingBox.top;
|
||||
workspaceMetrics.contentRight = blocksBoundingBox.right;
|
||||
workspaceMetrics.contentBottom = blocksBoundingBox.bottom;
|
||||
} else {
|
||||
workspaceMetrics.contentLeft = defaultMetrics.contentLeft / scale;
|
||||
workspaceMetrics.contentTop = defaultMetrics.contentTop / scale;
|
||||
workspaceMetrics.contentRight =
|
||||
(defaultMetrics.contentLeft + defaultMetrics.contentWidth) / scale;
|
||||
workspaceMetrics.contentBottom =
|
||||
(defaultMetrics.contentTop + defaultMetrics.contentHeight) / scale;
|
||||
}
|
||||
|
||||
return workspaceMetrics;
|
||||
};
|
||||
|
||||
var getObjectMetrics = function(object) {
|
||||
var objectMetrics = object.getBoundingRectangle();
|
||||
objectMetrics.height = objectMetrics.bottom - objectMetrics.top;
|
||||
objectMetrics.width = objectMetrics.right - objectMetrics.left;
|
||||
return objectMetrics;
|
||||
};
|
||||
|
||||
var bumpObjects = function(e) {
|
||||
// We always check isMovable_ again because the original
|
||||
// "not movable" state of isMovable_ could have been changed.
|
||||
if (!mainWorkspace.isDragging() && !mainWorkspace.isMovable() &&
|
||||
(Blockly.Events.BUMP_EVENTS.indexOf(e.type) != -1)) {
|
||||
var metrics = getWorkspaceMetrics();
|
||||
if (metrics.contentTop < metrics.viewTop ||
|
||||
metrics.contentBottom > metrics.viewBottom ||
|
||||
metrics.contentLeft < metrics.viewLeft ||
|
||||
metrics.contentRight > metrics.viewRight) {
|
||||
|
||||
// Handle undo.
|
||||
var oldGroup = null;
|
||||
if (e) {
|
||||
oldGroup = Blockly.Events.getGroup();
|
||||
Blockly.Events.setGroup(e.group);
|
||||
}
|
||||
|
||||
switch (e.type) {
|
||||
case Blockly.Events.BLOCK_CREATE:
|
||||
case Blockly.Events.BLOCK_MOVE:
|
||||
var object = mainWorkspace.getBlockById(e.blockId);
|
||||
if (object) {
|
||||
object = object.getRootBlock();
|
||||
}
|
||||
break;
|
||||
case Blockly.Events.COMMENT_CREATE:
|
||||
case Blockly.Events.COMMENT_MOVE:
|
||||
var object = mainWorkspace.getCommentById(e.commentId);
|
||||
break;
|
||||
}
|
||||
if (object) {
|
||||
var objectMetrics = getObjectMetrics(object);
|
||||
|
||||
// The idea is to find the region of valid coordinates for the top
|
||||
// left corner of the object, and then clamp the object's
|
||||
// top left corner within that region.
|
||||
|
||||
// The top of the object should always be at or below the top of
|
||||
// the workspace.
|
||||
var topClamp = metrics.viewTop;
|
||||
// The top of the object should ideally be positioned so that
|
||||
// the bottom of the object is not below the bottom of the
|
||||
// workspace.
|
||||
var bottomClamp = metrics.viewBottom - objectMetrics.height;
|
||||
// If the object is taller than the workspace we want to
|
||||
// top-align the block, which means setting the bottom clamp to
|
||||
// match.
|
||||
bottomClamp = Math.max(topClamp, bottomClamp);
|
||||
|
||||
var newYPosition = Blockly.utils.math.clamp(
|
||||
topClamp, objectMetrics.top, bottomClamp);
|
||||
var deltaY = newYPosition - objectMetrics.top;
|
||||
|
||||
// Note: Even in RTL mode the "anchor" of the object is the
|
||||
// top-left corner of the object.
|
||||
|
||||
// The left edge of the object should ideally be positioned at
|
||||
// or to the right of the left edge of the workspace.
|
||||
var leftClamp = metrics.viewLeft;
|
||||
// The left edge of the object should ideally be positioned so
|
||||
// that the right of the object is not outside the workspace bounds.
|
||||
var rightClamp = metrics.viewRight - objectMetrics.width;
|
||||
if (metrics.RTL) {
|
||||
// If the object is wider than the workspace and we're in RTL
|
||||
// mode we want to right-align the block, which means setting
|
||||
// the left clamp to match.
|
||||
leftClamp = Math.min(rightClamp, leftClamp);
|
||||
} else {
|
||||
// If the object is wider than the workspace and we're in LTR
|
||||
// mode we want to left-align the block, which means setting
|
||||
// the right clamp to match.
|
||||
rightClamp = Math.max(leftClamp, rightClamp);
|
||||
}
|
||||
|
||||
var newXPosition = Blockly.utils.math.clamp(
|
||||
leftClamp, objectMetrics.left, rightClamp);
|
||||
var deltaX = newXPosition - objectMetrics.left;
|
||||
|
||||
object.moveBy(deltaX, deltaY);
|
||||
}
|
||||
if (e) {
|
||||
if (!e.group && object) {
|
||||
console.warn('Moved object in bounds but there was no' +
|
||||
' event group. This may break undo.');
|
||||
}
|
||||
if (oldGroup !== null) {
|
||||
Blockly.Events.setGroup(oldGroup);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
mainWorkspace.addChangeListener(bumpObjects);
|
||||
}
|
||||
mainWorkspace.addChangeListener(Blockly.bumpIntoBoundsHandler_(mainWorkspace));
|
||||
|
||||
// The SVG is now fully assembled.
|
||||
Blockly.svgResize(mainWorkspace);
|
||||
@@ -331,6 +191,142 @@ Blockly.createMainWorkspace_ = function(svg, options, blockDragSurface,
|
||||
return mainWorkspace;
|
||||
};
|
||||
|
||||
/**
|
||||
* Extracts the object from the given event.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace the event originated
|
||||
* from.
|
||||
* @param {!Blockly.Events.BumpEvent} e An event containing an object.
|
||||
* @return {?Blockly.BlockSvg|?Blockly.WorkspaceCommentSvg} The extracted
|
||||
* object.
|
||||
* @private
|
||||
*/
|
||||
Blockly.extractObjectFromEvent_ = function(workspace, e) {
|
||||
var object = null;
|
||||
switch (e.type) {
|
||||
case Blockly.Events.BLOCK_CREATE:
|
||||
case Blockly.Events.BLOCK_MOVE:
|
||||
object = workspace.getBlockById(e.blockId);
|
||||
if (object) {
|
||||
object = object.getRootBlock();
|
||||
}
|
||||
break;
|
||||
case Blockly.Events.COMMENT_CREATE:
|
||||
case Blockly.Events.COMMENT_MOVE:
|
||||
object = workspace.getCommentById(e.commentId);
|
||||
break;
|
||||
}
|
||||
return object;
|
||||
};
|
||||
|
||||
/**
|
||||
* Bumps the top objects in the given workspace into bounds.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.bumpTopObjectsIntoBounds_ = function(workspace) {
|
||||
var metricsManager = workspace.getMetricsManager();
|
||||
if (!metricsManager.hasFixedEdges() || workspace.isDragging()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
|
||||
var topBlocks = workspace.getTopBoundedElements();
|
||||
for (var i = 0, block; (block = topBlocks[i]); i++) {
|
||||
Blockly.bumpObjectIntoBounds_(
|
||||
workspace, scrollMetricsInWsCoords, block);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates a handler for bumping objects when they cross fixed bounds.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace to handle.
|
||||
* @return {function(Blockly.Events.Abstract)} The event handler.
|
||||
* @private
|
||||
*/
|
||||
Blockly.bumpIntoBoundsHandler_ = function(workspace) {
|
||||
return function(e) {
|
||||
var metricsManager = workspace.getMetricsManager();
|
||||
if (!metricsManager.hasFixedEdges() || workspace.isDragging() ||
|
||||
Blockly.Events.BUMP_EVENTS.indexOf(e.type) === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true);
|
||||
|
||||
// Triggered by move/create event
|
||||
var object = Blockly.extractObjectFromEvent_(workspace, e);
|
||||
if (!object) {
|
||||
return;
|
||||
}
|
||||
// Handle undo.
|
||||
var oldGroup = Blockly.Events.getGroup();
|
||||
Blockly.Events.setGroup(e.group);
|
||||
|
||||
var wasBumped = Blockly.bumpObjectIntoBounds_(
|
||||
workspace, scrollMetricsInWsCoords,
|
||||
/** @type {!Blockly.IBoundedElement} */ (object));
|
||||
|
||||
if (wasBumped && !e.group) {
|
||||
console.warn('Moved object in bounds but there was no' +
|
||||
' event group. This may break undo.');
|
||||
}
|
||||
if (oldGroup !== null) {
|
||||
Blockly.Events.setGroup(oldGroup);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Bumps the given object that has passed out of bounds.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The workspace containing the object.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion} scrollMetrics Scroll metrics
|
||||
* in workspace coordinates.
|
||||
* @param {!Blockly.IBoundedElement} object The object to bump.
|
||||
* @return {boolean} True if block was bumped.
|
||||
* @private
|
||||
*/
|
||||
Blockly.bumpObjectIntoBounds_ = function(workspace, scrollMetrics, object) {
|
||||
// Compute new top/left position for object.
|
||||
var objectMetrics = object.getBoundingRectangle();
|
||||
var height = objectMetrics.bottom - objectMetrics.top;
|
||||
var width = objectMetrics.right - objectMetrics.left;
|
||||
|
||||
var topClamp = scrollMetrics.top;
|
||||
var scrollMetricsBottom = scrollMetrics.top + scrollMetrics.height;
|
||||
var bottomClamp = scrollMetricsBottom - height;
|
||||
// If the object is taller than the workspace we want to
|
||||
// top-align the block
|
||||
var newYPosition =
|
||||
Blockly.utils.math.clamp(topClamp, objectMetrics.top, bottomClamp);
|
||||
var deltaY = newYPosition - objectMetrics.top;
|
||||
|
||||
// Note: Even in RTL mode the "anchor" of the object is the
|
||||
// top-left corner of the object.
|
||||
var leftClamp = scrollMetrics.left;
|
||||
var scrollMetricsRight = scrollMetrics.left + scrollMetrics.width;
|
||||
var rightClamp = scrollMetricsRight - width;
|
||||
if (workspace.RTL) {
|
||||
// If the object is wider than the workspace and we're in RTL
|
||||
// mode we want to right-align the block, which means setting
|
||||
// the left clamp to match.
|
||||
leftClamp = Math.min(rightClamp, leftClamp);
|
||||
} else {
|
||||
// If the object is wider than the workspace and we're in LTR
|
||||
// mode we want to left-align the block, which means setting
|
||||
// the right clamp to match.
|
||||
rightClamp = Math.max(leftClamp, rightClamp);
|
||||
}
|
||||
var newXPosition =
|
||||
Blockly.utils.math.clamp(leftClamp, objectMetrics.left, rightClamp);
|
||||
var deltaX = newXPosition - objectMetrics.left;
|
||||
|
||||
if (deltaX || deltaY) {
|
||||
object.moveBy(deltaX, deltaY);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize Blockly with various handlers.
|
||||
* @param {!Blockly.WorkspaceSvg} mainWorkspace Newly created main workspace.
|
||||
@@ -353,6 +349,7 @@ Blockly.init_ = function(mainWorkspace) {
|
||||
Blockly.browserEvents.conditionalBind(window, 'resize', null, function() {
|
||||
Blockly.hideChaff(true);
|
||||
Blockly.svgResize(mainWorkspace);
|
||||
Blockly.bumpTopObjectsIntoBounds_(mainWorkspace);
|
||||
});
|
||||
mainWorkspace.setResizeHandlerWrapper(workspaceResizeHandler);
|
||||
|
||||
|
||||
@@ -29,3 +29,10 @@ Blockly.IBoundedElement = function() {};
|
||||
* @return {!Blockly.utils.Rect} Object with coordinates of the bounded element.
|
||||
*/
|
||||
Blockly.IBoundedElement.prototype.getBoundingRectangle;
|
||||
|
||||
/**
|
||||
* Move the element by a relative offset.
|
||||
* @param {number} dx Horizontal offset in workspace units.
|
||||
* @param {number} dy Vertical offset in workspace units.
|
||||
*/
|
||||
Blockly.IBoundedElement.prototype.moveBy;
|
||||
|
||||
@@ -28,30 +28,26 @@ goog.requireType('Blockly.utils.toolbox');
|
||||
Blockly.IMetricsManager = function() {};
|
||||
|
||||
/**
|
||||
* Gets the width and the height of the flyout on the workspace in pixel
|
||||
* coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion} viewMetrics 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 {!Blockly.MetricsManager.ContainerRegion} 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.
|
||||
* @protected
|
||||
* Returns whether the scroll area has fixed edges.
|
||||
* @return {boolean} Whether the scroll area has fixed edges.
|
||||
* @package
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getContentDimensionsBounded_;
|
||||
Blockly.IMetricsManager.prototype.hasFixedEdges;
|
||||
|
||||
/**
|
||||
* Gets the bounding box for all workspace contents, in pixel coordinates.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The dimensions of the
|
||||
* contents of the given workspace in pixel coordinates, as an object
|
||||
* containing
|
||||
* - height and width in pixels
|
||||
* - left and top in pixels relative to the workspace origin.
|
||||
* @protected
|
||||
* Returns the metrics for the scroll area of the workspace.
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the scroll metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Passing in null may cause
|
||||
* the view metrics to be computed again, if it is needed.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_contentMetrics The
|
||||
* content metrics if they have been previously computed. Passing in null
|
||||
* may cause the content metrics to be computed again, if it is needed.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll
|
||||
* container
|
||||
*/
|
||||
Blockly.IMetricsManager.prototype.getContentDimensionsExact_;
|
||||
Blockly.IMetricsManager.prototype.getScrollMetrics;
|
||||
|
||||
/**
|
||||
* Gets the width and the height of the flyout on the workspace in pixel
|
||||
@@ -107,19 +103,10 @@ Blockly.IMetricsManager.prototype.getViewMetrics;
|
||||
|
||||
/**
|
||||
* Gets content metrics in either pixel or workspace coordinates.
|
||||
*
|
||||
* This can mean two things:
|
||||
* If the workspace has a fixed width and height then the content
|
||||
* area is rectangle around all the top bounded elements on the workspace
|
||||
* (workspace comments and blocks).
|
||||
*
|
||||
* If the workspace does not have a fixed width and height then it is the
|
||||
* metrics of the area that content can be placed.
|
||||
* The content area is a rectangle around all the top bounded elements on the
|
||||
* workspace (workspace comments and blocks).
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the content metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Passing in null may cause
|
||||
* the view metrics to be computed again, if it is needed.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The
|
||||
* metrics for the content container.
|
||||
* @public
|
||||
|
||||
@@ -71,6 +71,17 @@ Blockly.MetricsManager.AbsoluteMetrics;
|
||||
*/
|
||||
Blockly.MetricsManager.ContainerRegion;
|
||||
|
||||
/**
|
||||
* Describes fixed edges of the workspace.
|
||||
* @typedef {{
|
||||
* top: (number|undefined),
|
||||
* bottom: (number|undefined),
|
||||
* left: (number|undefined),
|
||||
* right: (number|undefined)
|
||||
* }}
|
||||
*/
|
||||
Blockly.MetricsManager.FixedEdges;
|
||||
|
||||
/**
|
||||
* Gets the dimensions of the given workspace component, in pixel coordinates.
|
||||
* @param {?Blockly.IToolbox|?Blockly.IFlyout} elem The element to get the
|
||||
@@ -90,66 +101,6 @@ Blockly.MetricsManager.prototype.getDimensionsPx_ = function(elem) {
|
||||
return new Blockly.utils.Size(width, height);
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates the size of a scrollable workspace, which should include
|
||||
* room for a half screen border around the workspace contents. In pixel
|
||||
* coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion} viewMetrics 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 {!Blockly.MetricsManager.ContainerRegion} 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.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getContentDimensionsBounded_ = function(
|
||||
viewMetrics) {
|
||||
var content = this.getContentDimensionsExact_();
|
||||
var contentRight = content.left + content.width;
|
||||
var contentBottom = content.top + content.height;
|
||||
|
||||
// View height and width are both in pixels, and are the same as the SVG size.
|
||||
var viewWidth = viewMetrics.width;
|
||||
var viewHeight = viewMetrics.height;
|
||||
var halfWidth = viewWidth / 2;
|
||||
var halfHeight = viewHeight / 2;
|
||||
|
||||
// Add a border around the content that is at least half a screen wide.
|
||||
// Ensure border is wide enough that blocks can scroll over entire screen.
|
||||
var left = Math.min(content.left - halfWidth, contentRight - viewWidth);
|
||||
var right = Math.max(contentRight + halfWidth, content.left + viewWidth);
|
||||
|
||||
var top = Math.min(content.top - halfHeight, contentBottom - viewHeight);
|
||||
var bottom = Math.max(contentBottom + halfHeight, content.top + viewHeight);
|
||||
|
||||
return {left: left, top: top, height: bottom - top, width: right - left};
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the bounding box for all workspace contents, in pixel coordinates.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The dimensions of the
|
||||
* contents of the given workspace in pixel coordinates, as an object
|
||||
* containing
|
||||
* - height and width in pixels
|
||||
* - left and top in pixels relative to the workspace origin.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getContentDimensionsExact_ = function() {
|
||||
// Block bounding box is in workspace coordinates.
|
||||
var blockBox = this.workspace_.getBlocksBoundingBox();
|
||||
var scale = this.workspace_.scale;
|
||||
|
||||
// Convert to pixels.
|
||||
var top = blockBox.top * scale;
|
||||
var bottom = blockBox.bottom * scale;
|
||||
var left = blockBox.left * scale;
|
||||
var right = blockBox.right * scale;
|
||||
|
||||
return {top: top, left: left, width: right - left, height: bottom - top};
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the width and the height of the flyout on the workspace in pixel
|
||||
* coordinates. Returns 0 for the width and height if the workspace has a
|
||||
@@ -280,40 +231,145 @@ Blockly.MetricsManager.prototype.getViewMetrics = function(
|
||||
|
||||
/**
|
||||
* Gets content metrics in either pixel or workspace coordinates.
|
||||
*
|
||||
* This can mean two things:
|
||||
* If the workspace has a fixed width and height then the content
|
||||
* area is rectangle around all the top bounded elements on the workspace
|
||||
* (workspace comments and blocks).
|
||||
*
|
||||
* If the workspace does not have a fixed width and height then it is the
|
||||
* metrics of the area that content can be placed. This area is computed by
|
||||
* getting the rectangle around the top bounded elements on the workspace and
|
||||
* adding padding to all sides.
|
||||
* The content area is a rectangle around all the top bounded elements on the
|
||||
* workspace (workspace comments and blocks).
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the content metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Not passing in view
|
||||
* metrics may cause them to be computed again.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The
|
||||
* metrics for the content container.
|
||||
* @public
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getContentMetrics = function(
|
||||
opt_getWorkspaceCoordinates, opt_viewMetrics) {
|
||||
var scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
|
||||
var contentDimensions = null;
|
||||
if (this.workspace_.isContentBounded()) {
|
||||
opt_viewMetrics = opt_viewMetrics || this.getViewMetrics(false);
|
||||
contentDimensions = this.getContentDimensionsBounded_(opt_viewMetrics);
|
||||
} else {
|
||||
contentDimensions = this.getContentDimensionsExact_();
|
||||
}
|
||||
opt_getWorkspaceCoordinates) {
|
||||
var scale = opt_getWorkspaceCoordinates ? 1 : this.workspace_.scale;
|
||||
|
||||
// Block bounding box is in workspace coordinates.
|
||||
var blockBox = this.workspace_.getBlocksBoundingBox();
|
||||
|
||||
return {
|
||||
height: contentDimensions.height / scale,
|
||||
width: contentDimensions.width / scale,
|
||||
top: contentDimensions.top / scale,
|
||||
left: contentDimensions.left / scale,
|
||||
height: (blockBox.bottom - blockBox.top) * scale,
|
||||
width: (blockBox.right - blockBox.left) * scale,
|
||||
top: blockBox.top * scale,
|
||||
left: blockBox.left * scale,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether the scroll area has fixed edges.
|
||||
* @return {boolean} Whether the scroll area has fixed edges.
|
||||
* @package
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.hasFixedEdges = function() {
|
||||
// This exists for optimization of bump logic.
|
||||
return !this.workspace_.isMovableHorizontally() ||
|
||||
!this.workspace_.isMovableVertically();
|
||||
};
|
||||
|
||||
/**
|
||||
* Computes the fixed edges of the scroll area.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Passing in null may cause
|
||||
* the view metrics to be computed again, if it is needed.
|
||||
* @return {Blockly.MetricsManager.FixedEdges} The fixed edges of the scroll
|
||||
* area.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getComputedFixedEdges_ = function(
|
||||
opt_viewMetrics) {
|
||||
if (!this.hasFixedEdges()) {
|
||||
// Return early if there are no edges.
|
||||
return {};
|
||||
}
|
||||
|
||||
var hScrollEnabled = this.workspace_.isMovableHorizontally();
|
||||
var vScrollEnabled = this.workspace_.isMovableVertically();
|
||||
|
||||
var viewMetrics = opt_viewMetrics || this.getViewMetrics(false);
|
||||
|
||||
var edges = {};
|
||||
if (!vScrollEnabled) {
|
||||
edges.top = viewMetrics.top;
|
||||
edges.bottom = viewMetrics.top + viewMetrics.height;
|
||||
}
|
||||
if (!hScrollEnabled) {
|
||||
edges.left = viewMetrics.left;
|
||||
edges.right = viewMetrics.left + viewMetrics.width;
|
||||
}
|
||||
return edges;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the content area with added padding.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion} viewMetrics The view
|
||||
* metrics.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion} contentMetrics The content
|
||||
* metrics.
|
||||
* @return {{top: number, bottom: number, left: number, right: number}} The
|
||||
* padded content area.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getPaddedContent_ = function(
|
||||
viewMetrics, contentMetrics) {
|
||||
var contentBottom = contentMetrics.top + contentMetrics.height;
|
||||
var contentRight = contentMetrics.left + contentMetrics.width;
|
||||
|
||||
var viewWidth = viewMetrics.width;
|
||||
var viewHeight = viewMetrics.height;
|
||||
var halfWidth = viewWidth / 2;
|
||||
var halfHeight = viewHeight / 2;
|
||||
|
||||
// Add a padding around the content that is at least half a screen wide.
|
||||
// Ensure padding is wide enough that blocks can scroll over entire screen.
|
||||
var top =
|
||||
Math.min(contentMetrics.top - halfHeight, contentBottom - viewHeight);
|
||||
var left =
|
||||
Math.min(contentMetrics.left - halfWidth, contentRight - viewWidth);
|
||||
var bottom =
|
||||
Math.max(contentBottom + halfHeight, contentMetrics.top + viewHeight);
|
||||
var right =
|
||||
Math.max(contentRight + halfWidth, contentMetrics.left + viewWidth);
|
||||
|
||||
return {top: top, bottom: bottom, left: left, right: right};
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the metrics for the scroll area of the workspace.
|
||||
* @param {boolean=} opt_getWorkspaceCoordinates True to get the scroll metrics
|
||||
* in workspace coordinates, false to get them in pixel coordinates.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_viewMetrics The view
|
||||
* metrics if they have been previously computed. Passing in null may cause
|
||||
* the view metrics to be computed again, if it is needed.
|
||||
* @param {!Blockly.MetricsManager.ContainerRegion=} opt_contentMetrics The
|
||||
* content metrics if they have been previously computed. Passing in null
|
||||
* may cause the content metrics to be computed again, if it is needed.
|
||||
* @return {!Blockly.MetricsManager.ContainerRegion} The metrics for the scroll
|
||||
* container
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getScrollMetrics = function(
|
||||
opt_getWorkspaceCoordinates, opt_viewMetrics, opt_contentMetrics) {
|
||||
var scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
|
||||
var viewMetrics = opt_viewMetrics || this.getViewMetrics(false);
|
||||
var contentMetrics = opt_contentMetrics || this.getContentMetrics();
|
||||
var fixedEdges = this.getComputedFixedEdges_(viewMetrics);
|
||||
|
||||
// Add padding around content
|
||||
var paddedContent = this.getPaddedContent_(viewMetrics, contentMetrics);
|
||||
|
||||
// Use combination of fixed bounds and padded content to make scroll area.
|
||||
var top = fixedEdges.top !== undefined ?
|
||||
fixedEdges.top : paddedContent.top;
|
||||
var left = fixedEdges.left !== undefined ?
|
||||
fixedEdges.left : paddedContent.left;
|
||||
var bottom = fixedEdges.bottom !== undefined ?
|
||||
fixedEdges.bottom : paddedContent.bottom;
|
||||
var right = fixedEdges.right !== undefined ?
|
||||
fixedEdges.right : paddedContent.right;
|
||||
|
||||
return {
|
||||
top: top / scale,
|
||||
left: left / scale,
|
||||
width: (right - left) / scale,
|
||||
height: (bottom - top) / scale,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -325,6 +381,8 @@ Blockly.MetricsManager.prototype.getContentMetrics = function(
|
||||
* .viewWidth: Width of the visible portion of the workspace.
|
||||
* .contentHeight: Height of the content.
|
||||
* .contentWidth: Width of the content.
|
||||
* .scrollHeight: Height of the scroll area.
|
||||
* .scrollWidth: Width of the scroll area.
|
||||
* .svgHeight: Height of the Blockly div (the view + the toolbox,
|
||||
* simple or otherwise),
|
||||
* .svgWidth: Width of the Blockly div (the view + the toolbox,
|
||||
@@ -335,6 +393,8 @@ Blockly.MetricsManager.prototype.getContentMetrics = function(
|
||||
* the workspace origin.
|
||||
* .contentTop: Top-edge of the content, relative to the workspace origin.
|
||||
* .contentLeft: Left-edge of the content relative to the workspace origin.
|
||||
* .scrollTop: Top-edge of the scroll area, relative to the workspace origin.
|
||||
* .scrollLeft: Left-edge of the scroll area relative to the workspace origin.
|
||||
* .absoluteTop: Top-edge of the visible portion of the workspace, relative
|
||||
* to the blocklyDiv.
|
||||
* .absoluteLeft: Left-edge of the visible portion of the workspace, relative
|
||||
@@ -355,7 +415,9 @@ Blockly.MetricsManager.prototype.getMetrics = function() {
|
||||
var svgMetrics = this.getSvgMetrics();
|
||||
var absoluteMetrics = this.getAbsoluteMetrics();
|
||||
var viewMetrics = this.getViewMetrics();
|
||||
var contentMetrics = this.getContentMetrics(false, viewMetrics);
|
||||
var contentMetrics = this.getContentMetrics();
|
||||
var scrollMetrics =
|
||||
this.getScrollMetrics(false, viewMetrics, contentMetrics);
|
||||
|
||||
return {
|
||||
contentHeight: contentMetrics.height,
|
||||
@@ -363,6 +425,11 @@ Blockly.MetricsManager.prototype.getMetrics = function() {
|
||||
contentTop: contentMetrics.top,
|
||||
contentLeft: contentMetrics.left,
|
||||
|
||||
scrollHeight: scrollMetrics.height,
|
||||
scrollWidth: scrollMetrics.width,
|
||||
scrollTop: scrollMetrics.top,
|
||||
scrollLeft: scrollMetrics.left,
|
||||
|
||||
viewHeight: viewMetrics.height,
|
||||
viewWidth: viewMetrics.width,
|
||||
viewTop: viewMetrics.top,
|
||||
|
||||
@@ -469,6 +469,11 @@ Blockly.Mutator.prototype.getFlyoutMetrics_ = function() {
|
||||
contentTop: unsupported,
|
||||
contentLeft: unsupported,
|
||||
|
||||
scrollHeight: unsupported,
|
||||
scrollWidth: unsupported,
|
||||
scrollTop: unsupported,
|
||||
scrollLeft: unsupported,
|
||||
|
||||
viewHeight: this.workspaceHeight_,
|
||||
viewWidth: this.workspaceWidth_ - flyoutWidth,
|
||||
viewTop: unsupported,
|
||||
|
||||
@@ -128,15 +128,15 @@ Blockly.ScrollbarPair.prototype.resize = function() {
|
||||
} else {
|
||||
// Has the content been resized or moved?
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.contentWidth != hostMetrics.contentWidth ||
|
||||
this.oldHostMetrics_.scrollWidth != hostMetrics.scrollWidth ||
|
||||
this.oldHostMetrics_.viewLeft != hostMetrics.viewLeft ||
|
||||
this.oldHostMetrics_.contentLeft != hostMetrics.contentLeft) {
|
||||
this.oldHostMetrics_.scrollLeft != hostMetrics.scrollLeft) {
|
||||
resizeH = true;
|
||||
}
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.contentHeight != hostMetrics.contentHeight ||
|
||||
this.oldHostMetrics_.scrollHeight != hostMetrics.scrollHeight ||
|
||||
this.oldHostMetrics_.viewTop != hostMetrics.viewTop ||
|
||||
this.oldHostMetrics_.contentTop != hostMetrics.contentTop) {
|
||||
this.oldHostMetrics_.scrollTop != hostMetrics.scrollTop) {
|
||||
resizeV = true;
|
||||
}
|
||||
}
|
||||
@@ -174,7 +174,6 @@ Blockly.ScrollbarPair.prototype.resize = function() {
|
||||
this.oldHostMetrics_ = hostMetrics;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether scrolling horizontally is enabled.
|
||||
* @return {boolean} True if horizontal scroll is enabled.
|
||||
@@ -428,12 +427,13 @@ Blockly.Scrollbar.prototype.origin_ = new Blockly.utils.Coordinate(0, 0);
|
||||
Blockly.Scrollbar.prototype.startDragMouse_ = 0;
|
||||
|
||||
/**
|
||||
* The size of the area within which the scrollbar handle can move, in CSS
|
||||
* pixels (the size of the scrollbar background).
|
||||
* The length of the scrollbars (including the handle and the background), in
|
||||
* CSS pixels. This is equivalent to scrollbar background length and the area
|
||||
* within which the scrollbar handle can move.
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.scrollViewSize_ = 0;
|
||||
Blockly.Scrollbar.prototype.scrollbarLength_ = 0;
|
||||
|
||||
/**
|
||||
* The length of the scrollbar handle in CSS pixels.
|
||||
@@ -485,7 +485,7 @@ Blockly.Scrollbar.SCROLLBAR_MARGIN = 0.5;
|
||||
/**
|
||||
* @param {Blockly.utils.Metrics} first An object containing computed
|
||||
* measurements of a workspace.
|
||||
* @param {Blockly.utils.Metrics} second Another object containing computed
|
||||
* @param {?Blockly.utils.Metrics} second Another object containing computed
|
||||
* measurements of a workspace.
|
||||
* @return {boolean} Whether the two sets of metrics are equivalent.
|
||||
* @private
|
||||
@@ -501,10 +501,10 @@ Blockly.Scrollbar.metricsAreEquivalent_ = function(first, second) {
|
||||
first.viewTop != second.viewTop ||
|
||||
first.absoluteTop != second.absoluteTop ||
|
||||
first.absoluteLeft != second.absoluteLeft ||
|
||||
first.contentWidth != second.contentWidth ||
|
||||
first.contentHeight != second.contentHeight ||
|
||||
first.contentLeft != second.contentLeft ||
|
||||
first.contentTop != second.contentTop) {
|
||||
first.scrollWidth != second.scrollWidth ||
|
||||
first.scrollHeight != second.scrollHeight ||
|
||||
first.scrollLeft != second.scrollLeft ||
|
||||
first.scrollTop != second.scrollTop) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -541,11 +541,11 @@ Blockly.Scrollbar.prototype.dispose = function() {
|
||||
* @return {number} Constrained value, in CSS pixels.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.constrainLength_ = function(value) {
|
||||
Blockly.Scrollbar.prototype.constrainHandleLength_ = function(value) {
|
||||
if (value <= 0 || isNaN(value)) {
|
||||
value = 0;
|
||||
} else {
|
||||
value = Math.min(value, this.scrollViewSize_);
|
||||
value = Math.min(value, this.scrollbarLength_);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
@@ -568,14 +568,14 @@ Blockly.Scrollbar.prototype.setHandleLength_ = function(newLength) {
|
||||
* @return {number} Constrained value, in CSS pixels.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.constrainPosition_ = function(value) {
|
||||
Blockly.Scrollbar.prototype.constrainHandlePosition_ = function(value) {
|
||||
if (value <= 0 || isNaN(value)) {
|
||||
value = 0;
|
||||
} else {
|
||||
// Handle length should never be greater than this.scrollViewSize_.
|
||||
// If the viewSize is greater than or equal to the contentSize, the
|
||||
// handleLength will end up equal to this.scrollViewSize_.
|
||||
value = Math.min(value, this.scrollViewSize_ - this.handleLength_);
|
||||
// Handle length should never be greater than this.scrollbarLength_.
|
||||
// If the viewSize is greater than or equal to the scrollSize, the
|
||||
// handleLength will end up equal to this.scrollbarLength_.
|
||||
value = Math.min(value, this.scrollbarLength_ - this.handleLength_);
|
||||
}
|
||||
return value;
|
||||
};
|
||||
@@ -596,10 +596,10 @@ Blockly.Scrollbar.prototype.setHandlePosition = function(newPosition) {
|
||||
* @param {number} newSize The new scrollbar background length in CSS pixels.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.setScrollViewSize_ = function(newSize) {
|
||||
this.scrollViewSize_ = newSize;
|
||||
this.outerSvg_.setAttribute(this.lengthAttribute_, this.scrollViewSize_);
|
||||
this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollViewSize_);
|
||||
Blockly.Scrollbar.prototype.setScrollbarLength_ = function(newSize) {
|
||||
this.scrollbarLength_ = newSize;
|
||||
this.outerSvg_.setAttribute(this.lengthAttribute_, this.scrollbarLength_);
|
||||
this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollbarLength_);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -697,7 +697,7 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) {
|
||||
// Shorten the scrollbar to make room for the corner square.
|
||||
viewSize -= Blockly.Scrollbar.scrollbarThickness;
|
||||
}
|
||||
this.setScrollViewSize_(Math.max(0, viewSize));
|
||||
this.setScrollbarLength_(Math.max(0, viewSize));
|
||||
|
||||
var xCoordinate =
|
||||
hostMetrics.absoluteLeft + Blockly.Scrollbar.SCROLLBAR_MARGIN;
|
||||
@@ -722,10 +722,10 @@ Blockly.Scrollbar.prototype.resizeViewHorizontal = function(hostMetrics) {
|
||||
* the required dimensions, possibly fetched from the host object.
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.resizeContentHorizontal = function(hostMetrics) {
|
||||
if (hostMetrics.viewWidth >= hostMetrics.contentWidth) {
|
||||
// viewWidth is often greater than contentWidth in flyouts and
|
||||
if (hostMetrics.viewWidth >= hostMetrics.scrollWidth) {
|
||||
// viewWidth is often greater than scrollWidth in flyouts and
|
||||
// non-scrollable workspaces.
|
||||
this.setHandleLength_(this.scrollViewSize_);
|
||||
this.setHandleLength_(this.scrollbarLength_);
|
||||
this.setHandlePosition(0);
|
||||
if (!this.pair_) {
|
||||
// The scrollbar isn't needed.
|
||||
@@ -741,27 +741,27 @@ Blockly.Scrollbar.prototype.resizeContentHorizontal = function(hostMetrics) {
|
||||
|
||||
// Resize the handle.
|
||||
var handleLength =
|
||||
this.scrollViewSize_ * hostMetrics.viewWidth / hostMetrics.contentWidth;
|
||||
handleLength = this.constrainLength_(handleLength);
|
||||
this.scrollbarLength_ * hostMetrics.viewWidth / hostMetrics.scrollWidth;
|
||||
handleLength = this.constrainHandleLength_(handleLength);
|
||||
this.setHandleLength_(handleLength);
|
||||
|
||||
// Compute the handle offset.
|
||||
// The position of the handle can be between:
|
||||
// 0 and this.scrollViewSize_ - handleLength
|
||||
// If viewLeft == contentLeft
|
||||
// 0 and this.scrollbarLength_ - handleLength
|
||||
// If viewLeft == scrollLeft
|
||||
// then the offset should be 0
|
||||
// If viewRight == contentRight
|
||||
// then viewLeft = contentLeft + contentWidth - viewWidth
|
||||
// If viewRight == scrollRight
|
||||
// then viewLeft = scrollLeft + scrollWidth - viewWidth
|
||||
// then the offset should be max offset
|
||||
|
||||
var maxScrollDistance = hostMetrics.contentWidth - hostMetrics.viewWidth;
|
||||
var contentDisplacement = hostMetrics.viewLeft - hostMetrics.contentLeft;
|
||||
var maxScrollDistance = hostMetrics.scrollWidth - hostMetrics.viewWidth;
|
||||
var contentDisplacement = hostMetrics.viewLeft - hostMetrics.scrollLeft;
|
||||
// Percent of content to the left of our current position.
|
||||
var offsetRatio = contentDisplacement / maxScrollDistance;
|
||||
// Area available to scroll * percent to the left
|
||||
var maxHandleOffset = this.scrollViewSize_ - this.handleLength_;
|
||||
var maxHandleOffset = this.scrollbarLength_ - this.handleLength_;
|
||||
var handleOffset = maxHandleOffset * offsetRatio;
|
||||
handleOffset = this.constrainPosition_(handleOffset);
|
||||
handleOffset = this.constrainHandlePosition_(handleOffset);
|
||||
this.setHandlePosition(handleOffset);
|
||||
|
||||
// Compute ratio (for use with set calls, which pass in content displacement).
|
||||
@@ -794,7 +794,7 @@ Blockly.Scrollbar.prototype.resizeViewVertical = function(hostMetrics) {
|
||||
// Shorten the scrollbar to make room for the corner square.
|
||||
viewSize -= Blockly.Scrollbar.scrollbarThickness;
|
||||
}
|
||||
this.setScrollViewSize_(Math.max(0, viewSize));
|
||||
this.setScrollbarLength_(Math.max(0, viewSize));
|
||||
|
||||
var xCoordinate = this.workspace_.RTL ?
|
||||
hostMetrics.absoluteLeft + Blockly.Scrollbar.SCROLLBAR_MARGIN :
|
||||
@@ -817,10 +817,10 @@ Blockly.Scrollbar.prototype.resizeViewVertical = function(hostMetrics) {
|
||||
* the required dimensions, possibly fetched from the host object.
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) {
|
||||
if (hostMetrics.viewHeight >= hostMetrics.contentHeight) {
|
||||
// viewHeight is often greater than contentHeight in flyouts and
|
||||
if (hostMetrics.viewHeight >= hostMetrics.scrollHeight) {
|
||||
// viewHeight is often greater than scrollHeight in flyouts and
|
||||
// non-scrollable workspaces.
|
||||
this.setHandleLength_(this.scrollViewSize_);
|
||||
this.setHandleLength_(this.scrollbarLength_);
|
||||
this.setHandlePosition(0);
|
||||
if (!this.pair_) {
|
||||
// The scrollbar isn't needed.
|
||||
@@ -836,27 +836,27 @@ Blockly.Scrollbar.prototype.resizeContentVertical = function(hostMetrics) {
|
||||
|
||||
// Resize the handle.
|
||||
var handleLength =
|
||||
this.scrollViewSize_ * hostMetrics.viewHeight / hostMetrics.contentHeight;
|
||||
handleLength = this.constrainLength_(handleLength);
|
||||
this.scrollbarLength_ * hostMetrics.viewHeight / hostMetrics.scrollHeight;
|
||||
handleLength = this.constrainHandleLength_(handleLength);
|
||||
this.setHandleLength_(handleLength);
|
||||
|
||||
// Compute the handle offset.
|
||||
// The position of the handle can be between:
|
||||
// 0 and this.scrollViewSize_ - handleLength
|
||||
// If viewTop == contentTop
|
||||
// 0 and this.scrollbarLength_ - handleLength
|
||||
// If viewTop == scrollTop
|
||||
// then the offset should be 0
|
||||
// If viewBottom == contentBottom
|
||||
// then viewTop = contentTop + contentHeight - viewHeight
|
||||
// If viewBottom == scrollBottom
|
||||
// then viewTop = scrollTop + scrollHeight - viewHeight
|
||||
// then the offset should be max offset
|
||||
|
||||
var maxScrollDistance = hostMetrics.contentHeight - hostMetrics.viewHeight;
|
||||
var contentDisplacement = hostMetrics.viewTop - hostMetrics.contentTop;
|
||||
var maxScrollDistance = hostMetrics.scrollHeight - hostMetrics.viewHeight;
|
||||
var contentDisplacement = hostMetrics.viewTop - hostMetrics.scrollTop;
|
||||
// Percent of content to the left of our current position.
|
||||
var offsetRatio = contentDisplacement / maxScrollDistance;
|
||||
// Area available to scroll * percent to the left
|
||||
var maxHandleOffset = this.scrollViewSize_ - this.handleLength_;
|
||||
var maxHandleOffset = this.scrollbarLength_ - this.handleLength_;
|
||||
var handleOffset = maxHandleOffset * offsetRatio;
|
||||
handleOffset = this.constrainPosition_(handleOffset);
|
||||
handleOffset = this.constrainHandlePosition_(handleOffset);
|
||||
this.setHandlePosition(handleOffset);
|
||||
|
||||
// Compute ratio (for use with set calls, which pass in content displacement).
|
||||
@@ -1005,7 +1005,7 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) {
|
||||
handlePosition += pageLength;
|
||||
}
|
||||
|
||||
this.setHandlePosition(this.constrainPosition_(handlePosition));
|
||||
this.setHandlePosition(this.constrainHandlePosition_(handlePosition));
|
||||
|
||||
this.updateMetrics_();
|
||||
e.stopPropagation();
|
||||
@@ -1055,7 +1055,7 @@ Blockly.Scrollbar.prototype.onMouseMoveHandle_ = function(e) {
|
||||
var mouseDelta = currentMouse - this.startDragMouse_;
|
||||
var handlePosition = this.startDragHandle + mouseDelta;
|
||||
// Position the bar.
|
||||
this.setHandlePosition(this.constrainPosition_(handlePosition));
|
||||
this.setHandlePosition(this.constrainHandlePosition_(handlePosition));
|
||||
this.updateMetrics_();
|
||||
};
|
||||
|
||||
@@ -1093,7 +1093,7 @@ Blockly.Scrollbar.prototype.cleanUp_ = function() {
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.getRatio_ = function() {
|
||||
var scrollHandleRange = this.scrollViewSize_ - this.handleLength_;
|
||||
var scrollHandleRange = this.scrollbarLength_ - this.handleLength_;
|
||||
var ratio = this.handlePosition_ / scrollHandleRange;
|
||||
if (isNaN(ratio)) {
|
||||
ratio = 0;
|
||||
@@ -1125,7 +1125,7 @@ Blockly.Scrollbar.prototype.updateMetrics_ = function() {
|
||||
* Defaults to true.
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.set = function(value, updateMetrics) {
|
||||
this.setHandlePosition(this.constrainPosition_(value * this.ratio));
|
||||
this.setHandlePosition(this.constrainHandlePosition_(value * this.ratio));
|
||||
if (updateMetrics || updateMetrics === undefined) {
|
||||
this.updateMetrics_();
|
||||
}
|
||||
|
||||
@@ -343,7 +343,10 @@ Blockly.Toolbox.prototype.createFlyout_ = function() {
|
||||
'oneBasedIndex': workspace.options.oneBasedIndex,
|
||||
'horizontalLayout': workspace.horizontalLayout,
|
||||
'renderer': workspace.options.renderer,
|
||||
'rendererOverrides': workspace.options.rendererOverrides
|
||||
'rendererOverrides': workspace.options.rendererOverrides,
|
||||
'move': {
|
||||
'scrollbars': true,
|
||||
}
|
||||
}));
|
||||
// Options takes in either 'end' or 'start'. This has already been parsed to
|
||||
// be either 0 or 1, so set it after.
|
||||
|
||||
@@ -351,7 +351,7 @@ Blockly.Tooltip.show_ = function() {
|
||||
div.appendChild(document.createTextNode(lines[i]));
|
||||
Blockly.Tooltip.DIV.appendChild(div);
|
||||
}
|
||||
var rtl = Blockly.Tooltip.element_.RTL;
|
||||
var rtl = /** @type {{RTL: boolean}} */ (Blockly.Tooltip.element_).RTL;
|
||||
var windowWidth = document.documentElement.clientWidth;
|
||||
var windowHeight = document.documentElement.clientHeight;
|
||||
// Display the tooltip.
|
||||
|
||||
@@ -69,7 +69,10 @@ Blockly.Trashcan = function(workspace) {
|
||||
'rtl': this.workspace_.RTL,
|
||||
'oneBasedIndex': this.workspace_.options.oneBasedIndex,
|
||||
'renderer': this.workspace_.options.renderer,
|
||||
'rendererOverrides': this.workspace_.options.rendererOverrides
|
||||
'rendererOverrides': this.workspace_.options.rendererOverrides,
|
||||
'move': {
|
||||
'scrollbars': true,
|
||||
}
|
||||
}));
|
||||
// Create vertical or horizontal flyout.
|
||||
if (this.workspace_.horizontalLayout) {
|
||||
|
||||
@@ -42,6 +42,18 @@ Blockly.utils.Metrics.prototype.contentHeight;
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.contentWidth;
|
||||
|
||||
/**
|
||||
* Height of the scroll area.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.scrollHeight;
|
||||
|
||||
/**
|
||||
* Width of the scroll area.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.scrollWidth;
|
||||
|
||||
/**
|
||||
* Top-edge of the visible portion of the workspace, relative to the workspace
|
||||
* origin.
|
||||
@@ -68,6 +80,18 @@ Blockly.utils.Metrics.prototype.contentTop;
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.contentLeft;
|
||||
|
||||
/**
|
||||
* Top-edge of the scroll area, relative to the workspace origin.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.scrollTop;
|
||||
|
||||
/**
|
||||
* Left-edge of the scroll area relative to the workspace origin.
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.scrollLeft;
|
||||
|
||||
/**
|
||||
* Top-edge of the visible portion of the workspace, relative to the blocklyDiv.
|
||||
* @type {number}
|
||||
|
||||
@@ -38,15 +38,14 @@ Blockly.WorkspaceDragger = function(workspace) {
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.horizontalScrollEnabled_ =
|
||||
this.workspace_.scrollbar.canScrollHorizontally();
|
||||
this.horizontalScrollEnabled_ = this.workspace_.isMovableHorizontally();
|
||||
|
||||
/**
|
||||
* Whether vertical scroll is enabled.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.verticalScrollEnabled_ = this.workspace_.scrollbar.canScrollVertically();
|
||||
this.verticalScrollEnabled_ = this.workspace_.isMovableVertically();
|
||||
|
||||
/**
|
||||
* The scroll position of the workspace at the beginning of the drag.
|
||||
|
||||
@@ -986,7 +986,10 @@ Blockly.WorkspaceSvg.prototype.addFlyout = function(tagName) {
|
||||
'oneBasedIndex': this.options.oneBasedIndex,
|
||||
'horizontalLayout': this.horizontalLayout,
|
||||
'renderer': this.options.renderer,
|
||||
'rendererOverrides': this.options.rendererOverrides
|
||||
'rendererOverrides': this.options.rendererOverrides,
|
||||
'move': {
|
||||
'scrollbars': true,
|
||||
}
|
||||
}));
|
||||
workspaceOptions.toolboxPosition = this.options.toolboxPosition;
|
||||
if (this.horizontalLayout) {
|
||||
@@ -1157,11 +1160,11 @@ Blockly.WorkspaceSvg.prototype.maybeFireViewportChangeEvent = function() {
|
||||
// negligible changes in viewport top/left.
|
||||
return;
|
||||
}
|
||||
var event = new (Blockly.Events.get(Blockly.Events.VIEWPORT_CHANGE))(top,
|
||||
left, scale, this.id);
|
||||
this.oldScale_ = scale;
|
||||
this.oldTop_ = top;
|
||||
this.oldLeft_ = left;
|
||||
var event = new (Blockly.Events.get(Blockly.Events.VIEWPORT_CHANGE))(top,
|
||||
left, scale, this.id);
|
||||
Blockly.Events.fire(event);
|
||||
};
|
||||
|
||||
@@ -1629,22 +1632,6 @@ Blockly.WorkspaceSvg.prototype.isDraggable = function() {
|
||||
return this.options.moveOptions && this.options.moveOptions.drag;
|
||||
};
|
||||
|
||||
/**
|
||||
* Should the workspace have bounded content? Used to tell if the
|
||||
* workspace's content should be sized so that it can move (bounded) or not
|
||||
* (exact sizing).
|
||||
* @return {boolean} True if the workspace should be bounded, false otherwise.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.isContentBounded = function() {
|
||||
return (this.options.moveOptions && this.options.moveOptions.scrollbars) ||
|
||||
(this.options.moveOptions && this.options.moveOptions.wheel) ||
|
||||
(this.options.moveOptions && this.options.moveOptions.drag) ||
|
||||
(this.options.zoomOptions && this.options.zoomOptions.controls) ||
|
||||
(this.options.zoomOptions && this.options.zoomOptions.wheel) ||
|
||||
(this.options.zoomOptions && this.options.zoomOptions.pinch);
|
||||
};
|
||||
|
||||
/**
|
||||
* Is this workspace movable?
|
||||
*
|
||||
@@ -1663,6 +1650,28 @@ Blockly.WorkspaceSvg.prototype.isMovable = function() {
|
||||
(this.options.zoomOptions && this.options.zoomOptions.pinch);
|
||||
};
|
||||
|
||||
/**
|
||||
* Is this workspace movable horizontally?
|
||||
* @return {boolean} True if the workspace is movable horizontally, false
|
||||
* otherwise.
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.isMovableHorizontally = function() {
|
||||
var hasScrollbars = !!this.scrollbar;
|
||||
return this.isMovable() && (!hasScrollbars ||
|
||||
(hasScrollbars && this.scrollbar.canScrollHorizontally()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Is this workspace movable vertically?
|
||||
* @return {boolean} True if the workspace is movable vertically, false
|
||||
* otherwise.
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.isMovableVertically = function() {
|
||||
var hasScrollbars = !!this.scrollbar;
|
||||
return this.isMovable() && (!hasScrollbars ||
|
||||
(hasScrollbars && this.scrollbar.canScrollVertically()));
|
||||
};
|
||||
|
||||
/**
|
||||
* Handle a mouse-wheel on SVG drawing surface.
|
||||
* @param {!Event} e Mouse wheel event.
|
||||
@@ -2032,12 +2041,12 @@ Blockly.WorkspaceSvg.prototype.scrollCenter = function() {
|
||||
}
|
||||
|
||||
var metrics = this.getMetrics();
|
||||
var x = (metrics.contentWidth - metrics.viewWidth) / 2;
|
||||
var y = (metrics.contentHeight - metrics.viewHeight) / 2;
|
||||
var x = (metrics.scrollWidth - metrics.viewWidth) / 2;
|
||||
var y = (metrics.scrollHeight - metrics.viewHeight) / 2;
|
||||
|
||||
// Convert from workspace directions to canvas directions.
|
||||
x = -x - metrics.contentLeft;
|
||||
y = -y - metrics.contentTop;
|
||||
x = -x - metrics.scrollLeft;
|
||||
y = -y - metrics.scrollTop;
|
||||
this.scroll(x, y);
|
||||
};
|
||||
|
||||
@@ -2124,10 +2133,11 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
|
||||
// zoom correctly without scrollbars, but scroll does not resize the
|
||||
// scrollbars so we have to call resizeView/resizeContent as well.
|
||||
var metrics = this.getMetrics();
|
||||
// The scroll values and the view values are additive inverses of
|
||||
// each other, so when we subtract from one we have to add to the other.
|
||||
|
||||
this.scrollX -= metrics.absoluteLeft;
|
||||
this.scrollY -= metrics.absoluteTop;
|
||||
// // The scroll values and the view values are additive inverses of
|
||||
// // each other, so when we subtract from one we have to add to the other.
|
||||
metrics.viewLeft += metrics.absoluteLeft;
|
||||
metrics.viewTop += metrics.absoluteTop;
|
||||
|
||||
@@ -2167,22 +2177,18 @@ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) {
|
||||
|
||||
// Keep scrolling within the bounds of the content.
|
||||
var metrics = this.getMetrics();
|
||||
// This is the offset of the top-left corner of the view from the
|
||||
// workspace origin when the view is "seeing" the bottom-right corner of
|
||||
// the content.
|
||||
var maxOffsetOfViewFromOriginX = metrics.contentWidth + metrics.contentLeft -
|
||||
metrics.viewWidth;
|
||||
var maxOffsetOfViewFromOriginY = metrics.contentHeight + metrics.contentTop -
|
||||
metrics.viewHeight;
|
||||
// Canvas coordinates (aka scroll coordinates) have inverse directionality
|
||||
// to workspace coordinates so we have to inverse them.
|
||||
x = Math.min(x, -metrics.contentLeft);
|
||||
y = Math.min(y, -metrics.contentTop);
|
||||
x = Math.max(x, -maxOffsetOfViewFromOriginX);
|
||||
y = Math.max(y, -maxOffsetOfViewFromOriginY);
|
||||
|
||||
x = Math.min(x, -metrics.scrollLeft);
|
||||
y = Math.min(y, -metrics.scrollTop);
|
||||
var maxXScroll = metrics.scrollLeft + metrics.scrollWidth - metrics.viewWidth;
|
||||
var maxYScroll =
|
||||
metrics.scrollTop + metrics.scrollHeight - metrics.viewHeight;
|
||||
x = Math.max(x, -maxXScroll);
|
||||
y = Math.max(y, -maxYScroll);
|
||||
this.scrollX = x;
|
||||
this.scrollY = y;
|
||||
|
||||
if (this.scrollbar) {
|
||||
// The content position (displacement from the content's top-left to the
|
||||
// origin) plus the scroll position (displacement from the view's top-left
|
||||
@@ -2191,7 +2197,7 @@ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) {
|
||||
// the content's top-left to the view's top-left, matching the
|
||||
// directionality of the scrollbars.
|
||||
this.scrollbar.set(
|
||||
-(x + metrics.contentLeft), -(y + metrics.contentTop), false);
|
||||
-(x + metrics.scrollLeft), -(y + metrics.scrollTop), false);
|
||||
}
|
||||
// We have to shift the translation so that when the canvas is at 0, 0 the
|
||||
// workspace origin is not underneath the toolbox.
|
||||
@@ -2212,13 +2218,13 @@ Blockly.WorkspaceSvg.setTopLevelWorkspaceMetrics_ = function(xyRatio) {
|
||||
|
||||
if (typeof xyRatio.x == 'number') {
|
||||
this.scrollX =
|
||||
-(metrics.contentLeft +
|
||||
(metrics.contentWidth - metrics.viewWidth) * xyRatio.x);
|
||||
-(metrics.scrollLeft +
|
||||
(metrics.scrollWidth - metrics.viewWidth) * xyRatio.x);
|
||||
}
|
||||
if (typeof xyRatio.y == 'number') {
|
||||
this.scrollY =
|
||||
-(metrics.contentTop +
|
||||
(metrics.contentHeight - metrics.viewHeight) * xyRatio.y);
|
||||
-(metrics.scrollTop +
|
||||
(metrics.scrollHeight - metrics.viewHeight) * xyRatio.y);
|
||||
}
|
||||
// We have to shift the translation so that when the canvas is at 0, 0 the
|
||||
// workspace origin is not underneath the toolbox.
|
||||
|
||||
@@ -32,7 +32,8 @@ suite('Metrics', function() {
|
||||
scale: scale,
|
||||
scrollX: SCROLL_X,
|
||||
scrollY: SCROLL_Y,
|
||||
isContentBounded: function() {}
|
||||
isMovableHorizontally: function() { return true; },
|
||||
isMovableVertically: function() { return true; }
|
||||
};
|
||||
}
|
||||
|
||||
@@ -43,125 +44,6 @@ suite('Metrics', function() {
|
||||
sharedTestTeardown.call(this);
|
||||
});
|
||||
|
||||
suite('getContentDimensionsExact_', function() {
|
||||
test('Empty', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var defaultZoom = metricsManager.getContentDimensionsExact_(ws);
|
||||
assertDimensionsMatch(defaultZoom, 0, 0, 0, 0);
|
||||
});
|
||||
test('Empty zoom in', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomIn = metricsManager.getContentDimensionsExact_(ws);
|
||||
assertDimensionsMatch(zoomIn, 0, 0, 0, 0);
|
||||
});
|
||||
test('Empty zoom out', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomOut = metricsManager.getContentDimensionsExact_(ws);
|
||||
assertDimensionsMatch(zoomOut, 0, 0, 0, 0);
|
||||
});
|
||||
test('Non empty at origin', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var defaultZoom = metricsManager.getContentDimensionsExact_(ws);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(defaultZoom, 0, 0, 100, 100);
|
||||
});
|
||||
test('Non empty at origin zoom in', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomIn = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomIn, 0, 0, 200, 200);
|
||||
});
|
||||
test('Non empty at origin zoom out', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomOut = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomOut, 0, 0, 50, 50);
|
||||
});
|
||||
test('Non empty positive origin', function() {
|
||||
var ws = makeMockWs(1, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var defaultZoom = metricsManager.getContentDimensionsExact_(ws);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(defaultZoom, 10, 10, 100, 100);
|
||||
});
|
||||
test('Non empty positive origin zoom in', function() {
|
||||
var ws = makeMockWs(2, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomIn = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomIn, 20, 20, 200, 200);
|
||||
});
|
||||
test('Non empty positive origin zoom out', function() {
|
||||
var ws = makeMockWs(.5, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomOut = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomOut, 5, 5, 50, 50);
|
||||
});
|
||||
test('Non empty negative origin', function() {
|
||||
var ws = makeMockWs(1, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var defaultZoom = metricsManager.getContentDimensionsExact_(ws);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(defaultZoom, -10, -10, 100, 100);
|
||||
});
|
||||
test('Non empty negative origin zoom in', function() {
|
||||
var ws = makeMockWs(2, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomIn = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomIn, -20, -20, 200, 200);
|
||||
});
|
||||
test('Non empty negative origin zoom out', function() {
|
||||
var ws = makeMockWs(.5, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var zoomOut = metricsManager.getContentDimensionsExact_(ws);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(zoomOut, -5, -5, 50, 50);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getContentDimensionsBounded_', function() {
|
||||
setup(function() {
|
||||
this.ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
this.metricsManager = new Blockly.MetricsManager(this.ws);
|
||||
this.contentDimensionsStub =
|
||||
sinon.stub(this.metricsManager, 'getContentDimensionsExact_');
|
||||
});
|
||||
test('Empty workspace', function() {
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentDimensions = {top: 0, left: 0, width: 0, height: 0};
|
||||
this.contentDimensionsStub.returns(mockContentDimensions);
|
||||
|
||||
var contentMetrics =
|
||||
this.metricsManager.getContentDimensionsBounded_(mockViewMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -200, -200, 400, 400);
|
||||
});
|
||||
test('Non empty workspace', function() {
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentDimensions = {top: 100, left: 100, width: 50, height: 50};
|
||||
this.contentDimensionsStub.returns(mockContentDimensions);
|
||||
|
||||
var contentMetrics =
|
||||
this.metricsManager.getContentDimensionsBounded_(mockViewMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -50, -50, 350, 350);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getAbsoluteMetrics', function() {
|
||||
setup(function() {
|
||||
this.ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
@@ -296,54 +178,332 @@ suite('Metrics', function() {
|
||||
});
|
||||
|
||||
suite('getContentMetrics', function() {
|
||||
setup(function() {
|
||||
this.ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
this.metricsManager = new Blockly.MetricsManager(this.ws);
|
||||
this.viewMetricsStub = sinon.stub(this.metricsManager, 'getViewMetrics');
|
||||
this.isContentBoundedStub =
|
||||
sinon.stub(this.metricsManager.workspace_, 'isContentBounded');
|
||||
this.getBoundedMetricsStub =
|
||||
sinon.stub(this.metricsManager, 'getContentDimensionsBounded_');
|
||||
this.getExactMetricsStub =
|
||||
sinon.stub(this.metricsManager, 'getContentDimensionsExact_');
|
||||
test('Empty in ws coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Content Dimensions in pixel coordinates bounded ws', function() {
|
||||
this.isContentBoundedStub.returns(true);
|
||||
this.getBoundedMetricsStub.returns(
|
||||
{height: 100, width: 100, left: 100, top: 100});
|
||||
|
||||
var contentMetrics = this.metricsManager.getContentMetrics(false);
|
||||
|
||||
// Should return what getContentDimensionsBounded_ returns.
|
||||
assertDimensionsMatch(contentMetrics, 100, 100, 100, 100);
|
||||
sinon.assert.calledOnce(this.getBoundedMetricsStub);
|
||||
sinon.assert.calledOnce(this.viewMetricsStub);
|
||||
test('Empty zoom-in in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Content Dimensions in pixel coordinates exact ws', function() {
|
||||
this.isContentBoundedStub.returns(false);
|
||||
this.getExactMetricsStub.returns(
|
||||
{height: 100, width: 100, left: 100, top: 100});
|
||||
|
||||
var contentMetrics = this.metricsManager.getContentMetrics(false);
|
||||
|
||||
// Should return what getContentDimensionsExact_ returns.
|
||||
assertDimensionsMatch(contentMetrics, 100, 100, 100, 100);
|
||||
sinon.assert.calledOnce(this.getExactMetricsStub);
|
||||
sinon.assert.notCalled(this.viewMetricsStub);
|
||||
test('Empty zoom-out in ws coordinates', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Content Dimensions in ws coordinates bounded ws', function() {
|
||||
var getWorkspaceCoordinates = true;
|
||||
this.ws.scale = 2;
|
||||
this.isContentBoundedStub.returns(true);
|
||||
this.getBoundedMetricsStub.returns(
|
||||
{height: 100, width: 100, left: 100, top: 100});
|
||||
test('Non empty at origin ws coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 100, 100);
|
||||
});
|
||||
test('Non empty at origin zoom-in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 100, 100);
|
||||
});
|
||||
test('Non empty at origin zoom-out ws coordinates', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 100, 100);
|
||||
});
|
||||
test('Non empty positive origin ws coordinates', function() {
|
||||
var ws = makeMockWs(1, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, 10, 10, 100, 100);
|
||||
});
|
||||
test('Non empty positive origin zoom-in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 10, 10, 100, 100);
|
||||
});
|
||||
test('Non empty positive origin zoom-out ws coordinates', function() {
|
||||
var ws = makeMockWs(.5, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 10, 10, 100, 100);
|
||||
});
|
||||
test('Non empty negative origin ws coordinates', function() {
|
||||
var ws = makeMockWs(1, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(contentMetrics, -10, -10, 100, 100);
|
||||
});
|
||||
test('Non empty negative origin zoom-in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, -10, -10, 100, 100);
|
||||
});
|
||||
test('Non empty negative origin zoom-out ws coordinates', function() {
|
||||
var ws = makeMockWs(.5, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(true);
|
||||
assertDimensionsMatch(contentMetrics, -10, -10, 100, 100);
|
||||
});
|
||||
test('Empty in pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Empty zoom-in in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Empty zoom-out in pixel coordinates', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 0, 0);
|
||||
});
|
||||
test('Non empty at origin pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 100, 100);
|
||||
});
|
||||
test('Non empty at origin zoom-in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 200, 200);
|
||||
});
|
||||
test('Non empty at origin zoom-out pixel coordinates', function() {
|
||||
var ws = makeMockWs(.5, 0, 0, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 0, 0, 50, 50);
|
||||
});
|
||||
test('Non empty positive origin pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(contentMetrics, 10, 10, 100, 100);
|
||||
});
|
||||
test('Non empty positive origin zoom-in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 20, 20, 200, 200);
|
||||
});
|
||||
test('Non empty positive origin zoom-out pixel coordinates', function() {
|
||||
var ws = makeMockWs(.5, 10, 10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, 5, 5, 50, 50);
|
||||
});
|
||||
test('Non empty negative origin pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// Pixel and ws units are the same at default zoom.
|
||||
assertDimensionsMatch(contentMetrics, -10, -10, 100, 100);
|
||||
});
|
||||
test('Non empty negative origin zoom-in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 2 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, -20, -20, 200, 200);
|
||||
});
|
||||
test('Non empty negative origin zoom-out pixel coordinates', function() {
|
||||
var ws = makeMockWs(.5, -10, -10, 100, 100);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
var contentMetrics = metricsManager.getContentMetrics(false);
|
||||
// 1 ws unit = 0.5 pixels at this zoom level.
|
||||
assertDimensionsMatch(contentMetrics, -5, -5, 50, 50);
|
||||
});
|
||||
});
|
||||
|
||||
suite('getScrollMetrics', function() {
|
||||
test('Empty workspace in ws coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
this.metricsManager.getContentMetrics(getWorkspaceCoordinates);
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
assertDimensionsMatch(contentMetrics, 50, 50, 50, 50);
|
||||
sinon.assert.calledOnce(this.getBoundedMetricsStub);
|
||||
sinon.assert.calledOnce(this.viewMetricsStub);
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -200, -200, 400, 400);
|
||||
});
|
||||
test('Empty workspace zoom-in in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -100, -100, 200, 200);
|
||||
});
|
||||
test('Empty workspace zoom-out in ws coordinates', function() {
|
||||
var ws = makeMockWs(0.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -400, -400, 800, 800);
|
||||
});
|
||||
test('Non empty workspace in ws coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -50, -50, 350, 350);
|
||||
});
|
||||
test('Non empty workspace zoom-in in ws coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -25, -25, 175, 175);
|
||||
});
|
||||
test('Non empty workspace zoom-out in ws coordinates', function() {
|
||||
var ws = makeMockWs(0.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(true, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -100, -100, 700, 700);
|
||||
});
|
||||
test('Empty workspace in pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -200, -200, 400, 400);
|
||||
});
|
||||
test('Empty workspace zoom-in in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -200, -200, 400, 400);
|
||||
});
|
||||
test('Empty workspace zoom-out in pixel coordinates', function() {
|
||||
var ws = makeMockWs(0.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 0, left: 0, width: 0, height: 0};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -200, -200, 400, 400);
|
||||
});
|
||||
test('Non empty workspace in pixel coordinates', function() {
|
||||
var ws = makeMockWs(1, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -50, -50, 350, 350);
|
||||
});
|
||||
test('Non empty workspace zoom-in in pixel coordinates', function() {
|
||||
var ws = makeMockWs(2, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -50, -50, 350, 350);
|
||||
});
|
||||
test('Non empty workspace zoom-out in pixel coordinates', function() {
|
||||
var ws = makeMockWs(0.5, 0, 0, 0, 0);
|
||||
var metricsManager = new Blockly.MetricsManager(ws);
|
||||
// The location of the viewport.
|
||||
var mockViewMetrics = {top: 0, left: 0, width: 200, height: 200};
|
||||
// The bounding box around the blocks on the screen.
|
||||
var mockContentMetrics = {top: 100, left: 100, width: 50, height: 50};
|
||||
|
||||
var contentMetrics =
|
||||
metricsManager.getScrollMetrics(false, mockViewMetrics, mockContentMetrics);
|
||||
|
||||
// Should add half of the view width to all sides.
|
||||
assertDimensionsMatch(contentMetrics, -50, -50, 350, 350);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user