Files
blockly/core/bump_objects.js
Rachel Fenichel f4430e9e47 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 <cpcallen+github@gmail.com>

Co-authored-by: Christopher Allen <cpcallen+github@gmail.com>
2021-09-14 10:02:38 -07:00

74 lines
2.6 KiB
JavaScript

/**
* @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;