Merge pull request #101 from maxGraph/cellarray

Fixes CellArray related warnings. #96
development
Junsik Shim 2022-09-19 13:24:04 +09:00 committed by GitHub
commit 02ea6f1ceb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 833 additions and 890 deletions

View File

@ -25,7 +25,6 @@ import { getClientX, getClientY } from '../util/EventUtils';
import { makeDraggable } from '../util/gestureUtils'; import { makeDraggable } from '../util/gestureUtils';
import Editor from './Editor'; import Editor from './Editor';
import Cell from '../view/cell/Cell'; import Cell from '../view/cell/Cell';
import CellArray from '../view/cell/CellArray';
import { Graph } from '../view/Graph'; import { Graph } from '../view/Graph';
import EventObject from '../view/event/EventObject'; import EventObject from '../view/event/EventObject';
import ObjectCodec from '../serialization/ObjectCodec'; import ObjectCodec from '../serialization/ObjectCodec';
@ -108,7 +107,9 @@ export class EditorToolbar {
// Installs the insert function in the editor if an item is // Installs the insert function in the editor if an item is
// selected in the toolbar // selected in the toolbar
this.toolbar.addListener(InternalEvent.SELECT, (sender: Element, evt: EventObject) => { this.toolbar.addListener(
InternalEvent.SELECT,
(sender: Element, evt: EventObject) => {
const funct = evt.getProperty('function'); const funct = evt.getProperty('function');
if (funct != null) { if (funct != null) {
@ -119,7 +120,8 @@ export class EditorToolbar {
} else { } else {
(<Editor>this.editor).insertFunction = null; (<Editor>this.editor).insertFunction = null;
} }
}); }
);
// Resets the selected tool after a doubleclick or escape keystroke // Resets the selected tool after a doubleclick or escape keystroke
this.resetHandler = () => { this.resetHandler = () => {
@ -128,7 +130,10 @@ export class EditorToolbar {
} }
}; };
(<Editor>this.editor).graph.addListener(InternalEvent.DOUBLE_CLICK, this.resetHandler); (<Editor>this.editor).graph.addListener(
InternalEvent.DOUBLE_CLICK,
this.resetHandler
);
(<Editor>this.editor).addListener(InternalEvent.ESCAPE, this.resetHandler); (<Editor>this.editor).addListener(InternalEvent.ESCAPE, this.resetHandler);
} }
} }
@ -200,7 +205,11 @@ export class EditorToolbar {
* @param title - String that represents the title of the combo. * @param title - String that represents the title of the combo.
* @param value - Object that represents the value of the option. * @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 (<MaxToolbar>this.toolbar).addOption(combo, title, value); return (<MaxToolbar>this.toolbar).addOption(combo, title, value);
} }
@ -225,7 +234,7 @@ export class EditorToolbar {
(<Editor>this.editor).setMode(mode); (<Editor>this.editor).setMode(mode);
if (funct != null) { if (funct != null) {
funct((<Editor>this.editor)); funct(<Editor>this.editor);
} }
}; };
return (<MaxToolbar>this.toolbar).addSwitchMode(title, icon, clickHandler, pressed); return (<MaxToolbar>this.toolbar).addSwitchMode(title, icon, clickHandler, pressed);
@ -253,7 +262,12 @@ export class EditorToolbar {
icon: string, icon: string,
ptype: Function | Cell, ptype: Function | Cell,
pressed: string, pressed: string,
insert: (editor: Editor, cell: Cell, me: MouseEvent, cellUnderMousePointer?: Cell | null) => void, insert: (
editor: Editor,
cell: Cell,
me: MouseEvent,
cellUnderMousePointer?: Cell | null
) => void,
toggle: boolean = true toggle: boolean = true
): HTMLImageElement | HTMLButtonElement { ): HTMLImageElement | HTMLButtonElement {
// Creates a wrapper function that is in charge of constructing // Creates a wrapper function that is in charge of constructing
@ -272,7 +286,7 @@ export class EditorToolbar {
// after this item has been selected in the toolbar // after this item has been selected in the toolbar
const clickHandler = (evt: MouseEvent, cell: Cell | null) => { const clickHandler = (evt: MouseEvent, cell: Cell | null) => {
if (typeof insert === 'function') { if (typeof insert === 'function') {
insert((<Editor>this.editor), factory(), evt, cell); insert(<Editor>this.editor, factory(), evt, cell);
} else { } else {
this.drop(factory(), evt, cell); this.drop(factory(), evt, cell);
} }
@ -281,11 +295,22 @@ export class EditorToolbar {
InternalEvent.consume(evt); InternalEvent.consume(evt);
}; };
const img = (<MaxToolbar>this.toolbar).addMode(title, icon, clickHandler, pressed, null, toggle); const img = (<MaxToolbar>this.toolbar).addMode(
title,
icon,
clickHandler,
pressed,
null,
toggle
);
// Creates a wrapper function that calls the click handler without // Creates a wrapper function that calls the click handler without
// the graph argument // 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); clickHandler(evt, cell);
}; };
@ -303,7 +328,7 @@ export class EditorToolbar {
* @param target - Optional {@link Cell} that represents the drop target. * @param target - Optional {@link Cell} that represents the drop target.
*/ */
drop(vertex: Cell, evt: MouseEvent, target: Cell | null = null): void { drop(vertex: Cell, evt: MouseEvent, target: Cell | null = null): void {
const { graph } = (<Editor>this.editor); const { graph } = <Editor>this.editor;
const model = graph.getDataModel(); const model = graph.getDataModel();
if ( if (
@ -312,7 +337,7 @@ export class EditorToolbar {
!this.connectOnDrop || !this.connectOnDrop ||
!target.isConnectable() !target.isConnectable()
) { ) {
while (target != null && !graph.isValidDropTarget(target, new CellArray(vertex), evt)) { while (target != null && !graph.isValidDropTarget(target, [vertex], evt)) {
target = target.getParent(); target = target.getParent();
} }
this.insert(vertex, evt, target); this.insert(vertex, evt, target);
@ -330,7 +355,7 @@ export class EditorToolbar {
* @param target - Optional {@link Cell} that represents the parent. * @param target - Optional {@link Cell} that represents the parent.
*/ */
insert(vertex: Cell, evt: MouseEvent, target: Cell | null = null): any { insert(vertex: Cell, evt: MouseEvent, target: Cell | null = null): any {
const { graph } = (<Editor>this.editor); const { graph } = <Editor>this.editor;
if (graph.canImportCell(vertex)) { if (graph.canImportCell(vertex)) {
const x = getClientX(evt); const x = getClientX(evt);
@ -338,8 +363,12 @@ export class EditorToolbar {
const pt = convertPoint(graph.container, x, y); const pt = convertPoint(graph.container, x, y);
// Splits the target edge or inserts into target group // Splits the target edge or inserts into target group
if (target && graph.isSplitEnabled() && graph.isSplitTarget(target, new CellArray(vertex), evt)) { if (
return graph.splitEdge(target, new CellArray(vertex), null, pt.x, pt.y); target &&
graph.isSplitEnabled() &&
graph.isSplitTarget(target, [vertex], evt)
) {
return graph.splitEdge(target, [vertex], null, pt.x, pt.y);
} }
return (<Editor>this.editor).addVertex(target, vertex, pt.x, pt.y); return (<Editor>this.editor).addVertex(target, vertex, pt.x, pt.y);
} }
@ -407,7 +436,7 @@ export class EditorToolbar {
model.endUpdate(); model.endUpdate();
} }
graph.setSelectionCells(new CellArray(vertex, edge)); graph.setSelectionCells([vertex, edge]);
graph.scrollCellToVisible(vertex); graph.scrollCellToVisible(vertex);
} }
} }
@ -586,21 +615,16 @@ export class EditorToolbarCodec extends ObjectCodec {
const mode = node.getAttribute('mode'); const mode = node.getAttribute('mode');
const template = node.getAttribute('template'); const template = node.getAttribute('template');
const toggle = node.getAttribute('toggle') != '0'; const toggle = node.getAttribute('toggle') != '0';
const text = getTextContent(<Text><unknown>node); const text = getTextContent(<Text>(<unknown>node));
let elt = null; let elt = null;
let funct: any; let funct: any;
if (action != null) { if (action != null) {
elt = into.addItem(as, icon, action, pressedIcon); elt = into.addItem(as, icon, action, pressedIcon);
} else if (mode != null) { } else if (mode != null) {
funct = EditorToolbarCodec.allowEval funct = EditorToolbarCodec.allowEval ? eval(text) : null;
? eval(text)
: null;
elt = into.addMode(as, icon, mode, pressedIcon, funct); elt = into.addMode(as, icon, mode, pressedIcon, funct);
} else if ( } else if (template != null || (text != null && text.length > 0)) {
template != null ||
(text != null && text.length > 0)
) {
let cell = template ? editor.templates[template] : null; let cell = template ? editor.templates[template] : null;
const style = node.getAttribute('style'); const style = node.getAttribute('style');
@ -611,11 +635,7 @@ export class EditorToolbarCodec extends ObjectCodec {
let insertFunction = null; let insertFunction = null;
if ( if (text != null && text.length > 0 && EditorToolbarCodec.allowEval) {
text != null &&
text.length > 0 &&
EditorToolbarCodec.allowEval
) {
insertFunction = eval(text); insertFunction = eval(text);
} }
@ -667,14 +687,7 @@ export class EditorToolbarCodec extends ObjectCodec {
return null; return null;
}; };
const img = into.addPrototype( const img = into.addPrototype(as, icon, create, null, null, toggle);
as,
icon,
create,
null,
null,
toggle
);
select = into.addCombo(); select = into.addCombo();
// Selects the toolbar icon if a selection change // Selects the toolbar icon if a selection change
@ -702,11 +715,7 @@ export class EditorToolbarCodec extends ObjectCodec {
} else if (child.nodeName === 'add') { } else if (child.nodeName === 'add') {
const lab = child.getAttribute('as'); const lab = child.getAttribute('as');
const tmp = child.getAttribute('template'); const tmp = child.getAttribute('template');
const option = into.addOption( const option = into.addOption(select, lab, tmp || template);
select,
lab,
tmp || template
);
option.cellStyle = child.getAttribute('style'); option.cellStyle = child.getAttribute('style');
} }
} }

View File

@ -58,7 +58,10 @@ export { default as GeometryChange } from './view/undoable_changes/GeometryChang
export { RootChange, RootChangeCodec } from './view/undoable_changes/RootChange'; export { RootChange, RootChangeCodec } from './view/undoable_changes/RootChange';
export { default as SelectionChange } from './view/undoable_changes/SelectionChange'; export { default as SelectionChange } from './view/undoable_changes/SelectionChange';
export { default as StyleChange } from './view/undoable_changes/StyleChange'; 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 ValueChange } from './view/undoable_changes/ValueChange';
export { default as VisibleChange } from './view/undoable_changes/VisibleChange'; export { default as VisibleChange } from './view/undoable_changes/VisibleChange';
@ -158,6 +161,7 @@ export * as stringUtils from './util/StringUtils';
export * as xmlUtils from './util/xmlUtils'; export * as xmlUtils from './util/xmlUtils';
export * as styleUtils from './util/styleUtils'; export * as styleUtils from './util/styleUtils';
export * as mathUtils from './util/mathUtils'; export * as mathUtils from './util/mathUtils';
export * as cellArrayUtils from './util/cellArrayUtils';
export { default as Animation } from './view/animate/Animation'; export { default as Animation } from './view/animate/Animation';
export { default as Effects } from './view/animate/Effects'; export { default as Effects } from './view/animate/Effects';
@ -220,7 +224,6 @@ export { default as CellPath } from './view/cell/CellPath';
export { default as CellRenderer } from './view/cell/CellRenderer'; export { default as CellRenderer } from './view/cell/CellRenderer';
export { default as CellState } from './view/cell/CellState'; export { default as CellState } from './view/cell/CellState';
export { default as CellStatePreview } from './view/cell/CellStatePreview'; 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 TemporaryCellStates } from './view/cell/TemporaryCellStates';
export { default as ConnectionConstraint } from './view/other/ConnectionConstraint'; export { default as ConnectionConstraint } from './view/other/ConnectionConstraint';
export { default as Multiplicity } from './view/other/Multiplicity'; export { default as Multiplicity } from './view/other/Multiplicity';

View File

@ -16,8 +16,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import Cell from '../view/cell/Cell';
import { Graph } from '../view/Graph'; import { Graph } from '../view/Graph';
import CellArray from '../view/cell/CellArray'; import { getTopmostCells } from './cellArrayUtils';
/** /**
* @class * @class
@ -104,12 +105,12 @@ class Clipboard {
/** /**
* Holds the array of {@link mxCell} currently in the 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. * Sets the cells in the clipboard. Fires a {@link mxEvent.CHANGE} event.
*/ */
static setCells(cells: CellArray) { static setCells(cells: Cell[]) {
Clipboard.cells = cells; Clipboard.cells = cells;
} }
@ -135,7 +136,7 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be cut. * @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Optional array of {@link mxCell} to be cut. * @param cells - Optional array of {@link mxCell} to be cut.
*/ */
static cut(graph: Graph, cells?: CellArray) { static cut(graph: Graph, cells: Cell[] = []) {
cells = Clipboard.copy(graph, cells); cells = Clipboard.copy(graph, cells);
Clipboard.insertCount = 0; Clipboard.insertCount = 0;
Clipboard.removeCells(graph, cells); Clipboard.removeCells(graph, cells);
@ -150,8 +151,7 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be cut. * @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Array of {@link mxCell} to be cut. * @param cells - Array of {@link mxCell} to be cut.
*/ */
static removeCells(graph: Graph, cells: CellArray) { static removeCells(graph: Graph, cells: Cell[]) {
// @ts-ignore
graph.removeCells(cells); graph.removeCells(cells);
} }
@ -163,11 +163,11 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be copied. * @param graph - {@link graph} that contains the cells to be copied.
* @param cells - Optional array of {@link mxCell} to be copied. * @param cells - Optional array of {@link mxCell} to be copied.
*/ */
static copy(graph: Graph, cells?: CellArray) { static copy(graph: Graph, cells?: Cell[]) {
cells = cells || graph.getSelectionCells(); cells = cells || graph.getSelectionCells();
const result = graph.getExportableCells(cells).getTopmostCells(); const result = getTopmostCells(graph.getExportableCells(cells));
Clipboard.insertCount = 1; Clipboard.insertCount = 1;
// @ts-ignore
Clipboard.setCells(graph.cloneCells(result)); Clipboard.setCells(graph.cloneCells(result));
return result; return result;
} }
@ -190,12 +190,12 @@ class Clipboard {
cells = graph.getImportableCells(Clipboard.getCells()); cells = graph.getImportableCells(Clipboard.getCells());
const delta = Clipboard.insertCount * Clipboard.STEPSIZE; const delta = Clipboard.insertCount * Clipboard.STEPSIZE;
const parent = graph.getDefaultParent(); const parent = graph.getDefaultParent();
// @ts-ignore
cells = graph.importCells(cells, delta, delta, parent); cells = graph.importCells(cells, delta, delta, parent);
// Increments the counter and selects the inserted cells // Increments the counter and selects the inserted cells
Clipboard.insertCount++; Clipboard.insertCount++;
graph.setSelectionCells(<CellArray>cells); graph.setSelectionCells(cells);
} }
return cells; return cells;

View File

@ -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(<Cell>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 = <string>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>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[<string>ObjectIdentity.get(source)];
if (tmp != null) {
tmp.insertEdge(clone, true);
}
}
const target = cell.getTerminal(false);
if (target != null) {
const tmp = mapping[<string>ObjectIdentity.get(target)];
if (tmp != null) {
tmp.insertEdge(clone, false);
}
}
const childCount = clone.getChildCount();
for (let i = 0; i < childCount; i += 1) {
restoreClone(<Cell>clone.getChildAt(i), <Cell>cell.getChildAt(i), mapping);
}
};

View File

@ -30,7 +30,7 @@ import CellPath from '../view/cell/CellPath';
import Rectangle from '../view/geometry/Rectangle'; import Rectangle from '../view/geometry/Rectangle';
import Cell from '../view/cell/Cell'; import Cell from '../view/cell/Cell';
import GraphDataModel from '../view/GraphDataModel'; import GraphDataModel from '../view/GraphDataModel';
import CellArray from '../view/cell/CellArray';
import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../types'; import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../types';
/** /**
@ -438,7 +438,7 @@ export const removeAllStylenames = (style: string) => {
*/ */
export const setCellStyles = ( export const setCellStyles = (
model: GraphDataModel, model: GraphDataModel,
cells: CellArray, cells: Cell[],
key: keyof CellStateStyle, key: keyof CellStateStyle,
value: any value: any
) => { ) => {
@ -534,7 +534,7 @@ export const setStyle = (style: string | null, key: string, value: any) => {
*/ */
export const setCellStyleFlags = ( export const setCellStyleFlags = (
model: GraphDataModel, model: GraphDataModel,
cells: CellArray, cells: Cell[],
key: NumericCellStateStyleKeys, key: NumericCellStateStyleKeys,
flag: number, flag: number,
value: boolean value: boolean
@ -685,7 +685,7 @@ export const getSizeForString = (
* Sorts the given cells according to the order in the cell hierarchy. * Sorts the given cells according to the order in the cell hierarchy.
* Ascending is optional and defaults to true. * 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<Cell, string[]>(); const lookup = new Dictionary<Cell, string[]>();
cells.sort((o1, o2) => { cells.sort((o1, o2) => {

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import Cell from '../view/cell/Cell'; import Cell from '../view/cell/Cell';
import CellArray from '../view/cell/CellArray';
import Dictionary from './Dictionary'; import Dictionary from './Dictionary';
import { Graph } from '../view/Graph'; import { Graph } from '../view/Graph';
@ -42,7 +41,7 @@ export function findTreeRoots(
isolate: boolean = false, isolate: boolean = false,
invert: boolean = false invert: boolean = false
) { ) {
const roots: CellArray = new CellArray(); const roots: Cell[] = [];
if (parent != null) { if (parent != null) {
let best = null; let best = null;

View File

@ -1,4 +1,3 @@
/* /*
Copyright 2021-present The maxGraph project Contributors Copyright 2021-present The maxGraph project Contributors
Copyright (c) 2006-2015, JGraph Ltd Copyright (c) 2006-2015, JGraph Ltd
@ -20,7 +19,6 @@ limitations under the License.
import { DIALECT, NODETYPE, NS_SVG } from './Constants'; import { DIALECT, NODETYPE, NS_SVG } from './Constants';
import Point from '../view/geometry/Point'; import Point from '../view/geometry/Point';
import Cell from '../view/cell/Cell'; import Cell from '../view/cell/Cell';
import CellArray from '../view/cell/CellArray';
import { Graph } from '../view/Graph'; import { Graph } from '../view/Graph';
import { htmlEntities, trim } from './StringUtils'; import { htmlEntities, trim } from './StringUtils';
import TemporaryCellStates from '../view/cell/TemporaryCellStates'; import TemporaryCellStates from '../view/cell/TemporaryCellStates';
@ -38,19 +36,18 @@ export const createXmlDocument = () => {
export const parseXml = (xmlString: string): HTMLElement => { export const parseXml = (xmlString: string): HTMLElement => {
return new DOMParser().parseFromString(xmlString, 'text/xml').documentElement; return new DOMParser().parseFromString(xmlString, 'text/xml').documentElement;
} };
export const getViewXml = ( export const getViewXml = (
graph: Graph, graph: Graph,
scale: number = 1, scale: number = 1,
cells: CellArray | null=null, cells: Cell[] | null = null,
x0: number = 0, x0: number = 0,
y0: number = 0 y0: number = 0
) => { ) => {
if (cells == null) { if (cells == null) {
const model = graph.getDataModel(); const model = graph.getDataModel();
cells = new CellArray(<Cell>model.getRoot()); cells = [<Cell>model.getRoot()];
} }
const view = graph.getView(); const view = graph.getView();
@ -136,7 +133,13 @@ export const getXml = (node: Element, linefeed: string='&#xa;'): string => {
* Default is an empty string. * Default is an empty string.
* @param newline Option string that represents a linefeed. Default is '\n'. * @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 = []; const result = [];
if (node != null) { if (node != null) {
@ -154,7 +157,13 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline
if (node.nodeType === NODETYPE.DOCUMENT) { if (node.nodeType === NODETYPE.DOCUMENT) {
result.push( result.push(
getPrettyXml((<Document><unknown>node).documentElement, tab, indent, newline, ns) getPrettyXml(
(<Document>(<unknown>node)).documentElement,
tab,
indent,
newline,
ns
)
); );
} else if (node.nodeType === NODETYPE.DOCUMENT_FRAGMENT) { } else if (node.nodeType === NODETYPE.DOCUMENT_FRAGMENT) {
let tmp = node.firstChild; let tmp = node.firstChild;
@ -166,19 +175,19 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline
} }
} }
} else if (node.nodeType === NODETYPE.COMMENT) { } else if (node.nodeType === NODETYPE.COMMENT) {
const value = getTextContent(<Text><unknown>node); const value = getTextContent(<Text>(<unknown>node));
if (value.length > 0) { if (value.length > 0) {
result.push(`${indent}<!--${value}-->${newline}`); result.push(`${indent}<!--${value}-->${newline}`);
} }
} else if (node.nodeType === NODETYPE.TEXT) { } else if (node.nodeType === NODETYPE.TEXT) {
const value = trim(getTextContent(<Text><unknown>node)); const value = trim(getTextContent(<Text>(<unknown>node)));
if (value && value.length > 0) { if (value && value.length > 0) {
result.push(indent + htmlEntities(value, false) + newline); result.push(indent + htmlEntities(value, false) + newline);
} }
} else if (node.nodeType === NODETYPE.CDATA) { } else if (node.nodeType === NODETYPE.CDATA) {
const value = getTextContent(<Text><unknown>node); const value = getTextContent(<Text>(<unknown>node));
if (value.length > 0) { if (value.length > 0) {
result.push(`${indent}<![CDATA[${value}]]${newline}`); result.push(`${indent}<![CDATA[${value}]]${newline}`);
@ -205,9 +214,7 @@ export const getPrettyXml = (node: Element, tab: string, indent: string, newline
result.push(`>${newline}`); result.push(`>${newline}`);
while (tmp != null) { while (tmp != null) {
result.push( result.push(getPrettyXml(<Element>tmp, tab, indent + tab, newline, ns));
getPrettyXml(<Element>tmp, tab, indent + tab, newline, ns)
);
tmp = tmp.nextSibling; tmp = tmp.nextSibling;
} }

View File

@ -57,7 +57,6 @@ import ObjectCodec from '../serialization/ObjectCodec';
import type { GraphPlugin, GraphPluginConstructor, MouseListenerSet } from '../types'; import type { GraphPlugin, GraphPluginConstructor, MouseListenerSet } from '../types';
import Multiplicity from './other/Multiplicity'; import Multiplicity from './other/Multiplicity';
import CellArray from './cell/CellArray';
import ImageBundle from './image/ImageBundle'; import ImageBundle from './image/ImageBundle';
import GraphSelectionModel from './GraphSelectionModel'; import GraphSelectionModel from './GraphSelectionModel';
@ -102,7 +101,7 @@ class Graph extends EventSource {
* Group: Variables (that maybe should be in the mixins, but need to be created for each new class instance) * 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[] = []; imageBundles: ImageBundle[] = [];

View File

@ -32,9 +32,9 @@ import TerminalChange from './undoable_changes/TerminalChange';
import ValueChange from './undoable_changes/ValueChange'; import ValueChange from './undoable_changes/ValueChange';
import VisibleChange from './undoable_changes/VisibleChange'; import VisibleChange from './undoable_changes/VisibleChange';
import Geometry from './geometry/Geometry'; import Geometry from './geometry/Geometry';
import CellArray from './cell/CellArray';
import ObjectCodec from '../serialization/ObjectCodec'; import ObjectCodec from '../serialization/ObjectCodec';
import CodecRegistry from '../serialization/CodecRegistry'; import CodecRegistry from '../serialization/CodecRegistry';
import { cloneCells, filterCells } from '../util/cellArrayUtils';
import type { CellStyle, FilterFunction } from '../types'; import type { CellStyle, FilterFunction } from '../types';
@ -338,8 +338,8 @@ export class GraphDataModel extends EventSource {
return this.cells ? this.cells[id] : null; return this.cells ? this.cells[id] : null;
} }
filterCells(cells: CellArray, filter: FilterFunction) { filterCells(cells: Cell[], filter: FilterFunction) {
return new CellArray(...cells).filterCells(filter); return filterCells(filter)(cells);
} }
getRoot(cell: Cell | null = null) { getRoot(cell: Cell | null = null) {
@ -759,7 +759,7 @@ export class GraphDataModel extends EventSource {
* @param directed Optional boolean that specifies if the direction of the * @param directed Optional boolean that specifies if the direction of the
* edge should be taken into account. Default is false. * 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 tmp1 = source.getEdgeCount();
const tmp2 = target.getEdgeCount(); const tmp2 = target.getEdgeCount();
@ -774,7 +774,7 @@ export class GraphDataModel extends EventSource {
terminal = target; terminal = target;
} }
const result = new CellArray(); const result = [];
// Checks if the edge is connected to the correct // Checks if the edge is connected to the correct
// cell and returns the first match // cell and returns the first match
@ -1169,7 +1169,7 @@ export class GraphDataModel extends EventSource {
*/ */
cloneCell(cell: Cell | null = null, includeChildren: boolean = true): Cell | null { cloneCell(cell: Cell | null = null, includeChildren: boolean = true): Cell | null {
if (cell != null) { if (cell != null) {
return new CellArray(cell).cloneCells(includeChildren)[0]; return cloneCells(includeChildren)([cell])[0];
} }
return null; return null;
} }

View File

@ -16,15 +16,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import Client from "../Client"; import Client from '../Client';
import CellArray from "./cell/CellArray"
import EventSource from '../view/event/EventSource'; import EventSource from '../view/event/EventSource';
import { Graph } from "./Graph" import { Graph } from './Graph';
import Cell from "./cell/Cell"; import Cell from './cell/Cell';
import SelectionChange from "./undoable_changes/SelectionChange"; import SelectionChange from './undoable_changes/SelectionChange';
import UndoableEdit from "./undoable_changes/UndoableEdit"; import UndoableEdit from './undoable_changes/UndoableEdit';
import EventObject from "./event/EventObject"; import EventObject from './event/EventObject';
import InternalEvent from "./event/InternalEvent"; import InternalEvent from './event/InternalEvent';
/** /**
* Class: mxGraphSelectionModel * Class: mxGraphSelectionModel
@ -69,11 +68,11 @@ class GraphSelectionModel extends EventSource {
constructor(graph: Graph) { constructor(graph: Graph) {
super(); super();
this.graph = graph; this.graph = graph;
this.cells = new CellArray(); this.cells = [];
} }
graph: Graph; graph: Graph;
cells: CellArray; cells: Cell[];
/** /**
* Specifies the resource key for the status message after a long operation. * Specifies the resource key for the status message after a long operation.
@ -140,7 +139,7 @@ class GraphSelectionModel extends EventSource {
* @param cell {@link mxCell} to be selected. * @param cell {@link mxCell} to be selected.
*/ */
setCell(cell: Cell) { setCell(cell: Cell) {
this.setCells(cell ? new CellArray(cell) : new CellArray()); this.setCells(cell ? [cell] : []);
} }
/** /**
@ -148,12 +147,12 @@ class GraphSelectionModel extends EventSource {
* *
* @param cells Array of {@link Cell} to be selected. * @param cells Array of {@link Cell} to be selected.
*/ */
setCells(cells: CellArray) { setCells(cells: Cell[]) {
if (this.singleSelection) { if (this.singleSelection) {
cells = new CellArray(<Cell>this.getFirstSelectableCell(cells)); cells = [<Cell>this.getFirstSelectableCell(cells)];
} }
const tmp = new CellArray(); const tmp = [];
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
if (this.graph.isCellSelectable(cells[i])) { if (this.graph.isCellSelectable(cells[i])) {
tmp.push(cells[i]); tmp.push(cells[i]);
@ -165,7 +164,7 @@ class GraphSelectionModel extends EventSource {
/** /**
* Returns the first selectable cell in the given array of cells. * 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) { for (let i = 0; i < cells.length; i += 1) {
if (this.graph.isCellSelectable(cells[i])) { if (this.graph.isCellSelectable(cells[i])) {
return cells[i]; return cells[i];
@ -180,7 +179,7 @@ class GraphSelectionModel extends EventSource {
* @param cell {@link mxCell} to add to the selection. * @param cell {@link mxCell} to add to the selection.
*/ */
addCell(cell: Cell) { addCell(cell: Cell) {
this.addCells(new CellArray(cell)); this.addCells([cell]);
} }
/** /**
@ -189,16 +188,16 @@ class GraphSelectionModel extends EventSource {
* *
* @param cells Array of {@link Cell} to add to the selection. * @param cells Array of {@link Cell} to add to the selection.
*/ */
addCells(cells: CellArray) { addCells(cells: Cell[]) {
let remove = null; let remove = null;
if (this.singleSelection) { if (this.singleSelection) {
remove = this.cells; remove = this.cells;
const selectableCell = this.getFirstSelectableCell(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) { for (let i = 0; i < cells.length; i += 1) {
if (!this.isSelected(cells[i]) && this.graph.isCellSelectable(cells[i])) { if (!this.isSelected(cells[i]) && this.graph.isCellSelectable(cells[i])) {
tmp.push(cells[i]); tmp.push(cells[i]);
@ -215,7 +214,7 @@ class GraphSelectionModel extends EventSource {
* @param cell {@link mxCell} to remove from the selection. * @param cell {@link mxCell} to remove from the selection.
*/ */
removeCell(cell: Cell) { removeCell(cell: Cell) {
this.removeCells(new CellArray(cell)); this.removeCells([cell]);
} }
/** /**
@ -224,8 +223,8 @@ class GraphSelectionModel extends EventSource {
* *
* @param cells {@link mxCell}s to remove from the selection. * @param cells {@link mxCell}s to remove from the selection.
*/ */
removeCells(cells: CellArray) { removeCells(cells: Cell[]) {
const tmp = new CellArray(); const tmp = [];
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
if (this.isSelected(cells[i])) { if (this.isSelected(cells[i])) {
@ -241,16 +240,12 @@ class GraphSelectionModel extends EventSource {
* @param added Array of {@link Cell} to add to the selection. * @param added Array of {@link Cell} to add to the selection.
* @param remove Array of {@link Cell} to remove from 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 ( if (
(added && added.length > 0 && added[0]) || (added && added.length > 0 && added[0]) ||
(removed && removed.length > 0 && removed[0]) (removed && removed.length > 0 && removed[0])
) { ) {
const change = new SelectionChange( const change = new SelectionChange(this.graph, added || [], removed || []);
this.graph,
added || new CellArray(),
removed || new CellArray()
);
change.execute(); change.execute();
const edit = new UndoableEdit(this.graph, false); const edit = new UndoableEdit(this.graph, false);
edit.add(change); edit.add(change);

View File

@ -42,7 +42,6 @@ import ConnectionConstraint from './other/ConnectionConstraint';
import PopupMenuHandler from './handler/PopupMenuHandler'; import PopupMenuHandler from './handler/PopupMenuHandler';
import { getClientX, getClientY, getSource, isConsumed } from '../util/EventUtils'; import { getClientX, getClientY, getSource, isConsumed } from '../util/EventUtils';
import { clone } from '../util/cloneUtils'; import { clone } from '../util/cloneUtils';
import CellArray from './cell/CellArray';
import type { Graph } from './Graph'; import type { Graph } from './Graph';
import StyleRegistry from './style/StyleRegistry'; import StyleRegistry from './style/StyleRegistry';
import TooltipHandler from './handler/TooltipHandler'; import TooltipHandler from './handler/TooltipHandler';
@ -346,7 +345,7 @@ export class GraphView extends EventSource {
* *
* @param cells Array of {@link Cell} whose bounds should be returned. * @param cells Array of {@link Cell} whose bounds should be returned.
*/ */
getBounds(cells: CellArray) { getBounds(cells: Cell[]) {
let result: Rectangle | null = null; let result: Rectangle | null = null;
if (cells.length > 0) { if (cells.length > 0) {
@ -1973,7 +1972,7 @@ export class GraphView extends EventSource {
* have less elements than the given array. If no argument is given, then * have less elements than the given array. If no argument is given, then
* this returns {@link states}. * this returns {@link states}.
*/ */
getCellStates(cells: CellArray | null = null) { getCellStates(cells: Cell[] | null = null) {
if (!cells) { if (!cells) {
return this.states.getValues(); return this.states.getValues();
} }

View File

@ -22,7 +22,6 @@ import Animation from './Animation';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
/** /**
* Implements animation for morphing cells. Here is an example of * Implements animation for morphing cells. Here is an example of
@ -90,7 +89,7 @@ class Morphing extends Animation {
* then all cells are checked and animated if they have been moved * then all cells are checked and animated if they have been moved
* in the current transaction. * in the current transaction.
*/ */
cells: CellArray | null = null; cells: Cell[] | null = null;
/** /**
* Animation step. * Animation step.
@ -136,10 +135,7 @@ class Morphing extends Animation {
// change by subtracting the given delta vector from that location // change by subtracting the given delta vector from that location
delta = this.getDelta(state); delta = this.getDelta(state);
if ( if (cell.isVertex() && (delta.x != 0 || delta.y != 0)) {
cell.isVertex() &&
(delta.x != 0 || delta.y != 0)
) {
const translate = this.graph.view.getTranslate(); const translate = this.graph.view.getTranslate();
const scale = this.graph.view.getScale(); const scale = this.graph.view.getScale();
@ -154,11 +150,7 @@ class Morphing extends Animation {
const childCount = cell.getChildCount(); const childCount = cell.getChildCount();
for (let i = 0; i < childCount; i += 1) { for (let i = 0; i < childCount; i += 1) {
this.animateCell( this.animateCell(cell.getChildAt(i), move, recurse);
cell.getChildAt(i),
move,
recurse
);
} }
} }
} }

View File

@ -22,7 +22,6 @@ import CellOverlay from './CellOverlay';
import { clone } from '../../util/cloneUtils'; import { clone } from '../../util/cloneUtils';
import Point from '../geometry/Point'; import Point from '../geometry/Point';
import CellPath from './CellPath'; import CellPath from './CellPath';
import CellArray from './CellArray';
import { isNotNullish } from '../../util/Utils'; import { isNotNullish } from '../../util/Utils';
import ObjectCodec from '../../serialization/ObjectCodec'; import ObjectCodec from '../../serialization/ObjectCodec';
import CodecRegistry from '../../serialization/CodecRegistry'; import CodecRegistry from '../../serialization/CodecRegistry';
@ -91,8 +90,8 @@ export class Cell {
} }
// TODO: Document me!!! // TODO: Document me!!!
getChildren(): CellArray { getChildren(): Cell[] {
return this.children || new CellArray(); return this.children || [];
} }
// TODO: Document me! // TODO: Document me!
@ -168,12 +167,12 @@ export class Cell {
/** /**
* Holds the child cells. * Holds the child cells.
*/ */
children: CellArray = new CellArray(); children: Cell[] = [];
/** /**
* Holds the edges. * Holds the edges.
*/ */
edges: CellArray = new CellArray(); edges: Cell[] = [];
/** /**
* List of members that should not be cloned inside <clone>. This field is * List of members that should not be cloned inside <clone>. This field is
@ -684,14 +683,14 @@ export class Cell {
/** /**
* Returns the child vertices of the given parent. * Returns the child vertices of the given parent.
*/ */
getChildVertices(): CellArray { getChildVertices() {
return this.getChildCells(true, false); return this.getChildCells(true, false);
} }
/** /**
* Returns the child edges of the given parent. * Returns the child edges of the given parent.
*/ */
getChildEdges(): CellArray { getChildEdges() {
return this.getChildCells(false, true); return this.getChildCells(false, true);
} }
@ -704,9 +703,9 @@ export class Cell {
* @param edges Boolean indicating if child edges should be returned. * @param edges Boolean indicating if child edges should be returned.
* Default is false. * Default is false.
*/ */
getChildCells(vertices: boolean = false, edges: boolean = false): CellArray { getChildCells(vertices: boolean = false, edges: boolean = false) {
const childCount = this.getChildCount(); const childCount = this.getChildCount();
const result = new CellArray(); const result = [];
for (let i = 0; i < childCount; i += 1) { for (let i = 0; i < childCount; i += 1) {
const child = this.getChildAt(i); const child = this.getChildAt(i);
@ -748,21 +747,21 @@ export class Cell {
/** /**
* Returns all edges of the given cell without loops. * Returns all edges of the given cell without loops.
*/ */
getConnections(): CellArray { getConnections() {
return this.getEdges(true, true, false); return this.getEdges(true, true, false);
} }
/** /**
* Returns the incoming edges of the given cell without loops. * Returns the incoming edges of the given cell without loops.
*/ */
getIncomingEdges(): CellArray { getIncomingEdges() {
return this.getEdges(true, false, false); return this.getEdges(true, false, false);
} }
/** /**
* Returns the outgoing edges of the given cell without loops. * Returns the outgoing edges of the given cell without loops.
*/ */
getOutgoingEdges(): CellArray { getOutgoingEdges() {
return this.getEdges(false, true, false); return this.getEdges(false, true, false);
} }
@ -783,9 +782,9 @@ export class Cell {
incoming: boolean = true, incoming: boolean = true,
outgoing: boolean = true, outgoing: boolean = true,
includeLoops: boolean = true includeLoops: boolean = true
): CellArray { ) {
const edgeCount = this.getEdgeCount(); const edgeCount = this.getEdgeCount();
const result = new CellArray(); const result = [];
for (let i = 0; i < edgeCount; i += 1) { for (let i = 0; i < edgeCount; i += 1) {
const edge = this.getEdgeAt(i); const edge = this.getEdgeAt(i);
@ -831,7 +830,7 @@ export class Cell {
/** /**
* Returns all descendants of the given cell and the cell itself in an array. * Returns all descendants of the given cell and the cell itself in an array.
*/ */
getDescendants(): CellArray { getDescendants() {
return this.filterDescendants(null); return this.filterDescendants(null);
} }
@ -854,9 +853,9 @@ export class Cell {
* @param filter JavaScript function that takes an {@link Cell} as an argument * @param filter JavaScript function that takes an {@link Cell} as an argument
* and returns a boolean. * and returns a boolean.
*/ */
filterDescendants(filter: FilterFunction | null): CellArray { filterDescendants(filter: FilterFunction | null): Cell[] {
// Creates a new array for storing the result // Creates a new array for storing the result
let result = new CellArray(); let result: Cell[] = [];
// Checks if the filter returns true for the cell // Checks if the filter returns true for the cell
// and adds it to the result array // and adds it to the result array
@ -868,7 +867,7 @@ export class Cell {
const childCount = this.getChildCount(); const childCount = this.getChildCount();
for (let i = 0; i < childCount; i += 1) { for (let i = 0; i < childCount; i += 1) {
const child = this.getChildAt(i); const child = this.getChildAt(i);
result = new CellArray(...result.concat(child.filterDescendants(filter))); result = result.concat(child.filterDescendants(filter));
} }
return result; return result;

View File

@ -1,237 +0,0 @@
/*
Copyright 2021-present The maxGraph project Contributors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Cell from './Cell';
import Dictionary from '../../util/Dictionary';
import ObjectIdentity from '../../util/ObjectIdentity';
class CellArray extends Array<Cell> {
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(...(<Cell[]>super.map(arg0, ...args)));
}
// @ts-ignore
filter(arg0: any, ...args: any): CellArray {
return new CellArray(...(<Cell[]>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(<Cell>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 = <string>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>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[<string>ObjectIdentity.get(source)];
if (tmp != null) {
tmp.insertEdge(clone, true);
}
}
const target = cell.getTerminal(false);
if (target != null) {
const tmp = mapping[<string>ObjectIdentity.get(target)];
if (tmp != null) {
tmp.insertEdge(clone, false);
}
}
const childCount = clone.getChildCount();
for (let i = 0; i < childCount; i += 1) {
this.restoreClone(<Cell>clone.getChildAt(i), <Cell>cell.getChildAt(i), mapping);
}
}
}
export default CellArray;

View File

@ -61,7 +61,6 @@ import CellOverlay from './CellOverlay';
import { getClientX, getClientY, getSource } from '../../util/EventUtils'; import { getClientX, getClientY, getSource } from '../../util/EventUtils';
import { isNode } from '../../util/domUtils'; import { isNode } from '../../util/domUtils';
import { CellStateStyle } from '../../types'; import { CellStateStyle } from '../../types';
import CellArray from './CellArray';
import SelectionCellsHandler from '../handler/SelectionCellsHandler'; import SelectionCellsHandler from '../handler/SelectionCellsHandler';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
@ -612,7 +611,7 @@ class CellRenderer {
return (evt: Event) => { return (evt: Event) => {
if (this.forceControlClickHandler || graph.isEnabled()) { if (this.forceControlClickHandler || graph.isEnabled()) {
const collapse = !state.cell.isCollapsed(); 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); InternalEvent.consume(evt);
} }
}; };

View File

@ -22,7 +22,6 @@ import GraphView from '../GraphView';
import Cell from './Cell'; import Cell from './Cell';
import CellState from './CellState'; import CellState from './CellState';
import Shape from '../geometry/Shape'; import Shape from '../geometry/Shape';
import CellArray from './CellArray';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
/** /**
@ -53,7 +52,7 @@ class TemporaryCellStates {
constructor( constructor(
view: GraphView, view: GraphView,
scale: number = 1, scale: number = 1,
cells: CellArray, cells: Cell[],
isCellVisibleFn: Function | null = null, isCellVisibleFn: Function | null = null,
getLinkForCellState: Function | null = null getLinkForCellState: Function | null = null
) { ) {
@ -85,7 +84,9 @@ class TemporaryCellStates {
} }
}; };
(<Function>self.oldDoRedrawShape).apply((<Graph>view.graph).cellRenderer, [state]); (<Function>self.oldDoRedrawShape).apply((<Graph>view.graph).cellRenderer, [
state,
]);
shape.paint = oldPaint; shape.paint = oldPaint;
}; };
} }

View File

@ -32,7 +32,6 @@ import Shape from '../geometry/Shape';
import InternalMouseEvent from '../event/InternalMouseEvent'; import InternalMouseEvent from '../event/InternalMouseEvent';
import ImageBox from '../image/ImageBox'; import ImageBox from '../image/ImageBox';
import CellState from './CellState'; import CellState from './CellState';
import CellArray from './CellArray';
import type { Graph } from '../Graph'; import type { Graph } from '../Graph';
import type { CellHandle, CellStateStyle } from '../../types'; import type { CellHandle, CellStateStyle } from '../../types';
@ -101,7 +100,7 @@ class VertexHandle implements CellHandle {
* Sets the cell style with the given name to the corresponding value in <state>. * Sets the cell style with the given name to the corresponding value in <state>.
*/ */
copyStyle(key: keyof CellStateStyle) { 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]);
} }
/** /**

View File

@ -17,10 +17,7 @@ limitations under the License.
*/ */
import { getValue } from '../../util/Utils'; import { getValue } from '../../util/Utils';
import { import { getAlignmentAsPoint, setPrefixedStyle } from '../../util/styleUtils';
getAlignmentAsPoint,
setPrefixedStyle,
} from '../../util/styleUtils';
import Rectangle from '../geometry/Rectangle'; import Rectangle from '../geometry/Rectangle';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import Client from '../../Client'; import Client from '../../Client';
@ -42,7 +39,11 @@ import InternalMouseEvent from '../event/InternalMouseEvent';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import Shape from '../geometry/Shape'; import Shape from '../geometry/Shape';
import { clearSelection, extractTextWithWhitespace, isNode } from '../../util/domUtils'; import { clearSelection, extractTextWithWhitespace, isNode } from '../../util/domUtils';
import { getStringValue, htmlEntities, replaceTrailingNewlines } from '../../util/StringUtils'; import {
getStringValue,
htmlEntities,
replaceTrailingNewlines,
} from '../../util/StringUtils';
import { import {
getSource, getSource,
isConsumed, isConsumed,
@ -54,7 +55,6 @@ import EventSource from '../event/EventSource';
import type { Graph } from '../Graph'; import type { Graph } from '../Graph';
import type { GraphPlugin } from '../../types'; import type { GraphPlugin } from '../../types';
import CellArray from '../cell/CellArray';
import TooltipHandler from './TooltipHandler'; import TooltipHandler from './TooltipHandler';
/** /**
@ -889,7 +889,7 @@ class CellEditorHandler implements GraphPlugin {
} }
if (this.align !== null) { if (this.align !== null) {
this.graph.setCellStyles('align', this.align, new CellArray(state.cell)); this.graph.setCellStyles('align', this.align, [state.cell]);
} }
}); });
} }

View File

@ -56,7 +56,6 @@ import { Graph } from '../Graph';
import ConnectionConstraint from '../other/ConnectionConstraint'; import ConnectionConstraint from '../other/ConnectionConstraint';
import Shape from '../geometry/Shape'; import Shape from '../geometry/Shape';
import { CellStyle, GraphPlugin, Listenable } from '../../types'; import { CellStyle, GraphPlugin, Listenable } from '../../types';
import CellArray from '../cell/CellArray';
type FactoryMethod = ( type FactoryMethod = (
source: Cell | null, source: Cell | null,
@ -1749,7 +1748,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin {
target = this.createTargetVertex(evt, source); target = this.createTargetVertex(evt, source);
if (target) { if (target) {
dropTarget = this.graph.getDropTarget(new CellArray(target), evt, dropTarget); dropTarget = this.graph.getDropTarget([target], evt, dropTarget);
terminalInserted = true; terminalInserted = true;
// Disables edges as drop targets if the target cell was created // Disables edges as drop targets if the target cell was created

View File

@ -18,12 +18,7 @@ limitations under the License.
import Client from '../../Client'; import Client from '../../Client';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import { import { contains, getRotatedPoint, isNumeric, toRadians } from '../../util/mathUtils';
contains,
getRotatedPoint,
isNumeric,
toRadians,
} from '../../util/mathUtils';
import { convertPoint } from '../../util/styleUtils'; import { convertPoint } from '../../util/styleUtils';
import RectangleShape from '../geometry/node/RectangleShape'; import RectangleShape from '../geometry/node/RectangleShape';
import mxGuide from '../other/Guide'; import mxGuide from '../other/Guide';
@ -39,7 +34,12 @@ import {
import Dictionary from '../../util/Dictionary'; import Dictionary from '../../util/Dictionary';
import CellHighlight from '../cell/CellHighlight'; import CellHighlight from '../cell/CellHighlight';
import Rectangle from '../geometry/Rectangle'; 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 { Graph } from '../Graph';
import Guide from '../other/Guide'; import Guide from '../other/Guide';
import Shape from '../geometry/Shape'; import Shape from '../geometry/Shape';
@ -48,7 +48,6 @@ import SelectionCellsHandler from './SelectionCellsHandler';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import PopupMenuHandler from './PopupMenuHandler'; import PopupMenuHandler from './PopupMenuHandler';
import EventSource from '../event/EventSource'; import EventSource from '../event/EventSource';
import CellArray from '../cell/CellArray';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import ConnectionHandler from './ConnectionHandler'; import ConnectionHandler from './ConnectionHandler';
@ -325,7 +324,7 @@ class SelectionHandler implements GraphPlugin {
delayedSelection = false; delayedSelection = false;
first: Point | null = null; first: Point | null = null;
cells: CellArray | null = null; cells: Cell[] | null = null;
bounds: Rectangle | null = null; bounds: Rectangle | null = null;
pBounds: Rectangle | null = null; pBounds: Rectangle | null = null;
allCells: Dictionary<Cell, CellState> = new Dictionary(); allCells: Dictionary<Cell, CellState> = new Dictionary();
@ -481,7 +480,9 @@ class SelectionHandler implements GraphPlugin {
if (!this.graph.isToggleEvent(me.getEvent()) || !isAltDown(me.getEvent())) { if (!this.graph.isToggleEvent(me.getEvent()) || !isAltDown(me.getEvent())) {
while (c) { while (c) {
if (selectionCellsHandler.isHandled(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; return cellEditor.getEditingCell() !== c;
} }
c = c.getParent(); c = c.getParent();
@ -629,9 +630,9 @@ class SelectionHandler implements GraphPlugin {
* *
* @param initialCell <Cell> that triggered this handler. * @param initialCell <Cell> that triggered this handler.
*/ */
getCells(initialCell: Cell) { getCells(initialCell: Cell): Cell[] {
if (!this.delayedSelection && this.graph.isCellMovable(initialCell)) { if (!this.delayedSelection && this.graph.isCellMovable(initialCell)) {
return new CellArray(initialCell); return [initialCell];
} }
return this.graph.getMovableCells(this.graph.getSelectionCells()); return this.graph.getMovableCells(this.graph.getSelectionCells());
} }
@ -640,7 +641,7 @@ class SelectionHandler implements GraphPlugin {
* Returns the {@link Rectangle} used as the preview bounds for * Returns the {@link Rectangle} used as the preview bounds for
* moving the given cells. * moving the given cells.
*/ */
getPreviewBounds(cells: CellArray) { getPreviewBounds(cells: Cell[]) {
const bounds = this.getBoundingBox(cells); const bounds = this.getBoundingBox(cells);
if (bounds) { if (bounds) {
@ -678,7 +679,7 @@ class SelectionHandler implements GraphPlugin {
* *
* @param cells Array of {@link Cells} whose bounding box should be returned. * @param cells Array of {@link Cells} whose bounding box should be returned.
*/ */
getBoundingBox(cells: CellArray) { getBoundingBox(cells: Cell[]) {
let result = null; let result = null;
if (cells.length > 0) { if (cells.length > 0) {
@ -742,7 +743,7 @@ class SelectionHandler implements GraphPlugin {
/** /**
* Starts the handling of the mouse gesture. * 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.cell = cell;
this.first = convertPoint(this.graph.container, x, y); this.first = convertPoint(this.graph.container, x, y);
this.cells = cells ? cells : this.getCells(this.cell); this.cells = cells ? cells : this.getCells(this.cell);
@ -1369,7 +1370,7 @@ class SelectionHandler implements GraphPlugin {
* @param visible Boolean that specifies if the handles should be visible. * @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. * @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) { if (force || this.handlesVisible !== visible) {
this.handlesVisible = visible; this.handlesVisible = visible;
@ -1517,7 +1518,7 @@ class SelectionHandler implements GraphPlugin {
* Returns true if the given cells should be removed from the parent for the specified * Returns true if the given cells should be removed from the parent for the specified
* mousereleased event. * mousereleased event.
*/ */
shouldRemoveCellsFromParent(parent: Cell, cells: CellArray, evt: MouseEvent) { shouldRemoveCellsFromParent(parent: Cell, cells: Cell[], evt: MouseEvent) {
if (parent.isVertex()) { if (parent.isVertex()) {
const pState = this.graph.getView().getState(parent); const pState = this.graph.getView().getState(parent);
@ -1544,7 +1545,7 @@ class SelectionHandler implements GraphPlugin {
* Moves the given cells by the specified amount. * Moves the given cells by the specified amount.
*/ */
moveCells( moveCells(
cells: CellArray, cells: Cell[],
dx: number, dx: number,
dy: number, dy: number,
clone: boolean, clone: boolean,
@ -1608,7 +1609,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 // Selects the new cells if cells have been cloned

View File

@ -45,7 +45,6 @@ import Cell from '../cell/Cell';
import { CellHandle, Listenable } from '../../types'; import { CellHandle, Listenable } from '../../types';
import Shape from '../geometry/Shape'; import Shape from '../geometry/Shape';
import InternalMouseEvent from '../event/InternalMouseEvent'; import InternalMouseEvent from '../event/InternalMouseEvent';
import CellArray from '../cell/CellArray';
import EdgeHandler from './EdgeHandler'; import EdgeHandler from './EdgeHandler';
import EventSource from '../event/EventSource'; import EventSource from '../event/EventSource';
import SelectionHandler from './SelectionHandler'; import SelectionHandler from './SelectionHandler';
@ -214,7 +213,7 @@ class VertexHandler {
constructor(state: CellState) { constructor(state: CellState) {
this.state = state; this.state = state;
this.graph = (<Graph>this.state.view.graph); this.graph = <Graph>this.state.view.graph;
this.selectionBounds = this.getSelectionBounds(this.state); this.selectionBounds = this.getSelectionBounds(this.state);
this.bounds = new Rectangle( this.bounds = new Rectangle(
this.selectionBounds.x, this.selectionBounds.x,
@ -659,7 +658,7 @@ class VertexHandler {
this.ghostPreview = this.createGhostPreview(); this.ghostPreview = this.createGhostPreview();
} else { } else {
// Saves reference to parent state // Saves reference to parent state
const { model } = (<Graph>this.state.view.graph); const { model } = <Graph>this.state.view.graph;
const parent = this.state.cell.getParent(); const parent = this.state.cell.getParent();
if ( if (
@ -1299,7 +1298,7 @@ class VertexHandler {
if (!cell.isEdge()) { if (!cell.isEdge()) {
const style = this.graph.getCurrentCellStyle(cell); const style = this.graph.getCurrentCellStyle(cell);
const total = (style.rotation || 0) + angle; const total = (style.rotation || 0) + angle;
this.graph.setCellStyles('rotation', total, new CellArray(cell)); this.graph.setCellStyles('rotation', total, [cell]);
} }
let geo = cell.getGeometry(); let geo = cell.getGeometry();
@ -1877,7 +1876,9 @@ class VertexHandler {
// Hides rotation handle during text editing // Hides rotation handle during text editing
this.rotationShape.node.style.visibility = this.rotationShape.node.style.visibility =
(<Graph>this.state.view.graph).isEditing() || !this.handlesVisible ? 'hidden' : ''; (<Graph>this.state.view.graph).isEditing() || !this.handlesVisible
? 'hidden'
: '';
} }
} }
@ -1896,7 +1897,9 @@ class VertexHandler {
* Returns true if the given custom handle is visible. * Returns true if the given custom handle is visible.
*/ */
isCustomHandleVisible(handle: CellHandle) { isCustomHandleVisible(handle: CellHandle) {
return !this.graph.isEditing() && (<Graph>this.state.view.graph).getSelectionCount() === 1; return (
!this.graph.isEditing() && (<Graph>this.state.view.graph).getSelectionCount() === 1
);
} }
/** /**

View File

@ -17,7 +17,6 @@ limitations under the License.
*/ */
import GraphLayout from './GraphLayout'; import GraphLayout from './GraphLayout';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
/** /**
@ -141,7 +140,7 @@ class CircleLayout extends GraphLayout {
left = this.x0; left = this.x0;
top = this.y0; top = this.y0;
} }
this.circle(new CellArray(...vertices), r, <number>left, <number>top); this.circle(vertices, r, <number>left, <number>top);
}); });
} }
@ -158,7 +157,7 @@ class CircleLayout extends GraphLayout {
* of vertices and the given radius. This is called from * of vertices and the given radius. This is called from
* <execute>. * <execute>.
*/ */
circle(vertices: CellArray, r: number, left: number, top: number) { circle(vertices: Cell[], r: number, left: number, top: number) {
const vertexCount = vertices.length; const vertexCount = vertices.length;
const phi = (2 * Math.PI) / vertexCount; const phi = (2 * Math.PI) / vertexCount;

View File

@ -26,7 +26,6 @@ import WeightedCellSorter from './util/WeightedCellSorter';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import { findTreeRoots } from '../../util/treeTraversal'; import { findTreeRoots } from '../../util/treeTraversal';
import CellArray from '../cell/CellArray';
export interface _mxCompactTreeLayoutNode { export interface _mxCompactTreeLayoutNode {
cell?: Cell; cell?: Cell;
@ -37,11 +36,11 @@ export interface _mxCompactTreeLayoutNode {
offsetX?: number; offsetX?: number;
offsetY?: number; offsetY?: number;
contour?: { contour?: {
upperTail?: _mxCompactTreeLayoutLine, upperTail?: _mxCompactTreeLayoutLine;
upperHead?: _mxCompactTreeLayoutLine, upperHead?: _mxCompactTreeLayoutLine;
lowerTail?: _mxCompactTreeLayoutLine, lowerTail?: _mxCompactTreeLayoutLine;
lowerHead?: _mxCompactTreeLayoutLine, lowerHead?: _mxCompactTreeLayoutLine;
[key: string]: any, [key: string]: any;
}; };
next?: _mxCompactTreeLayoutNode; next?: _mxCompactTreeLayoutNode;
child?: _mxCompactTreeLayoutNode; child?: _mxCompactTreeLayoutNode;
@ -212,7 +211,7 @@ export class CompactTreeLayout extends GraphLayout {
* An array of the maximum height of cells (relative to the layout direction) * An array of the maximum height of cells (relative to the layout direction)
* per rank * per rank
*/ */
maxRankHeight: CellArray | null = null; maxRankHeight: Cell[] = [];
/** /**
* The cell to use as the root of the tree * The cell to use as the root of the tree
@ -232,9 +231,7 @@ export class CompactTreeLayout extends GraphLayout {
* @param vertex {@link mxCell} whose ignored state should be returned. * @param vertex {@link mxCell} whose ignored state should be returned.
*/ */
isVertexIgnored(vertex: Cell): boolean { isVertexIgnored(vertex: Cell): boolean {
return ( return super.isVertexIgnored(vertex) || vertex.getConnections().length === 0;
super.isVertexIgnored(vertex) || vertex.getConnections().length === 0
);
} }
/** /**
@ -320,7 +317,7 @@ export class CompactTreeLayout extends GraphLayout {
this.node = this.dfs(this.root, parent); this.node = this.dfs(this.root, parent);
if (this.alignRanks) { if (this.alignRanks) {
this.maxRankHeight = new CellArray(); this.maxRankHeight = [];
this.findRankHeights(this.node, 0); this.findRankHeights(this.node, 0);
this.setCellHeights(this.node, 0); this.setCellHeights(this.node, 0);
} }
@ -410,7 +407,7 @@ export class CompactTreeLayout extends GraphLayout {
/** /**
* Called if {@link sortEdges} is true to sort the array of outgoing edges in place. * 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(); const lookup = new Dictionary();
edges.sort((e1, e2) => { edges.sort((e1, e2) => {
@ -439,7 +436,7 @@ export class CompactTreeLayout extends GraphLayout {
* direction) of cells in each rank * direction) of cells in each rank
*/ */
findRankHeights(node: any, rank: number): void { findRankHeights(node: any, rank: number): void {
const maxRankHeight = <CellArray>this.maxRankHeight; const maxRankHeight = this.maxRankHeight;
if (maxRankHeight[rank] == null || maxRankHeight[rank] < node.height) { if (maxRankHeight[rank] == null || maxRankHeight[rank] < node.height) {
maxRankHeight[rank] = node.height; maxRankHeight[rank] = node.height;
} }
@ -456,7 +453,7 @@ export class CompactTreeLayout extends GraphLayout {
* direction) when the tops of each rank are to be aligned * direction) when the tops of each rank are to be aligned
*/ */
setCellHeights(node: any, rank: number): void { setCellHeights(node: any, rank: number): void {
const maxRankHeight = <CellArray>this.maxRankHeight; const maxRankHeight = this.maxRankHeight;
if (maxRankHeight[rank] != null && maxRankHeight[rank] > node.height) { if (maxRankHeight[rank] != null && maxRankHeight[rank] > node.height) {
node.height = maxRankHeight[rank]; node.height = maxRankHeight[rank];
} }
@ -557,7 +554,12 @@ export class CompactTreeLayout extends GraphLayout {
* Starts the actual compact tree layout algorithm * Starts the actual compact tree layout algorithm
* at the given node. * 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.x += x0 + node.offsetX;
node.y += y0 + node.offsetY; node.y += y0 + node.offsetY;
bounds = this.apply(node, bounds); bounds = this.apply(node, bounds);
@ -824,7 +826,10 @@ export class CompactTreeLayout extends GraphLayout {
* Starts the actual compact tree layout algorithm * Starts the actual compact tree layout algorithm
* at the given node. * 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 model = this.graph.getDataModel();
const cell = <Cell>node.cell; const cell = <Cell>node.cell;
let g: Rectangle = <Rectangle>cell.getGeometry(); let g: Rectangle = <Rectangle>cell.getGeometry();
@ -867,7 +872,7 @@ export class CompactTreeLayout extends GraphLayout {
let line: _mxCompactTreeLayoutLine = { let line: _mxCompactTreeLayoutLine = {
dx, dx,
dy, dy,
next next,
}; };
return line; return line;
} }
@ -878,7 +883,7 @@ export class CompactTreeLayout extends GraphLayout {
* a padding. * a padding.
*/ */
adjustParents(): void { adjustParents(): void {
const tmp = new CellArray(); const tmp = [];
for (const id in this.parentsChanged) { for (const id in this.parentsChanged) {
tmp.push(this.parentsChanged[id]); tmp.push(this.parentsChanged[id]);

View File

@ -19,7 +19,6 @@ import ObjectIdentity from '../../util/ObjectIdentity';
import GraphLayout from './GraphLayout'; import GraphLayout from './GraphLayout';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
/** /**
* Extends {@link GraphLayout} to implement a fast organic layout algorithm. * Extends {@link GraphLayout} to implement a fast organic layout algorithm.
@ -106,7 +105,7 @@ class MxFastOrganicLayout extends GraphLayout {
/** /**
* An array of all vertices to be laid out. * 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. * An array of locally stored X co-ordinate displacements for the vertices.
@ -172,7 +171,7 @@ class MxFastOrganicLayout extends GraphLayout {
*/ */
execute(parent: Cell) { execute(parent: Cell) {
const model = this.graph.getDataModel(); const model = this.graph.getDataModel();
this.vertexArray = new CellArray(); this.vertexArray = [];
let cells = this.graph.getChildVertices(parent); let cells = this.graph.getChildVertices(parent);
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {

View File

@ -22,7 +22,6 @@ import Geometry from '../geometry/Geometry';
import Point from '../geometry/Point'; import Point from '../geometry/Point';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
/** /**
* @class GraphLayout * @class GraphLayout
@ -241,14 +240,14 @@ class GraphLayout {
* Disables or enables the edge style of the given edge. * Disables or enables the edge style of the given edge.
*/ */
setEdgeStyleEnabled(edge: Cell, value: any): void { 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. * Disables or enables orthogonal end segments of the given edge.
*/ */
setOrthogonalEdge(edge: Cell, value: any): void { setOrthogonalEdge(edge: Cell, value: any): void {
this.graph.setCellStyles('orthogonal', value ? '1' : '0', new CellArray(edge)); this.graph.setCellStyles('orthogonal', value ? '1' : '0', [edge]);
} }
/** /**
@ -419,7 +418,7 @@ class GraphLayout {
* Shortcut to {@link Graph#updateGroupBounds} with moveGroup set to true. * Shortcut to {@link Graph#updateGroupBounds} with moveGroup set to true.
*/ */
arrangeGroups( arrangeGroups(
cells: CellArray, cells: Cell[],
border: number, border: number,
topBorder: number, topBorder: number,
rightBorder: number, rightBorder: number,

View File

@ -26,7 +26,6 @@ import MinimumCycleRemover from './hierarchical/MinimumCycleRemover';
import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction'; import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction';
import CoordinateAssignment from './hierarchical/CoordinateAssignment'; import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../../view/Graph'; import { Graph } from '../../view/Graph';
import CellArray from '../../view/cell/CellArray';
import Cell from '../../view/cell/Cell'; import Cell from '../../view/cell/Cell';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
@ -63,7 +62,7 @@ class HierarchicalLayout extends GraphLayout {
/** /**
* Holds the array of <Cell> that this layout contains. * Holds the array of <Cell> 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 * Specifies if the parent should be resized after the layout so that it
@ -151,7 +150,7 @@ class HierarchicalLayout extends GraphLayout {
/** /**
* A cache of edges whose source terminal is the key * A cache of edges whose source terminal is the key
*/ */
edgesCache: Dictionary<Cell, CellArray> = new Dictionary(); edgesCache: Dictionary<Cell, Cell[]> = new Dictionary();
/** /**
* A cache of edges whose source terminal is the key * A cache of edges whose source terminal is the key
@ -182,7 +181,7 @@ class HierarchicalLayout extends GraphLayout {
* @param parent Parent <Cell> that contains the children to be laid out. * @param parent Parent <Cell> that contains the children to be laid out.
* @param roots Optional starting roots of the layout. * @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; this.parent = parent;
const { model } = this.graph; const { model } = this.graph;
this.edgesCache = new Dictionary(); this.edgesCache = new Dictionary();
@ -190,7 +189,7 @@ class HierarchicalLayout extends GraphLayout {
this.edgesTargetTermCache = new Dictionary(); this.edgesTargetTermCache = new Dictionary();
if (roots != null && !(roots instanceof Array)) { if (roots != null && !(roots instanceof Array)) {
roots = new CellArray(roots); roots = [roots];
} }
// If the roots are set and the parent is set, only // If the roots are set and the parent is set, only
@ -223,7 +222,7 @@ class HierarchicalLayout extends GraphLayout {
} }
if (roots != null) { if (roots != null) {
const rootsCopy = new CellArray(); const rootsCopy = [];
for (let i = 0; i < roots.length; i += 1) { for (let i = 0; i < roots.length; i += 1) {
const ancestor = parent != null ? parent.isAncestor(roots[i]) : true; const ancestor = parent != null ? parent.isAncestor(roots[i]) : true;
@ -240,7 +239,7 @@ class HierarchicalLayout extends GraphLayout {
this.run(parent); this.run(parent);
if (this.resizeParent && !parent.isCollapsed()) { 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 // Maintaining parent location
@ -269,8 +268,8 @@ class HierarchicalLayout extends GraphLayout {
* @param parent <Cell> whose children should be checked. * @param parent <Cell> whose children should be checked.
* @param vertices array of vertices to limit search to * @param vertices array of vertices to limit search to
*/ */
findRoots(parent: Cell, vertices: CellArray): CellArray { findRoots(parent: Cell, vertices: Cell[]): Cell[] {
const roots = new CellArray(); const roots = [];
if (parent != null && vertices != null) { if (parent != null && vertices != null) {
const { model } = this.graph; const { model } = this.graph;
@ -320,14 +319,14 @@ class HierarchicalLayout extends GraphLayout {
* *
* @param cell <Cell> whose edges should be returned. * @param cell <Cell> whose edges should be returned.
*/ */
getEdges(cell: Cell): CellArray { getEdges(cell: Cell) {
const cachedEdges = this.edgesCache.get(cell); const cachedEdges = this.edgesCache.get(cell);
if (cachedEdges != null) { if (cachedEdges != null) {
return cachedEdges; return cachedEdges;
} }
const { model } = this.graph; const { model } = this.graph;
let edges = new CellArray(); let edges: Cell[] = [];
const isCollapsed = cell.isCollapsed(); const isCollapsed = cell.isCollapsed();
const childCount = cell.getChildCount(); const childCount = cell.getChildCount();
@ -342,7 +341,7 @@ class HierarchicalLayout extends GraphLayout {
} }
edges = edges.concat(cell.getEdges(true, true)); edges = edges.concat(cell.getEdges(true, true));
const result = new CellArray(); const result = [];
for (let i = 0; i < edges.length; i += 1) { for (let i = 0; i < edges.length; i += 1) {
const source = this.getVisibleTerminal(edges[i], true); const source = this.getVisibleTerminal(edges[i], true);
@ -423,7 +422,7 @@ class HierarchicalLayout extends GraphLayout {
const filledVertexSet = Object(); const filledVertexSet = Object();
this.filterDescendants(parent, filledVertexSet); this.filterDescendants(parent, filledVertexSet);
this.roots = new CellArray(); this.roots = [];
let filledVertexSetEmpty = true; let filledVertexSetEmpty = true;
// Poor man's isSetEmpty // Poor man's isSetEmpty
@ -472,7 +471,7 @@ class HierarchicalLayout extends GraphLayout {
} }
} else { } else {
// Find vertex set as directed traversal from roots // Find vertex set as directed traversal from roots
const roots = <CellArray>this.roots; const roots = this.roots as Cell[]; // NEED CHECK - roots cannot be null
for (let i = 0; i < roots.length; i += 1) { for (let i = 0; i < roots.length; i += 1) {
const vertexSet = Object(); const vertexSet = Object();
@ -498,7 +497,7 @@ class HierarchicalLayout extends GraphLayout {
for (let i = 0; i < hierarchyVertices.length; i += 1) { for (let i = 0; i < hierarchyVertices.length; i += 1) {
const vertexSet = hierarchyVertices[i]; const vertexSet = hierarchyVertices[i];
const tmp = new CellArray(); const tmp = [];
for (var key in vertexSet) { for (var key in vertexSet) {
tmp.push(vertexSet[key]); tmp.push(vertexSet[key]);
@ -507,7 +506,7 @@ class HierarchicalLayout extends GraphLayout {
this.model = new GraphHierarchyModel( this.model = new GraphHierarchyModel(
this, this,
tmp, tmp,
<CellArray>this.roots, this.roots as Cell[],
parent, parent,
this.tightenToSource this.tightenToSource
); );
@ -566,10 +565,10 @@ class HierarchicalLayout extends GraphLayout {
* target - * target -
* directed - * directed -
*/ */
getEdgesBetween(source: Cell, target: Cell, directed: boolean): CellArray { getEdgesBetween(source: Cell, target: Cell, directed: boolean): Cell[] {
directed = directed != null ? directed : false; directed = directed != null ? directed : false;
const edges = this.getEdges(source); const edges = this.getEdges(source);
const result = new CellArray(); const result = [];
// Checks if the edge is connected to the correct // Checks if the edge is connected to the correct
// cell and returns the first match // cell and returns the first match
@ -607,7 +606,7 @@ class HierarchicalLayout extends GraphLayout {
directed: boolean = false, directed: boolean = false,
edge: Cell | null = null, edge: Cell | null = null,
allVertices: { [key: string]: Cell } | null = null, allVertices: { [key: string]: Cell } | null = null,
currentComp: { [key: string]: (Cell | null) }, currentComp: { [key: string]: Cell | null },
hierarchyVertices: GraphHierarchyNode[], hierarchyVertices: GraphHierarchyNode[],
filledVertexSet: { [key: string]: Cell } | null = null filledVertexSet: { [key: string]: Cell } | null = null
) { ) {

View File

@ -29,7 +29,6 @@ import EventObject from '../event/EventObject';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Rectangle from '../geometry/Rectangle'; import Rectangle from '../geometry/Rectangle';
import { getClientX, getClientY } from '../../util/EventUtils'; import { getClientX, getClientY } from '../../util/EventUtils';
import CellArray from '../cell/CellArray';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import GraphLayout from './GraphLayout'; import GraphLayout from './GraphLayout';
import UndoableEdit from '../undoable_changes/UndoableEdit'; import UndoableEdit from '../undoable_changes/UndoableEdit';
@ -225,7 +224,7 @@ class LayoutManager extends EventSource {
* @param cell Array of {@link Cell} that have been moved. * @param cell Array of {@link Cell} that have been moved.
* @param evt Mouse event that represents the mousedown. * @param evt Mouse event that represents the mousedown.
*/ */
cellsMoved(cells: CellArray, evt: MouseEvent) { cellsMoved(cells: Cell[], evt: MouseEvent) {
if (cells.length > 0 && evt) { if (cells.length > 0 && evt) {
const point = convertPoint( const point = convertPoint(
this.getGraph().container, this.getGraph().container,
@ -250,9 +249,9 @@ class LayoutManager extends EventSource {
* @param bounds {@link mxRectangle} taht represents the new bounds. * @param bounds {@link mxRectangle} taht represents the new bounds.
*/ */
cellsResized( cellsResized(
cells: CellArray | null = null, cells: Cell[] | null = null,
bounds: Rectangle[] | null = null, bounds: Rectangle[] | null = null,
prev: CellArray | null = null prev: Cell[] | null = null
) { ) {
if (cells && bounds) { if (cells && bounds) {
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
@ -267,11 +266,11 @@ class LayoutManager extends EventSource {
/** /**
* Returns the cells for which a layout should be executed. * Returns the cells for which a layout should be executed.
*/ */
getCellsForChanges(changes: any[]): CellArray { getCellsForChanges(changes: any[]): Cell[] {
let result: CellArray = new CellArray(); let result: Cell[] = [];
for (const change of changes) { for (const change of changes) {
if (change instanceof RootChange) { if (change instanceof RootChange) {
return new CellArray(); return [];
} }
result = result.concat(this.getCellsForChange(change)); result = result.concat(this.getCellsForChange(change));
} }
@ -283,7 +282,7 @@ class LayoutManager extends EventSource {
* changes. * changes.
* @param change mxChildChange|mxTerminalChange|mxVisibleChange|... * @param change mxChildChange|mxTerminalChange|mxVisibleChange|...
*/ */
getCellsForChange(change: any): CellArray { getCellsForChange(change: any): Cell[] {
if (change instanceof ChildChange) { if (change instanceof ChildChange) {
return this.addCellsWithLayout( return this.addCellsWithLayout(
change.child, change.child,
@ -299,23 +298,20 @@ class LayoutManager extends EventSource {
return this.addCellsWithLayout(change.cell); return this.addCellsWithLayout(change.cell);
} }
return new CellArray(); return [];
} }
/** /**
* Adds all ancestors of the given cell that have a layout. * 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)); return this.addDescendantsWithLayout(cell, this.addAncestorsWithLayout(cell, result));
} }
/** /**
* Adds all ancestors of the given cell that have a layout. * Adds all ancestors of the given cell that have a layout.
*/ */
addAncestorsWithLayout( addAncestorsWithLayout(cell: Cell | null, result: Cell[] = []): Cell[] {
cell: Cell | null,
result: CellArray = new CellArray()
): CellArray {
if (cell) { if (cell) {
const layout = this.hasLayout(cell); const layout = this.hasLayout(cell);
@ -333,7 +329,7 @@ class LayoutManager extends EventSource {
/** /**
* Adds all descendants of the given cell that have a layout. * 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)) { if (cell && this.hasLayout(cell)) {
for (let i = 0; i < cell.getChildCount(); i += 1) { for (let i = 0; i < cell.getChildCount(); i += 1) {
const child = <Cell>cell.getChildAt(i); const child = <Cell>cell.getChildAt(i);
@ -351,16 +347,16 @@ class LayoutManager extends EventSource {
/** /**
* Executes the given layout on the given parent. * Executes the given layout on the given parent.
*/ */
executeLayoutForCells(cells: CellArray) { executeLayoutForCells(cells: Cell[]) {
const sorted = sortCells(cells, false); const sorted = sortCells(cells, false);
this.layoutCells(sorted, true); 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. * 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) { if (cells.length > 0) {
// Invokes the layouts while removing duplicates // Invokes the layouts while removing duplicates
const model = this.getGraph().getDataModel(); const model = this.getGraph().getDataModel();

View File

@ -20,7 +20,6 @@ import Point from '../geometry/Point';
import GraphLayout from './GraphLayout'; import GraphLayout from './GraphLayout';
import ObjectIdentity from '../../util/ObjectIdentity'; import ObjectIdentity from '../../util/ObjectIdentity';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Geometry from '../geometry/Geometry'; import Geometry from '../geometry/Geometry';
@ -84,7 +83,7 @@ class ParallelEdgeLayout extends GraphLayout {
/** /**
* Implements {@link GraphLayout#execute}. * 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); const lookup = this.findParallels(parent, cells);
this.graph.model.beginUpdate(); this.graph.model.beginUpdate();
@ -104,7 +103,7 @@ class ParallelEdgeLayout extends GraphLayout {
/** /**
* Finds the parallel edges in the given parent. * 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 lookup: any = [];
const addCell = (cell: Cell) => { const addCell = (cell: Cell) => {
@ -178,7 +177,7 @@ class ParallelEdgeLayout extends GraphLayout {
/** /**
* Lays out the parallel edges in the given array. * Lays out the parallel edges in the given array.
*/ */
layout(parallels: CellArray) { layout(parallels: Cell[]) {
const edge = parallels[0]; const edge = parallels[0];
const view = this.graph.getView(); const view = this.graph.getView();
const model = this.graph.getDataModel(); const model = this.graph.getDataModel();

View File

@ -24,7 +24,6 @@ import { DEFAULT_STARTSIZE } from '../../util/Constants';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Geometry from '../geometry/Geometry'; import Geometry from '../geometry/Geometry';
import CellArray from '../cell/CellArray';
/** /**
* Extends {@link GraphLayout} to create a horizontal or vertical stack of the * Extends {@link GraphLayout} to create a horizontal or vertical stack of the
@ -231,10 +230,10 @@ class StackLayout extends GraphLayout {
/** /**
* Returns the cells to be layouted. * Returns the cells to be layouted.
*/ */
getLayoutCells(parent: Cell): CellArray { getLayoutCells(parent: Cell): Cell[] {
const model = this.graph.getDataModel(); const model = this.graph.getDataModel();
const childCount = parent.getChildCount(); const childCount = parent.getChildCount();
const cells = new CellArray(); const cells = [];
for (let i = 0; i < childCount; i += 1) { for (let i = 0; i < childCount; i += 1) {
const child = parent.getChildAt(i); const child = parent.getChildAt(i);
@ -252,12 +251,12 @@ class StackLayout extends GraphLayout {
return this.horizontal return this.horizontal
? geo1.x === geo2.x ? geo1.x === geo2.x
? 0 ? 0
: (geo1.x > geo2.x && geo2.x > 0) : geo1.x > geo2.x && geo2.x > 0
? 1 ? 1
: -1 : -1
: geo1.y === geo2.y : geo1.y === geo2.y
? 0 ? 0
: (geo1.y > geo2.y && geo2.y > 0) : geo1.y > geo2.y && geo2.y > 0
? 1 ? 1
: -1; : -1;
}); });

View File

@ -28,7 +28,6 @@ import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingRe
import CoordinateAssignment from './hierarchical/CoordinateAssignment'; import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import Geometry from '../../view/geometry/Geometry'; import Geometry from '../../view/geometry/Geometry';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode'; import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
@ -48,7 +47,11 @@ import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
* deterministic. Default is true. * deterministic. Default is true.
*/ */
class SwimlaneLayout extends GraphLayout { class SwimlaneLayout extends GraphLayout {
constructor(graph: Graph, orientation: DIRECTION | null, deterministic: boolean = true) { constructor(
graph: Graph,
orientation: DIRECTION | null,
deterministic: boolean = true
) {
super(graph); super(graph);
this.orientation = orientation != null ? orientation : DIRECTION.NORTH; this.orientation = orientation != null ? orientation : DIRECTION.NORTH;
this.deterministic = deterministic != null ? deterministic : true; this.deterministic = deterministic != null ? deterministic : true;
@ -61,12 +64,12 @@ class SwimlaneLayout extends GraphLayout {
/** /**
* Holds the array of <Cell> that this layout contains. * Holds the array of <Cell> that this layout contains.
*/ */
roots: CellArray | null = null; roots: Cell[] | null = null;
/** /**
* Holds the array of <Cell> of the ordered swimlanes to lay out * Holds the array of <Cell> of the ordered swimlanes to lay out
*/ */
swimlanes: CellArray | null = null; swimlanes: Cell[] | null = null;
/** /**
* The cell width of any dummy vertices inserted * The cell width of any dummy vertices inserted
@ -159,7 +162,7 @@ class SwimlaneLayout extends GraphLayout {
/** /**
* A cache of edges whose source terminal is the key * A cache of edges whose source terminal is the key
*/ */
edgesCache: Dictionary<Cell, CellArray> = new Dictionary(); edgesCache: Dictionary<Cell, Cell[]> = new Dictionary();
/** /**
* A cache of edges whose source terminal is the key * A cache of edges whose source terminal is the key
@ -190,7 +193,7 @@ class SwimlaneLayout extends GraphLayout {
* @param parent Parent <Cell> that contains the children to be laid out. * @param parent Parent <Cell> that contains the children to be laid out.
* @param swimlanes Ordered array of swimlanes 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; this.parent = parent;
const { model } = this.graph; const { model } = this.graph;
this.edgesCache = new Dictionary(); this.edgesCache = new Dictionary();
@ -231,7 +234,7 @@ class SwimlaneLayout extends GraphLayout {
} }
this.swimlanes = swimlanes; this.swimlanes = swimlanes;
const dummyVertices = new CellArray(); const dummyVertices = [];
// Check the swimlanes all have vertices // Check the swimlanes all have vertices
// in them // in them
@ -257,7 +260,7 @@ class SwimlaneLayout extends GraphLayout {
this.run(parent); this.run(parent);
if (this.resizeParent && !parent.isCollapsed()) { 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 // Maintaining parent location
@ -285,7 +288,7 @@ class SwimlaneLayout extends GraphLayout {
*/ */
updateGroupBounds(): void { updateGroupBounds(): void {
// Get all vertices and edge in the layout // Get all vertices and edge in the layout
const cells = new CellArray(); const cells = [];
const model = <SwimlaneModel>this.model; const model = <SwimlaneModel>this.model;
for (const key in model.edgeMapper) { for (const key in model.edgeMapper) {
@ -299,7 +302,7 @@ class SwimlaneLayout extends GraphLayout {
let layoutBounds = this.graph.getBoundingBoxFromGeometry(cells, true); let layoutBounds = this.graph.getBoundingBoxFromGeometry(cells, true);
const childBounds = []; const childBounds = [];
const swimlanes = <CellArray>this.swimlanes; const swimlanes = this.swimlanes as Cell[];
for (let i = 0; i < swimlanes.length; i += 1) { for (let i = 0; i < swimlanes.length; i += 1) {
const lane = swimlanes[i]; const lane = swimlanes[i];
@ -350,7 +353,8 @@ class SwimlaneLayout extends GraphLayout {
newGeo.y = y; newGeo.y = y;
newGeo.width = childBounds[i].width + w + this.interRankCellSpacing / 2; newGeo.width = childBounds[i].width + w + this.interRankCellSpacing / 2;
newGeo.height = (<Rectangle>layoutBounds).height + size.height + 2 * this.parentBorder; newGeo.height =
(<Rectangle>layoutBounds).height + size.height + 2 * this.parentBorder;
this.graph.model.setGeometry(lane, newGeo); this.graph.model.setGeometry(lane, newGeo);
this.graph.moveCells(children, -x, geo.y - y); this.graph.moveCells(children, -x, geo.y - y);
@ -368,8 +372,8 @@ class SwimlaneLayout extends GraphLayout {
* @param parent <Cell> whose children should be checked. * @param parent <Cell> whose children should be checked.
* @param vertices array of vertices to limit search to * @param vertices array of vertices to limit search to
*/ */
findRoots(parent: Cell, vertices: { [key: string]: Cell }): CellArray { findRoots(parent: Cell, vertices: { [key: string]: Cell }): Cell[] {
const roots = new CellArray(); const roots = [];
if (parent != null && vertices != null) { if (parent != null && vertices != null) {
const { model } = this.graph; const { model } = this.graph;
@ -429,14 +433,14 @@ class SwimlaneLayout extends GraphLayout {
* *
* @param cell <Cell> whose edges should be returned. * @param cell <Cell> whose edges should be returned.
*/ */
getEdges(cell: Cell): CellArray { getEdges(cell: Cell): Cell[] {
const cachedEdges = this.edgesCache.get(cell); const cachedEdges = this.edgesCache.get(cell);
if (cachedEdges != null) { if (cachedEdges != null) {
return cachedEdges; return cachedEdges;
} }
let edges = new CellArray(); let edges: Cell[] = [];
const isCollapsed = cell.isCollapsed(); const isCollapsed = cell.isCollapsed();
const childCount = cell.getChildCount(); const childCount = cell.getChildCount();
@ -451,7 +455,7 @@ class SwimlaneLayout extends GraphLayout {
} }
edges = edges.concat(cell.getEdges(true, true)); edges = edges.concat(cell.getEdges(true, true));
const result = new CellArray(); const result = [];
for (let i = 0; i < edges.length; i += 1) { for (let i = 0; i < edges.length; i += 1) {
const source = this.getVisibleTerminal(edges[i], true); const source = this.getVisibleTerminal(edges[i], true);
@ -462,7 +466,11 @@ class SwimlaneLayout extends GraphLayout {
(source !== target && (source !== target &&
((target === cell && ((target === cell &&
(this.parent == null || (this.parent == null ||
this.graph.isValidAncestor(<Cell>source, this.parent, this.traverseAncestors))) || this.graph.isValidAncestor(
<Cell>source,
this.parent,
this.traverseAncestors
))) ||
(source === cell && (source === cell &&
(this.parent == null || (this.parent == null ||
this.graph.isValidAncestor( this.graph.isValidAncestor(
@ -539,7 +547,7 @@ class SwimlaneLayout extends GraphLayout {
this.filterDescendants(this.swimlanes[i], filledVertexSet); this.filterDescendants(this.swimlanes[i], filledVertexSet);
} }
this.roots = new CellArray(); this.roots = [];
let filledVertexSetEmpty = true; let filledVertexSetEmpty = true;
// Poor man's isSetEmpty // Poor man's isSetEmpty
@ -599,21 +607,36 @@ class SwimlaneLayout extends GraphLayout {
} }
} else { } else {
// Find vertex set as directed traversal from roots // Find vertex set as directed traversal from roots
const roots = <CellArray>this.roots; const roots = this.roots as Cell[];
for (let i = 0; i < roots.length; i += 1) { for (let i = 0; i < roots.length; i += 1) {
const vertexSet = Object(); const vertexSet = Object();
hierarchyVertices.push(vertexSet); 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) { for (var key in allVertexSet) {
tmp.push(allVertexSet[key]); tmp.push(allVertexSet[key]);
} }
this.model = new SwimlaneModel(this, tmp, <CellArray>this.roots, parent, this.tightenToSource); this.model = new SwimlaneModel(
this,
tmp,
this.roots as Cell[],
parent,
this.tightenToSource
);
this.cycleStage(parent); this.cycleStage(parent);
this.layeringStage(); this.layeringStage();
@ -675,7 +698,7 @@ class SwimlaneLayout extends GraphLayout {
*/ */
getEdgesBetween(source: Cell, target: Cell, directed: boolean = false) { getEdgesBetween(source: Cell, target: Cell, directed: boolean = false) {
const edges = this.getEdges(source); const edges = this.getEdges(source);
const result = new CellArray(); const result = [];
// Checks if the edge is connected to the correct // Checks if the edge is connected to the correct
// cell and returns the first match // cell and returns the first match
@ -752,7 +775,7 @@ class SwimlaneLayout extends GraphLayout {
} }
let otherIndex = 0; let otherIndex = 0;
const swimlanes = <CellArray>this.swimlanes; const swimlanes = this.swimlanes as Cell[];
// Get the swimlane index of the other terminal // Get the swimlane index of the other terminal
for (otherIndex = 0; otherIndex < swimlanes.length; otherIndex++) { for (otherIndex = 0; otherIndex < swimlanes.length; otherIndex++) {

View File

@ -22,7 +22,6 @@ import Rectangle from '../geometry/Rectangle';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
/** /**
* @class SwimlaneManager * @class SwimlaneManager
@ -211,7 +210,7 @@ class SwimlaneManager extends EventSource {
* *
* @param cell Array of {@link Cell} that have been added. * @param cell Array of {@link Cell} that have been added.
*/ */
cellsAdded(cells: CellArray) { cellsAdded(cells: Cell[]) {
if (cells.length > 0) { if (cells.length > 0) {
const model = this.graph.getDataModel(); const model = this.graph.getDataModel();
@ -264,7 +263,7 @@ class SwimlaneManager extends EventSource {
* *
* @param cells Array of {@link Cell} whose size was changed. * @param cells Array of {@link Cell} whose size was changed.
*/ */
cellsResized(cells: CellArray) { cellsResized(cells: Cell[]) {
if (cells.length > 0) { if (cells.length > 0) {
const model = this.getGraph().getDataModel(); const model = this.getGraph().getDataModel();

View File

@ -18,7 +18,6 @@ limitations under the License.
import GraphAbstractHierarchyCell from './GraphAbstractHierarchyCell'; import GraphAbstractHierarchyCell from './GraphAbstractHierarchyCell';
import ObjectIdentity from '../../../util/ObjectIdentity'; import ObjectIdentity from '../../../util/ObjectIdentity';
import CellArray from '../../cell/CellArray';
import Cell from '../../cell/Cell'; import Cell from '../../cell/Cell';
import GraphHierarchyNode from './GraphHierarchyNode'; import GraphHierarchyNode from './GraphHierarchyNode';
@ -27,7 +26,7 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell {
* The graph edge(s) this object represents. Parallel edges are all grouped * The graph edge(s) this object represents. Parallel edges are all grouped
* together within one hierarchy edge. * together within one hierarchy edge.
*/ */
edges: CellArray; edges: Cell[];
/** /**
* The object identities of the wrapped cells * The object identities of the wrapped cells
@ -63,7 +62,7 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell {
* *
* edges - a list of real graph edges this abstraction represents * edges - a list of real graph edges this abstraction represents
*/ */
constructor(edges: CellArray) { constructor(edges: Cell[]) {
super(); super();
this.edges = edges; this.edges = edges;
this.ids = []; this.ids = [];
@ -114,7 +113,9 @@ class GraphHierarchyEdge extends GraphAbstractHierarchyCell {
this.previousLayerConnectedCells[i] = []; this.previousLayerConnectedCells[i] = [];
if (i === 0) { if (i === 0) {
this.previousLayerConnectedCells[i].push(this.target as GraphAbstractHierarchyCell); this.previousLayerConnectedCells[i].push(
this.target as GraphAbstractHierarchyCell
);
} else { } else {
this.previousLayerConnectedCells[i].push(this); this.previousLayerConnectedCells[i].push(this);
} }

View File

@ -109,14 +109,16 @@ class GraphHierarchyNode extends GraphAbstractHierarchyCell {
getPreviousLayerConnectedCells(layer: number): GraphAbstractHierarchyCell[] { getPreviousLayerConnectedCells(layer: number): GraphAbstractHierarchyCell[] {
if (this.previousLayerConnectedCells == null) { if (this.previousLayerConnectedCells == null) {
this.previousLayerConnectedCells = []; this.previousLayerConnectedCells = [];
this.previousLayerConnectedCells[0] = []; // new CellArray()?? this.previousLayerConnectedCells[0] = [];
for (let i = 0; i < this.connectsAsSource.length; i += 1) { for (let i = 0; i < this.connectsAsSource.length; i += 1) {
const edge = this.connectsAsSource[i]; const edge = this.connectsAsSource[i];
if (edge.minRank === -1 || edge.minRank === layer - 1) { if (edge.minRank === -1 || edge.minRank === layer - 1) {
// No dummy nodes in edge, add node of other side of edge // No dummy nodes in edge, add node of other side of edge
this.previousLayerConnectedCells[0].push(<GraphAbstractHierarchyCell>edge.target); this.previousLayerConnectedCells[0].push(
<GraphAbstractHierarchyCell>edge.target
);
} else { } else {
// Edge spans at least two layers, add edge // Edge spans at least two layers, add edge
this.previousLayerConnectedCells[0].push(edge); this.previousLayerConnectedCells[0].push(edge);

View File

@ -20,7 +20,6 @@ import Dictionary from '../../../util/Dictionary';
import GraphHierarchyNode from '../datatypes/GraphHierarchyNode'; import GraphHierarchyNode from '../datatypes/GraphHierarchyNode';
import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge'; import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge';
import Cell from '../../cell/Cell'; import Cell from '../../cell/Cell';
import CellArray from '../../cell/CellArray';
import HierarchicalLayout from '../HierarchicalLayout'; import HierarchicalLayout from '../HierarchicalLayout';
import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell'; import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell';
@ -49,8 +48,8 @@ import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell'
class GraphHierarchyModel { class GraphHierarchyModel {
constructor( constructor(
layout: HierarchicalLayout, layout: HierarchicalLayout,
vertices: CellArray, vertices: Cell[],
roots: CellArray, roots: Cell[],
parent: Cell, parent: Cell,
tightenToSource: boolean tightenToSource: boolean
) { ) {
@ -146,7 +145,7 @@ class GraphHierarchyModel {
* Store of roots of this hierarchy model, these are real graph cells, not * Store of roots of this hierarchy model, these are real graph cells, not
* internal cells * internal cells
*/ */
roots: CellArray | null = null; roots: Cell[] | null = null;
/** /**
* The parent cell whose children are being laid out * The parent cell whose children are being laid out
@ -180,7 +179,7 @@ class GraphHierarchyModel {
*/ */
createInternalCells( createInternalCells(
layout: HierarchicalLayout, layout: HierarchicalLayout,
vertices: CellArray, vertices: Cell[],
internalVertices: { [key: number]: GraphHierarchyNode } internalVertices: { [key: number]: GraphHierarchyNode }
) { ) {
const graph = layout.getGraph(); const graph = layout.getGraph();
@ -392,7 +391,7 @@ class GraphHierarchyModel {
* to create dummy nodes for edges that cross layers. * to create dummy nodes for edges that cross layers.
*/ */
fixRanks(): void { fixRanks(): void {
// TODO: Should this be a CellArray? // TODO: Should this be a Cell[]?
const rankList: { [key: number]: GraphAbstractHierarchyCell[] } = {}; const rankList: { [key: number]: GraphAbstractHierarchyCell[] } = {};
this.ranks = []; this.ranks = [];
@ -418,7 +417,13 @@ class GraphHierarchyModel {
} }
this.visit( 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) { if (seen == 0 && node.maxRank < 0 && node.minRank < 0) {
rankList[node.temp[0]].push(node); rankList[node.temp[0]].push(node);
node.maxRank = node.temp[0]; node.maxRank = node.temp[0];

View File

@ -16,14 +16,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import GraphHierarchyNode from "../datatypes/GraphHierarchyNode"; import GraphHierarchyNode from '../datatypes/GraphHierarchyNode';
import GraphHierarchyEdge from "../datatypes/GraphHierarchyEdge"; import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge';
import CellPath from "../../cell/CellPath"; import CellPath from '../../cell/CellPath';
import Dictionary from "../../../util/Dictionary"; import Dictionary from '../../../util/Dictionary';
import CellArray from "../../cell/CellArray"; import Cell from '../../cell/Cell';
import Cell from "../../cell/Cell"; import { clone } from '../../../util/cloneUtils';
import { clone } from "../../../util/cloneUtils"; import SwimlaneLayout from '../SwimlaneLayout';
import SwimlaneLayout from "../SwimlaneLayout";
/** /**
* Internal model of a hierarchical graph. This model stores nodes and edges * Internal model of a hierarchical graph. This model stores nodes and edges
@ -50,8 +49,8 @@ import SwimlaneLayout from "../SwimlaneLayout";
class SwimlaneModel { class SwimlaneModel {
constructor( constructor(
layout: SwimlaneLayout, layout: SwimlaneLayout,
vertices: CellArray, vertices: Cell[],
roots: CellArray, roots: Cell[],
parent: Cell, parent: Cell,
tightenToSource: boolean tightenToSource: boolean
) { ) {
@ -103,10 +102,7 @@ class SwimlaneModel {
internalTargetCell = <GraphHierarchyNode>this.vertexMapper.get(targetCell); internalTargetCell = <GraphHierarchyNode>this.vertexMapper.get(targetCell);
} }
if ( if (internalTargetCell != null && internalVertices[i] !== internalTargetCell) {
internalTargetCell != null &&
internalVertices[i] !== internalTargetCell
) {
internalEdge.target = internalTargetCell; internalEdge.target = internalTargetCell;
if (internalTargetCell.connectsAsTarget.length == 0) { if (internalTargetCell.connectsAsTarget.length == 0) {
@ -150,7 +146,7 @@ class SwimlaneModel {
* Store of roots of this hierarchy model, these are real graph cells, not * Store of roots of this hierarchy model, these are real graph cells, not
* internal cells * internal cells
*/ */
roots: CellArray; roots: Cell[];
/** /**
* The parent cell whose children are being laid out * The parent cell whose children are being laid out
@ -189,11 +185,11 @@ class SwimlaneModel {
*/ */
createInternalCells( createInternalCells(
layout: SwimlaneLayout, layout: SwimlaneLayout,
vertices: CellArray, vertices: Cell[],
internalVertices: GraphHierarchyNode[] internalVertices: GraphHierarchyNode[]
): void { ): void {
const graph = layout.getGraph(); const graph = layout.getGraph();
const swimlanes = <CellArray>layout.swimlanes; const swimlanes = layout.swimlanes as Cell[];
// Create internal edges // Create internal edges
for (let i = 0; i < vertices.length; i += 1) { for (let i = 0; i < vertices.length; i += 1) {
@ -220,11 +216,7 @@ class SwimlaneModel {
const cell = <Cell>layout.getVisibleTerminal(conns[j], false); const cell = <Cell>layout.getVisibleTerminal(conns[j], false);
// Looking for outgoing edges only // Looking for outgoing edges only
if ( if (cell !== vertices[i] && cell.isVertex() && !layout.isVertexIgnored(cell)) {
cell !== vertices[i] &&
cell.isVertex() &&
!layout.isVertexIgnored(cell)
) {
// We process all edge between this source and its targets // We process all edge between this source and its targets
// If there are edges going both ways, we need to collect // If there are edges going both ways, we need to collect
// them all into one internal edges to avoid looping problems // them all into one internal edges to avoid looping problems
@ -238,11 +230,7 @@ class SwimlaneModel {
// are the same. All the graph edges will have been assigned to // 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 // an internal edge going the other way, so we don't want to
// process them again // process them again
const undirectedEdges = layout.getEdgesBetween( const undirectedEdges = layout.getEdgesBetween(vertices[i], cell, false);
vertices[i],
cell,
false
);
const directedEdges = layout.getEdgesBetween(vertices[i], cell, true); const directedEdges = layout.getEdgesBetween(vertices[i], cell, true);
if ( if (
@ -269,9 +257,7 @@ class SwimlaneModel {
internalEdge.source = internalVertices[i]; internalEdge.source = internalVertices[i];
if ( if (internalVertices[i].connectsAsSource.indexOf(internalEdge) < 0) {
internalVertices[i].connectsAsSource.indexOf(internalEdge) < 0
) {
internalVertices[i].connectsAsSource.push(internalEdge); internalVertices[i].connectsAsSource.push(internalEdge);
} }
} }
@ -468,10 +454,7 @@ class SwimlaneModel {
const slIndex = <number>root.swimlaneIndex; const slIndex = <number>root.swimlaneIndex;
const ranksPerGroup = <{ [key: number]: number }>this.ranksPerGroup; const ranksPerGroup = <{ [key: number]: number }>this.ranksPerGroup;
if ( if (ranksPerGroup[slIndex] == null || ranksPerGroup[slIndex] < chainCount) {
ranksPerGroup[slIndex] == null ||
ranksPerGroup[slIndex] < chainCount
) {
ranksPerGroup[slIndex] = chainCount; ranksPerGroup[slIndex] = chainCount;
} }
@ -486,13 +469,7 @@ class SwimlaneModel {
// Only navigate in source->target direction within the same // Only navigate in source->target direction within the same
// swimlane, or from a lower index swimlane to a higher one // swimlane, or from a lower index swimlane to a higher one
if (<number>root.swimlaneIndex < <number>targetNode.swimlaneIndex) { if (<number>root.swimlaneIndex < <number>targetNode.swimlaneIndex) {
this.maxChainDfs( this.maxChainDfs(root, targetNode, internalEdge, clone(seen, null, true), 0);
root,
targetNode,
internalEdge,
clone(seen, null, true),
0
);
} else if (root.swimlaneIndex === targetNode.swimlaneIndex) { } else if (root.swimlaneIndex === targetNode.swimlaneIndex) {
this.maxChainDfs( this.maxChainDfs(
root, root,
@ -537,7 +514,13 @@ class SwimlaneModel {
} }
this.visit( 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) { if (seen === 0 && node.maxRank < 0 && node.minRank < 0) {
rankList[node.temp[0]].push(node); rankList[node.temp[0]].push(node);
node.maxRank = node.temp[0]; node.maxRank = node.temp[0];

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import { import {
contains, contains,
@ -47,6 +46,7 @@ import Point from '../geometry/Point';
import { htmlEntities } from '../../util/StringUtils'; import { htmlEntities } from '../../util/StringUtils';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import { cloneCells, getTopmostCells } from '../../util/cellArrayUtils';
import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../../types'; import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../../types';
@ -66,12 +66,12 @@ declare module '../Graph' {
extendParentsOnAdd: boolean; extendParentsOnAdd: boolean;
extendParentsOnMove: boolean; extendParentsOnMove: boolean;
getBoundingBox: (cells: CellArray) => Rectangle | null; getBoundingBox: (cells: Cell[]) => Rectangle | null;
removeStateForCell: (cell: Cell) => void; removeStateForCell: (cell: Cell) => void;
getCurrentCellStyle: (cell: Cell, ignoreState?: boolean) => CellStateStyle; getCurrentCellStyle: (cell: Cell, ignoreState?: boolean) => CellStateStyle;
getCellStyle: (cell: Cell) => CellStateStyle; getCellStyle: (cell: Cell) => CellStateStyle;
postProcessCellStyle: (style: CellStateStyle) => CellStateStyle; postProcessCellStyle: (style: CellStateStyle) => CellStateStyle;
setCellStyle: (style: CellStyle, cells: CellArray) => void; setCellStyle: (style: CellStyle, cells: Cell[]) => void;
toggleCellStyle: ( toggleCellStyle: (
key: keyof CellStateStyle, key: keyof CellStateStyle,
defaultValue: boolean, defaultValue: boolean,
@ -80,25 +80,25 @@ declare module '../Graph' {
toggleCellStyles: ( toggleCellStyles: (
key: keyof CellStateStyle, key: keyof CellStateStyle,
defaultValue: boolean, defaultValue: boolean,
cells: CellArray cells: Cell[]
) => boolean | null; ) => boolean | null;
setCellStyles: ( setCellStyles: (
key: keyof CellStateStyle, key: keyof CellStateStyle,
value: CellStateStyle[keyof CellStateStyle], value: CellStateStyle[keyof CellStateStyle],
cells?: CellArray cells?: Cell[]
) => void; ) => void;
toggleCellStyleFlags: ( toggleCellStyleFlags: (
key: NumericCellStateStyleKeys, key: NumericCellStateStyleKeys,
flag: number, flag: number,
cells?: CellArray | null cells?: Cell[] | null
) => void; ) => void;
setCellStyleFlags: ( setCellStyleFlags: (
key: NumericCellStateStyleKeys, key: NumericCellStateStyleKeys,
flag: number, flag: number,
value?: boolean | null, value?: boolean | null,
cells?: CellArray | null cells?: Cell[] | null
) => void; ) => void;
alignCells: (align: string, cells?: CellArray, param?: number | null) => void; alignCells: (align: string, cells?: Cell[], param?: number | null) => void;
cloneCell: ( cloneCell: (
cell: Cell, cell: Cell,
allowInvalidEdges?: boolean, allowInvalidEdges?: boolean,
@ -106,11 +106,11 @@ declare module '../Graph' {
keepPosition?: boolean keepPosition?: boolean
) => Cell; ) => Cell;
cloneCells: ( cloneCells: (
cells: CellArray, cells: Cell[],
allowInvalidEdges: boolean, allowInvalidEdges?: boolean,
mapping: any, mapping?: any,
keepPosition?: boolean keepPosition?: boolean
) => CellArray; ) => Cell[];
addCell: ( addCell: (
cell: Cell, cell: Cell,
parent: Cell | null, parent: Cell | null,
@ -119,15 +119,15 @@ declare module '../Graph' {
target?: Cell | null target?: Cell | null
) => Cell; ) => Cell;
addCells: ( addCells: (
cells: CellArray, cells: Cell[],
parent: Cell | null, parent: Cell | null,
index: number | null, index: number | null,
source: Cell | null, source: Cell | null,
target: Cell | null, target: Cell | null,
absolute?: boolean absolute?: boolean
) => CellArray; ) => Cell[];
cellsAdded: ( cellsAdded: (
cells: CellArray, cells: Cell[],
parent: Cell, parent: Cell,
index: number, index: number,
source: Cell | null, source: Cell | null,
@ -137,16 +137,16 @@ declare module '../Graph' {
extend?: boolean extend?: boolean
) => void; ) => void;
autoSizeCell: (cell: Cell, recurse?: boolean) => void; autoSizeCell: (cell: Cell, recurse?: boolean) => void;
removeCells: (cells?: CellArray | null, includeEdges?: boolean | null) => CellArray; removeCells: (cells?: Cell[] | null, includeEdges?: boolean | null) => Cell[];
cellsRemoved: (cells: CellArray) => void; cellsRemoved: (cells: Cell[]) => void;
toggleCells: (show: boolean, cells: CellArray, includeEdges: boolean) => CellArray; toggleCells: (show: boolean, cells: Cell[], includeEdges: boolean) => Cell[];
cellsToggled: (cells: CellArray, show: boolean) => void; cellsToggled: (cells: Cell[], show: boolean) => void;
updateCellSize: (cell: Cell, ignoreChildren?: boolean) => Cell; updateCellSize: (cell: Cell, ignoreChildren?: boolean) => Cell;
cellSizeUpdated: (cell: Cell, ignoreChildren: boolean) => void; cellSizeUpdated: (cell: Cell, ignoreChildren: boolean) => void;
getPreferredSizeForCell: (cell: Cell, textWidth?: number | null) => Rectangle | null; getPreferredSizeForCell: (cell: Cell, textWidth?: number | null) => Rectangle | null;
resizeCell: (cell: Cell, bounds: Rectangle, recurse?: boolean) => Cell; resizeCell: (cell: Cell, bounds: Rectangle, recurse?: boolean) => Cell;
resizeCells: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => CellArray; resizeCells: (cells: Cell[], bounds: Rectangle[], recurse: boolean) => Cell[];
cellsResized: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => void; cellsResized: (cells: Cell[], bounds: Rectangle[], recurse: boolean) => void;
cellResized: ( cellResized: (
cell: Cell, cell: Cell,
bounds: Rectangle, bounds: Rectangle,
@ -158,24 +158,24 @@ declare module '../Graph' {
scaleCell: (cell: Cell, dx: number, dy: number, recurse: boolean) => void; scaleCell: (cell: Cell, dx: number, dy: number, recurse: boolean) => void;
extendParent: (cell: Cell) => void; extendParent: (cell: Cell) => void;
importCells: ( importCells: (
cells: CellArray, cells: Cell[],
dx: number, dx: number,
dy: number, dy: number,
target: Cell | null, target?: Cell | null,
evt: MouseEvent | null, evt?: MouseEvent | null,
mapping: any mapping?: any
) => CellArray; ) => Cell[];
moveCells: ( moveCells: (
cells: CellArray, cells: Cell[],
dx: number, dx: number,
dy: number, dy: number,
clone?: boolean, clone?: boolean,
target?: Cell | null, target?: Cell | null,
evt?: MouseEvent | null, evt?: MouseEvent | null,
mapping?: any mapping?: any
) => CellArray; ) => Cell[];
cellsMoved: ( cellsMoved: (
cells: CellArray, cells: Cell[],
dx: number, dx: number,
dy: number, dy: number,
disconnect: boolean, disconnect: boolean,
@ -185,11 +185,7 @@ declare module '../Graph' {
translateCell: (cell: Cell, dx: number, dy: number) => void; translateCell: (cell: Cell, dx: number, dy: number) => void;
getCellContainmentArea: (cell: Cell) => Rectangle | null; getCellContainmentArea: (cell: Cell) => Rectangle | null;
constrainChild: (cell: Cell, sizeFirst?: boolean) => void; constrainChild: (cell: Cell, sizeFirst?: boolean) => void;
getChildCells: ( getChildCells: (parent?: Cell | null, vertices?: boolean, edges?: boolean) => Cell[];
parent?: Cell | null,
vertices?: boolean,
edges?: boolean
) => CellArray;
getCellAt: ( getCellAt: (
x: number, x: number,
y: number, y: number,
@ -204,40 +200,40 @@ declare module '../Graph' {
width: number, width: number,
height: number, height: number,
parent?: Cell | null, parent?: Cell | null,
result?: CellArray, result?: Cell[],
intersection?: Rectangle | null, intersection?: Rectangle | null,
ignoreFn?: Function | null, ignoreFn?: Function | null,
includeDescendants?: boolean includeDescendants?: boolean
) => CellArray; ) => Cell[];
getCellsBeyond: ( getCellsBeyond: (
x0: number, x0: number,
y0: number, y0: number,
parent: Cell | null, parent: Cell | null,
rightHalfpane: boolean, rightHalfpane: boolean,
bottomHalfpane: boolean bottomHalfpane: boolean
) => CellArray; ) => Cell[];
intersects: (state: CellState, x: number, y: number) => boolean; intersects: (state: CellState, x: number, y: number) => boolean;
isValidAncestor: (cell: Cell, parent: Cell, recurse: boolean) => boolean; isValidAncestor: (cell: Cell, parent: Cell, recurse: boolean) => boolean;
isCellLocked: (cell: Cell) => boolean; isCellLocked: (cell: Cell) => boolean;
isCellsLocked: () => boolean; isCellsLocked: () => boolean;
setCellsLocked: (value: boolean) => void; setCellsLocked: (value: boolean) => void;
getCloneableCells: (cells: CellArray) => CellArray; getCloneableCells: (cells: Cell[]) => Cell[];
isCellCloneable: (cell: Cell) => boolean; isCellCloneable: (cell: Cell) => boolean;
isCellsCloneable: () => boolean; isCellsCloneable: () => boolean;
setCellsCloneable: (value: boolean) => void; setCellsCloneable: (value: boolean) => void;
getExportableCells: (cells: CellArray) => CellArray; getExportableCells: (cells: Cell[]) => Cell[];
canExportCell: (cell: Cell | null) => boolean; canExportCell: (cell: Cell | null) => boolean;
getImportableCells: (cells: CellArray) => CellArray; getImportableCells: (cells: Cell[]) => Cell[];
canImportCell: (cell: Cell | null) => boolean; canImportCell: (cell: Cell | null) => boolean;
isCellSelectable: (cell: Cell) => boolean; isCellSelectable: (cell: Cell) => boolean;
isCellsSelectable: () => boolean; isCellsSelectable: () => boolean;
setCellsSelectable: (value: boolean) => void; setCellsSelectable: (value: boolean) => void;
getDeletableCells: (cells: CellArray) => CellArray; getDeletableCells: (cells: Cell[]) => Cell[];
isCellDeletable: (cell: Cell) => boolean; isCellDeletable: (cell: Cell) => boolean;
isCellsDeletable: () => boolean; isCellsDeletable: () => boolean;
setCellsDeletable: (value: boolean) => void; setCellsDeletable: (value: boolean) => void;
isCellRotatable: (cell: Cell) => boolean; isCellRotatable: (cell: Cell) => boolean;
getMovableCells: (cells: CellArray) => CellArray; getMovableCells: (cells: Cell[]) => Cell[];
isCellMovable: (cell: Cell) => boolean; isCellMovable: (cell: Cell) => boolean;
isCellsMovable: () => boolean; isCellsMovable: () => boolean;
setCellsMovable: (value: boolean) => void; setCellsMovable: (value: boolean) => void;
@ -264,7 +260,7 @@ declare module '../Graph' {
includeDescendants?: boolean includeDescendants?: boolean
) => Rectangle | null; ) => Rectangle | null;
getBoundingBoxFromGeometry: ( getBoundingBoxFromGeometry: (
cells: CellArray, cells: Cell[],
includeEdges?: boolean includeEdges?: boolean
) => Rectangle | null; ) => Rectangle | null;
} }
@ -660,7 +656,7 @@ export const CellsMixin: PartialType = {
*/ */
toggleCellStyle(key, defaultValue = false, cell?) { toggleCellStyle(key, defaultValue = false, cell?) {
cell = cell ?? this.getSelectionCell(); cell = cell ?? this.getSelectionCell();
return this.toggleCellStyles(key, defaultValue, new CellArray(cell)); return this.toggleCellStyles(key, defaultValue, [cell]);
}, },
/** /**
@ -807,14 +803,14 @@ export const CellsMixin: PartialType = {
this.batchUpdate(() => { this.batchUpdate(() => {
const p = param as number; const p = param as number;
for (const cell of <CellArray>cells) { for (const cell of cells as Cell[]) {
const state = this.getView().getState(cell); const state = this.getView().getState(cell);
if (state != null) { if (state != null) {
let geo = cell.getGeometry(); let geo = cell.getGeometry();
if (geo != null && !cell.isEdge()) { if (geo != null && !cell.isEdge()) {
geo = <Geometry>geo.clone(); geo = geo.clone();
if (align === ALIGN.CENTER) { if (align === ALIGN.CENTER) {
geo.x += (p - state.x - state.width / 2) / s; geo.x += (p - state.x - state.width / 2) / s;
@ -857,14 +853,8 @@ export const CellsMixin: PartialType = {
* @param keepPosition Optional boolean indicating if the position of the cells should * @param keepPosition Optional boolean indicating if the position of the cells should
* be updated to reflect the lost parent cell. Default is `false`. * 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) { cloneCell(cell, allowInvalidEdges = false, mapping = null, keepPosition = false) {
return this.cloneCells( return this.cloneCells([cell], allowInvalidEdges, mapping, keepPosition)[0];
new CellArray(cell),
allowInvalidEdges,
mapping,
keepPosition
)[0];
}, },
/** /**
@ -880,9 +870,8 @@ export const CellsMixin: PartialType = {
* @param keepPosition Optional boolean indicating if the position of the cells should * @param keepPosition Optional boolean indicating if the position of the cells should
* be updated to reflect the lost parent cell. Default is `false`. * 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) { cloneCells(cells, allowInvalidEdges = true, mapping = {}, keepPosition = false) {
let clones; let clones: Cell[];
// Creates a dictionary for fast lookups // Creates a dictionary for fast lookups
const dict = new Dictionary<Cell, boolean>(); const dict = new Dictionary<Cell, boolean>();
@ -896,8 +885,8 @@ export const CellsMixin: PartialType = {
if (tmp.length > 0) { if (tmp.length > 0) {
const { scale } = this.getView(); const { scale } = this.getView();
const trans = this.getView().translate; const trans = this.getView().translate;
const out: CellArray = new CellArray(); const out: Cell[] = [];
clones = cells.cloneCells(true, mapping); clones = cloneCells(true, mapping)(cells);
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
const cell = cells[i]; const cell = cells[i];
@ -976,7 +965,7 @@ export const CellsMixin: PartialType = {
} }
clones = out; clones = out;
} else { } else {
clones = new CellArray(); clones = [];
} }
return clones; return clones;
}, },
@ -994,7 +983,7 @@ export const CellsMixin: PartialType = {
* @param target Optional {@link Cell} that represents the target terminal. * @param target Optional {@link Cell} that represents the target terminal.
*/ */
addCell(cell, parent = null, index = null, source = null, target = null) { 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];
}, },
/** /**
@ -1196,13 +1185,13 @@ export const CellsMixin: PartialType = {
} }
this.batchUpdate(() => { this.batchUpdate(() => {
this.cellsRemoved(<CellArray>cells); this.cellsRemoved(cells as Cell[]);
this.fireEvent( this.fireEvent(
new EventObject(InternalEvent.REMOVE_CELLS, { cells, includeEdges }) new EventObject(InternalEvent.REMOVE_CELLS, { cells, includeEdges })
); );
}); });
return cells ?? new CellArray(); return cells ?? [];
}, },
/** /**
@ -1226,7 +1215,7 @@ export const CellsMixin: PartialType = {
for (const cell of cells) { for (const cell of cells) {
// Disconnects edges which are not being removed // 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) => { const disconnectTerminal = (edge: Cell, source: boolean) => {
let geo = edge.getGeometry(); let geo = edge.getGeometry();
@ -1447,7 +1436,7 @@ export const CellsMixin: PartialType = {
} }
} }
this.cellsResized(new CellArray(cell), [geo], false); this.cellsResized([cell], [geo], false);
} }
}); });
}, },
@ -1567,7 +1556,7 @@ export const CellsMixin: PartialType = {
* @param bounds {@link mxRectangle} that represents the new bounds. * @param bounds {@link mxRectangle} that represents the new bounds.
*/ */
resizeCell(cell, bounds, recurse = false) { resizeCell(cell, bounds, recurse = false) {
return this.resizeCells(new CellArray(cell), [bounds], recurse)[0]; return this.resizeCells([cell], [bounds], recurse)[0];
}, },
/** /**
@ -1578,7 +1567,7 @@ export const CellsMixin: PartialType = {
* @param cells Array of {@link Cell} whose bounds should be changed. * @param cells Array of {@link Cell} whose bounds should be changed.
* @param bounds Array of {@link mxRectangles} that represent the new bounds. * @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(); recurse = recurse ?? this.isRecursiveResize();
this.batchUpdate(() => { this.batchUpdate(() => {
@ -1821,7 +1810,7 @@ export const CellsMixin: PartialType = {
p.width = Math.max(p.width, geo.x + geo.width); p.width = Math.max(p.width, geo.x + geo.width);
p.height = Math.max(p.height, geo.y + geo.height); p.height = Math.max(p.height, geo.y + geo.height);
this.cellsResized(new CellArray(parent), [p], false); this.cellsResized([parent], [p], false);
} }
} }
}, },
@ -1878,7 +1867,7 @@ export const CellsMixin: PartialType = {
) { ) {
if (dx !== 0 || dy !== 0 || clone || target) { if (dx !== 0 || dy !== 0 || clone || target) {
// Removes descendants with ancestors in cells to avoid multiple moving // Removes descendants with ancestors in cells to avoid multiple moving
cells = cells.getTopmostCells(); cells = getTopmostCells(cells);
const origCells = cells; const origCells = cells;
this.batchUpdate(() => { this.batchUpdate(() => {
@ -1901,7 +1890,7 @@ export const CellsMixin: PartialType = {
}; };
// Removes relative edge labels with selected terminals // Removes relative edge labels with selected terminals
const checked = new CellArray(); const checked = [];
for (const cell of cells) { for (const cell of cells) {
const geo = cell.getGeometry(); const geo = cell.getGeometry();
@ -2137,7 +2126,7 @@ export const CellsMixin: PartialType = {
// Finds parent offset // Finds parent offset
if (max && parent) { if (max && parent) {
const off = this.getBoundingBoxFromGeometry(new CellArray(parent), false); const off = this.getBoundingBoxFromGeometry([parent], false);
if (off) { if (off) {
max = Rectangle.fromRectangle(max); max = Rectangle.fromRectangle(max);
@ -2173,7 +2162,7 @@ export const CellsMixin: PartialType = {
} }
if (max) { if (max) {
const cells = new CellArray(cell); const cells = [cell];
if (!cell.isCollapsed()) { if (!cell.isCollapsed()) {
const desc = cell.getDescendants(); const desc = cell.getDescendants();
@ -2260,7 +2249,7 @@ export const CellsMixin: PartialType = {
parent = parent ?? this.getDefaultParent(); parent = parent ?? this.getDefaultParent();
const cells = parent.getChildCells(vertices, edges); const cells = parent.getChildCells(vertices, edges);
const result = new CellArray(); const result = [];
// Filters out the non-visible child cells // Filters out the non-visible child cells
for (const cell of cells) { for (const cell of cells) {
@ -2348,7 +2337,7 @@ export const CellsMixin: PartialType = {
width, width,
height, height,
parent = null, parent = null,
result = new CellArray(), result = [],
intersection = null, intersection = null,
ignoreFn = null, ignoreFn = null,
includeDescendants = false includeDescendants = false
@ -2444,7 +2433,7 @@ export const CellsMixin: PartialType = {
} }
} }
} }
return new CellArray(...result); return result;
}, },
/** /**
@ -2937,7 +2926,7 @@ export const CellsMixin: PartialType = {
* of all descendants should be included. Default is `false`. * of all descendants should be included. Default is `false`.
*/ */
getCellBounds(cell, includeEdges = false, includeDescendants = false) { getCellBounds(cell, includeEdges = false, includeDescendants = false) {
let cells = new CellArray(cell); let cells = [cell];
// Includes all connected edges // Includes all connected edges
if (includeEdges) { if (includeEdges) {
@ -3039,7 +3028,7 @@ export const CellsMixin: PartialType = {
if (geo.relative && parent) { if (geo.relative && parent) {
if (parent.isVertex() && parent !== this.getView().currentRoot) { if (parent.isVertex() && parent !== this.getView().currentRoot) {
tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false); tmp = this.getBoundingBoxFromGeometry([parent], false);
if (tmp) { if (tmp) {
bbox = new Rectangle( bbox = new Rectangle(
@ -3059,7 +3048,7 @@ export const CellsMixin: PartialType = {
bbox = Rectangle.fromRectangle(geo); bbox = Rectangle.fromRectangle(geo);
if (parent && parent.isVertex() && cells.indexOf(parent) >= 0) { if (parent && parent.isVertex() && cells.indexOf(parent) >= 0) {
tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false); tmp = this.getBoundingBoxFromGeometry([parent], false);
if (tmp) { if (tmp) {
bbox.x += tmp.x; bbox.x += tmp.x;

View File

@ -23,7 +23,6 @@ import { DIRECTION } from '../../util/Constants';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import { getRotatedPoint, toRadians } from '../../util/mathUtils'; import { getRotatedPoint, toRadians } from '../../util/mathUtils';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import Dictionary from '../../util/Dictionary'; import Dictionary from '../../util/Dictionary';
@ -74,8 +73,8 @@ declare module '../Graph' {
source: boolean, source: boolean,
constraint?: ConnectionConstraint | null constraint?: ConnectionConstraint | null
) => void; ) => void;
disconnectGraph: (cells: CellArray) => void; disconnectGraph: (cells: Cell[]) => void;
getConnections: (cell: Cell, parent?: Cell | null) => CellArray; getConnections: (cell: Cell, parent?: Cell | null) => Cell[];
isConstrainChild: (cell: Cell) => boolean; isConstrainChild: (cell: Cell) => boolean;
isConstrainChildren: () => boolean; isConstrainChildren: () => boolean;
setConstrainChildren: (value: boolean) => void; setConstrainChildren: (value: boolean) => void;
@ -308,50 +307,22 @@ const ConnectionsMixin: PartialType = {
if (constraint) { if (constraint) {
this.batchUpdate(() => { this.batchUpdate(() => {
if (!constraint || !constraint.point) { if (!constraint || !constraint.point) {
this.setCellStyles(source ? 'exitX' : 'entryX', null, new CellArray(edge)); this.setCellStyles(source ? 'exitX' : 'entryX', null, [edge]);
this.setCellStyles(source ? 'exitY' : 'entryY', null, new CellArray(edge)); this.setCellStyles(source ? 'exitY' : 'entryY', null, [edge]);
this.setCellStyles(source ? 'exitDx' : 'entryDx', null, new CellArray(edge)); this.setCellStyles(source ? 'exitDx' : 'entryDx', null, [edge]);
this.setCellStyles(source ? 'exitDy' : 'entryDy', null, new CellArray(edge)); this.setCellStyles(source ? 'exitDy' : 'entryDy', null, [edge]);
this.setCellStyles( this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', null, [edge]);
source ? 'exitPerimeter' : 'entryPerimeter',
null,
new CellArray(edge)
);
} else if (constraint.point) { } else if (constraint.point) {
this.setCellStyles( this.setCellStyles(source ? 'exitX' : 'entryX', constraint.point.x, [edge]);
source ? 'exitX' : 'entryX', this.setCellStyles(source ? 'exitY' : 'entryY', constraint.point.y, [edge]);
constraint.point.x, this.setCellStyles(source ? 'exitDx' : 'entryDx', constraint.dx, [edge]);
new CellArray(edge) this.setCellStyles(source ? 'exitDy' : 'entryDy', constraint.dy, [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)
);
// Only writes 0 since 1 is default // Only writes 0 since 1 is default
if (!constraint.perimeter) { if (!constraint.perimeter) {
this.setCellStyles( this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', '0', [edge]);
source ? 'exitPerimeter' : 'entryPerimeter',
'0',
new CellArray(edge)
);
} else { } else {
this.setCellStyles( this.setCellStyles(source ? 'exitPerimeter' : 'entryPerimeter', null, [edge]);
source ? 'exitPerimeter' : 'entryPerimeter',
null,
new CellArray(edge)
);
} }
} }
}); });
@ -519,7 +490,7 @@ const ConnectionsMixin: PartialType = {
// Sets or resets all previous information for connecting to a child port // Sets or resets all previous information for connecting to a child port
const key = source ? 'sourcePort' : 'targetPort'; const key = source ? 'sourcePort' : 'targetPort';
this.setCellStyles(key, id, new CellArray(edge)); this.setCellStyles(key, id, [edge]);
} }
this.getDataModel().setTerminal(edge, terminal, source); this.getDataModel().setTerminal(edge, terminal, source);

View File

@ -16,7 +16,6 @@ limitations under the License.
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
declare module '../Graph' { declare module '../Graph' {
@ -32,7 +31,7 @@ declare module '../Graph' {
setDropEnabled: (value: boolean) => void; setDropEnabled: (value: boolean) => void;
isSplitEnabled: () => boolean; isSplitEnabled: () => boolean;
setSplitEnabled: (value: boolean) => void; setSplitEnabled: (value: boolean) => void;
isSplitTarget: (target: Cell, cells?: CellArray, evt?: MouseEvent | null) => boolean; isSplitTarget: (target: Cell, cells?: Cell[], evt?: MouseEvent | null) => boolean;
} }
} }
@ -149,7 +148,7 @@ const DragDropMixin: PartialType = {
* @param cells {@link mxCell} that should split the edge. * @param cells {@link mxCell} that should split the edge.
* @param evt Mouseevent that triggered the invocation. * @param evt Mouseevent that triggered the invocation.
*/ */
isSplitTarget(target, cells=new CellArray(), evt) { isSplitTarget(target, cells = [], evt) {
if ( if (
target.isEdge() && target.isEdge() &&
cells.length === 1 && cells.length === 1 &&

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import { removeDuplicates } from '../../util/arrayUtils'; import { removeDuplicates } from '../../util/arrayUtils';
import { findNearestSegment } from '../../util/mathUtils'; import { findNearestSegment } from '../../util/mathUtils';
@ -52,7 +51,7 @@ declare module '../Graph' {
flipEdge: (edge: Cell) => Cell; flipEdge: (edge: Cell) => Cell;
splitEdge: ( splitEdge: (
edge: Cell, edge: Cell,
cells: CellArray, cells: Cell[],
newEdge: Cell | null, newEdge: Cell | null,
dx?: number, dx?: number,
dy?: number, dy?: number,
@ -76,10 +75,10 @@ declare module '../Graph' {
target: Cell | null, target: Cell | null,
index?: number | null index?: number | null
) => Cell; ) => Cell;
addAllEdges: (cells: CellArray) => CellArray; addAllEdges: (cells: Cell[]) => Cell[];
getAllEdges: (cells: CellArray | null) => CellArray; getAllEdges: (cells: Cell[] | null) => Cell[];
getIncomingEdges: (cell: Cell, parent: Cell | null) => CellArray; getIncomingEdges: (cell: Cell, parent: Cell | null) => Cell[];
getOutgoingEdges: (cell: Cell, parent: Cell | null) => CellArray; getOutgoingEdges: (cell: Cell, parent: Cell | null) => Cell[];
getEdges: ( getEdges: (
cell: Cell, cell: Cell,
parent?: Cell | null, parent?: Cell | null,
@ -87,10 +86,10 @@ declare module '../Graph' {
outgoing?: boolean, outgoing?: boolean,
includeLoops?: boolean, includeLoops?: boolean,
recurse?: boolean recurse?: boolean
) => CellArray; ) => Cell[];
getChildEdges: (parent: Cell) => CellArray; getChildEdges: (parent: Cell) => Cell[];
getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => CellArray; getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => Cell[];
resetEdges: (cells: CellArray) => void; resetEdges: (cells: Cell[]) => void;
resetEdge: (edge: Cell) => Cell; resetEdge: (edge: Cell) => Cell;
} }
} }
@ -385,7 +384,7 @@ const EdgeMixin: PartialType = {
true true
); );
this.cellsAdded( this.cellsAdded(
new CellArray(newEdge), [newEdge],
parent as Cell, parent as Cell,
parent ? parent.getChildCount() : 0, parent ? parent.getChildCount() : 0,
source, source,
@ -492,14 +491,14 @@ const EdgeMixin: PartialType = {
*/ */
addAllEdges(cells) { addAllEdges(cells) {
const allCells = cells.slice(); 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. * Returns all edges connected to the given cells or its descendants.
*/ */
getAllEdges(cells) { getAllEdges(cells) {
let edges: CellArray = new CellArray(); let edges: Cell[] = [];
if (cells) { if (cells) {
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
@ -571,7 +570,7 @@ const EdgeMixin: PartialType = {
includeLoops = true, includeLoops = true,
recurse = false recurse = false
) { ) {
let edges: CellArray = new CellArray(); let edges: Cell[] = [];
const isCollapsed = cell.isCollapsed(); const isCollapsed = cell.isCollapsed();
const childCount = cell.getChildCount(); const childCount = cell.getChildCount();
@ -584,7 +583,7 @@ const EdgeMixin: PartialType = {
} }
edges = edges.concat(cell.getEdges(incoming, outgoing)); edges = edges.concat(cell.getEdges(incoming, outgoing));
const result = new CellArray(); const result = [];
for (let i = 0; i < edges.length; i += 1) { for (let i = 0; i < edges.length; i += 1) {
const state = this.getView().getState(edges[i]); const state = this.getView().getState(edges[i]);
@ -636,7 +635,7 @@ const EdgeMixin: PartialType = {
*/ */
getEdgesBetween(source, target, directed = false) { getEdgesBetween(source, target, directed = false) {
const edges = this.getEdges(source); const edges = this.getEdges(source);
const result = new CellArray(); const result = [];
// Checks if the edge is connected to the correct // Checks if the edge is connected to the correct
// cell and returns the first match // cell and returns the first match

View File

@ -18,7 +18,6 @@ import Image from '../image/ImageBox';
import Client from '../../Client'; import Client from '../../Client';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import Geometry from '../geometry/Geometry'; import Geometry from '../geometry/Geometry';
@ -34,18 +33,18 @@ declare module '../Graph' {
getCollapseExpandResource: () => string; getCollapseExpandResource: () => string;
isFoldingEnabled: () => boolean; isFoldingEnabled: () => boolean;
getFoldableCells: (cells: CellArray, collapse: boolean) => CellArray | null; getFoldableCells: (cells: Cell[], collapse: boolean) => Cell[] | null;
isCellFoldable: (cell: Cell, collapse: boolean) => boolean; isCellFoldable: (cell: Cell, collapse: boolean) => boolean;
getFoldingImage: (state: CellState) => Image | null; getFoldingImage: (state: CellState) => Image | null;
foldCells: ( foldCells: (
collapse: boolean, collapse: boolean,
recurse?: boolean, recurse?: boolean,
cells?: CellArray | null, cells?: Cell[] | null,
checkFoldable?: boolean, checkFoldable?: boolean,
evt?: Event | null evt?: Event | null
) => CellArray | null; ) => Cell[] | null;
cellsFolded: ( cellsFolded: (
cells: CellArray | null, cells: Cell[] | null,
collapse: boolean, collapse: boolean,
recurse: boolean, recurse: boolean,
checkFoldable?: boolean checkFoldable?: boolean

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import { sortCells } from '../../util/styleUtils'; import { sortCells } from '../../util/styleUtils';
import Geometry from '../geometry/Geometry'; import Geometry from '../geometry/Geometry';
@ -27,27 +26,27 @@ import { Graph } from '../Graph';
declare module '../Graph' { declare module '../Graph' {
interface Graph { interface Graph {
groupCells: (group: Cell, border: number, cells?: CellArray | null) => Cell; groupCells: (group: Cell, border: number, cells?: Cell[] | null) => Cell;
getCellsForGroup: (cells: CellArray) => CellArray; getCellsForGroup: (cells: Cell[]) => Cell[];
getBoundsForGroup: ( getBoundsForGroup: (
group: Cell, group: Cell,
children: CellArray, children: Cell[],
border: number | null border: number | null
) => Rectangle | null; ) => Rectangle | null;
createGroupCell: (cells: CellArray) => Cell; createGroupCell: (cells: Cell[]) => Cell;
ungroupCells: (cells?: CellArray | null) => CellArray; ungroupCells: (cells?: Cell[] | null) => Cell[];
getCellsForUngroup: () => CellArray; getCellsForUngroup: () => Cell[];
removeCellsAfterUngroup: (cells: CellArray) => void; removeCellsAfterUngroup: (cells: Cell[]) => void;
removeCellsFromParent: (cells?: CellArray | null) => CellArray; removeCellsFromParent: (cells?: Cell[] | null) => Cell[];
updateGroupBounds: ( updateGroupBounds: (
cells: CellArray, cells: Cell[],
border?: number, border?: number,
moveGroup?: boolean, moveGroup?: boolean,
topBorder?: number, topBorder?: number,
rightBorder?: number, rightBorder?: number,
bottomBorder?: number, bottomBorder?: number,
leftBorder?: number leftBorder?: number
) => CellArray; ) => Cell[];
enterGroup: (cell: Cell) => void; enterGroup: (cell: Cell) => void;
exitGroup: () => void; exitGroup: () => void;
} }
@ -141,24 +140,15 @@ const GroupingMixin: PartialType = {
// Adds the group into the parent // Adds the group into the parent
let index = (<Cell>parent).getChildCount(); let index = (<Cell>parent).getChildCount();
this.cellsAdded( this.cellsAdded([group], <Cell>parent, index, null, null, false, false, false);
new CellArray(group),
<Cell>parent,
index,
null,
null,
false,
false,
false
);
// Adds the children into the group and moves // Adds the children into the group and moves
index = group.getChildCount(); index = group.getChildCount();
this.cellsAdded(<CellArray>cells, group, index, null, null, false, false, false); this.cellsAdded(<Cell[]>cells, group, index, null, null, false, false, false);
this.cellsMoved(<CellArray>cells, -bounds.x, -bounds.y, false, false, false); this.cellsMoved(<Cell[]>cells, -bounds.x, -bounds.y, false, false, false);
// Resizes the group // Resizes the group
this.cellsResized(new CellArray(group), [bounds], false); this.cellsResized([group], [bounds], false);
this.fireEvent( this.fireEvent(
new EventObject(InternalEvent.GROUP_CELLS, { group, border, cells }) new EventObject(InternalEvent.GROUP_CELLS, { group, border, cells })
@ -173,7 +163,7 @@ const GroupingMixin: PartialType = {
* in the given array. * in the given array.
*/ */
getCellsForGroup(cells) { getCellsForGroup(cells) {
const result = new CellArray(); const result = [];
if (cells != null && cells.length > 0) { if (cells != null && cells.length > 0) {
const parent = cells[0].getParent(); const parent = cells[0].getParent();
result.push(cells[0]); result.push(cells[0]);
@ -247,7 +237,7 @@ const GroupingMixin: PartialType = {
* selection cells are used. * selection cells are used.
*/ */
ungroupCells(cells) { ungroupCells(cells) {
let result: CellArray = new CellArray(); let result: Cell[] = [];
if (cells == null) { if (cells == null) {
cells = this.getCellsForUngroup(); cells = this.getCellsForUngroup();
@ -255,7 +245,7 @@ const GroupingMixin: PartialType = {
if (cells != null && cells.length > 0) { if (cells != null && cells.length > 0) {
this.batchUpdate(() => { this.batchUpdate(() => {
const _cells = <CellArray>cells; const _cells = <Cell[]>cells;
for (let i = 0; i < _cells.length; i += 1) { for (let i = 0; i < _cells.length; i += 1) {
let children = _cells[i].getChildren(); let children = _cells[i].getChildren();
@ -299,7 +289,7 @@ const GroupingMixin: PartialType = {
const cells = this.getSelectionCells(); const cells = this.getSelectionCells();
// Finds the cells with children // Finds the cells with children
const tmp = new CellArray(); const tmp = [];
for (let i = 0; i < cells.length; i += 1) { for (let i = 0; i < cells.length; i += 1) {
if (cells[i].isVertex() && cells[i].getChildCount() > 0) { if (cells[i].isVertex() && cells[i].getChildCount() > 0) {
@ -332,10 +322,8 @@ const GroupingMixin: PartialType = {
const parent = this.getDefaultParent(); const parent = this.getDefaultParent();
const index = parent.getChildCount(); const index = parent.getChildCount();
this.cellsAdded(<CellArray>cells, parent, index, null, null, true); this.cellsAdded(<Cell[]>cells, parent, index, null, null, true);
this.fireEvent( this.fireEvent(new EventObject(InternalEvent.REMOVE_CELLS_FROM_PARENT, { cells }));
new EventObject(InternalEvent.REMOVE_CELLS_FROM_PARENT, { cells })
);
}); });
return cells; return cells;
}, },
@ -383,7 +371,7 @@ const GroupingMixin: PartialType = {
continue; continue;
} }
const children = <CellArray>this.getChildCells(cells[i]); const children = this.getChildCells(cells[i]);
if (children != null && children.length > 0) { if (children != null && children.length > 0) {
const bounds = this.getBoundingBoxFromGeometry(children, true); const bounds = this.getBoundingBoxFromGeometry(children, true);

View File

@ -14,17 +14,17 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import CellArray from '../cell/CellArray';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import { sortCells } from '../../util/styleUtils'; import { sortCells } from '../../util/styleUtils';
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import Cell from '../cell/Cell';
declare module '../Graph' { declare module '../Graph' {
interface Graph { interface Graph {
orderCells: (back: boolean, cells?: CellArray) => CellArray; orderCells: (back: boolean, cells?: Cell[]) => Cell[];
cellsOrdered: (cells: CellArray, back: boolean) => void; cellsOrdered: (cells: Cell[], back: boolean) => void;
} }
} }
@ -57,7 +57,7 @@ const OrderMixin: PartialType = {
} }
this.batchUpdate(() => { this.batchUpdate(() => {
this.cellsOrdered(<CellArray>cells, back); this.cellsOrdered(<Cell[]>cells, back);
const event = new EventObject( const event = new EventObject(
InternalEvent.ORDER_CELLS, InternalEvent.ORDER_CELLS,
'back', 'back',
@ -86,13 +86,15 @@ const OrderMixin: PartialType = {
if (back) { if (back) {
this.getDataModel().add(parent, cells[i], i); this.getDataModel().add(parent, cells[i], i);
} else { } 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( this.fireEvent(new EventObject(InternalEvent.CELLS_ORDERED, { back, cells }));
new EventObject(InternalEvent.CELLS_ORDERED, { back, cells })
);
}); });
}, },
}; };

View File

@ -15,7 +15,6 @@ limitations under the License.
*/ */
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import CellArray from '../cell/CellArray';
import Rectangle from '../geometry/Rectangle'; import Rectangle from '../geometry/Rectangle';
import Dictionary from '../../util/Dictionary'; import Dictionary from '../../util/Dictionary';
import RootChange from '../undoable_changes/RootChange'; import RootChange from '../undoable_changes/RootChange';
@ -26,7 +25,7 @@ import GraphSelectionModel from '../GraphSelectionModel';
declare module '../Graph' { declare module '../Graph' {
interface Graph { interface Graph {
cells: CellArray; cells: Cell[];
doneResource: string; doneResource: string;
updatingSelectionResource: string; updatingSelectionResource: string;
singleSelection: boolean; singleSelection: boolean;
@ -39,14 +38,14 @@ declare module '../Graph' {
clearSelection: () => void; clearSelection: () => void;
getSelectionCount: () => number; getSelectionCount: () => number;
getSelectionCell: () => Cell; getSelectionCell: () => Cell;
getSelectionCells: () => CellArray; getSelectionCells: () => Cell[];
setSelectionCell: (cell: Cell | null) => void; setSelectionCell: (cell: Cell | null) => void;
setSelectionCells: (cells: CellArray) => void; setSelectionCells: (cells: Cell[]) => void;
addSelectionCell: (cell: Cell) => void; addSelectionCell: (cell: Cell) => void;
addSelectionCells: (cells: CellArray) => void; addSelectionCells: (cells: Cell[]) => void;
removeSelectionCell: (cell: Cell) => void; removeSelectionCell: (cell: Cell) => void;
removeSelectionCells: (cells: CellArray) => void; removeSelectionCells: (cells: Cell[]) => void;
selectRegion: (rect: Rectangle, evt: MouseEvent) => CellArray; selectRegion: (rect: Rectangle, evt: MouseEvent) => Cell[];
selectNextCell: () => void; selectNextCell: () => void;
selectPreviousCell: () => void; selectPreviousCell: () => void;
selectParentCell: () => void; selectParentCell: () => void;
@ -62,9 +61,9 @@ declare module '../Graph' {
selectGroups?: boolean selectGroups?: boolean
) => void; ) => void;
selectCellForEvent: (cell: Cell, evt: MouseEvent) => void; selectCellForEvent: (cell: Cell, evt: MouseEvent) => void;
selectCellsForEvent: (cells: CellArray, evt: MouseEvent) => void; selectCellsForEvent: (cells: Cell[], evt: MouseEvent) => void;
isSiblingSelected: (cell: Cell) => boolean; isSiblingSelected: (cell: Cell) => boolean;
getSelectionCellsForChanges: (changes: any[], ignoreFn?: Function | null) => CellArray; getSelectionCellsForChanges: (changes: any[], ignoreFn?: Function | null) => Cell[];
updateSelection: () => void; updateSelection: () => void;
} }
} }
@ -287,7 +286,8 @@ const SelectionMixin: PartialType = {
* @param isChild Boolean indicating if the first child cell should be selected. * @param isChild Boolean indicating if the first child cell should be selected.
*/ */
selectCell(isNext = false, isParent = false, isChild = false) { 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) { if (this.selectionModel.cells.length > 1) {
this.selectionModel.clear(); this.selectionModel.clear();
@ -468,7 +468,7 @@ const SelectionMixin: PartialType = {
*/ */
getSelectionCellsForChanges(changes, ignoreFn = null) { getSelectionCellsForChanges(changes, ignoreFn = null) {
const dict = new Dictionary(); const dict = new Dictionary();
const cells: CellArray = new CellArray(); const cells: Cell[] = [];
const addCell = (cell: Cell) => { const addCell = (cell: Cell) => {
if (!dict.get(cell) && this.getDataModel().contains(cell)) { if (!dict.get(cell) && this.getDataModel().contains(cell)) {
@ -510,7 +510,7 @@ const SelectionMixin: PartialType = {
*/ */
updateSelection() { updateSelection() {
const cells = this.getSelectionCells(); const cells = this.getSelectionCells();
const removed = new CellArray(); const removed = [];
for (const cell of cells) { for (const cell of cells) {
if (!this.getDataModel().contains(cell) || !cell.isVisible()) { if (!this.getDataModel().contains(cell) || !cell.isVisible()) {

View File

@ -20,7 +20,6 @@ import { mixInto } from '../../util/Utils';
import { convertPoint } from '../../util/styleUtils'; import { convertPoint } from '../../util/styleUtils';
import { mod } from '../../util/mathUtils'; import { mod } from '../../util/mathUtils';
import { DEFAULT_STARTSIZE, DIRECTION, SHAPE } from '../../util/Constants'; import { DEFAULT_STARTSIZE, DIRECTION, SHAPE } from '../../util/Constants';
import CellArray from '../cell/CellArray';
import { getClientX, getClientY } from '../../util/EventUtils'; import { getClientX, getClientY } from '../../util/EventUtils';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
@ -39,13 +38,9 @@ declare module '../Graph' {
getSwimlaneDirection: (style: CellStateStyle) => DirectionValue; getSwimlaneDirection: (style: CellStateStyle) => DirectionValue;
getActualStartSize: (swimlane: Cell, ignoreState: boolean) => Rectangle; getActualStartSize: (swimlane: Cell, ignoreState: boolean) => Rectangle;
isSwimlane: (cell: Cell, ignoreState?: boolean) => boolean; isSwimlane: (cell: Cell, ignoreState?: boolean) => boolean;
isValidDropTarget: ( isValidDropTarget: (cell: Cell, cells?: Cell[], evt?: MouseEvent | null) => boolean;
cell: Cell,
cells?: CellArray,
evt?: MouseEvent | null
) => boolean;
getDropTarget: ( getDropTarget: (
cells: CellArray, cells: Cell[],
evt: MouseEvent, evt: MouseEvent,
cell: Cell | null, cell: Cell | null,
clone?: boolean clone?: boolean

View File

@ -14,7 +14,6 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Dictionary from '../../util/Dictionary'; import Dictionary from '../../util/Dictionary';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
@ -24,11 +23,11 @@ declare module '../Graph' {
interface Graph { interface Graph {
isTerminalPointMovable: (cell: Cell, source: boolean) => boolean; isTerminalPointMovable: (cell: Cell, source: boolean) => boolean;
getOpposites: ( getOpposites: (
edges: CellArray, edges: Cell[],
terminal: Cell | null, terminal: Cell | null,
sources?: boolean, sources?: boolean,
targets?: boolean targets?: boolean
) => CellArray; ) => Cell[];
} }
} }
@ -74,7 +73,7 @@ const TerminalMixin: PartialType = {
* included in the result. Default is `true`. * included in the result. Default is `true`.
*/ */
getOpposites(edges, terminal = null, sources = true, targets = true) { getOpposites(edges, terminal = null, sources = true, targets = true) {
const terminals = new CellArray(); const terminals = [];
// Fast lookup to avoid duplicates in terminals array // Fast lookup to avoid duplicates in terminals array
const dict = new Dictionary<Cell, boolean>(); const dict = new Dictionary<Cell, boolean>();

View File

@ -17,7 +17,6 @@ limitations under the License.
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
import Geometry from '../geometry/Geometry'; import Geometry from '../geometry/Geometry';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
import { mixInto } from '../../util/Utils'; import { mixInto } from '../../util/Utils';
import type { CellStyle } from '../../types'; import type { CellStyle } from '../../types';
@ -41,7 +40,7 @@ declare module '../Graph' {
relative: boolean, relative: boolean,
geometryClass: typeof Geometry geometryClass: typeof Geometry
) => Cell; ) => Cell;
getChildVertices: (parent?: Cell | null) => CellArray; getChildVertices: (parent?: Cell | null) => Cell[];
isVertexLabelsMovable: () => boolean; isVertexLabelsMovable: () => boolean;
setVertexLabelsMovable: (value: boolean) => void; setVertexLabelsMovable: (value: boolean) => void;
} }

View File

@ -26,7 +26,6 @@ import { DIALECT } from '../../util/Constants';
import { addLinkToHead, write } from '../../util/domUtils'; import { addLinkToHead, write } from '../../util/domUtils';
import { Graph } from '../Graph'; import { Graph } from '../Graph';
import CellState from '../cell/CellState'; import CellState from '../cell/CellState';
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell'; import Cell from '../cell/Cell';
/** /**
@ -340,7 +339,14 @@ class PrintPreview {
* @param targetWindow Optional window that should be used for rendering. If * @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. * 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.graph = graph;
this.scale = scale != null ? scale : 1 / graph.pageScale; this.scale = scale != null ? scale : 1 / graph.pageScale;
this.x0 = x0; this.x0 = x0;
@ -398,7 +404,7 @@ class PrintPreview {
} }
if (!this.wnd) { if (!this.wnd) {
throw new Error("Create new window not allowed"); throw new Error('Create new window not allowed');
} }
const doc = this.wnd.document; const doc = this.wnd.document;
@ -666,7 +672,7 @@ class PrintPreview {
*/ */
createPageSelector(vpages: number, hpages: number): HTMLTableElement { createPageSelector(vpages: number, hpages: number): HTMLTableElement {
if (!this.wnd) { if (!this.wnd) {
throw new Error("Popup window not created"); throw new Error('Popup window not created');
} }
const doc = this.wnd.document; const doc = this.wnd.document;
const table = doc.createElement('table'); const table = doc.createElement('table');
@ -713,7 +719,14 @@ class PrintPreview {
* Takes the inner div as the argument. * Takes the inner div as the argument.
* @param pageNumber Integer representing the page number. * @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 div: HTMLDivElement | null = document.createElement('div');
let arg = null; let arg = null;
@ -805,7 +818,14 @@ class PrintPreview {
* @param div Div that contains the output. * @param div Div that contains the output.
* @param clip Contains the clipping rectangle as an {@link Rectangle}. * @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 view = this.graph.getView();
const previousContainer = this.graph.container; const previousContainer = this.graph.container;
this.graph.container = div; this.graph.container = div;
@ -895,7 +915,7 @@ class PrintPreview {
try { try {
// Creates the temporary cell states in the view and // Creates the temporary cell states in the view and
// draws them onto the temporary DOM nodes in the view // draws them onto the temporary DOM nodes in the view
const cells = new CellArray(<Cell>this.getRoot()); const cells = [<Cell>this.getRoot()];
temp = new TemporaryCellStates(view, scale, cells, null, (state: CellState) => { temp = new TemporaryCellStates(view, scale, cells, null, (state: CellState) => {
return this.getLinkForCellState(state); return this.getLinkForCellState(state);
}); });

View File

@ -17,21 +17,17 @@ limitations under the License.
import EventObject from '../event/EventObject'; import EventObject from '../event/EventObject';
import Translations from '../../util/Translations'; import Translations from '../../util/Translations';
import InternalEvent from '../event/InternalEvent'; import InternalEvent from '../event/InternalEvent';
import CellArray from '../cell/CellArray';
import type { UndoableChange } from '../../types'; import type { UndoableChange } from '../../types';
import type { Graph } from '../Graph'; import type { Graph } from '../Graph';
import Cell from '../cell/Cell';
/** /**
* @class SelectionChange * @class SelectionChange
* Action to change the current root in a view. * Action to change the current root in a view.
*/ */
class SelectionChange implements UndoableChange { class SelectionChange implements UndoableChange {
constructor( constructor(graph: Graph, added: Cell[] = [], removed: Cell[] = []) {
graph: Graph,
added: CellArray = new CellArray(),
removed: CellArray = new CellArray()
) {
this.graph = graph; this.graph = graph;
this.added = added.slice(); this.added = added.slice();
this.removed = removed.slice(); this.removed = removed.slice();
@ -39,9 +35,9 @@ class SelectionChange implements UndoableChange {
graph: Graph; graph: Graph;
added: CellArray; added: Cell[];
removed: CellArray; removed: Cell[];
/** /**
* Changes the current root of the view. * Changes the current root of the view.

View File

@ -27,6 +27,7 @@ import {
GraphDataModel, GraphDataModel,
styleUtils, styleUtils,
stringUtils, stringUtils,
cellArrayUtils,
} from '@maxgraph/core'; } from '@maxgraph/core';
import { globalTypes } from '../.storybook/preview'; import { globalTypes } from '../.storybook/preview';
@ -171,7 +172,7 @@ const Template = ({ label, ...args }) => {
if (graph.isEnabled() && !graph.isSelectionEmpty()) { if (graph.isEnabled() && !graph.isSelectionEmpty()) {
copyCells( copyCells(
graph, graph,
utils.sortCells(graph.model.getTopmostCells(graph.getSelectionCells())) styleUtils.sortCells(cellArrayUtils.getTopmostCells(graph.getSelectionCells()))
); );
dx = 0; dx = 0;
dy = 0; dy = 0;
@ -194,7 +195,7 @@ const Template = ({ label, ...args }) => {
let cells = []; let cells = [];
try { try {
const doc = utils.parseXml(xml); const doc = xmlUtils.parseXml(xml);
const node = doc.documentElement; const node = doc.documentElement;
if (node != null) { if (node != null) {

View File

@ -26,7 +26,6 @@ import {
Guide, Guide,
eventUtils, eventUtils,
Cell, Cell,
CellArray,
Geometry, Geometry,
} from '@maxgraph/core'; } from '@maxgraph/core';
@ -151,7 +150,7 @@ const Template = ({ label, ...args }) => {
const funct = (graph, evt, target, x, y) => { const funct = (graph, evt, target, x, y) => {
const cell = new Cell('Test', new Geometry(0, 0, 120, 40)); const cell = new Cell('Test', new Geometry(0, 0, 120, 40));
cell.vertex = true; 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) { if (cells != null && cells.length > 0) {
graph.scrollCellToVisible(cells[0]); graph.scrollCellToVisible(cells[0]);
@ -175,7 +174,16 @@ const Template = ({ label, ...args }) => {
// if scalePreview (last) argument is true. Dx and dy are null to force // 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 // the use of the defaults. Note that dx and dy are only used for the
// drag icon but not for the preview. // 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 // 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. // if the the x and y arguments are used in funct to insert the cell.

View File

@ -15,7 +15,12 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import { Graph, RubberBandHandler, SelectionHandler, PopupMenuHandler } from '@maxgraph/core'; import {
Graph,
RubberBandHandler,
SelectionHandler,
PopupMenuHandler,
} from '@maxgraph/core';
import { globalTypes } from '../.storybook/preview'; import { globalTypes } from '../.storybook/preview';
@ -58,8 +63,9 @@ const Template = ({ label, ...args }) => {
const graphHandlerGetInitialCellForEvent = const graphHandlerGetInitialCellForEvent =
SelectionHandler.prototype.getInitialCellForEvent; SelectionHandler.prototype.getInitialCellForEvent;
SelectionHandler.prototype.getInitialCellForEvent = function (me) { SelectionHandler.prototype.getInitialCellForEvent = function (me) {
const model = this.graph.getDataModel(); const psel = this.graph.getSelectionCell()
const psel = this.graph.getSelectionCell().getParent(); ? this.graph.getSelectionCell().getParent()
: null;
let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments); let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments);
let parent = cell.getParent(); let parent = cell.getParent();
@ -82,8 +88,9 @@ const Template = ({ label, ...args }) => {
const graphHandlerIsDelayedSelection = SelectionHandler.prototype.isDelayedSelection; const graphHandlerIsDelayedSelection = SelectionHandler.prototype.isDelayedSelection;
SelectionHandler.prototype.isDelayedSelection = function (cell) { SelectionHandler.prototype.isDelayedSelection = function (cell) {
let result = graphHandlerIsDelayedSelection.apply(this, arguments); let result = graphHandlerIsDelayedSelection.apply(this, arguments);
const model = this.graph.getDataModel(); const psel = this.graph.getSelectionCell()
const psel = this.graph.getSelectionCell().getParent(); ? this.graph.getSelectionCell().getParent()
: null;
const parent = cell.getParent(); const parent = cell.getParent();
if (psel == null || (psel != cell && psel != parent)) { if (psel == null || (psel != cell && psel != parent)) {

View File

@ -21,7 +21,6 @@ import {
RubberBandHandler, RubberBandHandler,
ImageBox, ImageBox,
Rectangle, Rectangle,
CellArray,
mathUtils, mathUtils,
domUtils, domUtils,
ConnectionHandler, ConnectionHandler,
@ -73,7 +72,7 @@ const Template = ({ label, ...args }) => {
InternalEvent.addGestureListeners(img, (evt) => { InternalEvent.addGestureListeners(img, (evt) => {
const s = graph.gridSize; 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); InternalEvent.consume(evt);
this.destroy(); this.destroy();
}); });
@ -99,7 +98,7 @@ const Template = ({ label, ...args }) => {
}); });
InternalEvent.addListener(img, 'click', (evt) => { InternalEvent.addListener(img, 'click', (evt) => {
graph.removeCells(new CellArray(state.cell)); graph.removeCells([state.cell]);
InternalEvent.consume(evt); InternalEvent.consume(evt);
this.destroy(); this.destroy();
}); });

View File

@ -24,7 +24,6 @@ import {
GraphDataModel, GraphDataModel,
KeyHandler, KeyHandler,
Cell, Cell,
CellArray,
Geometry, Geometry,
DragSource, DragSource,
DomHelpers, DomHelpers,
@ -160,7 +159,7 @@ const Template = ({ label, ...args }) => {
vertex.geometry.x = pt.x; vertex.geometry.x = pt.x;
vertex.geometry.y = pt.y; 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) // Creates the image which is used as the drag icon (preview)