From f4430e9e4745e3b62c4e53a685651de7bbc4f675 Mon Sep 17 00:00:00 2001 From: Rachel Fenichel Date: Tue, 14 Sep 2021 10:02:38 -0700 Subject: [PATCH] Move bump objects function into a separate module (#5453) * Move bump objects function into a separate module * Fix types * Update core/bump_objects.js Fix missing newline. Co-authored-by: Christopher Allen Co-authored-by: Christopher Allen --- core/block_dragger.js | 3 +- core/bump_objects.js | 73 +++++++++++++++++++++++++++++++++++++++++++ core/inject.js | 62 ++++-------------------------------- tests/deps.js | 5 +-- 4 files changed, 84 insertions(+), 59 deletions(-) create mode 100644 core/bump_objects.js diff --git a/core/block_dragger.js b/core/block_dragger.js index 32a6f4922..5c523cb55 100644 --- a/core/block_dragger.js +++ b/core/block_dragger.js @@ -24,6 +24,7 @@ const InsertionMarkerManager = goog.require('Blockly.InsertionMarkerManager'); /* eslint-disable-next-line no-unused-vars */ const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); const blockAnimation = goog.require('Blockly.blockAnimations'); +const bumpObjects = goog.require('Blockly.bumpObjects'); const common = goog.require('Blockly.common'); const dom = goog.require('Blockly.utils.dom'); const events = goog.require('Blockly.Events'); @@ -293,7 +294,7 @@ BlockDragger.prototype.endDrag = function(e, currentDragDeltaXY) { } else { // Blocks dragged directly from a flyout may need to be bumped into // bounds. - Blockly.bumpObjectIntoBounds_( + bumpObjects.bumpIntoBounds( this.draggingBlock_.workspace, this.workspace_.getMetricsManager().getScrollMetrics(true), this.draggingBlock_); diff --git a/core/bump_objects.js b/core/bump_objects.js new file mode 100644 index 000000000..efac96bf4 --- /dev/null +++ b/core/bump_objects.js @@ -0,0 +1,73 @@ +/** + * @license + * Copyright 2021 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * @fileoverview Utilities for bumping objects back into worksapce bounds. + * @author fenichel@google.com (Rachel Fenichel) + */ +'use strict'; + +goog.module('Blockly.bumpObjects'); + +/* eslint-disable-next-line no-unused-vars */ +const IBoundedElement = goog.requireType('Blockly.IBoundedElement'); +/* eslint-disable-next-line no-unused-vars */ +const MetricsManager = goog.requireType('Blockly.MetricsManager'); +/* eslint-disable-next-line no-unused-vars */ +const WorkspaceSvg = goog.requireType('Blockly.WorkspaceSvg'); +const mathUtils = goog.require('Blockly.utils.math'); + + +/** + * Bumps the given object that has passed out of bounds. + * @param {!WorkspaceSvg} workspace The workspace containing the object. + * @param {!MetricsManager.ContainerRegion} scrollMetrics Scroll metrics + * in workspace coordinates. + * @param {!IBoundedElement} object The object to bump. + * @return {boolean} True if block was bumped. + */ +const bumpObjectIntoBounds = function(workspace, scrollMetrics, object) { + // Compute new top/left position for object. + const objectMetrics = object.getBoundingRectangle(); + const height = objectMetrics.bottom - objectMetrics.top; + const width = objectMetrics.right - objectMetrics.left; + + const topClamp = scrollMetrics.top; + const scrollMetricsBottom = scrollMetrics.top + scrollMetrics.height; + const bottomClamp = scrollMetricsBottom - height; + // If the object is taller than the workspace we want to + // top-align the block + const newYPosition = + mathUtils.clamp(topClamp, objectMetrics.top, bottomClamp); + const deltaY = newYPosition - objectMetrics.top; + + // Note: Even in RTL mode the "anchor" of the object is the + // top-left corner of the object. + let leftClamp = scrollMetrics.left; + const scrollMetricsRight = scrollMetrics.left + scrollMetrics.width; + let rightClamp = scrollMetricsRight - width; + if (workspace.RTL) { + // If the object is wider than the workspace and we're in RTL + // mode we want to right-align the block, which means setting + // the left clamp to match. + leftClamp = Math.min(rightClamp, leftClamp); + } else { + // If the object is wider than the workspace and we're in LTR + // mode we want to left-align the block, which means setting + // the right clamp to match. + rightClamp = Math.max(leftClamp, rightClamp); + } + const newXPosition = + mathUtils.clamp(leftClamp, objectMetrics.left, rightClamp); + const deltaX = newXPosition - objectMetrics.left; + + if (deltaX || deltaY) { + object.moveBy(deltaX, deltaY); + return true; + } + return false; +}; +exports.bumpIntoBounds = bumpObjectIntoBounds; diff --git a/core/inject.js b/core/inject.js index c2446e602..663c015be 100644 --- a/core/inject.js +++ b/core/inject.js @@ -14,6 +14,7 @@ goog.provide('Blockly.inject'); goog.require('Blockly.BlockDragSurfaceSvg'); goog.require('Blockly.browserEvents'); +goog.require('Blockly.bumpObjects'); goog.require('Blockly.common'); goog.require('Blockly.Css'); goog.require('Blockly.DropDownDiv'); @@ -27,7 +28,6 @@ goog.require('Blockly.Tooltip'); goog.require('Blockly.utils'); goog.require('Blockly.utils.aria'); goog.require('Blockly.utils.dom'); -goog.require('Blockly.utils.math'); goog.require('Blockly.utils.Svg'); goog.require('Blockly.utils.userAgent'); goog.require('Blockly.Workspace'); @@ -239,7 +239,7 @@ Blockly.bumpTopObjectsIntoBounds_ = function(workspace) { var scrollMetricsInWsCoords = metricsManager.getScrollMetrics(true); var topBlocks = workspace.getTopBoundedElements(); for (var i = 0, block; (block = topBlocks[i]); i++) { - Blockly.bumpObjectIntoBounds_(workspace, scrollMetricsInWsCoords, block); + goog.module.get('Blockly.bumpObjects').bumpIntoBounds(workspace, scrollMetricsInWsCoords, block); } }; @@ -268,9 +268,10 @@ Blockly.bumpIntoBoundsHandler_ = function(workspace) { var oldGroup = Blockly.Events.getGroup(); Blockly.Events.setGroup(e.group); - var wasBumped = Blockly.bumpObjectIntoBounds_( - workspace, scrollMetricsInWsCoords, - /** @type {!Blockly.IBoundedElement} */ (object)); + var wasBumped = goog.module.get('Blockly.bumpObjects') + .bumpIntoBounds( + workspace, scrollMetricsInWsCoords, + /** @type {!Blockly.IBoundedElement} */ (object)); if (wasBumped && !e.group) { console.warn('Moved object in bounds but there was no' + @@ -288,57 +289,6 @@ Blockly.bumpIntoBoundsHandler_ = function(workspace) { }; }; -/** - * Bumps the given object that has passed out of bounds. - * @param {!Blockly.WorkspaceSvg} workspace The workspace containing the object. - * @param {!Blockly.MetricsManager.ContainerRegion} scrollMetrics Scroll metrics - * in workspace coordinates. - * @param {!Blockly.IBoundedElement} object The object to bump. - * @return {boolean} True if block was bumped. - * @package - */ -Blockly.bumpObjectIntoBounds_ = function(workspace, scrollMetrics, object) { - // Compute new top/left position for object. - var objectMetrics = object.getBoundingRectangle(); - var height = objectMetrics.bottom - objectMetrics.top; - var width = objectMetrics.right - objectMetrics.left; - - var topClamp = scrollMetrics.top; - var scrollMetricsBottom = scrollMetrics.top + scrollMetrics.height; - var bottomClamp = scrollMetricsBottom - height; - // If the object is taller than the workspace we want to - // top-align the block - var newYPosition = - Blockly.utils.math.clamp(topClamp, objectMetrics.top, bottomClamp); - var deltaY = newYPosition - objectMetrics.top; - - // Note: Even in RTL mode the "anchor" of the object is the - // top-left corner of the object. - var leftClamp = scrollMetrics.left; - var scrollMetricsRight = scrollMetrics.left + scrollMetrics.width; - var rightClamp = scrollMetricsRight - width; - if (workspace.RTL) { - // If the object is wider than the workspace and we're in RTL - // mode we want to right-align the block, which means setting - // the left clamp to match. - leftClamp = Math.min(rightClamp, leftClamp); - } else { - // If the object is wider than the workspace and we're in LTR - // mode we want to left-align the block, which means setting - // the right clamp to match. - rightClamp = Math.max(leftClamp, rightClamp); - } - var newXPosition = - Blockly.utils.math.clamp(leftClamp, objectMetrics.left, rightClamp); - var deltaX = newXPosition - objectMetrics.left; - - if (deltaX || deltaY) { - object.moveBy(deltaX, deltaY); - return true; - } - return false; -}; - /** * Initialize Blockly with various handlers. * @param {!Blockly.WorkspaceSvg} mainWorkspace Newly created main workspace. diff --git a/tests/deps.js b/tests/deps.js index 864ddfb32..75844ca38 100644 --- a/tests/deps.js +++ b/tests/deps.js @@ -10,7 +10,7 @@ goog.addDependency('../../blocks/variables_dynamic.js', ['Blockly.Constants.Vari goog.addDependency('../../core/block.js', ['Blockly.Block'], ['Blockly.ASTNode', 'Blockly.Blocks', 'Blockly.Connection', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BlockCreate', 'Blockly.Events.BlockDelete', 'Blockly.Events.BlockMove', 'Blockly.Extensions', 'Blockly.Input', 'Blockly.Tooltip', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.idGenerator', 'Blockly.utils.object'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/block_animations.js', ['Blockly.blockAnimations'], ['Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/block_drag_surface.js', ['Blockly.BlockDragSurfaceSvg'], ['Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/block_dragger.js', ['Blockly.BlockDragger'], ['Blockly.Events', 'Blockly.Events.BlockDrag', 'Blockly.Events.BlockMove', 'Blockly.InsertionMarkerManager', 'Blockly.blockAnimations', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.registry', 'Blockly.utils.Coordinate', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/block_svg.js', ['Blockly.BlockSvg'], ['Blockly.ASTNode', 'Blockly.Block', 'Blockly.ContextMenu', 'Blockly.ContextMenuRegistry', 'Blockly.Events', 'Blockly.Events.BlockMove', 'Blockly.Events.Selected', 'Blockly.FieldLabel', 'Blockly.MarkerManager', 'Blockly.Msg', 'Blockly.RenderedConnection', 'Blockly.TabNavigateCursor', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Xml', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Rect', 'Blockly.utils.Svg', 'Blockly.utils.deprecation', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/blockly.js', ['Blockly'], ['Blockly.ComponentManager', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Events.BlockCreate', 'Blockly.Events.FinishedLoading', 'Blockly.Events.Ui', 'Blockly.Events.UiBase', 'Blockly.Events.VarCreate', 'Blockly.Procedures', 'Blockly.ShortcutRegistry', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Variables', 'Blockly.WidgetDiv', 'Blockly.WorkspaceSvg', 'Blockly.Xml', 'Blockly.browserEvents', 'Blockly.clipboard', 'Blockly.common', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.dialog', 'Blockly.inject', 'Blockly.inputTypes', 'Blockly.internalConstants', 'Blockly.utils', 'Blockly.utils.Size', 'Blockly.utils.colour', 'Blockly.utils.deprecation', 'Blockly.utils.toolbox']); goog.addDependency('../../core/blockly_options.js', ['Blockly.BlocklyOptions'], [], {'lang': 'es6', 'module': 'goog'}); @@ -18,6 +18,7 @@ goog.addDependency('../../core/blocks.js', ['Blockly.Blocks'], [], {'lang': 'es6 goog.addDependency('../../core/browser_events.js', ['Blockly.browserEvents'], ['Blockly.Touch', 'Blockly.utils.global'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/bubble.js', ['Blockly.Bubble'], ['Blockly.Scrollbar', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/bubble_dragger.js', ['Blockly.BubbleDragger'], ['Blockly.Bubble', 'Blockly.ComponentManager', 'Blockly.Events', 'Blockly.Events.CommentMove', 'Blockly.constants', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); +goog.addDependency('../../core/bump_objects.js', ['Blockly.bumpObjects'], ['Blockly.utils.math'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/clipboard.js', ['Blockly.clipboard'], ['Blockly.Events'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/comment.js', ['Blockly.Comment'], ['Blockly.Bubble', 'Blockly.Css', 'Blockly.Events', 'Blockly.Events.BlockChange', 'Blockly.Events.BubbleOpen', 'Blockly.Icon', 'Blockly.Warning', 'Blockly.browserEvents', 'Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.object', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/common.js', ['Blockly.common'], [], {'lang': 'es6', 'module': 'goog'}); @@ -86,7 +87,7 @@ goog.addDependency('../../core/generator.js', ['Blockly.Generator'], ['Blockly.c goog.addDependency('../../core/gesture.js', ['Blockly.Gesture'], ['Blockly.BlockDragger', 'Blockly.BubbleDragger', 'Blockly.Events', 'Blockly.Events.Click', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.Workspace', 'Blockly.WorkspaceDragger', 'Blockly.blockAnimations', 'Blockly.browserEvents', 'Blockly.internalConstants', 'Blockly.registry', 'Blockly.utils', 'Blockly.utils.Coordinate'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/grid.js', ['Blockly.Grid'], ['Blockly.utils.Svg', 'Blockly.utils.dom', 'Blockly.utils.userAgent'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/icon.js', ['Blockly.Icon'], ['Blockly.browserEvents', 'Blockly.utils', 'Blockly.utils.Coordinate', 'Blockly.utils.Size', 'Blockly.utils.Svg', 'Blockly.utils.dom'], {'lang': 'es6', 'module': 'goog'}); -goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.common', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.math', 'Blockly.utils.userAgent']); +goog.addDependency('../../core/inject.js', ['Blockly.inject'], ['Blockly.BlockDragSurfaceSvg', 'Blockly.Css', 'Blockly.DropDownDiv', 'Blockly.Events', 'Blockly.Grid', 'Blockly.Msg', 'Blockly.Options', 'Blockly.ScrollbarPair', 'Blockly.Tooltip', 'Blockly.Touch', 'Blockly.WidgetDiv', 'Blockly.Workspace', 'Blockly.WorkspaceDragSurfaceSvg', 'Blockly.WorkspaceSvg', 'Blockly.browserEvents', 'Blockly.bumpObjects', 'Blockly.common', 'Blockly.utils', 'Blockly.utils.Svg', 'Blockly.utils.aria', 'Blockly.utils.dom', 'Blockly.utils.userAgent']); goog.addDependency('../../core/input.js', ['Blockly.Input'], ['Blockly.FieldLabel', 'Blockly.constants', 'Blockly.fieldRegistry', 'Blockly.inputTypes'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/input_types.js', ['Blockly.inputTypes'], ['Blockly.connectionTypes'], {'lang': 'es6', 'module': 'goog'}); goog.addDependency('../../core/insertion_marker_manager.js', ['Blockly.InsertionMarkerManager'], ['Blockly.ComponentManager', 'Blockly.Events', 'Blockly.blockAnimations', 'Blockly.connectionTypes', 'Blockly.constants', 'Blockly.internalConstants'], {'lang': 'es6', 'module': 'goog'});