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 Editor from './Editor';
import Cell from '../view/cell/Cell';
import CellArray from '../view/cell/CellArray';
import { Graph } from '../view/Graph';
import EventObject from '../view/event/EventObject';
import ObjectCodec from '../serialization/ObjectCodec';
@ -62,7 +61,7 @@ import type { DropHandler } from '../view/other/DragSource';
* description of the configuration format.
*/
export class EditorToolbar {
constructor(container: HTMLElement | null=null, editor: Editor | null=null) {
constructor(container: HTMLElement | null = null, editor: Editor | null = null) {
this.editor = editor;
if (container != null && editor != null) {
@ -108,18 +107,21 @@ export class EditorToolbar {
// Installs the insert function in the editor if an item is
// selected in the toolbar
this.toolbar.addListener(InternalEvent.SELECT, (sender: Element, evt: EventObject) => {
const funct = evt.getProperty('function');
this.toolbar.addListener(
InternalEvent.SELECT,
(sender: Element, evt: EventObject) => {
const funct = evt.getProperty('function');
if (funct != null) {
(<Editor>this.editor).insertFunction = () => {
funct.apply(this, [container]);
(<MaxToolbar>this.toolbar).resetMode();
};
} else {
(<Editor>this.editor).insertFunction = null;
if (funct != null) {
(<Editor>this.editor).insertFunction = () => {
funct.apply(this, [container]);
(<MaxToolbar>this.toolbar).resetMode();
};
} else {
(<Editor>this.editor).insertFunction = null;
}
}
});
);
// Resets the selected tool after a doubleclick or escape keystroke
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);
}
}
@ -200,7 +205,11 @@ export class EditorToolbar {
* @param title - String that represents the title of the combo.
* @param value - Object that represents the value of the option.
*/
addOption(combo: HTMLSelectElement, title: string, value: string | ((evt: any) => void) | null): HTMLElement {
addOption(
combo: HTMLSelectElement,
title: string,
value: string | ((evt: any) => void) | null
): HTMLElement {
return (<MaxToolbar>this.toolbar).addOption(combo, title, value);
}
@ -218,14 +227,14 @@ export class EditorToolbar {
title: string,
icon: string,
mode: string,
pressed: string | null=null,
funct: Function | null=null
pressed: string | null = null,
funct: Function | null = null
): any {
const clickHandler = () => {
(<Editor>this.editor).setMode(mode);
if (funct != null) {
funct((<Editor>this.editor));
funct(<Editor>this.editor);
}
};
return (<MaxToolbar>this.toolbar).addSwitchMode(title, icon, clickHandler, pressed);
@ -253,8 +262,13 @@ export class EditorToolbar {
icon: string,
ptype: Function | Cell,
pressed: string,
insert: (editor: Editor, cell: Cell, me: MouseEvent, cellUnderMousePointer?: Cell | null) => void,
toggle: boolean=true
insert: (
editor: Editor,
cell: Cell,
me: MouseEvent,
cellUnderMousePointer?: Cell | null
) => void,
toggle: boolean = true
): HTMLImageElement | HTMLButtonElement {
// Creates a wrapper function that is in charge of constructing
// the new cell instance to be inserted into the graph
@ -272,7 +286,7 @@ export class EditorToolbar {
// after this item has been selected in the toolbar
const clickHandler = (evt: MouseEvent, cell: Cell | null) => {
if (typeof insert === 'function') {
insert((<Editor>this.editor), factory(), evt, cell);
insert(<Editor>this.editor, factory(), evt, cell);
} else {
this.drop(factory(), evt, cell);
}
@ -281,11 +295,22 @@ export class EditorToolbar {
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
// 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);
};
@ -302,8 +327,8 @@ export class EditorToolbar {
* @param evt - Mouse event that represents the drop.
* @param target - Optional {@link Cell} that represents the drop target.
*/
drop(vertex: Cell, evt: MouseEvent, target: Cell | null=null): void {
const { graph } = (<Editor>this.editor);
drop(vertex: Cell, evt: MouseEvent, target: Cell | null = null): void {
const { graph } = <Editor>this.editor;
const model = graph.getDataModel();
if (
@ -312,7 +337,7 @@ export class EditorToolbar {
!this.connectOnDrop ||
!target.isConnectable()
) {
while (target != null && !graph.isValidDropTarget(target, new CellArray(vertex), evt)) {
while (target != null && !graph.isValidDropTarget(target, [vertex], evt)) {
target = target.getParent();
}
this.insert(vertex, evt, target);
@ -329,8 +354,8 @@ export class EditorToolbar {
* @param evt - Mouse event that represents the drop.
* @param target - Optional {@link Cell} that represents the parent.
*/
insert(vertex: Cell, evt: MouseEvent, target: Cell | null=null): any {
const { graph } = (<Editor>this.editor);
insert(vertex: Cell, evt: MouseEvent, target: Cell | null = null): any {
const { graph } = <Editor>this.editor;
if (graph.canImportCell(vertex)) {
const x = getClientX(evt);
@ -338,8 +363,12 @@ export class EditorToolbar {
const pt = convertPoint(graph.container, x, y);
// Splits the target edge or inserts into target group
if (target && graph.isSplitEnabled() && graph.isSplitTarget(target, new CellArray(vertex), evt)) {
return graph.splitEdge(target, new CellArray(vertex), null, pt.x, pt.y);
if (
target &&
graph.isSplitEnabled() &&
graph.isSplitTarget(target, [vertex], evt)
) {
return graph.splitEdge(target, [vertex], null, pt.x, pt.y);
}
return (<Editor>this.editor).addVertex(target, vertex, pt.x, pt.y);
}
@ -353,7 +382,7 @@ export class EditorToolbar {
* @param evt - Mouse event that represents the drop.
* @param source - Optional {@link Cell} that represents the source terminal.
*/
connect(vertex: Cell, evt: MouseEvent, source: Cell | null=null): void {
connect(vertex: Cell, evt: MouseEvent, source: Cell | null = null): void {
const { graph } = <Editor>this.editor;
const model = graph.getDataModel();
@ -407,7 +436,7 @@ export class EditorToolbar {
model.endUpdate();
}
graph.setSelectionCells(new CellArray(vertex, edge));
graph.setSelectionCells([vertex, edge]);
graph.scrollCellToVisible(vertex);
}
}
@ -586,21 +615,16 @@ export class EditorToolbarCodec extends ObjectCodec {
const mode = node.getAttribute('mode');
const template = node.getAttribute('template');
const toggle = node.getAttribute('toggle') != '0';
const text = getTextContent(<Text><unknown>node);
const text = getTextContent(<Text>(<unknown>node));
let elt = null;
let funct: any;
if (action != null) {
elt = into.addItem(as, icon, action, pressedIcon);
} else if (mode != null) {
funct = EditorToolbarCodec.allowEval
? eval(text)
: null;
funct = EditorToolbarCodec.allowEval ? eval(text) : null;
elt = into.addMode(as, icon, mode, pressedIcon, funct);
} else if (
template != null ||
(text != null && text.length > 0)
) {
} else if (template != null || (text != null && text.length > 0)) {
let cell = template ? editor.templates[template] : null;
const style = node.getAttribute('style');
@ -611,11 +635,7 @@ export class EditorToolbarCodec extends ObjectCodec {
let insertFunction = null;
if (
text != null &&
text.length > 0 &&
EditorToolbarCodec.allowEval
) {
if (text != null && text.length > 0 && EditorToolbarCodec.allowEval) {
insertFunction = eval(text);
}
@ -667,14 +687,7 @@ export class EditorToolbarCodec extends ObjectCodec {
return null;
};
const img = into.addPrototype(
as,
icon,
create,
null,
null,
toggle
);
const img = into.addPrototype(as, icon, create, null, null, toggle);
select = into.addCombo();
// Selects the toolbar icon if a selection change
@ -702,11 +715,7 @@ export class EditorToolbarCodec extends ObjectCodec {
} else if (child.nodeName === 'add') {
const lab = child.getAttribute('as');
const tmp = child.getAttribute('template');
const option = into.addOption(
select,
lab,
tmp || template
);
const option = into.addOption(select, lab, tmp || template);
option.cellStyle = child.getAttribute('style');
}
}

View File

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

View File

@ -16,8 +16,9 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import Cell from '../view/cell/Cell';
import { Graph } from '../view/Graph';
import CellArray from '../view/cell/CellArray';
import { getTopmostCells } from './cellArrayUtils';
/**
* @class
@ -104,12 +105,12 @@ class Clipboard {
/**
* Holds the array of {@link mxCell} currently in the clipboard.
*/
static cells: CellArray;
static cells: Cell[];
/**
* Sets the cells in the clipboard. Fires a {@link mxEvent.CHANGE} event.
*/
static setCells(cells: CellArray) {
static setCells(cells: Cell[]) {
Clipboard.cells = cells;
}
@ -135,7 +136,7 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Optional array of {@link mxCell} to be cut.
*/
static cut(graph: Graph, cells?: CellArray) {
static cut(graph: Graph, cells: Cell[] = []) {
cells = Clipboard.copy(graph, cells);
Clipboard.insertCount = 0;
Clipboard.removeCells(graph, cells);
@ -150,8 +151,7 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be cut.
* @param cells - Array of {@link mxCell} to be cut.
*/
static removeCells(graph: Graph, cells: CellArray) {
// @ts-ignore
static removeCells(graph: Graph, cells: Cell[]) {
graph.removeCells(cells);
}
@ -163,11 +163,11 @@ class Clipboard {
* @param graph - {@link graph} that contains the cells to be copied.
* @param cells - Optional array of {@link mxCell} to be copied.
*/
static copy(graph: Graph, cells?: CellArray) {
static copy(graph: Graph, cells?: Cell[]) {
cells = cells || graph.getSelectionCells();
const result = graph.getExportableCells(cells).getTopmostCells();
const result = getTopmostCells(graph.getExportableCells(cells));
Clipboard.insertCount = 1;
// @ts-ignore
Clipboard.setCells(graph.cloneCells(result));
return result;
}
@ -190,12 +190,12 @@ class Clipboard {
cells = graph.getImportableCells(Clipboard.getCells());
const delta = Clipboard.insertCount * Clipboard.STEPSIZE;
const parent = graph.getDefaultParent();
// @ts-ignore
cells = graph.importCells(cells, delta, delta, parent);
// Increments the counter and selects the inserted cells
Clipboard.insertCount++;
graph.setSelectionCells(<CellArray>cells);
graph.setSelectionCells(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 Cell from '../view/cell/Cell';
import GraphDataModel from '../view/GraphDataModel';
import CellArray from '../view/cell/CellArray';
import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../types';
/**
@ -438,7 +438,7 @@ export const removeAllStylenames = (style: string) => {
*/
export const setCellStyles = (
model: GraphDataModel,
cells: CellArray,
cells: Cell[],
key: keyof CellStateStyle,
value: any
) => {
@ -534,7 +534,7 @@ export const setStyle = (style: string | null, key: string, value: any) => {
*/
export const setCellStyleFlags = (
model: GraphDataModel,
cells: CellArray,
cells: Cell[],
key: NumericCellStateStyleKeys,
flag: number,
value: boolean
@ -685,7 +685,7 @@ export const getSizeForString = (
* Sorts the given cells according to the order in the cell hierarchy.
* Ascending is optional and defaults to true.
*/
export const sortCells = (cells: CellArray, ascending = true): CellArray => {
export const sortCells = (cells: Cell[], ascending = true): Cell[] => {
const lookup = new Dictionary<Cell, string[]>();
cells.sort((o1, o2) => {

View File

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

View File

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

View File

@ -57,7 +57,6 @@ import ObjectCodec from '../serialization/ObjectCodec';
import type { GraphPlugin, GraphPluginConstructor, MouseListenerSet } from '../types';
import Multiplicity from './other/Multiplicity';
import CellArray from './cell/CellArray';
import ImageBundle from './image/ImageBundle';
import GraphSelectionModel from './GraphSelectionModel';
@ -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)
*****************************************************************************/
cells = new CellArray();
cells: Cell[] = [];
imageBundles: ImageBundle[] = [];

View File

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

View File

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

View File

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

View File

@ -22,7 +22,6 @@ import Animation from './Animation';
import CellState from '../cell/CellState';
import Cell from '../cell/Cell';
import { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
/**
* Implements animation for morphing cells. Here is an example of
@ -57,7 +56,7 @@ import CellArray from '../cell/CellArray';
* @param delay Optional delay between the animation steps. Passed to <Animation>.
*/
class Morphing extends Animation {
constructor(graph: Graph, steps: number=6, ease: number=1.5, delay: number) {
constructor(graph: Graph, steps: number = 6, ease: number = 1.5, delay: number) {
super(delay);
this.graph = graph;
this.steps = steps;
@ -90,7 +89,7 @@ class Morphing extends Animation {
* then all cells are checked and animated if they have been moved
* in the current transaction.
*/
cells: CellArray | null = null;
cells: Cell[] | null = null;
/**
* Animation step.
@ -127,7 +126,7 @@ class Morphing extends Animation {
/**
* Animates the given cell state using <CellStatePreview.moveState>.
*/
animateCell(cell: Cell, move: CellStatePreview, recurse: boolean=false) {
animateCell(cell: Cell, move: CellStatePreview, recurse: boolean = false) {
const state = this.graph.getView().getState(cell);
let delta = null;
@ -136,10 +135,7 @@ class Morphing extends Animation {
// change by subtracting the given delta vector from that location
delta = this.getDelta(state);
if (
cell.isVertex() &&
(delta.x != 0 || delta.y != 0)
) {
if (cell.isVertex() && (delta.x != 0 || delta.y != 0)) {
const translate = this.graph.view.getTranslate();
const scale = this.graph.view.getScale();
@ -154,11 +150,7 @@ class Morphing extends Animation {
const childCount = cell.getChildCount();
for (let i = 0; i < childCount; i += 1) {
this.animateCell(
cell.getChildAt(i),
move,
recurse
);
this.animateCell(cell.getChildAt(i), move, recurse);
}
}
}
@ -167,7 +159,7 @@ class Morphing extends Animation {
* Returns true if the animation should not recursively find more
* deltas for children if the given parent state has been animated.
*/
stopRecursion(state: CellState | null=null, delta: Point | null=null) {
stopRecursion(state: CellState | null = null, delta: Point | null = null) {
return delta != null && (delta.x != 0 || delta.y != 0);
}
@ -190,7 +182,7 @@ class Morphing extends Animation {
* by using caching inside this method as the result per cell never changes
* during the lifecycle of this object.
*/
getOriginForCell(cell: Cell | null=null): Point | null {
getOriginForCell(cell: Cell | null = null): Point | null {
let result = null;
if (cell != null) {

View File

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

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

View File

@ -22,7 +22,6 @@ import GraphView from '../GraphView';
import Cell from './Cell';
import CellState from './CellState';
import Shape from '../geometry/Shape';
import CellArray from './CellArray';
import { Graph } from '../Graph';
/**
@ -53,7 +52,7 @@ class TemporaryCellStates {
constructor(
view: GraphView,
scale: number = 1,
cells: CellArray,
cells: Cell[],
isCellVisibleFn: 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;
};
}

View File

@ -32,7 +32,6 @@ import Shape from '../geometry/Shape';
import InternalMouseEvent from '../event/InternalMouseEvent';
import ImageBox from '../image/ImageBox';
import CellState from './CellState';
import CellArray from './CellArray';
import type { Graph } from '../Graph';
import type { CellHandle, CellStateStyle } from '../../types';
@ -101,7 +100,7 @@ class VertexHandle implements CellHandle {
* Sets the cell style with the given name to the corresponding value in <state>.
*/
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 {
getAlignmentAsPoint,
setPrefixedStyle,
} from '../../util/styleUtils';
import { getAlignmentAsPoint, setPrefixedStyle } from '../../util/styleUtils';
import Rectangle from '../geometry/Rectangle';
import InternalEvent from '../event/InternalEvent';
import Client from '../../Client';
@ -42,7 +39,11 @@ import InternalMouseEvent from '../event/InternalMouseEvent';
import CellState from '../cell/CellState';
import Shape from '../geometry/Shape';
import { clearSelection, extractTextWithWhitespace, isNode } from '../../util/domUtils';
import { getStringValue, htmlEntities, replaceTrailingNewlines } from '../../util/StringUtils';
import {
getStringValue,
htmlEntities,
replaceTrailingNewlines,
} from '../../util/StringUtils';
import {
getSource,
isConsumed,
@ -54,7 +55,6 @@ import EventSource from '../event/EventSource';
import type { Graph } from '../Graph';
import type { GraphPlugin } from '../../types';
import CellArray from '../cell/CellArray';
import TooltipHandler from './TooltipHandler';
/**
@ -889,7 +889,7 @@ class CellEditorHandler implements GraphPlugin {
}
if (this.align !== null) {
this.graph.setCellStyles('align', this.align, new CellArray(state.cell));
this.graph.setCellStyles('align', this.align, [state.cell]);
}
});
}

View File

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

View File

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

View File

@ -45,7 +45,6 @@ import Cell from '../cell/Cell';
import { CellHandle, Listenable } from '../../types';
import Shape from '../geometry/Shape';
import InternalMouseEvent from '../event/InternalMouseEvent';
import CellArray from '../cell/CellArray';
import EdgeHandler from './EdgeHandler';
import EventSource from '../event/EventSource';
import SelectionHandler from './SelectionHandler';
@ -214,7 +213,7 @@ class VertexHandler {
constructor(state: CellState) {
this.state = state;
this.graph = (<Graph>this.state.view.graph);
this.graph = <Graph>this.state.view.graph;
this.selectionBounds = this.getSelectionBounds(this.state);
this.bounds = new Rectangle(
this.selectionBounds.x,
@ -659,7 +658,7 @@ class VertexHandler {
this.ghostPreview = this.createGhostPreview();
} else {
// 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();
if (
@ -1299,7 +1298,7 @@ class VertexHandler {
if (!cell.isEdge()) {
const style = this.graph.getCurrentCellStyle(cell);
const total = (style.rotation || 0) + angle;
this.graph.setCellStyles('rotation', total, new CellArray(cell));
this.graph.setCellStyles('rotation', total, [cell]);
}
let geo = cell.getGeometry();
@ -1877,7 +1876,9 @@ class VertexHandler {
// Hides rotation handle during text editing
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.
*/
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 { Graph } from '../Graph';
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell';
/**
@ -141,7 +140,7 @@ class CircleLayout extends GraphLayout {
left = this.x0;
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
* <execute>.
*/
circle(vertices: CellArray, r: number, left: number, top: number) {
circle(vertices: Cell[], r: number, left: number, top: number) {
const vertexCount = vertices.length;
const phi = (2 * Math.PI) / vertexCount;

View File

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

View File

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

View File

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

View File

@ -26,7 +26,6 @@ import MinimumCycleRemover from './hierarchical/MinimumCycleRemover';
import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction';
import CoordinateAssignment from './hierarchical/CoordinateAssignment';
import { Graph } from '../../view/Graph';
import CellArray from '../../view/cell/CellArray';
import Cell from '../../view/cell/Cell';
import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
@ -48,8 +47,8 @@ import GraphHierarchyNode from './datatypes/GraphHierarchyNode';
class HierarchicalLayout extends GraphLayout {
constructor(
graph: Graph,
orientation: DIRECTION=DIRECTION.NORTH,
deterministic: boolean=true
orientation: DIRECTION = DIRECTION.NORTH,
deterministic: boolean = true
) {
super(graph);
this.orientation = orientation;
@ -63,7 +62,7 @@ class HierarchicalLayout extends GraphLayout {
/**
* 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
@ -124,7 +123,7 @@ class HierarchicalLayout extends GraphLayout {
fineTuning: boolean = true;
/**
* Whether or not to tighten the assigned ranks of vertices up towards
* Whether or not to tighten the assigned ranks of vertices up towards
* the source cells. Default is true.
*/
tightenToSource: boolean = true;
@ -151,7 +150,7 @@ class HierarchicalLayout extends GraphLayout {
/**
* 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
@ -182,7 +181,7 @@ class HierarchicalLayout extends GraphLayout {
* @param parent Parent <Cell> that contains the children to be laid out.
* @param roots Optional starting roots of the layout.
*/
execute(parent: Cell, roots: CellArray | null=null): void {
execute(parent: Cell, roots: Cell[] | Cell | null = null): void {
this.parent = parent;
const { model } = this.graph;
this.edgesCache = new Dictionary();
@ -190,7 +189,7 @@ class HierarchicalLayout extends GraphLayout {
this.edgesTargetTermCache = new Dictionary();
if (roots != null && !(roots instanceof Array)) {
roots = new CellArray(roots);
roots = [roots];
}
// If the roots are set and the parent is set, only
@ -223,7 +222,7 @@ class HierarchicalLayout extends GraphLayout {
}
if (roots != null) {
const rootsCopy = new CellArray();
const rootsCopy = [];
for (let i = 0; i < roots.length; i += 1) {
const ancestor = parent != null ? parent.isAncestor(roots[i]) : true;
@ -240,7 +239,7 @@ class HierarchicalLayout extends GraphLayout {
this.run(parent);
if (this.resizeParent && !parent.isCollapsed()) {
this.graph.updateGroupBounds(new CellArray(parent), this.parentBorder, this.moveParent);
this.graph.updateGroupBounds([parent], this.parentBorder, this.moveParent);
}
// Maintaining parent location
@ -269,8 +268,8 @@ class HierarchicalLayout extends GraphLayout {
* @param parent <Cell> whose children should be checked.
* @param vertices array of vertices to limit search to
*/
findRoots(parent: Cell, vertices: CellArray): CellArray {
const roots = new CellArray();
findRoots(parent: Cell, vertices: Cell[]): Cell[] {
const roots = [];
if (parent != null && vertices != null) {
const { model } = this.graph;
@ -320,14 +319,14 @@ class HierarchicalLayout extends GraphLayout {
*
* @param cell <Cell> whose edges should be returned.
*/
getEdges(cell: Cell): CellArray {
getEdges(cell: Cell) {
const cachedEdges = this.edgesCache.get(cell);
if (cachedEdges != null) {
return cachedEdges;
}
const { model } = this.graph;
let edges = new CellArray();
let edges: Cell[] = [];
const isCollapsed = cell.isCollapsed();
const childCount = cell.getChildCount();
@ -342,7 +341,7 @@ class HierarchicalLayout extends GraphLayout {
}
edges = edges.concat(cell.getEdges(true, true));
const result = new CellArray();
const result = [];
for (let i = 0; i < edges.length; i += 1) {
const source = this.getVisibleTerminal(edges[i], true);
@ -423,7 +422,7 @@ class HierarchicalLayout extends GraphLayout {
const filledVertexSet = Object();
this.filterDescendants(parent, filledVertexSet);
this.roots = new CellArray();
this.roots = [];
let filledVertexSetEmpty = true;
// Poor man's isSetEmpty
@ -472,7 +471,7 @@ class HierarchicalLayout extends GraphLayout {
}
} else {
// 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) {
const vertexSet = Object();
@ -498,7 +497,7 @@ class HierarchicalLayout extends GraphLayout {
for (let i = 0; i < hierarchyVertices.length; i += 1) {
const vertexSet = hierarchyVertices[i];
const tmp = new CellArray();
const tmp = [];
for (var key in vertexSet) {
tmp.push(vertexSet[key]);
@ -507,7 +506,7 @@ class HierarchicalLayout extends GraphLayout {
this.model = new GraphHierarchyModel(
this,
tmp,
<CellArray>this.roots,
this.roots as Cell[],
parent,
this.tightenToSource
);
@ -566,10 +565,10 @@ class HierarchicalLayout extends GraphLayout {
* target -
* directed -
*/
getEdgesBetween(source: Cell, target: Cell, directed: boolean): CellArray {
getEdgesBetween(source: Cell, target: Cell, directed: boolean): Cell[] {
directed = directed != null ? directed : false;
const edges = this.getEdges(source);
const result = new CellArray();
const result = [];
// Checks if the edge is connected to the correct
// cell and returns the first match
@ -604,12 +603,12 @@ class HierarchicalLayout extends GraphLayout {
// @ts-ignore
traverse(
vertex: Cell,
directed: boolean=false,
edge: Cell | null=null,
allVertices: { [key: string]: Cell } | null=null,
currentComp: { [key: string]: (Cell | null) },
directed: boolean = false,
edge: Cell | null = null,
allVertices: { [key: string]: Cell } | null = null,
currentComp: { [key: string]: Cell | null },
hierarchyVertices: GraphHierarchyNode[],
filledVertexSet: { [key: string]: Cell } | null=null
filledVertexSet: { [key: string]: Cell } | null = null
) {
if (vertex != null && allVertices != null) {
// Has this vertex been seen before in any traversal

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,6 @@ import Dictionary from '../../../util/Dictionary';
import GraphHierarchyNode from '../datatypes/GraphHierarchyNode';
import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge';
import Cell from '../../cell/Cell';
import CellArray from '../../cell/CellArray';
import HierarchicalLayout from '../HierarchicalLayout';
import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell';
@ -49,8 +48,8 @@ import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell'
class GraphHierarchyModel {
constructor(
layout: HierarchicalLayout,
vertices: CellArray,
roots: CellArray,
vertices: Cell[],
roots: Cell[],
parent: Cell,
tightenToSource: boolean
) {
@ -146,7 +145,7 @@ class GraphHierarchyModel {
* Store of roots of this hierarchy model, these are real graph cells, not
* internal cells
*/
roots: CellArray | null = null;
roots: Cell[] | null = null;
/**
* The parent cell whose children are being laid out
@ -180,7 +179,7 @@ class GraphHierarchyModel {
*/
createInternalCells(
layout: HierarchicalLayout,
vertices: CellArray,
vertices: Cell[],
internalVertices: { [key: number]: GraphHierarchyNode }
) {
const graph = layout.getGraph();
@ -274,7 +273,7 @@ class GraphHierarchyModel {
}
const internalNodes = this.vertexMapper.getValues();
for (let i = 0; i < internalNodes.length; i += 1) {
// Mark the node as not having had a layer assigned
internalNodes[i].temp[0] = -1;
@ -392,7 +391,7 @@ class GraphHierarchyModel {
* to create dummy nodes for edges that cross layers.
*/
fixRanks(): void {
// TODO: Should this be a CellArray?
// TODO: Should this be a Cell[]?
const rankList: { [key: number]: GraphAbstractHierarchyCell[] } = {};
this.ranks = [];
@ -418,7 +417,13 @@ class GraphHierarchyModel {
}
this.visit(
(parent: GraphHierarchyNode, node: GraphHierarchyNode, edge: GraphHierarchyNode, layer: number, seen: number) => {
(
parent: GraphHierarchyNode,
node: GraphHierarchyNode,
edge: GraphHierarchyNode,
layer: number,
seen: number
) => {
if (seen == 0 && node.maxRank < 0 && node.minRank < 0) {
rankList[node.temp[0]].push(node);
node.maxRank = node.temp[0];
@ -515,11 +520,11 @@ class GraphHierarchyModel {
* @param layer the layer on the dfs tree ( not the same as the model ranks )
*/
dfs(
parent: GraphHierarchyNode | null,
root: GraphHierarchyNode | null,
connectingEdge: GraphHierarchyEdge | null,
visitor: Function,
seen: { [key: string]: GraphHierarchyNode | null },
parent: GraphHierarchyNode | null,
root: GraphHierarchyNode | null,
connectingEdge: GraphHierarchyEdge | null,
visitor: Function,
seen: { [key: string]: GraphHierarchyNode | null },
layer: number
): void {
if (root != null) {
@ -564,13 +569,13 @@ class GraphHierarchyModel {
* @param layer the layer on the dfs tree ( not the same as the model ranks )
*/
extendedDfs(
parent: GraphHierarchyNode | null,
root: GraphHierarchyNode,
connectingEdge: GraphHierarchyEdge | null,
visitor: Function,
seen: { [key: string]: GraphHierarchyNode },
ancestors: any,
childHash: string | number,
parent: GraphHierarchyNode | null,
root: GraphHierarchyNode,
connectingEdge: GraphHierarchyEdge | null,
visitor: Function,
seen: { [key: string]: GraphHierarchyNode },
ancestors: any,
childHash: string | number,
layer: number
) {
// Explanation of custom hash set. Previously, the ancestors variable

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -26,7 +26,6 @@ import { DIALECT } from '../../util/Constants';
import { addLinkToHead, write } from '../../util/domUtils';
import { Graph } from '../Graph';
import CellState from '../cell/CellState';
import CellArray from '../cell/CellArray';
import Cell from '../cell/Cell';
/**
@ -178,14 +177,14 @@ import Cell from '../cell/Cell';
class PrintPreview {
constructor(
graph: Graph,
scale: number | null=null,
pageFormat: Rectangle | null=null,
border: number | null=null,
x0: number=0,
y0: number=0,
borderColor: string | null=null,
title: string='Printer-friendly version',
pageSelector: boolean | null=null
scale: number | null = null,
pageFormat: Rectangle | null = null,
border: number | null = null,
x0: number = 0,
y0: number = 0,
borderColor: string | null = null,
title: string = 'Printer-friendly version',
pageSelector: boolean | null = null
) {
this.graph = graph;
this.scale = scale != null ? scale : 1 / graph.pageScale;
@ -340,7 +339,14 @@ class PrintPreview {
* @param targetWindow Optional window that should be used for rendering. If
* this is specified then no HEAD tag, CSS and BODY tag will be written.
*/
appendGraph(graph: Graph, scale: number, x0: number, y0: number, forcePageBreaks: boolean, keepOpen: boolean) {
appendGraph(
graph: Graph,
scale: number,
x0: number,
y0: number,
forcePageBreaks: boolean,
keepOpen: boolean
) {
this.graph = graph;
this.scale = scale != null ? scale : 1 / graph.pageScale;
this.x0 = x0;
@ -357,10 +363,10 @@ class PrintPreview {
* this is specified then no HEAD tag, CSS and BODY tag will be written.
*/
open(
css: string | null=null,
targetWindow: Window | null=null,
forcePageBreaks: boolean=false,
keepOpen: boolean=false
css: string | null = null,
targetWindow: Window | null = null,
forcePageBreaks: boolean = false,
keepOpen: boolean = false
): Window | null {
// Closing the window while the page is being rendered may cause an
// exception in IE. This and any other exceptions are simply ignored.
@ -398,7 +404,7 @@ class PrintPreview {
}
if (!this.wnd) {
throw new Error("Create new window not allowed");
throw new Error('Create new window not allowed');
}
const doc = this.wnd.document;
@ -666,7 +672,7 @@ class PrintPreview {
*/
createPageSelector(vpages: number, hpages: number): HTMLTableElement {
if (!this.wnd) {
throw new Error("Popup window not created");
throw new Error('Popup window not created');
}
const doc = this.wnd.document;
const table = doc.createElement('table');
@ -713,7 +719,14 @@ class PrintPreview {
* Takes the inner div as the argument.
* @param pageNumber Integer representing the page number.
*/
renderPage(w: number, h: number, dx: number, dy: number, content: (div: HTMLDivElement) => void, pageNumber?: number): HTMLDivElement{
renderPage(
w: number,
h: number,
dx: number,
dy: number,
content: (div: HTMLDivElement) => void,
pageNumber?: number
): HTMLDivElement {
let div: HTMLDivElement | null = document.createElement('div');
let arg = null;
@ -805,7 +818,14 @@ class PrintPreview {
* @param div Div that contains the output.
* @param clip Contains the clipping rectangle as an {@link Rectangle}.
*/
addGraphFragment(dx: number, dy: number, scale: number, pageNumber: number, div: HTMLDivElement, clip: Rectangle) {
addGraphFragment(
dx: number,
dy: number,
scale: number,
pageNumber: number,
div: HTMLDivElement,
clip: Rectangle
) {
const view = this.graph.getView();
const previousContainer = this.graph.container;
this.graph.container = div;
@ -895,7 +915,7 @@ class PrintPreview {
try {
// Creates the temporary cell states in the view and
// draws them onto the temporary DOM nodes in the view
const cells = new CellArray(<Cell>this.getRoot());
const cells = [<Cell>this.getRoot()];
temp = new TemporaryCellStates(view, scale, cells, null, (state: CellState) => {
return this.getLinkForCellState(state);
});

View File

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

View File

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

View File

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

View File

@ -15,7 +15,12 @@ See the License for the specific language governing permissions and
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';
@ -58,8 +63,9 @@ const Template = ({ label, ...args }) => {
const graphHandlerGetInitialCellForEvent =
SelectionHandler.prototype.getInitialCellForEvent;
SelectionHandler.prototype.getInitialCellForEvent = function (me) {
const model = this.graph.getDataModel();
const psel = this.graph.getSelectionCell().getParent();
const psel = this.graph.getSelectionCell()
? this.graph.getSelectionCell().getParent()
: null;
let cell = graphHandlerGetInitialCellForEvent.apply(this, arguments);
let parent = cell.getParent();
@ -82,8 +88,9 @@ const Template = ({ label, ...args }) => {
const graphHandlerIsDelayedSelection = SelectionHandler.prototype.isDelayedSelection;
SelectionHandler.prototype.isDelayedSelection = function (cell) {
let result = graphHandlerIsDelayedSelection.apply(this, arguments);
const model = this.graph.getDataModel();
const psel = this.graph.getSelectionCell().getParent();
const psel = this.graph.getSelectionCell()
? this.graph.getSelectionCell().getParent()
: null;
const parent = cell.getParent();
if (psel == null || (psel != cell && psel != parent)) {

View File

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

View File

@ -24,7 +24,6 @@ import {
GraphDataModel,
KeyHandler,
Cell,
CellArray,
Geometry,
DragSource,
DomHelpers,
@ -160,7 +159,7 @@ const Template = ({ label, ...args }) => {
vertex.geometry.x = pt.x;
vertex.geometry.y = pt.y;
graph.setSelectionCells(graph.importCells(new CellArray(vertex), 0, 0, cell));
graph.setSelectionCells(graph.importCells([vertex], 0, 0, cell));
};
// Creates the image which is used as the drag icon (preview)