From b2bb10ea7e2e624e51df17adde2a02358994ebef Mon Sep 17 00:00:00 2001 From: Junsik Shim Date: Sat, 22 Jan 2022 12:54:58 +0900 Subject: [PATCH] Fixed the 'Anchors' example. --- .vscode/settings.json | 4 + packages/core/index.d.ts | 1 + packages/core/src/types.ts | 2 +- packages/core/src/view/GraphView.ts | 55 ++++------ .../src/view/handler/ConnectionHandler.ts | 11 +- .../src/view/handler/ConstraintHandler.ts | 52 ++++----- packages/core/src/view/mixins/CellsMixin.ts | 10 +- packages/core/src/view/style/EdgeStyle.ts | 100 ++++++++++++++---- packages/html/stories/Anchors.stories.js | 17 +-- 9 files changed, 154 insertions(+), 98 deletions(-) create mode 100644 .vscode/settings.json create mode 100644 packages/core/index.d.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..f82fc3965 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,4 @@ +{ + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true +} \ No newline at end of file diff --git a/packages/core/index.d.ts b/packages/core/index.d.ts new file mode 100644 index 000000000..c12648142 --- /dev/null +++ b/packages/core/index.d.ts @@ -0,0 +1 @@ +declare module '*.gif'; \ No newline at end of file diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 650da9e98..d869100b7 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -42,7 +42,7 @@ export type CellStateStyles = { defaultVertex?: CellStateStyles; deletable?: boolean; direction?: DirectionValue; - edge?: string; + edgeStyle?: string; editable?: boolean; elbow?: string; endArrow?: ArrowType; diff --git a/packages/core/src/view/GraphView.ts b/packages/core/src/view/GraphView.ts index e27d6a757..4d81838dd 100644 --- a/packages/core/src/view/GraphView.ts +++ b/packages/core/src/view/GraphView.ts @@ -14,17 +14,8 @@ import RectangleShape from './geometry/node/RectangleShape'; import { ALIGN } from '../util/Constants'; import Client from '../Client'; import InternalEvent from './event/InternalEvent'; -import { - convertPoint, - getCurrentStyle, - getOffset, -} from '../util/styleUtils'; -import { - getRotatedPoint, - ptSegDistSq, - relativeCcw, - toRadians, -} from '../util/mathUtils'; +import { convertPoint, getCurrentStyle, getOffset } from '../util/styleUtils'; +import { getRotatedPoint, ptSegDistSq, relativeCcw, toRadians } from '../util/mathUtils'; import MaxLog from '../gui/MaxLog'; import Translations from '../util/Translations'; import CellState from './cell/CellState'; @@ -49,7 +40,6 @@ import { MouseEventListener } from '../types'; import ObjectCodec from '../serialization/ObjectCodec'; import CodecRegistry from '../serialization/CodecRegistry'; - /** * @class GraphView * @extends {EventSource} @@ -236,9 +226,7 @@ export class GraphView extends EventSource { this.viewStateChanged(); } } - this.fireEvent( - new EventObject(InternalEvent.SCALE, { scale: value, previousScale }) - ); + this.fireEvent(new EventObject(InternalEvent.SCALE, { scale: value, previousScale })); } /** @@ -415,10 +403,10 @@ export class GraphView extends EventSource { } this.fireEvent( - new EventObject(InternalEvent.SCALE_AND_TRANSLATE, { - scale, - previousScale, - translate: this.translate, + new EventObject(InternalEvent.SCALE_AND_TRANSLATE, { + scale, + previousScale, + translate: this.translate, previousTranslate: previousTranslate, }) ); @@ -1320,15 +1308,17 @@ export class GraphView extends EventSource { let edgeStyle = this.isLoopStyleEnabled(edge, points, source, target) ? edge.style.loop ?? this.graph.defaultLoopStyle : !edge.style.noEdgeStyle ?? false - ? edge.style.edge + ? edge.style.edgeStyle : null; // Converts string values to objects if (typeof edgeStyle === 'string') { let tmp = StyleRegistry.getValue(edgeStyle); + if (!tmp && this.isAllowEval()) { tmp = eval(edgeStyle); } + edgeStyle = tmp; } @@ -2267,11 +2257,11 @@ export class GraphView extends EventSource { */ createHtml() { var container = this.graph.container; - + if (container != null) { this.canvas = this.createHtmlPane('100%', '100%'); this.canvas.style.overflow = 'hidden'; - + // Uses minimal size for inner DIVs on Canvas. This is required // for correct event processing in IE. If we have an overlapping // DIV then the events on the cells are only fired for labels. @@ -2279,20 +2269,20 @@ export class GraphView extends EventSource { this.drawPane = this.createHtmlPane('1px', '1px'); this.overlayPane = this.createHtmlPane('1px', '1px'); this.decoratorPane = this.createHtmlPane('1px', '1px'); - + this.canvas.appendChild(this.backgroundPane); this.canvas.appendChild(this.drawPane); this.canvas.appendChild(this.overlayPane); this.canvas.appendChild(this.decoratorPane); container.appendChild(this.canvas); - this.updateContainerStyle(container); + this.updateContainerStyle(container); } - }; + } /** * Function: updateHtmlCanvasSize - * + * * Updates the size of the HTML canvas. */ updateHtmlCanvasSize(width: number, height: number) { @@ -2312,16 +2302,16 @@ export class GraphView extends EventSource { this.canvas.style.height = '100%'; } } - }; + } /** * Function: createHtmlPane - * + * * Creates and returns a drawing pane in HTML (DIV). */ createHtmlPane(width: string, height: string) { var pane = document.createElement('DIV'); - + if (width != null && height != null) { pane.style.position = 'absolute'; pane.style.left = '0px'; @@ -2329,12 +2319,11 @@ export class GraphView extends EventSource { pane.style.width = width; pane.style.height = height; - } else { pane.style.position = 'relative'; } return pane; - }; + } /** * Updates the style of the container after installing the SVG DOM elements. @@ -2357,8 +2346,8 @@ export class GraphView extends EventSource { * Destroys the view and all its resources. */ destroy() { - let root: SVGElement | HTMLElement | null=null; - + let root: SVGElement | HTMLElement | null = null; + if (this.canvas && this.canvas instanceof SVGElement) { root = this.canvas.ownerSVGElement as SVGElement; } diff --git a/packages/core/src/view/handler/ConnectionHandler.ts b/packages/core/src/view/handler/ConnectionHandler.ts index 50f1674fd..19fabf0f6 100644 --- a/packages/core/src/view/handler/ConnectionHandler.ts +++ b/packages/core/src/view/handler/ConnectionHandler.ts @@ -610,7 +610,6 @@ class ConnectionHandler extends EventSource implements GraphPlugin { * Starts a new connection for the given state and coordinates. */ start(state: CellState, x: number, y: number, edgeState: CellState) { - console.log("ConnectionHandler start"); this.previous = state; this.first = new Point(x, y); this.edgeState = edgeState ?? this.createEdgeState(); @@ -1191,9 +1190,8 @@ class ConnectionHandler extends EventSource implements GraphPlugin { // Uses edge state to compute the terminal points if (this.edgeState) { this.updateEdgeState(current, constraint); - current = this.edgeState.absolutePoints[ - this.edgeState.absolutePoints.length - 1 - ]; + current = + this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 1]; pt2 = this.edgeState.absolutePoints[0]; } else { if (this.currentState) { @@ -1225,9 +1223,8 @@ class ConnectionHandler extends EventSource implements GraphPlugin { let tmp = pt2; if (this.edgeState && this.edgeState.absolutePoints.length >= 2) { - const tmp2 = this.edgeState.absolutePoints[ - this.edgeState.absolutePoints.length - 2 - ]; + const tmp2 = + this.edgeState.absolutePoints[this.edgeState.absolutePoints.length - 2]; if (tmp2) { tmp = tmp2; diff --git a/packages/core/src/view/handler/ConstraintHandler.ts b/packages/core/src/view/handler/ConstraintHandler.ts index db93efcfc..3991b07a3 100644 --- a/packages/core/src/view/handler/ConstraintHandler.ts +++ b/packages/core/src/view/handler/ConstraintHandler.ts @@ -26,6 +26,8 @@ import ConnectionConstraint from '../other/ConnectionConstraint'; import Point from '../geometry/Point'; import Cell from '../cell/Cell'; +import pointImg from '../../../images/point.gif'; + /** * Handles constraints on connection targets. This class is in charge of * showing fixed points when the mouse is over a vertex and handles constraints @@ -38,7 +40,7 @@ class ConstraintHandler { * {@link Image} to be used as the image for fixed connection points. */ // pointImage: mxImage; - pointImage = new Image(`${Client.imageBasePath}/point.gif`, 5, 5); + pointImage = new Image(pointImg, 5, 5); /** * Reference to the enclosing {@link mxGraph}. @@ -81,8 +83,8 @@ class ConstraintHandler { // Adds a graph model listener to update the current focus on changes this.resetHandler = () => { if ( - this.currentFocus != null && - this.graph.view.getState(this.currentFocus.cell) == null + this.currentFocus && + !this.graph.view.getState(this.currentFocus.cell) ) { this.reset(); } else { @@ -211,15 +213,15 @@ class ConstraintHandler { // Gets cell under actual point if different from event location if ( - cell == null && - point != null && + !cell && + point && (me.getGraphX() !== point.x || me.getGraphY() !== point.y) ) { cell = this.graph.getCellAt(point.x, point.y); } // Uses connectable parent vertex if one exists - if (cell != null && !cell.isConnectable()) { + if (cell && !cell.isConnectable()) { const parent = cell.getParent(); if (parent && parent.isVertex() && parent.isConnectable()) { @@ -246,7 +248,7 @@ class ConstraintHandler { ) { if (this.isEnabled() && !this.isEventIgnored(me)) { // Lazy installation of mouseleave handler - if (this.mouseleaveHandler == null && this.graph.container != null) { + if (!this.mouseleaveHandler && this.graph.container ) { this.mouseleaveHandler = () => { this.reset(); }; @@ -255,8 +257,8 @@ class ConstraintHandler { } const tol = this.getTolerance(me); - const x = point != null ? point.x : me.getGraphX(); - const y = point != null ? point.y : me.getGraphY(); + const x = point ? point.x : me.getGraphX(); + const y = point ? point.y : me.getGraphY(); const grid = new Rectangle(x - tol, y - tol, 2 * tol, 2 * tol); const mouse = new Rectangle( me.getGraphX() - tol, @@ -270,8 +272,8 @@ class ConstraintHandler { // Keeps focus icons visible while over vertex bounds and no other cell under mouse or shift is pressed if ( !this.isKeepFocusEvent(me) && - (this.currentFocusArea == null || - this.currentFocus == null || + (!this.currentFocusArea || + !this.currentFocus || state || !this.currentFocus.cell.isVertex() || !intersects(this.currentFocusArea, mouse)) && @@ -289,9 +291,9 @@ class ConstraintHandler { let tmp; if ( - this.focusIcons != null && - this.constraints != null && - (state == null || this.currentFocus === state) + this.focusIcons.length > 0 && + this.constraints && + (!state || this.currentFocus === state) ) { const cx = mouse.getCenterX(); const cy = mouse.getCenterY(); @@ -303,9 +305,9 @@ class ConstraintHandler { if ( (this.intersects(this.focusIcons[i], mouse, source, existingEdge) || - (point != null && + (point && this.intersects(this.focusIcons[i], grid, source, existingEdge))) && - (minDistSq == null || tmp < minDistSq) + (minDistSq === null || tmp < minDistSq) ) { this.currentConstraint = this.constraints[i]; this.currentPoint = this.focusPoints[i]; @@ -316,7 +318,7 @@ class ConstraintHandler { tmp.width -= 1; tmp.height -= 1; - if (this.focusHighlight == null) { + if (!this.focusHighlight) { const hl = this.createHighlightShape(); hl.dialect = DIALECT.SVG; hl.pointerEvents = false; @@ -325,7 +327,7 @@ class ConstraintHandler { this.focusHighlight = hl; const getState = () => { - return this.currentFocus != null ? this.currentFocus : state; + return this.currentFocus ? this.currentFocus : state; }; InternalEvent.redirectMouseEvents(hl.node, this.graph, getState); @@ -337,7 +339,7 @@ class ConstraintHandler { } } - if (this.currentConstraint == null) { + if (!this.currentConstraint) { this.destroyFocusHighlight(); } } else { @@ -354,9 +356,9 @@ class ConstraintHandler { */ redraw() { if ( - this.currentFocus != null && - this.constraints != null && - this.focusIcons != null + this.currentFocus && + this.constraints && + this.focusIcons.length > 0 ) { const state = this.graph.view.getState(this.currentFocus.cell) as CellState; this.currentFocus = state; @@ -423,12 +425,12 @@ class ConstraintHandler { icon.init(this.graph.getView().getDecoratorPane()); // Move the icon behind all other overlays - if (icon.node.previousSibling != null) { + if (icon.node.previousSibling) { icon.node.parentNode?.insertBefore(icon.node, icon.node.parentNode.firstChild); } const getState = () => { - return this.currentFocus != null ? this.currentFocus : state; + return this.currentFocus ? this.currentFocus : state; }; icon.redraw(); @@ -480,7 +482,7 @@ class ConstraintHandler { this.graph.view.removeListener(this.resetHandler); this.graph.removeListener(this.resetHandler); - if (this.mouseleaveHandler != null && this.graph.container != null) { + if (this.mouseleaveHandler && this.graph.container) { InternalEvent.removeListener( this.graph.container, 'mouseleave', diff --git a/packages/core/src/view/mixins/CellsMixin.ts b/packages/core/src/view/mixins/CellsMixin.ts index ed49acaac..28d1280ee 100644 --- a/packages/core/src/view/mixins/CellsMixin.ts +++ b/packages/core/src/view/mixins/CellsMixin.ts @@ -577,6 +577,7 @@ export const CellsMixin: PartialType = { if (!style) { style = {} as CellStateStyles; } + return style; }, @@ -2009,7 +2010,9 @@ export const CellsMixin: PartialType = { this.resetEdges(cells); } - this.fireEvent(new EventObject(InternalEvent.CELLS_MOVED, { cells, dx, dy, disconnect })); + this.fireEvent( + new EventObject(InternalEvent.CELLS_MOVED, { cells, dx, dy, disconnect }) + ); }); } }, @@ -2755,9 +2758,8 @@ export const CellsMixin: PartialType = { */ isCellResizable(cell) { const style = this.getCurrentCellStyle(cell); - const r = this.isCellsResizable() && - !this.isCellLocked(cell) && - (style.resizable ?? true); + const r = + this.isCellsResizable() && !this.isCellLocked(cell) && (style.resizable ?? true); return r; }, diff --git a/packages/core/src/view/style/EdgeStyle.ts b/packages/core/src/view/style/EdgeStyle.ts index 92d521fcd..9c46e404f 100644 --- a/packages/core/src/view/style/EdgeStyle.ts +++ b/packages/core/src/view/style/EdgeStyle.ts @@ -113,7 +113,13 @@ class EdgeStyle { * @param result Array of that represent the actual points of the * edge. */ - static EntityRelation(state: CellState, source: CellState, target: CellState, points: Point[], result: Point[]) { + static EntityRelation( + state: CellState, + source: CellState, + target: CellState, + points: Point[], + result: Point[] + ) { const { view } = state; const { graph } = view; const segment = getValue(state.style, 'segment', ENTITY_SEGMENT) * view.scale; @@ -218,7 +224,13 @@ class EdgeStyle { /** * Implements a self-reference, aka. loop. */ - static Loop(state: CellState, source: CellState, target: CellState, points: Point[], result: Point[]) { + static Loop( + state: CellState, + source: CellState, + target: CellState, + points: Point[], + result: Point[] + ) { const pts = state.absolutePoints; const p0 = pts[0]; @@ -295,7 +307,13 @@ class EdgeStyle { * unspecified. See for a description of the * parameters. */ - static ElbowConnector(state: CellState, source: CellState, target: CellState, points: Point[], result: Point[]) { + static ElbowConnector( + state: CellState, + source: CellState, + target: CellState, + points: Point[], + result: Point[] + ) { let pt = points != null && points.length > 0 ? points[0] : null; let vertical = false; @@ -312,7 +330,6 @@ class EdgeStyle { pt = state.view.transformControlPoint(state, pt); vertical = pt.y < top || pt.y > bottom; 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); @@ -338,7 +355,13 @@ class EdgeStyle { * Implements a vertical elbow edge. See for a description * of the parameters. */ - static SideToSide(state: CellState, source: CellState, target: CellState, points: Point[], result: Point[]) { + static SideToSide( + state: CellState, + source: CellState, + target: CellState, + points: Point[], + result: Point[] + ) { const { view } = state; let pt = points != null && points.length > 0 ? points[0] : null; const pts = state.absolutePoints; @@ -407,7 +430,13 @@ class EdgeStyle { * Implements a horizontal elbow edge. See for a * description of the parameters. */ - static TopToBottom(state: CellState, source: CellState, target: CellState, points: Point[], result: Point[]) { + static TopToBottom( + state: CellState, + source: CellState, + target: CellState, + points: Point[], + result: Point[] + ) { const { view } = state; let pt = points != null && points.length > 0 ? points[0] : null; const pts = state.absolutePoints; @@ -482,11 +511,23 @@ class EdgeStyle { * @param result Array of that represent the actual points of the * edge. */ - static SegmentConnector(state: CellState, sourceScaled: CellState, targetScaled: CellState, controlHints: Point[], result: Point[]) { - + static SegmentConnector( + state: CellState, + sourceScaled: CellState, + targetScaled: CellState, + controlHints: Point[], + result: Point[] + ) { // Creates array of all way- and terminalpoints // TODO: Figure out what to do when there are nulls in `pts`! - 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; @@ -952,10 +993,19 @@ class EdgeStyle { * @param result Array of that represent the actual points of the * edge. */ - static OrthConnector(state: CellState, sourceScaled: CellState, targetScaled: CellState, controlHints: Point[], result: Point[]) { - + static OrthConnector( + state: CellState, + sourceScaled: CellState, + targetScaled: CellState, + controlHints: Point[], + result: Point[] + ) { // TODO: Figure out what to do when there are nulls in `pts`! - 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); @@ -1022,9 +1072,11 @@ class EdgeStyle { // console.log('source rotation', rotation); if (rotation !== 0) { - const newRect = getBoundingBox( - new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), - rotation + const newRect = ( + getBoundingBox( + new Rectangle(sourceX, sourceY, sourceWidth, sourceHeight), + rotation + ) ); sourceX = newRect.x; sourceY = newRect.y; @@ -1040,9 +1092,11 @@ class EdgeStyle { // console.log('target rotation', rotation); if (rotation !== 0) { - const newRect = getBoundingBox( - new Rectangle(targetX, targetY, targetWidth, targetHeight), - rotation + const newRect = ( + getBoundingBox( + new Rectangle(targetX, targetY, targetWidth, targetHeight), + rotation + ) ); targetX = newRect.x; targetY = newRect.y; @@ -1464,7 +1518,12 @@ class EdgeStyle { } } - static getRoutePattern(dir: number[], quad: number, dx: number, dy: number): number[] | null { + static getRoutePattern( + dir: number[], + quad: number, + dx: number, + dy: number + ): number[] | null { let sourceIndex = dir[0] === DIRECTION_MASK.EAST ? 3 : dir[0]; let targetIndex = dir[1] === DIRECTION_MASK.EAST ? 3 : dir[1]; @@ -1478,7 +1537,8 @@ class EdgeStyle { targetIndex += 4; } - let result: number[] | null = EdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1]; + let result: number[] | null = + EdgeStyle.routePatterns[sourceIndex - 1][targetIndex - 1]; if (dx === 0 || dy === 0) { if (EdgeStyle.inlineRoutePatterns[sourceIndex - 1][targetIndex - 1] != null) { diff --git a/packages/html/stories/Anchors.stories.js b/packages/html/stories/Anchors.stories.js index 89da12a2c..acfc47e8e 100644 --- a/packages/html/stories/Anchors.stories.js +++ b/packages/html/stories/Anchors.stories.js @@ -44,16 +44,17 @@ const Template = ({ label, ...args }) => { class MyCustomGraph extends Graph { getAllConnectionConstraints(terminal, source) { - // Overridden to define per-shape connection points - if (terminal != null && terminal.shape != null) { - if (terminal.shape.stencil != null) { - if (terminal.shape.stencil.constraints != null) { + // Overridden to define per-geometry connection points + if (terminal && terminal.cell) { + if (terminal.shape.stencil) { + if (terminal.shape.stencil.constraints) { return terminal.shape.stencil.constraints; } - } else if (terminal.shape.constraints != null) { - return terminal.shape.constraints; + } else if (terminal.cell.geometry.constraints) { + return terminal.cell.geometry.constraints; } } + return null; } @@ -116,8 +117,8 @@ const Template = ({ label, ...args }) => { const e1 = graph.insertEdge({ parent, value: '', - position: v1, - size: v2, + source: v1, + target: v2, }); });