Merge remote-tracking branch 'junsik/development'

# Conflicts:
#	packages/core/src/atomic_changes/mxSelectionChange.ts
#	packages/core/src/view/cell/mxCell.ts
#	packages/core/src/view/cell/mxCellArray.ts
#	packages/core/src/view/connection/mxMultiplicity.ts
#	packages/core/src/view/graph/mxGraph.ts
#	packages/core/src/view/graph/mxGraphModel.ts
development
mcyph 2021-06-05 17:48:31 +10:00
commit 55be71c4ef
48 changed files with 4372 additions and 4339 deletions

20
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,20 @@
**Summary**
<!--
What existing issue does the pull request solve?
Please provide enough information so that others can review your pull request
-->
**Description for the changelog**
<!--
A short (one line) summary that describes the changes in this
pull request for inclusion in the change log
If this is a bug fix, your description should include "fixes #xxxx", or
"closes #xxxx", where #xxxx is the issue number
-->
**Other info**
<!--
Thanks for submitting a pull request!
Please make sure you read github's contributing guidelines;
https://docs.github.com/en/desktop/installing-and-configuring-github-desktop/getting-started-with-github-desktop#part-3-contributing-to-projects-with-github-desktop
-->

76
CODE_OF_CONDUCT.md Normal file
View File

@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team via jon.gadsden@owasp.org. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

View File

