diff --git a/core/block_drag_surface.ts b/core/block_drag_surface.ts deleted file mode 100644 index c249458cb..000000000 --- a/core/block_drag_surface.ts +++ /dev/null @@ -1,247 +0,0 @@ -/** - * @license - * Copyright 2016 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * A class that manages a surface for dragging blocks. When a - * block drag is started, we move the block (and children) to a separate DOM - * element that we move around using translate3d. At the end of the drag, the - * blocks are put back in into the SVG they came from. This helps - * performance by avoiding repainting the entire SVG on every mouse move - * while dragging blocks. - * - * @class - */ -import * as goog from '../closure/goog/goog.js'; -goog.declareModuleId('Blockly.BlockDragSurfaceSvg'); - -import {Coordinate} from './utils/coordinate.js'; -import * as deprecation from './utils/deprecation.js'; -import * as dom from './utils/dom.js'; -import {Svg} from './utils/svg.js'; -import * as svgMath from './utils/svg_math.js'; - -/** - * Class for a drag surface for the currently dragged block. This is a separate - * SVG that contains only the currently moving block, or nothing. - * - * @alias Blockly.BlockDragSurfaceSvg - */ -export class BlockDragSurfaceSvg { - /** - * The root element of the drag surface. - */ - private svg: SVGElement; - - /** - * This is where blocks live while they are being dragged if the drag - * surface is enabled. - */ - private dragGroup: SVGElement; - - /** - * Cached value for the scale of the drag surface. - * Used to set/get the correct translation during and after a drag. - */ - private scale = 1; - - /** - * Cached value for the translation of the drag surface. - * This translation is in pixel units, because the scale is applied to the - * drag group rather than the top-level SVG. - */ - private surfaceXY = new Coordinate(0, 0); - - /** - * Cached value for the translation of the child drag surface in pixel - * units. Since the child drag surface tracks the translation of the - * workspace this is ultimately the translation of the workspace. - */ - private readonly childSurfaceXY = new Coordinate(0, 0); - - /** @param container Containing element. */ - constructor(private readonly container: Element) { - this.svg = dom.createSvgElement( - Svg.SVG, - { - 'xmlns': dom.SVG_NS, - 'xmlns:html': dom.HTML_NS, - 'xmlns:xlink': dom.XLINK_NS, - 'version': '1.1', - 'class': 'blocklyBlockDragSurface', - }, - this.container - ); - - this.dragGroup = dom.createSvgElement(Svg.G, {}, this.svg); - } - - /** - * Create the drag surface and inject it into the container. - * - * @deprecated The DOM is automatically created by the constructor. - */ - createDom() { - // No alternative provided, because now the dom is just automatically - // created in the constructor now. - deprecation.warn('BlockDragSurfaceSvg createDom', 'June 2022', 'June 2023'); - } - - /** - * Set the SVG blocks on the drag surface's group and show the surface. - * Only one block group should be on the drag surface at a time. - * - * @param blocks Block or group of blocks to place on the drag surface. - */ - setBlocksAndShow(blocks: SVGElement) { - if (this.dragGroup.childNodes.length) { - throw Error('Already dragging a block.'); - } - // appendChild removes the blocks from the previous parent - this.dragGroup.appendChild(blocks); - this.svg.style.display = 'block'; - this.surfaceXY = new Coordinate(0, 0); - } - - /** - * Translate and scale the entire drag surface group to the given position, to - * keep in sync with the workspace. - * - * @param x X translation in pixel coordinates. - * @param y Y translation in pixel coordinates. - * @param scale Scale of the group. - */ - translateAndScaleGroup(x: number, y: number, scale: number) { - this.scale = scale; - // Make sure the svg exists on a pixel boundary so that it is not fuzzy. - const roundX = Math.round(x); - const roundY = Math.round(y); - this.childSurfaceXY.x = roundX; - this.childSurfaceXY.y = roundY; - this.dragGroup.setAttribute( - 'transform', - 'translate(' + roundX + ',' + roundY + ') scale(' + scale + ')' - ); - } - - /** - * Translate the drag surface's SVG based on its internal state. - * - * @internal - */ - translateSurfaceInternal_() { - // Make sure the svg exists on a pixel boundary so that it is not fuzzy. - const x = Math.round(this.surfaceXY.x); - const y = Math.round(this.surfaceXY.y); - this.svg.style.display = 'block'; - dom.setCssTransform(this.svg, 'translate3d(' + x + 'px, ' + y + 'px, 0)'); - } - - /** - * Translates the entire surface by a relative offset. - * - * @param deltaX Horizontal offset in pixel units. - * @param deltaY Vertical offset in pixel units. - */ - translateBy(deltaX: number, deltaY: number) { - const x = this.surfaceXY.x + deltaX; - const y = this.surfaceXY.y + deltaY; - this.surfaceXY = new Coordinate(x, y); - this.translateSurfaceInternal_(); - } - - /** - * Translate the entire drag surface during a drag. - * We translate the drag surface instead of the blocks inside the surface - * so that the browser avoids repainting the SVG. - * Because of this, the drag coordinates must be adjusted by scale. - * - * @param x X translation for the entire surface. - * @param y Y translation for the entire surface. - */ - translateSurface(x: number, y: number) { - this.surfaceXY = new Coordinate(x * this.scale, y * this.scale); - this.translateSurfaceInternal_(); - } - - /** - * Reports the surface translation in scaled workspace coordinates. - * Use this when finishing a drag to return blocks to the correct position. - * - * @returns Current translation of the surface. - */ - getSurfaceTranslation(): Coordinate { - const xy = svgMath.getRelativeXY(this.svg); - return new Coordinate(xy.x / this.scale, xy.y / this.scale); - } - - /** - * Provide a reference to the drag group (primarily for - * BlockSvg.getRelativeToSurfaceXY). - * - * @returns Drag surface group element. - */ - getGroup(): SVGElement { - return this.dragGroup; - } - - /** - * Returns the SVG drag surface. - * - * @returns The SVG drag surface. - */ - getSvgRoot(): SVGElement { - return this.svg; - } - - /** - * Get the current blocks on the drag surface, if any (primarily - * for BlockSvg.getRelativeToSurfaceXY). - * - * @returns Drag surface block DOM element, or null if no blocks exist. - */ - getCurrentBlock(): Element | null { - return this.dragGroup.firstChild as Element; - } - - /** - * Gets the translation of the child block surface - * This surface is in charge of keeping track of how much the workspace has - * moved. - * - * @returns The amount the workspace has been moved. - */ - getWsTranslation(): Coordinate { - // Returning a copy so the coordinate can not be changed outside this class. - return this.childSurfaceXY.clone(); - } - - /** - * Clear the group and hide the surface; move the blocks off onto the provided - * element. - * If the block is being deleted it doesn't need to go back to the original - * surface, since it would be removed immediately during dispose. - * - * @param opt_newSurface Surface the dragging blocks should be moved to, or - * null if the blocks should be removed from this surface without being - * moved to a different surface. - */ - clearAndHide(opt_newSurface?: Element) { - const currentBlockElement = this.getCurrentBlock(); - if (currentBlockElement) { - if (opt_newSurface) { - // appendChild removes the node from this.dragGroup - opt_newSurface.appendChild(currentBlockElement); - } else { - this.dragGroup.removeChild(currentBlockElement); - } - } - this.svg.style.display = 'none'; - if (this.dragGroup.childNodes.length) { - throw Error('Drag group was not cleared.'); - } - this.surfaceXY = new Coordinate(0, 0); - } -} diff --git a/core/workspace_drag_surface_svg.ts b/core/workspace_drag_surface_svg.ts deleted file mode 100644 index 08e19b656..000000000 --- a/core/workspace_drag_surface_svg.ts +++ /dev/null @@ -1,193 +0,0 @@ -/** - * @license - * Copyright 2016 Google LLC - * SPDX-License-Identifier: Apache-2.0 - */ - -/** - * An SVG that floats on top of the workspace. - * Blocks are moved into this SVG during a drag, improving performance. - * The entire SVG is translated using CSS translation instead of SVG so the - * blocks are never repainted during drag improving performance. - * - * @class - */ -import * as goog from '../closure/goog/goog.js'; -goog.declareModuleId('Blockly.WorkspaceDragSurfaceSvg'); - -import type {Coordinate} from './utils/coordinate.js'; -import * as dom from './utils/dom.js'; -import {Svg} from './utils/svg.js'; -import * as svgMath from './utils/svg_math.js'; - -/** - * Blocks are moved into this SVG during a drag, improving performance. - * The entire SVG is translated using CSS transforms instead of SVG so the - * blocks are never repainted during drag improving performance. - * - * @alias Blockly.WorkspaceDragSurfaceSvg - */ -export class WorkspaceDragSurfaceSvg { - /** - * The SVG drag surface. Set once by WorkspaceDragSurfaceSvg.createDom. - */ - private SVG!: SVGElement; - - /** - * The element to insert the block canvas and bubble canvas after when it - * goes back in the DOM at the end of a drag. - */ - private previousSibling: Element | null = null; - - /** @param container Containing element. */ - constructor(private readonly container: Element) { - this.createDom(); - } - - /** Create the drag surface and inject it into the container. */ - createDom() { - if (this.SVG) { - return; // Already created. - } - /** - * Dom structure when the workspace is being dragged. If there is no drag in - * progress, the SVG is empty and display: none. - * - * - * /g> - * - */ - this.SVG = dom.createSvgElement(Svg.SVG, { - 'xmlns': dom.SVG_NS, - 'xmlns:html': dom.HTML_NS, - 'xmlns:xlink': dom.XLINK_NS, - 'version': '1.1', - 'class': 'blocklyWsDragSurface blocklyOverflowVisible', - }); - this.container.appendChild(this.SVG); - } - - /** - * Translate the entire drag surface during a drag. - * We translate the drag surface instead of the blocks inside the surface - * so that the browser avoids repainting the SVG. - * Because of this, the drag coordinates must be adjusted by scale. - * - * @param x X translation for the entire surface - * @param y Y translation for the entire surface - * @internal - */ - translateSurface(x: number, y: number) { - // Make sure the svg exists on a pixel boundary so that it is not fuzzy. - const fixedX = Math.round(x); - const fixedY = Math.round(y); - - this.SVG.style.display = 'block'; - dom.setCssTransform( - this.SVG, - 'translate3d(' + fixedX + 'px, ' + fixedY + 'px, 0)' - ); - } - - /** - * Reports the surface translation in scaled workspace coordinates. - * Use this when finishing a drag to return blocks to the correct position. - * - * @returns Current translation of the surface - * @internal - */ - getSurfaceTranslation(): Coordinate { - return svgMath.getRelativeXY(this.SVG); - } - - /** - * Move the blockCanvas and bubbleCanvas out of the surface SVG and on to - * newSurface. - * - * @param newSurface The element to put the drag surface contents into. - * @internal - */ - clearAndHide(newSurface: SVGElement) { - if (!newSurface) { - throw Error( - "Couldn't clear and hide the drag surface: missing new surface." - ); - } - const blockCanvas = this.SVG.childNodes[0] as Element; - const bubbleCanvas = this.SVG.childNodes[1] as Element; - if ( - !blockCanvas || - !bubbleCanvas || - !( - blockCanvas.classList.contains('blocklyBlockCanvas') || - !bubbleCanvas.classList.contains('blocklyBubbleCanvas') - ) - ) { - throw Error( - "Couldn't clear and hide the drag surface. A node was missing." - ); - } - - // If there is a previous sibling, put the blockCanvas back right - // afterwards, otherwise insert it as the first child node in newSurface. - if (this.previousSibling !== null) { - dom.insertAfter(blockCanvas, this.previousSibling); - } else { - newSurface.insertBefore(blockCanvas, newSurface.firstChild); - } - - // Reattach the bubble canvas after the blockCanvas. - dom.insertAfter(bubbleCanvas, blockCanvas); - // Hide the drag surface. - this.SVG.style.display = 'none'; - if (this.SVG.childNodes.length) { - throw Error('Drag surface was not cleared.'); - } - dom.setCssTransform(this.SVG, ''); - this.previousSibling = null; - } - - /** - * Set the SVG to have the block canvas and bubble canvas in it and then - * show the surface. - * - * @param blockCanvas The block canvas element from the - * workspace. - * @param bubbleCanvas The element that contains the - bubbles. - * @param previousSibling The element to insert the block canvas and - bubble canvas after when it goes back in the DOM at the end of a - drag. - * @param width The width of the workspace SVG element. - * @param height The height of the workspace SVG element. - * @param scale The scale of the workspace being dragged. - * @internal - */ - setContentsAndShow( - blockCanvas: SVGElement, - bubbleCanvas: SVGElement, - previousSibling: Element, - width: number, - height: number, - scale: number - ) { - if (this.SVG.childNodes.length) { - throw Error('Already dragging a block.'); - } - this.previousSibling = previousSibling; - // Make sure the blocks and bubble canvas are scaled appropriately. - blockCanvas.setAttribute( - 'transform', - 'translate(0, 0) scale(' + scale + ')' - ); - bubbleCanvas.setAttribute( - 'transform', - 'translate(0, 0) scale(' + scale + ')' - ); - this.SVG.setAttribute('width', String(width)); - this.SVG.setAttribute('height', String(height)); - this.SVG.appendChild(blockCanvas); - this.SVG.appendChild(bubbleCanvas); - this.SVG.style.display = 'block'; - } -}