mirror of
https://github.com/google/blockly.git
synced 2026-01-08 09:30:06 +01:00
Update flyout metrics to work with the new metrics manager (#4684)
This commit is contained in:
@@ -21,6 +21,7 @@ goog.require('Blockly.Events');
|
||||
goog.require('Blockly.Events.BlockCreate');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Events.VarCreate');
|
||||
goog.require('Blockly.FlyoutMetricsManager');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.Gesture');
|
||||
goog.require('Blockly.ScrollbarPair');
|
||||
@@ -41,7 +42,6 @@ goog.requireType('Blockly.FlyoutButton');
|
||||
goog.requireType('Blockly.IDeleteArea');
|
||||
goog.requireType('Blockly.IFlyout');
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.utils.Metrics');
|
||||
goog.requireType('Blockly.utils.Rect');
|
||||
|
||||
|
||||
@@ -55,9 +55,6 @@ goog.requireType('Blockly.utils.Rect');
|
||||
* @implements {Blockly.IFlyout}
|
||||
*/
|
||||
Blockly.Flyout = function(workspaceOptions) {
|
||||
workspaceOptions.getMetrics =
|
||||
/** @type {function():!Blockly.utils.Metrics} */ (
|
||||
this.getMetrics_.bind(this));
|
||||
workspaceOptions.setMetrics = this.setMetrics_.bind(this);
|
||||
|
||||
/**
|
||||
@@ -65,6 +62,9 @@ Blockly.Flyout = function(workspaceOptions) {
|
||||
* @protected
|
||||
*/
|
||||
this.workspace_ = new Blockly.WorkspaceSvg(workspaceOptions);
|
||||
this.workspace_.setMetricsManager(
|
||||
new Blockly.FlyoutMetricsManager(this.workspace_, this));
|
||||
|
||||
this.workspace_.isFlyout = true;
|
||||
// Keep the workspace visibility consistent with the flyout's visibility.
|
||||
this.workspace_.setVisible(this.isVisible_);
|
||||
@@ -425,6 +425,8 @@ Blockly.Flyout.prototype.updateDisplay_ = function() {
|
||||
Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) {
|
||||
this.svgGroup_.setAttribute("width", width);
|
||||
this.svgGroup_.setAttribute("height", height);
|
||||
this.workspace_.setCachedParentSvgSize(width, height);
|
||||
|
||||
if (this.svgGroup_.tagName == 'svg') {
|
||||
var transform = 'translate(' + x + 'px,' + y + 'px)';
|
||||
Blockly.utils.dom.setCssTransform(this.svgGroup_, transform);
|
||||
@@ -1038,15 +1040,6 @@ Blockly.Flyout.prototype.position;
|
||||
*/
|
||||
Blockly.Flyout.prototype.isDragTowardWorkspace;
|
||||
|
||||
/**
|
||||
* Return an object with all the metrics required to size scrollbars for the
|
||||
* flyout.
|
||||
* @return {Blockly.utils.Metrics} Contains size and position metrics of the
|
||||
* flyout.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Flyout.prototype.getMetrics_;
|
||||
|
||||
/**
|
||||
* Sets the translation of the flyout to match the scrollbars.
|
||||
* @param {!{x:number,y:number}} xyRatio Contains a y property which is a float
|
||||
|
||||
@@ -27,7 +27,6 @@ goog.require('Blockly.WidgetDiv');
|
||||
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
goog.requireType('Blockly.utils.Metrics');
|
||||
|
||||
|
||||
/**
|
||||
@@ -43,73 +42,6 @@ Blockly.HorizontalFlyout = function(workspaceOptions) {
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.HorizontalFlyout, Blockly.Flyout);
|
||||
|
||||
/**
|
||||
* Return an object with all the metrics required to size scrollbars for the
|
||||
* flyout. The following properties are computed:
|
||||
* .viewHeight: Height of the visible rectangle,
|
||||
* .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.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.getMetrics_ = function() {
|
||||
if (!this.isVisible()) {
|
||||
// Flyout is hidden.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var optionBox = this.workspace_.getCanvas().getBBox();
|
||||
} catch (e) {
|
||||
// Firefox has trouble with hidden elements (Bug 528969).
|
||||
var optionBox = {height: 0, y: 0, width: 0, x: 0};
|
||||
}
|
||||
|
||||
var absoluteTop = this.SCROLLBAR_PADDING;
|
||||
var absoluteLeft = this.SCROLLBAR_PADDING;
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.BOTTOM) {
|
||||
absoluteTop = 0;
|
||||
}
|
||||
var viewHeight = this.height_;
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP) {
|
||||
viewHeight -= this.SCROLLBAR_PADDING;
|
||||
}
|
||||
var viewWidth = this.width_ - 2 * this.SCROLLBAR_PADDING;
|
||||
|
||||
var metrics = {
|
||||
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,
|
||||
viewTop: -this.workspace_.scrollY,
|
||||
viewLeft: -this.workspace_.scrollX,
|
||||
|
||||
absoluteTop: absoluteTop,
|
||||
absoluteLeft: absoluteLeft
|
||||
};
|
||||
return metrics;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the translation of the flyout to match the scrollbars.
|
||||
* @param {!{x:number,y:number}} xyRatio Contains a y property which is a float
|
||||
@@ -118,20 +50,23 @@ Blockly.HorizontalFlyout.prototype.getMetrics_ = function() {
|
||||
* @protected
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
var metrics = this.getMetrics_();
|
||||
// This is a fix to an apparent race condition.
|
||||
if (!metrics) {
|
||||
if (!this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
|
||||
if (typeof xyRatio.x == 'number') {
|
||||
this.workspace_.scrollX =
|
||||
-(metrics.scrollLeft +
|
||||
(metrics.scrollWidth - metrics.viewWidth) * xyRatio.x);
|
||||
-(scrollMetrics.left +
|
||||
(scrollMetrics.width - viewMetrics.width) * xyRatio.x);
|
||||
}
|
||||
|
||||
this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
|
||||
this.workspace_.scrollY + metrics.absoluteTop);
|
||||
this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.scrollY + absoluteMetrics.top);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -148,22 +83,24 @@ Blockly.HorizontalFlyout.prototype.getX = function() {
|
||||
* @return {number} Y coordinate.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.getY = function() {
|
||||
var targetWorkspaceMetrics = this.targetWorkspace.getMetrics();
|
||||
if (!targetWorkspaceMetrics) {
|
||||
// Hidden components will return null.
|
||||
if (!this.isVisible()) {
|
||||
return 0;
|
||||
}
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
|
||||
var y = 0;
|
||||
var atTop = this.toolboxPosition_ == Blockly.utils.toolbox.Position.TOP;
|
||||
// If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
|
||||
// If there is a category toolbox.
|
||||
if (targetWorkspaceMetrics.toolboxHeight) {
|
||||
if (toolboxMetrics.height) {
|
||||
if (atTop) {
|
||||
y = targetWorkspaceMetrics.toolboxHeight;
|
||||
y = toolboxMetrics.height;
|
||||
} else {
|
||||
y = targetWorkspaceMetrics.viewHeight - this.height_;
|
||||
y = viewMetrics.height - this.height_;
|
||||
}
|
||||
// Simple (flyout-only) toolbox.
|
||||
} else {
|
||||
@@ -171,7 +108,7 @@ Blockly.HorizontalFlyout.prototype.getY = function() {
|
||||
y = 0;
|
||||
} else {
|
||||
// The simple flyout does not cover the workspace.
|
||||
y = targetWorkspaceMetrics.viewHeight;
|
||||
y = viewMetrics.height;
|
||||
}
|
||||
}
|
||||
// Trashcan flyout is opposite the main flyout.
|
||||
@@ -183,8 +120,7 @@ Blockly.HorizontalFlyout.prototype.getY = function() {
|
||||
// to align the bottom edge of the flyout with the bottom edge of the
|
||||
// blocklyDiv, we calculate the full height of the div minus the height
|
||||
// of the flyout.
|
||||
y = targetWorkspaceMetrics.viewHeight +
|
||||
targetWorkspaceMetrics.absoluteTop - this.height_;
|
||||
y = viewMetrics.height + absoluteMetrics.top - this.height_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +137,7 @@ Blockly.HorizontalFlyout.prototype.position = function() {
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
// Record the width for Blockly.Flyout.getMetrics_.
|
||||
// Record the width for workspace metrics.
|
||||
this.width_ = targetWorkspaceViewMetrics.width;
|
||||
|
||||
var edgeWidth = targetWorkspaceViewMetrics.width - 2 * this.CORNER_RADIUS;
|
||||
@@ -275,8 +211,11 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
var delta = scrollDelta.x || scrollDelta.y;
|
||||
|
||||
if (delta) {
|
||||
var metrics = this.getMetrics_();
|
||||
var pos = (metrics.viewLeft - metrics.scrollLeft) + delta;
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
var pos = (viewMetrics.left - scrollMetrics.left) + delta;
|
||||
this.workspace_.scrollbar.setX(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
@@ -420,7 +359,7 @@ Blockly.HorizontalFlyout.prototype.reflowInternal_ = function() {
|
||||
this.targetWorkspace.scrollX, this.targetWorkspace.scrollY + flyoutHeight);
|
||||
}
|
||||
|
||||
// Record the height for .getMetrics_ and .position.
|
||||
// Record the height for workspace metrics and .position.
|
||||
this.height_ = flyoutHeight;
|
||||
this.position();
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ goog.require('Blockly.WidgetDiv');
|
||||
|
||||
goog.requireType('Blockly.Options');
|
||||
goog.requireType('Blockly.utils.Coordinate');
|
||||
goog.requireType('Blockly.utils.Metrics');
|
||||
|
||||
|
||||
/**
|
||||
@@ -48,70 +47,6 @@ Blockly.utils.object.inherits(Blockly.VerticalFlyout, Blockly.Flyout);
|
||||
*/
|
||||
Blockly.VerticalFlyout.registryName = 'verticalFlyout';
|
||||
|
||||
/**
|
||||
* Return an object with all the metrics required to size scrollbars for the
|
||||
* flyout. The following properties are computed:
|
||||
* .viewHeight: Height of the visible rectangle,
|
||||
* .viewWidth: Width of the visible rectangle,
|
||||
* .contentHeight: Height of the contents,
|
||||
* .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.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.getMetrics_ = function() {
|
||||
if (!this.isVisible()) {
|
||||
// Flyout is hidden.
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
var optionBox = this.workspace_.getCanvas().getBBox();
|
||||
} catch (e) {
|
||||
// Firefox has trouble with hidden elements (Bug 528969).
|
||||
var optionBox = {height: 0, y: 0, width: 0, x: 0};
|
||||
}
|
||||
|
||||
// Padding for the end of the scrollbar.
|
||||
var absoluteTop = this.SCROLLBAR_PADDING;
|
||||
var absoluteLeft = 0;
|
||||
|
||||
var viewHeight = this.height_ - 2 * this.SCROLLBAR_PADDING;
|
||||
var viewWidth = this.width_;
|
||||
if (!this.RTL) {
|
||||
viewWidth -= this.SCROLLBAR_PADDING;
|
||||
}
|
||||
|
||||
var metrics = {
|
||||
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,
|
||||
viewTop: -this.workspace_.scrollY,
|
||||
viewLeft: -this.workspace_.scrollX,
|
||||
|
||||
absoluteTop: absoluteTop,
|
||||
absoluteLeft: absoluteLeft
|
||||
};
|
||||
return metrics;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the translation of the flyout to match the scrollbars.
|
||||
* @param {!{x:number,y:number}} xyRatio Contains a y property which is a float
|
||||
@@ -120,18 +55,21 @@ Blockly.VerticalFlyout.prototype.getMetrics_ = function() {
|
||||
* @protected
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
var metrics = this.getMetrics_();
|
||||
// This is a fix to an apparent race condition.
|
||||
if (!metrics) {
|
||||
if (!this.isVisible()) {
|
||||
return;
|
||||
}
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
|
||||
if (typeof xyRatio.y == 'number') {
|
||||
this.workspace_.scrollY =
|
||||
-(metrics.scrollTop +
|
||||
(metrics.scrollHeight - metrics.viewHeight) * xyRatio.y);
|
||||
-(scrollMetrics.top +
|
||||
(scrollMetrics.height - viewMetrics.height) * xyRatio.y);
|
||||
}
|
||||
this.workspace_.translate(this.workspace_.scrollX + metrics.absoluteLeft,
|
||||
this.workspace_.scrollY + metrics.absoluteTop);
|
||||
this.workspace_.translate(this.workspace_.scrollX + absoluteMetrics.left,
|
||||
this.workspace_.scrollY + absoluteMetrics.top);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -139,22 +77,23 @@ Blockly.VerticalFlyout.prototype.setMetrics_ = function(xyRatio) {
|
||||
* @return {number} X coordinate.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
var targetWorkspaceMetrics = this.targetWorkspace.getMetrics();
|
||||
if (!targetWorkspaceMetrics) {
|
||||
// Hidden components will return null.
|
||||
if (!this.isVisible()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var absoluteMetrics = metricsManager.getAbsoluteMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var toolboxMetrics = metricsManager.getToolboxMetrics();
|
||||
var x = 0;
|
||||
|
||||
// If this flyout is not the trashcan flyout (e.g. toolbox or mutator).
|
||||
if (this.targetWorkspace.toolboxPosition == this.toolboxPosition_) {
|
||||
// If there is a category toolbox.
|
||||
if (targetWorkspaceMetrics.toolboxWidth) {
|
||||
if (toolboxMetrics.width) {
|
||||
if (this.toolboxPosition_ == Blockly.utils.toolbox.Position.LEFT) {
|
||||
x = targetWorkspaceMetrics.toolboxWidth;
|
||||
x = toolboxMetrics.width;
|
||||
} else {
|
||||
x = targetWorkspaceMetrics.viewWidth - this.width_;
|
||||
x = viewMetrics.width - this.width_;
|
||||
}
|
||||
// Simple (flyout-only) toolbox.
|
||||
} else {
|
||||
@@ -162,7 +101,7 @@ Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
x = 0;
|
||||
} else {
|
||||
// The simple flyout does not cover the workspace.
|
||||
x = targetWorkspaceMetrics.viewWidth;
|
||||
x = viewMetrics.width;
|
||||
}
|
||||
}
|
||||
// Trashcan flyout is opposite the main flyout.
|
||||
@@ -174,8 +113,7 @@ Blockly.VerticalFlyout.prototype.getX = function() {
|
||||
// to align the right edge of the flyout with the right edge of the
|
||||
// blocklyDiv, we calculate the full width of the div minus the width
|
||||
// of the flyout.
|
||||
x = targetWorkspaceMetrics.viewWidth +
|
||||
targetWorkspaceMetrics.absoluteLeft - this.width_;
|
||||
x = viewMetrics.width + absoluteMetrics.left - this.width_;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,7 +139,7 @@ Blockly.VerticalFlyout.prototype.position = function() {
|
||||
var metricsManager = this.targetWorkspace.getMetricsManager();
|
||||
var targetWorkspaceViewMetrics = metricsManager.getViewMetrics();
|
||||
|
||||
// Record the height for Blockly.Flyout.getMetrics_
|
||||
// Record the height for workspace metrics.
|
||||
this.height_ = targetWorkspaceViewMetrics.height;
|
||||
|
||||
var edgeWidth = this.width_ - this.CORNER_RADIUS;
|
||||
@@ -264,8 +202,11 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
var scrollDelta = Blockly.utils.getScrollDeltaPixels(e);
|
||||
|
||||
if (scrollDelta.y) {
|
||||
var metrics = this.getMetrics_();
|
||||
var pos = (metrics.viewTop - metrics.scrollTop) + scrollDelta.y;
|
||||
var metricsManager = this.workspace_.getMetricsManager();
|
||||
var scrollMetrics = metricsManager.getScrollMetrics();
|
||||
var viewMetrics = metricsManager.getViewMetrics();
|
||||
var pos = (viewMetrics.top - scrollMetrics.top) + scrollDelta.y;
|
||||
|
||||
this.workspace_.scrollbar.setY(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
@@ -426,7 +367,7 @@ Blockly.VerticalFlyout.prototype.reflowInternal_ = function() {
|
||||
this.targetWorkspace.scrollX + flyoutWidth, this.targetWorkspace.scrollY);
|
||||
}
|
||||
|
||||
// Record the width for .getMetrics_ and .position.
|
||||
// Record the width for workspace metrics and .position.
|
||||
this.width_ = flyoutWidth;
|
||||
this.position();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FlyoutMetricsManager');
|
||||
goog.provide('Blockly.MetricsManager');
|
||||
|
||||
goog.require('Blockly.IMetricsManager');
|
||||
@@ -121,7 +122,8 @@ Blockly.MetricsManager.prototype.getDimensionsPx_ = function(elem) {
|
||||
* @public
|
||||
*/
|
||||
Blockly.MetricsManager.prototype.getFlyoutMetrics = function(opt_own) {
|
||||
var flyoutDimensions = this.getDimensionsPx_(this.workspace_.getFlyout(opt_own));
|
||||
var flyoutDimensions =
|
||||
this.getDimensionsPx_(this.workspace_.getFlyout(opt_own));
|
||||
return {
|
||||
width: flyoutDimensions.width,
|
||||
height: flyoutDimensions.height,
|
||||
@@ -439,8 +441,7 @@ Blockly.MetricsManager.prototype.getMetrics = function() {
|
||||
var absoluteMetrics = this.getAbsoluteMetrics();
|
||||
var viewMetrics = this.getViewMetrics();
|
||||
var contentMetrics = this.getContentMetrics();
|
||||
var scrollMetrics =
|
||||
this.getScrollMetrics(false, viewMetrics, contentMetrics);
|
||||
var scrollMetrics = this.getScrollMetrics(false, viewMetrics, contentMetrics);
|
||||
|
||||
return {
|
||||
contentHeight: contentMetrics.height,
|
||||
@@ -476,3 +477,116 @@ Blockly.MetricsManager.prototype.getMetrics = function() {
|
||||
Blockly.registry.register(
|
||||
Blockly.registry.Type.METRICS_MANAGER, Blockly.registry.DEFAULT,
|
||||
Blockly.MetricsManager);
|
||||
|
||||
/**
|
||||
* Calculates metrics for a flyout's workspace.
|
||||
* The metrics are mainly used to size scrollbars for the flyout.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace The flyout's workspace.
|
||||
* @param {!Blockly.IFlyout} flyout The flyout.
|
||||
* @extends {Blockly.MetricsManager}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager = function(workspace, flyout) {
|
||||
/**
|
||||
* The flyout that owns the workspace to calculate metrics for.
|
||||
* @type {!Blockly.IFlyout}
|
||||
* @protected
|
||||
*/
|
||||
this.flyout_ = flyout;
|
||||
|
||||
Blockly.FlyoutMetricsManager.superClass_.constructor.call(this, workspace);
|
||||
};
|
||||
Blockly.utils.object.inherits(
|
||||
Blockly.FlyoutMetricsManager, Blockly.MetricsManager);
|
||||
|
||||
/**
|
||||
* Gets the bounding box of the blocks on the flyout's workspace.
|
||||
* This is in workspace coordinates.
|
||||
* @returns {!SVGRect|{height: number, y: number, width: number, x: number}} The
|
||||
* bounding box of the blocks on the workspace.
|
||||
* @private
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager.prototype.getBoundingBox_ = function() {
|
||||
try {
|
||||
var blockBoundingBox = this.workspace_.getCanvas().getBBox();
|
||||
} catch (e) {
|
||||
// Firefox has trouble with hidden elements (Bug 528969).
|
||||
// 2021 Update: It looks like this was fixed around Firefox 77 released in
|
||||
// 2020.
|
||||
var blockBoundingBox = {height: 0, y: 0, width: 0, x: 0};
|
||||
}
|
||||
return blockBoundingBox;
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager.prototype.getContentMetrics = function(
|
||||
opt_getWorkspaceCoordinates) {
|
||||
// The bounding box is in workspace coordinates.
|
||||
var blockBoundingBox = this.getBoundingBox_();
|
||||
var scale = opt_getWorkspaceCoordinates ? 1 : this.workspace_.scale;
|
||||
|
||||
return {
|
||||
height: blockBoundingBox.height * scale,
|
||||
width: blockBoundingBox.width * scale,
|
||||
top: blockBoundingBox.y * scale,
|
||||
left: blockBoundingBox.x * scale,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager.prototype.getScrollMetrics = function(
|
||||
opt_getWorkspaceCoordinates, opt_viewMetrics, opt_contentMetrics) {
|
||||
var contentMetrics = opt_contentMetrics || this.getContentMetrics();
|
||||
var margin = this.flyout_.MARGIN;
|
||||
var scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
|
||||
|
||||
return {
|
||||
height: (contentMetrics.height + 2 * margin) / scale,
|
||||
width: (contentMetrics.width + 2 * margin) / scale,
|
||||
top: contentMetrics.top - margin / scale,
|
||||
left: contentMetrics.left - margin / scale,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager.prototype.getViewMetrics = function(
|
||||
opt_getWorkspaceCoordinates) {
|
||||
var svgMetrics = this.getSvgMetrics();
|
||||
var scale = opt_getWorkspaceCoordinates ? this.workspace_.scale : 1;
|
||||
if (this.flyout_.horizontalLayout) {
|
||||
var viewWidth = svgMetrics.width - 2 * this.flyout_.SCROLLBAR_PADDING;
|
||||
var viewHeight = svgMetrics.height - this.flyout_.SCROLLBAR_PADDING;
|
||||
} else {
|
||||
var viewWidth = svgMetrics.width - this.flyout_.SCROLLBAR_PADDING;
|
||||
var viewHeight = svgMetrics.height - 2 * this.flyout_.SCROLLBAR_PADDING;
|
||||
}
|
||||
return {
|
||||
height: viewHeight / scale,
|
||||
width: viewWidth / scale,
|
||||
top: -this.workspace_.scrollY / scale,
|
||||
left: -this.workspace_.scrollX / scale,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @override
|
||||
*/
|
||||
Blockly.FlyoutMetricsManager.prototype.getAbsoluteMetrics = function() {
|
||||
var scrollbarPadding = this.flyout_.SCROLLBAR_PADDING;
|
||||
|
||||
if (this.flyout_.horizontalLayout) {
|
||||
// The viewWidth is svgWidth - 2 * scrollbarPadding. We want to put half
|
||||
// of that padding to the left of the blocks.
|
||||
return {top: 0, left: scrollbarPadding};
|
||||
} else {
|
||||
// The viewHeight is svgHeight - 2 * scrollbarPadding. We want to put half
|
||||
// of that padding to the top of the blocks.
|
||||
return {top: scrollbarPadding, left: 0};
|
||||
}
|
||||
};
|
||||
|
||||
@@ -241,8 +241,8 @@ Blockly.Mutator.prototype.resizeBubble_ = function() {
|
||||
var height = workspaceSize.height + doubleBorderWidth * 3;
|
||||
var flyout = this.workspace_.getFlyout();
|
||||
if (flyout) {
|
||||
var flyoutMetrics = flyout.getMetrics_();
|
||||
height = Math.max(height, flyoutMetrics.scrollHeight + 20);
|
||||
var flyoutScrollMetrics = this.workspace_.getMetricsManager().getScrollMetrics();
|
||||
height = Math.max(height, flyoutScrollMetrics.height + 20);
|
||||
width += flyout.getWidth();
|
||||
}
|
||||
if (this.block_.RTL) {
|
||||
|
||||
@@ -107,42 +107,42 @@ Blockly.utils.Metrics.prototype.absoluteLeft;
|
||||
|
||||
/**
|
||||
* Height of the Blockly div (the view + the toolbox, simple of otherwise).
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.svgHeight;
|
||||
|
||||
/**
|
||||
* Width of the Blockly div (the view + the toolbox, simple or otherwise).
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.svgWidth;
|
||||
|
||||
/**
|
||||
* Width of the toolbox, if it exists. Otherwise zero.
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.toolboxWidth;
|
||||
|
||||
/**
|
||||
* Height of the toolbox, if it exists. Otherwise zero.
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.toolboxHeight;
|
||||
|
||||
/**
|
||||
* Top, bottom, left or right. Use TOOLBOX_AT constants to compare.
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.toolboxPosition;
|
||||
|
||||
/**
|
||||
* Width of the flyout if it is always open. Otherwise zero.
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.flyoutWidth;
|
||||
|
||||
/**
|
||||
* Height of the flyout if it is always open. Otherwise zero.
|
||||
* @type {number|undefined}
|
||||
* @type {number}
|
||||
*/
|
||||
Blockly.utils.Metrics.prototype.flyoutHeight;
|
||||
|
||||
@@ -532,6 +532,16 @@ Blockly.WorkspaceSvg.prototype.getMetricsManager = function() {
|
||||
};
|
||||
|
||||
/**
|
||||
* Sets the metrics manager for the workspace.
|
||||
* @param {!Blockly.IMetricsManager} metricsManager The metrics manager.
|
||||
* @package
|
||||
*/
|
||||
Blockly.WorkspaceSvg.prototype.setMetricsManager = function(metricsManager) {
|
||||
this.metricsManager_ = metricsManager;
|
||||
this.getMetrics = this.metricsManager_.getMetrics.bind(this.metricsManager_);
|
||||
};
|
||||
|
||||
/*
|
||||
* Gets the plugin manager for this workspace.
|
||||
* @return {!Blockly.PluginManager} The plugin manager.
|
||||
* @public
|
||||
|
||||
@@ -34,13 +34,14 @@ suite('Flyout', function() {
|
||||
suite('simple flyout', function() {
|
||||
setup(function() {
|
||||
this.flyout = this.workspace.getFlyout();
|
||||
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
test('y is always 0', function() {
|
||||
chai.assert.equal(this.flyout.getY(), 0, 'y coordinate in vertical flyout should be 0');
|
||||
});
|
||||
test('x is right of workspace if flyout at right', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
viewWidth: 100,
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
width: 100,
|
||||
});
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.RIGHT;
|
||||
@@ -62,25 +63,30 @@ suite('Flyout', function() {
|
||||
toolbox: toolbox
|
||||
});
|
||||
this.flyout = this.workspace.getToolbox().getFlyout();
|
||||
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
teardown(function() {
|
||||
workspaceTeardown.call(this, this.workspace);
|
||||
});
|
||||
test('x is aligned with toolbox at left', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
toolboxWidth: 20,
|
||||
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
|
||||
width: 20,
|
||||
});
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.LEFT;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.LEFT;
|
||||
chai.assert.equal(this.flyout.getX(), 20, 'x should be aligned with toolbox');
|
||||
});
|
||||
test('x is aligned with toolbox at right', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
toolboxWidth: 20,
|
||||
viewWidth: 100,
|
||||
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
|
||||
width: 20,
|
||||
});
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
width: 100,
|
||||
});
|
||||
this.flyout.width_ = 10;
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.RIGHT;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT;
|
||||
@@ -92,6 +98,7 @@ suite('Flyout', function() {
|
||||
suite('trashcan flyout', function() {
|
||||
setup(function() {
|
||||
this.flyout = this.workspace.getFlyout();
|
||||
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
test('x is 0 if trashcan on left', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
@@ -104,10 +111,14 @@ suite('Flyout', function() {
|
||||
});
|
||||
test('trashcan on right covers right edge of workspace', function() {
|
||||
this.flyout.width_ = 20;
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
viewWidth: 100,
|
||||
absoluteLeft: 10,
|
||||
sinon.stub(this.targetMetricsManager, 'getAbsoluteMetrics').returns({
|
||||
left: 10,
|
||||
});
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
width: 100,
|
||||
});
|
||||
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.LEFT;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.RIGHT;
|
||||
@@ -130,6 +141,7 @@ suite('Flyout', function() {
|
||||
suite('simple flyout', function() {
|
||||
setup(function() {
|
||||
this.flyout = this.workspace.getFlyout();
|
||||
this.targetMetricsManager = this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
test('x is always 0', function() {
|
||||
chai.assert.equal(this.flyout.getX(), 0, 'x coordinate in horizontal flyout should be 0');
|
||||
@@ -144,8 +156,8 @@ suite('Flyout', function() {
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.BOTTOM;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
viewHeight: 50,
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
height: 50,
|
||||
});
|
||||
chai.assert.equal(this.flyout.getY(), 50, 'y should be below the workspace');
|
||||
});
|
||||
@@ -159,25 +171,31 @@ suite('Flyout', function() {
|
||||
horizontalLayout: true,
|
||||
});
|
||||
this.flyout = this.workspace.getToolbox().getFlyout();
|
||||
this.targetMetricsManager =
|
||||
this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
teardown(function() {
|
||||
workspaceTeardown.call(this, this.workspace);
|
||||
});
|
||||
test('y is aligned with toolbox at top', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
toolboxHeight: 20,
|
||||
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
|
||||
height: 20,
|
||||
});
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.TOP;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.TOP;
|
||||
chai.assert.equal(this.flyout.getY(), 20, 'y should be aligned with toolbox');
|
||||
});
|
||||
test('y is aligned with toolbox at bottom', function() {
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
toolboxHeight: 20,
|
||||
viewHeight: 100,
|
||||
sinon.stub(this.targetMetricsManager, 'getToolboxMetrics').returns({
|
||||
height: 20,
|
||||
});
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
height: 100,
|
||||
});
|
||||
this.flyout.height_ = 30;
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.BOTTOM;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
|
||||
@@ -189,6 +207,8 @@ suite('Flyout', function() {
|
||||
suite('trashcan flyout', function() {
|
||||
setup(function() {
|
||||
this.flyout = this.workspace.getFlyout();
|
||||
this.targetMetricsManager =
|
||||
this.flyout.targetWorkspace.getMetricsManager();
|
||||
});
|
||||
test('y is 0 if trashcan at top', function() {
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
@@ -200,10 +220,13 @@ suite('Flyout', function() {
|
||||
this.flyout.targetWorkspace.toolboxPosition =
|
||||
Blockly.utils.toolbox.Position.TOP;
|
||||
this.flyout.toolboxPosition_ = Blockly.utils.toolbox.Position.BOTTOM;
|
||||
sinon.stub(this.flyout.targetWorkspace, 'getMetrics').returns({
|
||||
viewHeight: 50,
|
||||
absoluteTop: 10,
|
||||
sinon.stub(this.targetMetricsManager, 'getAbsoluteMetrics').returns({
|
||||
top: 10,
|
||||
});
|
||||
sinon.stub(this.targetMetricsManager, 'getViewMetrics').returns({
|
||||
height: 50,
|
||||
});
|
||||
this.flyout.setVisible(true);
|
||||
this.flyout.height_ = 20;
|
||||
chai.assert.equal(this.flyout.getY(), 40, 'y + height should be aligned with bottom');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user