Import it from @grafloria/engine.
Also has every member of DiagramEntity, listed on its own entry.
tsclass DiagramModel extends DiagramEntity
Properties
| Name | Type | Default | Description |
|---|---|---|---|
name | string | 'Untitled Diagram' | |
nodes | Map<string, NodeModel> | ||
links | Map<string, LinkModel> | ||
groups | Map<string, GroupModel> | ||
strokes | Map<string, StrokeModel> | Freehand ink strokes. See StrokeModel for why these are not nodes. | |
linkIntegrityOwner | 'model' | 'external' | 'model' | Who owns the invariant "a link whose node is gone is not a link"? |
viewport |
Methods
get comments(): CommentRegisterTree— The comment register tree. Read-only in spirit: write through writeCommentRegister. The landing pad forapplyOp's whole-tree write (remote ops, replay, load).set comments(next: CommentRegisterTree)— The comment register tree. Read-only in spirit: write through writeCommentRegister. The landing pad forapplyOp's whole-tree write (remote ops, replay, load).writeCommentRegister(path: string, value: unknown): boolean— Write ONE comment register —t1.status,t1.messages.m3— and nothing else.readCommentRegister(path: string): unknown— Read one register. Returns undefined for any missing segment — never throws.constructor( name?: string, options?: { lodConfig?: LODConfig; id?: string; uuid?: string } )refreshLinkBounds(link: LinkModel): void— Re-index a link after its geometry changed WITHOUT achange:pointsevent.isReadonly(): boolean— Is this document locked against edits?setReadonly(value: boolean): void— Lock / unlock the document. Normally driven byDiagramEngine.setMode()— VIEW and PRESENTATION lock, DESIGNER unlocks — soDiagramModefinally means something. Can also be set directly for a host that has no mode concept.blocksDocumentWrite(): boolean— True when a document mutation must be refused right now.inSystemWrite(): boolean— True while a SYSTEM write is in flight. Read by the PER-NODE geometry lock (NodeState.locked) so it exempts measured writes exactly as the document lock does — see readonly-lock.ts.runSystemWrite<T>(fn: () => T): T— Run a SYSTEM write — a derived/measured value (auto-size, portal placement) the engine needs in order to render the document as it already is. Permitted even while locked. NOT reachable from user input; see readonly-lock.ts.addNode(node: NodeModel): voidremoveNode(nodeId: string): NodeModel | undefined— Remove node from diagram — AND every link attached to it.replaceNode(next: NodeModel): void— Swap the live model undernext.idfornext, KEEPING the links attached to it. (An id not on the canvas is simply added.)getLinksForNode(nodeId: string): LinkModel[]— Every link with an endpoint onnodeId(either end, including a self-loop).restoreNode(data: any): NodeModel | undefined— Restore node from serialized datagetNode(nodeId: string): NodeModel | undefined— Get node by IDgetNodes(): NodeModel[]— Get all nodesgetNodeByPortId(portId: string): NodeModel | undefined— Get node that owns a specific port Used for connection group validation and other port-based queries. O(1) via the portIndex (was an O(nodes×ports) linear scan).getPortById(portId: string): PortModel | undefined— Get the port model for a port id, O(1) via the portIndex. Companion to getNodeByPortId for callers that need the port itself.getDetachedAnchor(nodeId: string): DetachedParentAnchor | undefined— The last-known anchor of a REMOVED node, or undefined if the id is live, was never here, or the anchor was wholesale-cleared. The tolerant readers in NodeModel (getWorldPosition / getGlobalPosition / getGlobalTransformMatrix / setGlobalPosition) resolve an unresolvable parent through this so orphaned relative children freeze in place instead of jumping to their raw offsets. See {@link detachedAnchors} and the design argument on {@link removeNode}.clearNodes(): void— Clear all nodesaddLink(link: LinkModel): void— Add link to diagramremoveLink(linkId: string): LinkModel | undefined— Remove link from diagramrestoreLink(data: any): LinkModel | undefined— Restore link from serialized datagetLink(linkId: string): LinkModel | undefined— Get link by IDgetLinks(): LinkModel[]— Get all linksgetLinksForPort(portId: string): LinkModel[]— Get all links connected to a specific portclearLinks(): void— Clear all linkscreateSmartLink( sourceNode: NodeModel, targetNode: NodeModel, pathType: 'direct' | 'orthogonal' | 'smooth' | 'bezier' = 'smooth' ): LinkModel | undefined— Create a smart link with automatic port selectionconnectNodes( sourceNode: NodeModel, targetNode: NodeModel, pathType: 'direct' | 'orthogonal' | 'smooth' | 'bezier' = 'smooth' ): boolean— High-level API to connect two nodesgetNodeConnections(node: NodeModel): { incoming: LinkModel[]; outgoing: LinkModel[]; all: LinkModel[]; }— Get all connections for a nodedisconnectNodes(sourceNode: NodeModel, targetNode: NodeModel): number— Disconnect two nodesaddGroup(group: GroupModel): void— Add groupremoveGroup(groupId: string): GroupModel | undefined— Remove grouprestoreGroup(data: any): GroupModel | undefined— Restore group from serialized datagetGroup(groupId: string): GroupModel | undefined— Get group by IDgetGroups(): GroupModel[]— Get all groupsgetGroupsInRenderOrder(): GroupModel[]— Groups in deterministic back-to-front stacking order — ascendingzIndex, ties broken by Map insertion order (a STABLE sort keeps it). This is the model-level z-order story that replaces "stacking == Map insertion order" as the only determinant; a renderer paints groups in this order (behind their members) instead of relying on iteration order.getProxyNodeForGroup(groupId: string): NodeModel | undefined— The placeholder "group-as-node" for a collapsed group, if present. Placeholder nodes are ordinary NodeModels tagged with the group id so callers can filter them out of exports / counts.isProxyNode(node: NodeModel): boolean— Is this node a collapsed-group placeholder?clearGroups(): void— Clear all groupsaddStroke(stroke: StrokeModel): voidremoveStroke(strokeId: string): StrokeModel | undefinedrestoreStroke(data: SerializedStroke): StrokeModel | undefinedgetStroke(strokeId: string): StrokeModel | undefinedgetStrokes(): StrokeModel[]clearStrokes(): voidgetVisibleStrokes(viewport: Rectangle): StrokeModel[]— Strokes whose bounds overlapviewport. The ink layer's culling query.getStrokesAlongSegment(a: Point, b: Point, tolerance = 0): StrokeModel[]— Every stroke the pointer swept across travellinga→b. THE ERASER'S QUERY.getAncestors(groupId: string): GroupModel[]— Get a group's ancestor chain (nearest parent first), walking parentGroupId upward. Robust against malformed self/looping pointers.getDescendants(groupId: string): GroupModel[]— Get every group nested (directly or transitively) insidegroupId. Breadth-first over the parentGroupId back-pointers.getDepth(groupId: string): number— Nesting depth of a group: number of ancestors (0 for a top-level group).getSelectedNodes(): NodeModel[]— Get all selected nodesselectNode(node: NodeModel): void— Select a single node (clears previous selection)addToSelection(node: NodeModel): void— Add node to selection (multi-select)removeFromSelection(node: NodeModel): void— Remove node from selectiontoggleNodeSelection(node: NodeModel): void— Toggle node selection (add if not selected, remove if selected)clearSelection(): void— Clear all selectionsselectAll(): void— Select all nodesdeleteSelected(): number— Delete all selected nodes and their connected linksgetNodeAtPosition(x: number, y: number): NodeModel | undefined— Get node at position (for click detection) Returns the topmost node at the given positionisPointCoveredAbove(x: number, y: number, nodeId: string): boolean— Is (x, y) inside any node ABOVEnodeIdin z-order?lockSelected(): number— Option 3: Lock/pin selected nodes Locked nodes will not move during layout operationsunlockSelected(): number— Option 3: Unlock selected nodesgetLockedNodes(): NodeModel[]— Option 3: Get locked nodesunlockAll(): number— Option 3: Unlock all nodessetViewport(x: number, y: number, width: number, height: number, zoom?: number): void— Set viewportgetViewport(): { x: number; y: number; width: number; height: number; zoom: number }— Get current viewportpan(dx: number, dy: number): void— Pan viewportzoom(delta: number, center?: Point): void— Zoom viewport (relative adjustment)setZoom(level: number, center?: Point): void— Set absolute zoom level Option B: Pan/Zoom controlsfitToView(padding: number = 100): void— Fit viewport to show all nodes (without changing zoom level) Option B: Pan/Zoom controlszoomToFit(targetWidth: number, targetHeight: number, padding: number = 100): void— Fit viewport to show all nodes AND adjust zoom to fit screen Option B: Pan/Zoom controlsclear(): void— Clear all nodes, links, and groupsgetVisibleNodes(viewport: Rectangle): NodeModel[]— Get nodes visible in viewport This enables viewport virtualization - only render visible nodesgetVisibleLinks(viewport: Rectangle): LinkModel[]— Get links visible in viewport This enables viewport virtualization - only render visible linksfindNearestPort( point: Point, options?: NearestPortOptions ): NearestPortHit | null— The nearest port to a world point, served BY THE SPATIAL INDEX.getVisibleBounds(viewport: Rectangle): Rectangle | null— Get bounding box of all visible entities Useful for "fit to viewport" operationsgetDirtyNodes(): NodeModel[]— Get all dirty nodes Returns nodes that need re-renderinggetDirtyLinks(): LinkModel[]— Get all dirty links Returns links that need re-renderinggetDirtyGroups(): GroupModel[]— Get all dirty groups Returns groups that need re-renderingmarkAllClean(): void— Mark all entities as clean Call this after rendering to reset dirty flagsgetDirtyCount(): number— Get total count of dirty entities Useful for monitoring render performancegetVisibleDirtyNodes(viewport: Rectangle): NodeModel[]— Get visible dirty nodes Combines viewport virtualization with dirty marking Only returns nodes that are both visible AND need re-renderinggetVisibleDirtyLinks(viewport: Rectangle): LinkModel[]— Get visible dirty links Combines viewport virtualization with dirty marking Only returns links that are both visible AND need re-renderinggetLODLevel(zoom: number): LODLevel— Get LOD level based on zoomshouldRender(feature: LODFeature, lod: LODLevel): boolean— Single feature gate that reads the active LOD tier's feature set. Renderers call this instead of hardcodinglod === 'high'checks, so custom tiers work automatically.getLODConfig(): LODConfig— Get the current Level-of-Detail policy.setLODConfig(config: LODConfig): void— Replace the Level-of-Detail policy wholesale. Apps use this to define their own tiers (names, breakpoints and feature sets).registerLODTier(tier: LODTier): void— Register (or replace, by name) a single LOD tier. Lets apps extend the default policy with an extra tier without rebuilding the whole config.getNodesWithLOD(viewport: Rectangle, zoom: number): EntityWithLOD<NodeModel>[]— Get visible nodes with LOD information Combines viewport virtualization with Level of DetailgetLinksWithLOD(viewport: Rectangle, zoom: number): EntityWithLOD<LinkModel>[]— Get visible links with LOD information Combines viewport virtualization with Level of DetailshouldRenderLabels(lod: LODLevel): boolean— Check if labels should be rendered at this LOD level Now reads the LOD tier's feature set.shouldRenderIcons(lod: LODLevel): boolean— Check if icons should be rendered at this LOD level Now reads the LOD tier's feature set.shouldRenderBorders(lod: LODLevel): boolean— Check if borders should be rendered at this LOD level Now reads the LOD tier's feature set.shouldRenderShadows(lod: LODLevel): boolean— Check if shadows should be rendered at this LOD level Now reads the LOD tier's feature set.getLayoutManager(): LayoutManager— Get the layout manager for this diagramsetLayoutAlgorithm(type: LayoutAlgorithmType, config?: LayoutConfiguration): void— Set layout algorithmgetLayoutAlgorithm(): LayoutAlgorithmType— Get current layout algorithm typeconfigureLayout(config: LayoutConfiguration): void— Configure current layout algorithmgetLayoutConfiguration(): LayoutConfiguration— Get layout configurationsetAutoLayout(enabled: boolean): void— Enable or disable automatic layout for new nodes When enabled, newly added nodes will be automatically positioned using the current layout algorithmisAutoLayoutEnabled(): boolean— Check if auto-layout is enabledasync reLayout(config?: LayoutConfiguration): Promise<void>— Re-layout all nodes using current algorithm This will recalculate positions for all nodes in the diagramoverride endBatch(): void— Override: End batch update mode Fires accumulated events when all batches completeserialize(): SerializedDiagram— Serialize to JSONreconcilePortConnections(): Array<{ linkId: string; portId: string; end: 'source' | 'target' }>— Rebuild the derived port-connection registries from the diagram's links.applyIncremental(patch: DiagramIncremental): void— Apply an incremental patch (see serialization/Incremental.ts) — the receive side of toIncremental/apply. Added entities are installed through the SAME unified restore path as document load (fully wired); modified entities are updated IN PLACE so object identity is preserved for renderers holding references; normal change events fire (an applied patch IS a mutation, unlike a document load).static fromJSON(data: SerializedDiagram, options?: DiagramLoadOptions): DiagramModel(static) — Deserialize from JSON — THE document load path.override dispose(): void— Dispose diagram and all child entities Prevents memory leaks by: - Disposing all nodes, links, and groups - Breaking circular references - Clearing spatial indices - Calling parent dispose()
Was this page helpful?