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