diff --git a/core/block_drag_surface.ts b/core/block_drag_surface.ts deleted file mode 100644 index 909aa76bf22..00000000000 --- a/core/block_drag_surface.ts +++ /dev/null @@ -1,245 +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/block_dragger.ts b/core/block_dragger.ts index c977f5c5312..7673baf8bd6 100644 --- a/core/block_dragger.ts +++ b/core/block_dragger.ts @@ -94,7 +94,7 @@ export class BlockDragger implements IBlockDragger { } /** - * Start dragging a block. This includes moving it to the drag surface. + * Start dragging a block. * * @param currentDragDeltaXY How far the pointer has moved from the position * at mouse down, in pixel units. @@ -124,10 +124,6 @@ export class BlockDragger implements IBlockDragger { this.disconnectBlock_(healStack, currentDragDeltaXY); } this.draggingBlock_.setDragging(true); - // For future consideration: we may be able to put moveToDragSurface inside - // the block dragger, which would also let the block not track the block - // drag surface. - this.draggingBlock_.moveToDragSurface(); } /** @@ -221,16 +217,11 @@ export class BlockDragger implements IBlockDragger { const preventMove = !!this.dragTarget_ && this.dragTarget_.shouldPreventMove(this.draggingBlock_); - let newLoc: Coordinate; let delta: Coordinate|null = null; - if (preventMove) { - newLoc = this.startXY_; - } else { + if (!preventMove) { const newValues = this.getNewLocationAfterDrag_(currentDragDeltaXY); delta = newValues.delta; - newLoc = newValues.newLocation; } - this.draggingBlock_.moveOffDragSurface(newLoc); if (this.dragTarget_) { this.dragTarget_.onDrop(this.draggingBlock_); @@ -442,6 +433,8 @@ function initIconData(block: BlockSvg): IconPositionData[] { for (let i = 0, descendant; descendant = descendants[i]; i++) { const icons = descendant.getIcons(); for (let j = 0; j < icons.length; j++) { + // Only bother to track icons whose bubble is visible. + if (!icons[j].isVisible()) continue; const data = { // Coordinate with x and y properties (workspace // coordinates). diff --git a/core/block_svg.ts b/core/block_svg.ts index 0bd43a8439f..789a76177fc 100644 --- a/core/block_svg.ts +++ b/core/block_svg.ts @@ -142,7 +142,6 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, override nextConnection!: RenderedConnection; // TODO(b/109816955): remove '!', see go/strict-prop-init-fix. override previousConnection!: RenderedConnection; - private readonly useDragSurface_: boolean; private translation = ''; @@ -193,12 +192,6 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, this.pathObject = workspace.getRenderer().makePathObject(this.svgGroup_, this.style); - /** - * Whether to move the block to the drag surface when it is dragged. - * True if it should move, false if it should be translated directly. - */ - this.useDragSurface_ = !!workspace.getBlockDragSurface(); - const svgPath = this.pathObject.svgPath; (svgPath as AnyDuringMigration).tooltip = this; Tooltip.bindMouseEvents(svgPath); @@ -375,10 +368,6 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, let x = 0; let y = 0; - const dragSurfaceGroup = this.useDragSurface_ ? - this.workspace.getBlockDragSurface()!.getGroup() : - null; - let element: SVGElement = this.getSvgRoot(); if (element) { do { @@ -386,19 +375,8 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, const xy = svgMath.getRelativeXY(element); x += xy.x; y += xy.y; - // If this element is the current element on the drag surface, include - // the translation of the drag surface itself. - if (this.useDragSurface_ && - this.workspace.getBlockDragSurface()!.getCurrentBlock() === - element) { - const surfaceTranslation = - this.workspace.getBlockDragSurface()!.getSurfaceTranslation(); - x += surfaceTranslation.x; - y += surfaceTranslation.y; - } element = element.parentNode as SVGElement; - } while (element && element !== this.workspace.getCanvas() && - element !== dragSurfaceGroup); + } while (element && element !== this.workspace.getCanvas()); } return new Coordinate(x, y); } @@ -449,31 +427,6 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, return this.translation; } - /** - * Move this block to its workspace's drag surface, accounting for - * positioning. Generally should be called at the same time as - * setDragging_(true). Does nothing if useDragSurface_ is false. - * - * @internal - */ - moveToDragSurface() { - if (!this.useDragSurface_) { - return; - } - // The translation for drag surface blocks, - // is equal to the current relative-to-surface position, - // to keep the position in sync as it move on/off the surface. - // This is in workspace coordinates. - const xy = this.getRelativeToSurfaceXY(); - this.clearTransformAttributes_(); - this.workspace.getBlockDragSurface()!.translateSurface(xy.x, xy.y); - // Execute the move on the top-level SVG component - const svg = this.getSvgRoot(); - if (svg) { - this.workspace.getBlockDragSurface()!.setBlocksAndShow(svg); - } - } - /** * Move a block to a position. * @@ -485,40 +438,15 @@ export class BlockSvg extends Block implements IASTNodeLocationSvg, } /** - * Move this block back to the workspace block canvas. - * Generally should be called at the same time as setDragging_(false). - * Does nothing if useDragSurface_ is false. - * - * @param newXY The position the block should take on on the workspace canvas, - * in workspace coordinates. - * @internal - */ - moveOffDragSurface(newXY: Coordinate) { - if (!this.useDragSurface_) { - return; - } - // Translate to current position, turning off 3d. - this.translate(newXY.x, newXY.y); - this.workspace.getBlockDragSurface()!.clearAndHide( - this.workspace.getCanvas()); - } - - /** - * Move this block during a drag, taking into account whether we are using a - * drag surface to translate blocks. + * Move this block during a drag. * This block must be a top-level block. * * @param newLoc The location to translate to, in workspace coordinates. * @internal */ moveDuringDrag(newLoc: Coordinate) { - if (this.useDragSurface_) { - this.workspace.getBlockDragSurface()!.translateSurface( - newLoc.x, newLoc.y); - } else { - this.translate(newLoc.x, newLoc.y); - this.getSvgRoot().setAttribute('transform', this.getTranslation()); - } + this.translate(newLoc.x, newLoc.y); + this.getSvgRoot().setAttribute('transform', this.getTranslation()); } /** diff --git a/core/blockly.ts b/core/blockly.ts index 0537827a95c..81064ede52d 100644 --- a/core/blockly.ts +++ b/core/blockly.ts @@ -25,7 +25,6 @@ import './events/events_var_create.js'; import {Block} from './block.js'; import * as blockAnimations from './block_animations.js'; -import {BlockDragSurfaceSvg} from './block_drag_surface.js'; import {BlockDragger} from './block_dragger.js'; import {BlockSvg} from './block_svg.js'; import {BlocklyOptions} from './blockly_options.js'; @@ -160,7 +159,6 @@ import {Workspace} from './workspace.js'; import {WorkspaceAudio} from './workspace_audio.js'; import {WorkspaceComment} from './workspace_comment.js'; import {WorkspaceCommentSvg} from './workspace_comment_svg.js'; -import {WorkspaceDragSurfaceSvg} from './workspace_drag_surface_svg.js'; import {WorkspaceDragger} from './workspace_dragger.js'; import {resizeSvgContents as realResizeSvgContents, WorkspaceSvg} from './workspace_svg.js'; import * as Xml from './xml.js'; @@ -626,7 +624,6 @@ export {BasicCursor}; export {Block}; export {BlocklyOptions}; export {BlockDragger}; -export {BlockDragSurfaceSvg}; export {BlockSvg}; export {Blocks}; export {Bubble}; @@ -729,7 +726,6 @@ export {Workspace}; export {WorkspaceAudio}; export {WorkspaceComment}; export {WorkspaceCommentSvg}; -export {WorkspaceDragSurfaceSvg}; export {WorkspaceDragger}; export {WorkspaceSvg}; export {ZoomControls}; diff --git a/core/bubble.ts b/core/bubble.ts index 054043c2ede..7f8a1eb3bc5 100644 --- a/core/bubble.ts +++ b/core/bubble.ts @@ -12,7 +12,6 @@ import * as goog from '../closure/goog/goog.js'; goog.declareModuleId('Blockly.Bubble'); -import type {BlockDragSurfaceSvg} from './block_drag_surface.js'; import type {BlockSvg} from './block_svg.js'; import * as browserEvents from './browser_events.js'; import type {IBubble} from './interfaces/i_bubble.js'; @@ -785,20 +784,13 @@ export class Bubble implements IBubble { } /** - * Move this bubble during a drag, taking into account whether or not there is - * a drag surface. + * Move this bubble during a drag. * - * @param dragSurface The surface that carries rendered items during a drag, - * or null if no drag surface is in use. * @param newLoc The location to translate to, in workspace coordinates. * @internal */ - moveDuringDrag(dragSurface: BlockDragSurfaceSvg, newLoc: Coordinate) { - if (dragSurface) { - dragSurface.translateSurface(newLoc.x, newLoc.y); - } else { - this.moveTo(newLoc.x, newLoc.y); - } + moveDuringDrag(newLoc: Coordinate) { + this.moveTo(newLoc.x, newLoc.y); if (this.workspace_.RTL) { this.relativeLeft = this.anchorXY.x - newLoc.x - this.width; } else { diff --git a/core/bubble_dragger.ts b/core/bubble_dragger.ts index edd67655b3f..083faf7348d 100644 --- a/core/bubble_dragger.ts +++ b/core/bubble_dragger.ts @@ -12,7 +12,6 @@ import * as goog from '../closure/goog/goog.js'; goog.declareModuleId('Blockly.BubbleDragger'); -import type {BlockDragSurfaceSvg} from './block_drag_surface.js'; import {ComponentManager} from './component_manager.js'; import type {CommentMove} from './events/events_comment_move.js'; import * as eventUtils from './events/utils.js'; @@ -38,7 +37,6 @@ export class BubbleDragger { /** Whether the bubble would be deleted if dropped immediately. */ private wouldDeleteBubble_ = false; private readonly startXY_: Coordinate; - private dragSurface_: BlockDragSurfaceSvg|null; /** * @param bubble The item on the bubble canvas to drag. @@ -50,16 +48,10 @@ export class BubbleDragger { * beginning of the drag, in workspace coordinates. */ this.startXY_ = this.bubble.getRelativeToSurfaceXY(); - - /** - * The drag surface to move bubbles to during a drag, or null if none should - * be used. Block dragging and bubble dragging use the same surface. - */ - this.dragSurface_ = workspace.getBlockDragSurface(); } /** - * Start dragging a bubble. This includes moving it to the drag surface. + * Start dragging a bubble. * * @internal */ @@ -70,12 +62,6 @@ export class BubbleDragger { this.workspace.setResizesEnabled(false); this.bubble.setAutoLayout(false); - if (this.dragSurface_) { - this.bubble.moveTo(0, 0); - this.dragSurface_.translateSurface(this.startXY_.x, this.startXY_.y); - // Execute the move on the top-level SVG component. - this.dragSurface_.setBlocksAndShow(this.bubble.getSvgRoot()); - } this.bubble.setDragging && this.bubble.setDragging(true); } @@ -92,7 +78,7 @@ export class BubbleDragger { dragBubble(e: PointerEvent, currentDragDeltaXY: Coordinate) { const delta = this.pixelsToWorkspaceUnits_(currentDragDeltaXY); const newLoc = Coordinate.sum(this.startXY_, delta); - this.bubble.moveDuringDrag(this.dragSurface_, newLoc); + this.bubble.moveDuringDrag(newLoc); const oldDragTarget = this.dragTarget_; this.dragTarget_ = this.workspace.getDragTarget(e); @@ -172,9 +158,6 @@ export class BubbleDragger { this.bubble.dispose(); } else { // Put everything back onto the bubble canvas. - if (this.dragSurface_) { - this.dragSurface_.clearAndHide(this.workspace.getBubbleCanvas()); - } if (this.bubble.setDragging) { this.bubble.setDragging(false); } diff --git a/core/css.ts b/core/css.ts index 81b2e15a908..1582b783f37 100644 --- a/core/css.ts +++ b/core/css.ts @@ -98,31 +98,6 @@ let content = ` -webkit-user-select: none; } -.blocklyWsDragSurface { - display: none; - position: absolute; - top: 0; - left: 0; -} - -/* Added as a separate rule with multiple classes to make it more specific - than a bootstrap rule that selects svg:root. See issue #1275 for context. -*/ -.blocklyWsDragSurface.blocklyOverflowVisible { - overflow: visible; -} - -.blocklyBlockDragSurface { - display: none; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - overflow: visible !important; - z-index: 50; /* Display below toolbox, but above everything else. */ -} - .blocklyBlockCanvas.blocklyCanvasTransitioning, .blocklyBubbleCanvas.blocklyCanvasTransitioning { transition: transform .5s; @@ -258,16 +233,6 @@ let content = ` cursor: -webkit-grabbing; } -/* Change the cursor on the whole drag surface in case the mouse gets - ahead of block during a drag. This way the cursor is still a closed hand. - */ -.blocklyBlockDragSurface .blocklyDraggable { - /* backup for browsers (e.g. IE11) that don't support grabbing */ - cursor: url("<<>>/handclosed.cur"), auto; - cursor: grabbing; - cursor: -webkit-grabbing; -} - .blocklyDragging.blocklyDraggingDelete { cursor: url("<<>>/handdelete.cur"), auto; } @@ -320,8 +285,7 @@ let content = ` Don't allow users to select text. It gets annoying when trying to drag a block and selected text moves instead. */ -.blocklySvg text, -.blocklyBlockDragSurface text { +.blocklySvg text { user-select: none; -ms-user-select: none; -webkit-user-select: none; diff --git a/core/inject.ts b/core/inject.ts index 71a359edbde..d2f56186560 100644 --- a/core/inject.ts +++ b/core/inject.ts @@ -12,7 +12,6 @@ import * as goog from '../closure/goog/goog.js'; goog.declareModuleId('Blockly.inject'); -import {BlockDragSurfaceSvg} from './block_drag_surface.js'; import type {BlocklyOptions} from './blockly_options.js'; import * as browserEvents from './browser_events.js'; import * as bumpObjects from './bump_objects.js'; @@ -31,7 +30,6 @@ import * as dom from './utils/dom.js'; import {Svg} from './utils/svg.js'; import * as userAgent from './utils/useragent.js'; import * as WidgetDiv from './widgetdiv.js'; -import {WorkspaceDragSurfaceSvg} from './workspace_drag_surface_svg.js'; import {WorkspaceSvg} from './workspace_svg.js'; @@ -69,14 +67,7 @@ export function inject( (container as AnyDuringMigration).appendChild(subContainer); const svg = createDom(subContainer, options); - // Create surfaces for dragging things. These are optimizations - // so that the browser does not repaint during the drag. - const blockDragSurface = new BlockDragSurfaceSvg(subContainer); - - const workspaceDragSurface = new WorkspaceDragSurfaceSvg(subContainer); - - const workspace = - createMainWorkspace(svg, options, blockDragSurface, workspaceDragSurface); + const workspace = createMainWorkspace(svg, options); init(workspace); @@ -154,16 +145,11 @@ function createDom(container: Element, options: Options): Element { * * @param svg SVG element with pattern defined. * @param options Dictionary of options. - * @param blockDragSurface Drag surface SVG for the blocks. - * @param workspaceDragSurface Drag surface SVG for the workspace. * @returns Newly created main workspace. */ -function createMainWorkspace( - svg: Element, options: Options, blockDragSurface: BlockDragSurfaceSvg, - workspaceDragSurface: WorkspaceDragSurfaceSvg): WorkspaceSvg { +function createMainWorkspace(svg: Element, options: Options): WorkspaceSvg { options.parentWorkspace = null; - const mainWorkspace = - new WorkspaceSvg(options, blockDragSurface, workspaceDragSurface); + const mainWorkspace = new WorkspaceSvg(options); const wsOptions = mainWorkspace.options; mainWorkspace.scale = wsOptions.zoomOptions.startScale; svg.appendChild(mainWorkspace.createDom('blocklyMainBackground')); diff --git a/core/interfaces/i_block_dragger.ts b/core/interfaces/i_block_dragger.ts index 8fa4b9ddadd..e977369ea0a 100644 --- a/core/interfaces/i_block_dragger.ts +++ b/core/interfaces/i_block_dragger.ts @@ -21,7 +21,7 @@ goog.declareModuleId('Blockly.IBlockDragger'); */ export interface IBlockDragger { /** - * Start dragging a block. This includes moving it to the drag surface. + * Start dragging a block. * * @param currentDragDeltaXY How far the pointer has moved from the position * at mouse down, in pixel units. diff --git a/core/interfaces/i_bubble.ts b/core/interfaces/i_bubble.ts index f424af33446..af945043051 100644 --- a/core/interfaces/i_bubble.ts +++ b/core/interfaces/i_bubble.ts @@ -11,7 +11,6 @@ */ import * as goog from '../../closure/goog/goog.js'; import type {Coordinate} from '../utils/coordinate.js'; -import type {BlockDragSurfaceSvg} from '../block_drag_surface.js'; goog.declareModuleId('Blockly.IBubble'); import type {IContextMenu} from './i_contextmenu.js'; @@ -56,15 +55,11 @@ export interface IBubble extends IDraggable, IContextMenu { setDragging(dragging: boolean): void; /** - * Move this bubble during a drag, taking into account whether or not there is - * a drag surface. + * Move this bubble during a drag. * - * @param dragSurface The surface that carries rendered items during a drag, - * or null if no drag surface is in use. * @param newLoc The location to translate to, in workspace coordinates. */ - moveDuringDrag(dragSurface: BlockDragSurfaceSvg|null, newLoc: Coordinate): - void; + moveDuringDrag(newLoc: Coordinate): void; /** * Move the bubble to the specified location in workspace coordinates. diff --git a/core/scrollbar.ts b/core/scrollbar.ts index 652d5ae2de2..1ddf4cf5687 100644 --- a/core/scrollbar.ts +++ b/core/scrollbar.ts @@ -715,11 +715,6 @@ export class Scrollbar { // Look up the current translation and record it. this.startDragHandle = this.handlePosition; - // Tell the workspace to setup its drag surface since it is about to move. - // onMouseMoveHandle will call onScroll which actually tells the workspace - // to move. - this.workspace.setupDragSurface(); - // Record the current mouse position. this.startDragMouse = this.horizontal ? e.clientX : e.clientY; this.onMouseUpWrapper_ = browserEvents.conditionalBind( @@ -746,8 +741,6 @@ export class Scrollbar { /** Release the scrollbar handle and reset state accordingly. */ private onMouseUpHandle() { - // Tell the workspace to clean up now that the workspace is done moving. - this.workspace.resetDragSurface(); Touch.clearTouchIdentifier(); this.cleanUp(); } diff --git a/core/workspace_comment_svg.ts b/core/workspace_comment_svg.ts index 1c3e30d0120..329d37ceb5d 100644 --- a/core/workspace_comment_svg.ts +++ b/core/workspace_comment_svg.ts @@ -15,7 +15,6 @@ goog.declareModuleId('Blockly.WorkspaceCommentSvg'); // Unused import preserved for side-effects. Remove if unneeded. import './events/events_selected.js'; -import type {BlockDragSurfaceSvg} from './block_drag_surface.js'; import * as browserEvents from './browser_events.js'; import * as common from './common.js'; // import * as ContextMenu from './contextmenu.js'; @@ -93,7 +92,6 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements /** Whether the comment is rendered onscreen and is a part of the DOM. */ private rendered_ = false; - private readonly useDragSurface_: boolean; /** * @param workspace The block's workspace. @@ -119,12 +117,6 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements }); this.svgGroup_.appendChild(this.svgRect_); - /** - * Whether to move the comment to the drag surface when it is dragged. - * True if it should move, false if it should be translated directly. - */ - this.useDragSurface_ = !!workspace.getBlockDragSurface(); - this.render(); } @@ -308,10 +300,6 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements let x = 0; let y = 0; - const dragSurfaceGroup = this.useDragSurface_ ? - this.workspace.getBlockDragSurface()!.getGroup() : - null; - let element = this.getSvgRoot(); if (element) { do { @@ -319,21 +307,11 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements const xy = svgMath.getRelativeXY(element as Element); x += xy.x; y += xy.y; - // If this element is the current element on the drag surface, include - // the translation of the drag surface itself. - if (this.useDragSurface_ && - this.workspace.getBlockDragSurface()!.getCurrentBlock() === - element) { - const surfaceTranslation = - this.workspace.getBlockDragSurface()!.getSurfaceTranslation(); - x += surfaceTranslation.x; - y += surfaceTranslation.y; - } // AnyDuringMigration because: Type 'ParentNode | null' is not // assignable to type 'SVGElement'. element = element.parentNode as AnyDuringMigration; } while (element && element !== this.workspace.getBubbleCanvas() && - element !== dragSurfaceGroup); + element !== null); } this.xy_ = new Coordinate(x, y); return this.xy_; @@ -373,43 +351,14 @@ export class WorkspaceCommentSvg extends WorkspaceComment implements } /** - * Move this comment to its workspace's drag surface, accounting for - * positioning. Generally should be called at the same time as - * setDragging(true). Does nothing if useDragSurface_ is false. - * - * @internal - */ - moveToDragSurface() { - if (!this.useDragSurface_) { - return; - } - // The translation for drag surface blocks, - // is equal to the current relative-to-surface position, - // to keep the position in sync as it move on/off the surface. - // This is in workspace coordinates. - const xy = this.getRelativeToSurfaceXY(); - this.clearTransformAttributes_(); - this.workspace.getBlockDragSurface()!.translateSurface(xy.x, xy.y); - // Execute the move on the top-level SVG component - this.workspace.getBlockDragSurface()!.setBlocksAndShow(this.getSvgRoot()); - } - - /** - * Move this comment during a drag, taking into account whether we are using a - * drag surface to translate blocks. + * Move this comment during a drag. * - * @param dragSurface The surface that carries rendered items during a drag, - * or null if no drag surface is in use. * @param newLoc The location to translate to, in workspace coordinates. * @internal */ - moveDuringDrag(dragSurface: BlockDragSurfaceSvg, newLoc: Coordinate) { - if (dragSurface) { - dragSurface.translateSurface(newLoc.x, newLoc.y); - } else { - const translation = `translate(${newLoc.x}, ${newLoc.y})`; - this.getSvgRoot().setAttribute('transform', translation); - } + moveDuringDrag(newLoc: Coordinate) { + const translation = `translate(${newLoc.x}, ${newLoc.y})`; + this.getSvgRoot().setAttribute('transform', translation); } /** diff --git a/core/workspace_drag_surface_svg.ts b/core/workspace_drag_surface_svg.ts deleted file mode 100644 index c206786090a..00000000000 --- a/core/workspace_drag_surface_svg.ts +++ /dev/null @@ -1,176 +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'; - } -} diff --git a/core/workspace_dragger.ts b/core/workspace_dragger.ts index 686807e3965..939c73ab629 100644 --- a/core/workspace_dragger.ts +++ b/core/workspace_dragger.ts @@ -20,9 +20,6 @@ import type {WorkspaceSvg} from './workspace_svg.js'; /** * Class for a workspace dragger. It moves the 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. * * @alias Blockly.WorkspaceDragger */ @@ -67,7 +64,6 @@ export class WorkspaceDragger { if (common.getSelected()) { common.getSelected()!.unselect(); } - this.workspace.setupDragSurface(); } /** @@ -80,7 +76,6 @@ export class WorkspaceDragger { endDrag(currentDragDeltaXY: Coordinate) { // Make sure everything is up to date. this.drag(currentDragDeltaXY); - this.workspace.resetDragSurface(); } /** diff --git a/core/workspace_svg.ts b/core/workspace_svg.ts index 06c43d68274..f0cd6c43dba 100644 --- a/core/workspace_svg.ts +++ b/core/workspace_svg.ts @@ -20,7 +20,6 @@ import './events/events_theme_change.js'; import './events/events_viewport.js'; import type {Block} from './block.js'; -import type {BlockDragSurfaceSvg} from './block_drag_surface.js'; import type {BlockSvg} from './block_svg.js'; import type {BlocklyOptions} from './blockly_options.js'; import * as browserEvents from './browser_events.js'; @@ -75,7 +74,6 @@ import {Workspace} from './workspace.js'; import {WorkspaceAudio} from './workspace_audio.js'; import {WorkspaceComment} from './workspace_comment.js'; import {WorkspaceCommentSvg} from './workspace_comment_svg.js'; -import type {WorkspaceDragSurfaceSvg} from './workspace_drag_surface_svg.js'; import * as Xml from './xml.js'; import {ZoomControls} from './zoom_controls.js'; import {ContextMenuOption} from './contextmenu_registry.js'; @@ -225,26 +223,6 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { */ currentGesture_: Gesture|null = null; - /** This workspace's surface for dragging blocks, if it exists. */ - private readonly blockDragSurface: BlockDragSurfaceSvg|null = null; - - /** This workspace's drag surface, if it exists. */ - private readonly workspaceDragSurface: WorkspaceDragSurfaceSvg|null = null; - - /** - * Whether to move workspace to the drag surface when it is dragged. - * True if it should move, false if it should be translated directly. - */ - private readonly useWorkspaceDragSurface; - - /** - * Whether the drag surface is actively in use. When true, calls to - * translate will translate the drag surface instead of the translating the - * workspace directly. - * This is set to true in setupDragSurface and to false in resetDragSurface. - */ - private isDragSurfaceActive = false; - /** * The first parent div with 'injectionDiv' in the name, or null if not set. * Access this with getInjectionDiv. @@ -338,12 +316,8 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { /** * @param options Dictionary of options. - * @param opt_blockDragSurface Drag surface for blocks. - * @param opt_wsDragSurface Drag surface for the workspace. */ - constructor( - options: Options, opt_blockDragSurface?: BlockDragSurfaceSvg, - opt_wsDragSurface?: WorkspaceDragSurfaceSvg) { + constructor(options: Options) { super(options); const MetricsManagerClass = registry.getClassFromOptions( @@ -363,16 +337,6 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.connectionDBList = ConnectionDB.init(this.connectionChecker); - if (opt_blockDragSurface) { - this.blockDragSurface = opt_blockDragSurface; - } - - if (opt_wsDragSurface) { - this.workspaceDragSurface = opt_wsDragSurface; - } - - this.useWorkspaceDragSurface = !!this.workspaceDragSurface; - /** * Object in charge of loading, storing, and playing audio for a workspace. */ @@ -1152,18 +1116,10 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { * the Blockly div. */ translate(x: number, y: number) { - if (this.useWorkspaceDragSurface && this.isDragSurfaceActive) { - this.workspaceDragSurface?.translateSurface(x, y); - } else { - const translation = 'translate(' + x + ',' + y + ') ' + - 'scale(' + this.scale + ')'; - this.svgBlockCanvas_.setAttribute('transform', translation); - this.svgBubbleCanvas_.setAttribute('transform', translation); - } - // Now update the block drag surface if we're using one. - if (this.blockDragSurface) { - this.blockDragSurface.translateAndScaleGroup(x, y, this.scale); - } + const translation = 'translate(' + x + ',' + y + ') ' + + 'scale(' + this.scale + ')'; + this.svgBlockCanvas_.setAttribute('transform', translation); + this.svgBubbleCanvas_.setAttribute('transform', translation); // And update the grid if we're using one. if (this.grid) { this.grid.moveTo(x, y); @@ -1172,75 +1128,6 @@ export class WorkspaceSvg extends Workspace implements IASTNodeLocationSvg { this.maybeFireViewportChangeEvent(); } - /** - * Called at the end of a workspace drag to take the contents - * out of the drag surface and put them back into the workspace SVG. - * Does nothing if the workspace drag surface is not enabled. - * - * @internal - */ - resetDragSurface() { - // Don't do anything if we aren't using a drag surface. - if (!this.useWorkspaceDragSurface) { - return; - } - - this.isDragSurfaceActive = false; - - const trans = this.workspaceDragSurface!.getSurfaceTranslation(); - this.workspaceDragSurface!.clearAndHide(this.svgGroup_); - const translation = 'translate(' + trans.x + ',' + trans.y + ') ' + - 'scale(' + this.scale + ')'; - this.svgBlockCanvas_.setAttribute('transform', translation); - this.svgBubbleCanvas_.setAttribute('transform', translation); - } - - /** - * Called at the beginning of a workspace drag to move contents of - * the workspace to the drag surface. - * Does nothing if the drag surface is not enabled. - * - * @internal - */ - setupDragSurface() { - // Don't do anything if we aren't using a drag surface. - if (!this.useWorkspaceDragSurface) { - return; - } - - // This can happen if the user starts a drag, mouses up outside of the - // document where the mouseup listener is registered (e.g. outside of an - // iframe) and then moves the mouse back in the workspace. On mobile and - // ff, we get the mouseup outside the frame. On chrome and safari desktop we - // do not. - if (this.isDragSurfaceActive) { - return; - } - - this.isDragSurfaceActive = true; - - // Figure out where we want to put the canvas back. The order - // in the is important because things are layered. - const previousElement = this.svgBlockCanvas_.previousSibling as Element; - const width = parseInt(this.getParentSvg().getAttribute('width') ?? '0'); - const height = parseInt(this.getParentSvg().getAttribute('height') ?? '0'); - const coord = svgMath.getRelativeXY(this.getCanvas()); - this.workspaceDragSurface!.setContentsAndShow( - this.getCanvas(), this.getBubbleCanvas(), previousElement, width, - height, this.scale); - this.workspaceDragSurface!.translateSurface(coord.x, coord.y); - } - - /** - * Gets the drag surface blocks are moved to when a drag is started. - * - * @returns This workspace's block drag surface, if one is in use. - * @internal - */ - getBlockDragSurface(): BlockDragSurfaceSvg|null { - return this.blockDragSurface; - } - /** * Returns the horizontal offset of the workspace. * Intended for LTR/RTL compatibility in XML.