From 90b1cce5d59599d86ae7428a95fb8bfae93677e3 Mon Sep 17 00:00:00 2001 From: rachel-fenichel Date: Wed, 13 Apr 2016 13:56:09 -0700 Subject: [PATCH] Correctly locate and size scrollbar for all toolbox positions. --- core/blockly.js | 15 ++++- core/scrollbar.js | 136 +++++++++++++++++++++++++++------------------- 2 files changed, 92 insertions(+), 59 deletions(-) diff --git a/core/blockly.js b/core/blockly.js index b7adeb078..f3f99766c 100644 --- a/core/blockly.js +++ b/core/blockly.js @@ -413,7 +413,13 @@ Blockly.hideChaff = function(opt_allowToolbox) { Blockly.getMainWorkspaceMetrics_ = function() { var svgSize = Blockly.svgSize(this.getParentSvg()); if (this.toolbox_) { - svgSize.width -= this.toolbox_.width; + // If the toolbox is at the bottom it's laid out separately from the main + // workspace, rather than overlapping. + if (this.toolbox_.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { + svgSize.height -= this.toolbox_.height; + } else { + svgSize.width -= this.toolbox_.width; + } } // Set the margin to match the flyout's margin so that the workspace does // not jump as blocks are added. @@ -448,6 +454,11 @@ Blockly.getMainWorkspaceMetrics_ = function() { if (this.toolbox_ && this.toolbox_.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { absoluteLeft = this.toolbox_.width; } + var absoluteTop = 0; + if (this.toolbox_ && this.toolbox_.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { + absoluteTop = this.toolbox_.height; + } + var metrics = { viewHeight: svgSize.height, viewWidth: svgSize.width, @@ -457,7 +468,7 @@ Blockly.getMainWorkspaceMetrics_ = function() { viewLeft: -this.scrollX, contentTop: topEdge, contentLeft: leftEdge, - absoluteTop: 0, + absoluteTop: absoluteTop, absoluteLeft: absoluteLeft }; return metrics; diff --git a/core/scrollbar.js b/core/scrollbar.js index 42d053cc0..b8534d75e 100644 --- a/core/scrollbar.js +++ b/core/scrollbar.js @@ -270,69 +270,91 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) { * .absoluteLeft: Left-edge of view. */ if (this.horizontal_) { - var outerLength = hostMetrics.viewWidth - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; - } else { - // Only show the scrollbar if needed. - // Ideally this would also apply to scrollbar pairs, but that's a bigger - // headache (due to interactions with the corner square). - this.setVisible(outerLength < hostMetrics.contentWidth); - } - this.ratio_ = outerLength / hostMetrics.contentWidth; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - var innerLength = hostMetrics.viewWidth * this.ratio_; - var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * - this.ratio_; - this.svgKnob_.setAttribute('width', Math.max(0, innerLength)); - this.xCoordinate = hostMetrics.absoluteLeft + 0.5; - if (this.pair_ && this.workspace_.RTL) { - this.xCoordinate += hostMetrics.absoluteLeft + - Blockly.Scrollbar.scrollbarThickness; - } - this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - - Blockly.Scrollbar.scrollbarThickness - 0.5; - this.svgGroup_.setAttribute('transform', - 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.svgBackground_.setAttribute('width', Math.max(0, outerLength)); - this.svgKnob_.setAttribute('x', this.constrainKnob_(innerOffset)); + this.resizeHorizontal_(hostMetrics); } else { - var outerLength = hostMetrics.viewHeight - 1; - if (this.pair_) { - // Shorten the scrollbar to make room for the corner square. - outerLength -= Blockly.Scrollbar.scrollbarThickness; - } else { - // Only show the scrollbar if needed. - this.setVisible(outerLength < hostMetrics.contentHeight); - } - this.ratio_ = outerLength / hostMetrics.contentHeight; - if (this.ratio_ === -Infinity || this.ratio_ === Infinity || - isNaN(this.ratio_)) { - this.ratio_ = 0; - } - var innerLength = hostMetrics.viewHeight * this.ratio_; - var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * - this.ratio_; - this.svgKnob_.setAttribute('height', Math.max(0, innerLength)); - this.xCoordinate = hostMetrics.absoluteLeft + 0.5; - if (!this.workspace_.RTL) { - this.xCoordinate += hostMetrics.viewWidth - - Blockly.Scrollbar.scrollbarThickness - 1; - } - this.yCoordinate = hostMetrics.absoluteTop + 0.5; - this.svgGroup_.setAttribute('transform', - 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); - this.svgBackground_.setAttribute('height', Math.max(0, outerLength)); - this.svgKnob_.setAttribute('y', this.constrainKnob_(innerOffset)); + this.resizeVertical_(hostMetrics); } // Resizing may have caused some scrolling. this.onScroll_(); }; +/** + * Recalculate a horizontal scrollbar's location and length. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host + * object. + * @private + */ +Blockly.Scrollbar.prototype.resizeHorizontal_ = function(hostMetrics) { + var outerLength = hostMetrics.viewWidth - 1; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + // Ideally this would also apply to scrollbar pairs, but that's a bigger + // headache (due to interactions with the corner square). + this.setVisible(outerLength < hostMetrics.contentWidth); + } + this.ratio_ = outerLength / hostMetrics.contentWidth; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + var innerLength = hostMetrics.viewWidth * this.ratio_; + var innerOffset = (hostMetrics.viewLeft - hostMetrics.contentLeft) * + this.ratio_; + this.svgKnob_.setAttribute('width', Math.max(0, innerLength)); + this.xCoordinate = hostMetrics.absoluteLeft + 0.5; + if (this.pair_ && this.workspace_.RTL) { + this.xCoordinate += Blockly.Scrollbar.scrollbarThickness; + } + // Horizontal toolbar should always be just above the bottom of the workspace. + this.yCoordinate = hostMetrics.absoluteTop + hostMetrics.viewHeight - + Blockly.Scrollbar.scrollbarThickness - 0.5; + this.svgGroup_.setAttribute('transform', + 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); + this.svgBackground_.setAttribute('width', Math.max(0, outerLength)); + this.svgKnob_.setAttribute('x', this.constrainKnob_(innerOffset)); +}; + +/** + * Recalculate a vertical scrollbar's location and length. + * @param {!Object} hostMetrics A data structure describing all the + * required dimensions, possibly fetched from the host + * object. + * @private + */ +Blockly.Scrollbar.prototype.resizeVertical_ = function(hostMetrics) { + var outerLength = hostMetrics.viewHeight - 1; + if (this.pair_) { + // Shorten the scrollbar to make room for the corner square. + outerLength -= Blockly.Scrollbar.scrollbarThickness; + } else { + // Only show the scrollbar if needed. + this.setVisible(outerLength < hostMetrics.contentHeight); + } + this.ratio_ = outerLength / hostMetrics.contentHeight; + if (this.ratio_ === -Infinity || this.ratio_ === Infinity || + isNaN(this.ratio_)) { + this.ratio_ = 0; + } + var innerLength = hostMetrics.viewHeight * this.ratio_; + var innerOffset = (hostMetrics.viewTop - hostMetrics.contentTop) * + this.ratio_; + this.svgKnob_.setAttribute('height', Math.max(0, innerLength)); + this.xCoordinate = hostMetrics.absoluteLeft + 0.5; + if (!this.workspace_.RTL) { + this.xCoordinate += hostMetrics.viewWidth - + Blockly.Scrollbar.scrollbarThickness - 1; + } + this.yCoordinate = hostMetrics.absoluteTop + 0.5; + this.svgGroup_.setAttribute('transform', + 'translate(' + this.xCoordinate + ',' + this.yCoordinate + ')'); + this.svgBackground_.setAttribute('height', Math.max(0, outerLength)); + this.svgKnob_.setAttribute('y', this.constrainKnob_(innerOffset)); +}; + /** * Create all the DOM elements required for a scrollbar. * The resulting widget is not sized.