From 0591c37a110616fc7a7b7af4ef2e6a51edb19b3c Mon Sep 17 00:00:00 2001 From: Junsik Shim Date: Sat, 13 Aug 2022 17:51:39 +0900 Subject: [PATCH 1/2] Fix CellArray related warnings. #96 --- packages/core/src/editor/EditorToolbar.ts | 123 +++--- packages/core/src/index.ts | 6 +- packages/core/src/util/Clipboard.ts | 14 +- packages/core/src/util/styleUtils.ts | 8 +- packages/core/src/util/treeTraversal.ts | 3 +- packages/core/src/util/xmlUtils.ts | 45 +- packages/core/src/view/Graph.ts | 5 +- packages/core/src/view/GraphDataModel.ts | 11 +- packages/core/src/view/GraphSelectionModel.ts | 87 ++-- packages/core/src/view/GraphView.ts | 5 +- packages/core/src/view/animate/Morphing.ts | 22 +- packages/core/src/view/cell/Cell.ts | 35 +- packages/core/src/view/cell/CellArray.ts | 416 +++++++++--------- packages/core/src/view/cell/CellRenderer.ts | 3 +- .../core/src/view/cell/TemporaryCellStates.ts | 7 +- packages/core/src/view/cell/VertexHandle.ts | 3 +- .../src/view/handler/CellEditorHandler.ts | 14 +- .../src/view/handler/ConnectionHandler.ts | 3 +- .../core/src/view/handler/SelectionHandler.ts | 39 +- .../core/src/view/handler/VertexHandler.ts | 15 +- packages/core/src/view/layout/CircleLayout.ts | 5 +- .../core/src/view/layout/CompactTreeLayout.ts | 67 +-- .../core/src/view/layout/FastOrganicLayout.ts | 5 +- packages/core/src/view/layout/GraphLayout.ts | 7 +- .../src/view/layout/HierarchicalLayout.ts | 51 ++- .../core/src/view/layout/LayoutManager.ts | 32 +- .../src/view/layout/ParallelEdgeLayout.ts | 7 +- packages/core/src/view/layout/StackLayout.ts | 21 +- .../core/src/view/layout/SwimlaneLayout.ts | 77 ++-- .../core/src/view/layout/SwimlaneManager.ts | 5 +- .../layout/datatypes/GraphHierarchyEdge.ts | 9 +- .../hierarchical/GraphHierarchyModel.ts | 43 +- .../view/layout/hierarchical/SwimlaneModel.ts | 67 ++- packages/core/src/view/mixins/CellsMixin.ts | 124 +++--- .../core/src/view/mixins/ConnectionsMixin.ts | 57 +-- .../core/src/view/mixins/DragDropMixin.ts | 5 +- packages/core/src/view/mixins/EdgeMixin.ts | 31 +- packages/core/src/view/mixins/FoldingMixin.ts | 11 +- .../core/src/view/mixins/GroupingMixin.ts | 54 +-- packages/core/src/view/mixins/OrderMixin.ts | 18 +- .../core/src/view/mixins/SelectionMixin.ts | 24 +- .../core/src/view/mixins/SwimlaneMixin.ts | 9 +- .../core/src/view/mixins/TerminalMixin.ts | 7 +- packages/core/src/view/mixins/VertexMixin.ts | 3 +- packages/core/src/view/other/PrintPreview.ts | 58 ++- .../view/undoable_changes/SelectionChange.ts | 12 +- packages/html/stories/DragSource.stories.js | 14 +- packages/html/stories/HoverIcons.stories.js | 5 +- packages/html/stories/Toolbar.stories.js | 3 +- 49 files changed, 828 insertions(+), 867 deletions(-) diff --git a/packages/core/src/editor/EditorToolbar.ts b/packages/core/src/editor/EditorToolbar.ts index 0f8ecc41e..71690471f 100644 --- a/packages/core/src/editor/EditorToolbar.ts +++ b/packages/core/src/editor/EditorToolbar.ts @@ -14,7 +14,6 @@ import { getClientX, getClientY } from '../util/EventUtils'; import { makeDraggable } from '../util/gestureUtils'; import Editor from './Editor'; import Cell from '../view/cell/Cell'; -import CellArray from '../view/cell/CellArray'; import { Graph } from '../view/Graph'; import EventObject from '../view/event/EventObject'; import ObjectCodec from '../serialization/ObjectCodec'; @@ -51,7 +50,7 @@ import type { DropHandler } from '../view/other/DragSource'; * description of the configuration format. */ export class EditorToolbar { - constructor(container: HTMLElement | null=null, editor: Editor | null=null) { + constructor(container: HTMLElement | null = null, editor: Editor | null = null) { this.editor = editor; if (container != null && editor != null) { @@ -97,18 +96,21 @@ export class EditorToolbar { // Installs the insert function in the editor if an item is // selected in the toolbar - this.toolbar.addListener(InternalEvent.SELECT, (sender: Element, evt: EventObject) => { - const funct = evt.getProperty('function'); + this.toolbar.addListener( + InternalEvent.SELECT, + (sender: Element, evt: EventObject) => { + const funct = evt.getProperty('function'); - if (funct != null) { - (this.editor).insertFunction = () => { - funct.apply(this, [container]); - (this.toolbar).resetMode(); - }; - } else { - (this.editor).insertFunction = null; + if (funct != null) { + (this.editor).insertFunction = () => { + funct.apply(this, [container]); + (this.toolbar).resetMode(); + }; + } else { + (this.editor).insertFunction = null; + } } - }); + ); // Resets the selected tool after a doubleclick or escape keystroke this.resetHandler = () => { @@ -117,7 +119,10 @@ export class EditorToolbar { } }; - (this.editor).graph.addListener(InternalEvent.DOUBLE_CLICK, this.resetHandler); + (this.editor).graph.addListener( + InternalEvent.DOUBLE_CLICK, + this.resetHandler + ); (this.editor).addListener(InternalEvent.ESCAPE, this.resetHandler); } } @@ -189,7 +194,11 @@ export class EditorToolbar { * @param title - String that represents the title of the combo. * @param value - Object that represents the value of the option. */ - addOption(combo: HTMLSelectElement, title: string, value: string | ((evt: any) => void) | null): HTMLElement { + addOption( + combo: HTMLSelectElement, + title: string, + value: string | ((evt: any) => void) | null + ): HTMLElement { return (this.toolbar).addOption(combo, title, value); } @@ -207,14 +216,14 @@ export class EditorToolbar { title: string, icon: string, mode: string, - pressed: string | null=null, - funct: Function | null=null + pressed: string | null = null, + funct: Function | null = null ): any { const clickHandler = () => { (this.editor).setMode(mode); if (funct != null) { - funct((this.editor)); + funct(this.editor); } }; return (this.toolbar).addSwitchMode(title, icon, clickHandler, pressed); @@ -242,8 +251,13 @@ export class EditorToolbar { icon: string, ptype: Function | Cell, pressed: string, - insert: (editor: Editor, cell: Cell, me: MouseEvent, cellUnderMousePointer?: Cell | null) => void, - toggle: boolean=true + insert: ( + editor: Editor, + cell: Cell, + me: MouseEvent, + cellUnderMousePointer?: Cell | null + ) => void, + toggle: boolean = true ): HTMLImageElement | HTMLButtonElement { // Creates a wrapper function that is in charge of constructing // the new cell instance to be inserted into the graph @@ -261,7 +275,7 @@ export class EditorToolbar { // after this item has been selected in the toolbar const clickHandler = (evt: MouseEvent, cell: Cell | null) => { if (typeof insert === 'function') { - insert((this.editor), factory(), evt, cell); + insert(this.editor, factory(), evt, cell); } else { this.drop(factory(), evt, cell); } @@ -270,11 +284,22 @@ export class EditorToolbar { InternalEvent.consume(evt); }; - const img = (this.toolbar).addMode(title, icon, clickHandler, pressed, null, toggle); + const img = (this.toolbar).addMode( + title, + icon, + clickHandler, + pressed, + null, + toggle + ); // Creates a wrapper function that calls the click handler without // the graph argument - const dropHandler: DropHandler = (graph: Graph, evt: MouseEvent, cell: Cell | null) => { + const dropHandler: DropHandler = ( + graph: Graph, + evt: MouseEvent, + cell: Cell | null + ) => { clickHandler(evt, cell); }; @@ -291,8 +316,8 @@ export class EditorToolbar { * @param evt - Mouse event that represents the drop. * @param target - Optional {@link Cell} that represents the drop target. */ - drop(vertex: Cell, evt: MouseEvent, target: Cell | null=null): void { - const { graph } = (this.editor); + drop(vertex: Cell, evt: MouseEvent, target: Cell | null = null): void { + const { graph } = this.editor; const model = graph.getDataModel(); if ( @@ -301,7 +326,7 @@ export class EditorToolbar { !this.connectOnDrop || !target.isConnectable() ) { - while (target != null && !graph.isValidDropTarget(target, new CellArray(vertex), evt)) { + while (target != null && !graph.isValidDropTarget(target, [vertex], evt)) { target = target.getParent(); } this.insert(vertex, evt, target); @@ -318,8 +343,8 @@ export class EditorToolbar { * @param evt - Mouse event that represents the drop. * @param target - Optional {@link Cell} that represents the parent. */ - insert(vertex: Cell, evt: MouseEvent, target: Cell | null=null): any { - const { graph } = (this.editor); + insert(vertex: Cell, evt: MouseEvent, target: Cell | null = null): any { + const { graph } = this.editor; if (graph.canImportCell(vertex)) { const x = getClientX(evt); @@ -327,8 +352,12 @@ export class EditorToolbar { const pt = convertPoint(graph.container, x, y); // Splits the target edge or inserts into target group - if (target && graph.isSplitEnabled() && graph.isSplitTarget(target, new CellArray(vertex), evt)) { - return graph.splitEdge(target, new CellArray(vertex), null, pt.x, pt.y); + if ( + target && + graph.isSplitEnabled() && + graph.isSplitTarget(target, [vertex], evt) + ) { + return graph.splitEdge(target, [vertex], null, pt.x, pt.y); } return (this.editor).addVertex(target, vertex, pt.x, pt.y); } @@ -342,7 +371,7 @@ export class EditorToolbar { * @param evt - Mouse event that represents the drop. * @param source - Optional {@link Cell} that represents the source terminal. */ - connect(vertex: Cell, evt: MouseEvent, source: Cell | null=null): void { + connect(vertex: Cell, evt: MouseEvent, source: Cell | null = null): void { const { graph } = this.editor; const model = graph.getDataModel(); @@ -396,7 +425,7 @@ export class EditorToolbar { model.endUpdate(); } - graph.setSelectionCells(new CellArray(vertex, edge)); + graph.setSelectionCells([vertex, edge]); graph.scrollCellToVisible(vertex); } } @@ -575,21 +604,16 @@ export class EditorToolbarCodec extends ObjectCodec { const mode = node.getAttribute('mode'); const template = node.getAttribute('template'); const toggle = node.getAttribute('toggle') != '0'; - const text = getTextContent(node); + const text = getTextContent((node)); let elt = null; let funct: any; if (action != null) { elt = into.addItem(as, icon, action, pressedIcon); } else if (mode != null) { - funct = EditorToolbarCodec.allowEval - ? eval(text) - : null; + funct = EditorToolbarCodec.allowEval ? eval(text) : null; elt = into.addMode(as, icon, mode, pressedIcon, funct); - } else if ( - template != null || - (text != null && text.length > 0) - ) { + } else if (template != null || (text != null && text.length > 0)) { let cell = template ? editor.templates[template] : null; const style = node.getAttribute('style'); @@ -600,11 +624,7 @@ export class EditorToolbarCodec extends ObjectCodec { let insertFunction = null; - if ( - text != null && - text.length > 0 && - EditorToolbarCodec.allowEval - ) { + if (text != null && text.length > 0 && EditorToolbarCodec.allowEval) { insertFunction = eval(text); } @@ -656,14 +676,7 @@ export class EditorToolbarCodec extends ObjectCodec { return null; }; - const img = into.addPrototype( - as, - icon, - create, - null, - null, - toggle - ); + const img = into.addPrototype(as, icon, create, null, null, toggle); select = into.addCombo(); // Selects the toolbar icon if a selection change @@ -691,11 +704,7 @@ export class EditorToolbarCodec extends ObjectCodec { } else if (child.nodeName === 'add') { const lab = child.getAttribute('as'); const tmp = child.getAttribute('template'); - const option = into.addOption( - select, - lab, - tmp || template - ); + const option = into.addOption(select, lab, tmp || template); option.cellStyle = child.getAttribute('style'); } } diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index b55f847da..e48b1cd07 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -42,7 +42,10 @@ export { default as GeometryChange } from './view/undoable_changes/GeometryChang export { RootChange, RootChangeCodec } from './view/undoable_changes/RootChange'; export { default as SelectionChange } from './view/undoable_changes/SelectionChange'; export { default as StyleChange } from './view/undoable_changes/StyleChange'; -export { TerminalChange, TerminalChangeCodec } from './view/undoable_changes/TerminalChange'; +export { + TerminalChange, + TerminalChangeCodec, +} from './view/undoable_changes/TerminalChange'; export { default as ValueChange } from './view/undoable_changes/ValueChange'; export { default as VisibleChange } from './view/undoable_changes/VisibleChange'; @@ -204,7 +207,6 @@ export { default as CellPath } from './view/cell/CellPath'; export { default as CellRenderer } from './view/cell/CellRenderer'; export { default as CellState } from './view/cell/CellState'; export { default as CellStatePreview } from './view/cell/CellStatePreview'; -export { default as CellArray } from './view/cell/CellArray'; export { default as TemporaryCellStates } from './view/cell/TemporaryCellStates'; export { default as ConnectionConstraint } from './view/other/ConnectionConstraint'; export { default as Multiplicity } from './view/other/Multiplicity'; diff --git a/packages/core/src/util/Clipboard.ts b/packages/core/src/util/Clipboard.ts index 5da7c266a..d77fda22b 100644 --- a/packages/core/src/util/Clipboard.ts +++ b/packages/core/src/util/Clipboard.ts @@ -5,8 +5,8 @@ * Type definitions from the typed-mxgraph project */ +import Cell from '../view/cell/Cell'; import { Graph } from '../view/Graph'; -import CellArray from '../view/cell/CellArray'; /** * @class @@ -93,12 +93,12 @@ class Clipboard { /** * Holds the array of {@link mxCell} currently in the clipboard. */ - static cells: CellArray; + static cells: Cell[]; /** * Sets the cells in the clipboard. Fires a {@link mxEvent.CHANGE} event. */ - static setCells(cells: CellArray) { + static setCells(cells: Cell[]) { Clipboard.cells = cells; } @@ -124,7 +124,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be cut. * @param cells - Optional array of {@link mxCell} to be cut. */ - static cut(graph: Graph, cells?: CellArray) { + static cut(graph: Graph, cells: Cell[] = []) { cells = Clipboard.copy(graph, cells); Clipboard.insertCount = 0; Clipboard.removeCells(graph, cells); @@ -139,7 +139,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be cut. * @param cells - Array of {@link mxCell} to be cut. */ - static removeCells(graph: Graph, cells: CellArray) { + static removeCells(graph: Graph, cells: Cell[]) { // @ts-ignore graph.removeCells(cells); } @@ -152,7 +152,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be copied. * @param cells - Optional array of {@link mxCell} to be copied. */ - static copy(graph: Graph, cells?: CellArray) { + static copy(graph: Graph, cells?: Cell[]) { cells = cells || graph.getSelectionCells(); const result = graph.getExportableCells(cells).getTopmostCells(); Clipboard.insertCount = 1; @@ -184,7 +184,7 @@ class Clipboard { // Increments the counter and selects the inserted cells Clipboard.insertCount++; - graph.setSelectionCells(cells); + graph.setSelectionCells(cells); } return cells; diff --git a/packages/core/src/util/styleUtils.ts b/packages/core/src/util/styleUtils.ts index ff3834364..54597ffe7 100644 --- a/packages/core/src/util/styleUtils.ts +++ b/packages/core/src/util/styleUtils.ts @@ -18,7 +18,7 @@ import CellPath from '../view/cell/CellPath'; import Rectangle from '../view/geometry/Rectangle'; import Cell from '../view/cell/Cell'; import GraphDataModel from '../view/GraphDataModel'; -import CellArray from '../view/cell/CellArray'; + import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../types'; /** @@ -426,7 +426,7 @@ export const removeAllStylenames = (style: string) => { */ export const setCellStyles = ( model: GraphDataModel, - cells: CellArray, + cells: Cell[], key: keyof CellStateStyle, value: any ) => { @@ -522,7 +522,7 @@ export const setStyle = (style: string | null, key: string, value: any) => { */ export const setCellStyleFlags = ( model: GraphDataModel, - cells: CellArray, + cells: Cell[], key: NumericCellStateStyleKeys, flag: number, value: boolean @@ -673,7 +673,7 @@ export const getSizeForString = ( * Sorts the given cells according to the order in the cell hierarchy. * Ascending is optional and defaults to true. */ -export const sortCells = (cells: CellArray, ascending = true): CellArray => { +export const sortCells = (cells: Cell[], ascending = true): Cell[] => { const lookup = new Dictionary(); cells.sort((o1, o2) => { diff --git a/packages/core/src/util/treeTraversal.ts b/packages/core/src/util/treeTraversal.ts index 3bcb5e1a7..76263f601 100644 --- a/packages/core/src/util/treeTraversal.ts +++ b/packages/core/src/util/treeTraversal.ts @@ -1,5 +1,4 @@ import Cell from '../view/cell/Cell'; -import CellArray from '../view/cell/CellArray'; import Dictionary from './Dictionary'; import { Graph } from '../view/Graph'; @@ -26,7 +25,7 @@ export function findTreeRoots( isolate: boolean = false, invert: boolean = false ) { - const roots: CellArray = new CellArray(); + const roots: Cell[] = []; if (parent != null) { let best = null; diff --git a/packages/core/src/util/xmlUtils.ts b/packages/core/src/util/xmlUtils.ts index 4b1f0fc2f..ef598dbf6 100644 --- a/packages/core/src/util/xmlUtils.ts +++ b/packages/core/src/util/xmlUtils.ts @@ -1,4 +1,3 @@ - /** * Copyright (c) 2006-2015, JGraph Ltd * Copyright (c) 2006-2015, Gaudenz Alder @@ -8,7 +7,6 @@ import { DIALECT, NODETYPE, NS_SVG } from './Constants'; import Point from '../view/geometry/Point'; import Cell from '../view/cell/Cell'; -import CellArray from '../view/cell/CellArray'; import { Graph } from '../view/Graph'; import { htmlEntities, trim } from './StringUtils'; import TemporaryCellStates from '../view/cell/TemporaryCellStates'; @@ -26,19 +24,18 @@ export const createXmlDocument = () => { export const parseXml = (xmlString: string): HTMLElement => { return new DOMParser().parseFromString(xmlString, 'text/xml').documentElement; -} +}; export const getViewXml = ( graph: Graph, - scale: number=1, - cells: CellArray | null=null, - x0: number=0, - y0: number=0 + scale: number = 1, + cells: Cell[] | null = null, + x0: number = 0, + y0: number = 0 ) => { - if (cells == null) { const model = graph.getDataModel(); - cells = new CellArray(model.getRoot()); + cells = [model.getRoot()]; } const view = graph.getView(); @@ -102,7 +99,7 @@ export const getViewXml = ( * @param linefeed Optional string that linefeeds are converted into. Default is * */ -export const getXml = (node: Element, linefeed: string=' '): string => { +export const getXml = (node: Element, linefeed: string = ' '): string => { const xmlSerializer = new XMLSerializer(); let xml = xmlSerializer.serializeToString(node); @@ -124,7 +121,13 @@ export const getXml = (node: Element, linefeed: string=' '): string => { * Default is an empty string. * @param newline Option string that represents a linefeed. Default is '\n'. */ -export const getPrettyXml = (node: Element, tab: string, indent: string, newline: string, ns: string): string => { +export const getPrettyXml = ( + node: Element, + tab: string, + indent: string, + newline: string, + ns: string +): string => { const result = []; if (node != null) { @@ -142,7 +145,13 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline if (node.nodeType === NODETYPE.DOCUMENT) { result.push( - getPrettyXml((node).documentElement, tab, indent, newline, ns) + getPrettyXml( + ((node)).documentElement, + tab, + indent, + newline, + ns + ) ); } else if (node.nodeType === NODETYPE.DOCUMENT_FRAGMENT) { let tmp = node.firstChild; @@ -154,19 +163,19 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline } } } else if (node.nodeType === NODETYPE.COMMENT) { - const value = getTextContent(node); + const value = getTextContent((node)); if (value.length > 0) { result.push(`${indent}${newline}`); } } else if (node.nodeType === NODETYPE.TEXT) { - const value = trim(getTextContent(node)); + const value = trim(getTextContent((node))); if (value && value.length > 0) { result.push(indent + htmlEntities(value, false) + newline); } } else if (node.nodeType === NODETYPE.CDATA) { - const value = getTextContent(node); + const value = getTextContent((node)); if (value.length > 0) { result.push(`${indent}${newline}`); while (tmp != null) { - result.push( - getPrettyXml(tmp, tab, indent + tab, newline, ns) - ); + result.push(getPrettyXml(tmp, tab, indent + tab, newline, ns)); tmp = tmp.nextSibling; } @@ -212,7 +219,7 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline * Returns the first node where attr equals value. * This implementation does not use XPath. */ - export const findNode = ( +export const findNode = ( node: Element, attr: string, value: StyleValue diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts index f92c1473d..12bd1cdef 100644 --- a/packages/core/src/view/Graph.ts +++ b/packages/core/src/view/Graph.ts @@ -46,10 +46,11 @@ import ObjectCodec from '../serialization/ObjectCodec'; import type { GraphPlugin, GraphPluginConstructor, MouseListenerSet } from '../types'; import Multiplicity from './other/Multiplicity'; -import CellArray from './cell/CellArray'; import ImageBundle from './image/ImageBundle'; import GraphSelectionModel from './GraphSelectionModel'; +import './cell/CellArray'; + export const defaultPlugins: GraphPluginConstructor[] = [ CellEditorHandler, TooltipHandler, @@ -91,7 +92,7 @@ class Graph extends EventSource { * Group: Variables (that maybe should be in the mixins, but need to be created for each new class instance) *****************************************************************************/ - cells = new CellArray(); + cells: Cell[] = []; imageBundles: ImageBundle[] = []; diff --git a/packages/core/src/view/GraphDataModel.ts b/packages/core/src/view/GraphDataModel.ts index 427ebae4f..882ef84d8 100644 --- a/packages/core/src/view/GraphDataModel.ts +++ b/packages/core/src/view/GraphDataModel.ts @@ -20,7 +20,6 @@ import TerminalChange from './undoable_changes/TerminalChange'; import ValueChange from './undoable_changes/ValueChange'; import VisibleChange from './undoable_changes/VisibleChange'; import Geometry from './geometry/Geometry'; -import CellArray from './cell/CellArray'; import ObjectCodec from '../serialization/ObjectCodec'; import CodecRegistry from '../serialization/CodecRegistry'; @@ -326,8 +325,8 @@ export class GraphDataModel extends EventSource { return this.cells ? this.cells[id] : null; } - filterCells(cells: CellArray, filter: FilterFunction) { - return new CellArray(...cells).filterCells(filter); + filterCells(cells: Cell[], filter: FilterFunction) { + return cells.filterCells(filter); } getRoot(cell: Cell | null = null) { @@ -747,7 +746,7 @@ export class GraphDataModel extends EventSource { * @param directed Optional boolean that specifies if the direction of the * edge should be taken into account. Default is false. */ - getEdgesBetween(source: Cell, target: Cell, directed: boolean = false): CellArray { + getEdgesBetween(source: Cell, target: Cell, directed: boolean = false): Cell[] { const tmp1 = source.getEdgeCount(); const tmp2 = target.getEdgeCount(); @@ -762,7 +761,7 @@ export class GraphDataModel extends EventSource { terminal = target; } - const result = new CellArray(); + const result = []; // Checks if the edge is connected to the correct // cell and returns the first match @@ -1157,7 +1156,7 @@ export class GraphDataModel extends EventSource { */ cloneCell(cell: Cell | null = null, includeChildren: boolean = true): Cell | null { if (cell != null) { - return new CellArray(cell).cloneCells(includeChildren)[0]; + return [cell].cloneCells(includeChildren)[0]; } return null; } diff --git a/packages/core/src/view/GraphSelectionModel.ts b/packages/core/src/view/GraphSelectionModel.ts index 105bc2564..3aaf5c5ac 100644 --- a/packages/core/src/view/GraphSelectionModel.ts +++ b/packages/core/src/view/GraphSelectionModel.ts @@ -3,64 +3,63 @@ * Copyright (c) 2006-2015, Gaudenz Alder */ -import Client from "../Client"; -import CellArray from "./cell/CellArray" +import Client from '../Client'; import EventSource from '../view/event/EventSource'; -import { Graph } from "./Graph" -import Cell from "./cell/Cell"; -import SelectionChange from "./undoable_changes/SelectionChange"; -import UndoableEdit from "./undoable_changes/UndoableEdit"; -import EventObject from "./event/EventObject"; -import InternalEvent from "./event/InternalEvent"; +import { Graph } from './Graph'; +import Cell from './cell/Cell'; +import SelectionChange from './undoable_changes/SelectionChange'; +import UndoableEdit from './undoable_changes/UndoableEdit'; +import EventObject from './event/EventObject'; +import InternalEvent from './event/InternalEvent'; /** * Class: mxGraphSelectionModel * * Implements the selection model for a graph. Here is a listener that handles * all removed selection cells. - * + * * (code) * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt) * { * var cells = evt.getProperty('added'); - * + * * for (var i = 0; i < cells.length; i++) * { * // Handle cells[i]... * } * }); * (end) - * + * * Event: mxEvent.UNDO - * + * * Fires after the selection was changed in . The * edit property contains the {@link UndoableEdit} which contains the * {@link SelectionChange}. - * + * * Event: mxEvent.CHANGE - * + * * Fires after the selection changes by executing an {@link SelectionChange}. The * added and removed properties contain arrays of * cells that have been added to or removed from the selection, respectively. * The names are inverted due to historic reasons. This cannot be changed. - * + * * Constructor: mxGraphSelectionModel * * Constructs a new graph selection model for the given {@link Graph}. - * + * * Parameters: - * + * * graph - Reference to the enclosing {@link Graph}. */ class GraphSelectionModel extends EventSource { constructor(graph: Graph) { super(); this.graph = graph; - this.cells = new CellArray(); + this.cells = []; } graph: Graph; - cells: CellArray; + cells: Cell[]; /** * Specifies the resource key for the status message after a long operation. @@ -70,16 +69,16 @@ class GraphSelectionModel extends EventSource { doneResource = Client.language !== 'none' ? 'done' : ''; /** - * Specifies the resource key for the status message while the selection is - * being updated. If the resource for this key does not exist then the - * value is used as the status message. Default is 'updatingSelection'. - */ + * Specifies the resource key for the status message while the selection is + * being updated. If the resource for this key does not exist then the + * value is used as the status message. Default is 'updatingSelection'. + */ updatingSelectionResource = Client.language !== 'none' ? 'updatingSelection' : ''; - + /** - * Specifies if only one selected item at a time is allowed. - * Default is false. - */ + * Specifies if only one selected item at a time is allowed. + * Default is false. + */ singleSelection = false; /** @@ -98,7 +97,7 @@ class GraphSelectionModel extends EventSource { setSingleSelection(singleSelection: boolean) { this.singleSelection = singleSelection; } - + /** * Returns true if the given {@link Cell} is selected. */ @@ -127,7 +126,7 @@ class GraphSelectionModel extends EventSource { * @param cell {@link mxCell} to be selected. */ setCell(cell: Cell) { - this.setCells(cell ? new CellArray(cell) : new CellArray()); + this.setCells(cell ? [cell] : []); } /** @@ -135,12 +134,12 @@ class GraphSelectionModel extends EventSource { * * @param cells Array of {@link Cell} to be selected. */ - setCells(cells: CellArray) { + setCells(cells: Cell[]) { if (this.singleSelection) { - cells = new CellArray(this.getFirstSelectableCell(cells)); + cells = [this.getFirstSelectableCell(cells)]; } - const tmp = new CellArray(); + const tmp = []; for (let i = 0; i < cells.length; i += 1) { if (this.graph.isCellSelectable(cells[i])) { tmp.push(cells[i]); @@ -152,7 +151,7 @@ class GraphSelectionModel extends EventSource { /** * Returns the first selectable cell in the given array of cells. */ - getFirstSelectableCell(cells: CellArray) { + getFirstSelectableCell(cells: Cell[]) { for (let i = 0; i < cells.length; i += 1) { if (this.graph.isCellSelectable(cells[i])) { return cells[i]; @@ -167,7 +166,7 @@ class GraphSelectionModel extends EventSource { * @param cell {@link mxCell} to add to the selection. */ addCell(cell: Cell) { - this.addCells(new CellArray(cell)); + this.addCells([cell]); } /** @@ -176,16 +175,16 @@ class GraphSelectionModel extends EventSource { * * @param cells Array of {@link Cell} to add to the selection. */ - addCells(cells: CellArray) { + addCells(cells: Cell[]) { let remove = null; if (this.singleSelection) { remove = this.cells; const selectableCell = this.getFirstSelectableCell(cells); - cells = selectableCell ? new CellArray(selectableCell) : new CellArray(); + cells = selectableCell ? [selectableCell] : []; } - const tmp = new CellArray(); + const tmp = []; for (let i = 0; i < cells.length; i += 1) { if (!this.isSelected(cells[i]) && this.graph.isCellSelectable(cells[i])) { tmp.push(cells[i]); @@ -202,7 +201,7 @@ class GraphSelectionModel extends EventSource { * @param cell {@link mxCell} to remove from the selection. */ removeCell(cell: Cell) { - this.removeCells(new CellArray(cell)); + this.removeCells([cell]); } /** @@ -211,8 +210,8 @@ class GraphSelectionModel extends EventSource { * * @param cells {@link mxCell}s to remove from the selection. */ - removeCells(cells: CellArray) { - const tmp = new CellArray(); + removeCells(cells: Cell[]) { + const tmp = []; for (let i = 0; i < cells.length; i += 1) { if (this.isSelected(cells[i])) { @@ -228,16 +227,12 @@ class GraphSelectionModel extends EventSource { * @param added Array of {@link Cell} to add to the selection. * @param remove Array of {@link Cell} to remove from the selection. */ - changeSelection(added: CellArray | null=null, removed: CellArray | null=null) { + changeSelection(added: Cell[] | null = null, removed: Cell[] | null = null) { if ( (added && added.length > 0 && added[0]) || (removed && removed.length > 0 && removed[0]) ) { - const change = new SelectionChange( - this.graph, - added || new CellArray(), - removed || new CellArray() - ); + const change = new SelectionChange(this.graph, added || [], removed || []); change.execute(); const edit = new UndoableEdit(this.graph, false); edit.add(change); diff --git a/packages/core/src/view/GraphView.ts b/packages/core/src/view/GraphView.ts index 4d81838dd..ac80fc5c8 100644 --- a/packages/core/src/view/GraphView.ts +++ b/packages/core/src/view/GraphView.ts @@ -31,7 +31,6 @@ import ConnectionConstraint from './other/ConnectionConstraint'; import PopupMenuHandler from './handler/PopupMenuHandler'; import { getClientX, getClientY, getSource, isConsumed } from '../util/EventUtils'; import { clone } from '../util/cloneUtils'; -import CellArray from './cell/CellArray'; import type { Graph } from './Graph'; import StyleRegistry from './style/StyleRegistry'; import TooltipHandler from './handler/TooltipHandler'; @@ -335,7 +334,7 @@ export class GraphView extends EventSource { * * @param cells Array of {@link Cell} whose bounds should be returned. */ - getBounds(cells: CellArray) { + getBounds(cells: Cell[]) { let result: Rectangle | null = null; if (cells.length > 0) { @@ -1962,7 +1961,7 @@ export class GraphView extends EventSource { * have less elements than the given array. If no argument is given, then * this returns {@link states}. */ - getCellStates(cells: CellArray | null = null) { + getCellStates(cells: Cell[] | null = null) { if (!cells) { return this.states.getValues(); } diff --git a/packages/core/src/view/animate/Morphing.ts b/packages/core/src/view/animate/Morphing.ts index 9c7bb76dd..3d7aafddc 100644 --- a/packages/core/src/view/animate/Morphing.ts +++ b/packages/core/src/view/animate/Morphing.ts @@ -10,7 +10,6 @@ import Animation from './Animation'; import CellState from '../cell/CellState'; import Cell from '../cell/Cell'; import { Graph } from '../Graph'; -import CellArray from '../cell/CellArray'; /** * Implements animation for morphing cells. Here is an example of @@ -45,7 +44,7 @@ import CellArray from '../cell/CellArray'; * @param delay Optional delay between the animation steps. Passed to . */ class Morphing extends Animation { - constructor(graph: Graph, steps: number=6, ease: number=1.5, delay: number) { + constructor(graph: Graph, steps: number = 6, ease: number = 1.5, delay: number) { super(delay); this.graph = graph; this.steps = steps; @@ -78,7 +77,7 @@ class Morphing extends Animation { * then all cells are checked and animated if they have been moved * in the current transaction. */ - cells: CellArray | null = null; + cells: Cell[] | null = null; /** * Animation step. @@ -115,7 +114,7 @@ class Morphing extends Animation { /** * Animates the given cell state using . */ - animateCell(cell: Cell, move: CellStatePreview, recurse: boolean=false) { + animateCell(cell: Cell, move: CellStatePreview, recurse: boolean = false) { const state = this.graph.getView().getState(cell); let delta = null; @@ -124,10 +123,7 @@ class Morphing extends Animation { // change by subtracting the given delta vector from that location delta = this.getDelta(state); - if ( - cell.isVertex() && - (delta.x != 0 || delta.y != 0) - ) { + if (cell.isVertex() && (delta.x != 0 || delta.y != 0)) { const translate = this.graph.view.getTranslate(); const scale = this.graph.view.getScale(); @@ -142,11 +138,7 @@ class Morphing extends Animation { const childCount = cell.getChildCount(); for (let i = 0; i < childCount; i += 1) { - this.animateCell( - cell.getChildAt(i), - move, - recurse - ); + this.animateCell(cell.getChildAt(i), move, recurse); } } } @@ -155,7 +147,7 @@ class Morphing extends Animation { * Returns true if the animation should not recursively find more * deltas for children if the given parent state has been animated. */ - stopRecursion(state: CellState | null=null, delta: Point | null=null) { + stopRecursion(state: CellState | null = null, delta: Point | null = null) { return delta != null && (delta.x != 0 || delta.y != 0); } @@ -178,7 +170,7 @@ class Morphing extends Animation { * by using caching inside this method as the result per cell never changes * during the lifecycle of this object. */ - getOriginForCell(cell: Cell | null=null): Point | null { + getOriginForCell(cell: Cell | null = null): Point | null { let result = null; if (cell != null) { diff --git a/packages/core/src/view/cell/Cell.ts b/packages/core/src/view/cell/Cell.ts index f1a8a3d79..907e78023 100644 --- a/packages/core/src/view/cell/Cell.ts +++ b/packages/core/src/view/cell/Cell.ts @@ -11,7 +11,6 @@ import CellOverlay from './CellOverlay'; import { clone } from '../../util/cloneUtils'; import Point from '../geometry/Point'; import CellPath from './CellPath'; -import CellArray from './CellArray'; import { isNotNullish } from '../../util/Utils'; import ObjectCodec from '../../serialization/ObjectCodec'; import CodecRegistry from '../../serialization/CodecRegistry'; @@ -80,8 +79,8 @@ export class Cell { } // TODO: Document me!!! - getChildren(): CellArray { - return this.children || new CellArray(); + getChildren(): Cell[] { + return this.children || []; } // TODO: Document me! @@ -157,12 +156,12 @@ export class Cell { /** * Holds the child cells. */ - children: CellArray = new CellArray(); + children: Cell[] = []; /** * Holds the edges. */ - edges: CellArray = new CellArray(); + edges: Cell[] = []; /** * List of members that should not be cloned inside . This field is @@ -673,14 +672,14 @@ export class Cell { /** * Returns the child vertices of the given parent. */ - getChildVertices(): CellArray { + getChildVertices() { return this.getChildCells(true, false); } /** * Returns the child edges of the given parent. */ - getChildEdges(): CellArray { + getChildEdges() { return this.getChildCells(false, true); } @@ -693,9 +692,9 @@ export class Cell { * @param edges Boolean indicating if child edges should be returned. * Default is false. */ - getChildCells(vertices: boolean = false, edges: boolean = false): CellArray { + getChildCells(vertices: boolean = false, edges: boolean = false) { const childCount = this.getChildCount(); - const result = new CellArray(); + const result = []; for (let i = 0; i < childCount; i += 1) { const child = this.getChildAt(i); @@ -737,21 +736,21 @@ export class Cell { /** * Returns all edges of the given cell without loops. */ - getConnections(): CellArray { + getConnections() { return this.getEdges(true, true, false); } /** * Returns the incoming edges of the given cell without loops. */ - getIncomingEdges(): CellArray { + getIncomingEdges() { return this.getEdges(true, false, false); } /** * Returns the outgoing edges of the given cell without loops. */ - getOutgoingEdges(): CellArray { + getOutgoingEdges() { return this.getEdges(false, true, false); } @@ -772,9 +771,9 @@ export class Cell { incoming: boolean = true, outgoing: boolean = true, includeLoops: boolean = true - ): CellArray { + ) { const edgeCount = this.getEdgeCount(); - const result = new CellArray(); + const result = []; for (let i = 0; i < edgeCount; i += 1) { const edge = this.getEdgeAt(i); @@ -820,7 +819,7 @@ export class Cell { /** * Returns all descendants of the given cell and the cell itself in an array. */ - getDescendants(): CellArray { + getDescendants() { return this.filterDescendants(null); } @@ -843,9 +842,9 @@ export class Cell { * @param filter JavaScript function that takes an {@link Cell} as an argument * and returns a boolean. */ - filterDescendants(filter: FilterFunction | null): CellArray { + filterDescendants(filter: FilterFunction | null): Cell[] { // Creates a new array for storing the result - let result = new CellArray(); + let result: Cell[] = []; // Checks if the filter returns true for the cell // and adds it to the result array @@ -857,7 +856,7 @@ export class Cell { const childCount = this.getChildCount(); for (let i = 0; i < childCount; i += 1) { const child = this.getChildAt(i); - result = new CellArray(...result.concat(child.filterDescendants(filter))); + result = result.concat(child.filterDescendants(filter)); } return result; diff --git a/packages/core/src/view/cell/CellArray.ts b/packages/core/src/view/cell/CellArray.ts index c5ed71263..5956c110a 100644 --- a/packages/core/src/view/cell/CellArray.ts +++ b/packages/core/src/view/cell/CellArray.ts @@ -2,220 +2,208 @@ import Cell from './Cell'; import Dictionary from '../../util/Dictionary'; import ObjectIdentity from '../../util/ObjectIdentity'; -class CellArray extends Array { - constructor(...items: Cell[]) { - super(...items); - } - - // @ts-ignore - concat(items: any): CellArray { - return new CellArray(...super.concat(items)); - } - - // @ts-ignore - splice(arg0: number, ...args: any): CellArray { - return new CellArray(...super.splice(arg0, ...args)); - } - - // @ts-ignore - slice(...args: any): CellArray { - return new CellArray(...super.slice(...args)); - } - - // @ts-ignore - map(arg0: any, ...args: any): CellArray { - return new CellArray(...(super.map(arg0, ...args))); - } - - // @ts-ignore - filter(arg0: any, ...args: any): CellArray { - return new CellArray(...(super.filter(arg0, ...args))); - } - - /** - * Returns the cells from the given array where the given filter function - * returns true. - */ - filterCells(filter: Function): CellArray { - let result = new CellArray(); - - for (let i = 0; i < this.length; i += 1) { - if (filter(this[i])) { - result.push(this[i]); - } - } - return result; - } - - /** - * Returns all opposite vertices wrt terminal for the given edges, only - * returning sources and/or targets as specified. The result is returned - * as an array of {@link Cell}. - * - * @param {Cell} terminal that specifies the known end of the edges. - * @param sources Boolean that specifies if source terminals should be contained - * in the result. Default is true. - * @param targets Boolean that specifies if target terminals should be contained - * in the result. Default is true. - */ - getOpposites( - terminal: Cell, - sources: boolean = true, - targets: boolean = true - ): CellArray { - const terminals = new CellArray(); - - for (let i = 0; i < this.length; i += 1) { - const source = this[i].getTerminal(true); - const target = this[i].getTerminal(false); - - // Checks if the terminal is the source of - // the edge and if the target should be - // stored in the result - if (source === terminal && target != null && target !== terminal && targets) { - terminals.push(target); - } - - // Checks if the terminal is the taget of - // the edge and if the source should be - // stored in the result - else if (target === terminal && source != null && source !== terminal && sources) { - terminals.push(source); - } - } - return terminals; - } - - /** - * Returns the topmost cells of the hierarchy in an array that contains no - * descendants for each {@link Cell} that it contains. Duplicates should be - * removed in the cells array to improve performance. - */ - getTopmostCells(): CellArray { - const dict = new Dictionary(); - const tmp = new CellArray(); - - for (let i = 0; i < this.length; i += 1) { - dict.put(this[i], true); - } - - for (let i = 0; i < this.length; i += 1) { - const cell = this[i]; - let topmost = true; - let parent = cell.getParent(); - - while (parent != null) { - if (dict.get(parent)) { - topmost = false; - break; - } - parent = parent.getParent(); - } - - if (topmost) { - tmp.push(cell); - } - } - return tmp; - } - - /** - * Returns an array that represents the set (no duplicates) of all parents - * for the given array of cells. - */ - getParents(): CellArray { - const parents = []; - const dict = new Dictionary(); - - for (const cell of this) { - const parent = cell.getParent(); - if (parent != null && !dict.get(parent)) { - dict.put(parent, true); - parents.push(parent); - } - } - return new CellArray(...parents); - } - - /** - * Returns an array of clones for the given array of {@link Cell}`. - * Depending on the value of includeChildren, a deep clone is created for - * each cell. Connections are restored based if the corresponding - * cell is contained in the passed in array. - * - * @param includeChildren Boolean indicating if the cells should be cloned - * with all descendants. - * @param mapping Optional mapping for existing clones. - */ - cloneCells(includeChildren: boolean = true, mapping: any = {}): CellArray { - const clones: CellArray = new CellArray(); - - for (const cell of this) { - clones.push(this.cloneCellImpl(cell, mapping, includeChildren)); - } - - for (let i = 0; i < clones.length; i += 1) { - if (clones[i] != null) { - this.restoreClone(clones[i], this[i], mapping); - } - } - return clones; - } - - /** - * Inner helper method for cloning cells recursively. - * - * @private - */ - cloneCellImpl(cell: Cell, mapping: any = {}, includeChildren: boolean): Cell { - const ident = ObjectIdentity.get(cell); - let clone = mapping ? mapping[ident] : null; - - if (clone == null) { - clone = cell.clone(); - mapping[ident] = clone; - - if (includeChildren) { - const childCount = cell.getChildCount(); - - for (let i = 0; i < childCount; i += 1) { - const cloneChild = this.cloneCellImpl(cell.getChildAt(i), mapping, true); - clone.insert(cloneChild); - } - } - } - return clone; - } - - /** - * Inner helper method for restoring the connections in - * a network of cloned cells. - * - * @private - */ - restoreClone(clone: Cell, cell: Cell, mapping: any): void { - const source = cell.getTerminal(true); - - if (source != null) { - const tmp = mapping[ObjectIdentity.get(source)]; - if (tmp != null) { - tmp.insertEdge(clone, true); - } - } - - const target = cell.getTerminal(false); - if (target != null) { - const tmp = mapping[ObjectIdentity.get(target)]; - if (tmp != null) { - tmp.insertEdge(clone, false); - } - } - - const childCount = clone.getChildCount(); - for (let i = 0; i < childCount; i += 1) { - this.restoreClone(clone.getChildAt(i), cell.getChildAt(i), mapping); - } +declare global { + interface Array { + filterCells: (filter: Function) => T[]; + getOpposites: (terminal: Cell, sources: boolean, targets: boolean) => T[]; + getTopmostCells: () => T[]; + getParents: () => T[]; + cloneCells: (includeChildren?: boolean, mapping?: any) => T[]; + cloneCellImpl: (cell: Cell, mapping?: any, includeChildren?: boolean) => T; + restoreClone: (clone: Cell, cell: Cell, mapping: any) => void; } } -export default CellArray; +/** + * Returns the cells from the given array where the given filter function + * returns true. + */ +Array.prototype.filterCells = function (filter: Function) { + let result = [] as Cell[]; + + for (let i = 0; i < this.length; i += 1) { + if (filter(this[i])) { + result.push(this[i]); + } + } + + return result; +}; + +/** + * Returns all opposite vertices wrt terminal for the given edges, only + * returning sources and/or targets as specified. The result is returned + * as an array of {@link Cell}. + * + * @param {Cell} terminal that specifies the known end of the edges. + * @param sources Boolean that specifies if source terminals should be contained + * in the result. Default is true. + * @param targets Boolean that specifies if target terminals should be contained + * in the result. Default is true. + */ +Array.prototype.getOpposites = function ( + terminal: Cell, + sources: boolean = true, + targets: boolean = true +) { + const terminals = [] as Cell[]; + + for (let i = 0; i < this.length; i += 1) { + const source = this[i].getTerminal(true); + const target = this[i].getTerminal(false); + + // Checks if the terminal is the source of + // the edge and if the target should be + // stored in the result + if (source === terminal && target != null && target !== terminal && targets) { + terminals.push(target); + } + + // Checks if the terminal is the taget of + // the edge and if the source should be + // stored in the result + else if (target === terminal && source != null && source !== terminal && sources) { + terminals.push(source); + } + } + + return terminals; +}; + +/** + * Returns the topmost cells of the hierarchy in an array that contains no + * descendants for each {@link Cell} that it contains. Duplicates should be + * removed in the cells array to improve performance. + */ +Array.prototype.getTopmostCells = function () { + const dict = new Dictionary(); + const tmp = [] as Cell[]; + + for (let i = 0; i < this.length; i += 1) { + dict.put(this[i], true); + } + + for (let i = 0; i < this.length; i += 1) { + const cell = this[i]; + let topmost = true; + let parent = cell.getParent(); + + while (parent != null) { + if (dict.get(parent)) { + topmost = false; + break; + } + parent = parent.getParent(); + } + + if (topmost) { + tmp.push(cell); + } + } + + return tmp; +}; + +/** + * Returns an array that represents the set (no duplicates) of all parents + * for the given array of cells. + */ +Array.prototype.getParents = function () { + const parents = []; + const dict = new Dictionary(); + + for (const cell of this) { + const parent = cell.getParent(); + if (parent != null && !dict.get(parent)) { + dict.put(parent, true); + parents.push(parent); + } + } + + return parents; +}; + +/** + * Returns an array of clones for the given array of {@link Cell}`. + * Depending on the value of includeChildren, a deep clone is created for + * each cell. Connections are restored based if the corresponding + * cell is contained in the passed in array. + * + * @param includeChildren Boolean indicating if the cells should be cloned + * with all descendants. + * @param mapping Optional mapping for existing clones. + */ +Array.prototype.cloneCells = function (includeChildren = true, mapping: any = {}) { + const clones = [] as Cell[]; + + for (const cell of this) { + clones.push(this.cloneCellImpl(cell, mapping, includeChildren)); + } + + for (let i = 0; i < clones.length; i += 1) { + if (clones[i] != null) { + this.restoreClone(clones[i], this[i], mapping); + } + } + + return clones; +}; + +/** + * Inner helper method for cloning cells recursively. + * + * @private + */ +Array.prototype.cloneCellImpl = function ( + cell: Cell, + mapping: any = {}, + includeChildren: boolean = false +): Cell { + const ident = ObjectIdentity.get(cell); + let clone = mapping ? mapping[ident] : null; + + if (clone == null) { + clone = cell.clone(); + mapping[ident] = clone; + + if (includeChildren) { + const childCount = cell.getChildCount(); + + for (let i = 0; i < childCount; i += 1) { + const cloneChild = this.cloneCellImpl(cell.getChildAt(i), mapping, true); + clone.insert(cloneChild); + } + } + } + return clone; +}; + +/** + * Inner helper method for restoring the connections in + * a network of cloned cells. + * + * @private + */ +Array.prototype.restoreClone = function (clone: Cell, cell: Cell, mapping: any) { + const source = cell.getTerminal(true); + + if (source != null) { + const tmp = mapping[ObjectIdentity.get(source)]; + if (tmp != null) { + tmp.insertEdge(clone, true); + } + } + + const target = cell.getTerminal(false); + if (target != null) { + const tmp = mapping[ObjectIdentity.get(target)]; + if (tmp != null) { + tmp.insertEdge(clone, false); + } + } + + const childCount = clone.getChildCount(); + for (let i = 0; i < childCount; i += 1) { + this.restoreClone(clone.getChildAt(i), cell.getChildAt(i), mapping); + } +}; diff --git a/packages/core/src/view/cell/CellRenderer.ts b/packages/core/src/view/cell/CellRenderer.ts index afc979848..64186c067 100644 --- a/packages/core/src/view/cell/CellRenderer.ts +++ b/packages/core/src/view/cell/CellRenderer.ts @@ -48,7 +48,6 @@ import CellOverlay from './CellOverlay'; import { getClientX, getClientY, getSource } from '../../util/EventUtils'; import { isNode } from '../../util/domUtils'; import { CellStateStyle } from '../../types'; -import CellArray from './CellArray'; import SelectionCellsHandler from '../handler/SelectionCellsHandler'; import { Graph } from '../Graph'; @@ -599,7 +598,7 @@ class CellRenderer { return (evt: Event) => { if (this.forceControlClickHandler || graph.isEnabled()) { const collapse = !state.cell.isCollapsed(); - graph.foldCells(collapse, false, new CellArray(state.cell), false, evt); + graph.foldCells(collapse, false, [state.cell], false, evt); InternalEvent.consume(evt); } }; diff --git a/packages/core/src/view/cell/TemporaryCellStates.ts b/packages/core/src/view/cell/TemporaryCellStates.ts index 51f5a28ef..1b847db53 100644 --- a/packages/core/src/view/cell/TemporaryCellStates.ts +++ b/packages/core/src/view/cell/TemporaryCellStates.ts @@ -12,7 +12,6 @@ import GraphView from '../GraphView'; import Cell from './Cell'; import CellState from './CellState'; import Shape from '../geometry/Shape'; -import CellArray from './CellArray'; import { Graph } from '../Graph'; class TemporaryCellStates { @@ -40,7 +39,7 @@ class TemporaryCellStates { constructor( view: GraphView, scale: number = 1, - cells: CellArray, + cells: Cell[], isCellVisibleFn: Function | null = null, getLinkForCellState: Function | null = null ) { @@ -72,7 +71,9 @@ class TemporaryCellStates { } }; - (self.oldDoRedrawShape).apply((view.graph).cellRenderer, [state]); + (self.oldDoRedrawShape).apply((view.graph).cellRenderer, [ + state, + ]); shape.paint = oldPaint; }; } diff --git a/packages/core/src/view/cell/VertexHandle.ts b/packages/core/src/view/cell/VertexHandle.ts index bb38a7e8e..8d773a0fb 100644 --- a/packages/core/src/view/cell/VertexHandle.ts +++ b/packages/core/src/view/cell/VertexHandle.ts @@ -21,7 +21,6 @@ import Shape from '../geometry/Shape'; import InternalMouseEvent from '../event/InternalMouseEvent'; import ImageBox from '../image/ImageBox'; import CellState from './CellState'; -import CellArray from './CellArray'; import type { Graph } from '../Graph'; import type { CellHandle, CellStateStyle } from '../../types'; @@ -90,7 +89,7 @@ class VertexHandle implements CellHandle { * Sets the cell style with the given name to the corresponding value in . */ copyStyle(key: keyof CellStateStyle) { - this.graph.setCellStyles(key, this.state.style[key], new CellArray(this.state.cell)); + this.graph.setCellStyles(key, this.state.style[key], [this.state.cell]); } /** diff --git a/packages/core/src/view/handler/CellEditorHandler.ts b/packages/core/src/view/handler/CellEditorHandler.ts index 2a0d86baa..368d6e842 100644 --- a/packages/core/src/view/handler/CellEditorHandler.ts +++ b/packages/core/src/view/handler/CellEditorHandler.ts @@ -6,10 +6,7 @@ */ import { getValue } from '../../util/Utils'; -import { - getAlignmentAsPoint, - setPrefixedStyle, -} from '../../util/styleUtils'; +import { getAlignmentAsPoint, setPrefixedStyle } from '../../util/styleUtils'; import Rectangle from '../geometry/Rectangle'; import InternalEvent from '../event/InternalEvent'; import Client from '../../Client'; @@ -31,7 +28,11 @@ import InternalMouseEvent from '../event/InternalMouseEvent'; import CellState from '../cell/CellState'; import Shape from '../geometry/Shape'; import { clearSelection, extractTextWithWhitespace, isNode } from '../../util/domUtils'; -import { getStringValue, htmlEntities, replaceTrailingNewlines } from '../../util/StringUtils'; +import { + getStringValue, + htmlEntities, + replaceTrailingNewlines, +} from '../../util/StringUtils'; import { getSource, isConsumed, @@ -43,7 +44,6 @@ import EventSource from '../event/EventSource'; import type { Graph } from '../Graph'; import type { GraphPlugin } from '../../types'; -import CellArray from '../cell/CellArray'; import TooltipHandler from './TooltipHandler'; /** @@ -878,7 +878,7 @@ class CellEditorHandler implements GraphPlugin { } if (this.align !== null) { - this.graph.setCellStyles('align', this.align, new CellArray(state.cell)); + this.graph.setCellStyles('align', this.align, [state.cell]); } }); } diff --git a/packages/core/src/view/handler/ConnectionHandler.ts b/packages/core/src/view/handler/ConnectionHandler.ts index 7d91c1af1..540efbd7e 100644 --- a/packages/core/src/view/handler/ConnectionHandler.ts +++ b/packages/core/src/view/handler/ConnectionHandler.ts @@ -42,7 +42,6 @@ import { Graph } from '../Graph'; import ConnectionConstraint from '../other/ConnectionConstraint'; import Shape from '../geometry/Shape'; import { CellStyle, GraphPlugin, Listenable } from '../../types'; -import CellArray from '../cell/CellArray'; type FactoryMethod = ( source: Cell | null, @@ -1735,7 +1734,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin { target = this.createTargetVertex(evt, source); if (target) { - dropTarget = this.graph.getDropTarget(new CellArray(target), evt, dropTarget); + dropTarget = this.graph.getDropTarget([target], evt, dropTarget); terminalInserted = true; // Disables edges as drop targets if the target cell was created diff --git a/packages/core/src/view/handler/SelectionHandler.ts b/packages/core/src/view/handler/SelectionHandler.ts index ea9ee6310..90a8cb5e2 100644 --- a/packages/core/src/view/handler/SelectionHandler.ts +++ b/packages/core/src/view/handler/SelectionHandler.ts @@ -7,12 +7,7 @@ import Client from '../../Client'; import InternalEvent from '../event/InternalEvent'; -import { - contains, - getRotatedPoint, - isNumeric, - toRadians, -} from '../../util/mathUtils'; +import { contains, getRotatedPoint, isNumeric, toRadians } from '../../util/mathUtils'; import { convertPoint } from '../../util/styleUtils'; import RectangleShape from '../geometry/node/RectangleShape'; import mxGuide from '../other/Guide'; @@ -28,7 +23,12 @@ import { import Dictionary from '../../util/Dictionary'; import CellHighlight from '../cell/CellHighlight'; import Rectangle from '../geometry/Rectangle'; -import { getClientX, getClientY, isAltDown, isMultiTouchEvent } from '../../util/EventUtils'; +import { + getClientX, + getClientY, + isAltDown, + isMultiTouchEvent, +} from '../../util/EventUtils'; import { Graph } from '../Graph'; import Guide from '../other/Guide'; import Shape from '../geometry/Shape'; @@ -37,7 +37,6 @@ import SelectionCellsHandler from './SelectionCellsHandler'; import Cell from '../cell/Cell'; import PopupMenuHandler from './PopupMenuHandler'; import EventSource from '../event/EventSource'; -import CellArray from '../cell/CellArray'; import CellState from '../cell/CellState'; import EventObject from '../event/EventObject'; import ConnectionHandler from './ConnectionHandler'; @@ -314,7 +313,7 @@ class SelectionHandler implements GraphPlugin { delayedSelection = false; first: Point | null = null; - cells: CellArray | null = null; + cells: Cell[] | null = null; bounds: Rectangle | null = null; pBounds: Rectangle | null = null; allCells: Dictionary = new Dictionary(); @@ -470,7 +469,9 @@ class SelectionHandler implements GraphPlugin { if (!this.graph.isToggleEvent(me.getEvent()) || !isAltDown(me.getEvent())) { while (c) { if (selectionCellsHandler.isHandled(c)) { - const cellEditor = this.graph.getPlugin('CellEditorHandler') as CellEditorHandler; + const cellEditor = this.graph.getPlugin( + 'CellEditorHandler' + ) as CellEditorHandler; return cellEditor.getEditingCell() !== c; } c = c.getParent(); @@ -618,9 +619,9 @@ class SelectionHandler implements GraphPlugin { * * @param initialCell that triggered this handler. */ - getCells(initialCell: Cell) { + getCells(initialCell: Cell): Cell[] { if (!this.delayedSelection && this.graph.isCellMovable(initialCell)) { - return new CellArray(initialCell); + return [initialCell]; } return this.graph.getMovableCells(this.graph.getSelectionCells()); } @@ -629,7 +630,7 @@ class SelectionHandler implements GraphPlugin { * Returns the {@link Rectangle} used as the preview bounds for * moving the given cells. */ - getPreviewBounds(cells: CellArray) { + getPreviewBounds(cells: Cell[]) { const bounds = this.getBoundingBox(cells); if (bounds) { @@ -667,7 +668,7 @@ class SelectionHandler implements GraphPlugin { * * @param cells Array of {@link Cells} whose bounding box should be returned. */ - getBoundingBox(cells: CellArray) { + getBoundingBox(cells: Cell[]) { let result = null; if (cells.length > 0) { @@ -731,7 +732,7 @@ class SelectionHandler implements GraphPlugin { /** * Starts the handling of the mouse gesture. */ - start(cell: Cell, x: number, y: number, cells?: CellArray) { + start(cell: Cell, x: number, y: number, cells?: Cell[]) { this.cell = cell; this.first = convertPoint(this.graph.container, x, y); this.cells = cells ? cells : this.getCells(this.cell); @@ -1358,7 +1359,7 @@ class SelectionHandler implements GraphPlugin { * @param visible Boolean that specifies if the handles should be visible. * @param force Forces an update of the handler regardless of the last used value. */ - setHandlesVisibleForCells(cells: CellArray, visible: boolean, force = false) { + setHandlesVisibleForCells(cells: Cell[], visible: boolean, force = false) { if (force || this.handlesVisible !== visible) { this.handlesVisible = visible; @@ -1506,7 +1507,7 @@ class SelectionHandler implements GraphPlugin { * Returns true if the given cells should be removed from the parent for the specified * mousereleased event. */ - shouldRemoveCellsFromParent(parent: Cell, cells: CellArray, evt: MouseEvent) { + shouldRemoveCellsFromParent(parent: Cell, cells: Cell[], evt: MouseEvent) { if (parent.isVertex()) { const pState = this.graph.getView().getState(parent); @@ -1533,7 +1534,7 @@ class SelectionHandler implements GraphPlugin { * Moves the given cells by the specified amount. */ moveCells( - cells: CellArray, + cells: Cell[], dx: number, dy: number, clone: boolean, @@ -1597,7 +1598,7 @@ class SelectionHandler implements GraphPlugin { } } - this.graph.removeCells(new CellArray(...temp), false); + this.graph.removeCells(temp, false); }); // Selects the new cells if cells have been cloned diff --git a/packages/core/src/view/handler/VertexHandler.ts b/packages/core/src/view/handler/VertexHandler.ts index ba7760950..f284ca2f9 100644 --- a/packages/core/src/view/handler/VertexHandler.ts +++ b/packages/core/src/view/handler/VertexHandler.ts @@ -33,7 +33,6 @@ import Cell from '../cell/Cell'; import { CellHandle, Listenable } from '../../types'; import Shape from '../geometry/Shape'; import InternalMouseEvent from '../event/InternalMouseEvent'; -import CellArray from '../cell/CellArray'; import EdgeHandler from './EdgeHandler'; import EventSource from '../event/EventSource'; import SelectionHandler from './SelectionHandler'; @@ -202,7 +201,7 @@ class VertexHandler { constructor(state: CellState) { this.state = state; - this.graph = (this.state.view.graph); + this.graph = this.state.view.graph; this.selectionBounds = this.getSelectionBounds(this.state); this.bounds = new Rectangle( this.selectionBounds.x, @@ -647,7 +646,7 @@ class VertexHandler { this.ghostPreview = this.createGhostPreview(); } else { // Saves reference to parent state - const { model } = (this.state.view.graph); + const { model } = this.state.view.graph; const parent = this.state.cell.getParent(); if ( @@ -1287,7 +1286,7 @@ class VertexHandler { if (!cell.isEdge()) { const style = this.graph.getCurrentCellStyle(cell); const total = (style.rotation || 0) + angle; - this.graph.setCellStyles('rotation', total, new CellArray(cell)); + this.graph.setCellStyles('rotation', total, [cell]); } let geo = cell.getGeometry(); @@ -1865,7 +1864,9 @@ class VertexHandler { // Hides rotation handle during text editing this.rotationShape.node.style.visibility = - (this.state.view.graph).isEditing() || !this.handlesVisible ? 'hidden' : ''; + (this.state.view.graph).isEditing() || !this.handlesVisible + ? 'hidden' + : ''; } } @@ -1884,7 +1885,9 @@ class VertexHandler { * Returns true if the given custom handle is visible. */ isCustomHandleVisible(handle: CellHandle) { - return !this.graph.isEditing() && (this.state.view.graph).getSelectionCount() === 1; + return ( + !this.graph.isEditing() && (this.state.view.graph).getSelectionCount() === 1 + ); } /** diff --git a/packages/core/src/view/layout/CircleLayout.ts b/packages/core/src/view/layout/CircleLayout.ts index a51d6f0ef..04bf62955 100644 --- a/packages/core/src/view/layout/CircleLayout.ts +++ b/packages/core/src/view/layout/CircleLayout.ts @@ -6,7 +6,6 @@ */ import GraphLayout from './GraphLayout'; import { Graph } from '../Graph'; -import CellArray from '../cell/CellArray'; import Cell from '../cell/Cell'; /** @@ -130,7 +129,7 @@ class CircleLayout extends GraphLayout { left = this.x0; top = this.y0; } - this.circle(new CellArray(...vertices), r, left, top); + this.circle(vertices, r, left, top); }); } @@ -147,7 +146,7 @@ class CircleLayout extends GraphLayout { * of vertices and the given radius. This is called from * . */ - circle(vertices: CellArray, r: number, left: number, top: number) { + circle(vertices: Cell[], r: number, left: number, top: number) { const vertexCount = vertices.length; const phi = (2 * Math.PI) / vertexCount; diff --git a/packages/core/src/view/layout/CompactTreeLayout.ts b/packages/core/src/view/layout/CompactTreeLayout.ts index aa0915349..3306d02ef 100644 --- a/packages/core/src/view/layout/CompactTreeLayout.ts +++ b/packages/core/src/view/layout/CompactTreeLayout.ts @@ -15,7 +15,6 @@ import WeightedCellSorter from './util/WeightedCellSorter'; import Cell from '../cell/Cell'; import { Graph } from '../Graph'; import { findTreeRoots } from '../../util/treeTraversal'; -import CellArray from '../cell/CellArray'; export interface _mxCompactTreeLayoutNode { cell?: Cell; @@ -26,11 +25,11 @@ export interface _mxCompactTreeLayoutNode { offsetX?: number; offsetY?: number; contour?: { - upperTail?: _mxCompactTreeLayoutLine, - upperHead?: _mxCompactTreeLayoutLine, - lowerTail?: _mxCompactTreeLayoutLine, - lowerHead?: _mxCompactTreeLayoutLine, - [key: string]: any, + upperTail?: _mxCompactTreeLayoutLine; + upperHead?: _mxCompactTreeLayoutLine; + lowerTail?: _mxCompactTreeLayoutLine; + lowerHead?: _mxCompactTreeLayoutLine; + [key: string]: any; }; next?: _mxCompactTreeLayoutNode; child?: _mxCompactTreeLayoutNode; @@ -201,7 +200,7 @@ export class CompactTreeLayout extends GraphLayout { * An array of the maximum height of cells (relative to the layout direction) * per rank */ - maxRankHeight: CellArray | null = null; + maxRankHeight: Cell[] = []; /** * The cell to use as the root of the tree @@ -221,9 +220,7 @@ export class CompactTreeLayout extends GraphLayout { * @param vertex {@link mxCell} whose ignored state should be returned. */ isVertexIgnored(vertex: Cell): boolean { - return ( - super.isVertexIgnored(vertex) || vertex.getConnections().length === 0 - ); + return super.isVertexIgnored(vertex) || vertex.getConnections().length === 0; } /** @@ -309,7 +306,7 @@ export class CompactTreeLayout extends GraphLayout { this.node = this.dfs(this.root, parent); if (this.alignRanks) { - this.maxRankHeight = new CellArray(); + this.maxRankHeight = []; this.findRankHeights(this.node, 0); this.setCellHeights(this.node, 0); } @@ -399,7 +396,7 @@ export class CompactTreeLayout extends GraphLayout { /** * Called if {@link sortEdges} is true to sort the array of outgoing edges in place. */ - sortOutgoingEdges(source: Cell, edges: CellArray): void { + sortOutgoingEdges(source: Cell, edges: Cell[]): void { const lookup = new Dictionary(); edges.sort((e1, e2) => { @@ -428,7 +425,7 @@ export class CompactTreeLayout extends GraphLayout { * direction) of cells in each rank */ findRankHeights(node: any, rank: number): void { - const maxRankHeight = this.maxRankHeight; + const maxRankHeight = this.maxRankHeight; if (maxRankHeight[rank] == null || maxRankHeight[rank] < node.height) { maxRankHeight[rank] = node.height; } @@ -445,7 +442,7 @@ export class CompactTreeLayout extends GraphLayout { * direction) when the tops of each rank are to be aligned */ setCellHeights(node: any, rank: number): void { - const maxRankHeight = this.maxRankHeight; + const maxRankHeight = this.maxRankHeight; if (maxRankHeight[rank] != null && maxRankHeight[rank] > node.height) { node.height = maxRankHeight[rank]; } @@ -546,7 +543,12 @@ export class CompactTreeLayout extends GraphLayout { * Starts the actual compact tree layout algorithm * at the given node. */ - horizontalLayout(node: any, x0: number, y0: number, bounds: Rectangle | null=null): Rectangle | null { + horizontalLayout( + node: any, + x0: number, + y0: number, + bounds: Rectangle | null = null + ): Rectangle | null { node.x += x0 + node.offsetX; node.y += y0 + node.offsetY; bounds = this.apply(node, bounds); @@ -571,11 +573,11 @@ export class CompactTreeLayout extends GraphLayout { * at the given node. */ verticalLayout( - node: _mxCompactTreeLayoutNode, - parent: _mxCompactTreeLayoutNode | null, - x0: number, - y0: number, - bounds: Rectangle | null=null + node: _mxCompactTreeLayoutNode, + parent: _mxCompactTreeLayoutNode | null, + x0: number, + y0: number, + bounds: Rectangle | null = null ): Rectangle | null { node.x = node.x + x0 + node.offsetY; node.y = node.y + y0 + node.offsetX; @@ -755,11 +757,11 @@ export class CompactTreeLayout extends GraphLayout { } bridge( - line1: _mxCompactTreeLayoutLine, - x1: number, - y1: number, - line2: _mxCompactTreeLayoutLine, - x2: number, + line1: _mxCompactTreeLayoutLine, + x1: number, + y1: number, + line2: _mxCompactTreeLayoutLine, + x2: number, y2: number ) { const dx = x2 + line2.dx - x1; @@ -813,7 +815,10 @@ export class CompactTreeLayout extends GraphLayout { * Starts the actual compact tree layout algorithm * at the given node. */ - apply(node: _mxCompactTreeLayoutNode, bounds: Rectangle | null=null): Rectangle | null { + apply( + node: _mxCompactTreeLayoutNode, + bounds: Rectangle | null = null + ): Rectangle | null { const model = this.graph.getDataModel(); const cell = node.cell; let g: Rectangle = cell.getGeometry(); @@ -852,11 +857,11 @@ export class CompactTreeLayout extends GraphLayout { * Starts the actual compact tree layout algorithm * at the given node. */ - createLine(dx: number, dy: number, next: any=null): _mxCompactTreeLayoutLine { + createLine(dx: number, dy: number, next: any = null): _mxCompactTreeLayoutLine { let line: _mxCompactTreeLayoutLine = { - dx, - dy, - next + dx, + dy, + next, }; return line; } @@ -867,7 +872,7 @@ export class CompactTreeLayout extends GraphLayout { * a padding. */ adjustParents(): void { - const tmp = new CellArray(); + const tmp = []; for (const id in this.parentsChanged) { tmp.push(this.parentsChanged[id]); diff --git a/packages/core/src/view/layout/FastOrganicLayout.ts b/packages/core/src/view/layout/FastOrganicLayout.ts index 2527a3071..204029374 100644 --- a/packages/core/src/view/layout/FastOrganicLayout.ts +++ b/packages/core/src/view/layout/FastOrganicLayout.ts @@ -8,7 +8,6 @@ import ObjectIdentity from '../../util/ObjectIdentity'; import GraphLayout from './GraphLayout'; import { Graph } from '../Graph'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; /** * Extends {@link GraphLayout} to implement a fast organic layout algorithm. @@ -95,7 +94,7 @@ class MxFastOrganicLayout extends GraphLayout { /** * An array of all vertices to be laid out. */ - vertexArray: CellArray = new CellArray(); + vertexArray: Cell[] = []; /** * An array of locally stored X co-ordinate displacements for the vertices. @@ -161,7 +160,7 @@ class MxFastOrganicLayout extends GraphLayout { */ execute(parent: Cell) { const model = this.graph.getDataModel(); - this.vertexArray = new CellArray(); + this.vertexArray = []; let cells = this.graph.getChildVertices(parent); for (let i = 0; i < cells.length; i += 1) { diff --git a/packages/core/src/view/layout/GraphLayout.ts b/packages/core/src/view/layout/GraphLayout.ts index b4257bdd9..d06d10244 100644 --- a/packages/core/src/view/layout/GraphLayout.ts +++ b/packages/core/src/view/layout/GraphLayout.ts @@ -11,7 +11,6 @@ import Geometry from '../geometry/Geometry'; import Point from '../geometry/Point'; import { Graph } from '../Graph'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; /** * @class GraphLayout @@ -230,14 +229,14 @@ class GraphLayout { * Disables or enables the edge style of the given edge. */ setEdgeStyleEnabled(edge: Cell, value: any): void { - this.graph.setCellStyles('noEdgeStyle', value ? '0' : '1', new CellArray(edge)); + this.graph.setCellStyles('noEdgeStyle', value ? '0' : '1', [edge]); } /** * Disables or enables orthogonal end segments of the given edge. */ setOrthogonalEdge(edge: Cell, value: any): void { - this.graph.setCellStyles('orthogonal', value ? '1' : '0', new CellArray(edge)); + this.graph.setCellStyles('orthogonal', value ? '1' : '0', [edge]); } /** @@ -408,7 +407,7 @@ class GraphLayout { * Shortcut to {@link Graph#updateGroupBounds} with moveGroup set to true. */ arrangeGroups( - cells: CellArray, + cells: Cell[], border: number, topBorder: number, rightBorder: number, diff --git a/packages/core/src/view/layout/HierarchicalLayout.ts b/packages/core/src/view/layout/HierarchicalLayout.ts index 6301a1bd6..0c5d3dcde 100644 --- a/packages/core/src/view/layout/HierarchicalLayout.ts +++ b/packages/core/src/view/layout/HierarchicalLayout.ts @@ -14,7 +14,6 @@ import MinimumCycleRemover from './hierarchical/MinimumCycleRemover'; import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction'; import CoordinateAssignment from './hierarchical/CoordinateAssignment'; import { Graph } from '../../view/Graph'; -import CellArray from '../../view/cell/CellArray'; import Cell from '../../view/cell/Cell'; import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; @@ -36,8 +35,8 @@ import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; class HierarchicalLayout extends GraphLayout { constructor( graph: Graph, - orientation: DIRECTION=DIRECTION.NORTH, - deterministic: boolean=true + orientation: DIRECTION = DIRECTION.NORTH, + deterministic: boolean = true ) { super(graph); this.orientation = orientation; @@ -51,7 +50,7 @@ class HierarchicalLayout extends GraphLayout { /** * Holds the array of that this layout contains. */ - roots: CellArray | null = null; + roots: Cell[] | null = null; /** * Specifies if the parent should be resized after the layout so that it @@ -112,7 +111,7 @@ class HierarchicalLayout extends GraphLayout { fineTuning: boolean = true; /** - * Whether or not to tighten the assigned ranks of vertices up towards + * Whether or not to tighten the assigned ranks of vertices up towards * the source cells. Default is true. */ tightenToSource: boolean = true; @@ -139,7 +138,7 @@ class HierarchicalLayout extends GraphLayout { /** * A cache of edges whose source terminal is the key */ - edgesCache: Dictionary = new Dictionary(); + edgesCache: Dictionary = new Dictionary(); /** * A cache of edges whose source terminal is the key @@ -170,7 +169,7 @@ class HierarchicalLayout extends GraphLayout { * @param parent Parent that contains the children to be laid out. * @param roots Optional starting roots of the layout. */ - execute(parent: Cell, roots: CellArray | null=null): void { + execute(parent: Cell, roots: Cell[] | Cell | null = null): void { this.parent = parent; const { model } = this.graph; this.edgesCache = new Dictionary(); @@ -178,7 +177,7 @@ class HierarchicalLayout extends GraphLayout { this.edgesTargetTermCache = new Dictionary(); if (roots != null && !(roots instanceof Array)) { - roots = new CellArray(roots); + roots = [roots]; } // If the roots are set and the parent is set, only @@ -211,7 +210,7 @@ class HierarchicalLayout extends GraphLayout { } if (roots != null) { - const rootsCopy = new CellArray(); + const rootsCopy = []; for (let i = 0; i < roots.length; i += 1) { const ancestor = parent != null ? parent.isAncestor(roots[i]) : true; @@ -228,7 +227,7 @@ class HierarchicalLayout extends GraphLayout { this.run(parent); if (this.resizeParent && !parent.isCollapsed()) { - this.graph.updateGroupBounds(new CellArray(parent), this.parentBorder, this.moveParent); + this.graph.updateGroupBounds([parent], this.parentBorder, this.moveParent); } // Maintaining parent location @@ -257,8 +256,8 @@ class HierarchicalLayout extends GraphLayout { * @param parent whose children should be checked. * @param vertices array of vertices to limit search to */ - findRoots(parent: Cell, vertices: CellArray): CellArray { - const roots = new CellArray(); + findRoots(parent: Cell, vertices: Cell[]): Cell[] { + const roots = []; if (parent != null && vertices != null) { const { model } = this.graph; @@ -308,14 +307,14 @@ class HierarchicalLayout extends GraphLayout { * * @param cell whose edges should be returned. */ - getEdges(cell: Cell): CellArray { + getEdges(cell: Cell) { const cachedEdges = this.edgesCache.get(cell); if (cachedEdges != null) { return cachedEdges; } const { model } = this.graph; - let edges = new CellArray(); + let edges: Cell[] = []; const isCollapsed = cell.isCollapsed(); const childCount = cell.getChildCount(); @@ -330,7 +329,7 @@ class HierarchicalLayout extends GraphLayout { } edges = edges.concat(cell.getEdges(true, true)); - const result = new CellArray(); + const result = []; for (let i = 0; i < edges.length; i += 1) { const source = this.getVisibleTerminal(edges[i], true); @@ -411,7 +410,7 @@ class HierarchicalLayout extends GraphLayout { const filledVertexSet = Object(); this.filterDescendants(parent, filledVertexSet); - this.roots = new CellArray(); + this.roots = []; let filledVertexSetEmpty = true; // Poor man's isSetEmpty @@ -460,7 +459,7 @@ class HierarchicalLayout extends GraphLayout { } } else { // Find vertex set as directed traversal from roots - const roots = this.roots; + const roots = this.roots as Cell[]; // NEED CHECK - roots cannot be null for (let i = 0; i < roots.length; i += 1) { const vertexSet = Object(); @@ -486,7 +485,7 @@ class HierarchicalLayout extends GraphLayout { for (let i = 0; i < hierarchyVertices.length; i += 1) { const vertexSet = hierarchyVertices[i]; - const tmp = new CellArray(); + const tmp = []; for (var key in vertexSet) { tmp.push(vertexSet[key]); @@ -495,7 +494,7 @@ class HierarchicalLayout extends GraphLayout { this.model = new GraphHierarchyModel( this, tmp, - this.roots, + this.roots as Cell[], parent, this.tightenToSource ); @@ -554,10 +553,10 @@ class HierarchicalLayout extends GraphLayout { * target - * directed - */ - getEdgesBetween(source: Cell, target: Cell, directed: boolean): CellArray { + getEdgesBetween(source: Cell, target: Cell, directed: boolean): Cell[] { directed = directed != null ? directed : false; const edges = this.getEdges(source); - const result = new CellArray(); + const result = []; // Checks if the edge is connected to the correct // cell and returns the first match @@ -592,12 +591,12 @@ class HierarchicalLayout extends GraphLayout { // @ts-ignore traverse( vertex: Cell, - directed: boolean=false, - edge: Cell | null=null, - allVertices: { [key: string]: Cell } | null=null, - currentComp: { [key: string]: (Cell | null) }, + directed: boolean = false, + edge: Cell | null = null, + allVertices: { [key: string]: Cell } | null = null, + currentComp: { [key: string]: Cell | null }, hierarchyVertices: GraphHierarchyNode[], - filledVertexSet: { [key: string]: Cell } | null=null + filledVertexSet: { [key: string]: Cell } | null = null ) { if (vertex != null && allVertices != null) { // Has this vertex been seen before in any traversal diff --git a/packages/core/src/view/layout/LayoutManager.ts b/packages/core/src/view/layout/LayoutManager.ts index f042a1ce7..76a2706c1 100644 --- a/packages/core/src/view/layout/LayoutManager.ts +++ b/packages/core/src/view/layout/LayoutManager.ts @@ -18,7 +18,6 @@ import EventObject from '../event/EventObject'; import Cell from '../cell/Cell'; import Rectangle from '../geometry/Rectangle'; import { getClientX, getClientY } from '../../util/EventUtils'; -import CellArray from '../cell/CellArray'; import { Graph } from '../Graph'; import GraphLayout from './GraphLayout'; import UndoableEdit from '../undoable_changes/UndoableEdit'; @@ -214,7 +213,7 @@ class LayoutManager extends EventSource { * @param cell Array of {@link Cell} that have been moved. * @param evt Mouse event that represents the mousedown. */ - cellsMoved(cells: CellArray, evt: MouseEvent) { + cellsMoved(cells: Cell[], evt: MouseEvent) { if (cells.length > 0 && evt) { const point = convertPoint( this.getGraph().container, @@ -239,9 +238,9 @@ class LayoutManager extends EventSource { * @param bounds {@link mxRectangle} taht represents the new bounds. */ cellsResized( - cells: CellArray | null = null, + cells: Cell[] | null = null, bounds: Rectangle[] | null = null, - prev: CellArray | null = null + prev: Cell[] | null = null ) { if (cells && bounds) { for (let i = 0; i < cells.length; i += 1) { @@ -256,11 +255,11 @@ class LayoutManager extends EventSource { /** * Returns the cells for which a layout should be executed. */ - getCellsForChanges(changes: any[]): CellArray { - let result: CellArray = new CellArray(); + getCellsForChanges(changes: any[]): Cell[] { + let result: Cell[] = []; for (const change of changes) { if (change instanceof RootChange) { - return new CellArray(); + return []; } result = result.concat(this.getCellsForChange(change)); } @@ -272,7 +271,7 @@ class LayoutManager extends EventSource { * changes. * @param change mxChildChange|mxTerminalChange|mxVisibleChange|... */ - getCellsForChange(change: any): CellArray { + getCellsForChange(change: any): Cell[] { if (change instanceof ChildChange) { return this.addCellsWithLayout( change.child, @@ -288,23 +287,20 @@ class LayoutManager extends EventSource { return this.addCellsWithLayout(change.cell); } - return new CellArray(); + return []; } /** * Adds all ancestors of the given cell that have a layout. */ - addCellsWithLayout(cell: Cell | null, result: CellArray = new CellArray()) { + addCellsWithLayout(cell: Cell | null, result: Cell[] = []) { return this.addDescendantsWithLayout(cell, this.addAncestorsWithLayout(cell, result)); } /** * Adds all ancestors of the given cell that have a layout. */ - addAncestorsWithLayout( - cell: Cell | null, - result: CellArray = new CellArray() - ): CellArray { + addAncestorsWithLayout(cell: Cell | null, result: Cell[] = []): Cell[] { if (cell) { const layout = this.hasLayout(cell); @@ -322,7 +318,7 @@ class LayoutManager extends EventSource { /** * Adds all descendants of the given cell that have a layout. */ - addDescendantsWithLayout(cell: Cell | null, result: CellArray = new CellArray()) { + addDescendantsWithLayout(cell: Cell | null, result: Cell[] = []) { if (cell && this.hasLayout(cell)) { for (let i = 0; i < cell.getChildCount(); i += 1) { const child = cell.getChildAt(i); @@ -340,16 +336,16 @@ class LayoutManager extends EventSource { /** * Executes the given layout on the given parent. */ - executeLayoutForCells(cells: CellArray) { + executeLayoutForCells(cells: Cell[]) { const sorted = sortCells(cells, false); this.layoutCells(sorted, true); - this.layoutCells(new CellArray(...sorted.reverse()), false); + this.layoutCells(sorted.reverse(), false); } /** * Executes all layouts which have been scheduled during the changes. */ - layoutCells(cells: CellArray, bubble: boolean = false) { + layoutCells(cells: Cell[], bubble: boolean = false) { if (cells.length > 0) { // Invokes the layouts while removing duplicates const model = this.getGraph().getDataModel(); diff --git a/packages/core/src/view/layout/ParallelEdgeLayout.ts b/packages/core/src/view/layout/ParallelEdgeLayout.ts index 3ad390adf..b1427aa35 100644 --- a/packages/core/src/view/layout/ParallelEdgeLayout.ts +++ b/packages/core/src/view/layout/ParallelEdgeLayout.ts @@ -9,7 +9,6 @@ import Point from '../geometry/Point'; import GraphLayout from './GraphLayout'; import ObjectIdentity from '../../util/ObjectIdentity'; import { Graph } from '../Graph'; -import CellArray from '../cell/CellArray'; import Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; @@ -73,7 +72,7 @@ class ParallelEdgeLayout extends GraphLayout { /** * Implements {@link GraphLayout#execute}. */ - execute(parent: Cell, cells: CellArray | null=null): void { + execute(parent: Cell, cells: Cell[] | null = null): void { const lookup = this.findParallels(parent, cells); this.graph.model.beginUpdate(); @@ -93,7 +92,7 @@ class ParallelEdgeLayout extends GraphLayout { /** * Finds the parallel edges in the given parent. */ - findParallels(parent: Cell, cells: CellArray | null=null) { + findParallels(parent: Cell, cells: Cell[] | null = null) { const lookup: any = []; const addCell = (cell: Cell) => { @@ -167,7 +166,7 @@ class ParallelEdgeLayout extends GraphLayout { /** * Lays out the parallel edges in the given array. */ - layout(parallels: CellArray) { + layout(parallels: Cell[]) { const edge = parallels[0]; const view = this.graph.getView(); const model = this.graph.getDataModel(); diff --git a/packages/core/src/view/layout/StackLayout.ts b/packages/core/src/view/layout/StackLayout.ts index f5940593a..e129104b1 100644 --- a/packages/core/src/view/layout/StackLayout.ts +++ b/packages/core/src/view/layout/StackLayout.ts @@ -12,7 +12,6 @@ import { DEFAULT_STARTSIZE } from '../../util/Constants'; import { Graph } from '../Graph'; import Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; -import CellArray from '../cell/CellArray'; /** * Extends {@link GraphLayout} to create a horizontal or vertical stack of the @@ -34,11 +33,11 @@ import CellArray from '../cell/CellArray'; class StackLayout extends GraphLayout { constructor( graph: Graph, - horizontal: boolean | null=null, - spacing: number | null=null, - x0: number | null=null, - y0: number | null=null, - border: number | null=null + horizontal: boolean | null = null, + spacing: number | null = null, + x0: number | null = null, + y0: number | null = null, + border: number | null = null ) { super(graph); this.horizontal = horizontal != null ? horizontal : true; @@ -219,10 +218,10 @@ class StackLayout extends GraphLayout { /** * Returns the cells to be layouted. */ - getLayoutCells(parent: Cell): CellArray { + getLayoutCells(parent: Cell): Cell[] { const model = this.graph.getDataModel(); const childCount = parent.getChildCount(); - const cells = new CellArray(); + const cells = []; for (let i = 0; i < childCount; i += 1) { const child = parent.getChildAt(i); @@ -240,12 +239,12 @@ class StackLayout extends GraphLayout { return this.horizontal ? geo1.x === geo2.x ? 0 - : (geo1.x > geo2.x && geo2.x > 0) + : geo1.x > geo2.x && geo2.x > 0 ? 1 : -1 : geo1.y === geo2.y ? 0 - : (geo1.y > geo2.y && geo2.y > 0) + : geo1.y > geo2.y && geo2.y > 0 ? 1 : -1; }); @@ -284,7 +283,7 @@ class StackLayout extends GraphLayout { : pgeo.width - this.marginLeft - this.marginRight; fillValue -= 2 * this.border; } - + let x0 = this.x0 + this.border + this.marginLeft; let y0 = this.y0 + this.border + this.marginTop; diff --git a/packages/core/src/view/layout/SwimlaneLayout.ts b/packages/core/src/view/layout/SwimlaneLayout.ts index 410cfc555..f97360dbb 100644 --- a/packages/core/src/view/layout/SwimlaneLayout.ts +++ b/packages/core/src/view/layout/SwimlaneLayout.ts @@ -17,7 +17,6 @@ import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingRe import CoordinateAssignment from './hierarchical/CoordinateAssignment'; import { Graph } from '../Graph'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import Geometry from '../../view/geometry/Geometry'; import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; @@ -37,7 +36,11 @@ import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; * deterministic. Default is true. */ class SwimlaneLayout extends GraphLayout { - constructor(graph: Graph, orientation: DIRECTION | null, deterministic: boolean = true) { + constructor( + graph: Graph, + orientation: DIRECTION | null, + deterministic: boolean = true + ) { super(graph); this.orientation = orientation != null ? orientation : DIRECTION.NORTH; this.deterministic = deterministic != null ? deterministic : true; @@ -50,12 +53,12 @@ class SwimlaneLayout extends GraphLayout { /** * Holds the array of that this layout contains. */ - roots: CellArray | null = null; + roots: Cell[] | null = null; /** * Holds the array of of the ordered swimlanes to lay out */ - swimlanes: CellArray | null = null; + swimlanes: Cell[] | null = null; /** * The cell width of any dummy vertices inserted @@ -148,7 +151,7 @@ class SwimlaneLayout extends GraphLayout { /** * A cache of edges whose source terminal is the key */ - edgesCache: Dictionary = new Dictionary(); + edgesCache: Dictionary = new Dictionary(); /** * A cache of edges whose source terminal is the key @@ -179,7 +182,7 @@ class SwimlaneLayout extends GraphLayout { * @param parent Parent that contains the children to be laid out. * @param swimlanes Ordered array of swimlanes to be laid out */ - execute(parent: Cell, swimlanes: CellArray | null=null): void { + execute(parent: Cell, swimlanes: Cell[] | null = null): void { this.parent = parent; const { model } = this.graph; this.edgesCache = new Dictionary(); @@ -220,7 +223,7 @@ class SwimlaneLayout extends GraphLayout { } this.swimlanes = swimlanes; - const dummyVertices = new CellArray(); + const dummyVertices = []; // Check the swimlanes all have vertices // in them @@ -246,7 +249,7 @@ class SwimlaneLayout extends GraphLayout { this.run(parent); if (this.resizeParent && !parent.isCollapsed()) { - this.graph.updateGroupBounds(new CellArray(parent), this.parentBorder, this.moveParent); + this.graph.updateGroupBounds([parent], this.parentBorder, this.moveParent); } // Maintaining parent location @@ -274,7 +277,7 @@ class SwimlaneLayout extends GraphLayout { */ updateGroupBounds(): void { // Get all vertices and edge in the layout - const cells = new CellArray(); + const cells = []; const model = this.model; for (const key in model.edgeMapper) { @@ -288,7 +291,7 @@ class SwimlaneLayout extends GraphLayout { let layoutBounds = this.graph.getBoundingBoxFromGeometry(cells, true); const childBounds = []; - const swimlanes = this.swimlanes; + const swimlanes = this.swimlanes as Cell[]; for (let i = 0; i < swimlanes.length; i += 1) { const lane = swimlanes[i]; @@ -339,7 +342,8 @@ class SwimlaneLayout extends GraphLayout { newGeo.y = y; newGeo.width = childBounds[i].width + w + this.interRankCellSpacing / 2; - newGeo.height = (layoutBounds).height + size.height + 2 * this.parentBorder; + newGeo.height = + (layoutBounds).height + size.height + 2 * this.parentBorder; this.graph.model.setGeometry(lane, newGeo); this.graph.moveCells(children, -x, geo.y - y); @@ -357,8 +361,8 @@ class SwimlaneLayout extends GraphLayout { * @param parent whose children should be checked. * @param vertices array of vertices to limit search to */ - findRoots(parent: Cell, vertices: { [key: string]: Cell }): CellArray { - const roots = new CellArray(); + findRoots(parent: Cell, vertices: { [key: string]: Cell }): Cell[] { + const roots = []; if (parent != null && vertices != null) { const { model } = this.graph; @@ -418,14 +422,14 @@ class SwimlaneLayout extends GraphLayout { * * @param cell whose edges should be returned. */ - getEdges(cell: Cell): CellArray { + getEdges(cell: Cell): Cell[] { const cachedEdges = this.edgesCache.get(cell); if (cachedEdges != null) { return cachedEdges; } - let edges = new CellArray(); + let edges: Cell[] = []; const isCollapsed = cell.isCollapsed(); const childCount = cell.getChildCount(); @@ -440,7 +444,7 @@ class SwimlaneLayout extends GraphLayout { } edges = edges.concat(cell.getEdges(true, true)); - const result = new CellArray(); + const result = []; for (let i = 0; i < edges.length; i += 1) { const source = this.getVisibleTerminal(edges[i], true); @@ -451,7 +455,11 @@ class SwimlaneLayout extends GraphLayout { (source !== target && ((target === cell && (this.parent == null || - this.graph.isValidAncestor(source, this.parent, this.traverseAncestors))) || + this.graph.isValidAncestor( + source, + this.parent, + this.traverseAncestors + ))) || (source === cell && (this.parent == null || this.graph.isValidAncestor( @@ -528,7 +536,7 @@ class SwimlaneLayout extends GraphLayout { this.filterDescendants(this.swimlanes[i], filledVertexSet); } - this.roots = new CellArray(); + this.roots = []; let filledVertexSetEmpty = true; // Poor man's isSetEmpty @@ -588,21 +596,36 @@ class SwimlaneLayout extends GraphLayout { } } else { // Find vertex set as directed traversal from roots - const roots = this.roots; + const roots = this.roots as Cell[]; for (let i = 0; i < roots.length; i += 1) { const vertexSet = Object(); hierarchyVertices.push(vertexSet); - this.traverse(roots[i], true, null, allVertexSet, vertexSet, hierarchyVertices, null, i); // CHECK THIS PARAM!! ==================== + this.traverse( + roots[i], + true, + null, + allVertexSet, + vertexSet, + hierarchyVertices, + null, + i + ); // CHECK THIS PARAM!! ==================== } } - const tmp = new CellArray(); + const tmp = []; for (var key in allVertexSet) { tmp.push(allVertexSet[key]); } - this.model = new SwimlaneModel(this, tmp, this.roots, parent, this.tightenToSource); + this.model = new SwimlaneModel( + this, + tmp, + this.roots as Cell[], + parent, + this.tightenToSource + ); this.cycleStage(parent); this.layeringStage(); @@ -664,7 +687,7 @@ class SwimlaneLayout extends GraphLayout { */ getEdgesBetween(source: Cell, target: Cell, directed: boolean = false) { const edges = this.getEdges(source); - const result = new CellArray(); + const result = []; // Checks if the edge is connected to the correct // cell and returns the first match @@ -699,13 +722,13 @@ class SwimlaneLayout extends GraphLayout { */ // @ts-ignore traverse( - vertex: Cell | null=null, + vertex: Cell | null = null, directed: boolean, edge: Cell | null, - allVertices: { [key: string]: Cell } | null=null, + allVertices: { [key: string]: Cell } | null = null, currentComp: { [key: string]: Cell }, hierarchyVertices: GraphHierarchyNode[], - filledVertexSet: { [key: string]: Cell } | null=null, + filledVertexSet: { [key: string]: Cell } | null = null, swimlaneIndex: number ) { if (vertex != null && allVertices != null) { @@ -741,7 +764,7 @@ class SwimlaneLayout extends GraphLayout { } let otherIndex = 0; - const swimlanes = this.swimlanes; + const swimlanes = this.swimlanes as Cell[]; // Get the swimlane index of the other terminal for (otherIndex = 0; otherIndex < swimlanes.length; otherIndex++) { diff --git a/packages/core/src/view/layout/SwimlaneManager.ts b/packages/core/src/view/layout/SwimlaneManager.ts index bc0ddbaa6..e2a8887e3 100644 --- a/packages/core/src/view/layout/SwimlaneManager.ts +++ b/packages/core/src/view/layout/SwimlaneManager.ts @@ -11,7 +11,6 @@ import Rectangle from '../geometry/Rectangle'; import { Graph } from '../Graph'; import EventObject from '../event/EventObject'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; /** * @class SwimlaneManager @@ -200,7 +199,7 @@ class SwimlaneManager extends EventSource { * * @param cell Array of {@link Cell} that have been added. */ - cellsAdded(cells: CellArray) { + cellsAdded(cells: Cell[]) { if (cells.length > 0) { const model = this.graph.getDataModel(); @@ -253,7 +252,7 @@ class SwimlaneManager extends EventSource { * * @param cells Array of {@link Cell} whose size was changed. */ - cellsResized(cells: CellArray) { + cellsResized(cells: Cell[]) { if (cells.length > 0) { const model = this.getGraph().getDataModel(); diff --git a/packages/core/src/view/layout/datatypes/GraphHierarchyEdge.ts b/packages/core/src/view/layout/datatypes/GraphHierarchyEdge.ts index 742bcd60b..b2ee184e7 100644 --- a/packages/core/src/view/layout/datatypes/GraphHierarchyEdge.ts +++ b/packages/core/src/view/layout/datatypes/GraphHierarchyEdge.ts @@ -6,7 +6,6 @@ */ import GraphAbstractHierarchyCell from './GraphAbstractHierarchyCell'; import ObjectIdentity from '../../../util/ObjectIdentity'; -import CellArray from '../../cell/CellArray'; import Cell from '../../cell/Cell'; import GraphHierarchyNode from './GraphHierarchyNode'; @@ -15,7 +14,7 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell { * The graph edge(s) this object represents. Parallel edges are all grouped * together within one hierarchy edge. */ - edges: CellArray; + edges: Cell[]; /** * The object identities of the wrapped cells @@ -51,7 +50,7 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell { * * edges - a list of real graph edges this abstraction represents */ - constructor(edges: CellArray) { + constructor(edges: Cell[]) { super(); this.edges = edges; this.ids = []; @@ -102,7 +101,9 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell { this.previousLayerConnectedCells[i] = []; if (i === 0) { - this.previousLayerConnectedCells[i].push(this.target as GraphAbstractHierarchyCell); + this.previousLayerConnectedCells[i].push( + this.target as GraphAbstractHierarchyCell + ); } else { this.previousLayerConnectedCells[i].push(this); } diff --git a/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts b/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts index 07810356d..6a9d493e6 100644 --- a/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts +++ b/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts @@ -9,7 +9,6 @@ import Dictionary from '../../../util/Dictionary'; import GraphHierarchyNode from '../datatypes/GraphHierarchyNode'; import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge'; import Cell from '../../cell/Cell'; -import CellArray from '../../cell/CellArray'; import HierarchicalLayout from '../HierarchicalLayout'; import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell'; @@ -38,8 +37,8 @@ import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell' class GraphHierarchyModel { constructor( layout: HierarchicalLayout, - vertices: CellArray, - roots: CellArray, + vertices: Cell[], + roots: Cell[], parent: Cell, tightenToSource: boolean ) { @@ -135,7 +134,7 @@ class GraphHierarchyModel { * Store of roots of this hierarchy model, these are real graph cells, not * internal cells */ - roots: CellArray | null = null; + roots: Cell[] | null = null; /** * The parent cell whose children are being laid out @@ -169,7 +168,7 @@ class GraphHierarchyModel { */ createInternalCells( layout: HierarchicalLayout, - vertices: CellArray, + vertices: Cell[], internalVertices: { [key: number]: GraphHierarchyNode } ) { const graph = layout.getGraph(); @@ -263,7 +262,7 @@ class GraphHierarchyModel { } const internalNodes = this.vertexMapper.getValues(); - + for (let i = 0; i < internalNodes.length; i += 1) { // Mark the node as not having had a layer assigned internalNodes[i].temp[0] = -1; @@ -407,7 +406,13 @@ class GraphHierarchyModel { } this.visit( - (parent: GraphHierarchyNode, node: GraphHierarchyNode, edge: GraphHierarchyNode, layer: number, seen: number) => { + ( + parent: GraphHierarchyNode, + node: GraphHierarchyNode, + edge: GraphHierarchyNode, + layer: number, + seen: number + ) => { if (seen == 0 && node.maxRank < 0 && node.minRank < 0) { rankList[node.temp[0]].push(node); node.maxRank = node.temp[0]; @@ -504,11 +509,11 @@ class GraphHierarchyModel { * @param layer the layer on the dfs tree ( not the same as the model ranks ) */ dfs( - parent: GraphHierarchyNode | null, - root: GraphHierarchyNode | null, - connectingEdge: GraphHierarchyEdge | null, - visitor: Function, - seen: { [key: string]: GraphHierarchyNode | null }, + parent: GraphHierarchyNode | null, + root: GraphHierarchyNode | null, + connectingEdge: GraphHierarchyEdge | null, + visitor: Function, + seen: { [key: string]: GraphHierarchyNode | null }, layer: number ): void { if (root != null) { @@ -553,13 +558,13 @@ class GraphHierarchyModel { * @param layer the layer on the dfs tree ( not the same as the model ranks ) */ extendedDfs( - parent: GraphHierarchyNode | null, - root: GraphHierarchyNode, - connectingEdge: GraphHierarchyEdge | null, - visitor: Function, - seen: { [key: string]: GraphHierarchyNode }, - ancestors: any, - childHash: string | number, + parent: GraphHierarchyNode | null, + root: GraphHierarchyNode, + connectingEdge: GraphHierarchyEdge | null, + visitor: Function, + seen: { [key: string]: GraphHierarchyNode }, + ancestors: any, + childHash: string | number, layer: number ) { // Explanation of custom hash set. Previously, the ancestors variable diff --git a/packages/core/src/view/layout/hierarchical/SwimlaneModel.ts b/packages/core/src/view/layout/hierarchical/SwimlaneModel.ts index e5bb8ae6e..eff152494 100644 --- a/packages/core/src/view/layout/hierarchical/SwimlaneModel.ts +++ b/packages/core/src/view/layout/hierarchical/SwimlaneModel.ts @@ -4,14 +4,13 @@ * Updated to ES9 syntax by David Morrissey 2021 * Type definitions from the typed-mxgraph project */ -import GraphHierarchyNode from "../datatypes/GraphHierarchyNode"; -import GraphHierarchyEdge from "../datatypes/GraphHierarchyEdge"; -import CellPath from "../../cell/CellPath"; -import Dictionary from "../../../util/Dictionary"; -import CellArray from "../../cell/CellArray"; -import Cell from "../../cell/Cell"; -import { clone } from "../../../util/cloneUtils"; -import SwimlaneLayout from "../SwimlaneLayout"; +import GraphHierarchyNode from '../datatypes/GraphHierarchyNode'; +import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge'; +import CellPath from '../../cell/CellPath'; +import Dictionary from '../../../util/Dictionary'; +import Cell from '../../cell/Cell'; +import { clone } from '../../../util/cloneUtils'; +import SwimlaneLayout from '../SwimlaneLayout'; /** * Internal model of a hierarchical graph. This model stores nodes and edges @@ -38,8 +37,8 @@ import SwimlaneLayout from "../SwimlaneLayout"; class SwimlaneModel { constructor( layout: SwimlaneLayout, - vertices: CellArray, - roots: CellArray, + vertices: Cell[], + roots: Cell[], parent: Cell, tightenToSource: boolean ) { @@ -91,10 +90,7 @@ class SwimlaneModel { internalTargetCell = this.vertexMapper.get(targetCell); } - if ( - internalTargetCell != null && - internalVertices[i] !== internalTargetCell - ) { + if (internalTargetCell != null && internalVertices[i] !== internalTargetCell) { internalEdge.target = internalTargetCell; if (internalTargetCell.connectsAsTarget.length == 0) { @@ -138,7 +134,7 @@ class SwimlaneModel { * Store of roots of this hierarchy model, these are real graph cells, not * internal cells */ - roots: CellArray; + roots: Cell[]; /** * The parent cell whose children are being laid out @@ -177,11 +173,11 @@ class SwimlaneModel { */ createInternalCells( layout: SwimlaneLayout, - vertices: CellArray, + vertices: Cell[], internalVertices: GraphHierarchyNode[] ): void { const graph = layout.getGraph(); - const swimlanes = layout.swimlanes; + const swimlanes = layout.swimlanes as Cell[]; // Create internal edges for (let i = 0; i < vertices.length; i += 1) { @@ -208,11 +204,7 @@ class SwimlaneModel { const cell = layout.getVisibleTerminal(conns[j], false); // Looking for outgoing edges only - if ( - cell !== vertices[i] && - cell.isVertex() && - !layout.isVertexIgnored(cell) - ) { + if (cell !== vertices[i] && cell.isVertex() && !layout.isVertexIgnored(cell)) { // We process all edge between this source and its targets // If there are edges going both ways, we need to collect // them all into one internal edges to avoid looping problems @@ -226,11 +218,7 @@ class SwimlaneModel { // are the same. All the graph edges will have been assigned to // an internal edge going the other way, so we don't want to // process them again - const undirectedEdges = layout.getEdgesBetween( - vertices[i], - cell, - false - ); + const undirectedEdges = layout.getEdgesBetween(vertices[i], cell, false); const directedEdges = layout.getEdgesBetween(vertices[i], cell, true); if ( @@ -257,9 +245,7 @@ class SwimlaneModel { internalEdge.source = internalVertices[i]; - if ( - internalVertices[i].connectsAsSource.indexOf(internalEdge) < 0 - ) { + if (internalVertices[i].connectsAsSource.indexOf(internalEdge) < 0) { internalVertices[i].connectsAsSource.push(internalEdge); } } @@ -456,10 +442,7 @@ class SwimlaneModel { const slIndex = root.swimlaneIndex; const ranksPerGroup = <{ [key: number]: number }>this.ranksPerGroup; - if ( - ranksPerGroup[slIndex] == null || - ranksPerGroup[slIndex] < chainCount - ) { + if (ranksPerGroup[slIndex] == null || ranksPerGroup[slIndex] < chainCount) { ranksPerGroup[slIndex] = chainCount; } @@ -474,13 +457,7 @@ class SwimlaneModel { // Only navigate in source->target direction within the same // swimlane, or from a lower index swimlane to a higher one if (root.swimlaneIndex < targetNode.swimlaneIndex) { - this.maxChainDfs( - root, - targetNode, - internalEdge, - clone(seen, null, true), - 0 - ); + this.maxChainDfs(root, targetNode, internalEdge, clone(seen, null, true), 0); } else if (root.swimlaneIndex === targetNode.swimlaneIndex) { this.maxChainDfs( root, @@ -525,7 +502,13 @@ class SwimlaneModel { } this.visit( - (parent: GraphHierarchyNode, node: GraphHierarchyNode, edge: GraphHierarchyNode, layer: number, seen: number) => { + ( + parent: GraphHierarchyNode, + node: GraphHierarchyNode, + edge: GraphHierarchyNode, + layer: number, + seen: number + ) => { if (seen === 0 && node.maxRank < 0 && node.minRank < 0) { rankList[node.temp[0]].push(node); node.maxRank = node.temp[0]; diff --git a/packages/core/src/view/mixins/CellsMixin.ts b/packages/core/src/view/mixins/CellsMixin.ts index 2a1a96217..c220ee883 100644 --- a/packages/core/src/view/mixins/CellsMixin.ts +++ b/packages/core/src/view/mixins/CellsMixin.ts @@ -1,5 +1,4 @@ import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import { mixInto } from '../../util/Utils'; import { contains, @@ -50,12 +49,12 @@ declare module '../Graph' { extendParentsOnAdd: boolean; extendParentsOnMove: boolean; - getBoundingBox: (cells: CellArray) => Rectangle | null; + getBoundingBox: (cells: Cell[]) => Rectangle | null; removeStateForCell: (cell: Cell) => void; getCurrentCellStyle: (cell: Cell, ignoreState?: boolean) => CellStateStyle; getCellStyle: (cell: Cell) => CellStateStyle; postProcessCellStyle: (style: CellStateStyle) => CellStateStyle; - setCellStyle: (style: CellStyle, cells: CellArray) => void; + setCellStyle: (style: CellStyle, cells: Cell[]) => void; toggleCellStyle: ( key: keyof CellStateStyle, defaultValue: boolean, @@ -64,25 +63,25 @@ declare module '../Graph' { toggleCellStyles: ( key: keyof CellStateStyle, defaultValue: boolean, - cells: CellArray + cells: Cell[] ) => boolean | null; setCellStyles: ( key: keyof CellStateStyle, value: CellStateStyle[keyof CellStateStyle], - cells?: CellArray + cells?: Cell[] ) => void; toggleCellStyleFlags: ( key: NumericCellStateStyleKeys, flag: number, - cells?: CellArray | null + cells?: Cell[] | null ) => void; setCellStyleFlags: ( key: NumericCellStateStyleKeys, flag: number, value?: boolean | null, - cells?: CellArray | null + cells?: Cell[] | null ) => void; - alignCells: (align: string, cells?: CellArray, param?: number | null) => void; + alignCells: (align: string, cells?: Cell[], param?: number | null) => void; cloneCell: ( cell: Cell, allowInvalidEdges?: boolean, @@ -90,11 +89,11 @@ declare module '../Graph' { keepPosition?: boolean ) => Cell; cloneCells: ( - cells: CellArray, + cells: Cell[], allowInvalidEdges: boolean, mapping: any, keepPosition?: boolean - ) => CellArray; + ) => Cell[]; addCell: ( cell: Cell, parent: Cell | null, @@ -103,15 +102,15 @@ declare module '../Graph' { target?: Cell | null ) => Cell; addCells: ( - cells: CellArray, + cells: Cell[], parent: Cell | null, index: number | null, source: Cell | null, target: Cell | null, absolute?: boolean - ) => CellArray; + ) => Cell[]; cellsAdded: ( - cells: CellArray, + cells: Cell[], parent: Cell, index: number, source: Cell | null, @@ -121,16 +120,16 @@ declare module '../Graph' { extend?: boolean ) => void; autoSizeCell: (cell: Cell, recurse?: boolean) => void; - removeCells: (cells?: CellArray | null, includeEdges?: boolean | null) => CellArray; - cellsRemoved: (cells: CellArray) => void; - toggleCells: (show: boolean, cells: CellArray, includeEdges: boolean) => CellArray; - cellsToggled: (cells: CellArray, show: boolean) => void; + removeCells: (cells?: Cell[] | null, includeEdges?: boolean | null) => Cell[]; + cellsRemoved: (cells: Cell[]) => void; + toggleCells: (show: boolean, cells: Cell[], includeEdges: boolean) => Cell[]; + cellsToggled: (cells: Cell[], show: boolean) => void; updateCellSize: (cell: Cell, ignoreChildren?: boolean) => Cell; cellSizeUpdated: (cell: Cell, ignoreChildren: boolean) => void; getPreferredSizeForCell: (cell: Cell, textWidth?: number | null) => Rectangle | null; resizeCell: (cell: Cell, bounds: Rectangle, recurse?: boolean) => Cell; - resizeCells: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => CellArray; - cellsResized: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => void; + resizeCells: (cells: Cell[], bounds: Rectangle[], recurse: boolean) => Cell[]; + cellsResized: (cells: Cell[], bounds: Rectangle[], recurse: boolean) => void; cellResized: ( cell: Cell, bounds: Rectangle, @@ -142,24 +141,24 @@ declare module '../Graph' { scaleCell: (cell: Cell, dx: number, dy: number, recurse: boolean) => void; extendParent: (cell: Cell) => void; importCells: ( - cells: CellArray, + cells: Cell[], dx: number, dy: number, target: Cell | null, evt: MouseEvent | null, mapping: any - ) => CellArray; + ) => Cell[]; moveCells: ( - cells: CellArray, + cells: Cell[], dx: number, dy: number, clone?: boolean, target?: Cell | null, evt?: MouseEvent | null, mapping?: any - ) => CellArray; + ) => Cell[]; cellsMoved: ( - cells: CellArray, + cells: Cell[], dx: number, dy: number, disconnect: boolean, @@ -169,11 +168,7 @@ declare module '../Graph' { translateCell: (cell: Cell, dx: number, dy: number) => void; getCellContainmentArea: (cell: Cell) => Rectangle | null; constrainChild: (cell: Cell, sizeFirst?: boolean) => void; - getChildCells: ( - parent?: Cell | null, - vertices?: boolean, - edges?: boolean - ) => CellArray; + getChildCells: (parent?: Cell | null, vertices?: boolean, edges?: boolean) => Cell[]; getCellAt: ( x: number, y: number, @@ -188,40 +183,40 @@ declare module '../Graph' { width: number, height: number, parent?: Cell | null, - result?: CellArray, + result?: Cell[], intersection?: Rectangle | null, ignoreFn?: Function | null, includeDescendants?: boolean - ) => CellArray; + ) => Cell[]; getCellsBeyond: ( x0: number, y0: number, parent: Cell | null, rightHalfpane: boolean, bottomHalfpane: boolean - ) => CellArray; + ) => Cell[]; intersects: (state: CellState, x: number, y: number) => boolean; isValidAncestor: (cell: Cell, parent: Cell, recurse: boolean) => boolean; isCellLocked: (cell: Cell) => boolean; isCellsLocked: () => boolean; setCellsLocked: (value: boolean) => void; - getCloneableCells: (cells: CellArray) => CellArray; + getCloneableCells: (cells: Cell[]) => Cell[]; isCellCloneable: (cell: Cell) => boolean; isCellsCloneable: () => boolean; setCellsCloneable: (value: boolean) => void; - getExportableCells: (cells: CellArray) => CellArray; + getExportableCells: (cells: Cell[]) => Cell[]; canExportCell: (cell: Cell | null) => boolean; - getImportableCells: (cells: CellArray) => CellArray; + getImportableCells: (cells: Cell[]) => Cell[]; canImportCell: (cell: Cell | null) => boolean; isCellSelectable: (cell: Cell) => boolean; isCellsSelectable: () => boolean; setCellsSelectable: (value: boolean) => void; - getDeletableCells: (cells: CellArray) => CellArray; + getDeletableCells: (cells: Cell[]) => Cell[]; isCellDeletable: (cell: Cell) => boolean; isCellsDeletable: () => boolean; setCellsDeletable: (value: boolean) => void; isCellRotatable: (cell: Cell) => boolean; - getMovableCells: (cells: CellArray) => CellArray; + getMovableCells: (cells: Cell[]) => Cell[]; isCellMovable: (cell: Cell) => boolean; isCellsMovable: () => boolean; setCellsMovable: (value: boolean) => void; @@ -248,7 +243,7 @@ declare module '../Graph' { includeDescendants?: boolean ) => Rectangle | null; getBoundingBoxFromGeometry: ( - cells: CellArray, + cells: Cell[], includeEdges?: boolean ) => Rectangle | null; } @@ -644,7 +639,7 @@ export const CellsMixin: PartialType = { */ toggleCellStyle(key, defaultValue = false, cell?) { cell = cell ?? this.getSelectionCell(); - return this.toggleCellStyles(key, defaultValue, new CellArray(cell)); + return this.toggleCellStyles(key, defaultValue, [cell]); }, /** @@ -791,14 +786,14 @@ export const CellsMixin: PartialType = { this.batchUpdate(() => { const p = param as number; - for (const cell of cells) { + for (const cell of cells as Cell[]) { const state = this.getView().getState(cell); if (state != null) { let geo = cell.getGeometry(); if (geo != null && !cell.isEdge()) { - geo = geo.clone(); + geo = geo.clone(); if (align === ALIGN.CENTER) { geo.x += (p - state.x - state.width / 2) / s; @@ -843,12 +838,7 @@ export const CellsMixin: PartialType = { */ // cloneCell(cell: mxCell, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; cloneCell(cell, allowInvalidEdges = false, mapping = null, keepPosition = false) { - return this.cloneCells( - new CellArray(cell), - allowInvalidEdges, - mapping, - keepPosition - )[0]; + return this.cloneCells([cell], allowInvalidEdges, mapping, keepPosition)[0]; }, /** @@ -866,7 +856,7 @@ export const CellsMixin: PartialType = { */ // cloneCells(cells: mxCellArray, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; cloneCells(cells, allowInvalidEdges = true, mapping = {}, keepPosition = false) { - let clones; + let clones: Cell[]; // Creates a dictionary for fast lookups const dict = new Dictionary(); @@ -880,7 +870,7 @@ export const CellsMixin: PartialType = { if (tmp.length > 0) { const { scale } = this.getView(); const trans = this.getView().translate; - const out: CellArray = new CellArray(); + const out: Cell[] = []; clones = cells.cloneCells(true, mapping); for (let i = 0; i < cells.length; i += 1) { @@ -960,7 +950,7 @@ export const CellsMixin: PartialType = { } clones = out; } else { - clones = new CellArray(); + clones = []; } return clones; }, @@ -978,7 +968,7 @@ export const CellsMixin: PartialType = { * @param target Optional {@link Cell} that represents the target terminal. */ addCell(cell, parent = null, index = null, source = null, target = null) { - return this.addCells(new CellArray(cell), parent, index, source, target)[0]; + return this.addCells([cell], parent, index, source, target)[0]; }, /** @@ -1180,13 +1170,13 @@ export const CellsMixin: PartialType = { } this.batchUpdate(() => { - this.cellsRemoved(cells); + this.cellsRemoved(cells as Cell[]); this.fireEvent( new EventObject(InternalEvent.REMOVE_CELLS, { cells, includeEdges }) ); }); - return cells ?? new CellArray(); + return cells ?? []; }, /** @@ -1210,7 +1200,7 @@ export const CellsMixin: PartialType = { for (const cell of cells) { // Disconnects edges which are not being removed - const edges = this.getAllEdges(new CellArray(cell)); + const edges = this.getAllEdges([cell]); const disconnectTerminal = (edge: Cell, source: boolean) => { let geo = edge.getGeometry(); @@ -1431,7 +1421,7 @@ export const CellsMixin: PartialType = { } } - this.cellsResized(new CellArray(cell), [geo], false); + this.cellsResized([cell], [geo], false); } }); }, @@ -1551,7 +1541,7 @@ export const CellsMixin: PartialType = { * @param bounds {@link mxRectangle} that represents the new bounds. */ resizeCell(cell, bounds, recurse = false) { - return this.resizeCells(new CellArray(cell), [bounds], recurse)[0]; + return this.resizeCells([cell], [bounds], recurse)[0]; }, /** @@ -1562,7 +1552,7 @@ export const CellsMixin: PartialType = { * @param cells Array of {@link Cell} whose bounds should be changed. * @param bounds Array of {@link mxRectangles} that represent the new bounds. */ - resizeCells(cells, bounds, recurse): CellArray { + resizeCells(cells, bounds, recurse): Cell[] { recurse = recurse ?? this.isRecursiveResize(); this.batchUpdate(() => { @@ -1805,7 +1795,7 @@ export const CellsMixin: PartialType = { p.width = Math.max(p.width, geo.x + geo.width); p.height = Math.max(p.height, geo.y + geo.height); - this.cellsResized(new CellArray(parent), [p], false); + this.cellsResized([parent], [p], false); } } }, @@ -1885,7 +1875,7 @@ export const CellsMixin: PartialType = { }; // Removes relative edge labels with selected terminals - const checked = new CellArray(); + const checked = []; for (const cell of cells) { const geo = cell.getGeometry(); @@ -2121,7 +2111,7 @@ export const CellsMixin: PartialType = { // Finds parent offset if (max && parent) { - const off = this.getBoundingBoxFromGeometry(new CellArray(parent), false); + const off = this.getBoundingBoxFromGeometry([parent], false); if (off) { max = Rectangle.fromRectangle(max); @@ -2157,7 +2147,7 @@ export const CellsMixin: PartialType = { } if (max) { - const cells = new CellArray(cell); + const cells = [cell]; if (!cell.isCollapsed()) { const desc = cell.getDescendants(); @@ -2244,7 +2234,7 @@ export const CellsMixin: PartialType = { parent = parent ?? this.getDefaultParent(); const cells = parent.getChildCells(vertices, edges); - const result = new CellArray(); + const result = []; // Filters out the non-visible child cells for (const cell of cells) { @@ -2332,7 +2322,7 @@ export const CellsMixin: PartialType = { width, height, parent = null, - result = new CellArray(), + result = [], intersection = null, ignoreFn = null, includeDescendants = false @@ -2428,7 +2418,7 @@ export const CellsMixin: PartialType = { } } } - return new CellArray(...result); + return result; }, /** @@ -2921,7 +2911,7 @@ export const CellsMixin: PartialType = { * of all descendants should be included. Default is `false`. */ getCellBounds(cell, includeEdges = false, includeDescendants = false) { - let cells = new CellArray(cell); + let cells = [cell]; // Includes all connected edges if (includeEdges) { @@ -3023,7 +3013,7 @@ export const CellsMixin: PartialType = { if (geo.relative && parent) { if (parent.isVertex() && parent !== this.getView().currentRoot) { - tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false); + tmp = this.getBoundingBoxFromGeometry([parent], false); if (tmp) { bbox = new Rectangle( @@ -3043,7 +3033,7 @@ export const CellsMixin: PartialType = { bbox = Rectangle.fromRectangle(geo); if (parent && parent.isVertex() && cells.indexOf(parent) >= 0) { - tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false); + tmp = this.getBoundingBoxFromGeometry([parent], false); if (tmp) { bbox.x += tmp.x; diff --git a/packages/core/src/view/mixins/ConnectionsMixin.ts b/packages/core/src/view/mixins/ConnectionsMixin.ts index 1fb0ad6c1..e285266a8 100644 --- a/packages/core/src/view/mixins/ConnectionsMixin.ts +++ b/packages/core/src/view/mixins/ConnectionsMixin.ts @@ -7,7 +7,6 @@ import { DIRECTION } from '../../util/Constants'; import { mixInto } from '../../util/Utils'; import { getRotatedPoint, toRadians } from '../../util/mathUtils'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Dictionary from '../../util/Dictionary'; @@ -58,8 +57,8 @@ declare module '../Graph' { source: boolean, constraint?: ConnectionConstraint | null ) => void; - disconnectGraph: (cells: CellArray) => void; - getConnections: (cell: Cell, parent?: Cell | null) => CellArray; + disconnectGraph: (cells: Cell[]) => void; + getConnections: (cell: Cell, parent?: Cell | null) => Cell[]; isConstrainChild: (cell: Cell) => boolean; isConstrainChildren: () => boolean; setConstrainChildren: (value: boolean) => void; @@ -292,50 +291,22 @@ const ConnectionsMixin: PartialType = { if (constraint) { this.batchUpdate(() => { if (!constraint || !constraint.point) { - this.setCellStyles(source ? 'exitX' : 'entryX', null, new CellArray(edge)); - this.setCellStyles(source ? 'exitY' : 'entryY', null, new CellArray(edge)); - this.setCellStyles(source ? 'exitDx' : 'entryDx', null, new CellArray(edge)); - this.setCellStyles(source ? 'exitDy' : 'entryDy', null, new CellArray(edge)); - this.setCellStyles( - source ? 'exitPerimeter' : 'entryPerimeter', - null, - new CellArray(edge) - ); + this.setCellStyles(source ? 'exitX' : 'entryX', null, [edge]); + this.setCellStyles(source ? 'exitY' : 'entryY', null, [edge]); + this.setCellStyles(source ? 'exitDx' : 'entryDx', null, [edge]); + this.setCellStyles(source ? 'exitDy' : 'entryDy', null, [edge]); + this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', null, [edge]); } else if (constraint.point) { - this.setCellStyles( - source ? 'exitX' : 'entryX', - constraint.point.x, - new CellArray(edge) - ); - this.setCellStyles( - source ? 'exitY' : 'entryY', - constraint.point.y, - new CellArray(edge) - ); - this.setCellStyles( - source ? 'exitDx' : 'entryDx', - constraint.dx, - new CellArray(edge) - ); - this.setCellStyles( - source ? 'exitDy' : 'entryDy', - constraint.dy, - new CellArray(edge) - ); + this.setCellStyles(source ? 'exitX' : 'entryX', constraint.point.x, [edge]); + this.setCellStyles(source ? 'exitY' : 'entryY', constraint.point.y, [edge]); + this.setCellStyles(source ? 'exitDx' : 'entryDx', constraint.dx, [edge]); + this.setCellStyles(source ? 'exitDy' : 'entryDy', constraint.dy, [edge]); // Only writes 0 since 1 is default if (!constraint.perimeter) { - this.setCellStyles( - source ? 'exitPerimeter' : 'entryPerimeter', - '0', - new CellArray(edge) - ); + this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', '0', [edge]); } else { - this.setCellStyles( - source ? 'exitPerimeter' : 'entryPerimeter', - null, - new CellArray(edge) - ); + this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', null, [edge]); } } }); @@ -503,7 +474,7 @@ const ConnectionsMixin: PartialType = { // Sets or resets all previous information for connecting to a child port const key = source ? 'sourcePort' : 'targetPort'; - this.setCellStyles(key, id, new CellArray(edge)); + this.setCellStyles(key, id, [edge]); } this.getDataModel().setTerminal(edge, terminal, source); diff --git a/packages/core/src/view/mixins/DragDropMixin.ts b/packages/core/src/view/mixins/DragDropMixin.ts index 4cb9f4dc3..aa95db862 100644 --- a/packages/core/src/view/mixins/DragDropMixin.ts +++ b/packages/core/src/view/mixins/DragDropMixin.ts @@ -1,6 +1,5 @@ import { mixInto } from '../../util/Utils'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import { Graph } from '../Graph'; declare module '../Graph' { @@ -16,7 +15,7 @@ declare module '../Graph' { setDropEnabled: (value: boolean) => void; isSplitEnabled: () => boolean; setSplitEnabled: (value: boolean) => void; - isSplitTarget: (target: Cell, cells?: CellArray, evt?: MouseEvent | null) => boolean; + isSplitTarget: (target: Cell, cells?: Cell[], evt?: MouseEvent | null) => boolean; } } @@ -133,7 +132,7 @@ const DragDropMixin: PartialType = { * @param cells {@link mxCell} that should split the edge. * @param evt Mouseevent that triggered the invocation. */ - isSplitTarget(target, cells=new CellArray(), evt) { + isSplitTarget(target, cells = [], evt) { if ( target.isEdge() && cells.length === 1 && diff --git a/packages/core/src/view/mixins/EdgeMixin.ts b/packages/core/src/view/mixins/EdgeMixin.ts index f7c4313b8..063015450 100644 --- a/packages/core/src/view/mixins/EdgeMixin.ts +++ b/packages/core/src/view/mixins/EdgeMixin.ts @@ -1,5 +1,4 @@ import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import { mixInto } from '../../util/Utils'; import { removeDuplicates } from '../../util/arrayUtils'; import { findNearestSegment } from '../../util/mathUtils'; @@ -36,7 +35,7 @@ declare module '../Graph' { flipEdge: (edge: Cell) => Cell; splitEdge: ( edge: Cell, - cells: CellArray, + cells: Cell[], newEdge: Cell | null, dx?: number, dy?: number, @@ -60,10 +59,10 @@ declare module '../Graph' { target: Cell | null, index?: number | null ) => Cell; - addAllEdges: (cells: CellArray) => CellArray; - getAllEdges: (cells: CellArray | null) => CellArray; - getIncomingEdges: (cell: Cell, parent: Cell | null) => CellArray; - getOutgoingEdges: (cell: Cell, parent: Cell | null) => CellArray; + addAllEdges: (cells: Cell[]) => Cell[]; + getAllEdges: (cells: Cell[] | null) => Cell[]; + getIncomingEdges: (cell: Cell, parent: Cell | null) => Cell[]; + getOutgoingEdges: (cell: Cell, parent: Cell | null) => Cell[]; getEdges: ( cell: Cell, parent?: Cell | null, @@ -71,10 +70,10 @@ declare module '../Graph' { outgoing?: boolean, includeLoops?: boolean, recurse?: boolean - ) => CellArray; - getChildEdges: (parent: Cell) => CellArray; - getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => CellArray; - resetEdges: (cells: CellArray) => void; + ) => Cell[]; + getChildEdges: (parent: Cell) => Cell[]; + getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => Cell[]; + resetEdges: (cells: Cell[]) => void; resetEdge: (edge: Cell) => Cell; } } @@ -369,7 +368,7 @@ const EdgeMixin: PartialType = { true ); this.cellsAdded( - new CellArray(newEdge), + [newEdge], parent as Cell, parent ? parent.getChildCount() : 0, source, @@ -476,14 +475,14 @@ const EdgeMixin: PartialType = { */ addAllEdges(cells) { const allCells = cells.slice(); - return new CellArray(...removeDuplicates(allCells.concat(this.getAllEdges(cells)))); + return removeDuplicates(allCells.concat(this.getAllEdges(cells))); }, /** * Returns all edges connected to the given cells or its descendants. */ getAllEdges(cells) { - let edges: CellArray = new CellArray(); + let edges: Cell[] = []; if (cells) { for (let i = 0; i < cells.length; i += 1) { @@ -555,7 +554,7 @@ const EdgeMixin: PartialType = { includeLoops = true, recurse = false ) { - let edges: CellArray = new CellArray(); + let edges: Cell[] = []; const isCollapsed = cell.isCollapsed(); const childCount = cell.getChildCount(); @@ -568,7 +567,7 @@ const EdgeMixin: PartialType = { } edges = edges.concat(cell.getEdges(incoming, outgoing)); - const result = new CellArray(); + const result = []; for (let i = 0; i < edges.length; i += 1) { const state = this.getView().getState(edges[i]); @@ -620,7 +619,7 @@ const EdgeMixin: PartialType = { */ getEdgesBetween(source, target, directed = false) { const edges = this.getEdges(source); - const result = new CellArray(); + const result = []; // Checks if the edge is connected to the correct // cell and returns the first match diff --git a/packages/core/src/view/mixins/FoldingMixin.ts b/packages/core/src/view/mixins/FoldingMixin.ts index 2a039aadc..e26578000 100644 --- a/packages/core/src/view/mixins/FoldingMixin.ts +++ b/packages/core/src/view/mixins/FoldingMixin.ts @@ -2,7 +2,6 @@ import Image from '../image/ImageBox'; import Client from '../../Client'; import CellState from '../cell/CellState'; import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Geometry from '../geometry/Geometry'; @@ -18,18 +17,18 @@ declare module '../Graph' { getCollapseExpandResource: () => string; isFoldingEnabled: () => boolean; - getFoldableCells: (cells: CellArray, collapse: boolean) => CellArray | null; + getFoldableCells: (cells: Cell[], collapse: boolean) => Cell[] | null; isCellFoldable: (cell: Cell, collapse: boolean) => boolean; getFoldingImage: (state: CellState) => Image | null; foldCells: ( collapse: boolean, recurse?: boolean, - cells?: CellArray | null, + cells?: Cell[] | null, checkFoldable?: boolean, evt?: Event | null - ) => CellArray | null; + ) => Cell[] | null; cellsFolded: ( - cells: CellArray | null, + cells: Cell[] | null, collapse: boolean, recurse: boolean, checkFoldable?: boolean @@ -119,7 +118,7 @@ const FoldingMixin: PartialType = { }, /** - * @default true + * @default true */ /** diff --git a/packages/core/src/view/mixins/GroupingMixin.ts b/packages/core/src/view/mixins/GroupingMixin.ts index ebba05e6c..af1c520b1 100644 --- a/packages/core/src/view/mixins/GroupingMixin.ts +++ b/packages/core/src/view/mixins/GroupingMixin.ts @@ -1,5 +1,4 @@ import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import { mixInto } from '../../util/Utils'; import { sortCells } from '../../util/styleUtils'; import Geometry from '../geometry/Geometry'; @@ -11,27 +10,27 @@ import { Graph } from '../Graph'; declare module '../Graph' { interface Graph { - groupCells: (group: Cell, border: number, cells?: CellArray | null) => Cell; - getCellsForGroup: (cells: CellArray) => CellArray; + groupCells: (group: Cell, border: number, cells?: Cell[] | null) => Cell; + getCellsForGroup: (cells: Cell[]) => Cell[]; getBoundsForGroup: ( group: Cell, - children: CellArray, + children: Cell[], border: number | null ) => Rectangle | null; - createGroupCell: (cells: CellArray) => Cell; - ungroupCells: (cells?: CellArray | null) => CellArray; - getCellsForUngroup: () => CellArray; - removeCellsAfterUngroup: (cells: CellArray) => void; - removeCellsFromParent: (cells?: CellArray | null) => CellArray; + createGroupCell: (cells: Cell[]) => Cell; + ungroupCells: (cells?: Cell[] | null) => Cell[]; + getCellsForUngroup: () => Cell[]; + removeCellsAfterUngroup: (cells: Cell[]) => void; + removeCellsFromParent: (cells?: Cell[] | null) => Cell[]; updateGroupBounds: ( - cells: CellArray, + cells: Cell[], border?: number, moveGroup?: boolean, topBorder?: number, rightBorder?: number, bottomBorder?: number, leftBorder?: number - ) => CellArray; + ) => Cell[]; enterGroup: (cell: Cell) => void; exitGroup: () => void; } @@ -125,24 +124,15 @@ const GroupingMixin: PartialType = { // Adds the group into the parent let index = (parent).getChildCount(); - this.cellsAdded( - new CellArray(group), - parent, - index, - null, - null, - false, - false, - false - ); + this.cellsAdded([group], parent, index, null, null, false, false, false); // Adds the children into the group and moves index = group.getChildCount(); - this.cellsAdded(cells, group, index, null, null, false, false, false); - this.cellsMoved(cells, -bounds.x, -bounds.y, false, false, false); + this.cellsAdded(cells, group, index, null, null, false, false, false); + this.cellsMoved(cells, -bounds.x, -bounds.y, false, false, false); // Resizes the group - this.cellsResized(new CellArray(group), [bounds], false); + this.cellsResized([group], [bounds], false); this.fireEvent( new EventObject(InternalEvent.GROUP_CELLS, { group, border, cells }) @@ -157,7 +147,7 @@ const GroupingMixin: PartialType = { * in the given array. */ getCellsForGroup(cells) { - const result = new CellArray(); + const result = []; if (cells != null && cells.length > 0) { const parent = cells[0].getParent(); result.push(cells[0]); @@ -231,7 +221,7 @@ const GroupingMixin: PartialType = { * selection cells are used. */ ungroupCells(cells) { - let result: CellArray = new CellArray(); + let result: Cell[] = []; if (cells == null) { cells = this.getCellsForUngroup(); @@ -239,7 +229,7 @@ const GroupingMixin: PartialType = { if (cells != null && cells.length > 0) { this.batchUpdate(() => { - const _cells = cells; + const _cells = cells; for (let i = 0; i < _cells.length; i += 1) { let children = _cells[i].getChildren(); @@ -283,7 +273,7 @@ const GroupingMixin: PartialType = { const cells = this.getSelectionCells(); // Finds the cells with children - const tmp = new CellArray(); + const tmp = []; for (let i = 0; i < cells.length; i += 1) { if (cells[i].isVertex() && cells[i].getChildCount() > 0) { @@ -316,10 +306,8 @@ const GroupingMixin: PartialType = { const parent = this.getDefaultParent(); const index = parent.getChildCount(); - this.cellsAdded(cells, parent, index, null, null, true); - this.fireEvent( - new EventObject(InternalEvent.REMOVE_CELLS_FROM_PARENT, { cells }) - ); + this.cellsAdded(cells, parent, index, null, null, true); + this.fireEvent(new EventObject(InternalEvent.REMOVE_CELLS_FROM_PARENT, { cells })); }); return cells; }, @@ -367,7 +355,7 @@ const GroupingMixin: PartialType = { continue; } - const children = this.getChildCells(cells[i]); + const children = this.getChildCells(cells[i]); if (children != null && children.length > 0) { const bounds = this.getBoundingBoxFromGeometry(children, true); diff --git a/packages/core/src/view/mixins/OrderMixin.ts b/packages/core/src/view/mixins/OrderMixin.ts index 7fd397241..0ff55f4a5 100644 --- a/packages/core/src/view/mixins/OrderMixin.ts +++ b/packages/core/src/view/mixins/OrderMixin.ts @@ -1,14 +1,14 @@ -import CellArray from '../cell/CellArray'; import { mixInto } from '../../util/Utils'; import { sortCells } from '../../util/styleUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import { Graph } from '../Graph'; +import Cell from '../cell/Cell'; declare module '../Graph' { interface Graph { - orderCells: (back: boolean, cells?: CellArray) => CellArray; - cellsOrdered: (cells: CellArray, back: boolean) => void; + orderCells: (back: boolean, cells?: Cell[]) => Cell[]; + cellsOrdered: (cells: Cell[], back: boolean) => void; } } @@ -41,7 +41,7 @@ const OrderMixin: PartialType = { } this.batchUpdate(() => { - this.cellsOrdered(cells, back); + this.cellsOrdered(cells, back); const event = new EventObject( InternalEvent.ORDER_CELLS, 'back', @@ -70,13 +70,15 @@ const OrderMixin: PartialType = { if (back) { this.getDataModel().add(parent, cells[i], i); } else { - this.getDataModel().add(parent, cells[i], parent ? parent.getChildCount() - 1 : 0); + this.getDataModel().add( + parent, + cells[i], + parent ? parent.getChildCount() - 1 : 0 + ); } } - this.fireEvent( - new EventObject(InternalEvent.CELLS_ORDERED, { back, cells }) - ); + this.fireEvent(new EventObject(InternalEvent.CELLS_ORDERED, { back, cells })); }); }, }; diff --git a/packages/core/src/view/mixins/SelectionMixin.ts b/packages/core/src/view/mixins/SelectionMixin.ts index 3e7c3c801..2e5b86537 100644 --- a/packages/core/src/view/mixins/SelectionMixin.ts +++ b/packages/core/src/view/mixins/SelectionMixin.ts @@ -1,5 +1,4 @@ import Cell from '../cell/Cell'; -import CellArray from '../cell/CellArray'; import Rectangle from '../geometry/Rectangle'; import Dictionary from '../../util/Dictionary'; import RootChange from '../undoable_changes/RootChange'; @@ -10,7 +9,7 @@ import GraphSelectionModel from '../GraphSelectionModel'; declare module '../Graph' { interface Graph { - cells: CellArray; + cells: Cell[]; doneResource: string; updatingSelectionResource: string; singleSelection: boolean; @@ -23,14 +22,14 @@ declare module '../Graph' { clearSelection: () => void; getSelectionCount: () => number; getSelectionCell: () => Cell; - getSelectionCells: () => CellArray; + getSelectionCells: () => Cell[]; setSelectionCell: (cell: Cell | null) => void; - setSelectionCells: (cells: CellArray) => void; + setSelectionCells: (cells: Cell[]) => void; addSelectionCell: (cell: Cell) => void; - addSelectionCells: (cells: CellArray) => void; + addSelectionCells: (cells: Cell[]) => void; removeSelectionCell: (cell: Cell) => void; - removeSelectionCells: (cells: CellArray) => void; - selectRegion: (rect: Rectangle, evt: MouseEvent) => CellArray; + removeSelectionCells: (cells: Cell[]) => void; + selectRegion: (rect: Rectangle, evt: MouseEvent) => Cell[]; selectNextCell: () => void; selectPreviousCell: () => void; selectParentCell: () => void; @@ -46,9 +45,9 @@ declare module '../Graph' { selectGroups?: boolean ) => void; selectCellForEvent: (cell: Cell, evt: MouseEvent) => void; - selectCellsForEvent: (cells: CellArray, evt: MouseEvent) => void; + selectCellsForEvent: (cells: Cell[], evt: MouseEvent) => void; isSiblingSelected: (cell: Cell) => boolean; - getSelectionCellsForChanges: (changes: any[], ignoreFn?: Function | null) => CellArray; + getSelectionCellsForChanges: (changes: any[], ignoreFn?: Function | null) => Cell[]; updateSelection: () => void; } } @@ -271,7 +270,8 @@ const SelectionMixin: PartialType = { * @param isChild Boolean indicating if the first child cell should be selected. */ selectCell(isNext = false, isParent = false, isChild = false) { - const cell = this.selectionModel.cells.length > 0 ? this.selectionModel.cells[0] : null; + const cell = + this.selectionModel.cells.length > 0 ? this.selectionModel.cells[0] : null; if (this.selectionModel.cells.length > 1) { this.selectionModel.clear(); @@ -452,7 +452,7 @@ const SelectionMixin: PartialType = { */ getSelectionCellsForChanges(changes, ignoreFn = null) { const dict = new Dictionary(); - const cells: CellArray = new CellArray(); + const cells: Cell[] = []; const addCell = (cell: Cell) => { if (!dict.get(cell) && this.getDataModel().contains(cell)) { @@ -494,7 +494,7 @@ const SelectionMixin: PartialType = { */ updateSelection() { const cells = this.getSelectionCells(); - const removed = new CellArray(); + const removed = []; for (const cell of cells) { if (!this.getDataModel().contains(cell) || !cell.isVisible()) { diff --git a/packages/core/src/view/mixins/SwimlaneMixin.ts b/packages/core/src/view/mixins/SwimlaneMixin.ts index cfbefdf25..c8f5139b9 100644 --- a/packages/core/src/view/mixins/SwimlaneMixin.ts +++ b/packages/core/src/view/mixins/SwimlaneMixin.ts @@ -4,7 +4,6 @@ import { mixInto } from '../../util/Utils'; import { convertPoint } from '../../util/styleUtils'; import { mod } from '../../util/mathUtils'; import { DEFAULT_STARTSIZE, DIRECTION, SHAPE } from '../../util/Constants'; -import CellArray from '../cell/CellArray'; import { getClientX, getClientY } from '../../util/EventUtils'; import { Graph } from '../Graph'; @@ -23,13 +22,9 @@ declare module '../Graph' { getSwimlaneDirection: (style: CellStateStyle) => DirectionValue; getActualStartSize: (swimlane: Cell, ignoreState: boolean) => Rectangle; isSwimlane: (cell: Cell, ignoreState?: boolean) => boolean; - isValidDropTarget: ( - cell: Cell, - cells?: CellArray, - evt?: MouseEvent | null - ) => boolean; + isValidDropTarget: (cell: Cell, cells?: Cell[], evt?: MouseEvent | null) => boolean; getDropTarget: ( - cells: CellArray, + cells: Cell[], evt: MouseEvent, cell: Cell | null, clone?: boolean diff --git a/packages/core/src/view/mixins/TerminalMixin.ts b/packages/core/src/view/mixins/TerminalMixin.ts index 61fd5b22c..0c971254b 100644 --- a/packages/core/src/view/mixins/TerminalMixin.ts +++ b/packages/core/src/view/mixins/TerminalMixin.ts @@ -1,4 +1,3 @@ -import CellArray from '../cell/CellArray'; import Cell from '../cell/Cell'; import Dictionary from '../../util/Dictionary'; import { Graph } from '../Graph'; @@ -8,11 +7,11 @@ declare module '../Graph' { interface Graph { isTerminalPointMovable: (cell: Cell, source: boolean) => boolean; getOpposites: ( - edges: CellArray, + edges: Cell[], terminal: Cell | null, sources?: boolean, targets?: boolean - ) => CellArray; + ) => Cell[]; } } @@ -58,7 +57,7 @@ const TerminalMixin: PartialType = { * included in the result. Default is `true`. */ getOpposites(edges, terminal = null, sources = true, targets = true) { - const terminals = new CellArray(); + const terminals = []; // Fast lookup to avoid duplicates in terminals array const dict = new Dictionary(); diff --git a/packages/core/src/view/mixins/VertexMixin.ts b/packages/core/src/view/mixins/VertexMixin.ts index c6503520d..581e692ca 100644 --- a/packages/core/src/view/mixins/VertexMixin.ts +++ b/packages/core/src/view/mixins/VertexMixin.ts @@ -1,7 +1,6 @@ import Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; import { Graph } from '../Graph'; -import CellArray from '../cell/CellArray'; import { mixInto } from '../../util/Utils'; import type { CellStyle } from '../../types'; @@ -25,7 +24,7 @@ declare module '../Graph' { relative: boolean, geometryClass: typeof Geometry ) => Cell; - getChildVertices: (parent?: Cell | null) => CellArray; + getChildVertices: (parent?: Cell | null) => Cell[]; isVertexLabelsMovable: () => boolean; setVertexLabelsMovable: (value: boolean) => void; } diff --git a/packages/core/src/view/other/PrintPreview.ts b/packages/core/src/view/other/PrintPreview.ts index d59c225f0..48216563d 100644 --- a/packages/core/src/view/other/PrintPreview.ts +++ b/packages/core/src/view/other/PrintPreview.ts @@ -13,7 +13,6 @@ import { DIALECT } from '../../util/Constants'; import { addLinkToHead, write } from '../../util/domUtils'; import { Graph } from '../Graph'; import CellState from '../cell/CellState'; -import CellArray from '../cell/CellArray'; import Cell from '../cell/Cell'; /** @@ -165,14 +164,14 @@ import Cell from '../cell/Cell'; class PrintPreview { constructor( graph: Graph, - scale: number | null=null, - pageFormat: Rectangle | null=null, - border: number | null=null, - x0: number=0, - y0: number=0, - borderColor: string | null=null, - title: string='Printer-friendly version', - pageSelector: boolean | null=null + scale: number | null = null, + pageFormat: Rectangle | null = null, + border: number | null = null, + x0: number = 0, + y0: number = 0, + borderColor: string | null = null, + title: string = 'Printer-friendly version', + pageSelector: boolean | null = null ) { this.graph = graph; this.scale = scale != null ? scale : 1 / graph.pageScale; @@ -327,7 +326,14 @@ class PrintPreview { * @param targetWindow Optional window that should be used for rendering. If * this is specified then no HEAD tag, CSS and BODY tag will be written. */ - appendGraph(graph: Graph, scale: number, x0: number, y0: number, forcePageBreaks: boolean, keepOpen: boolean) { + appendGraph( + graph: Graph, + scale: number, + x0: number, + y0: number, + forcePageBreaks: boolean, + keepOpen: boolean + ) { this.graph = graph; this.scale = scale != null ? scale : 1 / graph.pageScale; this.x0 = x0; @@ -344,10 +350,10 @@ class PrintPreview { * this is specified then no HEAD tag, CSS and BODY tag will be written. */ open( - css: string | null=null, - targetWindow: Window | null=null, - forcePageBreaks: boolean=false, - keepOpen: boolean=false + css: string | null = null, + targetWindow: Window | null = null, + forcePageBreaks: boolean = false, + keepOpen: boolean = false ): Window | null { // Closing the window while the page is being rendered may cause an // exception in IE. This and any other exceptions are simply ignored. @@ -385,7 +391,7 @@ class PrintPreview { } if (!this.wnd) { - throw new Error("Create new window not allowed"); + throw new Error('Create new window not allowed'); } const doc = this.wnd.document; @@ -653,7 +659,7 @@ class PrintPreview { */ createPageSelector(vpages: number, hpages: number): HTMLTableElement { if (!this.wnd) { - throw new Error("Popup window not created"); + throw new Error('Popup window not created'); } const doc = this.wnd.document; const table = doc.createElement('table'); @@ -700,7 +706,14 @@ class PrintPreview { * Takes the inner div as the argument. * @param pageNumber Integer representing the page number. */ - renderPage(w: number, h: number, dx: number, dy: number, content: (div: HTMLDivElement) => void, pageNumber?: number): HTMLDivElement{ + renderPage( + w: number, + h: number, + dx: number, + dy: number, + content: (div: HTMLDivElement) => void, + pageNumber?: number + ): HTMLDivElement { let div: HTMLDivElement | null = document.createElement('div'); let arg = null; @@ -792,7 +805,14 @@ class PrintPreview { * @param div Div that contains the output. * @param clip Contains the clipping rectangle as an {@link Rectangle}. */ - addGraphFragment(dx: number, dy: number, scale: number, pageNumber: number, div: HTMLDivElement, clip: Rectangle) { + addGraphFragment( + dx: number, + dy: number, + scale: number, + pageNumber: number, + div: HTMLDivElement, + clip: Rectangle + ) { const view = this.graph.getView(); const previousContainer = this.graph.container; this.graph.container = div; @@ -882,7 +902,7 @@ class PrintPreview { try { // Creates the temporary cell states in the view and // draws them onto the temporary DOM nodes in the view - const cells = new CellArray(this.getRoot()); + const cells = [this.getRoot()]; temp = new TemporaryCellStates(view, scale, cells, null, (state: CellState) => { return this.getLinkForCellState(state); }); diff --git a/packages/core/src/view/undoable_changes/SelectionChange.ts b/packages/core/src/view/undoable_changes/SelectionChange.ts index 85b06529b..b5af90266 100644 --- a/packages/core/src/view/undoable_changes/SelectionChange.ts +++ b/packages/core/src/view/undoable_changes/SelectionChange.ts @@ -1,21 +1,17 @@ import EventObject from '../event/EventObject'; import Translations from '../../util/Translations'; import InternalEvent from '../event/InternalEvent'; -import CellArray from '../cell/CellArray'; import type { UndoableChange } from '../../types'; import type { Graph } from '../Graph'; +import Cell from '../cell/Cell'; /** * @class SelectionChange * Action to change the current root in a view. */ class SelectionChange implements UndoableChange { - constructor( - graph: Graph, - added: CellArray = new CellArray(), - removed: CellArray = new CellArray() - ) { + constructor(graph: Graph, added: Cell[] = [], removed: Cell[] = []) { this.graph = graph; this.added = added.slice(); this.removed = removed.slice(); @@ -23,9 +19,9 @@ class SelectionChange implements UndoableChange { graph: Graph; - added: CellArray; + added: Cell[]; - removed: CellArray; + removed: Cell[]; /** * Changes the current root of the view. diff --git a/packages/html/stories/DragSource.stories.js b/packages/html/stories/DragSource.stories.js index 412e5a77f..6d7d7e62d 100644 --- a/packages/html/stories/DragSource.stories.js +++ b/packages/html/stories/DragSource.stories.js @@ -9,7 +9,6 @@ import { Guide, eventUtils, Cell, - CellArray, Geometry, } from '@maxgraph/core'; @@ -134,7 +133,7 @@ const Template = ({ label, ...args }) => { const funct = (graph, evt, target, x, y) => { const cell = new Cell('Test', new Geometry(0, 0, 120, 40)); cell.vertex = true; - const cells = graph.importCells(new CellArray(cell), x, y, target); + const cells = graph.importCells([cell], x, y, target); if (cells != null && cells.length > 0) { graph.scrollCellToVisible(cells[0]); @@ -158,7 +157,16 @@ const Template = ({ label, ...args }) => { // if scalePreview (last) argument is true. Dx and dy are null to force // the use of the defaults. Note that dx and dy are only used for the // drag icon but not for the preview. - const ds = gestureUtils.makeDraggable(img, graphF, funct, dragElt, null, null, graphs[0].autoscroll, true); + const ds = gestureUtils.makeDraggable( + img, + graphF, + funct, + dragElt, + null, + null, + graphs[0].autoscroll, + true + ); // Redirects feature to global switch. Note that this feature should only be used // if the the x and y arguments are used in funct to insert the cell. diff --git a/packages/html/stories/HoverIcons.stories.js b/packages/html/stories/HoverIcons.stories.js index 6cb534f01..46c82c903 100644 --- a/packages/html/stories/HoverIcons.stories.js +++ b/packages/html/stories/HoverIcons.stories.js @@ -4,7 +4,6 @@ import { RubberBandHandler, ImageBox, Rectangle, - CellArray, mathUtils, domUtils, ConnectionHandler, @@ -56,7 +55,7 @@ const Template = ({ label, ...args }) => { InternalEvent.addGestureListeners(img, (evt) => { const s = graph.gridSize; - graph.setSelectionCells(graph.moveCells(new CellArray(state.cell), s, s, true)); + graph.setSelectionCells(graph.moveCells([state.cell], s, s, true)); InternalEvent.consume(evt); this.destroy(); }); @@ -82,7 +81,7 @@ const Template = ({ label, ...args }) => { }); InternalEvent.addListener(img, 'click', (evt) => { - graph.removeCells(new CellArray(state.cell)); + graph.removeCells([state.cell]); InternalEvent.consume(evt); this.destroy(); }); diff --git a/packages/html/stories/Toolbar.stories.js b/packages/html/stories/Toolbar.stories.js index 4c1bbba06..8334130d3 100644 --- a/packages/html/stories/Toolbar.stories.js +++ b/packages/html/stories/Toolbar.stories.js @@ -7,7 +7,6 @@ import { GraphDataModel, KeyHandler, Cell, - CellArray, Geometry, DragSource, DomHelpers, @@ -143,7 +142,7 @@ const Template = ({ label, ...args }) => { vertex.geometry.x = pt.x; vertex.geometry.y = pt.y; - graph.setSelectionCells(graph.importCells(new CellArray(vertex), 0, 0, cell)); + graph.setSelectionCells(graph.importCells([vertex], 0, 0, cell)); }; // Creates the image which is used as the drag icon (preview) From 3cc271370475949563184c90304082be69251921 Mon Sep 17 00:00:00 2001 From: Junsik Shim Date: Sat, 17 Sep 2022 11:30:23 +0900 Subject: [PATCH 2/2] Change CellArray to cellArrayUtils. --- packages/core/src/index.ts | 1 + packages/core/src/util/Clipboard.ts | 8 +- packages/core/src/util/cellArrayUtils.ts | 198 +++++++++++++++++ packages/core/src/view/Graph.ts | 2 - packages/core/src/view/GraphDataModel.ts | 5 +- packages/core/src/view/cell/CellArray.ts | 209 ------------------ .../layout/datatypes/GraphHierarchyNode.ts | 6 +- .../hierarchical/GraphHierarchyModel.ts | 2 +- packages/core/src/view/mixins/CellsMixin.ts | 17 +- packages/html/stories/Clipboard.stories.js | 5 +- packages/html/stories/Groups.stories.js | 17 +- 11 files changed, 234 insertions(+), 236 deletions(-) create mode 100644 packages/core/src/util/cellArrayUtils.ts delete mode 100644 packages/core/src/view/cell/CellArray.ts diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e48b1cd07..f56d55c4b 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -145,6 +145,7 @@ export * as stringUtils from './util/StringUtils'; export * as xmlUtils from './util/xmlUtils'; export * as styleUtils from './util/styleUtils'; export * as mathUtils from './util/mathUtils'; +export * as cellArrayUtils from './util/cellArrayUtils'; export { default as Animation } from './view/animate/Animation'; export { default as Effects } from './view/animate/Effects'; diff --git a/packages/core/src/util/Clipboard.ts b/packages/core/src/util/Clipboard.ts index d77fda22b..3c73de127 100644 --- a/packages/core/src/util/Clipboard.ts +++ b/packages/core/src/util/Clipboard.ts @@ -7,6 +7,7 @@ import Cell from '../view/cell/Cell'; import { Graph } from '../view/Graph'; +import { getTopmostCells } from './cellArrayUtils'; /** * @class @@ -140,7 +141,6 @@ class Clipboard { * @param cells - Array of {@link mxCell} to be cut. */ static removeCells(graph: Graph, cells: Cell[]) { - // @ts-ignore graph.removeCells(cells); } @@ -154,9 +154,9 @@ class Clipboard { */ static copy(graph: Graph, cells?: Cell[]) { cells = cells || graph.getSelectionCells(); - const result = graph.getExportableCells(cells).getTopmostCells(); + const result = getTopmostCells(graph.getExportableCells(cells)); Clipboard.insertCount = 1; - // @ts-ignore + Clipboard.setCells(graph.cloneCells(result)); return result; } @@ -179,7 +179,7 @@ class Clipboard { cells = graph.getImportableCells(Clipboard.getCells()); const delta = Clipboard.insertCount * Clipboard.STEPSIZE; const parent = graph.getDefaultParent(); - // @ts-ignore + cells = graph.importCells(cells, delta, delta, parent); // Increments the counter and selects the inserted cells diff --git a/packages/core/src/util/cellArrayUtils.ts b/packages/core/src/util/cellArrayUtils.ts new file mode 100644 index 000000000..e8ebb5c38 --- /dev/null +++ b/packages/core/src/util/cellArrayUtils.ts @@ -0,0 +1,198 @@ +import Cell from '../view/cell/Cell'; +import Dictionary from './Dictionary'; +import ObjectIdentity from './ObjectIdentity'; + +/** + * Returns the cells from the given array where the given filter function + * returns true. + */ +export const filterCells = (filter: Function) => (cells: Cell[]) => { + let result = [] as Cell[]; + + for (let i = 0; i < cells.length; i += 1) { + if (filter(cells[i])) { + result.push(cells[i]); + } + } + + return result; +}; + +/** + * Returns all opposite vertices wrt terminal for the given edges, only + * returning sources and/or targets as specified. The result is returned + * as an array of {@link Cell}. + * + * @param {Cell} terminal that specifies the known end of the edges. + * @param sources Boolean that specifies if source terminals should be contained + * in the result. Default is true. + * @param targets Boolean that specifies if target terminals should be contained + * in the result. Default is true. + */ +export const getOpposites = + (terminal: Cell, sources: boolean = true, targets: boolean = true) => + (edges: Cell[]) => { + const terminals = [] as Cell[]; + + for (let i = 0; i < edges.length; i += 1) { + const source = edges[i].getTerminal(true); + const target = edges[i].getTerminal(false); + + // Checks if the terminal is the source of + // the edge and if the target should be + // stored in the result + if (source === terminal && target != null && target !== terminal && targets) { + terminals.push(target); + } + + // Checks if the terminal is the taget of + // the edge and if the source should be + // stored in the result + else if (target === terminal && source != null && source !== terminal && sources) { + terminals.push(source); + } + } + + return terminals; + }; + +/** + * Returns the topmost cells of the hierarchy in an array that contains no + * descendants for each {@link Cell} that it contains. Duplicates should be + * removed in the cells array to improve performance. + */ +export const getTopmostCells = (cells: Cell[]) => { + const dict = new Dictionary(); + const tmp = [] as Cell[]; + + for (let i = 0; i < cells.length; i += 1) { + dict.put(cells[i], true); + } + + for (let i = 0; i < cells.length; i += 1) { + const cell = cells[i]; + let topmost = true; + let parent = cell.getParent(); + + while (parent != null) { + if (dict.get(parent)) { + topmost = false; + break; + } + parent = parent.getParent(); + } + + if (topmost) { + tmp.push(cell); + } + } + + return tmp; +}; + +/** + * Returns an array that represents the set (no duplicates) of all parents + * for the given array of cells. + */ +export const getParents = (cells: Cell[]) => { + const parents = []; + const dict = new Dictionary(); + + for (const cell of cells) { + const parent = cell.getParent(); + if (parent != null && !dict.get(parent)) { + dict.put(parent, true); + parents.push(parent); + } + } + + return parents; +}; + +/** + * Returns an array of clones for the given array of {@link Cell}`. + * Depending on the value of includeChildren, a deep clone is created for + * each cell. Connections are restored based if the corresponding + * cell is contained in the passed in array. + * + * @param includeChildren Boolean indicating if the cells should be cloned + * with all descendants. + * @param mapping Optional mapping for existing clones. + */ +export const cloneCells = + (includeChildren = true, mapping: any = {}) => + (cells: Cell[]) => { + const clones = [] as Cell[]; + + for (const cell of cells) { + clones.push(cloneCellImpl(cell, mapping, includeChildren)); + } + + for (let i = 0; i < clones.length; i += 1) { + if (clones[i] != null) { + restoreClone(clones[i], cells[i], mapping); + } + } + + return clones; + }; + +/** + * Inner helper method for cloning cells recursively. + * + * @private + */ +const cloneCellImpl = ( + cell: Cell, + mapping: any = {}, + includeChildren: boolean = false +): Cell => { + const ident = ObjectIdentity.get(cell); + let clone = mapping ? mapping[ident] : null; + + if (clone == null) { + clone = cell.clone(); + mapping[ident] = clone; + + if (includeChildren) { + const childCount = cell.getChildCount(); + + for (let i = 0; i < childCount; i += 1) { + const cloneChild = cloneCellImpl(cell.getChildAt(i), mapping, true); + clone.insert(cloneChild); + } + } + } + return clone; +}; + +/** + * Inner helper method for restoring the connections in + * a network of cloned cells. + * + * @private + */ +export const restoreClone = + (clone: Cell, cell: Cell, mapping: any) => (cells: Cell[]) => { + const source = cell.getTerminal(true); + + if (source != null) { + const tmp = mapping[ObjectIdentity.get(source)]; + if (tmp != null) { + tmp.insertEdge(clone, true); + } + } + + const target = cell.getTerminal(false); + if (target != null) { + const tmp = mapping[ObjectIdentity.get(target)]; + if (tmp != null) { + tmp.insertEdge(clone, false); + } + } + + const childCount = clone.getChildCount(); + for (let i = 0; i < childCount; i += 1) { + restoreClone(clone.getChildAt(i), cell.getChildAt(i), mapping); + } + }; diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts index 12bd1cdef..628992980 100644 --- a/packages/core/src/view/Graph.ts +++ b/packages/core/src/view/Graph.ts @@ -49,8 +49,6 @@ import Multiplicity from './other/Multiplicity'; import ImageBundle from './image/ImageBundle'; import GraphSelectionModel from './GraphSelectionModel'; -import './cell/CellArray'; - export const defaultPlugins: GraphPluginConstructor[] = [ CellEditorHandler, TooltipHandler, diff --git a/packages/core/src/view/GraphDataModel.ts b/packages/core/src/view/GraphDataModel.ts index 882ef84d8..c3a8052c8 100644 --- a/packages/core/src/view/GraphDataModel.ts +++ b/packages/core/src/view/GraphDataModel.ts @@ -22,6 +22,7 @@ import VisibleChange from './undoable_changes/VisibleChange'; import Geometry from './geometry/Geometry'; import ObjectCodec from '../serialization/ObjectCodec'; import CodecRegistry from '../serialization/CodecRegistry'; +import { cloneCells, filterCells } from '../util/cellArrayUtils'; import type { CellStyle, FilterFunction } from '../types'; @@ -326,7 +327,7 @@ export class GraphDataModel extends EventSource { } filterCells(cells: Cell[], filter: FilterFunction) { - return cells.filterCells(filter); + return filterCells(filter)(cells); } getRoot(cell: Cell | null = null) { @@ -1156,7 +1157,7 @@ export class GraphDataModel extends EventSource { */ cloneCell(cell: Cell | null = null, includeChildren: boolean = true): Cell | null { if (cell != null) { - return [cell].cloneCells(includeChildren)[0]; + return cloneCells(includeChildren)([cell])[0]; } return null; } diff --git a/packages/core/src/view/cell/CellArray.ts b/packages/core/src/view/cell/CellArray.ts deleted file mode 100644 index 5956c110a..000000000 --- a/packages/core/src/view/cell/CellArray.ts +++ /dev/null @@ -1,209 +0,0 @@ -import Cell from './Cell'; -import Dictionary from '../../util/Dictionary'; -import ObjectIdentity from '../../util/ObjectIdentity'; - -declare global { - interface Array { - filterCells: (filter: Function) => T[]; - getOpposites: (terminal: Cell, sources: boolean, targets: boolean) => T[]; - getTopmostCells: () => T[]; - getParents: () => T[]; - cloneCells: (includeChildren?: boolean, mapping?: any) => T[]; - cloneCellImpl: (cell: Cell, mapping?: any, includeChildren?: boolean) => T; - restoreClone: (clone: Cell, cell: Cell, mapping: any) => void; - } -} - -/** - * Returns the cells from the given array where the given filter function - * returns true. - */ -Array.prototype.filterCells = function (filter: Function) { - let result = [] as Cell[]; - - for (let i = 0; i < this.length; i += 1) { - if (filter(this[i])) { - result.push(this[i]); - } - } - - return result; -}; - -/** - * Returns all opposite vertices wrt terminal for the given edges, only - * returning sources and/or targets as specified. The result is returned - * as an array of {@link Cell}. - * - * @param {Cell} terminal that specifies the known end of the edges. - * @param sources Boolean that specifies if source terminals should be contained - * in the result. Default is true. - * @param targets Boolean that specifies if target terminals should be contained - * in the result. Default is true. - */ -Array.prototype.getOpposites = function ( - terminal: Cell, - sources: boolean = true, - targets: boolean = true -) { - const terminals = [] as Cell[]; - - for (let i = 0; i < this.length; i += 1) { - const source = this[i].getTerminal(true); - const target = this[i].getTerminal(false); - - // Checks if the terminal is the source of - // the edge and if the target should be - // stored in the result - if (source === terminal && target != null && target !== terminal && targets) { - terminals.push(target); - } - - // Checks if the terminal is the taget of - // the edge and if the source should be - // stored in the result - else if (target === terminal && source != null && source !== terminal && sources) { - terminals.push(source); - } - } - - return terminals; -}; - -/** - * Returns the topmost cells of the hierarchy in an array that contains no - * descendants for each {@link Cell} that it contains. Duplicates should be - * removed in the cells array to improve performance. - */ -Array.prototype.getTopmostCells = function () { - const dict = new Dictionary(); - const tmp = [] as Cell[]; - - for (let i = 0; i < this.length; i += 1) { - dict.put(this[i], true); - } - - for (let i = 0; i < this.length; i += 1) { - const cell = this[i]; - let topmost = true; - let parent = cell.getParent(); - - while (parent != null) { - if (dict.get(parent)) { - topmost = false; - break; - } - parent = parent.getParent(); - } - - if (topmost) { - tmp.push(cell); - } - } - - return tmp; -}; - -/** - * Returns an array that represents the set (no duplicates) of all parents - * for the given array of cells. - */ -Array.prototype.getParents = function () { - const parents = []; - const dict = new Dictionary(); - - for (const cell of this) { - const parent = cell.getParent(); - if (parent != null && !dict.get(parent)) { - dict.put(parent, true); - parents.push(parent); - } - } - - return parents; -}; - -/** - * Returns an array of clones for the given array of {@link Cell}`. - * Depending on the value of includeChildren, a deep clone is created for - * each cell. Connections are restored based if the corresponding - * cell is contained in the passed in array. - * - * @param includeChildren Boolean indicating if the cells should be cloned - * with all descendants. - * @param mapping Optional mapping for existing clones. - */ -Array.prototype.cloneCells = function (includeChildren = true, mapping: any = {}) { - const clones = [] as Cell[]; - - for (const cell of this) { - clones.push(this.cloneCellImpl(cell, mapping, includeChildren)); - } - - for (let i = 0; i < clones.length; i += 1) { - if (clones[i] != null) { - this.restoreClone(clones[i], this[i], mapping); - } - } - - return clones; -}; - -/** - * Inner helper method for cloning cells recursively. - * - * @private - */ -Array.prototype.cloneCellImpl = function ( - cell: Cell, - mapping: any = {}, - includeChildren: boolean = false -): Cell { - const ident = ObjectIdentity.get(cell); - let clone = mapping ? mapping[ident] : null; - - if (clone == null) { - clone = cell.clone(); - mapping[ident] = clone; - - if (includeChildren) { - const childCount = cell.getChildCount(); - - for (let i = 0; i < childCount; i += 1) { - const cloneChild = this.cloneCellImpl(cell.getChildAt(i), mapping, true); - clone.insert(cloneChild); - } - } - } - return clone; -}; - -/** - * Inner helper method for restoring the connections in - * a network of cloned cells. - * - * @private - */ -Array.prototype.restoreClone = function (clone: Cell, cell: Cell, mapping: any) { - const source = cell.getTerminal(true); - - if (source != null) { - const tmp = mapping[ObjectIdentity.get(source)]; - if (tmp != null) { - tmp.insertEdge(clone, true); - } - } - - const target = cell.getTerminal(false); - if (target != null) { - const tmp = mapping[ObjectIdentity.get(target)]; - if (tmp != null) { - tmp.insertEdge(clone, false); - } - } - - const childCount = clone.getChildCount(); - for (let i = 0; i < childCount; i += 1) { - this.restoreClone(clone.getChildAt(i), cell.getChildAt(i), mapping); - } -}; diff --git a/packages/core/src/view/layout/datatypes/GraphHierarchyNode.ts b/packages/core/src/view/layout/datatypes/GraphHierarchyNode.ts index eb6d3c84a..3dcc85a42 100644 --- a/packages/core/src/view/layout/datatypes/GraphHierarchyNode.ts +++ b/packages/core/src/view/layout/datatypes/GraphHierarchyNode.ts @@ -97,14 +97,16 @@ class GraphHierarchyNode extends GraphAbstractHierarchyCell { getPreviousLayerConnectedCells(layer: number): GraphAbstractHierarchyCell[] { if (this.previousLayerConnectedCells == null) { this.previousLayerConnectedCells = []; - this.previousLayerConnectedCells[0] = []; // new CellArray()?? + this.previousLayerConnectedCells[0] = []; for (let i = 0; i < this.connectsAsSource.length; i += 1) { const edge = this.connectsAsSource[i]; if (edge.minRank === -1 || edge.minRank === layer - 1) { // No dummy nodes in edge, add node of other side of edge - this.previousLayerConnectedCells[0].push(edge.target); + this.previousLayerConnectedCells[0].push( + edge.target + ); } else { // Edge spans at least two layers, add edge this.previousLayerConnectedCells[0].push(edge); diff --git a/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts b/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts index 6a9d493e6..2a334ec93 100644 --- a/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts +++ b/packages/core/src/view/layout/hierarchical/GraphHierarchyModel.ts @@ -380,7 +380,7 @@ class GraphHierarchyModel { * to create dummy nodes for edges that cross layers. */ fixRanks(): void { - // TODO: Should this be a CellArray? + // TODO: Should this be a Cell[]? const rankList: { [key: number]: GraphAbstractHierarchyCell[] } = {}; this.ranks = []; diff --git a/packages/core/src/view/mixins/CellsMixin.ts b/packages/core/src/view/mixins/CellsMixin.ts index c220ee883..b13e21dc6 100644 --- a/packages/core/src/view/mixins/CellsMixin.ts +++ b/packages/core/src/view/mixins/CellsMixin.ts @@ -30,6 +30,7 @@ import Point from '../geometry/Point'; import { htmlEntities } from '../../util/StringUtils'; import CellState from '../cell/CellState'; import { Graph } from '../Graph'; +import { cloneCells, getTopmostCells } from '../../util/cellArrayUtils'; import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../../types'; @@ -90,8 +91,8 @@ declare module '../Graph' { ) => Cell; cloneCells: ( cells: Cell[], - allowInvalidEdges: boolean, - mapping: any, + allowInvalidEdges?: boolean, + mapping?: any, keepPosition?: boolean ) => Cell[]; addCell: ( @@ -144,9 +145,9 @@ declare module '../Graph' { cells: Cell[], dx: number, dy: number, - target: Cell | null, - evt: MouseEvent | null, - mapping: any + target?: Cell | null, + evt?: MouseEvent | null, + mapping?: any ) => Cell[]; moveCells: ( cells: Cell[], @@ -836,7 +837,6 @@ export const CellsMixin: PartialType = { * @param keepPosition Optional boolean indicating if the position of the cells should * be updated to reflect the lost parent cell. Default is `false`. */ - // cloneCell(cell: mxCell, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; cloneCell(cell, allowInvalidEdges = false, mapping = null, keepPosition = false) { return this.cloneCells([cell], allowInvalidEdges, mapping, keepPosition)[0]; }, @@ -854,7 +854,6 @@ export const CellsMixin: PartialType = { * @param keepPosition Optional boolean indicating if the position of the cells should * be updated to reflect the lost parent cell. Default is `false`. */ - // cloneCells(cells: mxCellArray, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; cloneCells(cells, allowInvalidEdges = true, mapping = {}, keepPosition = false) { let clones: Cell[]; @@ -871,7 +870,7 @@ export const CellsMixin: PartialType = { const { scale } = this.getView(); const trans = this.getView().translate; const out: Cell[] = []; - clones = cells.cloneCells(true, mapping); + clones = cloneCells(true, mapping)(cells); for (let i = 0; i < cells.length; i += 1) { const cell = cells[i]; @@ -1852,7 +1851,7 @@ export const CellsMixin: PartialType = { ) { if (dx !== 0 || dy !== 0 || clone || target) { // Removes descendants with ancestors in cells to avoid multiple moving - cells = cells.getTopmostCells(); + cells = getTopmostCells(cells); const origCells = cells; this.batchUpdate(() => { diff --git a/packages/html/stories/Clipboard.stories.js b/packages/html/stories/Clipboard.stories.js index 58a648a02..7c069808f 100644 --- a/packages/html/stories/Clipboard.stories.js +++ b/packages/html/stories/Clipboard.stories.js @@ -10,6 +10,7 @@ import { GraphDataModel, styleUtils, stringUtils, + cellArrayUtils, } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -154,7 +155,7 @@ const Template = ({ label, ...args }) => { if (graph.isEnabled() && !graph.isSelectionEmpty()) { copyCells( graph, - utils.sortCells(graph.model.getTopmostCells(graph.getSelectionCells())) + styleUtils.sortCells(cellArrayUtils.getTopmostCells(graph.getSelectionCells())) ); dx = 0; dy = 0; @@ -177,7 +178,7 @@ const Template = ({ label, ...args }) => { let cells = []; try { - const doc = utils.parseXml(xml); + const doc = xmlUtils.parseXml(xml); const node = doc.documentElement; if (node != null) { diff --git a/packages/html/stories/Groups.stories.js b/packages/html/stories/Groups.stories.js index e77b488da..16525a935 100644 --- a/packages/html/stories/Groups.stories.js +++ b/packages/html/stories/Groups.stories.js @@ -1,4 +1,9 @@ -import { Graph, RubberBandHandler, SelectionHandler, PopupMenuHandler } from '@maxgraph/core'; +import { + Graph, + RubberBandHandler, + SelectionHandler, + PopupMenuHandler, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -41,8 +46,9 @@ const Template = ({ label, ...args }) => { const graphHandlerGetInitialCellForEvent = SelectionHandler.prototype.getInitialCellForEvent; SelectionHandler.prototype.getInitialCellForEvent = function (me) { - const model = this.graph.getDataModel(); - const psel = this.graph.getSelectionCell().getParent(); + const psel = this.graph.getSelectionCell() + ? this.graph.getSelectionCell().getParent() + : null; let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments); let parent = cell.getParent(); @@ -65,8 +71,9 @@ const Template = ({ label, ...args }) => { const graphHandlerIsDelayedSelection = SelectionHandler.prototype.isDelayedSelection; SelectionHandler.prototype.isDelayedSelection = function (cell) { let result = graphHandlerIsDelayedSelection.apply(this, arguments); - const model = this.graph.getDataModel(); - const psel = this.graph.getSelectionCell().getParent(); + const psel = this.graph.getSelectionCell() + ? this.graph.getSelectionCell().getParent() + : null; const parent = cell.getParent(); if (psel == null || (psel != cell && psel != parent)) {