feat: improve the EdgeMixin type (#212)

The methods defined in the `EdgeMixin` type were not documented.
The signature of the `insertEdge` method was using a spread `any`
parameter, so it provided no guidance nor guard.
Instead, the type now declares the various form of the methods with the
right signature.
development
Thomas Bouffard 2023-07-07 07:56:01 +02:00 committed by GitHub
parent cdd8830b5c
commit e82abd6da3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 417 additions and 248 deletions

View File

@ -88,7 +88,12 @@ graph.batchUpdate(() => {
style: { shape: 'ellipse', fillColor: 'orange' },
value: 'a regular ellipse',
});
graph.insertEdge(parent, null, 'a regular edge', vertex01, vertex02);
graph.insertEdge({
parent,
source: vertex01,
target: vertex02,
value: 'a regular edge',
});
});
```

View File

@ -0,0 +1,114 @@
/*
Copyright 2023-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 { describe, expect, test } from '@jest/globals';
import { Cell, type CellStyle, Geometry, Graph } from '../../../src';
function createGraph(): Graph {
// @ts-ignore - no need for a container, we don't check the view here
return new Graph(null);
}
describe('insertEdge', () => {
test('with several parameters', () => {
const graph = createGraph();
const source = new Cell();
const target = new Cell();
const style: CellStyle = { rounded: true, shape: 'line' };
const cell = graph.insertEdge(null, 'edge_1', 'a value', source, target, style);
expect(cell.getId()).toBe('edge_1');
expect(cell.vertex).toBeFalsy();
expect(cell.edge).toBeTruthy();
expect(cell.value).toBe('a value');
expect(cell.source).toBe(source);
expect(cell.target).toBe(target);
expect(cell.style).toStrictEqual(style);
const geometry = new Geometry();
geometry.relative = true;
expect(cell.geometry).toStrictEqual(geometry);
// parent created with cell as child
expect(cell.parent).not.toBeNull();
expect(cell.parent?.id).toBe('1'); // default parent
const children = cell.parent?.children;
expect(children).toContain(cell);
expect(children).toHaveLength(1);
// ensure that the cell is in the model
const cellFromModel = graph.getDataModel().getCell('edge_1');
expect(cellFromModel).toBe(cell);
});
test('with single parameter', () => {
const graph = createGraph();
const source = new Cell();
const target = new Cell();
const style: CellStyle = { startArrow: 'oval', strokeColor: 'red' };
const cell = graph.insertEdge({
source,
style,
target,
value: 'a value',
});
expect(cell.getId()).toBe('2'); // generated
expect(cell.vertex).toBeFalsy();
expect(cell.edge).toBeTruthy();
expect(cell.value).toBe('a value');
expect(cell.source).toBe(source);
expect(cell.target).toBe(target);
expect(cell.style).toStrictEqual(style);
const geometry = new Geometry();
geometry.relative = true;
expect(cell.geometry).toStrictEqual(geometry);
// parent created with cell as child
expect(cell.parent).not.toBeNull();
expect(cell.parent?.id).toBe('1'); // default parent
const children = cell.parent?.children;
expect(children).toContain(cell);
expect(children).toHaveLength(1);
// ensure that the cell is in the model
const cellFromModel = graph.getDataModel().getCell('2');
expect(cellFromModel).toBe(cell);
});
test('with single parameter and non default parent', () => {
const graph = createGraph();
const parentCell = graph.insertVertex({
value: 'non default',
position: [10, 10],
size: [400, 400],
});
expect(parentCell.getId()).toBe('2'); // generated
expect(parentCell.value).toBe('non default');
const childCell = graph.insertEdge({
parent: parentCell,
});
expect(childCell.getId()).toBe('3'); // generated
expect(childCell.parent).toBe(parentCell);
const children = parentCell.children;
expect(children).toContain(childCell);
expect(children).toHaveLength(1);
});
});

View File

@ -881,6 +881,30 @@ export type GradientMap = {
[k: string]: Gradient;
};
export type EdgeParameters = {
/**
* Optional string that defines the id of the new edge. If not set, the id is auto-generated when creating the vertex.
*/
id?: string;
/**
* The parent of the new edge. If not set, use the default parent.
*/
parent?: Cell | null;
/**
* The {@link Cell} that defines the source of the edge.
*/
source?: Cell | null;
style?: CellStyle;
/**
* The {@link Cell} that defines the target of the edge.
*/
target?: Cell | null;
/**
* Object to be used as the user object which is generally used to display the label of the vertex. The default implementation handles `string` object.
*/
value?: any;
};
export type VertexParameters = {
/**
* Class reference to a class derived from {@link Geometry}.

View File

@ -24,31 +24,142 @@ import InternalEvent from '../event/InternalEvent';
import Dictionary from '../../util/Dictionary';
import { Graph } from '../Graph';
import Point from '../geometry/Point';
import type { CellStyle } from '../../types';
import type { CellStyle, EdgeParameters } from '../../types';
declare module '../Graph' {
interface Graph {
/**
* Specifies if edge control points should be reset after the resize of a
* connected cell.
* @default false
*/
resetEdgesOnResize: boolean;
/**
* Specifies if edge control points should be reset after the move of a
* connected cell.
* @default false
*/
resetEdgesOnMove: boolean;
/**
* Specifies if edge control points should be reset after the the edge has been
* reconnected.
* @default true
*/
resetEdgesOnConnect: boolean;
/**
* Specifies if edges are connectable. This overrides the connectable field in edges.
* @default false
*/
connectableEdges: boolean;
/**
* Specifies if edges with disconnected terminals are allowed in the graph.
* @default true
*/
allowDanglingEdges: boolean;
/**
* Specifies if edges that are cloned should be validated and only inserted
* if they are valid.
* @default false
*/
cloneInvalidEdges: boolean;
/**
* Specifies the alternate edge style to be used if the main control point
* on an edge is being double-clicked.
* @default {}
*/
alternateEdgeStyle: CellStyle;
/**
* Specifies the return value for edges in {@link isLabelMovable}.
* @default true
*/
edgeLabelsMovable: boolean;
isResetEdgesOnMove: () => boolean;
isResetEdgesOnConnect: () => boolean;
isResetEdgesOnResize: () => boolean;
/**
* Returns {@link edgeLabelsMovable}.
*/
isEdgeLabelsMovable: () => boolean;
/**
* Sets {@link edgeLabelsMovable}.
*/
setEdgeLabelsMovable: (value: boolean) => void;
/**
* Specifies if dangling edges are allowed, that is, if edges are allowed
* that do not have a source and/or target terminal defined.
*
* @param value Boolean indicating if dangling edges are allowed.
*/
setAllowDanglingEdges: (value: boolean) => void;
/**
* Returns {@link allowDanglingEdges} as a boolean.
*/
isAllowDanglingEdges: () => boolean;
/**
* Specifies if edges should be connectable.
*
* @param value Boolean indicating if edges should be connectable.
*/
setConnectableEdges: (value: boolean) => void;
/**
* Returns {@link connectableEdges} as a boolean.
*/
isConnectableEdges: () => boolean;
/**
* Specifies if edges should be inserted when cloned but not valid wrt.
* {@link getEdgeValidationError}. If false such edges will be silently ignored.
*
* @param value Boolean indicating if cloned invalid edges should be
* inserted into the graph or ignored.
*/
setCloneInvalidEdges: (value: boolean) => void;
/**
* Returns {@link cloneInvalidEdges} as a boolean.
*/
isCloneInvalidEdges: () => boolean;
/**
* Toggles the style of the given edge between null (or empty) and
* {@link alternateEdgeStyle}. This method fires {@link InternalEvent.FLIP_EDGE} while the
* transaction is in progress. Returns the edge that was flipped.
*
* Here is an example that overrides this implementation to invert the
* value of {@link 'elbow'} without removing any existing styles.
*
* ```javascript
* graph.flipEdge = function(edge)
* {
* if (edge != null)
* {
* var style = this.getCurrentCellStyle(edge);
* var elbow = mxUtils.getValue(style, 'elbow',
* mxConstants.ELBOW_HORIZONTAL);
* var value = (elbow == mxConstants.ELBOW_HORIZONTAL) ?
* mxConstants.ELBOW_VERTICAL : mxConstants.ELBOW_HORIZONTAL;
* this.setCellStyles('elbow', value, [edge]);
* }
* };
* ```
*
* @param edge {@link Cell} whose style should be changed.
*/
flipEdge: (edge: Cell) => Cell;
/**
* 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 {@link Event#SPLIT_EDGE} while the transaction
* is in progress. Returns the new edge that was inserted.
*
* @param edge <Cell> that represents the edge to be split.
* @param cells {@link Cell}s that represents the cells to insert into the edge.
* @param newEdge <Cell> that represents the edge to be inserted.
* @param dx Optional integer that specifies the vector to move the cells.
* @param dy Optional integer that specifies the vector to move the cells.
* @param x Integer that specifies the x-coordinate of the drop location.
* @param y Integer that specifies the y-coordinate of the drop location.
* @param parent Optional parent to insert the cell. If null the parent of
* the edge is used.
*/
splitEdge: (
edge: Cell,
cells: Cell[],
@ -59,15 +170,68 @@ declare module '../Graph' {
y?: number,
parent?: Cell | null
) => Cell;
insertEdge: (...args: any[]) => Cell;
/**
* Adds a new edge into the given parent {@link Cell} using value as the user
* object and the given source and target as the terminals of the new edge.
* The id and style are used for the respective properties of the new
* {@link Cell}, which is returned.
*
* @param parent {@link Cell} that specifies the parent of the new edge. If not set, use the default parent.
* @param id Optional string that defines the Id of the new edge. If not set, the id is auto-generated when creating the vertex.
* @param value Object to be used as the user object which is generally used to display the label of the edge. The default implementation handles `string` object.
* @param source {@link Cell} that defines the source of the edge.
* @param target {@link Cell} that defines the target of the edge.
* @param style Optional object that defines the cell style.
*/
insertEdge(
parent: Cell | null,
id: string | null | undefined,
value: any,
source?: Cell | null,
target?: Cell | null,
style?: CellStyle
): Cell;
/**
* Adds a new edge into the given parent {@link Cell} using value as the user
* object and the given source and target as the terminals of the new edge.
* The id and style are used for the respective properties of the new
* {@link Cell}, which is returned.
*
* @param params the parameters used to create the new edge.
*/
insertEdge(params: EdgeParameters): Cell;
/**
* Hook method that creates the new edge for {@link insertEdge}. This
* implementation does not set the source and target of the edge, these
* are set when the edge is added to the model.
*
* @param parent {@link Cell} that specifies the parent of the new edge. If not set, use the default parent.
* @param id Optional string that defines the Id of the new edge. If not set, the id is auto-generated when creating the vertex.
* @param value Object to be used as the user object which is generally used to display the label of the edge. The default implementation handles `string` object.
* @param source {@link Cell} that defines the source of the edge.
* @param target {@link Cell} that defines the target of the edge.
* @param style Optional object that defines the cell style.
*/
createEdge: (
parent: Cell | null,
id: string,
value: any,
source: Cell | null,
target: Cell | null,
style: CellStyle
style?: CellStyle
) => Cell;
/**
* Adds the edge to the parent and connects it to the given source and
* target terminals. This is a shortcut method. Returns the edge that was
* added.
*
* @param edge {@link Cell} to be inserted into the given parent.
* @param parent {@link Cell} that represents the new parent. If no parent is
* given then the default parent is used.
* @param source Optional {@link Cell} that represents the source terminal.
* @param target Optional {@link Cell} that represents the target terminal.
* @param index Optional index to insert the cells at. Default is 'to append'.
*/
addEdge: (
edge: Cell,
parent: Cell | null,
@ -75,10 +239,55 @@ declare module '../Graph' {
target: Cell | null,
index?: number | null
) => Cell;
/**
* Returns an array with the given cells and all edges that are connected
* to a cell or one of its descendants.
*/
addAllEdges: (cells: Cell[]) => Cell[];
/**
* Returns all edges connected to the given cells or its descendants.
*/
getAllEdges: (cells: Cell[] | null) => Cell[];
/**
* Returns the visible incoming edges for the given cell. If the optional
* parent argument is specified, then only child edges of the given parent
* are returned.
*
* @param cell {@link mxCell} whose incoming edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
*/
getIncomingEdges: (cell: Cell, parent: Cell | null) => Cell[];
/**
* Returns the visible outgoing edges for the given cell. If the optional
* parent argument is specified, then only child edges of the given parent
* are returned.
*
* @param cell {@link mxCell} whose outgoing edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
*/
getOutgoingEdges: (cell: Cell, parent: Cell | null) => Cell[];
/**
* Returns the incoming and/or outgoing edges for the given cell.
* If the optional parent argument is specified, then only edges are returned
* where the opposite is in the given parent cell. If at least one of incoming
* or outgoing is true, then loops are ignored, if both are false, then all
* edges connected to the given cell are returned including loops.
*
* @param cell <Cell> whose edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
* @param incoming Optional boolean that specifies if incoming edges should
* be included in the result. Default is true.
* @param outgoing Optional boolean that specifies if outgoing edges should
* be included in the result. Default is true.
* @param includeLoops Optional boolean that specifies if loops should be
* included in the result. Default is true.
* @param recurse Optional boolean the specifies if the parent specified only
* need be an ancestral parent, true, or the direct parent, false.
* Default is false
*/
getEdges: (
cell: Cell,
parent?: Cell | null,
@ -87,9 +296,35 @@ declare module '../Graph' {
includeLoops?: boolean,
recurse?: boolean
) => Cell[];
/**
* Returns the visible child edges of the given parent.
*
* @param parent {@link mxCell} whose child vertices should be returned.
*/
getChildEdges: (parent: Cell) => Cell[];
/**
* Returns the edges between the given source and target. This takes into
* account collapsed and invisible cells and returns the connected edges
* as displayed on the screen.
*
* @param source
* @param target
* @param directed If set to true, only returns the directed edges i.e. edges whose source is `source` and target is `target`. Default is `false`.
*/
getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => Cell[];
/**
* Resets the control points of the edges that are connected to the given
* cells if not both ends of the edge are in the given cells array.
*
* @param cells Array of {@link Cell} for which the connected edges should be
* reset.
*/
resetEdges: (cells: Cell[]) => void;
/**
* Resets the control points of the given edge.
*
* @param edge {@link mxCell} whose points should be reset.
*/
resetEdge: (edge: Cell) => Cell;
}
}
@ -131,7 +366,6 @@ type PartialEdge = Pick<
| 'isCloneInvalidEdges'
| 'flipEdge'
| 'splitEdge'
| 'insertEdge'
| 'createEdge'
| 'addEdge'
| 'addAllEdges'
@ -143,174 +377,82 @@ type PartialEdge = Pick<
| 'getEdgesBetween'
| 'resetEdges'
| 'resetEdge'
>;
> & {
// handle the methods defined in the Graph interface with a single implementation
insertEdge: (...args: any[]) => Cell;
};
type PartialType = PartialGraph & PartialEdge;
// @ts-expect-error The properties of PartialGraph are defined elsewhere.
const EdgeMixin: PartialType = {
/**
* Specifies if edge control points should be reset after the resize of a
* connected cell.
* @default false
*/
resetEdgesOnResize: false,
isResetEdgesOnResize() {
return this.resetEdgesOnResize;
},
/**
* Specifies if edge control points should be reset after the move of a
* connected cell.
* @default false
*/
resetEdgesOnMove: false,
isResetEdgesOnMove() {
return this.resetEdgesOnMove;
},
/**
* Specifies if edge control points should be reset after the the edge has been
* reconnected.
* @default true
*/
resetEdgesOnConnect: true,
isResetEdgesOnConnect() {
return this.resetEdgesOnConnect;
},
/**
* Specifies if edges are connectable. This overrides the connectable field in edges.
* @default false
*/
connectableEdges: false,
/**
* Specifies if edges with disconnected terminals are allowed in the graph.
* @default true
*/
allowDanglingEdges: true,
/**
* Specifies if edges that are cloned should be validated and only inserted
* if they are valid.
* @default false
*/
cloneInvalidEdges: false,
/**
* Specifies the alternate edge style to be used if the main control point
* on an edge is being double clicked.
* @default {}
*/
alternateEdgeStyle: {},
/**
* Specifies the return value for edges in {@link isLabelMovable}.
* @default true
*/
edgeLabelsMovable: true,
/*****************************************************************************
* Group: Graph Behaviour
*****************************************************************************/
// ***************************************************************************
// Group: Graph Behaviour
// ***************************************************************************
/**
* Returns {@link edgeLabelsMovable}.
*/
isEdgeLabelsMovable() {
return this.edgeLabelsMovable;
},
/**
* Sets {@link edgeLabelsMovable}.
*/
setEdgeLabelsMovable(value) {
this.edgeLabelsMovable = value;
},
/**
* Specifies if dangling edges are allowed, that is, if edges are allowed
* that do not have a source and/or target terminal defined.
*
* @param value Boolean indicating if dangling edges are allowed.
*/
setAllowDanglingEdges(value) {
this.allowDanglingEdges = value;
},
/**
* Returns {@link allowDanglingEdges} as a boolean.
*/
isAllowDanglingEdges() {
return this.allowDanglingEdges;
},
/**
* Specifies if edges should be connectable.
*
* @param value Boolean indicating if edges should be connectable.
*/
setConnectableEdges(value) {
this.connectableEdges = value;
},
/**
* Returns {@link connectableEdges} as a boolean.
*/
isConnectableEdges() {
return this.connectableEdges;
},
/**
* Specifies if edges should be inserted when cloned but not valid wrt.
* {@link getEdgeValidationError}. If false such edges will be silently ignored.
*
* @param value Boolean indicating if cloned invalid edges should be
* inserted into the graph or ignored.
*/
setCloneInvalidEdges(value) {
this.cloneInvalidEdges = value;
},
/**
* Returns {@link cloneInvalidEdges} as a boolean.
*/
isCloneInvalidEdges() {
return this.cloneInvalidEdges;
},
/*****************************************************************************
* Group: Cell alignment and orientation
*****************************************************************************/
// ***************************************************************************
// Group: Cell alignment and orientation
// ***************************************************************************
/**
* Toggles the style of the given edge between null (or empty) and
* {@link alternateEdgeStyle}. This method fires {@link InternalEvent.FLIP_EDGE} while the
* transaction is in progress. Returns the edge that was flipped.
*
* Here is an example that overrides this implementation to invert the
* value of {@link 'elbow'} without removing any existing styles.
*
* ```javascript
* graph.flipEdge = function(edge)
* {
* if (edge != null)
* {
* var style = this.getCurrentCellStyle(edge);
* var elbow = mxUtils.getValue(style, 'elbow',
* mxConstants.ELBOW_HORIZONTAL);
* var value = (elbow == mxConstants.ELBOW_HORIZONTAL) ?
* mxConstants.ELBOW_VERTICAL : mxConstants.ELBOW_HORIZONTAL;
* this.setCellStyles('elbow', value, [edge]);
* }
* };
* ```
*
* @param edge {@link mxCell} whose style should be changed.
*/
flipEdge(edge) {
if (this.alternateEdgeStyle) {
this.batchUpdate(() => {
@ -330,22 +472,6 @@ const EdgeMixin: PartialType = {
return edge;
},
/**
* 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 {@link Event#SPLIT_EDGE} while the transaction
* is in progress. Returns the new edge that was inserted.
*
* @param edge <Cell> that represents the edge to be splitted.
* @param cells {@link Cells} that represents the cells to insert into the edge.
* @param newEdge <Cell> that represents the edge to be inserted.
* @param dx Optional integer that specifies the vector to move the cells.
* @param dy Optional integer that specifies the vector to move the cells.
* @param x Integer that specifies the x-coordinate of the drop location.
* @param y Integer that specifies the y-coordinate of the drop location.
* @param parent Optional parent to insert the cell. If null the parent of
* the edge is used.
*/
splitEdge(edge, cells, newEdge, dx = 0, dy = 0, x, y, parent = null) {
parent = parent ?? edge.getParent();
const source = edge.getTerminal(true);
@ -400,34 +526,19 @@ const EdgeMixin: PartialType = {
return newEdge as Cell;
},
/**
* Adds a new edge into the given parent {@link Cell} using value as the user
* object and the given source and target as the terminals of the new edge.
* The id and style are used for the respective properties of the new
* {@link Cell}, which is returned.
*
* @param parent {@link mxCell} that specifies the parent of the new edge.
* @param id Optional string that defines the Id of the new edge.
* @param value JavaScript object to be used as the user object.
* @param source {@link mxCell} that defines the source of the edge.
* @param target {@link mxCell} that defines the target of the edge.
* @param style Optional object that defines the cell style.
*/
insertEdge(...args) {
let parent: Cell;
let id = '';
let value: any; // note me - can be a string or a class instance!!!
let id: string;
let value: any;
let source: Cell;
let target: Cell;
let style: CellStyle;
if (args.length === 1) {
// If only a single parameter, treat as an object
// This syntax can be more readable
if (args.length === 1 && typeof args[0] === 'object') {
const params = args[0];
parent = params.parent;
id = params.id || '';
value = params.value || '';
id = params.id;
value = params.value;
source = params.source;
target = params.target;
style = params.style;
@ -436,19 +547,10 @@ const EdgeMixin: PartialType = {
[parent, id, value, source, target, style] = args;
}
if (typeof style === 'string')
throw new Error(`String-typed style is no longer supported: ${style}`);
const edge = this.createEdge(parent, id, value, source, target, style);
return this.addEdge(edge, parent, source, target);
},
/**
* Hook method that creates the new edge for {@link insertEdge}. This
* implementation does not set the source and target of the edge, these
* are set when the edge is added to the model.
*
*/
createEdge(
parent = null,
id,
@ -465,38 +567,19 @@ const EdgeMixin: PartialType = {
return edge;
},
/**
* Adds the edge to the parent and connects it to the given source and
* target terminals. This is a shortcut method. Returns the edge that was
* added.
*
* @param edge {@link mxCell} to be inserted into the given parent.
* @param parent {@link mxCell} that represents the new parent. If no parent is
* given then the default parent is used.
* @param source Optional {@link Cell} that represents the source terminal.
* @param target Optional {@link Cell} that represents the target terminal.
* @param index Optional index to insert the cells at. Default is 'to append'.
*/
addEdge(edge, parent = null, source = null, target = null, index = null) {
return this.addCell(edge, parent, index, source, target);
},
/*****************************************************************************
* Group: Folding
*****************************************************************************/
// ***************************************************************************
// Group: Folding
// ***************************************************************************
/**
* Returns an array with the given cells and all edges that are connected
* to a cell or one of its descendants.
*/
addAllEdges(cells) {
const allCells = cells.slice();
return removeDuplicates(allCells.concat(this.getAllEdges(cells)));
},
/**
* Returns all edges connected to the given cells or its descendants.
*/
getAllEdges(cells) {
let edges: Cell[] = [];
@ -516,52 +599,14 @@ const EdgeMixin: PartialType = {
return edges;
},
/**
* Returns the visible incoming edges for the given cell. If the optional
* parent argument is specified, then only child edges of the given parent
* are returned.
*
* @param cell {@link mxCell} whose incoming edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
*/
getIncomingEdges(cell, parent = null) {
return this.getEdges(cell, parent, true, false, false);
},
/**
* Returns the visible outgoing edges for the given cell. If the optional
* parent argument is specified, then only child edges of the given parent
* are returned.
*
* @param cell {@link mxCell} whose outgoing edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
*/
getOutgoingEdges(cell, parent = null) {
return this.getEdges(cell, parent, false, true, false);
},
/**
* Returns the incoming and/or outgoing edges for the given cell.
* If the optional parent argument is specified, then only edges are returned
* where the opposite is in the given parent cell. If at least one of incoming
* or outgoing is true, then loops are ignored, if both are false, then all
* edges connected to the given cell are returned including loops.
*
* @param cell <Cell> whose edges should be returned.
* @param parent Optional parent of the opposite end for an edge to be
* returned.
* @param incoming Optional boolean that specifies if incoming edges should
* be included in the result. Default is true.
* @param outgoing Optional boolean that specifies if outgoing edges should
* be included in the result. Default is true.
* @param includeLoops Optional boolean that specifies if loops should be
* included in the result. Default is true.
* @param recurse Optional boolean the specifies if the parent specified only
* need be an ancestral parent, true, or the direct parent, false.
* Default is false
*/
getEdges(
cell,
parent = null,
@ -611,28 +656,14 @@ const EdgeMixin: PartialType = {
return result;
},
/*****************************************************************************
* Group: Cell retrieval
*****************************************************************************/
// ***************************************************************************
// Group: Cell retrieval
// ***************************************************************************
/**
* Returns the visible child edges of the given parent.
*
* @param parent {@link mxCell} whose child vertices should be returned.
*/
getChildEdges(parent) {
return this.getChildCells(parent, false, true);
},
/**
* Returns the edges between the given source and target. This takes into
* account collapsed and invisible cells and returns the connected edges
* as displayed on the screen.
*
* source -
* target -
* directed -
*/
getEdgesBetween(source, target, directed = false) {
const edges = this.getEdges(source);
const result = [];
@ -659,17 +690,10 @@ const EdgeMixin: PartialType = {
return result;
},
/*****************************************************************************
* Group: Cell moving
*****************************************************************************/
// ***************************************************************************
// Group: Cell moving
// ***************************************************************************
/**
* Resets the control points of the edges that are connected to the given
* cells if not both ends of the edge are in the given cells array.
*
* @param cells Array of {@link Cell} for which the connected edges should be
* reset.
*/
resetEdges(cells) {
// Prepares faster cells lookup
const dict = new Dictionary();
@ -703,11 +727,6 @@ const EdgeMixin: PartialType = {
});
},
/**
* Resets the control points of the given edge.
*
* @param edge {@link mxCell} whose points should be reset.
*/
resetEdge(edge) {
let geo = edge.getGeometry();

View File

@ -19,8 +19,7 @@ import { Client, Graph, InternalEvent, RubberBandHandler } from '@maxgraph/core'
import { registerCustomShapes } from './custom-shapes';
// display the maxGraph version in the footer
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- the footer is present in index.html
const footer = document.querySelector<HTMLElement>('footer')!;
const footer = <HTMLElement>document.querySelector('footer');
footer.innerText = `Built with maxGraph ${Client.VERSION}`;
// Creates the graph inside the given container
@ -66,9 +65,10 @@ graph.batchUpdate(() => {
50,
{ fillColor: 'orange', shape: 'ellipse', verticalLabelPosition: 'bottom' }
);
// use the legacy insertEdge method
graph.insertEdge(parent, null, 'a regular edge', vertex01, vertex02);
// insert vertices using custom shapes using the new insertVertex method
// insert vertex using custom shapes using the new insertVertex method
const vertex11 = graph.insertVertex({
parent,
value: 'a custom rectangle',
@ -89,5 +89,12 @@ graph.batchUpdate(() => {
verticalLabelPosition: 'bottom',
},
});
graph.insertEdge(parent, null, 'another edge', vertex11, vertex12);
// use the new insertEdge method
graph.insertEdge({
parent,
value: 'another edge',
source: vertex11,
target: vertex12,
style: { endArrow: 'block', rounded: true },
});
});