UNPKG

js-draw

Version:

Draw pictures using a pen, touchscreen, or mouse! JS-draw is a drawing library for JavaScript and TypeScript.

101 lines (100 loc) 3.53 kB
import describeComponentList from '../components/util/describeComponentList.mjs'; import { assertIsStringArray } from '../util/assertions.mjs'; import Erase from './Erase.mjs'; import SerializableCommand from './SerializableCommand.mjs'; /** * A command that duplicates the {@link AbstractComponent}s it's given. This command * is the reverse of an {@link Erase} command. * * @example * ```ts * // Given some editor... * * // Find all elements intersecting the rectangle with top left (0,0) and * // (width,height)=(100,100). * const elems = editor.image.getComponentsIntersecting( * new Rect2(0, 0, 100, 100) * ); * * // Create a command that, when applied, will duplicate the elements. * const duplicateElems = new Duplicate(elems); * * // Apply the command (and make it undoable) * editor.dispatch(duplicateElems); * ``` * * @see {@link Editor.dispatch} {@link EditorImage.getComponentsIntersecting} */ class Duplicate extends SerializableCommand { constructor(toDuplicate, // @internal -- IDs given to the duplicate elements idsForDuplicates) { super('duplicate'); this.toDuplicate = toDuplicate; this.duplicates = toDuplicate.map((elem, idx) => { // For collaborative editing, it's important for the clones to have // the same IDs as the originals if (idsForDuplicates && idsForDuplicates[idx]) { return elem.cloneWithId(idsForDuplicates[idx]); } else { return elem.clone(); } }); this.reverse = new Erase(this.duplicates); } apply(editor) { this.reverse.unapply(editor); } unapply(editor) { this.reverse.apply(editor); } onDrop(editor) { this.reverse.onDrop(editor); } description(_editor, localizationTable) { if (this.duplicates.length === 0) { return localizationTable.duplicatedNoElements; } return localizationTable.duplicateAction(describeComponentList(localizationTable, this.duplicates) ?? localizationTable.elements, this.duplicates.length); } serializeToJSON() { return { originalIds: this.toDuplicate.map((elem) => elem.getId()), cloneIds: this.duplicates.map((elem) => elem.getId()), }; } } (() => { SerializableCommand.register('duplicate', (json, editor) => { let originalIds; let cloneIds; // Compatibility with older editors if (Array.isArray(json)) { originalIds = json; cloneIds = []; } else { originalIds = json.originalIds; cloneIds = json.cloneIds; } assertIsStringArray(originalIds); assertIsStringArray(cloneIds); // Resolve to elements -- only keep the elements that can be found in the image. const resolvedElements = []; const filteredCloneIds = []; for (let i = 0; i < originalIds.length; i++) { const originalId = originalIds[i]; const foundElement = editor.image.lookupElement(originalId); if (!foundElement) { console.warn('Duplicate command: Could not find element with ID', originalId); } else { filteredCloneIds.push(cloneIds[i]); resolvedElements.push(foundElement); } } return new Duplicate(resolvedElements, filteredCloneIds); }); })(); export default Duplicate;