finished converting most main base modules to typescript+eslint

development
mcyph 2021-04-09 15:26:04 +10:00
parent 889156b314
commit c372e77297
62 changed files with 668 additions and 578 deletions

View File

@ -60,5 +60,4 @@ class mxCellAttributeChange {
} }
export default mxCellAttributeChange; export default mxCellAttributeChange;
import("../serialization/mxGenericChangeCodec"); import('../serialization/mxGenericChangeCodec');

View File

@ -34,5 +34,4 @@ class mxGeometryChange {
} }
export default mxGeometryChange; export default mxGeometryChange;
import("../serialization/mxGenericChangeCodec"); import('../serialization/mxGenericChangeCodec');

View File

@ -36,5 +36,4 @@ class mxTerminalChange {
} }
export default mxTerminalChange; export default mxTerminalChange;
import("../serialization/mxTerminalChangeCodec"); import('../serialization/mxTerminalChangeCodec');

View File

@ -42,6 +42,7 @@ class mxCellHighlight {
this.repaintHandler = () => { this.repaintHandler = () => {
// Updates reference to state // Updates reference to state
if (this.state != null) { if (this.state != null) {
// @ts-ignore
const tmp = this.graph.view.getState(this.state.cell); const tmp = this.graph.view.getState(this.state.cell);
if (tmp == null) { if (tmp == null) {
@ -71,17 +72,17 @@ class mxCellHighlight {
} }
// TODO: Document me!! // TODO: Document me!!
highlightColor: string | null; highlightColor: string | null=null;
strokeWidth: number | null; strokeWidth: number | null=null;
dashed: boolean | null; dashed: boolean=false;
opacity: number | null; opacity: number=100;
repaintHandler: Function | null; repaintHandler: Function | null=null;
shape: mxShape | null; shape: mxShape | null=null;
/** /**
* Variable: keepOnTop * Variable: keepOnTop
@ -149,10 +150,14 @@ class mxCellHighlight {
if ( if (
!this.keepOnTop && !this.keepOnTop &&
// @ts-ignore
this.shape.node.parentNode.firstChild !== this.shape.node this.shape.node.parentNode.firstChild !== this.shape.node
) { ) {
// @ts-ignore
this.shape.node.parentNode.insertBefore( this.shape.node.parentNode.insertBefore(
// @ts-ignore
this.shape.node, this.shape.node,
// @ts-ignore
this.shape.node.parentNode.firstChild this.shape.node.parentNode.firstChild
); );
} }
@ -164,21 +169,21 @@ class mxCellHighlight {
* Creates and returns the highlight shape for the given state. * Creates and returns the highlight shape for the given state.
*/ */
createShape(): mxShape { createShape(): mxShape {
const shape = this.graph.cellRenderer.createShape(this.state); const shape = <mxShape>(<mxGraph>this.graph).cellRenderer.createShape(<mxCellState>this.state);
shape.svgStrokeTolerance = this.graph.tolerance; shape.svgStrokeTolerance = (<mxGraph>this.graph).tolerance;
shape.points = this.state.absolutePoints; shape.points = (<mxCellState>this.state).absolutePoints;
shape.apply(this.state); shape.apply(<mxCellState>this.state);
shape.stroke = this.highlightColor; shape.stroke = this.highlightColor;
shape.opacity = this.opacity; shape.opacity = this.opacity;
shape.isDashed = this.dashed; shape.isDashed = this.dashed;
shape.isShadow = false; shape.isShadow = false;
shape.dialect = mxConstants.DIALECT_SVG; shape.dialect = mxConstants.DIALECT_SVG;
shape.init(this.graph.getView().getOverlayPane()); shape.init((<mxGraph>this.graph).getView().getOverlayPane());
mxEvent.redirectMouseEvents(shape.node, this.graph, this.state); mxEvent.redirectMouseEvents(shape.node, this.graph, this.state);
if (this.graph.dialect !== mxConstants.DIALECT_SVG) { if ((<mxGraph>this.graph).dialect !== mxConstants.DIALECT_SVG) {
shape.pointerEvents = false; shape.pointerEvents = false;
} else { } else {
shape.svgPointerEvents = 'stroke'; shape.svgPointerEvents = 'stroke';
@ -192,7 +197,7 @@ class mxCellHighlight {
* *
* Returns the stroke width. * Returns the stroke width.
*/ */
getStrokeWidth(state: mxCellState | null = null): number { getStrokeWidth(state: mxCellState | null = null): number | null {
return this.strokeWidth; return this.strokeWidth;
} }
@ -205,6 +210,7 @@ class mxCellHighlight {
if (this.state != null && this.shape != null) { if (this.state != null && this.shape != null) {
this.shape.scale = this.state.view.scale; this.shape.scale = this.state.view.scale;
// @ts-ignore
if (this.graph.model.isEdge(this.state.cell)) { if (this.graph.model.isEdge(this.state.cell)) {
this.shape.strokewidth = this.getStrokeWidth(); this.shape.strokewidth = this.getStrokeWidth();
this.shape.points = this.state.absolutePoints; this.shape.points = this.state.absolutePoints;
@ -219,7 +225,7 @@ class mxCellHighlight {
this.shape.rotation = Number( this.shape.rotation = Number(
this.state.style[mxConstants.STYLE_ROTATION] || '0' this.state.style[mxConstants.STYLE_ROTATION] || '0'
); );
this.shape.strokewidth = this.getStrokeWidth() / this.state.view.scale; this.shape.strokewidth = <number>this.getStrokeWidth() / this.state.view.scale;
this.shape.outline = true; this.shape.outline = true;
} }
@ -246,7 +252,7 @@ class mxCellHighlight {
* *
* Marks the <markedState> and fires a <mark> event. * Marks the <markedState> and fires a <mark> event.
*/ */
highlight(state: mxCellState): void { highlight(state: mxCellState | null=null): void {
if (this.state !== state) { if (this.state !== state) {
if (this.shape != null) { if (this.shape != null) {
this.shape.destroy(); this.shape.destroy();
@ -268,7 +274,7 @@ class mxCellHighlight {
isHighlightAt(x: number, y: number): boolean { isHighlightAt(x: number, y: number): boolean {
let hit = false; let hit = false;
if (this.shape != null && document.elementFromPoint != null) { if (this.shape != null && document.elementFromPoint != null) {
let elt: Node & ParentNode = document.elementFromPoint(x, y); let elt: (Node & ParentNode) | null = document.elementFromPoint(x, y);
while (elt != null) { while (elt != null) {
if (elt === this.shape.node) { if (elt === this.shape.node) {
@ -287,9 +293,10 @@ class mxCellHighlight {
* Destroys the handler and all its resources and DOM nodes. * Destroys the handler and all its resources and DOM nodes.
*/ */
destroy(): void { destroy(): void {
this.graph.getView().removeListener(this.resetHandler); const graph = <mxGraph>this.graph;
this.graph.getView().removeListener(this.repaintHandler); graph.getView().removeListener(this.resetHandler);
this.graph.getModel().removeListener(this.repaintHandler); graph.getView().removeListener(this.repaintHandler);
graph.getModel().removeListener(this.repaintHandler);
if (this.shape != null) { if (this.shape != null) {
this.shape.destroy(); this.shape.destroy();

View File

@ -16,7 +16,7 @@ class mxMarker {
* *
* Maps from markers names to functions to paint the markers. * Maps from markers names to functions to paint the markers.
*/ */
static markers: []; static markers = [];
/** /**
* Function: addMarker * Function: addMarker

View File

@ -3,9 +3,9 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxShape from './mxShape';
import mxSvgCanvas2D from "../util/canvas/mxSvgCanvas2D";
import mxRectangle from 'mxgraph/util/datatypes/mxRectangle'; import mxRectangle from 'mxgraph/util/datatypes/mxRectangle';
import mxShape from './mxShape';
import mxSvgCanvas2D from '../util/canvas/mxSvgCanvas2D';
/** /**
* Class: mxActor * Class: mxActor
@ -48,10 +48,12 @@ import mxRectangle from 'mxgraph/util/datatypes/mxRectangle';
* 1. This is stored in <strokewidth>. * 1. This is stored in <strokewidth>.
*/ */
class mxActor extends mxShape { class mxActor extends mxShape {
constructor(bounds: mxRectangle | null=null, constructor(
bounds: mxRectangle | null = null,
fill: string | null = null, fill: string | null = null,
stroke: string | null = null, stroke: string | null = null,
strokewidth: number=1) { strokewidth: number = 1
) {
super(); super();
this.bounds = bounds; this.bounds = bounds;
this.fill = fill; this.fill = fill;

View File

@ -13,6 +13,7 @@ import mxClient from '../mxClient';
import mxCellState from '../util/datatypes/mxCellState'; import mxCellState from '../util/datatypes/mxCellState';
import mxAbstractCanvas2D from '../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../util/canvas/mxAbstractCanvas2D';
import mxStencil from './node/mxStencil'; import mxStencil from './node/mxStencil';
import mxCellOverlay from "../view/cell/mxCellOverlay";
const toBool = (i: any): boolean => { const toBool = (i: any): boolean => {
if (i === 0) return false; if (i === 0) return false;
@ -99,7 +100,7 @@ class mxShape {
* *
* container - DOM node that will contain the shape. * container - DOM node that will contain the shape.
*/ */
init(container: SVGElement | null = null) { init(container: HTMLElement | SVGElement | null = null) {
if (this.node == null) { if (this.node == null) {
this.node = this.create(container); this.node = this.create(container);
@ -125,14 +126,23 @@ class mxShape {
} }
// TODO: Document me!! // TODO: Document me!!
// Assigned in mxCellRenderer
preserveImageAspect: boolean=false;
overlay: mxCellOverlay | null=null;
indicator: mxShape | null=null;
indicatorShape: typeof mxShape | null=null;
// Assigned in mxCellHighlight
opacity: number | null=100;
isDashed: boolean=false;
fill: string | null = null; fill: string | null = null;
gradient: string | null = null; gradient: string | null = null;
gradientDirection: string | null = null; gradientDirection: string | null = null;
opacity: number | null = null;
fillOpacity: number | null = null; fillOpacity: number | null = null;
strokeOpacity: number | null = null; strokeOpacity: number | null = null;
@ -159,8 +169,6 @@ class mxShape {
isShadow: boolean = false; isShadow: boolean = false;
isDashed: boolean = false;
isRounded: boolean = false; isRounded: boolean = false;
rotation: number | null = null; rotation: number | null = null;
@ -214,7 +222,7 @@ class mxShape {
* *
* Holds the array of <mxPoints> that specify the points of this shape. * Holds the array of <mxPoints> that specify the points of this shape.
*/ */
points: mxPoint[] | null = null; points: (mxPoint | null)[] | null = null;
/** /**
* Variable: node * Variable: node
@ -349,7 +357,7 @@ class mxShape {
* *
* container - DOM node that will contain the shape. * container - DOM node that will contain the shape.
*/ */
create(container: SVGElement | null): SVGGElement { create(container: SVGElement | HTMLElement | null): SVGGElement {
return document.createElementNS("http://www.w3.org/2000/svg", "g"); return document.createElementNS("http://www.w3.org/2000/svg", "g");
} }
@ -709,6 +717,7 @@ class mxShape {
for (let i = 0; i < this.points.length; i += 1) { for (let i = 0; i < this.points.length; i += 1) {
if (this.points[i] != null) { if (this.points[i] != null) {
// @ts-ignore
pts.push(new mxPoint(this.points[i].x / s, this.points[i].y / s)); pts.push(new mxPoint(this.points[i].x / s, this.points[i].y / s));
} }
} }

View File

@ -72,7 +72,7 @@ class mxText extends mxShape {
value: string, value: string,
bounds: mxRectangle, bounds: mxRectangle,
align: string=mxConstants.ALIGN_CENTER, align: string=mxConstants.ALIGN_CENTER,
valign: string=mxConstants.ALIGN_MIDDLE, valign: string | null=mxConstants.ALIGN_MIDDLE,
color: string='black', color: string='black',
family: string=mxConstants.DEFAULT_FONTFAMILY, family: string=mxConstants.DEFAULT_FONTFAMILY,
size: number=mxConstants.DEFAULT_FONTSIZE, size: number=mxConstants.DEFAULT_FONTSIZE,
@ -89,9 +89,11 @@ class mxText extends mxShape {
clipped: boolean=false, clipped: boolean=false,
overflow: string='visible', overflow: string='visible',
labelPadding: number=0, labelPadding: number=0,
textDirection textDirection: string=mxConstants.DEFAULT_TEXT_DIRECTION
) { ) {
super(); super();
valign = valign != null ? valign : mxConstants.ALIGN_MIDDLE;
this.value = value; this.value = value;
this.bounds = bounds; this.bounds = bounds;
this.color = color; this.color = color;
@ -118,7 +120,7 @@ class mxText extends mxShape {
} }
// TODO: Document me! // TODO: Document me!
value: string; value: string | HTMLElement | SVGGElement | null;
bounds: mxRectangle; bounds: mxRectangle;
align: string=mxConstants.ALIGN_CENTER; align: string=mxConstants.ALIGN_CENTER;
valign: string=mxConstants.ALIGN_MIDDLE; valign: string=mxConstants.ALIGN_MIDDLE;
@ -138,8 +140,8 @@ class mxText extends mxShape {
clipped: boolean=false; clipped: boolean=false;
overflow: string='visible'; overflow: string='visible';
labelPadding: number=0; labelPadding: number=0;
textDirection; textDirection: string=mxConstants.DEFAULT_TEXT_DIRECTION;
margin: mxRectangle | null=null; margin: mxPoint | null=null;
unrotatedBoundingBox: mxRectangle | null=null; unrotatedBoundingBox: mxRectangle | null=null;
flipH: boolean=false; flipH: boolean=false;
flipV: boolean=false; flipV: boolean=false;
@ -213,7 +215,7 @@ class mxText extends mxShape {
* *
* Contains the last rendered text value. Used for caching. * Contains the last rendered text value. Used for caching.
*/ */
lastValue: string | null = null; lastValue: string | HTMLElement | SVGGElement | null = null;
/** /**
* Variable: cacheEnabled * Variable: cacheEnabled
@ -298,10 +300,10 @@ class mxText extends mxShape {
// Handles trailing newlines to make sure they are visible in rendering output // Handles trailing newlines to make sure they are visible in rendering output
val = val =
!mxUtils.isNode(this.value) && this.replaceLinefeeds && fmt === 'html' !mxUtils.isNode(this.value) && this.replaceLinefeeds && fmt === 'html'
? val.replace(/\n/g, '<br/>') ? (<string>val).replace(/\n/g, '<br/>')
: val; : val;
let dir = this.textDirection; let dir: string | null = this.textDirection;
if (dir === mxConstants.TEXT_DIRECTION_AUTO && !realHtml) { if (dir === mxConstants.TEXT_DIRECTION_AUTO && !realHtml) {
dir = this.getAutoDirection(); dir = this.getAutoDirection();
@ -346,6 +348,7 @@ class mxText extends mxShape {
(mxUtils.isNode(this.value) || (mxUtils.isNode(this.value) ||
this.dialect === mxConstants.DIALECT_STRICTHTML) this.dialect === mxConstants.DIALECT_STRICTHTML)
) { ) {
// @ts-ignore
if (this.node.nodeName === 'DIV') { if (this.node.nodeName === 'DIV') {
this.redrawHtmlShape(); this.redrawHtmlShape();
this.updateBoundingBox(); this.updateBoundingBox();
@ -393,8 +396,8 @@ class mxText extends mxShape {
this.spacingBottom = 2; this.spacingBottom = 2;
this.spacingLeft = 2; this.spacingLeft = 2;
this.horizontal = true; this.horizontal = true;
delete this.background; this.background = null;
delete this.border; this.border = null;
this.textDirection = mxConstants.DEFAULT_TEXT_DIRECTION; this.textDirection = mxConstants.DEFAULT_TEXT_DIRECTION;
this.margin = null; this.margin = null;
} }
@ -502,8 +505,8 @@ class mxText extends mxShape {
this.updateMargin(); this.updateMargin();
} }
this.flipV = null; this.flipV = false;
this.flipH = null; this.flipH = false;
} }
/** /**
@ -517,7 +520,7 @@ class mxText extends mxShape {
getAutoDirection() { getAutoDirection() {
// Looks for strong (directional) characters // Looks for strong (directional) characters
const tmp = /[A-Za-z\u05d0-\u065f\u066a-\u06ef\u06fa-\u07ff\ufb1d-\ufdff\ufe70-\ufefc]/.exec( const tmp = /[A-Za-z\u05d0-\u065f\u066a-\u06ef\u06fa-\u07ff\ufb1d-\ufdff\ufe70-\ufefc]/.exec(
this.value <string>this.value
); );
// Returns the direction defined by the character // Returns the direction defined by the character
@ -537,9 +540,11 @@ class mxText extends mxShape {
if (result != null) { if (result != null) {
// Rendered with no foreignObject // Rendered with no foreignObject
if (result.ownerSVGElement == null) { if (result.ownerSVGElement == null) {
// @ts-ignore
result = this.node.firstChild.firstChild; result = this.node.firstChild.firstChild;
} else { } else {
// Innermost DIV that contains the actual content // Innermost DIV that contains the actual content
// @ts-ignore
result = result.firstChild.firstChild.firstChild.firstChild.firstChild; result = result.firstChild.firstChild.firstChild.firstChild.firstChild;
} }
} }
@ -591,12 +596,16 @@ class mxText extends mxShape {
node.firstChild.firstChild.nodeName === 'foreignObject' node.firstChild.firstChild.nodeName === 'foreignObject'
) { ) {
// Uses second inner DIV for font metrics // Uses second inner DIV for font metrics
// @ts-ignore
node = node.firstChild.firstChild.firstChild.firstChild; node = node.firstChild.firstChild.firstChild.firstChild;
// @ts-ignore
oh = node.offsetHeight * this.scale; oh = node.offsetHeight * this.scale;
if (this.overflow === 'width') { if (this.overflow === 'width') {
// @ts-ignore
ow = this.boundingBox.width; ow = this.boundingBox.width;
} else { } else {
// @ts-ignore
ow = node.offsetWidth * this.scale; ow = node.offsetWidth * this.scale;
} }
} else { } else {
@ -632,12 +641,14 @@ class mxText extends mxShape {
} }
if (this.boundingBox != null) { if (this.boundingBox != null) {
const margin = <mxRectangle>this.margin;
if (rot !== 0) { if (rot !== 0) {
// Accounts for pre-rotated x and y // Accounts for pre-rotated x and y
const bbox = <mxRectangle>mxUtils.getBoundingBox( const bbox = <mxRectangle>mxUtils.getBoundingBox(
new mxRectangle( new mxRectangle(
this.margin.x * this.boundingBox.width, margin.x * this.boundingBox.width,
this.margin.y * this.boundingBox.height, margin.y * this.boundingBox.height,
this.boundingBox.width, this.boundingBox.width,
this.boundingBox.height this.boundingBox.height
), ),
@ -647,17 +658,17 @@ class mxText extends mxShape {
this.unrotatedBoundingBox = mxRectangle.fromRectangle(this.boundingBox); this.unrotatedBoundingBox = mxRectangle.fromRectangle(this.boundingBox);
this.unrotatedBoundingBox.x += this.unrotatedBoundingBox.x +=
this.margin.x * this.unrotatedBoundingBox.width; margin.x * this.unrotatedBoundingBox.width;
this.unrotatedBoundingBox.y += this.unrotatedBoundingBox.y +=
this.margin.y * this.unrotatedBoundingBox.height; margin.y * this.unrotatedBoundingBox.height;
this.boundingBox.x += bbox.x; this.boundingBox.x += bbox.x;
this.boundingBox.y += bbox.y; this.boundingBox.y += bbox.y;
this.boundingBox.width = bbox.width; this.boundingBox.width = bbox.width;
this.boundingBox.height = bbox.height; this.boundingBox.height = bbox.height;
} else { } else {
this.boundingBox.x += this.margin.x * this.boundingBox.width; this.boundingBox.x += margin.x * this.boundingBox.width;
this.boundingBox.y += this.margin.y * this.boundingBox.height; this.boundingBox.y += margin.y * this.boundingBox.height;
this.unrotatedBoundingBox = null; this.unrotatedBoundingBox = null;
} }
} }
@ -693,6 +704,7 @@ class mxText extends mxShape {
return ( return (
!this.horizontal && !this.horizontal &&
this.state != null && this.state != null &&
// @ts-ignore
this.state.view.graph.model.isVertex(this.state.cell) this.state.view.graph.model.isVertex(this.state.cell)
); );
} }
@ -702,7 +714,11 @@ class mxText extends mxShape {
* *
* Sets the state of the canvas for drawing the shape. * Sets the state of the canvas for drawing the shape.
*/ */
configureCanvas(c, x, y, w, h) { configureCanvas(c: mxSvgCanvas2D,
x: number,
y: number,
w: number,
h: number) {
super.configureCanvas(c, x, y, w, h); super.configureCanvas(c, x, y, w, h);
c.setFontColor(this.color); c.setFontColor(this.color);
@ -796,6 +812,8 @@ class mxText extends mxShape {
`position: absolute; left: ${Math.round(this.bounds.x)}px; ` + `position: absolute; left: ${Math.round(this.bounds.x)}px; ` +
`top: ${Math.round(this.bounds.y)}px; pointer-events: none; `; `top: ${Math.round(this.bounds.y)}px; pointer-events: none; `;
const block = this.getTextCss(); const block = this.getTextCss();
const margin = <mxPoint>this.margin;
const node = <SVGGElement>this.node;
mxSvgCanvas2D.createCss( mxSvgCanvas2D.createCss(
w + 2, w + 2,
@ -810,13 +828,20 @@ class mxText extends mxShape {
flex, flex,
block, block,
this.scale, this.scale,
(dx, dy, flex, item, block, ofl) => { (
dx: number,
dy: number,
flex: string,
item: string,
block: string,
ofl: string
) => {
const r = this.getTextRotation(); const r = this.getTextRotation();
let tr = let tr =
(this.scale !== 1 ? `scale(${this.scale}) ` : '') + (this.scale !== 1 ? `scale(${this.scale}) ` : '') +
(r !== 0 ? `rotate(${r}deg) ` : '') + (r !== 0 ? `rotate(${r}deg) ` : '') +
(this.margin.x !== 0 || this.margin.y !== 0 (margin.x !== 0 || margin.y !== 0
? `translate(${this.margin.x * 100}%,${this.margin.y * 100}%)` ? `translate(${margin.x * 100}%,${margin.y * 100}%)`
: ''); : '');
if (tr !== '') { if (tr !== '') {
@ -834,22 +859,25 @@ class mxText extends mxShape {
} }
} }
if (this.opacity < 100) { if (<number>this.opacity < 100) {
block += `opacity: ${this.opacity / 100}; `; block += `opacity: ${<number>this.opacity / 100}; `;
} }
this.node.setAttribute('style', flex); node.setAttribute('style', flex);
const html = mxUtils.isNode(this.value) const html = mxUtils.isNode(this.value)
// @ts-ignore
? this.value.outerHTML ? this.value.outerHTML
: this.getHtmlValue(); : this.getHtmlValue();
if (this.node.firstChild == null) { if (node.firstChild == null) {
this.node.innerHTML = `<div><div>${html}</div></div>`; node.innerHTML = `<div><div>${html}</div></div>`;
} }
this.node.firstChild.firstChild.setAttribute('style', block); // @ts-ignore
this.node.firstChild.setAttribute('style', item); node.firstChild.firstChild.setAttribute('style', block);
// @ts-ignore
node.firstChild.setAttribute('style', item);
} }
); );
} }
@ -859,8 +887,9 @@ class mxText extends mxShape {
* *
* Sets the inner HTML of the given element to the <value>. * Sets the inner HTML of the given element to the <value>.
*/ */
updateInnerHtml(elt) { updateInnerHtml(elt: HTMLElement) {
if (mxUtils.isNode(this.value)) { if (mxUtils.isNode(this.value)) {
// @ts-ignore
elt.innerHTML = this.value.outerHTML; elt.innerHTML = this.value.outerHTML;
} else { } else {
let val = this.value; let val = this.value;
@ -885,9 +914,11 @@ class mxText extends mxShape {
* Updates the HTML node(s) to reflect the latest bounds and scale. * Updates the HTML node(s) to reflect the latest bounds and scale.
*/ */
updateValue() { updateValue() {
const node = <SVGGElement>this.node;
if (mxUtils.isNode(this.value)) { if (mxUtils.isNode(this.value)) {
this.node.innerHTML = ''; node.innerHTML = '';
this.node.appendChild(this.value); node.appendChild(<HTMLElement | SVGGElement>this.value);
} else { } else {
let val = this.value; let val = this.value;
@ -909,11 +940,11 @@ class mxText extends mxShape {
if (this.overflow === 'fill' || this.overflow === 'width') { if (this.overflow === 'fill' || this.overflow === 'width') {
if (bg != null) { if (bg != null) {
this.node.style.backgroundColor = bg; node.style.backgroundColor = bg;
} }
if (bd != null) { if (bd != null) {
this.node.style.border = `1px solid ${bd}`; node.style.border = `1px solid ${bd}`;
} }
} else { } else {
let css = ''; let css = '';
@ -937,10 +968,10 @@ class mxText extends mxShape {
`padding-bottom:1px;padding-right:1px;line-height:${lh}">${val}</div>`; `padding-bottom:1px;padding-right:1px;line-height:${lh}">${val}</div>`;
} }
this.node.innerHTML = val; node.innerHTML = val;
// Sets text direction // Sets text direction
const divs = this.node.getElementsByTagName('div'); const divs = node.getElementsByTagName('div');
if (divs.length > 0) { if (divs.length > 0) {
let dir = this.textDirection; let dir = this.textDirection;
@ -969,9 +1000,10 @@ class mxText extends mxShape {
* *
* Updates the HTML node(s) to reflect the latest bounds and scale. * Updates the HTML node(s) to reflect the latest bounds and scale.
*/ */
updateFont(node) { updateFont(node: HTMLElement | SVGGElement) {
const { style } = node; const { style } = node;
// @ts-ignore
style.lineHeight = mxConstants.ABSOLUTE_LINE_HEIGHT style.lineHeight = mxConstants.ABSOLUTE_LINE_HEIGHT
? `${this.size * mxConstants.LINE_HEIGHT}px` ? `${this.size * mxConstants.LINE_HEIGHT}px`
: mxConstants.LINE_HEIGHT; : mxConstants.LINE_HEIGHT;
@ -1061,6 +1093,7 @@ class mxText extends mxShape {
sizeDiv.firstChild != null && sizeDiv.firstChild != null &&
sizeDiv.firstChild.nodeName === 'DIV' sizeDiv.firstChild.nodeName === 'DIV'
) { ) {
// @ts-ignore
sizeDiv = sizeDiv.firstChild; sizeDiv = sizeDiv.firstChild;
if (node.style.wordWrap === 'break-word') { if (node.style.wordWrap === 'break-word') {
@ -1072,7 +1105,7 @@ class mxText extends mxShape {
// Workaround for text measuring in hidden containers // Workaround for text measuring in hidden containers
if (tmp === 0) { if (tmp === 0) {
const prev = node.parentNode; const prev = <HTMLElement>node.parentNode;
node.style.visibility = 'hidden'; node.style.visibility = 'hidden';
document.body.appendChild(node); document.body.appendChild(node);
tmp = sizeDiv.offsetWidth; tmp = sizeDiv.offsetWidth;

View File

@ -9,7 +9,7 @@ import mxActor from './mxActor';
import mxUtils from '../util/mxUtils'; import mxUtils from '../util/mxUtils';
import mxConstants from '../util/mxConstants'; import mxConstants from '../util/mxConstants';
import mxAbstractCanvas2D from '../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../util/canvas/mxSvgCanvas2D';
class mxTriangle extends mxActor { class mxTriangle extends mxActor {
/** /**

View File

@ -5,7 +5,7 @@
*/ */
import mxActor from '../mxActor'; import mxActor from '../mxActor';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxRectangle from "../../util/datatypes/mxRectangle"; import mxRectangle from '../../util/datatypes/mxRectangle';
/** /**
* Class: mxCloud * Class: mxCloud
@ -29,10 +29,12 @@ import mxRectangle from "../../util/datatypes/mxRectangle";
* 1. This is stored in <strokewidth>. * 1. This is stored in <strokewidth>.
*/ */
class mxCloud extends mxActor { class mxCloud extends mxActor {
constructor(bounds: mxRectangle, constructor(
bounds: mxRectangle,
fill: string, fill: string,
stroke: string, stroke: string,
strokewidth: number=1) { strokewidth: number = 1
) {
super(); super();
this.bounds = bounds; this.bounds = bounds;
this.fill = fill; this.fill = fill;

View File

@ -7,8 +7,8 @@ import mxShape from '../mxShape';
import mxConstants from '../../util/mxConstants'; import mxConstants from '../../util/mxConstants';
import mxUtils from '../../util/mxUtils'; import mxUtils from '../../util/mxUtils';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
import mxRectangle from "../../util/datatypes/mxRectangle"; import mxRectangle from '../../util/datatypes/mxRectangle';
/** /**
* Class: mxCylinder * Class: mxCylinder
@ -33,10 +33,12 @@ import mxRectangle from "../../util/datatypes/mxRectangle";
* 1. This is stored in <strokewidth>. * 1. This is stored in <strokewidth>.
*/ */
class mxCylinder extends mxShape { class mxCylinder extends mxShape {
constructor(bounds: mxRectangle, constructor(
bounds: mxRectangle,
fill: string, fill: string,
stroke: string, stroke: string,
strokewidth: number=1) { strokewidth: number = 1
) {
super(); super();
this.bounds = bounds; this.bounds = bounds;
this.fill = fill; this.fill = fill;
@ -93,10 +95,7 @@ class mxCylinder extends mxShape {
* *
* Returns the cylinder size. * Returns the cylinder size.
*/ */
getCylinderSize(x: number, getCylinderSize(x: number, y: number, w: number, h: number): number {
y: number,
w: number,
h: number): number {
return Math.min(this.maxHeight, Math.round(h / 5)); return Math.min(this.maxHeight, Math.round(h / 5));
} }

View File

@ -9,7 +9,7 @@ import mxShape from '../mxShape';
import mxConstants from '../../util/mxConstants'; import mxConstants from '../../util/mxConstants';
import mxUtils from '../../util/mxUtils'; import mxUtils from '../../util/mxUtils';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
/** /**
* Class: mxDoubleEllipse * Class: mxDoubleEllipse
@ -55,10 +55,12 @@ import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D";
class mxDoubleEllipse extends mxShape { class mxDoubleEllipse extends mxShape {
strokewidth: number; strokewidth: number;
constructor(bounds: mxRectangle, constructor(
bounds: mxRectangle,
fill: string, fill: string,
stroke: string, stroke: string,
strokewidth: number=1) { strokewidth: number = 1
) {
super(); super();
this.bounds = bounds; this.bounds = bounds;
this.fill = fill; this.fill = fill;

View File

@ -5,8 +5,8 @@
*/ */
import mxShape from '../mxShape'; import mxShape from '../mxShape';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
import mxRectangle from "../../util/datatypes/mxRectangle"; import mxRectangle from '../../util/datatypes/mxRectangle';
/** /**
* Class: mxEllipse * Class: mxEllipse
@ -29,10 +29,12 @@ import mxRectangle from "../../util/datatypes/mxRectangle";
* 1. This is stored in <strokewidth>. * 1. This is stored in <strokewidth>.
*/ */
class mxEllipse extends mxShape { class mxEllipse extends mxShape {
constructor(bounds: mxRectangle, constructor(
bounds: mxRectangle,
fill: string, fill: string,
stroke: string, stroke: string,
strokewidth: number=1) { strokewidth: number = 1
) {
super(); super();
this.bounds = bounds; this.bounds = bounds;
this.fill = fill; this.fill = fill;

View File

@ -8,7 +8,7 @@ import mxPoint from '../../util/datatypes/mxPoint';
import mxUtils from '../../util/mxUtils'; import mxUtils from '../../util/mxUtils';
import mxConstants from '../../util/mxConstants'; import mxConstants from '../../util/mxConstants';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
/** /**
* Class: mxHexagon * Class: mxHexagon
@ -29,13 +29,7 @@ class mxHexagon extends mxActor {
* *
* Draws the path for this shape. * Draws the path for this shape.
*/ */
redrawPath( redrawPath(c: mxSvgCanvas2D, x: number, y: number, w: number, h: number) {
c: mxSvgCanvas2D,
x: number,
y: number,
w: number,
h: number
) {
const arcSize = const arcSize =
mxUtils.getValue( mxUtils.getValue(
this.style, this.style,

View File

@ -9,7 +9,8 @@ import mxConstants from '../../util/mxConstants';
import mxRectangleShape from './mxRectangleShape'; import mxRectangleShape from './mxRectangleShape';
import mxRectangle from '../../util/datatypes/mxRectangle'; import mxRectangle from '../../util/datatypes/mxRectangle';
import mxCellState from '../../util/datatypes/mxCellState'; import mxCellState from '../../util/datatypes/mxCellState';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
import mxCellOverlay from '../../view/cell/mxCellOverlay';
/** /**
* Class: mxImageShape * Class: mxImageShape
@ -54,6 +55,9 @@ class mxImageShape extends mxRectangleShape {
image: string; image: string;
// Used in mxCellRenderer
overlay: mxCellOverlay | null = null;
/** /**
* Variable: preserveImageAspect * Variable: preserveImageAspect
* *

View File

@ -9,7 +9,7 @@ import mxUtils from '../../util/mxUtils';
import mxShape from '../mxShape'; import mxShape from '../mxShape';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxRectangle from '../../util/datatypes/mxRectangle'; import mxRectangle from '../../util/datatypes/mxRectangle';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
/** /**
* Class: mxRectangleShape * Class: mxRectangleShape

View File

@ -9,7 +9,7 @@ import mxUtils from '../../util/mxUtils';
import mxConstants from '../../util/mxConstants'; import mxConstants from '../../util/mxConstants';
import mxRectangle from '../../util/datatypes/mxRectangle'; import mxRectangle from '../../util/datatypes/mxRectangle';
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D'; import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
import mxSvgCanvas2D from "../../util/canvas/mxSvgCanvas2D"; import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
/** /**
* Class: mxRhombus * Class: mxRhombus

View File

@ -12,8 +12,12 @@ import mxGraphView from '../../view/graph/mxGraphView';
import mxShape from '../../shape/mxShape'; import mxShape from '../../shape/mxShape';
import mxText from '../../shape/mxText'; import mxText from '../../shape/mxText';
import mxGraph from "../../view/graph/mxGraph"; import mxGraph from "../../view/graph/mxGraph";
import mxDictionary from "./mxDictionary";
class mxCellState extends mxRectangle { class mxCellState extends mxRectangle {
// referenced in mxCellRenderer
node: any;
// TODO: Document me!! // TODO: Document me!!
cellBounds: mxRectangle | null = null; cellBounds: mxRectangle | null = null;
@ -25,7 +29,7 @@ class mxCellState extends mxRectangle {
control: mxShape | null = null; control: mxShape | null = null;
// Used by mxCellRenderer's createCellOverlays() // Used by mxCellRenderer's createCellOverlays()
overlays: any[] | null = null; overlays: mxDictionary | null = null;
/** /**
* Variable: view * Variable: view

View File

@ -5,7 +5,6 @@
*/ */
import mxUtils from '../mxUtils'; import mxUtils from '../mxUtils';
import mxConstants from '../mxConstants';
class mxPoint { class mxPoint {
/** /**
@ -33,11 +32,9 @@ class mxPoint {
* coordinates are given, then the default values for <x> and <y> are used. * coordinates are given, then the default values for <x> and <y> are used.
*/ */
constructor(x, y) { constructor(x, y) {
if (x !== mxConstants.DO_NOTHING) {
this.x = x != null ? x : 0; this.x = x != null ? x : 0;
this.y = y != null ? y : 0; this.y = y != null ? y : 0;
} }
}
get x() { get x() {
return this._x || 0; return this._x || 0;

View File

@ -16,7 +16,6 @@
*/ */
import mxPoint from './mxPoint'; import mxPoint from './mxPoint';
import mxConstants from '../mxConstants';
class mxRectangle extends mxPoint { class mxRectangle extends mxPoint {
/** /**
@ -36,12 +35,10 @@ class mxRectangle extends mxPoint {
constructor(x, y, width, height) { constructor(x, y, width, height) {
super(x, y, width, height); super(x, y, width, height);
if (x !== mxConstants.DO_NOTHING) {
// replace super of mxPoint // replace super of mxPoint
this.width = width != null ? width : 0; this.width = width != null ? width : 0;
this.height = height != null ? height : 0; this.height = height != null ? height : 0;
} }
}
/** /**
* Function: fromRectangle * Function: fromRectangle
@ -176,19 +173,4 @@ class mxRectangle extends mxPoint {
} }
} }
// HACK: Prevent dependency problems with mxConstants
// importing mxRectangle and vice-versa
mxConstants.PAGE_FORMAT_A4_PORTRAIT = new mxRectangle(
...mxConstants.PAGE_FORMAT_A4_PORTRAIT
);
mxConstants.PAGE_FORMAT_A4_LANDSCAPE = new mxRectangle(
...mxConstants.PAGE_FORMAT_A4_LANDSCAPE
);
mxConstants.PAGE_FORMAT_LETTER_PORTRAIT = new mxRectangle(
...mxConstants.PAGE_FORMAT_LETTER_PORTRAIT
);
mxConstants.PAGE_FORMAT_LETTER_LANDSCAPE = new mxRectangle(
...mxConstants.PAGE_FORMAT_LETTER_LANDSCAPE
);
export default mxRectangle; export default mxRectangle;

View File

@ -3,6 +3,7 @@
* Copyright (c) 2006-2015, Gaudenz Alder * Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021 * Updated to ES9 syntax by David Morrissey 2021
*/ */
import mxRectangle from './datatypes/mxRectangle';
const mxConstants = { const mxConstants = {
DO_NOTHING: {}, DO_NOTHING: {},
@ -670,7 +671,7 @@ const mxConstants = {
* Defines the rectangle for the A4 portrait page format. The dimensions * Defines the rectangle for the A4 portrait page format. The dimensions
* of this page format are 826x1169 pixels. * of this page format are 826x1169 pixels.
*/ */
PAGE_FORMAT_A4_PORTRAIT: [0, 0, 827, 1169], PAGE_FORMAT_A4_PORTRAIT: new mxRectangle(0, 0, 827, 1169),
/** /**
* Variable: PAGE_FORMAT_A4_PORTRAIT * Variable: PAGE_FORMAT_A4_PORTRAIT
@ -678,7 +679,7 @@ const mxConstants = {
* Defines the rectangle for the A4 portrait page format. The dimensions * Defines the rectangle for the A4 portrait page format. The dimensions
* of this page format are 826x1169 pixels. * of this page format are 826x1169 pixels.
*/ */
PAGE_FORMAT_A4_LANDSCAPE: [0, 0, 1169, 827], PAGE_FORMAT_A4_LANDSCAPE: new mxRectangle(0, 0, 1169, 827),
/** /**
* Variable: PAGE_FORMAT_LETTER_PORTRAIT * Variable: PAGE_FORMAT_LETTER_PORTRAIT
@ -686,7 +687,7 @@ const mxConstants = {
* Defines the rectangle for the Letter portrait page format. The * Defines the rectangle for the Letter portrait page format. The
* dimensions of this page format are 850x1100 pixels. * dimensions of this page format are 850x1100 pixels.
*/ */
PAGE_FORMAT_LETTER_PORTRAIT: [0, 0, 850, 1100], PAGE_FORMAT_LETTER_PORTRAIT: new mxRectangle(0, 0, 850, 1100),
/** /**
* Variable: PAGE_FORMAT_LETTER_PORTRAIT * Variable: PAGE_FORMAT_LETTER_PORTRAIT
@ -694,7 +695,7 @@ const mxConstants = {
* Defines the rectangle for the Letter portrait page format. The dimensions * Defines the rectangle for the Letter portrait page format. The dimensions
* of this page format are 850x1100 pixels. * of this page format are 850x1100 pixels.
*/ */
PAGE_FORMAT_LETTER_LANDSCAPE: [0, 0, 1100, 850], PAGE_FORMAT_LETTER_LANDSCAPE: new mxRectangle(0, 0, 1100, 850),
/** /**
* Variable: NONE * Variable: NONE

View File

@ -460,8 +460,7 @@ class mxCell {
* isSource - Boolean that specifies if the source or target terminal * isSource - Boolean that specifies if the source or target terminal
* should be set. * should be set.
*/ */
setTerminal(terminal: mxCell | null, setTerminal(terminal: mxCell | null, isSource: boolean): mxCell | null {
isSource: boolean): mxCell | null {
if (isSource) { if (isSource) {
this.source = terminal; this.source = terminal;
} else { } else {
@ -519,9 +518,7 @@ class mxCell {
* index - Optional integer that specifies the index at which the child * index - Optional integer that specifies the index at which the child
* should be inserted into the child array. * should be inserted into the child array.
*/ */
insert(child: mxCell | null=null, insert(child: mxCell | null = null, index: number | null = null) {
index: number | null=null) {
if (child != null) { if (child != null) {
if (index == null) { if (index == null) {
index = this.getChildCount(); index = this.getChildCount();
@ -626,9 +623,7 @@ class mxCell {
* edge - <mxCell> to be inserted into the edge array. * edge - <mxCell> to be inserted into the edge array.
* isOutgoing - Boolean that specifies if the edge is outgoing. * isOutgoing - Boolean that specifies if the edge is outgoing.
*/ */
insertEdge(edge: mxCell | null, insertEdge(edge: mxCell | null, isOutgoing: boolean) {
isOutgoing: boolean) {
if (edge != null) { if (edge != null) {
edge.removeFromTerminal(isOutgoing); edge.removeFromTerminal(isOutgoing);
edge.setTerminal(this, isOutgoing); edge.setTerminal(this, isOutgoing);
@ -658,9 +653,7 @@ class mxCell {
* edge - <mxCell> to be removed from the edge array. * edge - <mxCell> to be removed from the edge array.
* isOutgoing - Boolean that specifies if the edge is outgoing. * isOutgoing - Boolean that specifies if the edge is outgoing.
*/ */
removeEdge(edge: mxCell | null, removeEdge(edge: mxCell | null, isOutgoing: boolean = false): mxCell | null {
isOutgoing: boolean=false): mxCell | null {
if (edge != null) { if (edge != null) {
if (edge.getTerminal(!isOutgoing) !== this && this.edges != null) { if (edge.getTerminal(!isOutgoing) !== this && this.edges != null) {
const index = this.getEdgeIndex(edge); const index = this.getEdgeIndex(edge);
@ -703,11 +696,13 @@ class mxCell {
*/ */
hasAttribute(name: string): boolean { hasAttribute(name: string): boolean {
const userObject = this.getValue(); const userObject = this.getValue();
return userObject != null && return (
userObject != null &&
(userObject.nodeType === mxConstants.NODETYPE_ELEMENT && (userObject.nodeType === mxConstants.NODETYPE_ELEMENT &&
userObject.hasAttribute userObject.hasAttribute
? userObject.hasAttribute(name) ? userObject.hasAttribute(name)
: userObject.getAttribute(name) != null); : userObject.getAttribute(name) != null)
);
} }
/** /**
@ -722,9 +717,7 @@ class mxCell {
* defaultValue - Optional default value to use if the attribute has no * defaultValue - Optional default value to use if the attribute has no
* value. * value.
*/ */
getAttribute(name: string, getAttribute(name: string, defaultValue: any): any {
defaultValue: any): any {
const userObject = this.getValue(); const userObject = this.getValue();
const val = const val =
userObject != null && userObject.nodeType === mxConstants.NODETYPE_ELEMENT userObject != null && userObject.nodeType === mxConstants.NODETYPE_ELEMENT
@ -743,9 +736,7 @@ class mxCell {
* name - Name of the attribute whose value should be set. * name - Name of the attribute whose value should be set.
* value - New value of the attribute. * value - New value of the attribute.
*/ */
setAttribute(name: string, setAttribute(name: string, value: any): void {
value: any): void {
const userObject = this.getValue(); const userObject = this.getValue();
if ( if (
userObject != null && userObject != null &&

View File

@ -189,7 +189,7 @@ class mxCellEditor {
* *
* Reference to the event that was used to start editing. * Reference to the event that was used to start editing.
*/ */
trigger: mxMouseEvent | null = null; trigger: mxMouseEvent | MouseEvent | null = null;
/** /**
* Variable: modified * Variable: modified
@ -778,7 +778,7 @@ class mxCellEditor {
* cell - <mxCell> to start editing. * cell - <mxCell> to start editing.
* trigger - Optional mouse event that triggered the editor. * trigger - Optional mouse event that triggered the editor.
*/ */
startEditing(cell: mxCell, trigger: mxMouseEvent | null = null): void { startEditing(cell: mxCell, trigger: mxMouseEvent | MouseEvent | null = null): void {
this.stopEditing(true); this.stopEditing(true);
this.align = null; this.align = null;

View File

@ -34,8 +34,41 @@ import mxShape from '../../shape/mxShape';
import mxCellState from '../../util/datatypes/mxCellState'; import mxCellState from '../../util/datatypes/mxCellState';
import mxCell from './mxCell'; import mxCell from './mxCell';
import mxGraphModel from "../graph/mxGraphModel"; import mxGraphModel from "../graph/mxGraphModel";
import mxCellOverlay from "./mxCellOverlay";
/**
* Class: mxCellRenderer
*
* Renders cells into a document object model. The <defaultShapes> is a global
* map of shapename, constructor pairs that is used in all instances. You can
* get a list of all available shape names using the following code.
*
* In general the cell renderer is in charge of creating, redrawing and
* destroying the shape and label associated with a cell state, as well as
* some other graphical objects, namely controls and overlays. The shape
* hieararchy in the display (ie. the hierarchy in which the DOM nodes
* appear in the document) does not reflect the cell hierarchy. The shapes
* are a (flat) sequence of shapes and labels inside the draw pane of the
* graph view, with some exceptions, namely the HTML labels being placed
* directly inside the graph container for certain browsers.
*
* (code)
* mxLog.show();
* for (var i in mxCellRenderer.defaultShapes)
* {
* mxLog.debug(i);
* }
* (end)
*
* Constructor: mxCellRenderer
*
* Constructs a new cell renderer with the following built-in shapes:
* arrow, rectangle, ellipse, rhombus, image, line, label, cylinder,
* swimlane, connector, actor and cloud.
*/
class mxCellRenderer { class mxCellRenderer {
constructor() {}
/** /**
* Variable: defaultShapes * Variable: defaultShapes
* *
@ -43,7 +76,7 @@ class mxCellRenderer {
* known to all instances of this class. For adding new shapes you should * known to all instances of this class. For adding new shapes you should
* use the static <mxCellRenderer.registerShape> function. * use the static <mxCellRenderer.registerShape> function.
*/ */
static defaultShapes = {}; static defaultShapes: { [key: string]: typeof mxShape; } = {};
/** /**
* Variable: defaultEdgeShape * Variable: defaultEdgeShape
@ -104,38 +137,6 @@ class mxCellRenderer {
*/ */
forceControlClickHandler: boolean = false; forceControlClickHandler: boolean = false;
/**
* Class: mxCellRenderer
*
* Renders cells into a document object model. The <defaultShapes> is a global
* map of shapename, constructor pairs that is used in all instances. You can
* get a list of all available shape names using the following code.
*
* In general the cell renderer is in charge of creating, redrawing and
* destroying the shape and label associated with a cell state, as well as
* some other graphical objects, namely controls and overlays. The shape
* hieararchy in the display (ie. the hierarchy in which the DOM nodes
* appear in the document) does not reflect the cell hierarchy. The shapes
* are a (flat) sequence of shapes and labels inside the draw pane of the
* graph view, with some exceptions, namely the HTML labels being placed
* directly inside the graph container for certain browsers.
*
* (code)
* mxLog.show();
* for (var i in mxCellRenderer.defaultShapes)
* {
* mxLog.debug(i);
* }
* (end)
*
* Constructor: mxCellRenderer
*
* Constructs a new cell renderer with the following built-in shapes:
* arrow, rectangle, ellipse, rhombus, image, line, label, cylinder,
* swimlane, connector, actor and cloud.
*/
constructor() {}
/** /**
* Function: registerShape * Function: registerShape
* *
@ -153,7 +154,7 @@ class mxCellRenderer {
* key - String representing the shape name. * key - String representing the shape name.
* shape - Constructor of the <mxShape> subclass. * shape - Constructor of the <mxShape> subclass.
*/ */
static registerShape = (key, shape) => { static registerShape(key: string, shape: typeof mxShape) {
mxCellRenderer.defaultShapes[key] = shape; mxCellRenderer.defaultShapes[key] = shape;
}; };
@ -168,9 +169,9 @@ class mxCellRenderer {
* state - <mxCellState> for which the shape should be initialized. * state - <mxCellState> for which the shape should be initialized.
*/ */
initializeShape(state: mxCellState) { initializeShape(state: mxCellState) {
state.shape.dialect = state.view.graph.dialect; (<mxShape>state.shape).dialect = state.view.graph.dialect;
this.configureShape(state); this.configureShape(state);
state.shape.init(state.view.getDrawPane()); (<mxShape>state.shape).init(state.view.getDrawPane());
} }
/** /**
@ -182,7 +183,7 @@ class mxCellRenderer {
* *
* state - <mxCellState> for which the shape should be created. * state - <mxCellState> for which the shape should be created.
*/ */
createShape(state: mxCellState): mxShape { createShape(state: mxCellState): mxShape | null {
let shape = null; let shape = null;
if (state.style != null) { if (state.style != null) {
@ -210,9 +211,10 @@ class mxCellRenderer {
* *
* state - <mxCellState> for which the indicator shape should be created. * state - <mxCellState> for which the indicator shape should be created.
*/ */
createIndicatorShape(state: mxCellState): mxShape { createIndicatorShape(state: mxCellState): void {
// @ts-ignore
state.shape.indicatorShape = this.getShape( state.shape.indicatorShape = this.getShape(
state.view.graph.getIndicatorShape(state) <string>state.view.graph.getIndicatorShape(state)
); );
} }
@ -222,6 +224,7 @@ class mxCellRenderer {
* Returns the shape for the given name from <defaultShapes>. * Returns the shape for the given name from <defaultShapes>.
*/ */
getShape(name: string): typeof mxShape { getShape(name: string): typeof mxShape {
// @ts-ignore
return name != null ? mxCellRenderer.defaultShapes[name] : null; return name != null ? mxCellRenderer.defaultShapes[name] : null;
} }
@ -233,9 +236,9 @@ class mxCellRenderer {
getShapeConstructor(state: mxCellState) { getShapeConstructor(state: mxCellState) {
let ctor = this.getShape(state.style[mxConstants.STYLE_SHAPE]); let ctor = this.getShape(state.style[mxConstants.STYLE_SHAPE]);
if (ctor == null) { if (ctor == null) {
ctor = state.view.graph.getModel().isEdge(state.cell) ctor = <typeof mxShape>(state.view.graph.getModel().isEdge(state.cell)
? this.defaultEdgeShape ? this.defaultEdgeShape
: this.defaultVertexShape; : this.defaultVertexShape);
} }
return ctor; return ctor;
} }
@ -250,18 +253,14 @@ class mxCellRenderer {
* state - <mxCellState> for which the shape should be configured. * state - <mxCellState> for which the shape should be configured.
*/ */
configureShape(state: mxCellState) { configureShape(state: mxCellState) {
state.shape.apply(state); const shape = <any>state.shape;
state.shape.image = state.view.graph.getImage(state); shape.apply(state);
state.shape.indicatorColor = state.view.graph.getIndicatorColor(state); shape.image = state.view.graph.getImage(state);
state.shape.indicatorStrokeColor = shape.indicatorColor = state.view.graph.getIndicatorColor(state);
state.style[mxConstants.STYLE_INDICATOR_STROKECOLOR]; shape.indicatorStrokeColor = state.style[mxConstants.STYLE_INDICATOR_STROKECOLOR];
state.shape.indicatorGradientColor = state.view.graph.getIndicatorGradientColor( shape.indicatorGradientColor = state.view.graph.getIndicatorGradientColor(state);
state shape.indicatorDirection = state.style[mxConstants.STYLE_INDICATOR_DIRECTION];
); shape.indicatorImage = state.view.graph.getIndicatorImage(state);
state.shape.indicatorDirection =
state.style[mxConstants.STYLE_INDICATOR_DIRECTION];
state.shape.indicatorImage = state.view.graph.getIndicatorImage(state);
this.postConfigureShape(state); this.postConfigureShape(state);
} }
@ -319,50 +318,59 @@ class mxCellRenderer {
* Resolves special keywords 'inherit', 'indicated' and 'swimlane' and sets * Resolves special keywords 'inherit', 'indicated' and 'swimlane' and sets
* the respective color on the shape. * the respective color on the shape.
*/ */
resolveColor(state, field, key) { resolveColor(state: mxCellState, field: string, key: string) {
const shape = const shape =
key === mxConstants.STYLE_FONTCOLOR ? state.text : state.shape; key === mxConstants.STYLE_FONTCOLOR ? state.text : state.shape;
if (shape != null) { if (shape != null) {
const { graph } = state.view; const { graph } = state.view;
// @ts-ignore
const value = shape[field]; const value = shape[field];
let referenced = null; let referenced = null;
if (value === 'inherit') { if (value === 'inherit') {
// @ts-ignore
referenced = graph.model.getParent(state.cell); referenced = graph.model.getParent(state.cell);
} else if (value === 'swimlane') { } else if (value === 'swimlane') {
// @ts-ignore
shape[field] = shape[field] =
key === mxConstants.STYLE_STROKECOLOR || key === mxConstants.STYLE_STROKECOLOR ||
key === mxConstants.STYLE_FONTCOLOR key === mxConstants.STYLE_FONTCOLOR
? '#000000' ? '#000000'
: '#ffffff'; : '#ffffff';
// @ts-ignore
if (graph.model.getTerminal(state.cell, false) != null) { if (graph.model.getTerminal(state.cell, false) != null) {
// @ts-ignore
referenced = graph.model.getTerminal(state.cell, false); referenced = graph.model.getTerminal(state.cell, false);
} else { } else {
referenced = state.cell; referenced = state.cell;
} }
referenced = graph.getSwimlane(referenced); referenced = graph.getSwimlane(<mxCell>referenced);
key = graph.swimlaneIndicatorColorAttribute; key = graph.swimlaneIndicatorColorAttribute;
} else if (value === 'indicated' && state.shape != null) { } else if (value === 'indicated' && state.shape != null) {
// @ts-ignore
shape[field] = state.shape.indicatorColor; shape[field] = state.shape.indicatorColor;
} else if ( } else if (
key !== mxConstants.STYLE_FILLCOLOR && key !== mxConstants.STYLE_FILLCOLOR &&
value === mxConstants.STYLE_FILLCOLOR && value === mxConstants.STYLE_FILLCOLOR &&
state.shape != null state.shape != null
) { ) {
// @ts-ignore
shape[field] = state.style[mxConstants.STYLE_FILLCOLOR]; shape[field] = state.style[mxConstants.STYLE_FILLCOLOR];
} else if ( } else if (
key !== mxConstants.STYLE_STROKECOLOR && key !== mxConstants.STYLE_STROKECOLOR &&
value === mxConstants.STYLE_STROKECOLOR && value === mxConstants.STYLE_STROKECOLOR &&
state.shape != null state.shape != null
) { ) {
// @ts-ignore
shape[field] = state.style[mxConstants.STYLE_STROKECOLOR]; shape[field] = state.style[mxConstants.STYLE_STROKECOLOR];
} }
if (referenced != null) { if (referenced != null) {
const rstate = graph.getView().getState(referenced); const rstate = graph.getView().getState(referenced);
// @ts-ignore
shape[field] = null; shape[field] = null;
if (rstate != null) { if (rstate != null) {
@ -370,8 +378,10 @@ class mxCellRenderer {
key === mxConstants.STYLE_FONTCOLOR ? rstate.text : rstate.shape; key === mxConstants.STYLE_FONTCOLOR ? rstate.text : rstate.shape;
if (rshape != null && field !== 'indicatorColor') { if (rshape != null && field !== 'indicatorColor') {
// @ts-ignore
shape[field] = rshape[field]; shape[field] = rshape[field];
} else { } else {
// @ts-ignore
shape[field] = rstate.style[key]; shape[field] = rstate.style[key];
} }
} }
@ -401,7 +411,7 @@ class mxCellRenderer {
* *
* state - <mxCellState> for which the label should be created. * state - <mxCellState> for which the label should be created.
*/ */
createLabel(state, value) { createLabel(state: mxCellState, value: any) {
const { graph } = state.view; const { graph } = state.view;
const isEdge = graph.getModel().isEdge(state.cell); const isEdge = graph.getModel().isEdge(state.cell);
@ -450,7 +460,7 @@ class mxCellRenderer {
// getCellAt for the subsequent mouseMoves and the final mouseUp. // getCellAt for the subsequent mouseMoves and the final mouseUp.
let forceGetCell = false; let forceGetCell = false;
const getState = evt => { const getState = (evt: Event | mxMouseEvent) => {
let result = state; let result = state;
if (mxClient.IS_TOUCH || forceGetCell) { if (mxClient.IS_TOUCH || forceGetCell) {
@ -460,7 +470,7 @@ class mxCellRenderer {
// Dispatches the drop event to the graph which // Dispatches the drop event to the graph which
// consumes and executes the source function // consumes and executes the source function
const pt = mxUtils.convertPoint(graph.container, x, y); const pt = mxUtils.convertPoint(graph.container, x, y);
result = graph.view.getState(graph.getCellAt(pt.x, pt.y)); result = <mxCellState>graph.view.getState(graph.getCellAt(pt.x, pt.y));
} }
return result; return result;
}; };
@ -468,7 +478,7 @@ class mxCellRenderer {
// TODO: Add handling for special touch device gestures // TODO: Add handling for special touch device gestures
mxEvent.addGestureListeners( mxEvent.addGestureListeners(
state.text.node, state.text.node,
evt => { (evt: mxMouseEvent) => {
if (this.isLabelEvent(state, evt)) { if (this.isLabelEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_DOWN, mxEvent.MOUSE_DOWN,
@ -479,7 +489,7 @@ class mxCellRenderer {
mxEvent.getSource(evt).nodeName === 'IMG'; mxEvent.getSource(evt).nodeName === 'IMG';
} }
}, },
evt => { (evt: mxMouseEvent) => {
if (this.isLabelEvent(state, evt)) { if (this.isLabelEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_MOVE, mxEvent.MOUSE_MOVE,
@ -487,7 +497,7 @@ class mxCellRenderer {
); );
} }
}, },
evt => { (evt: mxMouseEvent) => {
if (this.isLabelEvent(state, evt)) { if (this.isLabelEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_UP, mxEvent.MOUSE_UP,
@ -500,7 +510,7 @@ class mxCellRenderer {
// Uses double click timeout in mxGraph for quirks mode // Uses double click timeout in mxGraph for quirks mode
if (graph.nativeDblClickEnabled) { if (graph.nativeDblClickEnabled) {
mxEvent.addListener(state.text.node, 'dblclick', evt => { mxEvent.addListener(state.text.node, 'dblclick', (evt: MouseEvent) => {
if (this.isLabelEvent(state, evt)) { if (this.isLabelEvent(state, evt)) {
graph.dblClick(evt, state.cell); graph.dblClick(evt, state.cell);
mxEvent.consume(evt); mxEvent.consume(evt);
@ -519,7 +529,7 @@ class mxCellRenderer {
* *
* state - <mxCellState> whose label should be initialized. * state - <mxCellState> whose label should be initialized.
*/ */
initializeLabel(state, shape) { initializeLabel(state: mxCellState, shape: mxShape) {
if ( if (
mxClient.IS_SVG && mxClient.IS_SVG &&
mxClient.NO_FO && mxClient.NO_FO &&
@ -555,6 +565,7 @@ class mxCellRenderer {
if (shape == null) { if (shape == null) {
const tmp = new mxImageShape( const tmp = new mxImageShape(
new mxRectangle(), new mxRectangle(),
// @ts-ignore
overlays[i].image.src overlays[i].image.src
); );
tmp.dialect = state.view.graph.dialect; tmp.dialect = state.view.graph.dialect;
@ -564,6 +575,7 @@ class mxCellRenderer {
this.installCellOverlayListeners(state, overlays[i], tmp); this.installCellOverlayListeners(state, overlays[i], tmp);
if (overlays[i].cursor != null) { if (overlays[i].cursor != null) {
// @ts-ignore
tmp.node.style.cursor = overlays[i].cursor; tmp.node.style.cursor = overlays[i].cursor;
} }
@ -576,7 +588,7 @@ class mxCellRenderer {
// Removes unused // Removes unused
if (state.overlays != null) { if (state.overlays != null) {
state.overlays.visit((id, shape) => { state.overlays.visit((id: any, shape: { destroy: () => void; }) => {
shape.destroy(); shape.destroy();
}); });
} }
@ -593,7 +605,7 @@ class mxCellRenderer {
* state - <mxCellState> for which the overlay should be created. * state - <mxCellState> for which the overlay should be created.
* overlay - <mxImageShape> that represents the overlay. * overlay - <mxImageShape> that represents the overlay.
*/ */
initializeOverlay(state, overlay) { initializeOverlay(state: mxCellState, overlay: mxImageShape): void {
overlay.init(state.view.getOverlayPane()); overlay.init(state.view.getOverlayPane());
} }
@ -603,10 +615,12 @@ class mxCellRenderer {
* Installs the listeners for the given <mxCellState>, <mxCellOverlay> and * Installs the listeners for the given <mxCellState>, <mxCellOverlay> and
* <mxShape> that represents the overlay. * <mxShape> that represents the overlay.
*/ */
installCellOverlayListeners(state, overlay, shape) { installCellOverlayListeners(state: mxCellState,
overlay: mxCellOverlay,
shape: mxShape) {
const { graph } = state.view; const { graph } = state.view;
mxEvent.addListener(shape.node, 'click', function(evt) { mxEvent.addListener(shape.node, 'click', (evt: Event) => {
if (graph.isEditing()) { if (graph.isEditing()) {
graph.stopEditing(!graph.isInvokesStopCellEditing()); graph.stopEditing(!graph.isInvokesStopCellEditing());
} }
@ -618,16 +632,16 @@ class mxCellRenderer {
mxEvent.addGestureListeners( mxEvent.addGestureListeners(
shape.node, shape.node,
function(evt) { (evt: Event) => {
mxEvent.consume(evt); mxEvent.consume(evt);
}, },
function(evt) { (evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, state)); graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt, state));
} }
); );
if (mxClient.IS_TOUCH) { if (mxClient.IS_TOUCH) {
mxEvent.addListener(shape.node, 'touchend', function(evt) { mxEvent.addListener(shape.node, 'touchend', (evt: Event) => {
overlay.fireEvent( overlay.fireEvent(
new mxEventObject(mxEvent.CLICK, 'event', evt, 'cell', state.cell) new mxEventObject(mxEvent.CLICK, 'event', evt, 'cell', state.cell)
); );
@ -680,10 +694,10 @@ class mxCellRenderer {
createControlClickHandler(state: mxCellState): Function { createControlClickHandler(state: mxCellState): Function {
const { graph } = state.view; const { graph } = state.view;
return evt => { return (evt: mxEventObject) => {
if (this.forceControlClickHandler || graph.isEnabled()) { if (this.forceControlClickHandler || graph.isEnabled()) {
const collapse = !graph.isCellCollapsed(state.cell); const collapse = !graph.isCellCollapsed(state.cell);
graph.foldCells(collapse, false, [state.cell], null, evt); graph.foldCells(collapse, false, [state.cell], false, evt);
mxEvent.consume(evt); mxEvent.consume(evt);
} }
}; };
@ -701,7 +715,11 @@ class mxCellRenderer {
* handleEvents - Boolean indicating if mousedown and mousemove should fire events via the graph. * handleEvents - Boolean indicating if mousedown and mousemove should fire events via the graph.
* clickHandler - Optional function to implement clicks on the control. * clickHandler - Optional function to implement clicks on the control.
*/ */
initControl(state, control, handleEvents, clickHandler) { initControl(state: mxCellState,
control: mxShape,
handleEvents: boolean,
clickHandler: Function) {
const { graph } = state.view; const { graph } = state.view;
// In the special case where the label is in HTML and the display is SVG the image // In the special case where the label is in HTML and the display is SVG the image
@ -715,16 +733,18 @@ class mxCellRenderer {
if (isForceHtml) { if (isForceHtml) {
control.dialect = mxConstants.DIALECT_PREFERHTML; control.dialect = mxConstants.DIALECT_PREFERHTML;
control.init(graph.container); control.init(graph.container);
// @ts-ignore
control.node.style.zIndex = 1; control.node.style.zIndex = 1;
} else { } else {
control.init(state.view.getOverlayPane()); control.init(state.view.getOverlayPane());
} }
const node = control.innerNode || control.node; const node = control.node;
// Workaround for missing click event on iOS is to check tolerance below // Workaround for missing click event on iOS is to check tolerance below
if (clickHandler != null && !mxClient.IS_IOS) { if (clickHandler != null && !mxClient.IS_IOS) {
if (graph.isEnabled()) { if (graph.isEnabled()) {
// @ts-ignore
node.style.cursor = 'pointer'; node.style.cursor = 'pointer';
} }
@ -732,11 +752,11 @@ class mxCellRenderer {
} }
if (handleEvents) { if (handleEvents) {
let first = null; let first: mxPoint | null = null;
mxEvent.addGestureListeners( mxEvent.addGestureListeners(
node, node,
function(evt) { (evt: Event) => {
first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt)); first = new mxPoint(mxEvent.getClientX(evt), mxEvent.getClientY(evt));
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_DOWN, mxEvent.MOUSE_DOWN,
@ -744,13 +764,13 @@ class mxCellRenderer {
); );
mxEvent.consume(evt); mxEvent.consume(evt);
}, },
function(evt) { (evt: Event) => {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_MOVE, mxEvent.MOUSE_MOVE,
new mxMouseEvent(evt, state) new mxMouseEvent(evt, state)
); );
}, },
function(evt) { (evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt, state)); graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt, state));
mxEvent.consume(evt); mxEvent.consume(evt);
} }
@ -758,6 +778,7 @@ class mxCellRenderer {
// Uses capture phase for event interception to stop bubble phase // Uses capture phase for event interception to stop bubble phase
if (clickHandler != null && mxClient.IS_IOS) { if (clickHandler != null && mxClient.IS_IOS) {
// @ts-ignore
node.addEventListener( node.addEventListener(
'touchend', 'touchend',
evt => { evt => {
@ -792,7 +813,7 @@ class mxCellRenderer {
* state - <mxCellState> whose shape fired the event. * state - <mxCellState> whose shape fired the event.
* evt - Mouse event which was fired. * evt - Mouse event which was fired.
*/ */
isShapeEvent(state, evt) { isShapeEvent(state: mxCellState, evt: mxMouseEvent | MouseEvent) {
return true; return true;
} }
@ -807,7 +828,7 @@ class mxCellRenderer {
* state - <mxCellState> whose label fired the event. * state - <mxCellState> whose label fired the event.
* evt - Mouse event which was fired. * evt - Mouse event which was fired.
*/ */
isLabelEvent(state, evt) { isLabelEvent(state: mxCellState, evt: mxMouseEvent | MouseEvent) {
return true; return true;
} }
@ -826,7 +847,7 @@ class mxCellRenderer {
// Workaround for touch devices routing all events for a mouse // Workaround for touch devices routing all events for a mouse
// gesture (down, move, up) via the initial DOM node. Same for // gesture (down, move, up) via the initial DOM node. Same for
// HTML images in all IE versions (VML images are working). // HTML images in all IE versions (VML images are working).
const getState = evt => { const getState = (evt: Event) => {
let result = state; let result = state;
if ( if (
@ -840,15 +861,16 @@ class mxCellRenderer {
// Dispatches the drop event to the graph which // Dispatches the drop event to the graph which
// consumes and executes the source function // consumes and executes the source function
const pt = mxUtils.convertPoint(graph.container, x, y); const pt = mxUtils.convertPoint(graph.container, x, y);
result = graph.view.getState(graph.getCellAt(pt.x, pt.y)); result = <mxCellState>graph.view.getState(graph.getCellAt(pt.x, pt.y));
} }
return result; return result;
}; };
mxEvent.addGestureListeners( mxEvent.addGestureListeners(
// @ts-ignore
state.shape.node, state.shape.node,
evt => { (evt: MouseEvent) => {
if (this.isShapeEvent(state, evt)) { if (this.isShapeEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_DOWN, mxEvent.MOUSE_DOWN,
@ -856,15 +878,15 @@ class mxCellRenderer {
); );
} }
}, },
mxUtils.bind(this, evt => { (evt: MouseEvent) => {
if (this.isShapeEvent(state, evt)) { if (this.isShapeEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_MOVE, mxEvent.MOUSE_MOVE,
new mxMouseEvent(evt, getState(evt)) new mxMouseEvent(evt, getState(evt))
); );
} }
}), },
evt => { (evt: MouseEvent) => {
if (this.isShapeEvent(state, evt)) { if (this.isShapeEvent(state, evt)) {
graph.fireMouseEvent( graph.fireMouseEvent(
mxEvent.MOUSE_UP, mxEvent.MOUSE_UP,
@ -876,6 +898,7 @@ class mxCellRenderer {
// Uses double click timeout in mxGraph for quirks mode // Uses double click timeout in mxGraph for quirks mode
if (graph.nativeDblClickEnabled) { if (graph.nativeDblClickEnabled) {
// @ts-ignore
mxEvent.addListener(state.shape.node, 'dblclick', evt => { mxEvent.addListener(state.shape.node, 'dblclick', evt => {
if (this.isShapeEvent(state, evt)) { if (this.isShapeEvent(state, evt)) {
graph.dblClick(evt, state.cell); graph.dblClick(evt, state.cell);
@ -894,7 +917,7 @@ class mxCellRenderer {
* *
* state - <mxCellState> whose label should be redrawn. * state - <mxCellState> whose label should be redrawn.
*/ */
redrawLabel(state, forced) { redrawLabel(state: mxCellState, forced: boolean) {
const { graph } = state.view; const { graph } = state.view;
const value = this.getLabelValue(state); const value = this.getLabelValue(state);
const wrapping = graph.isWrapping(state.cell); const wrapping = graph.isWrapping(state.cell);
@ -946,7 +969,7 @@ class mxCellRenderer {
state.text.apply(state); state.text.apply(state);
// Special case where value is obtained via hook in graph // Special case where value is obtained via hook in graph
state.text.valign = graph.getVerticalAlign(state); state.text.valign = <string>graph.getVerticalAlign(state);
} }
const bounds = this.getLabelBounds(state); const bounds = this.getLabelBounds(state);
@ -956,9 +979,9 @@ class mxCellRenderer {
if ( if (
forced || forced ||
state.text.value !== value || state.text.value !== value ||
state.text.isWrapping !== wrapping || state.text.wrap !== wrapping ||
state.text.overflow !== overflow || state.text.overflow !== overflow ||
state.text.isClipping !== clipping || state.text.clipped !== clipping ||
state.text.scale !== nextScale || state.text.scale !== nextScale ||
state.text.dialect !== dialect || state.text.dialect !== dialect ||
state.text.bounds == null || state.text.bounds == null ||
@ -973,8 +996,10 @@ class mxCellRenderer {
state.text.overflow = overflow; state.text.overflow = overflow;
// Preserves visible state // Preserves visible state
// @ts-ignore
const vis = state.text.node.style.visibility; const vis = state.text.node.style.visibility;
this.redrawLabelShape(state.text); this.redrawLabelShape(state.text);
// @ts-ignore
state.text.node.style.visibility = vis; state.text.node.style.visibility = vis;
} }
} }
@ -990,8 +1015,8 @@ class mxCellRenderer {
* state - <mxCellState> whose label should be checked. * state - <mxCellState> whose label should be checked.
* shape - <mxText> shape to be checked. * shape - <mxText> shape to be checked.
*/ */
isTextShapeInvalid(state: mxCellState, shape) { isTextShapeInvalid(state: mxCellState, shape: mxText): boolean {
function check(property, stylename, defaultValue) { function check(property: string, stylename: string, defaultValue: any) {
let result = false; let result = false;
// Workaround for spacing added to directional spacing // Workaround for spacing added to directional spacing
@ -1002,9 +1027,11 @@ class mxCellRenderer {
stylename === 'spacingLeft' stylename === 'spacingLeft'
) { ) {
result = result =
parseFloat(shape[property]) - parseFloat(shape.spacing) !== // @ts-ignore
parseFloat(String(shape[property])) - parseFloat(String(shape.spacing)) !==
(state.style[stylename] || defaultValue); (state.style[stylename] || defaultValue);
} else { } else {
// @ts-ignore
result = shape[property] !== (state.style[stylename] || defaultValue); result = shape[property] !== (state.style[stylename] || defaultValue);
} }
@ -1032,8 +1059,8 @@ class mxCellRenderer {
check('spacingBottom', mxConstants.STYLE_SPACING_BOTTOM, 0) || check('spacingBottom', mxConstants.STYLE_SPACING_BOTTOM, 0) ||
check('spacingLeft', mxConstants.STYLE_SPACING_LEFT, 0) || check('spacingLeft', mxConstants.STYLE_SPACING_LEFT, 0) ||
check('horizontal', mxConstants.STYLE_HORIZONTAL, true) || check('horizontal', mxConstants.STYLE_HORIZONTAL, true) ||
check('background', mxConstants.STYLE_LABEL_BACKGROUNDCOLOR) || check('background', mxConstants.STYLE_LABEL_BACKGROUNDCOLOR, null) ||
check('border', mxConstants.STYLE_LABEL_BORDERCOLOR) || check('border', mxConstants.STYLE_LABEL_BORDERCOLOR, null) ||
check('opacity', mxConstants.STYLE_TEXT_OPACITY, 100) || check('opacity', mxConstants.STYLE_TEXT_OPACITY, 100) ||
check( check(
'textDirection', 'textDirection',
@ -1088,6 +1115,7 @@ class mxCellRenderer {
); );
if (isEdge) { if (isEdge) {
// @ts-ignore
const spacing = state.text.getSpacing(); const spacing = state.text.getSpacing();
bounds.x += spacing.x * scale; bounds.x += spacing.x * scale;
bounds.y += spacing.y * scale; bounds.y += spacing.y * scale;
@ -1100,6 +1128,7 @@ class mxCellRenderer {
} }
} else { } else {
// Inverts label position // Inverts label position
// @ts-ignore
if (state.text.isPaintBoundsInverted()) { if (state.text.isPaintBoundsInverted()) {
const tmp = bounds.x; const tmp = bounds.x;
bounds.x = bounds.y; bounds.x = bounds.y;
@ -1114,6 +1143,7 @@ class mxCellRenderer {
bounds.height = Math.max(1, state.height); bounds.height = Math.max(1, state.height);
} }
// @ts-ignore
if (state.text.isPaintBoundsInverted()) { if (state.text.isPaintBoundsInverted()) {
// Rotates around center of state // Rotates around center of state
const t = (state.width - state.height) / 2; const t = (state.width - state.height) / 2;
@ -1174,7 +1204,9 @@ class mxCellRenderer {
* bounds - <mxRectangle> the rectangle to be rotated. * bounds - <mxRectangle> the rectangle to be rotated.
*/ */
rotateLabelBounds(state: mxCellState, bounds: mxRectangle) { rotateLabelBounds(state: mxCellState, bounds: mxRectangle) {
// @ts-ignore
bounds.y -= state.text.margin.y * bounds.height; bounds.y -= state.text.margin.y * bounds.height;
// @ts-ignore
bounds.x -= state.text.margin.x * bounds.width; bounds.x -= state.text.margin.x * bounds.width;
if ( if (
@ -1183,6 +1215,7 @@ class mxCellRenderer {
state.style[mxConstants.STYLE_OVERFLOW] !== 'width') state.style[mxConstants.STYLE_OVERFLOW] !== 'width')
) { ) {
const s = state.view.scale; const s = state.view.scale;
// @ts-ignore
const spacing = state.text.getSpacing(); const spacing = state.text.getSpacing();
bounds.x += spacing.x * s; bounds.x += spacing.x * s;
bounds.y += spacing.y * s; bounds.y += spacing.y * s;
@ -1207,6 +1240,7 @@ class mxCellRenderer {
0, 0,
bounds.width - bounds.width -
(hpos === mxConstants.ALIGN_CENTER && lw == null (hpos === mxConstants.ALIGN_CENTER && lw == null
// @ts-ignore
? state.text.spacingLeft * s + state.text.spacingRight * s ? state.text.spacingLeft * s + state.text.spacingRight * s
: 0) : 0)
); );
@ -1214,17 +1248,20 @@ class mxCellRenderer {
0, 0,
bounds.height - bounds.height -
(vpos === mxConstants.ALIGN_MIDDLE (vpos === mxConstants.ALIGN_MIDDLE
// @ts-ignore
? state.text.spacingTop * s + state.text.spacingBottom * s ? state.text.spacingTop * s + state.text.spacingBottom * s
: 0) : 0)
); );
} }
// @ts-ignore
const theta = state.text.getTextRotation(); const theta = state.text.getTextRotation();
// Only needed if rotated around another center // Only needed if rotated around another center
if ( if (
theta !== 0 && theta !== 0 &&
state != null && state != null &&
// @ts-ignore
state.view.graph.model.isVertex(state.cell) state.view.graph.model.isVertex(state.cell)
) { ) {
const cx = state.getCenterX(); const cx = state.getCenterX();
@ -1254,7 +1291,7 @@ class mxCellRenderer {
* *
* state - <mxCellState> whose overlays should be redrawn. * state - <mxCellState> whose overlays should be redrawn.
*/ */
redrawCellOverlays(state, forced) { redrawCellOverlays(state: mxCellState, forced: boolean=false) {
this.createCellOverlays(state); this.createCellOverlays(state);
if (state.overlays != null) { if (state.overlays != null) {
@ -1266,7 +1303,8 @@ class mxCellRenderer {
const cos = Math.cos(rad); const cos = Math.cos(rad);
const sin = Math.sin(rad); const sin = Math.sin(rad);
state.overlays.visit((id, shape) => { state.overlays.visit((id: string, shape: mxShape) => {
// @ts-ignore
const bounds = shape.overlay.getBounds(state); const bounds = shape.overlay.getBounds(state);
if (!state.view.graph.getModel().isEdge(state.cell)) { if (!state.view.graph.getModel().isEdge(state.cell)) {
@ -1311,19 +1349,22 @@ class mxCellRenderer {
* *
* state - <mxCellState> whose control should be redrawn. * state - <mxCellState> whose control should be redrawn.
*/ */
redrawControl(state, forced) { redrawControl(state: mxCellState, forced: boolean=false) {
const image = state.view.graph.getFoldingImage(state); const image = state.view.graph.getFoldingImage(state);
if (state.control != null && image != null) { if (state.control != null && image != null) {
const bounds = this.getControlBounds(state, image.width, image.height); const bounds = this.getControlBounds(state, image.width, image.height);
const r = this.legacyControlPosition const r = this.legacyControlPosition
? mxUtils.getValue(state.style, mxConstants.STYLE_ROTATION, 0) ? mxUtils.getValue(state.style, mxConstants.STYLE_ROTATION, 0)
// @ts-ignore
: state.shape.getTextRotation(); : state.shape.getTextRotation();
const s = state.view.scale; const s = state.view.scale;
if ( if (
forced || forced ||
state.control.scale !== s || state.control.scale !== s ||
// @ts-ignore
!state.control.bounds.equals(bounds) || !state.control.bounds.equals(bounds) ||
state.control.rotation !== r state.control.rotation !== r
) { ) {
@ -1342,7 +1383,7 @@ class mxCellRenderer {
* Returns the bounds to be used to draw the control (folding icon) of the * Returns the bounds to be used to draw the control (folding icon) of the
* given state. * given state.
*/ */
getControlBounds(state, w, h) { getControlBounds(state: mxCellState, w: number, h: number): mxRectangle | null {
if (state.control != null) { if (state.control != null) {
const s = state.view.scale; const s = state.view.scale;
let cx = state.getCenterX(); let cx = state.getCenterX();
@ -1411,60 +1452,77 @@ class mxCellRenderer {
* htmlNode - Node in the graph container after which the shapes should be inserted that * htmlNode - Node in the graph container after which the shapes should be inserted that
* will not go into the <drawPane> (eg. HTML labels without foreignObjects). * will not go into the <drawPane> (eg. HTML labels without foreignObjects).
*/ */
insertStateAfter(state, node, htmlNode) { insertStateAfter(state: mxCellState,
node: HTMLElement | SVGElement | null,
htmlNode: HTMLElement | SVGElement | null) {
const shapes = this.getShapesForState(state); const shapes = this.getShapesForState(state);
for (let i = 0; i < shapes.length; i += 1) { for (let i = 0; i < shapes.length; i += 1) {
// @ts-ignore
if (shapes[i] != null && shapes[i].node != null) { if (shapes[i] != null && shapes[i].node != null) {
const html = const html =
// @ts-ignore
shapes[i].node.parentNode !== state.view.getDrawPane() && shapes[i].node.parentNode !== state.view.getDrawPane() &&
// @ts-ignore
shapes[i].node.parentNode !== state.view.getOverlayPane(); shapes[i].node.parentNode !== state.view.getOverlayPane();
const temp = html ? htmlNode : node; const temp = html ? htmlNode : node;
// @ts-ignore
if (temp != null && temp.nextSibling !== shapes[i].node) { if (temp != null && temp.nextSibling !== shapes[i].node) {
if (temp.nextSibling == null) { if (temp.nextSibling == null) {
// @ts-ignore
temp.parentNode.appendChild(shapes[i].node); temp.parentNode.appendChild(shapes[i].node);
} else { } else {
// @ts-ignore
temp.parentNode.insertBefore(shapes[i].node, temp.nextSibling); temp.parentNode.insertBefore(shapes[i].node, temp.nextSibling);
} }
} else if (temp == null) { } else if (temp == null) {
// Special case: First HTML node should be first sibling after canvas // Special case: First HTML node should be first sibling after canvas
if (shapes[i].node.parentNode === state.view.graph.container) { // @ts-ignore
const shapeNode: HTMLElement = <HTMLElement>shapes[i].node;
if (shapeNode.parentNode === state.view.graph.container) {
let { canvas } = state.view; let { canvas } = state.view;
while ( while (
canvas != null && canvas != null &&
canvas.parentNode !== state.view.graph.container canvas.parentNode !== state.view.graph.container
) { ) {
// @ts-ignore
canvas = canvas.parentNode; canvas = canvas.parentNode;
} }
if (canvas != null && canvas.nextSibling != null) { if (canvas != null && canvas.nextSibling != null) {
if (canvas.nextSibling !== shapes[i].node) { if (canvas.nextSibling !== shapeNode) {
shapes[i].node.parentNode.insertBefore( // @ts-ignore
shapes[i].node, shapeNode.parentNode.insertBefore(
shapeNode,
canvas.nextSibling canvas.nextSibling
); );
} }
} else { } else {
shapes[i].node.parentNode.appendChild(shapes[i].node); // @ts-ignore
shapeNode.parentNode.appendChild(shapeNode);
} }
} else if ( } else if (
shapes[i].node.parentNode != null && shapeNode.parentNode != null &&
shapes[i].node.parentNode.firstChild != null && shapeNode.parentNode.firstChild != null &&
shapes[i].node.parentNode.firstChild != shapes[i].node shapeNode.parentNode.firstChild != shapeNode
) { ) {
// Inserts the node as the first child of the parent to implement the order // Inserts the node as the first child of the parent to implement the order
shapes[i].node.parentNode.insertBefore( shapeNode.parentNode.insertBefore(
shapes[i].node, shapeNode,
shapes[i].node.parentNode.firstChild shapeNode.parentNode.firstChild
); );
} }
} }
if (html) { if (html) {
// @ts-ignore
htmlNode = shapes[i].node; htmlNode = shapes[i].node;
} else { } else {
// @ts-ignore
node = shapes[i].node; node = shapes[i].node;
} }
} }
@ -1567,6 +1625,7 @@ class mxCellRenderer {
this.installListeners(state); this.installListeners(state);
// Forces a refresh of the handler if one exists // Forces a refresh of the handler if one exists
// @ts-ignore
state.view.graph.selectionCellsHandler.updateHandler(state); state.view.graph.selectionCellsHandler.updateHandler(state);
} }
} else if ( } else if (
@ -1578,6 +1637,7 @@ class mxCellRenderer {
state.shape.resetStyles(); state.shape.resetStyles();
this.configureShape(state); this.configureShape(state);
// LATER: Ignore update for realtime to fix reset of current gesture // LATER: Ignore update for realtime to fix reset of current gesture
// @ts-ignore
state.view.graph.selectionCellsHandler.updateHandler(state); state.view.graph.selectionCellsHandler.updateHandler(state);
force = true; force = true;
} }
@ -1586,7 +1646,7 @@ class mxCellRenderer {
if ( if (
state.shape != null && state.shape != null &&
state.shape.indicatorShape != state.shape.indicatorShape !=
this.getShape(state.view.graph.getIndicatorShape(state)) this.getShape(<string>state.view.graph.getIndicatorShape(state))
) { ) {
if (state.shape.indicator != null) { if (state.shape.indicator != null) {
state.shape.indicator.destroy(); state.shape.indicator.destroy();
@ -1680,7 +1740,7 @@ class mxCellRenderer {
} }
if (state.overlays != null) { if (state.overlays != null) {
state.overlays.visit((id, shape) => { state.overlays.visit((id: string, shape: mxShape) => {
shape.destroy(); shape.destroy();
}); });
@ -1699,14 +1759,20 @@ class mxCellRenderer {
} }
// Adds default shapes into the default shapes array // Adds default shapes into the default shapes array
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_RECTANGLE, mxRectangleShape); mxCellRenderer.registerShape(mxConstants.SHAPE_RECTANGLE, mxRectangleShape);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_ELLIPSE, mxEllipse); mxCellRenderer.registerShape(mxConstants.SHAPE_ELLIPSE, mxEllipse);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_RHOMBUS, mxRhombus); mxCellRenderer.registerShape(mxConstants.SHAPE_RHOMBUS, mxRhombus);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_CYLINDER, mxCylinder); mxCellRenderer.registerShape(mxConstants.SHAPE_CYLINDER, mxCylinder);
mxCellRenderer.registerShape(mxConstants.SHAPE_CONNECTOR, mxConnector); mxCellRenderer.registerShape(mxConstants.SHAPE_CONNECTOR, mxConnector);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_ACTOR, mxActor); mxCellRenderer.registerShape(mxConstants.SHAPE_ACTOR, mxActor);
mxCellRenderer.registerShape(mxConstants.SHAPE_TRIANGLE, mxTriangle); mxCellRenderer.registerShape(mxConstants.SHAPE_TRIANGLE, mxTriangle);
mxCellRenderer.registerShape(mxConstants.SHAPE_HEXAGON, mxHexagon); mxCellRenderer.registerShape(mxConstants.SHAPE_HEXAGON, mxHexagon);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_CLOUD, mxCloud); mxCellRenderer.registerShape(mxConstants.SHAPE_CLOUD, mxCloud);
mxCellRenderer.registerShape(mxConstants.SHAPE_LINE, mxLine); mxCellRenderer.registerShape(mxConstants.SHAPE_LINE, mxLine);
mxCellRenderer.registerShape(mxConstants.SHAPE_ARROW, mxArrow); mxCellRenderer.registerShape(mxConstants.SHAPE_ARROW, mxArrow);
@ -1714,8 +1780,10 @@ mxCellRenderer.registerShape(
mxConstants.SHAPE_ARROW_CONNECTOR, mxConstants.SHAPE_ARROW_CONNECTOR,
mxArrowConnector mxArrowConnector
); );
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_DOUBLE_ELLIPSE, mxDoubleEllipse); mxCellRenderer.registerShape(mxConstants.SHAPE_DOUBLE_ELLIPSE, mxDoubleEllipse);
mxCellRenderer.registerShape(mxConstants.SHAPE_SWIMLANE, mxSwimlane); mxCellRenderer.registerShape(mxConstants.SHAPE_SWIMLANE, mxSwimlane);
// @ts-ignore
mxCellRenderer.registerShape(mxConstants.SHAPE_IMAGE, mxImageShape); mxCellRenderer.registerShape(mxConstants.SHAPE_IMAGE, mxImageShape);
mxCellRenderer.registerShape(mxConstants.SHAPE_LABEL, mxLabel); mxCellRenderer.registerShape(mxConstants.SHAPE_LABEL, mxLabel);

View File

@ -61,11 +61,13 @@ class mxConnectionConstraint {
* perimeter - Optional boolean that specifies if the fixed point should be * perimeter - Optional boolean that specifies if the fixed point should be
* projected onto the perimeter of the terminal. Default is true. * projected onto the perimeter of the terminal. Default is true.
*/ */
constructor(point: mxPoint | null=null, constructor(
point: mxPoint | null = null,
perimeter: boolean = true, perimeter: boolean = true,
name: string | null = null, name: string | null = null,
dx: number | null = null, dx: number | null = null,
dy: number | null=null) { dy: number | null = null
) {
this.point = point; this.point = point;
this.perimeter = perimeter != null ? perimeter : true; this.perimeter = perimeter != null ? perimeter : true;
this.name = name; this.name = name;

View File

@ -9094,6 +9094,7 @@ class mxGraph extends mxEventSource {
// @ts-ignore // @ts-ignore
(node === shape.node || node.parentNode === shape.node) (node === shape.node || node.parentNode === shape.node)
) { ) {
// @ts-ignore
tip = shape.overlay.toString(); tip = shape.overlay.toString();
} }
}); });
@ -9423,7 +9424,7 @@ class mxGraph extends mxEventSource {
* *
* state - <mxCellState> whose indicator shape should be returned. * state - <mxCellState> whose indicator shape should be returned.
*/ */
getIndicatorShape(state: mxCellState): mxShape | null { getIndicatorShape(state: mxCellState): string | null {
return state != null && state.style != null return state != null && state.style != null
? state.style[mxConstants.STYLE_INDICATOR_SHAPE] ? state.style[mxConstants.STYLE_INDICATOR_SHAPE]
: null; : null;
@ -11090,7 +11091,7 @@ class mxGraph extends mxEventSource {
* *
* cell - <mxCell> for which the ancestor swimlane should be returned. * cell - <mxCell> for which the ancestor swimlane should be returned.
*/ */
getSwimlane(cell: mxCell): mxCell | null { getSwimlane(cell: mxCell | null=null): mxCell | null {
while (cell != null && !this.isSwimlane(cell)) { while (cell != null && !this.isSwimlane(cell)) {
cell = <mxCell>this.getModel().getParent(cell); cell = <mxCell>this.getModel().getParent(cell);
} }

View File

@ -31,7 +31,63 @@ import mxGeometry from "../../util/datatypes/mxGeometry";
import mxConnectionConstraint from "../connection/mxConnectionConstraint"; import mxConnectionConstraint from "../connection/mxConnectionConstraint";
import mxPopupMenuHandler from "../../handler/mxPopupMenuHandler"; import mxPopupMenuHandler from "../../handler/mxPopupMenuHandler";
/**
* Class: mxGraphView
*
* Extends <mxEventSource> to implement a view for a graph. This class is in
* charge of computing the absolute coordinates for the relative child
* geometries, the points for perimeters and edge styles and keeping them
* cached in <mxCellStates> for faster retrieval. The states are updated
* whenever the model or the view state (translate, scale) changes. The scale
* and translate are honoured in the bounds.
*
* Event: mxEvent.UNDO
*
* Fires after the root was changed in <setCurrentRoot>. The <code>edit</code>
* property contains the <mxUndoableEdit> which contains the
* <mxCurrentRootChange>.
*
* Event: mxEvent.SCALE_AND_TRANSLATE
*
* Fires after the scale and translate have been changed in <scaleAndTranslate>.
* The <code>scale</code>, <code>previousScale</code>, <code>translate</code>
* and <code>previousTranslate</code> properties contain the new and previous
* scale and translate, respectively.
*
* Event: mxEvent.SCALE
*
* Fires after the scale was changed in <setScale>. The <code>scale</code> and
* <code>previousScale</code> properties contain the new and previous scale.
*
* Event: mxEvent.TRANSLATE
*
* Fires after the translate was changed in <setTranslate>. The
* <code>translate</code> and <code>previousTranslate</code> properties contain
* the new and previous value for translate.
*
* Event: mxEvent.DOWN and mxEvent.UP
*
* Fire if the current root is changed by executing an <mxCurrentRootChange>.
* The event name depends on the location of the root in the cell hierarchy
* with respect to the current root. The <code>root</code> and
* <code>previous</code> properties contain the new and previous root,
* respectively.
*
* Constructor: mxGraphView
*
* Constructs a new view for the given <mxGraph>.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
*/
class mxGraphView extends mxEventSource { class mxGraphView extends mxEventSource {
constructor(graph: mxGraph) {
super();
this.graph = graph;
}
// TODO: Document me! // TODO: Document me!
backgroundImage: mxImageShape | null=null; backgroundImage: mxImageShape | null=null;
@ -138,89 +194,31 @@ class mxGraphView extends mxEventSource {
* *
* During validation, this contains the last DOM node that was processed. * During validation, this contains the last DOM node that was processed.
*/ */
lastNode: HTMLElement | null = null; lastNode: HTMLElement | SVGElement | null = null;
/** /**
* Variable: lastHtmlNode * Variable: lastHtmlNode
* *
* During validation, this contains the last HTML DOM node that was processed. * During validation, this contains the last HTML DOM node that was processed.
*/ */
lastHtmlNode: HTMLElement | null = null; lastHtmlNode: HTMLElement | SVGElement | null = null;
/** /**
* Variable: lastForegroundNode * Variable: lastForegroundNode
* *
* During validation, this contains the last edge's DOM node that was processed. * During validation, this contains the last edge's DOM node that was processed.
*/ */
lastForegroundNode: HTMLElement | null = null; lastForegroundNode: HTMLElement | SVGElement | null = null;
/** /**
* Variable: lastForegroundHtmlNode * Variable: lastForegroundHtmlNode
* *
* During validation, this contains the last edge HTML DOM node that was processed. * During validation, this contains the last edge HTML DOM node that was processed.
*/ */
lastForegroundHtmlNode: HTMLElement | null = null; lastForegroundHtmlNode: HTMLElement | SVGElement | null = null;
/** /**
* Class: mxGraphView * Function: getGraphBounds
*
* Extends <mxEventSource> to implement a view for a graph. This class is in
* charge of computing the absolute coordinates for the relative child
* geometries, the points for perimeters and edge styles and keeping them
* cached in <mxCellStates> for faster retrieval. The states are updated
* whenever the model or the view state (translate, scale) changes. The scale
* and translate are honoured in the bounds.
*
* Event: mxEvent.UNDO
*
* Fires after the root was changed in <setCurrentRoot>. The <code>edit</code>
* property contains the <mxUndoableEdit> which contains the
* <mxCurrentRootChange>.
*
* Event: mxEvent.SCALE_AND_TRANSLATE
*
* Fires after the scale and translate have been changed in <scaleAndTranslate>.
* The <code>scale</code>, <code>previousScale</code>, <code>translate</code>
* and <code>previousTranslate</code> properties contain the new and previous
* scale and translate, respectively.
*
* Event: mxEvent.SCALE
*
* Fires after the scale was changed in <setScale>. The <code>scale</code> and
* <code>previousScale</code> properties contain the new and previous scale.
*
* Event: mxEvent.TRANSLATE
*
* Fires after the translate was changed in <setTranslate>. The
* <code>translate</code> and <code>previousTranslate</code> properties contain
* the new and previous value for translate.
*
* Event: mxEvent.DOWN and mxEvent.UP
*
* Fire if the current root is changed by executing an <mxCurrentRootChange>.
* The event name depends on the location of the root in the cell hierarchy
* with respect to the current root. The <code>root</code> and
* <code>previous</code> properties contain the new and previous root,
* respectively.
*
* Constructor: mxGraphView
*
* Constructs a new view for the given <mxGraph>.
*
* Parameters:
*
* graph - Reference to the enclosing <mxGraph>.
*/
constructor(graph: mxGraph) {
super();
this.graph = graph;
}
// Backwards compatibility getters/setters
/**
* Function: get graphBounds
* *
* Returns the <mxRectangle> that caches the scales and translated bounds of the current view. * Returns the <mxRectangle> that caches the scales and translated bounds of the current view.
*/ */
@ -238,7 +236,7 @@ class mxGraphView extends mxEventSource {
} }
/** /**
* Function: get scale * Function: getScale
* *
* Returns the <scale>. Default is 1 (100%). * Returns the <scale>. Default is 1 (100%).
*/ */
@ -663,11 +661,6 @@ class mxGraphView extends mxEventSource {
mxLog.leave('mxGraphView.validate', t0); mxLog.leave('mxGraphView.validate', t0);
} }
// TODO: Document me!!
get emptyBounds() {
return this.getEmptyBounds();
}
/** /**
* Function: getEmptyBounds * Function: getEmptyBounds
* *
@ -858,11 +851,6 @@ class mxGraphView extends mxEventSource {
} }
} }
// TODO: Document me!!
get backgroundPageBounds(): mxRectangle {
return this.getBackgroundPageBounds();
}
/** /**
* Function: getBackgroundPageBounds * Function: getBackgroundPageBounds
* *

View File

@ -602,7 +602,8 @@ class mxOutline {
: null; : null;
this.zoom = this.zoom =
me.isSource(this.sizer) || me.isSource(this.sizer) ||
(hit != null && mxUtils.intersects(shape.bounds, hit)); // @ts-ignore
(hit != null && mxUtils.intersects(this.sizer.bounds, hit));
this.startX = me.getX(); this.startX = me.getX();
this.startY = me.getY(); this.startY = me.getY();
this.active = true; this.active = true;

View File

@ -41,7 +41,12 @@ const PageTabs = ({ curPageURL, children }) => {
}} }}
> >
<h1>mxGraph Reloaded Examples</h1> <h1>mxGraph Reloaded Examples</h1>
<div style={{textAlign: "right"}}>See also the <a href="https://github.com/mcyph/mxgraph" style={{color: "blue"}}>GitHub repo</a></div> <div style={{ textAlign: 'right' }}>
See also the{' '}
<a href="https://github.com/mcyph/mxgraph" style={{ color: 'blue' }}>
GitHub repo
</a>
</div>
<ul className="pagetabs">{tabs}</ul> <ul className="pagetabs">{tabs}</ul>
{children} {children}
</div> </div>

View File

@ -84,9 +84,7 @@ class ExtendCanvas extends React.Component {
* page count. * page count.
*/ */
getPageLayout() { getPageLayout() {
const size = this.pageVisible const size = this.pageVisible ? this.getPageSize() : scrollTileSize;
? this.getPageSize()
: scrollTileSize;
const bounds = this.getGraphBounds(); const bounds = this.getGraphBounds();
if (bounds.width === 0 || bounds.height === 0) { if (bounds.width === 0 || bounds.height === 0) {
@ -172,7 +170,7 @@ class ExtendCanvas extends React.Component {
} }
// Creates the graph inside the given container // Creates the graph inside the given container
const graph = this.graph = new MyCustomGraph(this.el); const graph = (this.graph = new MyCustomGraph(this.el));
graph.panningHandler.ignoreCell = true; graph.panningHandler.ignoreCell = true;
graph.setPanning(true); graph.setPanning(true);

View File

@ -2,7 +2,7 @@ import React from 'react';
import Grid from './Grid'; import Grid from './Grid';
import Preview from '../Previews'; import Preview from '../Previews';
import ExtendCanvas from './ExtendCanvas'; import ExtendCanvas from './ExtendCanvas';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Backgrounds() { export default function _Backgrounds() {
return ( return (

View File

@ -34,7 +34,7 @@ class HelloWorld extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Create a sample graph in the DOM node with the specified ID. // Create a sample graph in the DOM node with the specified ID.
@ -69,7 +69,7 @@ class HelloWorld extends React.Component {
target: vertex2, target: vertex2,
}); });
}); });
}; }
} }
export default HelloWorld; export default HelloWorld;

View File

@ -1,9 +1,15 @@
import React from 'react'; import React from 'react';
import HelloWorld from "./HelloWorld"; import HelloWorld from './HelloWorld';
import Preview from "../Previews"; import Preview from '../Previews';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Basic() { export default function _Basic() {
{/* <Preview sourceKey="Template" content={<Template />} /> */} {
return <PageTabs curPageURL="/basic"><Preview sourceKey="HelloWorld" content={<HelloWorld />} /></PageTabs>; /* <Preview sourceKey="Template" content={<Template />} /> */
}
return (
<PageTabs curPageURL="/basic">
<Preview sourceKey="HelloWorld" content={<HelloWorld />} />
</PageTabs>
);
} }

View File

@ -12,8 +12,8 @@ import mxConnectionConstraint from '../../mxgraph/view/connection/mxConnectionCo
import mxPoint from '../../mxgraph/util/datatypes/mxPoint'; import mxPoint from '../../mxgraph/util/datatypes/mxPoint';
import mxPolyline from '../../mxgraph/shape/edge/mxPolyline'; import mxPolyline from '../../mxgraph/shape/edge/mxPolyline';
import mxCellState from '../../mxgraph/util/datatypes/mxCellState'; import mxCellState from '../../mxgraph/util/datatypes/mxCellState';
import mxGeometry from "../../mxgraph/util/datatypes/mxGeometry"; import mxGeometry from '../../mxgraph/util/datatypes/mxGeometry';
import mxConnectionHandler from "../../mxgraph/handler/mxConnectionHandler"; import mxConnectionHandler from '../../mxgraph/handler/mxConnectionHandler';
class Anchors extends React.Component { class Anchors extends React.Component {
constructor(props) { constructor(props) {
@ -41,7 +41,7 @@ class Anchors extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Disables the built-in context menu // Disables the built-in context menu

View File

@ -40,7 +40,7 @@ class FixedPoints extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Snaps to fixed points // Snaps to fixed points
@ -259,7 +259,7 @@ class FixedPoints extends React.Component {
return result; return result;
}; };
*/ */
}; }
} }
export default FixedPoints; export default FixedPoints;

View File

@ -6,7 +6,7 @@ import FixedPoints from './FixedPoints';
import HelloPort from './HelloPort'; import HelloPort from './HelloPort';
import Orthogonal from './Orthogonal'; import Orthogonal from './Orthogonal';
import PortRefs from './PortRefs'; import PortRefs from './PortRefs';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Connections() { export default function _Connections() {
return ( return (

View File

@ -35,7 +35,7 @@ class DragSource extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
class MyCustomGuide extends mxGuide { class MyCustomGuide extends mxGuide {
@ -183,7 +183,7 @@ class DragSource extends React.Component {
// Restores original drag icon while outside of graph // Restores original drag icon while outside of graph
ds.createDragElement = mxDragSource.prototype.createDragElement; ds.createDragElement = mxDragSource.prototype.createDragElement;
}; }
// NOTE: To enable cross-document DnD (eg. between frames), // NOTE: To enable cross-document DnD (eg. between frames),
// the following methods need to be overridden: // the following methods need to be overridden:

View File

@ -3,7 +3,7 @@ import Preview from '../Previews';
import Clipboard from './Clipboard'; import Clipboard from './Clipboard';
import DragSource from './DragSource'; import DragSource from './DragSource';
import Drop from './Drop'; import Drop from './Drop';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _DnDCopyPaste() { export default function _DnDCopyPaste() {
return ( return (

View File

@ -1,8 +1,12 @@
import React from 'react'; import React from 'react';
import Preview from "../Previews"; import Preview from '../Previews';
import Editing from "./Editing"; import Editing from './Editing';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Editing() { export default function _Editing() {
return <PageTabs curPageURL="/editing"><Preview sourceKey="Editing" content={<Editing />} /></PageTabs>; return (
<PageTabs curPageURL="/editing">
<Preview sourceKey="Editing" content={<Editing />} />
</PageTabs>
);
} }

View File

@ -33,7 +33,7 @@ class Animation extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
const graph = new mxGraph(this.el); const graph = new mxGraph(this.el);
@ -88,7 +88,7 @@ class Animation extends React.Component {
state.shape.node state.shape.node
.getElementsByTagName('path')[1] .getElementsByTagName('path')[1]
.setAttribute('class', 'flow'); .setAttribute('class', 'flow');
}; }
} }
export default Animation; export default Animation;

View File

@ -3,7 +3,7 @@ import Animation from './Animation';
import Preview from '../Previews'; import Preview from '../Previews';
import Morph from './Morph'; import Morph from './Morph';
import Overlays from './Overlays'; import Overlays from './Overlays';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function Effects() { export default function Effects() {
return ( return (

View File

@ -37,7 +37,7 @@ class Boundary extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Disables the built-in context menu // Disables the built-in context menu
@ -231,7 +231,7 @@ class Boundary extends React.Component {
v3.geometry.offset = new mxPoint(-10, -10); v3.geometry.offset = new mxPoint(-10, -10);
v3.geometry.relative = true; v3.geometry.relative = true;
}); });
}; }
} }
export default Boundary; export default Boundary;

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import Boundary from './Boundary'; import Boundary from './Boundary';
import Preview from '../Previews'; import Preview from '../Previews';
import Events from "./Events"; import Events from './Events';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Events() { export default function _Events() {
return ( return (

View File

@ -42,7 +42,7 @@ class Control extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Specifies the URL and size of the new control // Specifies the URL and size of the new control
@ -197,7 +197,7 @@ class Control extends React.Component {
graph.zoomOut(); graph.zoomOut();
}) })
); );
}; }
} }
export default Control; export default Control;

View File

@ -37,7 +37,7 @@ class FixedIcon extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Overrides the image bounds code to change the position // Overrides the image bounds code to change the position
@ -95,7 +95,7 @@ class FixedIcon extends React.Component {
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
} }
}; }
} }
export default FixedIcon; export default FixedIcon;

View File

@ -7,7 +7,7 @@ import HoverIcons from './HoverIcons';
import Images from './Images'; import Images from './Images';
import Indicators from './Indicators'; import Indicators from './Indicators';
import Markers from './Markers'; import Markers from './Markers';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Backgrounds() { export default function _Backgrounds() {
return ( return (

View File

@ -1,8 +1,8 @@
import Head from 'next/head'; import Head from 'next/head';
import Link from 'next/link'; import Link from 'next/link';
import styles from '../styles/Home.module.css'; import styles from '../styles/Home.module.css';
import PageTabs from "./PageTabs"; import PageTabs from './PageTabs';
import Basic from "./basic"; import Basic from './basic';
export default function Home() { export default function Home() {
return <Basic />; return <Basic />;

View File

@ -5,7 +5,7 @@ import Perimeter from './Perimeter';
import SecondLabel from './SecondLabel'; import SecondLabel from './SecondLabel';
import Wrapping from './Wrapping'; import Wrapping from './Wrapping';
import Labels from './Labels'; import Labels from './Labels';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Labels() { export default function _Labels() {
return ( return (

View File

@ -34,7 +34,7 @@ class Constituent extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Disables the built-in context menu // Disables the built-in context menu

View File

@ -36,7 +36,7 @@ class Folding extends React.Component {
/> />
</> </>
); );
}; }
componentDidMount() { componentDidMount() {
// Enables crisp rendering of rectangles in SVG // Enables crisp rendering of rectangles in SVG
@ -151,7 +151,7 @@ class Folding extends React.Component {
// Updates the display // Updates the display
graph.getModel().endUpdate(); graph.getModel().endUpdate();
} }
}; }
} }
export default Folding; export default Folding;

View File

@ -11,7 +11,7 @@ import OrgChart from './OrgChart';
import RadialTreeLayout from './RadialTreeLayout'; import RadialTreeLayout from './RadialTreeLayout';
import SwimLanes from './SwimLanes'; import SwimLanes from './SwimLanes';
import Tree from './Tree'; import Tree from './Tree';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Layout() { export default function _Layout() {
return ( return (

View File

@ -7,7 +7,7 @@ import Permissions from './Permissions';
import Thread from './Thread'; import Thread from './Thread';
import Validation from './Validation'; import Validation from './Validation';
import Visibility from './Visibility'; import Visibility from './Visibility';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Misc() { export default function _Misc() {
return ( return (

View File

@ -1,8 +1,10 @@
import React from 'react'; import React from 'react';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Printing() { export default function _Printing() {
return ( return (
<PageTabs curPageURL="/printing">{/* <Preview sourceKey="PageBreaks" content={<PageBreaks />} /> */}</PageTabs> <PageTabs curPageURL="/printing">
{/* <Preview sourceKey="PageBreaks" content={<PageBreaks />} /> */}
</PageTabs>
); );
} }

View File

@ -1,8 +1,8 @@
import React from 'react'; import React from 'react';
import Preview from '../Previews'; import Preview from '../Previews';
import Shape from './Shape'; import Shape from './Shape';
import Stencils from "./Stencils"; import Stencils from './Stencils';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _ShapesStencils() { export default function _ShapesStencils() {
return ( return (

View File

@ -7,7 +7,7 @@ import React from 'react';
import mxGraph from '../../mxgraph/view/graph/mxGraph'; import mxGraph from '../../mxgraph/view/graph/mxGraph';
import mxRubberband from '../../mxgraph/handler/mxRubberband'; import mxRubberband from '../../mxgraph/handler/mxRubberband';
import mxConstants from '../../mxgraph/util/mxConstants'; import mxConstants from '../../mxgraph/util/mxConstants';
import mxUtils from "../../mxgraph/util/mxUtils"; import mxUtils from '../../mxgraph/util/mxUtils';
class HoverStyle extends React.Component { class HoverStyle extends React.Component {
constructor(props) { constructor(props) {

View File

@ -3,7 +3,7 @@ import Preview from '../Previews';
import DynamicStyle from './DynamicStyle'; import DynamicStyle from './DynamicStyle';
import HoverStyle from './HoverStyle'; import HoverStyle from './HoverStyle';
import Stylesheet from './Stylesheet'; import Stylesheet from './Stylesheet';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Styles() { export default function _Styles() {
return ( return (

View File

@ -2,7 +2,7 @@ import React from 'react';
import Preview from '../Previews'; import Preview from '../Previews';
import DynamicToolbar from './DynamicToolbar'; import DynamicToolbar from './DynamicToolbar';
import Toolbar from './Toolbar'; import Toolbar from './Toolbar';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Toolbars() { export default function _Toolbars() {
return ( return (

View File

@ -1,8 +1,12 @@
import React from 'react'; import React from 'react';
import Windows from "./Windows"; import Windows from './Windows';
import Preview from "../Previews"; import Preview from '../Previews';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _Windows() { export default function _Windows() {
return <PageTabs curPageURL="/windows"><Preview sourceKey="Windows" content={<Windows />} /></PageTabs>; return (
<PageTabs curPageURL="/windows">
<Preview sourceKey="Windows" content={<Windows />} />
</PageTabs>
);
} }

View File

@ -3,7 +3,7 @@ import Preview from '../Previews';
import JsonData from './JsonData'; import JsonData from './JsonData';
import Resources from './Resources'; import Resources from './Resources';
import UserObject from './UserObject'; import UserObject from './UserObject';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _XMLJSON() { export default function _XMLJSON() {
return ( return (

View File

@ -2,7 +2,7 @@ import React from 'react';
import Preview from '../Previews'; import Preview from '../Previews';
import LOD from './LOD'; import LOD from './LOD';
import OffPage from './OffPage'; import OffPage from './OffPage';
import PageTabs from "../PageTabs"; import PageTabs from '../PageTabs';
export default function _ZoomOffpage() { export default function _ZoomOffpage() {
return ( return (

View File

@ -4,50 +4,38 @@
* Defines the startup sequence of the application. * Defines the startup sequence of the application.
*/ */
{ {
/** /**
* Constructs a new application (returns an mxEditor instance) * Constructs a new application (returns an mxEditor instance)
*/ */
function createEditor(config) function createEditor(config) {
{
let editor = null; let editor = null;
let hideSplash = function() const hideSplash = function() {
{
// Fades-out the splash screen // Fades-out the splash screen
let splash = document.getElementById('splash'); const splash = document.getElementById('splash');
if (splash != null) if (splash != null) {
{ try {
try
{
mxEvent.release(splash); mxEvent.release(splash);
mxEffects.fadeOut(splash, 100, true); mxEffects.fadeOut(splash, 100, true);
} } catch (e) {
catch (e)
{
splash.parentNode.removeChild(splash); splash.parentNode.removeChild(splash);
} }
} }
}; };
try try {
{ if (!mxClient.isBrowserSupported()) {
if (!mxClient.isBrowserSupported())
{
mxUtils.error('Browser is not supported!', 200, false); mxUtils.error('Browser is not supported!', 200, false);
} } else {
else
{
mxObjectCodec.allowEval = true; mxObjectCodec.allowEval = true;
let node = mxUtils.load(config).getDocumentElement(); const node = mxUtils.load(config).getDocumentElement();
editor = new mxEditor(node); editor = new mxEditor(node);
mxObjectCodec.allowEval = false; mxObjectCodec.allowEval = false;
// Adds active border for panning inside the container // Adds active border for panning inside the container
editor.graph.createPanningManager = function() editor.graph.createPanningManager = function() {
{ const pm = new mxPanningManager(this);
let pm = new mxPanningManager(this);
pm.border = 30; pm.border = 30;
return pm; return pm;
@ -57,10 +45,9 @@
editor.graph.timerAutoScroll = true; editor.graph.timerAutoScroll = true;
// Updates the window title after opening new files // Updates the window title after opening new files
let title = document.title; const { title } = document;
let funct = function(sender) const funct = function(sender) {
{ document.title = `${title} - ${sender.getTitle()}`;
document.title = title + ' - ' + sender.getTitle();
}; };
editor.addListener(mxEvent.OPEN, funct); editor.addListener(mxEvent.OPEN, funct);
@ -71,22 +58,19 @@
funct(editor); funct(editor);
// Displays version in statusbar // Displays version in statusbar
editor.setStatus('mxGraph '+mxClient.VERSION); editor.setStatus(`mxGraph ${mxClient.VERSION}`);
// Shows the application // Shows the application
hideSplash(); hideSplash();
} }
} } catch (e) {
catch (e)
{
hideSplash(); hideSplash();
// Shows an error message if the editor cannot start // Shows an error message if the editor cannot start
mxUtils.alert('Cannot start application: ' + e.message); mxUtils.alert(`Cannot start application: ${e.message}`);
throw e; // for debugging throw e; // for debugging
} }
return editor; return editor;
} }
} }

View File

@ -6,6 +6,7 @@
"esModuleInterop": true, "esModuleInterop": true,
"isolatedModules": true, "isolatedModules": true,
"jsx": "react-native", "jsx": "react-native",
"module": "es2020",
"lib": ["es2020", "dom"], "lib": ["es2020", "dom"],
"moduleResolution": "node", "moduleResolution": "node",
"noEmit": true, "noEmit": true,