From bdc50a9f485c9ea2ff26e15c944052608ec6ac87 Mon Sep 17 00:00:00 2001 From: Junsik Shim Date: Tue, 7 Sep 2021 18:07:27 +0900 Subject: [PATCH] Refactored everything... --- package-lock.json | 2 +- package.json | 28 +- packages/core/package.json | 11 +- packages/core/src/editor/mxDefaultToolbar.js | 23 +- packages/core/src/index.ts | 501 ++++------ packages/core/src/types.ts | 6 +- packages/core/src/util/Guide.ts | 6 +- packages/core/src/util/Utils.ts | 67 +- packages/core/src/util/animate/mxEffects.js | 23 +- packages/core/src/util/canvas/SvgCanvas2D.ts | 2 +- packages/core/src/util/gui/mxLog.js | 13 +- packages/core/src/util/gui/mxWindow.js | 2 +- .../src/util/serialization/mxEditorCodec.js | 2 +- .../src/util/serialization/mxGraphCodec.js | 2 +- .../util/serialization/mxGraphViewCodec.js | 8 +- .../src/util/serialization/mxModelCodec.js | 2 +- .../util/serialization/mxRootChangeCodec.js | 7 +- .../util/serialization/mxStylesheetCodec.js | 10 +- .../serialization/mxTerminalChangeCodec.js | 2 +- packages/core/src/util/storage/Clipboard.ts | 10 +- packages/core/src/view/Graph.ts | 229 +---- packages/core/src/view/GraphHandler.ts | 6 +- packages/core/src/view/Outline.ts | 36 +- packages/core/src/view/cell/CellMarker.ts | 8 +- packages/core/src/view/cell/CellRenderer.ts | 34 +- .../{GraphCells.ts => GraphCellsMixin.ts} | 911 +++++++++++------- packages/core/src/view/cell/TreeTraversal.ts | 2 +- .../core/src/view/cell/edge/EdgeHandler.ts | 9 +- .../src/view/cell/edge/ElbowEdgeHandler.ts | 2 +- .../edge/{GraphEdge.ts => GraphEdgeMixin.ts} | 275 ++++-- .../{GraphVertex.ts => GraphVertexMixin.ts} | 99 +- .../core/src/view/cell/vertex/VertexHandle.ts | 4 +- .../src/view/cell/vertex/VertexHandler.ts | 12 +- .../src/view/connection/ConnectionHandler.ts | 15 +- .../src/view/connection/ConstraintHandler.ts | 6 +- ...onnections.ts => GraphConnectionsMixin.ts} | 273 ++++-- .../core/src/view/drag_drop/DragSource.ts | 24 +- ...GraphDragDrop.ts => GraphDragDropMixin.ts} | 78 +- packages/core/src/view/editing/CellEditor.ts | 6 +- .../{GraphEditing.ts => GraphEditingMixin.ts} | 102 +- packages/core/src/view/event/CellTracker.ts | 4 +- .../{GraphEvents.ts => GraphEventsMixin.ts} | 446 ++++++--- packages/core/src/view/event/InternalEvent.ts | 4 +- .../{GraphFolding.ts => GraphFoldingMixin.ts} | 133 ++- .../core/src/view/geometry/shape/Shape.ts | 2 +- ...GraphGrouping.ts => GraphGroupingMixin.ts} | 155 +-- .../{GraphOrder.ts => GraphOrderMixin.ts} | 42 +- packages/core/src/view/image/GraphImage.ts | 50 - .../core/src/view/image/GraphImageMixin.ts | 65 ++ .../{GraphLabel.ts => GraphLabelMixin.ts} | 94 +- ...GraphOverlays.ts => GraphOverlaysMixin.ts} | 71 +- .../core/src/view/layout/LayoutManager.ts | 23 +- .../src/view/layout/layout/CircleLayout.ts | 2 +- .../view/layout/layout/CompactTreeLayout.ts | 4 +- .../src/view/layout/layout/EdgeLabelLayout.ts | 10 +- .../view/layout/layout/FastOrganicLayout.ts | 2 +- .../src/view/layout/layout/GraphLayout.ts | 28 +- .../view/layout/layout/ParallelEdgeLayout.ts | 2 +- .../src/view/layout/layout/PartitionLayout.ts | 9 +- .../view/layout/layout/RadialTreeLayout.ts | 19 +- .../src/view/layout/layout/StackLayout.ts | 76 +- .../layout/hierarchical/SwimlaneLayout.ts | 2 +- .../hierarchical/model/SwimlaneModel.ts | 9 +- .../hierarchical/stage/mxSwimlaneOrdering.js | 2 +- ...hPageBreaks.ts => GraphPageBreaksMixin.ts} | 33 +- .../{GraphPanning.ts => GraphPanningMixin.ts} | 122 ++- .../core/src/view/panning/PanningHandler.ts | 6 +- .../core/src/view/panning/PanningManager.ts | 4 +- .../src/view/popups_menus/PopupMenuHandler.ts | 6 +- .../{GraphPorts.ts => GraphPortsMixin.ts} | 43 +- .../core/src/view/printing/PrintPreview.ts | 4 +- .../core/src/view/selection/CellHighlight.ts | 2 +- ...aphSelection.ts => GraphSelectionMixin.ts} | 328 +++++-- .../core/src/view/selection/RubberBand.ts | 6 +- .../view/selection/SelectionCellsHandler.ts | 6 +- .../src/view/selection/SelectionChange.ts | 6 +- .../snap/{GraphSnap.ts => GraphSnapMixin.ts} | 93 +- packages/core/src/view/style/EdgeStyle.ts | 226 +---- packages/core/src/view/style/Perimeter.ts | 30 +- ...GraphSwimlane.ts => GraphSwimlaneMixin.ts} | 143 ++- ...GraphTerminal.ts => GraphTerminalMixin.ts} | 38 +- .../{GraphTooltip.ts => GraphTooltipMixin.ts} | 47 +- .../core/src/view/tooltip/TooltipHandler.ts | 6 +- ...hValidation.ts => GraphValidationMixin.ts} | 85 +- .../core/src/view/validation/Multiplicity.ts | 50 +- packages/core/src/view/view/GraphView.ts | 6 +- .../zoom/{GraphZoom.ts => GraphZoomMixin.ts} | 136 ++- tsconfig.json => packages/core/tsconfig.json | 20 +- packages/html/package.json | 4 +- packages/html/stories/Anchors.stories.js | 24 +- packages/html/stories/Animation.stories.js | 4 +- packages/html/stories/AutoLayout.stories.js | 33 +- packages/html/stories/Boundary.stories.js | 11 +- packages/html/stories/Clipboard.stories.js | 30 +- packages/html/stories/Collapse.stories.js | 4 +- packages/html/stories/Constituent.stories.js | 4 +- packages/html/stories/ContextIcons.stories.js | 11 +- packages/html/stories/Control.stories.js | 22 +- packages/html/stories/DragSource.stories.js | 30 +- packages/html/stories/Drop.stories.js | 11 +- .../html/stories/DynamicLoading.stories.js | 24 +- packages/html/stories/DynamicStyle.stories.js | 4 +- .../html/stories/DynamicToolbar.stories.js | 32 +- .../html/stories/EdgeTolerance.stories.js | 4 +- packages/html/stories/Editing.stories.js | 11 +- packages/html/stories/Events.stories.js | 26 +- packages/html/stories/ExtendCanvas.stories.js | 11 +- packages/html/stories/FileIO.stories.js | 4 +- packages/html/stories/FixedIcons.stories.js | 4 +- packages/html/stories/FixedPoints.stories.js | 22 +- packages/html/stories/Folding.stories.js | 4 +- packages/html/stories/Grid.stories.js | 22 +- packages/html/stories/Groups.stories.js | 4 +- packages/html/stories/Guides.stories.js | 20 +- packages/html/stories/Handles.stories.js | 28 +- packages/html/stories/HelloPort.stories.js | 20 +- packages/html/stories/HelloWorld.stories.js | 6 +- .../stories/HierarchicalLayout.stories.js | 22 +- packages/html/stories/HoverIcons.stories.js | 20 +- packages/html/stories/HoverStyle.stories.js | 4 +- packages/html/stories/Images.stories.js | 11 +- packages/html/stories/Indicators.stories.js | 4 +- packages/html/stories/JsonData.stories.js | 26 +- .../html/stories/LabelPosition.stories.js | 4 +- packages/html/stories/Labels.stories.js | 4 +- packages/html/stories/Layers.stories.js | 6 +- packages/html/stories/LoD.stories.js | 4 +- packages/html/stories/Markers.stories.js | 22 +- packages/html/stories/Merge.stories.js | 4 +- packages/html/stories/Monitor.stories.js | 24 +- packages/html/stories/Morph.stories.js | 10 +- packages/html/stories/OffPage.stories.js | 4 +- packages/html/stories/OrgChart.stories.js | 34 +- packages/html/stories/Orthogonal.stories.js | 26 +- packages/html/stories/Overlays.stories.js | 11 +- packages/html/stories/PageBreaks.stories.js | 10 +- packages/html/stories/Perimeter.stories.js | 4 +- packages/html/stories/Permissions.stories.js | 18 +- packages/html/stories/PortRefs.stories.js | 28 +- .../html/stories/RadialTreeLayout.stories.js | 10 +- packages/html/stories/SecondLabel.stories.js | 20 +- packages/html/stories/Shape.stories.js | 4 +- packages/html/stories/Stencils.stories.js | 37 +- packages/html/stories/Stylesheet.stories.js | 4 +- packages/html/stories/SwimLanes.stories.js | 30 +- packages/html/stories/Thread.stories.js | 4 +- packages/html/stories/Toolbar.stories.js | 32 +- packages/html/stories/Tree.stories.js | 31 +- packages/html/stories/UserObject.stories.js | 33 +- packages/html/stories/Validation.stories.js | 18 +- packages/html/stories/Visibility.stories.js | 4 +- packages/html/stories/Window.stories.js | 22 +- packages/html/stories/Wrapping.stories.js | 4 +- packages/react/package.json | 4 +- webpack.config.js | 2 +- 155 files changed, 3500 insertions(+), 3051 deletions(-) rename packages/core/src/view/cell/{GraphCells.ts => GraphCellsMixin.ts} (83%) rename packages/core/src/view/cell/edge/{GraphEdge.ts => GraphEdgeMixin.ts} (78%) rename packages/core/src/view/cell/vertex/{GraphVertex.ts => GraphVertexMixin.ts} (72%) rename packages/core/src/view/connection/{GraphConnections.ts => GraphConnectionsMixin.ts} (80%) rename packages/core/src/view/drag_drop/{GraphDragDrop.ts => GraphDragDropMixin.ts} (68%) rename packages/core/src/view/editing/{GraphEditing.ts => GraphEditingMixin.ts} (76%) rename packages/core/src/view/event/{GraphEvents.ts => GraphEventsMixin.ts} (80%) rename packages/core/src/view/folding/{GraphFolding.ts => GraphFoldingMixin.ts} (79%) rename packages/core/src/view/grouping_ordering/{GraphGrouping.ts => GraphGroupingMixin.ts} (84%) rename packages/core/src/view/grouping_ordering/{GraphOrder.ts => GraphOrderMixin.ts} (70%) delete mode 100644 packages/core/src/view/image/GraphImage.ts create mode 100644 packages/core/src/view/image/GraphImageMixin.ts rename packages/core/src/view/label/{GraphLabel.ts => GraphLabelMixin.ts} (75%) rename packages/core/src/view/layout/{GraphOverlays.ts => GraphOverlaysMixin.ts} (81%) rename packages/core/src/view/page_breaks/{GraphPageBreaks.ts => GraphPageBreaksMixin.ts} (84%) rename packages/core/src/view/panning/{GraphPanning.ts => GraphPanningMixin.ts} (81%) rename packages/core/src/view/ports/{GraphPorts.ts => GraphPortsMixin.ts} (71%) rename packages/core/src/view/selection/{GraphSelection.ts => GraphSelectionMixin.ts} (72%) rename packages/core/src/view/snap/{GraphSnap.ts => GraphSnapMixin.ts} (70%) rename packages/core/src/view/swimlane/{GraphSwimlane.ts => GraphSwimlaneMixin.ts} (77%) rename packages/core/src/view/terminal/{GraphTerminal.ts => GraphTerminalMixin.ts} (79%) rename packages/core/src/view/tooltip/{GraphTooltip.ts => GraphTooltipMixin.ts} (80%) rename packages/core/src/view/validation/{GraphValidation.ts => GraphValidationMixin.ts} (85%) rename packages/core/src/view/zoom/{GraphZoom.ts => GraphZoomMixin.ts} (65%) rename tsconfig.json => packages/core/tsconfig.json (53%) diff --git a/package-lock.json b/package-lock.json index 8ec81d432..cbd826381 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,5 +1,5 @@ { - "name": "mxgraph", + "name": "maxgraph", "version": "4.2.2", "lockfileVersion": 1, "requires": true, diff --git a/package.json b/package.json index 482c8e645..705404030 100644 --- a/package.json +++ b/package.json @@ -1,19 +1,19 @@ { - "name": "mxgraph", - "description": "mxGraph is a fully client side JavaScript diagramming library that uses SVG and HTML for rendering.", - "version": "4.2.2", - "homepage": "https://github.com/jgraph/mxgraph", + "name": "maxgraph", + "description": "max-graph is a fully client side JavaScript diagramming library that uses SVG and HTML for rendering.", + "version": "1.0.0", + "homepage": "https://github.com/maxGraph/maxGraph", "author": { - "name": "JGraph Ltd", - "email": "support@jgraph.com" + "name": "", + "email": "" }, - "license": "Apache-2.0", + "license": "MIT", "repository": { "type": "git", - "url": "git+https://github.com/jgraph/mxgraph.git" + "url": "git+https://github.com/maxGraph/maxGraph" }, "bugs": { - "url": "https://github.com/jgraph/mxgraph/issues" + "url": "https://github.com/maxGraph/maxGraph/issues" }, "main": "./javascript/dist/build.js", "scripts": { @@ -23,21 +23,21 @@ }, "devDependencies": { "@babel/core": "^7.13.15", + "@babel/plugin-proposal-class-properties": "^7.13.0", "@babel/preset-env": "^7.13.15", "@babel/preset-react": "^7.13.13", "@babel/preset-typescript": "^7.13.0", - "@babel/plugin-proposal-class-properties": "^7.13.0", + "@lerna/filter-options": "4.0.0", "babel-loader": "^8.2.2", "css-loader": "^5.2.1", + "file-loader": "^6.2.0", "lerna": "^4.0.0", - "@lerna/filter-options": "4.0.0", "prettier": "^2.2.1", "style-loader": "^2.0.0", + "typescript": "^4.2.4", "url-loader": "^4.1.1", - "file-loader": "^6.2.0", "webpack": "^5.32.0", "webpack-cli": "^4.6.0", - "webpack-merge": "^5.7.3", - "typescript": "^4.2.4" + "webpack-merge": "^5.7.3" } } diff --git a/packages/core/package.json b/packages/core/package.json index d68786d5a..9fcb3c3ca 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,10 +1,13 @@ { - "name": "@mxgraph/core", + "name": "@maxgraph/core", "version": "1.0.0", "description": "", - "module": "src/index.ts", - "main": "dist/mxgraph.js", - "types": "dist/mxgraph.d.ts", + "module": "./src/index.ts", + "main": "./dist/maxgraph.js", + "types": "./dist/maxgraph.d.ts", + "files": [ + "./dist" + ], "scripts": { "dev": "webpack --watch --mode=development", "build": "NODE_ENV=production webpack --mode=production", diff --git a/packages/core/src/editor/mxDefaultToolbar.js b/packages/core/src/editor/mxDefaultToolbar.js index e8dbca469..4329017da 100644 --- a/packages/core/src/editor/mxDefaultToolbar.js +++ b/packages/core/src/editor/mxDefaultToolbar.js @@ -8,7 +8,7 @@ import mxClient from '../mxClient'; import mxToolbar from '../util/gui/mxToolbar'; import Geometry from '../view/geometry/Geometry'; -import utils, { convertPoint } from '../util/Utils'; +import { convertPoint } from '../util/Utils'; import InternalEvent from '../view/event/InternalEvent'; import { getClientX, getClientY } from '../util/EventUtils'; import { makeDraggable } from '../util/GestureUtils'; @@ -265,14 +265,7 @@ class mxDefaultToolbar { InternalEvent.consume(evt); }; - const img = this.toolbar.addMode( - title, - icon, - clickHandler, - pressed, - null, - toggle - ); + const img = this.toolbar.addMode(title, icon, clickHandler, pressed, null, toggle); // Creates a wrapper function that calls the click handler without // the graph argument @@ -307,10 +300,7 @@ class mxDefaultToolbar { !this.connectOnDrop || !target.isConnectable() ) { - while ( - target != null && - !graph.isValidDropTarget(target, [vertex], evt) - ) { + while (target != null && !graph.isValidDropTarget(target, [vertex], evt)) { target = target.getParent(); } this.insert(vertex, evt, target); @@ -337,10 +327,7 @@ class mxDefaultToolbar { const pt = convertPoint(graph.container, x, y); // Splits the target edge or inserts into target group - if ( - graph.isSplitEnabled() && - graph.isSplitTarget(target, [vertex], evt) - ) { + if (graph.isSplitEnabled() && graph.isSplitTarget(target, [vertex], evt)) { return graph.splitEdge(target, [vertex], null, pt.x, pt.y); } return this.editor.addVertex(target, vertex, pt.x, pt.y); @@ -428,7 +415,7 @@ class mxDefaultToolbar { sprite.setAttribute('src', img.getAttribute('src')); // Handles delayed loading of the images - const loader = evt => { + const loader = (evt) => { // Preview uses the image node with double size. Later this can be // changed to use a separate preview and guides, but for this the // dropHandler must use the additional x- and y-arguments and the diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 3a809025b..ffb9f7eb0 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -1,348 +1,211 @@ -import mxClient from './mxClient'; +/* Graph mixins */ +import './view/ports/GraphPortsMixin'; +import './view/panning/GraphPanningMixin'; +import './view/zoom/GraphZoomMixin'; +import './view/event/GraphEventsMixin'; +import './view/image/GraphImageMixin'; +import './view/cell/GraphCellsMixin'; +import './view/selection/GraphSelectionMixin'; +import './view/connection/GraphConnectionsMixin'; +import './view/cell/edge/GraphEdgeMixin'; +import './view/cell/vertex/GraphVertexMixin'; +import './view/layout/GraphOverlaysMixin'; +import './view/editing/GraphEditingMixin'; +import './view/folding/GraphFoldingMixin'; +import './view/label/GraphLabelMixin'; +import './view/validation/GraphValidationMixin'; +import './view/snap/GraphSnapMixin'; +import './view/tooltip/GraphTooltipMixin'; +import './view/terminal/GraphTerminalMixin'; +import './view/drag_drop/GraphDragDropMixin'; +import './view/swimlane/GraphSwimlaneMixin'; +import './view/page_breaks/GraphPageBreaksMixin'; +import './view/grouping_ordering/GraphGroupingMixin'; +import './view/grouping_ordering/GraphOrderMixin'; -import CellAttributeChange from './view/cell/CellAttributeChange'; -import ChildChange from './view/model/ChildChange'; -import CollapseChange from './view/folding/CollapseChange'; -import CurrentRootChange from './view/view/CurrentRootChange'; -import GeometryChange from './view/geometry/GeometryChange'; -import RootChange from './view/model/RootChange'; -import SelectionChange from './view/selection/SelectionChange'; -import StyleChange from './view/style/StyleChange'; -import TerminalChange from './view/cell/edge/TerminalChange'; -import ValueChange from './view/cell/ValueChange'; -import VisibleChange from './view/style/VisibleChange'; +export { Graph } from './view/Graph'; -import mxDefaultKeyHandler from './editor/mxDefaultKeyHandler'; -import mxDefaultPopupMenu from './editor/mxDefaultPopupMenu'; -import mxDefaultToolbar from './editor/mxDefaultToolbar'; -import mxEditor from './editor/mxEditor'; +export { default as Model } from './view/model/Model'; +export { default as GraphView } from './view/view/GraphView'; +export { default as LayoutManager } from './view/layout/LayoutManager'; +export { default as Outline } from './view/Outline'; +export { default as PrintPreview } from './view/printing/PrintPreview'; +export { default as SwimlaneManager } from './view/layout/SwimlaneManager'; +export { default as mxClient } from './mxClient'; -import CellHighlight from './view/selection/CellHighlight'; -import CellMarker from './view/cell/CellMarker'; -import CellTracker from './view/event/CellTracker'; -import ConnectionHandler from './view/connection/ConnectionHandler'; -import ConstraintHandler from './view/connection/ConstraintHandler'; -import EdgeHandler from './view/cell/edge/EdgeHandler'; -import EdgeSegmentHandler from './view/cell/edge/EdgeSegmentHandler'; -import ElbowEdgeHandler from './view/cell/edge/ElbowEdgeHandler'; -import GraphHandler from './view/GraphHandler'; -import VertexHandle from './view/cell/vertex/VertexHandle'; -import mxKeyHandler from './view/event/mxKeyHandler'; -import PanningHandler from './view/panning/PanningHandler'; -import PopupMenuHandler from './view/popups_menus/PopupMenuHandler'; -import RubberBand from './view/selection/RubberBand'; -import SelectionCellsHandler from './view/selection/SelectionCellsHandler'; -import TooltipHandler from './view/tooltip/TooltipHandler'; -import VertexHandler from './view/cell/vertex/VertexHandler'; +export { default as CellAttributeChange } from './view/cell/CellAttributeChange'; +export { default as ChildChange } from './view/model/ChildChange'; +export { default as CollapseChange } from './view/folding/CollapseChange'; +export { default as CurrentRootChange } from './view/view/CurrentRootChange'; +export { default as GeometryChange } from './view/geometry/GeometryChange'; +export { default as RootChange } from './view/model/RootChange'; +export { default as SelectionChange } from './view/selection/SelectionChange'; +export { default as StyleChange } from './view/style/StyleChange'; +export { default as TerminalChange } from './view/cell/edge/TerminalChange'; +export { default as ValueChange } from './view/cell/ValueChange'; +export { default as VisibleChange } from './view/style/VisibleChange'; -import CircleLayout from './view/layout/layout/CircleLayout'; -import CompactTreeLayout from './view/layout/layout/CompactTreeLayout'; -import CompositeLayout from './view/layout/layout/CompositeLayout'; -import EdgeLabelLayout from './view/layout/layout/EdgeLabelLayout'; -import MxFastOrganicLayout from './view/layout/layout/FastOrganicLayout'; -import GraphLayout from './view/layout/layout/GraphLayout'; -import ParallelEdgeLayout from './view/layout/layout/ParallelEdgeLayout'; -import PartitionLayout from './view/layout/layout/PartitionLayout'; -import RadialTreeLayout from './view/layout/layout/RadialTreeLayout'; -import StackLayout from './view/layout/layout/StackLayout'; +export { default as mxDefaultKeyHandler } from './editor/mxDefaultKeyHandler'; +export { default as mxDefaultPopupMenu } from './editor/mxDefaultPopupMenu'; +export { default as mxDefaultToolbar } from './editor/mxDefaultToolbar'; +export { default as mxEditor } from './editor/mxEditor'; -import HierarchicalEdgeStyle from './view/layout/layout/hierarchical/HierarchicalEdgeStyle'; -import mxHierarchicalLayout from './view/layout/layout/hierarchical/mxHierarchicalLayout'; -import SwimlaneLayout from './view/layout/layout/hierarchical/SwimlaneLayout'; +export { default as CellHighlight } from './view/selection/CellHighlight'; +export { default as CellMarker } from './view/cell/CellMarker'; +export { default as CellTracker } from './view/event/CellTracker'; +export { default as ConnectionHandler } from './view/connection/ConnectionHandler'; +export { default as ConstraintHandler } from './view/connection/ConstraintHandler'; +export { default as EdgeHandler } from './view/cell/edge/EdgeHandler'; +export { default as EdgeSegmentHandler } from './view/cell/edge/EdgeSegmentHandler'; +export { default as ElbowEdgeHandler } from './view/cell/edge/ElbowEdgeHandler'; +export { default as GraphHandler } from './view/GraphHandler'; +export { default as VertexHandle } from './view/cell/vertex/VertexHandle'; +export { default as mxKeyHandler } from './view/event/mxKeyHandler'; +export { default as PanningHandler } from './view/panning/PanningHandler'; +export { default as PopupMenuHandler } from './view/popups_menus/PopupMenuHandler'; +export { default as RubberBand } from './view/selection/RubberBand'; +export { default as SelectionCellsHandler } from './view/selection/SelectionCellsHandler'; +export { default as TooltipHandler } from './view/tooltip/TooltipHandler'; +export { default as VertexHandler } from './view/cell/vertex/VertexHandler'; -import MxGraphAbstractHierarchyCell from './view/layout/layout/hierarchical/model/GraphAbstractHierarchyCell'; -import GraphHierarchyEdge from './view/layout/layout/hierarchical/model/GraphHierarchyEdge'; -import GraphHierarchyModel from './view/layout/layout/hierarchical/model/GraphHierarchyModel'; -import GraphHierarchyNode from './view/layout/layout/hierarchical/model/GraphHierarchyNode'; -import SwimlaneModel from './view/layout/layout/hierarchical/model/SwimlaneModel'; +export { default as CircleLayout } from './view/layout/layout/CircleLayout'; +export { default as CompactTreeLayout } from './view/layout/layout/CompactTreeLayout'; +export { default as CompositeLayout } from './view/layout/layout/CompositeLayout'; +export { default as EdgeLabelLayout } from './view/layout/layout/EdgeLabelLayout'; +export { default as MxFastOrganicLayout } from './view/layout/layout/FastOrganicLayout'; +export { default as GraphLayout } from './view/layout/layout/GraphLayout'; +export { default as ParallelEdgeLayout } from './view/layout/layout/ParallelEdgeLayout'; +export { default as PartitionLayout } from './view/layout/layout/PartitionLayout'; +export { default as RadialTreeLayout } from './view/layout/layout/RadialTreeLayout'; +export { default as StackLayout } from './view/layout/layout/StackLayout'; -import CoordinateAssignment from './view/layout/layout/hierarchical/stage/CoordinateAssignment'; -import MxHierarchicalLayoutStage from './view/layout/layout/hierarchical/stage/HierarchicalLayoutStage'; -import MedianHybridCrossingReduction from './view/layout/layout/hierarchical/stage/MedianHybridCrossingReduction'; -import MinimumCycleRemover from './view/layout/layout/hierarchical/stage/MinimumCycleRemover'; -import mxSwimlaneOrdering from './view/layout/layout/hierarchical/stage/mxSwimlaneOrdering'; +export { default as HierarchicalEdgeStyle } from './view/layout/layout/hierarchical/HierarchicalEdgeStyle'; +export { default as mxHierarchicalLayout } from './view/layout/layout/hierarchical/mxHierarchicalLayout'; +export { default as SwimlaneLayout } from './view/layout/layout/hierarchical/SwimlaneLayout'; -import mxCellCodec from './util/serialization/mxCellCodec'; -import mxChildChangeCodec from './util/serialization/mxChildChangeCodec'; -import mxCodec from './util/serialization/mxCodec'; -import mxCodecRegistry from './util/serialization/mxCodecRegistry'; -import mxDefaultKeyHandlerCodec from './util/serialization/mxDefaultKeyHandlerCodec'; -import mxDefaultPopupMenuCodec from './util/serialization/mxDefaultPopupMenuCodec'; -import mxDefaultToolbarCodec from './util/serialization/mxDefaultToolbarCodec'; -import mxEditorCodec from './util/serialization/mxEditorCodec'; -import mxGenericChangeCodec from './util/serialization/mxGenericChangeCodec'; -import mxGraphCodec from './util/serialization/mxGraphCodec'; -import mxGraphViewCodec from './util/serialization/mxGraphViewCodec'; -import mxModelCodec from './util/serialization/mxModelCodec'; -import mxObjectCodec from './util/serialization/mxObjectCodec'; -import mxRootChangeCodec from './util/serialization/mxRootChangeCodec'; -import mxStylesheetCodec from './util/serialization/mxStylesheetCodec'; -import mxTerminalChangeCodec from './util/serialization/mxTerminalChangeCodec'; +export { default as MxGraphAbstractHierarchyCell } from './view/layout/layout/hierarchical/model/GraphAbstractHierarchyCell'; +export { default as GraphHierarchyEdge } from './view/layout/layout/hierarchical/model/GraphHierarchyEdge'; +export { default as GraphHierarchyModel } from './view/layout/layout/hierarchical/model/GraphHierarchyModel'; +export { default as GraphHierarchyNode } from './view/layout/layout/hierarchical/model/GraphHierarchyNode'; +export { default as SwimlaneModel } from './view/layout/layout/hierarchical/model/SwimlaneModel'; -import Actor from './view/geometry/shape/Actor'; -import Label from './view/geometry/shape/node/LabelShape'; -import Shape from './view/geometry/shape/Shape'; -import SwimlaneShape from './view/geometry/shape/node/SwimlaneShape'; -import TextShape from './view/geometry/shape/node/TextShape'; -import TriangleShape from './view/geometry/shape/node/TriangleShape'; +export { default as CoordinateAssignment } from './view/layout/layout/hierarchical/stage/CoordinateAssignment'; +export { default as MxHierarchicalLayoutStage } from './view/layout/layout/hierarchical/stage/HierarchicalLayoutStage'; +export { default as MedianHybridCrossingReduction } from './view/layout/layout/hierarchical/stage/MedianHybridCrossingReduction'; +export { default as MinimumCycleRemover } from './view/layout/layout/hierarchical/stage/MinimumCycleRemover'; +export { default as mxSwimlaneOrdering } from './view/layout/layout/hierarchical/stage/mxSwimlaneOrdering'; -import Arrow from './view/geometry/shape/edge/Arrow'; -import ArrowConnector from './view/geometry/shape/edge/ArrowConnector'; -import Connector from './view/geometry/shape/edge/Connector'; -import Line from './view/geometry/shape/edge/Line'; -import Marker from './view/geometry/shape/edge/Marker'; -import Polyline from './view/geometry/shape/edge/Polyline'; +export { default as mxCellCodec } from './util/serialization/mxCellCodec'; +export { default as mxChildChangeCodec } from './util/serialization/mxChildChangeCodec'; +export { default as mxCodec } from './util/serialization/mxCodec'; +export { default as mxCodecRegistry } from './util/serialization/mxCodecRegistry'; +export { default as mxDefaultKeyHandlerCodec } from './util/serialization/mxDefaultKeyHandlerCodec'; +export { default as mxDefaultPopupMenuCodec } from './util/serialization/mxDefaultPopupMenuCodec'; +export { default as mxDefaultToolbarCodec } from './util/serialization/mxDefaultToolbarCodec'; +export { default as mxEditorCodec } from './util/serialization/mxEditorCodec'; +export { default as mxGenericChangeCodec } from './util/serialization/mxGenericChangeCodec'; +export { default as mxGraphCodec } from './util/serialization/mxGraphCodec'; +export { default as mxGraphViewCodec } from './util/serialization/mxGraphViewCodec'; +export { default as mxModelCodec } from './util/serialization/mxModelCodec'; +export { default as mxObjectCodec } from './util/serialization/mxObjectCodec'; +export { default as mxRootChangeCodec } from './util/serialization/mxRootChangeCodec'; +export { default as mxStylesheetCodec } from './util/serialization/mxStylesheetCodec'; +export { default as mxTerminalChangeCodec } from './util/serialization/mxTerminalChangeCodec'; -import CloudShape from './view/geometry/shape/node/CloudShape'; -import CylinderShape from './view/geometry/shape/node/CylinderShape'; -import DoubleEllipseShape from './view/geometry/shape/node/DoubleEllipseShape'; -import EllipseShape from './view/geometry/shape/node/EllipseShape'; -import HexagonShape from './view/geometry/shape/node/HexagonShape'; -import ImageShape from './view/geometry/shape/node/ImageShape'; -import RectangleShape from './view/geometry/shape/node/RectangleShape'; -import RhombusShape from './view/geometry/shape/node/RhombusShape'; -import StencilShape from './view/geometry/shape/node/StencilShape'; -import StencilShapeRegistry from './view/geometry/shape/node/StencilShapeRegistry'; +export { default as Actor } from './view/geometry/shape/Actor'; +export { default as Label } from './view/geometry/shape/node/LabelShape'; +export { default as Shape } from './view/geometry/shape/Shape'; +export { default as SwimlaneShape } from './view/geometry/shape/node/SwimlaneShape'; +export { default as TextShape } from './view/geometry/shape/node/TextShape'; +export { default as TriangleShape } from './view/geometry/shape/node/TriangleShape'; -import * as Constants from './util/Constants'; -import Guide from './util/Guide'; -import Resources from './util/Resources'; -import utils from './util/Utils'; -import * as CloneUtils from './util/CloneUtils'; -import * as DomUtils from './util/DomUtils'; -import * as EventUtils from './util/EventUtils'; -import * as GestureUtils from './util/GestureUtils'; -import * as StringUtils from './util/StringUtils'; -import * as XmlUtils from './util/XmlUtils'; +export { default as Arrow } from './view/geometry/shape/edge/Arrow'; +export { default as ArrowConnector } from './view/geometry/shape/edge/ArrowConnector'; +export { default as Connector } from './view/geometry/shape/edge/Connector'; +export { default as Line } from './view/geometry/shape/edge/Line'; +export { default as Marker } from './view/geometry/shape/edge/Marker'; +export { default as Polyline } from './view/geometry/shape/edge/Polyline'; -import mxAnimation from './util/animate/mxAnimation'; -import mxEffects from './util/animate/mxEffects'; -import mxMorphing from './util/animate/mxMorphing'; +export { default as CloudShape } from './view/geometry/shape/node/CloudShape'; +export { default as CylinderShape } from './view/geometry/shape/node/CylinderShape'; +export { default as DoubleEllipseShape } from './view/geometry/shape/node/DoubleEllipseShape'; +export { default as EllipseShape } from './view/geometry/shape/node/EllipseShape'; +export { default as HexagonShape } from './view/geometry/shape/node/HexagonShape'; +export { default as ImageShape } from './view/geometry/shape/node/ImageShape'; +export { default as RectangleShape } from './view/geometry/shape/node/RectangleShape'; +export { default as RhombusShape } from './view/geometry/shape/node/RhombusShape'; +export { default as StencilShape } from './view/geometry/shape/node/StencilShape'; +export { default as StencilShapeRegistry } from './view/geometry/shape/node/StencilShapeRegistry'; -import AbstractCanvas2D from './util/canvas/AbstractCanvas2D'; -import SvgCanvas2D from './util/canvas/SvgCanvas2D'; -import mxXmlCanvas2D from './util/canvas/mxXmlCanvas2D'; +export * as Constants from './util/Constants'; +export { default as Guide } from './util/Guide'; +export { default as Resources } from './util/Resources'; +export * as utils from './util/Utils'; +export * as CloneUtils from './util/CloneUtils'; +export * as DomUtils from './util/DomUtils'; +export * as EventUtils from './util/EventUtils'; +export * as GestureUtils from './util/GestureUtils'; +export * as StringUtils from './util/StringUtils'; +export * as XmlUtils from './util/XmlUtils'; -import Dictionary from './util/Dictionary'; -import Geometry from './view/geometry/Geometry'; -import ObjectIdentity from './util/ObjectIdentity'; -import Point from './view/geometry/Point'; -import Rectangle from './view/geometry/Rectangle'; +export { default as mxAnimation } from './util/animate/mxAnimation'; +export { default as mxEffects } from './util/animate/mxEffects'; +export { default as mxMorphing } from './util/animate/mxMorphing'; -import EdgeStyle from './view/style/EdgeStyle'; -import Perimeter from './view/style/Perimeter'; -import StyleRegistry from './view/style/StyleRegistry'; -import Stylesheet from './view/style/Stylesheet'; +export { default as AbstractCanvas2D } from './util/canvas/AbstractCanvas2D'; +export { default as SvgCanvas2D } from './util/canvas/SvgCanvas2D'; +export { default as mxXmlCanvas2D } from './util/canvas/mxXmlCanvas2D'; -import mxDivResizer from './util/dom/mxDivResizer'; -import * as mxDomHelpers from './util/dom/mxDomHelpers'; +export { default as Dictionary } from './util/Dictionary'; +export { default as Geometry } from './view/geometry/Geometry'; +export { default as ObjectIdentity } from './util/ObjectIdentity'; +export { default as Point } from './view/geometry/Point'; +export { default as Rectangle } from './view/geometry/Rectangle'; -import DragSource from './view/drag_drop/DragSource'; -import PanningManager from './view/panning/PanningManager'; +export { default as EdgeStyle } from './view/style/EdgeStyle'; +export { default as Perimeter } from './view/style/Perimeter'; +export { default as StyleRegistry } from './view/style/StyleRegistry'; +export { default as Stylesheet } from './view/style/Stylesheet'; -import InternalEvent from './view/event/InternalEvent'; -import EventObject from './view/event/EventObject'; -import EventSource from './view/event/EventSource'; -import InternalMouseEvent from './view/event/InternalMouseEvent'; +export { default as mxDivResizer } from './util/dom/mxDivResizer'; +export * as mxDomHelpers from './util/dom/mxDomHelpers'; -import mxForm from './util/gui/mxForm'; -import mxLog from './util/gui/mxLog'; -import PopupMenu from './util/gui/PopupMenu'; -import mxToolbar from './util/gui/mxToolbar'; -import mxWindow from './util/gui/mxWindow'; +export { default as DragSource } from './view/drag_drop/DragSource'; +export { default as PanningManager } from './view/panning/PanningManager'; -import ImageBox from './view/image/ImageBox'; -import ImageBundle from './view/image/ImageBundle'; -import ImageExport from './view/image/ImageExport'; +export { default as InternalEvent } from './view/event/InternalEvent'; +export { default as EventObject } from './view/event/EventObject'; +export { default as EventSource } from './view/event/EventSource'; +export { default as InternalMouseEvent } from './view/event/InternalMouseEvent'; -import mxUrlConverter from './util/network/mxUrlConverter'; -import mxXmlRequest from './util/network/mxXmlRequest'; +export { default as mxForm } from './util/gui/mxForm'; +export { default as mxLog } from './util/gui/mxLog'; +export { default as PopupMenu } from './util/gui/PopupMenu'; +export { default as mxToolbar } from './util/gui/mxToolbar'; +export { default as mxWindow } from './util/gui/mxWindow'; -import mxAutoSaveManager from './util/storage/mxAutoSaveManager'; -import Clipboard from './util/storage/Clipboard'; +export { default as ImageBox } from './view/image/ImageBox'; +export { default as ImageBundle } from './view/image/ImageBundle'; +export { default as ImageExport } from './view/image/ImageExport'; -import UndoableEdit from './view/model/UndoableEdit'; -import mxUndoManager from './util/mxUndoManager'; +export { default as mxUrlConverter } from './util/network/mxUrlConverter'; +export { default as mxXmlRequest } from './util/network/mxXmlRequest'; -import Cell from './view/cell/datatypes/Cell'; -import CellEditor from './view/editing/CellEditor'; -import CellOverlay from './view/cell/CellOverlay'; -import CellPath from './view/cell/datatypes/CellPath'; -import CellRenderer from './view/cell/CellRenderer'; -import CellState from './view/cell/datatypes/CellState'; -import CellStatePreview from './view/cell/CellStatePreview'; -import TemporaryCellStates from './view/cell/TemporaryCellStates'; +export { default as mxAutoSaveManager } from './util/storage/mxAutoSaveManager'; +export { default as Clipboard } from './util/storage/Clipboard'; -import ConnectionConstraint from './view/connection/ConnectionConstraint'; -import Multiplicity from './view/validation/Multiplicity'; +export { default as UndoableEdit } from './view/model/UndoableEdit'; +export { default as mxUndoManager } from './util/mxUndoManager'; -import Graph from './view/Graph'; -import Model from './view/model/Model'; -import GraphView from './view/view/GraphView'; -import LayoutManager from './view/layout/LayoutManager'; -import Outline from './view/Outline'; -import PrintPreview from './view/printing/PrintPreview'; -import SwimlaneManager from './view/layout/SwimlaneManager'; +export { default as Cell } from './view/cell/datatypes/Cell'; +export { default as CellEditor } from './view/editing/CellEditor'; +export { default as CellOverlay } from './view/cell/CellOverlay'; +export { default as CellPath } from './view/cell/datatypes/CellPath'; +export { default as CellRenderer } from './view/cell/CellRenderer'; +export { default as CellState } from './view/cell/datatypes/CellState'; +export { default as CellStatePreview } from './view/cell/CellStatePreview'; +export { default as TemporaryCellStates } from './view/cell/TemporaryCellStates'; +export { default as ConnectionConstraint } from './view/connection/ConnectionConstraint'; +export { default as Multiplicity } from './view/validation/Multiplicity'; import '../css/common.css'; - -export default { - mxClient, - mxLog, - ObjectIdentity, - Dictionary, - Resources, - Point, - Rectangle, - mxEffects, - utils, - Constants, - EventObject, - InternalMouseEvent, - EventSource, - InternalEvent, - mxXmlRequest, - Clipboard, - mxWindow, - mxForm, - Image, - mxDivResizer, - DragSource, - mxToolbar, - UndoableEdit, - mxUndoManager, - mxUrlConverter, - PanningManager, - PopupMenu, - mxAutoSaveManager, - mxAnimation, - mxMorphing, - ImageBox, - ImageBundle, - ImageExport, - AbstractCanvas2D, - mxXmlCanvas2D, - SvgCanvas2D, - Guide, - Shape, - StencilShape, - StencilShapeRegistry, - Marker, - Actor, - CloudShape, - RectangleShape, - EllipseShape, - DoubleEllipseShape, - RhombusShape, - Polyline, - Arrow, - ArrowConnector, - TextShape, - TriangleShape, - HexagonShape, - Line, - ImageShape, - Label, - CylinderShape, - Connector, - SwimlaneShape, - GraphLayout, - StackLayout, - PartitionLayout, - CompactTreeLayout, - RadialTreeLayout, - MxFastOrganicLayout, - CircleLayout, - ParallelEdgeLayout, - CompositeLayout, - EdgeLabelLayout, - MxGraphAbstractHierarchyCell, - GraphHierarchyNode, - GraphHierarchyEdge, - GraphHierarchyModel, - SwimlaneModel, - MxHierarchicalLayoutStage, - MedianHybridCrossingReduction, - MinimumCycleRemover, - CoordinateAssignment, - mxSwimlaneOrdering, - mxHierarchicalLayout, - SwimlaneLayout, - Model, - Cell, - Geometry, - CellPath, - Perimeter, - PrintPreview, - Stylesheet, - CellState, - CellEditor, - CellRenderer, - EdgeStyle, - StyleRegistry, - GraphView, - Graph, - CellOverlay, - Outline, - Multiplicity, - LayoutManager, - SwimlaneManager, - TemporaryCellStates, - CellStatePreview, - ConnectionConstraint, - GraphHandler, - PanningHandler, - PopupMenuHandler, - CellMarker, - SelectionCellsHandler, - ConnectionHandler, - ConstraintHandler, - RubberBand, - VertexHandle, - VertexHandler, - EdgeHandler, - ElbowEdgeHandler, - EdgeSegmentHandler, - mxKeyHandler, - TooltipHandler, - CellTracker, - CellHighlight, - mxDefaultKeyHandler, - mxDefaultPopupMenu, - mxDefaultToolbar, - mxEditor, - mxCodecRegistry, - mxCodec, - mxObjectCodec, - mxCellCodec, - mxModelCodec, - mxRootChangeCodec, - mxChildChangeCodec, - mxTerminalChangeCodec, - mxGenericChangeCodec, - // mxGraphCodec, - // mxGraphViewCodec, - // mxStylesheetCodec, - // mxDefaultKeyHandlerCodec, - // mxDefaultToolbarCodec, - // mxDefaultPopupMenuCodec, - // mxEditorCodec, - CloneUtils, - DomUtils, - EventUtils, - GestureUtils, - StringUtils, - XmlUtils, - mxDomHelpers, - CellAttributeChange, - ChildChange, - CollapseChange, - CurrentRootChange, - GeometryChange, - RootChange, - SelectionChange, - StyleChange, - TerminalChange, - ValueChange, - VisibleChange, -}; diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index cc82ae22f..961a0493f 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -3,7 +3,7 @@ import type CellState from './view/cell/datatypes/CellState'; import EventSource from './view/event/EventSource'; import type InternalMouseEvent from './view/event/InternalMouseEvent'; import type Shape from './view/geometry/shape/Shape'; -import type { MaxGraph } from './view/Graph'; +import type { Graph } from './view/Graph'; import type ImageBox from './view/image/ImageBox'; export type CellMap = { @@ -90,10 +90,12 @@ export type CellStateStyles = { labelBorderColor: ColorValue; labelPadding: number; labelPosition: AlignValue; + labelWidth: number; loop: Function; margin: number; movable: boolean; noEdgeStyle: boolean; + noLabel: boolean; opacity: number; orthogonal: boolean | null; overflow: OverflowValue; @@ -217,7 +219,7 @@ export type GradientMap = { }; export interface GraphPluginConstructor { - new (graph: MaxGraph): GraphPlugin; + new (graph: Graph): GraphPlugin; pluginId: string; } diff --git a/packages/core/src/util/Guide.ts b/packages/core/src/util/Guide.ts index cf95fdfaf..ad1a0f51f 100644 --- a/packages/core/src/util/Guide.ts +++ b/packages/core/src/util/Guide.ts @@ -11,7 +11,7 @@ import Polyline from '../view/geometry/shape/edge/Polyline'; import CellState from '../view/cell/datatypes/CellState'; import Shape from '../view/geometry/shape/Shape'; import Rectangle from '../view/geometry/Rectangle'; -import { MaxGraph } from '../view/Graph'; +import { Graph } from '../view/Graph'; import EventObject from '../view/event/EventObject'; import GraphView from '../view/view/GraphView'; import { ColorValue } from '../types'; @@ -26,7 +26,7 @@ import { ColorValue } from '../types'; * Constructs a new guide object. */ class Guide { - constructor(graph: MaxGraph, states: CellState[]) { + constructor(graph: Graph, states: CellState[]) { this.graph = graph; this.setStates(states); } @@ -36,7 +36,7 @@ class Guide { * * Reference to the enclosing instance. */ - graph: MaxGraph; + graph: Graph; /** * Variable: states diff --git a/packages/core/src/util/Utils.ts b/packages/core/src/util/Utils.ts index 37095b4e1..1e241b8e6 100644 --- a/packages/core/src/util/Utils.ts +++ b/packages/core/src/util/Utils.ts @@ -40,9 +40,9 @@ import CellState from '../view/cell/datatypes/CellState'; import Cell from '../view/cell/datatypes/Cell'; import Model from '../view/model/Model'; import CellArray from '../view/cell/datatypes/CellArray'; +import { Graph } from 'src/view/Graph'; import type { CellStateStyles, Properties, StyleValue } from '../types'; -import type { MaxGraph } from '../view/Graph'; /** * Class: mxUtils @@ -736,7 +736,7 @@ export const getPortConstraints = ( let rotation = 0; if (constraintRotationEnabled == 1) { - rotation = getValue(terminal.style, 'rotation', 0); + rotation = terminal.style.rotation ?? 0; } let quad = 0; @@ -2072,7 +2072,7 @@ export const getSizeForString = ( */ export const getScaleForPageCount = ( pageCount: number, - graph: MaxGraph, + graph: Graph, pageFormat?: Rectangle, border = 0 ) => { @@ -2209,7 +2209,7 @@ export const getScaleForPageCount = ( * h - Optional height of the graph view. */ export const show = ( - graph: MaxGraph, + graph: Graph, doc: Document, x0 = 0, y0 = 0, @@ -2325,7 +2325,7 @@ export const show = ( * * graph - to be printed. */ -export const printScreen = (graph: MaxGraph) => { +export const printScreen = (graph: Graph) => { const wnd = window.open(); if (!wnd) return; @@ -2353,52 +2353,17 @@ export const isNullish = (v: string | object | null | undefined | number) => export const isNotNullish = (v: string | object | null | undefined | number) => !isNullish(v); -export const copyPropertiesToPrototype = (source: any, sourceObj: any, target: any) => { - Object.getOwnPropertyNames(sourceObj).forEach((name) => { - try { - Object.defineProperty(target, name, { - ...(Object.getOwnPropertyDescriptor(source, name) || Object.create(null)), - value: sourceObj[name], +// Merge a mixin into the destination +export const mixInto = (dest: any) => (mixin: any) => { + const keys = Reflect.ownKeys(mixin); + try { + for (const key of keys) { + Object.defineProperty(dest.prototype, key, { + value: mixin[key], + writable: true, }); - } catch (e) { - console.error(e); } - }); + } catch (e) { + console.log('Error while mixing', e); + } }; - -export const copyMethodsToPrototype = (source: any, target: any) => { - Object.getOwnPropertyNames(source).forEach((name) => { - try { - if (name !== 'constructor') { - Object.defineProperty( - target, - name, - Object.getOwnPropertyDescriptor(source, name) || Object.create(null) - ); - } - } catch (e) { - console.error(e); - } - }); -}; - -// Mixins support -export const applyMixins = (derivedCtor: any, constructors: any[]) => { - constructors.forEach((baseCtor) => { - // Copy variables - copyPropertiesToPrototype(baseCtor.prototype, new baseCtor(), derivedCtor.prototype); - - // Copy methods - copyMethodsToPrototype(baseCtor.prototype, derivedCtor.prototype); - }); - - // Attach the derived prototype to each prototype. - constructors.forEach((baseCtor) => { - Object.setPrototypeOf(baseCtor.prototype, derivedCtor.prototype); - }); -}; - -// Creates a class using a type -export const autoImplement = (): new () => T => class {} as any; - -export default utils; diff --git a/packages/core/src/util/animate/mxEffects.js b/packages/core/src/util/animate/mxEffects.js index f7df8d473..28357be15 100644 --- a/packages/core/src/util/animate/mxEffects.js +++ b/packages/core/src/util/animate/mxEffects.js @@ -4,7 +4,7 @@ * Updated to ES9 syntax by David Morrissey 2021 * Type definitions from the typed-mxgraph project */ -import utils, { setOpacity } from '../Utils'; +import { setOpacity } from '../Utils'; import GeometryChange from '../../view/geometry/GeometryChange'; import TerminalChange from '../../view/cell/edge/TerminalChange'; import ValueChange from '../../view/cell/ValueChange'; @@ -56,17 +56,12 @@ class mxEffects { change instanceof ChildChange || change instanceof StyleChange ) { - const state = graph - .getView() - .getState(change.cell || change.child, false); + const state = graph.getView().getState(change.cell || change.child, false); if (state != null) { isRequired = true; - if ( - change.constructor !== GeometryChange || - change.cell.isEdge() - ) { + if (change.constructor !== GeometryChange || change.cell.isEdge()) { setOpacity(state.shape.node, (100 * step) / maxStep); } else { const { scale } = graph.getView(); @@ -74,10 +69,8 @@ class mxEffects { const dx = (change.geometry.x - change.previous.x) * scale; const dy = (change.geometry.y - change.previous.y) * scale; - const sx = - (change.geometry.width - change.previous.width) * scale; - const sy = - (change.geometry.height - change.previous.height) * scale; + const sx = (change.geometry.width - change.previous.width) * scale; + const sy = (change.geometry.height - change.previous.height) * scale; if (step === 0) { state.x -= dx; @@ -94,11 +87,7 @@ class mxEffects { graph.cellRenderer.redraw(state); // Fades all connected edges and children - mxEffects.cascadeOpacity( - graph, - change.cell, - (100 * step) / maxStep - ); + mxEffects.cascadeOpacity(graph, change.cell, (100 * step) / maxStep); } } } diff --git a/packages/core/src/util/canvas/SvgCanvas2D.ts b/packages/core/src/util/canvas/SvgCanvas2D.ts index c21221d46..420197603 100644 --- a/packages/core/src/util/canvas/SvgCanvas2D.ts +++ b/packages/core/src/util/canvas/SvgCanvas2D.ts @@ -972,7 +972,7 @@ class SvgCanvas2D extends AbstractCanvas2D { if (flipH ? !flipV : flipV) { theta *= -1; } - + console.log('theta', theta); if (theta !== 0) { s.transform += `rotate(${this.format(theta)},${this.format(cx)},${this.format( cy diff --git a/packages/core/src/util/gui/mxLog.js b/packages/core/src/util/gui/mxLog.js index 9c6ee0538..2af01e26e 100644 --- a/packages/core/src/util/gui/mxLog.js +++ b/packages/core/src/util/gui/mxLog.js @@ -8,7 +8,6 @@ import mxClient from '../../mxClient'; import InternalEvent from '../../view/event/InternalEvent'; import { getInnerHtml, write } from '../DomUtils'; -import utils from '../Utils'; import mxWindow, { popup } from './mxWindow'; /** @@ -146,10 +145,7 @@ class mxLog { const elt = mxLog.window.getElement(); const resizeHandler = (sender, evt) => { - mxLog.textarea.style.height = `${Math.max( - 0, - elt.offsetHeight - 70 - )}px`; + mxLog.textarea.style.height = `${Math.max(0, elt.offsetHeight - 70)}px`; }; mxLog.window.addListener(InternalEvent.RESIZE_END, resizeHandler); @@ -313,10 +309,7 @@ class mxLog { mxLog.textarea.value = mxLog.textarea.value + string; // Workaround for no update in Presto 2.5.22 (Opera 10.5) - if ( - navigator.userAgent != null && - navigator.userAgent.indexOf('Presto/2.5') >= 0 - ) { + if (navigator.userAgent != null && navigator.userAgent.indexOf('Presto/2.5') >= 0) { mxLog.textarea.style.visibility = 'hidden'; mxLog.textarea.style.visibility = 'visible'; } @@ -344,6 +337,6 @@ class mxLog { mxLog.write(`${string}\n`); } -}; +} export default mxLog; diff --git a/packages/core/src/util/gui/mxWindow.js b/packages/core/src/util/gui/mxWindow.js index c06d7315a..09b6c1da9 100644 --- a/packages/core/src/util/gui/mxWindow.js +++ b/packages/core/src/util/gui/mxWindow.js @@ -8,7 +8,7 @@ import Rectangle from '../../view/geometry/Rectangle'; import EventObject from '../../view/event/EventObject'; import EventSource from '../../view/event/EventSource'; -import utils, { fit, getCurrentStyle } from '../Utils'; +import { fit, getCurrentStyle } from '../Utils'; import InternalEvent from '../../view/event/InternalEvent'; import mxClient from '../../mxClient'; import { NODETYPE_TEXT } from '../Constants'; diff --git a/packages/core/src/util/serialization/mxEditorCodec.js b/packages/core/src/util/serialization/mxEditorCodec.js index 211c728ab..f56947e71 100644 --- a/packages/core/src/util/serialization/mxEditorCodec.js +++ b/packages/core/src/util/serialization/mxEditorCodec.js @@ -230,5 +230,5 @@ class mxEditorCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxEditorCodec()); +// mxCodecRegistry.register(new mxEditorCodec()); export default mxEditorCodec; diff --git a/packages/core/src/util/serialization/mxGraphCodec.js b/packages/core/src/util/serialization/mxGraphCodec.js index af4fe8301..6b706c645 100644 --- a/packages/core/src/util/serialization/mxGraphCodec.js +++ b/packages/core/src/util/serialization/mxGraphCodec.js @@ -40,5 +40,5 @@ class mxGraphCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxGraphCodec()); +// mxCodecRegistry.register(new mxGraphCodec()); export default mxGraphCodec; diff --git a/packages/core/src/util/serialization/mxGraphViewCodec.js b/packages/core/src/util/serialization/mxGraphViewCodec.js index 08180a53b..b5a910446 100644 --- a/packages/core/src/util/serialization/mxGraphViewCodec.js +++ b/packages/core/src/util/serialization/mxGraphViewCodec.js @@ -155,11 +155,7 @@ class mxGraphViewCodec extends mxObjectCodec { } for (let i = 0; i < childCount; i += 1) { - const childNode = this.encodeCell( - enc, - view, - cell.getChildAt(i) - ); + const childNode = this.encodeCell(enc, view, cell.getChildAt(i)); if (childNode != null) { node.appendChild(childNode); @@ -171,5 +167,5 @@ class mxGraphViewCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxGraphViewCodec()); +// mxCodecRegistry.register(new mxGraphViewCodec()); export default mxGraphViewCodec; diff --git a/packages/core/src/util/serialization/mxModelCodec.js b/packages/core/src/util/serialization/mxModelCodec.js index 7e446b94b..6e8d80ec9 100644 --- a/packages/core/src/util/serialization/mxModelCodec.js +++ b/packages/core/src/util/serialization/mxModelCodec.js @@ -74,5 +74,5 @@ class mxModelCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxModelCodec()); +// mxCodecRegistry.register(new mxModelCodec()); export default mxModelCodec; diff --git a/packages/core/src/util/serialization/mxRootChangeCodec.js b/packages/core/src/util/serialization/mxRootChangeCodec.js index 8e01db7b9..d16ce3e83 100644 --- a/packages/core/src/util/serialization/mxRootChangeCodec.js +++ b/packages/core/src/util/serialization/mxRootChangeCodec.js @@ -46,10 +46,7 @@ class mxRootChangeCodec extends mxObjectCodec { * using the respective decoder. */ beforeDecode(dec, node, obj) { - if ( - node.firstChild != null && - node.firstChild.nodeType === NODETYPE_ELEMENT - ) { + if (node.firstChild != null && node.firstChild.nodeType === NODETYPE_ELEMENT) { // Makes sure the original node isn't modified node = node.cloneNode(true); @@ -83,5 +80,5 @@ class mxRootChangeCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxRootChangeCodec()); +// mxCodecRegistry.register(new mxRootChangeCodec()); export default mxRootChangeCodec; diff --git a/packages/core/src/util/serialization/mxStylesheetCodec.js b/packages/core/src/util/serialization/mxStylesheetCodec.js index 4de161204..bc1ae1e3f 100644 --- a/packages/core/src/util/serialization/mxStylesheetCodec.js +++ b/packages/core/src/util/serialization/mxStylesheetCodec.js @@ -6,7 +6,7 @@ */ import Stylesheet from '../../view/style/Stylesheet'; -import utils, { isNumeric } from '../Utils'; +import { isNumeric } from '../Utils'; import mxCodecRegistry from './mxCodecRegistry'; import { NODETYPE_ELEMENT } from '../Constants'; import mxLog from '../gui/mxLog'; @@ -168,11 +168,7 @@ class mxStylesheetCodec extends mxObjectCodec { const text = getTextContent(entry); let value = null; - if ( - text != null && - text.length > 0 && - mxStylesheetCodec.allowEval - ) { + if (text != null && text.length > 0 && mxStylesheetCodec.allowEval) { value = eval(text); } else { value = entry.getAttribute('value'); @@ -204,5 +200,5 @@ class mxStylesheetCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxStylesheetCodec()); +// mxCodecRegistry.register(new mxStylesheetCodec()); export default mxStylesheetCodec; diff --git a/packages/core/src/util/serialization/mxTerminalChangeCodec.js b/packages/core/src/util/serialization/mxTerminalChangeCodec.js index fb1941dc5..a7c038ad4 100644 --- a/packages/core/src/util/serialization/mxTerminalChangeCodec.js +++ b/packages/core/src/util/serialization/mxTerminalChangeCodec.js @@ -43,5 +43,5 @@ class mxTerminalChangeCodec extends mxObjectCodec { } } -mxCodecRegistry.register(new mxTerminalChangeCodec()); +// mxCodecRegistry.register(new mxTerminalChangeCodec()); export default mxTerminalChangeCodec; diff --git a/packages/core/src/util/storage/Clipboard.ts b/packages/core/src/util/storage/Clipboard.ts index a93cc76c1..909e714d0 100644 --- a/packages/core/src/util/storage/Clipboard.ts +++ b/packages/core/src/util/storage/Clipboard.ts @@ -5,7 +5,7 @@ * Type definitions from the typed-mxgraph project */ -import { MaxGraph } from '../../view/Graph'; +import { Graph } from '../../view/Graph'; import CellArray from '../../view/cell/datatypes/CellArray'; /** @@ -126,7 +126,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be cut. * @param cells - Optional array of {@link mxCell} to be cut. */ - static cut(graph: MaxGraph, cells?: CellArray) { + static cut(graph: Graph, cells?: CellArray) { cells = Clipboard.copy(graph, cells); Clipboard.insertCount = 0; Clipboard.removeCells(graph, cells); @@ -141,7 +141,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be cut. * @param cells - Array of {@link mxCell} to be cut. */ - static removeCells(graph: MaxGraph, cells: CellArray) { + static removeCells(graph: Graph, cells: CellArray) { graph.removeCells(cells); } @@ -153,7 +153,7 @@ class Clipboard { * @param graph - {@link graph} that contains the cells to be copied. * @param cells - Optional array of {@link mxCell} to be copied. */ - static copy(graph: MaxGraph, cells?: CellArray) { + static copy(graph: Graph, cells?: CellArray) { cells = cells || graph.getSelectionCells(); const result = graph.getExportableCells(cells).getTopmostCells(); Clipboard.insertCount = 1; @@ -173,7 +173,7 @@ class Clipboard { * * @param graph - {@link graph} to paste the {@link cells} into. */ - static paste(graph: MaxGraph) { + static paste(graph: Graph) { let cells = null; if (!Clipboard.isEmpty() && Clipboard.getCells()) { diff --git a/packages/core/src/view/Graph.ts b/packages/core/src/view/Graph.ts index 52d8efdce..9b4ac2402 100644 --- a/packages/core/src/view/Graph.ts +++ b/packages/core/src/view/Graph.ts @@ -21,15 +21,7 @@ import GraphView from './view/GraphView'; import CellRenderer from './cell/CellRenderer'; import CellEditor from './editing/CellEditor'; import Point from './geometry/Point'; -import { - applyMixins, - autoImplement, - copyMethodsToPrototype, - copyPropertiesToPrototype, - getCurrentStyle, - hasScrollbars, - parseCssNumber, -} from '../util/Utils'; +import { getCurrentStyle, hasScrollbars, parseCssNumber } from '../util/Utils'; import Cell from './cell/datatypes/Cell'; import Model from './model/Model'; import Stylesheet from './style/Stylesheet'; @@ -43,7 +35,6 @@ import TerminalChange from './cell/edge/TerminalChange'; import ValueChange from './cell/ValueChange'; import CellState from './cell/datatypes/CellState'; import { isNode } from '../util/DomUtils'; -import CellArray from './cell/datatypes/CellArray'; import EdgeStyle from './style/EdgeStyle'; import EdgeHandler from './cell/edge/EdgeHandler'; import VertexHandler from './cell/vertex/VertexHandler'; @@ -52,185 +43,6 @@ import ElbowEdgeHandler from './cell/edge/ElbowEdgeHandler'; import Dictionary from '../util/Dictionary'; import type { GraphPlugin, GraphPluginConstructor } from '../types'; -import GraphPorts from './ports/GraphPorts'; -import GraphPanning from './panning/GraphPanning'; -import GraphZoom from './zoom/GraphZoom'; -import GraphEvents from './event/GraphEvents'; -import GraphImage from './image/GraphImage'; -import GraphCells from './cell/GraphCells'; -import GraphSelection from './selection/GraphSelection'; -import GraphConnections from './connection/GraphConnections'; -import GraphEdge from './cell/edge/GraphEdge'; -import GraphVertex from './cell/vertex/GraphVertex'; -import GraphOverlays from './layout/GraphOverlays'; -import GraphEditing from './editing/GraphEditing'; -import GraphFolding from './folding/GraphFolding'; -import GraphLabel from './label/GraphLabel'; -import GraphValidation from './validation/GraphValidation'; -import GraphSnap from './snap/GraphSnap'; -import GraphTooltip from './tooltip/GraphTooltip'; -import GraphTerminal from './terminal/GraphTerminal'; -import GraphDragDrop from './drag_drop/GraphDragDrop'; -import GraphSwimlane from './swimlane/GraphSwimlane'; -import GraphPageBreaks from './page_breaks/GraphPageBreaks'; - -type PartialEvents = Pick< - GraphEvents, - | 'sizeDidChange' - | 'isNativeDblClickEnabled' - | 'dblClick' - | 'fireMouseEvent' - | 'isMouseDown' - | 'fireGestureEvent' - | 'addMouseListener' - | 'removeMouseListener' - | 'isGridEnabledEvent' - | 'isIgnoreTerminalEvent' - | 'isCloneEvent' - | 'isToggleEvent' - | 'getEventTolerance' - | 'isInvokesStopCellEditing' - | 'getPointForEvent' - | 'isConstrainedEvent' - | 'isMouseTrigger' - | 'isEnterStopsCellEditing' - | 'getCursorForMouseEvent' ->; -type PartialSelection = Pick< - GraphSelection, - | 'clearSelection' - | 'isCellSelected' - | 'getSelectionCount' - | 'selectCellForEvent' - | 'setSelectionCell' - | 'getSelectionCells' - | 'updateSelection' - | 'selectRegion' - | 'cellAdded' - | 'cellRemoved' - | 'getUpdatingSelectionResource' - | 'getDoneResource' - | 'isSiblingSelected' - | 'setSelectionCells' ->; -type PartialCells = Pick< - GraphCells, - | 'removeStateForCell' - | 'getCellStyle' - | 'getCellAt' - | 'isCellBendable' - | 'isCellsCloneable' - | 'cloneCell' - | 'setCellStyles' - | 'isCellMovable' - | 'isCellResizable' - | 'getChildCells' - | 'isCellRotatable' - | 'getCellContainmentArea' - | 'getCurrentCellStyle' - | 'resizeCell' - | 'removeStateForCell' - | 'getMovableCells' - | 'getCloneableCells' - | 'isCellLocked' - | 'moveCells' - | 'removeCells' - | 'isCellDeletable' - | 'addCell' - | 'getExportableCells' - | 'cloneCells' - | 'importCells' - | 'getImportableCells' ->; -type PartialConnections = Pick< - GraphConnections, - | 'getConnectionConstraint' - | 'setConnectionConstraint' - | 'getConnectionPoint' - | 'isCellDisconnectable' - | 'getOutlineConstraint' - | 'connectCell' - | 'getConnections' - | 'isConstrainChild' - | 'isValidSource' - | 'getAllConnectionConstraints' ->; -type PartialEditing = Pick< - GraphEditing, - 'isEditing' | 'stopEditing' | 'labelChanged' | 'getEditingValue' ->; -type PartialTooltip = Pick; -type PartialValidation = Pick< - GraphValidation, - 'getEdgeValidationError' | 'validationAlert' | 'isEdgeValid' ->; -type PartialLabel = Pick< - GraphLabel, - 'isLabelMovable' | 'isHtmlLabel' | 'isWrapping' | 'isLabelClipped' | 'getLabel' ->; -type PartialTerminal = Pick; -type PartialSnap = Pick< - GraphSnap, - 'snap' | 'getGridSize' | 'isGridEnabled' | 'getSnapTolerance' | 'snapDelta' ->; -type PartialEdge = Pick< - GraphEdge, - | 'isAllowDanglingEdges' - | 'isResetEdgesOnConnect' - | 'getEdges' - | 'insertEdge' - | 'addEdge' - | 'splitEdge' - | 'flipEdge' ->; -type PartialOverlays = Pick; -type PartialFolding = Pick< - GraphFolding, - 'getFoldingImage' | 'isFoldingEnabled' | 'foldCells' ->; -type PartialPanning = Pick< - GraphPanning, - | 'panGraph' - | 'isUseScrollbarsForPanning' - | 'getPanDx' - | 'setPanDx' - | 'getPanDy' - | 'setPanDy' - | 'isTimerAutoScroll' - | 'isAllowAutoPanning' - | 'scrollCellToVisible' ->; -type PartialZoom = Pick; -type PartialDragDrop = Pick< - GraphDragDrop, - 'isDropEnabled' | 'isAutoScroll' | 'isAutoExtend' | 'isSplitEnabled' | 'isSplitTarget' ->; -type PartialSwimlane = Pick; -type PartialPorts = Pick< - GraphPorts, - 'isPort' | 'getTerminalForPort' | 'isPortsEnabled' | 'setPortsEnabled' ->; -type PartialClass = PartialEvents & - PartialSelection & - PartialCells & - PartialConnections & - PartialEditing & - PartialTooltip & - PartialValidation & - PartialLabel & - PartialTerminal & - PartialSnap & - PartialEdge & - PartialOverlays & - PartialFolding & - PartialPanning & - PartialZoom & - PartialDragDrop & - PartialSwimlane & - PartialPorts & - EventSource; - -export type MaxGraph = Graph & PartialClass; const defaultPlugins: GraphPluginConstructor[] = [ CellEditor, @@ -259,8 +71,7 @@ const defaultPlugins: GraphPluginConstructor[] = [ * @class graph * @extends {EventSource} */ -// @ts-ignore recursive reference error -class Graph extends autoImplement() { +class Graph extends EventSource { constructor( container: HTMLElement, model?: Model, @@ -291,7 +102,7 @@ class Graph extends autoImplement() { // Initiailzes plugins this.plugins.forEach((p: GraphPluginConstructor) => { - this.pluginsMap.put(p.pluginId, new p(this)); + this.pluginsMap[p.pluginId] = new p(this); }); this.view.revalidate(); @@ -303,7 +114,7 @@ class Graph extends autoImplement() { destroyed: boolean = false; - getPlugin = (id: string) => this.pluginsMap.get(id) as unknown; + getPlugin = (id: string) => this.pluginsMap[id] as unknown; graphModelChangeListener: Function | null = null; paintBackground: Function | null = null; @@ -318,7 +129,7 @@ class Graph extends autoImplement() { model: Model; plugins: GraphPluginConstructor[]; - pluginsMap: Dictionary = new Dictionary(); + pluginsMap: Record = {}; /** * Holds the {@link GraphView} that caches the {@link CellState}s for the cells. @@ -658,7 +469,6 @@ class Graph extends autoImplement() { // TODO: Document me!! batchUpdate(fn: Function) { - console.log(this.getModel, this.getModel()); this.getModel().beginUpdate(); try { fn(); @@ -1658,31 +1468,4 @@ class Graph extends autoImplement() { } } -applyMixins(Graph, [ - GraphCells, - GraphConnections, - GraphDragDrop, - GraphEdge, - GraphEditing, - GraphEvents, - GraphFolding, - GraphImage, - GraphLabel, - GraphOverlays, - GraphPageBreaks, - GraphPanning, - GraphPorts, - GraphSelection, - GraphSnap, - GraphSwimlane, - GraphTerminal, - GraphTooltip, - GraphValidation, - GraphVertex, - GraphZoom, -]); - -copyPropertiesToPrototype(EventSource.prototype, new EventSource(), Graph.prototype); -copyMethodsToPrototype(EventSource.prototype, Graph.prototype); - -export default Graph; +export { Graph }; diff --git a/packages/core/src/view/GraphHandler.ts b/packages/core/src/view/GraphHandler.ts index 4d8cb027b..26cda3341 100644 --- a/packages/core/src/view/GraphHandler.ts +++ b/packages/core/src/view/GraphHandler.ts @@ -25,7 +25,7 @@ import Dictionary from '../util/Dictionary'; import CellHighlight from './selection/CellHighlight'; import Rectangle from './geometry/Rectangle'; import { getClientX, getClientY, isAltDown, isMultiTouchEvent } from '../util/EventUtils'; -import { MaxGraph } from './Graph'; +import { Graph } from './Graph'; import Guide from '../util/Guide'; import Shape from './geometry/shape/Shape'; import InternalMouseEvent from './event/InternalMouseEvent'; @@ -63,7 +63,7 @@ import ConnectionHandler from './connection/ConnectionHandler'; class GraphHandler implements GraphPlugin { static pluginId = 'GraphHandler'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.graph = graph; this.graph.addMouseListener(this); @@ -166,7 +166,7 @@ class GraphHandler implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; panHandler: () => void; escapeHandler: (sender: EventSource, evt: EventObject) => void; diff --git a/packages/core/src/view/Outline.ts b/packages/core/src/view/Outline.ts index 49eb4cda1..17182769a 100644 --- a/packages/core/src/view/Outline.ts +++ b/packages/core/src/view/Outline.ts @@ -15,14 +15,14 @@ import { import Point from './geometry/Point'; import Rectangle from './geometry/Rectangle'; import RectangleShape from './geometry/shape/node/RectangleShape'; -import graph, { MaxGraph } from './Graph'; +import { Graph } from './Graph'; import ImageShape from './geometry/shape/node/ImageShape'; import InternalEvent from './event/InternalEvent'; -import utils from '../util/Utils'; import Image from './image/ImageBox'; import EventObject from './event/EventObject'; import { getSource, isMouseEvent } from '../util/EventUtils'; import EventSource from './event/EventSource'; +import { hasScrollbars } from '../util/Utils'; /** * @class Outline @@ -71,7 +71,7 @@ import EventSource from './event/EventSource'; * ``` */ class Outline { - constructor(source: MaxGraph, container: HTMLElement | null = null) { + constructor(source: Graph, container: HTMLElement | null = null) { this.source = source; if (container != null) { @@ -132,7 +132,7 @@ class Outline { // Refreshes the graph in the outline after a refresh of the main graph this.refreshHandler = (sender: any) => { - const outline = this.outline; + const outline = this.outline; outline.setStylesheet(this.source.getStylesheet()); outline.refresh(); }; @@ -154,21 +154,21 @@ class Outline { // complete gesture on the event target. This is needed because all the events // are routed via the initial element even if that element is removed from the // DOM, which happens when we repaint the selection border and zoom handles. - const handler = (evt: Event) => { + const handler = (evt: MouseEvent) => { const t = getSource(evt); const redirect = (evt: Event) => { - const outline = this.outline; + const outline = this.outline; outline.fireMouseEvent(InternalEvent.MOUSE_MOVE, new InternalMouseEvent(evt)); }; var redirect2 = (evt: Event) => { - const outline = this.outline; + const outline = this.outline; InternalEvent.removeGestureListeners(t, null, redirect, redirect2); outline.fireMouseEvent(InternalEvent.MOUSE_UP, new InternalMouseEvent(evt)); }; - const outline = this.outline; + const outline = this.outline; InternalEvent.addGestureListeners(t, null, redirect, redirect2); outline.fireMouseEvent(InternalEvent.MOUSE_DOWN, new InternalMouseEvent(evt)); }; @@ -224,12 +224,12 @@ class Outline { /** * Reference to the source {@link graph}. */ - source: MaxGraph; + source: Graph; /** * Reference to the {@link graph} that renders the outline. */ - outline: graph | null = null; + outline: Graph | null = null; /** * Renderhint to be used for the outline graph. @@ -308,8 +308,8 @@ class Outline { /** * Creates the {@link graph} used in the outline. */ - createGraph(container: HTMLElement): graph { - const graph = new graph( + createGraph(container: HTMLElement): Graph { + const graph = new Graph( container, this.source.getModel(), this.graphRenderHint, @@ -361,7 +361,7 @@ class Outline { */ // createSizer(): mxShape; createSizer(): RectangleShape { - const outline = this.outline; + const outline = this.outline; if (this.sizerImage != null) { const sizer = new ImageShape( new Rectangle(0, 0, this.sizerImage.width, this.sizerImage.height), @@ -599,8 +599,8 @@ class Outline { const sizerNode = sizer.node; const selectionBorder = this.selectionBorder; const selectionBorderNode = selectionBorder.node; - const source = this.source; - const outline = this.outline; + const source = this.source; + const outline = this.outline; selectionBorderNode.style.display = this.showViewport ? '' : 'none'; sizerNode.style.display = selectionBorderNode.style.display; @@ -628,7 +628,7 @@ class Outline { source.panGraph(-dx - this.dx0, -dy - this.dy0); } else { // Does *not* preview zooming on the source graph - const { container } = this.source; + const { container } = this.source; // @ts-ignore const viewRatio = container.clientWidth / container.clientHeight; dy = dx / viewRatio; @@ -692,8 +692,8 @@ class Outline { const delta = this.getTranslateForEvent(me); let dx = delta.x; let dy = delta.y; - const source = this.source; - const outline = this.outline; + const source = this.source; + const outline = this.outline; const selectionBorder = this.selectionBorder; if (Math.abs(dx) > 0 || Math.abs(dy) > 0) { diff --git a/packages/core/src/view/cell/CellMarker.ts b/packages/core/src/view/cell/CellMarker.ts index 036c4d121..fe87ec2fb 100644 --- a/packages/core/src/view/cell/CellMarker.ts +++ b/packages/core/src/view/cell/CellMarker.ts @@ -16,8 +16,8 @@ import { import CellHighlight from '../selection/CellHighlight'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; -import utils, { intersectsHotspot, isNumeric } from '../../util/Utils'; -import { MaxGraph } from '../Graph'; +import { intersectsHotspot, isNumeric } from '../../util/Utils'; +import { Graph } from '../Graph'; import { ColorValue } from '../../types'; import CellState from './datatypes/CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; @@ -65,7 +65,7 @@ import Cell from './datatypes/Cell'; */ class CellMarker extends EventSource { constructor( - graph: MaxGraph, + graph: Graph, validColor: ColorValue = DEFAULT_VALID_COLOR, invalidColor: ColorValue = DEFAULT_INVALID_COLOR, hotspot: number = DEFAULT_HOTSPOT @@ -84,7 +84,7 @@ class CellMarker extends EventSource { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: enabled diff --git a/packages/core/src/view/cell/CellRenderer.ts b/packages/core/src/view/cell/CellRenderer.ts index b924b99b4..8dad34c2b 100644 --- a/packages/core/src/view/cell/CellRenderer.ts +++ b/packages/core/src/view/cell/CellRenderer.ts @@ -47,7 +47,7 @@ import { SHAPE_SWIMLANE, SHAPE_TRIANGLE, } from '../../util/Constants'; -import utils, { +import { convertPoint, equalEntries, equalPoints, @@ -67,12 +67,12 @@ import Point from '../geometry/Point'; import Shape from '../geometry/shape/Shape'; import CellState from './datatypes/CellState'; import Cell from './datatypes/Cell'; -import Model from '../model/Model'; import CellOverlay from './CellOverlay'; import { getClientX, getClientY, getSource } from '../../util/EventUtils'; import { isNode } from '../../util/DomUtils'; import { CellStateStyles } from '../../types'; import CellArray from './datatypes/CellArray'; +import SelectionCellsHandler from '../selection/SelectionCellsHandler'; /** * Class: mxCellRenderer @@ -982,7 +982,7 @@ class CellRenderer { !state.text.bounds.equals(bounds) ) { state.text.dialect = dialect; - state.text.value = value; + state.text.value = value as string; state.text.bounds = bounds; state.text.scale = nextScale; state.text.wrap = wrapping; @@ -1135,8 +1135,8 @@ class CellRenderer { // Shape can modify its label bounds if (state.shape != null) { - const hpos = getValue(state.style, 'labelPosition', ALIGN_CENTER); - const vpos = getValue(state.style, 'verticalLabelPosition', ALIGN_MIDDLE); + const hpos = state.style.labelPosition ?? ALIGN_CENTER; + const vpos = state.style.verticalLabelPosition ?? ALIGN_MIDDLE; if (hpos === ALIGN_CENTER && vpos === ALIGN_MIDDLE) { bounds = state.shape.getLabelBounds(bounds); @@ -1144,10 +1144,10 @@ class CellRenderer { } // Label width style overrides actual label width - const lw = getValue(state.style, 'labelWidth', null); + const lw = state.style.labelWidth ?? null; if (lw != null) { - bounds.width = parseFloat(lw) * scale; + bounds.width = lw * scale; } if (!isEdge) { this.rotateLabelBounds(state, bounds); @@ -1304,16 +1304,14 @@ class CellRenderer { const bounds = this.getControlBounds(state, image.width, image.height); const r = this.legacyControlPosition - ? getValue(state.style, 'rotation', 0) - : // @ts-ignore - state.shape.getTextRotation(); + ? state.style.rotation ?? 0 + : state.shape!.getTextRotation(); const s = state.view.scale; if ( forced || state.control.scale !== s || - // @ts-ignore - !state.control.bounds.equals(bounds) || + !state.control.bounds!.equals(bounds) || state.control.rotation !== r ) { state.control.rotation = r; @@ -1556,8 +1554,10 @@ class CellRenderer { this.installListeners(state); // Forces a refresh of the handler if one exists - // @ts-ignore - state.view.graph.selectionCellsHandler.updateHandler(state); + const selectionCellsHandler = state.view.graph.getPlugin( + 'SelectionCellsHandler' + ) as SelectionCellsHandler; + selectionCellsHandler.updateHandler(state); } } else if ( !force && @@ -1568,8 +1568,10 @@ class CellRenderer { state.shape.resetStyles(); this.configureShape(state); // LATER: Ignore update for realtime to fix reset of current gesture - // @ts-ignore - state.view.graph.selectionCellsHandler.updateHandler(state); + const selectionCellsHandler = state.view.graph.getPlugin( + 'SelectionCellsHandler' + ) as SelectionCellsHandler; + selectionCellsHandler.updateHandler(state); force = true; } diff --git a/packages/core/src/view/cell/GraphCells.ts b/packages/core/src/view/cell/GraphCellsMixin.ts similarity index 83% rename from packages/core/src/view/cell/GraphCells.ts rename to packages/core/src/view/cell/GraphCellsMixin.ts index de94f5c66..4e359b998 100644 --- a/packages/core/src/view/cell/GraphCells.ts +++ b/packages/core/src/view/cell/GraphCellsMixin.ts @@ -1,14 +1,13 @@ import Cell from './datatypes/Cell'; -import StyleMap from '../style/StyleMap'; import CellArray from './datatypes/CellArray'; import { - autoImplement, contains, getBoundingBox, getRotatedPoint, getSizeForString, getValue, intersects, + mixInto, ptSegDistSq, setCellStyleFlags, setCellStyles, @@ -31,21 +30,230 @@ import Rectangle from '../geometry/Rectangle'; import Dictionary from '../../util/Dictionary'; import Point from '../geometry/Point'; import { htmlEntities } from '../../util/StringUtils'; -import InternalMouseEvent from '../event/InternalMouseEvent'; import CellState from './datatypes/CellState'; - -import type Graph from '../Graph'; -import type GraphImage from '../image/GraphImage'; -import type GraphSelection from '../selection/GraphSelection'; -import type GraphEdge from './edge/GraphEdge'; -import type GraphConnections from '../connection/GraphConnections'; -import type GraphValidation from '../validation/GraphValidation'; -import type GraphFolding from '../folding/GraphFolding'; -import type GraphLabel from '../label/GraphLabel'; -import type GraphSnap from '../snap/GraphSnap'; +import { Graph } from '../Graph'; import type { CellStateStyles } from '../../types'; -import GraphVertex from './vertex/GraphVertex'; + +declare module '../Graph' { + interface Graph { + cellsResizable: boolean; + cellsBendable: boolean; + cellsSelectable: boolean; + cellsDisconnectable: boolean; + autoSizeCells: boolean; + autoSizeCellsOnAdd: boolean; + cellsLocked: boolean; + cellsCloneable: boolean; + cellsDeletable: boolean; + cellsMovable: boolean; + extendParents: boolean; + extendParentsOnAdd: boolean; + extendParentsOnMove: boolean; + + getBoundingBox: (cells: CellArray) => Rectangle | null; + removeStateForCell: (cell: Cell) => void; + getCurrentCellStyle: (cell: Cell, ignoreState?: boolean) => CellStateStyles; + getCellStyle: (cell: Cell) => CellStateStyles; + postProcessCellStyle: (style: CellStateStyles) => CellStateStyles; + setCellStyle: (style: keyof CellStateStyles, cells: CellArray) => void; + toggleCellStyle: ( + key: keyof CellStateStyles, + defaultValue: boolean, + cell: Cell + ) => boolean | null; + toggleCellStyles: ( + key: keyof CellStateStyles, + defaultValue: boolean, + cells: CellArray + ) => boolean | null; + setCellStyles: ( + key: keyof CellStateStyles, + value: CellStateStyles[keyof CellStateStyles], + cells: CellArray + ) => void; + toggleCellStyleFlags: ( + key: keyof CellStateStyles, + flag: number, + cells: CellArray + ) => void; + setCellStyleFlags: ( + key: keyof CellStateStyles, + flag: number, + value: boolean | null, + cells: CellArray + ) => void; + alignCells: (align: string, cells: CellArray, param: number | null) => void; + cloneCell: ( + cell: Cell, + allowInvalidEdges?: boolean, + mapping?: any, + keepPosition?: boolean + ) => Cell; + cloneCells: ( + cells: CellArray, + allowInvalidEdges: boolean, + mapping: any, + keepPosition?: boolean + ) => CellArray; + addCell: ( + cell: Cell, + parent: Cell | null, + index?: number | null, + source?: Cell | null, + target?: Cell | null + ) => Cell; + addCells: ( + cells: CellArray, + parent: Cell | null, + index: number | null, + source: Cell | null, + target: Cell | null, + absolute?: boolean + ) => CellArray; + cellsAdded: ( + cells: CellArray, + parent: Cell, + index: number, + source: Cell | null, + target: Cell | null, + absolute: boolean, + constrain?: boolean, + extend?: boolean + ) => void; + autoSizeCell: (cell: Cell, recurse?: boolean) => void; + removeCells: (cells: CellArray | null, includeEdges: boolean) => CellArray; + cellsRemoved: (cells: CellArray) => void; + toggleCells: (show: boolean, cells: CellArray, includeEdges: boolean) => CellArray; + cellsToggled: (cells: CellArray, show: boolean) => void; + updateCellSize: (cell: Cell, ignoreChildren?: boolean) => Cell; + cellSizeUpdated: (cell: Cell, ignoreChildren: boolean) => void; + getPreferredSizeForCell: (cell: Cell, textWidth?: number | null) => Rectangle | null; + resizeCell: (cell: Cell, bounds: Rectangle, recurse?: boolean) => Cell; + resizeCells: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => CellArray; + cellsResized: (cells: CellArray, bounds: Rectangle[], recurse: boolean) => void; + cellResized: ( + cell: Cell, + bounds: Rectangle, + ignoreRelative: boolean, + recurse: boolean + ) => Geometry | null; + resizeChildCells: (cell: Cell, newGeo: Geometry) => void; + constrainChildCells: (cell: Cell) => void; + scaleCell: (cell: Cell, dx: number, dy: number, recurse: boolean) => void; + extendParent: (cell: Cell) => void; + importCells: ( + cells: CellArray, + dx: number, + dy: number, + target: Cell | null, + evt: MouseEvent | null, + mapping: any + ) => CellArray; + moveCells: ( + cells: CellArray, + dx: number, + dy: number, + clone?: boolean, + target?: Cell | null, + evt?: MouseEvent | null, + mapping?: any + ) => CellArray; + cellsMoved: ( + cells: CellArray, + dx: number, + dy: number, + disconnect: boolean, + constrain: boolean, + extend?: boolean + ) => void; + translateCell: (cell: Cell, dx: number, dy: number) => void; + getCellContainmentArea: (cell: Cell) => Rectangle | null; + constrainChild: (cell: Cell, sizeFirst?: boolean) => void; + getChildCells: ( + parent: Cell | null, + vertices?: boolean, + edges?: boolean + ) => CellArray; + getCellAt: ( + x: number, + y: number, + parent?: Cell | null, + vertices?: boolean, + edges?: boolean, + ignoreFn?: Function | null + ) => Cell | null; + getCells: ( + x: number, + y: number, + width: number, + height: number, + parent?: Cell | null, + result?: CellArray, + intersection?: Rectangle | null, + ignoreFn?: Function | null, + includeDescendants?: boolean + ) => CellArray; + getCellsBeyond: ( + x0: number, + y0: number, + parent: Cell | null, + rightHalfpane: boolean, + bottomHalfpane: boolean + ) => CellArray; + intersects: (state: CellState, x: number, y: number) => boolean; + isValidAncestor: (cell: Cell, parent: Cell, recurse: boolean) => boolean; + isCellLocked: (cell: Cell) => boolean; + isCellsLocked: () => boolean; + setCellsLocked: (value: boolean) => void; + getCloneableCells: (cells: CellArray) => CellArray; + isCellCloneable: (cell: Cell) => boolean; + isCellsCloneable: () => boolean; + setCellsCloneable: (value: boolean) => void; + getExportableCells: (cells: CellArray) => CellArray; + canExportCell: (cell: Cell | null) => boolean; + getImportableCells: (cells: CellArray) => CellArray; + canImportCell: (cell: Cell | null) => boolean; + isCellSelectable: (cell: Cell) => boolean; + isCellsSelectable: () => boolean; + setCellsSelectable: (value: boolean) => void; + getDeletableCells: (cells: CellArray) => CellArray; + isCellDeletable: (cell: Cell) => boolean; + isCellsDeletable: () => boolean; + setCellsDeletable: (value: boolean) => void; + isCellRotatable: (cell: Cell) => boolean; + getMovableCells: (cells: CellArray) => CellArray; + isCellMovable: (cell: Cell) => boolean; + isCellsMovable: () => boolean; + setCellsMovable: (value: boolean) => void; + isCellResizable: (cell: Cell) => boolean; + isCellsResizable: () => boolean; + setCellsResizable: (value: boolean) => void; + isCellBendable: (cell: Cell) => boolean; + isCellsBendable: () => boolean; + setCellsBendable: (value: boolean) => void; + isAutoSizeCell: (cell: Cell) => boolean; + isAutoSizeCells: () => boolean; + setAutoSizeCells: (value: boolean) => void; + isExtendParent: (cell: Cell) => boolean; + isExtendParents: () => boolean; + setExtendParents: (value: boolean) => void; + isExtendParentsOnAdd: (cell: Cell) => boolean; + setExtendParentsOnAdd: (value: boolean) => void; + isExtendParentsOnMove: () => boolean; + setExtendParentsOnMove: (value: boolean) => void; + getCursorForCell: (cell: Cell) => string | null; + getCellBounds: ( + cell: Cell, + includeEdges: boolean, + includeDescendants: boolean + ) => Rectangle | null; + getBoundingBoxFromGeometry: ( + cells: CellArray, + includeEdges: boolean + ) => Rectangle | null; + } +} type PartialGraph = Pick< Graph, @@ -62,11 +270,9 @@ type PartialGraph = Pick< | 'getMaximumGraphBounds' | 'isExportEnabled' | 'isImportEnabled' ->; -type PartialImage = Pick; -type PartialSelection = Pick; -type PartialEdge = Pick< - GraphEdge, + | 'getImageFromBundles' + | 'getSelectionCells' + | 'getSelectionCell' | 'addAllEdges' | 'getAllEdges' | 'isCloneInvalidEdges' @@ -74,120 +280,210 @@ type PartialEdge = Pick< | 'resetEdges' | 'isResetEdgesOnResize' | 'isResetEdgesOnMove' ->; -type PartialConnections = Pick< - GraphConnections, | 'isConstrainChild' | 'cellConnected' | 'isDisconnectOnMove' | 'isConstrainRelativeChildren' | 'disconnectGraph' + | 'getEdgeValidationError' + | 'getFoldingImage' + | 'isHtmlLabel' + | 'isGridEnabled' + | 'snap' + | 'getGridSize' + | 'isAllowNegativeCoordinates' + | 'setAllowNegativeCoordinates' + | 'getEventTolerance' >; -type PartialValidation = Pick; -type PartialFolding = Pick; -type PartialLabel = Pick; -type PartialSnap = Pick< - GraphSnap, - 'isGridEnabled' | 'snap' | 'getGridSize' | 'getTolerance' ->; -type PartialVertex = Pick< - GraphVertex, - 'isAllowNegativeCoordinates' | 'setAllowNegativeCoordinates' ->; -type PartialClass = PartialGraph & - PartialImage & - PartialSelection & - PartialEdge & - PartialConnections & - PartialValidation & - PartialFolding & - PartialLabel & - PartialSnap & - PartialVertex; -// @ts-ignore recursive reference error -class GraphCells extends autoImplement() { +type PartialCells = Pick< + Graph, + | 'cellsResizable' + | 'cellsBendable' + | 'cellsSelectable' + | 'cellsDisconnectable' + | 'autoSizeCells' + | 'autoSizeCellsOnAdd' + | 'cellsLocked' + | 'cellsCloneable' + | 'cellsDeletable' + | 'cellsMovable' + | 'extendParents' + | 'extendParentsOnAdd' + | 'extendParentsOnMove' + | 'getBoundingBox' + | 'removeStateForCell' + | 'getCurrentCellStyle' + | 'getCellStyle' + | 'postProcessCellStyle' + | 'setCellStyle' + | 'toggleCellStyle' + | 'toggleCellStyles' + | 'setCellStyles' + | 'toggleCellStyleFlags' + | 'setCellStyleFlags' + | 'alignCells' + | 'cloneCell' + | 'cloneCells' + | 'addCell' + | 'addCells' + | 'cellsAdded' + | 'autoSizeCell' + | 'removeCells' + | 'cellsRemoved' + | 'toggleCells' + | 'cellsToggled' + | 'updateCellSize' + | 'cellSizeUpdated' + | 'getPreferredSizeForCell' + | 'resizeCell' + | 'resizeCells' + | 'cellResized' + | 'cellsResized' + | 'resizeChildCells' + | 'constrainChildCells' + | 'scaleCell' + | 'extendParent' + | 'importCells' + | 'moveCells' + | 'cellsMoved' + | 'translateCell' + | 'getCellContainmentArea' + | 'constrainChild' + | 'getChildCells' + | 'getCellAt' + | 'getCells' + | 'getCellsBeyond' + | 'intersects' + | 'isValidAncestor' + | 'isCellLocked' + | 'isCellsLocked' + | 'setCellsLocked' + | 'getCloneableCells' + | 'isCellCloneable' + | 'isCellsCloneable' + | 'setCellsCloneable' + | 'getExportableCells' + | 'canExportCell' + | 'getImportableCells' + | 'canImportCell' + | 'isCellSelectable' + | 'isCellsSelectable' + | 'setCellsSelectable' + | 'getDeletableCells' + | 'isCellDeletable' + | 'isCellsDeletable' + | 'setCellsDeletable' + | 'isCellRotatable' + | 'getMovableCells' + | 'isCellMovable' + | 'isCellsMovable' + | 'setCellsMovable' + | 'isCellResizable' + | 'isCellsResizable' + | 'setCellsResizable' + | 'isCellBendable' + | 'isCellsBendable' + | 'setCellsBendable' + | 'isAutoSizeCell' + | 'isAutoSizeCells' + | 'setAutoSizeCells' + | 'isExtendParent' + | 'isExtendParents' + | 'setExtendParents' + | 'isExtendParentsOnAdd' + | 'setExtendParentsOnAdd' + | 'isExtendParentsOnMove' + | 'setExtendParentsOnMove' + | 'getCursorForCell' + | 'getCellBounds' + | 'getBoundingBoxFromGeometry' +>; +type PartialType = PartialGraph & PartialCells; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphCellsMixin: PartialType = { /** * Specifies the return value for {@link isCellsResizable}. * @default true */ - cellsResizable = true; + cellsResizable: true, /** * Specifies the return value for {@link isCellsBendable}. * @default true */ - cellsBendable = true; + cellsBendable: true, /** * Specifies the return value for {@link isCellsSelectable}. * @default true */ - cellsSelectable = true; + cellsSelectable: true, /** * Specifies the return value for {@link isCellsDisconnectable}. * @default true */ - cellsDisconnectable = true; + cellsDisconnectable: true, /** * Specifies if the graph should automatically update the cell size after an * edit. This is used in {@link isAutoSizeCell}. * @default false */ - autoSizeCells = false; + autoSizeCells: false, /** * Specifies if autoSize style should be applied when cells are added. * @default false */ - autoSizeCellsOnAdd = false; + autoSizeCellsOnAdd: false, /** * Specifies the return value for {@link isCellLocked}. * @default false */ - cellsLocked = false; + cellsLocked: false, /** * Specifies the return value for {@link isCellCloneable}. * @default true */ - cellsCloneable = true; + cellsCloneable: true, /** * Specifies the return value for {@link isCellDeletable}. * @default true */ - cellsDeletable = true; + cellsDeletable: true, /** * Specifies the return value for {@link isCellMovable}. * @default true */ - cellsMovable = true; + cellsMovable: true, /** * Specifies if a parent should contain the child bounds after a resize of * the child. This has precedence over {@link constrainChildren}. * @default true */ - extendParents = true; + extendParents: true, /** * Specifies if parents should be extended according to the {@link extendParents} * switch if cells are added. * @default true */ - extendParentsOnAdd = true; + extendParentsOnAdd: true, /** * Specifies if parents should be extended according to the {@link extendParents} * switch if cells are added. * @default false (for backwards compatibility) */ - extendParentsOnMove = false; + extendParentsOnMove: false, /** * Returns the bounding box for the given array of {@link Cell}. The bounding box for @@ -195,7 +491,7 @@ class GraphCells extends autoImplement() { * * @param cells Array of {@link Cell} whose bounding box should be returned. */ - getBoundingBox(cells: CellArray) { + getBoundingBox(cells) { let result = null; if (cells.length > 0) { @@ -214,7 +510,7 @@ class GraphCells extends autoImplement() { } } return result; - } + }, /** * Removes all cached information for the given cell and its descendants. @@ -224,14 +520,14 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that was removed from the model. */ - removeStateForCell(cell: Cell) { + removeStateForCell(cell) { for (const child of cell.getChildren()) { this.removeStateForCell(child); } this.getView().invalidate(cell, false, true); this.getView().removeState(cell); - } + }, /***************************************************************************** * Group: Cell styles @@ -244,10 +540,10 @@ class GraphCells extends autoImplement() { * @param cell {@link mxCell} whose style should be returned as an array. * @param ignoreState Optional boolean that specifies if the cell state should be ignored. */ - getCurrentCellStyle(cell: Cell, ignoreState = false) { + getCurrentCellStyle(cell, ignoreState = false) { const state = ignoreState ? null : this.getView().getState(cell); return state ? state.style : this.getCellStyle(cell); - } + }, /** * Returns an array of key, value pairs representing the cell style for the @@ -259,7 +555,7 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose style should be returned as an array. */ - getCellStyle(cell: Cell) { + getCellStyle(cell) { const stylename = cell.getStyle(); let style; const stylesheet = this.getStylesheet(); @@ -281,14 +577,14 @@ class GraphCells extends autoImplement() { style = {} as CellStateStyles; } return style; - } + }, /** * Tries to resolve the value for the image style in the image bundles and * turns short data URIs as defined in mxImageBundle to data URIs as * defined in RFC 2397 of the IETF. */ - postProcessCellStyle(style: CellStateStyles) { + postProcessCellStyle(style) { const key = style.image; let image = this.getImageFromBundles(key); @@ -315,7 +611,7 @@ class GraphCells extends autoImplement() { style.image = image; } return style; - } + }, /** * Sets the style of the specified cells. If no cells are given, then the @@ -325,16 +621,15 @@ class GraphCells extends autoImplement() { * @param cells Optional array of {@link Cell} to set the style for. Default is the * selection cells. */ - setCellStyle( - style: keyof CellStateStyles, - cells: CellArray = this.getSelectionCells() - ) { + setCellStyle(style, cells?) { + cells = cells ?? this.getSelectionCells(); + this.batchUpdate(() => { - for (const cell of cells) { + for (const cell of cells!) { this.getModel().setStyle(cell, style); } }); - } + }, /** * Toggles the boolean value for the given key in the style of the given cell @@ -349,13 +644,10 @@ class GraphCells extends autoImplement() { * @param cell Optional {@link Cell} whose style should be modified. Default is * the selection cell. */ - toggleCellStyle( - key: keyof CellStateStyles, - defaultValue = false, - cell: Cell = this.getSelectionCell() - ) { + toggleCellStyle(key, defaultValue = false, cell?) { + cell = cell ?? this.getSelectionCell(); return this.toggleCellStyles(key, defaultValue, new CellArray(cell)); - } + }, /** * Toggles the boolean value for the given key in the style of the given cells @@ -371,21 +663,19 @@ class GraphCells extends autoImplement() { * @param cells Optional array of {@link Cell} whose styles should be modified. * Default is the selection cells. */ - toggleCellStyles( - key: keyof CellStateStyles, - defaultValue = false, - cells: CellArray = this.getSelectionCells() - ) { - let value = null; + toggleCellStyles(key, defaultValue = false, cells?) { + let value = false; + + cells = cells ?? this.getSelectionCells(); if (cells.length > 0) { const style = this.getCurrentCellStyle(cells[0]); - value = getValue(style, key, defaultValue) ? 0 : 1; + value = style[key] ?? defaultValue ? false : true; this.setCellStyles(key, value, cells); } return value; - } + }, /** * Sets the key to value in the styles of the given cells. This will modify @@ -399,13 +689,11 @@ class GraphCells extends autoImplement() { * @param cells Optional array of {@link Cell} to change the style for. Default is * the selection cells. */ - setCellStyles( - key: keyof CellStateStyles, - value: CellStateStyles[keyof CellStateStyles], - cells: CellArray = this.getSelectionCells() - ) { + setCellStyles(key, value, cells) { + cells = cells ?? this.getSelectionCells(); + setCellStyles(this.getModel(), cells, key, value); - } + }, /** * Toggles the given bit for the given key in the styles of the specified @@ -416,13 +704,11 @@ class GraphCells extends autoImplement() { * @param cells Optional array of {@link Cell} to change the style for. Default is * the selection cells. */ - toggleCellStyleFlags( - key: keyof CellStateStyles, - flag: number, - cells: CellArray = this.getSelectionCells() - ) { + toggleCellStyleFlags(key, flag, cells) { + cells = cells ?? this.getSelectionCells(); + this.setCellStyleFlags(key, flag, null, cells); - } + }, /** * Sets or toggles the given bit for the given key in the styles of the @@ -434,12 +720,9 @@ class GraphCells extends autoImplement() { * @param cells Optional array of {@link Cell} to change the style for. Default is * the selection cells. */ - setCellStyleFlags( - key: keyof CellStateStyles, - flag: number, - value: boolean | null = null, - cells: CellArray = this.getSelectionCells() - ) { + setCellStyleFlags(key, flag, value = null, cells) { + cells = cells ?? this.getSelectionCells(); + if (cells.length > 0) { if (value === null) { const style = this.getCurrentCellStyle(cells[0]); @@ -449,7 +732,7 @@ class GraphCells extends autoImplement() { } setCellStyleFlags(this.getModel(), cells, key, flag, value); } - } + }, /***************************************************************************** * Group: Cell alignment and orientation @@ -464,11 +747,9 @@ class GraphCells extends autoImplement() { * @param cells Array of {@link Cell} to be aligned. * @param param Optional coordinate for the alignment. */ - alignCells( - align: string, - cells: CellArray = this.getSelectionCells(), - param: number | null = null - ) { + alignCells(align, cells, param = null) { + cells = cells ?? this.getSelectionCells(); + if (cells.length > 1) { // Finds the required coordinate for the alignment if (param === null) { @@ -546,7 +827,7 @@ class GraphCells extends autoImplement() { } return cells; - } + }, /***************************************************************************** * Group: Cell cloning, insertion and removal @@ -563,16 +844,14 @@ class GraphCells extends autoImplement() { * be updated to reflect the lost parent cell. Default is `false`. */ // cloneCell(cell: mxCell, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; - cloneCell( - cell: Cell, - allowInvalidEdges = false, - mapping: any = null, - keepPosition = false - ): Cell { - return (( - this.cloneCells(new CellArray(cell), allowInvalidEdges, mapping, keepPosition) - ))[0]; - } + cloneCell(cell, allowInvalidEdges = false, mapping = null, keepPosition = false) { + return this.cloneCells( + new CellArray(cell), + allowInvalidEdges, + mapping, + keepPosition + )[0]; + }, /** * Returns the clones for the given cells. The clones are created recursively @@ -588,12 +867,7 @@ class GraphCells extends autoImplement() { * be updated to reflect the lost parent cell. Default is `false`. */ // cloneCells(cells: mxCellArray, allowInvalidEdges?: boolean, mapping?: any, keepPosition?: boolean): mxCellArray; - cloneCells( - cells: CellArray, - allowInvalidEdges = true, - mapping: any = {}, - keepPosition = false - ) { + cloneCells(cells, allowInvalidEdges = true, mapping = {}, keepPosition = false) { let clones; // Creates a dictionary for fast lookups @@ -691,7 +965,7 @@ class GraphCells extends autoImplement() { clones = new CellArray(); } return clones; - } + }, /** * Adds the cell to the parent and connects it to the given source and @@ -705,15 +979,9 @@ class GraphCells extends autoImplement() { * @param source Optional {@link Cell} that represents the source terminal. * @param target Optional {@link Cell} that represents the target terminal. */ - addCell( - cell: Cell, - parent: Cell | null = null, - index: number | null = null, - source: Cell | null = null, - target: Cell | null = null - ) { + addCell(cell, parent = null, index = null, source = null, target = null) { return this.addCells(new CellArray(cell), parent, index, source, target)[0]; - } + }, /** * Function: addCells @@ -735,11 +1003,11 @@ class GraphCells extends autoImplement() { * their absolute position. Default is false. */ addCells( - cells: CellArray, - parent: Cell | null = null, - index: number | null = null, - source: Cell | null = null, - target: Cell | null = null, + cells, + parent = null, + index = null, + source = null, + target = null, absolute = false ) { const p = parent ?? this.getDefaultParent(); @@ -753,7 +1021,7 @@ class GraphCells extends autoImplement() { }); return cells; - } + }, /** * Function: cellsAdded @@ -762,11 +1030,11 @@ class GraphCells extends autoImplement() { * while the transaction is in progress. */ cellsAdded( - cells: CellArray, - parent: Cell, - index: number, - source: Cell | null = null, - target: Cell | null = null, + cells, + parent, + index, + source = null, + target = null, absolute = false, constrain = false, extend = true @@ -857,7 +1125,7 @@ class GraphCells extends autoImplement() { }) ); }); - } + }, /** * Resizes the specified cell to just fit around the its label and/or children @@ -866,7 +1134,7 @@ class GraphCells extends autoImplement() { * @param recurse Optional boolean which specifies if all descendants should be * autosized. Default is `true`. */ - autoSizeCell(cell: Cell, recurse = true) { + autoSizeCell(cell, recurse = true) { if (recurse) { for (const child of cell.getChildren()) { this.autoSizeCell(child); @@ -876,7 +1144,7 @@ class GraphCells extends autoImplement() { if (cell.isVertex() && this.isAutoSizeCell(cell)) { this.updateCellSize(cell); } - } + }, /** * Removes the given cells from the graph including all connected edges if @@ -889,7 +1157,7 @@ class GraphCells extends autoImplement() { * @param includeEdges Optional boolean which specifies if all connected edges * should be removed as well. Default is `true`. */ - removeCells(cells: CellArray | null = null, includeEdges = true) { + removeCells(cells = null, includeEdges = true) { if (!cells) { cells = this.getDeletableCells(this.getSelectionCells()); } @@ -926,8 +1194,8 @@ class GraphCells extends autoImplement() { ); }); - return cells; - } + return cells ?? new CellArray(); + }, /** * Removes the given cells from the model. This method fires @@ -935,7 +1203,7 @@ class GraphCells extends autoImplement() { * * @param cells Array of {@link Cell} to remove. */ - cellsRemoved(cells: CellArray) { + cellsRemoved(cells) { if (cells.length > 0) { const { scale } = this.getView(); const tr = this.getView().translate; @@ -1024,7 +1292,7 @@ class GraphCells extends autoImplement() { this.fireEvent(new EventObject(InternalEvent.CELLS_REMOVED, { cells })); }); } - } + }, /***************************************************************************** * Group: Cell visibility @@ -1042,11 +1310,9 @@ class GraphCells extends autoImplement() { * @param includeEdges Optional boolean indicating if the visible state of all * connected edges should be changed as well. Default is `true`. */ - toggleCells( - show = false, - cells: CellArray = this.getSelectionCells(), - includeEdges = true - ) { + toggleCells(show = false, cells, includeEdges = true) { + cells = cells ?? this.getSelectionCells(); + // Adds all connected edges recursively if (includeEdges) { cells = this.addAllEdges(cells); @@ -1059,7 +1325,7 @@ class GraphCells extends autoImplement() { ); }); return cells; - } + }, /** * Sets the visible state of the specified cells. @@ -1067,7 +1333,7 @@ class GraphCells extends autoImplement() { * @param cells Array of {@link Cell} whose visible state should be changed. * @param show Boolean that specifies the visible state to be assigned. */ - cellsToggled(cells: CellArray, show = false) { + cellsToggled(cells, show = false) { if (cells.length > 0) { this.batchUpdate(() => { for (const cell of cells) { @@ -1075,7 +1341,7 @@ class GraphCells extends autoImplement() { } }); } - } + }, /***************************************************************************** * Group: Cell sizing @@ -1088,7 +1354,7 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose size should be updated. */ - updateCellSize(cell: Cell, ignoreChildren = false) { + updateCellSize(cell, ignoreChildren = false) { this.batchUpdate(() => { this.cellSizeUpdated(cell, ignoreChildren); this.fireEvent( @@ -1096,7 +1362,7 @@ class GraphCells extends autoImplement() { ); }); return cell; - } + }, /** * Updates the size of the given cell in the model using @@ -1104,7 +1370,7 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} for which the size should be changed. */ - cellSizeUpdated(cell: Cell, ignoreChildren = false) { + cellSizeUpdated(cell, ignoreChildren = false) { this.batchUpdate(() => { const size = this.getPreferredSizeForCell(cell); let geo = cell.getGeometry(); @@ -1181,7 +1447,7 @@ class GraphCells extends autoImplement() { this.cellsResized(new CellArray(cell), [geo], false); } }); - } + }, /** * Returns the preferred width and height of the given {@link Cell} as an @@ -1190,7 +1456,7 @@ class GraphCells extends autoImplement() { * * ```javascript * var graphGetPreferredSizeForCell = graph.getPreferredSizeForCell; - * graph.getPreferredSizeForCell = function(cell) + * graph.getPreferredSizeForCell(cell) * { * var result = graphGetPreferredSizeForCell.apply(this, arguments); * var style = this.getCellStyle(cell); @@ -1207,7 +1473,7 @@ class GraphCells extends autoImplement() { * @param cell {@link mxCell} for which the preferred size should be returned. * @param textWidth Optional maximum text width for word wrapping. */ - getPreferredSizeForCell(cell: Cell, textWidth: number | null = null) { + getPreferredSizeForCell(cell, textWidth = null) { let result = null; const state = this.getView().createState(cell); @@ -1288,7 +1554,7 @@ class GraphCells extends autoImplement() { } return result; - } + }, /** * Sets the bounds of the given cell using {@link resizeCells}. Returns the @@ -1297,9 +1563,9 @@ class GraphCells extends autoImplement() { * @param cell {@link mxCell} whose bounds should be changed. * @param bounds {@link mxRectangle} that represents the new bounds. */ - resizeCell(cell: Cell, bounds: Rectangle, recurse = false) { + resizeCell(cell, bounds, recurse = false) { return this.resizeCells(new CellArray(cell), [bounds], recurse)[0]; - } + }, /** * Sets the bounds of the given cells and fires a {@link InternalEvent.RESIZE_CELLS} @@ -1309,11 +1575,9 @@ class GraphCells extends autoImplement() { * @param cells Array of {@link Cell} whose bounds should be changed. * @param bounds Array of {@link mxRectangles} that represent the new bounds. */ - resizeCells( - cells: CellArray, - bounds: Rectangle[], - recurse = this.isRecursiveResize() - ): CellArray { + resizeCells(cells, bounds, recurse): CellArray { + recurse = recurse ?? this.isRecursiveResize(); + this.batchUpdate(() => { const prev = this.cellsResized(cells, bounds, recurse); this.fireEvent( @@ -1321,7 +1585,7 @@ class GraphCells extends autoImplement() { ); }); return cells; - } + }, /** * Sets the bounds of the given cells and fires a {@link InternalEvent.CELLS_RESIZED} @@ -1365,7 +1629,7 @@ class GraphCells extends autoImplement() { * @param bounds Array of {@link mxRectangles} that represent the new bounds. * @param recurse Optional boolean that specifies if the children should be resized. */ - cellsResized(cells: CellArray, bounds: Rectangle[], recurse = false) { + cellsResized(cells, bounds, recurse = false) { const prev: (Geometry | null)[] = []; if (cells.length === bounds.length) { @@ -1390,7 +1654,7 @@ class GraphCells extends autoImplement() { }); } return prev; - } + }, /** * Resizes the parents recursively so that they contain the complete area @@ -1401,7 +1665,7 @@ class GraphCells extends autoImplement() { * @param ignoreRelative Boolean that indicates if relative cells should be ignored. * @param recurse Optional boolean that specifies if the children should be resized. */ - cellResized(cell: Cell, bounds: Rectangle, ignoreRelative = false, recurse = false) { + cellResized(cell, bounds, ignoreRelative = false, recurse = false) { const prev = cell.getGeometry(); if ( @@ -1444,7 +1708,7 @@ class GraphCells extends autoImplement() { } return prev; - } + }, /** * Resizes the child cells of the given cell for the given new geometry with @@ -1453,7 +1717,7 @@ class GraphCells extends autoImplement() { * @param cell {@link mxCell} that has been resized. * @param newGeo {@link mxGeometry} that represents the new bounds. */ - resizeChildCells(cell: Cell, newGeo: Geometry) { + resizeChildCells(cell, newGeo) { const geo = cell.getGeometry(); if (geo) { @@ -1464,18 +1728,18 @@ class GraphCells extends autoImplement() { this.scaleCell(child, dx, dy, true); } } - } + }, /** * Constrains the children of the given cell using {@link constrainChild}. * * @param cell {@link mxCell} that has been resized. */ - constrainChildCells(cell: Cell) { + constrainChildCells(cell) { for (const child of cell.getChildren()) { this.constrainChild(child); } - } + }, /** * Scales the points, position and size of the given cell according to the @@ -1486,7 +1750,7 @@ class GraphCells extends autoImplement() { * @param dy Vertical scaling factor. * @param recurse Boolean indicating if the child cells should be scaled. */ - scaleCell(cell: Cell, dx: number, dy: number, recurse = false) { + scaleCell(cell, dx, dy, recurse = false) { let geo = cell.getGeometry(); if (geo) { @@ -1529,7 +1793,7 @@ class GraphCells extends autoImplement() { this.getModel().setGeometry(cell, geo); } } - } + }, /** * Resizes the parents recursively so that they contain the complete area @@ -1537,7 +1801,7 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that has been resized. */ - extendParent(cell: Cell) { + extendParent(cell) { const parent = cell.getParent(); let p = parent ? parent.getGeometry() : null; @@ -1557,7 +1821,7 @@ class GraphCells extends autoImplement() { this.cellsResized(new CellArray(parent), [p], false); } } - } + }, /***************************************************************************** * Group: Cell moving @@ -1575,16 +1839,9 @@ class GraphCells extends autoImplement() { * @param evt Mouseevent that triggered the invocation. * @param mapping Optional mapping for existing clones. */ - importCells( - cells: CellArray, - dx: number, - dy: number, - target: Cell | null = null, - evt: MouseEvent | null = null, - mapping: any = {} - ) { + importCells(cells, dx, dy, target = null, evt = null, mapping = {}) { return this.moveCells(cells, dx, dy, true, target, evt, mapping); - } + }, /** * Function: moveCells @@ -1612,13 +1869,13 @@ class GraphCells extends autoImplement() { * mapping - Optional mapping for existing clones. */ moveCells( - cells: CellArray, - dx: number = 0, - dy: number = 0, + cells, + dx = 0, + dy = 0, clone = false, - target: Cell | null = null, - evt: MouseEvent | null = null, - mapping: any = null + target = null, + evt = null, + mapping = null ) { if (dx !== 0 || dy !== 0 || clone || target) { // Removes descendants with ancestors in cells to avoid multiple moving @@ -1731,7 +1988,7 @@ class GraphCells extends autoImplement() { }); } return cells; - } + }, /** * Function: cellsMoved @@ -1740,14 +1997,7 @@ class GraphCells extends autoImplement() { * using disconnectGraph is disconnect is true. This method fires * while the transaction is in progress. */ - cellsMoved( - cells: CellArray, - dx: number, - dy: number, - disconnect = false, - constrain = false, - extend = false - ) { + cellsMoved(cells, dx, dy, disconnect = false, constrain = false, extend = false) { if (dx !== 0 || dy !== 0) { this.batchUpdate(() => { if (disconnect) { @@ -1773,13 +2023,13 @@ class GraphCells extends autoImplement() { ); }); } - } + }, /** * Translates the geometry of the given cell and stores the new, * translated geometry in the model as an atomic change. */ - translateCell(cell: Cell, dx: number, dy: number) { + translateCell(cell, dx, dy) { let geometry = cell.getGeometry(); if (geometry) { @@ -1818,14 +2068,14 @@ class GraphCells extends autoImplement() { } this.getModel().setGeometry(cell, geometry); } - } + }, /** * Returns the {@link Rectangle} inside which a cell is to be kept. * * @param cell {@link mxCell} for which the area should be returned. */ - getCellContainmentArea(cell: Cell) { + getCellContainmentArea(cell) { if (!cell.isEdge()) { const parent = cell.getParent(); @@ -1872,7 +2122,7 @@ class GraphCells extends autoImplement() { } } return null; - } + }, /** * Keeps the given cell inside the bounds returned by @@ -1883,7 +2133,7 @@ class GraphCells extends autoImplement() { * @param cell {@link mxCell} which should be constrained. * @param sizeFirst Specifies if the size should be changed first. Default is `true`. */ - constrainChild(cell: Cell, sizeFirst = true) { + constrainChild(cell, sizeFirst = true) { let geo = cell.getGeometry(); if (geo && (this.isConstrainRelativeChildren() || !geo.relative)) { @@ -1943,7 +2193,7 @@ class GraphCells extends autoImplement() { const bbox = this.getBoundingBoxFromGeometry(cells, false); if (bbox) { - geo = geo.clone(); + geo = geo.clone(); // Cumulative horizontal movement let dx = 0; @@ -1996,7 +2246,7 @@ class GraphCells extends autoImplement() { } } } - } + }, /***************************************************************************** * Group: Cell retrieval @@ -2012,7 +2262,9 @@ class GraphCells extends autoImplement() { * @param edges Optional boolean that specifies if child edges should * be returned. Default is `false`. */ - getChildCells(parent: Cell = this.getDefaultParent(), vertices = false, edges = false) { + getChildCells(parent, vertices = false, edges = false) { + parent = parent ?? this.getDefaultParent(); + const cells = parent.getChildCells(vertices, edges); const result = new CellArray(); @@ -2023,7 +2275,7 @@ class GraphCells extends autoImplement() { } } return result; - } + }, /** * Returns the bottom-most cell that intersects the given point (x, y) in @@ -2044,14 +2296,7 @@ class GraphCells extends autoImplement() { * @param ignoreFn Optional function that returns true if cell should be ignored. * The function is passed the cell state and the x and y parameter. */ - getCellAt( - x: number, - y: number, - parent: Cell | null = null, - vertices = true, - edges = true, - ignoreFn: Function | null = null - ): Cell | null { + getCellAt(x, y, parent = null, vertices = true, edges = true, ignoreFn = null) { if (!parent) { parent = this.getCurrentRoot(); @@ -2087,7 +2332,7 @@ class GraphCells extends autoImplement() { } } return null; - } + }, /** * Returns the child vertices and edges of the given parent that are contained @@ -2104,14 +2349,14 @@ class GraphCells extends autoImplement() { * @param result Optional array to store the result in. */ getCells( - x: number, - y: number, - width: number, - height: number, - parent: Cell | null = null, - result: CellArray = new CellArray(), - intersection: Rectangle | null = null, - ignoreFn: Function | null = null, + x, + y, + width, + height, + parent = null, + result = new CellArray(), + intersection = null, + ignoreFn = null, includeDescendants = false ) { if (width > 0 || height > 0 || intersection) { @@ -2170,7 +2415,7 @@ class GraphCells extends autoImplement() { } } return result; - } + }, /** * Function: getCellsBeyond @@ -2190,13 +2435,7 @@ class GraphCells extends autoImplement() { * bottomHalfpane - Boolean indicating if the cells in the bottom halfpane * from the origin should be returned. */ - getCellsBeyond( - x0: number, - y0: number, - parent: Cell | null = null, - rightHalfpane = false, - bottomHalfpane = false - ) { + getCellsBeyond(x0, y0, parent = null, rightHalfpane = false, bottomHalfpane = false) { const result = []; if (rightHalfpane || bottomHalfpane) { @@ -2215,8 +2454,8 @@ class GraphCells extends autoImplement() { } } } - return result; - } + return new CellArray(...result); + }, /** * Returns the bottom-most cell that intersects the given point (x, y) in @@ -2226,11 +2465,11 @@ class GraphCells extends autoImplement() { * @param x X-coordinate of the location to be checked. * @param y Y-coordinate of the location to be checked. */ - intersects(state: CellState, x: number, y: number): boolean { + intersects(state, x, y) { const pts = state.absolutePoints; if (pts.length > 0) { - const t2 = this.getTolerance() * this.getTolerance(); + const t2 = this.getEventTolerance() * this.getEventTolerance(); let pt = pts[0]; for (let i = 1; i < pts.length; i += 1) { @@ -2263,7 +2502,7 @@ class GraphCells extends autoImplement() { } } return false; - } + }, /** * Returns whether or not the specified parent is a valid @@ -2274,9 +2513,9 @@ class GraphCells extends autoImplement() { * @param parent {@link mxCell} the possible parent cell * @param recurse boolean whether or not to recurse the child ancestors */ - isValidAncestor(cell: Cell, parent: Cell, recurse: boolean = false) { + isValidAncestor(cell, parent, recurse = false) { return recurse ? parent.isAncestor(cell) : cell.getParent() === parent; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -2289,11 +2528,11 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose locked state should be returned. */ - isCellLocked(cell: Cell) { + isCellLocked(cell) { const geometry = cell.getGeometry(); - return this.isCellsLocked() || (geometry && cell.isVertex() && geometry.relative); - } + return this.isCellsLocked() || (!!geometry && cell.isVertex() && geometry.relative); + }, /** * Returns true if the given cell may not be moved, sized, bended, @@ -2304,7 +2543,7 @@ class GraphCells extends autoImplement() { */ isCellsLocked() { return this.cellsLocked; - } + }, /** * Sets if any cell may be moved, sized, bended, disconnected, edited or @@ -2312,18 +2551,18 @@ class GraphCells extends autoImplement() { * * @param value Boolean that defines the new value for {@link cellsLocked}. */ - setCellsLocked(value: boolean) { + setCellsLocked(value) { this.cellsLocked = value; - } + }, /** * Returns the cells which may be exported in the given array of cells. */ - getCloneableCells(cells: CellArray) { + getCloneableCells(cells) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.isCellCloneable(cell); }); - } + }, /** * Returns true if the given cell is cloneable. This implementation returns @@ -2332,10 +2571,10 @@ class GraphCells extends autoImplement() { * * @param cell Optional {@link Cell} whose cloneable state should be returned. */ - isCellCloneable(cell: Cell) { + isCellCloneable(cell) { const style = this.getCurrentCellStyle(cell); return this.isCellsCloneable() && style.cloneable; - } + }, /** * Returns {@link cellsCloneable}, that is, if the graph allows cloning of cells @@ -2343,7 +2582,7 @@ class GraphCells extends autoImplement() { */ isCellsCloneable() { return this.cellsCloneable; - } + }, /** * Specifies if the graph should allow cloning of cells by holding down the @@ -2352,18 +2591,18 @@ class GraphCells extends autoImplement() { * * @param value Boolean indicating if the graph should be cloneable. */ - setCellsCloneable(value: boolean) { + setCellsCloneable(value) { this.cellsCloneable = value; - } + }, /** * Returns the cells which may be exported in the given array of cells. */ - getExportableCells(cells: CellArray) { + getExportableCells(cells) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.canExportCell(cell); }); - } + }, /** * Returns true if the given cell may be exported to the clipboard. This @@ -2371,18 +2610,18 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that represents the cell to be exported. */ - canExportCell(cell: Cell | null = null) { + canExportCell(cell = null) { return this.isExportEnabled(); - } + }, /** * Returns the cells which may be imported in the given array of cells. */ - getImportableCells(cells: CellArray) { + getImportableCells(cells) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.canImportCell(cell); }); - } + }, /** * Returns true if the given cell may be imported from the clipboard. @@ -2390,9 +2629,9 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that represents the cell to be imported. */ - canImportCell(cell: Cell | null = null) { + canImportCell(cell = null) { return this.isImportEnabled(); - } + }, /** * Returns true if the given cell is selectable. This implementation @@ -2401,7 +2640,7 @@ class GraphCells extends autoImplement() { * To add a new style for making cells (un)selectable, use the following code. * * ```javascript - * isCellSelectable = function(cell) + * isCellSelectable(cell) * { * var style = this.getCurrentCellStyle(cell); * @@ -2417,32 +2656,32 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose selectable state should be returned. */ - isCellSelectable(cell: Cell) { + isCellSelectable(cell) { return this.isCellsSelectable(); - } + }, /** * Returns {@link cellsSelectable}. */ isCellsSelectable() { return this.cellsSelectable; - } + }, /** * Sets {@link cellsSelectable}. */ - setCellsSelectable(value: boolean) { + setCellsSelectable(value) { this.cellsSelectable = value; - } + }, /** * Returns the cells which may be exported in the given array of cells. */ - getDeletableCells(cells: CellArray) { + getDeletableCells(cells) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.isCellDeletable(cell); }); - } + }, /** * Returns true if the given cell is moveable. This returns @@ -2451,26 +2690,26 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose deletable state should be returned. */ - isCellDeletable(cell: Cell) { + isCellDeletable(cell) { const style = this.getCurrentCellStyle(cell); return this.isCellsDeletable() && style.deletable; - } + }, /** * Returns {@link cellsDeletable}. */ isCellsDeletable() { return this.cellsDeletable; - } + }, /** * Sets {@link cellsDeletable}. * * @param value Boolean indicating if the graph should allow deletion of cells. */ - setCellsDeletable(value: boolean) { + setCellsDeletable(value) { this.cellsDeletable = value; - } + }, /** * Returns true if the given cell is rotatable. This returns true for the given @@ -2478,19 +2717,19 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose rotatable state should be returned. */ - isCellRotatable(cell: Cell) { + isCellRotatable(cell) { const style = this.getCurrentCellStyle(cell); return style.rotatable; - } + }, /** * Returns the cells which are movable in the given array of cells. */ - getMovableCells(cells: CellArray) { + getMovableCells(cells) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.isCellMovable(cell); }); - } + }, /** * Returns true if the given cell is moveable. This returns {@link cellsMovable} @@ -2499,18 +2738,18 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose movable state should be returned. */ - isCellMovable(cell: Cell) { + isCellMovable(cell) { const style = this.getCurrentCellStyle(cell); return this.isCellsMovable() && !this.isCellLocked(cell) && style.movable; - } + }, /** * Returns {@link cellsMovable}. */ isCellsMovable() { return this.cellsMovable; - } + }, /** * Specifies if the graph should allow moving of cells. This implementation @@ -2518,9 +2757,9 @@ class GraphCells extends autoImplement() { * * @param value Boolean indicating if the graph should allow moving of cells. */ - setCellsMovable(value: boolean) { + setCellsMovable(value) { this.cellsMovable = value; - } + }, /** * Returns true if the given cell is resizable. This returns @@ -2530,20 +2769,20 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose resizable state should be returned. */ - isCellResizable(cell: Cell) { + isCellResizable(cell) { const style = this.getCurrentCellStyle(cell); const r = this.isCellsResizable() && !this.isCellLocked(cell) && style.resizeable; return r; - } + }, /** * Returns {@link cellsResizable}. */ isCellsResizable() { return this.cellsResizable; - } + }, /** * Specifies if the graph should allow resizing of cells. This @@ -2552,9 +2791,9 @@ class GraphCells extends autoImplement() { * @param value Boolean indicating if the graph should allow resizing of * cells. */ - setCellsResizable(value: boolean) { + setCellsResizable(value) { this.cellsResizable = value; - } + }, /** * Returns true if the given cell is bendable. This returns {@link cellsBendable} @@ -2563,18 +2802,18 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose bendable state should be returned. */ - isCellBendable(cell: Cell) { + isCellBendable(cell) { const style = this.getCurrentCellStyle(cell); return this.isCellsBendable() && !this.isCellLocked(cell) && style.bendable; - } + }, /** * Returns {@link cellsBenadable}. */ isCellsBendable() { return this.cellsBendable; - } + }, /** * Specifies if the graph should allow bending of edges. This @@ -2583,9 +2822,9 @@ class GraphCells extends autoImplement() { * @param value Boolean indicating if the graph should allow bending of * edges. */ - setCellsBendable(value: boolean) { + setCellsBendable(value) { this.cellsBendable = value; - } + }, /** * Returns true if the size of the given cell should automatically be @@ -2595,18 +2834,18 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that should be resized. */ - isAutoSizeCell(cell: Cell) { + isAutoSizeCell(cell) { const style = this.getCurrentCellStyle(cell); return this.isAutoSizeCells() || style.autosize; - } + }, /** * Returns {@link autoSizeCells}. */ isAutoSizeCells() { return this.autoSizeCells; - } + }, /** * Specifies if cell sizes should be automatically updated after a label @@ -2617,9 +2856,9 @@ class GraphCells extends autoImplement() { * @param value Boolean indicating if cells should be resized * automatically. */ - setAutoSizeCells(value: boolean) { + setAutoSizeCells(value) { this.autoSizeCells = value; - } + }, /** * Returns true if the parent of the given cell should be extended if the @@ -2628,57 +2867,57 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} that has been resized. */ - isExtendParent(cell: Cell) { + isExtendParent(cell) { return !cell.isEdge() && this.isExtendParents(); - } + }, /** * Returns {@link extendParents}. */ isExtendParents() { return this.extendParents; - } + }, /** * Sets {@link extendParents}. * * @param value New boolean value for {@link extendParents}. */ - setExtendParents(value: boolean) { + setExtendParents(value) { this.extendParents = value; - } + }, /** * Returns {@link extendParentsOnAdd}. */ - isExtendParentsOnAdd(cell: Cell) { + isExtendParentsOnAdd(cell) { return this.extendParentsOnAdd; - } + }, /** * Sets {@link extendParentsOnAdd}. * * @param value New boolean value for {@link extendParentsOnAdd}. */ - setExtendParentsOnAdd(value: boolean) { + setExtendParentsOnAdd(value) { this.extendParentsOnAdd = value; - } + }, /** * Returns {@link extendParentsOnMove}. */ isExtendParentsOnMove() { return this.extendParentsOnMove; - } + }, /** * Sets {@link extendParentsOnMove}. * * @param value New boolean value for {@link extendParentsOnAdd}. */ - setExtendParentsOnMove(value: boolean) { + setExtendParentsOnMove(value) { this.extendParentsOnMove = value; - } + }, /***************************************************************************** * Group: Graph appearance @@ -2690,9 +2929,9 @@ class GraphCells extends autoImplement() { * * @param cell {@link mxCell} whose cursor should be returned. */ - getCursorForCell(cell: Cell): string | null { + getCursorForCell(cell) { return null; - } + }, /***************************************************************************** * Group: Graph display @@ -2708,7 +2947,7 @@ class GraphCells extends autoImplement() { * @param includeDescendants Optional boolean that specifies if the bounds * of all descendants should be included. Default is `false`. */ - getCellBounds(cell: Cell, includeEdges = false, includeDescendants = false) { + getCellBounds(cell, includeEdges = false, includeDescendants = false) { let cells = new CellArray(cell); // Includes all connected edges @@ -2731,7 +2970,7 @@ class GraphCells extends autoImplement() { } } return result; - } + }, /** * Returns the bounding box for the geometries of the vertices in the @@ -2765,7 +3004,7 @@ class GraphCells extends autoImplement() { * @param includeEdges Specifies if edge bounds should be included by computing * the bounding box for all points in geometry. Default is `false`. */ - getBoundingBoxFromGeometry(cells: CellArray, includeEdges = false) { + getBoundingBoxFromGeometry(cells, includeEdges = false) { let result = null; let tmp: Rectangle | null = null; @@ -2868,7 +3107,7 @@ class GraphCells extends autoImplement() { } } return result; - } -} + }, +}; -export default GraphCells; +mixInto(Graph)(GraphCellsMixin); diff --git a/packages/core/src/view/cell/TreeTraversal.ts b/packages/core/src/view/cell/TreeTraversal.ts index 7ae0e3ab8..eb734e72f 100644 --- a/packages/core/src/view/cell/TreeTraversal.ts +++ b/packages/core/src/view/cell/TreeTraversal.ts @@ -1,7 +1,7 @@ import Cell from './datatypes/Cell'; import CellArray from './datatypes/CellArray'; import Dictionary from '../../util/Dictionary'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; class TreeTraversal { dependencies = ['connections']; diff --git a/packages/core/src/view/cell/edge/EdgeHandler.ts b/packages/core/src/view/cell/edge/EdgeHandler.ts index 6c3996b9b..b424e6593 100644 --- a/packages/core/src/view/cell/edge/EdgeHandler.ts +++ b/packages/core/src/view/cell/edge/EdgeHandler.ts @@ -31,7 +31,7 @@ import { OUTLINE_HIGHLIGHT_COLOR, OUTLINE_HIGHLIGHT_STROKEWIDTH, } from '../../../util/Constants'; -import utils, { +import { contains, convertPoint, equalPoints, @@ -56,14 +56,13 @@ import { isMouseEvent, isShiftDown, } from '../../../util/EventUtils'; -import { MaxGraph } from '../../Graph'; +import { Graph } from '../../Graph'; import CellState from '../datatypes/CellState'; import Shape from '../../geometry/shape/Shape'; import { CellHandle, ColorValue, Listenable } from '../../../types'; import InternalMouseEvent from '../../event/InternalMouseEvent'; import Cell from '../datatypes/Cell'; import ImageBox from '../../image/ImageBox'; -import Marker from '../../geometry/shape/edge/Marker'; import EventSource from '../../event/EventSource'; import GraphHandler from '../../GraphHandler'; @@ -175,7 +174,7 @@ class EdgeHandler { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: state @@ -672,7 +671,7 @@ class EdgeHandler { }; } - return new MyMarker(this.graph); + return new MyMarker(this.graph) as CellMarker; } /** diff --git a/packages/core/src/view/cell/edge/ElbowEdgeHandler.ts b/packages/core/src/view/cell/edge/ElbowEdgeHandler.ts index 161d8ff3b..2733e77e9 100644 --- a/packages/core/src/view/cell/edge/ElbowEdgeHandler.ts +++ b/packages/core/src/view/cell/edge/ElbowEdgeHandler.ts @@ -17,7 +17,7 @@ import Point from '../../geometry/Point'; import EdgeStyle from '../../style/EdgeStyle'; import Resources from '../../../util/Resources'; import Rectangle from '../../geometry/Rectangle'; -import utils, { intersects } from '../../../util/Utils'; +import { intersects } from '../../../util/Utils'; import mxClient from '../../../mxClient'; import { isConsumed } from '../../../util/EventUtils'; import CellState from '../datatypes/CellState'; diff --git a/packages/core/src/view/cell/edge/GraphEdge.ts b/packages/core/src/view/cell/edge/GraphEdgeMixin.ts similarity index 78% rename from packages/core/src/view/cell/edge/GraphEdge.ts rename to packages/core/src/view/cell/edge/GraphEdgeMixin.ts index 1dd7d85b0..1d1b8a7c5 100644 --- a/packages/core/src/view/cell/edge/GraphEdge.ts +++ b/packages/core/src/view/cell/edge/GraphEdgeMixin.ts @@ -1,88 +1,198 @@ import Cell from '../datatypes/Cell'; import CellArray from '../datatypes/CellArray'; -import { autoImplement, findNearestSegment, removeDuplicates } from '../../../util/Utils'; +import { findNearestSegment, mixInto, removeDuplicates } from '../../../util/Utils'; import Geometry from '../../geometry/Geometry'; import EventObject from '../../event/EventObject'; import InternalEvent from '../../event/InternalEvent'; import Dictionary from '../../../util/Dictionary'; +import { Graph } from '../../Graph'; -import type Graph from '../../Graph'; -import type GraphCells from '../GraphCells'; -import type GraphConnections from '../../connection/GraphConnections'; +declare module '../../Graph' { + interface Graph { + resetEdgesOnResize: boolean; + resetEdgesOnMove: false; + resetEdgesOnConnect: boolean; + connectableEdges: boolean; + allowDanglingEdges: boolean; + cloneInvalidEdges: boolean; + alternateEdgeStyle: string | null; + edgeLabelsMovable: boolean; -type PartialGraph = Pick; -type PartialCells = Pick< - GraphCells, - | 'cloneCell' - | 'cellsMoved' - | 'cellsAdded' - | 'addCell' - | 'isValidAncestor' + isResetEdgesOnMove: () => boolean; + isResetEdgesOnConnect: () => boolean; + isResetEdgesOnResize: () => boolean; + isEdgeLabelsMovable: () => boolean; + setEdgeLabelsMovable: (value: boolean) => void; + setAllowDanglingEdges: (value: boolean) => void; + isAllowDanglingEdges: () => boolean; + setConnectableEdges: (value: boolean) => void; + isConnectableEdges: () => boolean; + setCloneInvalidEdges: (value: boolean) => void; + isCloneInvalidEdges: () => boolean; + flipEdge: (edge: Cell) => Cell; + splitEdge: ( + edge: Cell, + cells: CellArray, + newEdge: Cell | null, + dx?: number, + dy?: number, + x?: number, + y?: number, + parent?: Cell | null + ) => Cell; + insertEdge: (...args: any[]) => Cell; + createEdge: ( + parent: Cell | null, + id: string, + value: any, + source: Cell | null, + target: Cell | null, + style: any + ) => Cell; + addEdge: ( + edge: Cell, + parent: Cell | null, + source: Cell | null, + target: Cell | null, + index?: number | null + ) => Cell; + addAllEdges: (cells: CellArray) => CellArray; + getAllEdges: (cells: CellArray | null) => CellArray; + getIncomingEdges: (cell: Cell, parent: Cell | null) => CellArray; + getOutgoingEdges: (cell: Cell, parent: Cell | null) => CellArray; + getEdges: ( + cell: Cell, + parent?: Cell | null, + incoming?: boolean, + outgoing?: boolean, + includeLoops?: boolean, + recurse?: boolean + ) => CellArray; + getChildEdges: (parent: Cell) => CellArray; + getEdgesBetween: (source: Cell, target: Cell, directed?: boolean) => CellArray; + resetEdges: (cells: CellArray) => void; + resetEdge: (edge: Cell) => Cell; + } +} + +type PartialGraph = Pick< + Graph, + | 'batchUpdate' + | 'fireEvent' + | 'getModel' + | 'getView' | 'getChildCells' + | 'isValidAncestor' + | 'cellsAdded' + | 'cellsMoved' + | 'cloneCell' + | 'addCell' + | 'cellConnected' >; -type PartialConnections = Pick; -type PartialClass = PartialGraph & PartialCells & PartialConnections; +type PartialEdge = Pick< + Graph, + | 'resetEdgesOnResize' + | 'resetEdgesOnMove' + | 'resetEdgesOnConnect' + | 'connectableEdges' + | 'allowDanglingEdges' + | 'cloneInvalidEdges' + | 'alternateEdgeStyle' + | 'edgeLabelsMovable' + | 'isResetEdgesOnMove' + | 'isResetEdgesOnConnect' + | 'isResetEdgesOnResize' + | 'isEdgeLabelsMovable' + | 'setEdgeLabelsMovable' + | 'setAllowDanglingEdges' + | 'isAllowDanglingEdges' + | 'setConnectableEdges' + | 'isConnectableEdges' + | 'setCloneInvalidEdges' + | 'isCloneInvalidEdges' + | 'flipEdge' + | 'splitEdge' + | 'insertEdge' + | 'createEdge' + | 'addEdge' + | 'addAllEdges' + | 'getAllEdges' + | 'getIncomingEdges' + | 'getOutgoingEdges' + | 'getEdges' + | 'getChildEdges' + | 'getEdgesBetween' + | 'resetEdges' + | 'resetEdge' +>; +type PartialType = PartialGraph & PartialEdge; -// @ts-ignore recursive reference error -class GraphEdge extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphEdgeMixin: PartialType = { /** * Specifies if edge control points should be reset after the resize of a * connected cell. * @default false */ - resetEdgesOnResize = false; + resetEdgesOnResize: false, - isResetEdgesOnResize = () => this.resetEdgesOnResize; + isResetEdgesOnResize() { + return this.resetEdgesOnResize; + }, /** * Specifies if edge control points should be reset after the move of a * connected cell. * @default false */ - resetEdgesOnMove = false; + resetEdgesOnMove: false, - isResetEdgesOnMove = () => this.resetEdgesOnMove; + isResetEdgesOnMove() { + return this.resetEdgesOnMove; + }, /** * Specifies if edge control points should be reset after the the edge has been * reconnected. * @default true */ - resetEdgesOnConnect = true; + resetEdgesOnConnect: true, - isResetEdgesOnConnect = () => this.resetEdgesOnConnect; + isResetEdgesOnConnect() { + return this.resetEdgesOnConnect; + }, /** * Specifies if edges are connectable. This overrides the connectable field in edges. * @default false */ - connectableEdges = false; + connectableEdges: false, /** * Specifies if edges with disconnected terminals are allowed in the graph. * @default true */ - allowDanglingEdges = true; + allowDanglingEdges: true, /** * Specifies if edges that are cloned should be validated and only inserted * if they are valid. * @default true */ - cloneInvalidEdges = false; + cloneInvalidEdges: false, /** * Specifies the alternate edge style to be used if the main control point * on an edge is being double clicked. * @default null */ - alternateEdgeStyle: string | null = null; + alternateEdgeStyle: null, /** * Specifies the return value for edges in {@link isLabelMovable}. * @default true */ - edgeLabelsMovable = true; + edgeLabelsMovable: true, /***************************************************************************** * Group: Graph Behaviour @@ -93,14 +203,14 @@ class GraphEdge extends autoImplement() { */ isEdgeLabelsMovable() { return this.edgeLabelsMovable; - } + }, /** * Sets {@link edgeLabelsMovable}. */ - setEdgeLabelsMovable(value: boolean) { + setEdgeLabelsMovable(value) { this.edgeLabelsMovable = value; - } + }, /** * Specifies if dangling edges are allowed, that is, if edges are allowed @@ -108,32 +218,32 @@ class GraphEdge extends autoImplement() { * * @param value Boolean indicating if dangling edges are allowed. */ - setAllowDanglingEdges(value: boolean) { + setAllowDanglingEdges(value) { this.allowDanglingEdges = value; - } + }, /** * Returns {@link allowDanglingEdges} as a boolean. */ isAllowDanglingEdges() { return this.allowDanglingEdges; - } + }, /** * Specifies if edges should be connectable. * * @param value Boolean indicating if edges should be connectable. */ - setConnectableEdges(value: boolean) { + setConnectableEdges(value) { this.connectableEdges = value; - } + }, /** * Returns {@link connectableEdges} as a boolean. */ isConnectableEdges() { return this.connectableEdges; - } + }, /** * Specifies if edges should be inserted when cloned but not valid wrt. @@ -142,16 +252,16 @@ class GraphEdge extends autoImplement() { * @param value Boolean indicating if cloned invalid edges should be * inserted into the graph or ignored. */ - setCloneInvalidEdges(value: boolean) { + setCloneInvalidEdges(value) { this.cloneInvalidEdges = value; - } + }, /** * Returns {@link cloneInvalidEdges} as a boolean. */ isCloneInvalidEdges() { return this.cloneInvalidEdges; - } + }, /***************************************************************************** * Group: Cell alignment and orientation @@ -182,8 +292,7 @@ class GraphEdge extends autoImplement() { * * @param edge {@link mxCell} whose style should be changed. */ - // flipEdge(edge: mxCell): mxCell; - flipEdge(edge: Cell) { + flipEdge(edge) { if (this.alternateEdgeStyle) { this.batchUpdate(() => { const style = edge.getStyle(); @@ -200,7 +309,7 @@ class GraphEdge extends autoImplement() { }); } return edge; - } + }, /** * Function: splitEdge @@ -222,16 +331,7 @@ class GraphEdge extends autoImplement() { * parent - Optional parent to insert the cell. If null the parent of * the edge is used. */ - splitEdge( - edge: Cell, - cells: CellArray, - newEdge: Cell | null, - dx = 0, - dy = 0, - x: number, - y: number, - parent: Cell | null = null - ) { + splitEdge(edge, cells, newEdge, dx = 0, dy = 0, x, y, parent = null) { parent = parent ?? edge.getParent(); const source = edge.getTerminal(true); @@ -282,8 +382,8 @@ class GraphEdge extends autoImplement() { ); }); - return newEdge; - } + return newEdge as Cell; + }, /** * Adds a new edge into the given parent {@link Cell} using value as the user @@ -298,7 +398,7 @@ class GraphEdge extends autoImplement() { * @param target {@link mxCell} that defines the target of the edge. * @param style Optional string that defines the cell style. */ - insertEdge(...args: any[]) { + insertEdge(...args) { let parent: Cell; let id: string = ''; let value: any; // note me - can be a string or a class instance!!! @@ -323,7 +423,7 @@ class GraphEdge extends autoImplement() { const edge = this.createEdge(parent, id, value, source, target, style); return this.addEdge(edge, parent, source, target); - } + }, /** * Hook method that creates the new edge for {@link insertEdge}. This @@ -331,21 +431,14 @@ class GraphEdge extends autoImplement() { * are set when the edge is added to the model. * */ - createEdge( - parent: Cell | null = null, - id: string, - value: any, - source: Cell | null = null, - target: Cell | null = null, - style: any - ) { + createEdge(parent = null, id, value, source = null, target = null, style) { // Creates the edge const edge = new Cell(value, new Geometry(), style); edge.setId(id); edge.setEdge(true); (edge.geometry).relative = true; return edge; - } + }, /** * Adds the edge to the parent and connects it to the given source and @@ -359,15 +452,9 @@ class GraphEdge extends autoImplement() { * @param target Optional {@link Cell} that represents the target terminal. * @param index Optional index to insert the cells at. Default is 'to append'. */ - addEdge( - edge: Cell, - parent: Cell | null = null, - source: Cell | null = null, - target: Cell | null = null, - index: number | null = null - ) { + addEdge(edge, parent = null, source = null, target = null, index = null) { return this.addCell(edge, parent, index, source, target); - } + }, /***************************************************************************** * Group: Folding @@ -377,15 +464,15 @@ class GraphEdge extends autoImplement() { * Returns an array with the given cells and all edges that are connected * to a cell or one of its descendants. */ - addAllEdges(cells: CellArray) { + addAllEdges(cells) { const allCells = cells.slice(); return new CellArray(...removeDuplicates(allCells.concat(this.getAllEdges(cells)))); - } + }, /** * Returns all edges connected to the given cells or its descendants. */ - getAllEdges(cells: CellArray | null) { + getAllEdges(cells) { let edges: CellArray = new CellArray(); if (cells) { @@ -402,7 +489,7 @@ class GraphEdge extends autoImplement() { } } return edges; - } + }, /** * Returns the visible incoming edges for the given cell. If the optional @@ -413,9 +500,9 @@ class GraphEdge extends autoImplement() { * @param parent Optional parent of the opposite end for an edge to be * returned. */ - getIncomingEdges(cell: Cell, parent: Cell | null = null) { + getIncomingEdges(cell, parent = null) { return this.getEdges(cell, parent, true, false, false); - } + }, /** * Returns the visible outgoing edges for the given cell. If the optional @@ -426,9 +513,9 @@ class GraphEdge extends autoImplement() { * @param parent Optional parent of the opposite end for an edge to be * returned. */ - getOutgoingEdges(cell: Cell, parent: Cell | null = null) { + getOutgoingEdges(cell, parent = null) { return this.getEdges(cell, parent, false, true, false); - } + }, /** * Function: getEdges @@ -455,8 +542,8 @@ class GraphEdge extends autoImplement() { * Default is false */ getEdges( - cell: Cell, - parent: Cell | null = null, + cell, + parent = null, incoming = true, outgoing = true, includeLoops = true, @@ -501,7 +588,7 @@ class GraphEdge extends autoImplement() { } } return result; - } + }, /***************************************************************************** * Group: Cell retrieval @@ -512,9 +599,9 @@ class GraphEdge extends autoImplement() { * * @param parent {@link mxCell} whose child vertices should be returned. */ - getChildEdges(parent: Cell) { + getChildEdges(parent) { return this.getChildCells(parent, false, true); - } + }, /** * Returns the edges between the given source and target. This takes into @@ -525,7 +612,7 @@ class GraphEdge extends autoImplement() { * target - * directed - */ - getEdgesBetween(source: Cell, target: Cell, directed = false) { + getEdgesBetween(source, target, directed = false) { const edges = this.getEdges(source); const result = new CellArray(); @@ -549,7 +636,7 @@ class GraphEdge extends autoImplement() { } } return result; - } + }, /***************************************************************************** * Group: Cell moving @@ -562,7 +649,7 @@ class GraphEdge extends autoImplement() { * @param cells Array of {@link Cell} for which the connected edges should be * reset. */ - resetEdges(cells: CellArray) { + resetEdges(cells) { // Prepares faster cells lookup const dict = new Dictionary(); @@ -596,14 +683,14 @@ class GraphEdge extends autoImplement() { } finally { this.getModel().endUpdate(); } - } + }, /** * Resets the control points of the given edge. * * @param edge {@link mxCell} whose points should be reset. */ - resetEdge(edge: Cell) { + resetEdge(edge) { let geo = edge.getGeometry(); // Resets the control points @@ -614,7 +701,7 @@ class GraphEdge extends autoImplement() { } return edge; - } -} + }, +}; -export default GraphEdge; +mixInto(Graph)(GraphEdgeMixin); diff --git a/packages/core/src/view/cell/vertex/GraphVertex.ts b/packages/core/src/view/cell/vertex/GraphVertexMixin.ts similarity index 72% rename from packages/core/src/view/cell/vertex/GraphVertex.ts rename to packages/core/src/view/cell/vertex/GraphVertexMixin.ts index 2e4d3fff3..ab09ca422 100644 --- a/packages/core/src/view/cell/vertex/GraphVertex.ts +++ b/packages/core/src/view/cell/vertex/GraphVertexMixin.ts @@ -1,38 +1,77 @@ import Cell from '../datatypes/Cell'; import Geometry from '../../geometry/Geometry'; -import { autoImplement } from '../../../util/Utils'; +import { Graph } from '../../Graph'; +import CellArray from '../datatypes/CellArray'; +import { mixInto } from '../../../util/Utils'; -import type GraphCells from '../GraphCells'; +declare module '../../Graph' { + interface Graph { + vertexLabelsMovable: boolean; + allowNegativeCoordinates: boolean; -type PartialCells = Pick; -type PartialClass = PartialCells; + isAllowNegativeCoordinates: () => boolean; + setAllowNegativeCoordinates: (value: boolean) => void; + insertVertex: (...args: any[]) => Cell; + createVertex: ( + parent: Cell, + id: string, + value: any, + x: number, + y: number, + width: number, + height: number, + style: any, + relative: boolean, + geometryClass: typeof Geometry + ) => Cell; + getChildVertices: (parent: Cell) => CellArray; + isVertexLabelsMovable: () => boolean; + setVertexLabelsMovable: (value: boolean) => void; + } +} -class GraphVertex extends autoImplement() { +type PartialGraph = Pick; +type PartialVertex = Pick< + Graph, + | 'vertexLabelsMovable' + | 'allowNegativeCoordinates' + | 'isAllowNegativeCoordinates' + | 'setAllowNegativeCoordinates' + | 'insertVertex' + | 'createVertex' + | 'getChildVertices' + | 'isVertexLabelsMovable' + | 'setVertexLabelsMovable' +>; +type PartialType = PartialGraph & PartialVertex; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphVertexMixin: PartialType = { /** * Specifies the return value for vertices in {@link isLabelMovable}. * @default false */ - vertexLabelsMovable = false; + vertexLabelsMovable: false, /** * Specifies if negative coordinates for vertices are allowed. * @default true */ - allowNegativeCoordinates = true; + allowNegativeCoordinates: true, /** * Returns {@link allowNegativeCoordinates}. */ isAllowNegativeCoordinates() { return this.allowNegativeCoordinates; - } + }, /** * Sets {@link allowNegativeCoordinates}. */ - setAllowNegativeCoordinates(value: boolean) { + setAllowNegativeCoordinates(value) { this.allowNegativeCoordinates = value; - } + }, /** * Function: insertVertex @@ -77,7 +116,7 @@ class GraphVertex extends autoImplement() { * geometryClass - Optional class reference to a class derived from mxGeometry. * This can be useful for defining custom constraints. */ - insertVertex = (...args: any[]) => { + insertVertex(...args) { let parent; let id; let value; @@ -124,7 +163,7 @@ class GraphVertex extends autoImplement() { ); return this.addCell(vertex, parent); - }; + }, /** * Function: createVertex @@ -132,16 +171,16 @@ class GraphVertex extends autoImplement() { * Hook method that creates the new vertex for . */ createVertex( - parent: Cell, - id: string, - value: any, - x: number, - y: number, - width: number, - height: number, - style: any, - relative: boolean = false, - geometryClass: typeof Geometry = Geometry + parent, + id, + value, + x, + y, + width, + height, + style, + relative = false, + geometryClass = Geometry ) { // Creates the geometry for the vertex const geometry = new geometryClass(x, y, width, height); @@ -154,16 +193,16 @@ class GraphVertex extends autoImplement() { vertex.setConnectable(true); return vertex; - } + }, /** * Returns the visible child vertices of the given parent. * * @param parent {@link mxCell} whose children should be returned. */ - getChildVertices(parent: Cell) { + getChildVertices(parent) { return this.getChildCells(parent, true, false); - } + }, /***************************************************************************** * Group: Graph Behaviour @@ -174,14 +213,14 @@ class GraphVertex extends autoImplement() { */ isVertexLabelsMovable() { return this.vertexLabelsMovable; - } + }, /** * Sets {@link vertexLabelsMovable}. */ - setVertexLabelsMovable(value: boolean) { + setVertexLabelsMovable(value) { this.vertexLabelsMovable = value; - } -} + }, +}; -export default GraphVertex; +mixInto(Graph)(GraphVertexMixin); diff --git a/packages/core/src/view/cell/vertex/VertexHandle.ts b/packages/core/src/view/cell/vertex/VertexHandle.ts index 3499caba0..e74cd06b2 100644 --- a/packages/core/src/view/cell/vertex/VertexHandle.ts +++ b/packages/core/src/view/cell/vertex/VertexHandle.ts @@ -25,7 +25,7 @@ import ImageBox from '../../image/ImageBox'; import CellState from '../datatypes/CellState'; import CellArray from '../datatypes/CellArray'; -import type { MaxGraph } from '../../Graph'; +import type { Graph } from '../../Graph'; import type { CellHandle, CellStateStyles } from '../../../types'; /** @@ -50,7 +50,7 @@ class VertexHandle implements CellHandle { this.init(); } - graph: MaxGraph; + graph: Graph; state: CellState; shape: Shape | ImageShape | null; diff --git a/packages/core/src/view/cell/vertex/VertexHandler.ts b/packages/core/src/view/cell/vertex/VertexHandler.ts index 1dac3fe1e..8a46beb12 100644 --- a/packages/core/src/view/cell/vertex/VertexHandler.ts +++ b/packages/core/src/view/cell/vertex/VertexHandler.ts @@ -29,7 +29,7 @@ import Point from '../../geometry/Point'; import { getRotatedPoint, intersects, mod, toRadians } from '../../../util/Utils'; import mxClient from '../../../mxClient'; import { isMouseEvent, isShiftDown } from '../../../util/EventUtils'; -import { MaxGraph } from '../../Graph'; +import { Graph } from '../../Graph'; import CellState from '../datatypes/CellState'; import Image from '../../image/ImageBox'; import Cell from '../datatypes/Cell'; @@ -74,7 +74,7 @@ class VertexHandler { // VML dialect required here for event transparency in IE this.selectionBorder.dialect = DIALECT_SVG; this.selectionBorder.pointerEvents = false; - this.selectionBorder.rotation = Number(this.state.style.rotation || '0'); + this.selectionBorder.rotation = this.state.style.rotation ?? 0; this.selectionBorder.init(this.graph.getView().getOverlayPane()); InternalEvent.redirectMouseEvents(this.selectionBorder.node, this.graph, this.state); @@ -193,7 +193,7 @@ class VertexHandler { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: state @@ -2009,7 +2009,7 @@ class VertexHandler { } if (this.selectionBorder != null) { - this.selectionBorder.rotation = Number(this.state.style.rotation || '0'); + this.selectionBorder.rotation = this.state.style.rotation ?? 0; } if (this.edgeHandlers != null) { @@ -2096,7 +2096,7 @@ class VertexHandler { // VML dialect required here for event transparency in IE this.parentHighlight.dialect = DIALECT_SVG; this.parentHighlight.pointerEvents = false; - this.parentHighlight.rotation = Number(pstate.style.rotation || '0'); + this.parentHighlight.rotation = pstate.style.rotation ?? 0; this.parentHighlight.init(this.graph.getView().getOverlayPane()); this.parentHighlight.redraw(); @@ -2122,7 +2122,7 @@ class VertexHandler { this.preview.bounds.height = Math.max(0, this.preview.bounds.height - 1); } - this.preview.rotation = Number(this.state.style.rotation || '0'); + this.preview.rotation = this.state.style.rotation ?? 0; this.preview.redraw(); } diff --git a/packages/core/src/view/connection/ConnectionHandler.ts b/packages/core/src/view/connection/ConnectionHandler.ts index 624059e10..388161a15 100644 --- a/packages/core/src/view/connection/ConnectionHandler.ts +++ b/packages/core/src/view/connection/ConnectionHandler.ts @@ -20,13 +20,7 @@ import { TOOLTIP_VERTICAL_OFFSET, VALID_COLOR, } from '../../util/Constants'; -import utils, { - convertPoint, - getOffset, - getRotatedPoint, - getValue, - toRadians, -} from '../../util/Utils'; +import { convertPoint, getOffset, getRotatedPoint, getValue } from '../../util/Utils'; import InternalMouseEvent from '../event/InternalMouseEvent'; import ImageShape from '../geometry/shape/node/ImageShape'; import CellMarker from '../cell/CellMarker'; @@ -42,10 +36,9 @@ import { isConsumed, isShiftDown, } from '../../util/EventUtils'; -import graph, { MaxGraph } from '../Graph'; import Image from '../image/ImageBox'; import CellState from '../cell/datatypes/CellState'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; import ConnectionConstraint from './ConnectionConstraint'; import Shape from '../geometry/shape/Shape'; import { GraphPlugin, Listenable } from '../../types'; @@ -212,7 +205,7 @@ type FactoryMethod = (source: Cell | null, target: Cell | null, style?: string) class ConnectionHandler extends EventSource implements GraphPlugin { static pluginId = 'ConnectionHandler'; - constructor(graph: MaxGraph, factoryMethod: FactoryMethod | null = null) { + constructor(graph: Graph, factoryMethod: FactoryMethod | null = null) { super(); this.graph = graph; @@ -279,7 +272,7 @@ class ConnectionHandler extends EventSource implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: factoryMethod diff --git a/packages/core/src/view/connection/ConstraintHandler.ts b/packages/core/src/view/connection/ConstraintHandler.ts index 4b046f5ef..92392efe9 100644 --- a/packages/core/src/view/connection/ConstraintHandler.ts +++ b/packages/core/src/view/connection/ConstraintHandler.ts @@ -20,7 +20,7 @@ import Rectangle from '../geometry/Rectangle'; import ImageShape from '../geometry/shape/node/ImageShape'; import RectangleShape from '../geometry/shape/node/RectangleShape'; import { isShiftDown } from '../../util/EventUtils'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import CellState from '../cell/datatypes/CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; import ConnectionConstraint from './ConnectionConstraint'; @@ -35,7 +35,7 @@ import Cell from '../cell/datatypes/Cell'; * @class ConstraintHandler */ class ConstraintHandler { - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.graph = graph; // Adds a graph model listener to update the current focus on changes @@ -66,7 +66,7 @@ class ConstraintHandler { /** * Reference to the enclosing {@link mxGraph}. */ - graph: MaxGraph; + graph: Graph; resetHandler: () => void; diff --git a/packages/core/src/view/connection/GraphConnections.ts b/packages/core/src/view/connection/GraphConnectionsMixin.ts similarity index 80% rename from packages/core/src/view/connection/GraphConnections.ts rename to packages/core/src/view/connection/GraphConnectionsMixin.ts index 608a0aa58..8545db4e8 100644 --- a/packages/core/src/view/connection/GraphConnections.ts +++ b/packages/core/src/view/connection/GraphConnectionsMixin.ts @@ -4,59 +4,143 @@ import InternalMouseEvent from '../event/InternalMouseEvent'; import ConnectionConstraint from './ConnectionConstraint'; import Rectangle from '../geometry/Rectangle'; import { DIRECTION_NORTH, DIRECTION_SOUTH, DIRECTION_WEST } from '../../util/Constants'; -import utils, { - autoImplement, - getRotatedPoint, - getValue, - toRadians, -} from '../../util/Utils'; +import { getRotatedPoint, mixInto, toRadians } from '../../util/Utils'; import Cell from '../cell/datatypes/Cell'; import CellArray from '../cell/datatypes/CellArray'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Dictionary from '../../util/Dictionary'; -import Geometry from '../geometry/Geometry'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; import ConnectionHandler from './ConnectionHandler'; -import GraphCells from '../cell/GraphCells'; -import GraphPorts from '../ports/GraphPorts'; -import GraphEdge from '../cell/edge/GraphEdge'; -type PartialGraph = Pick; -type PartialCells = Pick; -type PartialPorts = Pick; -type PartialEdge = Pick< - GraphEdge, +declare module '../Graph' { + interface Graph { + connectionHandler: ConnectionHandler | null; + constrainChildren: boolean; + constrainRelativeChildren: boolean; + disconnectOnMove: boolean; + cellsDisconnectable: boolean; + + getConnectionHandler: () => ConnectionHandler | null; + setConnectionHandler: (connectionHandler: ConnectionHandler) => void; + getOutlineConstraint: ( + point: Point, + terminalState: CellState, + me: InternalMouseEvent + ) => ConnectionConstraint | null; + getAllConnectionConstraints: ( + terminal: CellState | null, + source: boolean + ) => ConnectionConstraint[] | null; + getConnectionConstraint: ( + edge: CellState, + terminal: CellState | null, + source: boolean + ) => ConnectionConstraint; + setConnectionConstraint: ( + edge: Cell, + terminal: Cell | null, + source: boolean, + constraint: ConnectionConstraint | null + ) => void; + getConnectionPoint: ( + vertex: CellState, + constraint: ConnectionConstraint, + round?: boolean + ) => Point | null; + connectCell: ( + edge: Cell, + terminal: Cell | null, + source: boolean, + constraint?: ConnectionConstraint | null + ) => Cell; + cellConnected: ( + edge: Cell, + terminal: Cell | null, + source: boolean, + constraint?: ConnectionConstraint | null + ) => void; + disconnectGraph: (cells: CellArray) => void; + getConnections: (cell: Cell, parent: Cell | null) => CellArray; + isConstrainChild: (cell: Cell) => boolean; + isConstrainChildren: () => boolean; + setConstrainChildren: (value: boolean) => void; + isConstrainRelativeChildren: () => boolean; + setConstrainRelativeChildren: (value: boolean) => void; + isDisconnectOnMove: () => boolean; + setDisconnectOnMove: (value: boolean) => void; + isCellDisconnectable: (cell: Cell, terminal: Cell | null, source: boolean) => boolean; + isCellsDisconnectable: () => boolean; + setCellsDisconnectable: (value: boolean) => void; + isValidSource: (cell: Cell | null) => boolean; + isValidTarget: (cell: Cell | null) => boolean; + isValidConnection: (source: Cell | null, target: Cell | null) => boolean; + setConnectable: (connectable: boolean) => void; + isConnectable: () => boolean; + } +} + +type PartialGraph = Pick; +type PartialConnections = Pick< + Graph, + | 'connectionHandler' + | 'constrainChildren' + | 'constrainRelativeChildren' + | 'disconnectOnMove' + | 'cellsDisconnectable' + | 'getConnectionHandler' + | 'setConnectionHandler' + | 'getOutlineConstraint' + | 'getAllConnectionConstraints' + | 'getConnectionConstraint' + | 'setConnectionConstraint' + | 'getConnectionPoint' + | 'connectCell' + | 'cellConnected' + | 'disconnectGraph' + | 'getConnections' + | 'isConstrainChild' + | 'isConstrainChildren' + | 'setConstrainChildren' + | 'isConstrainRelativeChildren' + | 'setConstrainRelativeChildren' + | 'isDisconnectOnMove' + | 'setDisconnectOnMove' + | 'isCellDisconnectable' + | 'isCellsDisconnectable' + | 'setCellsDisconnectable' + | 'isValidSource' + | 'isValidTarget' + | 'isValidConnection' + | 'setConnectable' + | 'isConnectable' + | 'setCellStyles' + | 'fireEvent' + | 'isPort' + | 'getTerminalForPort' | 'isResetEdgesOnConnect' | 'resetEdge' | 'getEdges' + | 'isCellLocked' | 'isAllowDanglingEdges' | 'isConnectableEdges' >; -type PartialClass = PartialGraph & PartialCells & PartialPorts & PartialEdge; +type PartialType = PartialGraph & PartialConnections; -// @ts-ignore recursive reference error -class GraphConnections extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphConnectionsMixin: PartialType = { /***************************************************************************** * Group: Cell connecting and connection constraints *****************************************************************************/ - connectionHandler: ConnectionHandler | null = null; - - getConnectionHandler() { - return this.connectionHandler; - } - - setConnectionHandler(connectionHandler: ConnectionHandler) { - this.connectionHandler = connectionHandler; - } + connectionHandler: null, /** * Specifies if a child should be constrained inside the parent bounds after a * move or resize of the child. * @default true */ - constrainChildren = true; + constrainChildren: true, /** * Specifies if child cells with relative geometries should be constrained @@ -64,21 +148,29 @@ class GraphConnections extends autoImplement() { * {@link maximumGraphBounds}. * @default false */ - constrainRelativeChildren = false; + constrainRelativeChildren: false, /** * Specifies if edges should be disconnected from their terminals when they * are moved. * @default true */ - disconnectOnMove = true; + disconnectOnMove: true, - cellsDisconnectable = true; + cellsDisconnectable: true, + + getConnectionHandler() { + return this.connectionHandler; + }, + + setConnectionHandler(connectionHandler) { + this.connectionHandler = connectionHandler; + }, /** * Returns the constraint used to connect to the outline of the given state. */ - getOutlineConstraint(point: Point, terminalState: CellState, me: InternalMouseEvent) { + getOutlineConstraint(point, terminalState, me) { if (terminalState.shape) { const bounds = this.getView().getPerimeterBounds(terminalState); const direction = terminalState.style.direction; @@ -145,7 +237,7 @@ class GraphConnections extends autoImplement() { return new ConnectionConstraint(new Point(x, y), false); } return null; - } + }, /** * Returns an array of all {@link mxConnectionConstraints} for the given terminal. If @@ -155,12 +247,12 @@ class GraphConnections extends autoImplement() { * @param terminal {@link mxCellState} that represents the terminal. * @param source Boolean that specifies if the terminal is the source or target. */ - getAllConnectionConstraints(terminal: CellState | null, source: boolean) { + getAllConnectionConstraints(terminal, source) { if (terminal && terminal.shape && terminal.shape.stencil) { return terminal.shape.stencil.constraints; } return null; - } + }, /** * Returns an {@link ConnectionConstraint} that describes the given connection @@ -170,11 +262,7 @@ class GraphConnections extends autoImplement() { * @param terminal {@link mxCellState} that represents the terminal. * @param source Boolean indicating if the terminal is the source or target. */ - getConnectionConstraint( - edge: CellState, - terminal: CellState | null, - source: boolean = false - ) { + getConnectionConstraint(edge, terminal, source = false) { let point: Point | null = null; const x = edge.style[source ? 'exitX' : 'entryX']; @@ -203,7 +291,7 @@ class GraphConnections extends autoImplement() { } return new ConnectionConstraint(point, perimeter, null, dx, dy); - } + }, /** * Sets the {@link ConnectionConstraint} that describes the given connection point. @@ -216,12 +304,7 @@ class GraphConnections extends autoImplement() { * @param constraint Optional {@link ConnectionConstraint} to be used for this * connection. */ - setConnectionConstraint( - edge: Cell, - terminal: Cell | null, - source: boolean = false, - constraint: ConnectionConstraint | null = null - ) { + setConnectionConstraint(edge, terminal, source = false, constraint = null) { if (constraint) { this.getModel().beginUpdate(); @@ -277,7 +360,7 @@ class GraphConnections extends autoImplement() { this.getModel().endUpdate(); } } - } + }, /** * Returns the nearest point in the list of absolute points or the center @@ -287,11 +370,7 @@ class GraphConnections extends autoImplement() { * @param constraint {@link mxConnectionConstraint} that represents the connection point * constraint as returned by {@link getConnectionConstraint}. */ - getConnectionPoint( - vertex: CellState, - constraint: ConnectionConstraint, - round: boolean = true - ) { + getConnectionPoint(vertex, constraint, round = true) { let point: Point | null = null; if (constraint.point) { @@ -381,7 +460,7 @@ class GraphConnections extends autoImplement() { point.y = Math.round(point.y); } return point; - } + }, /** * Connects the specified end of the given edge to the given terminal @@ -394,12 +473,7 @@ class GraphConnections extends autoImplement() { * @param constraint Optional {@link ConnectionConstraint} to be used for this * connection. */ - connectCell( - edge: Cell, - terminal: Cell | null = null, - source: boolean = false, - constraint: ConnectionConstraint | null = null - ) { + connectCell(edge, terminal = null, source = false, constraint = null) { this.getModel().beginUpdate(); try { const previous = edge.getTerminal(source); @@ -421,7 +495,7 @@ class GraphConnections extends autoImplement() { this.getModel().endUpdate(); } return edge; - } + }, /** * Sets the new terminal for the given edge and resets the edge points if @@ -433,12 +507,7 @@ class GraphConnections extends autoImplement() { * @param source Boolean indicating if the new terminal is the source or target. * @param constraint {@link mxConnectionConstraint} to be used for this connection. */ - cellConnected( - edge: Cell, - terminal: Cell | null, - source: boolean = false, - constraint: ConnectionConstraint | null = null - ) { + cellConnected(edge, terminal, source = false, constraint = null) { this.getModel().beginUpdate(); try { const previous = edge.getTerminal(source); @@ -483,7 +552,7 @@ class GraphConnections extends autoImplement() { } finally { this.getModel().endUpdate(); } - } + }, /** * Disconnects the given edges from the terminals which are not in the @@ -491,7 +560,7 @@ class GraphConnections extends autoImplement() { * * @param cells Array of {@link Cell} to be disconnected. */ - disconnectGraph(cells: CellArray) { + disconnectGraph(cells) { this.getModel().beginUpdate(); try { const { scale, translate: tr } = this.getView(); @@ -564,7 +633,7 @@ class GraphConnections extends autoImplement() { } finally { this.getModel().endUpdate(); } - } + }, /** * Returns all visible edges connected to the given cell without loops. @@ -573,9 +642,9 @@ class GraphConnections extends autoImplement() { * @param parent Optional parent of the opposite end for a connection to be * returned. */ - getConnections(cell: Cell, parent: Cell | null = null) { + getConnections(cell, parent = null) { return this.getEdges(cell, parent, true, true, false); - } + }, /** * Returns true if the given cell should be kept inside the bounds of its @@ -585,41 +654,41 @@ class GraphConnections extends autoImplement() { * * @param cell {@link mxCell} that should be constrained. */ - isConstrainChild(cell: Cell) { + isConstrainChild(cell) { return ( this.isConstrainChildren() && !!cell.getParent() && !(cell.getParent()).isEdge() ); - } + }, /** * Returns {@link constrainChildren}. */ isConstrainChildren() { return this.constrainChildren; - } + }, /** * Sets {@link constrainChildren}. */ - setConstrainChildren(value: boolean) { + setConstrainChildren(value) { this.constrainChildren = value; - } + }, /** * Returns {@link constrainRelativeChildren}. */ isConstrainRelativeChildren() { return this.constrainRelativeChildren; - } + }, /** * Sets {@link constrainRelativeChildren}. */ - setConstrainRelativeChildren(value: boolean) { + setConstrainRelativeChildren(value) { this.constrainRelativeChildren = value; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -630,7 +699,7 @@ class GraphConnections extends autoImplement() { */ isDisconnectOnMove() { return this.disconnectOnMove; - } + }, /** * Specifies if edges should be disconnected when moved. (Note: Cloned @@ -639,9 +708,9 @@ class GraphConnections extends autoImplement() { * @param value Boolean indicating if edges should be disconnected * when moved. */ - setDisconnectOnMove(value: boolean) { + setDisconnectOnMove(value) { this.disconnectOnMove = value; - } + }, /** * Returns true if the given cell is disconnectable from the source or @@ -653,27 +722,23 @@ class GraphConnections extends autoImplement() { * @param source Boolean indicating if the source or target terminal is to be * disconnected. */ - isCellDisconnectable( - cell: Cell, - terminal: Cell | null = null, - source: boolean = false - ) { + isCellDisconnectable(cell, terminal = null, source = false) { return this.isCellsDisconnectable() && !this.isCellLocked(cell); - } + }, /** * Returns {@link cellsDisconnectable}. */ isCellsDisconnectable() { return this.cellsDisconnectable; - } + }, /** * Sets {@link cellsDisconnectable}. */ - setCellsDisconnectable(value: boolean) { + setCellsDisconnectable(value) { this.cellsDisconnectable = value; - } + }, /** * Returns true if the given cell is a valid source for new connections. @@ -682,14 +747,14 @@ class GraphConnections extends autoImplement() { * * @param cell {@link mxCell} that represents a possible source or null. */ - isValidSource(cell: Cell | null) { + isValidSource(cell) { return ( (cell == null && this.isAllowDanglingEdges()) || (cell != null && (!cell.isEdge() || this.isConnectableEdges()) && cell.isConnectable()) ); - } + }, /** * Returns {@link isValidSource} for the given cell. This is called by @@ -697,9 +762,9 @@ class GraphConnections extends autoImplement() { * * @param cell {@link mxCell} that represents a possible target or null. */ - isValidTarget(cell: Cell | null): boolean { + isValidTarget(cell) { return this.isValidSource(cell); - } + }, /** * Returns true if the given target cell is a valid target for source. @@ -711,9 +776,9 @@ class GraphConnections extends autoImplement() { * @param source {@link mxCell} that represents the source cell. * @param target {@link mxCell} that represents the target cell. */ - isValidConnection(source: Cell | null, target: Cell | null): boolean { + isValidConnection(source, target) { return this.isValidSource(source) && this.isValidTarget(target); - } + }, /** * Specifies if the graph should allow new connections. This implementation @@ -721,16 +786,16 @@ class GraphConnections extends autoImplement() { * * @param connectable Boolean indicating if new connections should be allowed. */ - setConnectable(connectable: boolean) { + setConnectable(connectable) { (this.connectionHandler).setEnabled(connectable); - } + }, /** * Returns true if the {@link connectionHandler} is enabled. */ isConnectable() { return (this.connectionHandler).isEnabled(); - } -} + }, +}; -export default GraphConnections; +mixInto(Graph)(GraphConnectionsMixin); diff --git a/packages/core/src/view/drag_drop/DragSource.ts b/packages/core/src/view/drag_drop/DragSource.ts index 51a307bde..e65dd9a90 100644 --- a/packages/core/src/view/drag_drop/DragSource.ts +++ b/packages/core/src/view/drag_drop/DragSource.ts @@ -6,7 +6,7 @@ */ import Rectangle from '../geometry/Rectangle'; import CellHighlight from '../selection/CellHighlight'; -import utils, { +import { getDocumentScrollOrigin, getOffset, getScrollOrigin, @@ -28,15 +28,13 @@ import { } from '../../util/EventUtils'; import EventSource from '../event/EventSource'; import EventObject from '../event/EventObject'; -import { MaxGraph } from '../Graph'; -import InternalMouseEvent from '../event/InternalMouseEvent'; +import { Graph } from '../Graph'; import Guide from '../../util/Guide'; import Cell from '../cell/datatypes/Cell'; -import { GraphPlugin } from '../../types'; import GraphHandler from '../GraphHandler'; type DropHandler = ( - graph: MaxGraph, + graph: Graph, evt: MouseEvent, cell: Cell | null, x?: number, @@ -123,7 +121,7 @@ class DragSource { /** * Reference to the {@link mxGraph} that is the current drop target. */ - currentGraph: MaxGraph | null = null; + currentGraph: Graph | null = null; /** * Holds the current drop target under the mouse. @@ -241,7 +239,7 @@ class DragSource { * Returns the drop target for the given graph and coordinates. This * implementation uses {@link mxGraph.getCellAt}. */ - getDropTarget(graph: MaxGraph, x: number, y: number, evt: MouseEvent) { + getDropTarget(graph: Graph, x: number, y: number, evt: MouseEvent) { return graph.getCellAt(x, y); } @@ -257,7 +255,7 @@ class DragSource { * Creates and returns an element which can be used as a preview in the given * graph. */ - createPreviewElement(graph: MaxGraph): HTMLElement | null { + createPreviewElement(graph: Graph): HTMLElement | null { return null; } @@ -378,7 +376,7 @@ class DragSource { /** * Returns true if the given graph contains the given event. */ - graphContainsEvent(graph: MaxGraph, evt: MouseEvent) { + graphContainsEvent(graph: Graph, evt: MouseEvent) { const x = getClientX(evt); const y = getClientY(evt); const offset = getOffset(graph.container); @@ -516,7 +514,7 @@ class DragSource { /** * Actives the given graph as a drop target. */ - dragEnter(graph: MaxGraph, evt: MouseEvent) { + dragEnter(graph: Graph, evt: MouseEvent) { graph.isMouseDown = true; graph.isMouseTrigger = isMouseEvent(evt); this.previewElement = this.createPreviewElement(graph); @@ -542,7 +540,7 @@ class DragSource { /** * Deactivates the given graph as a drop target. */ - dragExit(graph: MaxGraph, evt?: MouseEvent) { + dragExit(graph: Graph, evt?: MouseEvent) { this.currentDropTarget = null; this.currentPoint = null; graph.isMouseDown = false; @@ -573,7 +571,7 @@ class DragSource { * Implements autoscroll, updates the {@link currentPoint}, highlights any drop * targets and updates the preview. */ - dragOver(graph: MaxGraph, evt: MouseEvent) { + dragOver(graph: Graph, evt: MouseEvent) { const offset = getOffset(graph.container); const origin = getScrollOrigin(graph.container); let x = getClientX(evt) - offset.x + origin.x - graph.getPanDx(); @@ -646,7 +644,7 @@ class DragSource { * implementation uses {@link mxGraph.getCellAt}. */ drop( - graph: MaxGraph, + graph: Graph, evt: MouseEvent, dropTarget: Cell | null = null, x: number, diff --git a/packages/core/src/view/drag_drop/GraphDragDrop.ts b/packages/core/src/view/drag_drop/GraphDragDropMixin.ts similarity index 68% rename from packages/core/src/view/drag_drop/GraphDragDrop.ts rename to packages/core/src/view/drag_drop/GraphDragDropMixin.ts index 8d2bc1296..52a33657c 100644 --- a/packages/core/src/view/drag_drop/GraphDragDrop.ts +++ b/packages/core/src/view/drag_drop/GraphDragDropMixin.ts @@ -1,19 +1,49 @@ -import { autoImplement } from '../../util/Utils'; +import { mixInto } from '../../util/Utils'; import Cell from '../cell/datatypes/Cell'; import CellArray from '../cell/datatypes/CellArray'; -import InternalMouseEvent from '../event/InternalMouseEvent'; +import { Graph } from '../Graph'; -import type GraphValidation from '../validation/GraphValidation'; +declare module '../Graph' { + interface Graph { + dropEnabled: boolean; + splitEnabled: boolean; + autoScroll: boolean; + autoExtend: boolean; -type PartialValidation = Pick; -type PartialClass = PartialValidation; + isAutoScroll: () => boolean; + isAutoExtend: () => boolean; + isDropEnabled: () => boolean; + setDropEnabled: (value: boolean) => void; + isSplitEnabled: () => boolean; + setSplitEnabled: (value: boolean) => void; + isSplitTarget: (target: Cell, cells: CellArray, evt: MouseEvent) => boolean; + } +} -class GraphDragDrop extends autoImplement() { +type PartialGraph = Pick; +type PartialDragDrop = Pick< + Graph, + | 'dropEnabled' + | 'splitEnabled' + | 'autoScroll' + | 'autoExtend' + | 'isAutoScroll' + | 'isAutoExtend' + | 'isDropEnabled' + | 'setDropEnabled' + | 'isSplitEnabled' + | 'setSplitEnabled' + | 'isSplitTarget' +>; +type PartialType = PartialGraph & PartialDragDrop; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphDragDropMixin: PartialType = { /** * Specifies the return value for {@link isDropEnabled}. * @default false */ - dropEnabled = false; + dropEnabled: false, /** * Specifies if dropping onto edges should be enabled. This is ignored if @@ -21,7 +51,7 @@ class GraphDragDrop extends autoImplement() { * out the drop operation. * @default true */ - splitEnabled = true; + splitEnabled: true, /** * Specifies if the graph should automatically scroll if the mouse goes near @@ -33,9 +63,11 @@ class GraphDragDrop extends autoImplement() { * no scrollbars, the use of {@link allowAutoPanning} is recommended. * @default true */ - autoScroll = true; + autoScroll: true, - isAutoScroll = () => this.autoScroll; + isAutoScroll() { + return this.autoScroll; + }, /** * Specifies if the size of the graph should be automatically extended if the @@ -43,9 +75,11 @@ class GraphDragDrop extends autoImplement() { * account if the container has scrollbars. See {@link autoScroll}. * @default true */ - autoExtend = true; + autoExtend: true, - isAutoExtend = () => this.autoExtend; + isAutoExtend() { + return this.autoExtend; + }, /***************************************************************************** * Group: Graph behaviour @@ -56,7 +90,7 @@ class GraphDragDrop extends autoImplement() { */ isDropEnabled() { return this.dropEnabled; - } + }, /** * Specifies if the graph should allow dropping of cells onto or into other @@ -65,9 +99,9 @@ class GraphDragDrop extends autoImplement() { * @param dropEnabled Boolean indicating if the graph should allow dropping * of cells into other cells. */ - setDropEnabled(value: boolean) { + setDropEnabled(value) { this.dropEnabled = value; - } + }, /***************************************************************************** * Group: Split behaviour @@ -78,7 +112,7 @@ class GraphDragDrop extends autoImplement() { */ isSplitEnabled() { return this.splitEnabled; - } + }, /** * Specifies if the graph should allow dropping of cells onto or into other @@ -87,9 +121,9 @@ class GraphDragDrop extends autoImplement() { * @param dropEnabled Boolean indicating if the graph should allow dropping * of cells into other cells. */ - setSplitEnabled(value: boolean) { + setSplitEnabled(value) { this.splitEnabled = value; - } + }, /** * Returns true if the given edge may be splitted into two edges with the @@ -99,7 +133,7 @@ class GraphDragDrop extends autoImplement() { * @param cells {@link mxCell} that should split the edge. * @param evt Mouseevent that triggered the invocation. */ - isSplitTarget(target: Cell, cells: CellArray, evt: MouseEvent) { + isSplitTarget(target, cells, evt) { if ( target.isEdge() && cells.length === 1 && @@ -112,7 +146,7 @@ class GraphDragDrop extends autoImplement() { return !cells[0].isAncestor(src) && !cells[0].isAncestor(trg); } return false; - } -} + }, +}; -export default GraphDragDrop; +mixInto(Graph)(GraphDragDropMixin); diff --git a/packages/core/src/view/editing/CellEditor.ts b/packages/core/src/view/editing/CellEditor.ts index f5ccbec55..d00589c8a 100644 --- a/packages/core/src/view/editing/CellEditor.ts +++ b/packages/core/src/view/editing/CellEditor.ts @@ -48,7 +48,7 @@ import { } from '../../util/EventUtils'; import EventSource from '../event/EventSource'; -import type { MaxGraph } from '../Graph'; +import type { Graph } from '../Graph'; import type { GraphPlugin } from '../../types'; import CellArray from '../cell/datatypes/CellArray'; import TooltipHandler from '../tooltip/TooltipHandler'; @@ -162,7 +162,7 @@ import TooltipHandler from '../tooltip/TooltipHandler'; class CellEditor implements GraphPlugin { static pluginId = 'CellEditor'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.graph = graph; // Stops editing after zoom changes @@ -202,7 +202,7 @@ class CellEditor implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: textarea diff --git a/packages/core/src/view/editing/GraphEditing.ts b/packages/core/src/view/editing/GraphEditingMixin.ts similarity index 76% rename from packages/core/src/view/editing/GraphEditing.ts rename to packages/core/src/view/editing/GraphEditingMixin.ts index 20fe08c29..2a6cef37f 100644 --- a/packages/core/src/view/editing/GraphEditing.ts +++ b/packages/core/src/view/editing/GraphEditingMixin.ts @@ -3,32 +3,62 @@ import { isMultiTouchEvent } from '../../util/EventUtils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import InternalMouseEvent from '../event/InternalMouseEvent'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type GraphSelection from '../selection/GraphSelection'; -import type GraphEvents from '../event/GraphEvents'; -import type Graph from '../Graph'; -import type GraphCells from '../cell/GraphCells'; +declare module '../Graph' { + interface Graph { + cellsEditable: boolean; + + startEditing: (evt: MouseEvent) => void; + startEditingAtCell: (cell: Cell | null, evt: MouseEvent) => void; + getEditingValue: (cell: Cell, evt: MouseEvent | null) => string; + stopEditing: (cancel: boolean) => void; + labelChanged: (cell: Cell, value: any, evt: InternalMouseEvent | EventObject) => Cell; + cellLabelChanged: (cell: Cell, value: any, autoSize: boolean) => void; + isEditing: (cell?: Cell | null) => boolean; + isCellEditable: (cell: Cell) => boolean; + isCellsEditable: () => boolean; + setCellsEditable: (value: boolean) => void; + } +} type PartialGraph = Pick< Graph, - 'getCellEditor' | 'convertValueToString' | 'batchUpdate' | 'getModel' + | 'getCellEditor' + | 'convertValueToString' + | 'batchUpdate' + | 'getModel' + | 'getSelectionCell' + | 'fireEvent' + | 'isAutoSizeCell' + | 'cellSizeUpdated' + | 'getCurrentCellStyle' + | 'isCellLocked' >; -type PartialSelection = Pick; -type PartialEvents = Pick; -type PartialCells = Pick< - GraphCells, - 'isAutoSizeCell' | 'cellSizeUpdated' | 'getCurrentCellStyle' | 'isCellLocked' +type PartialEditing = Pick< + Graph, + | 'cellsEditable' + | 'startEditing' + | 'startEditingAtCell' + | 'getEditingValue' + | 'stopEditing' + | 'labelChanged' + | 'cellLabelChanged' + | 'isEditing' + | 'isCellEditable' + | 'isCellsEditable' + | 'setCellsEditable' >; -type PartialClass = PartialGraph & PartialSelection & PartialEvents & PartialCells; +type PartialType = PartialGraph & PartialEditing; -// @ts-ignore recursive reference error -class GraphEditing extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphEditingMixin: PartialType = { /** * Specifies the return value for {@link isCellEditable}. * @default true */ - cellsEditable = true; + cellsEditable: true, /***************************************************************************** * Group: Cell in-place editing @@ -40,9 +70,9 @@ class GraphEditing extends autoImplement() { * * @param evt Optional mouse event that triggered the editing. */ - startEditing(evt: MouseEvent) { + startEditing(evt) { this.startEditingAtCell(null, evt); - } + }, /** * Fires a {@link startEditing} event and invokes {@link CellEditor.startEditing} @@ -52,7 +82,7 @@ class GraphEditing extends autoImplement() { * @param cell {@link mxCell} to start the in-place editor for. * @param evt Optional mouse event that triggered the editing. */ - startEditingAtCell(cell: Cell | null = null, evt: MouseEvent) { + startEditingAtCell(cell = null, evt) { if (!evt || !isMultiTouchEvent(evt)) { if (!cell) { cell = this.getSelectionCell(); @@ -70,7 +100,7 @@ class GraphEditing extends autoImplement() { ); } } - } + }, /** * Returns the initial value for in-place editing. This implementation @@ -81,9 +111,9 @@ class GraphEditing extends autoImplement() { * @param cell {@link mxCell} for which the initial editing value should be returned. * @param evt Optional mouse event that triggered the editor. */ - getEditingValue(cell: Cell, evt: MouseEvent | null) { + getEditingValue(cell, evt) { return this.convertValueToString(cell); - } + }, /** * Stops the current editing and fires a {@link editingStopped} event. @@ -91,10 +121,10 @@ class GraphEditing extends autoImplement() { * @param cancel Boolean that specifies if the current editing value * should be stored. */ - stopEditing(cancel: boolean = false) { + stopEditing(cancel = false) { this.getCellEditor().stopEditing(cancel); this.fireEvent(new EventObject(InternalEvent.EDITING_STOPPED, 'cancel', cancel)); - } + }, /** * Sets the label of the specified cell to the given value using @@ -105,7 +135,7 @@ class GraphEditing extends autoImplement() { * @param value New label to be assigned. * @param evt Optional event that triggered the change. */ - labelChanged(cell: Cell, value: any, evt: InternalMouseEvent | EventObject) { + labelChanged(cell, value, evt) { this.batchUpdate(() => { const old = cell.value; this.cellLabelChanged(cell, value, this.isAutoSizeCell(cell)); @@ -119,7 +149,7 @@ class GraphEditing extends autoImplement() { ); }); return cell; - } + }, /** * Sets the new label for a cell. If autoSize is true then @@ -148,7 +178,7 @@ class GraphEditing extends autoImplement() { * @param value New label to be assigned. * @param autoSize Boolean that specifies if {@link cellSizeUpdated} should be called. */ - cellLabelChanged(cell: Cell, value: any, autoSize: boolean = false) { + cellLabelChanged(cell, value, autoSize = false) { this.batchUpdate(() => { this.getModel().setValue(cell, value); @@ -156,7 +186,7 @@ class GraphEditing extends autoImplement() { this.cellSizeUpdated(cell, false); } }); - } + }, /***************************************************************************** * Group: Graph behaviour @@ -169,10 +199,10 @@ class GraphEditing extends autoImplement() { * * @param cell {@link mxCell} that should be checked. */ - isEditing(cell: Cell | null = null) { + isEditing(cell = null) { const editingCell = this.getCellEditor().getEditingCell(); return !cell ? !!editingCell : cell === editingCell; - } + }, /** * Returns true if the given cell is editable. This returns {@link cellsEditable} for @@ -181,18 +211,18 @@ class GraphEditing extends autoImplement() { * * @param cell {@link mxCell} whose editable state should be returned. */ - isCellEditable(cell: Cell) { + isCellEditable(cell) { const style = this.getCurrentCellStyle(cell); return this.isCellsEditable() && !this.isCellLocked(cell) && style.editable; - } + }, /** * Returns {@link cellsEditable}. */ isCellsEditable() { return this.cellsEditable; - } + }, /** * Specifies if the graph should allow in-place editing for cell labels. @@ -201,9 +231,9 @@ class GraphEditing extends autoImplement() { * @param value Boolean indicating if the graph should allow in-place * editing. */ - setCellsEditable(value: boolean) { + setCellsEditable(value) { this.cellsEditable = value; - } -} + }, +}; -export default GraphEditing; +mixInto(Graph)(GraphEditingMixin); diff --git a/packages/core/src/view/event/CellTracker.ts b/packages/core/src/view/event/CellTracker.ts index d72f79751..c7428b2f2 100644 --- a/packages/core/src/view/event/CellTracker.ts +++ b/packages/core/src/view/event/CellTracker.ts @@ -6,7 +6,7 @@ */ import CellMarker from '../cell/CellMarker'; import InternalMouseEvent from './InternalMouseEvent'; -import Graph, { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import Cell from '../cell/datatypes/Cell'; import EventSource from './EventSource'; @@ -67,7 +67,7 @@ import EventSource from './EventSource'; */ class CellTracker extends CellMarker { constructor( - graph: MaxGraph, + graph: Graph, color: string, funct: ((me: InternalMouseEvent) => Cell) | null = null ) { diff --git a/packages/core/src/view/event/GraphEvents.ts b/packages/core/src/view/event/GraphEventsMixin.ts similarity index 80% rename from packages/core/src/view/event/GraphEvents.ts rename to packages/core/src/view/event/GraphEventsMixin.ts index 7aea83ed1..8bfa2d9c8 100644 --- a/packages/core/src/view/event/GraphEvents.ts +++ b/packages/core/src/view/event/GraphEventsMixin.ts @@ -21,94 +21,248 @@ import Cell from '../cell/datatypes/Cell'; import PanningHandler from '../panning/PanningHandler'; import ConnectionHandler from '../connection/ConnectionHandler'; import Point from '../geometry/Point'; -import { convertPoint, getValue, autoImplement } from '../../util/Utils'; +import { convertPoint, mixInto } from '../../util/Utils'; import { NONE, SHAPE_SWIMLANE } from '../../util/Constants'; import mxClient from '../../mxClient'; import EventSource from './EventSource'; import CellEditor from '../editing/CellEditor'; - -import type Graph from '../Graph'; -import type GraphCells from '../cell/GraphCells'; -import type GraphSelection from '../selection/GraphSelection'; -import type GraphEditing from '../editing/GraphEditing'; -import type GraphSnap from '../snap/GraphSnap'; -import { MouseEventListener, MouseListenerSet } from '../../types'; +import { Graph } from '../Graph'; import TooltipHandler from '../tooltip/TooltipHandler'; -import GraphDragDrop from '../drag_drop/GraphDragDrop'; -import GraphPageBreaks from '../page_breaks/GraphPageBreaks'; + +import type { MouseEventListener, MouseListenerSet } from '../../types'; + +declare module '../Graph' { + interface Graph { + mouseListeners: MouseListenerSet[]; + lastTouchEvent: MouseEvent | null; + doubleClickCounter: number; + lastTouchCell: Cell | null; + fireDoubleClick: boolean | null; + tapAndHoldThread: number | null; + lastMouseX: number | null; + lastMouseY: number | null; + isMouseTrigger: boolean | null; + ignoreMouseEvents: boolean | null; + mouseMoveRedirect: MouseEventListener | null; + mouseUpRedirect: MouseEventListener | null; + lastEvent: any; // FIXME: Check if this can be more specific - DOM events or mxEventObjects! + escapeEnabled: boolean; + invokesStopCellEditing: boolean; + enterStopsCellEditing: boolean; + isMouseDown: boolean; + nativeDblClickEnabled: boolean; + doubleTapEnabled: boolean; + doubleTapTimeout: number; + doubleTapTolerance: number; + lastTouchX: number; + lastTouchY: number; + lastTouchTime: number; + tapAndHoldEnabled: boolean; + tapAndHoldDelay: number; + tapAndHoldInProgress: boolean; + tapAndHoldValid: boolean; + initialTouchX: number; + initialTouchY: number; + tolerance: number; + + isNativeDblClickEnabled: () => boolean; + getEventTolerance: () => number; + escape: (evt: Event) => void; + click: (me: InternalMouseEvent) => boolean; + dblClick: (evt: MouseEvent, cell?: Cell | null) => void; + tapAndHold: (me: InternalMouseEvent) => void; + addMouseListener: (listener: MouseListenerSet) => void; + removeMouseListener: (listener: MouseListenerSet) => void; + updateMouseEvent: (me: InternalMouseEvent, evtName: string) => InternalMouseEvent; + getStateForTouchEvent: (evt: MouseEvent) => CellState | null; + isEventIgnored: ( + evtName: string, + me: InternalMouseEvent, + sender: EventSource + ) => boolean; + isSyntheticEventIgnored: ( + evtName: string, + me: InternalMouseEvent, + sender: any + ) => boolean; + isEventSourceIgnored: (evtName: string, me: InternalMouseEvent) => boolean; + getEventState: (state: CellState) => CellState; + fireMouseEvent: ( + evtName: string, + me: InternalMouseEvent, + sender?: EventSource + ) => void; + consumeMouseEvent: ( + evtName: string, + me: InternalMouseEvent, + sender: EventSource + ) => void; + fireGestureEvent: (evt: MouseEvent, cell?: Cell | null) => void; + sizeDidChange: () => void; + isCloneEvent: (evt: MouseEvent) => boolean; + isTransparentClickEvent: (evt: MouseEvent) => boolean; + isToggleEvent: (evt: MouseEvent) => boolean; + isGridEnabledEvent: (evt: MouseEvent) => boolean; + isConstrainedEvent: (evt: MouseEvent) => boolean; + isIgnoreTerminalEvent: (evt: MouseEvent) => boolean; + getPointForEvent: (evt: MouseEvent, addOffset?: boolean) => Point; + isEscapeEnabled: () => boolean; + setEscapeEnabled: (value: boolean) => void; + isInvokesStopCellEditing: () => boolean; + setInvokesStopCellEditing: (value: boolean) => void; + isEnterStopsCellEditing: () => boolean; + setEnterStopsCellEditing: (value: boolean) => void; + getCursorForMouseEvent: (me: InternalMouseEvent) => string | null; + } +} type PartialGraph = Pick< Graph, | 'fireEvent' | 'isEnabled' - | 'getView' - | 'getGraphBounds' - | 'getContainer' - | 'paintBackground' + | 'getCellAt' + | 'isCellSelected' + | 'selectCellForEvent' + | 'clearSelection' + | 'isCellEditable' + | 'isEditing' + | 'startEditingAtCell' | 'getPlugin' + | 'getView' + | 'getContainer' | 'getPanDx' | 'getPanDy' - | 'getMinimumContainerSize' + | 'getEventSource' + | 'setEventSource' + | 'isAutoScroll' + | 'getGraphBounds' | 'scrollPointToVisible' | 'isIgnoreScrollbars' | 'isTranslateToScrollPosition' + | 'isAutoExtend' + | 'isEditing' + | 'stopEditing' | 'getBorder' + | 'getMinimumContainerSize' | 'isResizeContainer' | 'doResizeContainer' | 'isPreferPageSize' | 'isPageVisible' | 'getPreferredPageSize' | 'getMinimumGraphSize' + | 'getGridSize' + | 'snap' + | 'getCursorForCell' + | 'paintBackground' + | 'updatePageBreaks' | 'isPageBreaksVisible' >; -type PartialCells = Pick; -type PartialSelection = Pick< - GraphSelection, - 'isCellSelected' | 'selectCellForEvent' | 'clearSelection' +type PartialEvents = Pick< + Graph, + | 'mouseListeners' + | 'lastTouchEvent' + | 'doubleClickCounter' + | 'lastTouchCell' + | 'fireDoubleClick' + | 'tapAndHoldThread' + | 'lastMouseX' + | 'lastMouseY' + | 'isMouseTrigger' + | 'ignoreMouseEvents' + | 'mouseMoveRedirect' + | 'mouseUpRedirect' + | 'lastEvent' + | 'escapeEnabled' + | 'invokesStopCellEditing' + | 'enterStopsCellEditing' + | 'isMouseDown' + | 'nativeDblClickEnabled' + | 'doubleTapEnabled' + | 'doubleTapTimeout' + | 'doubleTapTolerance' + | 'lastTouchX' + | 'lastTouchY' + | 'lastTouchTime' + | 'tapAndHoldEnabled' + | 'tapAndHoldDelay' + | 'tapAndHoldInProgress' + | 'tapAndHoldValid' + | 'initialTouchX' + | 'initialTouchY' + | 'tolerance' + | 'isNativeDblClickEnabled' + | 'getEventTolerance' + | 'escape' + | 'click' + | 'dblClick' + | 'tapAndHold' + | 'addMouseListener' + | 'removeMouseListener' + | 'updateMouseEvent' + | 'getStateForTouchEvent' + | 'isEventIgnored' + | 'isSyntheticEventIgnored' + | 'isEventSourceIgnored' + | 'getEventState' + | 'fireMouseEvent' + | 'consumeMouseEvent' + | 'fireGestureEvent' + | 'sizeDidChange' + | 'isCloneEvent' + | 'isTransparentClickEvent' + | 'isToggleEvent' + | 'isGridEnabledEvent' + | 'isConstrainedEvent' + | 'isIgnoreTerminalEvent' + | 'getPointForEvent' + | 'isEscapeEnabled' + | 'setEscapeEnabled' + | 'isInvokesStopCellEditing' + | 'setInvokesStopCellEditing' + | 'isEnterStopsCellEditing' + | 'setEnterStopsCellEditing' + | 'getCursorForMouseEvent' >; -type PartialEditing = Pick< - GraphEditing, - 'isCellEditable' | 'isEditing' | 'startEditingAtCell' | 'stopEditing' ->; -type PartialSnap = Pick; -type PartialDragDrop = Pick; -type PartialPageBreaks = Pick; -type PartialClass = PartialGraph & - PartialCells & - PartialSelection & - PartialEditing & - PartialSnap & - PartialDragDrop & - PartialPageBreaks & - EventSource; +type PartialType = PartialGraph & PartialEvents; -// @ts-ignore recursive reference error -class GraphEvents extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphEventsMixin: PartialType = { /** * Holds the mouse event listeners. See {@link fireMouseEvent}. */ - mouseListeners: MouseListenerSet[] = []; + mouseListeners: [], // TODO: Document me! - lastTouchEvent: MouseEvent | null = null; - doubleClickCounter: number = 0; - lastTouchCell: Cell | null = null; - fireDoubleClick: boolean | null = null; - tapAndHoldThread: number | null = null; - lastMouseX: number | null = null; - lastMouseY: number | null = null; - isMouseTrigger: boolean | null = null; - ignoreMouseEvents: boolean | null = null; - mouseMoveRedirect: MouseEventListener | null = null; - mouseUpRedirect: MouseEventListener | null = null; - lastEvent: any; // FIXME: Check if this can be more specific - DOM events or mxEventObjects! + lastTouchEvent: null, + + doubleClickCounter: 0, + + lastTouchCell: null, + + fireDoubleClick: null, + + tapAndHoldThread: null, + + lastMouseX: null, + + lastMouseY: null, + + isMouseTrigger: null, + + ignoreMouseEvents: null, + + mouseMoveRedirect: null, + + mouseUpRedirect: null, + + lastEvent: null, // FIXME: Check if this can be more specific - DOM events or mxEventObjects! /** * Specifies if {@link mxKeyHandler} should invoke {@link escape} when the escape key * is pressed. * @default true */ - escapeEnabled = true; + escapeEnabled: true, /** * If `true`, when editing is to be stopped by way of selection changing, @@ -117,7 +271,7 @@ class GraphEvents extends autoImplement() { * {@link CellEditor}. * @default true */ - invokesStopCellEditing = true; + invokesStopCellEditing: true, /** * If `true`, pressing the enter key without pressing control or shift will stop @@ -125,98 +279,102 @@ class GraphEvents extends autoImplement() { * cell editing. Note: You can always use F2 and escape to stop editing. * @default false */ - enterStopsCellEditing = false; + enterStopsCellEditing: false, /** * Holds the state of the mouse button. */ - isMouseDown = false; + isMouseDown: false, /** * Specifies if native double click events should be detected. * @default true */ - nativeDblClickEnabled = true; - - isNativeDblClickEnabled = () => this.nativeDblClickEnabled; + nativeDblClickEnabled: true, /** * Specifies if double taps on touch-based devices should be handled as a * double click. * @default true */ - doubleTapEnabled = true; + doubleTapEnabled: true, /** * Specifies the timeout in milliseconds for double taps and non-native double clicks. * @default 500 */ - doubleTapTimeout = 500; + doubleTapTimeout: 500, /** * Specifies the tolerance in pixels for double taps and double clicks in quirks mode. * @default 25 */ - doubleTapTolerance = 25; + doubleTapTolerance: 25, /** * Variable: lastTouchX * * Holds the x-coordinate of the last touch event for double tap detection. */ - lastTouchX = 0; + lastTouchX: 0, /** * Holds the x-coordinate of the last touch event for double tap detection. */ - lastTouchY = 0; + lastTouchY: 0, /** * Holds the time of the last touch event for double click detection. */ - lastTouchTime = 0; + lastTouchTime: 0, /** * Specifies if tap and hold should be used for starting connections on touch-based * devices. * @default true */ - tapAndHoldEnabled = true; + tapAndHoldEnabled: true, /** * Specifies the time in milliseconds for a tap and hold. * @default 500 */ - tapAndHoldDelay = 500; + tapAndHoldDelay: 500, /** * `True` if the timer for tap and hold events is running. */ - tapAndHoldInProgress = false; + tapAndHoldInProgress: false, /** * `True` as long as the timer is running and the touch events * stay within the given {@link tapAndHoldTolerance}. */ - tapAndHoldValid = false; + tapAndHoldValid: false, /** * Holds the x-coordinate of the initial touch event for tap and hold. */ - initialTouchX = 0; + initialTouchX: 0, /** * Holds the y-coordinate of the initial touch event for tap and hold. */ - initialTouchY = 0; + initialTouchY: 0, /** * Tolerance in pixels for a move to be handled as a single click. * @default 4 */ - tolerance = 4; + tolerance: 4, - getEventTolerance = () => this.tolerance; + isNativeDblClickEnabled() { + return this.nativeDblClickEnabled; + }, + + getEventTolerance() { + return this.tolerance; + }, /***************************************************************************** * Group: Event processing @@ -227,9 +385,9 @@ class GraphEvents extends autoImplement() { * * @param evt Mouseevent that represents the keystroke. */ - escape(evt: Event) { + escape(evt) { this.fireEvent(new EventObject(InternalEvent.ESCAPE, 'event', evt)); - } + }, /** * Processes a singleclick on an optional cell and fires a {@link click} event. @@ -257,7 +415,7 @@ class GraphEvents extends autoImplement() { * * @param me {@link mxMouseEvent} that represents the single click. */ - click(me: InternalMouseEvent) { + click(me) { const evt = me.getEvent(); let cell = me.getCell(); const mxe = new EventObject(InternalEvent.CLICK, 'event', evt, 'cell', cell); @@ -334,7 +492,7 @@ class GraphEvents extends autoImplement() { } } return false; - } + }, /** * Processes a doubleclick on an optional cell and fires a {@link dblclick} @@ -372,7 +530,7 @@ class GraphEvents extends autoImplement() { * @param evt Mouseevent that represents the doubleclick. * @param cell Optional {@link Cell} under the mousepointer. */ - dblClick(evt: MouseEvent, cell: Cell | null = null) { + dblClick(evt, cell = null) { const mxe = new EventObject(InternalEvent.DOUBLE_CLICK, { event: evt, cell: cell }); this.fireEvent(mxe); @@ -388,7 +546,7 @@ class GraphEvents extends autoImplement() { this.startEditingAtCell(cell, evt); InternalEvent.consume(evt); } - } + }, /** * Handles the {@link InternalMouseEvent} by highlighting the {@link CellState}. @@ -396,7 +554,7 @@ class GraphEvents extends autoImplement() { * @param me {@link mxMouseEvent} that represents the touch event. * @param state Optional {@link CellState} that is associated with the event. */ - tapAndHold(me: InternalMouseEvent) { + tapAndHold(me) { const evt = me.getEvent(); const mxe = new EventObject( InternalEvent.TAP_AND_HOLD, @@ -443,7 +601,7 @@ class GraphEvents extends autoImplement() { } } } - } + }, /***************************************************************************** * Group: Graph events @@ -456,23 +614,23 @@ class GraphEvents extends autoImplement() { * * @param listener Listener to be added to the graph event listeners. */ - addMouseListener(listener: MouseListenerSet) { + addMouseListener(listener) { this.mouseListeners.push(listener); - } + }, /** * Removes the specified graph listener. * * @param listener Listener to be removed from the graph event listeners. */ - removeMouseListener(listener: MouseListenerSet) { + removeMouseListener(listener) { for (let i = 0; i < this.mouseListeners.length; i += 1) { if (this.mouseListeners[i] === listener) { this.mouseListeners.splice(i, 1); break; } } - } + }, /** * Sets the graphX and graphY properties if the given {@link InternalMouseEvent} if @@ -481,7 +639,7 @@ class GraphEvents extends autoImplement() { * @param me {@link mxMouseEvent} to be updated. * @param evtName Name of the mouse event. */ - updateMouseEvent(me: InternalMouseEvent, evtName: string) { + updateMouseEvent(me, evtName) { const pt = convertPoint(this.getContainer(), me.getX(), me.getY()); me.graphX = pt.x - this.getPanDx(); @@ -502,12 +660,12 @@ class GraphEvents extends autoImplement() { } return me; - } + }, /** * Returns the state for the given touch event. */ - getStateForTouchEvent(evt: MouseEvent) { + getStateForTouchEvent(evt) { const x = getClientX(evt); const y = getClientY(evt); @@ -517,12 +675,12 @@ class GraphEvents extends autoImplement() { const cell = this.getCellAt(pt.x, pt.y); return cell ? this.getView().getState(cell) : null; - } + }, /** * Returns true if the event should be ignored in {@link fireMouseEvent}. */ - isEventIgnored(evtName: string, me: InternalMouseEvent, sender: EventSource) { + isEventIgnored(evtName, me, sender) { const mouseEvent = isMouseEvent(me.getEvent()); let result = false; @@ -559,25 +717,24 @@ class GraphEvents extends autoImplement() { ) { this.setEventSource(me.getSource()); - this.mouseMoveRedirect = (evt: MouseEvent) => { + (this.mouseMoveRedirect = (evt: MouseEvent) => { this.fireMouseEvent( InternalEvent.MOUSE_MOVE, new InternalMouseEvent(evt, this.getStateForTouchEvent(evt)) ); - }; - this.mouseUpRedirect = (evt: MouseEvent) => { - this.fireMouseEvent( - InternalEvent.MOUSE_UP, - new InternalMouseEvent(evt, this.getStateForTouchEvent(evt)) + }), + (this.mouseUpRedirect = (evt: MouseEvent) => { + this.fireMouseEvent( + InternalEvent.MOUSE_UP, + new InternalMouseEvent(evt, this.getStateForTouchEvent(evt)) + ); + }), + InternalEvent.addGestureListeners( + eventSource, + null, + this.mouseMoveRedirect, + this.mouseUpRedirect ); - }; - - InternalEvent.addGestureListeners( - eventSource, - null, - this.mouseMoveRedirect, - this.mouseUpRedirect - ); } // Factored out the workarounds for FF to make it easier to override/remove @@ -621,13 +778,12 @@ class GraphEvents extends autoImplement() { } return result; - } + }, /** * Hook for ignoring synthetic mouse events after touchend in Firefox. */ - // isSyntheticEventIgnored(evtName: string, me: mxMouseEvent, sender: mxEventSource): boolean; - isSyntheticEventIgnored(evtName: string, me: InternalMouseEvent, sender: any): boolean { + isSyntheticEventIgnored(evtName, me, sender) { let result = false; const mouseEvent = isMouseEvent(me.getEvent()); @@ -639,7 +795,7 @@ class GraphEvents extends autoImplement() { this.ignoreMouseEvents = true; } return result; - } + }, /** * Returns true if the event should be ignored in {@link fireMouseEvent}. This @@ -650,7 +806,7 @@ class GraphEvents extends autoImplement() { * @param evtName The name of the event. * @param me {@link mxMouseEvent} that should be ignored. */ - isEventSourceIgnored(evtName: string, me: InternalMouseEvent) { + isEventSourceIgnored(evtName, me) { const source = me.getSource(); if (!source) return true; @@ -676,7 +832,7 @@ class GraphEvents extends autoImplement() { // @ts-ignore type could exist source.type !== 'file')) ); - } + }, /** * Returns the {@link CellState} to be used when firing the mouse event for the @@ -684,9 +840,9 @@ class GraphEvents extends autoImplement() { * * {@link CellState} - State whose event source should be returned. */ - getEventState(state: CellState) { + getEventState(state) { return state; - } + }, /** * Dispatches the given event in the graph event dispatch loop. Possible @@ -698,7 +854,9 @@ class GraphEvents extends autoImplement() { * @param me {@link mxMouseEvent} to be fired. * @param sender Optional sender argument. Default is `this`. */ - fireMouseEvent(evtName: string, me: InternalMouseEvent, sender: EventSource = this) { + fireMouseEvent(evtName, me, sender) { + sender = sender ?? (this as Graph); + if (this.isEventSourceIgnored(evtName, me)) { const tooltipHandler = this.getPlugin('TooltipHandler') as TooltipHandler; @@ -902,17 +1060,19 @@ class GraphEvents extends autoImplement() { this.consumeMouseEvent(evtName, me, sender); } - } + }, /** * Consumes the given {@link InternalMouseEvent} if it's a touchStart event. */ - consumeMouseEvent(evtName: string, me: InternalMouseEvent, sender: EventSource = this) { + consumeMouseEvent(evtName, me, sender) { + sender = sender ?? this; + // Workaround for duplicate click in Windows 8 with Chrome/FF/Opera with touch if (evtName === InternalEvent.MOUSE_DOWN && isTouchEvent(me.getEvent())) { me.consume(false); } - } + }, /** * Dispatches a {@link InternalEvent.GESTURE} event. The following example will resize the @@ -945,11 +1105,11 @@ class GraphEvents extends autoImplement() { * @param evt Gestureend event that represents the gesture. * @param cell Optional {@link Cell} associated with the gesture. */ - fireGestureEvent(evt: MouseEvent, cell: Cell | null = null): void { + fireGestureEvent(evt, cell = null) { // Resets double tap event handling when gestures take place this.lastTouchTime = 0; this.fireEvent(new EventObject(InternalEvent.GESTURE, 'event', evt, 'cell', cell)); - } + }, /** * Called when the size of the graph has changed. This implementation fires @@ -1009,7 +1169,7 @@ class GraphEvents extends autoImplement() { this.updatePageBreaks(this.isPageBreaksVisible(), width, height); this.fireEvent(new EventObject(InternalEvent.SIZE, 'bounds', bounds)); - } + }, /***************************************************************************** * Group: Graph display @@ -1019,49 +1179,49 @@ class GraphEvents extends autoImplement() { * Returns true if the given event is a clone event. This implementation * returns true if control is pressed. */ - isCloneEvent(evt: MouseEvent) { + isCloneEvent(evt) { return isControlDown(evt); - } + }, /** * Hook for implementing click-through behaviour on selected cells. If this * returns true the cell behind the selected cell will be selected. This * implementation returns false; */ - isTransparentClickEvent(evt: MouseEvent) { + isTransparentClickEvent(evt) { return false; - } + }, /** * Returns true if the given event is a toggle event. This implementation * returns true if the meta key (Cmd) is pressed on Macs or if control is * pressed on any other platform. */ - isToggleEvent(evt: MouseEvent) { + isToggleEvent(evt) { return mxClient.IS_MAC ? isMetaDown(evt) : isControlDown(evt); - } + }, /** * Returns true if the given mouse event should be aligned to the grid. */ - isGridEnabledEvent(evt: MouseEvent) { + isGridEnabledEvent(evt) { return !isAltDown(evt); - } + }, /** * Returns true if the given mouse event should be aligned to the grid. */ - isConstrainedEvent(evt: MouseEvent) { + isConstrainedEvent(evt) { return isShiftDown(evt); - } + }, /** * Returns true if the given mouse event should not allow any connections to be * made. This implementation returns false. */ - isIgnoreTerminalEvent(evt: MouseEvent) { + isIgnoreTerminalEvent(evt) { return false; - } + }, /** * Returns an {@link Point} representing the given event in the unscaled, @@ -1071,7 +1231,7 @@ class GraphEvents extends autoImplement() { * @param addOffset Optional boolean that specifies if the position should be * offset by half of the {@link gridSize}. Default is `true`. */ - getPointForEvent(evt: MouseEvent, addOffset = true) { + getPointForEvent(evt, addOffset = true) { const p = convertPoint(this.getContainer(), getClientX(evt), getClientY(evt)); const s = this.getView().scale; const tr = this.getView().translate; @@ -1081,7 +1241,7 @@ class GraphEvents extends autoImplement() { p.y = this.snap(p.y / s - tr.y - off); return p; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -1092,44 +1252,44 @@ class GraphEvents extends autoImplement() { */ isEscapeEnabled() { return this.escapeEnabled; - } + }, /** * Sets {@link escapeEnabled}. * * @param enabled Boolean indicating if escape should be enabled. */ - setEscapeEnabled(value: boolean) { + setEscapeEnabled(value) { this.escapeEnabled = value; - } + }, /** * Returns {@link invokesStopCellEditing}. */ isInvokesStopCellEditing() { return this.invokesStopCellEditing; - } + }, /** * Sets {@link invokesStopCellEditing}. */ - setInvokesStopCellEditing(value: boolean) { + setInvokesStopCellEditing(value) { this.invokesStopCellEditing = value; - } + }, /** * Returns {@link enterStopsCellEditing}. */ isEnterStopsCellEditing() { return this.enterStopsCellEditing; - } + }, /** * Sets {@link enterStopsCellEditing}. */ - setEnterStopsCellEditing(value: boolean) { + setEnterStopsCellEditing(value) { this.enterStopsCellEditing = value; - } + }, /***************************************************************************** * Group: Graph appearance @@ -1141,10 +1301,10 @@ class GraphEvents extends autoImplement() { * * @param me {@link mxMouseEvent} whose cursor should be returned. */ - getCursorForMouseEvent(me: InternalMouseEvent) { + getCursorForMouseEvent(me) { const cell = me.getCell(); return cell ? this.getCursorForCell(cell) : null; - } -} + }, +}; -export default GraphEvents; +mixInto(Graph)(GraphEventsMixin); diff --git a/packages/core/src/view/event/InternalEvent.ts b/packages/core/src/view/event/InternalEvent.ts index 4877cd445..fc2fbc5cc 100644 --- a/packages/core/src/view/event/InternalEvent.ts +++ b/packages/core/src/view/event/InternalEvent.ts @@ -7,7 +7,6 @@ import InternalMouseEvent from './InternalMouseEvent'; import mxClient from '../../mxClient'; import { isConsumed, isMouseEvent } from '../../util/EventUtils'; -import graph from '../Graph'; import CellState from '../cell/datatypes/CellState'; import { EventCache, @@ -16,6 +15,7 @@ import { Listenable, MouseEventListener, } from '../../types'; +import { Graph } from '../Graph'; // Checks if passive event listeners are supported // see https://github.com/Modernizr/Modernizr/issues/1894 @@ -230,7 +230,7 @@ class InternalEvent { */ static redirectMouseEvents( node: Listenable, - graph: graph, + graph: Graph, state: CellState | ((evt: Event) => CellState | null) | null = null, down: MouseEventListener | null = null, move: MouseEventListener | null = null, diff --git a/packages/core/src/view/folding/GraphFolding.ts b/packages/core/src/view/folding/GraphFoldingMixin.ts similarity index 79% rename from packages/core/src/view/folding/GraphFolding.ts rename to packages/core/src/view/folding/GraphFoldingMixin.ts index 1e6e26e92..e5fab0aa2 100644 --- a/packages/core/src/view/folding/GraphFolding.ts +++ b/packages/core/src/view/folding/GraphFoldingMixin.ts @@ -6,13 +6,41 @@ import CellArray from '../cell/datatypes/CellArray'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Geometry from '../geometry/Geometry'; -import { autoImplement, getValue, toRadians } from '../../util/Utils'; +import { getValue, mixInto, toRadians } from '../../util/Utils'; import Rectangle from '../geometry/Rectangle'; +import { Graph } from '../Graph'; -import type Graph from '../Graph'; -import type GraphCells from '../cell/GraphCells'; -import type GraphSelection from '../selection/GraphSelection'; -import type GraphEditing from '../editing/GraphEditing'; +declare module '../Graph' { + interface Graph { + options: GraphFoldingOptions; + collapseExpandResource: string; + + getCollapseExpandResource: () => string; + isFoldingEnabled: () => boolean; + getFoldableCells: (cells: CellArray, collapse: boolean) => CellArray | null; + isCellFoldable: (cell: Cell, collapse: boolean) => boolean; + getFoldingImage: (state: CellState) => Image | null; + foldCells: ( + collapse: boolean, + recurse: boolean, + cells: CellArray | null, + checkFoldable: boolean, + evt: Event | null + ) => CellArray | null; + cellsFolded: ( + cells: CellArray | null, + collapse: boolean, + recurse: boolean, + checkFoldable?: boolean + ) => void; + swapBounds: (cell: Cell, willCollapse: boolean) => void; + updateAlternateBounds: ( + cell: Cell | null, + geo: Geometry | null, + willCollapse: boolean + ) => void; + } +} /** * GraphFoldingOptions @@ -35,26 +63,42 @@ type GraphFoldingOptions = { collapseToPreferredSize: boolean; }; -type PartialGraph = Pick; -type PartialCells = Pick< - GraphCells, +type PartialGraph = Pick< + Graph, + | 'getModel' + | 'fireEvent' | 'getCurrentCellStyle' | 'isExtendParent' | 'extendParent' | 'constrainChild' | 'getPreferredSizeForCell' + | 'getSelectionCells' + | 'stopEditing' >; -type PartialSelection = Pick; -type PartialEditing = Pick; -type PartialClass = PartialGraph & PartialCells & PartialSelection & PartialEditing; +type PartialFolding = Pick< + Graph, + | 'options' + | 'collapseExpandResource' + | 'getCollapseExpandResource' + | 'isFoldingEnabled' + | 'getFoldableCells' + | 'isCellFoldable' + | 'getFoldingImage' + | 'foldCells' + | 'cellsFolded' + | 'swapBounds' + | 'updateAlternateBounds' +>; +type PartialType = PartialGraph & PartialFolding; -class GraphFolding extends autoImplement() { - options: GraphFoldingOptions = { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphFoldingMixin: PartialType = { + options: { foldingEnabled: true, collapsedImage: new Image(`${mxClient.imageBasePath}/collapsed.gif`, 9, 9), expandedImage: new Image(`${mxClient.imageBasePath}/expanded.gif`, 9, 9), collapseToPreferredSize: true, - }; + }, /** * Specifies the resource key for the tooltip on the collapse/expand icon. @@ -62,11 +106,15 @@ class GraphFolding extends autoImplement() { * the tooltip. * @default 'collapse-expand' */ - collapseExpandResource: string = mxClient.language != 'none' ? 'collapse-expand' : ''; + collapseExpandResource: mxClient.language != 'none' ? 'collapse-expand' : '', - getCollapseExpandResource = () => this.collapseExpandResource; + getCollapseExpandResource() { + return this.collapseExpandResource; + }, - isFoldingEnabled = () => this.options.foldingEnabled; + isFoldingEnabled() { + return this.options.foldingEnabled; + }, /** * @@ -76,11 +124,11 @@ class GraphFolding extends autoImplement() { /** * Returns the cells which are movable in the given array of cells. */ - getFoldableCells(cells: CellArray, collapse: boolean = false): CellArray | null { + getFoldableCells(cells, collapse = false) { return this.getModel().filterCells(cells, (cell: Cell) => { return this.isCellFoldable(cell, collapse); }); - } + }, /** * Returns true if the given cell is foldable. This implementation @@ -90,16 +138,16 @@ class GraphFolding extends autoImplement() { * @param cell {@link mxCell} whose foldable state should be returned. */ // isCellFoldable(cell: mxCell, collapse: boolean): boolean; - isCellFoldable(cell: Cell, collapse: boolean = false): boolean { + isCellFoldable(cell, collapse = false) { const style = this.getCurrentCellStyle(cell); return cell.getChildCount() > 0 && style.foldable; - } + }, /** * Returns the {@link Image} used to display the collapsed state of * the specified cell state. This returns null for all edges. */ - getFoldingImage(state: CellState): Image | null { + getFoldingImage(state) { if (state != null && this.options.foldingEnabled && !state.cell.isEdge()) { const tmp = (state.cell).isCollapsed(); @@ -108,7 +156,7 @@ class GraphFolding extends autoImplement() { } } return null; - } + }, /***************************************************************************** * Group: Folding @@ -131,12 +179,12 @@ class GraphFolding extends autoImplement() { */ // foldCells(collapse: boolean, recurse: boolean, cells: mxCellArray, checkFoldable?: boolean, evt?: Event): mxCellArray; foldCells( - collapse: boolean = false, - recurse: boolean = false, - cells: CellArray | null = null, - checkFoldable: boolean = false, - evt: Event | null = null - ): CellArray | null { + collapse = false, + recurse = false, + cells = null, + checkFoldable = false, + evt = null + ) { if (cells == null) { cells = this.getFoldableCells(this.getSelectionCells(), collapse); } @@ -161,7 +209,7 @@ class GraphFolding extends autoImplement() { this.getModel().endUpdate(); } return cells; - } + }, /** * Sets the collapsed state of the specified cells. This method fires @@ -176,12 +224,7 @@ class GraphFolding extends autoImplement() { * checked. Default is `false`. */ // cellsFolded(cells: mxCellArray, collapse: boolean, recurse: boolean, checkFoldable?: boolean): void; - cellsFolded( - cells: CellArray | null = null, - collapse: boolean = false, - recurse: boolean = false, - checkFoldable: boolean = false - ): void { + cellsFolded(cells = null, collapse = false, recurse = false, checkFoldable = false) { if (cells != null && cells.length > 0) { this.getModel().beginUpdate(); try { @@ -221,7 +264,7 @@ class GraphFolding extends autoImplement() { this.getModel().endUpdate(); } } - } + }, /** * Swaps the alternate and the actual bounds in the geometry of the given @@ -231,7 +274,7 @@ class GraphFolding extends autoImplement() { * @param willCollapse Boolean indicating if the cell is going to be collapsed. */ // swapBounds(cell: mxCell, willCollapse: boolean): void; - swapBounds(cell: Cell, willCollapse: boolean = false): void { + swapBounds(cell, willCollapse = false) { let geo = cell.getGeometry(); if (geo != null) { geo = geo.clone(); @@ -241,7 +284,7 @@ class GraphFolding extends autoImplement() { this.getModel().setGeometry(cell, geo); } - } + }, /** * Updates or sets the alternate bounds in the given geometry for the given @@ -256,11 +299,7 @@ class GraphFolding extends autoImplement() { * @param willCollapse Boolean indicating if the cell is going to be collapsed. */ // updateAlternateBounds(cell: mxCell, geo: mxGeometry, willCollapse: boolean): void; - updateAlternateBounds( - cell: Cell | null = null, - geo: Geometry | null = null, - willCollapse: boolean = false - ): void { + updateAlternateBounds(cell = null, geo = null, willCollapse = false) { if (cell != null && geo != null) { const style = this.getCurrentCellStyle(cell); @@ -305,7 +344,7 @@ class GraphFolding extends autoImplement() { } } } - } -} + }, +}; -export default GraphFolding; +mixInto(Graph)(GraphFoldingMixin); diff --git a/packages/core/src/view/geometry/shape/Shape.ts b/packages/core/src/view/geometry/shape/Shape.ts index 6cfe7d6e1..d7d89043f 100644 --- a/packages/core/src/view/geometry/shape/Shape.ts +++ b/packages/core/src/view/geometry/shape/Shape.ts @@ -1230,7 +1230,7 @@ class Shape { */ getShapeRotation() { let rot = this.getRotation(); - + console.log('rot', rot, this, this.rotation); if (this.direction === DIRECTION_NORTH) { rot += 270; } else if (this.direction === DIRECTION_WEST) { diff --git a/packages/core/src/view/grouping_ordering/GraphGrouping.ts b/packages/core/src/view/grouping_ordering/GraphGroupingMixin.ts similarity index 84% rename from packages/core/src/view/grouping_ordering/GraphGrouping.ts rename to packages/core/src/view/grouping_ordering/GraphGroupingMixin.ts index a84e37990..31d24e37d 100644 --- a/packages/core/src/view/grouping_ordering/GraphGrouping.ts +++ b/packages/core/src/view/grouping_ordering/GraphGroupingMixin.ts @@ -1,16 +1,40 @@ import Cell from '../cell/datatypes/Cell'; import CellArray from '../cell/datatypes/CellArray'; -import { autoImplement, sortCells } from '../../util/Utils'; +import { mixInto, sortCells } from '../../util/Utils'; import Geometry from '../geometry/Geometry'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Rectangle from '../geometry/Rectangle'; import Point from '../geometry/Point'; -import Graph from '../Graph'; -import GraphSelection from '../selection/GraphSelection'; -import GraphCells from '../cell/GraphCells'; -import GraphSwimlane from '../swimlane/GraphSwimlane'; -import GraphEdge from '../cell/edge/GraphEdge'; +import { Graph } from '../Graph'; + +declare module '../Graph' { + interface Graph { + groupCells: (group: Cell, border: number, cells: CellArray) => Cell; + getCellsForGroup: (cells: CellArray) => CellArray; + getBoundsForGroup: ( + group: Cell, + children: CellArray, + border: number | null + ) => Rectangle | null; + createGroupCell: (cells: CellArray) => Cell; + ungroupCells: (cells: CellArray) => CellArray; + getCellsForUngroup: () => CellArray; + removeCellsAfterUngroup: (cells: CellArray) => void; + removeCellsFromParent: (cells: CellArray) => CellArray; + updateGroupBounds: ( + cells: CellArray, + border: number, + moveGroup: boolean, + topBorder: number, + rightBorder: number, + bottomBorder: number, + leftBorder: number + ) => CellArray; + enterGroup: (cell: Cell) => void; + exitGroup: () => void; + } +} type PartialGraph = Pick< Graph, @@ -21,9 +45,6 @@ type PartialGraph = Pick< | 'batchUpdate' | 'isValidRoot' | 'getCurrentRoot' ->; -type PartialCells = Pick< - GraphCells, | 'cellsAdded' | 'cellsMoved' | 'cellsResized' @@ -31,23 +52,33 @@ type PartialCells = Pick< | 'cellsRemoved' | 'getChildCells' | 'moveCells' + | 'addAllEdges' + | 'getSelectionCells' + | 'getSelectionCell' + | 'clearSelection' + | 'setSelectionCell' + | 'isSwimlane' + | 'getStartSize' + | 'getActualStartSize' >; -type PartialEdge = Pick; -type PartialSelection = Pick< - GraphSelection, - 'getSelectionCells' | 'getSelectionCell' | 'clearSelection' | 'setSelectionCell' +type PartialGrouping = Pick< + Graph, + | 'groupCells' + | 'getCellsForGroup' + | 'getBoundsForGroup' + | 'createGroupCell' + | 'ungroupCells' + | 'getCellsForUngroup' + | 'removeCellsAfterUngroup' + | 'removeCellsFromParent' + | 'updateGroupBounds' + | 'enterGroup' + | 'exitGroup' >; -type PartialSwimlane = Pick< - GraphSwimlane, - 'isSwimlane' | 'getStartSize' | 'getActualStartSize' ->; -type PartialClass = PartialGraph & - PartialCells & - PartialEdge & - PartialSelection & - PartialSwimlane; +type PartialType = PartialGraph & PartialGrouping; -class GraphGrouping extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphGroupingMixin: PartialType = { /***************************************************************************** * Group: Grouping *****************************************************************************/ @@ -66,13 +97,9 @@ class GraphGrouping extends autoImplement() { * @param cells Optional array of {@link Cell} to be grouped. If `null` is specified * then the selection cells are used. */ - // groupCells(group: mxCell | null, border?: number, cells?: mxCellArray): mxCell; - groupCells( - group: Cell, - border: number = 0, - cells: CellArray = sortCells(this.getSelectionCells(), true) - ) { - cells = this.getCellsForGroup(cells); + groupCells(group, border = 0, cells) { + if (!cells) cells = sortCells(this.getSelectionCells(), true); + if (!cells) cells = this.getCellsForGroup(cells); if (group == null) { group = this.createGroupCell(cells); @@ -133,13 +160,13 @@ class GraphGrouping extends autoImplement() { } } return group; - } + }, /** * Returns the cells with the same parent as the first cell * in the given array. */ - getCellsForGroup(cells: CellArray): CellArray { + getCellsForGroup(cells) { const result = new CellArray(); if (cells != null && cells.length > 0) { const parent = cells[0].getParent(); @@ -153,16 +180,12 @@ class GraphGrouping extends autoImplement() { } } return result; - } + }, /** * Returns the bounds to be used for the given group and children. */ - getBoundsForGroup( - group: Cell, - children: CellArray, - border: number | null - ): Rectangle | null { + getBoundsForGroup(group, children, border) { const result = this.getBoundingBoxFromGeometry(children, true); if (result != null) { if (this.isSwimlane(group)) { @@ -183,7 +206,7 @@ class GraphGrouping extends autoImplement() { } } return result; - } + }, /** * Hook for creating the group cell to hold the given array of {@link Cell} if @@ -201,14 +224,13 @@ class GraphGrouping extends autoImplement() { * return group; * }; */ - // createGroupCell(cells: mxCellArray): mxCell; - createGroupCell(cells: CellArray) { + createGroupCell(cells) { const group = new Cell(''); group.setVertex(true); group.setConnectable(false); return group; - } + }, /** * Ungroups the given cells by moving the children the children to their @@ -218,8 +240,7 @@ class GraphGrouping extends autoImplement() { * @param cells Array of cells to be ungrouped. If null is specified then the * selection cells are used. */ - // ungroupCells(cells: mxCellArray): mxCellArray; - ungroupCells(cells: CellArray) { + ungroupCells(cells) { let result: CellArray = new CellArray(); if (cells == null) { @@ -264,14 +285,14 @@ class GraphGrouping extends autoImplement() { } } return result; - } + }, /** * Function: getCellsForUngroup * * Returns the selection cells that can be ungrouped. */ - getCellsForUngroup(): CellArray { + getCellsForUngroup() { const cells = this.getSelectionCells(); // Finds the cells with children @@ -283,16 +304,16 @@ class GraphGrouping extends autoImplement() { } } return tmp; - } + }, /** * Hook to remove the groups after {@link ungroupCells}. * * @param cells Array of {@link Cell} that were ungrouped. */ - removeCellsAfterUngroup(cells: CellArray): void { + removeCellsAfterUngroup(cells) { this.cellsRemoved(this.addAllEdges(cells)); - } + }, /** * Removes the specified cells from their parents and adds them to the @@ -300,7 +321,7 @@ class GraphGrouping extends autoImplement() { * * @param cells Array of {@link Cell} to be removed from their parents. */ - removeCellsFromParent(cells: CellArray): CellArray { + removeCellsFromParent(cells) { if (cells == null) { cells = this.getSelectionCells(); } @@ -317,7 +338,7 @@ class GraphGrouping extends autoImplement() { this.getModel().endUpdate(); } return cells; - } + }, /** * Function: updateGroupBounds @@ -340,14 +361,14 @@ class GraphGrouping extends autoImplement() { * leftBorder - Optional top border to be added in the group. Default is 0. */ updateGroupBounds( - cells: CellArray, - border: number = 0, - moveGroup: boolean = false, - topBorder: number = 0, - rightBorder: number = 0, - bottomBorder: number = 0, - leftBorder: number = 0 - ): CellArray { + cells, + border = 0, + moveGroup = false, + topBorder = 0, + rightBorder = 0, + bottomBorder = 0, + leftBorder = 0 + ) { if (cells == null) { cells = this.getSelectionCells(); } @@ -402,7 +423,7 @@ class GraphGrouping extends autoImplement() { } }); return cells; - } + }, /***************************************************************************** * Group: Drilldown @@ -416,25 +437,25 @@ class GraphGrouping extends autoImplement() { * @param cell Optional {@link Cell} to be used as the new root. Default is the * selection cell. */ - enterGroup(cell: Cell): void { + enterGroup(cell) { cell = cell || this.getSelectionCell(); if (cell != null && this.isValidRoot(cell)) { this.getView().setCurrentRoot(cell); this.clearSelection(); } - } + }, /** * Changes the current root to the next valid root in the displayed cell * hierarchy. */ - exitGroup(): void { + exitGroup() { const root = this.getModel().getRoot(); const current = this.getCurrentRoot(); if (current != null) { - let next = current.getParent(); + let next = current.getParent() as Cell; // Finds the next valid root in the hierarchy while (next !== root && !this.isValidRoot(next) && next.getParent() !== root) { @@ -456,7 +477,7 @@ class GraphGrouping extends autoImplement() { this.setSelectionCell(current); } } - } -} + }, +}; -export default GraphGrouping; +mixInto(Graph)(GraphGroupingMixin); diff --git a/packages/core/src/view/grouping_ordering/GraphOrder.ts b/packages/core/src/view/grouping_ordering/GraphOrderMixin.ts similarity index 70% rename from packages/core/src/view/grouping_ordering/GraphOrder.ts rename to packages/core/src/view/grouping_ordering/GraphOrderMixin.ts index 3784896e6..ffd415fe9 100644 --- a/packages/core/src/view/grouping_ordering/GraphOrder.ts +++ b/packages/core/src/view/grouping_ordering/GraphOrderMixin.ts @@ -1,15 +1,25 @@ import CellArray from '../cell/datatypes/CellArray'; -import { autoImplement, sortCells } from '../../util/Utils'; +import { mixInto, sortCells } from '../../util/Utils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; -import Graph from '../Graph'; -import GraphSelection from '../selection/GraphSelection'; +import { Graph } from '../Graph'; -type PartialGraph = Pick; -type PartialSelection = Pick; -type PartialClass = PartialGraph & PartialSelection; +declare module '../Graph' { + interface Graph { + orderCells: (back: boolean, cells: CellArray) => CellArray; + cellsOrdered: (cells: CellArray, back: boolean) => void; + } +} -class GraphOrder extends autoImplement() { +type PartialGraph = Pick< + Graph, + 'fireEvent' | 'batchUpdate' | 'getModel' | 'getSelectionCells' +>; +type PartialOrder = Pick; +type PartialType = PartialGraph & PartialOrder; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphOrderMixin: PartialType = { /***************************************************************************** * Group: Order *****************************************************************************/ @@ -23,11 +33,9 @@ class GraphOrder extends autoImplement() { * @param cells Array of {@link mxCell} to move to the background. If null is * specified then the selection cells are used. */ - orderCells( - back: boolean = false, - cells: CellArray = this.getSelectionCells() - ): CellArray { - if (cells == null) { + orderCells(back = false, cells) { + if (!cells) cells = this.getSelectionCells(); + if (!cells) { cells = sortCells(this.getSelectionCells(), true); } @@ -44,7 +52,7 @@ class GraphOrder extends autoImplement() { }); return cells; - } + }, /** * Moves the given cells to the front or back. This method fires @@ -53,7 +61,7 @@ class GraphOrder extends autoImplement() { * @param cells Array of {@link mxCell} whose order should be changed. * @param back Boolean that specifies if the cells should be moved to back. */ - cellsOrdered(cells: CellArray, back: boolean = false) { + cellsOrdered(cells, back = false) { this.batchUpdate(() => { for (let i = 0; i < cells.length; i += 1) { const parent = cells[i].getParent(); @@ -69,7 +77,7 @@ class GraphOrder extends autoImplement() { new EventObject(InternalEvent.CELLS_ORDERED, 'back', back, 'cells', cells) ); }); - } -} + }, +}; -export default GraphOrder; +mixInto(Graph)(GraphOrderMixin); diff --git a/packages/core/src/view/image/GraphImage.ts b/packages/core/src/view/image/GraphImage.ts deleted file mode 100644 index 2fe2506d4..000000000 --- a/packages/core/src/view/image/GraphImage.ts +++ /dev/null @@ -1,50 +0,0 @@ -import ImageBundle from './ImageBundle'; - -class GraphImage { - /** - * Holds the list of image bundles. - */ - imageBundles: ImageBundle[] = []; - - /***************************************************************************** - * Group: Image bundles - *****************************************************************************/ - - /** - * Adds the specified {@link ImageBundle}. - */ - addImageBundle(bundle: ImageBundle) { - this.imageBundles.push(bundle); - } - - /** - * Removes the specified {@link ImageBundle}. - */ - removeImageBundle(bundle: ImageBundle) { - const tmp = []; - for (let i = 0; i < this.imageBundles.length; i += 1) { - if (this.imageBundles[i] !== bundle) { - tmp.push(this.imageBundles[i]); - } - } - this.imageBundles = tmp; - } - - /** - * Searches all {@link imageBundles} for the specified key and returns the value - * for the first match or null if the key is not found. - */ - getImageFromBundles(key: string) { - if (key) { - for (let i = 0; i < this.imageBundles.length; i += 1) { - const image = this.imageBundles[i].getImage(key); - if (image) { - return image; - } - } - } - return null; - } -} - -export default GraphImage; diff --git a/packages/core/src/view/image/GraphImageMixin.ts b/packages/core/src/view/image/GraphImageMixin.ts new file mode 100644 index 000000000..e013c3361 --- /dev/null +++ b/packages/core/src/view/image/GraphImageMixin.ts @@ -0,0 +1,65 @@ +import { mixInto } from '../../util/Utils'; +import { Graph } from '../Graph'; +import ImageBundle from './ImageBundle'; + +declare module '../Graph' { + interface Graph { + imageBundles: ImageBundle[]; + + addImageBundle: (bundle: ImageBundle) => void; + removeImageBundle: (bundle: ImageBundle) => void; + getImageFromBundles: (key: string) => string | null; + } +} + +/***************************************************************************** + * Group: Image bundles + *****************************************************************************/ + +type PartialImage = Pick< + Graph, + 'imageBundles' | 'addImageBundle' | 'removeImageBundle' | 'getImageFromBundles' +>; +type PartialType = PartialImage; + +const GraphImageMixin: PartialType = { + imageBundles: [], + + /** + * Adds the specified {@link ImageBundle}. + */ + addImageBundle(bundle) { + this.imageBundles.push(bundle); + }, + + /** + * Removes the specified {@link ImageBundle}. + */ + removeImageBundle(bundle) { + const tmp: ImageBundle[] = []; + for (let i = 0; i < this.imageBundles.length; i += 1) { + if (this.imageBundles[i] !== bundle) { + tmp.push(this.imageBundles[i]); + } + } + this.imageBundles = tmp; + }, + + /** + * Searches all {@link imageBundles} for the specified key and returns the value + * for the first match or null if the key is not found. + */ + getImageFromBundles(key) { + if (key) { + for (let i = 0; i < this.imageBundles.length; i += 1) { + const image = this.imageBundles[i].getImage(key); + if (image) { + return image; + } + } + } + return null; + }, +}; + +mixInto(Graph)(GraphImageMixin); diff --git a/packages/core/src/view/label/GraphLabel.ts b/packages/core/src/view/label/GraphLabelMixin.ts similarity index 75% rename from packages/core/src/view/label/GraphLabel.ts rename to packages/core/src/view/label/GraphLabelMixin.ts index fc5d1183c..1b08ac174 100644 --- a/packages/core/src/view/label/GraphLabel.ts +++ b/packages/core/src/view/label/GraphLabelMixin.ts @@ -1,18 +1,48 @@ +import { mixInto } from '../../util/Utils'; import Cell from '../cell/datatypes/Cell'; -import { autoImplement, getValue } from '../../util/Utils'; +import { Graph } from '../Graph'; -import type Graph from '../Graph'; -import type GraphCells from '../cell/GraphCells'; -import type GraphEdge from '../cell/edge/GraphEdge'; -import type GraphVertex from '../cell/vertex/GraphVertex'; +declare module '../Graph' { + interface Graph { + labelsVisible: boolean; + htmlLabels: boolean; -type PartialGraph = Pick; -type PartialCells = Pick; -type PartialEdge = Pick; -type PartialVertex = Pick; -type PartialClass = PartialGraph & PartialCells & PartialEdge & PartialVertex; + getLabel: (cell: Cell) => string | null; + isHtmlLabel: (cell: Cell) => boolean; + isLabelsVisible: () => boolean; + isHtmlLabels: () => boolean; + setHtmlLabels: (value: boolean) => void; + isWrapping: (cell: Cell) => boolean; + isLabelClipped: (cell: Cell) => boolean; + isLabelMovable: (cell: Cell) => boolean; + } +} -class GraphLabel extends autoImplement() { +type PartialGraph = Pick< + Graph, + | 'convertValueToString' + | 'getCurrentCellStyle' + | 'isCellLocked' + | 'isEdgeLabelsMovable' + | 'isVertexLabelsMovable' +>; +type PartialLabel = Pick< + Graph, + | 'labelsVisible' + | 'htmlLabels' + | 'getLabel' + | 'isHtmlLabel' + | 'isLabelsVisible' + | 'isHtmlLabels' + | 'setHtmlLabels' + | 'isWrapping' + | 'isLabelClipped' + | 'isLabelMovable' +>; +type PartialType = PartialGraph & PartialLabel; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphLabelMixin: PartialType = { /** * Returns a string or DOM node that represents the label for the given * cell. This implementation uses {@link convertValueToString} if {@link labelsVisible} @@ -61,19 +91,19 @@ class GraphLabel extends autoImplement() { * * @param cell {@link mxCell} whose label should be returned. */ - getLabel(cell: Cell) { + getLabel(cell) { let result: string | null = ''; if (this.isLabelsVisible() && cell != null) { const style = this.getCurrentCellStyle(cell); - if (!getValue(style, 'noLabel', false)) { + if (!(style.noLabel ?? false)) { result = this.convertValueToString(cell); } } return result; - } + }, /** * Returns true if the label must be rendered as HTML markup. The default @@ -81,37 +111,39 @@ class GraphLabel extends autoImplement() { * * @param cell {@link mxCell} whose label should be displayed as HTML markup. */ - isHtmlLabel(cell: Cell): boolean { + isHtmlLabel(cell) { return this.isHtmlLabels(); - } + }, /** * Specifies if labels should be visible. This is used in {@link getLabel}. Default * is true. */ - labelsVisible: boolean = true; + labelsVisible: true, - isLabelsVisible = () => this.labelsVisible; + isLabelsVisible() { + return this.labelsVisible; + }, /** * Specifies the return value for {@link isHtmlLabel}. * @default false */ - htmlLabels: boolean = false; + htmlLabels: false, /** * Returns {@link htmlLabels}. */ - isHtmlLabels(): boolean { + isHtmlLabels() { return this.htmlLabels; - } + }, /** * Sets {@link htmlLabels}. */ - setHtmlLabels(value: boolean): void { + setHtmlLabels(value: boolean) { this.htmlLabels = value; - } + }, /** * This enables wrapping for HTML labels. @@ -154,9 +186,9 @@ class GraphLabel extends autoImplement() { * * @param state {@link mxCell} whose label should be wrapped. */ - isWrapping(cell: Cell): boolean { + isWrapping(cell) { return this.getCurrentCellStyle(cell).whiteSpace === 'wrap'; - } + }, /** * Returns true if the overflow portion of labels should be hidden. If this @@ -166,9 +198,9 @@ class GraphLabel extends autoImplement() { * * @param state {@link mxCell} whose label should be clipped. */ - isLabelClipped(cell: Cell): boolean { + isLabelClipped(cell) { return this.getCurrentCellStyle(cell).overflow === 'hidden'; - } + }, /** * Returns true if the given edges's label is moveable. This returns @@ -177,13 +209,13 @@ class GraphLabel extends autoImplement() { * * @param cell {@link mxCell} whose label should be moved. */ - isLabelMovable(cell: Cell): boolean { + isLabelMovable(cell) { return ( !this.isCellLocked(cell) && ((cell.isEdge() && this.isEdgeLabelsMovable()) || (cell.isVertex() && this.isVertexLabelsMovable())) ); - } -} + }, +}; -export default GraphLabel; +mixInto(Graph)(GraphLabelMixin); diff --git a/packages/core/src/view/layout/GraphOverlays.ts b/packages/core/src/view/layout/GraphOverlaysMixin.ts similarity index 81% rename from packages/core/src/view/layout/GraphOverlays.ts rename to packages/core/src/view/layout/GraphOverlaysMixin.ts index 58c988191..6f0493676 100644 --- a/packages/core/src/view/layout/GraphOverlays.ts +++ b/packages/core/src/view/layout/GraphOverlaysMixin.ts @@ -4,10 +4,24 @@ import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import Image from '../image/ImageBox'; import InternalMouseEvent from '../event/InternalMouseEvent'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type Graph from '../Graph'; -import type GraphSelection from '../selection/GraphSelection'; +declare module '../Graph' { + interface Graph { + addCellOverlay: (cell: Cell, overlay: CellOverlay) => CellOverlay; + getCellOverlays: (cell: Cell) => CellOverlay[]; + removeCellOverlay: (cell: Cell, overlay: CellOverlay | null) => CellOverlay | null; + removeCellOverlays: (cell: Cell) => CellOverlay[]; + clearCellOverlays: (cell: Cell | null) => void; + setCellWarning: ( + cell: Cell, + warning: string | null, + img?: Image, + isSelect?: boolean + ) => CellOverlay | null; + } +} type PartialGraph = Pick< Graph, @@ -17,11 +31,21 @@ type PartialGraph = Pick< | 'isEnabled' | 'getWarningImage' | 'getCellRenderer' + | 'setSelectionCell' >; -type PartialSelection = Pick; -type PartialClass = PartialGraph & PartialSelection; +type PartialOverlays = Pick< + Graph, + | 'addCellOverlay' + | 'getCellOverlays' + | 'removeCellOverlay' + | 'removeCellOverlays' + | 'clearCellOverlays' + | 'setCellWarning' +>; +type PartialType = PartialGraph & PartialOverlays; -class GraphOverlays extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphOverlaysMixin: PartialType = { /***************************************************************************** * Group: Overlays *****************************************************************************/ @@ -33,7 +57,7 @@ class GraphOverlays extends autoImplement() { * @param cell {@link mxCell} to add the overlay for. * @param overlay {@link mxCellOverlay} to be added for the cell. */ - addCellOverlay(cell: Cell, overlay: CellOverlay): CellOverlay { + addCellOverlay(cell, overlay) { cell.overlays.push(overlay); // Immediately update the cell display if the state exists @@ -47,7 +71,7 @@ class GraphOverlays extends autoImplement() { new EventObject(InternalEvent.ADD_OVERLAY, 'cell', cell, 'overlay', overlay) ); return overlay; - } + }, /** * Returns the array of {@link mxCellOverlays} for the given cell or null, if @@ -55,9 +79,9 @@ class GraphOverlays extends autoImplement() { * * @param cell {@link mxCell} whose overlays should be returned. */ - getCellOverlays(cell: Cell) { + getCellOverlays(cell) { return cell.overlays; - } + }, /** * Removes and returns the given {@link CellOverlay} from the given cell. This @@ -68,7 +92,7 @@ class GraphOverlays extends autoImplement() { * @param overlay Optional {@link CellOverlay} to be removed. */ // removeCellOverlay(cell: mxCell, overlay: mxCellOverlay): mxCellOverlay; - removeCellOverlay(cell: Cell, overlay: CellOverlay | null = null) { + removeCellOverlay(cell, overlay = null) { if (!overlay) { this.removeCellOverlays(cell); } else { @@ -93,7 +117,7 @@ class GraphOverlays extends autoImplement() { } return overlay; - } + }, /** * Removes all {@link mxCellOverlays} from the given cell. This method @@ -102,7 +126,7 @@ class GraphOverlays extends autoImplement() { * * @param cell {@link mxCell} whose overlays should be removed */ - removeCellOverlays(cell: Cell) { + removeCellOverlays(cell) { const { overlays } = cell; cell.overlays = []; @@ -127,7 +151,7 @@ class GraphOverlays extends autoImplement() { } return overlays; - } + }, /** * Removes all {@link mxCellOverlays} in the graph for the given cell and all its @@ -138,7 +162,7 @@ class GraphOverlays extends autoImplement() { * @param cell Optional {@link Cell} that represents the root of the subtree to * remove the overlays from. Default is the root in the model. */ - clearCellOverlays(cell: Cell | null = null) { + clearCellOverlays(cell = null) { cell = cell ?? this.getModel().getRoot(); if (!cell) return; @@ -152,7 +176,7 @@ class GraphOverlays extends autoImplement() { const child = cell.getChildAt(i); this.clearCellOverlays(child); // recurse } - } + }, /** * Creates an overlay for the given cell using the warning and image or @@ -173,12 +197,9 @@ class GraphOverlays extends autoImplement() { * @param isSelect Optional boolean indicating if a click on the overlay * should select the corresponding cell. Default is `false`. */ - setCellWarning( - cell: Cell, - warning: string | null = null, - img: Image = this.getWarningImage(), - isSelect = false - ) { + setCellWarning(cell, warning = null, img, isSelect = false) { + img = img ?? this.getWarningImage(); + if (warning && warning.length > 0) { // Creates the overlay with the image and warning const overlay = new CellOverlay(img, `${warning}`); @@ -201,7 +222,7 @@ class GraphOverlays extends autoImplement() { this.removeCellOverlays(cell); return null; - } -} + }, +}; -export default GraphOverlays; +mixInto(Graph)(GraphOverlaysMixin); diff --git a/packages/core/src/view/layout/LayoutManager.ts b/packages/core/src/view/layout/LayoutManager.ts index fb98a22f5..870dc55cf 100644 --- a/packages/core/src/view/layout/LayoutManager.ts +++ b/packages/core/src/view/layout/LayoutManager.ts @@ -7,7 +7,7 @@ import EventSource from '../event/EventSource'; import InternalEvent from '../event/InternalEvent'; -import utils, { convertPoint, sortCells } from '../../util/Utils'; +import { convertPoint, sortCells } from '../../util/Utils'; import RootChange from '../model/RootChange'; import ChildChange from '../model/ChildChange'; import TerminalChange from '../cell/edge/TerminalChange'; @@ -16,12 +16,11 @@ import VisibleChange from '../style/VisibleChange'; import StyleChange from '../style/StyleChange'; import EventObject from '../event/EventObject'; import Cell from '../cell/datatypes/Cell'; -import graph from '../Graph'; import Rectangle from '../geometry/Rectangle'; import InternalMouseEvent from '../event/InternalMouseEvent'; import { getClientX, getClientY } from '../../util/EventUtils'; import CellArray from '../cell/datatypes/CellArray'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; /** * @class LayoutManager @@ -49,7 +48,7 @@ import Graph from '../Graph'; * been passed to {@link layoutCells}. */ class LayoutManager extends EventSource { - constructor(graph: graph) { + constructor(graph: Graph) { super(); // Executes the layout before the changes are dispatched @@ -83,7 +82,7 @@ class LayoutManager extends EventSource { /** * Reference to the enclosing {@link graph}. */ - graph: graph | null = null; + graph: Graph | null = null; /** * Specifies if the layout should bubble along @@ -150,7 +149,7 @@ class LayoutManager extends EventSource { /** * Returns the graph that this layout operates on. */ - getGraph(): graph | null { + getGraph(): Graph | null { return this.graph; } @@ -222,11 +221,11 @@ class LayoutManager extends EventSource { cellsMoved(cells: CellArray, evt: InternalMouseEvent): void { if (cells != null && evt != null) { const point = convertPoint( - (this.getGraph()).container, + (this.getGraph()).container, getClientX(evt), getClientY(evt) ); - const model = (this.getGraph()).getModel(); + const model = (this.getGraph()).getModel(); for (let i = 0; i < cells.length; i += 1) { const layout = this.getLayout(cells[i].getParent(), InternalEvent.MOVE_CELLS); @@ -250,7 +249,7 @@ class LayoutManager extends EventSource { prev: CellArray | null = null ): void { if (cells != null && bounds != null) { - const model = (this.getGraph()).getModel(); + const model = (this.getGraph()).getModel(); for (let i = 0; i < cells.length; i += 1) { const layout = this.getLayout(cells[i].getParent(), InternalEvent.RESIZE_CELLS); @@ -318,7 +317,7 @@ class LayoutManager extends EventSource { } if (this.isBubbling()) { - const model = (this.getGraph()).getModel(); + const model = (this.getGraph()).getModel(); this.addAncestorsWithLayout(cell.getParent(), result); } } @@ -330,7 +329,7 @@ class LayoutManager extends EventSource { */ addDescendantsWithLayout(cell: Cell, result: CellArray = new CellArray()): CellArray { if (cell != null && this.hasLayout(cell)) { - const model = (this.getGraph()).getModel(); + const model = (this.getGraph()).getModel(); for (let i = 0; i < cell.getChildCount(); i += 1) { const child = cell.getChildAt(i); @@ -359,7 +358,7 @@ class LayoutManager extends EventSource { layoutCells(cells: CellArray, bubble: boolean = false): void { if (cells.length > 0) { // Invokes the layouts while removing duplicates - const model = (this.getGraph()).getModel(); + const model = (this.getGraph()).getModel(); model.beginUpdate(); try { diff --git a/packages/core/src/view/layout/layout/CircleLayout.ts b/packages/core/src/view/layout/layout/CircleLayout.ts index 1d17373b1..536e6bed3 100644 --- a/packages/core/src/view/layout/layout/CircleLayout.ts +++ b/packages/core/src/view/layout/layout/CircleLayout.ts @@ -5,7 +5,7 @@ * Type definitions from the typed-mxgraph project */ import GraphLayout from './GraphLayout'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import CellArray from '../../cell/datatypes/CellArray'; import Cell from '../../cell/datatypes/Cell'; diff --git a/packages/core/src/view/layout/layout/CompactTreeLayout.ts b/packages/core/src/view/layout/layout/CompactTreeLayout.ts index 9fd198a8c..504b0bc71 100644 --- a/packages/core/src/view/layout/layout/CompactTreeLayout.ts +++ b/packages/core/src/view/layout/layout/CompactTreeLayout.ts @@ -10,11 +10,11 @@ import Point from '../../geometry/Point'; import GraphLayout from './GraphLayout'; import CellPath from '../../cell/datatypes/CellPath'; import Rectangle from '../../geometry/Rectangle'; -import utils, { sortCells } from '../../../util/Utils'; +import { sortCells } from '../../../util/Utils'; import WeightedCellSorter from './WeightedCellSorter'; import CellArray from '../../cell/datatypes/CellArray'; import Cell from '../../cell/datatypes/Cell'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; /** * @class CompactTreeLayout diff --git a/packages/core/src/view/layout/layout/EdgeLabelLayout.ts b/packages/core/src/view/layout/layout/EdgeLabelLayout.ts index 714a0316f..9256fae58 100644 --- a/packages/core/src/view/layout/layout/EdgeLabelLayout.ts +++ b/packages/core/src/view/layout/layout/EdgeLabelLayout.ts @@ -7,9 +7,9 @@ import Point from '../../geometry/Point'; import GraphLayout from './GraphLayout'; -import utils, { intersects } from '../../../util/Utils'; +import { intersects } from '../../../util/Utils'; import Cell from '../../cell/datatypes/Cell'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import CellArray from '../../cell/datatypes/CellArray'; import CellState from '../../cell/datatypes/CellState'; @@ -75,11 +75,7 @@ class EdgeLabelLayout extends GraphLayout { for (let i = 0; i < e.length; i += 1) { const edge = e[i]; - if ( - edge != null && - edge.text != null && - edge.text.boundingBox != null - ) { + if (edge != null && edge.text != null && edge.text.boundingBox != null) { for (let j = 0; j < v.length; j += 1) { const vertex = v[j]; diff --git a/packages/core/src/view/layout/layout/FastOrganicLayout.ts b/packages/core/src/view/layout/layout/FastOrganicLayout.ts index 3ceea4dc0..f077a8561 100644 --- a/packages/core/src/view/layout/layout/FastOrganicLayout.ts +++ b/packages/core/src/view/layout/layout/FastOrganicLayout.ts @@ -6,7 +6,7 @@ */ import ObjectIdentity from '../../../util/ObjectIdentity'; import GraphLayout from './GraphLayout'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import Cell from '../../cell/datatypes/Cell'; /** diff --git a/packages/core/src/view/layout/layout/GraphLayout.ts b/packages/core/src/view/layout/layout/GraphLayout.ts index a632a38c2..cc22f0acb 100644 --- a/packages/core/src/view/layout/layout/GraphLayout.ts +++ b/packages/core/src/view/layout/layout/GraphLayout.ts @@ -9,7 +9,7 @@ import Dictionary from '../../../util/Dictionary'; import Rectangle from '../../geometry/Rectangle'; import Geometry from '../../geometry/Geometry'; import Point from '../../geometry/Point'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import Cell from '../../cell/datatypes/Cell'; import CellArray from '../../cell/datatypes/CellArray'; @@ -134,7 +134,13 @@ class GraphLayout { * null for the first step of the traversal. * @param visited Optional {@link Dictionary} of cell paths for the visited cells. */ - traverse(vertex: Cell, directed?: boolean, func?: Function, edge?: Cell, visited?: Dictionary): void { + traverse( + vertex: Cell, + directed?: boolean, + func?: Function, + edge?: Cell, + visited?: Dictionary + ): void { if (func != null && vertex != null) { directed = directed != null ? directed : true; visited = visited || new Dictionary(); @@ -320,11 +326,7 @@ class GraphLayout { if (this.useBoundingBox) { const state = this.graph.getView().getState(cell); - if ( - state != null && - state.text != null && - state.text.boundingBox != null - ) { + if (state != null && state.text != null && state.text.boundingBox != null) { const { scale } = this.graph.getView(); const box = state.text.boundingBox; @@ -376,20 +378,14 @@ class GraphLayout { if (this.useBoundingBox) { const state = this.graph.getView().getState(cell); - if ( - state != null && - state.text != null && - state.text.boundingBox != null - ) { + if (state != null && state.text != null && state.text.boundingBox != null) { const { scale } = this.graph.getView(); const tmp = state.text.boundingBox; const dx0 = Math.max(state.x - tmp.x, 0) / scale; const dy0 = Math.max(state.y - tmp.y, 0) / scale; - const dx1 = - Math.max(tmp.x + tmp.width - (state.x + state.width), 0) / scale; - const dy1 = - Math.max(tmp.y + tmp.height - (state.y + state.height), 0) / scale; + const dx1 = Math.max(tmp.x + tmp.width - (state.x + state.width), 0) / scale; + const dy1 = Math.max(tmp.y + tmp.height - (state.y + state.height), 0) / scale; geo = new Rectangle( geo.x - dx0, diff --git a/packages/core/src/view/layout/layout/ParallelEdgeLayout.ts b/packages/core/src/view/layout/layout/ParallelEdgeLayout.ts index 3f294289d..efed1d901 100644 --- a/packages/core/src/view/layout/layout/ParallelEdgeLayout.ts +++ b/packages/core/src/view/layout/layout/ParallelEdgeLayout.ts @@ -8,7 +8,7 @@ import Point from '../../geometry/Point'; import GraphLayout from './GraphLayout'; import ObjectIdentity from '../../../util/ObjectIdentity'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import CellArray from '../../cell/datatypes/CellArray'; import Cell from '../../cell/datatypes/Cell'; diff --git a/packages/core/src/view/layout/layout/PartitionLayout.ts b/packages/core/src/view/layout/layout/PartitionLayout.ts index 987b7b169..2449b8c44 100644 --- a/packages/core/src/view/layout/layout/PartitionLayout.ts +++ b/packages/core/src/view/layout/layout/PartitionLayout.ts @@ -7,7 +7,7 @@ import Rectangle from '../../geometry/Rectangle'; import GraphLayout from './GraphLayout'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import Cell from '../../cell/datatypes/Cell'; /** @@ -28,7 +28,12 @@ import Cell from '../../cell/datatypes/Cell'; * @class */ class PartitionLayout extends GraphLayout { - constructor(graph: Graph, horizontal: boolean=true, spacing: number=0, border: number=0) { + constructor( + graph: Graph, + horizontal: boolean = true, + spacing: number = 0, + border: number = 0 + ) { super(graph); this.horizontal = horizontal != null ? horizontal : true; this.spacing = spacing || 0; diff --git a/packages/core/src/view/layout/layout/RadialTreeLayout.ts b/packages/core/src/view/layout/layout/RadialTreeLayout.ts index 94c83e849..f1e8e25f9 100644 --- a/packages/core/src/view/layout/layout/RadialTreeLayout.ts +++ b/packages/core/src/view/layout/layout/RadialTreeLayout.ts @@ -6,7 +6,7 @@ */ import CompactTreeLayout from './CompactTreeLayout'; import Cell from '../../cell/datatypes/Cell'; -import Graph from '../../Graph'; +import { Graph } from '../../Graph'; import CellArray from '../../cell/datatypes/CellArray'; /** @@ -108,8 +108,7 @@ class RadialTreeLayout extends CompactTreeLayout { */ isVertexIgnored(vertex: Cell): boolean { return ( - super.isVertexIgnored(vertex) || - this.graph.getConnections(vertex).length === 0 + super.isVertexIgnored(vertex) || this.graph.getConnections(vertex).length === 0 ); } @@ -166,8 +165,7 @@ class RadialTreeLayout extends CompactTreeLayout { // Extend out row so they meet the maximum gradient and convert to polar co-ords for (let i = 0; i < this.row.length; i += 1) { - const xLeftLimit = - this.centerX - this.nodeDistance - maxLeftGrad * this.rowRadi[i]; + const xLeftLimit = this.centerX - this.nodeDistance - maxLeftGrad * this.rowRadi[i]; const xRightLimit = this.centerX + this.nodeDistance + maxRightGrad * this.rowRadi[i]; const fullWidth = xRightLimit - xLeftLimit; @@ -221,12 +219,8 @@ class RadialTreeLayout extends CompactTreeLayout { const vertexBounds = this.getVertexBounds(node.cell); this.setVertexLocation( node.cell, - this.centerX - - vertexBounds.width / 2 + - this.rowRadi[i] * Math.cos(node.theta), - this.centerY - - vertexBounds.height / 2 + - this.rowRadi[i] * Math.sin(node.theta) + this.centerX - vertexBounds.width / 2 + this.rowRadi[i] * Math.cos(node.theta), + this.centerY - vertexBounds.height / 2 + this.rowRadi[i] * Math.sin(node.theta) ); } } @@ -272,8 +266,7 @@ class RadialTreeLayout extends CompactTreeLayout { vertexBounds.x + vertexBounds.width / 2, this.rowMaxCenX[rowNum] ); - this.rowRadi[rowNum] = - vertexBounds.y - this.getVertexBounds(this.root).y; + this.rowRadi[rowNum] = vertexBounds.y - this.getVertexBounds(this.root).y; if (child.child != null) { rowHasChildren = true; diff --git a/packages/core/src/view/layout/layout/StackLayout.ts b/packages/core/src/view/layout/layout/StackLayout.ts index 721314aba..fe03c99e6 100644 --- a/packages/core/src/view/layout/layout/StackLayout.ts +++ b/packages/core/src/view/layout/layout/StackLayout.ts @@ -6,11 +6,9 @@ */ import GraphLayout from './GraphLayout'; import Rectangle from '../../geometry/Rectangle'; -import utils, { getNumber, getValue } from '../../../util/Utils'; -import { - DEFAULT_STARTSIZE, -} from '../../../util/Constants'; -import Graph from '../../Graph'; +import { getNumber, getValue } from '../../../util/Utils'; +import { DEFAULT_STARTSIZE } from '../../../util/Constants'; +import { Graph } from '../../Graph'; import Cell from '../../cell/datatypes/Cell'; import Geometry from '../../geometry/Geometry'; import CellArray from '../../cell/datatypes/CellArray'; @@ -151,11 +149,7 @@ class StackLayout extends GraphLayout { /** * Implements mxGraphLayout.moveCell. */ - moveCell( - cell: Cell, - x: number, - y: number - ): void { + moveCell(cell: Cell, x: number, y: number): void { const model = this.graph.getModel(); const parent = cell.getParent(); const horizontal = this.isHorizontal(); @@ -299,11 +293,7 @@ class StackLayout extends GraphLayout { if (this.graph.isSwimlane(parent)) { // Uses computed style to get latest const style = this.graph.getCellStyle(parent); - let start = getNumber( - style, - 'startSize', - DEFAULT_STARTSIZE - ); + let start = getNumber(style, 'startSize', DEFAULT_STARTSIZE); const horz = getValue(style, 'horizontal', true) == 1; if (pgeo != null) { @@ -343,11 +333,9 @@ class StackLayout extends GraphLayout { if (this.wrap != null && last != null) { if ( (horizontal && - last.x + last.width + geo.width + 2 * this.spacing > - this.wrap) || + last.x + last.width + geo.width + 2 * this.spacing > this.wrap) || (!horizontal && - last.y + last.height + geo.height + 2 * this.spacing > - this.wrap) + last.y + last.height + geo.height + 2 * this.spacing > this.wrap) ) { last = null; @@ -375,32 +363,24 @@ class StackLayout extends GraphLayout { if (horizontal) { geo.x = this.snap( - (this.allowGaps ? Math.max(temp, geo.x) : temp) - - this.marginLeft + (this.allowGaps ? Math.max(temp, geo.x) : temp) - this.marginLeft ) + this.marginLeft; } else { geo.y = this.snap( - (this.allowGaps ? Math.max(temp, geo.y) : temp) - - this.marginTop + (this.allowGaps ? Math.max(temp, geo.y) : temp) - this.marginTop ) + this.marginTop; } } else if (!this.keepFirstLocation) { if (horizontal) { geo.x = this.allowGaps && geo.x > x0 - ? Math.max( - this.snap(geo.x - this.marginLeft) + this.marginLeft, - x0 - ) + ? Math.max(this.snap(geo.x - this.marginLeft) + this.marginLeft, x0) : x0; } else { geo.y = this.allowGaps && geo.y > y0 - ? Math.max( - this.snap(geo.y - this.marginTop) + this.marginTop, - y0 - ) + ? Math.max(this.snap(geo.y - this.marginTop) + this.marginTop, y0) : y0; } } @@ -437,29 +417,14 @@ class StackLayout extends GraphLayout { } } - if ( - this.resizeParent && - pgeo != null && - last != null && - !parent.isCollapsed() - ) { + if (this.resizeParent && pgeo != null && last != null && !parent.isCollapsed()) { this.updateParentGeometry(parent, pgeo, last); - } else if ( - this.resizeLast && - pgeo != null && - last != null && - lastChild != null - ) { + } else if (this.resizeLast && pgeo != null && last != null && lastChild != null) { if (horizontal) { last.width = - pgeo.width - - last.x - - this.spacing - - this.marginRight - - this.marginLeft; + pgeo.width - last.x - this.spacing - this.marginRight - this.marginLeft; } else { - last.height = - pgeo.height - last.y - this.spacing - this.marginBottom; + last.height = pgeo.height - last.y - this.spacing - this.marginBottom; } this.setChildGeometry(lastChild, last); @@ -480,10 +445,7 @@ class StackLayout extends GraphLayout { * child - The given child of . * geo - The specific geometry of . */ - setChildGeometry( - child: Cell, - geo: Geometry - ) { + setChildGeometry(child: Cell, geo: Geometry) { const geo2 = child.getGeometry(); if ( @@ -508,11 +470,7 @@ class StackLayout extends GraphLayout { * pgeo - The new for parent. * last - The last . */ - updateParentGeometry( - parent: Cell, - pgeo: Geometry, - last: Geometry - ) { + updateParentGeometry(parent: Cell, pgeo: Geometry, last: Geometry) { const horizontal = this.isHorizontal(); const model = this.graph.getModel(); diff --git a/packages/core/src/view/layout/layout/hierarchical/SwimlaneLayout.ts b/packages/core/src/view/layout/layout/hierarchical/SwimlaneLayout.ts index 898a84226..b724b2c37 100644 --- a/packages/core/src/view/layout/layout/hierarchical/SwimlaneLayout.ts +++ b/packages/core/src/view/layout/layout/hierarchical/SwimlaneLayout.ts @@ -15,7 +15,7 @@ import ObjectIdentity from '../../../../util/ObjectIdentity'; import mxSwimlaneOrdering from './stage/mxSwimlaneOrdering'; import MedianHybridCrossingReduction from './stage/MedianHybridCrossingReduction'; import CoordinateAssignment from './stage/CoordinateAssignment'; -import Graph from '../../../Graph'; +import { Graph } from '../../../Graph'; import Cell from '../../../cell/datatypes/Cell'; import CellArray from '../../../cell/datatypes/CellArray'; diff --git a/packages/core/src/view/layout/layout/hierarchical/model/SwimlaneModel.ts b/packages/core/src/view/layout/layout/hierarchical/model/SwimlaneModel.ts index 51b7c38f6..7e5168063 100644 --- a/packages/core/src/view/layout/layout/hierarchical/model/SwimlaneModel.ts +++ b/packages/core/src/view/layout/layout/hierarchical/model/SwimlaneModel.ts @@ -4,7 +4,6 @@ * Updated to ES9 syntax by David Morrissey 2021 * Type definitions from the typed-mxgraph project */ -import utils from '../../../../../util/Utils'; import GraphHierarchyNode from './GraphHierarchyNode'; import GraphHierarchyEdge from './GraphHierarchyEdge'; import CellPath from '../../../../cell/datatypes/CellPath'; @@ -487,13 +486,7 @@ class SwimlaneModel { // Only navigate in source->target direction within the same // swimlane, or from a lower index swimlane to a higher one if (root.swimlaneIndex < targetNode.swimlaneIndex) { - this.maxChainDfs( - root, - targetNode, - internalEdge, - clone(seen, null, true), - 0 - ); + this.maxChainDfs(root, targetNode, internalEdge, clone(seen, null, true), 0); } else if (root.swimlaneIndex === targetNode.swimlaneIndex) { this.maxChainDfs( root, diff --git a/packages/core/src/view/layout/layout/hierarchical/stage/mxSwimlaneOrdering.js b/packages/core/src/view/layout/layout/hierarchical/stage/mxSwimlaneOrdering.js index 810626a7c..ba66b4e52 100644 --- a/packages/core/src/view/layout/layout/hierarchical/stage/mxSwimlaneOrdering.js +++ b/packages/core/src/view/layout/layout/hierarchical/stage/mxSwimlaneOrdering.js @@ -5,7 +5,7 @@ * Type definitions from the typed-mxgraph project */ import MxHierarchicalLayoutStage from './HierarchicalLayoutStage'; -import utils, { remove } from '../../../../../util/Utils'; +import { remove } from '../../../../../util/Utils'; import CellPath from '../../../../cell/datatypes/CellPath'; import { clone } from '../../../../../util/CloneUtils'; diff --git a/packages/core/src/view/page_breaks/GraphPageBreaks.ts b/packages/core/src/view/page_breaks/GraphPageBreaksMixin.ts similarity index 84% rename from packages/core/src/view/page_breaks/GraphPageBreaks.ts rename to packages/core/src/view/page_breaks/GraphPageBreaksMixin.ts index 73c726d6f..75deda58e 100644 --- a/packages/core/src/view/page_breaks/GraphPageBreaks.ts +++ b/packages/core/src/view/page_breaks/GraphPageBreaksMixin.ts @@ -1,9 +1,17 @@ import Rectangle from '../geometry/Rectangle'; import Point from '../geometry/Point'; import Polyline from '../geometry/shape/edge/Polyline'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type Graph from '../Graph'; +declare module '../Graph' { + interface Graph { + horizontalPageBreaks: any[] | null; + verticalPageBreaks: any[] | null; + + updatePageBreaks: (visible: boolean, width: number, height: number) => void; + } +} type PartialGraph = Pick< Graph, @@ -16,11 +24,16 @@ type PartialGraph = Pick< | 'getDialect' | 'isPageBreakDashed' >; -type PartialClass = PartialGraph; +type PartialPageBreaks = Pick< + Graph, + 'horizontalPageBreaks' | 'verticalPageBreaks' | 'updatePageBreaks' +>; +type PartialType = PartialGraph & PartialPageBreaks; -class GraphPageBreaks extends autoImplement() { - horizontalPageBreaks: any[] | null = null; - verticalPageBreaks: any[] | null = null; +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphPageBreaksMixin: PartialType = { + horizontalPageBreaks: null, + verticalPageBreaks: null, /** * Invokes from {@link sizeDidChange} to redraw the page breaks. @@ -29,7 +42,7 @@ class GraphPageBreaks extends autoImplement() { * @param width Specifies the width of the container in pixels. * @param height Specifies the height of the container in pixels. */ - updatePageBreaks(visible: boolean, width: number, height: number): void { + updatePageBreaks(visible, width, height) { const { scale, translate: tr } = this.getView(); const fmt = this.getPageFormat(); const ps = scale * this.getPageScale(); @@ -119,7 +132,7 @@ class GraphPageBreaks extends autoImplement() { drawPageBreaks(this.horizontalPageBreaks); drawPageBreaks(this.verticalPageBreaks); - } -} + }, +}; -export default GraphPageBreaks; +mixInto(Graph)(GraphPageBreaksMixin); diff --git a/packages/core/src/view/panning/GraphPanning.ts b/packages/core/src/view/panning/GraphPanningMixin.ts similarity index 81% rename from packages/core/src/view/panning/GraphPanning.ts rename to packages/core/src/view/panning/GraphPanningMixin.ts index 996b8f6e2..a377b2a8d 100644 --- a/packages/core/src/view/panning/GraphPanning.ts +++ b/packages/core/src/view/panning/GraphPanningMixin.ts @@ -1,21 +1,65 @@ -import { autoImplement, hasScrollbars } from '../../util/Utils'; +import { hasScrollbars, mixInto } from '../../util/Utils'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import PanningHandler from './PanningHandler'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; import Cell from '../cell/datatypes/Cell'; import Rectangle from '../geometry/Rectangle'; import Point from '../geometry/Point'; -import GraphEvents from '../event/GraphEvents'; import SelectionCellsHandler from '../selection/SelectionCellsHandler'; -type PartialGraph = Pick; -type PartialEvents = Pick; -type PartialClass = PartialGraph & PartialEvents; +declare module '../Graph' { + interface Graph { + shiftPreview1: HTMLElement | null; + shiftPreview2: HTMLElement | null; + useScrollbarsForPanning: boolean; + timerAutoScroll: boolean; + allowAutoPanning: boolean; + panDx: number; + panDy: number; -class GraphPanning extends autoImplement() { - shiftPreview1: HTMLElement | null = null; - shiftPreview2: HTMLElement | null = null; + isUseScrollbarsForPanning: () => boolean; + isTimerAutoScroll: () => boolean; + isAllowAutoPanning: () => boolean; + getPanDx: () => number; + setPanDx: (dx: number) => void; + getPanDy: () => number; + setPanDy: (dy: number) => void; + panGraph: (dx: number, dy: number) => void; + scrollCellToVisible: (cell: Cell, center?: boolean) => void; + scrollRectToVisible: (rect: Rectangle) => boolean; + setPanning: (enabled: boolean) => void; + } +} + +type PartialGraph = Pick; +type PartialPanning = Pick< + Graph, + | 'shiftPreview1' + | 'shiftPreview2' + | 'useScrollbarsForPanning' + | 'timerAutoScroll' + | 'allowAutoPanning' + | 'panDx' + | 'panDy' + | 'isUseScrollbarsForPanning' + | 'isTimerAutoScroll' + | 'isAllowAutoPanning' + | 'getPanDx' + | 'setPanDx' + | 'getPanDy' + | 'setPanDy' + | 'panGraph' + | 'scrollCellToVisible' + | 'scrollRectToVisible' + | 'setPanning' +>; +type PartialType = PartialGraph & PartialPanning; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphPanningMixin: PartialType = { + shiftPreview1: null, + shiftPreview2: null, /** * Specifies if scrollbars should be used for panning in {@link panGraph} if @@ -24,9 +68,11 @@ class GraphPanning extends autoImplement() { * then no panning occurs if this is `true`. * @default true */ - useScrollbarsForPanning = true; + useScrollbarsForPanning: true, - isUseScrollbarsForPanning = () => this.useScrollbarsForPanning; + isUseScrollbarsForPanning() { + return this.useScrollbarsForPanning; + }, /** * Specifies if autoscrolling should be carried out via mxPanningManager even @@ -36,9 +82,11 @@ class GraphPanning extends autoImplement() { * are visible and scrollable in all directions. * @default false */ - timerAutoScroll = false; + timerAutoScroll: false, - isTimerAutoScroll = () => this.timerAutoScroll; + isTimerAutoScroll() { + return this.timerAutoScroll; + }, /** * Specifies if panning via {@link panGraph} should be allowed to implement autoscroll @@ -47,27 +95,39 @@ class GraphPanning extends autoImplement() { * positive value. * @default false */ - allowAutoPanning = false; + allowAutoPanning: false, - isAllowAutoPanning = () => this.allowAutoPanning; + isAllowAutoPanning() { + return this.allowAutoPanning; + }, /** * Current horizontal panning value. * @default 0 */ - panDx = 0; + panDx: 0, - getPanDx = () => this.panDx; - setPanDx = (dx: number) => (this.panDx = dx); + getPanDx() { + return this.panDx; + }, + + setPanDx(dx) { + this.panDx = dx; + }, /** * Current vertical panning value. * @default 0 */ - panDy = 0; + panDy: 0, - getPanDy = () => this.panDy; - setPanDy = (dy: number) => (this.panDy = dy); + getPanDy() { + return this.panDy; + }, + + setPanDy(dy) { + this.panDy = dy; + }, /** * Shifts the graph display by the given amount. This is used to preview @@ -77,7 +137,7 @@ class GraphPanning extends autoImplement() { * @param dx Amount to shift the graph along the x-axis. * @param dy Amount to shift the graph along the y-axis. */ - panGraph(dx: number, dy: number) { + panGraph(dx, dy) { const container = this.getContainer(); if (this.useScrollbarsForPanning && hasScrollbars(container)) { @@ -175,7 +235,7 @@ class GraphPanning extends autoImplement() { this.fireEvent(new EventObject(InternalEvent.PAN)); } - } + }, /** * Pans the graph so that it shows the given cell. Optionally the cell may @@ -192,7 +252,7 @@ class GraphPanning extends autoImplement() { * @param cell {@link mxCell} to be made visible. * @param center Optional boolean flag. Default is `false`. */ - scrollCellToVisible(cell: Cell, center = false) { + scrollCellToVisible(cell, center = false) { const x = -this.getView().translate.x; const y = -this.getView().translate.y; @@ -221,14 +281,14 @@ class GraphPanning extends autoImplement() { this.getView().setTranslate(tr2.x, tr2.y); } } - } + }, /** * Pans the graph so that it shows the given rectangle. * * @param rect {@link mxRectangle} to be made visible. */ - scrollRectToVisible(rect: Rectangle) { + scrollRectToVisible(rect) { let isChanged = false; const container = this.getContainer(); @@ -311,7 +371,7 @@ class GraphPanning extends autoImplement() { } return isChanged; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -323,11 +383,11 @@ class GraphPanning extends autoImplement() { * * @param enabled Boolean indicating if panning should be enabled. */ - setPanning(enabled: boolean) { + setPanning(enabled) { const panningHandler = this.getPlugin('PanningHandler') as PanningHandler; if (panningHandler) panningHandler.panningEnabled = enabled; - } -} + }, +}; -export default GraphPanning; +mixInto(Graph)(GraphPanningMixin); diff --git a/packages/core/src/view/panning/PanningHandler.ts b/packages/core/src/view/panning/PanningHandler.ts index 802676179..36a000588 100644 --- a/packages/core/src/view/panning/PanningHandler.ts +++ b/packages/core/src/view/panning/PanningHandler.ts @@ -20,7 +20,7 @@ import PanningManager from './PanningManager'; import InternalMouseEvent from '../event/InternalMouseEvent'; import type { GraphPlugin, MouseEventListener } from '../../types'; -import type { MaxGraph } from '../Graph'; +import type { Graph } from '../Graph'; /** * Class: mxPanningHandler @@ -54,7 +54,7 @@ import type { MaxGraph } from '../Graph'; class PanningHandler extends EventSource implements GraphPlugin { static pluginId = 'PanningHandler'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { super(); this.graph = graph; @@ -117,7 +117,7 @@ class PanningHandler extends EventSource implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; panningManager: PanningManager; diff --git a/packages/core/src/view/panning/PanningManager.ts b/packages/core/src/view/panning/PanningManager.ts index 376c6e68b..84bbe5b1e 100644 --- a/packages/core/src/view/panning/PanningManager.ts +++ b/packages/core/src/view/panning/PanningManager.ts @@ -11,7 +11,7 @@ import EventObject from '../event/EventObject'; import EventSource from '../event/EventSource'; import InternalEvent from '../event/InternalEvent'; import InternalMouseEvent from '../event/InternalMouseEvent'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; /** * Class: mxPanningManager @@ -19,7 +19,7 @@ import { MaxGraph } from '../Graph'; * Implements a handler for panning. */ class PanningManager { - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.thread = null; this.active = false; this.tdx = 0; diff --git a/packages/core/src/view/popups_menus/PopupMenuHandler.ts b/packages/core/src/view/popups_menus/PopupMenuHandler.ts index 10788a1c6..46ea19c10 100644 --- a/packages/core/src/view/popups_menus/PopupMenuHandler.ts +++ b/packages/core/src/view/popups_menus/PopupMenuHandler.ts @@ -8,7 +8,7 @@ import PopupMenu from '../../util/gui/PopupMenu'; import InternalEvent from '../event/InternalEvent'; import { getScrollOrigin } from '../../util/Utils'; import { getMainEvent, isMultiTouchEvent } from '../../util/EventUtils'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import InternalMouseEvent from '../event/InternalMouseEvent'; import { GraphPlugin, PopupMenuItem } from '../../types'; import TooltipHandler from '../tooltip/TooltipHandler'; @@ -27,7 +27,7 @@ import EventObject from '../event/EventObject'; class PopupMenuHandler extends PopupMenu implements GraphPlugin { static pluginId = 'PopupMenuHandler'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { super(); this.graph = graph; @@ -53,7 +53,7 @@ class PopupMenuHandler extends PopupMenu implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: selectOnPopup diff --git a/packages/core/src/view/ports/GraphPorts.ts b/packages/core/src/view/ports/GraphPortsMixin.ts similarity index 71% rename from packages/core/src/view/ports/GraphPorts.ts rename to packages/core/src/view/ports/GraphPortsMixin.ts index 4d5175aa1..8b0ff4c42 100644 --- a/packages/core/src/view/ports/GraphPorts.ts +++ b/packages/core/src/view/ports/GraphPortsMixin.ts @@ -1,12 +1,31 @@ +import { mixInto } from '../../util/Utils'; import Cell from '../cell/datatypes/Cell'; +import { Graph } from '../Graph'; -class GraphPorts { +declare module '../Graph' { + interface Graph { + portsEnabled: boolean; + + isPort: (cell: Cell | null) => boolean; + getTerminalForPort: (cell: Cell, source: boolean) => Cell | null; + isPortsEnabled: () => boolean; + setPortsEnabled: (value: boolean) => void; + } +} + +type PartialPorts = Pick< + Graph, + 'portsEnabled' | 'isPort' | 'getTerminalForPort' | 'isPortsEnabled' | 'setPortsEnabled' +>; +type PartialType = PartialPorts; + +const GraphPortsMixin: PartialType = { /** * Specifies if ports are enabled. This is used in {@link cellConnected} to update * the respective style. * @default true */ - portsEnabled: boolean = true; + portsEnabled: true, /***************************************************************************** * Group: Drilldown @@ -33,9 +52,9 @@ class GraphPorts { * * @param cell {@link mxCell} that represents the port. */ - isPort(cell: Cell | null) { + isPort(cell) { return false; - } + }, /** * Returns the terminal to be used for a given port. This implementation @@ -44,9 +63,9 @@ class GraphPorts { * @param cell {@link mxCell} that represents the port. * @param source If the cell is the source or target port. */ - getTerminalForPort(cell: Cell, source: boolean = false): Cell | null { + getTerminalForPort(cell, source = false) { return cell.getParent(); - } + }, /***************************************************************************** * Group: Graph behaviour @@ -55,18 +74,18 @@ class GraphPorts { /** * Returns {@link portsEnabled} as a boolean. */ - isPortsEnabled(): boolean { + isPortsEnabled() { return this.portsEnabled; - } + }, /** * Specifies if the ports should be enabled. * * @param value Boolean indicating if the ports should be enabled. */ - setPortsEnabled(value: boolean): void { + setPortsEnabled(value) { this.portsEnabled = value; - } -} + }, +}; -export default GraphPorts; +mixInto(Graph)(GraphPortsMixin); diff --git a/packages/core/src/view/printing/PrintPreview.ts b/packages/core/src/view/printing/PrintPreview.ts index cbc33a262..204a6ade2 100644 --- a/packages/core/src/view/printing/PrintPreview.ts +++ b/packages/core/src/view/printing/PrintPreview.ts @@ -8,10 +8,10 @@ import Rectangle from '../geometry/Rectangle'; import TemporaryCellStates from '../cell/TemporaryCellStates'; import InternalEvent from '../event/InternalEvent'; import mxClient from '../../mxClient'; -import utils, { intersects } from '../../util/Utils'; +import { intersects } from '../../util/Utils'; import { DIALECT_SVG } from '../../util/Constants'; import { write } from '../../util/DomUtils'; -import Graph from '../Graph'; +import { Graph } from '../Graph'; /** * @class PrintPreview diff --git a/packages/core/src/view/selection/CellHighlight.ts b/packages/core/src/view/selection/CellHighlight.ts index d6508b965..8e3c07ad8 100644 --- a/packages/core/src/view/selection/CellHighlight.ts +++ b/packages/core/src/view/selection/CellHighlight.ts @@ -198,7 +198,7 @@ class CellHighlight { this.state.width + 2 * this.spacing, this.state.height + 2 * this.spacing ); - this.shape.rotation = Number(this.state.style.rotation || '0'); + this.shape.rotation = this.state.style.rotation ?? 0; this.shape.strokeWidth = this.getStrokeWidth() / this.state.view.scale; this.shape.outline = true; } diff --git a/packages/core/src/view/selection/GraphSelection.ts b/packages/core/src/view/selection/GraphSelectionMixin.ts similarity index 72% rename from packages/core/src/view/selection/GraphSelection.ts rename to packages/core/src/view/selection/GraphSelectionMixin.ts index b4672d601..ab14f0510 100644 --- a/packages/core/src/view/selection/GraphSelection.ts +++ b/packages/core/src/view/selection/GraphSelectionMixin.ts @@ -9,75 +9,192 @@ import InternalEvent from '../event/InternalEvent'; import Dictionary from '../../util/Dictionary'; import RootChange from '../model/RootChange'; import ChildChange from '../model/ChildChange'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type GraphCells from '../cell/GraphCells'; -import type Graph from '../Graph'; -import type GraphEvents from '../event/GraphEvents'; -import type EventSource from '../event/EventSource'; -import { MaxGraph } from '../Graph'; +declare module '../Graph' { + interface Graph { + cells: CellArray; + doneResource: string; + updatingSelectionResource: string; + singleSelection: boolean; + selectionModel: any | null; + + getDoneResource: () => string; + getUpdatingSelectionResource: () => string; + getSelectionModel: () => any; + setSelectionModel: (selectionModel: any) => void; + isSingleSelection: () => boolean; + setSingleSelection: (singleSelection: boolean) => void; + isSelected: (cell: Cell) => boolean; + isEmpty: () => boolean; + clear: () => void; + setCell: (cell: Cell | null) => void; + setCells: (cells: CellArray) => void; + getFirstSelectableCell: (cells: CellArray) => Cell | null; + addCellToSelection: (cell: Cell) => void; + addCellsToSelection: (cells: CellArray) => void; + removeCellFromSelection: (cell: Cell) => void; + removeCellsFromSelection: (cells: CellArray) => void; + changeSelection: (added: CellArray | null, removed: CellArray | null) => void; + cellAdded: (cell: Cell) => void; + cellRemoved: (cell: Cell) => void; + isCellSelected: (cell: Cell) => boolean; + isSelectionEmpty: () => boolean; + clearSelection: () => void; + getSelectionCount: () => number; + getSelectionCell: () => Cell; + getSelectionCells: () => CellArray; + setSelectionCell: (cell: Cell | null) => void; + setSelectionCells: (cells: CellArray) => void; + addSelectionCell: (cell: Cell) => void; + addSelectionCells: (cells: CellArray) => void; + removeSelectionCell: (cell: Cell) => void; + removeSelectionCells: (cells: CellArray) => void; + selectRegion: (rect: Rectangle, evt: MouseEvent) => CellArray; + selectNextCell: () => void; + selectPreviousCell: () => void; + selectParentCell: () => void; + selectChildCell: () => void; + selectCell: (isNext?: boolean, isParent?: boolean, isChild?: boolean) => void; + selectAll: (parent?: Cell | null, descendants?: boolean) => void; + selectVertices: (parent: Cell, selectGroups: boolean) => void; + selectEdges: (parent: Cell) => void; + selectCells: ( + vertices: boolean, + edges: boolean, + parent: Cell, + selectGroups?: boolean + ) => void; + selectCellForEvent: (cell: Cell, evt: MouseEvent) => void; + selectCellsForEvent: (cells: CellArray, evt: MouseEvent) => void; + isSiblingSelected: (cell: Cell) => boolean; + getSelectionCellsForChanges: (changes: any[], ignoreFn: Function | null) => CellArray; + updateSelection: () => void; + } +} type PartialGraph = Pick< Graph, - 'fireEvent' | 'getDefaultParent' | 'getView' | 'getCurrentRoot' | 'getModel' + | 'getModel' + | 'getView' + | 'isCellSelectable' + | 'fireEvent' + | 'getDefaultParent' + | 'getCurrentRoot' + | 'getCells' + | 'isToggleEvent' >; -type PartialCells = Pick; -type PartialEvents = Pick; -type PartialClass = PartialGraph & PartialCells & PartialEvents & EventSource; +type PartialCells = Pick< + Graph, + | 'cells' + | 'doneResource' + | 'updatingSelectionResource' + | 'singleSelection' + | 'selectionModel' + | 'getDoneResource' + | 'getUpdatingSelectionResource' + | 'getSelectionModel' + | 'setSelectionModel' + | 'isSingleSelection' + | 'setSingleSelection' + | 'isSelected' + | 'isEmpty' + | 'clear' + | 'setCell' + | 'setCells' + | 'getFirstSelectableCell' + | 'addCellToSelection' + | 'addCellsToSelection' + | 'removeCellFromSelection' + | 'removeCellsFromSelection' + | 'changeSelection' + | 'cellAdded' + | 'cellRemoved' + | 'isCellSelected' + | 'isSelectionEmpty' + | 'clearSelection' + | 'getSelectionCount' + | 'getSelectionCell' + | 'getSelectionCells' + | 'setSelectionCell' + | 'setSelectionCells' + | 'addSelectionCell' + | 'addSelectionCells' + | 'removeSelectionCell' + | 'removeSelectionCells' + | 'selectRegion' + | 'selectNextCell' + | 'selectPreviousCell' + | 'selectParentCell' + | 'selectChildCell' + | 'selectCell' + | 'selectAll' + | 'selectVertices' + | 'selectEdges' + | 'selectCells' + | 'selectCellForEvent' + | 'selectCellsForEvent' + | 'isSiblingSelected' + | 'getSelectionCellsForChanges' + | 'updateSelection' +>; +type PartialType = PartialGraph & PartialCells; -// @ts-ignore recursive reference error -class GraphSelection extends autoImplement() { - // TODO: Document me!! - cells: CellArray = new CellArray(); +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphSelectionMixin: PartialType = { + cells: new CellArray(), /** * Specifies the resource key for the status message after a long operation. * If the resource for this key does not exist then the value is used as * the status message. Default is 'done'. */ - doneResource: string = mxClient.language !== 'none' ? 'done' : ''; - - getDoneResource = () => this.doneResource; + doneResource: mxClient.language !== 'none' ? 'done' : '', /** * Specifies the resource key for the status message while the selection is * being updated. If the resource for this key does not exist then the * value is used as the status message. Default is 'updatingSelection'. */ - updatingSelectionResource: string = - mxClient.language !== 'none' ? 'updatingSelection' : ''; - - getUpdatingSelectionResource = () => this.updatingSelectionResource; + updatingSelectionResource: mxClient.language !== 'none' ? 'updatingSelection' : '', /** * Specifies if only one selected item at a time is allowed. * Default is false. */ - singleSelection: boolean = false; + singleSelection: false, - // TODO: Document me!! - selectionModel: GraphSelection | null = null; + selectionModel: null, + + getDoneResource() { + return this.doneResource; + }, + + getUpdatingSelectionResource() { + return this.updatingSelectionResource; + }, /** * Returns the {@link mxGraphSelectionModel} that contains the selection. */ getSelectionModel() { return this.selectionModel; - } + }, /** * Sets the {@link mxSelectionModel} that contains the selection. */ - setSelectionModel(selectionModel: GraphSelection) { + setSelectionModel(selectionModel) { this.selectionModel = selectionModel; - } + }, /** * Returns {@link singleSelection} as a boolean. */ isSingleSelection() { return this.singleSelection; - } + }, /** * Sets the {@link singleSelection} flag. @@ -85,23 +202,23 @@ class GraphSelection extends autoImplement() { * @param {boolean} singleSelection Boolean that specifies the new value for * {@link singleSelection}. */ - setSingleSelection(singleSelection: boolean) { + setSingleSelection(singleSelection) { this.singleSelection = singleSelection; - } + }, /** * Returns true if the given {@link Cell} is selected. */ - isSelected(cell: Cell) { + isSelected(cell) { return this.cells.indexOf(cell) >= 0; - } + }, /** * Returns true if no cells are currently selected. */ isEmpty() { return this.cells.length === 0; - } + }, /** * Clears the selection and fires a {@link change} event if the selection was not @@ -109,23 +226,23 @@ class GraphSelection extends autoImplement() { */ clear() { this.changeSelection(null, this.cells); - } + }, /** * Selects the specified {@link Cell} using {@link setCells}. * * @param cell {@link mxCell} to be selected. */ - setCell(cell: Cell | null) { + setCell(cell) { this.setCells(cell ? new CellArray(cell) : new CellArray()); - } + }, /** * Selects the given array of {@link Cell} and fires a {@link change} event. * * @param cells Array of {@link Cell} to be selected. */ - setCells(cells: CellArray): void { + setCells(cells) { if (this.singleSelection) { cells = new CellArray(this.getFirstSelectableCell(cells)); } @@ -137,12 +254,12 @@ class GraphSelection extends autoImplement() { } } this.changeSelection(tmp, this.cells); - } + }, /** * Returns the first selectable cell in the given array of cells. */ - getFirstSelectableCell(cells: CellArray) { + getFirstSelectableCell(cells) { for (let i = 0; i < cells.length; i += 1) { if (this.isCellSelectable(cells[i])) { return cells[i]; @@ -150,16 +267,16 @@ class GraphSelection extends autoImplement() { } return null; - } + }, /** * Adds the given {@link Cell} to the selection and fires a {@link select} event. * * @param cell {@link mxCell} to add to the selection. */ - addCellToSelection(cell: Cell) { + addCellToSelection(cell) { this.addCellsToSelection(new CellArray(cell)); - } + }, /** * Adds the given array of {@link Cell} to the selection and fires a {@link select} @@ -167,7 +284,7 @@ class GraphSelection extends autoImplement() { * * @param cells Array of {@link Cell} to add to the selection. */ - addCellsToSelection(cells: CellArray) { + addCellsToSelection(cells) { let remove = null; if (this.singleSelection) { remove = this.cells; @@ -185,7 +302,7 @@ class GraphSelection extends autoImplement() { } this.changeSelection(tmp, remove); - } + }, /** * Removes the specified {@link Cell} from the selection and fires a {@link select} @@ -193,9 +310,9 @@ class GraphSelection extends autoImplement() { * * @param cell {@link mxCell} to remove from the selection. */ - removeCellFromSelection(cell: Cell) { + removeCellFromSelection(cell) { this.removeCellsFromSelection(new CellArray(cell)); - } + }, /** * Removes the specified {@link Cell} from the selection and fires a {@link select} @@ -203,7 +320,7 @@ class GraphSelection extends autoImplement() { * * @param cells {@link mxCell}s to remove from the selection. */ - removeCellsFromSelection(cells: CellArray) { + removeCellsFromSelection(cells) { const tmp = new CellArray(); for (let i = 0; i < cells.length; i += 1) { @@ -213,7 +330,7 @@ class GraphSelection extends autoImplement() { } this.changeSelection(null, tmp); - } + }, /** * Adds/removes the specified arrays of {@link Cell} to/from the selection. @@ -221,22 +338,22 @@ class GraphSelection extends autoImplement() { * @param added Array of {@link Cell} to add to the selection. * @param remove Array of {@link Cell} to remove from the selection. */ - changeSelection(added: CellArray | null = null, removed: CellArray | null = null) { + changeSelection(added = null, removed = null) { if ( (added && added.length > 0 && added[0]) || (removed && removed.length > 0 && removed[0]) ) { const change = new SelectionChange( - this as MaxGraph, + this as Graph, added || new CellArray(), removed || new CellArray() ); change.execute(); - const edit = new UndoableEdit(this, false); + const edit = new UndoableEdit(this as Graph, false); edit.add(change); this.fireEvent(new EventObject(InternalEvent.UNDO, 'edit', edit)); } - } + }, /** * Inner callback to add the specified {@link Cell} to the selection. No event @@ -246,11 +363,11 @@ class GraphSelection extends autoImplement() { * * @param cell {@link mxCell} to add to the selection. */ - cellAdded(cell: Cell) { + cellAdded(cell) { if (!this.isSelected(cell)) { this.cells.push(cell); } - } + }, /** * Inner callback to remove the specified {@link Cell} from the selection. No @@ -258,12 +375,12 @@ class GraphSelection extends autoImplement() { * * @param cell {@link mxCell} to remove from the selection. */ - cellRemoved(cell: Cell) { + cellRemoved(cell) { const index = this.cells.indexOf(cell); if (index >= 0) { this.cells.splice(index, 1); } - } + }, /***************************************************************************** * Selection @@ -274,98 +391,98 @@ class GraphSelection extends autoImplement() { * * @param cell {@link mxCell} for which the selection state should be returned. */ - isCellSelected(cell: Cell) { + isCellSelected(cell) { return this.isSelected(cell); - } + }, /** * Returns true if the selection is empty. */ isSelectionEmpty() { return this.isEmpty(); - } + }, /** * Clears the selection using {@link mxGraphSelectionModel.clear}. */ clearSelection() { this.clear(); - } + }, /** * Returns the number of selected cells. */ getSelectionCount() { return this.cells.length; - } + }, /** * Returns the first cell from the array of selected {@link Cell}. */ getSelectionCell() { return this.cells[0]; - } + }, /** * Returns the array of selected {@link Cell}. */ getSelectionCells() { return this.cells.slice(); - } + }, /** * Sets the selection cell. * * @param cell {@link mxCell} to be selected. */ - setSelectionCell(cell: Cell | null) { + setSelectionCell(cell) { this.setCell(cell); - } + }, /** * Sets the selection cell. * * @param cells Array of {@link Cell} to be selected. */ - setSelectionCells(cells: CellArray) { + setSelectionCells(cells) { this.setCells(cells); - } + }, /** * Adds the given cell to the selection. * * @param cell {@link mxCell} to be add to the selection. */ - addSelectionCell(cell: Cell) { + addSelectionCell(cell) { this.addCellToSelection(cell); - } + }, /** * Adds the given cells to the selection. * * @param cells Array of {@link Cell} to be added to the selection. */ - addSelectionCells(cells: CellArray) { + addSelectionCells(cells) { this.addCellsToSelection(cells); - } + }, /** * Removes the given cell from the selection. * * @param cell {@link mxCell} to be removed from the selection. */ - removeSelectionCell(cell: Cell) { + removeSelectionCell(cell) { this.removeCellFromSelection(cell); - } + }, /** * Removes the given cells from the selection. * * @param cells Array of {@link Cell} to be removed from the selection. */ - removeSelectionCells(cells: CellArray) { + removeSelectionCells(cells) { this.removeCellsFromSelection(cells); - } + }, /** * Selects and returns the cells inside the given rectangle for the @@ -375,39 +492,39 @@ class GraphSelection extends autoImplement() { * @param evt Mouseevent that triggered the selection. */ // selectRegion(rect: mxRectangle, evt: Event): mxCellArray; - selectRegion(rect: Rectangle, evt: MouseEvent) { + selectRegion(rect, evt) { const cells = this.getCells(rect.x, rect.y, rect.width, rect.height); this.selectCellsForEvent(cells, evt); return cells; - } + }, /** * Selects the next cell. */ selectNextCell() { this.selectCell(true); - } + }, /** * Selects the previous cell. */ selectPreviousCell() { this.selectCell(); - } + }, /** * Selects the parent cell. */ selectParentCell() { this.selectCell(false, true); - } + }, /** * Selects the first child cell. */ selectChildCell() { this.selectCell(false, false, true); - } + }, /** * Selects the next, parent, first child or previous cell, if all arguments @@ -460,7 +577,7 @@ class GraphSelection extends autoImplement() { this.setSelectionCell(child); } } - } + }, /** * Selects all children of the given parent cell or the children of the @@ -472,7 +589,9 @@ class GraphSelection extends autoImplement() { * @param descendants Optional boolean specifying whether all descendants should be * selected. Default is `false`. */ - selectAll(parent: Cell = this.getDefaultParent(), descendants: boolean = false) { + selectAll(parent, descendants = false) { + parent = parent ?? this.getDefaultParent(); + const cells = descendants ? parent.filterDescendants((cell: Cell) => { return cell !== parent && !!this.getView().getState(cell); @@ -480,21 +599,21 @@ class GraphSelection extends autoImplement() { : parent.getChildren(); this.setSelectionCells(cells); - } + }, /** * Select all vertices inside the given parent or the default parent. */ - selectVertices(parent: Cell, selectGroups = false) { + selectVertices(parent, selectGroups = false) { this.selectCells(true, false, parent, selectGroups); - } + }, /** * Select all vertices inside the given parent or the default parent. */ - selectEdges(parent: Cell) { + selectEdges(parent) { this.selectCells(false, true, parent); - } + }, /** * Selects all vertices and/or edges depending on the given boolean @@ -509,12 +628,9 @@ class GraphSelection extends autoImplement() { * @param selectGroups Optional boolean that specifies if groups should be * selected. Default is `false`. */ - selectCells( - vertices = false, - edges = false, - parent: Cell = this.getDefaultParent(), - selectGroups = false - ) { + selectCells(vertices = false, edges = false, parent, selectGroups = false) { + parent = parent ?? this.getDefaultParent(); + const filter = (cell: Cell) => { const p = cell.getParent(); @@ -531,7 +647,7 @@ class GraphSelection extends autoImplement() { const cells = parent.filterDescendants(filter); this.setSelectionCells(cells); - } + }, /** * Selects the given cell by either adding it to the selection or @@ -541,7 +657,7 @@ class GraphSelection extends autoImplement() { * @param cell {@link mxCell} to be selected. * @param evt Optional mouseevent that triggered the selection. */ - selectCellForEvent(cell: Cell, evt: MouseEvent) { + selectCellForEvent(cell, evt) { const isSelected = this.isCellSelected(cell); if (this.isToggleEvent(evt)) { @@ -553,7 +669,7 @@ class GraphSelection extends autoImplement() { } else if (!isSelected || this.getSelectionCount() !== 1) { this.setSelectionCell(cell); } - } + }, /** * Selects the given cells by either adding them to the selection or @@ -563,18 +679,18 @@ class GraphSelection extends autoImplement() { * @param cells Array of {@link Cell} to be selected. * @param evt Optional mouseevent that triggered the selection. */ - selectCellsForEvent(cells: CellArray, evt: MouseEvent) { + selectCellsForEvent(cells, evt) { if (this.isToggleEvent(evt)) { this.addSelectionCells(cells); } else { this.setSelectionCells(cells); } - } + }, /** * Returns true if any sibling of the given cell is selected. */ - isSiblingSelected(cell: Cell) { + isSiblingSelected(cell) { const parent = cell.getParent() as Cell; const childCount = parent.getChildCount(); @@ -586,7 +702,7 @@ class GraphSelection extends autoImplement() { } return false; - } + }, /***************************************************************************** * Selection state @@ -603,7 +719,7 @@ class GraphSelection extends autoImplement() { * change should be ignored. * */ - getSelectionCellsForChanges(changes: any[], ignoreFn: Function | null = null) { + getSelectionCellsForChanges(changes, ignoreFn = null) { const dict = new Dictionary(); const cells: CellArray = new CellArray(); @@ -640,7 +756,7 @@ class GraphSelection extends autoImplement() { } } return cells; - } + }, /** * Removes selection cells that are not in the model from the selection. @@ -666,7 +782,7 @@ class GraphSelection extends autoImplement() { } } this.removeSelectionCells(removed); - } -} + }, +}; -export default GraphSelection; +mixInto(Graph)(GraphSelectionMixin); diff --git a/packages/core/src/view/selection/RubberBand.ts b/packages/core/src/view/selection/RubberBand.ts index 220d6cb4a..544d99f0f 100644 --- a/packages/core/src/view/selection/RubberBand.ts +++ b/packages/core/src/view/selection/RubberBand.ts @@ -17,7 +17,7 @@ import mxClient from '../../mxClient'; import Rectangle from '../geometry/Rectangle'; import { isAltDown, isMultiTouchEvent } from '../../util/EventUtils'; import { clearSelection } from '../../util/DomUtils'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import { GraphPlugin } from '../../types'; import EventObject from '../event/EventObject'; import EventSource from '../event/EventSource'; @@ -30,7 +30,7 @@ import EventSource from '../event/EventSource'; class RubberBand implements GraphPlugin { static pluginId = 'RubberBand'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.graph = graph; this.graph.addMouseListener(this); @@ -71,7 +71,7 @@ class RubberBand implements GraphPlugin { forceRubberbandHandler: Function; panHandler: Function; gestureHandler: Function; - graph: MaxGraph; + graph: Graph; first: Point | null = null; destroyed: boolean = false; dragHandler: ((evt: MouseEvent) => void) | null = null; diff --git a/packages/core/src/view/selection/SelectionCellsHandler.ts b/packages/core/src/view/selection/SelectionCellsHandler.ts index c30255334..97823b896 100644 --- a/packages/core/src/view/selection/SelectionCellsHandler.ts +++ b/packages/core/src/view/selection/SelectionCellsHandler.ts @@ -9,7 +9,7 @@ import Dictionary from '../../util/Dictionary'; import EventObject from '../event/EventObject'; import InternalEvent from '../event/InternalEvent'; import { sortCells } from '../../util/Utils'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import Cell from '../cell/datatypes/Cell'; import CellState from '../cell/datatypes/CellState'; import { GraphPlugin } from '../../types'; @@ -42,7 +42,7 @@ import InternalMouseEvent from '../event/InternalMouseEvent'; class SelectionCellsHandler extends EventSource implements GraphPlugin { static pluginId = 'SelectionCellsHandler'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { super(); this.graph = graph; @@ -71,7 +71,7 @@ class SelectionCellsHandler extends EventSource implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: enabled diff --git a/packages/core/src/view/selection/SelectionChange.ts b/packages/core/src/view/selection/SelectionChange.ts index 65a591521..73920e5e6 100644 --- a/packages/core/src/view/selection/SelectionChange.ts +++ b/packages/core/src/view/selection/SelectionChange.ts @@ -4,7 +4,7 @@ import InternalEvent from '../event/InternalEvent'; import CellArray from '../cell/datatypes/CellArray'; import type { UndoableChange } from '../../types'; -import type { MaxGraph } from '../Graph'; +import type { Graph } from '../Graph'; /** * @class SelectionChange @@ -12,7 +12,7 @@ import type { MaxGraph } from '../Graph'; */ class SelectionChange implements UndoableChange { constructor( - graph: MaxGraph, + graph: Graph, added: CellArray = new CellArray(), removed: CellArray = new CellArray() ) { @@ -21,7 +21,7 @@ class SelectionChange implements UndoableChange { this.removed = removed.slice(); } - graph: MaxGraph; + graph: Graph; added: CellArray; diff --git a/packages/core/src/view/snap/GraphSnap.ts b/packages/core/src/view/snap/GraphSnapMixin.ts similarity index 70% rename from packages/core/src/view/snap/GraphSnap.ts rename to packages/core/src/view/snap/GraphSnapMixin.ts index f09e69dac..5237ded11 100644 --- a/packages/core/src/view/snap/GraphSnap.ts +++ b/packages/core/src/view/snap/GraphSnapMixin.ts @@ -1,29 +1,66 @@ -import { autoImplement } from '../../util/Utils'; +import { mixInto } from '../../util/Utils'; import Point from '../geometry/Point'; import Rectangle from '../geometry/Rectangle'; +import { Graph } from '../Graph'; -import type Graph from '../Graph'; +declare module '../Graph' { + interface Graph { + snapTolerance: number; + gridSize: number; + gridEnabled: boolean; + + getSnapTolerance: () => number; + snap: (value: number) => number; + snapDelta: ( + delta: Point, + bounds: Rectangle, + ignoreGrid: boolean, + ignoreHorizontal: boolean, + ignoreVertical: boolean + ) => Point; + isGridEnabled: () => boolean; + setGridEnabled: (value: boolean) => void; + getGridSize: () => number; + setGridSize: (value: number) => void; + } +} type PartialGraph = Pick; -type PartialClass = PartialGraph; +type PartialSnap = Pick< + Graph, + | 'snapTolerance' + | 'gridSize' + | 'gridEnabled' + | 'getSnapTolerance' + | 'snap' + | 'snapDelta' + | 'isGridEnabled' + | 'setGridEnabled' + | 'getGridSize' + | 'setGridSize' +>; +type PartialType = PartialGraph & PartialSnap; -class GraphSnap extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphSnapMixin: PartialType = { // TODO: Document me! - snapTolerance: number = 0; + snapTolerance: 0, - getSnapTolerance = () => this.snapTolerance; + getSnapTolerance() { + return this.snapTolerance; + }, /** * Specifies the grid size. * @default 10 */ - gridSize = 10; + gridSize: 10, /** * Specifies if the grid is enabled. This is used in {@link snap}. * @default true */ - gridEnabled = true; + gridEnabled: true, /***************************************************************************** * Group: Graph display @@ -34,12 +71,12 @@ class GraphSnap extends autoImplement() { * * @param value Numeric value to be snapped to the grid. */ - snap(value: number) { + snap(value) { if (this.gridEnabled) { value = Math.round(value / this.gridSize) * this.gridSize; } return value; - } + }, /** * Function: snapDelta @@ -47,8 +84,8 @@ class GraphSnap extends autoImplement() { * Snaps the given delta with the given scaled bounds. */ snapDelta( - delta: Point, - bounds: Rectangle, + delta, + bounds, ignoreGrid = false, ignoreHorizontal = false, ignoreVertical = false @@ -102,7 +139,7 @@ class GraphSnap extends autoImplement() { } } return delta; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -113,44 +150,30 @@ class GraphSnap extends autoImplement() { */ isGridEnabled() { return this.gridEnabled; - } + }, /** * Specifies if the grid should be enabled. * * @param value Boolean indicating if the grid should be enabled. */ - setGridEnabled(value: boolean) { + setGridEnabled(value) { this.gridEnabled = value; - } + }, /** * Returns {@link gridSize}. */ getGridSize() { return this.gridSize; - } + }, /** * Sets {@link gridSize}. */ - setGridSize(value: number) { + setGridSize(value) { this.gridSize = value; - } + }, +}; - /** - * Returns {@link tolerance}. - */ - getTolerance() { - return this.snapTolerance; - } - - /** - * Sets {@link tolerance}. - */ - setTolerance(value: number) { - this.snapTolerance = value; - } -} - -export default GraphSnap; +mixInto(Graph)(GraphSnapMixin); diff --git a/packages/core/src/view/style/EdgeStyle.ts b/packages/core/src/view/style/EdgeStyle.ts index 219e1978a..69ce4baf4 100644 --- a/packages/core/src/view/style/EdgeStyle.ts +++ b/packages/core/src/view/style/EdgeStyle.ts @@ -5,7 +5,7 @@ * Type definitions from the typed-mxgraph project */ -import utils, { +import { contains, getBoundingBox, getNumber, @@ -129,8 +129,7 @@ class EdgeStyle { static EntityRelation(state, source, target, points, result) { const { view } = state; const { graph } = view; - const segment = - getValue(state.style, 'segment', ENTITY_SEGMENT) * view.scale; + const segment = getValue(state.style, 'segment', ENTITY_SEGMENT) * view.scale; const pts = state.absolutePoints; const p0 = pts[0]; @@ -145,8 +144,7 @@ class EdgeStyle { isSourceLeft = sourceGeometry.x <= 0.5; } else if (target != null) { isSourceLeft = - (pe != null ? pe.x : target.x + target.width) < - (p0 != null ? p0.x : source.x); + (pe != null ? pe.x : target.x + target.width) < (p0 != null ? p0.x : source.x); } } @@ -155,12 +153,7 @@ class EdgeStyle { source.x = p0.x; source.y = p0.y; } else if (source != null) { - const constraint = getPortConstraints( - source, - state, - true, - DIRECTION_MASK_NONE - ); + const constraint = getPortConstraints(source, state, true, DIRECTION_MASK_NONE); if ( constraint !== DIRECTION_MASK_NONE && @@ -181,8 +174,7 @@ class EdgeStyle { isTargetLeft = targetGeometry.x <= 0.5; } else if (source != null) { isTargetLeft = - (p0 != null ? p0.x : source.x + source.width) < - (pe != null ? pe.x : target.x); + (p0 != null ? p0.x : source.x + source.width) < (pe != null ? pe.x : target.x); } } @@ -191,12 +183,7 @@ class EdgeStyle { target.x = pe.x; target.y = pe.y; } else if (target != null) { - const constraint = getPortConstraints( - target, - state, - false, - DIRECTION_MASK_NONE - ); + const constraint = getPortConstraints(target, state, false, DIRECTION_MASK_NONE); if ( constraint !== DIRECTION_MASK_NONE && @@ -223,9 +210,7 @@ class EdgeStyle { // Adds intermediate points if both go out on same side if (isSourceLeft === isTargetLeft) { - const x = isSourceLeft - ? Math.min(x0, xe) - segment - : Math.max(x0, xe) + segment; + const x = isSourceLeft ? Math.min(x0, xe) - segment : Math.max(x0, xe) + segment; result.push(new Point(x, y0)); result.push(new Point(x, ye)); @@ -284,14 +269,8 @@ class EdgeStyle { let y = 0; let dy = 0; - const seg = - getValue(state.style, 'segment', graph.gridSize) * - view.scale; - const dir = getValue( - state.style, - 'direction', - DIRECTION_WEST - ); + const seg = getValue(state.style, 'segment', graph.gridSize) * view.scale; + const dir = getValue(state.style, 'direction', DIRECTION_WEST); if (dir === DIRECTION_NORTH || dir === DIRECTION_SOUTH) { x = view.getRoutingCenterX(source); @@ -343,16 +322,10 @@ class EdgeStyle { if (source != null && target != null) { if (pt != null) { const left = Math.min(source.x, target.x); - const right = Math.max( - source.x + source.width, - target.x + target.width - ); + const right = Math.max(source.x + source.width, target.x + target.width); const top = Math.min(source.y, target.y); - const bottom = Math.max( - source.y + source.height, - target.y + target.height - ); + const bottom = Math.max(source.y + source.height, target.y + target.height); pt = state.view.transformControlPoint(state, pt); @@ -360,29 +333,20 @@ class EdgeStyle { horizontal = pt.x < left || pt.x > right; } else { const left = Math.max(source.x, target.x); - const right = Math.min( - source.x + source.width, - target.x + target.width - ); + const right = Math.min(source.x + source.width, target.x + target.width); vertical = left === right; if (!vertical) { const top = Math.max(source.y, target.y); - const bottom = Math.min( - source.y + source.height, - target.y + target.height - ); + const bottom = Math.min(source.y + source.height, target.y + target.height); horizontal = top === bottom; } } } - if ( - !horizontal && - (vertical || state.style.elbow === ELBOW_VERTICAL) - ) { + if (!horizontal && (vertical || state.style.elbow === ELBOW_VERTICAL)) { EdgeStyle.TopToBottom(state, source, target, points, result); } else { EdgeStyle.SideToSide(state, source, target, points, result); @@ -437,34 +401,22 @@ class EdgeStyle { } } - if ( - !contains(target, x, y1) && - !contains(source, x, y1) - ) { + if (!contains(target, x, y1) && !contains(source, x, y1)) { result.push(new Point(x, y1)); } - if ( - !contains(target, x, y2) && - !contains(source, x, y2) - ) { + if (!contains(target, x, y2) && !contains(source, x, y2)) { result.push(new Point(x, y2)); } if (result.length === 1) { if (pt != null) { - if ( - !contains(target, x, pt.y) && - !contains(source, x, pt.y) - ) { + if (!contains(target, x, pt.y) && !contains(source, x, pt.y)) { result.push(new Point(x, pt.y)); } } else { const t = Math.max(source.y, target.y); - const b = Math.min( - source.y + source.height, - target.y + target.height - ); + const b = Math.min(source.y + source.height, target.y + target.height); result.push(new Point(x, t + (b - t) / 2)); } @@ -529,10 +481,7 @@ class EdgeStyle { if (result.length === 1) { if (pt != null && result.length === 1) { - if ( - !contains(target, pt.x, y) && - !contains(source, pt.x, y) - ) { + if (!contains(target, pt.x, y) && !contains(source, pt.x, y)) { result.push(new Point(pt.x, y)); } } else { @@ -559,18 +508,9 @@ class EdgeStyle { * edge. * */ - static SegmentConnector( - state, - sourceScaled, - targetScaled, - controlHints, - result - ) { + static SegmentConnector(state, sourceScaled, targetScaled, controlHints, result) { // Creates array of all way- and terminalpoints - const pts = EdgeStyle.scalePointArray( - state.absolutePoints, - state.view.scale - ); + const pts = EdgeStyle.scalePointArray(state.absolutePoints, state.view.scale); const source = EdgeStyle.scaleCellState(sourceScaled, state.view.scale); const target = EdgeStyle.scaleCellState(targetScaled, state.view.scale); const tol = 1; @@ -618,11 +558,7 @@ class EdgeStyle { let hints = []; for (let i = 0; i < controlHints.length; i += 1) { - const tmp = state.view.transformControlPoint( - state, - controlHints[i], - true - ); + const tmp = state.view.transformControlPoint(state, controlHints[i], true); if (tmp != null) { hints.push(tmp); @@ -671,10 +607,8 @@ class EdgeStyle { // Check for alignment with fixed points and with channels // at source and target segments only for (let i = 0; i < 2; i += 1) { - const fixedVertAlign = - currentPt != null && currentPt.x === currentHint.x; - const fixedHozAlign = - currentPt != null && currentPt.y === currentHint.y; + const fixedVertAlign = currentPt != null && currentPt.x === currentHint.x; + const fixedHozAlign = currentPt != null && currentPt.y === currentHint.y; const inHozChan = currentTerm != null && @@ -692,10 +626,7 @@ class EdgeStyle { // of a floating port, or if the hint is exactly co-incident with a // fixed point, ignore the source and try to work out the orientation // from the target end - if ( - i == 0 && - ((hozChan && vertChan) || (fixedVertAlign && fixedHozAlign)) - ) { + if (i == 0 && ((hozChan && vertChan) || (fixedVertAlign && fixedHozAlign))) { } else { if ( currentPt != null && @@ -826,11 +757,7 @@ class EdgeStyle { while ( result.length > 1 && result[result.length - 1] != null && - contains( - target, - result[result.length - 1].x, - result[result.length - 1].y - ) + contains(target, result[result.length - 1].x, result[result.length - 1].y) ) { result.splice(result.length - 1, 1); } @@ -967,11 +894,7 @@ class EdgeStyle { if (value === 'auto') { // Computes the automatic jetty size - const type = getValue( - state.style, - isSource ? 'startArrow' : 'endArrow', - NONE - ); + const type = getValue(state.style, isSource ? 'startArrow' : 'endArrow', NONE); if (type !== NONE) { const size = getNumber( @@ -980,10 +903,8 @@ class EdgeStyle { DEFAULT_MARKERSIZE ); value = - Math.max( - 2, - Math.ceil((size + EdgeStyle.orthBuffer) / EdgeStyle.orthBuffer) - ) * EdgeStyle.orthBuffer; + Math.max(2, Math.ceil((size + EdgeStyle.orthBuffer) / EdgeStyle.orthBuffer)) * + EdgeStyle.orthBuffer; } else { value = 2 * EdgeStyle.orthBuffer; } @@ -1070,21 +991,12 @@ class EdgeStyle { * edge. * */ - static OrthConnector( - state, - sourceScaled, - targetScaled, - controlHints, - result - ) { + static OrthConnector(state, sourceScaled, targetScaled, controlHints, result) { const { graph } = state.view; const sourceEdge = source == null ? false : source.cell.isEdge(); const targetEdge = target == null ? false : target.cell.isEdge(); - const pts = EdgeStyle.scalePointArray( - state.absolutePoints, - state.view.scale - ); + const pts = EdgeStyle.scalePointArray(state.absolutePoints, state.view.scale); let source = EdgeStyle.scaleCellState(sourceScaled, state.view.scale); let target = EdgeStyle.scaleCellState(targetScaled, state.view.scale); @@ -1126,19 +1038,11 @@ class EdgeStyle { if ( tooShort || - (EdgeStyle.orthPointsFallback && - controlHints != null && - controlHints.length > 0) || + (EdgeStyle.orthPointsFallback && controlHints != null && controlHints.length > 0) || sourceEdge || targetEdge ) { - EdgeStyle.SegmentConnector( - state, - sourceScaled, - targetScaled, - controlHints, - result - ); + EdgeStyle.SegmentConnector(state, sourceScaled, targetScaled, controlHints, result); return; } @@ -1150,13 +1054,8 @@ class EdgeStyle { let rotation = 0; if (source != null) { - portConstraint[0] = getPortConstraints( - source, - state, - true, - DIRECTION_MASK_ALL - ); - rotation = getValue(source.style, 'rotation', 0); + portConstraint[0] = getPortConstraints(source, state, true, DIRECTION_MASK_ALL); + rotation = source.style.rotation ?? 0; // console.log('source rotation', rotation); @@ -1173,13 +1072,8 @@ class EdgeStyle { } if (target != null) { - portConstraint[1] = getPortConstraints( - target, - state, - false, - DIRECTION_MASK_ALL - ); - rotation = getValue(target.style, 'rotation', 0); + portConstraint[1] = getPortConstraints(target, state, false, DIRECTION_MASK_ALL); + rotation = target.style.rotation ?? 0; // console.log('target rotation', rotation); @@ -1292,19 +1186,10 @@ class EdgeStyle { const sourceBottomDist = geo[1][1] - (geo[0][1] + geo[0][3]); const sourceRightDist = geo[1][0] - (geo[0][0] + geo[0][2]); - EdgeStyle.vertexSeperations[1] = Math.max( - sourceLeftDist - totalBuffer, - 0 - ); + EdgeStyle.vertexSeperations[1] = Math.max(sourceLeftDist - totalBuffer, 0); EdgeStyle.vertexSeperations[2] = Math.max(sourceTopDist - totalBuffer, 0); - EdgeStyle.vertexSeperations[4] = Math.max( - sourceBottomDist - totalBuffer, - 0 - ); - EdgeStyle.vertexSeperations[3] = Math.max( - sourceRightDist - totalBuffer, - 0 - ); + EdgeStyle.vertexSeperations[4] = Math.max(sourceBottomDist - totalBuffer, 0); + EdgeStyle.vertexSeperations[3] = Math.max(sourceRightDist - totalBuffer, 0); //= ============================================================= // Start of source and target direction determination @@ -1317,13 +1202,9 @@ class EdgeStyle { const vertPref = []; horPref[0] = - sourceLeftDist >= sourceRightDist - ? DIRECTION_MASK_WEST - : DIRECTION_MASK_EAST; + sourceLeftDist >= sourceRightDist ? DIRECTION_MASK_WEST : DIRECTION_MASK_EAST; vertPref[0] = - sourceTopDist >= sourceBottomDist - ? DIRECTION_MASK_NORTH - : DIRECTION_MASK_SOUTH; + sourceTopDist >= sourceBottomDist ? DIRECTION_MASK_NORTH : DIRECTION_MASK_SOUTH; horPref[1] = reversePortConstraints(horPref[0]); vertPref[1] = reversePortConstraints(vertPref[0]); @@ -1359,10 +1240,7 @@ class EdgeStyle { if (preferredVertDist > 0 && preferredHorizDist > 0) { // Possibility of two segment edge connection - if ( - (horPref[0] & portConstraint[0]) > 0 && - (vertPref[1] & portConstraint[1]) > 0 - ) { + if ((horPref[0] & portConstraint[0]) > 0 && (vertPref[1] & portConstraint[1]) > 0) { prefOrdering[0][0] = horPref[0]; prefOrdering[0][1] = vertPref[0]; prefOrdering[1][0] = vertPref[1]; @@ -1455,8 +1333,7 @@ class EdgeStyle { targetIndex += 4; } - const routePattern = - EdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1]; + const routePattern = EdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1]; // console.log('routePattern', routePattern); @@ -1495,8 +1372,7 @@ class EdgeStyle { // Rotate the index of this direction by the quad // to get the real direction - let directionIndex = - nextDirection === DIRECTION_MASK_EAST ? 3 : nextDirection; + let directionIndex = nextDirection === DIRECTION_MASK_EAST ? 3 : nextDirection; directionIndex += quad; @@ -1517,10 +1393,8 @@ class EdgeStyle { // We can't base the new position on index - 1 // because sometime elbows turn out not to exist, // then we'd have to rewind. - EdgeStyle.wayPoints1[currentIndex][0] = - EdgeStyle.wayPoints1[currentIndex - 1][0]; - EdgeStyle.wayPoints1[currentIndex][1] = - EdgeStyle.wayPoints1[currentIndex - 1][1]; + EdgeStyle.wayPoints1[currentIndex][0] = EdgeStyle.wayPoints1[currentIndex - 1][0]; + EdgeStyle.wayPoints1[currentIndex][1] = EdgeStyle.wayPoints1[currentIndex - 1][1]; } const tar = (routePattern[i] & EdgeStyle.TARGET_MASK) > 0; @@ -1564,11 +1438,9 @@ class EdgeStyle { } else if (center) { // Which center we're travelling to depend on the current direction EdgeStyle.wayPoints1[currentIndex][0] += - direction[0] * - Math.abs(EdgeStyle.vertexSeperations[directionIndex] / 2); + direction[0] * Math.abs(EdgeStyle.vertexSeperations[directionIndex] / 2); EdgeStyle.wayPoints1[currentIndex][1] += - direction[1] * - Math.abs(EdgeStyle.vertexSeperations[directionIndex] / 2); + direction[1] * Math.abs(EdgeStyle.vertexSeperations[directionIndex] / 2); } if ( diff --git a/packages/core/src/view/style/Perimeter.ts b/packages/core/src/view/style/Perimeter.ts index a52828f30..3c71c0105 100644 --- a/packages/core/src/view/style/Perimeter.ts +++ b/packages/core/src/view/style/Perimeter.ts @@ -5,7 +5,7 @@ * Type definitions from the typed-mxgraph project */ -import utils, { intersection } from '../../util/Utils'; +import { intersection } from '../../util/Utils'; import Point from '../geometry/Point'; import { DIRECTION_EAST, @@ -311,8 +311,7 @@ class Perimeter { orthogonal: boolean = false ): Point | null { const direction = vertex != null ? vertex.style.direction : null; - const vertical = - direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH; + const vertical = direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH; const { x } = bounds; const { y } = bounds; @@ -395,10 +394,7 @@ class Perimeter { cy = pt.y; } - if ( - (vertical && next.x <= x + w / 2) || - (!vertical && next.y <= y + h / 2) - ) { + if ((vertical && next.x <= x + w / 2) || (!vertical && next.y <= y + h / 2)) { result = intersection( next.x, next.y, @@ -410,16 +406,7 @@ class Perimeter { corner.y ); } else { - result = intersection( - next.x, - next.y, - cx, - cy, - corner.x, - corner.y, - end.x, - end.y - ); + result = intersection(next.x, next.y, cx, cy, corner.x, corner.y, end.x, end.y); } } @@ -460,8 +447,7 @@ class Perimeter { vertex != null ? Perimeter.getValue(vertex.style, 'direction', DIRECTION_EAST) : DIRECTION_EAST; - const vertical = - direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH; + const vertical = direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH; let a = new Point(); let b = new Point(); @@ -735,7 +721,11 @@ class Perimeter { return result; } - private static getValue(style: CellStateStyles, direction: string, DIRECTION_EAST: string) { + private static getValue( + style: CellStateStyles, + direction: string, + DIRECTION_EAST: string + ) { return ''; } } diff --git a/packages/core/src/view/swimlane/GraphSwimlane.ts b/packages/core/src/view/swimlane/GraphSwimlaneMixin.ts similarity index 77% rename from packages/core/src/view/swimlane/GraphSwimlane.ts rename to packages/core/src/view/swimlane/GraphSwimlaneMixin.ts index 75a167392..05edc9964 100644 --- a/packages/core/src/view/swimlane/GraphSwimlane.ts +++ b/packages/core/src/view/swimlane/GraphSwimlaneMixin.ts @@ -1,6 +1,6 @@ import Cell from '../cell/datatypes/Cell'; import Rectangle from '../geometry/Rectangle'; -import utils, { autoImplement, convertPoint, getValue, mod } from '../../util/Utils'; +import { convertPoint, getValue, mixInto, mod } from '../../util/Utils'; import { DEFAULT_STARTSIZE, DIRECTION_EAST, @@ -10,44 +10,94 @@ import { SHAPE_SWIMLANE, } from '../../util/Constants'; import CellArray from '../cell/datatypes/CellArray'; -import InternalMouseEvent from '../event/InternalMouseEvent'; import { getClientX, getClientY } from '../../util/EventUtils'; +import { Graph } from '../Graph'; -import type Graph from '../Graph'; -import GraphCells from '../cell/GraphCells'; -import { CellStateStyles } from '../../types'; -import GraphDragDrop from '../drag_drop/GraphDragDrop'; -import GraphPanning from '../panning/GraphPanning'; +import { CellStateStyles, DirectionValue } from '../../types'; + +declare module '../Graph' { + interface Graph { + swimlaneSelectionEnabled: boolean; + swimlaneNesting: boolean; + swimlaneIndicatorColorAttribute: string; + + getSwimlane: (cell: Cell | null) => Cell | null; + getSwimlaneAt: (x: number, y: number, parent?: Cell | null) => Cell | null; + hitsSwimlaneContent: (swimlane: Cell, x: number, y: number) => boolean; + getStartSize: (swimlane: Cell, ignoreState?: boolean) => Rectangle; + getSwimlaneDirection: (style: CellStateStyles) => DirectionValue; + getActualStartSize: (swimlane: Cell, ignoreState: boolean) => Rectangle; + isSwimlane: (cell: Cell, ignoreState?: boolean) => boolean; + isValidDropTarget: (cell: Cell, cells: CellArray, evt: MouseEvent) => boolean; + getDropTarget: ( + cells: CellArray, + evt: MouseEvent, + cell: Cell | null, + clone?: boolean + ) => Cell | null; + isSwimlaneNesting: () => boolean; + setSwimlaneNesting: (value: boolean) => void; + isSwimlaneSelectionEnabled: () => boolean; + setSwimlaneSelectionEnabled: (value: boolean) => void; + } +} type PartialGraph = Pick< Graph, - 'getDefaultParent' | 'getCurrentRoot' | 'getModel' | 'getView' | 'getContainer' + | 'getDefaultParent' + | 'getCurrentRoot' + | 'getModel' + | 'getView' + | 'getContainer' + | 'getCurrentCellStyle' + | 'intersects' + | 'isSplitEnabled' + | 'isSplitTarget' + | 'getPanDx' + | 'getPanDy' >; -type PartialCells = Pick; -type PartialDragDrop = Pick; -type PartialPanning = Pick; -type PartialClass = PartialGraph & PartialCells & PartialDragDrop & PartialPanning; +type PartialSwimlane = Pick< + Graph, + | 'swimlaneSelectionEnabled' + | 'swimlaneNesting' + | 'swimlaneIndicatorColorAttribute' + | 'getSwimlane' + | 'getSwimlaneAt' + | 'hitsSwimlaneContent' + | 'getStartSize' + | 'getSwimlaneDirection' + | 'getActualStartSize' + | 'isSwimlane' + | 'isValidDropTarget' + | 'getDropTarget' + | 'isSwimlaneNesting' + | 'setSwimlaneNesting' + | 'isSwimlaneSelectionEnabled' + | 'setSwimlaneSelectionEnabled' +>; +type PartialType = PartialGraph & PartialSwimlane; -class GraphSwimlane extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphSwimlaneMixin: PartialType = { /** * Specifies if swimlanes should be selectable via the content if the * mouse is released. * @default true */ - swimlaneSelectionEnabled = true; + swimlaneSelectionEnabled: true, /** * Specifies if nesting of swimlanes is allowed. * @default true */ - swimlaneNesting = true; + swimlaneNesting: true, /** * The attribute used to find the color for the indicator if the indicator * color is set to 'swimlane'. * @default {@link 'fillColor'} */ - swimlaneIndicatorColorAttribute = 'fillColor'; + swimlaneIndicatorColorAttribute: 'fillColor', /** * Returns the nearest ancestor of the given cell which is a swimlane, or @@ -55,12 +105,12 @@ class GraphSwimlane extends autoImplement() { * * @param cell {@link mxCell} for which the ancestor swimlane should be returned. */ - getSwimlane(cell: Cell | null = null) { + getSwimlane(cell = null) { while (cell && !this.isSwimlane(cell)) { cell = cell.getParent(); } return cell; - } + }, /** * Returns the bottom-most swimlane that intersects the given point (x, y) @@ -71,7 +121,7 @@ class GraphSwimlane extends autoImplement() { * @param parent {@link mxCell} that should be used as the root of the recursion. * Default is {@link defaultParent}. */ - getSwimlaneAt(x: number, y: number, parent?: Cell | null): Cell | null { + getSwimlaneAt(x, y, parent) { if (!parent) { parent = this.getCurrentRoot(); @@ -103,7 +153,7 @@ class GraphSwimlane extends autoImplement() { } } return null; - } + }, /** * Returns true if the given coordinate pair is inside the content @@ -113,7 +163,7 @@ class GraphSwimlane extends autoImplement() { * @param x X-coordinate of the mouse event. * @param y Y-coordinate of the mouse event. */ - hitsSwimlaneContent(swimlane: Cell, x: number, y: number) { + hitsSwimlaneContent(swimlane, x, y) { const state = this.getView().getState(swimlane); const size = this.getStartSize(swimlane); @@ -130,7 +180,7 @@ class GraphSwimlane extends autoImplement() { } } return false; - } + }, /***************************************************************************** * Group: Graph appearance @@ -145,7 +195,7 @@ class GraphSwimlane extends autoImplement() { * @param swimlane {@link mxCell} whose start size should be returned. * @param ignoreState Optional boolean that specifies if cell state should be ignored. */ - getStartSize(swimlane: Cell, ignoreState = false) { + getStartSize(swimlane, ignoreState = false) { const result = new Rectangle(); const style = this.getCurrentCellStyle(swimlane, ignoreState); const size = parseInt(getValue(style, 'startSize', DEFAULT_STARTSIZE)); @@ -156,12 +206,12 @@ class GraphSwimlane extends autoImplement() { result.width = size; } return result; - } + }, /** * Returns the direction for the given swimlane style. */ - getSwimlaneDirection(style: CellStateStyles) { + getSwimlaneDirection(style) { const dir = style.direction ?? DIRECTION_EAST; const flipH = style.flipH; const flipV = style.flipV; @@ -186,8 +236,10 @@ class GraphSwimlane extends autoImplement() { n += 2; } - return [DIRECTION_NORTH, DIRECTION_EAST, DIRECTION_SOUTH, DIRECTION_WEST][mod(n, 4)]; - } + return [DIRECTION_NORTH, DIRECTION_EAST, DIRECTION_SOUTH, DIRECTION_WEST][ + mod(n, 4) + ] as DirectionValue; + }, /** * Returns the actual start size of the given swimlane taking into account @@ -198,7 +250,7 @@ class GraphSwimlane extends autoImplement() { * @param swimlane {@link mxCell} whose start size should be returned. * @param ignoreState Optional boolean that specifies if cell state should be ignored. */ - getActualStartSize(swimlane: Cell, ignoreState = false) { + getActualStartSize(swimlane, ignoreState = false) { const result = new Rectangle(); if (this.isSwimlane(swimlane, ignoreState)) { @@ -217,7 +269,7 @@ class GraphSwimlane extends autoImplement() { } } return result; - } + }, /** * Returns true if the given cell is a swimlane in the graph. A swimlane is @@ -227,12 +279,12 @@ class GraphSwimlane extends autoImplement() { * @param cell {@link mxCell} to be checked. * @param ignoreState Optional boolean that specifies if the cell state should be ignored. */ - isSwimlane(cell: Cell, ignoreState = false) { + isSwimlane(cell, ignoreState = false) { if (cell && cell.getParent() !== this.getModel().getRoot() && !cell.isEdge()) { return this.getCurrentCellStyle(cell, ignoreState).shape === SHAPE_SWIMLANE; } return false; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -248,14 +300,14 @@ class GraphSwimlane extends autoImplement() { * @param cells {@link mxCell} that should be dropped into the target. * @param evt Mouseevent that triggered the invocation. */ - isValidDropTarget(cell: Cell, cells: CellArray, evt: MouseEvent) { + isValidDropTarget(cell, cells, evt) { return ( cell && ((this.isSplitEnabled() && this.isSplitTarget(cell, cells, evt)) || (!cell.isEdge() && (this.isSwimlane(cell) || (cell.getChildCount() > 0 && !cell.isCollapsed())))) ); - } + }, /** * Returns the given cell if it is a drop target for the given cells or the @@ -271,12 +323,7 @@ class GraphSwimlane extends autoImplement() { * @param cell {@link mxCell} that is under the mousepointer. * @param clone Optional boolean to indicate of cells will be cloned. */ - getDropTarget( - cells: CellArray, - evt: MouseEvent, - cell: Cell | null = null, - clone = false - ) { + getDropTarget(cells, evt, cell = null, clone = false) { if (!this.isSwimlaneNesting()) { for (let i = 0; i < cells.length; i += 1) { if (this.isSwimlane(cells[i])) { @@ -323,14 +370,14 @@ class GraphSwimlane extends autoImplement() { } return !this.getModel().isLayer(cell) && !parent ? cell : null; - } + }, /** * Returns {@link swimlaneNesting} as a boolean. */ isSwimlaneNesting() { return this.swimlaneNesting; - } + }, /** * Specifies if swimlanes can be nested by drag and drop. This is only @@ -338,16 +385,16 @@ class GraphSwimlane extends autoImplement() { * * @param value Boolean indicating if swimlanes can be nested. */ - setSwimlaneNesting(value: boolean) { + setSwimlaneNesting(value) { this.swimlaneNesting = value; - } + }, /** * Returns {@link swimlaneSelectionEnabled} as a boolean. */ isSwimlaneSelectionEnabled() { return this.swimlaneSelectionEnabled; - } + }, /** * Specifies if swimlanes should be selected if the mouse is released @@ -356,9 +403,9 @@ class GraphSwimlane extends autoImplement() { * @param value Boolean indicating if swimlanes content areas * should be selected when the mouse is released over them. */ - setSwimlaneSelectionEnabled(value: boolean) { + setSwimlaneSelectionEnabled(value) { this.swimlaneSelectionEnabled = value; - } -} + }, +}; -export default GraphSwimlane; +mixInto(Graph)(GraphSwimlaneMixin); diff --git a/packages/core/src/view/terminal/GraphTerminal.ts b/packages/core/src/view/terminal/GraphTerminalMixin.ts similarity index 79% rename from packages/core/src/view/terminal/GraphTerminal.ts rename to packages/core/src/view/terminal/GraphTerminalMixin.ts index 3086c4431..7edb17b37 100644 --- a/packages/core/src/view/terminal/GraphTerminal.ts +++ b/packages/core/src/view/terminal/GraphTerminalMixin.ts @@ -1,14 +1,27 @@ import CellArray from '../cell/datatypes/CellArray'; import Cell from '../cell/datatypes/Cell'; import Dictionary from '../../util/Dictionary'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type Graph from '../Graph'; +declare module '../Graph' { + interface Graph { + isTerminalPointMovable: (cell: Cell, source: boolean) => boolean; + getOpposites: ( + edges: CellArray, + terminal: Cell | null, + sources?: boolean, + targets?: boolean + ) => CellArray; + } +} type PartialGraph = Pick; -type PartialClass = PartialGraph; +type PartialTerminal = Pick; +type PartialType = PartialGraph & PartialTerminal; -class GraphTerminal extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphTerminalMixin: PartialType = { /***************************************************************************** * Group: Graph behaviour *****************************************************************************/ @@ -23,9 +36,9 @@ class GraphTerminal extends autoImplement() { * @param cell {@link mxCell} whose terminal point should be moved. * @param source Boolean indicating if the source or target terminal should be moved. */ - isTerminalPointMovable(cell: Cell, source: boolean) { + isTerminalPointMovable(cell, source) { return true; - } + }, /***************************************************************************** * Group: Cell retrieval @@ -44,12 +57,7 @@ class GraphTerminal extends autoImplement() { * @param targets Optional boolean that specifies if targer terminals should be * included in the result. Default is `true`. */ - getOpposites( - edges: CellArray, - terminal: Cell | null = null, - sources = true, - targets = true - ): CellArray { + getOpposites(edges, terminal = null, sources = true, targets = true) { const terminals = new CellArray(); // Fast lookup to avoid duplicates in terminals array @@ -84,7 +92,7 @@ class GraphTerminal extends autoImplement() { } } return terminals; - } -} + }, +}; -export default GraphTerminal; +mixInto(Graph)(GraphTerminalMixin); diff --git a/packages/core/src/view/tooltip/GraphTooltip.ts b/packages/core/src/view/tooltip/GraphTooltipMixin.ts similarity index 80% rename from packages/core/src/view/tooltip/GraphTooltip.ts rename to packages/core/src/view/tooltip/GraphTooltipMixin.ts index 4e85697ed..0adb8d465 100644 --- a/packages/core/src/view/tooltip/GraphTooltip.ts +++ b/packages/core/src/view/tooltip/GraphTooltipMixin.ts @@ -3,18 +3,33 @@ import { htmlEntities } from '../../util/StringUtils'; import Resources from '../../util/Resources'; import Shape from '../geometry/shape/Shape'; import Cell from '../cell/datatypes/Cell'; -import { autoImplement } from '../../util/Utils'; - -import type Graph from '../Graph'; -import type GraphFolding from '../folding/GraphFolding'; +import { Graph } from '../Graph'; import SelectionCellsHandler from '../selection/SelectionCellsHandler'; import TooltipHandler from './TooltipHandler'; +import { mixInto } from '../../util/Utils'; -type PartialGraph = Pick; -type PartialFolding = Pick; -type PartialClass = PartialGraph & PartialFolding; +declare module '../Graph' { + interface Graph { + getTooltip: ( + state: CellState, + node: HTMLElement | SVGElement, + x: number, + y: number + ) => HTMLElement | string | null; + getTooltipForCell: (cell: Cell) => HTMLElement | string; + setTooltips: (enabled: boolean) => void; + } +} -class GraphTooltip extends autoImplement() { +type PartialGraph = Pick< + Graph, + 'convertValueToString' | 'getPlugin' | 'getCollapseExpandResource' +>; +type PartialTooltip = Pick; +type PartialType = PartialGraph & PartialTooltip; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphTooltipMixin: PartialType = { /** * Returns the string or DOM node that represents the tooltip for the given * state, node and coordinate pair. This implementation checks if the given @@ -30,7 +45,7 @@ class GraphTooltip extends autoImplement() { * @param x X-coordinate of the mouse. * @param y Y-coordinate of the mouse. */ - getTooltip(state: CellState, node: HTMLElement | SVGElement, x: number, y: number) { + getTooltip(state, node, x, y) { let tip: HTMLElement | string | null = null; // Checks if the mouse is over the folding icon @@ -70,7 +85,7 @@ class GraphTooltip extends autoImplement() { } return tip; - } + }, /** * Returns the string or DOM node to be used as the tooltip for the given @@ -90,7 +105,7 @@ class GraphTooltip extends autoImplement() { * * @param cell {@link mxCell} whose tooltip should be returned. */ - getTooltipForCell(cell: Cell) { + getTooltipForCell(cell) { let tip = null; if (cell && 'getTooltip' in cell) { @@ -101,7 +116,7 @@ class GraphTooltip extends autoImplement() { } return tip; - } + }, /***************************************************************************** * Group: Graph behaviour @@ -113,11 +128,11 @@ class GraphTooltip extends autoImplement() { * * @param enabled Boolean indicating if tooltips should be enabled. */ - setTooltips(enabled: boolean) { + setTooltips(enabled) { const tooltipHandler = this.getPlugin('TooltipHandler') as TooltipHandler; tooltipHandler.setEnabled(enabled); - } -} + }, +}; -export default GraphTooltip; +mixInto(Graph)(GraphTooltipMixin); diff --git a/packages/core/src/view/tooltip/TooltipHandler.ts b/packages/core/src/view/tooltip/TooltipHandler.ts index 771635a91..92e945461 100644 --- a/packages/core/src/view/tooltip/TooltipHandler.ts +++ b/packages/core/src/view/tooltip/TooltipHandler.ts @@ -9,7 +9,7 @@ import { fit, getScrollOrigin } from '../../util/Utils'; import { TOOLTIP_VERTICAL_OFFSET } from '../../util/Constants'; import { getSource, isMouseEvent } from '../../util/EventUtils'; import { isNode } from '../../util/DomUtils'; -import { MaxGraph } from '../Graph'; +import { Graph } from '../Graph'; import CellState from '../cell/datatypes/CellState'; import InternalMouseEvent from '../event/InternalMouseEvent'; import PopupMenuHandler from '../popups_menus/PopupMenuHandler'; @@ -44,7 +44,7 @@ import EventSource from '../event/EventSource'; class TooltipHandler implements GraphPlugin { static pluginId = 'TooltipHandler'; - constructor(graph: MaxGraph) { + constructor(graph: Graph) { this.graph = graph; this.delay = 500; this.graph.addMouseListener(this); @@ -90,7 +90,7 @@ class TooltipHandler implements GraphPlugin { * * Reference to the enclosing . */ - graph: MaxGraph; + graph: Graph; /** * Variable: delay diff --git a/packages/core/src/view/validation/GraphValidation.ts b/packages/core/src/view/validation/GraphValidationMixin.ts similarity index 85% rename from packages/core/src/view/validation/GraphValidation.ts rename to packages/core/src/view/validation/GraphValidationMixin.ts index eddd2d9bb..ab4ef73dd 100644 --- a/packages/core/src/view/validation/GraphValidation.ts +++ b/packages/core/src/view/validation/GraphValidationMixin.ts @@ -3,12 +3,26 @@ import Resources from '../../util/Resources'; import { isNode } from '../../util/DomUtils'; import CellState from '../cell/datatypes/CellState'; import Multiplicity from './Multiplicity'; -import { autoImplement } from '../../util/Utils'; +import { Graph } from '../Graph'; +import { mixInto } from '../../util/Utils'; -import type Graph from '../Graph'; -import type GraphEdge from '../cell/edge/GraphEdge'; -import type GraphConnections from '../connection/GraphConnections'; -import type GraphOverlays from '../layout/GraphOverlays'; +declare module '../Graph' { + interface Graph { + multiplicities: Multiplicity[]; + + validationAlert: (message: string) => void; + isEdgeValid: (edge: Cell | null, source: Cell, target: Cell) => boolean; + getEdgeValidationError: ( + edge: Cell | null, + source: Cell | null, + target: Cell | null + ) => string | null; + validateEdge: (edge: Cell, source: Cell, target: Cell) => string | null; + validateGraph: (cell: Cell | null, context: any) => string | null; + getCellValidationError: (cell: Cell) => string | null; + validateCell: (cell: Cell, context: CellState) => string | null; + } +} type PartialGraph = Pick< Graph, @@ -19,18 +33,30 @@ type PartialGraph = Pick< | 'isValidRoot' | 'getContainsValidationErrorsResource' | 'getAlreadyConnectedResource' + | 'isAllowDanglingEdges' + | 'isValidConnection' + | 'setCellWarning' >; -type PartialEdge = Pick; -type PartialConnections = Pick; -type PartialOverlays = Pick; -type PartialClass = PartialGraph & PartialEdge & PartialConnections & PartialOverlays; +type PartialValidation = Pick< + Graph, + | 'multiplicities' + | 'validationAlert' + | 'isEdgeValid' + | 'getEdgeValidationError' + | 'validateEdge' + | 'validateGraph' + | 'getCellValidationError' + | 'validateCell' +>; +type PartialType = PartialGraph & PartialValidation; -class GraphValidation extends autoImplement() { +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphValidationMixin: PartialType = { /** * An array of {@link Multiplicity} describing the allowed * connections in a graph. */ - multiplicities: Multiplicity[] = []; + multiplicities: [], /***************************************************************************** * Group: Validation @@ -40,9 +66,9 @@ class GraphValidation extends autoImplement() { * Displays the given validation error in a dialog. This implementation uses * mxUtils.alert. */ - validationAlert(message: string) { + validationAlert(message) { alert(message); - } + }, /** * Checks if the return value of {@link getEdgeValidationError} for the given @@ -52,9 +78,9 @@ class GraphValidation extends autoImplement() { * @param source {@link mxCell} that represents the source terminal. * @param target {@link mxCell} that represents the target terminal. */ - isEdgeValid(edge: Cell | null, source: Cell, target: Cell) { + isEdgeValid(edge, source, target) { return !this.getEdgeValidationError(edge, source, target); - } + }, /** * Returns the validation error message to be displayed when inserting or @@ -93,11 +119,7 @@ class GraphValidation extends autoImplement() { * @param source {@link mxCell} that represents the source terminal. * @param target {@link mxCell} that represents the target terminal. */ - getEdgeValidationError( - edge: Cell | null = null, - source: Cell | null = null, - target: Cell | null = null - ) { + getEdgeValidationError(edge = null, source = null, target = null) { if (edge && !this.isAllowDanglingEdges() && (!source || !target)) { return ''; } @@ -164,7 +186,7 @@ class GraphValidation extends autoImplement() { } return this.isAllowDanglingEdges() ? null : ''; - } + }, /** * Hook method for subclassers to return an error message for the given @@ -174,10 +196,9 @@ class GraphValidation extends autoImplement() { * @param source {@link mxCell} that represents the source terminal. * @param target {@link mxCell} that represents the target terminal. */ - // validateEdge(edge: mxCell, source: mxCell, target: mxCell): string | null; - validateEdge(edge: Cell, source: Cell, target: Cell): void | null { + validateEdge(edge, source, target) { return null; - } + }, /** * Validates the graph by validating each descendant of the given cell or @@ -193,7 +214,7 @@ class GraphValidation extends autoImplement() { * the graph root. * @param context Object that represents the global validation state. */ - validateGraph(cell: Cell | null, context: any): string | null { + validateGraph(cell, context) { cell = cell ?? this.getModel().getRoot(); if (!cell) { @@ -261,7 +282,7 @@ class GraphValidation extends autoImplement() { this.getView().validate(); } return warning.length > 0 || !isValid ? warning : null; - } + }, /** * Checks all {@link multiplicities} that cannot be enforced while the graph is @@ -270,7 +291,7 @@ class GraphValidation extends autoImplement() { * * @param cell {@link mxCell} for which the multiplicities should be checked. */ - getCellValidationError(cell: Cell) { + getCellValidationError(cell) { const outCount = cell.getDirectedEdgeCount(true); const inCount = cell.getDirectedEdgeCount(false); const value = cell.getValue(); @@ -295,7 +316,7 @@ class GraphValidation extends autoImplement() { } return error.length > 0 ? error : null; - } + }, /** * Hook method for subclassers to return an error message for the given @@ -305,9 +326,9 @@ class GraphValidation extends autoImplement() { * @param cell {@link mxCell} that represents the cell to validate. * @param context Object that represents the global validation state. */ - validateCell(cell: Cell, context: CellState): string | null { + validateCell(cell, context) { return null; - } -} + }, +}; -export default GraphValidation; +mixInto(Graph)(GraphValidationMixin); diff --git a/packages/core/src/view/validation/Multiplicity.ts b/packages/core/src/view/validation/Multiplicity.ts index 2021d9237..f4f18e8e4 100644 --- a/packages/core/src/view/validation/Multiplicity.ts +++ b/packages/core/src/view/validation/Multiplicity.ts @@ -7,8 +7,8 @@ import Resources from '../../util/Resources'; import { isNode } from '../../util/DomUtils'; -import Cell from "../cell/datatypes/Cell"; -import graph from "../Graph"; +import Cell from '../cell/datatypes/Cell'; +import { Graph } from '../Graph'; /** * @class Multiplicity @@ -41,7 +41,7 @@ class Multiplicity { validNeighbors: string[], countError: string, typeError: string, - validNeighborsAllowed: boolean=true + validNeighborsAllowed: boolean = true ) { this.source = source; this.type = type; @@ -131,13 +131,14 @@ class Multiplicity { * @param sourceOut Number of outgoing edges from the source terminal. * @param targetIn Number of incoming edges for the target terminal. */ - check(graph: graph, - edge: Cell, - source: Cell, - target: Cell, - sourceOut: number, - targetIn: number): string | null { - + check( + graph: Graph, + edge: Cell, + source: Cell, + target: Cell, + sourceOut: number, + targetIn: number + ): string | null { let error = ''; if ( @@ -172,11 +173,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: Graph, edge: Cell, source: Cell, target: Cell): boolean { const sourceValue = source.getValue(); const targetValue = target.getValue(); let isValid = !this.validNeighborsAllowed; @@ -200,9 +197,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: Graph, edge: Cell, terminal: Cell): boolean { const value = terminal.getValue(); return this.checkType(graph, value, this.type, this.attr, this.value); @@ -211,14 +206,19 @@ class Multiplicity { /** * Checks the type of the given value. */ - checkType(graph: graph, - value: string | Element | Cell, - type: string, - attr?: string, - attrValue?: any): boolean { - + checkType( + graph: Graph, + value: string | Element | Cell, + type: string, + attr?: string, + attrValue?: any + ): boolean { if (value != null) { - if (typeof value !== 'string' && 'nodeType' in value && !Number.isNaN(value.nodeType)) { + if ( + typeof value !== 'string' && + 'nodeType' in value && + !Number.isNaN(value.nodeType) + ) { // Checks if value is a DOM node return isNode(value, type, attr, attrValue); } diff --git a/packages/core/src/view/view/GraphView.ts b/packages/core/src/view/view/GraphView.ts index b44a41786..5a5c157f9 100644 --- a/packages/core/src/view/view/GraphView.ts +++ b/packages/core/src/view/view/GraphView.ts @@ -49,7 +49,7 @@ import { getClientX, getClientY, getSource, isConsumed } from '../../util/EventU import { clone } from '../../util/CloneUtils'; import CellArray from '../cell/datatypes/CellArray'; -import type { MaxGraph } from '../Graph'; +import type { Graph } from '../Graph'; import StyleRegistry from '../style/StyleRegistry'; import TooltipHandler from '../tooltip/TooltipHandler'; import { MouseEventListener } from '../../types'; @@ -98,7 +98,7 @@ import { MouseEventListener } from '../../types'; * respectively. */ class GraphView extends EventSource { - constructor(graph: MaxGraph) { + constructor(graph: Graph) { super(); this.graph = graph; @@ -159,7 +159,7 @@ class GraphView extends EventSource { /** * Reference to the enclosing {@link graph}. */ - graph: MaxGraph; + graph: Graph; /** * {@link Cell} that acts as the root of the displayed cell hierarchy. diff --git a/packages/core/src/view/zoom/GraphZoom.ts b/packages/core/src/view/zoom/GraphZoomMixin.ts similarity index 65% rename from packages/core/src/view/zoom/GraphZoom.ts rename to packages/core/src/view/zoom/GraphZoomMixin.ts index ed30121c4..88b21c987 100644 --- a/packages/core/src/view/zoom/GraphZoom.ts +++ b/packages/core/src/view/zoom/GraphZoomMixin.ts @@ -1,25 +1,59 @@ -import Rectangle from "../geometry/Rectangle"; -import {hasScrollbars} from "../../util/Utils"; +import Rectangle from '../geometry/Rectangle'; +import { hasScrollbars, mixInto } from '../../util/Utils'; +import { Graph } from '../Graph'; -class GraphZoom { +declare module '../Graph' { + interface Graph { + zoomFactor: number; + keepSelectionVisibleOnZoom: boolean; + centerZoom: boolean; + zoomIn: () => void; + zoomOut: () => void; + zoomActual: () => void; + zoomTo: (scale: number, center: boolean) => void; + zoom: (factor: number, center?: boolean) => void; + zoomToRect: (rect: Rectangle) => void; + } +} + +type PartialGraph = Pick< + Graph, + 'getView' | 'getSelectionCell' | 'getContainer' | 'scrollRectToVisible' +>; +type PartialZoom = Pick< + Graph, + | 'zoomFactor' + | 'keepSelectionVisibleOnZoom' + | 'centerZoom' + | 'zoomIn' + | 'zoomOut' + | 'zoomActual' + | 'zoomTo' + | 'zoom' + | 'zoomToRect' +>; +type PartialType = PartialGraph & PartialZoom; + +// @ts-expect-error The properties of PartialGraph are defined elsewhere. +const GraphZoomMixin: PartialType = { /** * Specifies the factor used for {@link zoomIn} and {@link zoomOut}. * @default 1.2 (120%) */ - zoomFactor: number = 1.2; + zoomFactor: 1.2, /** * Specifies if the viewport should automatically contain the selection cells after a zoom operation. * @default false */ - keepSelectionVisibleOnZoom: boolean = false; + keepSelectionVisibleOnZoom: false, /** * Specifies if the zoom operations should go into the center of the actual * diagram rather than going from top, left. * @default true */ - centerZoom: boolean = true; + centerZoom: true, /***************************************************************************** * Group: Graph display @@ -28,49 +62,51 @@ class GraphZoom { /** * Zooms into the graph by {@link zoomFactor}. */ - zoomIn(): void { + zoomIn() { this.zoom(this.zoomFactor); - } + }, /** * Zooms out of the graph by {@link zoomFactor}. */ - zoomOut(): void { + zoomOut() { this.zoom(1 / this.zoomFactor); - } + }, /** * Resets the zoom and panning in the view. */ - zoomActual(): void { - if (this.view.scale === 1) { - this.view.setTranslate(0, 0); + zoomActual() { + if (this.getView().scale === 1) { + this.getView().setTranslate(0, 0); } else { - this.view.translate.x = 0; - this.view.translate.y = 0; + this.getView().translate.x = 0; + this.getView().translate.y = 0; - this.view.setScale(1); + this.getView().setScale(1); } - } + }, /** * Zooms the graph to the given scale with an optional boolean center * argument, which is passd to {@link zoom}. */ - zoomTo(scale: number, center: boolean = false): void { - this.zoom(scale / this.view.scale, center); - } + zoomTo(scale, center = false) { + this.zoom(scale / this.getView().scale, center); + }, /** * Zooms the graph using the given factor. Center is an optional boolean * argument that keeps the graph scrolled to the center. If the center argument * is omitted, then {@link centerZoom} will be used as its value. */ - zoom(factor: number, center: boolean = this.centerZoom): void { - const scale = Math.round(this.view.scale * factor * 100) / 100; - const state = this.view.getState(this.getSelectionCell()); - const container = this.container; - factor = scale / this.view.scale; + zoom(factor, center) { + center = center ?? this.centerZoom; + + const scale = Math.round(this.getView().scale * factor * 100) / 100; + const state = this.getView().getState(this.getSelectionCell()); + const container = this.getContainer(); + factor = scale / this.getView().scale; if (this.keepSelectionVisibleOnZoom && state != null) { const rect = new Rectangle( @@ -81,16 +117,16 @@ class GraphZoom { ); // Refreshes the display only once if a scroll is carried out - this.view.scale = scale; + this.getView().scale = scale; if (!this.scrollRectToVisible(rect)) { - this.view.revalidate(); + this.getView().revalidate(); // Forces an event to be fired but does not revalidate again - this.view.setScale(scale); + this.getView().setScale(scale); } } else { - const _hasScrollbars = hasScrollbars(this.container); + const _hasScrollbars = hasScrollbars(this.getContainer()); if (center && !_hasScrollbars) { let dx = container.offsetWidth; @@ -101,24 +137,24 @@ class GraphZoom { dx *= -f; dy *= -f; } else { - const f = (1 / factor - 1) / (this.view.scale * 2); + const f = (1 / factor - 1) / (this.getView().scale * 2); dx *= f; dy *= f; } - this.view.scaleAndTranslate( + this.getView().scaleAndTranslate( scale, - this.view.translate.x + dx, - this.view.translate.y + dy + this.getView().translate.x + dx, + this.getView().translate.y + dy ); } else { // Allows for changes of translate and scrollbars during setscale - const tx = this.view.translate.x; - const ty = this.view.translate.y; + const tx = this.getView().translate.x; + const ty = this.getView().translate.y; const sl = container.scrollLeft; const st = container.scrollTop; - this.view.setScale(scale); + this.getView().setScale(scale); if (_hasScrollbars) { let dx = 0; @@ -130,15 +166,15 @@ class GraphZoom { } container.scrollLeft = - (this.view.translate.x - tx) * this.view.scale + + (this.getView().translate.x - tx) * this.getView().scale + Math.round(sl * factor + dx); container.scrollTop = - (this.view.translate.y - ty) * this.view.scale + + (this.getView().translate.y - ty) * this.getView().scale + Math.round(st * factor + dy); } } } - } + }, /** * Zooms the graph to the specified rectangle. If the rectangle does not have same aspect @@ -150,8 +186,8 @@ class GraphZoom { * @param rect The un-scaled and un-translated rectangluar region that should be just visible * after the operation */ - zoomToRect(rect: Rectangle): void { - const container = this.container; + zoomToRect(rect) { + const container = this.getContainer(); const scaleX = container.clientWidth / rect.width; const scaleY = container.clientHeight / rect.height; const aspectFactor = scaleX / scaleY; @@ -198,20 +234,20 @@ class GraphZoom { } const scale = container.clientWidth / rect.width; - const newScale = this.view.scale * scale; + const newScale = this.getView().scale * scale; - if (!hasScrollbars(this.container)) { - this.view.scaleAndTranslate( + if (!hasScrollbars(this.getContainer())) { + this.getView().scaleAndTranslate( newScale, - this.view.translate.x - rect.x / this.view.scale, - this.view.translate.y - rect.y / this.view.scale + this.getView().translate.x - rect.x / this.getView().scale, + this.getView().translate.y - rect.y / this.getView().scale ); } else { - this.view.setScale(newScale); + this.getView().setScale(newScale); container.scrollLeft = Math.round(rect.x * scale); container.scrollTop = Math.round(rect.y * scale); } - } -} + }, +}; -export default GraphZoom; +mixInto(Graph)(GraphZoomMixin); diff --git a/tsconfig.json b/packages/core/tsconfig.json similarity index 53% rename from tsconfig.json rename to packages/core/tsconfig.json index 891387f73..a5e7b7d7a 100644 --- a/tsconfig.json +++ b/packages/core/tsconfig.json @@ -3,24 +3,22 @@ "baseUrl": ".", "allowJs": true, "allowSyntheticDefaultImports": true, + "declaration": true, + "declarationDir": "./dist", + "declarationMap": false, + "emitDeclarationOnly": true, "esModuleInterop": true, "isolatedModules": true, "jsx": "preserve", - "module": "umd", + "module": "ES2020", "lib": ["dom"], "moduleResolution": "node", - "noEmit": true, + "outDir": "./dist", "strict": true, - "target": "es5", - "resolveJsonModule": true, // Required for JSON files + "target": "ES2020", "skipLibCheck": true, "forceConsistentCasingInFileNames": true }, - "exclude": [ - "node_modules", - "e2e", - "**/*.json", // Don't try and check JSON files - "**/*.spec.ts" - ], - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"] + "exclude": ["node_modules", "e2e", "**/*.json", "**/*.spec.ts"], + "include": ["**/*.ts", "**/*.tsx"] } diff --git a/packages/html/package.json b/packages/html/package.json index ae65a09c5..bb105677a 100644 --- a/packages/html/package.json +++ b/packages/html/package.json @@ -1,5 +1,5 @@ { - "name": "@mxgraph/html", + "name": "@maxgraph/html", "version": "1.0.0", "description": "", "main": "index.js", @@ -9,7 +9,7 @@ "author": "", "license": "ISC", "dependencies": { - "@mxgraph/core": "*" + "@maxgraph/core": "*" }, "devDependencies": { "@babel/core": "^7.13.15", diff --git a/packages/html/stories/Anchors.stories.js b/packages/html/stories/Anchors.stories.js index 1d8b3a800..d6f895218 100644 --- a/packages/html/stories/Anchors.stories.js +++ b/packages/html/stories/Anchors.stories.js @@ -1,4 +1,14 @@ -import mxgraph from '@mxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + ConnectionHandler, + ConnectionConstraint, + Geometry, + Polyline, + Point, + CellState, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,18 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - ConnectionHandler, - ConnectionConstraint, - Geometry, - Polyline, - Point, - CellState, - } = mxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Animation.stories.js b/packages/html/stories/Animation.stories.js index e2f6ca668..2ebd02e91 100644 --- a/packages/html/stories/Animation.stories.js +++ b/packages/html/stories/Animation.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Point } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -12,8 +12,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Point } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/AutoLayout.stories.js b/packages/html/stories/AutoLayout.stories.js index 615ee2be0..0f62823da 100644 --- a/packages/html/stories/AutoLayout.stories.js +++ b/packages/html/stories/AutoLayout.stories.js @@ -1,4 +1,18 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + InternalEvent, + CellRenderer, + EdgeHandler, + mxHierarchicalLayout, + Constants, + CellOverlay, + ImageBox, + mxClient, + mxMorphing, + EventObject, + EventUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,23 +32,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - InternalEvent, - utils, - CellRenderer, - EdgeHandler, - mxHierarchicalLayout, - Constants, - CellOverlay, - ImageBox, - mxClient, - mxMorphing, - EventObject, - EventUtils, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Boundary.stories.js b/packages/html/stories/Boundary.stories.js index ac5e6f08c..c01716079 100644 --- a/packages/html/stories/Boundary.stories.js +++ b/packages/html/stories/Boundary.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + Point, + GraphHandler, + utils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,8 +25,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, InternalEvent, Rubberband, Point, GraphHandler, utils } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Clipboard.stories.js b/packages/html/stories/Clipboard.stories.js index 0f5591d47..84bb20f50 100644 --- a/packages/html/stories/Clipboard.stories.js +++ b/packages/html/stories/Clipboard.stories.js @@ -1,4 +1,15 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + mxClipboard, + utils, + EventUtils, + mxClient, + mxCodec, + Model, + mxStringUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,19 +29,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - mxClipboard, - utils, - EventUtils, - mxClient, - mxCodec, - GraphModel, - mxStringUtils, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; @@ -48,7 +46,7 @@ const Template = ({ label, ...args }) => { // Public helper method for shared clipboard. mxClipboard.cellsToString = function (cells) { const codec = new mxCodec(); - const model = new GraphModel(); + const model = new Model(); const parent = model.getRoot().getChildAt(0); for (let i = 0; i < cells.length; i++) { @@ -183,7 +181,7 @@ const Template = ({ label, ...args }) => { const node = doc.documentElement; if (node != null) { - const model = new GraphModel(); + const model = new Model(); const codec = new mxCodec(node.ownerDocument); codec.decode(node, model); diff --git a/packages/html/stories/Collapse.stories.js b/packages/html/stories/Collapse.stories.js index 02ec2d3d6..230c21de1 100644 --- a/packages/html/stories/Collapse.stories.js +++ b/packages/html/stories/Collapse.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rectangle } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rectangle } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Constituent.stories.js b/packages/html/stories/Constituent.stories.js index c506ad8e7..88ab9867a 100644 --- a/packages/html/stories/Constituent.stories.js +++ b/packages/html/stories/Constituent.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, InternalEvent, GraphHandler, Rubberband } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,8 +18,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, InternalEvent, GraphHandler, Rubberband } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/ContextIcons.stories.js b/packages/html/stories/ContextIcons.stories.js index 0469cde0a..f64053cb0 100644 --- a/packages/html/stories/ContextIcons.stories.js +++ b/packages/html/stories/ContextIcons.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + EventUtils, + utils, + VertexHandler, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +21,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, InternalEvent, Rubberband, EventUtils, utils, VertexHandler } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Control.stories.js b/packages/html/stories/Control.stories.js index 68522d00b..93bb998d7 100644 --- a/packages/html/stories/Control.stories.js +++ b/packages/html/stories/Control.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + mxDomHelpers, + ImageShape, + Rectangle, + CellRenderer, + ImageBox, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,17 +23,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - mxDomHelpers, - ImageShape, - Rectangle, - CellRenderer, - ImageBox, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/DragSource.stories.js b/packages/html/stories/DragSource.stories.js index 12005e6d0..0d11c5c6c 100644 --- a/packages/html/stories/DragSource.stories.js +++ b/packages/html/stories/DragSource.stories.js @@ -1,4 +1,17 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + mxDomUtils, + Rubberband, + DragSource, + utils, + GestureUtils, + EdgeHandler, + GraphHandler, + Guide, + EventUtils, + Cell, + Geometry, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,21 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - mxDomUtils, - Rubberband, - DragSource, - utils, - GestureUtils, - EdgeHandler, - GraphHandler, - Guide, - EventUtils, - Cell, - Geometry, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Drop.stories.js b/packages/html/stories/Drop.stories.js index c62602450..05c22ff03 100644 --- a/packages/html/stories/Drop.stories.js +++ b/packages/html/stories/Drop.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + utils, + EventUtils, + InternalEvent, + mxClient, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; import { getXml, parseXml } from '@maxgraph/core/util/XmlUtils'; @@ -19,8 +26,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, utils, EventUtils, InternalEvent, mxClient } = maxgraph; - const div = document.createElement('div'); div.innerHTML = 'Drag & drop your images below:
'; diff --git a/packages/html/stories/DynamicLoading.stories.js b/packages/html/stories/DynamicLoading.stories.js index 0f3ca8a43..13abe403e 100644 --- a/packages/html/stories/DynamicLoading.stories.js +++ b/packages/html/stories/DynamicLoading.stories.js @@ -1,4 +1,14 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Text, + mxEffects, + InternalEvent, + Constants, + Perimeter, + mxCodec, + utils, + mxXmlUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,18 +20,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Text, - mxEffects, - InternalEvent, - Constants, - Perimeter, - mxCodec, - utils, - mxXmlUtils, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/DynamicStyle.stories.js b/packages/html/stories/DynamicStyle.stories.js index c4d192a83..68f0c25bc 100644 --- a/packages/html/stories/DynamicStyle.stories.js +++ b/packages/html/stories/DynamicStyle.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, utils, Constants, Rubberband } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, utils, Constants, Rubberband } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/DynamicToolbar.stories.js b/packages/html/stories/DynamicToolbar.stories.js index 82e91eb2c..9efde2b47 100644 --- a/packages/html/stories/DynamicToolbar.stories.js +++ b/packages/html/stories/DynamicToolbar.stories.js @@ -1,4 +1,17 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + ConnectionHandler, + ImageBox, + mxToolbar, + Model, + mxKeyHandler, + Cell, + Geometry, + InternalEvent, + utils, + GestureUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,21 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - ConnectionHandler, - ImageBox, - mxToolbar, - GraphModel, - mxKeyHandler, - Cell, - Geometry, - InternalEvent, - utils, - GestureUtils, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); @@ -66,7 +64,7 @@ const Template = ({ label, ...args }) => { // Creates the model and the graph inside the container // using the fastest rendering available on the browser - const model = new GraphModel(); + const model = new Model(); const graph = new Graph(container, model); // Enables new connections in the graph diff --git a/packages/html/stories/EdgeTolerance.stories.js b/packages/html/stories/EdgeTolerance.stories.js index 5960b1be4..297d8155b 100644 --- a/packages/html/stories/EdgeTolerance.stories.js +++ b/packages/html/stories/EdgeTolerance.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, utils } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, utils } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Editing.stories.js b/packages/html/stories/Editing.stories.js index 379993228..18d4ea0d2 100644 --- a/packages/html/stories/Editing.stories.js +++ b/packages/html/stories/Editing.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + mxKeyHandler, + utils, + mxDomUtils, + CloneUtils, + EventUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +17,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, mxKeyHandler, utils, mxDomUtils, CloneUtils, EventUtils } = maxgraph; - const div = document.createElement('div'); div.innerHTML = ` Double-click the upper/lower half of the cell to edit different fields diff --git a/packages/html/stories/Events.stories.js b/packages/html/stories/Events.stories.js index 1b19ada23..0d927dca3 100644 --- a/packages/html/stories/Events.stories.js +++ b/packages/html/stories/Events.stories.js @@ -1,4 +1,15 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + ConnectionHandler, + LayoutManager, + mxParallelEdgeLayout, + ImageBox, + mxKeyHandler, + Constants, + EdgeStyle, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,19 +29,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - ConnectionHandler, - LayoutManager, - mxParallelEdgeLayout, - ImageBox, - mxKeyHandler, - Constants, - EdgeStyle, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/ExtendCanvas.stories.js b/packages/html/stories/ExtendCanvas.stories.js index b305d965e..d1a28f64e 100644 --- a/packages/html/stories/ExtendCanvas.stories.js +++ b/packages/html/stories/ExtendCanvas.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + Rectangle, + Point, + utils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,8 +25,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, InternalEvent, Rubberband, Rectangle, Point, utils } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'auto'; diff --git a/packages/html/stories/FileIO.stories.js b/packages/html/stories/FileIO.stories.js index c1c901556..6d5e7385f 100644 --- a/packages/html/stories/FileIO.stories.js +++ b/packages/html/stories/FileIO.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Constants } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; import { clone } from '@maxgraph/core/util/CloneUtils'; @@ -13,8 +13,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Constants } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/FixedIcons.stories.js b/packages/html/stories/FixedIcons.stories.js index 892560d59..e4ee2cc71 100644 --- a/packages/html/stories/FixedIcons.stories.js +++ b/packages/html/stories/FixedIcons.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rubberband, Rectangle, Constants, utils, mxLabel } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, Rectangle, Constants, utils, mxLabel } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/FixedPoints.stories.js b/packages/html/stories/FixedPoints.stories.js index 2f86bb8d5..b720f34e3 100644 --- a/packages/html/stories/FixedPoints.stories.js +++ b/packages/html/stories/FixedPoints.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + ConnectionHandler, + ConnectionConstraint, + ConstraintHandler, + Point, + CellState, + EdgeHandler, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; import { intersects } from '@maxgraph/core/util/Utils'; @@ -15,17 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - ConnectionHandler, - ConnectionConstraint, - ConstraintHandler, - Point, - CellState, - EdgeHandler, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Folding.stories.js b/packages/html/stories/Folding.stories.js index 0bec34da8..aac06993d 100644 --- a/packages/html/stories/Folding.stories.js +++ b/packages/html/stories/Folding.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Constants, EdgeStyle, StackLayout, LayoutManager } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Constants, EdgeStyle, StackLayout, LayoutManager } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Grid.stories.js b/packages/html/stories/Grid.stories.js index 5f57d02da..7c79e774a 100644 --- a/packages/html/stories/Grid.stories.js +++ b/packages/html/stories/Grid.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + mxLog, + GraphView, + Point, + mxDomHelpers, + EventUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,17 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - mxLog, - GraphView, - Point, - mxDomHelpers, - EventUtils, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Groups.stories.js b/packages/html/stories/Groups.stories.js index 31117498d..d79e10012 100644 --- a/packages/html/stories/Groups.stories.js +++ b/packages/html/stories/Groups.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rubberband, GraphHandler, mxPopupMenuHandler } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, GraphHandler, mxPopupMenuHandler } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Guides.stories.js b/packages/html/stories/Guides.stories.js index 97630f187..bc11be398 100644 --- a/packages/html/stories/Guides.stories.js +++ b/packages/html/stories/Guides.stories.js @@ -1,4 +1,12 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + GraphHandler, + InternalEvent, + Constants, + EdgeHandler, + EdgeStyle, + Rubberband, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,16 +22,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - GraphHandler, - InternalEvent, - Constants, - EdgeHandler, - EdgeStyle, - Rubberband, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Handles.stories.js b/packages/html/stories/Handles.stories.js index 1a2fa430d..bd66765dd 100644 --- a/packages/html/stories/Handles.stories.js +++ b/packages/html/stories/Handles.stories.js @@ -1,4 +1,16 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + CylinderShape, + mxDomHelpers, + CellRenderer, + Point, + Rectangle, + VertexHandler, + InternalEvent, + Rubberband, + utils, + VertexHandle, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,20 +30,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - CylinderShape, - mxDomHelpers, - CellRenderer, - Point, - Rectangle, - VertexHandler, - InternalEvent, - Rubberband, - utils, - VertexHandle, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/HelloPort.stories.js b/packages/html/stories/HelloPort.stories.js index 3514f95e9..92522a334 100644 --- a/packages/html/stories/HelloPort.stories.js +++ b/packages/html/stories/HelloPort.stories.js @@ -1,4 +1,12 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + EdgeStyle, + Point, + Constants, + mxDomHelpers, + mxClient, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; import { popup } from '@maxgraph/core/util/gui/mxWindow'; @@ -16,16 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - EdgeStyle, - Point, - Constants, - mxDomHelpers, - mxClient, - } = maxgraph; - mxClient.setImageBasePath('/images'); const div = document.createElement('div'); diff --git a/packages/html/stories/HelloWorld.stories.js b/packages/html/stories/HelloWorld.stories.js index a9c98d0e9..05ad8f655 100644 --- a/packages/html/stories/HelloWorld.stories.js +++ b/packages/html/stories/HelloWorld.stories.js @@ -1,6 +1,4 @@ -import Graph from '@maxgraph/core/view/Graph'; -import InternalEvent from '@maxgraph/core/view/event/InternalEvent'; - +import { Graph, InternalEvent, RubberBand } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; export default { @@ -28,7 +26,7 @@ const Template = ({ label, ...args }) => { container.style.cursor = 'default'; if (!args.contextMenu) InternalEvent.disableContextMenu(container); - console.log(Graph, Graph.prototype); + const graph = new Graph(container); // if (args.rubberBand) new Rubberband(graph); diff --git a/packages/html/stories/HierarchicalLayout.stories.js b/packages/html/stories/HierarchicalLayout.stories.js index 980986386..0e45518f1 100644 --- a/packages/html/stories/HierarchicalLayout.stories.js +++ b/packages/html/stories/HierarchicalLayout.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + mxDomUtils, + mxFastOrganicLayout, + mxHierarchicalLayout, + Perimeter, + InternalEvent, + Rubberband, + Constants, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,17 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - mxDomUtils, - mxFastOrganicLayout, - mxHierarchicalLayout, - Perimeter, - InternalEvent, - Rubberband, - Constants, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/HoverIcons.stories.js b/packages/html/stories/HoverIcons.stories.js index b41cfafd2..c7626af97 100644 --- a/packages/html/stories/HoverIcons.stories.js +++ b/packages/html/stories/HoverIcons.stories.js @@ -1,4 +1,12 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + InternalEvent, + Rubberband, + ImageBox, + Rectangle, + utils, + ConnectionHandler, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,16 +22,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - InternalEvent, - Rubberband, - ImageBox, - Rectangle, - utils, - ConnectionHandler, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/HoverStyle.stories.js b/packages/html/stories/HoverStyle.stories.js index b186bc47c..3cfafa93c 100644 --- a/packages/html/stories/HoverStyle.stories.js +++ b/packages/html/stories/HoverStyle.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Constants, Rubberband, CloneUtils } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Constants, Rubberband, CloneUtils } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Images.stories.js b/packages/html/stories/Images.stories.js index 14c1bf1b4..fb18ef78a 100644 --- a/packages/html/stories/Images.stories.js +++ b/packages/html/stories/Images.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + CloneUtils, + ImageBox, + Rectangle, + Constants, + Perimeter, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +17,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, CloneUtils, ImageBox, Rectangle, Constants, Perimeter } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Indicators.stories.js b/packages/html/stories/Indicators.stories.js index c92ccd8e9..8156b145f 100644 --- a/packages/html/stories/Indicators.stories.js +++ b/packages/html/stories/Indicators.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, EdgeStyle, Constants, mxKeyHandler } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, EdgeStyle, Constants, mxKeyHandler } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/JsonData.stories.js b/packages/html/stories/JsonData.stories.js index 7ffcae502..29fc0b072 100644 --- a/packages/html/stories/JsonData.stories.js +++ b/packages/html/stories/JsonData.stories.js @@ -1,5 +1,15 @@ -import maxgraph from '@maxgraph/core'; -import { popup } from '@maxgraph/core/util/gui/mxWindow'; +import { + Graph, + mxObjectCodec, + mxDomHelpers, + mxCodecRegistry, + InternalEvent, + mxClient, + mxCodec, + mxDomUtils, + utils, + popup, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -11,18 +21,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - mxObjectCodec, - mxDomHelpers, - mxCodecRegistry, - InternalEvent, - mxClient, - mxCodec, - mxDomUtils, - utils, - } = maxgraph; - mxClient.setImageBasePath('/images'); const div = document.createElement('div'); diff --git a/packages/html/stories/LabelPosition.stories.js b/packages/html/stories/LabelPosition.stories.js index 553fcb971..f80d593e4 100644 --- a/packages/html/stories/LabelPosition.stories.js +++ b/packages/html/stories/LabelPosition.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Labels.stories.js b/packages/html/stories/Labels.stories.js index 9b4ec3f9e..a87006b1c 100644 --- a/packages/html/stories/Labels.stories.js +++ b/packages/html/stories/Labels.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rubberband, mxKeyHandler, Constants, Rectangle } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, mxKeyHandler, Constants, Rectangle } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Layers.stories.js b/packages/html/stories/Layers.stories.js index 86277bf04..c080ebb6e 100644 --- a/packages/html/stories/Layers.stories.js +++ b/packages/html/stories/Layers.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, mxDomHelpers, Cell, Model, Point } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, mxDomHelpers, Cell, GraphModel, Point } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); @@ -29,7 +27,7 @@ const Template = ({ label, ...args }) => { const root = new Cell(); const layer0 = root.insert(new Cell()); const layer1 = root.insert(new Cell()); - const model = new GraphModel(root); + const model = new Model(root); const graph = new Graph(container, model); diff --git a/packages/html/stories/LoD.stories.js b/packages/html/stories/LoD.stories.js index b84415b9c..43384d5b9 100644 --- a/packages/html/stories/LoD.stories.js +++ b/packages/html/stories/LoD.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, mxDomHelpers } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, mxDomHelpers } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Markers.stories.js b/packages/html/stories/Markers.stories.js index 4068889a7..6373d0670 100644 --- a/packages/html/stories/Markers.stories.js +++ b/packages/html/stories/Markers.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + EdgeHandler, + GraphHandler, + CellRenderer, + Marker, + CylinderShape, + Arrow, + Point, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,17 +19,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - EdgeHandler, - GraphHandler, - CellRenderer, - Marker, - CylinderShape, - Arrow, - Point, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Merge.stories.js b/packages/html/stories/Merge.stories.js index 68f2db6a0..7ee112976 100644 --- a/packages/html/stories/Merge.stories.js +++ b/packages/html/stories/Merge.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Perimeter, Constants, Rubberband } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Perimeter, Constants, Rubberband } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Monitor.stories.js b/packages/html/stories/Monitor.stories.js index b3b58b27c..8a08d7d8c 100644 --- a/packages/html/stories/Monitor.stories.js +++ b/packages/html/stories/Monitor.stories.js @@ -1,4 +1,14 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + EdgeStyle, + mxDomHelpers, + mxXmlUtils, + Perimeter, + utils, + Constants, + CloneUtils, + mxCodec, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,18 +20,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - EdgeStyle, - mxDomHelpers, - mxXmlUtils, - Perimeter, - utils, - Constants, - CloneUtils, - mxCodec, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Morph.stories.js b/packages/html/stories/Morph.stories.js index 64e7e3302..e3c9758ee 100644 --- a/packages/html/stories/Morph.stories.js +++ b/packages/html/stories/Morph.stories.js @@ -1,4 +1,10 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + mxDomHelpers, + mxMorphing, + InternalEvent, + Rubberband, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,8 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, mxDomHelpers, mxMorphing, InternalEvent, Rubberband } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/OffPage.stories.js b/packages/html/stories/OffPage.stories.js index 67e59a4d0..73928b7eb 100644 --- a/packages/html/stories/OffPage.stories.js +++ b/packages/html/stories/OffPage.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, CellTracker, Constants, InternalEvent } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, CellTracker, Constants, InternalEvent } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/OrgChart.stories.js b/packages/html/stories/OrgChart.stories.js index f848ebf72..72a50aa73 100644 --- a/packages/html/stories/OrgChart.stories.js +++ b/packages/html/stories/OrgChart.stories.js @@ -1,4 +1,19 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Constants, + InternalEvent, + mxClient, + Point, + Outline, + EdgeStyle, + mxKeyHandler, + CompactTreeLayout, + LayoutManager, + CellOverlay, + ImageBox, + utils, + mxToolbar, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,23 +29,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Constants, - InternalEvent, - mxClient, - Point, - Outline, - EdgeStyle, - mxKeyHandler, - CompactTreeLayout, - LayoutManager, - CellOverlay, - ImageBox, - utils, - mxToolbar, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Orthogonal.stories.js b/packages/html/stories/Orthogonal.stories.js index 09e034aaa..fa22d27b3 100644 --- a/packages/html/stories/Orthogonal.stories.js +++ b/packages/html/stories/Orthogonal.stories.js @@ -1,4 +1,15 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + ConnectionHandler, + GraphHandler, + Guide, + Point, + CellState, + EdgeHandler, + GraphView, + InternalEvent, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,19 +21,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - ConnectionHandler, - GraphHandler, - Guide, - Point, - CellState, - EdgeHandler, - GraphView, - InternalEvent, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Overlays.stories.js b/packages/html/stories/Overlays.stories.js index 5ac85507f..a7579024d 100644 --- a/packages/html/stories/Overlays.stories.js +++ b/packages/html/stories/Overlays.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + CellOverlay, + InternalEvent, + CellTracker, + utils, + ImageBox, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +17,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, CellOverlay, InternalEvent, CellTracker, utils, ImageBox } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/PageBreaks.stories.js b/packages/html/stories/PageBreaks.stories.js index 23842d4e4..92c083264 100644 --- a/packages/html/stories/PageBreaks.stories.js +++ b/packages/html/stories/PageBreaks.stories.js @@ -1,4 +1,10 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rectangle, + Rubberband, + mxDomHelpers, + InternalEvent, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,8 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rectangle, Rubberband, mxDomHelpers, InternalEvent } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Perimeter.stories.js b/packages/html/stories/Perimeter.stories.js index 2cc801d8d..28b9c53c4 100644 --- a/packages/html/stories/Perimeter.stories.js +++ b/packages/html/stories/Perimeter.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rubberband, GraphView, utils } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, GraphView, utils } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Permissions.stories.js b/packages/html/stories/Permissions.stories.js index 8cc71329f..ec63e63d0 100644 --- a/packages/html/stories/Permissions.stories.js +++ b/packages/html/stories/Permissions.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + ConnectionHandler, + ImageBox, + Rubberband, + mxKeyHandler, + mxDomHelpers, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,15 +21,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - ConnectionHandler, - ImageBox, - Rubberband, - mxKeyHandler, - mxDomHelpers, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/PortRefs.stories.js b/packages/html/stories/PortRefs.stories.js index fed064cea..6b4cb03e0 100644 --- a/packages/html/stories/PortRefs.stories.js +++ b/packages/html/stories/PortRefs.stories.js @@ -1,4 +1,16 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + Point, + EdgeHandler, + ConstraintHandler, + ImageBox, + Shape, + TriangleShape, + Constants, + ConnectionConstraint, + mxClient, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,20 +22,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - Point, - EdgeHandler, - ConstraintHandler, - ImageBox, - Shape, - TriangleShape, - Constants, - ConnectionConstraint, - mxClient, - } = maxgraph; - mxClient.setImageBasePath('/images'); const container = document.createElement('div'); diff --git a/packages/html/stories/RadialTreeLayout.stories.js b/packages/html/stories/RadialTreeLayout.stories.js index 6f6d9939e..b66e00447 100644 --- a/packages/html/stories/RadialTreeLayout.stories.js +++ b/packages/html/stories/RadialTreeLayout.stories.js @@ -1,4 +1,10 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + Constants, + mxRadialTreeLayout, + Perimeter, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +20,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, Constants, mxRadialTreeLayout, Perimeter } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/SecondLabel.stories.js b/packages/html/stories/SecondLabel.stories.js index 2b2844a11..769589150 100644 --- a/packages/html/stories/SecondLabel.stories.js +++ b/packages/html/stories/SecondLabel.stories.js @@ -1,4 +1,12 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + RectangleShape, + mxDomHelpers, + Text, + Point, + Rectangle, + Constants, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,16 +18,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - RectangleShape, - mxDomHelpers, - Text, - Point, - Rectangle, - Constants, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Shape.stories.js b/packages/html/stories/Shape.stories.js index ddee680b2..0dc09f3bc 100644 --- a/packages/html/stories/Shape.stories.js +++ b/packages/html/stories/Shape.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, CylinderShape, Constants, CellRenderer } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, CylinderShape, Constants, CellRenderer } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Stencils.stories.js b/packages/html/stories/Stencils.stories.js index 95f9f051e..d20d03aa0 100644 --- a/packages/html/stories/Stencils.stories.js +++ b/packages/html/stories/Stencils.stories.js @@ -1,5 +1,20 @@ -import maxgraph from '@maxgraph/core'; -import { load } from '@mxgraph/core/src/util/network/mxXmlRequest'; +import { + Graph, + ConnectionHandler, + mxDomHelpers, + EdgeHandler, + InternalEvent, + Point, + CellHighlight, + Constants, + VertexHandler, + Rubberband, + Shape, + StencilShape, + StencilRegistry, + CellRenderer, + utils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -19,24 +34,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - ConnectionHandler, - mxDomHelpers, - EdgeHandler, - InternalEvent, - Point, - CellHighlight, - Constants, - VertexHandler, - Rubberband, - Shape, - StencilShape, - StencilRegistry, - CellRenderer, - utils, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Stylesheet.stories.js b/packages/html/stories/Stylesheet.stories.js index 4c0041a3b..4ec4dec03 100644 --- a/packages/html/stories/Stylesheet.stories.js +++ b/packages/html/stories/Stylesheet.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Perimeter, Constants, EdgeStyle } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Perimeter, Constants, EdgeStyle } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/SwimLanes.stories.js b/packages/html/stories/SwimLanes.stories.js index 4e59bf8fe..bc729b82f 100644 --- a/packages/html/stories/SwimLanes.stories.js +++ b/packages/html/stories/SwimLanes.stories.js @@ -1,4 +1,17 @@ -import maxgraph from '@maxgraph/core'; +import { + mxEditor, + ConnectionHandler, + ImageBox, + Perimeter, + Point, + Constants, + CloneUtils, + EdgeStyle, + InternalEvent, + SwimlaneManager, + StackLayout, + LayoutManager, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,21 +23,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - mxEditor, - ConnectionHandler, - ImageBox, - Perimeter, - Point, - Constants, - CloneUtils, - EdgeStyle, - InternalEvent, - SwimlaneManager, - StackLayout, - LayoutManager, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Thread.stories.js b/packages/html/stories/Thread.stories.js index 88a073382..c63994f54 100644 --- a/packages/html/stories/Thread.stories.js +++ b/packages/html/stories/Thread.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, mxClient } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, mxClient } = maxgraph; - mxClient.setImageBasePath('/images'); const container = document.createElement('div'); diff --git a/packages/html/stories/Toolbar.stories.js b/packages/html/stories/Toolbar.stories.js index 62068e71e..27e6884d0 100644 --- a/packages/html/stories/Toolbar.stories.js +++ b/packages/html/stories/Toolbar.stories.js @@ -1,4 +1,17 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + ConnectionHandler, + ImageBox, + mxToolbar, + Model, + mxKeyHandler, + Cell, + Geometry, + DragSource, + mxDomHelpers, + GestureUtils, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,21 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - ConnectionHandler, - ImageBox, - mxToolbar, - GraphModel, - mxKeyHandler, - Cell, - Geometry, - DragSource, - mxDomHelpers, - GestureUtils, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); @@ -66,7 +64,7 @@ const Template = ({ label, ...args }) => { // Creates the model and the graph inside the container // using the fastest rendering available on the browser - const model = new GraphModel(); + const model = new Model(); const graph = new Graph(container, model); graph.dropEnabled = true; diff --git a/packages/html/stories/Tree.stories.js b/packages/html/stories/Tree.stories.js index 4f5ee65f2..8c5cd96a9 100644 --- a/packages/html/stories/Tree.stories.js +++ b/packages/html/stories/Tree.stories.js @@ -1,4 +1,17 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + CylinderShape, + CellRenderer, + GraphView, + ImageBox, + mxClient, + EdgeStyle, + mxKeyHandler, + CompactTreeLayout, + LayoutManager, + Rectangle, + Point, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,22 +23,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Constants, - CylinderShape, - CellRenderer, - GraphView, - ImageBox, - mxClient, - EdgeStyle, - mxKeyHandler, - CompactTreeLayout, - LayoutManager, - Rectangle, - Point, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/UserObject.stories.js b/packages/html/stories/UserObject.stories.js index 52ffab0c0..07cd60f86 100644 --- a/packages/html/stories/UserObject.stories.js +++ b/packages/html/stories/UserObject.stories.js @@ -1,5 +1,18 @@ -import maxgraph from '@maxgraph/core'; -import { popup } from '@maxgraph/core/util/gui/mxWindow'; +import { + Graph, + Rectangle, + mxDomHelpers, + mxKeyHandler, + InternalEvent, + mxXmlUtils, + mxCodec, + Constants, + utils, + EdgeStyle, + mxDomUtils, + mxForm, + CellAttributeChange, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -11,22 +24,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rectangle, - mxDomHelpers, - mxKeyHandler, - InternalEvent, - mxXmlUtils, - mxCodec, - Constants, - utils, - EdgeStyle, - mxDomUtils, - mxForm, - CellAttributeChange, - } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Validation.stories.js b/packages/html/stories/Validation.stories.js index 6b9bd0cf0..4accc7f5b 100644 --- a/packages/html/stories/Validation.stories.js +++ b/packages/html/stories/Validation.stories.js @@ -1,4 +1,11 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + Rubberband, + mxXmlUtils, + Multiplicity, + mxKeyHandler, + InternalEvent, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,15 +21,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - Rubberband, - mxXmlUtils, - Multiplicity, - mxKeyHandler, - InternalEvent, - } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/html/stories/Visibility.stories.js b/packages/html/stories/Visibility.stories.js index 78b9d15d0..ec3af6247 100644 --- a/packages/html/stories/Visibility.stories.js +++ b/packages/html/stories/Visibility.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph, Rubberband, mxDomHelpers } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -14,8 +14,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph, Rubberband, mxDomHelpers } = maxgraph; - const div = document.createElement('div'); const container = document.createElement('div'); diff --git a/packages/html/stories/Window.stories.js b/packages/html/stories/Window.stories.js index 271099db0..fee0e53c3 100644 --- a/packages/html/stories/Window.stories.js +++ b/packages/html/stories/Window.stories.js @@ -1,4 +1,13 @@ -import maxgraph from '@maxgraph/core'; +import { + Graph, + mxWindow, + mxKeyHandler, + Rubberband, + InternalEvent, + mxLog, + mxDomUtils, + mxClient, +} from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -18,17 +27,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { - Graph, - mxWindow, - mxKeyHandler, - Rubberband, - InternalEvent, - mxLog, - mxDomUtils, - mxClient, - } = maxgraph; - mxClient.setImageBasePath('/images'); const container = document.createElement('div'); diff --git a/packages/html/stories/Wrapping.stories.js b/packages/html/stories/Wrapping.stories.js index ba38d4771..36a95e731 100644 --- a/packages/html/stories/Wrapping.stories.js +++ b/packages/html/stories/Wrapping.stories.js @@ -1,4 +1,4 @@ -import maxgraph from '@maxgraph/core'; +import { Graph } from '@maxgraph/core'; import { globalTypes } from '../.storybook/preview'; @@ -10,8 +10,6 @@ export default { }; const Template = ({ label, ...args }) => { - const { Graph } = maxgraph; - const container = document.createElement('div'); container.style.position = 'relative'; container.style.overflow = 'hidden'; diff --git a/packages/react/package.json b/packages/react/package.json index 69459aa34..00fad3fc8 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,8 +1,8 @@ { - "name": "@mxgraph/react", + "name": "@maxgraph/react", "version": "1.0.0", "description": "", - "main": "dist/mxgraph-react.js", + "main": "dist/maxgraph-react.js", "scripts": { "dev": "start-storybook -p 8902" }, diff --git a/webpack.config.js b/webpack.config.js index 968774ce1..9d683835b 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,5 +1,5 @@ module.exports = { - devtool: 'eval-source-map', + devtool: 'inline-source-map', module: { rules: [ {