@ -1,3 +1,8 @@
import { isNullish } from '../util/mxUtils';
import mxCell from '../view/cell/mxCell';
import type { UndoableChange } from '../types';
/**
* Class: mxCellAttributeChange
*
@ -30,8 +35,13 @@
* Constructs a change of a attribute of the DOM node
* stored as the value of the given {@link mxCell}`.
*/
class mxCellAttributeChange {
constructor(cell, attribute, value) {
class mxCellAttributeChange implements UndoableChange {
cell: mxCell;
attribute: string;
value: any;
previous: any;
constructor(cell: mxCell, attribute: string, value: any) {
this.cell = cell;
this.attribute = attribute;
this.value = value;
@ -46,19 +56,16 @@ class mxCellAttributeChange {
*/
// execute(): void;
execute() {
if (this.cell != null) {
const tmp = this.cell.getAttribute(this.attribute);
const tmp = this.cell.getAttribute(this.attribute);
if (this.previous == null) {
this.cell.value.removeAttribute(this.attribute);
} else {
this.cell.setAttribute(this.attribute, this.previous);
}
this.previous = tmp;
if (isNullish(this.previous)) {
this.cell.value.removeAttribute(this.attribute);
} else {
this.cell.setAttribute(this.attribute, this.previous);
}
this.previous = tmp;
}
}
export default mxCellAttributeChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -1,3 +1,8 @@
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
import mxCell from '../view/cell/mxCell';
/**
* Action to add or remove a child in a model.
*
@ -8,8 +13,20 @@
*
* @class mxChildChange
*/
class mxChildChange {
constructor(model, parent, child, index) {
class mxChildChange implements UndoableChange {
model: mxGraphModel;
parent: mxCell | null;
child: mxCell;
previous: mxCell | null;
index: number;
previousIndex: number;
constructor(
model: mxGraphModel,
parent: mxCell | null,
child: mxCell,
index: number = 0
) {
this.model = model;
this.parent = parent;
this.previous = parent;
@ -24,31 +41,28 @@ class mxChildChange {
* removes or restores the cell's
* connections.
*/
// execute(): void;
execute() {
if (this.child != null) {
let tmp = this.child.getParent();
const tmp2 = tmp != null ? tmp.getIndex(this.child) : 0;
let tmp = this.child.getParent();
const tmp2 = tmp ? tmp.getIndex(this.child) : 0;
if (this.previous == null) {
this.connect(this.child, false);
}
tmp = this.model.parentForCellChanged(
this.child,
this.previous,
this.previousIndex
);
if (this.previous != null) {
this.connect(this.child, true);
}
this.parent = this.previous;
this.previous = tmp;
this.index = this.previousIndex;
this.previousIndex = tmp2;
if (!this.previous) {
this.connect(this.child, false);
}
tmp = this.model.parentForCellChanged(
this.child,
this.previous,
this.previousIndex
);
if (this.previous) {
this.connect(this.child, true);
}
this.parent = this.previous;
this.previous = tmp;
this.index = this.previousIndex;
this.previousIndex = tmp2;
}
/**
@ -58,14 +72,11 @@ class mxChildChange {
*
* @warning doc from mxGraph source code is incorrect
*/
// connect(cell: mxCell, isConnect: boolean): void;
connect(cell, isConnect) {
isConnect = isConnect != null ? isConnect : true;
connect(cell: mxCell, isConnect: boolean = true) {
const source = cell.getTerminal(true);
const target = cell.getTerminal(false);
if (source != null) {
if (source) {
if (isConnect) {
this.model.terminalForCellChanged(cell, source, true);
} else {
@ -73,7 +84,7 @@ class mxChildChange {
}
}
if (target != null) {
if (target) {
if (isConnect) {
this.model.terminalForCellChanged(cell, target, false);
} else {
@ -93,4 +104,3 @@ class mxChildChange {
}
export default mxChildChange;
// import('../serialization/mxChildChangeCodec');

View File

@ -1,3 +1,8 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Class: mxCollapseChange
*
@ -8,8 +13,13 @@
* Constructs a change of a collapsed state in the
* specified model.
*/
class mxCollapseChange {
constructor(model, cell, collapsed) {
class mxCollapseChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
collapsed: boolean;
previous: boolean;
constructor(model: mxGraphModel, cell: mxCell, collapsed: boolean) {
this.model = model;
this.cell = cell;
this.collapsed = collapsed;
@ -22,17 +32,13 @@ class mxCollapseChange {
* Changes the collapsed state of {@link cell}` to {@link previous}` using
* <mxGraphModel.collapsedStateForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.collapsed = this.previous;
this.previous = this.model.collapsedStateForCellChanged(
this.cell,
this.previous
);
}
this.collapsed = this.previous;
this.previous = this.model.collapsedStateForCellChanged(
this.cell,
this.previous
);
}
}
export default mxCollapseChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -3,26 +3,30 @@ import mxEventObject from '../util/event/mxEventObject';
import mxPoint from '../util/datatypes/mxPoint';
import mxCell from '../view/cell/mxCell';
import mxEvent from '../util/event/mxEvent';
import mxGraphModel from '../view/graph/mxGraphModel';
import mxGraph from "../view/graph/mxGraph";
import type { UndoableChange } from '../types';
/**
* Class: mxCurrentRootChange
*
* Action to change the current root in a view.
*/
class mxCurrentRootChange {
constructor(view: mxGraphView, root: mxCell) {
class mxCurrentRootChange implements UndoableChange {
view: mxGraphView;
root: mxCell | null;
previous: mxCell | null;
isUp: boolean;
constructor(view: mxGraphView, root: mxCell | null) {
this.view = view;
this.root = root;
this.previous = root;
this.isUp = root == null;
this.isUp = root === null;
if (!this.isUp) {
let tmp: mxCell | null = this.view.currentRoot;
const model: mxGraphModel = (<mxGraph>this.view.graph).getModel();
let tmp = this.view.currentRoot;
while (tmp != null) {
while (tmp) {
if (tmp === root) {
this.isUp = true;
break;
@ -32,28 +36,19 @@ class mxCurrentRootChange {
}
}
view: mxGraphView;
root: mxCell;
previous: mxCell;
isUp: boolean;
/**
* Changes the current root of the view.
*/
// execute(): void;
execute(): void {
execute() {
const tmp = this.view.currentRoot;
this.view.currentRoot = this.previous;
this.previous = <mxCell>tmp;
this.previous = tmp;
const translate = (<mxGraph>this.view.graph).getTranslateForRoot(
const translate = this.view.graph.getTranslateForRoot(
this.view.currentRoot
);
if (translate != null) {
if (translate) {
this.view.translate = new mxPoint(-translate.x, -translate.y);
}
@ -64,7 +59,7 @@ class mxCurrentRootChange {
this.view.refresh();
}
const name: string = this.isUp ? mxEvent.UP : mxEvent.DOWN;
const name = this.isUp ? mxEvent.UP : mxEvent.DOWN;
this.view.fireEvent(
new mxEventObject(
@ -75,6 +70,7 @@ class mxCurrentRootChange {
this.previous
)
);
this.isUp = !this.isUp;
}
}

View File

@ -1,38 +0,0 @@
/**
* Class: mxGeometryChange
*
* Action to change a cell's geometry in a model.
*
* Constructor: mxGeometryChange
*
* Constructs a change of a geometry in the
* specified model.
*/
class mxGeometryChange {
constructor(model, cell, geometry) {
this.model = model;
this.cell = cell;
this.geometry = geometry;
this.previous = geometry;
}
/**
* Function: execute
*
* Changes the geometry of {@link cell}` ro {@link previous}` using
* <mxGraphModel.geometryForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.geometry = this.previous;
this.previous = this.model.geometryForCellChanged(
this.cell,
this.previous
);
}
}
}
export default mxGeometryChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -0,0 +1,42 @@
import mxGeometry from '../util/datatypes/mxGeometry';
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Class: mxGeometryChange
*
* Action to change a cell's geometry in a model.
*
* Constructor: mxGeometryChange
*
* Constructs a change of a geometry in the
* specified model.
*/
class mxGeometryChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
geometry: mxGeometry | null;
previous: mxGeometry | null;
constructor(model: mxGraphModel, cell: mxCell, geometry: mxGeometry | null) {
this.model = model;
this.cell = cell;
this.geometry = geometry;
this.previous = geometry;
}
/**
* Function: execute
*
* Changes the geometry of {@link cell}` ro {@link previous}` using
* <mxGraphModel.geometryForCellChanged>.
*/
execute() {
this.geometry = this.previous;
this.previous = this.model.geometryForCellChanged(this.cell, this.previous);
}
}
export default mxGeometryChange;

View File

@ -1,3 +1,8 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Action to change the root in a model.
*
@ -8,8 +13,12 @@
*
* @class mxRootChange
*/
class mxRootChange {
constructor(model, root) {
class mxRootChange implements UndoableChange {
model: mxGraphModel;
root: mxCell | null;
previous: mxCell | null;
constructor(model: mxGraphModel, root: mxCell | null) {
this.model = model;
this.root = root;
this.previous = root;
@ -19,7 +28,6 @@ class mxRootChange {
* Carries out a change of the root using
* <mxGraphModel.rootChanged>.
*/
// execute(): void;
execute() {
this.root = this.previous;
this.previous = this.model.rootChanged(this.previous);
@ -27,4 +35,3 @@ class mxRootChange {
}
export default mxRootChange;
// import('../serialization/mxRootChangeCodec');

View File

@ -6,11 +6,13 @@ import mxGraphSelectionModel from '../view/graph/mxGraphSelectionModel';
import mxCell from '../view/cell/mxCell';
import mxCellArray from "../view/cell/mxCellArray";
import type { UndoableChange } from '../types';
/**
* @class mxSelectionChange
* Action to change the current root in a view.
*/
class mxSelectionChange {
class mxSelectionChange implements UndoableChange {
constructor(
selectionModel: mxGraphSelectionModel,
added: mxCellArray = new mxCellArray(),
@ -30,7 +32,6 @@ class mxSelectionChange {
/**
* Changes the current root of the view.
*/
// execute(): void;
execute() {
const t0: any = mxLog.enter('mxSelectionChange.execute');
@ -38,16 +39,12 @@ class mxSelectionChange {
mxResources.get(this.selectionModel.updatingSelectionResource) ||
this.selectionModel.updatingSelectionResource;
if (this.removed != null) {
for (const removed of this.removed) {
this.selectionModel.cellRemoved(removed);
}
for (const removed of this.removed) {
this.selectionModel.cellRemoved(removed);
}
if (this.added != null) {
for (const added of this.added) {
this.selectionModel.cellAdded(added);
}
for (const added of this.added) {
this.selectionModel.cellAdded(added);
}
[this.added, this.removed] = [this.removed, this.added];

View File

@ -1,30 +0,0 @@
/**
* Action to change a cell's style in a model.
*
* @class mxStyleChange
*/
class mxStyleChange {
constructor(model, cell, style) {
this.model = model;
this.cell = cell;
this.style = style;
this.previous = style;
}
/**
* Function: execute
*
* Changes the style of {@link cell}` to {@link previous}` using
* <mxGraphModel.styleForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.style = this.previous;
this.previous = this.model.styleForCellChanged(this.cell, this.previous);
}
}
}
export default mxStyleChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -0,0 +1,36 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Action to change a cell's style in a model.
*
* @class mxStyleChange
*/
class mxStyleChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
style: string | null;
previous: string | null;
constructor(model: mxGraphModel, cell: mxCell, style: string | null) {
this.model = model;
this.cell = cell;
this.style = style;
this.previous = style;
}
/**
* Function: execute
*
* Changes the style of {@link cell}` to {@link previous}` using
* <mxGraphModel.styleForCellChanged>.
*/
execute() {
this.style = this.previous;
this.previous = this.model.styleForCellChanged(this.cell, this.previous);
}
}
export default mxStyleChange;

View File

@ -1,36 +0,0 @@
/**
* Action to change a terminal in a model.
*
* Constructor: mxTerminalChange
*
* Constructs a change of a terminal in the
* specified model.
*/
class mxTerminalChange {
constructor(model, cell, terminal, source) {
this.model = model;
this.cell = cell;
this.terminal = terminal;
this.previous = terminal;
this.source = source;
}
/**
* Changes the terminal of {@link cell}` to {@link previous}` using
* <mxGraphModel.terminalForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.terminal = this.previous;
this.previous = this.model.terminalForCellChanged(
this.cell,
this.previous,
this.source
);
}
}
}
export default mxTerminalChange;
// import('../serialization/mxTerminalChangeCodec');

View File

@ -0,0 +1,48 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Action to change a terminal in a model.
*
* Constructor: mxTerminalChange
*
* Constructs a change of a terminal in the
* specified model.
*/
class mxTerminalChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
terminal: mxCell | null;
previous: mxCell | null;
source: boolean;
constructor(
model: mxGraphModel,
cell: mxCell,
terminal: mxCell | null,
source: boolean
) {
this.model = model;
this.cell = cell;
this.terminal = terminal;
this.previous = terminal;
this.source = source;
}
/**
* Changes the terminal of {@link cell}` to {@link previous}` using
* <mxGraphModel.terminalForCellChanged>.
*/
execute() {
this.terminal = this.previous;
this.previous = this.model.terminalForCellChanged(
this.cell,
this.previous,
this.source
);
}
}
export default mxTerminalChange;

View File

@ -1,31 +0,0 @@
/**
* Action to change a user object in a model.
*
* Constructs a change of a user object in the
* specified model.
*
* @class mxValueChange
*/
class mxValueChange {
constructor(model, cell, value) {
this.model = model;
this.cell = cell;
this.value = value;
this.previous = value;
}
/**
* Changes the value of {@link cell}` to {@link previous}` using
* <mxGraphModel.valueForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.value = this.previous;
this.previous = this.model.valueForCellChanged(this.cell, this.previous);
}
}
}
export default mxValueChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -0,0 +1,37 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Action to change a user object in a model.
*
* Constructs a change of a user object in the
* specified model.
*
* @class mxValueChange
*/
class mxValueChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
value: unknown;
previous: unknown;
constructor(model: mxGraphModel, cell: mxCell, value: unknown) {
this.model = model;
this.cell = cell;
this.value = value;
this.previous = value;
}
/**
* Changes the value of {@link cell}` to {@link previous}` using
* <mxGraphModel.valueForCellChanged>.
*/
execute() {
this.value = this.previous;
this.previous = this.model.valueForCellChanged(this.cell, this.previous);
}
}
export default mxValueChange;

View File

@ -1,3 +1,8 @@
import mxCell from '../view/cell/mxCell';
import mxGraphModel from '../view/graph/mxGraphModel';
import type { UndoableChange } from '../types';
/**
* Class: mxVisibleChange
*
@ -8,8 +13,13 @@
* Constructs a change of a visible state in the
* specified model.
*/
class mxVisibleChange {
constructor(model, cell, visible) {
class mxVisibleChange implements UndoableChange {
model: mxGraphModel;
cell: mxCell;
visible: boolean;
previous: boolean;
constructor(model: mxGraphModel, cell: mxCell, visible: boolean) {
this.model = model;
this.cell = cell;
this.visible = visible;
@ -22,17 +32,13 @@ class mxVisibleChange {
* Changes the visible state of {@link cell}` to {@link previous}` using
* <mxGraphModel.visibleStateForCellChanged>.
*/
// execute(): void;
execute() {
if (this.cell != null) {
this.visible = this.previous;
this.previous = this.model.visibleStateForCellChanged(
this.cell,
this.previous
);
}
this.visible = this.previous;
this.previous = this.model.visibleStateForCellChanged(
this.cell,
this.previous
);
}
}
export default mxVisibleChange;
// import('../serialization/mxGenericChangeCodec');

View File

@ -15,6 +15,7 @@ import mxRectangle from '../util/datatypes/mxRectangle';
import mxCellState from '../view/cell/mxCellState';
import mxGraph from '../view/graph/mxGraph';
import mxShape from '../shape/mxShape';
import { ColorValue } from '../types';
/**
* A helper class to highlight cells. Here is an example for a given cell.
@ -27,59 +28,57 @@ import mxShape from '../shape/mxShape';
*/
class mxCellHighlight {
constructor(
graph: mxGraph | null = null,
highlightColor: string = DEFAULT_VALID_COLOR,
strokeWidth: number = HIGHLIGHT_STROKEWIDTH,
dashed: boolean = false
graph: mxGraph,
highlightColor: ColorValue = DEFAULT_VALID_COLOR,
strokeWidth = HIGHLIGHT_STROKEWIDTH,
dashed = false
) {
if (graph != null) {
this.graph = graph;
this.highlightColor = highlightColor;
this.strokeWidth = strokeWidth;
this.dashed = dashed;
this.opacity = HIGHLIGHT_OPACITY;
this.graph = graph;
this.highlightColor = highlightColor;
this.strokeWidth = strokeWidth;
this.dashed = dashed;
this.opacity = HIGHLIGHT_OPACITY;
// Updates the marker if the graph changes
this.repaintHandler = () => {
// Updates reference to state
if (this.state != null) {
// @ts-ignore
const tmp = this.graph.view.getState(this.state.cell);
// Updates the marker if the graph changes
this.repaintHandler = () => {
// Updates reference to state
if (this.state != null) {
// @ts-ignore
const tmp = this.graph.view.getState(this.state.cell);
if (tmp == null) {
this.hide();
} else {
this.state = tmp;
this.repaint();
}
if (tmp == null) {
this.hide();
} else {
this.state = tmp;
this.repaint();
}
};
}
};
this.graph.getView().addListener(mxEvent.SCALE, this.repaintHandler);
this.graph.getView().addListener(mxEvent.TRANSLATE, this.repaintHandler);
this.graph
.getView()
.addListener(mxEvent.SCALE_AND_TRANSLATE, this.repaintHandler);
this.graph.getModel().addListener(mxEvent.CHANGE, this.repaintHandler);
this.graph.getView().addListener(mxEvent.SCALE, this.repaintHandler);
this.graph.getView().addListener(mxEvent.TRANSLATE, this.repaintHandler);
this.graph
.getView()
.addListener(mxEvent.SCALE_AND_TRANSLATE, this.repaintHandler);
this.graph.getModel().addListener(mxEvent.CHANGE, this.repaintHandler);
// Hides the marker if the current root changes
this.resetHandler = () => {
this.hide();
};
// Hides the marker if the current root changes
this.resetHandler = () => {
this.hide();
};
this.graph.getView().addListener(mxEvent.DOWN, this.resetHandler);
this.graph.getView().addListener(mxEvent.UP, this.resetHandler);
}
this.graph.getView().addListener(mxEvent.DOWN, this.resetHandler);
this.graph.getView().addListener(mxEvent.UP, this.resetHandler);
}
// TODO: Document me!!
highlightColor: string | null = null;
highlightColor: ColorValue = null;
strokeWidth: number | null = null;
strokeWidth: number = 0;
dashed: boolean = false;
dashed = false;
opacity: number = 100;
opacity = 100;
repaintHandler: Function | null = null;
@ -89,35 +88,30 @@ class mxCellHighlight {
* Specifies if the highlights should appear on top of everything else in the overlay pane.
* @default false
*/
// keepOnTop: boolean;
keepOnTop: boolean = false;
keepOnTop = false;
/**
* Reference to the enclosing {@link mxGraph}.
* @default true
*/
// graph: boolean;
graph: mxGraph | null = null;
graph: mxGraph;
/**
* Reference to the {@link mxCellState}.
* @default null
*/
// state: mxCellState;
state: mxCellState | null = null;
/**
* Specifies the spacing between the highlight for vertices and the vertex.
* @default 2
*/
// spacing: number;
spacing: number = 2;
spacing = 2;
/**
* Holds the handler that automatically invokes reset if the highlight should be hidden.
* @default null
*/
// resetHandler: any;
resetHandler: Function | null = null;
/**
@ -125,11 +119,10 @@ class mxCellHighlight {
*
* @param {string} color - String that represents the new highlight color.
*/
// setHighlightColor(color: string): void;
setHighlightColor(color: string): void {
setHighlightColor(color: ColorValue) {
this.highlightColor = color;
if (this.shape != null) {
if (this.shape) {
this.shape.stroke = color;
}
}
@ -137,21 +130,17 @@ class mxCellHighlight {
/**
* Creates and returns the highlight shape for the given state.
*/
// drawHighlight(): void;
drawHighlight(): void {
drawHighlight() {
this.shape = this.createShape();
this.repaint();
const node = this.shape?.node;
if (
!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(
// @ts-ignore
this.shape.node,
// @ts-ignore
this.shape.node.parentNode.firstChild
);
}
@ -160,10 +149,9 @@ class mxCellHighlight {
/**
* Creates and returns the highlight shape for the given state.
*/
// createShape(): mxShape;
createShape(): mxShape {
createShape() {
const shape = <mxShape>(
(<mxGraph>this.graph).cellRenderer.createShape(<mxCellState>this.state)
this.graph.cellRenderer.createShape(<mxCellState>this.state)
);
shape.svgStrokeTolerance = (<mxGraph>this.graph).tolerance;

View File

@ -16,6 +16,11 @@ import mxCellHighlight from './mxCellHighlight';
import mxEventObject from '../util/event/mxEventObject';
import mxEvent from '../util/event/mxEvent';
import mxUtils from '../util/mxUtils';
import mxGraph from '../view/graph/mxGraph';
import { ColorValue } from '../types';
import mxCellState from '../view/cell/mxCellState';
import mxMouseEvent from '../util/event/mxMouseEvent';
import mxCell from '../view/cell/mxCell';
/**
* Class: mxCellMarker
@ -58,18 +63,19 @@ import mxUtils from '../util/mxUtils';
* <mxConstants.DEFAULT_HOTSPOT>.
*/
class mxCellMarker extends mxEventSource {
constructor(graph, validColor, invalidColor, hotspot) {
constructor(
graph: mxGraph,
validColor: ColorValue = DEFAULT_VALID_COLOR,
invalidColor: ColorValue = DEFAULT_INVALID_COLOR,
hotspot: number = DEFAULT_HOTSPOT
) {
super();
if (graph != null) {
this.graph = graph;
this.validColor = validColor != null ? validColor : DEFAULT_VALID_COLOR;
this.invalidColor =
invalidColor != null ? invalidColor : DEFAULT_INVALID_COLOR;
this.hotspot = hotspot != null ? hotspot : DEFAULT_HOTSPOT;
this.highlight = new mxCellHighlight(graph);
}
this.graph = graph;
this.validColor = validColor;
this.invalidColor = invalidColor;
this.hotspot = hotspot;
this.highlight = new mxCellHighlight(graph);
}
/**
@ -77,15 +83,13 @@ class mxCellMarker extends mxEventSource {
*
* Reference to the enclosing <mxGraph>.
*/
// graph: mxGraph;
graph = null;
graph: mxGraph;
/**
* Variable: enabled
*
* Specifies if the marker is enabled. Default is true.
*/
// enabled: boolean;
enabled = true;
/**
@ -96,7 +100,6 @@ class mxCellMarker extends mxEventSource {
* as the hotspot. Possible values are between 0 and 1. Default is
* mxConstants.DEFAULT_HOTSPOT.
*/
// hotspot: number;
hotspot = DEFAULT_HOTSPOT;
/**
@ -104,7 +107,6 @@ class mxCellMarker extends mxEventSource {
*
* Specifies if the hotspot is enabled. Default is false.
*/
// hotspotEnabled: boolean;
hotspotEnabled = false;
/**
@ -112,40 +114,37 @@ class mxCellMarker extends mxEventSource {
*
* Holds the valid marker color.
*/
// validColor: string;
validColor = null;
validColor: ColorValue;
/**
* Variable: invalidColor
*
* Holds the invalid marker color.
*/
// invalidColor: string;
invalidColor = null;
invalidColor: ColorValue;
/**
* Variable: currentColor
*
* Holds the current marker color.
*/
// currentColor: string;
currentColor = null;
currentColor: ColorValue | null = null;
/**
* Variable: validState
*
* Holds the marked <mxCellState> if it is valid.
*/
// validState: mxCellState;
validState = null;
validState: mxCellState | null = null;
/**
* Variable: markedState
*
* Holds the marked <mxCellState>.
*/
// markedState: mxCellState;
markedState = null;
markedState: mxCellState | null = null;
highlight: mxCellHighlight;
/**
* Function: setEnabled
@ -157,8 +156,7 @@ class mxCellMarker extends mxEventSource {
*
* enabled - Boolean that specifies the new enabled state.
*/
// setEnabled(enabled: boolean): void;
setEnabled(enabled) {
setEnabled(enabled: boolean) {
this.enabled = enabled;
}
@ -168,7 +166,6 @@ class mxCellMarker extends mxEventSource {
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
// isEnabled(): boolean;
isEnabled() {
return this.enabled;
}
@ -178,8 +175,7 @@ class mxCellMarker extends mxEventSource {
*
* Sets the <hotspot>.
*/
// setHotspot(hotspot: number): void;
setHotspot(hotspot) {
setHotspot(hotspot: number) {
this.hotspot = hotspot;
}
@ -188,7 +184,6 @@ class mxCellMarker extends mxEventSource {
*
* Returns the <hotspot>.
*/
// getHotspot(): number;
getHotspot() {
return this.hotspot;
}
@ -198,8 +193,7 @@ class mxCellMarker extends mxEventSource {
*
* Specifies whether the hotspot should be used in <intersects>.
*/
// setHotspotEnabled(enabled: boolean): void;
setHotspotEnabled(enabled) {
setHotspotEnabled(enabled: boolean) {
this.hotspotEnabled = enabled;
}
@ -208,7 +202,6 @@ class mxCellMarker extends mxEventSource {
*
* Returns true if hotspot is used in <intersects>.
*/
// isHotspotEnabled(): boolean;
isHotspotEnabled() {
return this.hotspotEnabled;
}
@ -218,9 +211,8 @@ class mxCellMarker extends mxEventSource {
*
* Returns true if <validState> is not null.
*/
// hasValidState(): boolean;
hasValidState() {
return this.validState != null;
return !!this.validState;
}
/**
@ -228,7 +220,6 @@ class mxCellMarker extends mxEventSource {
*
* Returns the <validState>.
*/
// getValidState(): mxCellState;
getValidState() {
return this.validState;
}
@ -238,7 +229,6 @@ class mxCellMarker extends mxEventSource {
*
* Returns the <markedState>.
*/
// getMarkedState(): mxCellState;
getMarkedState() {
return this.markedState;
}
@ -248,11 +238,10 @@ class mxCellMarker extends mxEventSource {
*
* Resets the state of the cell marker.
*/
// reset(): void;
reset() {
this.validState = null;
if (this.markedState != null) {
if (this.markedState) {
this.markedState = null;
this.unmark();
}
@ -268,8 +257,7 @@ class mxCellMarker extends mxEventSource {
* regardless of the marker color. The state is returned regardless of the
* marker color and valid state.
*/
// process(me: mxMouseEvent): mxCellState;
process(me) {
process(me: mxMouseEvent) {
let state = null;
if (this.isEnabled()) {
@ -285,13 +273,13 @@ class mxCellMarker extends mxEventSource {
*
* Sets and marks the current valid state.
*/
// setCurrentState(state: mxCellState, me: mxMouseEvent, color: string): void;
setCurrentState(state, me, color) {
const isValid = state != null ? this.isValidState(state) : false;
color =
color != null
? color
: this.getMarkerColor(me.getEvent(), state, isValid);
setCurrentState(
state: mxCellState,
me: mxMouseEvent,
color: ColorValue = null
) {
const isValid = state ? this.isValidState(state) : false;
color = color ?? this.getMarkerColor(me.getEvent(), state, isValid);
if (isValid) {
this.validState = state;
@ -302,10 +290,10 @@ class mxCellMarker extends mxEventSource {
if (state !== this.markedState || color !== this.currentColor) {
this.currentColor = color;
if (state != null && this.currentColor != null) {
if (state && this.currentColor) {
this.markedState = state;
this.mark();
} else if (this.markedState != null) {
} else if (this.markedState) {
this.markedState = null;
this.unmark();
}
@ -317,12 +305,11 @@ class mxCellMarker extends mxEventSource {
*
* Marks the given cell using the given color, or <validColor> if no color is specified.
*/
// markCell(cell: mxCell, color: string): void;
markCell(cell, color) {
markCell(cell: mxCell, color: ColorValue) {
const state = this.graph.getView().getState(cell);
if (state != null) {
this.currentColor = color != null ? color : this.validColor;
if (state) {
this.currentColor = color ?? this.validColor;
this.markedState = state;
this.mark();
}
@ -333,7 +320,6 @@ class mxCellMarker extends mxEventSource {
*
* Marks the <markedState> and fires a <mark> event.
*/
// mark(): void;
mark() {
this.highlight.setHighlightColor(this.currentColor);
this.highlight.highlight(this.markedState);

View File

@ -35,6 +35,11 @@ import {
isConsumed,
isShiftDown,
} from '../util/mxEventUtils';
import mxGraph from '../view/graph/mxGraph';
import mxImage from '../util/image/mxImage';
import mxCellState from '../view/cell/mxCellState';
type FactoryMethod = (source: mxCell, target: mxCell, style?: string) => mxCell;
/**
* Class: mxConnectionHandler
@ -193,21 +198,19 @@ import {
* the <mxCell> that represents the new edge.
*/
class mxConnectionHandler extends mxEventSource {
constructor(graph, factoryMethod) {
constructor(graph: mxGraph, factoryMethod: FactoryMethod | null = null) {
super();
if (graph != null) {
this.graph = graph;
this.factoryMethod = factoryMethod;
this.init();
this.graph = graph;
this.factoryMethod = factoryMethod;
this.init();
// Handles escape keystrokes
this.escapeHandler = (sender, evt) => {
this.reset();
};
// Handles escape keystrokes
this.escapeHandler = () => {
this.reset();
};
this.graph.addListener(mxEvent.ESCAPE, this.escapeHandler);
}
this.graph.addListener(mxEvent.ESCAPE, this.escapeHandler);
}
/**
@ -216,7 +219,7 @@ class mxConnectionHandler extends mxEventSource {
* Reference to the enclosing <mxGraph>.
*/
// graph: mxGraph;
graph = null;
graph: mxGraph;
/**
* Variable: factoryMethod
@ -226,7 +229,7 @@ class mxConnectionHandler extends mxEventSource {
* a new <mxCell> that represents the edge. This is used in <createEdge>.
*/
// factoryMethod: (source: mxCell, target: mxCell, style?: string) => mxCell;
factoryMethod = true;
factoryMethod: FactoryMethod | null = null;
/**
* Variable: moveIconFront
@ -236,7 +239,6 @@ class mxConnectionHandler extends mxEventSource {
* the connect icon. This has precendence over <moveIconBack> when set
* to true. Default is false.
*/
// moveIconFront: boolean;
moveIconFront = false;
/**
@ -246,7 +248,6 @@ class mxConnectionHandler extends mxEventSource {
* be set to true if the icons of the connection handler conflict with other
* handles, such as the vertex label move handle. Default is false.
*/
// moveIconBack: boolean;
moveIconBack = false;
/**
@ -255,8 +256,8 @@ class mxConnectionHandler extends mxEventSource {
* <mxImage> that is used to trigger the creation of a new connection. This
* is used in <createIcons>. Default is null.
*/
// connectImage: mxImage;
connectImage = null;
connectImage: mxImage | null = null;
/**
* Variable: targetConnectImage
@ -264,7 +265,6 @@ class mxConnectionHandler extends mxEventSource {
* Specifies if the connect icon should be centered on the target state
* while connections are being previewed. Default is false.
*/
// targetConnectImage: boolean;
targetConnectImage = false;
/**
@ -272,7 +272,6 @@ class mxConnectionHandler extends mxEventSource {
*
* Specifies if events are handled. Default is true.
*/
// enabled: boolean;
enabled = true;
/**
@ -280,7 +279,6 @@ class mxConnectionHandler extends mxEventSource {
*
* Specifies if new edges should be selected. Default is true.
*/
// select: boolean;
select = true;
/**
@ -293,7 +291,6 @@ class mxConnectionHandler extends mxEventSource {
* the source cell and the newly created vertex in <createTargetVertex>, which
* can be overridden to create a new target. Default is false.
*/
// createTarget: boolean;
createTarget = false;
/**
@ -301,8 +298,7 @@ class mxConnectionHandler extends mxEventSource {
*
* Holds the <mxTerminalMarker> used for finding source and target cells.
*/
// marker: any;
marker = null;
marker: mxCellMarker | null = null;
/**
* Variable: constraintHandler
@ -310,8 +306,7 @@ class mxConnectionHandler extends mxEventSource {
* Holds the <mxConstraintHandler> used for drawing and highlighting
* constraints.
*/
// constraintHandler: mxConstraintHandler;
constraintHandler = null;
constraintHandler: mxConstraintHandler | null = null;
/**
* Variable: error
@ -327,7 +322,6 @@ class mxConnectionHandler extends mxEventSource {
* Specifies if single clicks should add waypoints on the new edge. Default is
* false.
*/
// waypointsEnabled: boolean;
waypointsEnabled = false;
/**
@ -337,7 +331,6 @@ class mxConnectionHandler extends mxEventSource {
* button when highlighting the source. Default is false, that is, the
* handler only highlights the source if no button is being pressed.
*/
// ignoreMouseDown: boolean;
ignoreMouseDown = false;
/**
@ -346,8 +339,7 @@ class mxConnectionHandler extends mxEventSource {
* Holds the <mxPoint> where the mouseDown took place while the handler is
* active.
*/
// first: mxPoint;
first = null;
first: mxPoint | null = null;
/**
* Variable: connectIconOffset
@ -357,7 +349,6 @@ class mxConnectionHandler extends mxEventSource {
* Note that placing the icon under the mouse pointer with an
* offset of (0,0) will affect hit detection.
*/
// connectIconOffset: mxPoint;
connectIconOffset = new mxPoint(0, TOOLTIP_VERTICAL_OFFSET);
/**
@ -366,8 +357,7 @@ class mxConnectionHandler extends mxEventSource {
* Optional <mxCellState> that represents the preview edge while the
* handler is active. This is created in <createEdgeState>.
*/
// edgeState: mxCellState;
edgeState = null;
edgeState: mxCellState | null = null;
/**
* Variable: changeHandler
@ -391,7 +381,6 @@ class mxConnectionHandler extends mxEventSource {
* Counts the number of mouseDown events since the start. The initial mouse
* down event counts as 1.
*/
// mouseDownCounter: number;
mouseDownCounter = 0;
/**
@ -401,7 +390,6 @@ class mxConnectionHandler extends mxEventSource {
* where the preview cannot be made transparent to events and if the built-in hit detection on
* the HTML elements in the page should be used. Default is the value of <mxClient.IS_VML>.
*/
// movePreviewAway: boolean;
movePreviewAway = false;
/**
@ -411,7 +399,6 @@ class mxConnectionHandler extends mxEventSource {
* enabled. This will allow to place the connection point along the outline of
* the highlighted target. Default is false.
*/
// outlineConnect: boolean;
outlineConnect = false;
/**
@ -420,7 +407,6 @@ class mxConnectionHandler extends mxEventSource {
* Specifies if the actual shape of the edge state should be used for the preview.
* Default is false. (Ignored if no edge state is created in <createEdgeState>.)
*/
// livePreview: boolean;
livePreview = false;
/**
@ -437,16 +423,16 @@ class mxConnectionHandler extends mxEventSource {
* Specifies if new edges should be inserted before the source vertex in the
* cell hierarchy. Default is false for backwards compatibility.
*/
// insertBeforeSource: boolean;
insertBeforeSource = false;
escapeHandler: () => void;
/**
* Function: isEnabled
*
* Returns true if events are handled. This implementation
* returns <enabled>.
*/
// isEnabled(): boolean;
isEnabled() {
return this.enabled;
}
@ -461,8 +447,7 @@ class mxConnectionHandler extends mxEventSource {
*
* enabled - Boolean that specifies the new enabled state.
*/
// setEnabled(enabled: boolean): void;
setEnabled(enabled) {
setEnabled(enabled: boolean) {
this.enabled = enabled;
}
@ -480,8 +465,13 @@ class mxConnectionHandler extends mxEventSource {
* dropTarget - <mxCell> that represents the cell under the mouse when it was
* released.
*/
// isInsertBefore(edge: mxCell, source: mxCell, target: mxCell, evt: MouseEvent, dropTarget: mxCell): boolean;
isInsertBefore(edge, source, target, evt, dropTarget) {
isInsertBefore(
edge: mxCell,
source: mxCell,
target: mxCell,
evt: MouseEvent,
dropTarget: mxCell
) {
return this.insertBeforeSource && source !== target;
}
@ -494,8 +484,7 @@ class mxConnectionHandler extends mxEventSource {
*
* evt - Current active native pointer event.
*/
// isCreateTarget(evt: Event): boolean;
isCreateTarget(evt) {
isCreateTarget(evt: Event) {
return this.createTarget;
}
@ -504,8 +493,7 @@ class mxConnectionHandler extends mxEventSource {
*
* Sets <createTarget>.
*/
// setCreateTarget(value: boolean): void;
setCreateTarget(value) {
setCreateTarget(value: boolean) {
this.createTarget = value;
}
@ -514,19 +502,21 @@ class mxConnectionHandler extends mxEventSource {
*
* Creates the preview shape for new connections.
*/
// createShape(): mxShape;
createShape() {
// Creates the edge preview
const shape =
this.livePreview && this.edgeState != null
this.livePreview && this.edgeState
? this.graph.cellRenderer.createShape(this.edgeState)
: new mxPolyline([], INVALID_COLOR);
shape.dialect = DIALECT_SVG;
shape.scale = this.graph.view.scale;
shape.pointerEvents = false;
shape.isDashed = true;
shape.init(this.graph.getView().getOverlayPane());
mxEvent.redirectMouseEvents(shape.node, this.graph, null);
if (shape && shape.node) {
shape.dialect = DIALECT_SVG;
shape.scale = this.graph.view.scale;
shape.pointerEvents = false;
shape.isDashed = true;
shape.init(this.graph.getView().getOverlayPane());
mxEvent.redirectMouseEvents(shape.node, this.graph, null);
}
return shape;
}
@ -584,8 +574,7 @@ class mxConnectionHandler extends mxEventSource {
* Returns true if the given cell is connectable. This is a hook to
* disable floating connections. This implementation returns true.
*/
// isConnectableCell(cell: mxCell): boolean;
isConnectableCell(cell) {
isConnectableCell(cell: mxCell) {
return true;
}
@ -594,7 +583,6 @@ class mxConnectionHandler extends mxEventSource {
*
* Creates and returns the <mxCellMarker> used in <marker>.
*/
// createMarker(): mxCellMarker;
createMarker() {
const self = this;

View File

@ -73,7 +73,7 @@ const mxClient = {
*
* (code)
* <script type="text/javascript">
* let mxLoadResources = true;
* let mxForceIncludes = false;
* </script>
* <script type="text/javascript" src="/path/to/core/directory/js/mxClient.js"></script>
* (end)

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,7 @@ import mxConnectionConstraint from '../../view/connection/mxConnectionConstraint
import mxRectangle from '../../util/datatypes/mxRectangle';
import mxShape from '../mxShape';
import mxResources from '../../util/mxResources';
import mxUtils from '../../util/mxUtils';
import mxUtils, { getNumber, getValue, isNotNullish } from '../../util/mxUtils';
import {
DIRECTION_NORTH,
DIRECTION_SOUTH,
@ -19,6 +19,8 @@ import {
} from '../../util/mxConstants';
import mxStencilRegistry from './mxStencilRegistry';
import { getChildNodes, getTextContent } from '../../util/mxDomUtils';
import mxPoint from '../../util/datatypes/mxPoint';
import mxSvgCanvas2D from '../../util/canvas/mxSvgCanvas2D';
/**
* Implements a generic shape which is based on a XML node as a description.
@ -26,7 +28,7 @@ import { getChildNodes, getTextContent } from '../../util/mxDomUtils';
* @class mxStencil
*/
class mxStencil extends mxShape {
constructor(desc) {
constructor(desc: Element) {
super();
this.desc = desc;
this.parseDescription();
@ -39,8 +41,7 @@ class mxStencil extends mxShape {
* Static global variable that specifies the default value for the localized
* attribute of the text element. Default is false.
*/
// defaultLocalized: boolean;
defaultLocalized = false;
static defaultLocalized = false;
/**
* Function: allowEval
@ -49,48 +50,42 @@ class mxStencil extends mxShape {
* evaluating text content and images. Default is false. Set this to true
* if stencils can not contain user input.
*/
// allowEval: boolean;
allowEval = false;
static allowEval = false;
/**
* Variable: desc
*
* Holds the XML node with the stencil description.
*/
// desc: Element;
desc = null;
desc: Element;
/**
* Variable: constraints
*
* Holds an array of <mxConnectionConstraints> as defined in the shape.
*/
// constraints: mxConnectionConstraint[];
constraints = null;
constraints: mxConnectionConstraint[] = [];
/**
* Variable: aspect
*
* Holds the aspect of the shape. Default is 'auto'.
*/
// aspect: string;
aspect = null;
aspect = 'auto';
/**
* Variable: w0
*
* Holds the width of the shape. Default is 100.
*/
// w0: number;
w0 = null;
w0 = 100;
/**
* Variable: h0
*
* Holds the height of the shape. Default is 100.
*/
// h0: number;
h0 = null;
h0 = 100;
/**
* Variable: bgNodes
@ -98,30 +93,27 @@ class mxStencil extends mxShape {
* Holds the XML node with the stencil description.
*/
// bgNode: Element;
bgNode = null;
bgNode: Element | null = null;
/**
* Variable: fgNodes
*
* Holds the XML node with the stencil description.
*/
// fgNode: Element;
fgNode = null;
fgNode: Element | null = null;
/**
* Variable: strokewidth
*
* Holds the strokewidth direction from the description.
*/
// strokewidth: number;
strokewidth = null;
strokeWidth: string | null = null;
/**
* Function: parseDescription
*
* Reads <w0>, <h0>, <aspect>, <bgNodes> and <fgNodes> from <desc>.
*/
// parseDescription(): void;
parseDescription() {
// LATER: Preprocess nodes for faster painting
this.fgNode = this.desc.getElementsByTagName('foreground')[0];
@ -133,14 +125,14 @@ class mxStencil extends mxShape {
// variable means fill the available space and fixed means
// use w0 and h0 to compute the aspect.
const aspect = this.desc.getAttribute('aspect');
this.aspect = aspect != null ? aspect : 'variable';
this.aspect = aspect ?? 'variable';
// Possible values for strokewidth are all numbers and "inherit"
// where the inherit means take the value from the style (ie. the
// user-defined stroke-width). Note that the strokewidth is scaled
// by the minimum scaling that is used to draw the shape (sx, sy).
const sw = this.desc.getAttribute('strokewidth');
this.strokewidth = sw != null ? sw : '1';
this.strokeWidth = isNotNullish(sw) ? sw : '1';
}
/**
@ -149,7 +141,6 @@ class mxStencil extends mxShape {
* Reads the constraints from <desc> into <constraints> using
* <parseConstraint>.
*/
// parseConstraints(): void;
parseConstraints() {
const conns = this.desc.getElementsByTagName('connections')[0];
@ -171,8 +162,7 @@ class mxStencil extends mxShape {
*
* Parses the given XML node and returns its <mxConnectionConstraint>.
*/
// parseConstraint(node: Element): void;
parseConstraint(node) {
parseConstraint(node: Element) {
const x = Number(node.getAttribute('x'));
const y = Number(node.getAttribute('y'));
const perimeter = node.getAttribute('perimeter') == '1';
@ -188,8 +178,7 @@ class mxStencil extends mxShape {
* is used as a key to <mxResources.get> if the localized attribute in the text
* node is 1 or if <defaultLocalized> is true.
*/
// evaluateTextAttribute(node: string, attribute: string, shape: string): string;
evaluateTextAttribute(node, attribute, shape) {
evaluateTextAttribute(node: Element, attribute: string, shape: mxShape) {
let result = this.evaluateAttribute(node, attribute, shape);
const loc = node.getAttribute('localized');
@ -208,8 +197,7 @@ class mxStencil extends mxShape {
* a function it is invoked with <shape> as the only argument and the return
* value is used as the attribute value to be returned.
*/
// evaluateAttribute(node: string, attribute: string, shape: string): string;
evaluateAttribute(node, attribute, shape) {
evaluateAttribute(node: Element, attribute: string, shape: mxShape) {
let result = node.getAttribute(attribute);
if (result == null) {
@ -232,8 +220,14 @@ class mxStencil extends mxShape {
*
* Draws this stencil inside the given bounds.
*/
// drawShape(canvas: mxAbstractCanvas2D, shape: string, x: number, y: number, w: number, h: number): void;
drawShape(canvas, shape, x, y, w, h) {
drawShape(
canvas: mxSvgCanvas2D,
shape: mxShape,
x: number,
y: number,
w: number,
h: number
) {
const stack = canvas.states.slice();
// TODO: Internal structure (array of special structs?), relative and absolute
@ -242,19 +236,19 @@ class mxStencil extends mxShape {
// (start, segment, end blocks), pluggable markers, how to implement
// swimlanes (title area) with this API, add icon, horizontal/vertical
// label, indicator for all shapes, rotation
const direction = mxUtils.getValue(shape.style, 'direction', null);
const aspect = this.computeAspect(shape.style, x, y, w, h, direction);
const direction = getValue(shape.style, 'direction', null);
const aspect = this.computeAspect(shape, x, y, w, h, direction);
const minScale = Math.min(aspect.width, aspect.height);
const sw =
this.strokewidth == 'inherit'
? Number(mxUtils.getNumber(shape.style, 'strokeWidth', 1))
: Number(this.strokewidth) * minScale;
this.strokeWidth == 'inherit'
? Number(getNumber(shape.style, 'strokeWidth', 1))
: Number(this.strokeWidth) * minScale;
canvas.setStrokeWidth(sw);
// Draws a transparent rectangle for catching events
if (
shape.style != null &&
mxUtils.getValue(shape.style, 'pointerEvents', '0') == '1'
getValue(shape.style, 'pointerEvents', '0') == '1'
) {
canvas.setStrokeColor(NONE);
canvas.rect(x, y, w, h);
@ -286,7 +280,7 @@ class mxStencil extends mxShape {
true,
!shape.outline ||
shape.style == null ||
mxUtils.getValue(shape.style, 'backgroundOutline', 0) == 0
getValue(shape.style, 'backgroundOutline', 0) == 0
);
// Restores stack for unequal count of save/restore calls
@ -300,7 +294,18 @@ class mxStencil extends mxShape {
*
* Draws this stencil inside the given bounds.
*/
drawChildren(canvas, shape, x, y, w, h, node, aspect, disableShadow, paint) {
drawChildren(
canvas: mxSvgCanvas2D,
shape: mxShape,
x: number,
y: number,
w: number,
h: number,
node: Element | null,
aspect: string,
disableShadow: boolean,
paint: boolean
) {
if (node != null && w > 0 && h > 0) {
let tmp = node.firstChild;
@ -327,8 +332,14 @@ class mxStencil extends mxShape {
* bounds - <mxRectangle> that should contain the stencil.
* direction - Optional direction of the shape to be darwn.
*/
// computeAspect(shape: string, x: number, y: number, w: number, h: number, direction?: string): mxRectangle;
computeAspect(shape, x, y, w, h, direction) {
computeAspect(
shape: mxShape,
x: number,
y: number,
w: number,
h: number,
direction?: string
) {
let x0 = x;
let y0 = y;
let sx = w / this.w0;
@ -369,7 +380,14 @@ class mxStencil extends mxShape {
*
* Draws this stencil inside the given bounds.
*/
drawNode(canvas, shape, node, aspect, disableShadow, paint) {
drawNode(
canvas: mxSvgCanvas2D,
shape: mxShape,
node: Element,
aspect: mxRectangle,
disableShadow: boolean,
paint: boolean
) {
const name = node.nodeName;
const x0 = aspect.x;
const y0 = aspect.y;
@ -493,7 +511,7 @@ class mxStencil extends mxShape {
Number(node.getAttribute('rx')) * sx,
Number(node.getAttribute('ry')) * sy,
Number(node.getAttribute('x-axis-rotation')),
Number(node.getAttribute('large-arc-flag')),
Boolean(node.getAttribute('large-arc-flag')),
Number(node.getAttribute('sweep-flag')),
x0 + Number(node.getAttribute('x')) * sx,
y0 + Number(node.getAttribute('y')) * sy
@ -556,8 +574,8 @@ class mxStencil extends mxShape {
const dr = shape.rotation;
// Depends on flipping
const flipH = mxUtils.getValue(shape.style, 'flipH', 0) == 1;
const flipV = mxUtils.getValue(shape.style, 'flipV', 0) == 1;
const flipH = getValue(shape.style, 'flipH', 0) == 1;
const flipV = getValue(shape.style, 'flipV', 0) == 1;
if (flipH && flipV) {
rotation -= dr;

View File

@ -23,6 +23,12 @@
* (end)
*/
import mxStencil from './mxStencil';
type Stencils = {
[k: string]: mxStencil;
};
/**
* A singleton class that provides a registry for stencils and the methods
* for painting those stencils onto a canvas or into a DOM.
@ -30,7 +36,7 @@
* @class mxStencilRegistry
*/
class mxStencilRegistry {
static stencils = {};
static stencils: Stencils = {};
/**
* Adds the given <mxStencil>.
@ -38,8 +44,7 @@ class mxStencilRegistry {
* @param {string} name
* @param {mxStencil} stencil
*/
// static addStencil(name: string, stencil: mxStencil): void;
static addStencil(name, stencil) {
static addStencil(name: string, stencil: mxStencil) {
mxStencilRegistry.stencils[name] = stencil;
}
@ -49,8 +54,7 @@ class mxStencilRegistry {
* @param {string} name
* @returns {mxStencil}
*/
// static getStencil(name: string): mxStencil;
static getStencil(name) {
static getStencil(name: string) {
return mxStencilRegistry.stencils[name];
}
}

View File

@ -0,0 +1,83 @@
import type mxCell from './view/cell/mxCell';
export type CellMap = {
[id: string]: mxCell;
};
export type FilterFunction = (cell: mxCell) => boolean;
export type UndoableChange = {
execute: () => void;
undo?: () => void;
redo?: () => void;
};
export type StyleValue = string | number;
export type StyleProperties = {
[k: string]: StyleValue;
};
export type Properties = {
[k: string]: any;
};
export type CellStateStyles = {
[k: string]: string;
};
export type ColorValue = string | null;
export type DirectionValue = 'north' | 'south' | 'east' | 'west' | null;
export type AlignValue =
| 'left'
| 'center'
| 'right'
| 'top'
| 'middle'
| 'bottom'
| null;
export type CanvasState = {
dx: number;
dy: number;
scale: number;
alpha: number;
fillAlpha: number;
strokeAlpha: number;
fillColor: ColorValue;
gradientFillAlpha: number;
gradientColor: ColorValue;
gradientAlpha: number;
gradientDirection: string | null;
strokeColor: ColorValue;
strokeWidth: number | null;
dashed: boolean;
dashPattern: string;
fixDash: boolean;
lineCap: string;
lineJoin: string;
miterLimit: number;
fontColor: ColorValue;
fontBackgroundColor: ColorValue;
fontBorderColor: ColorValue;
fontSize: number;
fontFamily: string;
fontStyle: number;
shadow: boolean;
shadowColor: ColorValue;
shadowAlpha: number;
shadowDx: number;
shadowDy: number;
rotation: number;
rotationCx: number;
rotationCy: number;
transform: string | null;
};
export interface Gradient extends SVGLinearGradientElement {
mxRefCount: number;
}
export type GradientMap = {
[k: string]: Gradient;
};

View File

@ -4,7 +4,7 @@
* Updated to ES9 syntax by David Morrissey 2021
* Type definitions from the typed-mxgraph project
*/
import mxUtils from '../mxUtils';
import { arcToCurves, getRotatedPoint } from '../mxUtils';
import {
DEFAULT_FONTFAMILY,
DEFAULT_FONTSIZE,
@ -16,6 +16,9 @@ import {
} from '../mxConstants';
import mxUrlConverter from '../network/mxUrlConverter';
import mxPoint from '../datatypes/mxPoint';
import { clone } from '../mxCloneUtils';
import type { CanvasState, ColorValue } from '../../types';
/**
* Class: mxAbstractCanvas2D
@ -38,26 +41,28 @@ class mxAbstractCanvas2D {
this.reset();
}
converter: mxUrlConverter;
/**
* Variable: state
*
* Holds the current state.
*/
state = null;
state: CanvasState = this.createState();
/**
* Variable: states
*
* Stack of states.
*/
states = null;
states: CanvasState[] = [];
/**
* Variable: path
*
* Holds the current path as an array.
*/
path = null;
path: (string | number)[] = [];
/**
* Variable: rotateHtml
@ -181,7 +186,7 @@ class mxAbstractCanvas2D {
rotation: 0,
rotationCx: 0,
rotationCy: 0,
};
} as CanvasState;
}
/**
@ -189,8 +194,8 @@ class mxAbstractCanvas2D {
*
* Rounds all numbers to integers.
*/
format(value) {
return Math.round(parseFloat(value));
format(value: number) {
return Math.round(value);
}
/**
@ -198,20 +203,18 @@ class mxAbstractCanvas2D {
*
* Adds the given operation to the path.
*/
addOp = (...args) => {
if (this.path != null) {
this.path.push(args[0]);
addOp = (op: string, ...args: number[]) => {
this.path.push(op);
if (args.length > 2) {
const s = this.state;
if (args.length > 1) {
const s = this.state;
for (let i = 2; i < args.length; i += 2) {
this.lastX = args[i - 1];
this.lastY = args[i];
for (let i = 1; i < args.length; i += 2) {
this.lastX = args[i - 1];
this.lastY = args[i];
this.path.push(this.format((this.lastX + s.dx) * s.scale));
this.path.push(this.format((this.lastY + s.dy) * s.scale));
}
this.path.push(this.format((this.lastX + s.dx) * s.scale));
this.path.push(this.format((this.lastY + s.dy) * s.scale));
}
}
};
@ -221,10 +224,10 @@ class mxAbstractCanvas2D {
*
* Rotates the given point and returns the result as an <mxPoint>.
*/
rotatePoint(x, y, theta, cx, cy) {
rotatePoint(x: number, y: number, theta: number, cx: number, cy: number) {
const rad = theta * (Math.PI / 180);
return mxUtils.getRotatedPoint(
return getRotatedPoint(
new mxPoint(x, y),
Math.cos(rad),
Math.sin(rad),
@ -239,7 +242,7 @@ class mxAbstractCanvas2D {
*/
save() {
this.states.push(this.state);
this.state = mxUtils.clone(this.state);
this.state = clone(this.state);
}
/**
@ -248,9 +251,9 @@ class mxAbstractCanvas2D {
* Restores the current state.
*/
restore() {
if (this.states.length > 0) {
this.state = this.states.pop();
}
const state = this.states.pop();
if (state) this.state = state;
}
/**
@ -258,7 +261,7 @@ class mxAbstractCanvas2D {
*
* Sets the current link. Hook for subclassers.
*/
setLink(link) {
setLink(link: string | null) {
// nop
}
@ -267,9 +270,10 @@ class mxAbstractCanvas2D {
*
* Scales the current state.
*/
scale(value) {
scale(value: number) {
this.state.scale *= value;
this.state.strokeWidth *= value;
if (this.state.strokeWidth !== null) this.state.strokeWidth *= value;
}
/**
@ -277,7 +281,7 @@ class mxAbstractCanvas2D {
*
* Translates the current state.
*/
translate(dx, dy) {
translate(dx: number, dy: number) {
this.state.dx += dx;
this.state.dy += dy;
}
@ -287,7 +291,13 @@ class mxAbstractCanvas2D {
*
* Rotates the current state.
*/
rotate(theta, flipH, flipV, cx, cy) {
rotate(
theta: number,
flipH: boolean,
flipV: boolean,
cx: number,
cy: number
) {
// nop
}
@ -296,7 +306,7 @@ class mxAbstractCanvas2D {
*
* Sets the current alpha.
*/
setAlpha(value) {
setAlpha(value: number) {
this.state.alpha = value;
}
@ -305,7 +315,7 @@ class mxAbstractCanvas2D {
*
* Sets the current solid fill alpha.
*/
setFillAlpha(value) {
setFillAlpha(value: number) {
this.state.fillAlpha = value;
}
@ -314,7 +324,7 @@ class mxAbstractCanvas2D {
*
* Sets the current stroke alpha.
*/
setStrokeAlpha(value) {
setStrokeAlpha(value: number) {
this.state.strokeAlpha = value;
}
@ -323,12 +333,10 @@ class mxAbstractCanvas2D {
*
* Sets the current fill color.
*/
setFillColor(value) {
if (value === NONE) {
value = null;
}
setFillColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.fillColor = value;
this.state.fillColor = v;
this.state.gradientColor = null;
}
@ -337,12 +345,22 @@ class mxAbstractCanvas2D {
*
* Sets the current gradient.
*/
setGradient(color1, color2, x, y, w, h, direction, alpha1, alpha2) {
setGradient(
color1: ColorValue,
color2: ColorValue,
x: number,
y: number,
w: number,
h: number,
direction: string | null,
alpha1 = 1,
alpha2: number = 1
) {
const s = this.state;
s.fillColor = color1;
s.gradientFillAlpha = alpha1 != null ? alpha1 : 1;
s.gradientFillAlpha = alpha1;
s.gradientColor = color2;
s.gradientAlpha = alpha2 != null ? alpha2 : 1;
s.gradientAlpha = alpha2;
s.gradientDirection = direction;
}
@ -351,12 +369,9 @@ class mxAbstractCanvas2D {
*
* Sets the current stroke color.
*/
setStrokeColor(value) {
if (value === NONE) {
value = null;
}
this.state.strokeColor = value;
setStrokeColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.strokeColor = v;
}
/**
@ -364,7 +379,7 @@ class mxAbstractCanvas2D {
*
* Sets the current stroke width.
*/
setStrokeWidth(value) {
setStrokeWidth(value: number | null) {
this.state.strokeWidth = value;
}
@ -373,7 +388,7 @@ class mxAbstractCanvas2D {
*
* Enables or disables dashed lines.
*/
setDashed(value, fixDash) {
setDashed(value: boolean, fixDash = false) {
this.state.dashed = value;
this.state.fixDash = fixDash;
}
@ -383,7 +398,7 @@ class mxAbstractCanvas2D {
*
* Sets the current dash pattern.
*/
setDashPattern(value) {
setDashPattern(value: string) {
this.state.dashPattern = value;
}
@ -392,7 +407,7 @@ class mxAbstractCanvas2D {
*
* Sets the current line cap.
*/
setLineCap(value) {
setLineCap(value: string) {
this.state.lineCap = value;
}
@ -401,7 +416,7 @@ class mxAbstractCanvas2D {
*
* Sets the current line join.
*/
setLineJoin(value) {
setLineJoin(value: string) {
this.state.lineJoin = value;
}
@ -410,7 +425,7 @@ class mxAbstractCanvas2D {
*
* Sets the current miter limit.
*/
setMiterLimit(value) {
setMiterLimit(value: number) {
this.state.miterLimit = value;
}
@ -419,12 +434,9 @@ class mxAbstractCanvas2D {
*
* Sets the current font color.
*/
setFontColor(value) {
if (value === NONE) {
value = null;
}
this.state.fontColor = value;
setFontColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.fontColor = v;
}
/**
@ -432,12 +444,9 @@ class mxAbstractCanvas2D {
*
* Sets the current font background color.
*/
setFontBackgroundColor(value) {
if (value === NONE) {
value = null;
}
this.state.fontBackgroundColor = value;
setFontBackgroundColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.fontBackgroundColor = v;
}
/**
@ -445,12 +454,9 @@ class mxAbstractCanvas2D {
*
* Sets the current font border color.
*/
setFontBorderColor(value) {
if (value === NONE) {
value = null;
}
this.state.fontBorderColor = value;
setFontBorderColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.fontBorderColor = v;
}
/**
@ -458,8 +464,8 @@ class mxAbstractCanvas2D {
*
* Sets the current font size.
*/
setFontSize(value) {
this.state.fontSize = parseFloat(value);
setFontSize(value: number) {
this.state.fontSize = value;
}
/**
@ -467,7 +473,7 @@ class mxAbstractCanvas2D {
*
* Sets the current font family.
*/
setFontFamily(value) {
setFontFamily(value: string) {
this.state.fontFamily = value;
}
@ -476,11 +482,7 @@ class mxAbstractCanvas2D {
*
* Sets the current font style.
*/
setFontStyle(value) {
if (value == null) {
value = 0;
}
setFontStyle(value: number) {
this.state.fontStyle = value;
}
@ -489,7 +491,7 @@ class mxAbstractCanvas2D {
*
* Enables or disables and configures the current shadow.
*/
setShadow(enabled) {
setShadow(enabled: boolean) {
this.state.shadow = enabled;
}
@ -498,12 +500,9 @@ class mxAbstractCanvas2D {
*
* Enables or disables and configures the current shadow.
*/
setShadowColor(value) {
if (value === NONE) {
value = null;
}
this.state.shadowColor = value;
setShadowColor(value: ColorValue) {
const v = value === NONE ? null : value;
this.state.shadowColor = v;
}
/**
@ -511,7 +510,7 @@ class mxAbstractCanvas2D {
*
* Enables or disables and configures the current shadow.
*/
setShadowAlpha(value) {
setShadowAlpha(value: number) {
this.state.shadowAlpha = value;
}
@ -520,7 +519,7 @@ class mxAbstractCanvas2D {
*
* Enables or disables and configures the current shadow.
*/
setShadowOffset(dx, dy) {
setShadowOffset(dx: number, dy: number) {
this.state.shadowDx = dx;
this.state.shadowDy = dy;
}
@ -541,7 +540,7 @@ class mxAbstractCanvas2D {
*
* Moves the current path the given coordinates.
*/
moveTo(x, y) {
moveTo(x: number, y: number) {
this.addOp(this.moveOp, x, y);
}
@ -550,7 +549,7 @@ class mxAbstractCanvas2D {
*
* Draws a line to the given coordinates. Uses moveTo with the op argument.
*/
lineTo(x, y) {
lineTo(x: number, y: number) {
this.addOp(this.lineOp, x, y);
}
@ -559,7 +558,7 @@ class mxAbstractCanvas2D {
*
* Adds a quadratic curve to the current path.
*/
quadTo(x1, y1, x2, y2) {
quadTo(x1: number, y1: number, x2: number, y2: number) {
this.addOp(this.quadOp, x1, y1, x2, y2);
}
@ -568,7 +567,14 @@ class mxAbstractCanvas2D {
*
* Adds a bezier curve to the current path.
*/
curveTo(x1, y1, x2, y2, x3, y3) {
curveTo(
x1: number,
y1: number,
x2: number,
y2: number,
x3: number,
y3: number
) {
this.addOp(this.curveOp, x1, y1, x2, y2, x3, y3);
}
@ -578,8 +584,16 @@ class mxAbstractCanvas2D {
* Adds the given arc to the current path. This is a synthetic operation that
* is broken down into curves.
*/
arcTo(rx, ry, angle, largeArcFlag, sweepFlag, x, y) {
const curves = mxUtils.arcToCurves(
arcTo(
rx: number,
ry: number,
angle: number,
largeArcFlag: boolean,
sweepFlag: boolean,
x: number,
y: number
) {
const curves = arcToCurves(
this.lastX,
this.lastY,
rx,
@ -610,7 +624,14 @@ class mxAbstractCanvas2D {
*
* Closes the current path.
*/
close(x1, y1, x2, y2, x3, y3) {
close(
x1?: number,
y1?: number,
x2?: number,
y2?: number,
x3?: number,
y3?: number
) {
this.addOp(this.closeOp);
}

View File

@ -5,7 +5,7 @@
* Type definitions from the typed-mxgraph project
*/
import mxUtils from '../mxUtils';
import { getAlignmentAsPoint, isNotNullish } from '../mxUtils';
import mxClient from '../../mxClient';
import {
ABSOLUTE_LINE_HEIGHT,
@ -35,6 +35,12 @@ import mxAbstractCanvas2D from './mxAbstractCanvas2D';
import { parseXml } from '../mxXmlUtils';
import { importNodeImplementation, isNode, write } from '../mxDomUtils';
import { htmlEntities, trim } from '../mxStringUtils';
import {
AlignValue,
ColorValue,
DirectionValue,
GradientMap,
} from '../../types';
// Activates workaround for gradient ID resolution if base tag is used.
const useAbsoluteIds =
@ -82,7 +88,7 @@ const useAbsoluteIds =
* Or set the respective attribute in the SVG element directly.
*/
class mxSvgCanvas2D extends mxAbstractCanvas2D {
constructor(root, styleEnabled) {
constructor(root: SVGElement, styleEnabled: boolean) {
super();
/**
@ -97,7 +103,7 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
*
* Local cache of gradients for quick lookups.
*/
this.gradients = [];
this.gradients = {};
/**
* Variable: defs
@ -153,31 +159,35 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
}
}
root: SVGElement;
gradients: GradientMap;
defs: SVGDefsElement | null = null;
styleEnabled = true;
/**
* Holds the current DOM node.
*/
// node: Element;
node = null;
node: SVGElement | null = null;
/**
* Specifies if plain text output should match the vertical HTML alignment.
* @default true.
*/
// matchHtmlAlignment: boolean;
matchHtmlAlignment = true;
/**
* Specifies if text output should be enabled.
* @default true
*/
// textEnabled: boolean;
textEnabled = true;
/**
* Specifies if use of foreignObject for HTML markup is allowed.
* @default true
*/
// foEnabled: boolean;
foEnabled = true;
/**
@ -185,101 +195,97 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
* If this is set to `null` then no fallback text is added to the exported document.
* @default [Object]
*/
// foAltText: string;
foAltText = '[Object]';
/**
* Offset to be used for foreignObjects.
* @default 0
*/
// foOffset: number;
foOffset = 0;
/**
* Offset to be used for text elements.
* @default 0
*/
// textOffset: number;
textOffset = 0;
/**
* Offset to be used for image elements.
* @default 0
*/
// imageOffset: number;
imageOffset = 0;
/**
* Adds transparent paths for strokes.
* @default 0
*/
// strokeTolerance: number;
strokeTolerance = 0;
/**
* Minimum stroke width for output.
* @default 1
*/
// minStrokeWidth: number;
minStrokeWidth = 1;
/**
* Local counter for references in SVG export.
* @default 0
*/
// refCount: number;
refCount = 0;
/**
* Correction factor for {@link mxConstants.LINE_HEIGHT} in HTML output.
* @default 1
*/
// lineHeightCorrection: number;
lineHeightCorrection = 1;
/**
* Default value for active pointer events.
* @default all
*/
// pointerEventsValue: string;
pointerEventsValue = 'all';
/**
* Padding to be added for text that is not wrapped to account for differences in font metrics on different platforms in pixels.
* @default 10.
*/
// fontMetricsPadding: number;
fontMetricsPadding = 10;
/**
* Specifies if offsetWidth and offsetHeight should be cached. This is used to speed up repaint of text in {@link updateText}.
* @default true
*/
// cacheOffsetSize: boolean;
cacheOffsetSize = true;
/**
* Updates existing DOM nodes for text rendering.
*/
static createCss = (
w,
h,
align,
valign,
wrap,
overflow,
clip,
bg,
border,
flex,
block,
s,
callback
w: number,
h: number,
align: AlignValue,
valign: string,
wrap: boolean,
overflow: string,
clip: boolean,
bg: ColorValue,
border: ColorValue,
flex: string,
block: string,
scale: number,
callback: (
dx: number,
dy: number,
flex: string,
item: string,
block: string,
ofl: string
) => void
) => {
let item = `box-sizing: border-box; font-size: 0; text-align: ${
align === ALIGN_LEFT ? 'left' : align === ALIGN_RIGHT ? 'right' : 'center'
}; `;
const pt = mxUtils.getAlignmentAsPoint(align, valign);
const pt = getAlignmentAsPoint(align, valign);
let ofl = 'overflow: hidden; ';
let fw = 'width: 1px; ';
let fh = 'height: 1px; ';
@ -311,11 +317,11 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
let bgc = '';
if (bg != null) {
if (bg) {
bgc += `background-color: ${bg}; `;
}
if (border != null) {
if (border) {
bgc += `border: 1px solid ${border}; `;
}
@ -329,13 +335,13 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
block += `white-space: normal; word-wrap: ${WORD_WRAP}; `;
fw = `width: ${Math.round(w)}px; `;
if (ofl != '' && overflow !== 'fill') {
if (ofl !== '' && overflow !== 'fill') {
dy = 0;
}
} else {
block += 'white-space: nowrap; ';
if (ofl == '') {
if (ofl === '') {
dx = 0;
}
}
@ -346,9 +352,8 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
/**
* Rounds all numbers to 2 decimal points.
*/
// format(value: string): number;
format(value) {
return parseFloat(parseFloat(value).toFixed(2));
format(value: number) {
return parseFloat(value.toFixed(2));
}
/**
@ -357,7 +362,6 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
* workaround for the fact that window.location.search is empty if there is
* no search string behind the question mark.
*/
// getBaseUrl(): string;
getBaseUrl() {
let { href } = window.location;
const hash = href.lastIndexOf('#');
@ -372,17 +376,15 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
/**
* Returns any offsets for rendering pixels.
*/
// reset(): void;
reset() {
super.reset();
this.gradients = [];
this.gradients = {};
}
/**
* Creates the optional style section.
*/
// createStyle(x?: any): HTMLElement;
createStyle(x) {
createStyle() {
const style = this.createElement('style');
style.setAttribute('type', 'text/css');
write(
@ -396,21 +398,11 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
/**
* Private helper function to create SVG elements
*/
// createElement(tagName: string, namespace?: string): HTMLElement;
createElement(tagName, namespace) {
if (this.root.ownerDocument.createElementNS != null) {
return this.root.ownerDocument.createElementNS(
namespace || NS_SVG,
tagName
);
}
const elt = this.root.ownerDocument.createElement(tagName);
if (namespace != null) {
elt.setAttribute('xmlns', namespace);
}
return elt;
createElement(tagName: string, namespace?: string) {
return this.root.ownerDocument.createElementNS(
namespace || NS_SVG,
tagName
) as SVGElement;
}
/**
@ -419,21 +411,21 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
* Returns the alternate text string for the given foreignObject.
*/
getAlternateText(
fo,
x,
y,
w,
h,
str,
align,
valign,
wrap,
fo: SVGForeignObjectElement,
x: number,
y: number,
w: number,
h: number,
str: Element | string,
align: AlignValue,
valign: string,
wrap: boolean,
format,
overflow,
clip,
overflow: boolean,
clip: boolean,
rotation
) {
return str != null ? this.foAltText : null;
return isNotNullish(str) ? this.foAltText : null;
}
/**
@ -448,8 +440,8 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
w,
h,
str,
align,
valign,
align: AlignValue,
valign: AlignValue,
wrap,
format,
overflow,
@ -473,7 +465,7 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
);
const s = this.state;
if (text != null && s.fontSize > 0) {
if (isNotNullish(text) && s.fontSize > 0) {
const dy = valign === ALIGN_TOP ? 1 : valign === ALIGN_BOTTOM ? 0 : 0.3;
const anchor =
align === ALIGN_RIGHT
@ -483,8 +475,8 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
: 'middle';
const alt = this.createElement('text');
alt.setAttribute('x', Math.round(x + s.dx));
alt.setAttribute('y', Math.round(y + s.dy + dy * s.fontSize));
alt.setAttribute('x', String(Math.round(x + s.dx)));
alt.setAttribute('y', String(Math.round(y + s.dy + dy * s.fontSize)));
alt.setAttribute('fill', s.fontColor || 'black');
alt.setAttribute('font-family', s.fontFamily);
alt.setAttribute('font-size', `${Math.round(s.fontSize)}px`);
@ -527,7 +519,13 @@ class mxSvgCanvas2D extends mxAbstractCanvas2D {
* Private helper function to create SVG elements
*/
// createGradientId(start: string, end: string, alpha1: string, alpha2: string, direction: string): string;
createGradientId(start, end, alpha1, alpha2, direction) {
createGradientId(
start: string,
end: string,
alpha1: number,
alpha2: number,
direction: DirectionValue
) {
// Removes illegal characters from gradient ID
if (start.charAt(0) === '#') {
start = start.substring(1);

View File

@ -7,6 +7,12 @@
import mxObjectIdentity from './mxObjectIdentity';
type Dictionary<T, U> = {
[key: string]: U;
};
type Visitor<T, U> = (key: string, value: U) => void;
/**
* Class: mxDictionary
*
@ -17,7 +23,7 @@ import mxObjectIdentity from './mxObjectIdentity';
*
* Constructs a new dictionary which allows object to be used as keys.
*/
class mxDictionary {
class mxDictionary<T, U> {
constructor() {
this.clear();
}
@ -27,7 +33,7 @@ class mxDictionary {
*
* Stores the (key, value) pairs in this dictionary.
*/
map = null;
map: Dictionary<T, U> = {};
/**
* Function: clear
@ -43,7 +49,7 @@ class mxDictionary {
*
* Returns the value for the given key.
*/
get(key) {
get(key: T) {
const id = mxObjectIdentity.get(key);
return this.map[id];
@ -55,7 +61,7 @@ class mxDictionary {
* Stores the value under the given key and returns the previous
* value for that key.
*/
put(key, value) {
put(key: T, value: U) {
const id = mxObjectIdentity.get(key);
const previous = this.map[id];
this.map[id] = value;
@ -69,7 +75,7 @@ class mxDictionary {
* Removes the value for the given key and returns the value that
* has been removed.
*/
remove(key) {
remove(key: T) {
const id = mxObjectIdentity.get(key);
const previous = this.map[id];
delete this.map[id];
@ -118,7 +124,7 @@ class mxDictionary {
*
* visitor - A function that takes the key and value as arguments.
*/
visit(visitor) {
visit(visitor: Visitor<string, U>) {
for (const key in this.map) {
visitor(key, this.map[key]);
}

View File

@ -7,7 +7,7 @@
import mxPoint from './mxPoint';
import mxRectangle from './mxRectangle';
import mxUtils from '../mxUtils';
import mxUtils, { equalPoints, getRotatedPoint, toRadians } from '../mxUtils';
import { clone } from '../mxCloneUtils';
/**
@ -74,14 +74,18 @@ import { clone } from '../mxCloneUtils';
* defines the absolute offset for the label inside the vertex or group.
*/
class mxGeometry extends mxRectangle {
constructor(x, y, width, height) {
constructor(
x: number = 0,
y: number = 0,
width: number = 0,
height: number = 0
) {
super(x, y, width, height);
}
/**
* Global switch to translate the points in translate. Default is true.
*/
// TRANSLATE_CONTROL_POINTS: boolean;
TRANSLATE_CONTROL_POINTS = true;
/**
@ -90,24 +94,21 @@ class mxGeometry extends mxRectangle {
*
* @see {@link swap}
*/
// alternateBounds: mxRectangle;
alternateBounds = null;
alternateBounds: mxRectangle | null = null;
/**
* Defines the source {@link mxPoint} of the edge. This is used if the
* corresponding edge does not have a source vertex. Otherwise it is
* ignored. Default is null.
*/
// sourcePoint: mxPoint;
sourcePoint = null;
sourcePoint: mxPoint | null = null;
/**
* Defines the target {@link mxPoint} of the edge. This is used if the
* corresponding edge does not have a target vertex. Otherwise it is
* ignored. Default is null.
*/
// targetPoint: mxPoint;
targetPoint = null;
targetPoint: mxPoint | null = null;
/**
* Array of {@link mxPoints} which specifies the control points along the edge.
@ -115,8 +116,7 @@ class mxGeometry extends mxRectangle {
* use {@link targetPoint} and {@link sourcePoint} or set the terminals of the edge to
* a non-null value. Default is null.
*/
// points: Array<mxPoint>;
points = null;
points: mxPoint[] = [];
/**
* For edges, this holds the offset (in pixels) from the position defined
@ -125,8 +125,7 @@ class mxGeometry extends mxRectangle {
* coordinates. For absolute geometries (for vertices), this defines the
* offset for the label. Default is null.
*/
// offset: mxPoint;
offset = null;
offset: mxPoint | null = null;
/**
* Specifies if the coordinates in the geometry are to be interpreted as
@ -141,7 +140,6 @@ class mxGeometry extends mxRectangle {
*
* Default is false.
*/
// relative: boolean;
relative = false;
/**
@ -153,9 +151,8 @@ class mxGeometry extends mxRectangle {
* calling this method and setting the geometry of the cell using
* {@link mxGraphModel.setGeometry}.
*/
// swap(): void;
swap() {
if (this.alternateBounds != null) {
if (this.alternateBounds) {
const old = new mxRectangle(this.x, this.y, this.width, this.height);
this.x = this.alternateBounds.x;
@ -173,8 +170,7 @@ class mxGeometry extends mxRectangle {
*
* @param {Boolean} isSource that specifies if the source or target point should be returned.
*/
// getTerminalPoint(isSource: boolean): mxPoint;
getTerminalPoint(isSource) {
getTerminalPoint(isSource: boolean) {
return isSource ? this.sourcePoint : this.targetPoint;
}
@ -185,8 +181,7 @@ class mxGeometry extends mxRectangle {
* @param {Point} point to be used as the new source or target point.
* @param {Boolean} isSource that specifies if the source or target point should be set.
*/
// setTerminalPoint(point: mxPoint, isSource: boolean): mxPoint;
setTerminalPoint(point, isSource) {
setTerminalPoint(point: mxPoint, isSource: boolean) {
if (isSource) {
this.sourcePoint = point;
} else {
@ -205,40 +200,39 @@ class mxGeometry extends mxRectangle {
* @param {Number} angle that specifies the rotation angle in degrees.
* @param {mxPoint} cx that specifies the center of the rotation.
*/
// rotate(angle: number, cx: mxPoint): void;
rotate(angle, cx) {
const rad = mxUtils.toRadians(angle);
rotate(angle: number, cx: mxPoint) {
const rad = toRadians(angle);
const cos = Math.cos(rad);
const sin = Math.sin(rad);
// Rotates the geometry
if (!this.relative) {
const ct = new mxPoint(this.getCenterX(), this.getCenterY());
const pt = mxUtils.getRotatedPoint(ct, cos, sin, cx);
const pt = getRotatedPoint(ct, cos, sin, cx);
this.x = Math.round(pt.x - this.width / 2);
this.y = Math.round(pt.y - this.height / 2);
}
// Rotates the source point
if (this.sourcePoint != null) {
const pt = mxUtils.getRotatedPoint(this.sourcePoint, cos, sin, cx);
if (this.sourcePoint) {
const pt = getRotatedPoint(this.sourcePoint, cos, sin, cx);
this.sourcePoint.x = Math.round(pt.x);
this.sourcePoint.y = Math.round(pt.y);
}
// Translates the target point
if (this.targetPoint != null) {
const pt = mxUtils.getRotatedPoint(this.targetPoint, cos, sin, cx);
if (this.targetPoint) {
const pt = getRotatedPoint(this.targetPoint, cos, sin, cx);
this.targetPoint.x = Math.round(pt.x);
this.targetPoint.y = Math.round(pt.y);
}
// Translate the control points
if (this.points != null) {
if (this.points) {
for (let i = 0; i < this.points.length; i += 1) {
if (this.points[i] != null) {
const pt = mxUtils.getRotatedPoint(this.points[i], cos, sin, cx);
if (this.points[i]) {
const pt = getRotatedPoint(this.points[i], cos, sin, cx);
this.points[i].x = Math.round(pt.x);
this.points[i].y = Math.round(pt.y);
}
@ -246,34 +240,6 @@ class mxGeometry extends mxRectangle {
}
}
get width() {
return this._width || 0;
}
set width(width) {
width = parseFloat(width);
// `null` is used as a default value, so comment this out for now.
// if (Number.isNaN(width)) {
// throw new Error('Invalid width supplied');
// }
this._width = width;
}
get height() {
return this._height || 0;
}
set height(height) {
height = parseFloat(height);
// `null` is used as a default value, so comment this out for now.
// if (Number.isNaN(height)) {
// throw new Error('Invalid height supplied');
// }
this._height = height;
}
/**
* Translates the geometry by the specified amount. That is, {@link x} and {@link y} of the
* geometry, the {@link sourcePoint}, {@link targetPoint} and all {@link points} are translated
@ -284,11 +250,7 @@ class mxGeometry extends mxRectangle {
* @param {Number} dx that specifies the x-coordinate of the translation.
* @param {Number} dy that specifies the y-coordinate of the translation.
*/
// translate(dx: number, dy: number): void;
translate(dx, dy) {
dx = parseFloat(dx);
dy = parseFloat(dy);
translate(dx: number, dy: number) {
// Translates the geometry
if (!this.relative) {
this.x += dx;
@ -296,21 +258,21 @@ class mxGeometry extends mxRectangle {
}
// Translates the source point
if (this.sourcePoint != null) {
if (this.sourcePoint) {
this.sourcePoint.x = this.sourcePoint.x + dx;
this.sourcePoint.y = this.sourcePoint.y + dy;
}
// Translates the target point
if (this.targetPoint != null) {
if (this.targetPoint) {
this.targetPoint.x = this.targetPoint.x + dx;
this.targetPoint.y = this.targetPoint.y + dy;
}
// Translate the control points
if (this.TRANSLATE_CONTROL_POINTS && this.points != null) {
if (this.TRANSLATE_CONTROL_POINTS && this.points) {
for (let i = 0; i < this.points.length; i += 1) {
if (this.points[i] != null) {
if (this.points[i]) {
this.points[i].x = this.points[i].x + dx;
this.points[i].y = this.points[i].y + dy;
}
@ -329,30 +291,24 @@ class mxGeometry extends mxRectangle {
* @param {Number} sy that specifies the vertical scale factor.
* @param {Optional} fixedAspect boolean to keep the aspect ratio fixed.
*/
// scale(sx: number, sy: number, fixedAspect: boolean): void;
scale(sx, sy, fixedAspect) {
sx = parseFloat(sx);
sy = parseFloat(sy);
scale(sx: number, sy: number, fixedAspect: boolean) {
// Translates the source point
if (this.sourcePoint != null) {
if (this.sourcePoint) {
this.sourcePoint.x = this.sourcePoint.x * sx;
this.sourcePoint.y = this.sourcePoint.y * sy;
}
// Translates the target point
if (this.targetPoint != null) {
if (this.targetPoint) {
this.targetPoint.x = this.targetPoint.x * sx;
this.targetPoint.y = this.targetPoint.y * sy;
}
// Translate the control points
if (this.points != null) {
for (let i = 0; i < this.points.length; i += 1) {
if (this.points[i] != null) {
this.points[i].x = this.points[i].x * sx;
this.points[i].y = this.points[i].y * sy;
}
for (let i = 0; i < this.points.length; i += 1) {
if (this.points[i]) {
this.points[i].x = this.points[i].x * sx;
this.points[i].y = this.points[i].y * sy;
}
}
@ -373,30 +329,26 @@ class mxGeometry extends mxRectangle {
/**
* Returns true if the given object equals this geometry.
*/
// equals(obj: mxGeometry): boolean;
equals(obj) {
equals(geom: mxGeometry | null) {
if (!geom) return false;
return (
super.equals(obj) &&
this.relative === obj.relative &&
((this.sourcePoint == null && obj.sourcePoint == null) ||
(this.sourcePoint != null &&
this.sourcePoint.equals(obj.sourcePoint))) &&
((this.targetPoint == null && obj.targetPoint == null) ||
(this.targetPoint != null &&
this.targetPoint.equals(obj.targetPoint))) &&
((this.points == null && obj.points == null) ||
(this.points != null &&
mxUtils.equalPoints(this.points, obj.points))) &&
((this.alternateBounds == null && obj.alternateBounds == null) ||
(this.alternateBounds != null &&
this.alternateBounds.equals(obj.alternateBounds))) &&
((this.offset == null && obj.offset == null) ||
(this.offset != null && this.offset.equals(obj.offset)))
super.equals(geom) &&
this.relative === geom.relative &&
((this.sourcePoint === null && geom.sourcePoint === null) ||
!!this.sourcePoint?.equals(geom.sourcePoint)) &&
((this.targetPoint === null && geom.targetPoint === null) ||
!!this.targetPoint?.equals(geom.targetPoint)) &&
equalPoints(this.points, geom.points) &&
((this.alternateBounds === null && geom.alternateBounds === null) ||
!!this.alternateBounds?.equals(geom.alternateBounds)) &&
((this.offset === null && geom.offset === null) ||
!!this.offset?.equals(geom.offset))
);
}
clone() {
return clone(this);
return clone(this) as mxGeometry;
}
}

View File

@ -1,70 +0,0 @@
/**
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021
* Type definitions from the typed-mxgraph project
*/
import { getFunctionName } from '../mxStringUtils';
/**
* @class
*
* Identity for JavaScript objects and functions. This is implemented using
* a simple incrementing counter which is stored in each object under
* {@link FIELD_NAME}.
*
* The identity for an object does not change during its lifecycle.
*/
class mxObjectIdentity {
/**
* Name of the field to be used to store the object ID. Default is
* <code>mxObjectId</code>.
*/
// static FIELD_NAME: string;
static FIELD_NAME = 'mxObjectId';
/**
* Current counter.
*/
// static counter: number;
static counter = 0;
/**
* Returns the ID for the given object or function or null if no object
* is specified.
*/
// static get(obj: any): any;
static get(obj) {
if (obj != null) {
if (obj[mxObjectIdentity.FIELD_NAME] == null) {
if (typeof obj === 'object') {
const ctor = getFunctionName(obj.constructor);
obj[
mxObjectIdentity.FIELD_NAME
] = `${ctor}#${mxObjectIdentity.counter++}`;
} else if (typeof obj === 'function') {
obj[
mxObjectIdentity.FIELD_NAME
] = `Function#${mxObjectIdentity.counter++}`;
}
}
return obj[mxObjectIdentity.FIELD_NAME];
}
return null;
}
/**
* Deletes the ID from the given object or function.
*/
// static clear(obj: any): void;
static clear(obj) {
if (typeof obj === 'object' || typeof obj === 'function') {
delete obj[mxObjectIdentity.FIELD_NAME];
}
}
}
export default mxObjectIdentity;

View File

@ -0,0 +1,68 @@
/**
* Copyright (c) 2006-2015, JGraph Ltd
* Copyright (c) 2006-2015, Gaudenz Alder
* Updated to ES9 syntax by David Morrissey 2021
* Type definitions from the typed-mxgraph project
*/
import { getFunctionName } from '../mxStringUtils';
import { isNullish } from '../mxUtils';
const FIELD_NAME = 'mxObjectId';
type IdentityObject = {
[FIELD_NAME]?: string;
[k: string]: any;
};
type IdentityFunction = {
(): any;
[FIELD_NAME]?: string;
};
/**
* @class
*
* Identity for JavaScript objects and functions. This is implemented using
* a simple incrementing counter which is stored in each object under
* {@link FIELD_NAME}.
*
* The identity for an object does not change during its lifecycle.
*/
class mxObjectIdentity {
/**
* Name of the field to be used to store the object ID. Default is
* <code>mxObjectId</code>.
*/
static FIELD_NAME = FIELD_NAME;
/**
* Current counter.
*/
static counter = 0;
/**
* Returns the ID for the given object or function.
*/
static get(obj: IdentityObject | IdentityFunction) {
if (isNullish(obj[FIELD_NAME])) {
if (typeof obj === 'object') {
const ctor = getFunctionName(obj.constructor);
obj[FIELD_NAME] = `${ctor}#${mxObjectIdentity.counter++}`;
} else if (typeof obj === 'function') {
obj[FIELD_NAME] = `Function#${mxObjectIdentity.counter++}`;
}
}
return obj[FIELD_NAME] as string;
}
/**
* Deletes the ID from the given object or function.
*/
static clear(obj: IdentityObject | IdentityFunction) {
delete obj[FIELD_NAME];
}
}
export default mxObjectIdentity;

View File

@ -16,9 +16,9 @@
* coordinates are given, then the default values for <x> and <y> are used.
*/
class mxPoint {
constructor(x, y) {
this.x = x != null ? x : 0;
this.y = y != null ? y : 0;
constructor(x: number = 0, y: number = 0) {
this.x = x;
this.y = y;
}
/**
@ -26,38 +26,32 @@ class mxPoint {
*
* Holds the x-coordinate of the point. Default is 0.
*/
// x: number;
_x = null;
_x = 0;
/**
* Variable: y
*
* Holds the y-coordinate of the point. Default is 0.
*/
// y: number;
_y = null;
_y = 0;
get x() {
return this._x || 0;
return this._x;
}
set x(x) {
x = parseFloat(x);
if (Number.isNaN(x)) {
throw new Error('Invalid x supplied');
}
set x(x: number) {
if (Number.isNaN(x)) throw new Error('Invalid x supplied.');
this._x = x;
}
get y() {
return this._y || 0;
return this._y;
}
set y(y) {
y = parseFloat(y);
if (Number.isNaN(y)) {
throw new Error('Invalid y supplied');
}
set y(y: number) {
if (Number.isNaN(y)) throw new Error('Invalid y supplied.');
this._y = y;
}
@ -66,9 +60,10 @@ class mxPoint {
*
* Returns true if the given object equals this point.
*/
// equals(obj: mxPoint): boolean;
equals(obj) {
return obj != null && obj.x == this.x && obj.y == this.y;
equals(p: mxPoint | null) {
if (!p) return false;
return p.x === this.x && p.y === this.y;
}
/**
@ -76,7 +71,6 @@ class mxPoint {
*
* Returns a clone of this <mxPoint>.
*/
// clone(): mxPoint;
clone() {
return new mxPoint(this.x, this.y);
}

View File

@ -19,12 +19,17 @@ import mxPoint from './mxPoint';
* are given then the respective default values are used.
*/
class mxRectangle extends mxPoint {
constructor(x, y, width, height) {
constructor(
x: number = 0,
y: number = 0,
width: number = 0,
height: number = 0
) {
super(x, y);
// replace super of mxPoint
this.width = width != null ? width : 0;
this.height = height != null ? height : 0;
this.width = width;
this.height = height;
}
/**
@ -32,24 +37,41 @@ class mxRectangle extends mxPoint {
*
* Holds the width of the rectangle. Default is 0.
*/
// width: number;
width = null;
_width = 0;
/**
* Variable: height
*
* Holds the height of the rectangle. Default is 0.
*/
// height: number;
height = null;
_height = 0;
get width() {
return this._width;
}
set width(width: number) {
if (Number.isNaN(width)) throw new Error('Invalid width supplied.');
this._width = width;
}
get height() {
return this._height;
}
set height(height: number) {
if (Number.isNaN(height)) throw new Error('Invalid height supplied.');
this._height = height;
}
/**
* Function: fromRectangle
*
* Returns a new <mxRectangle> which is a copy of the given rectangle.
*/
// static fromRectangle(rect: mxRectangle): mxRectangle;
static fromRectangle = rect => {
static fromRectangle = (rect: mxRectangle) => {
return new mxRectangle(rect.x, rect.y, rect.width, rect.height);
};
@ -58,12 +80,11 @@ class mxRectangle extends mxPoint {
*
* Sets this rectangle to the specified values
*/
// setRect(x: number, y: number, w: number, h: number): void;
setRect(x, y, w, h) {
setRect(x: number, y: number, width: number, height: number) {
this.x = x;
this.y = y;
this.width = w;
this.height = h;
this.width = width;
this.height = height;
}
/**
@ -71,7 +92,6 @@ class mxRectangle extends mxPoint {
*
* Returns the x-coordinate of the center point.
*/
// getCenterX(): number;
getCenterX() {
return this.x + this.width / 2;
}
@ -81,7 +101,6 @@ class mxRectangle extends mxPoint {
*
* Returns the y-coordinate of the center point.
*/
// getCenterY(): number;
getCenterY() {
return this.y + this.height / 2;
}
@ -91,19 +110,16 @@ class mxRectangle extends mxPoint {
*
* Adds the given rectangle to this rectangle.
*/
// add(rect: mxRectangle): void;
add(rect) {
if (rect != null) {
const minX = Math.min(this.x, rect.x);
const minY = Math.min(this.y, rect.y);
const maxX = Math.max(this.x + this.width, rect.x + rect.width);
const maxY = Math.max(this.y + this.height, rect.y + rect.height);
add(rect: mxRectangle) {
const minX = Math.min(this.x, rect.x);
const minY = Math.min(this.y, rect.y);
const maxX = Math.max(this.x + this.width, rect.x + rect.width);
const maxY = Math.max(this.y + this.height, rect.y + rect.height);
this.x = minX;
this.y = minY;
this.width = maxX - minX;
this.height = maxY - minY;
}
this.x = minX;
this.y = minY;
this.width = maxX - minX;
this.height = maxY - minY;
}
/**
@ -111,20 +127,17 @@ class mxRectangle extends mxPoint {
*
* Changes this rectangle to where it overlaps with the given rectangle.
*/
// intersect(rect: mxRectangle): void;
intersect(rect) {
if (rect != null) {
const r1 = this.x + this.width;
const r2 = rect.x + rect.width;
intersect(rect: mxRectangle) {
const r1 = this.x + this.width;
const r2 = rect.x + rect.width;
const b1 = this.y + this.height;
const b2 = rect.y + rect.height;
const b1 = this.y + this.height;
const b2 = rect.y + rect.height;
this.x = Math.max(this.x, rect.x);
this.y = Math.max(this.y, rect.y);
this.width = Math.min(r1, r2) - this.x;
this.height = Math.min(b1, b2) - this.y;
}
this.x = Math.max(this.x, rect.x);
this.y = Math.max(this.y, rect.y);
this.width = Math.min(r1, r2) - this.x;
this.height = Math.min(b1, b2) - this.y;
}
/**
@ -134,14 +147,11 @@ class mxRectangle extends mxPoint {
* the given amount from the x- and y-coordinates and adds twice the amount
* to the width and height.
*/
// grow(amount: number): void;
grow(amount) {
grow(amount: number) {
this.x -= amount;
this.y -= amount;
this.width += 2 * amount;
this.height += 2 * amount;
return this;
}
/**
@ -149,7 +159,6 @@ class mxRectangle extends mxPoint {
*
* Returns the top, left corner as a new <mxPoint>.
*/
// getPoint(): mxPoint;
getPoint() {
return new mxPoint(this.x, this.y);
}
@ -159,11 +168,11 @@ class mxRectangle extends mxPoint {
*
* Rotates this rectangle by 90 degree around its center point.
*/
// rotate90(): void;
rotate90() {
const t = (this.width - this.height) / 2;
this.x += t;
this.y -= t;
const tmp = this.width;
this.width = this.height;
this.height = tmp;
@ -174,14 +183,14 @@ class mxRectangle extends mxPoint {
*
* Returns true if the given object equals this rectangle.
*/
// equals(obj: mxRectangle): boolean;
equals(obj) {
equals(rect: mxRectangle | null) {
if (!rect) return false;
return (
obj != null &&
obj.x === this.x &&
obj.y === this.y &&
obj.width === this.width &&
obj.height === this.height
rect.x === this.x &&
rect.y === this.y &&
rect.width === this.width &&
rect.height === this.height
);
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -126,3 +126,138 @@ export const getViewXml = (graph, scale, cells, x0, y0) => {
return result;
};
/**
* Function: getXml
*
* Returns the XML content of the specified node. For Internet Explorer,
* all \r\n\t[\t]* are removed from the XML string and the remaining \r\n
* are replaced by \n. All \n are then replaced with linefeed, or &#xa; if
* no linefeed is defined.
*
* Parameters:
*
* node - DOM node to return the XML for.
* linefeed - Optional string that linefeeds are converted into. Default is
* &#xa;
*/
export const getXml = (node, linefeed) => {
let xml = '';
if (window.XMLSerializer != null) {
const xmlSerializer = new XMLSerializer();
xml = xmlSerializer.serializeToString(node);
} else if (node.xml != null) {
xml = node.xml
.replace(/\r\n\t[\t]*/g, '')
.replace(/>\r\n/g, '>')
.replace(/\r\n/g, '\n');
}
// Replaces linefeeds with HTML Entities.
linefeed = linefeed || '&#xa;';
xml = xml.replace(/\n/g, linefeed);
return xml;
};
/**
* Function: getPrettyXML
*
* Returns a pretty printed string that represents the XML tree for the
* given node. This method should only be used to print XML for reading,
* use <getXml> instead to obtain a string for processing.
*
* Parameters:
*
* node - DOM node to return the XML for.
* tab - Optional string that specifies the indentation for one level.
* Default is two spaces.
* indent - Optional string that represents the current indentation.
* Default is an empty string.
* newline - Option string that represents a linefeed. Default is '\n'.
*/
export const getPrettyXml = (node, tab, indent, newline, ns) => {
const result = [];
if (node != null) {
tab = tab != null ? tab : ' ';
indent = indent != null ? indent : '';
newline = newline != null ? newline : '\n';
if (node.namespaceURI != null && node.namespaceURI !== ns) {
ns = node.namespaceURI;
if (node.getAttribute('xmlns') == null) {
node.setAttribute('xmlns', node.namespaceURI);
}
}
if (node.nodeType === NODETYPE_DOCUMENT) {
result.push(
mxUtils.getPrettyXml(node.documentElement, tab, indent, newline, ns)
);
} else if (node.nodeType === NODETYPE_DOCUMENT_FRAGMENT) {
let tmp = node.firstChild;
if (tmp != null) {
while (tmp != null) {
result.push(mxUtils.getPrettyXml(tmp, tab, indent, newline, ns));
tmp = tmp.nextSibling;
}
}
} else if (node.nodeType === NODETYPE_COMMENT) {
const value = getTextContent(node);
if (value.length > 0) {
result.push(`${indent}<!--${value}-->${newline}`);
}
} else if (node.nodeType === NODETYPE_TEXT) {
const value = trim(getTextContent(node));
if (value.length > 0) {
result.push(indent + htmlEntities(value, false) + newline);
}
} else if (node.nodeType === NODETYPE_CDATA) {
const value = getTextContent(node);
if (value.length > 0) {
result.push(`${indent}<![CDATA[${value}]]${newline}`);
}
} else {
result.push(`${indent}<${node.nodeName}`);
// Creates the string with the node attributes
// and converts all HTML entities in the values
const attrs = node.attributes;
if (attrs != null) {
for (let i = 0; i < attrs.length; i += 1) {
const val = htmlEntities(attrs[i].value);
result.push(` ${attrs[i].nodeName}="${val}"`);
}
}
// Recursively creates the XML string for each child
// node and appends it here with an indentation
let tmp = node.firstChild;
if (tmp != null) {
result.push(`>${newline}`);
while (tmp != null) {
result.push(
mxUtils.getPrettyXml(tmp, tab, indent + tab, newline, ns)
);
tmp = tmp.nextSibling;
}
result.push(`${indent}</${node.nodeName}>${newline}`);
} else {
result.push(` />${newline}`);
}
}
}
return result.join('');
};

View File

@ -21,7 +21,6 @@ class mxUrlConverter {
*
* Specifies if the converter is enabled. Default is true.
*/
// enabled: boolean;
enabled = true;
/**
@ -29,23 +28,20 @@ class mxUrlConverter {
*
* Specifies the base URL to be used as a prefix for relative URLs.
*/
// baseUrl: string;
baseUrl = null;
baseUrl: string | null = null;
/**
* Variable: baseDomain
*
* Specifies the base domain to be used as a prefix for absolute URLs.
*/
// baseDomain: string;
baseDomain = null;
baseDomain: string | null = null;
/**
* Function: updateBaseUrl
*
* Private helper function to update the base URL.
*/
// updateBaseUrl(): void;
updateBaseUrl() {
this.baseDomain = `${location.protocol}//${location.host}`;
this.baseUrl = this.baseDomain + location.pathname;
@ -62,7 +58,6 @@ class mxUrlConverter {
*
* Returns <enabled>.
*/
// isEnabled(): boolean;
isEnabled() {
return this.enabled;
}
@ -72,8 +67,7 @@ class mxUrlConverter {
*
* Sets <enabled>.
*/
// setEnabled(value: boolean): void;
setEnabled(value) {
setEnabled(value: boolean) {
this.enabled = value;
}
@ -82,7 +76,6 @@ class mxUrlConverter {
*
* Returns <baseUrl>.
*/
// getBaseUrl(): string;
getBaseUrl() {
return this.baseUrl;
}
@ -92,8 +85,7 @@ class mxUrlConverter {
*
* Sets <baseUrl>.
*/
// setBaseUrl(value: string): void;
setBaseUrl(value) {
setBaseUrl(value: string) {
this.baseUrl = value;
}
@ -102,7 +94,6 @@ class mxUrlConverter {
*
* Returns <baseDomain>.
*/
// getBaseDomain(): string;
getBaseDomain() {
return this.baseDomain;
}
@ -112,8 +103,7 @@ class mxUrlConverter {
*
* Sets <baseDomain>.
*/
// setBaseDomain(value: string): void;
setBaseDomain(value) {
setBaseDomain(value: string) {
this.baseDomain = value;
}
@ -122,15 +112,14 @@ class mxUrlConverter {
*
* Returns true if the given URL is relative.
*/
// isRelativeUrl(url: string): boolean;
isRelativeUrl(url) {
isRelativeUrl(url: string) {
return (
url != null &&
url.substring(0, 2) != '//' &&
url.substring(0, 7) != 'http://' &&
url.substring(0, 8) != 'https://' &&
url.substring(0, 10) != 'data:image' &&
url.substring(0, 7) != 'file://'
url &&
url.substring(0, 2) !== '//' &&
url.substring(0, 7) !== 'http://' &&
url.substring(0, 8) !== 'https://' &&
url.substring(0, 10) !== 'data:image' &&
url.substring(0, 7) !== 'file://'
);
}
@ -140,14 +129,13 @@ class mxUrlConverter {
* Converts the given URL to an absolute URL with protol and domain.
* Relative URLs are first converted to absolute URLs.
*/
// convert(url: string): string;
convert(url) {
convert(url: string) {
if (this.isEnabled() && this.isRelativeUrl(url)) {
if (this.getBaseUrl() == null) {
if (!this.getBaseUrl()) {
this.updateBaseUrl();
}
if (url.charAt(0) == '/') {
if (url.charAt(0) === '/') {
url = this.getBaseDomain() + url;
} else {
url = this.getBaseUrl() + url;

View File

@ -9,6 +9,8 @@ import mxEvent from '../event/mxEvent';
import mxEventObject from '../event/mxEventObject';
import mxEventSource from '../event/mxEventSource';
import type { UndoableChange } from '../../types';
/**
* Class: mxUndoableEdit
*
@ -75,7 +77,7 @@ class mxUndoableEdit {
* expected to either have an undo and redo function, or an execute
* function. Default is an empty array.
*/
changes: any[] = [];
changes: UndoableChange[] = [];
/**
* Variable: significant
@ -83,32 +85,28 @@ class mxUndoableEdit {
* Specifies if the undoable change is significant.
* Default is true.
*/
// significant: boolean;
significant: boolean = true;
significant = true;
/**
* Variable: undone
*
* Specifies if this edit has been undone. Default is false.
*/
// undone: boolean;
undone: boolean = false;
undone = false;
/**
* Variable: redone
*
* Specifies if this edit has been redone. Default is false.
*/
// redone: boolean;
redone: boolean = false;
redone = false;
/**
* Function: isEmpty
*
* Returns true if the this edit contains no changes.
*/
// isEmpty(): boolean;
isEmpty(): boolean {
isEmpty() {
return this.changes.length === 0;
}
@ -117,8 +115,7 @@ class mxUndoableEdit {
*
* Returns <significant>.
*/
// isSignificant(): boolean;
isSignificant(): boolean {
isSignificant() {
return this.significant;
}
@ -128,9 +125,8 @@ class mxUndoableEdit {
* Adds the specified change to this edit. The change is an object that is
* expected to either have an undo and redo, or an execute function.
*/
// add(change: mxUndoableChange): void;
add(change: any): void {
// FIXME!!!
add(change: UndoableChange) {
this.changes.push(change);
}
@ -140,8 +136,7 @@ class mxUndoableEdit {
* Hook to notify any listeners of the changes after an <undo> or <redo>
* has been carried out. This implementation is empty.
*/
// notify(): void;
notify(): void {}
notify() {}
/**
* Function: die
@ -149,16 +144,14 @@ class mxUndoableEdit {
* Hook to free resources after the edit has been removed from the command
* history. This implementation is empty.
*/
// die(): void;
die(): void {}
die() {}
/**
* Function: undo
*
* Undoes all changes in this edit.
*/
// undo(): void;
undo(): void {
undo() {
if (!this.undone) {
this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));
const count = this.changes.length;
@ -166,9 +159,9 @@ class mxUndoableEdit {
for (let i = count - 1; i >= 0; i--) {
const change = this.changes[i];
if (change.execute != null) {
if (change.execute) {
change.execute();
} else if (change.undo != null) {
} else if (change.undo) {
change.undo();
}
@ -182,6 +175,7 @@ class mxUndoableEdit {
this.redone = false;
this.source.fireEvent(new mxEventObject(mxEvent.END_EDIT));
}
this.notify();
}
@ -190,8 +184,7 @@ class mxUndoableEdit {
*
* Redoes all changes in this edit.
*/
// redo(): void;
redo(): void {
redo() {
if (!this.redone) {
this.source.fireEvent(new mxEventObject(mxEvent.START_EDIT));
const count = this.changes.length;
@ -215,6 +208,7 @@ class mxUndoableEdit {
this.redone = true;
this.source.fireEvent(new mxEventObject(mxEvent.END_EDIT));
}
this.notify();
}
}

View File

@ -12,6 +12,9 @@ import { clone } from '../../util/mxCloneUtils';
import mxPoint from '../../util/datatypes/mxPoint';
import mxCellPath from './mxCellPath';
import mxCellArray from "./mxCellArray";
import { isNotNullish } from '../../util/mxUtils';
import type { FilterFunction } from '../../types';
/**
* Cells are the elements of the graph model. They represent the state
@ -68,7 +71,7 @@ class mxCell {
this.setGeometry(geometry);
this.setStyle(style);
if (this.onInit != null) {
if (this.onInit) {
this.onInit();
}
}
@ -82,10 +85,10 @@ class mxCell {
// used by invalidate() of mxGraphView
invalidating: boolean = false;
onInit: Function | null = null;
onInit: (() => void) | null = null;
// used by addCellOverlay() of mxGraph
overlays: mxCellOverlay[] | null = null;
overlays: mxCellOverlay[] = [];
/**
* Holds the Id. Default is null.
@ -201,7 +204,7 @@ class mxCell {
* Sets the user object of the cell. The user object
* is stored in <value>.
*/
setValue(value: number): void {
setValue(value: any): void {
this.value = value;
}
@ -227,7 +230,7 @@ class mxCell {
/**
* Sets the <mxGeometry> to be used as the <geometry>.
*/
setGeometry(geometry: mxGeometry | null): void {
setGeometry(geometry: mxGeometry | null) {
this.geometry = geometry;
}
@ -241,7 +244,7 @@ class mxCell {
/**
* Sets the string to be used as the <style>.
*/
setStyle(style: string | null): void {
setStyle(style: string | null) {
this.style = style;
}
@ -351,7 +354,7 @@ class mxCell {
*
* @param parent<mxCell> that represents the new parent.
*/
setParent(parent: mxCell | null): void {
setParent(parent: mxCell | null) {
this.parent = parent;
}
@ -363,7 +366,7 @@ class mxCell {
* @param source Boolean that specifies if the source terminal should be
* returned.
*/
getTerminal(source: boolean = false): mxCell | null {
getTerminal(source: boolean = false) {
return source ? this.source : this.target;
}
@ -374,12 +377,13 @@ class mxCell {
* @param {boolean} isSource boolean that specifies if the source or target terminal
* should be set.
*/
setTerminal(terminal: mxCell | null, isSource: boolean): mxCell | null {
setTerminal(terminal: mxCell | null, isSource: boolean) {
if (isSource) {
this.source = terminal;
} else {
this.target = terminal;
}
return terminal;
}
@ -387,7 +391,7 @@ class mxCell {
* Returns the number of child cells.
*/
getChildCount(): number {
return this.children == null ? 0 : this.children.length;
return this.children.length;
}
/**
@ -397,8 +401,8 @@ class mxCell {
*
* @param childChild whose index should be returned.
*/
getIndex(child: mxCell | null): number {
if (child === null || !this.children) return -1;
getIndex(child: mxCell | null) {
if (child === null) return -1;
return this.children.indexOf(child);
}
@ -410,7 +414,7 @@ class mxCell {
* @param indexInteger that specifies the child to be returned.
*/
getChildAt(index: number): mxCell | null {
return this.children == null ? null : this.children[index];
return this.children[index];
}
/**
@ -425,8 +429,8 @@ class mxCell {
* @param indexOptional integer that specifies the index at which the child
* should be inserted into the child array.
*/
insert(child: mxCell, index: number | null = null): mxCell | null {
if (index == null) {
insert(child: mxCell, index?: number): mxCell | null {
if (index === undefined) {
index = this.getChildCount();
if (child.getParent() === this) {
@ -437,12 +441,8 @@ class mxCell {
child.removeFromParent();
child.setParent(this);
if (this.children == null) {
this.children = new mxCellArray();
this.children.push(child);
} else {
this.children.splice(index, 0, child);
}
this.children.splice(index, 0, child);
return child;
}
@ -458,13 +458,15 @@ class mxCell {
*/
remove(index: number): mxCell | null {
let child = null;
if (this.children != null && index >= 0) {
if (index >= 0) {
child = this.getChildAt(index);
if (child != null) {
if (child) {
this.children.splice(index, 1);
child.setParent(null);
}
}
return child;
}
@ -472,7 +474,7 @@ class mxCell {
* Removes the cell from its parent.
*/
removeFromParent(): void {
if (this.parent != null) {
if (this.parent) {
const index = this.parent.getIndex(this);
this.parent.remove(index);
}
@ -481,8 +483,8 @@ class mxCell {
/**
* Returns the number of edges in the edge array.
*/
getEdgeCount(): number {
return this.edges == null ? 0 : this.edges.length;
getEdgeCount() {
return this.edges.length;
}
/**
@ -492,8 +494,7 @@ class mxCell {
*
* @param edge<mxCell> whose index in <edges> should be returned.
*/
getEdgeIndex(edge: mxCell): number {
if (!this.edges) return -1;
getEdgeIndex(edge: mxCell) {
return this.edges.indexOf(edge);
}
@ -504,8 +505,8 @@ class mxCell {
*
* @param indexInteger that specifies the index of the edge to be returned.
*/
getEdgeAt(index: number): mxCell | null {
return this.edges == null ? null : this.edges[index];
getEdgeAt(index: number) {
return this.edges[index];
}
/**
@ -517,22 +518,18 @@ class mxCell {
* @param edge <mxCell> to be inserted into the edge array.
* @param isOutgoing Boolean that specifies if the edge is outgoing.
*/
insertEdge(edge: mxCell | null, isOutgoing: boolean) {
if (edge != null) {
edge.removeFromTerminal(isOutgoing);
edge.setTerminal(this, isOutgoing);
insertEdge(edge: mxCell, isOutgoing: boolean = false) {
edge.removeFromTerminal(isOutgoing);
edge.setTerminal(this, isOutgoing);
if (
this.edges == null ||
edge.getTerminal(!isOutgoing) !== this ||
this.edges.indexOf(edge) < 0
) {
if (this.edges == null) {
this.edges = new mxCellArray();
}
this.edges.push(edge);
}
if (
this.edges.length === 0 ||
edge.getTerminal(!isOutgoing) !== this ||
this.edges.indexOf(edge) < 0
) {
this.edges.push(edge);
}
return edge;
}
@ -550,12 +547,13 @@ class mxCell {
if (edge.getTerminal(!isOutgoing) !== this && this.edges != null) {
const index = this.getEdgeIndex(edge);
if (index >= 0) {
this.edges.splice(index, 1);
}
if (index >= 0) {
this.edges.splice(index, 1);
}
edge.setTerminal(null, isOutgoing);
}
edge.setTerminal(null, isOutgoing);
return edge;
}
@ -568,7 +566,8 @@ class mxCell {
*/
removeFromTerminal(isSource: boolean): void {
const terminal = this.getTerminal(isSource);
if (terminal != null) {
if (terminal) {
terminal.removeEdge(this, isSource);
}
}
@ -583,11 +582,12 @@ class mxCell {
*/
hasAttribute(name: string): boolean {
const userObject = this.getValue();
return (
userObject != null &&
isNotNullish(userObject) &&
(userObject.nodeType === NODETYPE_ELEMENT && userObject.hasAttribute
? userObject.hasAttribute(name)
: userObject.getAttribute(name) != null)
: isNotNullish(userObject.getAttribute(name)))
);
}
@ -604,10 +604,11 @@ class mxCell {
getAttribute(name: string, defaultValue: any): any {
const userObject = this.getValue();
const val =
userObject != null && userObject.nodeType === NODETYPE_ELEMENT
isNotNullish(userObject) && userObject.nodeType === NODETYPE_ELEMENT
? userObject.getAttribute(name)
: null;
return val != null ? val : defaultValue;
return val ? val : defaultValue;
}
/**
@ -620,7 +621,8 @@ class mxCell {
*/
setAttribute(name: string, value: any): void {
const userObject = this.getValue();
if (userObject != null && userObject.nodeType === NODETYPE_ELEMENT) {
if (isNotNullish(userObject) && userObject.nodeType === NODETYPE_ELEMENT) {
userObject.setAttribute(name, value);
}
}
@ -641,10 +643,10 @@ class mxCell {
*/
cloneValue(): any {
let value = this.getValue();
if (value != null) {
if (isNotNullish(value)) {
if (typeof value.clone === 'function') {
value = value.clone();
} else if (value.nodeType != null) {
} else if (isNotNullish(value.nodeType)) {
value = value.cloneNode(true);
}
}
@ -660,11 +662,11 @@ class mxCell {
// Creates the cell path for the second cell
let path = mxCellPath.create(cell2);
if (path != null && path.length > 0) {
if (path.length > 0) {
// Bubbles through the ancestors of the first
// cell to find the nearest common ancestor.
let cell: mxCell | null = this;
let current: string | null = mxCellPath.create(<mxCell>cell);
let current: string | null = mxCellPath.create(cell);
// Inverts arguments
if (path.length < current.length) {
@ -674,18 +676,15 @@ class mxCell {
path = tmp;
}
while (cell != null) {
const parent = <mxCell>cell.getParent();
while (cell && current) {
const parent: mxCell | null = cell.getParent();
// Checks if the cell path is equal to the beginning of the given cell path
if (
path.indexOf(current + mxCellPath.PATH_SEPARATOR) === 0 &&
parent != null
) {
if (path.indexOf(current + mxCellPath.PATH_SEPARATOR) === 0 && parent) {
return cell;
}
current = mxCellPath.getParentPath(<string>current);
current = mxCellPath.getParentPath(current);
cell = parent;
}
}
@ -699,10 +698,11 @@ class mxCell {
*
* @param {mxCell} child that specifies the child.
*/
isAncestor(child: mxCell | null): boolean {
while (child != null && child !== this) {
child = <mxCell>child.getParent();
isAncestor(child: mxCell | null) {
while (child && child !== this) {
child = child.getParent();
}
return child === this;
}
@ -734,7 +734,7 @@ class mxCell {
const result = new mxCellArray();
for (let i = 0; i < childCount; i += 1) {
const child = <mxCell>this.getChildAt(i);
const child = this.getChildAt(i);
if (
(!edges && !vertices) ||
@ -744,6 +744,7 @@ class mxCell {
result.push(child);
}
}
return result;
}
@ -757,8 +758,7 @@ class mxCell {
*/
getDirectedEdgeCount(
outgoing: boolean,
ignoredEdge: mxCell | null = null
): number {
ignoredEdge: mxCell | null = null) {
let count = 0;
const edgeCount = this.getEdgeCount();
@ -768,6 +768,7 @@ class mxCell {
count += 1;
}
}
return count;
}
@ -814,7 +815,7 @@ class mxCell {
const result = new mxCellArray();
for (let i = 0; i < edgeCount; i += 1) {
const edge = <mxCell>this.getEdgeAt(i);
const edge = this.getEdgeAt(i);
const source = edge.getTerminal(true);
const target = edge.getTerminal(false);
@ -834,24 +835,23 @@ class mxCell {
* Returns the absolute, accumulated origin for the children inside the
* given parent as an {@link mxPoint}.
*/
// getOrigin(cell: mxCell): mxPoint;
getOrigin(): mxPoint {
let result = null;
let result = new mxPoint();
const parent = this.getParent();
if (this != null && this.getParent()) {
result = (<mxCell>this.getParent()).getOrigin();
if (parent) {
result = parent.getOrigin();
if (!this.isEdge()) {
const geo = this.getGeometry();
if (geo != null) {
if (geo) {
result.x += geo.x;
result.y += geo.y;
}
}
} else {
result = new mxPoint();
}
return result;
}
@ -881,25 +881,20 @@ class mxCell {
* @param filter JavaScript function that takes an {@link mxCell} as an argument
* and returns a boolean.
*/
filterDescendants(filter: Function | null): mxCellArray {
let parent = this;
filterDescendants(filter: FilterFunction | null): mxCellArray {
// Creates a new array for storing the result
let result = new mxCellArray();
// Recursion starts at the root of the model
parent = parent || this.getRoot();
// Checks if the filter returns true for the cell
// and adds it to the result array
if (filter == null || filter(parent)) {
result.push(parent);
if (filter === null || filter(this)) {
result.push(this);
}
// Visits the children of the cell
const childCount = parent.getChildCount();
const childCount = this.getChildCount();
for (let i = 0; i < childCount; i += 1) {
const child = <mxCell>parent.getChildAt(i);
const child = this.getChildAt(i);
result = new mxCellArray(...result.concat(child.filterDescendants(filter)));
}
@ -913,13 +908,13 @@ class mxCell {
let root: mxCell = this;
let cell: mxCell = this;
while (cell != null) {
while (cell) {
root = cell;
cell = <mxCell>cell.getParent();
cell = cell.getParent();
}
return root;
}
}
export default mxCell;
// import('../../serialization/mxCellCodec');

View File

@ -18,7 +18,6 @@ class mxCellPath {
/**
* Defines the separator between the path components. Default is ".".
*/
// static PATH_SEPARATOR: string;
static PATH_SEPARATOR = '.';
/**
@ -30,20 +29,16 @@ class mxCellPath {
*
* cell - Cell whose path should be returned.
*/
// static create(cell: mxCell): string;
static create(cell: mxCell): string {
let result = '';
let parent = cell.getParent();
if (cell != null) {
let parent = cell.getParent();
while (parent) {
const index = parent.getIndex(cell);
result = index + mxCellPath.PATH_SEPARATOR + result;
while (parent != null) {
const index = parent.getIndex(cell);
result = index + mxCellPath.PATH_SEPARATOR + result;
cell = parent;
parent = cell.getParent();
}
cell = parent;
parent = cell.getParent();
}
// Remove trailing separator
@ -62,18 +57,16 @@ class mxCellPath {
*
* path - Path whose parent path should be returned.
*/
// static getParentPath(path: string): string;
static getParentPath(path: string): string | null {
if (path != null) {
const index = path.lastIndexOf(mxCellPath.PATH_SEPARATOR);
static getParentPath(path: string) {
const index = path.lastIndexOf(mxCellPath.PATH_SEPARATOR);
if (index >= 0) {
return path.substring(0, index);
}
if (path.length > 0) {
return '';
}
if (index >= 0) {
return path.substring(0, index);
}
if (path.length > 0) {
return '';
}
return null;
}
@ -86,15 +79,14 @@ class mxCellPath {
* root - Root cell of the path to be resolved.
* path - String that defines the path.
*/
// static resolve(root: string, path: string): string;
static resolve(root: mxCell, path: string): mxCell | null {
let parent: mxCell | null | undefined = root;
if (path != null) {
const tokens = path.split(mxCellPath.PATH_SEPARATOR);
for (let i = 0; i < tokens.length; i += 1) {
parent = parent?.getChildAt(parseInt(tokens[i])) || null;
}
static resolve(root: mxCell, path: string) {
let parent: mxCell | null = root;
const tokens = path.split(mxCellPath.PATH_SEPARATOR);
for (let i = 0; i < tokens.length; i += 1) {
parent = parent.getChildAt(parseInt(tokens[i]));
}
return parent;
}
@ -102,8 +94,7 @@ class mxCellPath {
* Compares the given cell paths and returns -1 if p1 is smaller, 0 if
* p1 is equal and 1 if p1 is greater than p2.
*/
// static compare(p1: string, p2: string): number;
static compare(p1: string, p2: string): number {
static compare(p1: string[], p2: string[]) {
const min = Math.min(p1.length, p2.length);
let comp = 0;

View File

@ -47,7 +47,7 @@ import {
SHAPE_SWIMLANE,
SHAPE_TRIANGLE,
} from '../../util/mxConstants';
import mxUtils from '../../util/mxUtils';
import mxUtils, { convertPoint, getValue } from '../../util/mxUtils';
import mxRectangle from '../../util/datatypes/mxRectangle';
import mxStencilRegistry from '../../shape/node/mxStencilRegistry';
import mxEvent from '../../util/event/mxEvent';
@ -111,7 +111,6 @@ class mxCellRenderer {
*
* Defines the default shape for edges. Default is <mxConnector>.
*/
// defaultEdgeShape: mxConnector;
defaultEdgeShape: typeof mxShape = mxConnector;
/**
@ -119,7 +118,6 @@ class mxCellRenderer {
*
* Defines the default shape for vertices. Default is <mxRectangleShape>.
*/
// defaultVertexShape: mxRectangleShape;
defaultVertexShape: typeof mxRectangleShape = mxRectangleShape;
/**
@ -127,7 +125,6 @@ class mxCellRenderer {
*
* Defines the default shape for labels. Default is <mxText>.
*/
// defaultTextShape: mxText;
defaultTextShape: typeof mxText = mxText;
/**
@ -136,8 +133,7 @@ class mxCellRenderer {
* Specifies if the folding icon should ignore the horizontal
* orientation of a swimlane. Default is true.
*/
// legacyControlPosition: boolean;
legacyControlPosition: boolean = true;
legacyControlPosition = true;
/**
* Variable: legacySpacing
@ -145,24 +141,21 @@ class mxCellRenderer {
* Specifies if spacing and label position should be ignored if overflow is
* fill or width. Default is true for backwards compatiblity.
*/
// legacySpacing: boolean;
legacySpacing: boolean = true;
legacySpacing = true;
/**
* Variable: antiAlias
*
* Anti-aliasing option for new shapes. Default is true.
*/
// antiAlias: boolean;
antiAlias: boolean = true;
antiAlias = true;
/**
* Variable: minSvgStrokeWidth
*
* Minimum stroke width for SVG output.
*/
// minSvgStrokeWidth: number;
minSvgStrokeWidth: number = 1;
minSvgStrokeWidth = 1;
/**
* Variable: forceControlClickHandler
@ -170,8 +163,7 @@ class mxCellRenderer {
* Specifies if the enabled state of the graph should be ignored in the control
* click handler (to allow folding in disabled graphs). Default is false.
*/
// forceControlClickHandler: boolean;
forceControlClickHandler: boolean = false;
forceControlClickHandler = false;
/**
* Registers the given constructor under the specified key in this instance of the renderer.
@ -183,7 +175,6 @@ class mxCellRenderer {
* @param key the shape name.
* @param shape constructor of the {@link mxShape} subclass.
*/
// static registerShape(key: string, shape: new (...args: any) => mxShape): void;
static registerShape(key: string, shape: typeof mxShape) {
mxCellRenderer.defaultShapes[key] = shape;
}
@ -198,11 +189,12 @@ class mxCellRenderer {
*
* state - <mxCellState> for which the shape should be initialized.
*/
// initializeShape(state: mxCellState): void;
initializeShape(state: mxCellState) {
(<mxShape>state.shape).dialect = state.view.graph.dialect;
this.configureShape(state);
(<mxShape>state.shape).init(state.view.getDrawPane());
if (state.shape) {
state.shape.dialect = state.view.graph.dialect;
this.configureShape(state);
state.shape.init(state.view.getDrawPane());
}
}
/**
@ -214,21 +206,20 @@ class mxCellRenderer {
*
* state - <mxCellState> for which the shape should be created.
*/
// createShape(state: mxCellState): mxShape;
createShape(state: mxCellState): mxShape | null {
createShape(state: mxCellState) {
let shape = null;
if (state.style != null) {
// Checks if there is a stencil for the name and creates
// a shape instance for the stencil if one exists
const stencil = mxStencilRegistry.getStencil(state.style.shape);
if (stencil != null) {
shape = new mxShape(stencil);
} else {
const ctor = this.getShapeConstructor(state);
shape = new ctor();
}
// Checks if there is a stencil for the name and creates
// a shape instance for the stencil if one exists
const stencil = mxStencilRegistry.getStencil(state.style.shape);
if (stencil) {
shape = new mxShape(stencil);
} else {
const ctor = this.getShapeConstructor(state);
shape = new ctor();
}
return shape;
}
@ -241,12 +232,12 @@ class mxCellRenderer {
*
* state - <mxCellState> for which the indicator shape should be created.
*/
// createIndicatorShape(state: mxCellState): void;
createIndicatorShape(state: mxCellState): void {
// @ts-ignore
state.shape.indicatorShape = this.getShape(
<string>state.view.graph.getIndicatorShape(state)
);
createIndicatorShape(state: mxCellState) {
if (state.shape) {
state.shape.indicatorShape = this.getShape(
state.view.graph.getIndicatorShape(state)
);
}
}
/**
@ -254,10 +245,8 @@ class mxCellRenderer {
*
* Returns the shape for the given name from <defaultShapes>.
*/
// getShape(name: string): mxShape;
getShape(name: string): typeof mxShape {
// @ts-ignore
return name != null ? mxCellRenderer.defaultShapes[name] : null;
getShape(name: string | null) {
return name ? mxCellRenderer.defaultShapes[name] : null;
}
/**
@ -265,14 +254,15 @@ class mxCellRenderer {
*
* Returns the constructor to be used for creating the shape.
*/
// getShapeConstructor(state: mxCellState): any;
getShapeConstructor(state: mxCellState) {
let ctor = this.getShape(state.style.shape);
if (ctor == null) {
if (!ctor) {
ctor = <typeof mxShape>(
(state.cell.isEdge() ? this.defaultEdgeShape : this.defaultVertexShape)
);
}
return ctor;
}
@ -285,19 +275,21 @@ class mxCellRenderer {
*
* state - <mxCellState> for which the shape should be configured.
*/
// configureShape(state: mxCellState): void;
configureShape(state: mxCellState) {
const shape = <any>state.shape;
shape.apply(state);
shape.image = state.view.graph.getImage(state);
shape.indicatorColor = state.view.graph.getIndicatorColor(state);
shape.indicatorStrokeColor = state.style.indicatorStrokeColor;
shape.indicatorGradientColor = state.view.graph.getIndicatorGradientColor(
state
);
shape.indicatorDirection = state.style.indicatorDirection;
shape.indicatorImage = state.view.graph.getIndicatorImage(state);
this.postConfigureShape(state);
const shape = state.shape;
if (shape) {
shape.apply(state);
shape.image = state.view.graph.getImage(state);
shape.indicatorColor = state.view.graph.getIndicatorColor(state);
shape.indicatorStrokeColor = state.style.indicatorStrokeColor;
shape.indicatorGradientColor = state.view.graph.getIndicatorGradientColor(
state
);
shape.indicatorDirection = state.style.indicatorDirection;
shape.indicatorImage = state.view.graph.getIndicatorImage(state);
this.postConfigureShape(state);
}
}
/**
@ -330,12 +322,7 @@ class mxCellRenderer {
// LATER: Check if the color has actually changed
if (state.style != null) {
const values = ['inherit', 'swimlane', 'indicated'];
const styles = [
'fillColor',
'strokeColor',
'gradientColor',
'fontColor',
];
const styles = ['fillColor', 'strokeColor', 'gradientColor', 'fontColor'];
for (let i = 0; i < styles.length; i += 1) {
if (values.indexOf(state.style[styles[i]]) >= 0) {
@ -368,9 +355,7 @@ class mxCellRenderer {
} else if (value === 'swimlane') {
// @ts-ignore
shape[field] =
key === 'strokeColor' || key === 'fontColor'
? '#000000'
: '#ffffff';
key === 'strokeColor' || key === 'fontColor' ? '#000000' : '#ffffff';
// @ts-ignore
if (state.cell.getTerminal(false) != null) {
@ -502,7 +487,7 @@ class mxCellRenderer {
// Dispatches the drop event to the graph which
// consumes and executes the source function
const pt = mxUtils.convertPoint(graph.container, x, y);
const pt = convertPoint(graph.container, x, y);
result = <mxCellState>(
graph.view.getState(graph.getCellAt(pt.x, pt.y))
);
@ -903,7 +888,7 @@ class mxCellRenderer {
// Dispatches the drop event to the graph which
// consumes and executes the source function
const pt = mxUtils.convertPoint(graph.container, x, y);
const pt = convertPoint(graph.container, x, y);
result = <mxCellState>graph.view.getState(graph.getCellAt(pt.x, pt.y));
}
@ -1191,16 +1176,8 @@ class mxCellRenderer {
// Shape can modify its label bounds
if (state.shape != null) {
const hpos = mxUtils.getValue(
state.style,
'labelPosition',
ALIGN_CENTER
);
const vpos = mxUtils.getValue(
state.style,
'verticalLabelPosition',
ALIGN_MIDDLE
);
const hpos = getValue(state.style, 'labelPosition', ALIGN_CENTER);
const vpos = getValue(state.style, 'verticalLabelPosition', ALIGN_MIDDLE);
if (hpos === ALIGN_CENTER && vpos === ALIGN_MIDDLE) {
bounds = state.shape.getLabelBounds(bounds);
@ -1208,7 +1185,7 @@ class mxCellRenderer {
}
// Label width style overrides actual label width
const lw = mxUtils.getValue(state.style, 'labelWidth', null);
const lw = getValue(state.style, 'labelWidth', null);
if (lw != null) {
bounds.width = parseFloat(lw) * scale;
@ -1240,8 +1217,7 @@ class mxCellRenderer {
if (
!this.legacySpacing ||
(state.style.overflow !== 'fill' &&
state.style.overflow !== 'width')
(state.style.overflow !== 'fill' && state.style.overflow !== 'width')
) {
const s = state.view.scale;
// @ts-ignore
@ -1249,17 +1225,9 @@ class mxCellRenderer {
bounds.x += spacing.x * s;
bounds.y += spacing.y * s;
const hpos = mxUtils.getValue(
state.style,
'labelPosition',
ALIGN_CENTER
);
const vpos = mxUtils.getValue(
state.style,
'verticalLabelPosition',
ALIGN_MIDDLE
);
const lw = mxUtils.getValue(state.style, 'labelWidth', null);
const hpos = getValue(state.style, 'labelPosition', ALIGN_CENTER);
const vpos = getValue(state.style, 'verticalLabelPosition', ALIGN_MIDDLE);
const lw = getValue(state.style, 'labelWidth', null);
bounds.width = Math.max(
0,
@ -1294,7 +1262,7 @@ class mxCellRenderer {
if (bounds.x !== cx || bounds.y !== cy) {
const rad = theta * (Math.PI / 180);
const pt = mxUtils.getRotatedPoint(
const pt = getRotatedPoint(
new mxPoint(bounds.x, bounds.y),
Math.cos(rad),
Math.sin(rad),
@ -1321,11 +1289,8 @@ class mxCellRenderer {
this.createCellOverlays(state);
if (state.overlays != null) {
const rot = mxUtils.mod(
mxUtils.getValue(state.style, 'rotation', 0),
90
);
const rad = mxUtils.toRadians(rot);
const rot = mod(getValue(state.style, 'rotation', 0), 90);
const rad = toRadians(rot);
const cos = Math.cos(rad);
const sin = Math.sin(rad);
@ -1338,7 +1303,7 @@ class mxCellRenderer {
let cx = bounds.getCenterX();
let cy = bounds.getCenterY();
const point = mxUtils.getRotatedPoint(
const point = getRotatedPoint(
new mxPoint(cx, cy),
cos,
sin,
@ -1383,7 +1348,7 @@ class mxCellRenderer {
const bounds = this.getControlBounds(state, image.width, image.height);
const r = this.legacyControlPosition
? mxUtils.getValue(state.style, 'rotation', 0)
? getValue(state.style, 'rotation', 0)
: // @ts-ignore
state.shape.getTextRotation();
const s = state.view.scale;
@ -1430,7 +1395,7 @@ class mxCellRenderer {
let rot = state.shape.getShapeRotation();
if (this.legacyControlPosition) {
rot = mxUtils.getValue(state.style, 'rotation', 0);
rot = getValue(state.style, 'rotation', 0);
} else if (state.shape.isPaintBoundsInverted()) {
const t = (state.width - state.height) / 2;
cx += t;
@ -1438,11 +1403,11 @@ class mxCellRenderer {
}
if (rot !== 0) {
const rad = mxUtils.toRadians(rot);
const rad = toRadians(rot);
const cos = Math.cos(rad);
const sin = Math.sin(rad);
const point = mxUtils.getRotatedPoint(
const point = getRotatedPoint(
new mxPoint(cx, cy),
cos,
sin,
@ -1665,7 +1630,7 @@ class mxCellRenderer {
} else if (
!force &&
state.shape != null &&
(!mxUtils.equalEntries(state.shape.style, state.style) ||
(!equalEntries(state.shape.style, state.style) ||
this.checkPlaceholderStyles(state))
) {
state.shape.resetStyles();
@ -1754,7 +1719,7 @@ class mxCellRenderer {
shape.scale !== state.view.scale ||
(state.absolutePoints == null && !shape.bounds.equals(state)) ||
(state.absolutePoints != null &&
!mxUtils.equalPoints(shape.points, state.absolutePoints))
!equalPoints(shape.points, state.absolutePoints))
);
}

View File

@ -11,8 +11,9 @@ import mxCell from './mxCell';
import mxGraphView from '../graph/mxGraphView';
import mxShape from '../../shape/mxShape';
import mxText from '../../shape/mxText';
import mxGraph from "../graph/mxGraph";
import mxDictionary from "../../util/datatypes/mxDictionary";
import mxDictionary from '../../util/datatypes/mxDictionary';
import type { CellStateStyles } from '../../types';
/**
* Class: mxCellState
@ -40,19 +41,19 @@ import mxDictionary from "../../util/datatypes/mxDictionary";
* style - Array of key, value pairs that constitute the style.
*/
class mxCellState extends mxRectangle {
constructor(view: mxGraphView, cell: mxCell, style: {}) {
constructor(view: mxGraphView, cell: mxCell, style: CellStateStyles) {
super();
this.view = view;
this.cell = cell;
this.style = style != null ? style : {};
this.style = style ?? {};
this.origin = new mxPoint();
this.absoluteOffset = new mxPoint();
}
// referenced in mxCellRenderer
node: any;
node: HTMLElement | null = null;
// TODO: Document me!!
cellBounds: mxRectangle | null = null;
@ -65,14 +66,13 @@ class mxCellState extends mxRectangle {
control: mxShape | null = null;
// Used by mxCellRenderer's createCellOverlays()
overlays: mxDictionary | null = null;
overlays: mxDictionary<mxCell, mxShape> | null = null;
/**
* Variable: view
*
* Reference to the enclosing <mxGraphView>.
*/
// view: mxGraphView;
view: mxGraphView;
/**
@ -80,7 +80,6 @@ class mxCellState extends mxRectangle {
*
* Reference to the <mxCell> that is represented by this state.
*/
// cell: mxCell;
cell: mxCell;
/**
@ -89,23 +88,21 @@ class mxCellState extends mxRectangle {
* Contains an array of key, value pairs that represent the style of the
* cell.
*/
// style: { [key: string]: any };
style: any; // TODO: Important - make the style type more strictly typed to allow for typescript checking of individual properties!!!
style: CellStateStyles; // TODO: Important - make the style type more strictly typed to allow for typescript checking of individual properties!!!
/**
* Variable: invalidStyle
*
* Specifies if the style is invalid. Default is false.
*/
invalidStyle: boolean = false;
invalidStyle = false;
/**
* Variable: invalid
*
* Specifies if the state is invalid. Default is true.
*/
// invalid: boolean;
invalid: boolean = true;
invalid = true;
/**
* Variable: origin
@ -113,7 +110,6 @@ class mxCellState extends mxRectangle {
* <mxPoint> that holds the origin for all child cells. Default is a new
* empty <mxPoint>.
*/
// origin: mxPoint;
origin: mxPoint;
/**
@ -122,8 +118,7 @@ class mxCellState extends mxRectangle {
* Holds an array of <mxPoints> that represent the absolute points of an
* edge.
*/
// absolutePoints: mxPoint[];
absolutePoints: (mxPoint | null)[] | null = null;
absolutePoints: (mxPoint | null)[] = [];
/**
* Variable: absoluteOffset
@ -132,7 +127,6 @@ class mxCellState extends mxRectangle {
* absolute coordinates of the label position. For vertices, this is the
* offset of the label relative to the top, left corner of the vertex.
*/
// absoluteOffset: mxPoint;
absoluteOffset: mxPoint;
/**
@ -140,7 +134,6 @@ class mxCellState extends mxRectangle {
*
* Caches the visible source terminal state.
*/
// visibleSourceState: mxCellState;
visibleSourceState: mxCellState | null = null;
/**
@ -148,7 +141,6 @@ class mxCellState extends mxRectangle {
*
* Caches the visible target terminal state.
*/
// visibleTargetState: mxCellState;
visibleTargetState: mxCellState | null = null;
/**
@ -156,16 +148,14 @@ class mxCellState extends mxRectangle {
*
* Caches the distance between the end points for an edge.
*/
// terminalDistance: number;
terminalDistance: number = 0;
terminalDistance = 0;
/**
* Variable: length
*
* Caches the length of an edge.
*/
// length: number;
length: number = 0;
length = 0;
/**
* Variable: segments
@ -173,15 +163,13 @@ class mxCellState extends mxRectangle {
* Array of numbers that represent the cached length of each segment of the
* edge.
*/
// segments: number[];
segments: number[] | null = null;
segments: number[] = [];
/**
* Variable: shape
*
* Holds the <mxShape> that represents the cell graphically.
*/
// shape: mxShape;
shape: mxShape | null = null;
/**
@ -190,7 +178,6 @@ class mxCellState extends mxRectangle {
* Holds the <mxText> that represents the label of the cell. Thi smay be
* null if the cell has no label.
*/
// text: mxText;
text: mxText | null = null;
/**
@ -198,7 +185,6 @@ class mxCellState extends mxRectangle {
*
* Holds the unscaled width of the state.
*/
// unscaledWidth: number;
unscaledWidth: number | null = null;
/**
@ -219,7 +205,6 @@ class mxCellState extends mxRectangle {
* border - Optional border to be added around the perimeter bounds.
* bounds - Optional <mxRectangle> to be used as the initial bounds.
*/
// getPerimeterBounds(border?: number, bounds?: mxRectangle): mxRectangle;
getPerimeterBounds(
border: number = 0,
bounds: mxRectangle = new mxRectangle(
@ -228,10 +213,10 @@ class mxCellState extends mxRectangle {
this.width,
this.height
)
): mxRectangle {
) {
if (
this.shape != null &&
this.shape.stencil != null &&
this.shape &&
this.shape.stencil &&
this.shape.stencil.aspect === 'fixed'
) {
const aspect = this.shape.stencil.computeAspect(
@ -251,6 +236,7 @@ class mxCellState extends mxRectangle {
if (border !== 0) {
bounds.grow(border);
}
return bounds;
}
@ -265,21 +251,14 @@ class mxCellState extends mxRectangle {
* isSource - Boolean that specifies if the first or last point should
* be assigned.
*/
// setAbsoluteTerminalPoint(point: mxPoint, isSource: boolean): void;
setAbsoluteTerminalPoint(point: mxPoint,
isSource: boolean=false): void {
setAbsoluteTerminalPoint(point: mxPoint, isSource = false) {
if (isSource) {
if (this.absolutePoints == null) {
this.absolutePoints = [];
}
if (this.absolutePoints.length === 0) {
this.absolutePoints.push(point);
} else {
this.absolutePoints[0] = point;
}
} else if (this.absolutePoints == null) {
this.absolutePoints = [];
} else if (this.absolutePoints.length === 0) {
this.absolutePoints.push(null);
this.absolutePoints.push(point);
} else if (this.absolutePoints.length === 1) {
@ -294,12 +273,11 @@ class mxCellState extends mxRectangle {
*
* Sets the given cursor on the shape and text shape.
*/
// setCursor(cursor: string): void;
setCursor(cursor: string): void {
if (this.shape != null) {
setCursor(cursor: string) {
if (this.shape) {
this.shape.setCursor(cursor);
}
if (this.text != null) {
if (this.text) {
this.text.setCursor(cursor);
}
}
@ -314,10 +292,9 @@ class mxCellState extends mxRectangle {
* source - Boolean that specifies if the source or target cell should be
* returned.
*/
// getVisibleTerminal(source: boolean): mxCell;
getVisibleTerminal(source: boolean = false): mxCell | null {
getVisibleTerminal(source = false) {
const tmp = this.getVisibleTerminalState(source);
return tmp != null ? tmp.cell : null;
return tmp ? tmp.cell : null;
}
/**
@ -330,8 +307,7 @@ class mxCellState extends mxRectangle {
* source - Boolean that specifies if the source or target state should be
* returned.
*/
// getVisibleTerminalState(source?: boolean): mxCellState;
getVisibleTerminalState(source: boolean = false): mxCellState | null {
getVisibleTerminalState(source = false): mxCellState | null {
return source ? this.visibleSourceState : this.visibleTargetState;
}
@ -345,11 +321,7 @@ class mxCellState extends mxRectangle {
* terminalState - <mxCellState> that represents the terminal.
* source - Boolean that specifies if the source or target state should be set.
*/
// setVisibleTerminalState(terminalState: mxCellState, source: boolean): void;
setVisibleTerminalState(
terminalState: mxCellState,
source: boolean = false
): void {
setVisibleTerminalState(terminalState: mxCellState, source = false) {
if (source) {
this.visibleSourceState = terminalState;
} else {
@ -362,9 +334,8 @@ class mxCellState extends mxRectangle {
*
* Returns the unscaled, untranslated bounds.
*/
// getCellBounds(): mxRectangle;
getCellBounds(): mxRectangle {
return <mxRectangle>this.cellBounds;
getCellBounds() {
return this.cellBounds;
}
/**
@ -374,9 +345,8 @@ class mxCellState extends mxRectangle {
* <getCellBounds> but with a 90 degree rotation if the shape's
* isPaintBoundsInverted returns true.
*/
// getPaintBounds(): mxRectangle;
getPaintBounds(): mxRectangle {
return <mxRectangle>this.paintBounds;
getPaintBounds() {
return this.paintBounds;
}
/**
@ -384,12 +354,11 @@ class mxCellState extends mxRectangle {
*
* Updates the cellBounds and paintBounds.
*/
// updateCachedBounds(): void;
updateCachedBounds(): void {
const view = <mxGraphView>this.view;
updateCachedBounds() {
const view = this.view;
const tr = view.translate;
const s = view.scale;
this.cellBounds = new mxRectangle(
this.x / s - tr.x,
this.y / s - tr.y,
@ -398,7 +367,7 @@ class mxCellState extends mxRectangle {
);
this.paintBounds = mxRectangle.fromRectangle(this.cellBounds);
if (this.shape != null && this.shape.isPaintBoundsInverted()) {
if (this.shape && this.shape.isPaintBoundsInverted()) {
this.paintBounds.rotate90();
}
}
@ -408,8 +377,7 @@ class mxCellState extends mxRectangle {
*
* Copies all fields from the given state to this state.
*/
// setState(state: mxCellState): void;
setState(state: mxCellState): void {
setState(state: mxCellState) {
this.view = state.view;
this.cell = state.cell;
this.style = state.style;
@ -433,28 +401,24 @@ class mxCellState extends mxRectangle {
*
* Returns a clone of this <mxPoint>.
*/
// clone(): mxCellState;
clone(): mxCellState {
const clone = new mxCellState(<mxGraphView>this.view, <mxCell>this.cell, this.style);
clone() {
const clone = new mxCellState(this.view, this.cell, this.style);
// Clones the absolute points
if (this.absolutePoints != null) {
clone.absolutePoints = [];
for (let i = 0; i < this.absolutePoints.length; i += 1) {
clone.absolutePoints[i] = (<mxPoint[]>this.absolutePoints)[i].clone();
}
for (let i = 0; i < this.absolutePoints.length; i += 1) {
const p = this.absolutePoints[i];
clone.absolutePoints[i] = p ? p.clone() : null;
}
if (this.origin != null) {
if (this.origin) {
clone.origin = this.origin.clone();
}
if (this.absoluteOffset != null) {
if (this.absoluteOffset) {
clone.absoluteOffset = this.absoluteOffset.clone();
}
if (this.boundingBox != null) {
if (this.boundingBox) {
clone.boundingBox = this.boundingBox.clone();
}
@ -476,22 +440,19 @@ class mxCellState extends mxRectangle {
*
* Destroys the state and all associated resources.
*/
// destroy(): void;
destroy(): void {
(<mxGraph>(<mxGraphView>this.view).graph).cellRenderer.destroy(this);
destroy() {
this.view.graph.cellRenderer.destroy(this);
}
/**
* Returns true if the given cell state is a loop.
*
* @param state {@link mxCellState} that represents a potential loop.
*/
// isLoop(state: mxCellState): boolean;
isLoop(): boolean {
isLoop(state: mxCellState) {
const src = this.getVisibleTerminalState(true);
const trg = this.getVisibleTerminalState(false);
return src != null && src == trg;
return src && src === trg;
}
}

View File

@ -205,8 +205,8 @@ class mxGraph extends mxEventSource {
lastMouseY: number | null = null;
isMouseTrigger: boolean | null = null;
ignoreMouseEvents: boolean | null = null;
mouseMoveRedirect: Function | null = null;
mouseUpRedirect: Function | null = null;
mouseMoveRedirect: EventListener | null = null;
mouseUpRedirect: EventListener | null = null;
lastEvent: any; // FIXME: Check if this can be more specific - DOM events or mxEventObjects!
horizontalPageBreaks: any[] | null = null;
verticalPageBreaks: any[] | null = null;

View File

@ -23,6 +23,8 @@ import mxVisibleChange from '../../atomic_changes/mxVisibleChange';
import mxGeometry from "../../util/datatypes/mxGeometry";
import mxCellArray from "../cell/mxCellArray";
import type { CellMap, FilterFunction, UndoableChange } from '../../types';
/**
* Extends {@link mxEventSource} to implement a graph model. The graph model acts as
* a wrapper around the cells which are in charge of storing the actual graph
@ -338,7 +340,7 @@ class mxGraphModel extends mxEventSource {
}
filterCells(cells: mxCellArray,
filter: Function): mxCellArray | null {
filter: FilterFunction): mxCellArray | null {
return new mxCellArray(...cells).filterCells(filter);
}

View File

@ -21,7 +21,16 @@ import {
} from '../../util/mxConstants';
import mxClient from '../../mxClient';
import mxEvent from '../../util/event/mxEvent';
import mxUtils from '../../util/mxUtils';
import {
convertPoint,
getCurrentStyle,
getOffset,
getRotatedPoint,
getValue,
ptSegDistSq,
relativeCcw,
toRadians,
} from '../../util/mxUtils';
import mxLog from '../../util/gui/mxLog';
import mxResources from '../../util/mxResources';
import mxCellState from '../cell/mxCellState';
@ -102,7 +111,7 @@ class mxGraphView extends mxEventSource {
backgroundPageShape: mxShape | null = null;
EMPTY_POINT: mxPoint = new mxPoint();
EMPTY_POINT = new mxPoint();
canvas: SVGElement | null = null;
@ -119,110 +128,95 @@ class mxGraphView extends mxEventSource {
* If the resource for this key does not exist then the value is used as
* the status message. Default is 'done'.
*/
// doneResource: 'done' | '';
doneResource: string = mxClient.language !== 'none' ? 'done' : '';
doneResource = mxClient.language !== 'none' ? 'done' : '';
/**
* Specifies the resource key for the status message while the document is
* being updated. If the resource for this key does not exist then the
* value is used as the status message. Default is 'updatingDocument'.
*/
// updatingDocumentResource: 'updatingDocument' | '';
updatingDocumentResource: string =
updatingDocumentResource =
mxClient.language !== 'none' ? 'updatingDocument' : '';
/**
* Specifies if string values in cell styles should be evaluated using
* {@link mxUtils.eval}. This will only be used if the string values can't be mapped
* {@link eval}. This will only be used if the string values can't be mapped
* to objects using {@link mxStyleRegistry}. Default is false. NOTE: Enabling this
* switch carries a possible security risk.
*/
// allowEval: boolean;
allowEval: boolean = false;
allowEval = false;
/**
* Specifies if a gesture should be captured when it goes outside of the
* graph container. Default is true.
*/
// captureDocumentGesture: boolean;
captureDocumentGesture: boolean = true;
captureDocumentGesture = true;
/**
* Specifies if shapes should be created, updated and destroyed using the
* methods of {@link mxCellRenderer} in {@link graph}. Default is true.
*/
// rendering: boolean;
rendering: boolean = true;
rendering = true;
/**
* Reference to the enclosing {@link mxGraph}.
*/
// graph: mxGraph;
graph: mxGraph;
/**
* {@link mxCell} that acts as the root of the displayed cell hierarchy.
*/
// currentRoot: mxCell;
currentRoot: mxCell | null = null;
graphBounds: mxRectangle = new mxRectangle();
graphBounds = new mxRectangle();
scale: number = 1;
scale = 1;
/**
* {@link mxPoint} that specifies the current translation. Default is a new
* empty {@link mxPoint}.
*/
// translate: mxPoint;
translate: mxPoint = new mxPoint();
translate = new mxPoint();
states: mxDictionary = new mxDictionary();
states = new mxDictionary<mxCellState>();
/**
* Specifies if the style should be updated in each validation step. If this
* is false then the style is only updated if the state is created or if the
* style of the cell was changed. Default is false.
*/
// updateStyle: boolean;
updateStyle: boolean = false;
updateStyle = false;
/**
* During validation, this contains the last DOM node that was processed.
*/
// lastNode: Element;
lastNode: HTMLElement | SVGElement | null = null;
/**
* During validation, this contains the last HTML DOM node that was processed.
*/
// lastHtmlNode: HTMLElement;
lastHtmlNode: HTMLElement | SVGElement | null = null;
/**
* During validation, this contains the last edge's DOM node that was processed.
*/
// lastForegroundNode: Element;
lastForegroundNode: HTMLElement | SVGElement | null = null;
/**
* During validation, this contains the last edge HTML DOM node that was processed.
*/
// lastForegroundHtmlNode: HTMLElement;
lastForegroundHtmlNode: HTMLElement | SVGElement | null = null;
/**
* Returns {@link graphBounds}.
*/
// getGraphBounds(): mxRectangle;
getGraphBounds(): mxRectangle {
getGraphBounds() {
return this.graphBounds;
}
/**
* Sets {@link graphBounds}.
*/
// setGraphBounds(value: mxRectangle): void;
setGraphBounds(value: mxRectangle) {
this.graphBounds = value;
}
@ -230,8 +224,7 @@ class mxGraphView extends mxEventSource {
/**
* Returns the {@link scale}.
*/
// getScale(): number;
getScale(): number {
getScale() {
return this.scale;
}
@ -241,7 +234,6 @@ class mxGraphView extends mxEventSource {
*
* @param value Decimal value that specifies the new scale (1 is 100%).
*/
// setScale(value: number): void;
setScale(value: number) {
const previousScale: number = this.scale;
if (previousScale !== value) {
@ -264,8 +256,7 @@ class mxGraphView extends mxEventSource {
/**
* Returns the {@link translate}.
*/
// getTranslate(): mxPoint;
getTranslate(): mxPoint {
getTranslate() {
return this.translate;
}
@ -277,7 +268,6 @@ class mxGraphView extends mxEventSource {
* @param dx X-coordinate of the translation.
* @param dy Y-coordinate of the translation.
*/
// setTranslate(dx: number, dy: number): void;
setTranslate(dx: number, dy: number) {
const previousTranslate = new mxPoint(this.translate.x, this.translate.y);
@ -301,7 +291,7 @@ class mxGraphView extends mxEventSource {
);
}
isRendering(): boolean {
isRendering() {
return this.rendering;
}
@ -309,7 +299,7 @@ class mxGraphView extends mxEventSource {
this.rendering = value;
}
isAllowEval(): boolean {
isAllowEval() {
return this.allowEval;
}
@ -329,7 +319,7 @@ class mxGraphView extends mxEventSource {
* Sets {@link states}.
*/
// setStates(value: mxDictionary<mxCellState>): void;
setStates(value: any): void {
setStates(value: mxDictionary): void {
this.states = value;
}
@ -506,22 +496,23 @@ class mxGraphView extends mxEventSource {
* recursion.
*/
// clear(cell: mxCell, force?: boolean, recurse?: boolean): void;
clear(
cell: mxCell = <mxCell>(<mxGraph>this.graph).getModel().getRoot(),
force: boolean = false,
recurse: boolean = true
) {
const model: mxGraphModel = (<mxGraph>this.graph).getModel();
this.removeState(<mxCell>cell);
clear(cell?: mxCell | null, force: boolean = false, recurse: boolean = true) {
if (!cell) {
cell = this.graph.getModel().getRoot();
}
if (recurse && (force || cell != this.currentRoot)) {
const childCount: number = cell.getChildCount();
if (cell) {
this.removeState(cell);
for (let i = 0; i < childCount; i += 1) {
this.clear(<mxCell>cell.getChildAt(i), force);
if (recurse && (force || cell !== this.currentRoot)) {
const childCount: number = cell.getChildCount();
for (let i = 0; i < childCount; i += 1) {
this.clear(cell.getChildAt(i), force);
}
} else {
this.invalidate(cell);
}
} else {
this.invalidate(cell);
}
}
@ -605,6 +596,7 @@ class mxGraphView extends mxEventSource {
)
)
);
this.setGraphBounds(
graphBounds != null ? graphBounds : this.getEmptyBounds()
);
@ -747,41 +739,41 @@ class mxGraphView extends mxEventSource {
this.backgroundPageShape.init(this.backgroundPane);
this.backgroundPageShape.redraw();
// Adds listener for double click handling on background
if (graph.nativeDblClickEnabled) {
mxEvent.addListener(
this.backgroundPageShape.node,
'dblclick',
(evt: MouseEvent) => {
if (this.backgroundPageShape.node) {
// Adds listener for double click handling on background
if (graph.nativeDblClickEnabled) {
mxEvent.addListener(this.backgroundPageShape.node, 'dblclick', ((
evt: MouseEvent
) => {
graph.dblClick(evt);
}) as EventListener);
}
// Adds basic listeners for graph event dispatching outside of the
// container and finishing the handling of a single gesture
mxEvent.addGestureListeners(
this.backgroundPageShape.node,
(evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt));
},
(evt: Event) => {
// Hides the tooltip if mouse is outside container
if (
graph.tooltipHandler != null &&
graph.tooltipHandler.isHideOnHover()
) {
graph.tooltipHandler.hide();
}
if (graph.isMouseDown && !isConsumed(evt)) {
graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt));
}
},
(evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt));
}
);
}
// Adds basic listeners for graph event dispatching outside of the
// container and finishing the handling of a single gesture
mxEvent.addGestureListeners(
this.backgroundPageShape.node,
(evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_DOWN, new mxMouseEvent(evt));
},
(evt: Event) => {
// Hides the tooltip if mouse is outside container
if (
graph.tooltipHandler != null &&
graph.tooltipHandler.isHideOnHover()
) {
graph.tooltipHandler.hide();
}
if (graph.isMouseDown && !isConsumed(evt)) {
graph.fireMouseEvent(mxEvent.MOUSE_MOVE, new mxMouseEvent(evt));
}
},
(evt: Event) => {
graph.fireMouseEvent(mxEvent.MOUSE_UP, new mxMouseEvent(evt));
}
);
} else {
this.backgroundPageShape.scale = this.scale;
this.backgroundPageShape.bounds = bounds;
@ -1052,14 +1044,15 @@ class mxGraphView extends mxEventSource {
const pState = this.getState(state.cell.getParent());
if (geo.relative && pState != null && !pState.cell.isEdge()) {
const alpha = mxUtils.toRadians(pState.style.rotation || '0');
const alpha = toRadians(pState.style.rotation || '0');
if (alpha !== 0) {
const cos = Math.cos(alpha);
const sin = Math.sin(alpha);
const ct = new mxPoint(state.getCenterX(), state.getCenterY());
const cx = new mxPoint(pState.getCenterX(), pState.getCenterY());
const pt = mxUtils.getRotatedPoint(ct, cos, sin, cx);
const pt = getRotatedPoint(ct, cos, sin, cx);
state.x = pt.x - state.width / 2;
state.y = pt.y - state.height / 2;
}
@ -1117,10 +1110,10 @@ class mxGraphView extends mxEventSource {
*/
// updateVertexLabelOffset(state: mxCellState): void;
updateVertexLabelOffset(state: mxCellState) {
const h = mxUtils.getValue(state.style, 'labelPosition', ALIGN_CENTER);
const h = getValue(state.style, 'labelPosition', ALIGN_CENTER);
if (h === ALIGN_LEFT) {
let lw = mxUtils.getValue(state.style, 'labelWidth', null);
let lw = getValue(state.style, 'labelWidth', null);
if (lw != null) {
lw *= this.scale;
@ -1134,11 +1127,11 @@ class mxGraphView extends mxEventSource {
// @ts-ignore
state.absoluteOffset.x += state.width;
} else if (h === ALIGN_CENTER) {
const lw = mxUtils.getValue(state.style, 'labelWidth', null);
const lw = getValue(state.style, 'labelWidth', null);
if (lw != null) {
// Aligns text block with given width inside the vertex width
const align = mxUtils.getValue(state.style, 'align', ALIGN_CENTER);
const align = getValue(state.style, 'align', ALIGN_CENTER);
let dx = 0;
if (align === ALIGN_CENTER) {
@ -1154,11 +1147,7 @@ class mxGraphView extends mxEventSource {
}
}
const v = mxUtils.getValue(
state.style,
'verticalLabelPosition',
ALIGN_MIDDLE
);
const v = getValue(state.style, 'verticalLabelPosition', ALIGN_MIDDLE);
if (v === ALIGN_TOP) {
// @ts-ignore
@ -1452,7 +1441,7 @@ class mxGraphView extends mxEventSource {
if (
(points == null || points.length < 2) &&
(!mxUtils.getValue(edge.style, 'orthogonalLoop', false) ||
(!getValue(edge.style, 'orthogonalLoop', false) ||
((sc == null || sc.point == null) && (tc == null || tc.point == null)))
) {
return source != null && source === target;
@ -1471,12 +1460,8 @@ class mxGraphView extends mxEventSource {
target: mxCellState | null = null
): any {
let edgeStyle: any = this.isLoopStyleEnabled(edge, points, source, target)
? mxUtils.getValue(
edge.style,
'loop',
(<mxGraph>this.graph).defaultLoopStyle
)
: !mxUtils.getValue(edge.style, 'noEdgeStyle', false)
? getValue(edge.style, 'loop', (<mxGraph>this.graph).defaultLoopStyle)
: !getValue(edge.style, 'noEdgeStyle', false)
? edge.style.edge
: null;
@ -1564,13 +1549,13 @@ class mxGraphView extends mxEventSource {
let next = this.getNextPoint(edge, end, source);
const orth = (<mxGraph>this.graph).isOrthogonal(edge);
const alpha = mxUtils.toRadians(Number(start.style.rotation || '0'));
const alpha = toRadians(Number(start.style.rotation || '0'));
const center = new mxPoint(start.getCenterX(), start.getCenterY());
if (alpha !== 0) {
const cos = Math.cos(-alpha);
const sin = Math.sin(-alpha);
next = mxUtils.getRotatedPoint(next, cos, sin, center);
next = getRotatedPoint(next, cos, sin, center);
}
let border = parseFloat(edge.style.perimeterSpacing || 0);
@ -1589,7 +1574,7 @@ class mxGraphView extends mxEventSource {
if (alpha !== 0) {
const cos = Math.cos(alpha);
const sin = Math.sin(alpha);
pt = mxUtils.getRotatedPoint(pt, cos, sin, center);
pt = getRotatedPoint(pt, cos, sin, center);
}
return pt;
@ -1610,7 +1595,7 @@ class mxGraphView extends mxEventSource {
source: boolean = false
): mxCellState | null {
const key = source ? 'sourcePort' : 'targetPort';
const id = mxUtils.getValue(state.style, key);
const id = getValue(state.style, key);
if (id != null) {
const tmp = this.getState(
@ -1659,17 +1644,13 @@ class mxGraphView extends mxEventSource {
let flipV = false;
if (terminal.cell.isVertex()) {
flipH = mxUtils.getValue(terminal.style, 'flipH', 0) == 1;
flipV = mxUtils.getValue(terminal.style, 'flipV', 0) == 1;
flipH = getValue(terminal.style, 'flipH', 0) == 1;
flipV = getValue(terminal.style, 'flipV', 0) == 1;
// Legacy support for stencilFlipH/V
if (terminal.shape != null && terminal.shape.stencil != null) {
flipH =
mxUtils.getValue(terminal.style, 'stencilFlipH', 0) == 1 ||
flipH;
flipV =
mxUtils.getValue(terminal.style, 'stencilFlipV', 0) == 1 ||
flipV;
flipH = getValue(terminal.style, 'stencilFlipH', 0) == 1 || flipH;
flipV = getValue(terminal.style, 'stencilFlipV', 0) == 1 || flipV;
}
if (flipH) {
@ -1708,9 +1689,7 @@ class mxGraphView extends mxEventSource {
// getRoutingCenterX(state: mxCellState): number;
getRoutingCenterX(state: mxCellState) {
const f =
state.style != null
? parseFloat(state.style.routingCenterX) || 0
: 0;
state.style != null ? parseFloat(state.style.routingCenterX) || 0 : 0;
return state.getCenterX() + f * state.width;
}
@ -1720,9 +1699,7 @@ class mxGraphView extends mxEventSource {
// getRoutingCenterY(state: mxCellState): number;
getRoutingCenterY(state: mxCellState) {
const f =
state.style != null
? parseFloat(state.style.routingCenterY) || 0
: 0;
state.style != null ? parseFloat(state.style.routingCenterY) || 0 : 0;
return state.getCenterY() + f * state.height;
}
@ -2019,7 +1996,7 @@ class mxGraphView extends mxEventSource {
// Works out which line segment the point of the label is closest to
let p0 = absolutePoints[0];
let pe = absolutePoints[1];
let minDist = mxUtils.ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
let minDist = ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
let length = 0;
let index = 0;
let tmp = 0;
@ -2027,7 +2004,7 @@ class mxGraphView extends mxEventSource {
for (let i = 2; i < pointCount; i += 1) {
p0 = pe;
pe = absolutePoints[i];
const dist = mxUtils.ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
const dist = ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y);
tmp += segments[i - 2];
if (dist <= minDist) {
@ -2074,10 +2051,8 @@ class mxGraphView extends mxEventSource {
projlen = seg;
}
let yDistance = Math.sqrt(
mxUtils.ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y)
);
const direction = mxUtils.relativeCcw(p0.x, p0.y, pe.x, pe.y, x, y);
let yDistance = Math.sqrt(ptSegDistSq(p0.x, p0.y, pe.x, pe.y, x, y));
const direction = relativeCcw(p0.x, p0.y, pe.x, pe.y, x, y);
if (direction === -1) {
yDistance = -yDistance;
@ -2261,7 +2236,7 @@ class mxGraphView extends mxEventSource {
// isScrollEvent(evt: Event): boolean;
isScrollEvent(evt: MouseEvent) {
const graph = <mxGraph>this.graph;
const offset = mxUtils.getOffset(graph.container);
const offset = getOffset(graph.container);
const pt = new mxPoint(evt.clientX - offset.x, evt.clientY - offset.y);
const container = <HTMLElement>graph.container;
@ -2303,20 +2278,20 @@ class mxGraphView extends mxEventSource {
// Support for touch device gestures (eg. pinch to zoom)
// Double-tap handling is implemented in mxGraph.fireMouseEvent
if (mxClient.IS_TOUCH) {
mxEvent.addListener(container, 'gesturestart', (evt: MouseEvent) => {
mxEvent.addListener(container, 'gesturestart', ((evt: MouseEvent) => {
graph.fireGestureEvent(evt);
mxEvent.consume(evt);
});
}) as EventListener);
mxEvent.addListener(container, 'gesturechange', (evt: MouseEvent) => {
mxEvent.addListener(container, 'gesturechange', ((evt: MouseEvent) => {
graph.fireGestureEvent(evt);
mxEvent.consume(evt);
});
}) as EventListener);
mxEvent.addListener(container, 'gestureend', (evt: MouseEvent) => {
mxEvent.addListener(container, 'gestureend', ((evt: MouseEvent) => {
graph.fireGestureEvent(evt);
mxEvent.consume(evt);
});
}) as EventListener);
}
// Fires event only for one pointer per gesture
@ -2325,7 +2300,7 @@ class mxGraphView extends mxEventSource {
// Adds basic listeners for graph event dispatching
mxEvent.addGestureListeners(
container,
(evt: MouseEvent) => {
((evt: MouseEvent) => {
// Condition to avoid scrollbar events starting a rubberband selection
if (
this.isContainerEvent(evt) &&
@ -2335,7 +2310,7 @@ class mxGraphView extends mxEventSource {
// @ts-ignore
pointerId = evt.pointerId;
}
},
}) as EventListener,
(evt: Event) => {
if (
this.isContainerEvent(evt) &&
@ -2357,11 +2332,11 @@ class mxGraphView extends mxEventSource {
// Adds listener for double click handling on background, this does always
// use native event handler, we assume that the DOM of the background
// does not change during the double click
mxEvent.addListener(container, 'dblclick', (evt: MouseEvent) => {
mxEvent.addListener(container, 'dblclick', ((evt: MouseEvent) => {
if (this.isContainerEvent(evt)) {
graph.dblClick(evt);
}
});
}) as EventListener);
// Workaround for touch events which started on some DOM node
// on top of the container, in which case the cells under the
@ -2378,7 +2353,7 @@ class mxGraphView extends mxEventSource {
// Dispatches the drop event to the graph which
// consumes and executes the source function
const pt = mxUtils.convertPoint(container, x, y);
const pt = convertPoint(container, x, y);
state = (<mxGraphView>graph.view).getState(
graph.getCellAt(pt.x, pt.y)
);
@ -2503,7 +2478,7 @@ class mxGraphView extends mxEventSource {
// updateContainerStyle(container: Element): void;
updateContainerStyle(container: HTMLElement) {
// Workaround for offset of container
const style = mxUtils.getCurrentStyle(container);
const style = getCurrentStyle(container);
if (style != null && style.position == 'static') {
container.style.position = 'relative';
@ -2535,7 +2510,7 @@ class mxGraphView extends mxEventSource {
this.moveHandler,
this.endHandler
);
mxEvent.release((<mxGraph>this.graph).container);
mxEvent.release(this.graph.container);
root.parentNode.removeChild(root);
this.moveHandler = null;
@ -2548,8 +2523,8 @@ class mxGraphView extends mxEventSource {
}
}
endHandler: Function | null = null;
moveHandler: Function | null = null;
endHandler: EventListener | null = null;
moveHandler: EventListener | null = null;
}
export default mxGraphView;

View File

@ -6,7 +6,7 @@
*/
import mxEventSource from '../../util/event/mxEventSource';
import mxUtils from '../../util/mxUtils';
import { getValue } from '../../util/mxUtils';
import mxEvent from '../../util/event/mxEvent';
import mxRectangle from '../../util/datatypes/mxRectangle';
import mxGraph from './mxGraph';
@ -190,7 +190,7 @@ class mxSwimlaneManager extends mxEventSource {
isCellHorizontal(cell: mxCell): boolean {
if ((<mxGraph>this.graph).isSwimlane(cell)) {
const style = (<mxGraph>this.graph).getCellStyle(cell);
return mxUtils.getValue(style, 'horizontal', 1) == 1;
return getValue(style, 'horizontal', 1) == 1;
}
return !this.isHorizontal();
}