Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions packages/core/src/editor/Editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import RootChange from '../view/undoable_changes/RootChange';
import ValueChange from '../view/undoable_changes/ValueChange';
import CellAttributeChange from '../view/undoable_changes/CellAttributeChange';
import PrintPreview from '../view/other/PrintPreview';
import mxClipboard from '../util/Clipboard';
import Clipboard from '../util/Clipboard';
import MaxLog from '../gui/MaxLog';
import { isNode } from '../util/domUtils';
import { getViewXml, getXml } from '../util/xmlUtils';
Expand Down Expand Up @@ -982,19 +982,19 @@ export class Editor extends EventSource {

this.addAction('cut', (editor: Editor) => {
if (editor.graph.isEnabled()) {
mxClipboard.cut(editor.graph);
Clipboard.cut(editor.graph);
}
});

this.addAction('copy', (editor: Editor) => {
if (editor.graph.isEnabled()) {
mxClipboard.copy(editor.graph);
Clipboard.copy(editor.graph);
}
});

this.addAction('paste', (editor: Editor) => {
if (editor.graph.isEnabled()) {
mxClipboard.paste(editor.graph);
Clipboard.paste(editor.graph);
}
});

Expand Down
125 changes: 53 additions & 72 deletions packages/core/src/util/Clipboard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,32 +25,23 @@ import { getTopmostCells } from './cellArrayUtils';
*
* Singleton that implements a clipboard for graph cells.
*
* ### Example:
*
* To copy the selection cells from the graph to the clipboard and paste them into graph2, do the following:
* ```javascript
* Clipboard.copy(graph);
* Clipboard.paste(graph2);
* ```
*
* This copies the selection cells from the graph to the clipboard and
* pastes them into graph2.
*
* For fine-grained control of the clipboard data the {@link graph.canExportCell}
* and {@link graph.canImportCell} functions can be overridden.
* For fine-grained control of the clipboard data the {@link Graph.canExportCell} and {@link Graph.canImportCell} functions can be overridden.
*
* To restore previous parents for pasted cells, the implementation for
* {@link copy} and {@link paste} can be changed as follows.
* To restore previous parents for pasted cells, the implementation for {@link copy} and {@link paste} can be changed as follows.
*
* ```javascript
* Clipboard.copy = function(graph, cells)
* {
* cells = cells || graph.getSelectionCells();
* var result = graph.getExportableCells(cells);
* ```typescript
* Clipboard.copy = function(graph: Graph, cells: Cell[]): void {
* cells = cells ?? graph.getSelectionCells();
* const result = graph.getExportableCells(cells);
*
* Clipboard.parents = new Object();
*
* for (var i = 0; i < result.length; i++)
* {
* for (let i = 0; i < result.length; i++) {
* Clipboard.parents[i] = graph.model.getParent(cells[i]);
* }
*
Expand All @@ -60,40 +51,36 @@ import { getTopmostCells } from './cellArrayUtils';
* return result;
* };
*
* Clipboard.paste = function(graph)
* {
* if (!Clipboard.isEmpty())
* {
* var cells = graph.getImportableCells(Clipboard.getCells());
* var delta = Clipboard.insertCount * Clipboard.STEPSIZE;
* var parent = graph.getDefaultParent();
* Clipboard.paste = function(graph: Graph): void {
* if (Clipboard.isEmpty()) {
* return;
* }
* const cells = graph.getImportableCells(Clipboard.getCells());
* const delta = Clipboard.insertCount * Clipboard.STEPSIZE;
* const parent = graph.getDefaultParent();
*
* graph.model.beginUpdate();
* try
* {
* for (var i = 0; i < cells.length; i++)
* {
* var tmp = (Clipboard.parents != null && graph.model.contains(Clipboard.parents[i])) ?
* Clipboard.parents[i] : parent;
* cells[i] = graph.importCells([cells[i]], delta, delta, tmp)[0];
* }
* graph.model.beginUpdate();
* try {
* for (let i = 0; i < cells.length; i++) {
* const tmp = (Clipboard.parents && graph.model.contains(Clipboard.parents[i])) ?
* Clipboard.parents[i] : parent;
* cells[i] = graph.importCells([cells[i]], delta, delta, tmp)[0];
* }
* finally
* {
* graph.model.endUpdate();
* }
*
* // Increments the counter and selects the inserted cells
* Clipboard.insertCount++;
* graph.setSelectionCells(cells);
* }
* finally {
* graph.model.endUpdate();
* }
*
* // Increments the counter and selects the inserted cells
* Clipboard.insertCount++;
* graph.setSelectionCells(cells);
* };
* ```
*/
class Clipboard {
/**
* Defines the step size to offset the cells after each paste operation.
* Default is 10.
* @default 10
*/
static STEPSIZE = 10;

Expand All @@ -103,40 +90,40 @@ class Clipboard {
static insertCount = 1;

/**
* Holds the array of {@link mxCell} currently in the clipboard.
* Holds the array of {@link Cell} currently in the clipboard.
*/
static cells: Cell[];

/**
* Sets the cells in the clipboard. Fires a {@link mxEvent.CHANGE} event.
* Sets the cells in the clipboard. Fires a {@link InternalEvent.CHANGE} event.
*/
static setCells(cells: Cell[]) {
static setCells(cells: Cell[]): void {
Clipboard.cells = cells;
}

/**
* Returns the cells in the clipboard.
* Returns the cells in the clipboard.
*/
static getCells() {
static getCells(): Cell[] {
return Clipboard.cells;
}

/**
* Returns true if the clipboard currently has not data stored.
* Returns `true` if the clipboard currently has no data stored.
*/
static isEmpty() {
static isEmpty(): boolean {
return !Clipboard.getCells();
}

/**
* Cuts the given array of {@link mxCell} from the specified graph.
* If cells is null then the selection cells of the graph will
* be used. Returns the cells that have been cut from the graph.
* Cuts the given array of {@link Cell} from the specified graph.
* If {@link cells} is `null` then the selection cells of the graph will be used.
*
* @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Optional array of {@link mxCell} to be cut.
* @param cells - Optional array of {@link Cell} to be cut.
* @returns Returns the cells that have been cut from the graph.
*/
static cut(graph: Graph, cells: Cell[] = []) {
static cut(graph: Graph, cells: Cell[] = []): Cell[] {
cells = Clipboard.copy(graph, cells);
Clipboard.insertCount = 0;
Clipboard.removeCells(graph, cells);
Expand All @@ -145,25 +132,24 @@ class Clipboard {
}

/**
* Hook to remove the given cells from the given graph after
* a cut operation.
* Hook to remove the given cells from the given graph after a cut operation.
*
* @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Array of {@link mxCell} to be cut.
* @param cells - Array of {@link Cell} to be cut.
*/
static removeCells(graph: Graph, cells: Cell[]) {
static removeCells(graph: Graph, cells: Cell[]): void {
graph.removeCells(cells);
}

/**
* Copies the given array of {@link mxCell} from the specified
* graph to {@link cells}. Returns the original array of cells that has
* been cloned. Descendants of cells in the array are ignored.
* Copies the given array of {@link Cell} from the specified graph to {@link cells}.
* Returns the original array of cells that has been cloned.
* Descendants of cells in the array are ignored.
*
* @param graph - {@link graph} that contains the cells to be copied.
* @param cells - Optional array of {@link mxCell} to be copied.
* @param cells - Optional array of {@link Cell} to be copied.
*/
static copy(graph: Graph, cells?: Cell[]) {
static copy(graph: Graph, cells?: Cell[]): Cell[] {
cells = cells || graph.getSelectionCells();
const result = getTopmostCells(graph.getExportableCells(cells));
Clipboard.insertCount = 1;
Expand All @@ -173,17 +159,12 @@ class Clipboard {
}

/**
* Pastes the {@link cells} into the specified graph restoring
* the relation to {@link parents}, if possible. If the parents
* are no longer in the graph or invisible then the
* cells are added to the graph's default or into the
* swimlane under the cell's new location if one exists.
* The cells are added to the graph using {@link graph.importCells}
* and returned.
* Pastes the {@link Cell}s into the specified graph associating them to the default parent.
* The cells are added to the graph using {@link graph.importCells} and returned.
*
* @param graph - {@link graph} to paste the {@link cells} into.
* @param graph - {@link Graph} to paste the {@link Cell}s into.
*/
static paste(graph: Graph) {
static paste(graph: Graph): Cell[] | null {
let cells = null;

if (!Clipboard.isEmpty() && Clipboard.getCells()) {
Expand Down
29 changes: 0 additions & 29 deletions packages/core/src/util/Utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,6 @@ export const getValue = (array: any, key: string, defaultValue?: any) => {
};

export const copyTextToClipboard = (text: string): void => {
// Credit: https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript
if (!navigator.clipboard) {
fallbackCopyTextToClipboard(text);
return;
}
navigator.clipboard.writeText(text).then(
function () {
GlobalConfig.logger.info('Async: Copying to clipboard was successful!');
Expand All @@ -112,30 +107,6 @@ export const copyTextToClipboard = (text: string): void => {
);
};

const fallbackCopyTextToClipboard = (text: string): void => {
const textArea = document.createElement('textarea');
textArea.value = text;

// Avoid scrolling to bottom
textArea.style.top = '0';
textArea.style.left = '0';
textArea.style.position = 'fixed';

document.body.appendChild(textArea);
textArea.focus();
textArea.select();

try {
const successful = document.execCommand('copy');
const msg = successful ? 'successful' : 'unsuccessful';
GlobalConfig.logger.info(`Fallback: Copying text command was ${msg}`);
} catch (err) {
GlobalConfig.logger.error('Fallback: Oops, unable to copy', err);
}

document.body.removeChild(textArea);
};

/**
* If `baseTimestamp` is provided and not zero, returns a message describing the elapsed milliseconds since this value.
* Otherwise, returns an empty string.
Expand Down