mirror of
https://github.com/google/blockly.git
synced 2026-01-08 09:30:06 +01:00
Use ScrollbarPair and WorkspaceDragger in flyouts (#4607)
* Use ScrollbarPair for flyouts * Address PR comments * Fix compile error
This commit is contained in:
@@ -262,12 +262,9 @@ Blockly.Flyout.prototype.init = function(targetWorkspace) {
|
||||
this.targetWorkspace = targetWorkspace;
|
||||
this.workspace_.targetWorkspace = targetWorkspace;
|
||||
|
||||
/**
|
||||
* @type {!Blockly.Scrollbar}
|
||||
* @package
|
||||
*/
|
||||
this.scrollbar = new Blockly.Scrollbar(this.workspace_,
|
||||
this.horizontalLayout, false, 'blocklyFlyoutScrollbar');
|
||||
this.workspace_.scrollbar = new Blockly.ScrollbarPair(
|
||||
this.workspace_, this.horizontalLayout, !this.horizontalLayout,
|
||||
'blocklyFlyoutScrollbar');
|
||||
|
||||
this.hide();
|
||||
|
||||
@@ -305,10 +302,6 @@ Blockly.Flyout.prototype.dispose = function() {
|
||||
this.targetWorkspace.removeChangeListener(this.filterWrapper_);
|
||||
this.filterWrapper_ = null;
|
||||
}
|
||||
if (this.scrollbar) {
|
||||
this.scrollbar.dispose();
|
||||
this.scrollbar = null;
|
||||
}
|
||||
if (this.workspace_) {
|
||||
this.workspace_.getThemeManager().unsubscribe(this.svgBackground_);
|
||||
this.workspace_.targetWorkspace = null;
|
||||
@@ -397,7 +390,7 @@ Blockly.Flyout.prototype.updateDisplay_ = function() {
|
||||
this.svgGroup_.style.display = show ? 'block' : 'none';
|
||||
// Update the scrollbar's visibility too since it should mimic the
|
||||
// flyout's visibility.
|
||||
this.scrollbar.setContainerVisible(show);
|
||||
this.workspace_.scrollbar.setContainerVisible(show);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -422,14 +415,11 @@ Blockly.Flyout.prototype.positionAt_ = function(width, height, x, y) {
|
||||
}
|
||||
|
||||
// Update the scrollbar (if one exists).
|
||||
if (this.scrollbar) {
|
||||
var scrollbar = this.workspace_.scrollbar;
|
||||
if (scrollbar) {
|
||||
// Set the scrollbars origin to be the top left of the flyout.
|
||||
this.scrollbar.setOrigin(x, y);
|
||||
this.scrollbar.resize();
|
||||
// Set the position again so that if the metrics were the same (and the
|
||||
// resize failed) our position is still updated.
|
||||
this.scrollbar.setPosition(
|
||||
this.scrollbar.position.x, this.scrollbar.position.y);
|
||||
scrollbar.setOrigin(x, y);
|
||||
scrollbar.resize();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -929,7 +919,8 @@ Blockly.Flyout.prototype.reflow = function() {
|
||||
* @package
|
||||
*/
|
||||
Blockly.Flyout.prototype.isScrollable = function() {
|
||||
return this.scrollbar ? this.scrollbar.isVisible() : false;
|
||||
return this.workspace_.scrollbar ?
|
||||
this.workspace_.scrollbar.isVisible() : false;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright 2017 Google LLC
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @fileoverview Methods for dragging a flyout visually.
|
||||
* @author fenichel@google.com (Rachel Fenichel)
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.provide('Blockly.FlyoutDragger');
|
||||
|
||||
goog.require('Blockly.utils.object');
|
||||
goog.require('Blockly.WorkspaceDragger');
|
||||
|
||||
goog.requireType('Blockly.IFlyout');
|
||||
|
||||
|
||||
/**
|
||||
* Class for a flyout dragger. It moves a flyout workspace around when it is
|
||||
* being dragged by a mouse or touch.
|
||||
* Note that the workspace itself manages whether or not it has a drag surface
|
||||
* and how to do translations based on that. This simply passes the right
|
||||
* commands based on events.
|
||||
* @param {!Blockly.IFlyout} flyout The flyout to drag.
|
||||
* @extends {Blockly.WorkspaceDragger}
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.FlyoutDragger = function(flyout) {
|
||||
Blockly.FlyoutDragger.superClass_.constructor.call(this,
|
||||
flyout.getWorkspace());
|
||||
|
||||
/**
|
||||
* The scrollbar to update to move the flyout.
|
||||
* Unlike the main workspace, the flyout has only one scrollbar, in either the
|
||||
* horizontal or the vertical direction.
|
||||
* @type {!Blockly.Scrollbar}
|
||||
* @private
|
||||
*/
|
||||
this.scrollbar_ = flyout.scrollbar;
|
||||
|
||||
/**
|
||||
* Whether the flyout scrolls horizontally. If false, the flyout scrolls
|
||||
* vertically.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.horizontalLayout_ = flyout.horizontalLayout;
|
||||
};
|
||||
Blockly.utils.object.inherits(Blockly.FlyoutDragger, Blockly.WorkspaceDragger);
|
||||
|
||||
/**
|
||||
* Move the flyout based on the most recent mouse movements.
|
||||
* @param {!Blockly.utils.Coordinate} currentDragDeltaXY How far the pointer has
|
||||
* moved from the position at the start of the drag, in pixel coordinates.
|
||||
* @package
|
||||
*/
|
||||
Blockly.FlyoutDragger.prototype.drag = function(currentDragDeltaXY) {
|
||||
// startScrollXY_ is assigned by the superclass.
|
||||
var newXY = Blockly.utils.Coordinate.sum(this.startScrollXY_,
|
||||
currentDragDeltaXY);
|
||||
|
||||
// We can't call workspace.scroll because the flyout's workspace doesn't own
|
||||
// it's own scrollbars. This is because (as of 2.20190722.1) the
|
||||
// workspace's scrollbar property must be a scrollbar pair, rather than a
|
||||
// single scrollbar.
|
||||
// Instead we'll just expect setting the scrollbar to update the scroll of
|
||||
// the workspace as well.
|
||||
if (this.horizontalLayout_) {
|
||||
this.scrollbar_.set(-newXY.x);
|
||||
} else {
|
||||
this.scrollbar_.set(-newXY.y);
|
||||
}
|
||||
};
|
||||
@@ -247,7 +247,7 @@ Blockly.HorizontalFlyout.prototype.setBackgroundPath_ = function(width,
|
||||
* Scroll the flyout to the top.
|
||||
*/
|
||||
Blockly.HorizontalFlyout.prototype.scrollToStart = function() {
|
||||
this.scrollbar.set(this.RTL ? Infinity : 0);
|
||||
this.workspace_.scrollbar.setX(this.RTL ? Infinity : 0);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -265,7 +265,7 @@ Blockly.HorizontalFlyout.prototype.wheel_ = function(e) {
|
||||
var limit = metrics.contentWidth - metrics.viewWidth;
|
||||
pos = Math.min(pos, limit);
|
||||
pos = Math.max(pos, 0);
|
||||
this.scrollbar.set(pos);
|
||||
this.workspace_.scrollbar.setX(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
|
||||
@@ -241,7 +241,7 @@ Blockly.VerticalFlyout.prototype.setBackgroundPath_ = function(width, height) {
|
||||
* Scroll the flyout to the top.
|
||||
*/
|
||||
Blockly.VerticalFlyout.prototype.scrollToStart = function() {
|
||||
this.scrollbar.set(0);
|
||||
this.workspace_.scrollbar.setY(0);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -258,7 +258,7 @@ Blockly.VerticalFlyout.prototype.wheel_ = function(e) {
|
||||
var limit = metrics.contentHeight - metrics.viewHeight;
|
||||
pos = Math.min(pos, limit);
|
||||
pos = Math.max(pos, 0);
|
||||
this.scrollbar.set(pos);
|
||||
this.workspace_.scrollbar.setY(pos);
|
||||
// When the flyout moves from a wheel event, hide WidgetDiv and DropDownDiv.
|
||||
Blockly.WidgetDiv.hide();
|
||||
Blockly.DropDownDiv.hideWithoutAnimation();
|
||||
|
||||
@@ -20,7 +20,6 @@ goog.require('Blockly.BubbleDragger');
|
||||
goog.require('Blockly.constants');
|
||||
goog.require('Blockly.Events');
|
||||
goog.require('Blockly.Events.Click');
|
||||
goog.require('Blockly.FlyoutDragger');
|
||||
goog.require('Blockly.Tooltip');
|
||||
goog.require('Blockly.Touch');
|
||||
goog.require('Blockly.utils');
|
||||
@@ -383,7 +382,7 @@ Blockly.Gesture.prototype.updateIsDraggingBlock_ = function() {
|
||||
* This function should be called on a mouse/touch move event the first time the
|
||||
* drag radius is exceeded. It should be called no more than once per gesture.
|
||||
* If a workspace is being dragged this function creates the necessary
|
||||
* WorkspaceDragger or FlyoutDragger and starts the drag.
|
||||
* WorkspaceDragger and starts the drag.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
@@ -395,12 +394,8 @@ Blockly.Gesture.prototype.updateIsDraggingWorkspace_ = function() {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.flyout_) {
|
||||
this.workspaceDragger_ = new Blockly.FlyoutDragger(this.flyout_);
|
||||
} else {
|
||||
this.workspaceDragger_ = new Blockly.WorkspaceDragger(
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
|
||||
}
|
||||
this.workspaceDragger_ = new Blockly.WorkspaceDragger(
|
||||
/** @type {!Blockly.WorkspaceSvg} */ (this.startWorkspace_));
|
||||
|
||||
this.isDraggingWorkspace_ = true;
|
||||
this.workspaceDragger_.startDrag();
|
||||
|
||||
@@ -380,7 +380,9 @@ Blockly.init_ = function(mainWorkspace) {
|
||||
}
|
||||
|
||||
if (options.moveOptions && options.moveOptions.scrollbars) {
|
||||
mainWorkspace.scrollbar = new Blockly.ScrollbarPair(mainWorkspace);
|
||||
mainWorkspace.scrollbar =
|
||||
new Blockly.ScrollbarPair(
|
||||
mainWorkspace, true, true, 'blocklyMainWorkspaceScrollbar');
|
||||
mainWorkspace.scrollbar.resize();
|
||||
} else {
|
||||
mainWorkspace.setMetrics({x: 0.5, y: 0.5});
|
||||
|
||||
@@ -29,23 +29,41 @@ goog.require('Blockly.utils.Svg');
|
||||
/**
|
||||
* Class for a pair of scrollbars. Horizontal and vertical.
|
||||
* @param {!Blockly.WorkspaceSvg} workspace Workspace to bind the scrollbars to.
|
||||
* @param {boolean=} addHorizontal Whether to add a horizontal scrollbar.
|
||||
* Defaults to true.
|
||||
* @param {boolean=} addVertical Whether to add a vertical scrollbar. Defaults
|
||||
* to true.
|
||||
* @param {string=} opt_class A class to be applied to these scrollbars.
|
||||
* @constructor
|
||||
*/
|
||||
Blockly.ScrollbarPair = function(workspace) {
|
||||
Blockly.ScrollbarPair = function(
|
||||
workspace, addHorizontal, addVertical, opt_class) {
|
||||
this.workspace_ = workspace;
|
||||
this.hScroll = new Blockly.Scrollbar(
|
||||
workspace, true, true, 'blocklyMainWorkspaceScrollbar');
|
||||
this.vScroll = new Blockly.Scrollbar(
|
||||
workspace, false, true, 'blocklyMainWorkspaceScrollbar');
|
||||
this.corner_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
'height': Blockly.Scrollbar.scrollbarThickness,
|
||||
'width': Blockly.Scrollbar.scrollbarThickness,
|
||||
'class': 'blocklyScrollbarBackground'
|
||||
},
|
||||
null);
|
||||
Blockly.utils.dom.insertAfter(this.corner_, workspace.getBubbleCanvas());
|
||||
|
||||
addHorizontal = addHorizontal === undefined ? true : addHorizontal;
|
||||
addVertical = addVertical === undefined ? true : addVertical;
|
||||
var isPair = addHorizontal && addVertical;
|
||||
|
||||
if (addHorizontal) {
|
||||
this.hScroll = new Blockly.Scrollbar(
|
||||
workspace, true, isPair, opt_class);
|
||||
}
|
||||
if (addVertical ) {
|
||||
this.vScroll = new Blockly.Scrollbar(
|
||||
workspace, false, isPair, opt_class);
|
||||
}
|
||||
|
||||
if (isPair) {
|
||||
this.corner_ = Blockly.utils.dom.createSvgElement(
|
||||
Blockly.utils.Svg.RECT,
|
||||
{
|
||||
'height': Blockly.Scrollbar.scrollbarThickness,
|
||||
'width': Blockly.Scrollbar.scrollbarThickness,
|
||||
'class': 'blocklyScrollbarBackground'
|
||||
},
|
||||
null);
|
||||
Blockly.utils.dom.insertAfter(this.corner_, workspace.getBubbleCanvas());
|
||||
}
|
||||
|
||||
/**
|
||||
* Previously recorded metrics from the workspace.
|
||||
@@ -64,10 +82,14 @@ Blockly.ScrollbarPair.prototype.dispose = function() {
|
||||
this.corner_ = null;
|
||||
this.workspace_ = null;
|
||||
this.oldHostMetrics_ = null;
|
||||
this.hScroll.dispose();
|
||||
this.hScroll = null;
|
||||
this.vScroll.dispose();
|
||||
this.vScroll = null;
|
||||
if (this.hScroll) {
|
||||
this.hScroll.dispose();
|
||||
this.hScroll = null;
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.dispose();
|
||||
this.vScroll = null;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -108,13 +130,14 @@ Blockly.ScrollbarPair.prototype.resize = function() {
|
||||
resizeV = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (resizeH || resizeV) {
|
||||
try {
|
||||
Blockly.Events.disable();
|
||||
if (resizeH) {
|
||||
if (this.hScroll && resizeH) {
|
||||
this.hScroll.resize(hostMetrics);
|
||||
}
|
||||
if (resizeV) {
|
||||
if (this.vScroll && resizeV) {
|
||||
this.vScroll.resize(hostMetrics);
|
||||
}
|
||||
} finally {
|
||||
@@ -123,64 +146,173 @@ Blockly.ScrollbarPair.prototype.resize = function() {
|
||||
this.workspace_.maybeFireViewportChangeEvent();
|
||||
}
|
||||
|
||||
// Reposition the corner square.
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth ||
|
||||
this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) {
|
||||
this.corner_.setAttribute('x', this.vScroll.position.x);
|
||||
}
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight ||
|
||||
this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop) {
|
||||
this.corner_.setAttribute('y', this.hScroll.position.y);
|
||||
if (this.hScroll && this.vScroll) {
|
||||
// Reposition the corner square.
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.viewWidth != hostMetrics.viewWidth ||
|
||||
this.oldHostMetrics_.absoluteLeft != hostMetrics.absoluteLeft) {
|
||||
this.corner_.setAttribute('x', this.vScroll.position.x);
|
||||
}
|
||||
if (!this.oldHostMetrics_ ||
|
||||
this.oldHostMetrics_.viewHeight != hostMetrics.viewHeight ||
|
||||
this.oldHostMetrics_.absoluteTop != hostMetrics.absoluteTop) {
|
||||
this.corner_.setAttribute('y', this.hScroll.position.y);
|
||||
}
|
||||
}
|
||||
|
||||
// Cache the current metrics to potentially short-cut the next resize event.
|
||||
this.oldHostMetrics_ = hostMetrics;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns whether scrolling horizontally is enabled.
|
||||
* @return {boolean} True if horizontal scroll is enabled.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.canScrollHorizontally = function() {
|
||||
return !!this.hScroll;
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns whether scrolling vertically is enabled.
|
||||
* @return {boolean} True if vertical scroll is enabled.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.canScrollVertically = function() {
|
||||
return !!this.vScroll;
|
||||
};
|
||||
|
||||
/**
|
||||
* Record the origin of the workspace that the scrollbar is in, in pixels
|
||||
* relative to the injection div origin. This is for times when the scrollbar is
|
||||
* used in an object whose origin isn't the same as the main workspace
|
||||
* (e.g. in a flyout.)
|
||||
* @param {number} x The x coordinate of the scrollbar's origin, in CSS pixels.
|
||||
* @param {number} y The y coordinate of the scrollbar's origin, in CSS pixels.
|
||||
* @package
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.setOrigin = function(x, y) {
|
||||
if (this.hScroll) {
|
||||
this.hScroll.setOrigin(x, y);
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.setOrigin(x, y);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the handles of both scrollbars to be at a certain position in CSS pixels
|
||||
* relative to their parents.
|
||||
* @param {number} x Horizontal scroll value.
|
||||
* @param {number} y Vertical scroll value.
|
||||
* @param {boolean} updateMetrics Whether to update metrics on this set call.
|
||||
* Defaults to true.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.set = function(x, y) {
|
||||
Blockly.ScrollbarPair.prototype.set = function(x, y, updateMetrics) {
|
||||
// This function is equivalent to:
|
||||
// this.hScroll.set(x);
|
||||
// this.vScroll.set(y);
|
||||
// However, that calls setMetrics twice which causes a chain of
|
||||
// getAttribute->setAttribute->getAttribute resulting in an extra layout pass.
|
||||
// Combining them speeds up rendering.
|
||||
var xyRatio = {};
|
||||
if (this.hScroll) {
|
||||
this.hScroll.set(x, false);
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.set(y, false);
|
||||
}
|
||||
|
||||
var hHandlePosition = x * this.hScroll.ratio;
|
||||
var vHandlePosition = y * this.vScroll.ratio;
|
||||
|
||||
var hBarLength = this.hScroll.scrollViewSize_;
|
||||
var vBarLength = this.vScroll.scrollViewSize_;
|
||||
|
||||
xyRatio.x = this.getRatio_(hHandlePosition, hBarLength);
|
||||
xyRatio.y = this.getRatio_(vHandlePosition, vBarLength);
|
||||
this.workspace_.setMetrics(xyRatio);
|
||||
|
||||
this.hScroll.setHandlePosition(hHandlePosition);
|
||||
this.vScroll.setHandlePosition(vHandlePosition);
|
||||
if (updateMetrics || updateMetrics === undefined) {
|
||||
// Update metrics.
|
||||
var xyRatio = {};
|
||||
if (this.hScroll) {
|
||||
xyRatio.x = this.hScroll.getRatio_();
|
||||
}
|
||||
if (this.vScroll) {
|
||||
xyRatio.y = this.vScroll.getRatio_();
|
||||
}
|
||||
this.workspace_.setMetrics(xyRatio);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper to calculate the ratio of handle position to scrollbar view size.
|
||||
* @param {number} handlePosition The value of the handle.
|
||||
* @param {number} viewSize The total size of the scrollbar's view.
|
||||
* @return {number} Ratio.
|
||||
* @private
|
||||
* Set the handle of the horizontal scrollbar to be at a certain position in
|
||||
* CSS pixels relative to its parents.
|
||||
* @param {number} x Horizontal scroll value.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.getRatio_ = function(handlePosition, viewSize) {
|
||||
var ratio = handlePosition / viewSize;
|
||||
if (isNaN(ratio)) {
|
||||
return 0;
|
||||
Blockly.ScrollbarPair.prototype.setX = function(x) {
|
||||
if (this.hScroll) {
|
||||
this.hScroll.set(x, true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the handle of the vertical scrollbar to be at a certain position in
|
||||
* CSS pixels relative to its parents.
|
||||
* @param {number} y Vertical scroll value.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.setY = function(y) {
|
||||
if (this.vScroll) {
|
||||
this.vScroll.set(y, true);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this scrollbar's container is visible.
|
||||
* @param {boolean} visible Whether the container is visible.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.setContainerVisible = function(visible) {
|
||||
if (this.hScroll) {
|
||||
this.hScroll.setContainerVisible(visible);
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.setContainerVisible(visible);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If any of the scrollbars are visible. Non-paired scrollbars may disappear
|
||||
* when they aren't needed.
|
||||
* @return {boolean} True if visible.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.isVisible = function() {
|
||||
var isVisible = false;
|
||||
if (this.hScroll) {
|
||||
isVisible = this.hScroll.isVisible();
|
||||
}
|
||||
if (this.vScroll) {
|
||||
isVisible = isVisible || this.vScroll.isVisible();
|
||||
}
|
||||
return isVisible;
|
||||
};
|
||||
|
||||
/**
|
||||
* Recalculates the scrollbars' locations within their path and length.
|
||||
* This should be called when the contents of the workspace have changed.
|
||||
* @param {!Blockly.utils.Metrics} hostMetrics A data structure describing all
|
||||
* the required dimensions, possibly fetched from the host object.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.resizeContent = function(hostMetrics) {
|
||||
if (this.hScroll) {
|
||||
this.hScroll.resizeContentHorizontal(hostMetrics);
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.resizeContentVertical(hostMetrics);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Recalculates the scrollbars' locations on the screen and path length.
|
||||
* This should be called when the layout or size of the window has changed.
|
||||
* @param {!Blockly.utils.Metrics} hostMetrics A data structure describing all
|
||||
* the required dimensions, possibly fetched from the host object.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.resizeView = function(hostMetrics) {
|
||||
if (this.hScroll) {
|
||||
this.hScroll.resizeViewHorizontal(hostMetrics);
|
||||
}
|
||||
if (this.vScroll) {
|
||||
this.vScroll.resizeViewVertical(hostMetrics);
|
||||
}
|
||||
return ratio;
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
@@ -394,15 +526,6 @@ Blockly.Scrollbar.prototype.setScrollViewSize_ = function(newSize) {
|
||||
this.svgBackground_.setAttribute(this.lengthAttribute_, this.scrollViewSize_);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set whether this scrollbar's container is visible.
|
||||
* @param {boolean} visible Whether the container is visible.
|
||||
*/
|
||||
Blockly.ScrollbarPair.prototype.setContainerVisible = function(visible) {
|
||||
this.hScroll.setContainerVisible(visible);
|
||||
this.vScroll.setContainerVisible(visible);
|
||||
};
|
||||
|
||||
/**
|
||||
* Set the position of the scrollbar's SVG group in CSS pixels relative to the
|
||||
* scrollbar's origin. This sets the scrollbar's location within the workspace.
|
||||
@@ -461,7 +584,7 @@ Blockly.Scrollbar.prototype.resize = function(opt_metrics) {
|
||||
this.resizeVertical_(hostMetrics);
|
||||
}
|
||||
// Resizing may have caused some scrolling.
|
||||
this.onScroll_();
|
||||
this.updateMetrics_();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -742,7 +865,7 @@ Blockly.Scrollbar.prototype.onMouseDownBar_ = function(e) {
|
||||
|
||||
this.setHandlePosition(this.constrainHandle_(handlePosition));
|
||||
|
||||
this.onScroll_();
|
||||
this.updateMetrics_();
|
||||
e.stopPropagation();
|
||||
e.preventDefault();
|
||||
};
|
||||
@@ -791,7 +914,7 @@ Blockly.Scrollbar.prototype.onMouseMoveHandle_ = function(e) {
|
||||
var handlePosition = this.startDragHandle + mouseDelta;
|
||||
// Position the bar.
|
||||
this.setHandlePosition(this.constrainHandle_(handlePosition));
|
||||
this.onScroll_();
|
||||
this.updateMetrics_();
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -839,14 +962,25 @@ Blockly.Scrollbar.prototype.constrainHandle_ = function(value) {
|
||||
};
|
||||
|
||||
/**
|
||||
* Called when scrollbar is moved.
|
||||
* @private
|
||||
* Helper to calculate the ratio of handle position to scrollbar view size.
|
||||
* @return {number} Ratio.
|
||||
* @protected
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.onScroll_ = function() {
|
||||
Blockly.Scrollbar.prototype.getRatio_ = function() {
|
||||
var ratio = this.handlePosition_ / this.scrollViewSize_;
|
||||
if (isNaN(ratio)) {
|
||||
ratio = 0;
|
||||
return 0;
|
||||
}
|
||||
return ratio;
|
||||
};
|
||||
|
||||
/**
|
||||
* Updates workspace metrics based on new scroll ratio. Called when scrollbar is
|
||||
* moved.
|
||||
* @private
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.updateMetrics_ = function() {
|
||||
var ratio = this.getRatio_();
|
||||
var xyRatio = {};
|
||||
if (this.horizontal_) {
|
||||
xyRatio.x = ratio;
|
||||
@@ -859,12 +993,16 @@ Blockly.Scrollbar.prototype.onScroll_ = function() {
|
||||
/**
|
||||
* Set the scrollbar handle's position.
|
||||
* @param {number} value The distance from the top/left end of the bar, in CSS
|
||||
* pixels. It may be larger than the maximum allowable position of the
|
||||
* scrollbar handle.
|
||||
* pixels. It may be larger than the maximum allowable position of the
|
||||
* scrollbar handle.
|
||||
* @param {boolean=} updateMetrics Whether to update metrics on this set call.
|
||||
* Defaults to true.
|
||||
*/
|
||||
Blockly.Scrollbar.prototype.set = function(value) {
|
||||
Blockly.Scrollbar.prototype.set = function(value, updateMetrics) {
|
||||
this.setHandlePosition(this.constrainHandle_(value * this.ratio));
|
||||
this.onScroll_();
|
||||
if (updateMetrics || updateMetrics === undefined) {
|
||||
this.updateMetrics_();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,6 +31,21 @@ Blockly.WorkspaceDragger = function(workspace) {
|
||||
*/
|
||||
this.workspace_ = workspace;
|
||||
|
||||
/**
|
||||
* Whether horizontal scroll is enabled.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.horizontalScrollEnabled_ =
|
||||
this.workspace_.scrollbar.canScrollHorizontally();
|
||||
|
||||
/**
|
||||
* Whether vertical scroll is enabled.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.verticalScrollEnabled_ = this.workspace_.scrollbar.canScrollVertically();
|
||||
|
||||
/**
|
||||
* The scroll position of the workspace at the beginning of the drag.
|
||||
* Coordinate system: pixel coordinates.
|
||||
@@ -81,5 +96,14 @@ Blockly.WorkspaceDragger.prototype.endDrag = function(currentDragDeltaXY) {
|
||||
*/
|
||||
Blockly.WorkspaceDragger.prototype.drag = function(currentDragDeltaXY) {
|
||||
var newXY = Blockly.utils.Coordinate.sum(this.startScrollXY_, currentDragDeltaXY);
|
||||
this.workspace_.scroll(newXY.x, newXY.y);
|
||||
|
||||
if (this.horizontalScrollEnabled_ && this.verticalScrollEnabled_) {
|
||||
this.workspace_.scroll(newXY.x, newXY.y);
|
||||
} else if (this.horizontalScrollEnabled_) {
|
||||
this.workspace_.scroll(newXY.x, this.workspace_.scrollY);
|
||||
} else if (this.verticalScrollEnabled_) {
|
||||
this.workspace_.scroll(this.workspace_.scrollX, newXY.y);
|
||||
} else {
|
||||
throw new TypeError('Invalid state.');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2089,11 +2089,9 @@ Blockly.WorkspaceSvg.prototype.setScale = function(newScale) {
|
||||
this.scroll(this.scrollX, this.scrollY);
|
||||
if (this.scrollbar) {
|
||||
if (this.flyout_) {
|
||||
this.scrollbar.hScroll.resizeViewHorizontal(metrics);
|
||||
this.scrollbar.vScroll.resizeViewVertical(metrics);
|
||||
this.scrollbar.resizeView(metrics);
|
||||
} else {
|
||||
this.scrollbar.hScroll.resizeContentHorizontal(metrics);
|
||||
this.scrollbar.vScroll.resizeContentVertical(metrics);
|
||||
this.scrollbar.resizeContent(metrics);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -2147,11 +2145,8 @@ Blockly.WorkspaceSvg.prototype.scroll = function(x, y) {
|
||||
// content's top-left. Then we negate this so we get the displacement from
|
||||
// the content's top-left to the view's top-left, matching the
|
||||
// directionality of the scrollbars.
|
||||
|
||||
this.scrollbar.hScroll.setHandlePosition(-(x + metrics.contentLeft) *
|
||||
this.scrollbar.hScroll.ratio);
|
||||
this.scrollbar.vScroll.setHandlePosition(-(y + metrics.contentTop) *
|
||||
this.scrollbar.vScroll.ratio);
|
||||
this.scrollbar.set(
|
||||
-(x + metrics.contentLeft), -(y + metrics.contentTop), false);
|
||||
}
|
||||
// We have to shift the translation so that when the canvas is at 0, 0 the
|
||||
// workspace origin is not underneath the toolbox.
|
||||
|
||||
Reference in New Issue
Block a user