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.
|
||||
*/
|
||||
model: Model | null = null;
|
||||
model: Model;
|
||||
|
||||
/**
|
||||
* Holds the {@link GraphView} that caches the {@link CellState}s for the cells.
|
||||
|
@ -400,27 +400,6 @@ class Graph extends EventSource {
|
|||
*/
|
||||
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}.
|
||||
* @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.
|
||||
*/
|
||||
createGraphHandler(): mxGraphHandler {
|
||||
return new mxGraphHandler(this);
|
||||
createGraphHandler(): GraphHandler {
|
||||
return new GraphHandler(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1236,150 +1215,6 @@ class Graph extends EventSource {
|
|||
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
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -216,112 +301,6 @@ class Edge {
|
|||
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
|
||||
*****************************************************************************/
|
||||
|
|
|
@ -33,9 +33,17 @@ class EventObject {
|
|||
this.name = name;
|
||||
this.properties = [];
|
||||
|
||||
for (let i = 0; i < args.length; i += 2) {
|
||||
if (args[i + 1] != null) {
|
||||
this.properties[args[i]] = args[i + 1];
|
||||
if (!!args[0] && args[0].constructor === Object) {
|
||||
// A literal object ({})
|
||||
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.
|
||||
*/
|
||||
// name: string;
|
||||
name: string = '';
|
||||
|
||||
/**
|
||||
|
@ -53,7 +60,6 @@ class EventObject {
|
|||
*
|
||||
* Holds the properties as an associative array.
|
||||
*/
|
||||
// properties: any[];
|
||||
properties: any = null;
|
||||
|
||||
/**
|
||||
|
@ -61,7 +67,6 @@ class EventObject {
|
|||
*
|
||||
* Holds the consumed state. Default is false.
|
||||
*/
|
||||
// consumed: boolean;
|
||||
consumed: boolean = false;
|
||||
|
||||
/**
|
||||
|
@ -69,7 +74,6 @@ class EventObject {
|
|||
*
|
||||
* Returns <name>.
|
||||
*/
|
||||
// getName(): string;
|
||||
getName(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
@ -79,7 +83,6 @@ class EventObject {
|
|||
*
|
||||
* Returns <properties>.
|
||||
*/
|
||||
// getProperties(): any[];
|
||||
getProperties(): any {
|
||||
return this.properties;
|
||||
}
|
||||
|
@ -89,7 +92,6 @@ class EventObject {
|
|||
*
|
||||
* Returns the property for the given key.
|
||||
*/
|
||||
// getProperty(key: string): any;
|
||||
getProperty(key: string): any {
|
||||
return this.properties[key];
|
||||
}
|
||||
|
@ -99,7 +101,6 @@ class EventObject {
|
|||
*
|
||||
* Returns true if the event has been consumed.
|
||||
*/
|
||||
// isConsumed(): boolean;
|
||||
isConsumed(): boolean {
|
||||
return this.consumed;
|
||||
}
|
||||
|
@ -109,7 +110,6 @@ class EventObject {
|
|||
*
|
||||
* Consumes the event.
|
||||
*/
|
||||
// consume(): void;
|
||||
consume(): void {
|
||||
this.consumed = true;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue