From a67f841671dd5d61647ea4f159350e5823b69e69 Mon Sep 17 00:00:00 2001 From: picklesrus Date: Mon, 29 Feb 2016 12:52:38 -0800 Subject: [PATCH] Replace the call to getBBox() in getMainWorkspaceMetrics with a manual calculation. getBBox() can cause the browser to re-layout the whole page and we have much of the information (e.g. individual block height and width) we need already cached. Note that getBoundingRectangle's calculation is slightly different than the one returned by getBBox. It is off by 3 in the y direction due to how one of the curves is drawn. This new calculation is technically more accurate. --- core/block_svg.js | 29 +++++++++++++++++++++++++++++ core/blockly.js | 8 ++------ core/workspace_svg.js | 40 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+), 6 deletions(-) diff --git a/core/block_svg.js b/core/block_svg.js index b351800c8..4a1f79be1 100644 --- a/core/block_svg.js +++ b/core/block_svg.js @@ -348,6 +348,35 @@ Blockly.BlockSvg.prototype.getHeightWidth = function() { return {height: height, width: width}; }; +/** + * Returns the coordinates of a bounding box describing the dimensions of this block + * and any blocks stacked below it. + * @return {!{topLeft: goog.math.Coordinate, bottomRight: goog.math.Coordinate}} + * Object with top left and bottom right coordinates of the bounding box. + */ +Blockly.BlockSvg.prototype.getBoundingRectangle = function() { + var blockXY = this.getRelativeToSurfaceXY(this); + var tab = this.outputConnection ? Blockly.BlockSvg.TAB_WIDTH : 0; + var blockBounds = this.getHeightWidth(); + var topLeft; + var bottomRight; + if (this.RTL) { + // Width has the tab built into it already so subtract it here. + topLeft = new goog.math.Coordinate(blockXY.x - (blockBounds.width - tab), blockXY.y); + // Add the width of the tab/puzzle piece knob to the x coordinate + // since X is the corner of the rectangle, not the whole puzzle piece. + bottomRight = new goog.math.Coordinate(blockXY.x + tab, blockXY.y + blockBounds.height); + } else { + // Subtract the width of the tab/puzzle piece knob to the x coordinate + // since X is the corner of the rectangle, not the whole puzzle piece. + topLeft = new goog.math.Coordinate(blockXY.x - tab, blockXY.y); + // Width has the tab built into it already so subtract it here. + bottomRight = new goog.math.Coordinate(blockXY.x + blockBounds.width - tab, + blockXY.y + blockBounds.height); + } + return { topLeft : topLeft, bottomRight : bottomRight }; +}; + /** * Set whether the block is collapsed or not. * @param {boolean} collapsed True if collapsed. diff --git a/core/blockly.js b/core/blockly.js index d98250346..8c0cf9fb1 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -521,12 +521,8 @@ Blockly.getMainWorkspaceMetrics_ = function() { var MARGIN = Blockly.Flyout.prototype.CORNER_RADIUS - 1; var viewWidth = svgSize.width - MARGIN; var viewHeight = svgSize.height - MARGIN; - try { - var blockBox = this.getCanvas().getBBox(); - } catch (e) { - // Firefox has trouble with hidden elements (Bug 528969). - return null; - } + var blockBox = this.getBlocksBoundingBox(); + // Fix scale. var contentWidth = blockBox.width * this.scale; var contentHeight = blockBox.height * this.scale; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 273c04d3a..52eabd6a0 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -660,6 +660,46 @@ Blockly.WorkspaceSvg.prototype.onMouseWheel_ = function(e) { e.preventDefault(); }; +/** + * Calculate the bounding box for the blocks on the workspace. + * + * @return {Object} Contains the position and size of the bounding box + * containing the blocks on the workspace. + */ +Blockly.WorkspaceSvg.prototype.getBlocksBoundingBox = function() { + var topBlocks = this.getTopBlocks(); + // There are no blocks, return empty rectangle. + if (topBlocks.length <= 0) { + return {x: 0, y: 0, width: 0, height: 0}; + } + + // Initialize boundary using the first block. + var boundary = topBlocks[0].getBoundingRectangle(); + + // Start at 1 since the 0th block was used for initialization + for (var i = 1; i < topBlocks.length; i++) { + var blockBoundary = topBlocks[i].getBoundingRectangle(); + if (blockBoundary.topLeft.x < boundary.topLeft.x) { + boundary.topLeft.x = blockBoundary.topLeft.x; + } + if (blockBoundary.bottomRight.x > boundary.bottomRight.x) { + boundary.bottomRight.x = blockBoundary.bottomRight.x + } + if (blockBoundary.topLeft.y < boundary.topLeft.y) { + boundary.topLeft.y = blockBoundary.topLeft.y; + } + if (blockBoundary.bottomRight.y > boundary.bottomRight.y) { + boundary.bottomRight.y = blockBoundary.bottomRight.y; + } + } + return { + x: boundary.topLeft.x, + y: boundary.topLeft.y, + width: boundary.bottomRight.x - boundary.topLeft.x, + height: boundary.bottomRight.y - boundary.topLeft.y + }; +}; + /** * Clean up the workspace by ordering all the blocks in a column. * @private