diff --git a/packages/core/__tests__/util/styleUtils.test.ts b/packages/core/__tests__/util/styleUtils.test.ts index a3f0d2c390..b4f85bb6a8 100644 --- a/packages/core/__tests__/util/styleUtils.test.ts +++ b/packages/core/__tests__/util/styleUtils.test.ts @@ -22,7 +22,7 @@ import { setCellStyles, } from '../../src/util/styleUtils'; import { FONT } from '../../src/util/Constants'; -import { type CellStyle } from '../../src/types'; +import { type CellStyle, BaseGraph } from '../../src'; import { createGraphWithoutPlugins } from '../utils'; describe('parseCssNumber', () => { @@ -122,10 +122,11 @@ describe('setStyleFlag', () => { }); }); -test('setCellStyleFlags on vertex', () => { - // Need a graph to have a view and ensure that the cell state is updated - const graph = createGraphWithoutPlugins(); - +// In this test, we need a graph to have a view and ensure that the cell state is updated +test.each([ + ['BaseGraph', new BaseGraph()], + ['Graph', createGraphWithoutPlugins()], +])('setCellStyleFlags on vertex using %s', (_name, graph) => { const style: CellStyle = { fontStyle: 4, spacing: 8 }; const cell = graph.insertVertex({ value: 'a value', @@ -141,10 +142,11 @@ test('setCellStyleFlags on vertex', () => { expect(graph.getView().getState(cell)?.style?.fontStyle).toBe(5); }); -test('setCellStyles on vertex', () => { - // Need a graph to have a view and ensure that the cell state is updated - const graph = createGraphWithoutPlugins(); - +// In this test, we need a graph to have a view and ensure that the cell state is updated +test.each([ + ['BaseGraph', new BaseGraph()], + ['Graph', createGraphWithoutPlugins()], +])('setCellStyles on vertex using %s', (_name, graph) => { const style: CellStyle = { strokeColor: 'yellow', labelWidth: 100 }; const cell = graph.insertVertex({ value: 'a value', diff --git a/packages/core/__tests__/utils.ts b/packages/core/__tests__/utils.ts index 9582145c13..037e836fcc 100644 --- a/packages/core/__tests__/utils.ts +++ b/packages/core/__tests__/utils.ts @@ -17,9 +17,16 @@ limitations under the License. import { Cell, type CellStateStyle, Graph } from '../src'; import { jest } from '@jest/globals'; -// no need for a container, we don't check the view here +/** + * Creates a new {@link Graph} without `container` (use the default value of the parameters). + * + * This is useful when tests don't check the view. + */ export const createGraphWithoutContainer = (): Graph => new Graph(); +/** + * Creates a new {@link Graph} without any plugins (pass an empty array of plugins). + */ export const createGraphWithoutPlugins = (): Graph => new Graph(undefined, undefined, []); export const createCellWithStyle = (style: CellStateStyle): Cell => { diff --git a/packages/core/__tests__/view/Graph.test.ts b/packages/core/__tests__/view/Graph.test.ts index bac2838a9b..8f6cfa9fe1 100644 --- a/packages/core/__tests__/view/Graph.test.ts +++ b/packages/core/__tests__/view/Graph.test.ts @@ -16,17 +16,19 @@ limitations under the License. import { describe, expect, test } from '@jest/globals'; import { + AbstractGraph, Cell, CellState, + EdgeHandler, EdgeSegmentHandler, EdgeStyle, ElbowEdgeHandler, Point, Rectangle, RectangleShape, + VertexHandler, } from '../../src'; import { createGraphWithoutPlugins } from '../utils'; -import EdgeHandler from '../../src/view/handler/EdgeHandler'; describe('isOrthogonal', () => { test('Style of the CellState, orthogonal: true', () => { @@ -66,6 +68,16 @@ describe('isOrthogonal', () => { }); }); +function createCellState(graph: AbstractGraph, isEdge: boolean): CellState { + const cell = new Cell(); + cell.setEdge(isEdge); + cell.setVertex(!isEdge); + const cellState = new CellState(graph.view, cell, {}); + cellState.absolutePoints = [new Point(0, 0)]; + cellState.shape = new RectangleShape(new Rectangle(), 'green', 'blue'); + return cellState; +} + describe('createEdgeHandler', () => { test.each([ ['ElbowConnector', EdgeStyle.ElbowConnector], @@ -74,8 +86,7 @@ describe('createEdgeHandler', () => { ['TopToBottom', EdgeStyle.TopToBottom], ])('Expect ElbowEdgeHandler for edgeStyle: %s', (_name, edgeStyle) => { const graph = createGraphWithoutPlugins(); - const cellState = new CellState(graph.view, new Cell(), {}); - cellState.shape = new RectangleShape(new Rectangle(), 'green', 'blue'); + const cellState = createCellState(graph, true); expect(graph.createEdgeHandler(cellState, edgeStyle)).toBeInstanceOf( ElbowEdgeHandler ); @@ -87,9 +98,7 @@ describe('createEdgeHandler', () => { ['SegmentConnector', EdgeStyle.SegmentConnector], ])('Expect EdgeSegmentHandler for edgeStyle: %s', (_name, edgeStyle) => { const graph = createGraphWithoutPlugins(); - const cellState = new CellState(graph.view, new Cell(), {}); - cellState.absolutePoints = [new Point(0, 0)]; - cellState.shape = new RectangleShape(new Rectangle(), 'green', 'blue'); + const cellState = createCellState(graph, true); expect(graph.createEdgeHandler(cellState, edgeStyle)).toBeInstanceOf( EdgeSegmentHandler ); @@ -100,8 +109,21 @@ describe('createEdgeHandler', () => { ['null', null], ])('Expect EdgeHandler for edgeStyle: %s', (_name, edgeStyle) => { const graph = createGraphWithoutPlugins(); - const cellState = new CellState(graph.view, new Cell(), {}); - cellState.shape = new RectangleShape(new Rectangle(), 'green', 'blue'); + const cellState = createCellState(graph, true); expect(graph.createEdgeHandler(cellState, edgeStyle)).toBeInstanceOf(EdgeHandler); }); }); + +describe('createHandler', () => { + test('Expect VertexHandler', () => { + const graph = createGraphWithoutPlugins(); + const cellState = createCellState(graph, false); + expect(graph.createHandler(cellState)).toBeInstanceOf(VertexHandler); + }); + + test('Expect EdgeHandler', () => { + const graph = createGraphWithoutPlugins(); + const cellState = createCellState(graph, true); + expect(graph.createHandler(cellState)).toBeInstanceOf(EdgeHandler); + }); +}); diff --git a/packages/core/src/editor/Editor.ts b/packages/core/src/editor/Editor.ts index 229aca84c1..4e23ce7096 100644 --- a/packages/core/src/editor/Editor.ts +++ b/packages/core/src/editor/Editor.ts @@ -34,6 +34,7 @@ import Outline from '../view/other/Outline'; import Cell from '../view/cell/Cell'; import Geometry from '../view/geometry/Geometry'; import { ALIGN, FONT } from '../util/Constants'; +import type { AbstractGraph } from '../view/AbstractGraph'; import { Graph } from '../view/Graph'; import SwimlaneManager from '../view/layout/SwimlaneManager'; import LayoutManager from '../view/layout/LayoutManager'; @@ -505,15 +506,13 @@ export class Editor extends EventSource { outline: any = null; /** - * Holds a {@link graph} for displaying the diagram. The graph - * is created in {@link setGraphContainer}. + * Holds a {@link AbstractGraph} for displaying the diagram. The graph is created in {@link setGraphContainer}. */ // @ts-ignore - graph: Graph; + graph: AbstractGraph; /** - * Holds the render hint used for creating the - * graph in {@link setGraphContainer}. See {@link graph}. Default is null. + * Holds the render hint used for creating the {@link graph} in {@link setGraphContainer}. * @default null */ graphRenderHint: any = null; @@ -640,7 +639,7 @@ export class Editor extends EventSource { defaultGroup: any = null; /** - * Default size for the border of new groups. If `null`, then {@link Graph.gridSize} is used. + * Default size for the border of new groups. If `null`, then {@link AbstractGraph.gridSize} is used. * @default null */ groupBorderSize: number | null = null; @@ -843,7 +842,7 @@ export class Editor extends EventSource { movePropertiesDialog = false; /** - * Specifies if {@link Graph.validateGraph} should automatically be invoked after + * Specifies if {@link AbstractGraph.validateGraph} should automatically be invoked after * each change. Default is false. * @default false */ @@ -1387,12 +1386,13 @@ export class Editor extends EventSource { } /** - * Creates the {@link graph} for the editor. + * Creates the {@link AbstractGraph} for the editor. * - * The graph is created with no container and is initialized from {@link setGraphContainer}. - * @returns graph instance + * The AbstractGraph is created with no container and is initialized from {@link setGraphContainer}. + * + * @returns the AbstractGraph instance used by the Editor */ - createGraph(): Graph { + createGraph(): AbstractGraph { const graph = new Graph(); // Enables rubberband, tooltips, panning @@ -1445,11 +1445,11 @@ export class Editor extends EventSource { } /** - * Sets the graph's container using [@link mxGraph.init}. + * Sets the graph's container using {@link AbstractGraph.init}. * @param graph * @returns SwimlaneManager instance */ - createSwimlaneManager(graph: Graph): SwimlaneManager { + createSwimlaneManager(graph: AbstractGraph): SwimlaneManager { const swimlaneMgr = new SwimlaneManager(graph, false); swimlaneMgr.isHorizontal = () => { @@ -1465,11 +1465,11 @@ export class Editor extends EventSource { /** * Creates a layout manager for the swimlane and diagram layouts, that - * is, the locally defined inter and intraswimlane layouts. + * is, the locally defined inter and intra swimlane layouts. * @param graph * @returns LayoutManager instance */ - createLayoutManager(graph: Graph): LayoutManager { + createLayoutManager(graph: AbstractGraph): LayoutManager { const layoutMgr = new LayoutManager(graph); layoutMgr.getLayout = (cell: Cell) => { @@ -1510,13 +1510,13 @@ export class Editor extends EventSource { } /** - * Sets the graph's container using {@link graph.init}. + * Sets the graph's container using {@link AbstractGraph.init}. * @param container */ setGraphContainer(container?: HTMLElement | null): void { if (!this.graph.container && container) { // Creates the graph instance inside the given container and render hint - // this.graph = new mxGraph(container, null, this.graphRenderHint); + // this.graph = new Graph(container, null, this.graphRenderHint); // @ts-ignore TODO: FIXME!! ============================================================================================== this.graph.init(container); @@ -1533,11 +1533,11 @@ export class Editor extends EventSource { } /** - * Overrides {@link graph.dblClick} to invoke {@link dblClickAction} + * Overrides {@link AbstractGraph.dblClick} to invoke {@link dblClickAction} * on a cell and reset the selection tool in the toolbar. * @param graph */ - installDblClickHandler(graph: Graph): void { + installDblClickHandler(graph: AbstractGraph): void { // Installs a listener for double click events graph.addListener(InternalEvent.DOUBLE_CLICK, (sender: any, evt: EventObject) => { const cell = evt.getProperty('cell'); @@ -1553,7 +1553,7 @@ export class Editor extends EventSource { * Adds the {@link undoManager} to the graph model and the view. * @param graph */ - installUndoHandler(graph: Graph): void { + installUndoHandler(graph: AbstractGraph): void { const listener = (sender: any, evt: EventObject) => { const edit = evt.getProperty('edit'); (this.undoManager).undoableEditHappened(edit); @@ -1576,7 +1576,7 @@ export class Editor extends EventSource { * Installs listeners for dispatching the {@link root} event. * @param graph */ - installDrillHandler(graph: Graph): void { + installDrillHandler(graph: AbstractGraph): void { const listener = (sender: any) => { this.fireEvent(new EventObject(InternalEvent.ROOT)); }; @@ -1591,7 +1591,7 @@ export class Editor extends EventSource { * fires a {@link root} event. * @param graph */ - installChangeHandler(graph: Graph): void { + installChangeHandler(graph: AbstractGraph): void { const listener = (sender: any, evt: EventObject) => { // Updates the modified state this.setModified(true); @@ -1624,7 +1624,7 @@ export class Editor extends EventSource { * Installs the handler for invoking {@link insertFunction} if one is defined. * @param graph */ - installInsertHandler(graph: Graph): void { + installInsertHandler(graph: AbstractGraph): void { const insertHandler: MouseListenerSet = { mouseDown: (_sender: EventSource, me: InternalMouseEvent) => { if ( @@ -1791,7 +1791,7 @@ export class Editor extends EventSource { } /** - * Returns the string value of the root cell in {@link graph.model}. + * Returns the string value of the root cell in {@link AbstractGraph.model}. */ getRootTitle(): string { const root = this.graph.getDataModel().getRoot()!; @@ -1814,7 +1814,7 @@ export class Editor extends EventSource { /** * Invokes {@link createGroup} to create a new group cell and the invokes - * {@link graph.groupCells}, using the grid size of the graph as the spacing + * {@link AbstractGraph.groupCells}, using the grid size of the graph as the spacing * in the group's content area. */ groupCells(): any { diff --git a/packages/core/src/editor/EditorToolbar.ts b/packages/core/src/editor/EditorToolbar.ts index 322a306813..c6e11ee493 100644 --- a/packages/core/src/editor/EditorToolbar.ts +++ b/packages/core/src/editor/EditorToolbar.ts @@ -25,7 +25,7 @@ import { getClientX, getClientY } from '../util/EventUtils'; import { makeDraggable } from '../util/gestureUtils'; import Editor from './Editor'; import type Cell from '../view/cell/Cell'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; import EventObject from '../view/event/EventObject'; import type { DropHandler } from '../view/other/DragSource'; @@ -300,10 +300,9 @@ export class EditorToolbar { toggle ); - // Creates a wrapper function that calls the click handler without - // the graph argument + // Creates a wrapper function that calls the click handler without the graph argument const dropHandler: DropHandler = ( - graph: Graph, + _graph: AbstractGraph, evt: MouseEvent, cell: Cell | null ) => { diff --git a/packages/core/src/i18n/Translations.ts b/packages/core/src/i18n/Translations.ts index 30a17aea16..43361128c7 100644 --- a/packages/core/src/i18n/Translations.ts +++ b/packages/core/src/i18n/Translations.ts @@ -73,7 +73,7 @@ import { I18nProvider } from '../types'; * * ## Loading default resources * - * Call {@link loadResources} to load the default resources file for both {@link Graph} and {@link Editor}. + * Call {@link loadResources} to load the default resources file for both {@link AbstractGraph} and {@link Editor}. * * @category I18n */ diff --git a/packages/core/src/i18n/config.ts b/packages/core/src/i18n/config.ts index 47c35e6fd9..28968f3672 100644 --- a/packages/core/src/i18n/config.ts +++ b/packages/core/src/i18n/config.ts @@ -88,9 +88,9 @@ export const TranslationsConfig = { * - {@link Editor.propertiesResource} * - {@link Editor.tasksResource} * - {@link ElbowEdgeHandler.doubleClickOrientationResource} - * - {@link Graph.alreadyConnectedResource}. - * - {@link Graph.collapseExpandResource} - * - {@link Graph.containsValidationErrorsResource} and + * - {@link AbstractGraph.alreadyConnectedResource}. + * - {@link AbstractGraph.collapseExpandResource} + * - {@link AbstractGraph.containsValidationErrorsResource} and * - {@link GraphSelectionModel.doneResource} * - {@link GraphSelectionModel.updatingSelectionResource} * - {@link GraphView.doneResource} diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index d0b7aef9b0..41b484dc8f 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -17,6 +17,8 @@ limitations under the License. // Contribution of Mixins to the Graph type (no side effects, types only) import './view/mixins/_graph-mixins-types'; +export { AbstractGraph } from './view/AbstractGraph'; +export { BaseGraph } from './view/BaseGraph'; export { Graph } from './view/Graph'; export * from './view/plugins'; diff --git a/packages/core/src/serialization/codecs/GraphViewCodec.ts b/packages/core/src/serialization/codecs/GraphViewCodec.ts index 2cbcf44b02..96987820ed 100644 --- a/packages/core/src/serialization/codecs/GraphViewCodec.ts +++ b/packages/core/src/serialization/codecs/GraphViewCodec.ts @@ -51,7 +51,7 @@ export class GraphViewCodec extends ObjectCodec { * If {@link Cell.isEdge} returns `true` for the cell, then edge is used for the node name, else if {@link Cell.isVertex} returns `true` for the cell, * then vertex is used for the node name. * - * {@link Graph.getLabel} is used to create the label attribute for the cell. + * {@link AbstractGraph.getLabel} is used to create the label attribute for the cell. * For graph nodes and vertices the bounds are encoded into x, y, width and height. * For edges the points are encoded into a points attribute as a space-separated list of comma-separated coordinate pairs (e.g. x0,y0 x1,y1 ... xn,yn). * All values from the cell style are added as attribute values to the node. diff --git a/packages/core/src/serialization/codecs/editor/EditorToolbarCodec.ts b/packages/core/src/serialization/codecs/editor/EditorToolbarCodec.ts index a79111a175..2475fa48b1 100644 --- a/packages/core/src/serialization/codecs/editor/EditorToolbarCodec.ts +++ b/packages/core/src/serialization/codecs/editor/EditorToolbarCodec.ts @@ -89,7 +89,7 @@ export class EditorToolbarCodec extends ObjectCodec { * ``` * * In the above function, editor is the enclosing {@link Editor} instance, cell is the clone of the template, evt is the mouse event that represents the - * drop and targetCell is the cell under the mouse pointer where the drop occurred. The targetCell is retrieved using {@link Graph#getCellAt}. + * drop and targetCell is the cell under the mouse pointer where the drop occurred. The targetCell is retrieved using {@link AbstractGraph.getCellAt}. * * Furthermore, nodes with the mode attribute may define a function to be executed upon selection of the respective toolbar icon. In the * example below, the default edge style is set when this specific diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index de79b71bca..7c991b60ac 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -14,8 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { IDENTITY_FIELD_NAME } from './util/Constants'; -import type { Graph } from './view/Graph'; +import type { IDENTITY_FIELD_NAME } from './util/Constants'; +import type { AbstractGraph } from './view/AbstractGraph'; import type AbstractCanvas2D from './view/canvas/AbstractCanvas2D'; import type Cell from './view/cell/Cell'; import type CellState from './view/cell/CellState'; @@ -26,6 +26,11 @@ import type Point from './view/geometry/Point'; import type Rectangle from './view/geometry/Rectangle'; import type Shape from './view/geometry/Shape'; import type ImageBox from './view/image/ImageBox'; +import type CellRenderer from './view/cell/CellRenderer'; +import type GraphDataModel from './view/GraphDataModel'; +import type { Stylesheet } from './view/style/Stylesheet'; +import type GraphSelectionModel from './view/GraphSelectionModel'; +import type GraphView from './view/GraphView'; export type FilterFunction = (cell: Cell) => boolean; @@ -121,7 +126,7 @@ export type CellStateStyle = { * This specifies if a cell should be resized automatically if its value changed. * This is normally combined with {@link resizable} to disable manual resizing. * - * Note that a cell is in fact auto-resizable according to the value returned by {@link Graph.isAutoSizeCell}. + * Note that a cell is in fact auto-resizable according to the value returned by {@link AbstractGraph.isAutoSizeCell}. * @default false */ autoSize?: boolean; @@ -133,14 +138,14 @@ export type CellStateStyle = { /** * This specifies if the control points of an edge can be moved. * - * Note that a cell is in fact bendable according to the value returned by {@link Graph.isCellBendable}. + * Note that a cell is in fact bendable according to the value returned by {@link AbstractGraph.isCellBendable}. * @default true */ bendable?: boolean; /** * This specifies if a cell can be cloned. * - * Note that a cell is in fact cloneable according to the value returned by {@link Graph.isCellCloneable}. + * Note that a cell is in fact cloneable according to the value returned by {@link AbstractGraph.isCellCloneable}. * @default true */ cloneable?: boolean; @@ -167,7 +172,7 @@ export type CellStateStyle = { /** * This specifies if a cell can be deleted. * - * Note that a cell is in fact deletable according to the value returned by {@link Graph.isCellDeletable}. + * Note that a cell is in fact deletable according to the value returned by {@link AbstractGraph.isCellDeletable}. * @default true */ deletable?: boolean; @@ -190,7 +195,7 @@ export type CellStateStyle = { /** * This specifies if the value of a cell can be edited using the in-place editor. * - * Note that a cell is in fact editable according to the value returned by {@link Graph.isCellEditable}. + * Note that a cell is in fact editable according to the value returned by {@link AbstractGraph.isCellEditable}. * @default true */ editable?: boolean; @@ -309,7 +314,7 @@ export type CellStateStyle = { flipV?: boolean; /** * This specifies if a cell is foldable using a folding icon. - * See {@link Graph.isCellFoldable}. + * See {@link AbstractGraph.isCellFoldable}. * @default true */ foldable?: boolean; @@ -485,7 +490,7 @@ export type CellStateStyle = { * The possible values are the functions defined in {@link EdgeStyle}. * * See {@link edgeStyle}. - * See {@link Graph.defaultLoopStyle}. + * See {@link AbstractGraph.defaultLoopStyle}. */ loopStyle?: EdgeStyleFunction; /** @@ -497,7 +502,7 @@ export type CellStateStyle = { /** * This specifies if a cell can be moved. * - * Note that a cell is in fact movable according to the value returned by {@link Graph.isCellMovable}. + * Note that a cell is in fact movable according to the value returned by {@link AbstractGraph.isCellMovable}. * @default true */ movable?: boolean; @@ -521,10 +526,10 @@ export type CellStateStyle = { * the edge is vertical or horizontal if possible and if the point is not at a fixed location. * The computation of the connection points involves the {@link perimeter}. * - * This is used in {@link Graph.isOrthogonal}, which is in charge of determining if the edge terminals should be orthogonal. + * This is used in {@link AbstractGraph.isOrthogonal}, which is in charge of determining if the edge terminals should be orthogonal. * * If the {@link orthogonal} property is not explicitly set but the {@link edgeStyle} belongs to one of the "orthogonal" `EdgeStyle` connectors, - * for example when using {@link EdgeStyle.SegmentConnector} or {@link EdgeStyle.EntityRelation}, the {@link Graph.isOrthogonal} method which also returns `true`. + * for example when using {@link EdgeStyle.SegmentConnector} or {@link EdgeStyle.EntityRelation}, the {@link AbstractGraph.isOrthogonal} method which also returns `true`. * @default undefined */ orthogonal?: boolean | null; @@ -542,7 +547,7 @@ export type CellStateStyle = { * - A value of 'fill' will use the vertex bounds. * - A value of 'width' will use the vertex width for the label. * - * See {@link Graph.isLabelClipped}. + * See {@link AbstractGraph.isLabelClipped}. * * Note that the vertical alignment is ignored for overflow filling and for horizontal * alignment. @@ -600,7 +605,7 @@ export type CellStateStyle = { /** * This specifies if a cell can be resized. * - * Note that a cell is in fact resizable according to the value returned by {@link Graph.isCellResizable}. + * Note that a cell is in fact resizable according to the value returned by {@link AbstractGraph.isCellResizable}. * @default true */ resizable?: boolean; @@ -621,7 +626,7 @@ export type CellStateStyle = { /** * This specifies if a cell can be rotated. * - * Note that a cell is in fact rotatable according to the value returned by {@link Graph.isCellRotatable}. + * Note that a cell is in fact rotatable according to the value returned by {@link AbstractGraph.isCellRotatable}. * @default true */ rotatable?: boolean; @@ -1102,7 +1107,7 @@ export type VertexParameters = { /** @category Plugin */ export interface GraphPluginConstructor { pluginId: string; - new (graph: Graph): GraphPlugin; + new (graph: AbstractGraph): GraphPlugin; } /** @category Plugin */ @@ -1346,6 +1351,9 @@ export interface I18nProvider { ): void; } +/** + * @category Graph + */ export type GraphFoldingOptions = { /** * Specifies if folding (collapse and expand via an image icon in the graph should be enabled). @@ -1373,3 +1381,28 @@ export type GraphFoldingOptions = { * @since 0.18.0 */ export type ShapeConstructor = new (...arguments_: any) => Shape; + +/** + * Options passed to the {@link AbstractGraph} constructor. + * + * @since 0.18.0 + * @category Graph + */ +export type GraphOptions = { + container?: HTMLElement; + plugins?: GraphPluginConstructor[]; +} & GraphCollaboratorsOptions; + +/** + * Collaborators injected in the {@link AbstractGraph} when it is instantiated. + * + * @since 0.18.0 + * @category Graph + */ +export type GraphCollaboratorsOptions = { + cellRenderer?: CellRenderer; + model?: GraphDataModel; + selectionModel?: (graph: AbstractGraph) => GraphSelectionModel; + stylesheet?: Stylesheet; + view?: (graph: AbstractGraph) => GraphView; +}; diff --git a/packages/core/src/util/Clipboard.ts b/packages/core/src/util/Clipboard.ts index 38cae2741e..d67828486d 100644 --- a/packages/core/src/util/Clipboard.ts +++ b/packages/core/src/util/Clipboard.ts @@ -17,7 +17,7 @@ limitations under the License. */ import type Cell from '../view/cell/Cell'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; import { getTopmostCells } from './cellArrayUtils'; /** @@ -31,7 +31,7 @@ import { getTopmostCells } from './cellArrayUtils'; * Clipboard.paste(graph2); * ``` * - * For fine-grained control of the clipboard data the {@link Graph.canExportCell} and {@link Graph.canImportCell} functions can be overridden. + * For fine-grained control of the clipboard data the {@link AbstractGraph.canExportCell} and {@link AbstractGraph.canImportCell} functions can be overridden. * * To restore previous parents for pasted cells, the implementation for {@link copy} and {@link paste} can be changed as follows. * @@ -119,11 +119,11 @@ class Clipboard { * Cuts the given array of {@link Cell} from the specified graph. * If {@link cells} is `null` then the selection cells of the graph will be used. * - * @param graph - {@link graph} that contains the cells to be cut. + * @param graph - {@link AbstractGraph} that contains the cells to be cut. * @param cells - Optional array of {@link Cell} to be cut. * @returns Returns the cells that have been cut from the graph. */ - static cut(graph: Graph, cells: Cell[] = []): Cell[] { + static cut(graph: AbstractGraph, cells: Cell[] = []): Cell[] { cells = Clipboard.copy(graph, cells); Clipboard.insertCount = 0; Clipboard.removeCells(graph, cells); @@ -134,10 +134,10 @@ class Clipboard { /** * Hook to remove the given cells from the given graph after a cut operation. * - * @param graph - {@link graph} that contains the cells to be cut. + * @param graph - {@link AbstractGraph} that contains the cells to be cut. * @param cells - Array of {@link Cell} to be cut. */ - static removeCells(graph: Graph, cells: Cell[]): void { + static removeCells(graph: AbstractGraph, cells: Cell[]): void { graph.removeCells(cells); } @@ -146,10 +146,10 @@ class Clipboard { * Returns the original array of cells that has been cloned. * Descendants of cells in the array are ignored. * - * @param graph - {@link graph} that contains the cells to be copied. + * @param graph - {@link AbstractGraph} that contains the cells to be copied. * @param cells - Optional array of {@link Cell} to be copied. */ - static copy(graph: Graph, cells?: Cell[]): Cell[] { + static copy(graph: AbstractGraph, cells?: Cell[]): Cell[] { cells = cells || graph.getSelectionCells(); const result = getTopmostCells(graph.getExportableCells(cells)); Clipboard.insertCount = 1; @@ -160,11 +160,11 @@ class Clipboard { /** * Pastes the {@link Cell}s into the specified graph associating them to the default parent. - * The cells are added to the graph using {@link graph.importCells} and returned. + * The cells are added to the graph using {@link AbstractGraph.importCells} and returned. * - * @param graph - {@link Graph} to paste the {@link Cell}s into. + * @param graph - {@link AbstractGraph} to paste the {@link Cell}s into. */ - static paste(graph: Graph): Cell[] | null { + static paste(graph: AbstractGraph): Cell[] | null { let cells = null; if (!Clipboard.isEmpty() && Clipboard.getCells()) { diff --git a/packages/core/src/util/gestureUtils.ts b/packages/core/src/util/gestureUtils.ts index d25e295262..b9d9bc71bd 100644 --- a/packages/core/src/util/gestureUtils.ts +++ b/packages/core/src/util/gestureUtils.ts @@ -17,14 +17,14 @@ limitations under the License. import DragSource, { DropHandler } from '../view/other/DragSource'; import Point from '../view/geometry/Point'; import { TOOLTIP_VERTICAL_OFFSET } from './Constants'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; import type Cell from '../view/cell/Cell'; /** * Configures the given DOM element to act as a drag source for the - * specified graph. Returns a a new {@link DragSource}. If - * {@link DragSource#guideEnabled} is enabled then the x and y arguments must - * be used in funct to match the preview location. + * specified graph. Returns a new {@link DragSource}. If + * {@link DragSource.guidesEnabled} is enabled then the x and y arguments must + * be used in `funct` to match the preview location. * * Example: * @@ -66,8 +66,8 @@ import type Cell from '../view/cell/Cell'; * ``` * * @param element DOM element to make draggable. - * @param graphF {@link Graph} that acts as the drop target or a function that takes a - * mouse event and returns the current {@link Graph}. + * @param graphF {@link AbstractGraph} that acts as the drop target or a function that takes a + * mouse event and returns the current {@link AbstractGraph}. * @param funct Function to execute on a successful drop. * @param dragElement Optional DOM node to be used for the drag preview. * @param dx Optional horizontal offset between the cursor and the drag @@ -75,18 +75,18 @@ import type Cell from '../view/cell/Cell'; * @param dy Optional vertical offset between the cursor and the drag * preview. * @param autoscroll Optional boolean that specifies if autoscroll should be - * used. Default is {@link Graph.autoscroll}. + * used. Default is {@link AbstractGraph.autoscroll}. * @param scalePreview Optional boolean that specifies if the preview element * should be scaled according to the graph scale. If this is true, then * the offsets will also be scaled. Default is false. * @param highlightDropTargets Optional boolean that specifies if dropTargets * should be highlighted. Default is true. * @param getDropTarget Optional function to return the drop target for a given - * location (x, y). Default is {@link Graph.getCellAt}. + * location (x, y). Default is {@link AbstractGraph.getCellAt}. */ export const makeDraggable = ( element: Element, - graphF: Graph | Function, + graphF: AbstractGraph | Function, funct: DropHandler, dragElement: Element | null = null, dx: number | null = null, @@ -95,7 +95,7 @@ export const makeDraggable = ( scalePreview = false, highlightDropTargets = true, getDropTarget: - | ((graph: Graph, x: number, y: number, evt: MouseEvent) => Cell) + | ((graph: AbstractGraph, x: number, y: number, evt: MouseEvent) => Cell) | null = null ) => { const dragSource = new DragSource(element, funct); diff --git a/packages/core/src/util/printUtils.ts b/packages/core/src/util/printUtils.ts index 48922c2856..e9081fc51b 100644 --- a/packages/core/src/util/printUtils.ts +++ b/packages/core/src/util/printUtils.ts @@ -20,7 +20,7 @@ import Client from '../Client'; import { PAGE_FORMAT_A4_PORTRAIT } from './Constants'; import Rectangle from '../view/geometry/Rectangle'; import { getOuterHtml } from './domUtils'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; import { removeCursors } from './styleUtils'; /** @@ -30,14 +30,14 @@ import { removeCursors } from './styleUtils'; * pages in the print output. See {@link PrintPreview} for an example. * * @param pageCount Specifies the number of pages in the print output. - * @param graph {@link Graph} that should be printed. + * @param graph {@link AbstractGraph} that should be printed. * @param pageFormat Optional {@link Rectangle} that specifies the page format. * Default is . * @param border The border along each side of every page. */ export const getScaleForPageCount = ( pageCount: number, - graph: Graph, + graph: AbstractGraph, pageFormat?: Rectangle, border = 0 ) => { @@ -162,7 +162,7 @@ export const getScaleForPageCount = ( * If you experience problems with missing stylesheets in IE then try adding * the domain to the trusted sites. * - * @param graph {@link Graph} to be copied. + * @param graph {@link AbstractGraph} to be copied. * @param doc Document where the new graph is created. * @param x0 X-coordinate of the graph view origin. Default is 0. * @param y0 Y-coordinate of the graph view origin. Default is 0. @@ -170,7 +170,7 @@ export const getScaleForPageCount = ( * @param h Optional height of the graph view. */ export const show = ( - graph: Graph, + graph: AbstractGraph, doc: Document | null = null, x0 = 0, y0 = 0, @@ -279,9 +279,9 @@ export const show = ( * * This function should be called from within the document with the graph. * - * @param graph {@link Graph} to be printed. + * @param graph {@link AbstractGraph} to be printed. */ -export const printScreen = (graph: Graph) => { +export const printScreen = (graph: AbstractGraph) => { const wnd = window.open(); if (!wnd) return; diff --git a/packages/core/src/util/treeTraversal.ts b/packages/core/src/util/treeTraversal.ts index 98cd5a385d..b43f135c74 100644 --- a/packages/core/src/util/treeTraversal.ts +++ b/packages/core/src/util/treeTraversal.ts @@ -16,7 +16,7 @@ limitations under the License. import type Cell from '../view/cell/Cell'; import Dictionary from './Dictionary'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; /***************************************************************************** * Group: Tree and traversal-related @@ -27,6 +27,7 @@ import type { Graph } from '../view/Graph'; * edges. If the result is empty then the with the greatest difference * between incoming and outgoing edges is returned. * + * @param graph the Graph to use for the traversal. * @param parent {@link Cell} whose children should be checked. * @param isolate Optional boolean that specifies if edges should be ignored if * the opposite end is not a child of the given parent cell. Default is @@ -36,7 +37,7 @@ import type { Graph } from '../view/Graph'; * counted. Default is `false`. */ export function findTreeRoots( - graph: Graph, + graph: AbstractGraph, parent: Cell, isolate = false, invert = false diff --git a/packages/core/src/util/xmlUtils.ts b/packages/core/src/util/xmlUtils.ts index 6240b3ac3d..a57ca31dbe 100644 --- a/packages/core/src/util/xmlUtils.ts +++ b/packages/core/src/util/xmlUtils.ts @@ -19,7 +19,7 @@ limitations under the License. import { DIALECT, NODETYPE, NS_SVG } from './Constants'; import Point from '../view/geometry/Point'; import type Cell from '../view/cell/Cell'; -import type { Graph } from '../view/Graph'; +import type { AbstractGraph } from '../view/AbstractGraph'; import { htmlEntities, trim } from './StringUtils'; import TemporaryCellStates from '../view/cell/TemporaryCellStates'; import type { StyleValue } from '../types'; @@ -39,7 +39,7 @@ export const parseXml = (xmlString: string): Document => { }; export const getViewXml = ( - graph: Graph, + graph: AbstractGraph, scale = 1, cells: Cell[] | null = null, x0 = 0, diff --git a/packages/core/src/view/AbstractGraph.ts b/packages/core/src/view/AbstractGraph.ts new file mode 100644 index 0000000000..5992a6bc52 --- /dev/null +++ b/packages/core/src/view/AbstractGraph.ts @@ -0,0 +1,1452 @@ +/* +Copyright 2021-present The maxGraph project Contributors +Copyright (c) 2006-2015, JGraph Ltd +Copyright (c) 2006-2015, Gaudenz Alder + +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 Image from './image/ImageBox'; +import EventObject from './event/EventObject'; +import EventSource from './event/EventSource'; +import InternalEvent from './event/InternalEvent'; +import Rectangle from './geometry/Rectangle'; +import Client from '../Client'; +import type PanningHandler from './plugins/PanningHandler'; +import GraphView from './GraphView'; +import CellRenderer from './cell/CellRenderer'; +import Point from './geometry/Point'; +import { getCurrentStyle, hasScrollbars, parseCssNumber } from '../util/styleUtils'; +import Cell from './cell/Cell'; +import GraphDataModel from './GraphDataModel'; +import { Stylesheet } from './style/Stylesheet'; +import { PAGE_FORMAT_A4_PORTRAIT } from '../util/Constants'; +import ChildChange from './undoable_changes/ChildChange'; +import GeometryChange from './undoable_changes/GeometryChange'; +import RootChange from './undoable_changes/RootChange'; +import StyleChange from './undoable_changes/StyleChange'; +import TerminalChange from './undoable_changes/TerminalChange'; +import ValueChange from './undoable_changes/ValueChange'; +import CellState from './cell/CellState'; +import { isNode } from '../util/domUtils'; +import { EdgeStyle } from './style/edge'; +import EdgeHandler from './handler/EdgeHandler'; +import VertexHandler from './handler/VertexHandler'; +import EdgeSegmentHandler from './handler/EdgeSegmentHandler'; +import ElbowEdgeHandler from './handler/ElbowEdgeHandler'; +import type { + EdgeStyleFunction, + GraphCollaboratorsOptions, + GraphFoldingOptions, + GraphOptions, + GraphPlugin, + MouseListenerSet, +} from '../types'; +import Multiplicity from './other/Multiplicity'; +import ImageBundle from './image/ImageBundle'; +import { applyGraphMixins } from './mixins/_graph-mixins-apply'; +import { isNullish } from '../internal/utils'; +import { isI18nEnabled } from '../internal/i18n-utils'; + +/** + * Extends {@link EventSource} to implement a graph component for the browser. This is the entry point class of the package. + * + * To activate panning and connections use {@link setPanning} and {@link setConnectable}. + * For rubberband selection you must create a new instance of {@link rubberband}. + * + * The following listeners are added to {@link mouseListeners} by default: + * + * - tooltipHandler: {@link TooltipHandler} that displays tooltips + * - panningHandler: {@link PanningHandler} for panning and popup menus + * - connectionHandler: {@link ConnectionHandler} for creating connections + * - selectionHandler: {@link SelectionHandler} for moving and cloning cells + * + * These listeners will be called in the above order if they are enabled. + * + * @category Graph + */ +export abstract class AbstractGraph extends EventSource { + container: HTMLElement; + + destroyed = false; + + graphModelChangeListener: Function | null = null; + paintBackground: Function | null = null; + isConstrainedMoving = false; + + // =================================================================================================================== + // Group: Variables (that maybe should be in the mixins, but need to be created for each new class instance) + // =================================================================================================================== + + cells: Cell[] = []; + + imageBundles: ImageBundle[] = []; + + /** + * Holds the mouse event listeners. See {@link fireMouseEvent}. + */ + mouseListeners: MouseListenerSet[] = []; + + /** + * An array of {@link Multiplicity} describing the allowed connections in a graph. + */ + multiplicities: Multiplicity[] = []; + + /** + * Holds the {@link GraphDataModel} that contains the cells to be displayed. + */ + model!: GraphDataModel; // initialized in "initializeCollaborators" + + private plugins: Record = {}; + + /** + * Holds the {@link GraphView} that caches the {@link CellState}s for the cells. + */ + view!: GraphView; // initialized in "initializeCollaborators" + + /** + * Holds the {@link Stylesheet} that defines the appearance of the cells. + * + * Use the following code to read a stylesheet into an existing graph. + * + * @example + * ```javascript + * var req = mxUtils.load('stylesheet.xml'); + * var root = req.getDocumentElement(); + * var dec = new Codec(root.ownerDocument); + * dec.decode(root, graph.stylesheet); + * ``` + */ + stylesheet!: Stylesheet; // initialized in "initializeCollaborators" + + /** + * Holds the {@link CellRenderer} for rendering the cells in the graph. + */ + cellRenderer!: CellRenderer; // initialized in "initializeCollaborators" + + /** + * RenderHint as it was passed to the constructor. + */ + renderHint: string | null = null; + + /** + * Dialect to be used for drawing the graph. Possible values are all constants in {@link DIALECT}. + */ + dialect: 'svg' | 'mixedHtml' | 'preferHtml' | 'strictHtml' = 'svg'; + + /** + * Value returned by {@link getOverlap} if {@link isAllowOverlapParent} returns + * `true` for the given cell. {@link getOverlap} is used in {@link constrainChild} if + * {@link isConstrainChild} returns `true`. The value specifies the + * portion of the child which is allowed to overlap the parent. + */ + defaultOverlap = 0.5; + + /** + * Specifies the default parent to be used to insert new cells. + * This is used in {@link getDefaultParent}. + * @default null + */ + defaultParent: Cell | null = null; + + /** + * Specifies the {@link Image} to be returned by {@link getBackgroundImage}. + * @default null + * + * @example + * ```javascript + * var img = new mxImage('http://www.example.com/maps/examplemap.jpg', 1024, 768); + * graph.setBackgroundImage(img); + * graph.view.validate(); + * ``` + */ + backgroundImage: Image | null = null; + + /** + * Specifies if the background page should be visible. + * Not yet implemented. + * @default false + */ + pageVisible = false; + + /** + * Specifies if a dashed line should be drawn between multiple pages. + * If you change this value while a graph is being displayed then you + * should call {@link sizeDidChange} to force an update of the display. + * @default false + */ + pageBreaksVisible = false; + + /** + * Specifies the color for page breaks. + * @default gray + */ + pageBreakColor = 'gray'; + + /** + * Specifies the page breaks should be dashed. + * @default true + */ + pageBreakDashed = true; + + /** + * Specifies the minimum distance in pixels for page breaks to be visible. + * @default 20 + */ + minPageBreakDist = 20; + + /** + * Specifies if the graph size should be rounded to the next page number in + * {@link sizeDidChange}. This is only used if the graph container has scrollbars. + * @default false + */ + preferPageSize = false; + + /** + * Specifies the page format for the background page. + * This is used as the default in {@link PrintPreview} and for painting the background page + * if {@link pageVisible} is `true` and the page breaks if {@link pageBreaksVisible} is `true`. + * @default {@link mxConstants.PAGE_FORMAT_A4_PORTRAIT} + */ + pageFormat = new Rectangle(...PAGE_FORMAT_A4_PORTRAIT); + + /** + * Specifies the scale of the background page. + * Not yet implemented. + * @default 1.5 + */ + pageScale = 1.5; + + /** + * Specifies the return value for {@link isEnabled}. + * @default true + */ + enabled = true; + + /** + * Specifies the return value for {@link canExportCell}. + * @default true + */ + exportEnabled = true; + + /** + * Specifies the return value for {@link canImportCell}. + * @default true + */ + importEnabled = true; + + /** + * Specifies if the graph should automatically scroll regardless of the + * scrollbars. This will scroll the container using positive values for + * scroll positions (ie usually only rightwards and downwards). To avoid + * possible conflicts with panning, set {@link translateToScrollPosition} to `true`. + */ + ignoreScrollbars = false; + + /** + * Specifies if the graph should automatically convert the current scroll + * position to a translate in the graph view when a mouseUp event is received. + * This can be used to avoid conflicts when using {@link autoScroll} and + * {@link ignoreScrollbars} with no scrollbars in the container. + */ + translateToScrollPosition = false; + + /** + * {@link Rectangle} that specifies the area in which all cells in the diagram + * should be placed. Uses in {@link getMaximumGraphBounds}. Use a width or height of + * `0` if you only want to give a upper, left corner. + */ + maximumGraphBounds: Rectangle | null = null; + + /** + * {@link Rectangle} that specifies the minimum size of the graph. This is ignored + * if the graph container has no scrollbars. + * @default null + */ + minimumGraphSize: Rectangle | null = null; + + /** + * {@link Rectangle} that specifies the minimum size of the {@link container} if + * {@link resizeContainer} is `true`. + */ + minimumContainerSize: Rectangle | null = null; + + /** + * {@link Rectangle} that specifies the maximum size of the container if + * {@link resizeContainer} is `true`. + */ + maximumContainerSize: Rectangle | null = null; + + /** + * Specifies if the container should be resized to the graph size when + * the graph size has changed. + * @default false + */ + resizeContainer = false; + + /** + * Border to be added to the bottom and right side when the container is + * being resized after the graph has been changed. + * @default 0 + */ + border = 0; + + /** + * Specifies if edges should appear in the foreground regardless of their order + * in the model. If {@link keepEdgesInForeground} and {@link keepEdgesInBackground} are + * both `true` then the normal order is applied. + * @default false + */ + keepEdgesInForeground = false; + + /** + * Specifies if edges should appear in the background regardless of their order + * in the model. If {@link keepEdgesInForeground} and {@link keepEdgesInBackground} are + * both `true` then the normal order is applied. + * @default false + */ + keepEdgesInBackground = false; + + /** + * Specifies the return value for {@link isRecursiveResize}. + * @default false (for backwards compatibility) + */ + recursiveResize = false; + + /** + * Specifies if the scale and translate should be reset if the root changes in + * the model. + * @default true + */ + resetViewOnRootChange = true; + + /** + * Specifies if loops (aka self-references) are allowed. + * @default false + */ + allowLoops = false; + + /** + * {@link EdgeStyle} to be used for loops. This is a fallback for loops if the + * {@link CellStateStyle.loopStyle} is `undefined`. + * @default {@link EdgeStyle.Loop} + */ + defaultLoopStyle = EdgeStyle.Loop; + + /** + * Specifies if multiple edges in the same direction between the same pair of + * vertices are allowed. + * @default true + */ + multigraph = true; + + /** + * Specifies the minimum scale to be applied in {@link fit}. Set this to `null` to allow any value. + * @default 0.1 + */ + minFitScale: number | null = 0.1; + + /** + * Specifies the maximum scale to be applied in {@link fit}. Set this to `null` to allow any value. + * @default 8 + */ + maxFitScale: number | null = 8; + + /** + * Specifies the {@link Image} for the image to be used to display a warning + * overlay. See {@link setCellWarning}. Default value is Client.imageBasePath + + * '/warning'. The extension for the image depends on the platform. It is + * '.png' on the Mac and '.gif' on all other platforms. + */ + warningImage: Image = new Image( + `${Client.imageBasePath}/warning${Client.IS_MAC ? '.png' : '.gif'}`, + 16, + 16 + ); + + /** + * Specifies the resource key for the error message to be displayed in + * non-multigraphs when two vertices are already connected. If the resource + * for this key does not exist then the value is used as the error message. + * @default 'alreadyConnected' + */ + alreadyConnectedResource: string = isI18nEnabled() ? 'alreadyConnected' : ''; + + /** + * Specifies the resource key for the warning message to be displayed when + * a collapsed cell contains validation errors. If the resource for this + * key does not exist then the value is used as the warning message. + * @default 'containsValidationErrors' + */ + containsValidationErrorsResource: string = isI18nEnabled() + ? 'containsValidationErrors' + : ''; + + /** Folding options. */ + options: GraphFoldingOptions = { + foldingEnabled: true, + collapsedImage: new Image(`${Client.imageBasePath}/collapsed.gif`, 9, 9), + expandedImage: new Image(`${Client.imageBasePath}/expanded.gif`, 9, 9), + collapseToPreferredSize: true, + }; + + // =================================================================================================================== + // Group: "Create Class Instance" factory functions. + // These can be overridden in subclasses to allow the Graph to instantiate user-defined implementations with custom behavior. + // Notice that the methods will be moved as part of https://github.com/maxGraph/maxGraph/issues/762 + // =================================================================================================================== + + /** + * Hooks to create a new {@link EdgeHandler} for the given {@link CellState}. + * + * @param state {@link CellState} to create the handler for. + */ + createEdgeHandlerInstance(state: CellState): EdgeHandler { + // Note this method not being called createEdgeHandler to keep compatibility + // with older code which overrides/calls createEdgeHandler + return new EdgeHandler(state); + } + + /** + * Hooks to create a new {@link EdgeSegmentHandler} for the given {@link CellState}. + * + * @param state {@link CellState} to create the handler for. + */ + createEdgeSegmentHandler(state: CellState) { + return new EdgeSegmentHandler(state); + } + + /** + * Hooks to create a new {@link ElbowEdgeHandler} for the given {@link CellState}. + * + * @param state {@link CellState} to create the handler for. + */ + createElbowEdgeHandler(state: CellState) { + return new ElbowEdgeHandler(state); + } + + /** + * Hooks to create a new {@link VertexHandler} for the given {@link CellState}. + * + * @param state {@link CellState} to create the handler for. + */ + createVertexHandler(state: CellState): VertexHandler { + return new VertexHandler(state); + } + + // =================================================================================================================== + // Group: Main graph constructor and functions + // =================================================================================================================== + + /** + * Convenient hook method that can be used to register global styles and shapes using the related global registries. + * + * While registration can also be done outside of this class (as it applies globally), + * implementing it here makes the registration process transparent to the caller of this class. + * + * Subclasses can override this method to register custom defaults. + */ + protected registerDefaults(): void { + // do nothing, it's the purpose of this class not to load defaults. + } + + protected abstract initializeCollaborators(options?: GraphCollaboratorsOptions): void; + + constructor(options?: GraphOptions) { + super(); + this.registerDefaults(); + + this.container = options?.container ?? document.createElement('div'); + + // collaborators + this.initializeCollaborators(options); + + // Adds a graph model listener to update the view + this.graphModelChangeListener = (_sender: any, evt: EventObject) => { + this.graphModelChanged(evt.getProperty('edit').changes); + }; + this.getDataModel().addListener(InternalEvent.CHANGE, this.graphModelChangeListener); + + // Initializes the container using the view + this.view.init(); + + // Updates the size of the container for the current graph + this.sizeDidChange(); + + // Initializes plugins + options?.plugins?.forEach((p) => (this.plugins[p.pluginId] = new p(this))); + + this.view.revalidate(); + } + + getContainer = () => this.container; + getPlugin = (id: string): T => this.plugins[id] as T; + getCellRenderer = () => this.cellRenderer; + getDialect = () => this.dialect; + isPageVisible = () => this.pageVisible; + isPageBreaksVisible = () => this.pageBreaksVisible; + getPageBreakColor = () => this.pageBreakColor; + isPageBreakDashed = () => this.pageBreakDashed; + getMinPageBreakDist = () => this.minPageBreakDist; + isPreferPageSize = () => this.preferPageSize; + getPageFormat = () => this.pageFormat; + getPageScale = () => this.pageScale; + isExportEnabled = () => this.exportEnabled; + isImportEnabled = () => this.importEnabled; + isIgnoreScrollbars = () => this.ignoreScrollbars; + isTranslateToScrollPosition = () => this.translateToScrollPosition; + + getMinimumGraphSize = () => this.minimumGraphSize; + setMinimumGraphSize = (size: Rectangle | null) => (this.minimumGraphSize = size); + + getMinimumContainerSize = () => this.minimumContainerSize; + setMinimumContainerSize = (size: Rectangle | null) => + (this.minimumContainerSize = size); + + getWarningImage() { + return this.warningImage; + } + + getAlreadyConnectedResource = () => this.alreadyConnectedResource; + + getContainsValidationErrorsResource = () => this.containsValidationErrorsResource; + + /** + * Updates the model in a transaction. + * + * @param fn the update to be performed in the transaction. + * + * @see {@link GraphDataModel.batchUpdate} + */ + batchUpdate(fn: () => void) { + this.getDataModel().batchUpdate(fn); + } + + /** + * Returns the {@link GraphDataModel} that contains the cells. + */ + getDataModel() { + return this.model; + } + + /** + * Returns the {@link GraphView} that contains the {@link mxCellStates}. + */ + getView() { + return this.view; + } + + /** + * Returns the {@link Stylesheet} that defines the style. + */ + getStylesheet() { + return this.stylesheet; + } + + /** + * Sets the {@link Stylesheet} that defines the style. + */ + setStylesheet(stylesheet: Stylesheet) { + this.stylesheet = stylesheet; + } + + /** + * Called when the graph model changes. Invokes {@link processChange} on each + * item of the given array to update the view accordingly. + * + * @param changes Array that contains the individual changes. + */ + graphModelChanged(changes: any[]) { + for (const change of changes) { + this.processChange(change); + } + + this.updateSelection(); + this.view.validate(); + this.sizeDidChange(); + } + + /** + * Processes the given change and invalidates the respective cached data + * in {@link GraphView}. This fires a {@link root} event if the root has changed in the + * model. + * + * @param {(RootChange|ChildChange|TerminalChange|GeometryChange|ValueChange|StyleChange)} change - Object that represents the change on the model. + */ + processChange(change: any): void { + // Resets the view settings, removes all cells and clears + // the selection if the root changes. + if (change instanceof RootChange) { + this.clearSelection(); + this.setDefaultParent(null); + + if (change.previous) this.removeStateForCell(change.previous); + + if (this.resetViewOnRootChange) { + this.view.scale = 1; + this.view.translate.x = 0; + this.view.translate.y = 0; + } + + this.fireEvent(new EventObject(InternalEvent.ROOT)); + } + + // Adds or removes a child to the view by online invaliding + // the minimal required portions of the cache, namely, the + // old and new parent and the child. + else if (change instanceof ChildChange) { + const newParent = change.child.getParent(); + this.view.invalidate(change.child, true, true); + + if ( + !newParent || + !this.getDataModel().contains(newParent) || + newParent.isCollapsed() + ) { + this.view.invalidate(change.child, true, true); + this.removeStateForCell(change.child); + + // Handles special case of current root of view being removed + if (this.view.currentRoot == change.child) { + this.home(); + } + } + + if (newParent != change.previous) { + // Refreshes the collapse/expand icons on the parents + if (newParent != null) { + this.view.invalidate(newParent, false, false); + } + + if (change.previous != null) { + this.view.invalidate(change.previous, false, false); + } + } + } + + // Handles two special cases where the shape does not need to be + // recreated from scratch, it only needs to be invalidated. + else if (change instanceof TerminalChange || change instanceof GeometryChange) { + // Checks if the geometry has changed to avoid unnessecary revalidation + if ( + change instanceof TerminalChange || + (change.previous == null && change.geometry != null) || + (change.previous != null && !change.previous.equals(change.geometry)) + ) { + this.view.invalidate(change.cell); + } + } + + // Handles two special cases where only the shape, but no + // descendants need to be recreated + else if (change instanceof ValueChange) { + this.view.invalidate(change.cell, false, false); + } + + // Requires a new mxShape in JavaScript + else if (change instanceof StyleChange) { + this.view.invalidate(change.cell, true, true); + const state = this.view.getState(change.cell); + + if (state != null) { + state.invalidStyle = true; + } + } + + // Removes the state from the cache by default + else if (change.cell != null && change.cell instanceof Cell) { + this.removeStateForCell(change.cell); + } + } + + /** + * Scrolls the graph to the given point, extending the graph container if + * specified. + */ + scrollPointToVisible(x: number, y: number, extend = false, border = 20) { + const panningHandler = this.getPlugin('PanningHandler'); + + if ( + !this.isTimerAutoScroll() && + (this.ignoreScrollbars || hasScrollbars(this.container)) + ) { + const c = this.container; + + if ( + x >= c.scrollLeft && + y >= c.scrollTop && + x <= c.scrollLeft + c.clientWidth && + y <= c.scrollTop + c.clientHeight + ) { + let dx = c.scrollLeft + c.clientWidth - x; + + if (dx < border) { + const old = c.scrollLeft; + c.scrollLeft += border - dx; + + // Automatically extends the canvas size to the bottom, right + // if the event is outside of the canvas and the edge of the + // canvas has been reached. Notes: Needs fix for IE. + if (extend && old === c.scrollLeft) { + // @ts-ignore + const root = this.view.getDrawPane().ownerSVGElement; + const width = c.scrollWidth + border - dx; + + // Updates the clipping region. This is an expensive + // operation that should not be executed too often. + // @ts-ignore + root.style.width = `${width}px`; + + c.scrollLeft += border - dx; + } + } else { + dx = x - c.scrollLeft; + + if (dx < border) { + c.scrollLeft -= border - dx; + } + } + + let dy = c.scrollTop + c.clientHeight - y; + + if (dy < border) { + const old = c.scrollTop; + c.scrollTop += border - dy; + + if (old == c.scrollTop && extend) { + // @ts-ignore + const root = this.view.getDrawPane().ownerSVGElement; + const height = c.scrollHeight + border - dy; + + // Updates the clipping region. This is an expensive + // operation that should not be executed too often. + // @ts-ignore + root.style.height = `${height}px`; + + c.scrollTop += border - dy; + } + } else { + dy = y - c.scrollTop; + + if (dy < border) { + c.scrollTop -= border - dy; + } + } + } + } else if ( + this.isAllowAutoPanning() && + panningHandler && + !panningHandler.isActive() + ) { + panningHandler.getPanningManager().panTo(x + this.getPanDx(), y + this.getPanDy()); + } + } + + /** + * Returns the size of the border and padding on all four sides of the + * container. The left, top, right and bottom borders are stored in the x, y, + * width and height of the returned {@link Rectangle}, respectively. + */ + getBorderSizes(): Rectangle { + const css = getCurrentStyle(this.container); + + return new Rectangle( + parseCssNumber(css.paddingLeft) + + (css.borderLeftStyle != 'none' ? parseCssNumber(css.borderLeftWidth) : 0), + parseCssNumber(css.paddingTop) + + (css.borderTopStyle != 'none' ? parseCssNumber(css.borderTopWidth) : 0), + parseCssNumber(css.paddingRight) + + (css.borderRightStyle != 'none' ? parseCssNumber(css.borderRightWidth) : 0), + parseCssNumber(css.paddingBottom) + + (css.borderBottomStyle != 'none' ? parseCssNumber(css.borderBottomWidth) : 0) + ); + } + + /** + * Returns the preferred size of the background page if {@link preferPageSize} is true. + */ + getPreferredPageSize(bounds: Rectangle, width: number, height: number) { + const tr = this.view.translate; + const fmt = this.pageFormat; + const ps = this.pageScale; + const page = new Rectangle( + 0, + 0, + Math.ceil(fmt.width * ps), + Math.ceil(fmt.height * ps) + ); + + const hCount = this.pageBreaksVisible ? Math.ceil(width / page.width) : 1; + const vCount = this.pageBreaksVisible ? Math.ceil(height / page.height) : 1; + + return new Rectangle( + 0, + 0, + hCount * page.width + 2 + tr.x, + vCount * page.height + 2 + tr.y + ); + } + + /** + * Scales the graph such that the complete diagram fits into {@link AbstractGraph.container} and returns the current scale in the view. + * To fit an initial graph prior to rendering, set {@link GraphView.rendering} to `false` prior to changing the model + * and execute the following after changing the model. + * + * ```javascript + * graph.view.rendering = false; + * // here, change the model + * graph.fit(); + * graph.view.rendering = true; + * graph.refresh(); + * ``` + * + * To fit and center the graph, use {@link FitPlugin.fitCenter}. + * + * @param border Optional number that specifies the border. Default is {@link border}. + * @param keepOrigin Optional boolean that specifies if the translate should be changed. Default is `false`. + * @param margin Optional margin in pixels. Default is `0`. + * @param enabled Optional boolean that specifies if the scale should be set or just returned. Default is `true`. + * @param ignoreWidth Optional boolean that specifies if the width should be ignored. Default is `false`. + * @param ignoreHeight Optional boolean that specifies if the height should be ignored. Default is `false`. + * @param maxHeight Optional maximum height. + */ + fit( + border: number = this.getBorder(), + keepOrigin = false, + margin = 0, + enabled = true, + ignoreWidth = false, + ignoreHeight = false, + maxHeight: number | null = null + ): number { + const { container, view } = this; + if (container) { + // Adds spacing and border from css + const cssBorder = this.getBorderSizes(); + let w1: number = container.offsetWidth - cssBorder.x - cssBorder.width - 1; + let h1: number = + maxHeight != null + ? maxHeight + : container.offsetHeight - cssBorder.y - cssBorder.height - 1; + let bounds = view.getGraphBounds(); + + if (bounds.width > 0 && bounds.height > 0) { + if (keepOrigin && bounds.x != null && bounds.y != null) { + bounds = bounds.clone(); + bounds.width += bounds.x; + bounds.height += bounds.y; + bounds.x = 0; + bounds.y = 0; + } + + // LATER: Use unscaled bounding boxes to fix rounding errors + const originalScale = view.scale; + let w2 = bounds.width / originalScale; + let h2 = bounds.height / originalScale; + + // Fits to the size of the background image if required + if (this.backgroundImage) { + w2 = Math.max(w2, this.backgroundImage.width - bounds.x / originalScale); + h2 = Math.max(h2, this.backgroundImage.height - bounds.y / originalScale); + } + + const b: number = (keepOrigin ? border : 2 * border) + margin + 1; + + w1 -= b; + h1 -= b; + + let newScale = ignoreWidth + ? h1 / h2 + : ignoreHeight + ? w1 / w2 + : Math.min(w1 / w2, h1 / h2); + + if (this.minFitScale != null) { + newScale = Math.max(newScale, this.minFitScale); + } + + if (this.maxFitScale != null) { + newScale = Math.min(newScale, this.maxFitScale); + } + + if (enabled) { + if (!keepOrigin) { + if (!hasScrollbars(container)) { + const x0 = + bounds.x != null + ? Math.floor( + view.translate.x - + bounds.x / originalScale + + border / newScale + + margin / 2 + ) + : border; + const y0 = + bounds.y != null + ? Math.floor( + view.translate.y - + bounds.y / originalScale + + border / newScale + + margin / 2 + ) + : border; + + view.scaleAndTranslate(newScale, x0, y0); + } else { + view.setScale(newScale); + const newBounds = this.getGraphBounds(); + + if (newBounds.x != null) { + container.scrollLeft = newBounds.x; + } + + if (newBounds.y != null) { + container.scrollTop = newBounds.y; + } + } + } else if (view.scale != newScale) { + view.setScale(newScale); + } + } else { + return newScale; + } + } + } + return view.scale; + } + + /** + * Resizes the container for the given graph width and height. + */ + doResizeContainer(width: number, height: number): void { + if (this.maximumContainerSize != null) { + width = Math.min(this.maximumContainerSize.width, width); + height = Math.min(this.maximumContainerSize.height, height); + } + const container = this.container; + container.style.width = `${Math.ceil(width)}px`; + container.style.height = `${Math.ceil(height)}px`; + } + + /***************************************************************************** + * Group: UNCLASSIFIED + *****************************************************************************/ + + /** + * Creates a new handler for the given cell state. This implementation + * returns a new {@link EdgeHandler} of the corresponding cell is an edge, + * otherwise it returns an {@link VertexHandler}. + * + * @param state {@link CellState} whose handler should be created. + */ + createHandler(state: CellState) { + let result: EdgeHandler | VertexHandler | null = null; + + if (state.cell.isEdge()) { + const source = state.getVisibleTerminalState(true); + const target = state.getVisibleTerminalState(false); + const geo = state.cell.getGeometry(); + + const edgeStyle = this.getView().getEdgeStyle( + state, + geo ? geo.points || undefined : undefined, + source, + target + ); + result = this.createEdgeHandler(state, edgeStyle); + } else { + result = this.createVertexHandler(state); + } + return result; + } + + /** + * Hooks to create a new {@link EdgeHandler} for the given {@link CellState}. + * + * @param state {@link CellState} to create the handler for. + * @param edgeStyle the {@link EdgeStyleFunction} that let choose the actual edge handler. + */ + createEdgeHandler(state: CellState, edgeStyle: EdgeStyleFunction | null): EdgeHandler { + let result = null; + if ( + edgeStyle == EdgeStyle.ElbowConnector || + edgeStyle == EdgeStyle.Loop || + edgeStyle == EdgeStyle.SideToSide || + edgeStyle == EdgeStyle.TopToBottom + ) { + result = this.createElbowEdgeHandler(state); + } else if ( + edgeStyle == EdgeStyle.ManhattanConnector || + edgeStyle == EdgeStyle.OrthConnector || + edgeStyle == EdgeStyle.SegmentConnector + ) { + result = this.createEdgeSegmentHandler(state); + } else { + result = this.createEdgeHandlerInstance(state); + } + + return result; + } + + /***************************************************************************** + * Group: Drilldown + *****************************************************************************/ + + /** + * Returns the current root of the displayed cell hierarchy. This is a + * shortcut to {@link GraphView.currentRoot} in {@link GraphView}. + */ + getCurrentRoot() { + return this.view.currentRoot; + } + + /** + * Returns the translation to be used if the given cell is the root cell as + * an {@link Point}. This implementation returns null. + * + * To keep the children at their absolute position while stepping into groups, + * this function can be overridden as follows. + * + * @example + * ```javascript + * var offset = new mxPoint(0, 0); + * + * while (cell != null) + * { + * var geo = this.model.getGeometry(cell); + * + * if (geo != null) + * { + * offset.x -= geo.x; + * offset.y -= geo.y; + * } + * + * cell = this.model.getParent(cell); + * } + * + * return offset; + * ``` + * + * @param cell {@link Cell} that represents the root. + */ + getTranslateForRoot(cell: Cell | null): Point | null { + return null; + } + + /** + * Returns the offset to be used for the cells inside the given cell. The + * root and layer cells may be identified using {@link GraphDataModel.isRoot} and + * {@link GraphDataModel.isLayer}. For all other current roots, the + * {@link GraphView.currentRoot} field points to the respective cell, so that + * the following holds: cell == this.view.currentRoot. This implementation + * returns null. + * + * @param cell {@link Cell} whose offset should be returned. + */ + getChildOffsetForCell(cell: Cell): Point | null { + return null; + } + + /** + * Uses the root of the model as the root of the displayed cell hierarchy + * and selects the previous root. + */ + home() { + const current = this.getCurrentRoot(); + + if (current != null) { + this.view.setCurrentRoot(null); + const state = this.view.getState(current); + + if (state != null) { + this.setSelectionCell(current); + } + } + } + + /** + * Returns true if the given cell is a valid root for the cell display + * hierarchy. This implementation returns true for all non-null values. + * + * @param cell {@link Cell} which should be checked as a possible root. + */ + isValidRoot(cell: Cell) { + return !!cell; + } + + /***************************************************************************** + * Group: Graph display + *****************************************************************************/ + + /** + * Returns the bounds of the visible graph. Shortcut to + * {@link GraphView.getGraphBounds}. See also: {@link getBoundingBoxFromGeometry}. + */ + getGraphBounds(): Rectangle { + return this.view.getGraphBounds(); + } + + /** + * Returns the bounds inside which the diagram should be kept as an + * {@link Rectangle}. + */ + getMaximumGraphBounds(): Rectangle | null { + return this.maximumGraphBounds; + } + + /** + * 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 + * last step. + * + * @param cell Optional {@link Cell} for which the cell states should be cleared. + */ + refresh(cell: Cell | null = null): void { + if (cell) { + this.view.clear(cell, false); + } else { + this.view.clear(undefined, true); + } + this.view.validate(); + this.sizeDidChange(); + this.fireEvent(new EventObject(InternalEvent.REFRESH)); + } + + /** + * Centers the graph in the container. + * + * @param horizontal Optional boolean that specifies if the graph should be centered + * horizontally. Default is `true`. + * @param vertical Optional boolean that specifies if the graph should be centered + * vertically. Default is `true`. + * @param cx Optional float that specifies the horizontal center. Default is `0.5`. + * @param cy Optional float that specifies the vertical center. Default is `0.5`. + */ + center(horizontal = true, vertical = true, cx = 0.5, cy = 0.5): void { + const container = this.container; + const _hasScrollbars = hasScrollbars(this.container); + const padding = 2 * this.getBorder(); + const cw = container.clientWidth - padding; + const ch = container.clientHeight - padding; + const bounds = this.getGraphBounds(); + + const t = this.view.translate; + const s = this.view.scale; + + let dx = horizontal ? cw - bounds.width : 0; + let dy = vertical ? ch - bounds.height : 0; + + if (!_hasScrollbars) { + this.view.setTranslate( + horizontal ? Math.floor(t.x - bounds.x / s + (dx * cx) / s) : t.x, + vertical ? Math.floor(t.y - bounds.y / s + (dy * cy) / s) : t.y + ); + } else { + bounds.x -= t.x; + bounds.y -= t.y; + + const sw = container.scrollWidth; + const sh = container.scrollHeight; + + if (sw > cw) { + dx = 0; + } + + if (sh > ch) { + dy = 0; + } + + this.view.setTranslate( + Math.floor(dx / 2 - bounds.x), + Math.floor(dy / 2 - bounds.y) + ); + container.scrollLeft = (sw - cw) / 2; + container.scrollTop = (sh - ch) / 2; + } + } + + /** + * Returns `true` if perimeter points should be computed such that the resulting edge has only horizontal or vertical segments. + * + * @param edge {@link CellState} that represents the edge. + */ + isOrthogonal(edge: CellState): boolean { + const orthogonal = edge.style.orthogonal; + if (!isNullish(orthogonal)) { + return orthogonal; + } + + // fallback when the orthogonal style is not defined + const edgeStyle = this.view.getEdgeStyle(edge); + + return [ + EdgeStyle.EntityRelation, + EdgeStyle.ElbowConnector, + EdgeStyle.ManhattanConnector, + EdgeStyle.OrthConnector, + EdgeStyle.SegmentConnector, + EdgeStyle.SideToSide, + EdgeStyle.TopToBottom, + ].includes(edgeStyle!); + } + + /***************************************************************************** + * Group: Graph appearance + *****************************************************************************/ + + /** + * Returns the {@link backgroundImage} as an {@link Image}. + */ + getBackgroundImage(): Image | null { + return this.backgroundImage; + } + + /** + * Sets the new {@link backgroundImage}. + * + * @param image New {@link Image} to be used for the background. + */ + setBackgroundImage(image: Image | null): void { + this.backgroundImage = image; + } + + /** + * Returns the textual representation for the given cell. + * + * This implementation returns the node name or string-representation of the user object. + * + * + * The following returns the label attribute from the cells user object if it is an XML node. + * + * @example + * ```javascript + * graph.convertValueToString = function(cell) + * { + * return cell.getAttribute('label'); + * } + * ``` + * + * See also: {@link cellLabelChanged}. + * + * @param cell {@link Cell} whose textual representation should be returned. + */ + convertValueToString(cell: Cell): string { + const value = cell.getValue(); + + if (value != null) { + if (isNode(value)) { + return value.nodeName; + } + if (typeof value.toString === 'function') { + return value.toString(); + } + } + return ''; + } + + /** + * Returns the string to be used as the link for the given cell. + * + * This implementation returns null. + * + * @param cell {@link Cell} whose link should be returned. + */ + getLinkForCell(cell: Cell): string | null { + return null; + } + + /** + * Returns the value of {@link border}. + */ + getBorder(): number { + return this.border; + } + + /** + * Sets the value of {@link border}. + * + * @param value Positive integer that represents the border to be used. + */ + setBorder(value: number): void { + this.border = value; + } + + /***************************************************************************** + * Group: Graph behaviour + *****************************************************************************/ + + /** + * Returns {@link resizeContainer}. + */ + isResizeContainer() { + return this.resizeContainer; + } + + /** + * Sets {@link resizeContainer}. + * + * @param value Boolean indicating if the container should be resized. + */ + setResizeContainer(value: boolean) { + this.resizeContainer = value; + } + + /** + * Returns true if the graph is {@link enabled}. + */ + isEnabled() { + return this.enabled; + } + + /** + * Specifies if the graph should allow any interactions. This + * implementation updates {@link enabled}. + * + * @param value Boolean indicating if the graph should be enabled. + */ + setEnabled(value: boolean) { + this.enabled = value; + } + + /** + * Returns {@link multigraph} as a boolean. + */ + isMultigraph() { + return this.multigraph; + } + + /** + * Specifies if the graph should allow multiple connections between the + * same pair of vertices. + * + * @param value Boolean indicating if the graph allows multiple connections + * between the same pair of vertices. + */ + setMultigraph(value: boolean) { + this.multigraph = value; + } + + /** + * Returns {@link allowLoops} as a boolean. + */ + isAllowLoops() { + return this.allowLoops; + } + + /** + * Specifies if loops are allowed. + * + * @param value Boolean indicating if loops are allowed. + */ + setAllowLoops(value: boolean) { + this.allowLoops = value; + } + + /** + * Returns {@link recursiveResize}. + * + * @param state {@link CellState} that is being resized. + */ + isRecursiveResize(state: CellState | null = null) { + return this.recursiveResize; + } + + /** + * Sets {@link recursiveResize}. + * + * @param value New boolean value for {@link recursiveResize}. + */ + setRecursiveResize(value: boolean) { + this.recursiveResize = value; + } + + /** + * Returns a decimal number representing the amount of the width and height + * of the given cell that is allowed to overlap its parent. A value of 0 + * means all children must stay inside the parent, 1 means the child is + * allowed to be placed outside of the parent such that it touches one of + * the parents sides. If {@link isAllowOverlapParent} returns false for the given + * cell, then this method returns 0. + * + * @param cell {@link Cell} for which the overlap ratio should be returned. + */ + getOverlap(cell: Cell) { + return this.isAllowOverlapParent(cell) ? this.defaultOverlap : 0; + } + + /** + * Returns true if the given cell is allowed to be placed outside the + * parents area. + * + * @param cell {@link Cell} that represents the child to be checked. + */ + isAllowOverlapParent(cell: Cell): boolean { + return false; + } + + /***************************************************************************** + * Group: Cell retrieval + *****************************************************************************/ + + /** + * Returns {@link defaultParent} or {@link GraphView.currentRoot} or the first child + * of {@link GraphDataModel.root} if both are null. The value returned by + * this function should be used as the parent for new cells (aka default + * layer). + */ + getDefaultParent() { + let parent = this.getCurrentRoot(); + + if (!parent) { + parent = this.defaultParent; + + if (!parent) { + const root = this.getDataModel().getRoot(); + parent = root.getChildAt(0); + } + } + + return parent; + } + + /** + * Sets the {@link defaultParent} to the given cell. Set this to null to return + * the first child of the root in getDefaultParent. + */ + setDefaultParent(cell: Cell | null) { + this.defaultParent = cell; + } + + /** + * Destroys the graph and all its resources. + */ + destroy() { + if (!this.destroyed) { + this.destroyed = true; + + Object.values(this.plugins).forEach((p) => p.onDestroy()); + + this.view.destroy(); + + if (this.model && this.graphModelChangeListener) { + this.getDataModel().removeListener(this.graphModelChangeListener); + this.graphModelChangeListener = null; + } + } + } +} + +// This introduces a side effect, but it is necessary to ensure the Graph is enriched with all properties and methods defined in mixins. +// It is only called when Graph is imported, so the Graph definition is always consistent. +// And this doesn't impact the tree-shaking. +applyGraphMixins(AbstractGraph); diff --git a/packages/core/src/view/BaseGraph.ts b/packages/core/src/view/BaseGraph.ts new file mode 100644 index 0000000000..6eb6cd89f0 --- /dev/null +++ b/packages/core/src/view/BaseGraph.ts @@ -0,0 +1,44 @@ +/* +Copyright 2025-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 type { GraphCollaboratorsOptions } from '../types'; +import { AbstractGraph } from './AbstractGraph'; +import GraphDataModel from './GraphDataModel'; +import CellRenderer from './cell/CellRenderer'; +import { Stylesheet } from './style/Stylesheet'; +import GraphSelectionModel from './GraphSelectionModel'; +import GraphView from './GraphView'; + +/** + * An implementation of {@link AbstractGraph} that does not load any default built-ins (plugins, style elements). + * + * This class is optimized for production environments by enabling efficient tree-shaking. + * + * For evaluation and prototyping purposes, consider using {@link Graph}, which requires less configuration. + * + * @category Graph + */ +export class BaseGraph extends AbstractGraph { + protected override initializeCollaborators(options?: GraphCollaboratorsOptions): void { + this.cellRenderer = options?.cellRenderer ?? new CellRenderer(); + this.model = options?.model ?? new GraphDataModel(); + this.setSelectionModel( + options?.selectionModel?.(this) ?? new GraphSelectionModel(this) + ); + this.setStylesheet(options?.stylesheet ?? new Stylesheet()); + this.view = options?.view?.(this) ?? new GraphView(this); + } +} diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts index 3e186aaccc..7428d4f90d 100644 --- a/packages/core/src/view/Graph.ts +++ b/packages/core/src/view/Graph.ts @@ -16,44 +16,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -import Image from './image/ImageBox'; -import EventObject from './event/EventObject'; -import EventSource from './event/EventSource'; -import InternalEvent from './event/InternalEvent'; -import Rectangle from './geometry/Rectangle'; -import Client from '../Client'; -import type PanningHandler from './plugins/PanningHandler'; +import type { GraphCollaboratorsOptions, GraphPluginConstructor } from '../types'; +import { AbstractGraph } from './AbstractGraph'; import GraphView from './GraphView'; import CellRenderer from './cell/CellRenderer'; -import Point from './geometry/Point'; -import { getCurrentStyle, hasScrollbars, parseCssNumber } from '../util/styleUtils'; -import Cell from './cell/Cell'; import GraphDataModel from './GraphDataModel'; import { Stylesheet } from './style/Stylesheet'; -import { PAGE_FORMAT_A4_PORTRAIT } from '../util/Constants'; - -import ChildChange from './undoable_changes/ChildChange'; -import GeometryChange from './undoable_changes/GeometryChange'; -import RootChange from './undoable_changes/RootChange'; -import StyleChange from './undoable_changes/StyleChange'; -import TerminalChange from './undoable_changes/TerminalChange'; -import ValueChange from './undoable_changes/ValueChange'; -import CellState from './cell/CellState'; -import { isNode } from '../util/domUtils'; -import { EdgeStyle } from './style/edge'; -import EdgeHandler from './handler/EdgeHandler'; -import VertexHandler from './handler/VertexHandler'; -import EdgeSegmentHandler from './handler/EdgeSegmentHandler'; -import ElbowEdgeHandler from './handler/ElbowEdgeHandler'; -import type { - EdgeStyleFunction, - GraphFoldingOptions, - GraphPlugin, - GraphPluginConstructor, - MouseListenerSet, -} from '../types'; -import Multiplicity from './other/Multiplicity'; -import ImageBundle from './image/ImageBundle'; import GraphSelectionModel from './GraphSelectionModel'; import { registerDefaultShapes } from './cell/register-shapes'; import { @@ -61,358 +29,16 @@ import { registerDefaultEdgeStyles, registerDefaultPerimeters, } from './style/register'; -import { applyGraphMixins } from './mixins/_graph-mixins-apply'; import { getDefaultPlugins } from './plugins'; -import { isNullish } from '../internal/utils'; -import { isI18nEnabled } from '../internal/i18n-utils'; /** - * Extends {@link EventSource} to implement a graph component for the browser. This is the main class of the package. - * - * To activate panning and connections use {@link setPanning} and {@link setConnectable}. - * For rubberband selection you must create a new instance of {@link rubberband}. + * An implementation of {@link AbstractGraph} that automatically loads some default built-ins (plugins, style elements). * - * The following listeners are added to {@link mouseListeners} by default: + * Good for evaluation and prototyping, but not recommended for production use. Use {@link BaseGraph} instead. * - * - tooltipHandler: {@link TooltipHandler} that displays tooltips - * - panningHandler: {@link PanningHandler} for panning and popup menus - * - connectionHandler: {@link ConnectionHandler} for creating connections - * - selectionHandler: {@link SelectionHandler} for moving and cloning cells - * - * These listeners will be called in the above order if they are enabled. + * @category Graph */ -class Graph extends EventSource { - container: HTMLElement; - - destroyed = false; - - graphModelChangeListener: Function | null = null; - paintBackground: Function | null = null; - isConstrainedMoving = false; - - // =================================================================================================================== - // Group: Variables (that maybe should be in the mixins, but need to be created for each new class instance) - // =================================================================================================================== - - cells: Cell[] = []; - - imageBundles: ImageBundle[] = []; - - /** - * Holds the mouse event listeners. See {@link fireMouseEvent}. - */ - mouseListeners: MouseListenerSet[] = []; - - /** - * An array of {@link Multiplicity} describing the allowed connections in a graph. - */ - multiplicities: Multiplicity[] = []; - - /** - * Holds the {@link GraphDataModel} that contains the cells to be displayed. - */ - model: GraphDataModel; - - private plugins: Record = {}; - - /** - * Holds the {@link GraphView} that caches the {@link CellState}s for the cells. - */ - view: GraphView; - - /** - * Holds the {@link Stylesheet} that defines the appearance of the cells. - * - * Use the following code to read a stylesheet into an existing graph. - * - * @example - * ```javascript - * var req = mxUtils.load('stylesheet.xml'); - * var root = req.getDocumentElement(); - * var dec = new Codec(root.ownerDocument); - * dec.decode(root, graph.stylesheet); - * ``` - */ - // @ts-ignore - stylesheet: Stylesheet; - - /** - * Holds the {@link CellRenderer} for rendering the cells in the graph. - */ - cellRenderer: CellRenderer; - - /** - * RenderHint as it was passed to the constructor. - */ - renderHint: string | null = null; - - /** - * Dialect to be used for drawing the graph. Possible values are all constants in {@link DIALECT}. - */ - dialect: 'svg' | 'mixedHtml' | 'preferHtml' | 'strictHtml' = 'svg'; - - /** - * Value returned by {@link getOverlap} if {@link isAllowOverlapParent} returns - * `true` for the given cell. {@link getOverlap} is used in {@link constrainChild} if - * {@link isConstrainChild} returns `true`. The value specifies the - * portion of the child which is allowed to overlap the parent. - */ - defaultOverlap = 0.5; - - /** - * Specifies the default parent to be used to insert new cells. - * This is used in {@link getDefaultParent}. - * @default null - */ - defaultParent: Cell | null = null; - - /** - * Specifies the {@link Image} to be returned by {@link getBackgroundImage}. - * @default null - * - * @example - * ```javascript - * var img = new mxImage('http://www.example.com/maps/examplemap.jpg', 1024, 768); - * graph.setBackgroundImage(img); - * graph.view.validate(); - * ``` - */ - backgroundImage: Image | null = null; - - /** - * Specifies if the background page should be visible. - * Not yet implemented. - * @default false - */ - pageVisible = false; - - /** - * Specifies if a dashed line should be drawn between multiple pages. - * If you change this value while a graph is being displayed then you - * should call {@link sizeDidChange} to force an update of the display. - * @default false - */ - pageBreaksVisible = false; - - /** - * Specifies the color for page breaks. - * @default gray - */ - pageBreakColor = 'gray'; - - /** - * Specifies the page breaks should be dashed. - * @default true - */ - pageBreakDashed = true; - - /** - * Specifies the minimum distance in pixels for page breaks to be visible. - * @default 20 - */ - minPageBreakDist = 20; - - /** - * Specifies if the graph size should be rounded to the next page number in - * {@link sizeDidChange}. This is only used if the graph container has scrollbars. - * @default false - */ - preferPageSize = false; - - /** - * Specifies the page format for the background page. - * This is used as the default in {@link PrintPreview} and for painting the background page - * if {@link pageVisible} is `true` and the page breaks if {@link pageBreaksVisible} is `true`. - * @default {@link mxConstants.PAGE_FORMAT_A4_PORTRAIT} - */ - pageFormat = new Rectangle(...PAGE_FORMAT_A4_PORTRAIT); - - /** - * Specifies the scale of the background page. - * Not yet implemented. - * @default 1.5 - */ - pageScale = 1.5; - - /** - * Specifies the return value for {@link isEnabled}. - * @default true - */ - enabled = true; - - /** - * Specifies the return value for {@link canExportCell}. - * @default true - */ - exportEnabled = true; - - /** - * Specifies the return value for {@link canImportCell}. - * @default true - */ - importEnabled = true; - - /** - * Specifies if the graph should automatically scroll regardless of the - * scrollbars. This will scroll the container using positive values for - * scroll positions (ie usually only rightwards and downwards). To avoid - * possible conflicts with panning, set {@link translateToScrollPosition} to `true`. - */ - ignoreScrollbars = false; - - /** - * Specifies if the graph should automatically convert the current scroll - * position to a translate in the graph view when a mouseUp event is received. - * This can be used to avoid conflicts when using {@link autoScroll} and - * {@link ignoreScrollbars} with no scrollbars in the container. - */ - translateToScrollPosition = false; - - /** - * {@link Rectangle} that specifies the area in which all cells in the diagram - * should be placed. Uses in {@link getMaximumGraphBounds}. Use a width or height of - * `0` if you only want to give a upper, left corner. - */ - maximumGraphBounds: Rectangle | null = null; - - /** - * {@link Rectangle} that specifies the minimum size of the graph. This is ignored - * if the graph container has no scrollbars. - * @default null - */ - minimumGraphSize: Rectangle | null = null; - - /** - * {@link Rectangle} that specifies the minimum size of the {@link container} if - * {@link resizeContainer} is `true`. - */ - minimumContainerSize: Rectangle | null = null; - - /** - * {@link Rectangle} that specifies the maximum size of the container if - * {@link resizeContainer} is `true`. - */ - maximumContainerSize: Rectangle | null = null; - - /** - * Specifies if the container should be resized to the graph size when - * the graph size has changed. - * @default false - */ - resizeContainer = false; - - /** - * Border to be added to the bottom and right side when the container is - * being resized after the graph has been changed. - * @default 0 - */ - border = 0; - - /** - * Specifies if edges should appear in the foreground regardless of their order - * in the model. If {@link keepEdgesInForeground} and {@link keepEdgesInBackground} are - * both `true` then the normal order is applied. - * @default false - */ - keepEdgesInForeground = false; - - /** - * Specifies if edges should appear in the background regardless of their order - * in the model. If {@link keepEdgesInForeground} and {@link keepEdgesInBackground} are - * both `true` then the normal order is applied. - * @default false - */ - keepEdgesInBackground = false; - - /** - * Specifies the return value for {@link isRecursiveResize}. - * @default false (for backwards compatibility) - */ - recursiveResize = false; - - /** - * Specifies if the scale and translate should be reset if the root changes in - * the model. - * @default true - */ - resetViewOnRootChange = true; - - /** - * Specifies if loops (aka self-references) are allowed. - * @default false - */ - allowLoops = false; - - /** - * {@link EdgeStyle} to be used for loops. This is a fallback for loops if the - * {@link CellStateStyle.loopStyle} is `undefined`. - * @default {@link EdgeStyle.Loop} - */ - defaultLoopStyle = EdgeStyle.Loop; - - /** - * Specifies if multiple edges in the same direction between the same pair of - * vertices are allowed. - * @default true - */ - multigraph = true; - - /** - * Specifies the minimum scale to be applied in {@link fit}. Set this to `null` to allow any value. - * @default 0.1 - */ - minFitScale: number | null = 0.1; - - /** - * Specifies the maximum scale to be applied in {@link fit}. Set this to `null` to allow any value. - * @default 8 - */ - maxFitScale: number | null = 8; - - /** - * Specifies the {@link Image} for the image to be used to display a warning - * overlay. See {@link setCellWarning}. Default value is Client.imageBasePath + - * '/warning'. The extension for the image depends on the platform. It is - * '.png' on the Mac and '.gif' on all other platforms. - */ - warningImage: Image = new Image( - `${Client.imageBasePath}/warning${Client.IS_MAC ? '.png' : '.gif'}`, - 16, - 16 - ); - - /** - * Specifies the resource key for the error message to be displayed in - * non-multigraphs when two vertices are already connected. If the resource - * for this key does not exist then the value is used as the error message. - * @default 'alreadyConnected' - */ - alreadyConnectedResource: string = isI18nEnabled() ? 'alreadyConnected' : ''; - - /** - * Specifies the resource key for the warning message to be displayed when - * a collapsed cell contains validation errors. If the resource for this - * key does not exist then the value is used as the warning message. - * @default 'containsValidationErrors' - */ - containsValidationErrorsResource: string = isI18nEnabled() - ? 'containsValidationErrors' - : ''; - - /** Folding options. */ - options: GraphFoldingOptions = { - foldingEnabled: true, - collapsedImage: new Image(`${Client.imageBasePath}/collapsed.gif`, 9, 9), - expandedImage: new Image(`${Client.imageBasePath}/expanded.gif`, 9, 9), - collapseToPreferredSize: true, - }; - - // =================================================================================================================== - // Group: "Create Class Instance" factory functions. - // These can be overridden in subclasses of Graph to allow the Graph to instantiate user-defined implementations with - // custom behavior. - // =================================================================================================================== - +export class Graph extends AbstractGraph { /** * Creates a new {@link CellRenderer} to be used in this graph. */ @@ -420,35 +46,6 @@ class Graph extends EventSource { return new CellRenderer(); } - /** - * Hooks to create a new {@link EdgeHandler} for the given {@link CellState}. - * - * @param state {@link CellState} to create the handler for. - */ - createEdgeHandlerInstance(state: CellState): EdgeHandler { - // Note this method not being called createEdgeHandler to keep compatibility - // with older code which overrides/calls createEdgeHandler - return new EdgeHandler(state); - } - - /** - * Hooks to create a new {@link EdgeSegmentHandler} for the given {@link CellState}. - * - * @param state {@link CellState} to create the handler for. - */ - createEdgeSegmentHandler(state: CellState) { - return new EdgeSegmentHandler(state); - } - - /** - * Hooks to create a new {@link ElbowEdgeHandler} for the given {@link CellState}. - * - * @param state {@link CellState} to create the handler for. - */ - createElbowEdgeHandler(state: CellState) { - return new ElbowEdgeHandler(state); - } - /** * Creates a new {@link GraphDataModel} to be used in this graph. */ @@ -477,1022 +74,29 @@ class Graph extends EventSource { return new Stylesheet(); } - /** - * Hooks to create a new {@link VertexHandler} for the given {@link CellState}. - * - * @param state {@link CellState} to create the handler for. - */ - createVertexHandler(state: CellState): VertexHandler { - return new VertexHandler(state); - } - - // =================================================================================================================== - // Group: Main graph constructor and functions - // =================================================================================================================== - - protected registerDefaults(): void { + // Register all builtins provided by maxGraph + protected override registerDefaults(): void { registerDefaultEdgeMarkers(); registerDefaultEdgeStyles(); registerDefaultPerimeters(); registerDefaultShapes(); } + // Use the create factory methods of the class instead of the collaborators because they cannot be passed in the constructor + protected override initializeCollaborators(options?: GraphCollaboratorsOptions): void { + this.cellRenderer = this.createCellRenderer(); + this.model = options?.model ?? this.createGraphDataModel(); + this.setSelectionModel(this.createSelectionModel()); + this.setStylesheet(options?.stylesheet ?? this.createStylesheet()); + this.view = this.createGraphView(); + } + constructor( container?: HTMLElement, model?: GraphDataModel, plugins: GraphPluginConstructor[] = getDefaultPlugins(), stylesheet?: Stylesheet | null ) { - super(); - this.registerDefaults(); - - this.container = container ?? document.createElement('div'); - this.model = model ?? this.createGraphDataModel(); - this.cellRenderer = this.createCellRenderer(); - this.setStylesheet(stylesheet ?? this.createStylesheet()); - this.view = this.createGraphView(); - - // Adds a graph model listener to update the view - this.graphModelChangeListener = (sender: any, evt: EventObject) => { - this.graphModelChanged(evt.getProperty('edit').changes); - }; - this.getDataModel().addListener(InternalEvent.CHANGE, this.graphModelChangeListener); - - // Initializes the container using the view - this.view.init(); - - // Updates the size of the container for the current graph - this.sizeDidChange(); - - // Set the selection model - this.setSelectionModel(this.createSelectionModel()); - - // Initializes plugins - plugins.forEach((p) => (this.plugins[p.pluginId] = new p(this))); - - this.view.revalidate(); - } - - getContainer = () => this.container; - getPlugin = (id: string): T => this.plugins[id] as T; - getCellRenderer = () => this.cellRenderer; - getDialect = () => this.dialect; - isPageVisible = () => this.pageVisible; - isPageBreaksVisible = () => this.pageBreaksVisible; - getPageBreakColor = () => this.pageBreakColor; - isPageBreakDashed = () => this.pageBreakDashed; - getMinPageBreakDist = () => this.minPageBreakDist; - isPreferPageSize = () => this.preferPageSize; - getPageFormat = () => this.pageFormat; - getPageScale = () => this.pageScale; - isExportEnabled = () => this.exportEnabled; - isImportEnabled = () => this.importEnabled; - isIgnoreScrollbars = () => this.ignoreScrollbars; - isTranslateToScrollPosition = () => this.translateToScrollPosition; - - getMinimumGraphSize = () => this.minimumGraphSize; - setMinimumGraphSize = (size: Rectangle | null) => (this.minimumGraphSize = size); - - getMinimumContainerSize = () => this.minimumContainerSize; - setMinimumContainerSize = (size: Rectangle | null) => - (this.minimumContainerSize = size); - - getWarningImage() { - return this.warningImage; - } - - getAlreadyConnectedResource = () => this.alreadyConnectedResource; - - getContainsValidationErrorsResource = () => this.containsValidationErrorsResource; - - /** - * Updates the model in a transaction. - * - * @param fn the update to be performed in the transaction. - * - * @see {@link GraphDataModel.batchUpdate} - */ - batchUpdate(fn: () => void) { - this.getDataModel().batchUpdate(fn); - } - - /** - * Returns the {@link GraphDataModel} that contains the cells. - */ - getDataModel() { - return this.model; - } - - /** - * Returns the {@link GraphView} that contains the {@link mxCellStates}. - */ - getView() { - return this.view; - } - - /** - * Returns the {@link Stylesheet} that defines the style. - */ - getStylesheet() { - return this.stylesheet; - } - - /** - * Sets the {@link Stylesheet} that defines the style. - */ - setStylesheet(stylesheet: Stylesheet) { - this.stylesheet = stylesheet; - } - - /** - * Called when the graph model changes. Invokes {@link processChange} on each - * item of the given array to update the view accordingly. - * - * @param changes Array that contains the individual changes. - */ - graphModelChanged(changes: any[]) { - for (const change of changes) { - this.processChange(change); - } - - this.updateSelection(); - this.view.validate(); - this.sizeDidChange(); - } - - /** - * Processes the given change and invalidates the respective cached data - * in {@link GraphView}. This fires a {@link root} event if the root has changed in the - * model. - * - * @param {(RootChange|ChildChange|TerminalChange|GeometryChange|ValueChange|StyleChange)} change - Object that represents the change on the model. - */ - processChange(change: any): void { - // Resets the view settings, removes all cells and clears - // the selection if the root changes. - if (change instanceof RootChange) { - this.clearSelection(); - this.setDefaultParent(null); - - if (change.previous) this.removeStateForCell(change.previous); - - if (this.resetViewOnRootChange) { - this.view.scale = 1; - this.view.translate.x = 0; - this.view.translate.y = 0; - } - - this.fireEvent(new EventObject(InternalEvent.ROOT)); - } - - // Adds or removes a child to the view by online invaliding - // the minimal required portions of the cache, namely, the - // old and new parent and the child. - else if (change instanceof ChildChange) { - const newParent = change.child.getParent(); - this.view.invalidate(change.child, true, true); - - if ( - !newParent || - !this.getDataModel().contains(newParent) || - newParent.isCollapsed() - ) { - this.view.invalidate(change.child, true, true); - this.removeStateForCell(change.child); - - // Handles special case of current root of view being removed - if (this.view.currentRoot == change.child) { - this.home(); - } - } - - if (newParent != change.previous) { - // Refreshes the collapse/expand icons on the parents - if (newParent != null) { - this.view.invalidate(newParent, false, false); - } - - if (change.previous != null) { - this.view.invalidate(change.previous, false, false); - } - } - } - - // Handles two special cases where the shape does not need to be - // recreated from scratch, it only needs to be invalidated. - else if (change instanceof TerminalChange || change instanceof GeometryChange) { - // Checks if the geometry has changed to avoid unnessecary revalidation - if ( - change instanceof TerminalChange || - (change.previous == null && change.geometry != null) || - (change.previous != null && !change.previous.equals(change.geometry)) - ) { - this.view.invalidate(change.cell); - } - } - - // Handles two special cases where only the shape, but no - // descendants need to be recreated - else if (change instanceof ValueChange) { - this.view.invalidate(change.cell, false, false); - } - - // Requires a new mxShape in JavaScript - else if (change instanceof StyleChange) { - this.view.invalidate(change.cell, true, true); - const state = this.view.getState(change.cell); - - if (state != null) { - state.invalidStyle = true; - } - } - - // Removes the state from the cache by default - else if (change.cell != null && change.cell instanceof Cell) { - this.removeStateForCell(change.cell); - } - } - - /** - * Scrolls the graph to the given point, extending the graph container if - * specified. - */ - scrollPointToVisible(x: number, y: number, extend = false, border = 20) { - const panningHandler = this.getPlugin('PanningHandler'); - - if ( - !this.isTimerAutoScroll() && - (this.ignoreScrollbars || hasScrollbars(this.container)) - ) { - const c = this.container; - - if ( - x >= c.scrollLeft && - y >= c.scrollTop && - x <= c.scrollLeft + c.clientWidth && - y <= c.scrollTop + c.clientHeight - ) { - let dx = c.scrollLeft + c.clientWidth - x; - - if (dx < border) { - const old = c.scrollLeft; - c.scrollLeft += border - dx; - - // Automatically extends the canvas size to the bottom, right - // if the event is outside of the canvas and the edge of the - // canvas has been reached. Notes: Needs fix for IE. - if (extend && old === c.scrollLeft) { - // @ts-ignore - const root = this.view.getDrawPane().ownerSVGElement; - const width = c.scrollWidth + border - dx; - - // Updates the clipping region. This is an expensive - // operation that should not be executed too often. - // @ts-ignore - root.style.width = `${width}px`; - - c.scrollLeft += border - dx; - } - } else { - dx = x - c.scrollLeft; - - if (dx < border) { - c.scrollLeft -= border - dx; - } - } - - let dy = c.scrollTop + c.clientHeight - y; - - if (dy < border) { - const old = c.scrollTop; - c.scrollTop += border - dy; - - if (old == c.scrollTop && extend) { - // @ts-ignore - const root = this.view.getDrawPane().ownerSVGElement; - const height = c.scrollHeight + border - dy; - - // Updates the clipping region. This is an expensive - // operation that should not be executed too often. - // @ts-ignore - root.style.height = `${height}px`; - - c.scrollTop += border - dy; - } - } else { - dy = y - c.scrollTop; - - if (dy < border) { - c.scrollTop -= border - dy; - } - } - } - } else if ( - this.isAllowAutoPanning() && - panningHandler && - !panningHandler.isActive() - ) { - panningHandler.getPanningManager().panTo(x + this.getPanDx(), y + this.getPanDy()); - } - } - - /** - * Returns the size of the border and padding on all four sides of the - * container. The left, top, right and bottom borders are stored in the x, y, - * width and height of the returned {@link Rectangle}, respectively. - */ - getBorderSizes(): Rectangle { - const css = getCurrentStyle(this.container); - - return new Rectangle( - parseCssNumber(css.paddingLeft) + - (css.borderLeftStyle != 'none' ? parseCssNumber(css.borderLeftWidth) : 0), - parseCssNumber(css.paddingTop) + - (css.borderTopStyle != 'none' ? parseCssNumber(css.borderTopWidth) : 0), - parseCssNumber(css.paddingRight) + - (css.borderRightStyle != 'none' ? parseCssNumber(css.borderRightWidth) : 0), - parseCssNumber(css.paddingBottom) + - (css.borderBottomStyle != 'none' ? parseCssNumber(css.borderBottomWidth) : 0) - ); - } - - /** - * Returns the preferred size of the background page if {@link preferPageSize} is true. - */ - getPreferredPageSize(bounds: Rectangle, width: number, height: number) { - const tr = this.view.translate; - const fmt = this.pageFormat; - const ps = this.pageScale; - const page = new Rectangle( - 0, - 0, - Math.ceil(fmt.width * ps), - Math.ceil(fmt.height * ps) - ); - - const hCount = this.pageBreaksVisible ? Math.ceil(width / page.width) : 1; - const vCount = this.pageBreaksVisible ? Math.ceil(height / page.height) : 1; - - return new Rectangle( - 0, - 0, - hCount * page.width + 2 + tr.x, - vCount * page.height + 2 + tr.y - ); - } - - /** - * Scales the graph such that the complete diagram fits into {@link Graph.container} and returns the current scale in the view. - * To fit an initial graph prior to rendering, set {@link GraphView.rendering} to `false` prior to changing the model - * and execute the following after changing the model. - * - * ```javascript - * graph.view.rendering = false; - * // here, change the model - * graph.fit(); - * graph.view.rendering = true; - * graph.refresh(); - * ``` - * - * To fit and center the graph, use {@link FitPlugin.fitCenter}. - * - * @param border Optional number that specifies the border. Default is {@link border}. - * @param keepOrigin Optional boolean that specifies if the translate should be changed. Default is `false`. - * @param margin Optional margin in pixels. Default is `0`. - * @param enabled Optional boolean that specifies if the scale should be set or just returned. Default is `true`. - * @param ignoreWidth Optional boolean that specifies if the width should be ignored. Default is `false`. - * @param ignoreHeight Optional boolean that specifies if the height should be ignored. Default is `false`. - * @param maxHeight Optional maximum height. - */ - fit( - border: number = this.getBorder(), - keepOrigin = false, - margin = 0, - enabled = true, - ignoreWidth = false, - ignoreHeight = false, - maxHeight: number | null = null - ): number { - const { container, view } = this; - if (container) { - // Adds spacing and border from css - const cssBorder = this.getBorderSizes(); - let w1: number = container.offsetWidth - cssBorder.x - cssBorder.width - 1; - let h1: number = - maxHeight != null - ? maxHeight - : container.offsetHeight - cssBorder.y - cssBorder.height - 1; - let bounds = view.getGraphBounds(); - - if (bounds.width > 0 && bounds.height > 0) { - if (keepOrigin && bounds.x != null && bounds.y != null) { - bounds = bounds.clone(); - bounds.width += bounds.x; - bounds.height += bounds.y; - bounds.x = 0; - bounds.y = 0; - } - - // LATER: Use unscaled bounding boxes to fix rounding errors - const originalScale = view.scale; - let w2 = bounds.width / originalScale; - let h2 = bounds.height / originalScale; - - // Fits to the size of the background image if required - if (this.backgroundImage) { - w2 = Math.max(w2, this.backgroundImage.width - bounds.x / originalScale); - h2 = Math.max(h2, this.backgroundImage.height - bounds.y / originalScale); - } - - const b: number = (keepOrigin ? border : 2 * border) + margin + 1; - - w1 -= b; - h1 -= b; - - let newScale = ignoreWidth - ? h1 / h2 - : ignoreHeight - ? w1 / w2 - : Math.min(w1 / w2, h1 / h2); - - if (this.minFitScale != null) { - newScale = Math.max(newScale, this.minFitScale); - } - - if (this.maxFitScale != null) { - newScale = Math.min(newScale, this.maxFitScale); - } - - if (enabled) { - if (!keepOrigin) { - if (!hasScrollbars(container)) { - const x0 = - bounds.x != null - ? Math.floor( - view.translate.x - - bounds.x / originalScale + - border / newScale + - margin / 2 - ) - : border; - const y0 = - bounds.y != null - ? Math.floor( - view.translate.y - - bounds.y / originalScale + - border / newScale + - margin / 2 - ) - : border; - - view.scaleAndTranslate(newScale, x0, y0); - } else { - view.setScale(newScale); - const newBounds = this.getGraphBounds(); - - if (newBounds.x != null) { - container.scrollLeft = newBounds.x; - } - - if (newBounds.y != null) { - container.scrollTop = newBounds.y; - } - } - } else if (view.scale != newScale) { - view.setScale(newScale); - } - } else { - return newScale; - } - } - } - return view.scale; - } - - /** - * Resizes the container for the given graph width and height. - */ - doResizeContainer(width: number, height: number): void { - if (this.maximumContainerSize != null) { - width = Math.min(this.maximumContainerSize.width, width); - height = Math.min(this.maximumContainerSize.height, height); - } - const container = this.container; - container.style.width = `${Math.ceil(width)}px`; - container.style.height = `${Math.ceil(height)}px`; - } - - /***************************************************************************** - * Group: UNCLASSIFIED - *****************************************************************************/ - - /** - * Creates a new handler for the given cell state. This implementation - * returns a new {@link EdgeHandler} of the corresponding cell is an edge, - * otherwise it returns an {@link VertexHandler}. - * - * @param state {@link CellState} whose handler should be created. - */ - createHandler(state: CellState) { - let result: EdgeHandler | VertexHandler | null = null; - - if (state.cell.isEdge()) { - const source = state.getVisibleTerminalState(true); - const target = state.getVisibleTerminalState(false); - const geo = state.cell.getGeometry(); - - const edgeStyle = this.getView().getEdgeStyle( - state, - geo ? geo.points || undefined : undefined, - source, - target - ); - result = this.createEdgeHandler(state, edgeStyle); - } else { - result = this.createVertexHandler(state); - } - return result; - } - - /** - * Hooks to create a new {@link EdgeHandler} for the given {@link CellState}. - * - * @param state {@link CellState} to create the handler for. - * @param edgeStyle the {@link EdgeStyleFunction} that let choose the actual edge handler. - */ - createEdgeHandler(state: CellState, edgeStyle: EdgeStyleFunction | null): EdgeHandler { - let result = null; - if ( - edgeStyle == EdgeStyle.ElbowConnector || - edgeStyle == EdgeStyle.Loop || - edgeStyle == EdgeStyle.SideToSide || - edgeStyle == EdgeStyle.TopToBottom - ) { - result = this.createElbowEdgeHandler(state); - } else if ( - edgeStyle == EdgeStyle.ManhattanConnector || - edgeStyle == EdgeStyle.OrthConnector || - edgeStyle == EdgeStyle.SegmentConnector - ) { - result = this.createEdgeSegmentHandler(state); - } else { - result = this.createEdgeHandlerInstance(state); - } - - return result; - } - - /***************************************************************************** - * Group: Drilldown - *****************************************************************************/ - - /** - * Returns the current root of the displayed cell hierarchy. This is a - * shortcut to {@link GraphView.currentRoot} in {@link GraphView}. - */ - getCurrentRoot() { - return this.view.currentRoot; - } - - /** - * Returns the translation to be used if the given cell is the root cell as - * an {@link Point}. This implementation returns null. - * - * To keep the children at their absolute position while stepping into groups, - * this function can be overridden as follows. - * - * @example - * ```javascript - * var offset = new mxPoint(0, 0); - * - * while (cell != null) - * { - * var geo = this.model.getGeometry(cell); - * - * if (geo != null) - * { - * offset.x -= geo.x; - * offset.y -= geo.y; - * } - * - * cell = this.model.getParent(cell); - * } - * - * return offset; - * ``` - * - * @param cell {@link mxCell} that represents the root. - */ - getTranslateForRoot(cell: Cell | null): Point | null { - return null; - } - - /** - * Returns the offset to be used for the cells inside the given cell. The - * root and layer cells may be identified using {@link GraphDataModel.isRoot} and - * {@link GraphDataModel.isLayer}. For all other current roots, the - * {@link GraphView.currentRoot} field points to the respective cell, so that - * the following holds: cell == this.view.currentRoot. This implementation - * returns null. - * - * @param cell {@link mxCell} whose offset should be returned. - */ - getChildOffsetForCell(cell: Cell): Point | null { - return null; - } - - /** - * Uses the root of the model as the root of the displayed cell hierarchy - * and selects the previous root. - */ - home() { - const current = this.getCurrentRoot(); - - if (current != null) { - this.view.setCurrentRoot(null); - const state = this.view.getState(current); - - if (state != null) { - this.setSelectionCell(current); - } - } - } - - /** - * Returns true if the given cell is a valid root for the cell display - * hierarchy. This implementation returns true for all non-null values. - * - * @param cell {@link mxCell} which should be checked as a possible root. - */ - isValidRoot(cell: Cell) { - return !!cell; - } - - /***************************************************************************** - * Group: Graph display - *****************************************************************************/ - - /** - * Returns the bounds of the visible graph. Shortcut to - * {@link GraphView.getGraphBounds}. See also: {@link getBoundingBoxFromGeometry}. - */ - getGraphBounds(): Rectangle { - return this.view.getGraphBounds(); - } - - /** - * Returns the bounds inside which the diagram should be kept as an - * {@link Rectangle}. - */ - getMaximumGraphBounds(): Rectangle | null { - return this.maximumGraphBounds; - } - - /** - * 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 - * last step. - * - * @param cell Optional {@link Cell} for which the cell states should be cleared. - */ - refresh(cell: Cell | null = null): void { - if (cell) { - this.view.clear(cell, false); - } else { - this.view.clear(undefined, true); - } - this.view.validate(); - this.sizeDidChange(); - this.fireEvent(new EventObject(InternalEvent.REFRESH)); - } - - /** - * Centers the graph in the container. - * - * @param horizontal Optional boolean that specifies if the graph should be centered - * horizontally. Default is `true`. - * @param vertical Optional boolean that specifies if the graph should be centered - * vertically. Default is `true`. - * @param cx Optional float that specifies the horizontal center. Default is `0.5`. - * @param cy Optional float that specifies the vertical center. Default is `0.5`. - */ - center(horizontal = true, vertical = true, cx = 0.5, cy = 0.5): void { - const container = this.container; - const _hasScrollbars = hasScrollbars(this.container); - const padding = 2 * this.getBorder(); - const cw = container.clientWidth - padding; - const ch = container.clientHeight - padding; - const bounds = this.getGraphBounds(); - - const t = this.view.translate; - const s = this.view.scale; - - let dx = horizontal ? cw - bounds.width : 0; - let dy = vertical ? ch - bounds.height : 0; - - if (!_hasScrollbars) { - this.view.setTranslate( - horizontal ? Math.floor(t.x - bounds.x / s + (dx * cx) / s) : t.x, - vertical ? Math.floor(t.y - bounds.y / s + (dy * cy) / s) : t.y - ); - } else { - bounds.x -= t.x; - bounds.y -= t.y; - - const sw = container.scrollWidth; - const sh = container.scrollHeight; - - if (sw > cw) { - dx = 0; - } - - if (sh > ch) { - dy = 0; - } - - this.view.setTranslate( - Math.floor(dx / 2 - bounds.x), - Math.floor(dy / 2 - bounds.y) - ); - container.scrollLeft = (sw - cw) / 2; - container.scrollTop = (sh - ch) / 2; - } - } - - /** - * Returns `true` if perimeter points should be computed such that the resulting edge has only horizontal or vertical segments. - * - * @param edge {@link CellState} that represents the edge. - */ - isOrthogonal(edge: CellState): boolean { - const orthogonal = edge.style.orthogonal; - if (!isNullish(orthogonal)) { - return orthogonal; - } - - // fallback when the orthogonal style is not defined - const edgeStyle = this.view.getEdgeStyle(edge); - - return [ - EdgeStyle.EntityRelation, - EdgeStyle.ElbowConnector, - EdgeStyle.ManhattanConnector, - EdgeStyle.OrthConnector, - EdgeStyle.SegmentConnector, - EdgeStyle.SideToSide, - EdgeStyle.TopToBottom, - ].includes(edgeStyle!); - } - - /***************************************************************************** - * Group: Graph appearance - *****************************************************************************/ - - /** - * Returns the {@link backgroundImage} as an {@link Image}. - */ - getBackgroundImage(): Image | null { - return this.backgroundImage; - } - - /** - * Sets the new {@link backgroundImage}. - * - * @param image New {@link Image} to be used for the background. - */ - setBackgroundImage(image: Image | null): void { - this.backgroundImage = image; - } - - /** - * Returns the textual representation for the given cell. - * - * This implementation returns the node name or string-representation of the user object. - * - * - * The following returns the label attribute from the cells user object if it is an XML node. - * - * @example - * ```javascript - * graph.convertValueToString = function(cell) - * { - * return cell.getAttribute('label'); - * } - * ``` - * - * See also: {@link cellLabelChanged}. - * - * @param cell {@link Cell} whose textual representation should be returned. - */ - convertValueToString(cell: Cell): string { - const value = cell.getValue(); - - if (value != null) { - if (isNode(value)) { - return value.nodeName; - } - if (typeof value.toString === 'function') { - return value.toString(); - } - } - return ''; - } - - /** - * Returns the string to be used as the link for the given cell. - * - * This implementation returns null. - * - * @param cell {@link Cell} whose link should be returned. - */ - getLinkForCell(cell: Cell): string | null { - return null; - } - - /** - * Returns the value of {@link border}. - */ - getBorder(): number { - return this.border; - } - - /** - * Sets the value of {@link border}. - * - * @param value Positive integer that represents the border to be used. - */ - setBorder(value: number): void { - this.border = value; - } - - /***************************************************************************** - * Group: Graph behaviour - *****************************************************************************/ - - /** - * Returns {@link resizeContainer}. - */ - isResizeContainer() { - return this.resizeContainer; - } - - /** - * Sets {@link resizeContainer}. - * - * @param value Boolean indicating if the container should be resized. - */ - setResizeContainer(value: boolean) { - this.resizeContainer = value; - } - - /** - * Returns true if the graph is {@link enabled}. - */ - isEnabled() { - return this.enabled; - } - - /** - * Specifies if the graph should allow any interactions. This - * implementation updates {@link enabled}. - * - * @param value Boolean indicating if the graph should be enabled. - */ - setEnabled(value: boolean) { - this.enabled = value; - } - - /** - * Returns {@link multigraph} as a boolean. - */ - isMultigraph() { - return this.multigraph; - } - - /** - * Specifies if the graph should allow multiple connections between the - * same pair of vertices. - * - * @param value Boolean indicating if the graph allows multiple connections - * between the same pair of vertices. - */ - setMultigraph(value: boolean) { - this.multigraph = value; - } - - /** - * Returns {@link allowLoops} as a boolean. - */ - isAllowLoops() { - return this.allowLoops; - } - - /** - * Specifies if loops are allowed. - * - * @param value Boolean indicating if loops are allowed. - */ - setAllowLoops(value: boolean) { - this.allowLoops = value; - } - - /** - * Returns {@link recursiveResize}. - * - * @param state {@link CellState} that is being resized. - */ - isRecursiveResize(state: CellState | null = null) { - return this.recursiveResize; - } - - /** - * Sets {@link recursiveResize}. - * - * @param value New boolean value for {@link recursiveResize}. - */ - setRecursiveResize(value: boolean) { - this.recursiveResize = value; - } - - /** - * Returns a decimal number representing the amount of the width and height - * of the given cell that is allowed to overlap its parent. A value of 0 - * means all children must stay inside the parent, 1 means the child is - * allowed to be placed outside of the parent such that it touches one of - * the parents sides. If {@link isAllowOverlapParent} returns false for the given - * cell, then this method returns 0. - * - * @param cell {@link mxCell} for which the overlap ratio should be returned. - */ - getOverlap(cell: Cell) { - return this.isAllowOverlapParent(cell) ? this.defaultOverlap : 0; - } - - /** - * Returns true if the given cell is allowed to be placed outside of the - * parents area. - * - * @param cell {@link mxCell} that represents the child to be checked. - */ - isAllowOverlapParent(cell: Cell): boolean { - return false; - } - - /***************************************************************************** - * Group: Cell retrieval - *****************************************************************************/ - - /** - * Returns {@link defaultParent} or {@link GraphView.currentRoot} or the first child - * child of {@link GraphDataModel.root} if both are null. The value returned by - * this function should be used as the parent for new cells (aka default - * layer). - */ - getDefaultParent() { - let parent = this.getCurrentRoot(); - - if (!parent) { - parent = this.defaultParent; - - if (!parent) { - const root = this.getDataModel().getRoot(); - parent = root.getChildAt(0); - } - } - - return parent; - } - - /** - * Sets the {@link defaultParent} to the given cell. Set this to null to return - * the first child of the root in getDefaultParent. - */ - setDefaultParent(cell: Cell | null) { - this.defaultParent = cell; - } - - /** - * Destroys the graph and all its resources. - */ - destroy() { - if (!this.destroyed) { - this.destroyed = true; - - Object.values(this.plugins).forEach((p) => p.onDestroy()); - - this.view.destroy(); - - if (this.model && this.graphModelChangeListener) { - this.getDataModel().removeListener(this.graphModelChangeListener); - this.graphModelChangeListener = null; - } - } + super({ container, model, plugins, stylesheet: stylesheet ?? undefined }); } } - -// This introduces a side effect, but it is necessary to ensure the Graph is enriched with all properties and methods defined in mixins. -// It is only called when Graph is imported, so the Graph definition is always consistent. -// And this doesn't impact the tree-shaking. -applyGraphMixins(Graph); - -export { Graph }; diff --git a/packages/core/src/view/GraphSelectionModel.ts b/packages/core/src/view/GraphSelectionModel.ts index 09245a8b51..3bc3b786bd 100644 --- a/packages/core/src/view/GraphSelectionModel.ts +++ b/packages/core/src/view/GraphSelectionModel.ts @@ -17,7 +17,7 @@ limitations under the License. */ import EventSource from '../view/event/EventSource'; -import type { Graph } from './Graph'; +import type { AbstractGraph } from './AbstractGraph'; import type Cell from './cell/Cell'; import SelectionChange from './undoable_changes/SelectionChange'; import UndoableEdit from './undoable_changes/UndoableEdit'; @@ -26,20 +26,19 @@ import InternalEvent from './event/InternalEvent'; import { isI18nEnabled } from '../internal/i18n-utils'; /** - * Implements the selection model for a graph. Here is a listener that handles - * all removed selection cells. + * Implements the selection model for a graph. * - * (code) - * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt) - * { - * var cells = evt.getProperty('added'); + * Here is a listener that handles all removed selection cells. * - * for (var i = 0; i < cells.length; i++) - * { - * // Handle cells[i]... + * ```javascript + * graph.getSelectionModel().addListener(mxEvent.CHANGE, function(sender, evt) { + * const cells = evt.getProperty('added'); + * for (const cell of cells) { + * // Handle cell... * } * }); - * (end) + * ``` + * * * Event: mxEvent.UNDO * @@ -54,22 +53,19 @@ import { isI18nEnabled } from '../internal/i18n-utils'; * cells that have been added to or removed from the selection, respectively. * The names are inverted due to historic reasons. This cannot be changed. * - * Constructor: mxGraphSelectionModel - * - * Constructs a new graph selection model for the given {@link Graph}. - * - * Parameters: - * - * graph - Reference to the enclosing {@link Graph}. */ class GraphSelectionModel extends EventSource { - constructor(graph: Graph) { + /** + * Constructs a new graph selection model for the given {@link AbstractGraph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. + */ + constructor(graph: AbstractGraph) { super(); this.graph = graph; this.cells = []; } - graph: Graph; + graph: AbstractGraph; cells: Cell[]; /** diff --git a/packages/core/src/view/GraphView.ts b/packages/core/src/view/GraphView.ts index 897c1862f7..f937c57105 100644 --- a/packages/core/src/view/GraphView.ts +++ b/packages/core/src/view/GraphView.ts @@ -41,7 +41,7 @@ import ConnectionConstraint from './other/ConnectionConstraint'; import type PopupMenuHandler from './plugins/PopupMenuHandler'; import { getClientX, getClientY, getSource, isConsumed } from '../util/EventUtils'; import { clone } from '../util/cloneUtils'; -import type { Graph } from './Graph'; +import type { AbstractGraph } from './AbstractGraph'; import StyleRegistry from './style/StyleRegistry'; import type TooltipHandler from './plugins/TooltipHandler'; import type { EdgeStyleFunction, MouseEventListener } from '../types'; @@ -92,7 +92,7 @@ import { isI18nEnabled } from '../internal/i18n-utils'; * respectively. */ export class GraphView extends EventSource { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); this.graph = graph; @@ -156,9 +156,9 @@ export class GraphView extends EventSource { rendering = true; /** - * Reference to the enclosing {@link graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * {@link Cell} that acts as the root of the displayed cell hierarchy. @@ -227,7 +227,7 @@ export class GraphView extends EventSource { /** * Sets the scale and fires a {@link scale} event before calling {@link revalidate} followed - * by {@link Graph.sizeDidChange}. + * by {@link AbstractGraph.sizeDidChange}. * * @param value Decimal value that specifies the new scale (1 is 100%). */ @@ -259,7 +259,7 @@ export class GraphView extends EventSource { /** * Sets the translation and fires a {@link translate} event before calling - * {@link revalidate} followed by {@link Graph.sizeDidChange}. The translation is the + * {@link revalidate} followed by {@link AbstractGraph.sizeDidChange}. The translation is the * negative of the origin. * * @param dx X-coordinate of the translation. @@ -378,7 +378,7 @@ export class GraphView extends EventSource { /** * Sets and returns the current root and fires an {@link undo} event before - * calling {@link graph.sizeDidChange}. + * calling {@link AbstractGraph.sizeDidChange}. * * @param root {@link mxCell} that specifies the root of the displayed cell hierarchy. */ @@ -400,7 +400,7 @@ export class GraphView extends EventSource { /** * Sets the scale and translation and fires a {@link scale} and {@link translate} event - * before calling {@link revalidate} followed by {@link graph.sizeDidChange}. + * before calling {@link revalidate} followed by {@link AbstractGraph.sizeDidChange}. * * @param scale Decimal value that specifies the new scale (1 is 100%). * @param dx X-coordinate of the translation. @@ -1283,7 +1283,7 @@ export class GraphView extends EventSource { } /** - * Returns `true` if the given edge should be routed with {@link graph.defaultLoopStyle} + * Returns `true` if the given edge should be routed with {@link AbstractGraph.defaultLoopStyle} * or the {@link CellStateStyle.orthogonalLoop} defined for the given edge. * This implementation returns `true` if the given edge is a loop and does not */ diff --git a/packages/core/src/view/animate/Animation.ts b/packages/core/src/view/animate/Animation.ts index 91b10fa663..99bc33af4a 100644 --- a/packages/core/src/view/animate/Animation.ts +++ b/packages/core/src/view/animate/Animation.ts @@ -22,9 +22,6 @@ import InternalEvent from '../event/InternalEvent'; /** * Implements a basic animation in JavaScript. - * - * @class Animation - * @extends {EventSource} */ class Animation extends EventSource { constructor(delay = 20) { @@ -33,7 +30,8 @@ class Animation extends EventSource { } /** - * Specifies the delay between the animation steps. Defaul is 30ms. + * Specifies the delay between the animation steps. + * @default 20ms */ delay: number; diff --git a/packages/core/src/view/animate/Effects.ts b/packages/core/src/view/animate/Effects.ts index 33ed3c862a..8eb005c665 100644 --- a/packages/core/src/view/animate/Effects.ts +++ b/packages/core/src/view/animate/Effects.ts @@ -22,7 +22,7 @@ import TerminalChange from '../undoable_changes/TerminalChange'; import ValueChange from '../undoable_changes/ValueChange'; import ChildChange from '../undoable_changes/ChildChange'; import StyleChange from '../undoable_changes/StyleChange'; -import type { Graph } from '../../view/Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../../view/cell/Cell'; import { UndoableChange } from '../../types'; import Geometry from '../geometry/Geometry'; @@ -48,12 +48,16 @@ class Effects { * }); * ``` * - * @param graph - {@link Graph} that received the changes. + * @param graph - {@link AbstractGraph} that received the changes. * @param changes - Array of changes to be animated. * @param done - Optional function argument that is invoked after the * last step of the animation. */ - static animateChanges(graph: Graph, changes: UndoableChange[], done?: Function): void { + static animateChanges( + graph: AbstractGraph, + changes: UndoableChange[], + done?: Function + ): void { const maxStep = 10; let step = 0; @@ -125,11 +129,11 @@ class Effects { /** * Sets the opacity on the given cell and its descendants. * - * @param graph - {@link Graph} that contains the cells. + * @param graph - {@link AbstractGraph} that contains the cells. * @param cell - {@link Cell} to set the opacity for. * @param opacity - New value for the opacity in %. */ - static cascadeOpacity(graph: Graph, cell: Cell, opacity: number): void { + static cascadeOpacity(graph: AbstractGraph, cell: Cell, opacity: number): void { // Fades all children const childCount = cell.getChildCount(); diff --git a/packages/core/src/view/animate/Morphing.ts b/packages/core/src/view/animate/Morphing.ts index aff0a6d256..30346f5a01 100644 --- a/packages/core/src/view/animate/Morphing.ts +++ b/packages/core/src/view/animate/Morphing.ts @@ -21,7 +21,7 @@ import CellStatePreview from '../cell/CellStatePreview'; import Animation from './Animation'; import type CellState from '../cell/CellState'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Implements animation for morphing cells. Here is an example of @@ -50,23 +50,20 @@ import type { Graph } from '../Graph'; * * Constructs an animation. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. * @param steps Optional number of steps in the morphing animation. Default is 6. * @param ease Optional easing constant for the animation. Default is 1.5. - * @param delay Optional delay between the animation steps. Passed to . + * @param delay Optional delay between the animation steps. Passed to {@link Animation}. */ class Morphing extends Animation { - constructor(graph: Graph, steps = 6, ease = 1.5, delay?: number) { + constructor(graph: AbstractGraph, steps = 6, ease = 1.5, delay?: number) { super(delay); this.graph = graph; this.steps = steps; this.ease = ease; } - /** - * Specifies the delay between the animation steps. Defaul is 30ms. - */ - graph: Graph; + graph: AbstractGraph; /** * Specifies the maximum number of steps for the morphing. diff --git a/packages/core/src/view/cell/Cell.ts b/packages/core/src/view/cell/Cell.ts index 6084418937..6acd9e6c7f 100644 --- a/packages/core/src/view/cell/Cell.ts +++ b/packages/core/src/view/cell/Cell.ts @@ -40,8 +40,8 @@ import { isElement, isNullish } from '../../internal/utils'; * graph.insertVertex(graph.getDefaultParent(), null, node, 40, 40, 80, 30); * ``` * - * For the label to work, {@link graph.convertValueToString} and - * {@link graph.cellLabelChanged} should be overridden as follows: + * For the label to work, {@link AbstractGraph.convertValueToString} and + * {@link AbstractGraph.cellLabelChanged} should be overridden as follows: * * ```javascript * graph.convertValueToString(cell) { diff --git a/packages/core/src/view/cell/CellHighlight.ts b/packages/core/src/view/cell/CellHighlight.ts index c5c5a79de2..5ffe0ee64a 100644 --- a/packages/core/src/view/cell/CellHighlight.ts +++ b/packages/core/src/view/cell/CellHighlight.ts @@ -25,7 +25,7 @@ import { import InternalEvent from '../event/InternalEvent'; import Rectangle from '../geometry/Rectangle'; import type CellState from './CellState'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import Shape from '../geometry/Shape'; import type { ColorValue } from '../../types'; @@ -59,10 +59,9 @@ class CellHighlight { keepOnTop = false; /** - * Reference to the enclosing {@link graph}. - * @default true + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Reference to the {@link CellState}. @@ -83,7 +82,7 @@ class CellHighlight { resetHandler: Function; constructor( - graph: Graph, + graph: AbstractGraph, highlightColor?: ColorValue, strokeWidth?: number, dashed?: boolean diff --git a/packages/core/src/view/cell/CellMarker.ts b/packages/core/src/view/cell/CellMarker.ts index fab20c2b5c..cef7ef5b29 100644 --- a/packages/core/src/view/cell/CellMarker.ts +++ b/packages/core/src/view/cell/CellMarker.ts @@ -29,7 +29,7 @@ import CellHighlight from './CellHighlight'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import { intersectsHotspot } from '../../util/mathUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { ColorValue } from '../../types'; import type CellState from './CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; @@ -59,9 +59,9 @@ import type Cell from './Cell'; */ class CellMarker extends EventSource { /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Specifies if the marker is enabled. @@ -113,13 +113,13 @@ class CellMarker extends EventSource { /** * Constructs a new cell marker. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. * @param validColor Optional marker color for valid states. Default is {@link DEFAULT_VALID_COLOR}. * @param invalidColor Optional marker color for invalid states. Default is {@link DEFAULT_INVALID_COLOR}. * @param hotspot Portion of the width and height where a state intersects a given coordinate pair. A value of 0 means always highlight. Default is {@link DEFAULT_HOTSPOT}. */ constructor( - graph: Graph, + graph: AbstractGraph, validColor: ColorValue = DEFAULT_VALID_COLOR, invalidColor: ColorValue = DEFAULT_INVALID_COLOR, hotspot: number = DEFAULT_HOTSPOT diff --git a/packages/core/src/view/cell/CellOverlay.ts b/packages/core/src/view/cell/CellOverlay.ts index fd09bb74ec..29c8ae519c 100644 --- a/packages/core/src/view/cell/CellOverlay.ts +++ b/packages/core/src/view/cell/CellOverlay.ts @@ -27,9 +27,9 @@ import { AlignValue, VAlignValue } from '../../types'; /** * Extends {@link EventSource} to implement a graph overlay, represented by an icon * and a tooltip. Overlays can handle and fire events and are added to - * the graph using {@link Graph#addCellOverlay}, and removed using - * {@link Graph#removeCellOverlay}, or {@link Graph#removeCellOverlays} to remove all overlays. - * The {@link Graph#getCellOverlays} function returns the array of overlays for a given + * the graph using {@link AbstractGraph.addCellOverlay}, and removed using + * {@link AbstractGraph.removeCellOverlay}, or {@link AbstractGraph.removeCellOverlays} to remove all overlays. + * The {@link AbstractGraph.getCellOverlays} function returns the array of overlays for a given * cell in a graph. If multiple overlays exist for the same cell, then * should be overridden in at least one of the overlays. * diff --git a/packages/core/src/view/cell/CellStatePreview.ts b/packages/core/src/view/cell/CellStatePreview.ts index 20d856582c..e3c8024ba7 100644 --- a/packages/core/src/view/cell/CellStatePreview.ts +++ b/packages/core/src/view/cell/CellStatePreview.ts @@ -20,26 +20,23 @@ import Point from '../geometry/Point'; import Dictionary from '../../util/Dictionary'; import type CellState from './CellState'; import type Cell from './Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type GraphView from '../GraphView'; /** * Implements a live preview for moving cells. */ class CellStatePreview { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.deltas = new Dictionary(); this.graph = graph; } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; - /** - * Reference to the enclosing {@link Graph}. - */ deltas: Dictionary; /** diff --git a/packages/core/src/view/cell/CellTracker.ts b/packages/core/src/view/cell/CellTracker.ts index 3c0061e569..7091c97fa7 100644 --- a/packages/core/src/view/cell/CellTracker.ts +++ b/packages/core/src/view/cell/CellTracker.ts @@ -18,7 +18,7 @@ limitations under the License. import CellMarker from './CellMarker'; import InternalMouseEvent from '../event/InternalMouseEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from './Cell'; import EventSource from '../event/EventSource'; import type { ColorValue, MouseListenerSet } from '../../types'; @@ -78,7 +78,7 @@ import type { ColorValue, MouseListenerSet } from '../../types'; */ class CellTracker extends CellMarker implements MouseListenerSet { constructor( - graph: Graph, + graph: AbstractGraph, color: ColorValue, funct: ((me: InternalMouseEvent) => Cell) | null = null ) { diff --git a/packages/core/src/view/cell/VertexHandle.ts b/packages/core/src/view/cell/VertexHandle.ts index 7f0b458a32..d48718896b 100644 --- a/packages/core/src/view/cell/VertexHandle.ts +++ b/packages/core/src/view/cell/VertexHandle.ts @@ -28,7 +28,7 @@ import InternalMouseEvent from '../event/InternalMouseEvent'; import ImageBox from '../image/ImageBox'; import CellState from './CellState'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type { CellHandle, CellStateStyle } from '../../types'; import { HandleConfig } from '../handler/config'; @@ -40,7 +40,7 @@ import { HandleConfig } from '../handler/config'; class VertexHandle implements CellHandle { dependencies = ['snap', 'cells']; - graph: Graph; + graph: AbstractGraph; state: CellState; shape: Shape | ImageShape | null; diff --git a/packages/core/src/view/event/EventSource.ts b/packages/core/src/view/event/EventSource.ts index 7ca2295f7f..cccf954ae8 100644 --- a/packages/core/src/view/event/EventSource.ts +++ b/packages/core/src/view/event/EventSource.ts @@ -24,20 +24,20 @@ type EventListenerObject = { }; /** - * Base class for objects that dispatch named events. To create a subclass that - * inherits from mxEventSource, the following code is used. + * Base class for objects that dispatch named events. * - * ```javascript - * function MyClass() { }; + * To create a subclass that inherits from `EventSource`, the following code is used: * - * MyClass.prototype = new mxEventSource(); - * constructor = MyClass; + * ```javascript + * class MyClass extends EventSource { + * // implement the logic here + * }; * ``` * * Known Subclasses: * - {@link CellOverlay} * - {@link Editor} - * - {@link Graph} + * - {@link AbstractGraph} * - {@link GraphDataModel} * - {@link GraphView} * - {@link MaxToolbar} diff --git a/packages/core/src/view/event/InternalEvent.ts b/packages/core/src/view/event/InternalEvent.ts index 83c71cfc28..3aea2b046c 100644 --- a/packages/core/src/view/event/InternalEvent.ts +++ b/packages/core/src/view/event/InternalEvent.ts @@ -27,7 +27,7 @@ import type { Listenable, MouseEventListener, } from '../../types'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; // Checks if passive event listeners are supported // see https://github.com/Modernizr/Modernizr/issues/1894 @@ -54,7 +54,7 @@ try { * @class InternalEvent * * Cross-browser DOM event support. For internal event handling, - * {@link mxEventSource} and the graph event dispatch loop in {@link graph} are used. + * {@link EventSource} and the graph event dispatch loop in {@link AbstractGraph} are used. * * ### Memory Leaks: * @@ -238,7 +238,7 @@ class InternalEvent { */ static redirectMouseEvents( node: Listenable, - graph: Graph, + graph: AbstractGraph, state: CellState | ((evt: Event) => CellState | null) | null = null, down: MouseEventListener | null = null, move: MouseEventListener | null = null, diff --git a/packages/core/src/view/event/InternalMouseEvent.ts b/packages/core/src/view/event/InternalMouseEvent.ts index 084d7b3c5b..fd41b471db 100644 --- a/packages/core/src/view/event/InternalMouseEvent.ts +++ b/packages/core/src/view/event/InternalMouseEvent.ts @@ -80,13 +80,13 @@ class InternalMouseEvent { /** * Holds the x-coordinate of the event in the graph. This value is set in - * {@link Graph#fireMouseEvent}. + * {@link AbstractGraph.fireMouseEvent}. */ graphX: number; /** * Holds the y-coordinate of the event in the graph. This value is set in - * {@link Graph#fireMouseEvent}. + * {@link AbstractGraph.fireMouseEvent}. */ graphY: number; @@ -97,7 +97,7 @@ class InternalMouseEvent { /** * Holds the that was passed to the constructor. This can be - * different from depending on the result of {@link Graph#getEventState}. + * different from depending on the result of {@link AbstractGraph.getEventState}. */ sourceState: CellState | null; diff --git a/packages/core/src/view/geometry/Geometry.ts b/packages/core/src/view/geometry/Geometry.ts index 8f0db6d981..79efd4af02 100644 --- a/packages/core/src/view/geometry/Geometry.ts +++ b/packages/core/src/view/geometry/Geometry.ts @@ -45,7 +45,7 @@ import { clone } from '../../util/cloneUtils'; * be ignored or interpreted differently depending on the edge's {@link edgeStyle}. * * To disable automatic reset of control points after a cell has been moved or - * resized, {@link graph.resetEdgesOnMove} and {@link graph.resetEdgesOnResize} may be used. + * resized, {@link AbstractGraph.resetEdgesOnMove} and {@link AbstractGraph.resetEdgesOnResize} may be used. * * ### Edge Labels * diff --git a/packages/core/src/view/handler/ConstraintHandler.ts b/packages/core/src/view/handler/ConstraintHandler.ts index 4adce23d46..d2c4e0a6ac 100644 --- a/packages/core/src/view/handler/ConstraintHandler.ts +++ b/packages/core/src/view/handler/ConstraintHandler.ts @@ -31,7 +31,7 @@ import Rectangle from '../geometry/Rectangle'; import ImageShape from '../geometry/node/ImageShape'; import RectangleShape from '../geometry/node/RectangleShape'; import { isShiftDown } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import CellState from '../cell/CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; import ConnectionConstraint from '../other/ConnectionConstraint'; @@ -43,7 +43,6 @@ import type Cell from '../cell/Cell'; * showing fixed points when the mouse is over a vertex and handles constraints * to establish new connections. * - * @class ConstraintHandler */ class ConstraintHandler { /** @@ -52,9 +51,9 @@ class ConstraintHandler { pointImage = new Image(`${Client.imageBasePath}/point.gif`, 5, 5); /** - * Reference to the enclosing {@link mxGraph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; resetHandler: () => void; @@ -86,7 +85,7 @@ class ConstraintHandler { mouseleaveHandler: (() => void) | null = null; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; // Adds a graph model listener to update the current focus on changes diff --git a/packages/core/src/view/handler/EdgeHandler.ts b/packages/core/src/view/handler/EdgeHandler.ts index 4872b9dd32..2e596e2358 100644 --- a/packages/core/src/view/handler/EdgeHandler.ts +++ b/packages/core/src/view/handler/EdgeHandler.ts @@ -53,7 +53,7 @@ import { isMouseEvent, isShiftDown, } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import CellState from '../cell/CellState'; import Shape from '../geometry/Shape'; import type { CellHandle, ColorValue, Listenable, MouseListenerSet } from '../../types'; @@ -70,15 +70,15 @@ import { EdgeHandlerConfig, HandleConfig } from './config'; * * Uses {@link CellMarker} for finding and highlighting new source and target vertices. * - * This handler is automatically created in {@link Graph.createHandler} for each selected edge. + * This handler is automatically created in {@link AbstractGraph.createHandler} for each selected edge. * * Some elements of this handler and its subclasses can be configured using {@link EdgeHandlerConfig}. */ class EdgeHandler implements MouseListenerSet { /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Reference to the {@link CellState} being modified. @@ -507,7 +507,7 @@ class EdgeHandler implements MouseListenerSet { /** * Returns the error message or an empty string if the connection for the * given source, target pair is not valid. Otherwise, it returns null. This - * implementation uses {@link Graph#getEdgeValidationError}. + * implementation uses {@link AbstractGraph.getEdgeValidationError}. * * @param source {@link Cell} that represents the source terminal. * @param target {@link Cell} that represents the target terminal. @@ -2248,7 +2248,7 @@ class EdgeHandlerCellMarker extends CellMarker { edgeHandler: EdgeHandler; constructor( - graph: Graph, + graph: AbstractGraph, edgeHandler: EdgeHandler, validColor: ColorValue = DEFAULT_VALID_COLOR, invalidColor: ColorValue = DEFAULT_INVALID_COLOR, diff --git a/packages/core/src/view/handler/ElbowEdgeHandler.ts b/packages/core/src/view/handler/ElbowEdgeHandler.ts index 7ad1e4f16a..c2e4bae2ca 100644 --- a/packages/core/src/view/handler/ElbowEdgeHandler.ts +++ b/packages/core/src/view/handler/ElbowEdgeHandler.ts @@ -31,7 +31,7 @@ import { isI18nEnabled, translate } from '../../internal/i18n-utils'; * Graph event handler that reconnects edges and modifies control points and * the edge label location. Uses {@link CellMarker} for finding and * highlighting new source and target vertices. This handler is automatically - * created in {@link Graph.createHandler}. It extends {@link EdgeHandler}. + * created in {@link AbstractGraph.createHandler}. It extends {@link EdgeHandler}. * * Constructor: mxEdgeHandler * @@ -45,7 +45,7 @@ class ElbowEdgeHandler extends EdgeHandler { } /** - * Specifies if a double click on the middle handle should call {@link Graph#flipEdge}. + * Specifies if a double click on the middle handle should call {@link AbstractGraph.flipEdge}. * @default true */ flipEnabled = true; @@ -92,7 +92,7 @@ class ElbowEdgeHandler extends EdgeHandler { } /** - * Creates a virtual bend that supports double-clicking and calls {@link Graph#flipEdge}. + * Creates a virtual bend that supports double-clicking and calls {@link AbstractGraph.flipEdge}. */ createVirtualBend(dblClickHandler?: (evt: MouseEvent) => void) { const bend = this.createHandleShape(); diff --git a/packages/core/src/view/handler/KeyHandler.ts b/packages/core/src/view/handler/KeyHandler.ts index 62c901b6b8..46b51e44e1 100644 --- a/packages/core/src/view/handler/KeyHandler.ts +++ b/packages/core/src/view/handler/KeyHandler.ts @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import InternalEvent from '../event/InternalEvent'; import { isAncestorNode } from '../../util/domUtils'; import { @@ -34,7 +34,7 @@ import type CellEditorHandler from '../plugins/CellEditorHandler'; * element (default). * * This handler installs a key event listener in the topmost DOM node and - * processes all events that originate from descendants of {@link Graph.container} + * processes all events that originate from descendants of {@link AbstractGraph.container} * or from the topmost DOM node. The latter means that all unhandled keystrokes * are handled by this object regardless of the focused state of the {@link graph}. * @@ -74,11 +74,11 @@ class KeyHandler { /** * Constructs an event handler that executes functions bound to specific keystrokes. * - * @param graph Reference to the associated {@link Graph}. + * @param graph Reference to the associated {@link AbstractGraph}. * @param target Optional reference to the event target. * If `null`, the document element is used as the event target, that is, the object where the key event listener is installed. */ - constructor(graph: Graph, target: Element | null = null) { + constructor(graph: AbstractGraph, target: Element | null = null) { if (graph != null) { this.graph = graph; this.target = target || document.documentElement; @@ -95,9 +95,9 @@ class KeyHandler { keydownHandler: ((event: KeyboardEvent) => void) | null = null; /** - * Reference to the {@link Graph} associated with this handler. + * Reference to the {@link AbstractGraph} associated with this handler. */ - graph: Graph | null = null; + graph: AbstractGraph | null = null; /** * Reference to the target DOM, that is, the DOM node where the key event @@ -225,7 +225,7 @@ class KeyHandler { /** * Returns `true` if the event should be processed by this handler. - * That is, if the event source is either the target, one of its direct children a descendant of the {@link Graph.container}, + * That is, if the event source is either the target, one of its direct children a descendant of the {@link AbstractGraph.container}, * or the {@link CellEditorHandler} plugin of the {@link graph}. * * @param evt Key event that represents the keystroke. @@ -280,7 +280,7 @@ class KeyHandler { * called later if the event is not an escape keystroke, in which case * {@link escape} is called. * - * This implementation returns `true` if {@link Graph.isEnabled} + * This implementation returns `true` if {@link AbstractGraph.isEnabled} * returns `true` for both, this handler and {@link graph}, if the event is not * consumed and if {@link isGraphEvent} returns `true`. * @@ -296,7 +296,7 @@ class KeyHandler { } /** - * Returns true if the given keystroke should be ignored. This returns {@link Graph.isEditing}. + * Returns true if the given keystroke should be ignored. This returns {@link AbstractGraph.isEditing}. * * @param evt Key event that represents the keystroke. */ @@ -306,7 +306,7 @@ class KeyHandler { /** * Hook to process ESCAPE keystrokes. This implementation invokes - * {@link Graph.stopEditing} to cancel the current editing, connecting + * {@link AbstractGraph.stopEditing} to cancel the current editing, connecting * and/or other ongoing modifications. * * @param evt Key event that represents the keystroke. Possible keycode in this case is 27 (ESCAPE). diff --git a/packages/core/src/view/handler/VertexHandler.ts b/packages/core/src/view/handler/VertexHandler.ts index 763ae3f498..a14c75b8e1 100644 --- a/packages/core/src/view/handler/VertexHandler.ts +++ b/packages/core/src/view/handler/VertexHandler.ts @@ -26,7 +26,7 @@ import Point from '../geometry/Point'; import { getRotatedPoint, intersects, mod, toRadians } from '../../util/mathUtils'; import Client from '../../Client'; import { isMouseEvent, isShiftDown } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import CellState from '../cell/CellState'; import Image from '../image/ImageBox'; import type Cell from '../cell/Cell'; @@ -42,7 +42,7 @@ import { HandleConfig, VertexHandlerConfig } from './config'; /** * Event handler for resizing cells. * - * This handler is automatically created in {@link Graph.createHandler}. + * This handler is automatically created in {@link AbstractGraph.createHandler}. * * Some elements of this handler and its subclasses can be configured using {@link EdgeHandlerConfig}. */ @@ -53,9 +53,9 @@ class VertexHandler implements MouseListenerSet { selectionBorder: RectangleShape; /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Reference to the {@link CellState} being modified. @@ -785,7 +785,7 @@ class VertexHandler implements MouseListenerSet { /** * Checks if the coordinates for the given event are within the - * {@link Graph#tolerance}. If the event is a mouse event then the tolerance is + * {@link AbstractGraph.tolerance}. If the event is a mouse event then the tolerance is * ignored. */ checkTolerance(me: InternalMouseEvent) { @@ -1408,7 +1408,7 @@ class VertexHandler implements MouseListenerSet { /** * Uses the given vector to change the bounds of the given cell - * in the graph using {@link Graph#resizeCell}. + * in the graph using {@link AbstractGraph.resizeCell}. */ resizeCell( cell: Cell, diff --git a/packages/core/src/view/image/ImageBundle.ts b/packages/core/src/view/image/ImageBundle.ts index 1074c470c3..9eb2939423 100644 --- a/packages/core/src/view/image/ImageBundle.ts +++ b/packages/core/src/view/image/ImageBundle.ts @@ -52,7 +52,7 @@ type ImageMap = { * If you are using mxOutline, you should use the same image bundles in the * graph that renders the outline. * - * The keys for images are resolved in {@link Graph#postProcessCellStyle} and + * The keys for images are resolved in {@link AbstractGraph.postProcessCellStyle} and * turned into a data URI if the returned value has a short data URI format * as specified above. * diff --git a/packages/core/src/view/layout/CircleLayout.ts b/packages/core/src/view/layout/CircleLayout.ts index 57ea1ccdbc..716b8c91c8 100644 --- a/packages/core/src/view/layout/CircleLayout.ts +++ b/packages/core/src/view/layout/CircleLayout.ts @@ -17,7 +17,7 @@ limitations under the License. */ import GraphLayout from './GraphLayout'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; /** @@ -38,10 +38,10 @@ class CircleLayout extends GraphLayout { /** * Constructs a new circular layout for the specified radius. * - * @param graph {@link Graph} that contains the cells. + * @param graph {@link AbstractGraph} that contains the cells. * @param radius Optional radius as an int. Default is 100. */ - constructor(graph: Graph, radius = 100) { + constructor(graph: AbstractGraph, radius = 100) { super(graph); this.radius = radius; } diff --git a/packages/core/src/view/layout/CompactTreeLayout.ts b/packages/core/src/view/layout/CompactTreeLayout.ts index 005d51ffa2..0e1dd5b9dd 100644 --- a/packages/core/src/view/layout/CompactTreeLayout.ts +++ b/packages/core/src/view/layout/CompactTreeLayout.ts @@ -24,7 +24,7 @@ import Rectangle from '../geometry/Rectangle'; import { sortCells } from '../../util/styleUtils'; import WeightedCellSorter from './util/WeightedCellSorter'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { findTreeRoots } from '../../util/treeTraversal'; /** @@ -75,7 +75,7 @@ export interface _mxCompactTreeLayoutLine { * @category Layout */ export class CompactTreeLayout extends GraphLayout { - constructor(graph: Graph, horizontal = true, invert = false) { + constructor(graph: AbstractGraph, horizontal = true, invert = false) { super(graph); this.horizontal = horizontal; this.invert = invert; diff --git a/packages/core/src/view/layout/CompositeLayout.ts b/packages/core/src/view/layout/CompositeLayout.ts index ef8c89d6fa..4c0943c6b1 100644 --- a/packages/core/src/view/layout/CompositeLayout.ts +++ b/packages/core/src/view/layout/CompositeLayout.ts @@ -17,7 +17,7 @@ limitations under the License. */ import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import GraphLayout from './GraphLayout'; /** @@ -42,11 +42,11 @@ class CompositeLayout extends GraphLayout { * Constructs a new layout using the given layouts. The graph instance is * required for creating the transaction that contains all layouts. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. * @param layouts Array of {@link GraphLayout}s. * @param master Optional layout that handles moves. If no layout is given, then the first layout of the above array is used to handle moves. */ - constructor(graph: Graph, layouts: GraphLayout[], master?: GraphLayout) { + constructor(graph: AbstractGraph, layouts: GraphLayout[], master?: GraphLayout) { super(graph); this.layouts = layouts; this.master = master; diff --git a/packages/core/src/view/layout/EdgeLabelLayout.ts b/packages/core/src/view/layout/EdgeLabelLayout.ts index fc63c48147..cd99a70efc 100644 --- a/packages/core/src/view/layout/EdgeLabelLayout.ts +++ b/packages/core/src/view/layout/EdgeLabelLayout.ts @@ -20,7 +20,7 @@ import Point from '../geometry/Point'; import GraphLayout from './GraphLayout'; import { intersects } from '../../util/mathUtils'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import CellState from '../cell/CellState'; import TextShape from '../geometry/node/TextShape'; import Rectangle from '../geometry/Rectangle'; @@ -39,7 +39,7 @@ import Rectangle from '../geometry/Rectangle'; * @category Layout */ class EdgeLabelLayout extends GraphLayout { - constructor(graph: Graph, radius: number) { + constructor(graph: AbstractGraph, radius: number) { super(graph); } diff --git a/packages/core/src/view/layout/FastOrganicLayout.ts b/packages/core/src/view/layout/FastOrganicLayout.ts index 6ef6697572..dd01d082a7 100644 --- a/packages/core/src/view/layout/FastOrganicLayout.ts +++ b/packages/core/src/view/layout/FastOrganicLayout.ts @@ -17,7 +17,7 @@ limitations under the License. */ import ObjectIdentity from '../../util/ObjectIdentity'; import GraphLayout from './GraphLayout'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; /** @@ -35,7 +35,7 @@ import type Cell from '../cell/Cell'; * @category Layout */ class MxFastOrganicLayout extends GraphLayout { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(graph); } diff --git a/packages/core/src/view/layout/GraphLayout.ts b/packages/core/src/view/layout/GraphLayout.ts index d1a42f57a5..7da1e924c8 100644 --- a/packages/core/src/view/layout/GraphLayout.ts +++ b/packages/core/src/view/layout/GraphLayout.ts @@ -20,7 +20,7 @@ import Dictionary from '../../util/Dictionary'; import Rectangle from '../geometry/Rectangle'; import Geometry from '../geometry/Geometry'; import Point from '../geometry/Point'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import { GraphLayoutTraverseArgs } from './types'; @@ -33,14 +33,14 @@ import { GraphLayoutTraverseArgs } from './types'; * @category Layout */ class GraphLayout { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Boolean indicating if the bounding box of the label should be used if it iss available. @@ -96,7 +96,7 @@ class GraphLayout { /** * Returns the graph that this layout operates on. */ - getGraph(): Graph { + getGraph(): AbstractGraph { return this.graph; } @@ -417,7 +417,7 @@ class GraphLayout { } /** - * Shortcut to {@link Graph#updateGroupBounds} with moveGroup set to true. + * Shortcut to {@link AbstractGraph.updateGroupBounds} with moveGroup set to true. */ arrangeGroups( cells: Cell[], diff --git a/packages/core/src/view/layout/HierarchicalLayout.ts b/packages/core/src/view/layout/HierarchicalLayout.ts index 0a2e5e5334..8a12b348ed 100644 --- a/packages/core/src/view/layout/HierarchicalLayout.ts +++ b/packages/core/src/view/layout/HierarchicalLayout.ts @@ -25,7 +25,7 @@ import ObjectIdentity from '../../util/ObjectIdentity'; import MinimumCycleRemover from './hierarchical/MinimumCycleRemover'; import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction'; import CoordinateAssignment from './hierarchical/CoordinateAssignment'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import { HierarchicalGraphLayoutTraverseArgs } from './types'; @@ -38,12 +38,12 @@ class HierarchicalLayout extends GraphLayout { /** * Constructs a new hierarchical layout algorithm. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. * @param orientation Optional constant that defines the orientation of this layout. Default is {@link DIRECTION.NORTH}. * @param deterministic Optional boolean that specifies if this layout should be deterministic. Default is true. */ constructor( - graph: Graph, + graph: AbstractGraph, orientation: DIRECTION = DIRECTION.NORTH, deterministic = true ) { diff --git a/packages/core/src/view/layout/LayoutManager.ts b/packages/core/src/view/layout/LayoutManager.ts index 378eac76b5..32051c788f 100644 --- a/packages/core/src/view/layout/LayoutManager.ts +++ b/packages/core/src/view/layout/LayoutManager.ts @@ -29,7 +29,7 @@ import EventObject from '../event/EventObject'; import type Cell from '../cell/Cell'; import Rectangle from '../geometry/Rectangle'; import { getClientX, getClientY } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import GraphLayout from './GraphLayout'; import UndoableEdit from '../undoable_changes/UndoableEdit'; @@ -57,9 +57,9 @@ import UndoableEdit from '../undoable_changes/UndoableEdit'; */ class LayoutManager extends EventSource { /** - * Reference to the enclosing {@link graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph!: Graph; + graph!: AbstractGraph; /** * Specifies if the layout should bubble along @@ -89,7 +89,7 @@ class LayoutManager extends EventSource { */ resizeHandler: (...args: any[]) => any; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); // Executes the layout before the changes are dispatched @@ -164,7 +164,7 @@ class LayoutManager extends EventSource { /** * Sets the graph that the layouts operate on. */ - setGraph(graph: Graph | null) { + setGraph(graph: AbstractGraph | null) { if (this.graph) { const model = this.graph.getDataModel(); model.removeListener(this.undoHandler); diff --git a/packages/core/src/view/layout/ParallelEdgeLayout.ts b/packages/core/src/view/layout/ParallelEdgeLayout.ts index 7abc210b48..ea27477f2b 100644 --- a/packages/core/src/view/layout/ParallelEdgeLayout.ts +++ b/packages/core/src/view/layout/ParallelEdgeLayout.ts @@ -19,7 +19,7 @@ limitations under the License. import Point from '../geometry/Point'; import GraphLayout from './GraphLayout'; import ObjectIdentity from '../../util/ObjectIdentity'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; @@ -63,7 +63,7 @@ import Geometry from '../geometry/Geometry'; * @category Layout */ class ParallelEdgeLayout extends GraphLayout { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(graph); } diff --git a/packages/core/src/view/layout/PartitionLayout.ts b/packages/core/src/view/layout/PartitionLayout.ts index 2b7a9b66f0..93e3b8be3e 100644 --- a/packages/core/src/view/layout/PartitionLayout.ts +++ b/packages/core/src/view/layout/PartitionLayout.ts @@ -18,7 +18,7 @@ limitations under the License. import Rectangle from '../geometry/Rectangle'; import GraphLayout from './GraphLayout'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; /** @@ -39,7 +39,7 @@ import type Cell from '../cell/Cell'; * @category Layout */ class PartitionLayout extends GraphLayout { - constructor(graph: Graph, horizontal = true, spacing = 0, border = 0) { + constructor(graph: AbstractGraph, horizontal = true, spacing = 0, border = 0) { super(graph); this.horizontal = horizontal != null ? horizontal : true; this.spacing = spacing || 0; diff --git a/packages/core/src/view/layout/RadialTreeLayout.ts b/packages/core/src/view/layout/RadialTreeLayout.ts index 231bf30658..4fbac515b6 100644 --- a/packages/core/src/view/layout/RadialTreeLayout.ts +++ b/packages/core/src/view/layout/RadialTreeLayout.ts @@ -22,7 +22,7 @@ import { _mxCompactTreeLayoutNode, } from './CompactTreeLayout'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Extends {@link CompactTreeLayout} to implement a radial tree algorithm. This @@ -37,7 +37,7 @@ import type { Graph } from '../Graph'; * @category Layout */ class RadialTreeLayout extends CompactTreeLayout { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(graph, false); } @@ -133,7 +133,7 @@ class RadialTreeLayout extends CompactTreeLayout { * Implements {@link GraphLayout#execute}. * * If the parent has any connected edges, then it is used as the root of - * the tree. Else, {@link Graph#findTreeRoots} will be used to find a suitable + * the tree. Else, {@link AbstractGraph.findTreeRoots} will be used to find a suitable * root node within the set of children of the given parent. * * @param parent {@link mxCell} whose children should be laid out. diff --git a/packages/core/src/view/layout/StackLayout.ts b/packages/core/src/view/layout/StackLayout.ts index 1ec3bba0ed..c0a36d5691 100644 --- a/packages/core/src/view/layout/StackLayout.ts +++ b/packages/core/src/view/layout/StackLayout.ts @@ -18,7 +18,7 @@ limitations under the License. import GraphLayout from './GraphLayout'; import { DEFAULT_STARTSIZE } from '../../util/Constants'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; @@ -37,7 +37,7 @@ import Geometry from '../geometry/Geometry'; */ class StackLayout extends GraphLayout { constructor( - graph: Graph, + graph: AbstractGraph, horizontal: boolean | null = null, spacing: number | null = null, x0: number | null = null, diff --git a/packages/core/src/view/layout/SwimlaneLayout.ts b/packages/core/src/view/layout/SwimlaneLayout.ts index 6e817f48b5..773ab320df 100644 --- a/packages/core/src/view/layout/SwimlaneLayout.ts +++ b/packages/core/src/view/layout/SwimlaneLayout.ts @@ -26,7 +26,7 @@ import ObjectIdentity from '../../util/ObjectIdentity'; import SwimlaneOrdering from './hierarchical/SwimlaneOrdering'; import MedianHybridCrossingReduction from './hierarchical/MedianHybridCrossingReduction'; import CoordinateAssignment from './hierarchical/CoordinateAssignment'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import Geometry from '../../view/geometry/Geometry'; import { SwimlaneGraphLayoutTraverseArgs } from './types'; @@ -40,11 +40,11 @@ class SwimlaneLayout extends GraphLayout { /** * Constructs a new hierarchical layout algorithm. * - * @param graph Reference to the enclosing {@link Graph}. - * @param orientation Optional constant that defines the orientation of this layout. Default is {@link DIRECTION_NORTH}. + * @param graph Reference to the enclosing {@link AbstractGraph}. + * @param orientation Optional constant that defines the orientation of this layout. Default is {@link DIRECTION.NORTH}. * @param deterministic Optional boolean that specifies if this layout should be deterministic. Default is true. */ - constructor(graph: Graph, orientation: DIRECTION | null, deterministic = true) { + constructor(graph: AbstractGraph, orientation: DIRECTION | null, deterministic = true) { super(graph); this.orientation = orientation != null ? orientation : DIRECTION.NORTH; this.deterministic = deterministic != null ? deterministic : true; diff --git a/packages/core/src/view/layout/SwimlaneManager.ts b/packages/core/src/view/layout/SwimlaneManager.ts index b9f7e9b1f3..e3d6989ec6 100644 --- a/packages/core/src/view/layout/SwimlaneManager.ts +++ b/packages/core/src/view/layout/SwimlaneManager.ts @@ -19,7 +19,7 @@ limitations under the License. import EventSource from '../event/EventSource'; import InternalEvent from '../event/InternalEvent'; import Rectangle from '../geometry/Rectangle'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import EventObject from '../event/EventObject'; import type Cell from '../cell/Cell'; @@ -32,7 +32,12 @@ import type Cell from '../cell/Cell'; * @category Layout */ class SwimlaneManager extends EventSource { - constructor(graph: Graph, horizontal = true, addEnabled = true, resizeEnabled = true) { + constructor( + graph: AbstractGraph, + horizontal = true, + addEnabled = true, + resizeEnabled = true + ) { super(); this.horizontal = horizontal; @@ -55,9 +60,9 @@ class SwimlaneManager extends EventSource { } /** - * Reference to the enclosing {@link graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph!: Graph; + graph!: AbstractGraph; /** * Specifies if event handling is enabled. @@ -164,7 +169,7 @@ class SwimlaneManager extends EventSource { /** * Sets the graph that the manager operates on. */ - setGraph(graph: Graph | null) { + setGraph(graph: AbstractGraph | null) { if (this.graph) { this.graph.removeListener(this.addHandler); this.graph.removeListener(this.resizeHandler); diff --git a/packages/core/src/view/layout/hierarchical/CoordinateAssignment.ts b/packages/core/src/view/layout/hierarchical/CoordinateAssignment.ts index 16dde3347d..62feb72f53 100644 --- a/packages/core/src/view/layout/hierarchical/CoordinateAssignment.ts +++ b/packages/core/src/view/layout/hierarchical/CoordinateAssignment.ts @@ -28,7 +28,7 @@ import GraphHierarchyModel from './GraphHierarchyModel'; import Cell from '../../../view/cell/Cell'; import GraphHierarchyNode from '../datatypes/GraphHierarchyNode'; import GraphAbstractHierarchyCell from '../datatypes/GraphAbstractHierarchyCell'; -import type { Graph } from '../../../view/Graph'; +import type { AbstractGraph } from '../../AbstractGraph'; import Geometry from '../../../view/geometry/Geometry'; import GraphHierarchyEdge from '../datatypes/GraphHierarchyEdge'; import SwimlaneLayout from '../SwimlaneLayout'; @@ -664,7 +664,7 @@ class CoordinateAssignment extends HierarchicalLayoutStage { * @param facade the facade describing the input graph * @param model an internal model of the hierarchical layout */ - initialCoords(facade: Graph, model: GraphHierarchyModel) { + initialCoords(facade: AbstractGraph, model: GraphHierarchyModel) { this.calculateWidestRank(facade, model); // Sweep up and down from the widest rank @@ -691,7 +691,7 @@ class CoordinateAssignment extends HierarchicalLayoutStage { * @param graph the facade describing the input graph * @param model an internal model of the hierarchical layout */ - rankCoordinates(rankValue: number, graph: Graph, model: GraphHierarchyModel) { + rankCoordinates(rankValue: number, graph: AbstractGraph, model: GraphHierarchyModel) { const ranks = model.ranks; const rank = ranks[rankValue]; let maxY = 0.0; @@ -759,7 +759,7 @@ class CoordinateAssignment extends HierarchicalLayoutStage { * @param graph the facade describing the input graph * @param model an internal model of the hierarchical layout */ - calculateWidestRank(graph: Graph, model: GraphHierarchyModel) { + calculateWidestRank(graph: AbstractGraph, model: GraphHierarchyModel) { // Starting y co-ordinate let y = -this.interRankCellSpacing; @@ -860,7 +860,7 @@ class CoordinateAssignment extends HierarchicalLayoutStage { * @param graph the facade describing the input graph * @param model an internal model of the hierarchical layout */ - minPath(graph: Graph, model: GraphHierarchyModel) { + minPath(graph: AbstractGraph, model: GraphHierarchyModel) { // Work down and up each edge with at least 2 control points // trying to straighten each one out. If the same number of // straight segments are formed in both directions, the @@ -1030,7 +1030,7 @@ class CoordinateAssignment extends HierarchicalLayoutStage { * @param graph the input graph * @param model the layout model */ - setCellLocations(graph: Graph, model: GraphHierarchyModel) { + setCellLocations(graph: AbstractGraph, model: GraphHierarchyModel) { this.rankTopY = []; this.rankBottomY = []; const ranks = model.ranks; diff --git a/packages/core/src/view/mixins/CellsMixin.ts b/packages/core/src/view/mixins/CellsMixin.ts index 6c497b79e8..343220f15f 100644 --- a/packages/core/src/view/mixins/CellsMixin.ts +++ b/packages/core/src/view/mixins/CellsMixin.ts @@ -43,11 +43,11 @@ import Dictionary from '../../util/Dictionary'; import Point from '../geometry/Point'; import { htmlEntities } from '../../util/StringUtils'; import CellState from '../cell/CellState'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { cloneCells, getTopmostCells } from '../../util/cellArrayUtils'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getView' | 'getStylesheet' | 'batchUpdate' @@ -90,7 +90,7 @@ type PartialGraph = Pick< >; type PartialCells = Pick< - Graph, + AbstractGraph, | 'cellsResizable' | 'cellsBendable' | 'cellsSelectable' diff --git a/packages/core/src/view/mixins/CellsMixin.type.ts b/packages/core/src/view/mixins/CellsMixin.type.ts index 503d1d70c5..4c2fa2dc1f 100644 --- a/packages/core/src/view/mixins/CellsMixin.type.ts +++ b/packages/core/src/view/mixins/CellsMixin.type.ts @@ -20,8 +20,8 @@ import type { CellStateStyle, CellStyle, NumericCellStateStyleKeys } from '../.. import type Geometry from '../geometry/Geometry'; import type CellState from '../cell/CellState'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies the return value for {@link isCellsResizable}. * @default true diff --git a/packages/core/src/view/mixins/ConnectionsMixin.ts b/packages/core/src/view/mixins/ConnectionsMixin.ts index ae51139a24..0f1f94a99c 100644 --- a/packages/core/src/view/mixins/ConnectionsMixin.ts +++ b/packages/core/src/view/mixins/ConnectionsMixin.ts @@ -22,12 +22,12 @@ import Cell from '../cell/Cell'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Dictionary from '../../util/Dictionary'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type ConnectionHandler from '../plugins/ConnectionHandler'; -type PartialGraph = Pick; +type PartialGraph = Pick; type PartialConnections = Pick< - Graph, + AbstractGraph, | 'constrainChildren' | 'constrainRelativeChildren' | 'disconnectOnMove' diff --git a/packages/core/src/view/mixins/ConnectionsMixin.type.ts b/packages/core/src/view/mixins/ConnectionsMixin.type.ts index c5af5e7670..c74d9de7f8 100644 --- a/packages/core/src/view/mixins/ConnectionsMixin.type.ts +++ b/packages/core/src/view/mixins/ConnectionsMixin.type.ts @@ -20,8 +20,8 @@ import type InternalMouseEvent from '../event/InternalMouseEvent'; import type ConnectionConstraint from '../other/ConnectionConstraint'; import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies if a child should be constrained inside the parent bounds after a move or resize of the child. * @default true diff --git a/packages/core/src/view/mixins/DragDropMixin.ts b/packages/core/src/view/mixins/DragDropMixin.ts index eca4558cb4..62a13d3252 100644 --- a/packages/core/src/view/mixins/DragDropMixin.ts +++ b/packages/core/src/view/mixins/DragDropMixin.ts @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; -type PartialGraph = Pick; +type PartialGraph = Pick; type PartialDragDrop = Pick< - Graph, + AbstractGraph, | 'dropEnabled' | 'splitEnabled' | 'autoScroll' diff --git a/packages/core/src/view/mixins/DragDropMixin.type.ts b/packages/core/src/view/mixins/DragDropMixin.type.ts index 06f01f7f7f..cd6056a371 100644 --- a/packages/core/src/view/mixins/DragDropMixin.type.ts +++ b/packages/core/src/view/mixins/DragDropMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies the return value for {@link isDropEnabled}. * @default false diff --git a/packages/core/src/view/mixins/EdgeMixin.ts b/packages/core/src/view/mixins/EdgeMixin.ts index d6fa6bd7c4..f13efda018 100644 --- a/packages/core/src/view/mixins/EdgeMixin.ts +++ b/packages/core/src/view/mixins/EdgeMixin.ts @@ -18,7 +18,7 @@ import type { CellStyle } from '../../types'; import Dictionary from '../../util/Dictionary'; import { removeDuplicates } from '../../util/arrayUtils'; import { findNearestSegment } from '../../util/mathUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import Cell from '../cell/Cell'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; @@ -26,7 +26,7 @@ import Geometry from '../geometry/Geometry'; import type Point from '../geometry/Point'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'batchUpdate' | 'fireEvent' | 'getDataModel' @@ -40,7 +40,7 @@ type PartialGraph = Pick< | 'cellConnected' >; type PartialEdge = Pick< - Graph, + AbstractGraph, | 'resetEdgesOnResize' | 'resetEdgesOnMove' | 'resetEdgesOnConnect' diff --git a/packages/core/src/view/mixins/EdgeMixin.type.ts b/packages/core/src/view/mixins/EdgeMixin.type.ts index d30beb970f..a7f96e3cea 100644 --- a/packages/core/src/view/mixins/EdgeMixin.type.ts +++ b/packages/core/src/view/mixins/EdgeMixin.type.ts @@ -17,8 +17,8 @@ limitations under the License. import type { CellStyle, EdgeParameters, EdgeParametersValue } from '../../types'; import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies if edge control points should be reset after the resize of a connected cell. * @default false diff --git a/packages/core/src/view/mixins/EditingMixin.ts b/packages/core/src/view/mixins/EditingMixin.ts index 9e4772f196..6b6149a1d8 100644 --- a/packages/core/src/view/mixins/EditingMixin.ts +++ b/packages/core/src/view/mixins/EditingMixin.ts @@ -17,11 +17,11 @@ limitations under the License. import { isMultiTouchEvent } from '../../util/EventUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type CellEditorHandler from '../plugins/CellEditorHandler'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'convertValueToString' | 'batchUpdate' | 'getDataModel' @@ -34,7 +34,7 @@ type PartialGraph = Pick< | 'getPlugin' >; type PartialEditing = Pick< - Graph, + AbstractGraph, | 'cellsEditable' | 'startEditing' | 'startEditingAtCell' diff --git a/packages/core/src/view/mixins/EditingMixin.type.ts b/packages/core/src/view/mixins/EditingMixin.type.ts index f310ccea07..31cb004e9a 100644 --- a/packages/core/src/view/mixins/EditingMixin.type.ts +++ b/packages/core/src/view/mixins/EditingMixin.type.ts @@ -18,8 +18,8 @@ import type Cell from '../cell/Cell'; import type InternalMouseEvent from '../event/InternalMouseEvent'; import type EventObject from '../event/EventObject'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * @default true */ diff --git a/packages/core/src/view/mixins/EventsMixin.ts b/packages/core/src/view/mixins/EventsMixin.ts index 7721e6a2ff..2c3e5189fe 100644 --- a/packages/core/src/view/mixins/EventsMixin.ts +++ b/packages/core/src/view/mixins/EventsMixin.ts @@ -41,11 +41,11 @@ import { convertPoint } from '../../util/styleUtils'; import { NONE } from '../../util/Constants'; import Client from '../../Client'; import type CellEditorHandler from '../plugins/CellEditorHandler'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type TooltipHandler from '../plugins/TooltipHandler'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'fireEvent' | 'isEnabled' | 'getCellAt' @@ -88,7 +88,7 @@ type PartialGraph = Pick< | 'isSwimlane' >; type PartialEvents = Pick< - Graph, + AbstractGraph, | 'mouseListeners' | 'lastTouchEvent' | 'doubleClickCounter' @@ -573,7 +573,7 @@ export const EventsMixin: PartialType = { }, fireMouseEvent(evtName, me, sender) { - sender = sender ?? (this as Graph); + sender = sender ?? (this as AbstractGraph); if (this.isEventSourceIgnored(evtName, me)) { const tooltipHandler = this.getPlugin('TooltipHandler'); diff --git a/packages/core/src/view/mixins/EventsMixin.type.ts b/packages/core/src/view/mixins/EventsMixin.type.ts index 6a0e2e868c..f7b98e2606 100644 --- a/packages/core/src/view/mixins/EventsMixin.type.ts +++ b/packages/core/src/view/mixins/EventsMixin.type.ts @@ -21,8 +21,8 @@ import type CellState from '../cell/CellState'; import type EventSource from '../event/EventSource'; import type Point from '../geometry/Point'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { mouseListeners: MouseListenerSet[]; lastTouchEvent: MouseEvent | null; doubleClickCounter: number; diff --git a/packages/core/src/view/mixins/FoldingMixin.ts b/packages/core/src/view/mixins/FoldingMixin.ts index 4cc84162fa..421d373974 100644 --- a/packages/core/src/view/mixins/FoldingMixin.ts +++ b/packages/core/src/view/mixins/FoldingMixin.ts @@ -20,11 +20,11 @@ import InternalEvent from '../event/InternalEvent'; import Geometry from '../geometry/Geometry'; import { toRadians } from '../../util/mathUtils'; import Rectangle from '../geometry/Rectangle'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { isI18nEnabled } from '../../internal/i18n-utils'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getDataModel' | 'fireEvent' | 'getCurrentCellStyle' @@ -38,7 +38,7 @@ type PartialGraph = Pick< | 'options' >; type PartialFolding = Pick< - Graph, + AbstractGraph, | 'collapseExpandResource' | 'getCollapseExpandResource' | 'isFoldingEnabled' diff --git a/packages/core/src/view/mixins/FoldingMixin.type.ts b/packages/core/src/view/mixins/FoldingMixin.type.ts index 35917111c7..bc1506a2b2 100644 --- a/packages/core/src/view/mixins/FoldingMixin.type.ts +++ b/packages/core/src/view/mixins/FoldingMixin.type.ts @@ -19,8 +19,8 @@ import type CellState from '../cell/CellState'; import type ImageBox from '../image/ImageBox'; import type Geometry from '../geometry/Geometry'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies the resource key for the tooltip on the collapse/expand icon. * If the resource for this key does not exist then the value is used as diff --git a/packages/core/src/view/mixins/GroupingMixin.ts b/packages/core/src/view/mixins/GroupingMixin.ts index 79f43be2d4..f4eec9d6b8 100644 --- a/packages/core/src/view/mixins/GroupingMixin.ts +++ b/packages/core/src/view/mixins/GroupingMixin.ts @@ -21,10 +21,10 @@ import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Rectangle from '../geometry/Rectangle'; import type Point from '../geometry/Point'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getDataModel' | 'fireEvent' | 'getView' @@ -49,7 +49,7 @@ type PartialGraph = Pick< | 'getActualStartSize' >; type PartialGrouping = Pick< - Graph, + AbstractGraph, | 'groupCells' | 'getCellsForGroup' | 'getBoundsForGroup' diff --git a/packages/core/src/view/mixins/GroupingMixin.type.ts b/packages/core/src/view/mixins/GroupingMixin.type.ts index 59a788ee01..163c9b04f2 100644 --- a/packages/core/src/view/mixins/GroupingMixin.type.ts +++ b/packages/core/src/view/mixins/GroupingMixin.type.ts @@ -17,8 +17,8 @@ limitations under the License. import type Cell from '../cell/Cell'; import type Rectangle from '../geometry/Rectangle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Adds the cells into the given group. * The change is carried out using {@link cellsAdded}, {@link cellsMoved} and {@link cellsResized}. diff --git a/packages/core/src/view/mixins/ImageMixin.ts b/packages/core/src/view/mixins/ImageMixin.ts index 712be72cfe..e17c94362b 100644 --- a/packages/core/src/view/mixins/ImageMixin.ts +++ b/packages/core/src/view/mixins/ImageMixin.ts @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type ImageBundle from '../image/ImageBundle'; type PartialImage = Pick< - Graph, + AbstractGraph, 'imageBundles' | 'addImageBundle' | 'removeImageBundle' | 'getImageFromBundles' >; type PartialType = PartialImage; diff --git a/packages/core/src/view/mixins/ImageMixin.type.ts b/packages/core/src/view/mixins/ImageMixin.type.ts index 30a0fbb292..eaab8f1b3b 100644 --- a/packages/core/src/view/mixins/ImageMixin.type.ts +++ b/packages/core/src/view/mixins/ImageMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type ImageBundle from '../image/ImageBundle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { imageBundles: ImageBundle[]; /** diff --git a/packages/core/src/view/mixins/LabelMixin.ts b/packages/core/src/view/mixins/LabelMixin.ts index a819746d43..e40aa25694 100644 --- a/packages/core/src/view/mixins/LabelMixin.ts +++ b/packages/core/src/view/mixins/LabelMixin.ts @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'convertValueToString' | 'getCurrentCellStyle' | 'isCellLocked' @@ -25,7 +25,7 @@ type PartialGraph = Pick< | 'isVertexLabelsMovable' >; type PartialLabel = Pick< - Graph, + AbstractGraph, | 'labelsVisible' | 'htmlLabels' | 'getLabel' diff --git a/packages/core/src/view/mixins/LabelMixin.type.ts b/packages/core/src/view/mixins/LabelMixin.type.ts index 02ba5645d4..bb86bd45e6 100644 --- a/packages/core/src/view/mixins/LabelMixin.type.ts +++ b/packages/core/src/view/mixins/LabelMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies if labels should be visible. This is used in {@link getLabel}. * @default true diff --git a/packages/core/src/view/mixins/OrderMixin.ts b/packages/core/src/view/mixins/OrderMixin.ts index cd2fc8b920..09eab6790e 100644 --- a/packages/core/src/view/mixins/OrderMixin.ts +++ b/packages/core/src/view/mixins/OrderMixin.ts @@ -17,14 +17,14 @@ limitations under the License. import { sortCells } from '../../util/styleUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; type PartialGraph = Pick< - Graph, + AbstractGraph, 'fireEvent' | 'batchUpdate' | 'getDataModel' | 'getSelectionCells' >; -type PartialOrder = Pick; +type PartialOrder = Pick; type PartialType = PartialGraph & PartialOrder; // @ts-expect-error The properties of PartialGraph are defined elsewhere. diff --git a/packages/core/src/view/mixins/OrderMixin.type.ts b/packages/core/src/view/mixins/OrderMixin.type.ts index 933632c2ca..1fb7ecf79f 100644 --- a/packages/core/src/view/mixins/OrderMixin.type.ts +++ b/packages/core/src/view/mixins/OrderMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Moves the given cells to the front or back. The change is carried out using {@link cellsOrdered}. * diff --git a/packages/core/src/view/mixins/OverlaysMixin.ts b/packages/core/src/view/mixins/OverlaysMixin.ts index 99daa63b1d..4d11227fd4 100644 --- a/packages/core/src/view/mixins/OverlaysMixin.ts +++ b/packages/core/src/view/mixins/OverlaysMixin.ts @@ -18,10 +18,10 @@ import CellOverlay from '../cell/CellOverlay'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import type InternalMouseEvent from '../event/InternalMouseEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getView' | 'fireEvent' | 'getDataModel' @@ -31,7 +31,7 @@ type PartialGraph = Pick< | 'setSelectionCell' >; type PartialOverlays = Pick< - Graph, + AbstractGraph, | 'addCellOverlay' | 'getCellOverlays' | 'removeCellOverlay' diff --git a/packages/core/src/view/mixins/OverlaysMixin.type.ts b/packages/core/src/view/mixins/OverlaysMixin.type.ts index 0ff21e19e1..e5c5a265b4 100644 --- a/packages/core/src/view/mixins/OverlaysMixin.type.ts +++ b/packages/core/src/view/mixins/OverlaysMixin.type.ts @@ -18,8 +18,8 @@ import type Cell from '../cell/Cell'; import type CellOverlay from '../cell/CellOverlay'; import type Image from '../image/ImageBox'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Adds an {@link CellOverlay} for the specified cell. * diff --git a/packages/core/src/view/mixins/PageBreaksMixin.ts b/packages/core/src/view/mixins/PageBreaksMixin.ts index 3545dddcef..1877062bad 100644 --- a/packages/core/src/view/mixins/PageBreaksMixin.ts +++ b/packages/core/src/view/mixins/PageBreaksMixin.ts @@ -17,10 +17,10 @@ limitations under the License. import Rectangle from '../geometry/Rectangle'; import Point from '../geometry/Point'; import PolylineShape from '../geometry/edge/PolylineShape'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getView' | 'getGraphBounds' | 'getPageFormat' @@ -31,7 +31,7 @@ type PartialGraph = Pick< | 'isPageBreakDashed' >; type PartialPageBreaks = Pick< - Graph, + AbstractGraph, 'horizontalPageBreaks' | 'verticalPageBreaks' | 'updatePageBreaks' >; type PartialType = PartialGraph & PartialPageBreaks; diff --git a/packages/core/src/view/mixins/PageBreaksMixin.type.ts b/packages/core/src/view/mixins/PageBreaksMixin.type.ts index f37b5faaaa..0c4dcce96e 100644 --- a/packages/core/src/view/mixins/PageBreaksMixin.type.ts +++ b/packages/core/src/view/mixins/PageBreaksMixin.type.ts @@ -18,8 +18,8 @@ limitations under the License. // TS2436: Ambient module declaration cannot specify relative module name. export {}; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** @default null */ horizontalPageBreaks: any[] | null; diff --git a/packages/core/src/view/mixins/PanningMixin.ts b/packages/core/src/view/mixins/PanningMixin.ts index 1ccb354c41..2b24926cb2 100644 --- a/packages/core/src/view/mixins/PanningMixin.ts +++ b/packages/core/src/view/mixins/PanningMixin.ts @@ -18,14 +18,17 @@ import { hasScrollbars } from '../../util/styleUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import type PanningHandler from '../plugins/PanningHandler'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import Rectangle from '../geometry/Rectangle'; import Point from '../geometry/Point'; import type SelectionCellsHandler from '../plugins/SelectionCellsHandler'; -type PartialGraph = Pick; +type PartialGraph = Pick< + AbstractGraph, + 'getContainer' | 'getView' | 'getPlugin' | 'fireEvent' +>; type PartialPanning = Pick< - Graph, + AbstractGraph, | 'shiftPreview1' | 'shiftPreview2' | 'useScrollbarsForPanning' diff --git a/packages/core/src/view/mixins/PanningMixin.type.ts b/packages/core/src/view/mixins/PanningMixin.type.ts index f16a28c648..8249d7aec1 100644 --- a/packages/core/src/view/mixins/PanningMixin.type.ts +++ b/packages/core/src/view/mixins/PanningMixin.type.ts @@ -17,8 +17,8 @@ limitations under the License. import type Cell from '../cell/Cell'; import type Rectangle from '../geometry/Rectangle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** @default null */ shiftPreview1: HTMLElement | null; diff --git a/packages/core/src/view/mixins/PortsMixin.ts b/packages/core/src/view/mixins/PortsMixin.ts index 5b52fa49a5..b19fef9be8 100644 --- a/packages/core/src/view/mixins/PortsMixin.ts +++ b/packages/core/src/view/mixins/PortsMixin.ts @@ -14,10 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialPorts = Pick< - Graph, + AbstractGraph, 'portsEnabled' | 'isPort' | 'getTerminalForPort' | 'isPortsEnabled' | 'setPortsEnabled' >; type PartialType = PartialPorts; diff --git a/packages/core/src/view/mixins/PortsMixin.type.ts b/packages/core/src/view/mixins/PortsMixin.type.ts index 2e730248de..b39fbbe3b2 100644 --- a/packages/core/src/view/mixins/PortsMixin.type.ts +++ b/packages/core/src/view/mixins/PortsMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies if ports are enabled. This is used in {@link cellConnected} to update the respective style. * @default true diff --git a/packages/core/src/view/mixins/SelectionMixin.ts b/packages/core/src/view/mixins/SelectionMixin.ts index 3a55487cc2..70d8a39b1a 100644 --- a/packages/core/src/view/mixins/SelectionMixin.ts +++ b/packages/core/src/view/mixins/SelectionMixin.ts @@ -18,10 +18,10 @@ import Cell from '../cell/Cell'; import Dictionary from '../../util/Dictionary'; import RootChange from '../undoable_changes/RootChange'; import ChildChange from '../undoable_changes/ChildChange'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getDataModel' | 'getView' | 'isCellSelectable' @@ -32,7 +32,7 @@ type PartialGraph = Pick< | 'isToggleEvent' >; type PartialCells = Pick< - Graph, + AbstractGraph, | 'singleSelection' | 'selectionModel' | 'getSelectionModel' diff --git a/packages/core/src/view/mixins/SelectionMixin.type.ts b/packages/core/src/view/mixins/SelectionMixin.type.ts index 5ab30cd565..651b591116 100644 --- a/packages/core/src/view/mixins/SelectionMixin.type.ts +++ b/packages/core/src/view/mixins/SelectionMixin.type.ts @@ -18,8 +18,8 @@ import type Cell from '../cell/Cell'; import type GraphSelectionModel from '../GraphSelectionModel'; import type Rectangle from '../geometry/Rectangle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { cells: Cell[]; doneResource: string; updatingSelectionResource: string; diff --git a/packages/core/src/view/mixins/SnapMixin.ts b/packages/core/src/view/mixins/SnapMixin.ts index 80256edbda..a50983cbb0 100644 --- a/packages/core/src/view/mixins/SnapMixin.ts +++ b/packages/core/src/view/mixins/SnapMixin.ts @@ -14,11 +14,11 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; -type PartialGraph = Pick; +type PartialGraph = Pick; type PartialSnap = Pick< - Graph, + AbstractGraph, | 'snapTolerance' | 'gridSize' | 'gridEnabled' diff --git a/packages/core/src/view/mixins/SnapMixin.type.ts b/packages/core/src/view/mixins/SnapMixin.type.ts index abbb73d4b7..92a440dc87 100644 --- a/packages/core/src/view/mixins/SnapMixin.type.ts +++ b/packages/core/src/view/mixins/SnapMixin.type.ts @@ -17,8 +17,8 @@ limitations under the License. import type Point from '../geometry/Point'; import type Rectangle from '../geometry/Rectangle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * @default 0 */ diff --git a/packages/core/src/view/mixins/SwimlaneMixin.ts b/packages/core/src/view/mixins/SwimlaneMixin.ts index eeef275f5e..a1668c28c6 100644 --- a/packages/core/src/view/mixins/SwimlaneMixin.ts +++ b/packages/core/src/view/mixins/SwimlaneMixin.ts @@ -19,11 +19,11 @@ import { convertPoint } from '../../util/styleUtils'; import { mod } from '../../util/mathUtils'; import { DEFAULT_STARTSIZE, DIRECTION, SHAPE } from '../../util/Constants'; import { getClientX, getClientY } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type { DirectionValue } from '../../types'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getDefaultParent' | 'getCurrentRoot' | 'getDataModel' @@ -37,7 +37,7 @@ type PartialGraph = Pick< | 'getPanDy' >; type PartialSwimlane = Pick< - Graph, + AbstractGraph, | 'swimlaneSelectionEnabled' | 'swimlaneNesting' | 'swimlaneIndicatorColorAttribute' diff --git a/packages/core/src/view/mixins/SwimlaneMixin.type.ts b/packages/core/src/view/mixins/SwimlaneMixin.type.ts index 58ec1c539a..1418949a17 100644 --- a/packages/core/src/view/mixins/SwimlaneMixin.type.ts +++ b/packages/core/src/view/mixins/SwimlaneMixin.type.ts @@ -18,8 +18,8 @@ import type Cell from '../cell/Cell'; import type Rectangle from '../geometry/Rectangle'; import type { CellStateStyle, DirectionValue } from '../../types'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies if swimlanes should be selectable via the content if the mouse is released. * @default true diff --git a/packages/core/src/view/mixins/TerminalMixin.ts b/packages/core/src/view/mixins/TerminalMixin.ts index 95d051b653..bff8a1c85c 100644 --- a/packages/core/src/view/mixins/TerminalMixin.ts +++ b/packages/core/src/view/mixins/TerminalMixin.ts @@ -16,10 +16,10 @@ limitations under the License. import type Cell from '../cell/Cell'; import Dictionary from '../../util/Dictionary'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; -type PartialGraph = Pick; -type PartialTerminal = Pick; +type PartialGraph = Pick; +type PartialTerminal = Pick; type PartialType = PartialGraph & PartialTerminal; // @ts-expect-error The properties of PartialGraph are defined elsewhere. diff --git a/packages/core/src/view/mixins/TerminalMixin.type.ts b/packages/core/src/view/mixins/TerminalMixin.type.ts index 195b397cce..e2af2ef62a 100644 --- a/packages/core/src/view/mixins/TerminalMixin.type.ts +++ b/packages/core/src/view/mixins/TerminalMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Returns true if the given terminal point is movable. This is independent * from {@link isCellConnectable} and {@link isCellDisconnectable} and controls if terminal diff --git a/packages/core/src/view/mixins/TooltipMixin.ts b/packages/core/src/view/mixins/TooltipMixin.ts index 46b3b8760e..a01fa19504 100644 --- a/packages/core/src/view/mixins/TooltipMixin.ts +++ b/packages/core/src/view/mixins/TooltipMixin.ts @@ -17,16 +17,19 @@ limitations under the License. import { htmlEntities } from '../../util/StringUtils'; import type Shape from '../geometry/Shape'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type SelectionCellsHandler from '../plugins/SelectionCellsHandler'; import type TooltipHandler from '../plugins/TooltipHandler'; import { translate } from '../../internal/i18n-utils'; type PartialGraph = Pick< - Graph, + AbstractGraph, 'convertValueToString' | 'getPlugin' | 'getCollapseExpandResource' >; -type PartialTooltip = Pick; +type PartialTooltip = Pick< + AbstractGraph, + 'getTooltip' | 'getTooltipForCell' | 'setTooltips' +>; type PartialType = PartialGraph & PartialTooltip; // @ts-expect-error The properties of PartialGraph are defined elsewhere. diff --git a/packages/core/src/view/mixins/TooltipMixin.type.ts b/packages/core/src/view/mixins/TooltipMixin.type.ts index 4b140b3d6a..1cd5b1e4a2 100644 --- a/packages/core/src/view/mixins/TooltipMixin.type.ts +++ b/packages/core/src/view/mixins/TooltipMixin.type.ts @@ -17,8 +17,8 @@ limitations under the License. import type CellState from '../cell/CellState'; import type Cell from '../cell/Cell'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Returns the string or DOM node that represents the tooltip for the given * state, node and coordinate pair. This implementation checks if the given diff --git a/packages/core/src/view/mixins/ValidationMixin.ts b/packages/core/src/view/mixins/ValidationMixin.ts index e124b11354..457ec240bd 100644 --- a/packages/core/src/view/mixins/ValidationMixin.ts +++ b/packages/core/src/view/mixins/ValidationMixin.ts @@ -16,11 +16,11 @@ limitations under the License. import type Cell from '../cell/Cell'; import { isNode } from '../../util/domUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { translate } from '../../internal/i18n-utils'; type PartialGraph = Pick< - Graph, + AbstractGraph, | 'getDataModel' | 'isAllowLoops' | 'isMultigraph' @@ -33,7 +33,7 @@ type PartialGraph = Pick< | 'setCellWarning' >; type PartialValidation = Pick< - Graph, + AbstractGraph, | 'multiplicities' | 'validationAlert' | 'isEdgeValid' @@ -104,7 +104,7 @@ export const ValidationMixin: PartialType = { // Checks the change against each multiplicity rule for (const multiplicity of this.multiplicities) { const err = multiplicity.check( - (this), // needs to cast to Graph + (this), // needs to cast to Graph edge, source, target, diff --git a/packages/core/src/view/mixins/ValidationMixin.type.ts b/packages/core/src/view/mixins/ValidationMixin.type.ts index 826e193aa0..6d11efda66 100644 --- a/packages/core/src/view/mixins/ValidationMixin.type.ts +++ b/packages/core/src/view/mixins/ValidationMixin.type.ts @@ -18,8 +18,8 @@ import type Multiplicity from '../other/Multiplicity'; import type Cell from '../cell/Cell'; import type CellState from '../cell/CellState'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { multiplicities: Multiplicity[]; /** diff --git a/packages/core/src/view/mixins/VertexMixin.ts b/packages/core/src/view/mixins/VertexMixin.ts index 3fba4e536c..57c4dccd1f 100644 --- a/packages/core/src/view/mixins/VertexMixin.ts +++ b/packages/core/src/view/mixins/VertexMixin.ts @@ -16,12 +16,12 @@ limitations under the License. import Cell from '../cell/Cell'; import Geometry from '../geometry/Geometry'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type { CellStyle } from '../../types'; -type PartialGraph = Pick; +type PartialGraph = Pick; type PartialVertex = Pick< - Graph, + AbstractGraph, | 'vertexLabelsMovable' | 'allowNegativeCoordinates' | 'isAllowNegativeCoordinates' diff --git a/packages/core/src/view/mixins/VertexMixin.type.ts b/packages/core/src/view/mixins/VertexMixin.type.ts index 0e7952ffdc..ec9d90382d 100644 --- a/packages/core/src/view/mixins/VertexMixin.type.ts +++ b/packages/core/src/view/mixins/VertexMixin.type.ts @@ -18,8 +18,8 @@ import type Cell from '../cell/Cell'; import type { CellStyle, VertexParameters } from '../../types'; import type Geometry from '../geometry/Geometry'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies the return value for vertices in {@link isLabelMovable}. * @default false @@ -53,7 +53,7 @@ declare module '../Graph' { * When adding new vertices from a mouse event, one should take into * account the offset of the graph container and the scale and translation * of the view in order to find the correct unscaled, untranslated - * coordinates using {@link Graph#getPointForEvent} as follows: + * coordinates using {@link AbstractGraph.getPointForEvent} as follows: * * ```javascript * const pt = graph.getPointForEvent(evt); @@ -69,7 +69,7 @@ declare module '../Graph' { * } * ``` * - * See {@link Graph} for more information on using images. + * See {@link AbstractGraph} for more information on using images. * * @param parent the parent of the new vertex. If not set, use the default parent. * @param id Optional string that defines the id of the new vertex. If not set, the id is auto-generated when creating the vertex. @@ -104,7 +104,7 @@ declare module '../Graph' { * When adding new vertices from a mouse event, one should take into * account the offset of the graph container and the scale and translation * of the view in order to find the correct unscaled, untranslated - * coordinates using {@link Graph#getPointForEvent} as follows: + * coordinates using {@link AbstractGraph.getPointForEvent} as follows: * * ```javascript * const pt = graph.getPointForEvent(evt); @@ -125,7 +125,7 @@ declare module '../Graph' { * } * ``` * - * See {@link Graph} for more information on using images. + * See {@link AbstractGraph} for more information on using images. * * @param params the parameters used to create the new vertex. */ diff --git a/packages/core/src/view/mixins/ZoomMixin.ts b/packages/core/src/view/mixins/ZoomMixin.ts index 7777eed9e7..c82634e00c 100644 --- a/packages/core/src/view/mixins/ZoomMixin.ts +++ b/packages/core/src/view/mixins/ZoomMixin.ts @@ -16,14 +16,14 @@ limitations under the License. import Rectangle from '../geometry/Rectangle'; import { hasScrollbars } from '../../util/styleUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; type PartialGraph = Pick< - Graph, + AbstractGraph, 'getView' | 'getSelectionCell' | 'getContainer' | 'scrollRectToVisible' >; type PartialZoom = Pick< - Graph, + AbstractGraph, | 'zoomFactor' | 'keepSelectionVisibleOnZoom' | 'centerZoom' diff --git a/packages/core/src/view/mixins/ZoomMixin.type.ts b/packages/core/src/view/mixins/ZoomMixin.type.ts index 4bf3436eec..0cc6e491f3 100644 --- a/packages/core/src/view/mixins/ZoomMixin.type.ts +++ b/packages/core/src/view/mixins/ZoomMixin.type.ts @@ -16,8 +16,8 @@ limitations under the License. import type Rectangle from '../geometry/Rectangle'; -declare module '../Graph' { - interface Graph { +declare module '../AbstractGraph' { + interface AbstractGraph { /** * Specifies the factor used for {@link zoomIn} and {@link zoomOut}. * @default 1.2 (120%) diff --git a/packages/core/src/view/mixins/_graph-mixins-apply.ts b/packages/core/src/view/mixins/_graph-mixins-apply.ts index 0de63c1595..a4bee47a13 100644 --- a/packages/core/src/view/mixins/_graph-mixins-apply.ts +++ b/packages/core/src/view/mixins/_graph-mixins-apply.ts @@ -15,7 +15,7 @@ limitations under the License. */ import { mixInto } from '../../internal/utils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { CellsMixin } from './CellsMixin'; import { ConnectionsMixin } from './ConnectionsMixin'; import { DragDropMixin } from './DragDropMixin'; @@ -40,7 +40,7 @@ import { ValidationMixin } from './ValidationMixin'; import { VertexMixin } from './VertexMixin'; import { ZoomMixin } from './ZoomMixin'; -export const applyGraphMixins = (target: typeof Graph) => { +export const applyGraphMixins = (target: typeof AbstractGraph) => { const mixIntoGraph = mixInto(target); // Apply the mixins in alphabetic order to ease maintenance. diff --git a/packages/core/src/view/other/AutoSaveManager.ts b/packages/core/src/view/other/AutoSaveManager.ts index 548fdb7d47..54f42046b9 100644 --- a/packages/core/src/view/other/AutoSaveManager.ts +++ b/packages/core/src/view/other/AutoSaveManager.ts @@ -18,7 +18,7 @@ limitations under the License. import EventSource from '../event/EventSource'; import InternalEvent from '../event/InternalEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Manager for automatically saving diagrams. The hook must be @@ -33,7 +33,7 @@ import type { Graph } from '../Graph'; * ``` */ class AutoSaveManager extends EventSource { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); // Notifies the manager of a change @@ -47,9 +47,9 @@ class AutoSaveManager extends EventSource { } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph | null = null; + graph: AbstractGraph | null = null; /** * Minimum amount of seconds between two consecutive autosaves. Eg. a @@ -115,7 +115,7 @@ class AutoSaveManager extends EventSource { /** * Sets the graph that the layouts operate on. */ - setGraph(graph: Graph | null): void { + setGraph(graph: AbstractGraph | null): void { if (this.graph != null) { this.graph.getDataModel().removeListener(this.changeHandler); } diff --git a/packages/core/src/view/other/DragSource.ts b/packages/core/src/view/other/DragSource.ts index fa4a060fea..d9c4547512 100644 --- a/packages/core/src/view/other/DragSource.ts +++ b/packages/core/src/view/other/DragSource.ts @@ -40,12 +40,12 @@ import { } from '../../util/EventUtils'; import EventSource from '../event/EventSource'; import EventObject from '../event/EventObject'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type Cell from '../cell/Cell'; import type SelectionHandler from '../plugins/SelectionHandler'; export type DropHandler = ( - graph: Graph, + graph: AbstractGraph, evt: MouseEvent, cell: Cell | null, x?: number, @@ -123,9 +123,9 @@ class DragSource { enabled = true; /** - * Reference to the {@link Graph} that is the current drop target. + * Reference to the {@link AbstractGraph} that is the current drop target. */ - currentGraph: Graph | null = null; + currentGraph: AbstractGraph | null = null; /** * Holds the current drop target under the mouse. @@ -241,9 +241,9 @@ class DragSource { /** * Returns the drop target for the given graph and coordinates. - * This implementation uses {@link Graph.getCellAt}. + * This implementation uses {@link AbstractGraph.getCellAt}. */ - getDropTarget(graph: Graph, x: number, y: number, evt: MouseEvent) { + getDropTarget(graph: AbstractGraph, x: number, y: number, evt: MouseEvent) { return graph.getCellAt(x, y); } @@ -259,7 +259,7 @@ class DragSource { * Creates and returns an element which can be used as a preview in the given * graph. */ - createPreviewElement(graph: Graph): HTMLElement | null { + createPreviewElement(graph: AbstractGraph): HTMLElement | null { return null; } @@ -286,7 +286,7 @@ class DragSource { /** * Returns the drop target for the given graph and coordinates. - * This implementation uses {@link Graph.getCellAt}. + * This implementation uses {@link AbstractGraph.getCellAt}. * * To ignore popup menu events for a drag source, this function can be overridden as follows. * @@ -376,7 +376,7 @@ class DragSource { /** * Returns true if the given graph contains the given event. */ - graphContainsEvent(graph: Graph, evt: MouseEvent) { + graphContainsEvent(graph: AbstractGraph, evt: MouseEvent) { const x = getClientX(evt); const y = getClientY(evt); const offset = getOffset(graph.container); @@ -514,7 +514,7 @@ class DragSource { /** * Actives the given graph as a drop target. */ - dragEnter(graph: Graph, evt: MouseEvent) { + dragEnter(graph: AbstractGraph, evt: MouseEvent) { graph.isMouseDown = true; graph.isMouseTrigger = isMouseEvent(evt); this.previewElement = this.createPreviewElement(graph); @@ -540,7 +540,7 @@ class DragSource { /** * Deactivates the given graph as a drop target. */ - dragExit(graph: Graph, evt?: MouseEvent) { + dragExit(graph: AbstractGraph, evt?: MouseEvent) { this.currentDropTarget = null; this.currentPoint = null; graph.isMouseDown = false; @@ -571,7 +571,7 @@ class DragSource { * Implements autoscroll, updates the {@link currentPoint}, highlights any drop * targets and updates the preview. */ - dragOver(graph: Graph, evt: MouseEvent) { + dragOver(graph: AbstractGraph, evt: MouseEvent) { const offset = getOffset(graph.container); const origin = getScrollOrigin(graph.container); let x = getClientX(evt) - offset.x + origin.x - graph.getPanDx(); @@ -641,10 +641,10 @@ class DragSource { /** * Returns the drop target for the given graph and coordinates. This - * implementation uses {@link Graph.getCellAt}. + * implementation uses {@link AbstractGraph.getCellAt}. */ drop( - graph: Graph, + graph: AbstractGraph, evt: MouseEvent, dropTarget: Cell | null = null, x: number, diff --git a/packages/core/src/view/other/Guide.ts b/packages/core/src/view/other/Guide.ts index abbbcb5e7f..ecbe2980fd 100644 --- a/packages/core/src/view/other/Guide.ts +++ b/packages/core/src/view/other/Guide.ts @@ -22,7 +22,7 @@ import PolylineShape from '../geometry/edge/PolylineShape'; import type CellState from '../cell/CellState'; import Shape from '../geometry/Shape'; import Rectangle from '../geometry/Rectangle'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Implements the alignment of selection cells to other cells in the graph. @@ -32,18 +32,18 @@ import type { Graph } from '../Graph'; * Constructs a new guide object. */ class Guide { - constructor(graph: Graph, states: CellState[]) { + constructor(graph: AbstractGraph, states: CellState[]) { this.graph = graph; this.setStates(states); } /** - * Reference to the enclosing {@link Graph} instance. + * Reference to the enclosing {@link AbstractGraph} instance. */ - graph: Graph; + graph: AbstractGraph; /** - * Contains the {@link CellStates} that are used for alignment. + * Contains the {@link CellState}s that are used for alignment. */ states: CellState[] = []; diff --git a/packages/core/src/view/other/Multiplicity.ts b/packages/core/src/view/other/Multiplicity.ts index fd9fb6fd1c..ee5d40eb7c 100644 --- a/packages/core/src/view/other/Multiplicity.ts +++ b/packages/core/src/view/other/Multiplicity.ts @@ -18,7 +18,7 @@ limitations under the License. import { isNode } from '../../util/domUtils'; import type Cell from '../cell/Cell'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import { translate } from '../../internal/i18n-utils'; /** @@ -26,7 +26,7 @@ import { translate } from '../../internal/i18n-utils'; * * Defines invalid connections along with the error messages that they produce. * To add or remove rules on a graph, you must add/remove instances of this - * class to {@link graph.multiplicities}. + * class to {@link AbstractGraph.multiplicities}. * * ### Example * @@ -132,15 +132,15 @@ class Multiplicity { * Checks the multiplicity for the given arguments and returns the error * for the given connection or null if the multiplicity does not apply. * - * @param graph Reference to the enclosing {@link graph} instance. - * @param edge {@link mxCell} that represents the edge to validate. - * @param source {@link mxCell} that represents the source terminal. - * @param target {@link mxCell} that represents the target terminal. + * @param graph Reference to the enclosing {@link AbstractGraph} instance. + * @param edge {@link Cell} that represents the edge to validate. + * @param source {@link Cell} that represents the source terminal. + * @param target {@link Cell} that represents the target terminal. * @param sourceOut Number of outgoing edges from the source terminal. * @param targetIn Number of incoming edges for the target terminal. */ check( - graph: Graph, + graph: AbstractGraph, edge: Cell, source: Cell, target: Cell, @@ -181,7 +181,7 @@ class Multiplicity { * Checks if there are any valid neighbours in {@link validNeighbors}. This is only * called if {@link validNeighbors} is a non-empty array. */ - checkNeighbors(graph: Graph, edge: Cell, source: Cell, target: Cell): boolean { + checkNeighbors(graph: AbstractGraph, edge: Cell, source: Cell, target: Cell): boolean { const sourceValue = source.getValue(); const targetValue = target.getValue(); let isValid = !this.validNeighborsAllowed; @@ -205,7 +205,7 @@ class Multiplicity { * given cell is the source or target of the given edge, depending on * {@link source}. This implementation uses {@link checkType} on the terminal's value. */ - checkTerminal(graph: Graph, edge: Cell, terminal: Cell): boolean { + checkTerminal(graph: AbstractGraph, edge: Cell, terminal: Cell): boolean { const value = terminal?.getValue() ?? null; return this.checkType(graph, value, this.type, this.attr, this.value); @@ -215,7 +215,7 @@ class Multiplicity { * Checks the type of the given value. */ checkType( - graph: Graph, + graph: AbstractGraph, value: string | Element | Cell, type: string, attr?: string, diff --git a/packages/core/src/view/other/Outline.ts b/packages/core/src/view/other/Outline.ts index 0e2e963956..106744555b 100644 --- a/packages/core/src/view/other/Outline.ts +++ b/packages/core/src/view/other/Outline.ts @@ -27,7 +27,8 @@ import { import Point from '../geometry/Point'; import Rectangle from '../geometry/Rectangle'; import RectangleShape from '../geometry/node/RectangleShape'; -import { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; +import { BaseGraph } from '../BaseGraph'; import ImageShape from '../geometry/node/ImageShape'; import InternalEvent from '../event/InternalEvent'; import Image from '../image/ImageBox'; @@ -79,7 +80,7 @@ import { getDefaultPlugins } from '../plugins'; * ``` */ class Outline implements MouseListenerSet { - constructor(source: Graph, container?: HTMLElement | null) { + constructor(source: AbstractGraph, container?: HTMLElement | null) { this.source = source; if (container) { @@ -231,14 +232,14 @@ class Outline implements MouseListenerSet { index: number | null = null; /** - * Reference to the source {@link graph}. + * Reference to the source {@link AbstractGraph}. */ - source: Graph; + source: AbstractGraph; /** - * Reference to the {@link graph} that renders the outline. + * Reference to the {@link AbstractGraph} that renders the outline. */ - outline: Graph | null = null; + outline: AbstractGraph | null = null; /** * Renderhint to be used for the outline graph. @@ -315,18 +316,22 @@ class Outline implements MouseListenerSet { suspended = false; /** - * Creates the {@link graph} used in the outline. + * Creates the {@link AbstractGraph} used in the outline. */ - createGraph(container: HTMLElement): Graph { - const graph = new Graph( + createGraph(container: HTMLElement): AbstractGraph { + // The Graph here uses the same globally registered style elements as the source Graph. + // So we can use BaseGraph here (it doesn't register style elements). + const graph = new BaseGraph({ container, - this.source.getDataModel(), + model: this.source.getDataModel(), // TODO review the list of plugins for the Graph of an Outline - // we could pass an empty array or a selection of plugins - // it may be necessary to make the plugins array configurable to allow custom plugins and improve tree-shaking - getDefaultPlugins(), - this.source.getStylesheet() - ); + // We may not need plugins here as the actions are done on the source Graph, not this one. + // If we need to keep using some plugins, it may be necessary to make the plugins array configurable to allow custom plugins + // and improve tree-shaking. + plugins: getDefaultPlugins(), + stylesheet: this.source.getStylesheet(), + }); + graph.options.foldingEnabled = false; graph.autoScroll = false; return graph; diff --git a/packages/core/src/view/other/PanningManager.ts b/packages/core/src/view/other/PanningManager.ts index 9d4d24de5c..7aa870e414 100644 --- a/packages/core/src/view/other/PanningManager.ts +++ b/packages/core/src/view/other/PanningManager.ts @@ -20,13 +20,13 @@ import { MouseEventListener, MouseListenerSet } from '../../types'; import { hasScrollbars } from '../../util/styleUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Implements a handler for panning. */ class PanningManager { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.thread = null; this.active = false; this.tdx = 0; diff --git a/packages/core/src/view/other/PrintPreview.ts b/packages/core/src/view/other/PrintPreview.ts index 5cf5a58d31..08e4143837 100644 --- a/packages/core/src/view/other/PrintPreview.ts +++ b/packages/core/src/view/other/PrintPreview.ts @@ -24,7 +24,7 @@ import Client from '../../Client'; import { intersects } from '../../util/mathUtils'; import { DIALECT } from '../../util/Constants'; import { addLinkToHead, write } from '../../util/domUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type CellState from '../cell/CellState'; import type Cell from '../cell/Cell'; import { GlobalConfig } from '../../util/config'; @@ -147,7 +147,7 @@ import { GlobalConfig } from '../../util/config'; */ class PrintPreview { constructor( - graph: Graph, + graph: AbstractGraph, scale: number | null = null, pageFormat: Rectangle | null = null, border: number | null = null, @@ -171,9 +171,9 @@ class PrintPreview { } /** - * Reference to the {@link graph} that should be previewed. + * Reference to the {@link AbstractGraph} that should be previewed. */ - graph: Graph; + graph: AbstractGraph; /** * Holds the {@link Rectangle} that defines the page format. @@ -311,7 +311,7 @@ class PrintPreview { * this is specified then no HEAD tag, CSS and BODY tag will be written. */ appendGraph( - graph: Graph, + graph: AbstractGraph, scale: number, x0: number, y0: number, diff --git a/packages/core/src/view/plugins/CellEditorHandler.ts b/packages/core/src/view/plugins/CellEditorHandler.ts index 06e232f95e..202654af15 100644 --- a/packages/core/src/view/plugins/CellEditorHandler.ts +++ b/packages/core/src/view/plugins/CellEditorHandler.ts @@ -48,14 +48,14 @@ import { } from '../../util/EventUtils'; import EventSource from '../event/EventSource'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type { GraphPlugin } from '../../types'; import type TooltipHandler from './TooltipHandler'; /** * In-place editor for the graph. To control this editor, use - * {@link Graph#invokesStopCellEditing}, {@link Graph#enterStopsCellEditing} and - * {@link Graph#escapeEnabled}. If {@link Graph#enterStopsCellEditing} is true then + * {@link AbstractGraph.invokesStopCellEditing}, {@link AbstractGraph.enterStopsCellEditing} and + * {@link AbstractGraph.escapeEnabled}. If {@link AbstractGraph.enterStopsCellEditing} is true then * ctrl-enter or shift-enter can be used to create a linefeed. The F2 and * escape keys can always be used to stop editing. * @@ -153,7 +153,7 @@ import type TooltipHandler from './TooltipHandler'; class CellEditorHandler implements GraphPlugin { static pluginId = 'CellEditorHandler'; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; // Stops editing after zoom changes @@ -189,9 +189,9 @@ class CellEditorHandler implements GraphPlugin { textDirection: '' | 'auto' | 'ltr' | 'rtl' | null = null; /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Holds the DIV that is used for text editing. Note that this may be null before the first @@ -312,10 +312,9 @@ class CellEditorHandler implements GraphPlugin { } /** - * Called in if cancel is false to invoke {@link Graph#labelChanged}. + * Called in if cancel is false to invoke {@link AbstractGraph.labelChanged}. */ - // applyValue(state: CellState, value: string): void; - applyValue(state: CellState, value: any) { + applyValue(state: CellState, value: any): void { this.graph.labelChanged(state.cell, value, this.trigger); } @@ -463,7 +462,7 @@ class CellEditorHandler implements GraphPlugin { /** * Returns true if the given keydown event should stop cell editing. This - * returns true if F2 is pressed of if {@link Graph#enterStopsCellEditing} is true + * returns true if F2 is pressed of if {@link AbstractGraph.enterStopsCellEditing} is true * and enter is pressed without control or shift. */ isStopEditingEvent(evt: KeyboardEvent) { diff --git a/packages/core/src/view/plugins/ConnectionHandler.ts b/packages/core/src/view/plugins/ConnectionHandler.ts index 52229aa75d..1eface8b4a 100644 --- a/packages/core/src/view/plugins/ConnectionHandler.ts +++ b/packages/core/src/view/plugins/ConnectionHandler.ts @@ -54,7 +54,7 @@ import { } from '../../util/EventUtils'; import Image from '../image/ImageBox'; import CellState from '../cell/CellState'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import ConnectionConstraint from '../other/ConnectionConstraint'; import Shape from '../geometry/Shape'; import type { @@ -75,7 +75,7 @@ type FactoryMethod = ( * Graph event handler that creates new connections. * Uses {@link CellMarker} for finding and highlighting the source and target vertices and {@link factoryMethod} to create the edge instance. * - * This handler is enabled using {@link Graph.setConnectable}. + * This handler is enabled using {@link AbstractGraph.setConnectable}. * * Example: * @@ -180,7 +180,7 @@ type FactoryMethod = ( * Depending on the logic in the handler, this doesn't necessarily have to be the target * of the inserted edge. To print the source, target or any optional ports IDs that the * edge is connected to, the following code can be used. To get more details about the - * actual connection point, {@link Graph.getConnectionConstraint} can be used. To resolve + * actual connection point, {@link AbstractGraph.getConnectionConstraint} can be used. To resolve * the port IDs, use {@link GraphDataModel.getCell}. * * ```javascript @@ -221,9 +221,9 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene waypoints: Point[] = []; /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Function that is used for creating new edges. The function takes the @@ -385,13 +385,13 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene * Constructs an event handler that connects vertices using the specified * factory method to create the new edges. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. * @param factoryMethod Optional function to create the edge. The function takes * the source and target {@link Cell} as the first and second argument and an * optional cell style from the preview as the third argument. It returns * the {@link Cell} that represents the new edge. */ - constructor(graph: Graph, factoryMethod: FactoryMethod | null = null) { + constructor(graph: AbstractGraph, factoryMethod: FactoryMethod | null = null) { super(); this.graph = graph; @@ -555,7 +555,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene } /** - * Returns {@link Graph#isValidSource} for the given source terminal. + * Returns {@link AbstractGraph.isValidSource} for the given source terminal. * * @param cell that represents the source terminal. * @param me {@link MouseEvent} that is associated with this call. @@ -565,8 +565,8 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene } /** - * Returns true. The call to {@link Graph#isValidTarget} is implicit by calling - * {@link Graph#getEdgeValidationError} in . This is an + * Returns true. The call to {@link AbstractGraph.isValidTarget} is implicit by calling + * {@link AbstractGraph.getEdgeValidationError} in . This is an * additional hook for disabling certain targets in this specific handler. * * @param cell that represents the target terminal. @@ -578,7 +578,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene /** * Returns the error message or an empty string if the connection for the * given source target pair is not valid. Otherwise it returns null. This - * implementation uses {@link Graph#getEdgeValidationError}. + * implementation uses {@link AbstractGraph.getEdgeValidationError}. * * @param source that represents the source terminal. * @param target that represents the target terminal. @@ -1830,7 +1830,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene /** * Creates, inserts and returns the new edge for the given parameters. This * implementation does only use if is defined, - * otherwise {@link Graph#insertEdge} will be used. + * otherwise {@link AbstractGraph.insertEdge} will be used. */ insertEdge( parent: Cell, @@ -1952,7 +1952,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin, MouseListene /** * Destroys the handler and all its resources and DOM nodes. This should be * called on all instances. It is called automatically for the built-in - * instance created for each {@link Graph}. + * instance created for each {@link AbstractGraph}. */ onDestroy() { this.graph.removeMouseListener(this); @@ -1994,7 +1994,7 @@ class ConnectionHandlerCellMarker extends CellMarker { hotspotEnabled = true; constructor( - graph: Graph, + graph: AbstractGraph, connectionHandler: ConnectionHandler, validColor: ColorValue = DEFAULT_VALID_COLOR, invalidColor: ColorValue = DEFAULT_INVALID_COLOR, diff --git a/packages/core/src/view/plugins/FitPlugin.ts b/packages/core/src/view/plugins/FitPlugin.ts index 6bf5a61201..b68fa75b76 100644 --- a/packages/core/src/view/plugins/FitPlugin.ts +++ b/packages/core/src/view/plugins/FitPlugin.ts @@ -15,7 +15,7 @@ limitations under the License. */ import type { GraphPlugin } from '../../types'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; function keep2digits(value: number): number { return Number(value.toFixed(2)); @@ -52,9 +52,9 @@ export class FitPlugin implements GraphPlugin { /** * Constructs the plugin that provides `fit` methods. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. */ - constructor(private readonly graph: Graph) {} + constructor(private readonly graph: AbstractGraph) {} /** * Fit and center the graph within its container. diff --git a/packages/core/src/view/plugins/PanningHandler.ts b/packages/core/src/view/plugins/PanningHandler.ts index 09716350dc..8ef8eb75c3 100644 --- a/packages/core/src/view/plugins/PanningHandler.ts +++ b/packages/core/src/view/plugins/PanningHandler.ts @@ -32,7 +32,7 @@ import PanningManager from '../other/PanningManager'; import InternalMouseEvent from '../event/InternalMouseEvent'; import type { GraphPlugin, MouseEventListener } from '../../types'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; /** * Event handler that pans and creates popupmenus. To use the left @@ -40,7 +40,7 @@ import type { Graph } from '../Graph'; * resizing, use and . For grid size * steps while panning, use . * - * When registered in the {@link Graph.constructor} plugins list, it can be enabled using {@link Graph.setPanning}. + * When registered in the {@link AbstractGraph.constructor} plugins list, it can be enabled using {@link AbstractGraph.setPanning}. * * Event: mxEvent.PAN_START * @@ -62,7 +62,7 @@ import type { Graph } from '../Graph'; class PanningHandler extends EventSource implements GraphPlugin { static pluginId = 'PanningHandler'; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); this.graph = graph; @@ -121,9 +121,9 @@ class PanningHandler extends EventSource implements GraphPlugin { } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; panningManager: PanningManager; @@ -131,7 +131,7 @@ class PanningHandler extends EventSource implements GraphPlugin { /** * Specifies if panning should be active for the left mouse button. - * Setting this to true may conflict with {@link Rubberband}. Default is false. + * Setting this to true may conflict with {@link RubberBandHandler}. Default is false. */ useLeftButtonForPanning = false; diff --git a/packages/core/src/view/plugins/PopupMenuHandler.ts b/packages/core/src/view/plugins/PopupMenuHandler.ts index 3fb1c4bcc5..4ac5bf6180 100644 --- a/packages/core/src/view/plugins/PopupMenuHandler.ts +++ b/packages/core/src/view/plugins/PopupMenuHandler.ts @@ -20,7 +20,7 @@ import MaxPopupMenu from '../../gui/MaxPopupMenu'; import InternalEvent from '../event/InternalEvent'; import { getScrollOrigin } from '../../util/styleUtils'; import { getMainEvent, isMultiTouchEvent } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import InternalMouseEvent from '../event/InternalMouseEvent'; import type { GraphPlugin } from '../../types'; import type TooltipHandler from './TooltipHandler'; @@ -37,7 +37,7 @@ import EventObject from '../event/EventObject'; class PopupMenuHandler extends MaxPopupMenu implements GraphPlugin { static pluginId = 'PopupMenuHandler'; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); this.graph = graph; @@ -59,9 +59,9 @@ class PopupMenuHandler extends MaxPopupMenu implements GraphPlugin { popupTrigger = false; /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Specifies if cells should be selected if a popupmenu is displayed for diff --git a/packages/core/src/view/plugins/RubberBandHandler.ts b/packages/core/src/view/plugins/RubberBandHandler.ts index eabed71062..cd381726d6 100644 --- a/packages/core/src/view/plugins/RubberBandHandler.ts +++ b/packages/core/src/view/plugins/RubberBandHandler.ts @@ -30,7 +30,7 @@ import Client from '../../Client'; import Rectangle from '../geometry/Rectangle'; import { isAltDown, isMultiTouchEvent } from '../../util/EventUtils'; import { clearSelection } from '../../util/domUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import type { GraphPlugin, MouseListenerSet } from '../../types'; import EventObject from '../event/EventObject'; import EventSource from '../event/EventSource'; @@ -60,7 +60,7 @@ import EventSource from '../event/EventSource'; class RubberBandHandler implements GraphPlugin, MouseListenerSet { static pluginId = 'RubberBandHandler'; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; this.graph.addMouseListener(this); @@ -101,7 +101,7 @@ class RubberBandHandler implements GraphPlugin, MouseListenerSet { forceRubberbandHandler: Function; panHandler: Function; gestureHandler: Function; - graph: Graph; + graph: AbstractGraph; first: Point | null = null; destroyed = false; dragHandler: ((evt: MouseEvent) => void) | null = null; @@ -295,7 +295,7 @@ class RubberBandHandler implements GraphPlugin, MouseListenerSet { } /** - * Handles the event by selecting the region of the rubberband using {@link Graph#selectRegion}. + * Handles the event by selecting the region of the rubberband using {@link AbstractGraph.selectRegion}. */ mouseUp(_sender: EventSource, me: InternalMouseEvent) { const active = this.isActive(); diff --git a/packages/core/src/view/plugins/SelectionCellsHandler.ts b/packages/core/src/view/plugins/SelectionCellsHandler.ts index 21382ccd10..6ff08fe499 100644 --- a/packages/core/src/view/plugins/SelectionCellsHandler.ts +++ b/packages/core/src/view/plugins/SelectionCellsHandler.ts @@ -21,7 +21,7 @@ import Dictionary from '../../util/Dictionary'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import { sortCells } from '../../util/styleUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import Cell from '../cell/Cell'; import CellState from '../cell/CellState'; import type { GraphPlugin, MouseListenerSet } from '../../types'; @@ -51,7 +51,7 @@ type Handler = EdgeHandler | VertexHandler; class SelectionCellsHandler extends EventSource implements GraphPlugin, MouseListenerSet { static pluginId = 'SelectionCellsHandler'; - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(); this.graph = graph; @@ -76,9 +76,9 @@ class SelectionCellsHandler extends EventSource implements GraphPlugin, MouseLis } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Specifies if events are handled. Default is true. diff --git a/packages/core/src/view/plugins/SelectionHandler.ts b/packages/core/src/view/plugins/SelectionHandler.ts index c63b219f86..3be83049d0 100644 --- a/packages/core/src/view/plugins/SelectionHandler.ts +++ b/packages/core/src/view/plugins/SelectionHandler.ts @@ -21,7 +21,7 @@ import InternalEvent from '../event/InternalEvent'; import { contains, getRotatedPoint, isNumeric, toRadians } from '../../util/mathUtils'; import { convertPoint } from '../../util/styleUtils'; import RectangleShape from '../geometry/node/RectangleShape'; -import mxGuide from '../other/Guide'; +import Guide from '../other/Guide'; import Point from '../geometry/Point'; import { CURSOR, @@ -40,8 +40,7 @@ import { isAltDown, isMultiTouchEvent, } from '../../util/EventUtils'; -import type { Graph } from '../Graph'; -import Guide from '../other/Guide'; +import type { AbstractGraph } from '../AbstractGraph'; import Shape from '../geometry/Shape'; import InternalMouseEvent from '../event/InternalMouseEvent'; import type SelectionCellsHandler from './SelectionCellsHandler'; @@ -56,10 +55,10 @@ import type CellEditorHandler from './CellEditorHandler'; import type { ColorValue, GraphPlugin } from '../../types'; /** - * Graph event handler that handles selection. Individual cells are handled - * separately using {@link VertexHandler} or one of the edge handlers. These - * handlers are created using {@link Graph#createHandler} in - * {@link GraphSelectionModel#cellAdded}. + * Graph event handler that handles selection. + * + * Individual cells are handled separately by {@link SelectionCellsHandler} using {@link VertexHandler} or one of the {@link EdgeHandler}s. + * When the {@link SelectionCellsHandler} plugin is registered in the {@link AbstractGraph}, {@link SelectionHandler} interacts with this plugin to propagate global selection events to individual cells. * * To avoid the container to scroll a moved cell into view, set {@link scrollOnMove} to `false`. * @@ -71,9 +70,9 @@ class SelectionHandler implements GraphPlugin { /** * Constructs an event handler that creates handles for the selection cells. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. */ - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; this.graph.addMouseListener(this); @@ -168,9 +167,9 @@ class SelectionHandler implements GraphPlugin { } /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; panHandler: () => void; escapeHandler: (sender: EventSource, evt: EventObject) => void; @@ -282,7 +281,7 @@ class SelectionHandler implements GraphPlugin { /** * Specifies if the graph container should be used for preview. If this is used - * then drop target detection relies entirely on {@link Graph#getCellAt} because + * then drop target detection relies entirely on {@link AbstractGraph.getCellAt} because * the HTML preview does not "let events through". Default is false. */ htmlPreview = false; @@ -667,7 +666,7 @@ class SelectionHandler implements GraphPlugin { * For vertices, this method uses the bounding box of the corresponding shape * if one exists. The bounding box of the corresponding text label and all * controls and overlays are ignored. See also: {@link GraphView#getBounds} and - * {@link Graph#getBoundingBox}. + * {@link AbstractGraph.getBoundingBox}. * * @param cells Array of {@link Cells} whose bounding box should be returned. */ @@ -729,7 +728,7 @@ class SelectionHandler implements GraphPlugin { } createGuide() { - return new mxGuide(this.graph, this.getGuideStates()); + return new Guide(this.graph, this.getGuideStates()); } /** diff --git a/packages/core/src/view/plugins/TooltipHandler.ts b/packages/core/src/view/plugins/TooltipHandler.ts index a529ae3fbf..c43e8f1369 100644 --- a/packages/core/src/view/plugins/TooltipHandler.ts +++ b/packages/core/src/view/plugins/TooltipHandler.ts @@ -21,7 +21,7 @@ import { fit, getScrollOrigin } from '../../util/styleUtils'; import { TOOLTIP_VERTICAL_OFFSET } from '../../util/Constants'; import { getSource, isMouseEvent } from '../../util/EventUtils'; import { isNode } from '../../util/domUtils'; -import type { Graph } from '../Graph'; +import type { AbstractGraph } from '../AbstractGraph'; import CellState from '../cell/CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; import type PopupMenuHandler from './PopupMenuHandler'; @@ -31,9 +31,9 @@ import EventSource from '../event/EventSource'; /** * Graph event handler that displays tooltips. * - * {@link Graph#getTooltip} is used to get the tooltip for a cell or handle. + * {@link AbstractGraph.getTooltip} is used to get the tooltip for a cell or handle. * - * This handler is generally enabled using {@link Graph#setTooltips}. + * This handler is generally enabled using {@link AbstractGraph.setTooltips}. * * @category Plugin */ @@ -75,9 +75,9 @@ class TooltipHandler implements GraphPlugin, MouseListenerSet { /** * Constructs an event handler that displays tooltips. * - * @param graph Reference to the enclosing {@link Graph}. + * @param graph Reference to the enclosing {@link AbstractGraph}. */ - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { this.graph = graph; this.graph.addMouseListener(this); } @@ -91,9 +91,9 @@ class TooltipHandler implements GraphPlugin, MouseListenerSet { zIndex = 10005; /** - * Reference to the enclosing {@link Graph}. + * Reference to the enclosing {@link AbstractGraph}. */ - graph: Graph; + graph: AbstractGraph; /** * Delay to show the tooltip in milliseconds. diff --git a/packages/core/src/view/style/config.ts b/packages/core/src/view/style/config.ts index e6410c815e..9773bc34d4 100644 --- a/packages/core/src/view/style/config.ts +++ b/packages/core/src/view/style/config.ts @@ -87,6 +87,12 @@ export const resetOrthogonalConnectorConfig = (): void => { shallowCopy(originalOrthogonalConnectorConfig, OrthogonalConnectorConfig); }; +/** + * @experimental Subject to change or removal. maxGraph's global configuration may be modified in the future without prior notice. + * @since 0.16.0 + * @category Configuration + * @category EdgeStyle + */ export type ManhattanConnectorConfigType = { /** * Limit for directions change when searching route. diff --git a/packages/core/src/view/undoable_changes/SelectionChange.ts b/packages/core/src/view/undoable_changes/SelectionChange.ts index 35c9131f50..fc4e281d82 100644 --- a/packages/core/src/view/undoable_changes/SelectionChange.ts +++ b/packages/core/src/view/undoable_changes/SelectionChange.ts @@ -18,20 +18,20 @@ import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import type { UndoableChange } from '../../types'; -import type { Graph } from '../Graph'; +import { AbstractGraph } from '../AbstractGraph'; import Cell from '../cell/Cell'; /** * Action to change the current root in a view. */ class SelectionChange implements UndoableChange { - constructor(graph: Graph, added: Cell[] = [], removed: Cell[] = []) { + constructor(graph: AbstractGraph, added: Cell[] = [], removed: Cell[] = []) { this.graph = graph; this.added = added.slice(); this.removed = removed.slice(); } - graph: Graph; + graph: AbstractGraph; added: Cell[]; diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index b11d7eb465..29f29adb3f 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -26,6 +26,7 @@ "Vertex Shapes", "EdgeStyle", "Editor", + "Graph", "GUI", "I18n", "Layout", diff --git a/packages/html/stories/DynamicToolbar.stories.ts b/packages/html/stories/DynamicToolbar.stories.ts index 1d611d9c07..3f75cffbdd 100644 --- a/packages/html/stories/DynamicToolbar.stories.ts +++ b/packages/html/stories/DynamicToolbar.stories.ts @@ -16,6 +16,7 @@ limitations under the License. */ import { + type AbstractGraph, Cell, cellArrayUtils, type CellStyle, @@ -146,7 +147,7 @@ const Template = ({ label, ...args }: Record) => { // Function that is executed when the image is dropped on the graph. // The cell argument points to the cell under the mouse pointer if there is one. const dropHandler = ( - graph: Graph, + graph: AbstractGraph, _evt: MouseEvent, _cell: Cell | null, x?: number, diff --git a/packages/html/stories/MenuStyle.stories.ts b/packages/html/stories/MenuStyle.stories.ts index 0bda78f07c..fcd56862cd 100644 --- a/packages/html/stories/MenuStyle.stories.ts +++ b/packages/html/stories/MenuStyle.stories.ts @@ -22,6 +22,7 @@ This example demonstrates using CSS to style the mxPopupMenu. */ import { + type AbstractGraph, Client, CellOverlay, CellRenderer, @@ -110,7 +111,7 @@ const Template = ({ label, ...args }: Record) => { } class MyCustomPopupMenuHandler extends PopupMenuHandler { - constructor(graph: Graph) { + constructor(graph: AbstractGraph) { super(graph); // Configures automatic expand on mouseover this.autoExpand = true; // TODO autoExpand is not working diff --git a/packages/html/stories/Toolbar.stories.ts b/packages/html/stories/Toolbar.stories.ts index c122dfa93e..c4aaddf6e2 100644 --- a/packages/html/stories/Toolbar.stories.ts +++ b/packages/html/stories/Toolbar.stories.ts @@ -16,6 +16,7 @@ limitations under the License. */ import { + type AbstractGraph, Cell, type CellStyle, Client, @@ -177,7 +178,7 @@ const Template = ({ label, ...args }: { [p: string]: any }) => { // Function that is executed when the image is dropped on // the graph. The cell argument points to the cell under // the mousepointer if there is one. - const funct = (graph: Graph, _evt: MouseEvent, cell: Cell | null) => { + const funct = (graph: AbstractGraph, _evt: MouseEvent, cell: Cell | null) => { graph.stopEditing(false); const pt = graph.getPointForEvent(evt); @@ -207,7 +208,7 @@ const Template = ({ label, ...args }: { [p: string]: any }) => { // Function that is executed when the image is dropped on // the graph. The cell argument points to the cell under // the mousepointer if there is one. - const funct = (graph: Graph, evt: MouseEvent, cell: Cell | null) => { + const funct = (graph: AbstractGraph, evt: MouseEvent, cell: Cell | null) => { graph.stopEditing(false); const pt = graph.getPointForEvent(evt); diff --git a/packages/js-example-selected-features/src/index.js b/packages/js-example-selected-features/src/index.js index 2e3fc8fc03..fe82e29d41 100644 --- a/packages/js-example-selected-features/src/index.js +++ b/packages/js-example-selected-features/src/index.js @@ -17,10 +17,10 @@ limitations under the License. import '@maxgraph/core/css/common.css'; // required by RubberBandHandler import './style.css'; import { + BaseGraph, constants, DomHelpers, EdgeMarker, - Graph, InternalEvent, MarkerShape, ModelXmlSerializer, @@ -33,15 +33,9 @@ import { } from '@maxgraph/core'; /** - * Create a custom implementation to not load all default built-in styles. This is because Graph registers them. - * - * In the future, we expect to have an implementation of Graph that does not do it. - * See https://github.com/maxGraph/maxGraph/issues/760 + * Custom implementation of {@link BaseGraph} that only register the built-in styles required by the example. */ -class CustomGraph extends Graph { - /** - * Only registers the elements required for this example. Do not let Graph load all default built-in styles. - */ +class CustomGraph extends BaseGraph { registerDefaults() { // Register styles StyleRegistry.putValue('rectanglePerimeter', Perimeter.RectanglePerimeter); // declared in the default vertex style, so must be registered to be used @@ -83,12 +77,15 @@ const initializeGraph = (container) => { // Disables the built-in context menu InternalEvent.disableContextMenu(container); - const graph = new CustomGraph(container, undefined, [ - PanningHandler, // Enables panning with the mouse - RubberBandHandler, // Enables rubber band selection - SelectionCellsHandler, // Enables management of selected cells - SelectionHandler, // Enables selection with the mouse - ]); + const graph = new CustomGraph({ + container, + plugins: [ + PanningHandler, // Enables panning with the mouse + RubberBandHandler, // Enables rubber band selection + SelectionCellsHandler, // Enables management of selected cells + SelectionHandler, // Enables selection with the mouse + ], + }); graph.setPanning(true); // Use mouse right button for panning const modelXmlSerializer = new ModelXmlSerializer(graph.model); diff --git a/packages/js-example-without-defaults/src/index.js b/packages/js-example-without-defaults/src/index.js index a1ab455da9..e4e8678d65 100644 --- a/packages/js-example-without-defaults/src/index.js +++ b/packages/js-example-without-defaults/src/index.js @@ -15,32 +15,13 @@ limitations under the License. */ import './style.css'; -import { constants, Graph, InternalEvent } from '@maxgraph/core'; - -/** - * Create a custom implementation to not load all default built-in styles. This is because Graph registers them. - * - * In the future, we expect to have an implementation of Graph that does not do it. - * See https://github.com/maxGraph/maxGraph/issues/760 - */ -class CustomGraph extends Graph { - /** - * Only registers the elements required for this example. Do not let Graph load all default built-in styles. - */ - registerDefaults() { - // do nothing - } -} +import { BaseGraph, constants, InternalEvent } from '@maxgraph/core'; const initializeGraph = (container) => { // Disables the built-in context menu InternalEvent.disableContextMenu(container); - const graph = new CustomGraph( - container, - undefined, - [] // override default plugins, use none - ); + const graph = new BaseGraph({ container }); // create a dedicated style for "ellipse" to share properties graph.getStylesheet().putCellStyle('myEllipse', { diff --git a/packages/ts-example-selected-features/src/main.ts b/packages/ts-example-selected-features/src/main.ts index 2074e4a5bb..aee4ee63bb 100644 --- a/packages/ts-example-selected-features/src/main.ts +++ b/packages/ts-example-selected-features/src/main.ts @@ -17,13 +17,13 @@ limitations under the License. import '@maxgraph/core/css/common.css'; // required by RubberBandHandler import './style.css'; import { + BaseGraph, CellRenderer, constants, EdgeMarker, EdgeStyle, EllipseShape, FitPlugin, - Graph, InternalEvent, MarkerShape, PanningHandler, @@ -35,15 +35,9 @@ import { } from '@maxgraph/core'; /** - * Create a custom implementation to not load all default built-in styles. This is because Graph registers them. - * - * In the future, we expect to have an implementation of Graph that does not do it. - * See https://github.com/maxGraph/maxGraph/issues/760 + * Custom implementation of {@link BaseGraph} that only register the built-in styles required by the example. */ -class CustomGraph extends Graph { - /** - * Only registers the elements required for this example. Do not let Graph load all default built-in styles. - */ +class CustomGraph extends BaseGraph { protected override registerDefaults() { // Register shapes // RectangleShape is not registered here because it is always available. It is the fallback shape for vertices when no shape is returned by the registry @@ -64,13 +58,16 @@ const initializeGraph = (container: HTMLElement) => { // Disables the built-in context menu InternalEvent.disableContextMenu(container); - const graph = new CustomGraph(container, undefined, [ - FitPlugin, // Enables the fitCenter method - PanningHandler, // Enables panning with the mouse - RubberBandHandler, // Enables rubber band selection - SelectionCellsHandler, // Enables management of selected cells - SelectionHandler, // Enables selection with the mouse - ]); + const graph = new CustomGraph({ + container, + plugins: [ + FitPlugin, // Enables the fitCenter method + PanningHandler, // Enables panning with the mouse + RubberBandHandler, // Enables rubber band selection + SelectionCellsHandler, // Enables management of selected cells + SelectionHandler, // Enables selection with the mouse + ], + }); graph.setPanning(true); // Use mouse right button for panning // create a dedicated style for "ellipse" to share properties diff --git a/packages/ts-example-selected-features/vite.config.js b/packages/ts-example-selected-features/vite.config.js index 1cf35ce529..b64fc88af9 100644 --- a/packages/ts-example-selected-features/vite.config.js +++ b/packages/ts-example-selected-features/vite.config.js @@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { }, }, }, - chunkSizeWarningLimit: 440, // @maxgraph/core + chunkSizeWarningLimit: 369, // @maxgraph/core }, }; }); diff --git a/packages/ts-example-without-defaults/src/main.ts b/packages/ts-example-without-defaults/src/main.ts index 62adfaf187..4354cdfe67 100644 --- a/packages/ts-example-without-defaults/src/main.ts +++ b/packages/ts-example-without-defaults/src/main.ts @@ -15,32 +15,13 @@ limitations under the License. */ import './style.css'; -import { constants, Graph, InternalEvent } from '@maxgraph/core'; - -/** - * Create a custom implementation to not load all default built-in styles. This is because Graph registers them. - * - * In the future, we expect to have an implementation of Graph that does not do it. - * See https://github.com/maxGraph/maxGraph/issues/760 - */ -class CustomGraph extends Graph { - /** - * Only registers the elements required for this example. Do not let Graph load all default built-in styles. - */ - protected override registerDefaults() { - // do nothing - } -} +import { BaseGraph, constants, InternalEvent } from '@maxgraph/core'; const initializeGraph = (container: HTMLElement) => { // Disables the built-in context menu InternalEvent.disableContextMenu(container); - const graph = new CustomGraph( - container, - undefined, - [] // override default plugins, use none - ); + const graph = new BaseGraph({ container }); // create a dedicated style for "ellipse" to share properties graph.getStylesheet().putCellStyle('myEllipse', { diff --git a/packages/ts-example-without-defaults/vite.config.js b/packages/ts-example-without-defaults/vite.config.js index 2de35c1c92..83aec18b62 100644 --- a/packages/ts-example-without-defaults/vite.config.js +++ b/packages/ts-example-without-defaults/vite.config.js @@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { }, }, }, - chunkSizeWarningLimit: 435, // @maxgraph/core + chunkSizeWarningLimit: 331, // @maxgraph/core }, }; }); diff --git a/packages/ts-example/vite.config.js b/packages/ts-example/vite.config.js index 1d99c3d626..1cf35ce529 100644 --- a/packages/ts-example/vite.config.js +++ b/packages/ts-example/vite.config.js @@ -27,7 +27,7 @@ export default defineConfig(({ mode }) => { }, }, }, - chunkSizeWarningLimit: 439, // @maxgraph/core + chunkSizeWarningLimit: 440, // @maxgraph/core }, }; });