From 68a8a5ff194ae2cc23ceadb06c74a76d76fbdec4 Mon Sep 17 00:00:00 2001 From: Beka Westberg Date: Mon, 31 Jul 2023 09:22:24 -0700 Subject: [PATCH] feat: add basic pasters (#7331) * feat: implement basic IPaster interface * feat: add pasters for blocks and workspace comments --- core/clipboard/block_paster.ts | 31 ++++++++++++++++++++++ core/clipboard/workspace_comment_paster.ts | 30 +++++++++++++++++++++ core/interfaces/i_paster.ts | 23 ++++++++++++++++ 3 files changed, 84 insertions(+) create mode 100644 core/clipboard/block_paster.ts create mode 100644 core/clipboard/workspace_comment_paster.ts create mode 100644 core/interfaces/i_paster.ts diff --git a/core/clipboard/block_paster.ts b/core/clipboard/block_paster.ts new file mode 100644 index 000000000..363f70cad --- /dev/null +++ b/core/clipboard/block_paster.ts @@ -0,0 +1,31 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {BlockSvg} from '../block_svg.js'; +import {CopyData} from '../interfaces/i_copyable'; +import {IPaster} from '../interfaces/i_paster.js'; +import {State, append} from '../serialization/blocks'; +import {Coordinate} from '../utils/coordinate.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; + +export class BlockPaster implements IPaster { + paste( + copyData: BlockCopyData, + workspace: WorkspaceSvg, + coordinate?: Coordinate, + ): BlockSvg | null { + if (!workspace.isCapacityAvailable(copyData.typeCounts!)) return null; + + const state = copyData.saveInfo as State; + if (coordinate) { + state['x'] = coordinate.x; + state['y'] = coordinate.y; + } + return append(state, workspace, {recordUndo: true}) as BlockSvg; + } +} + +export interface BlockCopyData extends CopyData {} diff --git a/core/clipboard/workspace_comment_paster.ts b/core/clipboard/workspace_comment_paster.ts new file mode 100644 index 000000000..11211564c --- /dev/null +++ b/core/clipboard/workspace_comment_paster.ts @@ -0,0 +1,30 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {IPaster} from '../interfaces/i_paster.js'; +import {CopyData} from '../interfaces/i_copyable.js'; +import {Coordinate} from '../utils/coordinate.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; +import {WorkspaceCommentSvg} from '../workspace_comment_svg.js'; + +export class WorkspaceCommentPaster + implements IPaster +{ + paste( + copyData: WorkspaceCommentCopyData, + workspace: WorkspaceSvg, + coordinate?: Coordinate, + ): WorkspaceCommentSvg { + const state = copyData.saveInfo as Element; + if (coordinate) { + state.setAttribute('x', `${coordinate.x}`); + state.setAttribute('y', `${coordinate.y}`); + } + return WorkspaceCommentSvg.fromXmlRendered(state, workspace); + } +} + +export interface WorkspaceCommentCopyData extends CopyData {} diff --git a/core/interfaces/i_paster.ts b/core/interfaces/i_paster.ts new file mode 100644 index 000000000..9653d25df --- /dev/null +++ b/core/interfaces/i_paster.ts @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2023 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import {Coordinate} from '../utils/coordinate.js'; +import {WorkspaceSvg} from '../workspace_svg.js'; +import {ICopyable, CopyData} from './i_copyable.js'; + +/** An object that can paste data into a workspace. */ +export interface IPaster { + paste( + copyData: U, + workspace: WorkspaceSvg, + coordinate?: Coordinate, + ): T | null; +} + +/** @returns True if the given object is a paster. */ +export function isPaster(obj: any): obj is IPaster { + return obj.paste !== undefined; +}