cleanups, and started preferring for ... of loops over for (i=0; ... when feasible
parent
9d2e144637
commit
29fff201da
|
@ -155,7 +155,7 @@ class Graph extends EventSource {
|
||||||
/**
|
/**
|
||||||
* Holds the {@link Model} that contains the cells to be displayed.
|
* Holds the {@link Model} that contains the cells to be displayed.
|
||||||
*/
|
*/
|
||||||
model: Model | null = null;
|
model: Model;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the {@link GraphView} that caches the {@link CellState}s for the cells.
|
* Holds the {@link GraphView} that caches the {@link CellState}s for the cells.
|
||||||
|
@ -400,27 +400,6 @@ class Graph extends EventSource {
|
||||||
*/
|
*/
|
||||||
constrainRelativeChildren: boolean = false;
|
constrainRelativeChildren: boolean = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies if a parent should contain the child bounds after a resize of
|
|
||||||
* the child. This has precedence over {@link constrainChildren}.
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
extendParents: boolean = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies if parents should be extended according to the {@link extendParents}
|
|
||||||
* switch if cells are added.
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
extendParentsOnAdd: boolean = true;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies if parents should be extended according to the {@link extendParents}
|
|
||||||
* switch if cells are added.
|
|
||||||
* @default false (for backwards compatibility)
|
|
||||||
*/
|
|
||||||
extendParentsOnMove: boolean = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies the return value for {@link isRecursiveResize}.
|
* Specifies the return value for {@link isRecursiveResize}.
|
||||||
* @default false (for backwards compatibility)
|
* @default false (for backwards compatibility)
|
||||||
|
@ -556,8 +535,8 @@ class Graph extends EventSource {
|
||||||
/**
|
/**
|
||||||
* Creates and returns a new {@link GraphHandler} to be used in this graph.
|
* Creates and returns a new {@link GraphHandler} to be used in this graph.
|
||||||
*/
|
*/
|
||||||
createGraphHandler(): mxGraphHandler {
|
createGraphHandler(): GraphHandler {
|
||||||
return new mxGraphHandler(this);
|
return new GraphHandler(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1236,150 +1215,6 @@ class Graph extends EventSource {
|
||||||
return this.maximumGraphBounds;
|
return this.maximumGraphBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the bounding box for the geometries of the vertices in the
|
|
||||||
* given array of cells. This can be used to find the graph bounds during
|
|
||||||
* a layout operation (ie. before the last endUpdate) as follows:
|
|
||||||
*
|
|
||||||
* ```javascript
|
|
||||||
* var cells = graph.getChildCells(graph.getDefaultParent(), true, true);
|
|
||||||
* var bounds = graph.getBoundingBoxFromGeometry(cells, true);
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* This can then be used to move cells to the origin:
|
|
||||||
*
|
|
||||||
* ```javascript
|
|
||||||
* if (bounds.x < 0 || bounds.y < 0)
|
|
||||||
* {
|
|
||||||
* graph.moveCells(cells, -Math.min(bounds.x, 0), -Math.min(bounds.y, 0))
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* Or to translate the graph view:
|
|
||||||
*
|
|
||||||
* ```javascript
|
|
||||||
* if (bounds.x < 0 || bounds.y < 0)
|
|
||||||
* {
|
|
||||||
* graph.view.setTranslate(-Math.min(bounds.x, 0), -Math.min(bounds.y, 0));
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*
|
|
||||||
* @param cells Array of {@link Cell} whose bounds should be returned.
|
|
||||||
* @param includeEdges Specifies if edge bounds should be included by computing
|
|
||||||
* the bounding box for all points in geometry. Default is `false`.
|
|
||||||
*/
|
|
||||||
getBoundingBoxFromGeometry(
|
|
||||||
cells: CellArray,
|
|
||||||
includeEdges: boolean = false
|
|
||||||
): Rectangle | null {
|
|
||||||
includeEdges = includeEdges != null ? includeEdges : false;
|
|
||||||
let result = null;
|
|
||||||
let tmp: Rectangle | null = null;
|
|
||||||
|
|
||||||
for (const cell of cells) {
|
|
||||||
if (includeEdges || cell.isVertex()) {
|
|
||||||
// Computes the bounding box for the points in the geometry
|
|
||||||
const geo = cell.getGeometry();
|
|
||||||
|
|
||||||
if (geo != null) {
|
|
||||||
let bbox = null;
|
|
||||||
|
|
||||||
if (cell.isEdge()) {
|
|
||||||
const addPoint = (pt: Point | null) => {
|
|
||||||
if (pt != null) {
|
|
||||||
if (tmp == null) {
|
|
||||||
tmp = new Rectangle(pt.x, pt.y, 0, 0);
|
|
||||||
} else {
|
|
||||||
tmp.add(new Rectangle(pt.x, pt.y, 0, 0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (cell.getTerminal(true) == null) {
|
|
||||||
addPoint(geo.getTerminalPoint(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cell.getTerminal(false) == null) {
|
|
||||||
addPoint(geo.getTerminalPoint(false));
|
|
||||||
}
|
|
||||||
|
|
||||||
const pts = geo.points;
|
|
||||||
|
|
||||||
if (pts != null && pts.length > 0) {
|
|
||||||
tmp = new Rectangle(pts[0].x, pts[0].y, 0, 0);
|
|
||||||
|
|
||||||
for (let j = 1; j < pts.length; j++) {
|
|
||||||
addPoint(pts[j]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bbox = tmp;
|
|
||||||
} else {
|
|
||||||
const parent = <Cell>cell.getParent();
|
|
||||||
|
|
||||||
if (geo.relative) {
|
|
||||||
if (
|
|
||||||
parent.isVertex() &&
|
|
||||||
parent !== this.view.currentRoot
|
|
||||||
) {
|
|
||||||
tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false);
|
|
||||||
|
|
||||||
if (tmp != null) {
|
|
||||||
bbox = new Rectangle(
|
|
||||||
geo.x * tmp.width,
|
|
||||||
geo.y * tmp.height,
|
|
||||||
geo.width,
|
|
||||||
geo.height
|
|
||||||
);
|
|
||||||
|
|
||||||
if (cells.indexOf(parent) >= 0) {
|
|
||||||
bbox.x += tmp.x;
|
|
||||||
bbox.y += tmp.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
bbox = Rectangle.fromRectangle(geo);
|
|
||||||
|
|
||||||
if (parent.isVertex() && cells.indexOf(parent) >= 0) {
|
|
||||||
tmp = this.getBoundingBoxFromGeometry(new CellArray(parent), false);
|
|
||||||
|
|
||||||
if (tmp != null) {
|
|
||||||
bbox.x += tmp.x;
|
|
||||||
bbox.y += tmp.y;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bbox != null && geo.offset != null) {
|
|
||||||
bbox.x += geo.offset.x;
|
|
||||||
bbox.y += geo.offset.y;
|
|
||||||
}
|
|
||||||
|
|
||||||
const style = this.getCurrentCellStyle(cell);
|
|
||||||
|
|
||||||
if (bbox != null) {
|
|
||||||
const angle = getValue(style, 'rotation', 0);
|
|
||||||
|
|
||||||
if (angle !== 0) {
|
|
||||||
bbox = getBoundingBox(bbox, angle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bbox != null) {
|
|
||||||
if (result == null) {
|
|
||||||
result = Rectangle.fromRectangle(bbox);
|
|
||||||
} else {
|
|
||||||
result.add(bbox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears all cell states or the states for the hierarchy starting at the
|
* Clears all cell states or the states for the hierarchy starting at the
|
||||||
* given cell and validates the graph. This fires a refresh event as the
|
* given cell and validates the graph. This fires a refresh event as the
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -129,6 +129,91 @@ class Edge {
|
||||||
return edge;
|
return edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function: splitEdge
|
||||||
|
*
|
||||||
|
* Splits the given edge by adding the newEdge between the previous source
|
||||||
|
* and the given cell and reconnecting the source of the given edge to the
|
||||||
|
* given cell. This method fires <mxEvent.SPLIT_EDGE> while the transaction
|
||||||
|
* is in progress. Returns the new edge that was inserted.
|
||||||
|
*
|
||||||
|
* Parameters:
|
||||||
|
*
|
||||||
|
* edge - <mxCell> that represents the edge to be splitted.
|
||||||
|
* cells - <mxCells> that represents the cells to insert into the edge.
|
||||||
|
* newEdge - <mxCell> that represents the edge to be inserted.
|
||||||
|
* dx - Optional integer that specifies the vector to move the cells.
|
||||||
|
* dy - Optional integer that specifies the vector to move the cells.
|
||||||
|
* x - Integer that specifies the x-coordinate of the drop location.
|
||||||
|
* y - Integer that specifies the y-coordinate of the drop location.
|
||||||
|
* parent - Optional parent to insert the cell. If null the parent of
|
||||||
|
* the edge is used.
|
||||||
|
*/
|
||||||
|
splitEdge(
|
||||||
|
edge: Cell,
|
||||||
|
cells: CellArray,
|
||||||
|
newEdge: Cell,
|
||||||
|
dx: number = 0,
|
||||||
|
dy: number = 0,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
parent: Cell | null = null
|
||||||
|
) {
|
||||||
|
parent = parent != null ? parent : edge.getParent();
|
||||||
|
const source = edge.getTerminal(true);
|
||||||
|
|
||||||
|
this.graph.batchUpdate(() => {
|
||||||
|
if (newEdge == null) {
|
||||||
|
newEdge = <Cell>this.cloneCell(edge);
|
||||||
|
|
||||||
|
// Removes waypoints before/after new cell
|
||||||
|
const state = this.graph.view.getState(edge);
|
||||||
|
let geo = newEdge.getGeometry();
|
||||||
|
|
||||||
|
if (geo != null && geo.points != null && state != null) {
|
||||||
|
const t = this.graph.view.translate;
|
||||||
|
const s = this.graph.view.scale;
|
||||||
|
const idx = findNearestSegment(state, (dx + t.x) * s, (dy + t.y) * s);
|
||||||
|
|
||||||
|
geo.points = geo.points.slice(0, idx);
|
||||||
|
geo = <Geometry>edge.getGeometry();
|
||||||
|
|
||||||
|
if (geo != null && geo.points != null) {
|
||||||
|
geo = <Geometry>geo.clone();
|
||||||
|
geo.points = geo.points.slice(idx);
|
||||||
|
this.graph.model.setGeometry(edge, geo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.cellsMoved(cells, dx, dy, false, false);
|
||||||
|
this.cellsAdded(
|
||||||
|
cells,
|
||||||
|
parent,
|
||||||
|
parent ? parent.getChildCount() : 0,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
this.cellsAdded(
|
||||||
|
new CellArray(newEdge),
|
||||||
|
parent,
|
||||||
|
parent ? parent.getChildCount() : 0,
|
||||||
|
source,
|
||||||
|
cells[0],
|
||||||
|
false
|
||||||
|
);
|
||||||
|
this.cellConnected(edge, cells[0], true);
|
||||||
|
this.graph.fireEvent(
|
||||||
|
new EventObject(
|
||||||
|
InternalEvent.SPLIT_EDGE,
|
||||||
|
{ edge, cells, newEdge, dx, dy }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return newEdge;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a new edge into the given parent {@link Cell} using value as the user
|
* Adds a new edge into the given parent {@link Cell} using value as the user
|
||||||
|
@ -216,112 +301,6 @@ class Edge {
|
||||||
return this.addCell(edge, parent, index, source, target);
|
return this.addCell(edge, parent, index, source, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* Group: Cell cloning, insertion and removal
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Function: splitEdge
|
|
||||||
*
|
|
||||||
* Splits the given edge by adding the newEdge between the previous source
|
|
||||||
* and the given cell and reconnecting the source of the given edge to the
|
|
||||||
* given cell. This method fires <mxEvent.SPLIT_EDGE> while the transaction
|
|
||||||
* is in progress. Returns the new edge that was inserted.
|
|
||||||
*
|
|
||||||
* Parameters:
|
|
||||||
*
|
|
||||||
* edge - <mxCell> that represents the edge to be splitted.
|
|
||||||
* cells - <mxCells> that represents the cells to insert into the edge.
|
|
||||||
* newEdge - <mxCell> that represents the edge to be inserted.
|
|
||||||
* dx - Optional integer that specifies the vector to move the cells.
|
|
||||||
* dy - Optional integer that specifies the vector to move the cells.
|
|
||||||
* x - Integer that specifies the x-coordinate of the drop location.
|
|
||||||
* y - Integer that specifies the y-coordinate of the drop location.
|
|
||||||
* parent - Optional parent to insert the cell. If null the parent of
|
|
||||||
* the edge is used.
|
|
||||||
*/
|
|
||||||
splitEdge(
|
|
||||||
edge: Cell,
|
|
||||||
cells: CellArray,
|
|
||||||
newEdge: Cell,
|
|
||||||
dx: number = 0,
|
|
||||||
dy: number = 0,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
parent: Cell | null = null
|
|
||||||
) {
|
|
||||||
parent = parent != null ? parent : edge.getParent();
|
|
||||||
const source = edge.getTerminal(true);
|
|
||||||
|
|
||||||
this.getModel().beginUpdate();
|
|
||||||
try {
|
|
||||||
if (newEdge == null) {
|
|
||||||
newEdge = <Cell>this.cloneCell(edge);
|
|
||||||
|
|
||||||
// Removes waypoints before/after new cell
|
|
||||||
const state = this.getView().getState(edge);
|
|
||||||
let geo = newEdge.getGeometry();
|
|
||||||
|
|
||||||
if (geo != null && geo.points != null && state != null) {
|
|
||||||
const t = this.getView().translate;
|
|
||||||
const s = this.getView().scale;
|
|
||||||
const idx = findNearestSegment(
|
|
||||||
state,
|
|
||||||
(dx + t.x) * s,
|
|
||||||
(dy + t.y) * s
|
|
||||||
);
|
|
||||||
|
|
||||||
geo.points = geo.points.slice(0, idx);
|
|
||||||
geo = <Geometry>edge.getGeometry();
|
|
||||||
|
|
||||||
if (geo != null && geo.points != null) {
|
|
||||||
geo = <Geometry>geo.clone();
|
|
||||||
geo.points = geo.points.slice(idx);
|
|
||||||
this.getModel().setGeometry(edge, geo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.cellsMoved(cells, dx, dy, false, false);
|
|
||||||
this.cellsAdded(
|
|
||||||
cells,
|
|
||||||
parent,
|
|
||||||
parent ? parent.getChildCount() : 0,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
this.cellsAdded(
|
|
||||||
new CellArray(newEdge),
|
|
||||||
parent,
|
|
||||||
parent ? parent.getChildCount() : 0,
|
|
||||||
source,
|
|
||||||
cells[0],
|
|
||||||
false
|
|
||||||
);
|
|
||||||
this.cellConnected(edge, cells[0], true);
|
|
||||||
this.fireEvent(
|
|
||||||
new EventObject(
|
|
||||||
InternalEvent.SPLIT_EDGE,
|
|
||||||
'edge',
|
|
||||||
edge,
|
|
||||||
'cells',
|
|
||||||
cells,
|
|
||||||
'newEdge',
|
|
||||||
newEdge,
|
|
||||||
'dx',
|
|
||||||
dx,
|
|
||||||
'dy',
|
|
||||||
dy
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} finally {
|
|
||||||
this.getModel().endUpdate();
|
|
||||||
}
|
|
||||||
|
|
||||||
return newEdge;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Group: Folding
|
* Group: Folding
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
|
@ -33,9 +33,17 @@ class EventObject {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.properties = [];
|
this.properties = [];
|
||||||
|
|
||||||
for (let i = 0; i < args.length; i += 2) {
|
if (!!args[0] && args[0].constructor === Object) {
|
||||||
if (args[i + 1] != null) {
|
// A literal object ({})
|
||||||
this.properties[args[i]] = args[i + 1];
|
for (const [key, value] of Object.entries(args[0])) {
|
||||||
|
this.properties[key] = value;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// two-values [key, value, key, value, ...]
|
||||||
|
for (let i = 0; i < args.length; i += 2) {
|
||||||
|
if (args[i + 1] != null) {
|
||||||
|
this.properties[args[i]] = args[i + 1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +53,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Holds the name.
|
* Holds the name.
|
||||||
*/
|
*/
|
||||||
// name: string;
|
|
||||||
name: string = '';
|
name: string = '';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +60,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Holds the properties as an associative array.
|
* Holds the properties as an associative array.
|
||||||
*/
|
*/
|
||||||
// properties: any[];
|
|
||||||
properties: any = null;
|
properties: any = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,7 +67,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Holds the consumed state. Default is false.
|
* Holds the consumed state. Default is false.
|
||||||
*/
|
*/
|
||||||
// consumed: boolean;
|
|
||||||
consumed: boolean = false;
|
consumed: boolean = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +74,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns <name>.
|
* Returns <name>.
|
||||||
*/
|
*/
|
||||||
// getName(): string;
|
|
||||||
getName(): string {
|
getName(): string {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
@ -79,7 +83,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns <properties>.
|
* Returns <properties>.
|
||||||
*/
|
*/
|
||||||
// getProperties(): any[];
|
|
||||||
getProperties(): any {
|
getProperties(): any {
|
||||||
return this.properties;
|
return this.properties;
|
||||||
}
|
}
|
||||||
|
@ -89,7 +92,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns the property for the given key.
|
* Returns the property for the given key.
|
||||||
*/
|
*/
|
||||||
// getProperty(key: string): any;
|
|
||||||
getProperty(key: string): any {
|
getProperty(key: string): any {
|
||||||
return this.properties[key];
|
return this.properties[key];
|
||||||
}
|
}
|
||||||
|
@ -99,7 +101,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns true if the event has been consumed.
|
* Returns true if the event has been consumed.
|
||||||
*/
|
*/
|
||||||
// isConsumed(): boolean;
|
|
||||||
isConsumed(): boolean {
|
isConsumed(): boolean {
|
||||||
return this.consumed;
|
return this.consumed;
|
||||||
}
|
}
|
||||||
|
@ -109,7 +110,6 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Consumes the event.
|
* Consumes the event.
|
||||||
*/
|
*/
|
||||||
// consume(): void;
|
|
||||||
consume(): void {
|
consume(): void {
|
||||||
this.consumed = true;
|
this.consumed = true;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue