From a0aa84d861fdaa3ddeb833e64ea2fc58abe3e43b Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Sat, 16 Feb 2019 14:34:35 -0800 Subject: [PATCH 1/3] Changed absolute metrics to avoid simple toolboxes. --- core/bubble.js | 77 ++++++---------------- core/flyout_horizontal.js | 19 ++++-- core/flyout_vertical.js | 22 +++++-- core/inject.js | 20 ------ core/mutator.js | 4 +- core/workspace_svg.js | 132 ++++++++++++++++++++++++-------------- 6 files changed, 134 insertions(+), 140 deletions(-) diff --git a/core/bubble.js b/core/bubble.js index 305741b99..42b6cdc9b 100644 --- a/core/bubble.js +++ b/core/bubble.js @@ -408,8 +408,6 @@ Blockly.Bubble.prototype.layoutBubble_ = function() { metrics.viewWidth /= this.workspace_.scale; metrics.viewTop /= this.workspace_.scale; metrics.viewHeight /= this.workspace_.scale; - metrics.flyoutWidth /= this.workspace_.scale; - metrics.flyoutHeight /= this.workspace_.scale; var optimalLeft = this.getOptimalRelativeLeft_(metrics); var optimalTop = this.getOptimalRelativeTop_(metrics); @@ -487,19 +485,13 @@ Blockly.Bubble.prototype.getOverlap_ = function(relativeMin, metrics) { // The position of the top-left corner of the workspace. var workspaceMin = { - x: metrics.viewLeft + ((metrics.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) ? - metrics.flyoutWidth : 0), - y: metrics.viewTop + ((metrics.toolboxPosition == Blockly.TOOLBOX_AT_TOP) ? - metrics.flyoutHeight : 0) + x: metrics.viewLeft, + y: metrics.viewTop }; // The position of the bottom-right corner of the workspace. var workspaceMax = { - x: metrics.viewLeft + metrics.viewWidth - - ((metrics.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) ? - metrics.flyoutWidth : 0), - y: metrics.viewTop + metrics.viewHeight - - ((metrics.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) ? - metrics.flyoutHeight : 0) + x: metrics.viewLeft + metrics.viewWidth, + y: metrics.viewTop + metrics.viewHeight }; var overlapWidth = Math.min(bubbleMax.x, workspaceMax.x) - @@ -529,38 +521,22 @@ Blockly.Bubble.prototype.getOptimalRelativeLeft_ = function(metrics) { } if (this.workspace_.RTL) { - // Everything is flipped in RTL. + // Bubble coordinates are flipped in RTL. var bubbleRight = this.anchorXY_.x - relativeLeft; var bubbleLeft = bubbleRight - this.width_; - var scrollbarRight = 0; - // Thickness in workspace units. - var scrollbarLeft = - Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale; + + var workspaceRight = metrics.viewLeft + metrics.viewWidth; + var workspaceLeft = metrics.viewLeft + + // Thickness in workspace units. + (Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale); } else { var bubbleLeft = relativeLeft + this.anchorXY_.x; var bubbleRight = bubbleLeft + this.width_; - // Thickness in workspace units. - var scrollbarRight = - Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale; - var scrollbarLeft = 0; - } - switch (metrics.toolboxPosition) { - case Blockly.TOOLBOX_AT_LEFT: - var workspaceLeft = metrics.viewLeft + metrics.flyoutWidth; - var workspaceRight = - metrics.viewLeft + metrics.viewWidth - scrollbarRight; - break; - case Blockly.TOOLBOX_AT_RIGHT: - var workspaceLeft = metrics.viewLeft + scrollbarLeft; - var workspaceRight = - metrics.viewLeft + metrics.viewWidth - metrics.flyoutWidth; - break; - default: - var workspaceLeft = metrics.viewLeft + scrollbarLeft; - var workspaceRight = - metrics.viewLeft + metrics.viewWidth - scrollbarRight; - break; + var workspaceLeft = metrics.viewLeft; + var workspaceRight = metrics.viewLeft + metrics.viewWidth - + // Thickness in workspace units. + (Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale); } if (this.workspace_.RTL) { @@ -604,27 +580,10 @@ Blockly.Bubble.prototype.getOptimalRelativeTop_ = function(metrics) { var bubbleTop = this.anchorXY_.y + relativeTop; var bubbleBottom = bubbleTop + this.height_; - - // Thickness in workspace units. - var scrollbarThickness = - Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale; - switch (metrics.toolboxPosition) { - case Blockly.TOOLBOX_AT_TOP: - var workspaceTop = metrics.viewTop + metrics.flyoutHeight; - var workspaceBottom = metrics.viewTop + metrics.viewHeight - - scrollbarThickness; - break; - case Blockly.TOOLBOX_AT_BOTTOM: - var workspaceTop = metrics.viewTop; - var workspaceBottom = metrics.viewTop + metrics.viewHeight - - metrics.flyoutHeight; - break; - default: - var workspaceTop = metrics.viewTop; - var workspaceBottom = metrics.viewTop + metrics.viewHeight - - scrollbarThickness; - break; - } + var workspaceTop = metrics.viewTop; + var workspaceBottom = metrics.viewTop + metrics.viewHeight - + // Thickness in workspace units. + (Blockly.Scrollbar.scrollbarThickness / this.workspace_.scale); var anchorY = this.anchorXY_.y; if (bubbleTop < workspaceTop) { diff --git a/core/flyout_horizontal.js b/core/flyout_horizontal.js index 0dad7570c..008d9ecd0 100644 --- a/core/flyout_horizontal.js +++ b/core/flyout_horizontal.js @@ -152,10 +152,21 @@ Blockly.HorizontalFlyout.prototype.position = function() { var edgeHeight = this.height_ - this.CORNER_RADIUS; this.setBackgroundPath_(edgeWidth, edgeHeight); - var x = targetWorkspaceMetrics.absoluteLeft; - var y = targetWorkspaceMetrics.absoluteTop; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_BOTTOM) { - y += (targetWorkspaceMetrics.viewHeight - this.height_); + // X is always 0 since this is a horizontal flyout. + var x = 0; + // If there is a toolbox. + if (targetWorkspaceMetrics.toolboxHeight) { + if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) { + var y = targetWorkspaceMetrics.toolboxHeight; + } else { + var y = targetWorkspaceMetrics.viewHeight - this.height_; + } + } else { + if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_TOP) { + var y = 0; + } else { + var y = targetWorkspaceMetrics.viewHeight; + } } this.positionAt_(this.width_, this.height_, x, y); }; diff --git a/core/flyout_vertical.js b/core/flyout_vertical.js index 3fc36962c..a6b10ba65 100644 --- a/core/flyout_vertical.js +++ b/core/flyout_vertical.js @@ -149,13 +149,21 @@ Blockly.VerticalFlyout.prototype.position = function() { var edgeHeight = targetWorkspaceMetrics.viewHeight - 2 * this.CORNER_RADIUS; this.setBackgroundPath_(edgeWidth, edgeHeight); - var y = targetWorkspaceMetrics.absoluteTop; - var x = targetWorkspaceMetrics.absoluteLeft; - if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_RIGHT) { - x += (targetWorkspaceMetrics.viewWidth - this.width_); - // Save the location of the left edge of the flyout, for use when Firefox - // gets the bounding client rect wrong. - this.leftEdge_ = x; + // Y is always 0 since this is a vertical flyout. + var y = 0; + // If there is a toolbox. + if (targetWorkspaceMetrics.toolboxWidth) { + if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_LEFT) { + var x = targetWorkspaceMetrics.toolboxWidth; + } else { + var x = targetWorkspaceMetrics.viewWidth - this.width_; + } + } else { + if (this.toolboxPosition_ == Blockly.TOOLBOX_AT_LEFT) { + var x = 0; + } else { + var x = targetWorkspaceMetrics.viewWidth; + } } this.positionAt_(this.width_, this.height_, x, y); }; diff --git a/core/inject.js b/core/inject.js index 7a89b8cb9..2121bd649 100644 --- a/core/inject.js +++ b/core/inject.js @@ -398,26 +398,6 @@ Blockly.init_ = function(mainWorkspace) { mainWorkspace.setMetrics({x: .5, y: .5}); } - if (mainWorkspace.flyout_) { - // Translate the workspace sideways to avoid the fixed flyout. - switch (mainWorkspace.toolboxPosition) { - case Blockly.TOOLBOX_AT_LEFT: - mainWorkspace.scrollX = - mainWorkspace.RTL ? 0 : mainWorkspace.flyout_.width_; - break; - case Blockly.TOOLBOX_AT_RIGHT: - mainWorkspace.scrollX = - mainWorkspace.RTL ? -mainWorkspace.flyout_.width_ : 0; - break; - case Blockly.TOOLBOX_AT_TOP: - mainWorkspace.scrollY = mainWorkspace.flyout_.height_; - break; - // If the toolbox is at the top left (workspace origin) is untouched, - // so no need to include it. - } - mainWorkspace.translate(mainWorkspace.scrollX, mainWorkspace.scrollY); - } - // Load the sounds. if (options.hasSounds) { Blockly.inject.loadSounds_(options.pathToMedia, mainWorkspace); diff --git a/core/mutator.js b/core/mutator.js index da50251ea..17723b31c 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -385,9 +385,9 @@ Blockly.Mutator.prototype.workspaceChanged_ = function() { Blockly.Mutator.prototype.getFlyoutMetrics_ = function() { return { viewHeight: this.workspaceHeight_, - viewWidth: this.workspaceWidth_, + viewWidth: this.workspaceWidth_ - this.workspace_.flyout_.width_, absoluteTop: 0, - absoluteLeft: 0 + absoluteLeft: this.workspace_.RTL ? 0 : this.workspace_.flyout_.width_ }; }; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 1ec2c706f..28db0d2f2 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -1670,13 +1670,15 @@ Blockly.WorkspaceSvg.prototype.zoom = function(x, y, amount) { // Find the new scrollX/scrollY so that the center remains in the same // position (relative to the center) after we zoom. + // newScale and matrix.a should be identical (within a rounding error). var matrix = matrix.translate(x * (1 - scaleChange), y * (1 - scaleChange)) .scale(scaleChange); - // newScale and matrix.a should be identical (within a rounding error). - // ScrollX and scrollY are in pixels. - var metrics = this.getMetrics(); - this.scrollX = matrix.e - metrics.absoluteLeft; - this.scrollY = matrix.f - metrics.absoluteTop; + // scrollX and scrollY are in pixels. + // The scrollX and scrollY still need to have absoluteLeft and absoluteTop + // subtracted from them, but we'll leave that for setScale so that they're + // correctly updated for the new flyout size if we have a simple toolbox. + this.scrollX = matrix.e; + this.scrollY = matrix.f; this.setScale(newScale); }; @@ -1686,8 +1688,19 @@ Blockly.WorkspaceSvg.prototype.zoom = function(x, y, amount) { */ Blockly.WorkspaceSvg.prototype.zoomCenter = function(type) { var metrics = this.getMetrics(); - var x = (metrics.viewWidth / 2) + metrics.absoluteLeft; - var y = (metrics.viewHeight / 2) + metrics.absoluteTop; + console.log(metrics); + if (this.flyout_) { + // If you want blocks in the center of the view (visible portion of the + // workspace) to stay centered when the size of the view decreases (i.e. + // when the size of the flyout increases) you need the center of the + // *blockly div* to stay in the same pixel-position. + // Note: This only works because of how scrollCenter positions blocks. + var x = metrics.svgWidth / 2; + var y = metrics.svgHeight / 2; + } else { + var x = (metrics.viewWidth / 2) + metrics.absoluteLeft; + var y = (metrics.viewHeight / 2) + metrics.absoluteTop; + } this.zoom(x, y, type); }; @@ -1702,6 +1715,8 @@ Blockly.WorkspaceSvg.prototype.zoomToFit = function() { } var metrics = this.getMetrics(); + var workspaceWidth = metrics.viewWidth; + var workspaceHeight = metrics.viewHeight; var blocksBox = this.getBlocksBoundingBox(); var blocksWidth = blocksBox.width; var blocksHeight = blocksBox.height; @@ -1709,21 +1724,24 @@ Blockly.WorkspaceSvg.prototype.zoomToFit = function() { return; // Prevents zooming to infinity. } if (this.flyout_) { - // We add the flyout size to the block size because the flyout contains - // blocks, and we want all of the blocks to fit within the view. If we - // don't add them, they'll end up overlapping. + // We have to add the flyout size to both the workspace size and the + // block size because the blocks we want to resize include the blocks in + // the flyout, and the area we want to fit them includes the portion of + // the workspace that is behind the flyout. if (this.horizontalLayout) { + workspaceHeight += this.flyout_.height_; // Convert from pixels to workspace coordinates. blocksHeight += this.flyout_.height_ / this.scale; } else { + workspaceWidth += this.flyout_.width_; // Convert from pixels to workspace coordinates. blocksWidth += this.flyout_.width_ / this.scale; } } // Scale Units: (pixels / workspaceUnit) - var ratioX = metrics.viewWidth / blocksWidth; - var ratioY = metrics.viewHeight / blocksHeight; + var ratioX = workspaceWidth / blocksWidth; + var ratioY = workspaceHeight / blocksHeight; this.setScale(Math.min(ratioX, ratioY)); this.scrollCenter(); }; @@ -1768,23 +1786,6 @@ Blockly.WorkspaceSvg.prototype.scrollCenter = function() { var metrics = this.getMetrics(); var x = (metrics.contentWidth - metrics.viewWidth) / 2; var y = (metrics.contentHeight - metrics.viewHeight) / 2; - // Shift the x and y to disregard the permanent flyout (if it exists). - if (this.flyout_) { - switch (this.toolboxPosition) { - case Blockly.TOOLBOX_AT_LEFT: - x -= this.flyout_.width_ / 2; - break; - case Blockly.TOOLBOX_AT_RIGHT: - x += this.flyout_.width_ / 2; - break; - case Blockly.TOOLBOX_AT_TOP: - y -= this.flyout_.height_ / 2; - break; - case Blockly.TOOLBOX_AT_BOTTOM: - y += this.flyout_.height_ / 2; - break; - } - } // Convert from workspace directions to canvas directions. x = -x - metrics.contentLeft; @@ -1865,22 +1866,37 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) { newScale = this.options.zoomOptions.minScale; } this.scale = newScale; - if (this.grid_) { - this.grid_.update(this.scale); - } - // We call scroll instead of scrollbar.resize() so that we can center the - // zoom correctly without scrollbars, but scroll does not resize the - // scrollbars so we have to call resizeContent as well. - this.scroll(this.scrollX, this.scrollY); - if (this.scrollbar) { - var metrics = this.getMetrics(); - this.scrollbar.hScroll.resizeContentHorizontal(metrics); - this.scrollbar.vScroll.resizeContentVertical(metrics); - } + Blockly.hideChaff(false); if (this.flyout_) { // No toolbox, resize flyout. this.flyout_.reflow(); + this.recordDeleteAreas(); + } + if (this.grid_) { + this.grid_.update(this.scale); + } + + // We call scroll instead of scrollbar.resize() so that we can center the + // 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; + metrics.viewLeft += metrics.absoluteLeft; + metrics.viewTop += metrics.absoluteTop; + + this.scroll(this.scrollX, this.scrollY); + if (this.scrollbar) { + if (this.flyout_) { + this.scrollbar.hScroll.resizeViewHorizontal(metrics); + this.scrollbar.vScroll.resizeViewVertical(metrics); + } else { + this.scrollbar.hScroll.resizeContentHorizontal(metrics); + this.scrollbar.vScroll.resizeContentVertical(metrics); + } } }; @@ -2056,6 +2072,10 @@ Blockly.WorkspaceSvg.getContentDimensionsBounded_ = function(ws, svgSize) { * .viewWidth: Width of the visible portion of the workspace. * .contentHeight: Height of the content. * .contentWidth: Width of the content. + * .svgHeight: Height of the blockly div (the view + the toolbox, + * simple or otherwise), + * .svgWidth: Width of the blockly div (the view + the toolbox, + * simple or otherwise), * .viewTop: Top-edge of the visible portion of the workspace, relative to * the workspace origin. * .viewLeft: Left-edge of the visible portion of the workspace, relative to @@ -2087,28 +2107,41 @@ Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_ = function() { // Contains height and width in CSS pixels. // svgSize is equivalent to the size of the injectionDiv at this point. var svgSize = Blockly.svgSize(this.getParentSvg()); + var viewSize = {height: svgSize.height, width: svgSize.width}; if (this.toolbox_) { if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP || this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) { - svgSize.height -= toolboxDimensions.height; + viewSize.height -= toolboxDimensions.height; } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT || this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { - svgSize.width -= toolboxDimensions.width; + viewSize.width -= toolboxDimensions.width; + } + } else if (this.flyout_) { + if (this.toolboxPosition == Blockly.TOOLBOX_AT_TOP || + this.toolboxPosition == Blockly.TOOLBOX_AT_BOTTOM) { + viewSize.height -= flyoutDimensions.height; + } else if (this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT || + this.toolboxPosition == Blockly.TOOLBOX_AT_RIGHT) { + viewSize.width -= flyoutDimensions.width; } } // svgSize is now the space taken up by the Blockly workspace, not including // the toolbox. var contentDimensions = - Blockly.WorkspaceSvg.getContentDimensions_(this, svgSize); + Blockly.WorkspaceSvg.getContentDimensions_(this, viewSize); var absoluteLeft = 0; if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { absoluteLeft = toolboxDimensions.width; + } else if (this.flyout_ && this.toolboxPosition == Blockly.TOOLBOX_AT_LEFT) { + absoluteLeft = flyoutDimensions.width; } var absoluteTop = 0; if (this.toolbox_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { absoluteTop = toolboxDimensions.height; + } else if (this.flyout_ && this.toolboxPosition == Blockly.TOOLBOX_AT_TOP) { + absoluteTop = flyoutDimensions.height; } var metrics = { @@ -2117,14 +2150,17 @@ Blockly.WorkspaceSvg.getTopLevelWorkspaceMetrics_ = function() { contentTop: contentDimensions.top, contentLeft: contentDimensions.left, - viewHeight: svgSize.height, - viewWidth: svgSize.width, - viewTop: -this.scrollY, // Must be in pixels, somehow. - viewLeft: -this.scrollX, // Must be in pixels, somehow. + viewHeight: viewSize.height, + viewWidth: viewSize.width, + viewTop: -this.scrollY, + viewLeft: -this.scrollX, absoluteTop: absoluteTop, absoluteLeft: absoluteLeft, + svgHeight: svgSize.height, + svgWidth: svgSize.width, + toolboxWidth: toolboxDimensions.width, toolboxHeight: toolboxDimensions.height, From 69718f2fd4fe1c358b20d2d60e50fee80ce2c0ec Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Tue, 26 Feb 2019 16:33:18 -0800 Subject: [PATCH 2/3] Removed accessing private flyout.width_ variable. --- core/mutator.js | 7 ++++--- core/workspace_svg.js | 4 ++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/mutator.js b/core/mutator.js index 17723b31c..abb1e7cf7 100644 --- a/core/mutator.js +++ b/core/mutator.js @@ -272,7 +272,7 @@ Blockly.Mutator.prototype.setVisible = function(visible) { this.rootBlock_.setDeletable(false); if (this.workspace_.flyout_) { var margin = this.workspace_.flyout_.CORNER_RADIUS * 2; - var x = this.workspace_.flyout_.width_ + margin; + var x = this.workspace_.getFlyout_().getWidth() + margin; } else { var margin = 16; var x = margin; @@ -385,9 +385,10 @@ Blockly.Mutator.prototype.workspaceChanged_ = function() { Blockly.Mutator.prototype.getFlyoutMetrics_ = function() { return { viewHeight: this.workspaceHeight_, - viewWidth: this.workspaceWidth_ - this.workspace_.flyout_.width_, + viewWidth: this.workspaceWidth_ - this.workspace_.getFlyout_().getWidth(), absoluteTop: 0, - absoluteLeft: this.workspace_.RTL ? 0 : this.workspace_.flyout_.width_ + absoluteLeft: this.workspace_.RTL ? 0 : + this.workspace_.getFlyout_().getWidth() }; }; diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 28db0d2f2..1d9306eea 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -1733,9 +1733,9 @@ Blockly.WorkspaceSvg.prototype.zoomToFit = function() { // Convert from pixels to workspace coordinates. blocksHeight += this.flyout_.height_ / this.scale; } else { - workspaceWidth += this.flyout_.width_; + workspaceWidth += this.flyout_.getWidth(); // Convert from pixels to workspace coordinates. - blocksWidth += this.flyout_.width_ / this.scale; + blocksWidth += this.flyout_.getWidth() / this.scale; } } From 168ee80b05081dbb8b9cfc0656d51727d99fa167 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Tue, 26 Feb 2019 16:37:56 -0800 Subject: [PATCH 3/3] Removed console log. --- core/workspace_svg.js | 1 - 1 file changed, 1 deletion(-) diff --git a/core/workspace_svg.js b/core/workspace_svg.js index 1d9306eea..b13bcacc4 100644 --- a/core/workspace_svg.js +++ b/core/workspace_svg.js @@ -1688,7 +1688,6 @@ Blockly.WorkspaceSvg.prototype.zoom = function(x, y, amount) { */ Blockly.WorkspaceSvg.prototype.zoomCenter = function(type) { var metrics = this.getMetrics(); - console.log(metrics); if (this.flyout_) { // If you want blocks in the center of the view (visible portion of the // workspace) to stay centered when the size of the view decreases (i.e.