commit
061ff34917
|
@ -119,8 +119,8 @@ import mxAnimation from './util/animate/mxAnimation';
|
||||||
import mxEffects from './util/animate/mxEffects';
|
import mxEffects from './util/animate/mxEffects';
|
||||||
import mxMorphing from './util/animate/mxMorphing';
|
import mxMorphing from './util/animate/mxMorphing';
|
||||||
|
|
||||||
import mxAbstractCanvas2D from './util/canvas/mxAbstractCanvas2D';
|
import mxAbstractCanvas2D from './util/canvas/AbstractCanvas2D';
|
||||||
import mxSvgCanvas2D from './util/canvas/mxSvgCanvas2D';
|
import mxSvgCanvas2D from './util/canvas/SvgCanvas2D';
|
||||||
import mxXmlCanvas2D from './util/canvas/mxXmlCanvas2D';
|
import mxXmlCanvas2D from './util/canvas/mxXmlCanvas2D';
|
||||||
|
|
||||||
import Dictionary from './util/Dictionary';
|
import Dictionary from './util/Dictionary';
|
||||||
|
@ -151,7 +151,7 @@ import mxPopupMenu from './util/gui/mxPopupMenu';
|
||||||
import mxToolbar from './util/gui/mxToolbar';
|
import mxToolbar from './util/gui/mxToolbar';
|
||||||
import mxWindow from './util/gui/mxWindow';
|
import mxWindow from './util/gui/mxWindow';
|
||||||
|
|
||||||
import Image from './view/image/Image';
|
import Image from './view/image/ImageBox';
|
||||||
import ImageBundle from './view/image/ImageBundle';
|
import ImageBundle from './view/image/ImageBundle';
|
||||||
import ImageExport from './view/image/ImageExport';
|
import ImageExport from './view/image/ImageExport';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type Cell from './view/cell/datatypes/Cell';
|
import type Cell from './view/cell/datatypes/Cell';
|
||||||
|
import Shape from './view/geometry/shape/Shape';
|
||||||
|
|
||||||
export type CellMap = {
|
export type CellMap = {
|
||||||
[id: string]: Cell;
|
[id: string]: Cell;
|
||||||
|
@ -23,19 +24,88 @@ export type Properties = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export type CellStateStyles = {
|
export type CellStateStyles = {
|
||||||
[k: string]: string;
|
absoluteArcSize: number;
|
||||||
|
align: AlignValue;
|
||||||
|
arcSize: number;
|
||||||
|
backgroundColor: ColorValue;
|
||||||
|
backgroundOutline: number;
|
||||||
|
curved: boolean;
|
||||||
|
dashed: boolean;
|
||||||
|
dashPattern: string;
|
||||||
|
direction: DirectionValue;
|
||||||
|
endArrow: ArrowType;
|
||||||
|
endFill: boolean;
|
||||||
|
endSize: number;
|
||||||
|
fillColor: ColorValue;
|
||||||
|
fillOpacity: number;
|
||||||
|
fixDash: boolean;
|
||||||
|
flipH: boolean;
|
||||||
|
flipV: boolean;
|
||||||
|
fontColor: ColorValue;
|
||||||
|
fontFamily: string;
|
||||||
|
fontSize: number;
|
||||||
|
fontStyle: number;
|
||||||
|
glass: boolean;
|
||||||
|
gradientColor: ColorValue;
|
||||||
|
gradientDirection: DirectionValue;
|
||||||
|
horizontal: boolean;
|
||||||
|
image: string;
|
||||||
|
imageAlign: AlignValue;
|
||||||
|
imageAspect: boolean;
|
||||||
|
imageBackground: ColorValue;
|
||||||
|
imageBorder: ColorValue;
|
||||||
|
imageHeight: number;
|
||||||
|
imageWidth: number;
|
||||||
|
indicatorColor: ColorValue;
|
||||||
|
indicatorHeight: number;
|
||||||
|
indicatorImage: string;
|
||||||
|
indicatorShape: Shape;
|
||||||
|
indicatorWidth: number;
|
||||||
|
labelBorderColor: ColorValue;
|
||||||
|
labelPosition: AlignValue;
|
||||||
|
margin: number;
|
||||||
|
opacity: number;
|
||||||
|
pointerEvents: boolean;
|
||||||
|
rotation: number;
|
||||||
|
rounded: boolean;
|
||||||
|
separatorColor: ColorValue;
|
||||||
|
shadow: boolean;
|
||||||
|
spacing: number;
|
||||||
|
spacingBottom: number;
|
||||||
|
spacingLeft: number;
|
||||||
|
spacingRight: number;
|
||||||
|
spacingTop: number;
|
||||||
|
startArrow: ArrowType;
|
||||||
|
startFill: boolean;
|
||||||
|
startSize: number;
|
||||||
|
strokeColor: ColorValue;
|
||||||
|
strokeOpacity: number;
|
||||||
|
strokeWidth: number;
|
||||||
|
swimlaneFillColor: ColorValue;
|
||||||
|
swimlaneLine: boolean;
|
||||||
|
textDirection: TextDirectionValue;
|
||||||
|
textOpacity: number;
|
||||||
|
verticalAlign: VAlignValue;
|
||||||
|
verticalLabelPosition: VAlignValue;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ColorValue = string | null;
|
export type ColorValue = string;
|
||||||
export type DirectionValue = 'north' | 'south' | 'east' | 'west' | null;
|
export type DirectionValue = 'north' | 'south' | 'east' | 'west';
|
||||||
export type AlignValue =
|
export type TextDirectionValue = '' | 'ltr' | 'rtl' | 'auto';
|
||||||
| 'left'
|
export type AlignValue = 'left' | 'center' | 'right';
|
||||||
| 'center'
|
export type VAlignValue = 'top' | 'middle' | 'bottom';
|
||||||
| 'right'
|
export type OverflowValue = 'fill' | 'width' | 'auto' | 'hidden' | 'scroll' | 'visible';
|
||||||
| 'top'
|
export type ArrowType =
|
||||||
| 'middle'
|
| 'none'
|
||||||
| 'bottom'
|
| 'classic'
|
||||||
| null;
|
| 'classicThin'
|
||||||
|
| 'block'
|
||||||
|
| 'blockThin'
|
||||||
|
| 'open'
|
||||||
|
| 'openThin'
|
||||||
|
| 'oval'
|
||||||
|
| 'diamond'
|
||||||
|
| 'diamondThin';
|
||||||
|
|
||||||
export type CanvasState = {
|
export type CanvasState = {
|
||||||
dx: number;
|
dx: number;
|
||||||
|
@ -48,9 +118,9 @@ export type CanvasState = {
|
||||||
gradientFillAlpha: number;
|
gradientFillAlpha: number;
|
||||||
gradientColor: ColorValue;
|
gradientColor: ColorValue;
|
||||||
gradientAlpha: number;
|
gradientAlpha: number;
|
||||||
gradientDirection: string | null;
|
gradientDirection: DirectionValue;
|
||||||
strokeColor: ColorValue;
|
strokeColor: ColorValue;
|
||||||
strokeWidth: number | null;
|
strokeWidth: number;
|
||||||
dashed: boolean;
|
dashed: boolean;
|
||||||
dashPattern: string;
|
dashPattern: string;
|
||||||
fixDash: boolean;
|
fixDash: boolean;
|
||||||
|
|
|
@ -5,13 +5,15 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import mxObjectIdentity from './mxObjectIdentity';
|
import ObjectIdentity from './ObjectIdentity';
|
||||||
|
|
||||||
//type Dictionary<T, U> = {
|
//type Dictionary<T, U> = {
|
||||||
// [key: string]: U;
|
// [key: string]: U;
|
||||||
//};
|
//};
|
||||||
|
|
||||||
type Visitor<T, U> = (key: string, value: U) => void;
|
type MapKey = string;
|
||||||
|
|
||||||
|
type Visitor<MapKey, U> = (key: MapKey, value: U) => void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxDictionary
|
* Class: mxDictionary
|
||||||
|
@ -33,7 +35,7 @@ class Dictionary<T, U> {
|
||||||
*
|
*
|
||||||
* Stores the (key, value) pairs in this dictionary.
|
* Stores the (key, value) pairs in this dictionary.
|
||||||
*/
|
*/
|
||||||
map: Dictionary<T, U> = {};
|
map: Record<MapKey, U> = {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: clear
|
* Function: clear
|
||||||
|
@ -50,7 +52,7 @@ class Dictionary<T, U> {
|
||||||
* Returns the value for the given key.
|
* Returns the value for the given key.
|
||||||
*/
|
*/
|
||||||
get(key: T) {
|
get(key: T) {
|
||||||
const id = mxObjectIdentity.get(key);
|
const id = ObjectIdentity.get(key);
|
||||||
|
|
||||||
return this.map[id];
|
return this.map[id];
|
||||||
}
|
}
|
||||||
|
@ -62,7 +64,7 @@ class Dictionary<T, U> {
|
||||||
* value for that key.
|
* value for that key.
|
||||||
*/
|
*/
|
||||||
put(key: T, value: U) {
|
put(key: T, value: U) {
|
||||||
const id = mxObjectIdentity.get(key);
|
const id = ObjectIdentity.get(key);
|
||||||
const previous = this.map[id];
|
const previous = this.map[id];
|
||||||
this.map[id] = value;
|
this.map[id] = value;
|
||||||
|
|
||||||
|
@ -76,7 +78,7 @@ class Dictionary<T, U> {
|
||||||
* has been removed.
|
* has been removed.
|
||||||
*/
|
*/
|
||||||
remove(key: T) {
|
remove(key: T) {
|
||||||
const id = mxObjectIdentity.get(key);
|
const id = ObjectIdentity.get(key);
|
||||||
const previous = this.map[id];
|
const previous = this.map[id];
|
||||||
delete this.map[id];
|
delete this.map[id];
|
||||||
|
|
||||||
|
@ -124,7 +126,7 @@ class Dictionary<T, U> {
|
||||||
*
|
*
|
||||||
* visitor - A function that takes the key and value as arguments.
|
* visitor - A function that takes the key and value as arguments.
|
||||||
*/
|
*/
|
||||||
visit(visitor: Visitor<string, U>) {
|
visit(visitor: Visitor<MapKey, U>) {
|
||||||
for (const key in this.map) {
|
for (const key in this.map) {
|
||||||
visitor(key, this.map[key]);
|
visitor(key, this.map[key]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ type IdentityFunction = {
|
||||||
*
|
*
|
||||||
* The identity for an object does not change during its lifecycle.
|
* The identity for an object does not change during its lifecycle.
|
||||||
*/
|
*/
|
||||||
class mxObjectIdentity {
|
class ObjectIdentity {
|
||||||
/**
|
/**
|
||||||
* Name of the field to be used to store the object ID. Default is
|
* Name of the field to be used to store the object ID. Default is
|
||||||
* <code>mxObjectId</code>.
|
* <code>mxObjectId</code>.
|
||||||
|
@ -48,9 +48,9 @@ class mxObjectIdentity {
|
||||||
if (isNullish(obj[FIELD_NAME])) {
|
if (isNullish(obj[FIELD_NAME])) {
|
||||||
if (typeof obj === 'object') {
|
if (typeof obj === 'object') {
|
||||||
const ctor = getFunctionName(obj.constructor);
|
const ctor = getFunctionName(obj.constructor);
|
||||||
obj[FIELD_NAME] = `${ctor}#${mxObjectIdentity.counter++}`;
|
obj[FIELD_NAME] = `${ctor}#${ObjectIdentity.counter++}`;
|
||||||
} else if (typeof obj === 'function') {
|
} else if (typeof obj === 'function') {
|
||||||
obj[FIELD_NAME] = `Function#${mxObjectIdentity.counter++}`;
|
obj[FIELD_NAME] = `Function#${ObjectIdentity.counter++}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,4 +65,4 @@ class mxObjectIdentity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default mxObjectIdentity;
|
export default ObjectIdentity;
|
|
@ -41,13 +41,8 @@ import Cell from '../view/cell/datatypes/Cell';
|
||||||
import Model from '../view/model/Model';
|
import Model from '../view/model/Model';
|
||||||
import graph from '../view/Graph';
|
import graph from '../view/Graph';
|
||||||
|
|
||||||
import type {
|
import type { CellStateStyles, Properties, StyleProperties, StyleValue } from '../types';
|
||||||
CellStateStyles,
|
import CellArray from '../view/cell/datatypes/CellArray';
|
||||||
Properties,
|
|
||||||
StyleProperties,
|
|
||||||
StyleValue,
|
|
||||||
} from '../types';
|
|
||||||
import CellArray from "../view/cell/datatypes/CellArray";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxUtils
|
* Class: mxUtils
|
||||||
|
@ -164,11 +159,7 @@ export const parseCssNumber = (value: string) => {
|
||||||
* mxUtils.setPrefixedStyle(node.style, 'transformOrigin', '0% 0%');
|
* mxUtils.setPrefixedStyle(node.style, 'transformOrigin', '0% 0%');
|
||||||
* (end)
|
* (end)
|
||||||
*/
|
*/
|
||||||
export const setPrefixedStyle = (
|
export const setPrefixedStyle = (style: StyleProperties, name: string, value: string) => {
|
||||||
style: StyleProperties,
|
|
||||||
name: string,
|
|
||||||
value: string
|
|
||||||
) => {
|
|
||||||
let prefix = null;
|
let prefix = null;
|
||||||
|
|
||||||
if (mxClient.IS_SF || mxClient.IS_GC) {
|
if (mxClient.IS_SF || mxClient.IS_GC) {
|
||||||
|
@ -343,11 +334,7 @@ export const getValue = (array: any, key: string, defaultValue?: any) => {
|
||||||
return value;
|
return value;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getStringValue = (
|
export const getStringValue = (array: any, key: string, defaultValue: string) => {
|
||||||
array: any,
|
|
||||||
key: string,
|
|
||||||
defaultValue: string
|
|
||||||
) => {
|
|
||||||
let value = array != null ? array[key] : null;
|
let value = array != null ? array[key] : null;
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
value = defaultValue;
|
value = defaultValue;
|
||||||
|
@ -455,10 +442,7 @@ export const equalEntries = (a: Properties | null, b: Properties | null) => {
|
||||||
for (var key in a) {
|
for (var key in a) {
|
||||||
count--;
|
count--;
|
||||||
|
|
||||||
if (
|
if ((!Number.isNaN(a[key]) || !Number.isNaN(b[key])) && a[key] !== b[key]) {
|
||||||
(!Number.isNaN(a[key]) || !Number.isNaN(b[key])) &&
|
|
||||||
a[key] !== b[key]
|
|
||||||
) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -588,10 +572,7 @@ export const arcToCurves = (
|
||||||
}
|
}
|
||||||
|
|
||||||
sds =
|
sds =
|
||||||
seif *
|
seif * Math.sqrt((r1x * r2y - r1x * rydd - r2y * rxdd) / (r1x * rydd + r2y * rxdd));
|
||||||
Math.sqrt(
|
|
||||||
(r1x * r2y - r1x * rydd - r2y * rxdd) / (r1x * rydd + r2y * rxdd)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const txd = (sds * r1 * ryd) / r2;
|
const txd = (sds * r1 * ryd) / r2;
|
||||||
|
@ -614,8 +595,7 @@ export const arcToCurves = (
|
||||||
const sse = (dr * 2) / Math.PI;
|
const sse = (dr * 2) / Math.PI;
|
||||||
const seg = Math.ceil(sse < 0 ? -1 * sse : sse);
|
const seg = Math.ceil(sse < 0 ? -1 * sse : sse);
|
||||||
const segr = dr / seg;
|
const segr = dr / seg;
|
||||||
const t =
|
const t = ((8 / 3) * Math.sin(segr / 4) * Math.sin(segr / 4)) / Math.sin(segr / 2);
|
||||||
((8 / 3) * Math.sin(segr / 4) * Math.sin(segr / 4)) / Math.sin(segr / 2);
|
|
||||||
const cpsir1 = cpsi * r1;
|
const cpsir1 = cpsi * r1;
|
||||||
const cpsir2 = cpsi * r2;
|
const cpsir2 = cpsi * r2;
|
||||||
const spsir1 = spsi * r1;
|
const spsir1 = spsi * r1;
|
||||||
|
@ -679,10 +659,7 @@ export const getBoundingBox = (
|
||||||
const cos = Math.cos(rad);
|
const cos = Math.cos(rad);
|
||||||
const sin = Math.sin(rad);
|
const sin = Math.sin(rad);
|
||||||
|
|
||||||
cx =
|
cx = cx != null ? cx : new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
||||||
cx != null
|
|
||||||
? cx
|
|
||||||
: new Point(rect.x + rect.width / 2, rect.y + rect.height / 2);
|
|
||||||
|
|
||||||
let p1 = new Point(rect.x, rect.y);
|
let p1 = new Point(rect.x, rect.y);
|
||||||
let p2 = new Point(rect.x + rect.width, rect.y);
|
let p2 = new Point(rect.x + rect.width, rect.y);
|
||||||
|
@ -708,12 +685,7 @@ export const getBoundingBox = (
|
||||||
*
|
*
|
||||||
* Rotates the given point by the given cos and sin.
|
* Rotates the given point by the given cos and sin.
|
||||||
*/
|
*/
|
||||||
export const getRotatedPoint = (
|
export const getRotatedPoint = (pt: Point, cos: number, sin: number, c = new Point()) => {
|
||||||
pt: Point,
|
|
||||||
cos: number,
|
|
||||||
sin: number,
|
|
||||||
c = new Point()
|
|
||||||
) => {
|
|
||||||
const x = pt.x - c.x;
|
const x = pt.x - c.x;
|
||||||
const y = pt.y - c.y;
|
const y = pt.y - c.y;
|
||||||
|
|
||||||
|
@ -745,11 +717,7 @@ export const getPortConstraints = (
|
||||||
const value = getValue(
|
const value = getValue(
|
||||||
terminal.style,
|
terminal.style,
|
||||||
'portConstraint',
|
'portConstraint',
|
||||||
getValue(
|
getValue(edge.style, source ? 'sourcePortConstraint' : 'targetPortConstraint', null)
|
||||||
edge.style,
|
|
||||||
source ? 'sourcePortConstraint' : 'targetPortConstraint',
|
|
||||||
null
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (isNullish(value)) {
|
if (isNullish(value)) {
|
||||||
|
@ -758,11 +726,7 @@ export const getPortConstraints = (
|
||||||
|
|
||||||
const directions = value.toString();
|
const directions = value.toString();
|
||||||
let returnValue = DIRECTION_MASK_NONE;
|
let returnValue = DIRECTION_MASK_NONE;
|
||||||
const constraintRotationEnabled = getValue(
|
const constraintRotationEnabled = getValue(terminal.style, 'portConstraintRotation', 0);
|
||||||
terminal.style,
|
|
||||||
'portConstraintRotation',
|
|
||||||
0
|
|
||||||
);
|
|
||||||
let rotation = 0;
|
let rotation = 0;
|
||||||
|
|
||||||
if (constraintRotationEnabled == 1) {
|
if (constraintRotationEnabled == 1) {
|
||||||
|
@ -876,11 +840,7 @@ export const reversePortConstraints = (constraint: number) => {
|
||||||
* Finds the index of the nearest segment on the given cell state for
|
* Finds the index of the nearest segment on the given cell state for
|
||||||
* the specified coordinate pair.
|
* the specified coordinate pair.
|
||||||
*/
|
*/
|
||||||
export const findNearestSegment = (
|
export const findNearestSegment = (state: CellState, x: number, y: number) => {
|
||||||
state: CellState,
|
|
||||||
x: number,
|
|
||||||
y: number
|
|
||||||
) => {
|
|
||||||
let index = -1;
|
let index = -1;
|
||||||
|
|
||||||
if (state.absolutePoints.length > 0) {
|
if (state.absolutePoints.length > 0) {
|
||||||
|
@ -979,11 +939,7 @@ export const getDirectedBounds = (
|
||||||
* Returns the intersection between the polygon defined by the array of
|
* Returns the intersection between the polygon defined by the array of
|
||||||
* points and the line between center and point.
|
* points and the line between center and point.
|
||||||
*/
|
*/
|
||||||
export const getPerimeterPoint = (
|
export const getPerimeterPoint = (pts: Point[], center: Point, point: Point) => {
|
||||||
pts: Point[],
|
|
||||||
center: Point,
|
|
||||||
point: Point
|
|
||||||
) => {
|
|
||||||
let min = null;
|
let min = null;
|
||||||
|
|
||||||
for (let i = 0; i < pts.length - 1; i += 1) {
|
for (let i = 0; i < pts.length - 1; i += 1) {
|
||||||
|
@ -1023,11 +979,7 @@ export const getPerimeterPoint = (
|
||||||
* p1 - <mxPoint> that represents the first point of the segment.
|
* p1 - <mxPoint> that represents the first point of the segment.
|
||||||
* p2 - <mxPoint> that represents the second point of the segment.
|
* p2 - <mxPoint> that represents the second point of the segment.
|
||||||
*/
|
*/
|
||||||
export const rectangleIntersectsSegment = (
|
export const rectangleIntersectsSegment = (bounds: Rectangle, p1: Point, p2: Point) => {
|
||||||
bounds: Rectangle,
|
|
||||||
p1: Point,
|
|
||||||
p2: Point
|
|
||||||
) => {
|
|
||||||
const top = bounds.y;
|
const top = bounds.y;
|
||||||
const left = bounds.x;
|
const left = bounds.x;
|
||||||
const bottom = top + bounds.height;
|
const bottom = top + bounds.height;
|
||||||
|
@ -1286,8 +1238,7 @@ export const getDocumentScrollOrigin = (doc: Document) => {
|
||||||
const y =
|
const y =
|
||||||
wnd != null && window.pageYOffset !== undefined
|
wnd != null && window.pageYOffset !== undefined
|
||||||
? window.pageYOffset
|
? window.pageYOffset
|
||||||
: (document.documentElement || document.body.parentNode || document.body)
|
: (document.documentElement || document.body.parentNode || document.body).scrollTop;
|
||||||
.scrollTop;
|
|
||||||
|
|
||||||
return new Point(x, y);
|
return new Point(x, y);
|
||||||
};
|
};
|
||||||
|
@ -1378,7 +1329,7 @@ export const convertPoint = (container: HTMLElement, x: number, y: number) => {
|
||||||
*
|
*
|
||||||
* n - String representing the possibly numeric value.
|
* n - String representing the possibly numeric value.
|
||||||
*/
|
*/
|
||||||
export const isNumeric = (n: string) => {
|
export const isNumeric = (n: any) => {
|
||||||
return (
|
return (
|
||||||
!Number.isNaN(parseFloat(n)) &&
|
!Number.isNaN(parseFloat(n)) &&
|
||||||
isFinite(+n) &&
|
isFinite(+n) &&
|
||||||
|
@ -1792,12 +1743,7 @@ export const removeAllStylenames = (style: string) => {
|
||||||
* key - Key of the style to be changed.
|
* key - Key of the style to be changed.
|
||||||
* value - New value for the given key.
|
* value - New value for the given key.
|
||||||
*/
|
*/
|
||||||
export const setCellStyles = (
|
export const setCellStyles = (model: Model, cells: Cell[], key: string, value: any) => {
|
||||||
model: Model,
|
|
||||||
cells: Cell[],
|
|
||||||
key: string,
|
|
||||||
value: any
|
|
||||||
) => {
|
|
||||||
if (cells.length > 0) {
|
if (cells.length > 0) {
|
||||||
model.beginUpdate();
|
model.beginUpdate();
|
||||||
try {
|
try {
|
||||||
|
@ -1842,8 +1788,7 @@ export const setStyle = (style: string | null, key: string, value: any) => {
|
||||||
if (isValue) {
|
if (isValue) {
|
||||||
style = `${key}=${value}${next < 0 ? ';' : style.substring(next)}`;
|
style = `${key}=${value}${next < 0 ? ';' : style.substring(next)}`;
|
||||||
} else {
|
} else {
|
||||||
style =
|
style = next < 0 || next == style.length - 1 ? '' : style.substring(next + 1);
|
||||||
next < 0 || next == style.length - 1 ? '' : style.substring(next + 1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const index = style.indexOf(`;${key}=`);
|
const index = style.indexOf(`;${key}=`);
|
||||||
|
@ -1861,8 +1806,7 @@ export const setStyle = (style: string | null, key: string, value: any) => {
|
||||||
next < 0 ? ';' : style.substring(next)
|
next < 0 ? ';' : style.substring(next)
|
||||||
}`;
|
}`;
|
||||||
} else {
|
} else {
|
||||||
style =
|
style = style.substring(0, index) + (next < 0 ? ';' : style.substring(next));
|
||||||
style.substring(0, index) + (next < 0 ? ';' : style.substring(next));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2128,9 +2072,7 @@ export const getScaleForPageCount = (
|
||||||
}
|
}
|
||||||
|
|
||||||
pageFormat =
|
pageFormat =
|
||||||
pageFormat != null
|
pageFormat != null ? pageFormat : new Rectangle(...PAGE_FORMAT_A4_PORTRAIT);
|
||||||
? pageFormat
|
|
||||||
: new Rectangle(...PAGE_FORMAT_A4_PORTRAIT);
|
|
||||||
|
|
||||||
const availablePageWidth = pageFormat.width - border * 2;
|
const availablePageWidth = pageFormat.width - border * 2;
|
||||||
const availablePageHeight = pageFormat.height - border * 2;
|
const availablePageHeight = pageFormat.height - border * 2;
|
||||||
|
@ -2202,8 +2144,7 @@ export const getScaleForPageCount = (
|
||||||
roundRowDownProportion = Math.floor(numRowPages - 1) / numRowPages;
|
roundRowDownProportion = Math.floor(numRowPages - 1) / numRowPages;
|
||||||
}
|
}
|
||||||
if (roundColumnDownProportion == 1) {
|
if (roundColumnDownProportion == 1) {
|
||||||
roundColumnDownProportion =
|
roundColumnDownProportion = Math.floor(numColumnPages - 1) / numColumnPages;
|
||||||
Math.floor(numColumnPages - 1) / numColumnPages;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check which rounding down is smaller, but in the case of very small roundings
|
// Check which rounding down is smaller, but in the case of very small roundings
|
||||||
|
@ -2279,13 +2220,11 @@ export const show = (
|
||||||
const dy = Math.ceil(y0 - bounds.y);
|
const dy = Math.ceil(y0 - bounds.y);
|
||||||
|
|
||||||
if (w == null) {
|
if (w == null) {
|
||||||
w =
|
w = Math.ceil(bounds.width + x0) + Math.ceil(Math.ceil(bounds.x) - bounds.x);
|
||||||
Math.ceil(bounds.width + x0) + Math.ceil(Math.ceil(bounds.x) - bounds.x);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (h == null) {
|
if (h == null) {
|
||||||
h =
|
h = Math.ceil(bounds.height + y0) + Math.ceil(Math.ceil(bounds.y) - bounds.y);
|
||||||
Math.ceil(bounds.height + y0) + Math.ceil(Math.ceil(bounds.y) - bounds.y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.writeln('<html><head>');
|
doc.writeln('<html><head>');
|
||||||
|
@ -2322,7 +2261,7 @@ export const show = (
|
||||||
div.style.position = 'absolute';
|
div.style.position = 'absolute';
|
||||||
div.style.left = `${dx}px`;
|
div.style.left = `${dx}px`;
|
||||||
div.style.top = `${dy}px`;
|
div.style.top = `${dy}px`;
|
||||||
|
|
||||||
if (graph.container && graph.view.drawPane) {
|
if (graph.container && graph.view.drawPane) {
|
||||||
let node = graph.container.firstChild;
|
let node = graph.container.firstChild;
|
||||||
let svg: SVGElement | null = null;
|
let svg: SVGElement | null = null;
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { arcToCurves, getRotatedPoint } from '../Utils';
|
||||||
import {
|
import {
|
||||||
DEFAULT_FONTFAMILY,
|
DEFAULT_FONTFAMILY,
|
||||||
DEFAULT_FONTSIZE,
|
DEFAULT_FONTSIZE,
|
||||||
|
DIRECTION_EAST,
|
||||||
NONE,
|
NONE,
|
||||||
SHADOWCOLOR,
|
SHADOWCOLOR,
|
||||||
SHADOW_OFFSET_X,
|
SHADOW_OFFSET_X,
|
||||||
|
@ -18,7 +19,15 @@ import mxUrlConverter from '../network/mxUrlConverter';
|
||||||
import Point from '../../view/geometry/Point';
|
import Point from '../../view/geometry/Point';
|
||||||
import { clone } from '../CloneUtils';
|
import { clone } from '../CloneUtils';
|
||||||
|
|
||||||
import type { CanvasState, ColorValue } from '../../types';
|
import type {
|
||||||
|
AlignValue,
|
||||||
|
CanvasState,
|
||||||
|
ColorValue,
|
||||||
|
DirectionValue,
|
||||||
|
OverflowValue,
|
||||||
|
TextDirectionValue,
|
||||||
|
VAlignValue,
|
||||||
|
} from '../../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxAbstractCanvas2D
|
* Class: mxAbstractCanvas2D
|
||||||
|
@ -30,7 +39,7 @@ import type { CanvasState, ColorValue } from '../../types';
|
||||||
*
|
*
|
||||||
* Constructs a new abstract canvas.
|
* Constructs a new abstract canvas.
|
||||||
*/
|
*/
|
||||||
class mxAbstractCanvas2D {
|
class AbstractCanvas2D {
|
||||||
constructor() {
|
constructor() {
|
||||||
/**
|
/**
|
||||||
* Variable: converter
|
* Variable: converter
|
||||||
|
@ -127,6 +136,9 @@ class mxAbstractCanvas2D {
|
||||||
*/
|
*/
|
||||||
pointerEvents = false;
|
pointerEvents = false;
|
||||||
|
|
||||||
|
// from Polyline (maybe from other shapes also)
|
||||||
|
pointerEventsValue: string | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: createUrlConverter
|
* Function: createUrlConverter
|
||||||
*
|
*
|
||||||
|
@ -159,12 +171,12 @@ class mxAbstractCanvas2D {
|
||||||
alpha: 1,
|
alpha: 1,
|
||||||
fillAlpha: 1,
|
fillAlpha: 1,
|
||||||
strokeAlpha: 1,
|
strokeAlpha: 1,
|
||||||
fillColor: null,
|
fillColor: NONE,
|
||||||
gradientFillAlpha: 1,
|
gradientFillAlpha: 1,
|
||||||
gradientColor: null,
|
gradientColor: NONE,
|
||||||
gradientAlpha: 1,
|
gradientAlpha: 1,
|
||||||
gradientDirection: null,
|
gradientDirection: DIRECTION_EAST,
|
||||||
strokeColor: null,
|
strokeColor: NONE,
|
||||||
strokeWidth: 1,
|
strokeWidth: 1,
|
||||||
dashed: false,
|
dashed: false,
|
||||||
dashPattern: '3 3',
|
dashPattern: '3 3',
|
||||||
|
@ -173,8 +185,8 @@ class mxAbstractCanvas2D {
|
||||||
lineJoin: 'miter',
|
lineJoin: 'miter',
|
||||||
miterLimit: 10,
|
miterLimit: 10,
|
||||||
fontColor: '#000000',
|
fontColor: '#000000',
|
||||||
fontBackgroundColor: null,
|
fontBackgroundColor: NONE,
|
||||||
fontBorderColor: null,
|
fontBorderColor: NONE,
|
||||||
fontSize: DEFAULT_FONTSIZE,
|
fontSize: DEFAULT_FONTSIZE,
|
||||||
fontFamily: DEFAULT_FONTFAMILY,
|
fontFamily: DEFAULT_FONTFAMILY,
|
||||||
fontStyle: 0,
|
fontStyle: 0,
|
||||||
|
@ -291,13 +303,7 @@ class mxAbstractCanvas2D {
|
||||||
*
|
*
|
||||||
* Rotates the current state.
|
* Rotates the current state.
|
||||||
*/
|
*/
|
||||||
rotate(
|
rotate(theta: number, flipH: boolean, flipV: boolean, cx: number, cy: number) {
|
||||||
theta: number,
|
|
||||||
flipH: boolean,
|
|
||||||
flipV: boolean,
|
|
||||||
cx: number,
|
|
||||||
cy: number
|
|
||||||
) {
|
|
||||||
// nop
|
// nop
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,10 +340,8 @@ class mxAbstractCanvas2D {
|
||||||
* Sets the current fill color.
|
* Sets the current fill color.
|
||||||
*/
|
*/
|
||||||
setFillColor(value: ColorValue) {
|
setFillColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.fillColor = value;
|
||||||
|
this.state.gradientColor = NONE;
|
||||||
this.state.fillColor = v;
|
|
||||||
this.state.gradientColor = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -352,7 +356,7 @@ class mxAbstractCanvas2D {
|
||||||
y: number,
|
y: number,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
direction: string | null,
|
direction: DirectionValue,
|
||||||
alpha1 = 1,
|
alpha1 = 1,
|
||||||
alpha2: number = 1
|
alpha2: number = 1
|
||||||
) {
|
) {
|
||||||
|
@ -370,8 +374,7 @@ class mxAbstractCanvas2D {
|
||||||
* Sets the current stroke color.
|
* Sets the current stroke color.
|
||||||
*/
|
*/
|
||||||
setStrokeColor(value: ColorValue) {
|
setStrokeColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.strokeColor = value;
|
||||||
this.state.strokeColor = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -379,7 +382,7 @@ class mxAbstractCanvas2D {
|
||||||
*
|
*
|
||||||
* Sets the current stroke width.
|
* Sets the current stroke width.
|
||||||
*/
|
*/
|
||||||
setStrokeWidth(value: number | null) {
|
setStrokeWidth(value: number) {
|
||||||
this.state.strokeWidth = value;
|
this.state.strokeWidth = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -435,8 +438,7 @@ class mxAbstractCanvas2D {
|
||||||
* Sets the current font color.
|
* Sets the current font color.
|
||||||
*/
|
*/
|
||||||
setFontColor(value: ColorValue) {
|
setFontColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.fontColor = value;
|
||||||
this.state.fontColor = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -445,8 +447,7 @@ class mxAbstractCanvas2D {
|
||||||
* Sets the current font background color.
|
* Sets the current font background color.
|
||||||
*/
|
*/
|
||||||
setFontBackgroundColor(value: ColorValue) {
|
setFontBackgroundColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.fontBackgroundColor = value;
|
||||||
this.state.fontBackgroundColor = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -455,8 +456,7 @@ class mxAbstractCanvas2D {
|
||||||
* Sets the current font border color.
|
* Sets the current font border color.
|
||||||
*/
|
*/
|
||||||
setFontBorderColor(value: ColorValue) {
|
setFontBorderColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.fontBorderColor = value;
|
||||||
this.state.fontBorderColor = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -501,8 +501,7 @@ class mxAbstractCanvas2D {
|
||||||
* Enables or disables and configures the current shadow.
|
* Enables or disables and configures the current shadow.
|
||||||
*/
|
*/
|
||||||
setShadowColor(value: ColorValue) {
|
setShadowColor(value: ColorValue) {
|
||||||
const v = value === NONE ? null : value;
|
this.state.shadowColor = value;
|
||||||
this.state.shadowColor = v;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -567,14 +566,7 @@ class mxAbstractCanvas2D {
|
||||||
*
|
*
|
||||||
* Adds a bezier curve to the current path.
|
* Adds a bezier curve to the current path.
|
||||||
*/
|
*/
|
||||||
curveTo(
|
curveTo(x1: number, y1: number, x2: number, y2: number, x3: number, y3: number) {
|
||||||
x1: number,
|
|
||||||
y1: number,
|
|
||||||
x2: number,
|
|
||||||
y2: number,
|
|
||||||
x3: number,
|
|
||||||
y3: number
|
|
||||||
) {
|
|
||||||
this.addOp(this.curveOp, x1, y1, x2, y2, x3, y3);
|
this.addOp(this.curveOp, x1, y1, x2, y2, x3, y3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -624,14 +616,7 @@ class mxAbstractCanvas2D {
|
||||||
*
|
*
|
||||||
* Closes the current path.
|
* Closes the current path.
|
||||||
*/
|
*/
|
||||||
close(
|
close(x1?: number, y1?: number, x2?: number, y2?: number, x3?: number, y3?: number) {
|
||||||
x1?: number,
|
|
||||||
y1?: number,
|
|
||||||
x2?: number,
|
|
||||||
y2?: number,
|
|
||||||
x3?: number,
|
|
||||||
y3?: number
|
|
||||||
) {
|
|
||||||
this.addOp(this.closeOp);
|
this.addOp(this.closeOp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,6 +626,59 @@ class mxAbstractCanvas2D {
|
||||||
* Empty implementation for backwards compatibility. This will be removed.
|
* Empty implementation for backwards compatibility. This will be removed.
|
||||||
*/
|
*/
|
||||||
end() {}
|
end() {}
|
||||||
|
|
||||||
|
stroke() {}
|
||||||
|
|
||||||
|
fill() {}
|
||||||
|
|
||||||
|
fillAndStroke() {}
|
||||||
|
|
||||||
|
rect(x: number, y: number, w: number, h: number) {}
|
||||||
|
|
||||||
|
roundrect(x: number, y: number, w: number, h: number, r1: number, r2: number) {}
|
||||||
|
|
||||||
|
ellipse(x: number, y: number, w: number, h: number) {}
|
||||||
|
|
||||||
|
image(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
src: string,
|
||||||
|
aspect = true,
|
||||||
|
flipH = false,
|
||||||
|
flipV = false
|
||||||
|
) {}
|
||||||
|
|
||||||
|
text(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
str: string,
|
||||||
|
align: AlignValue,
|
||||||
|
valign: VAlignValue,
|
||||||
|
wrap: boolean,
|
||||||
|
format: string,
|
||||||
|
overflow: OverflowValue,
|
||||||
|
clip: boolean,
|
||||||
|
rotation = 0,
|
||||||
|
dir: TextDirectionValue
|
||||||
|
) {}
|
||||||
|
|
||||||
|
updateText(
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
align: AlignValue,
|
||||||
|
valign: VAlignValue,
|
||||||
|
wrap: boolean,
|
||||||
|
overflow: OverflowValue,
|
||||||
|
clip: boolean,
|
||||||
|
rotation = 0,
|
||||||
|
node: SVGElement
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default mxAbstractCanvas2D;
|
export default AbstractCanvas2D;
|
File diff suppressed because it is too large
Load Diff
|
@ -4,7 +4,7 @@
|
||||||
* Updated to ES9 syntax by David Morrissey 2021
|
* Updated to ES9 syntax by David Morrissey 2021
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import mxAbstractCanvas2D from './mxAbstractCanvas2D';
|
import mxAbstractCanvas2D from './AbstractCanvas2D';
|
||||||
import {
|
import {
|
||||||
DEFAULT_FONTFAMILY,
|
DEFAULT_FONTFAMILY,
|
||||||
DEFAULT_FONTSIZE,
|
DEFAULT_FONTSIZE,
|
||||||
|
@ -916,21 +916,7 @@ class mxXmlCanvas2D extends mxAbstractCanvas2D {
|
||||||
* rotation - Number that specifies the angle of the rotation around the anchor point of the text.
|
* rotation - Number that specifies the angle of the rotation around the anchor point of the text.
|
||||||
* dir - Optional string that specifies the text direction. Possible values are rtl and lrt.
|
* dir - Optional string that specifies the text direction. Possible values are rtl and lrt.
|
||||||
*/
|
*/
|
||||||
text(
|
text(x, y, w, h, str, align, valign, wrap, format, overflow, clip, rotation, dir) {
|
||||||
x,
|
|
||||||
y,
|
|
||||||
w,
|
|
||||||
h,
|
|
||||||
str,
|
|
||||||
align,
|
|
||||||
valign,
|
|
||||||
wrap,
|
|
||||||
format,
|
|
||||||
overflow,
|
|
||||||
clip,
|
|
||||||
rotation,
|
|
||||||
dir
|
|
||||||
) {
|
|
||||||
if (this.textEnabled && str != null) {
|
if (this.textEnabled && str != null) {
|
||||||
if (isNode(str)) {
|
if (isNode(str)) {
|
||||||
str = getOuterHtml(str);
|
str = getOuterHtml(str);
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import Image from './image/Image';
|
import Image from './image/ImageBox';
|
||||||
import EventObject from './event/EventObject';
|
import EventObject from './event/EventObject';
|
||||||
import EventSource from './event/EventSource';
|
import EventSource from './event/EventSource';
|
||||||
import InternalEvent from './event/InternalEvent';
|
import InternalEvent from './event/InternalEvent';
|
||||||
|
@ -23,16 +23,16 @@ import CellRenderer from './cell/CellRenderer';
|
||||||
import CellEditor from './editing/CellEditor';
|
import CellEditor from './editing/CellEditor';
|
||||||
import Point from './geometry/Point';
|
import Point from './geometry/Point';
|
||||||
import {
|
import {
|
||||||
getBoundingBox, getCurrentStyle,
|
getBoundingBox,
|
||||||
getValue, hasScrollbars, parseCssNumber,
|
getCurrentStyle,
|
||||||
|
getValue,
|
||||||
|
hasScrollbars,
|
||||||
|
parseCssNumber,
|
||||||
} from '../util/Utils';
|
} from '../util/Utils';
|
||||||
import Cell from './cell/datatypes/Cell';
|
import Cell from './cell/datatypes/Cell';
|
||||||
import Model from './model/Model';
|
import Model from './model/Model';
|
||||||
import Stylesheet from './style/Stylesheet';
|
import Stylesheet from './style/Stylesheet';
|
||||||
import {
|
import { DIALECT_SVG, PAGE_FORMAT_A4_PORTRAIT } from '../util/Constants';
|
||||||
DIALECT_SVG,
|
|
||||||
PAGE_FORMAT_A4_PORTRAIT,
|
|
||||||
} from '../util/Constants';
|
|
||||||
|
|
||||||
import ChildChange from './model/ChildChange';
|
import ChildChange from './model/ChildChange';
|
||||||
import GeometryChange from './geometry/GeometryChange';
|
import GeometryChange from './geometry/GeometryChange';
|
||||||
|
@ -42,12 +42,12 @@ import TerminalChange from './cell/edge/TerminalChange';
|
||||||
import ValueChange from './cell/ValueChange';
|
import ValueChange from './cell/ValueChange';
|
||||||
import CellState from './cell/datatypes/CellState';
|
import CellState from './cell/datatypes/CellState';
|
||||||
import { isNode } from '../util/DomUtils';
|
import { isNode } from '../util/DomUtils';
|
||||||
import CellArray from "./cell/datatypes/CellArray";
|
import CellArray from './cell/datatypes/CellArray';
|
||||||
import EdgeStyle from "./style/EdgeStyle";
|
import EdgeStyle from './style/EdgeStyle';
|
||||||
import EdgeHandler from "./cell/edge/EdgeHandler";
|
import EdgeHandler from './cell/edge/EdgeHandler';
|
||||||
import VertexHandler from "./cell/vertex/VertexHandler";
|
import VertexHandler from './cell/vertex/VertexHandler';
|
||||||
import EdgeSegmentHandler from "./cell/edge/EdgeSegmentHandler";
|
import EdgeSegmentHandler from './cell/edge/EdgeSegmentHandler';
|
||||||
import ElbowEdgeHandler from "./cell/edge/ElbowEdgeHandler";
|
import ElbowEdgeHandler from './cell/edge/ElbowEdgeHandler';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link EventSource} to implement a graph component for
|
* Extends {@link EventSource} to implement a graph component for
|
||||||
|
@ -83,9 +83,7 @@ class Graph extends EventSource {
|
||||||
this.model = model != null ? model : new Model();
|
this.model = model != null ? model : new Model();
|
||||||
this.cellRenderer = this.createCellRenderer();
|
this.cellRenderer = this.createCellRenderer();
|
||||||
this.setSelectionModel(this.createSelectionModel());
|
this.setSelectionModel(this.createSelectionModel());
|
||||||
this.setStylesheet(
|
this.setStylesheet(stylesheet != null ? stylesheet : this.createStylesheet());
|
||||||
stylesheet != null ? stylesheet : this.createStylesheet()
|
|
||||||
);
|
|
||||||
this.view = this.createGraphView();
|
this.view = this.createGraphView();
|
||||||
|
|
||||||
// Adds a graph model listener to update the view
|
// Adds a graph model listener to update the view
|
||||||
|
@ -673,10 +671,7 @@ class Graph extends EventSource {
|
||||||
|
|
||||||
// Handles two special cases where the shape does not need to be
|
// Handles two special cases where the shape does not need to be
|
||||||
// recreated from scratch, it only needs to be invalidated.
|
// recreated from scratch, it only needs to be invalidated.
|
||||||
else if (
|
else if (change instanceof TerminalChange || change instanceof GeometryChange) {
|
||||||
change instanceof TerminalChange ||
|
|
||||||
change instanceof GeometryChange
|
|
||||||
) {
|
|
||||||
// Checks if the geometry has changed to avoid unnessecary revalidation
|
// Checks if the geometry has changed to avoid unnessecary revalidation
|
||||||
if (
|
if (
|
||||||
change instanceof TerminalChange ||
|
change instanceof TerminalChange ||
|
||||||
|
@ -807,21 +802,13 @@ class Graph extends EventSource {
|
||||||
|
|
||||||
return new Rectangle(
|
return new Rectangle(
|
||||||
parseCssNumber(css.paddingLeft) +
|
parseCssNumber(css.paddingLeft) +
|
||||||
(css.borderLeftStyle != 'none'
|
(css.borderLeftStyle != 'none' ? parseCssNumber(css.borderLeftWidth) : 0),
|
||||||
? parseCssNumber(css.borderLeftWidth)
|
|
||||||
: 0),
|
|
||||||
parseCssNumber(css.paddingTop) +
|
parseCssNumber(css.paddingTop) +
|
||||||
(css.borderTopStyle != 'none'
|
(css.borderTopStyle != 'none' ? parseCssNumber(css.borderTopWidth) : 0),
|
||||||
? parseCssNumber(css.borderTopWidth)
|
|
||||||
: 0),
|
|
||||||
parseCssNumber(css.paddingRight) +
|
parseCssNumber(css.paddingRight) +
|
||||||
(css.borderRightStyle != 'none'
|
(css.borderRightStyle != 'none' ? parseCssNumber(css.borderRightWidth) : 0),
|
||||||
? parseCssNumber(css.borderRightWidth)
|
|
||||||
: 0),
|
|
||||||
parseCssNumber(css.paddingBottom) +
|
parseCssNumber(css.paddingBottom) +
|
||||||
(css.borderBottomStyle != 'none'
|
(css.borderBottomStyle != 'none' ? parseCssNumber(css.borderBottomWidth) : 0)
|
||||||
? parseCssNumber(css.borderBottomWidth)
|
|
||||||
: 0)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -909,8 +896,7 @@ class Graph extends EventSource {
|
||||||
if (this.container != null) {
|
if (this.container != null) {
|
||||||
// Adds spacing and border from css
|
// Adds spacing and border from css
|
||||||
const cssBorder = this.getBorderSizes();
|
const cssBorder = this.getBorderSizes();
|
||||||
let w1: number =
|
let w1: number = this.container.offsetWidth - cssBorder.x - cssBorder.width - 1;
|
||||||
this.container.offsetWidth - cssBorder.x - cssBorder.width - 1;
|
|
||||||
let h1: number =
|
let h1: number =
|
||||||
maxHeight != null
|
maxHeight != null
|
||||||
? maxHeight
|
? maxHeight
|
||||||
|
@ -962,19 +948,13 @@ class Graph extends EventSource {
|
||||||
const x0 =
|
const x0 =
|
||||||
bounds.x != null
|
bounds.x != null
|
||||||
? Math.floor(
|
? Math.floor(
|
||||||
this.view.translate.x -
|
this.view.translate.x - bounds.x / s + border / s2 + margin / 2
|
||||||
bounds.x / s +
|
|
||||||
border / s2 +
|
|
||||||
margin / 2
|
|
||||||
)
|
)
|
||||||
: border;
|
: border;
|
||||||
const y0 =
|
const y0 =
|
||||||
bounds.y != null
|
bounds.y != null
|
||||||
? Math.floor(
|
? Math.floor(
|
||||||
this.view.translate.y -
|
this.view.translate.y - bounds.y / s + border / s2 + margin / 2
|
||||||
bounds.y / s +
|
|
||||||
border / s2 +
|
|
||||||
margin / 2
|
|
||||||
)
|
)
|
||||||
: border;
|
: border;
|
||||||
|
|
||||||
|
@ -1026,9 +1006,7 @@ class Graph extends EventSource {
|
||||||
*
|
*
|
||||||
* @param state {@link mxCellState} whose handler should be created.
|
* @param state {@link mxCellState} whose handler should be created.
|
||||||
*/
|
*/
|
||||||
createHandler(
|
createHandler(state: CellState): mxEdgeHandler | VertexHandler | null {
|
||||||
state: CellState
|
|
||||||
): mxEdgeHandler | VertexHandler | null {
|
|
||||||
let result: mxEdgeHandler | VertexHandler | null = null;
|
let result: mxEdgeHandler | VertexHandler | null = null;
|
||||||
|
|
||||||
if (state.cell.isEdge()) {
|
if (state.cell.isEdge()) {
|
||||||
|
@ -1242,7 +1220,6 @@ class Graph extends EventSource {
|
||||||
cx: number = 0.5,
|
cx: number = 0.5,
|
||||||
cy: number = 0.5
|
cy: number = 0.5
|
||||||
): void {
|
): void {
|
||||||
|
|
||||||
const container = <HTMLElement>this.container;
|
const container = <HTMLElement>this.container;
|
||||||
const _hasScrollbars = hasScrollbars(this.container);
|
const _hasScrollbars = hasScrollbars(this.container);
|
||||||
const padding = 2 * this.getBorder();
|
const padding = 2 * this.getBorder();
|
||||||
|
|
|
@ -19,10 +19,10 @@ import graph from './Graph';
|
||||||
import ImageShape from './geometry/shape/node/ImageShape';
|
import ImageShape from './geometry/shape/node/ImageShape';
|
||||||
import InternalEvent from './event/InternalEvent';
|
import InternalEvent from './event/InternalEvent';
|
||||||
import utils from '../util/Utils';
|
import utils from '../util/Utils';
|
||||||
import Image from './image/Image';
|
import Image from './image/ImageBox';
|
||||||
import EventObject from './event/EventObject';
|
import EventObject from './event/EventObject';
|
||||||
import { getSource, isMouseEvent } from '../util/EventUtils';
|
import { getSource, isMouseEvent } from '../util/EventUtils';
|
||||||
import EventSource from "./event/EventSource";
|
import EventSource from './event/EventSource';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class Outline
|
* @class Outline
|
||||||
|
@ -510,10 +510,8 @@ class Outline {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Adds the scrollbar offset to the finder
|
// Adds the scrollbar offset to the finder
|
||||||
this.bounds.x +=
|
this.bounds.x += (this.source.container.scrollLeft * navView.scale) / scale;
|
||||||
(this.source.container.scrollLeft * navView.scale) / scale;
|
this.bounds.y += (this.source.container.scrollTop * navView.scale) / scale;
|
||||||
this.bounds.y +=
|
|
||||||
(this.source.container.scrollTop * navView.scale) / scale;
|
|
||||||
|
|
||||||
const selectionBorder = <RectangleShape>this.selectionBorder;
|
const selectionBorder = <RectangleShape>this.selectionBorder;
|
||||||
let b = <Rectangle>selectionBorder.bounds;
|
let b = <Rectangle>selectionBorder.bounds;
|
||||||
|
@ -567,12 +565,7 @@ class Outline {
|
||||||
const tol = !isMouseEvent(me.getEvent()) ? this.source.tolerance : 0;
|
const tol = !isMouseEvent(me.getEvent()) ? this.source.tolerance : 0;
|
||||||
const hit =
|
const hit =
|
||||||
tol > 0
|
tol > 0
|
||||||
? new Rectangle(
|
? new Rectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol)
|
||||||
me.getGraphX() - tol,
|
|
||||||
me.getGraphY() - tol,
|
|
||||||
2 * tol,
|
|
||||||
2 * tol
|
|
||||||
)
|
|
||||||
: null;
|
: null;
|
||||||
this.zoom =
|
this.zoom =
|
||||||
me.isSource(this.sizer) ||
|
me.isSource(this.sizer) ||
|
||||||
|
@ -691,10 +684,7 @@ class Outline {
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
getTranslateForEvent(me: InternalMouseEvent): Point {
|
getTranslateForEvent(me: InternalMouseEvent): Point {
|
||||||
return new Point(
|
return new Point(me.getX() - <number>this.startX, me.getY() - <number>this.startY);
|
||||||
me.getX() - <number>this.startX,
|
|
||||||
me.getY() - <number>this.startY
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -713,10 +703,7 @@ class Outline {
|
||||||
if (!this.zoom) {
|
if (!this.zoom) {
|
||||||
// Applies the new translation if the source
|
// Applies the new translation if the source
|
||||||
// has no scrollbars
|
// has no scrollbars
|
||||||
if (
|
if (!source.useScrollbarsForPanning || !utils.hasScrollbars(source.container)) {
|
||||||
!source.useScrollbarsForPanning ||
|
|
||||||
!utils.hasScrollbars(source.container)
|
|
||||||
) {
|
|
||||||
source.panGraph(0, 0);
|
source.panGraph(0, 0);
|
||||||
dx /= outline.getView().scale;
|
dx /= outline.getView().scale;
|
||||||
dy /= outline.getView().scale;
|
dy /= outline.getView().scale;
|
||||||
|
@ -727,10 +714,7 @@ class Outline {
|
||||||
// Applies the new zoom
|
// Applies the new zoom
|
||||||
const w = (<Rectangle>selectionBorder.bounds).width;
|
const w = (<Rectangle>selectionBorder.bounds).width;
|
||||||
const { scale } = source.getView();
|
const { scale } = source.getView();
|
||||||
source.zoomTo(
|
source.zoomTo(Math.max(this.minScale, scale - (dx * scale) / w), false);
|
||||||
Math.max(this.minScale, scale - (dx * scale) / w),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.update();
|
this.update();
|
||||||
|
@ -752,11 +736,7 @@ class Outline {
|
||||||
this.source.removeListener(this.refreshHandler);
|
this.source.removeListener(this.refreshHandler);
|
||||||
this.source.getModel().removeListener(this.updateHandler);
|
this.source.getModel().removeListener(this.updateHandler);
|
||||||
this.source.getView().removeListener(this.updateHandler);
|
this.source.getView().removeListener(this.updateHandler);
|
||||||
InternalEvent.removeListener(
|
InternalEvent.removeListener(this.source.container, 'scroll', this.updateHandler);
|
||||||
this.source.container,
|
|
||||||
'scroll',
|
|
||||||
this.updateHandler
|
|
||||||
);
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
this.source = null;
|
this.source = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import {
|
||||||
import CellHighlight from '../selection/CellHighlight';
|
import CellHighlight from '../selection/CellHighlight';
|
||||||
import EventObject from '../event/EventObject';
|
import EventObject from '../event/EventObject';
|
||||||
import InternalEvent from '../event/InternalEvent';
|
import InternalEvent from '../event/InternalEvent';
|
||||||
import utils, { intersectsHotspot } from '../../util/Utils';
|
import utils, { intersectsHotspot, isNumeric } from '../../util/Utils';
|
||||||
import graph from '../Graph';
|
import graph from '../Graph';
|
||||||
import { ColorValue } from '../../types';
|
import { ColorValue } from '../../types';
|
||||||
import CellState from './datatypes/CellState';
|
import CellState from './datatypes/CellState';
|
||||||
|
@ -274,9 +274,9 @@ class CellMarker extends EventSource {
|
||||||
* Sets and marks the current valid state.
|
* Sets and marks the current valid state.
|
||||||
*/
|
*/
|
||||||
setCurrentState(
|
setCurrentState(
|
||||||
state: CellState,
|
state: CellState | null,
|
||||||
me: InternalMouseEvent,
|
me: InternalMouseEvent,
|
||||||
color: ColorValue = null
|
color: ColorValue | null = null
|
||||||
) {
|
) {
|
||||||
const isValid = state ? this.isValidState(state) : false;
|
const isValid = state ? this.isValidState(state) : false;
|
||||||
color = color ?? this.getMarkerColor(me.getEvent(), state, isValid);
|
color = color ?? this.getMarkerColor(me.getEvent(), state, isValid);
|
||||||
|
@ -305,8 +305,7 @@ class CellMarker extends EventSource {
|
||||||
*
|
*
|
||||||
* Marks the given cell using the given color, or <validColor> if no color is specified.
|
* Marks the given cell using the given color, or <validColor> if no color is specified.
|
||||||
*/
|
*/
|
||||||
markCell(cell: Cell,
|
markCell(cell: Cell, color: ColorValue) {
|
||||||
color: ColorValue) {
|
|
||||||
const state = this.graph.getView().getState(cell);
|
const state = this.graph.getView().getState(cell);
|
||||||
|
|
||||||
if (state) {
|
if (state) {
|
||||||
|
@ -353,9 +352,7 @@ class CellMarker extends EventSource {
|
||||||
* Returns the valid- or invalidColor depending on the value of isValid.
|
* Returns the valid- or invalidColor depending on the value of isValid.
|
||||||
* The given <mxCellState> is ignored by this implementation.
|
* The given <mxCellState> is ignored by this implementation.
|
||||||
*/
|
*/
|
||||||
getMarkerColor(evt: Event,
|
getMarkerColor(evt: Event, state: CellState | null, isValid: boolean) {
|
||||||
state: CellState,
|
|
||||||
isValid: boolean): string {
|
|
||||||
return isValid ? this.validColor : this.invalidColor;
|
return isValid ? this.validColor : this.invalidColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,7 +376,7 @@ class CellMarker extends EventSource {
|
||||||
* Returns the <mxCell> for the given event and cell. This returns the
|
* Returns the <mxCell> for the given event and cell. This returns the
|
||||||
* given cell.
|
* given cell.
|
||||||
*/
|
*/
|
||||||
getCell(me: InternalMouseEvent): Cell {
|
getCell(me: InternalMouseEvent) {
|
||||||
return me.getCell();
|
return me.getCell();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,17 +397,21 @@ class CellMarker extends EventSource {
|
||||||
* This returns true if the <hotspot> is 0 or the coordinates are inside
|
* This returns true if the <hotspot> is 0 or the coordinates are inside
|
||||||
* the hotspot for the given cell state.
|
* the hotspot for the given cell state.
|
||||||
*/
|
*/
|
||||||
intersects(state: CellState, me: InternalMouseEvent): boolean {
|
intersects(state: CellState, me: InternalMouseEvent) {
|
||||||
if (this.hotspotEnabled) {
|
const x = me.getGraphX();
|
||||||
|
const y = me.getGraphY();
|
||||||
|
|
||||||
|
if (this.hotspotEnabled && isNumeric(x) && isNumeric(y)) {
|
||||||
return intersectsHotspot(
|
return intersectsHotspot(
|
||||||
state,
|
state,
|
||||||
me.getGraphX(),
|
x as number,
|
||||||
me.getGraphY(),
|
y as number,
|
||||||
this.hotspot,
|
this.hotspot,
|
||||||
MIN_HOTSPOT_SIZE,
|
MIN_HOTSPOT_SIZE,
|
||||||
MAX_HOTSPOT_SIZE
|
MAX_HOTSPOT_SIZE
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,9 +420,7 @@ class CellMarker extends EventSource {
|
||||||
*
|
*
|
||||||
* Destroys the handler and all its resources and DOM nodes.
|
* Destroys the handler and all its resources and DOM nodes.
|
||||||
*/
|
*/
|
||||||
destroy(): void {
|
destroy() {
|
||||||
this.graph.getView().removeListener(this.resetHandler);
|
|
||||||
this.graph.getModel().removeListener(this.resetHandler);
|
|
||||||
this.highlight.destroy();
|
this.highlight.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
import Point from '../geometry/Point';
|
import Point from '../geometry/Point';
|
||||||
import Rectangle from '../geometry/Rectangle';
|
import Rectangle from '../geometry/Rectangle';
|
||||||
import EventSource from '../event/EventSource';
|
import EventSource from '../event/EventSource';
|
||||||
import Image from '../image/Image';
|
import ImageBox from '../image/ImageBox';
|
||||||
import CellState from "./datatypes/CellState";
|
import CellState from './datatypes/CellState';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxCellOverlay
|
* Class: mxCellOverlay
|
||||||
|
@ -66,12 +66,14 @@ import CellState from "./datatypes/CellState";
|
||||||
* (default).
|
* (default).
|
||||||
*/
|
*/
|
||||||
class CellOverlay extends EventSource {
|
class CellOverlay extends EventSource {
|
||||||
constructor(image: Image,
|
constructor(
|
||||||
tooltip: string | null=null,
|
image: ImageBox,
|
||||||
align: string='right',
|
tooltip: string | null = null,
|
||||||
verticalAlign: string='bottom',
|
align: string = 'right',
|
||||||
offset: Point=new Point(),
|
verticalAlign: string = 'bottom',
|
||||||
cursor: string='help') {
|
offset: Point = new Point(),
|
||||||
|
cursor: string = 'help'
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.image = image;
|
this.image = image;
|
||||||
|
@ -85,14 +87,14 @@ class CellOverlay extends EventSource {
|
||||||
*
|
*
|
||||||
* Holds the <mxImage> to be used as the icon.
|
* Holds the <mxImage> to be used as the icon.
|
||||||
*/
|
*/
|
||||||
image: Image | null = null;
|
image: ImageBox;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: tooltip
|
* Variable: tooltip
|
||||||
*
|
*
|
||||||
* Holds the optional string to be used as the tooltip.
|
* Holds the optional string to be used as the tooltip.
|
||||||
*/
|
*/
|
||||||
tooltip?: string | null = null;
|
tooltip?: string | null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: align
|
* Variable: align
|
||||||
|
@ -118,14 +120,14 @@ class CellOverlay extends EventSource {
|
||||||
* Holds the offset as an <mxPoint>. The offset will be scaled according to the
|
* Holds the offset as an <mxPoint>. The offset will be scaled according to the
|
||||||
* current scale.
|
* current scale.
|
||||||
*/
|
*/
|
||||||
offset: Point = new Point();
|
offset = new Point();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: cursor
|
* Variable: cursor
|
||||||
*
|
*
|
||||||
* Holds the cursor for the overlay. Default is 'help'.
|
* Holds the cursor for the overlay. Default is 'help'.
|
||||||
*/
|
*/
|
||||||
cursor: string = 'help';
|
cursor = 'help';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: defaultOverlap
|
* Variable: defaultOverlap
|
||||||
|
@ -133,7 +135,7 @@ class CellOverlay extends EventSource {
|
||||||
* Defines the overlapping for the overlay, that is, the proportional distance
|
* Defines the overlapping for the overlay, that is, the proportional distance
|
||||||
* from the origin to the point defined by the alignment. Default is 0.5.
|
* from the origin to the point defined by the alignment. Default is 0.5.
|
||||||
*/
|
*/
|
||||||
defaultOverlap: number = 0.5;
|
defaultOverlap = 0.5;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: getBounds
|
* Function: getBounds
|
||||||
|
@ -173,7 +175,7 @@ class CellOverlay extends EventSource {
|
||||||
const s = state.view.scale;
|
const s = state.view.scale;
|
||||||
let pt = null;
|
let pt = null;
|
||||||
|
|
||||||
const image = <Image>this.image;
|
const image = this.image;
|
||||||
const w = image.width;
|
const w = image.width;
|
||||||
const h = image.height;
|
const h = image.height;
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ class CellRenderer {
|
||||||
|
|
||||||
if (shape) {
|
if (shape) {
|
||||||
shape.apply(state);
|
shape.apply(state);
|
||||||
shape.image = state.getImage();
|
shape.imageSrc = state.getImage();
|
||||||
shape.indicatorColor = state.getIndicatorColor();
|
shape.indicatorColor = state.getIndicatorColor();
|
||||||
shape.indicatorStrokeColor = state.style.indicatorStrokeColor;
|
shape.indicatorStrokeColor = state.style.indicatorStrokeColor;
|
||||||
shape.indicatorGradientColor = state.getIndicatorGradientColor();
|
shape.indicatorGradientColor = state.getIndicatorGradientColor();
|
||||||
|
@ -371,11 +371,7 @@ class CellRenderer {
|
||||||
} else if (value === 'indicated' && state.shape != null) {
|
} else if (value === 'indicated' && state.shape != null) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
shape[field] = state.shape.indicatorColor;
|
shape[field] = state.shape.indicatorColor;
|
||||||
} else if (
|
} else if (key !== 'fillColor' && value === 'fillColor' && state.shape != null) {
|
||||||
key !== 'fillColor' &&
|
|
||||||
value === 'fillColor' &&
|
|
||||||
state.shape != null
|
|
||||||
) {
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
shape[field] = state.style.fillColor;
|
shape[field] = state.style.fillColor;
|
||||||
} else if (
|
} else if (
|
||||||
|
@ -465,9 +461,7 @@ class CellRenderer {
|
||||||
);
|
);
|
||||||
state.text.opacity =
|
state.text.opacity =
|
||||||
state.style.textOpacity == null ? 100 : state.style.textOpacity;
|
state.style.textOpacity == null ? 100 : state.style.textOpacity;
|
||||||
state.text.dialect = isForceHtml
|
state.text.dialect = isForceHtml ? DIALECT_STRICTHTML : state.view.graph.dialect;
|
||||||
? DIALECT_STRICTHTML
|
|
||||||
: state.view.graph.dialect;
|
|
||||||
state.text.style = state.style;
|
state.text.style = state.style;
|
||||||
state.text.state = state;
|
state.text.state = state;
|
||||||
this.initializeLabel(state, state.text);
|
this.initializeLabel(state, state.text);
|
||||||
|
@ -489,9 +483,7 @@ class CellRenderer {
|
||||||
// Dispatches the drop event to the graph which
|
// Dispatches the drop event to the graph which
|
||||||
// consumes and executes the source function
|
// consumes and executes the source function
|
||||||
const pt = convertPoint(graph.container, x, y);
|
const pt = convertPoint(graph.container, x, y);
|
||||||
result = <CellState>(
|
result = <CellState>graph.view.getState(graph.getCellAt(pt.x, pt.y));
|
||||||
graph.view.getState(graph.getCellAt(pt.x, pt.y))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -506,8 +498,7 @@ class CellRenderer {
|
||||||
new InternalMouseEvent(evt, state)
|
new InternalMouseEvent(evt, state)
|
||||||
);
|
);
|
||||||
forceGetCell =
|
forceGetCell =
|
||||||
graph.dialect !== DIALECT_SVG &&
|
graph.dialect !== DIALECT_SVG && getSource(evt).nodeName === 'IMG';
|
||||||
getSource(evt).nodeName === 'IMG';
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(evt: MouseEvent) => {
|
(evt: MouseEvent) => {
|
||||||
|
@ -576,8 +567,7 @@ class CellRenderer {
|
||||||
dict = new Dictionary();
|
dict = new Dictionary();
|
||||||
|
|
||||||
for (let i = 0; i < overlays.length; i += 1) {
|
for (let i = 0; i < overlays.length; i += 1) {
|
||||||
const shape =
|
const shape = state.overlays != null ? state.overlays.remove(overlays[i]) : null;
|
||||||
state.overlays != null ? state.overlays.remove(overlays[i]) : null;
|
|
||||||
|
|
||||||
if (shape == null) {
|
if (shape == null) {
|
||||||
const tmp = new ImageShape(
|
const tmp = new ImageShape(
|
||||||
|
@ -645,7 +635,7 @@ class CellRenderer {
|
||||||
}
|
}
|
||||||
|
|
||||||
overlay.fireEvent(
|
overlay.fireEvent(
|
||||||
new EventObject(InternalEvent.CLICK, {event: evt, cell: state.cell})
|
new EventObject(InternalEvent.CLICK, { event: evt, cell: state.cell })
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -655,14 +645,17 @@ class CellRenderer {
|
||||||
InternalEvent.consume(evt);
|
InternalEvent.consume(evt);
|
||||||
},
|
},
|
||||||
(evt: Event) => {
|
(evt: Event) => {
|
||||||
graph.event.fireMouseEvent(InternalEvent.MOUSE_MOVE, new InternalMouseEvent(evt, state));
|
graph.event.fireMouseEvent(
|
||||||
|
InternalEvent.MOUSE_MOVE,
|
||||||
|
new InternalMouseEvent(evt, state)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
if (mxClient.IS_TOUCH) {
|
if (mxClient.IS_TOUCH) {
|
||||||
InternalEvent.addListener(shape.node, 'touchend', (evt: Event) => {
|
InternalEvent.addListener(shape.node, 'touchend', (evt: Event) => {
|
||||||
overlay.fireEvent(
|
overlay.fireEvent(
|
||||||
new EventObject(InternalEvent.CLICK, {event: evt, cell: state.cell})
|
new EventObject(InternalEvent.CLICK, { event: evt, cell: state.cell })
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -746,9 +739,7 @@ class CellRenderer {
|
||||||
// should go into the graph container directly in order to be clickable. Otherwise
|
// should go into the graph container directly in order to be clickable. Otherwise
|
||||||
// it is obscured by the HTML label that overlaps the cell.
|
// it is obscured by the HTML label that overlaps the cell.
|
||||||
const isForceHtml =
|
const isForceHtml =
|
||||||
graph.isHtmlLabel(state.cell) &&
|
graph.isHtmlLabel(state.cell) && mxClient.NO_FO && graph.dialect === DIALECT_SVG;
|
||||||
mxClient.NO_FO &&
|
|
||||||
graph.dialect === DIALECT_SVG;
|
|
||||||
|
|
||||||
if (isForceHtml) {
|
if (isForceHtml) {
|
||||||
control.dialect = DIALECT_PREFERHTML;
|
control.dialect = DIALECT_PREFERHTML;
|
||||||
|
@ -791,7 +782,10 @@ class CellRenderer {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
(evt: Event) => {
|
(evt: Event) => {
|
||||||
graph.event.fireMouseEvent(InternalEvent.MOUSE_UP, new InternalMouseEvent(evt, state));
|
graph.event.fireMouseEvent(
|
||||||
|
InternalEvent.MOUSE_UP,
|
||||||
|
new InternalMouseEvent(evt, state)
|
||||||
|
);
|
||||||
InternalEvent.consume(evt);
|
InternalEvent.consume(evt);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -833,8 +827,7 @@ class CellRenderer {
|
||||||
* state - <mxCellState> whose shape fired the event.
|
* state - <mxCellState> whose shape fired the event.
|
||||||
* evt - Mouse event which was fired.
|
* evt - Mouse event which was fired.
|
||||||
*/
|
*/
|
||||||
isShapeEvent(state: CellState,
|
isShapeEvent(state: CellState, evt: InternalMouseEvent | MouseEvent): boolean {
|
||||||
evt: InternalMouseEvent | MouseEvent): boolean {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,8 +842,7 @@ class CellRenderer {
|
||||||
* state - <mxCellState> whose label fired the event.
|
* state - <mxCellState> whose label fired the event.
|
||||||
* evt - Mouse event which was fired.
|
* evt - Mouse event which was fired.
|
||||||
*/
|
*/
|
||||||
isLabelEvent(state: CellState,
|
isLabelEvent(state: CellState, evt: InternalMouseEvent | MouseEvent): boolean {
|
||||||
evt: InternalMouseEvent | MouseEvent): boolean {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -938,15 +930,13 @@ class CellRenderer {
|
||||||
*
|
*
|
||||||
* state - <mxCellState> whose label should be redrawn.
|
* state - <mxCellState> whose label should be redrawn.
|
||||||
*/
|
*/
|
||||||
redrawLabel(state: CellState,
|
redrawLabel(state: CellState, forced: boolean): void {
|
||||||
forced: boolean): void {
|
|
||||||
const { graph } = state.view;
|
const { graph } = state.view;
|
||||||
const value = this.getLabelValue(state);
|
const value = this.getLabelValue(state);
|
||||||
const wrapping = graph.isWrapping(state.cell);
|
const wrapping = graph.isWrapping(state.cell);
|
||||||
const clipping = graph.isLabelClipped(state.cell);
|
const clipping = graph.isLabelClipped(state.cell);
|
||||||
const isForceHtml =
|
const isForceHtml =
|
||||||
state.view.graph.isHtmlLabel(state.cell) ||
|
state.view.graph.isHtmlLabel(state.cell) || (value != null && isNode(value));
|
||||||
(value != null && isNode(value));
|
|
||||||
const dialect = isForceHtml ? DIALECT_STRICTHTML : state.view.graph.dialect;
|
const dialect = isForceHtml ? DIALECT_STRICTHTML : state.view.graph.dialect;
|
||||||
const overflow = state.style.overflow || 'visible';
|
const overflow = state.style.overflow || 'visible';
|
||||||
|
|
||||||
|
@ -961,11 +951,7 @@ class CellRenderer {
|
||||||
state.text = null;
|
state.text = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (state.text == null && value != null && (isNode(value) || value.length > 0)) {
|
||||||
state.text == null &&
|
|
||||||
value != null &&
|
|
||||||
(isNode(value) || value.length > 0)
|
|
||||||
) {
|
|
||||||
this.createLabel(state, value);
|
this.createLabel(state, value);
|
||||||
} else if (state.text != null && (value == null || value.length == 0)) {
|
} else if (state.text != null && (value == null || value.length == 0)) {
|
||||||
state.text.destroy();
|
state.text.destroy();
|
||||||
|
@ -977,10 +963,7 @@ class CellRenderer {
|
||||||
// result in getLabelBounds we apply the new style to the shape
|
// result in getLabelBounds we apply the new style to the shape
|
||||||
if (forced) {
|
if (forced) {
|
||||||
// Checks if a full repaint is needed
|
// Checks if a full repaint is needed
|
||||||
if (
|
if (state.text.lastValue != null && this.isTextShapeInvalid(state, state.text)) {
|
||||||
state.text.lastValue != null &&
|
|
||||||
this.isTextShapeInvalid(state, state.text)
|
|
||||||
) {
|
|
||||||
// Forces a full repaint
|
// Forces a full repaint
|
||||||
state.text.lastValue = null;
|
state.text.lastValue = null;
|
||||||
}
|
}
|
||||||
|
@ -1035,8 +1018,7 @@ class CellRenderer {
|
||||||
* state - <mxCellState> whose label should be checked.
|
* state - <mxCellState> whose label should be checked.
|
||||||
* shape - <mxText> shape to be checked.
|
* shape - <mxText> shape to be checked.
|
||||||
*/
|
*/
|
||||||
isTextShapeInvalid(state: CellState,
|
isTextShapeInvalid(state: CellState, shape: TextShape): boolean {
|
||||||
shape: TextShape): boolean {
|
|
||||||
function check(property: string, stylename: string, defaultValue: any) {
|
function check(property: string, stylename: string, defaultValue: any) {
|
||||||
let result = false;
|
let result = false;
|
||||||
|
|
||||||
|
@ -1049,8 +1031,7 @@ class CellRenderer {
|
||||||
) {
|
) {
|
||||||
result =
|
result =
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
parseFloat(String(shape[property])) -
|
parseFloat(String(shape[property])) - parseFloat(String(shape.spacing)) !==
|
||||||
parseFloat(String(shape.spacing)) !==
|
|
||||||
(state.style[stylename] || defaultValue);
|
(state.style[stylename] || defaultValue);
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -1119,10 +1100,7 @@ class CellRenderer {
|
||||||
const { graph } = state.view;
|
const { graph } = state.view;
|
||||||
const { scale } = state.view;
|
const { scale } = state.view;
|
||||||
const isEdge = state.cell.isEdge();
|
const isEdge = state.cell.isEdge();
|
||||||
let bounds = new Rectangle(
|
let bounds = new Rectangle(state.absoluteOffset.x, state.absoluteOffset.y);
|
||||||
state.absoluteOffset.x,
|
|
||||||
state.absoluteOffset.y
|
|
||||||
);
|
|
||||||
|
|
||||||
if (isEdge) {
|
if (isEdge) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -1273,8 +1251,7 @@ class CellRenderer {
|
||||||
*
|
*
|
||||||
* state - <mxCellState> whose overlays should be redrawn.
|
* state - <mxCellState> whose overlays should be redrawn.
|
||||||
*/
|
*/
|
||||||
redrawCellOverlays(state: CellState,
|
redrawCellOverlays(state: CellState, forced: boolean = false): void {
|
||||||
forced: boolean = false): void {
|
|
||||||
this.createCellOverlays(state);
|
this.createCellOverlays(state);
|
||||||
|
|
||||||
if (state.overlays != null) {
|
if (state.overlays != null) {
|
||||||
|
@ -1329,8 +1306,7 @@ class CellRenderer {
|
||||||
*
|
*
|
||||||
* state - <mxCellState> whose control should be redrawn.
|
* state - <mxCellState> whose control should be redrawn.
|
||||||
*/
|
*/
|
||||||
redrawControl(state: CellState,
|
redrawControl(state: CellState, forced: boolean = false): void {
|
||||||
forced: boolean = false): void {
|
|
||||||
const image = state.view.graph.getFoldingImage(state);
|
const image = state.view.graph.getFoldingImage(state);
|
||||||
|
|
||||||
if (state.control != null && image != null) {
|
if (state.control != null && image != null) {
|
||||||
|
@ -1364,11 +1340,7 @@ class CellRenderer {
|
||||||
* Returns the bounds to be used to draw the control (folding icon) of the
|
* Returns the bounds to be used to draw the control (folding icon) of the
|
||||||
* given state.
|
* given state.
|
||||||
*/
|
*/
|
||||||
getControlBounds(
|
getControlBounds(state: CellState, w: number, h: number): Rectangle | null {
|
||||||
state: CellState,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): Rectangle | null {
|
|
||||||
if (state.control != null) {
|
if (state.control != null) {
|
||||||
const s = state.view.scale;
|
const s = state.view.scale;
|
||||||
let cx = state.getCenterX();
|
let cx = state.getCenterX();
|
||||||
|
@ -1471,10 +1443,7 @@ class CellRenderer {
|
||||||
if (shapeNode.parentNode === state.view.graph.container) {
|
if (shapeNode.parentNode === state.view.graph.container) {
|
||||||
let { canvas } = state.view;
|
let { canvas } = state.view;
|
||||||
|
|
||||||
while (
|
while (canvas != null && canvas.parentNode !== state.view.graph.container) {
|
||||||
canvas != null &&
|
|
||||||
canvas.parentNode !== state.view.graph.container
|
|
||||||
) {
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
canvas = canvas.parentNode;
|
canvas = canvas.parentNode;
|
||||||
}
|
}
|
||||||
|
@ -1482,10 +1451,7 @@ class CellRenderer {
|
||||||
if (canvas != null && canvas.nextSibling != null) {
|
if (canvas != null && canvas.nextSibling != null) {
|
||||||
if (canvas.nextSibling !== shapeNode) {
|
if (canvas.nextSibling !== shapeNode) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
shapeNode.parentNode.insertBefore(
|
shapeNode.parentNode.insertBefore(shapeNode, canvas.nextSibling);
|
||||||
shapeNode,
|
|
||||||
canvas.nextSibling
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -1497,10 +1463,7 @@ class CellRenderer {
|
||||||
shapeNode.parentNode.firstChild != shapeNode
|
shapeNode.parentNode.firstChild != shapeNode
|
||||||
) {
|
) {
|
||||||
// Inserts the node as the first child of the parent to implement the order
|
// Inserts the node as the first child of the parent to implement the order
|
||||||
shapeNode.parentNode.insertBefore(
|
shapeNode.parentNode.insertBefore(shapeNode, shapeNode.parentNode.firstChild);
|
||||||
shapeNode,
|
|
||||||
shapeNode.parentNode.firstChild
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1527,9 +1490,7 @@ class CellRenderer {
|
||||||
*
|
*
|
||||||
* state - <mxCellState> whose shapes should be returned.
|
* state - <mxCellState> whose shapes should be returned.
|
||||||
*/
|
*/
|
||||||
getShapesForState(
|
getShapesForState(state: CellState): [Shape | null, TextShape | null, Shape | null] {
|
||||||
state: CellState
|
|
||||||
): [Shape | null, TextShape | null, Shape | null] {
|
|
||||||
return [state.shape, state.text, state.control];
|
return [state.shape, state.text, state.control];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1549,11 +1510,7 @@ class CellRenderer {
|
||||||
* be drawn into the DOM. If this is false then redraw and/or reconfigure
|
* be drawn into the DOM. If this is false then redraw and/or reconfigure
|
||||||
* will not be called on the shape.
|
* will not be called on the shape.
|
||||||
*/
|
*/
|
||||||
redraw(
|
redraw(state: CellState, force: boolean = false, rendering: boolean = true): void {
|
||||||
state: CellState,
|
|
||||||
force: boolean = false,
|
|
||||||
rendering: boolean = true
|
|
||||||
): void {
|
|
||||||
const shapeChanged = this.redrawShape(state, force, rendering);
|
const shapeChanged = this.redrawShape(state, force, rendering);
|
||||||
|
|
||||||
if (state.shape != null && rendering) {
|
if (state.shape != null && rendering) {
|
||||||
|
@ -1628,8 +1585,7 @@ class CellRenderer {
|
||||||
// Updates indicator shape
|
// Updates indicator shape
|
||||||
if (
|
if (
|
||||||
state.shape != null &&
|
state.shape != null &&
|
||||||
state.shape.indicatorShape !=
|
state.shape.indicatorShape != this.getShape(state.getIndicatorShape())
|
||||||
this.getShape(state.getIndicatorShape())
|
|
||||||
) {
|
) {
|
||||||
if (state.shape.indicator != null) {
|
if (state.shape.indicator != null) {
|
||||||
state.shape.indicator.destroy();
|
state.shape.indicator.destroy();
|
||||||
|
@ -1658,12 +1614,7 @@ class CellRenderer {
|
||||||
state.shape.bounds = null;
|
state.shape.bounds = null;
|
||||||
} else {
|
} else {
|
||||||
state.shape.points = null;
|
state.shape.points = null;
|
||||||
state.shape.bounds = new Rectangle(
|
state.shape.bounds = new Rectangle(state.x, state.y, state.width, state.height);
|
||||||
state.x,
|
|
||||||
state.y,
|
|
||||||
state.width,
|
|
||||||
state.height
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
state.shape.scale = state.view.scale;
|
state.shape.scale = state.view.scale;
|
||||||
|
@ -1700,8 +1651,7 @@ class CellRenderer {
|
||||||
shape.bounds == null ||
|
shape.bounds == null ||
|
||||||
shape.scale !== state.view.scale ||
|
shape.scale !== state.view.scale ||
|
||||||
(state.absolutePoints == null && !shape.bounds.equals(state)) ||
|
(state.absolutePoints == null && !shape.bounds.equals(state)) ||
|
||||||
(state.absolutePoints != null &&
|
(state.absolutePoints != null && !equalPoints(shape.points, state.absolutePoints))
|
||||||
!equalPoints(shape.points, state.absolutePoints))
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,16 +13,17 @@ import Dictionary from '../../util/Dictionary';
|
||||||
import GraphView from '../view/GraphView';
|
import GraphView from '../view/GraphView';
|
||||||
import Cell from './datatypes/Cell';
|
import Cell from './datatypes/Cell';
|
||||||
import CellState from './datatypes/CellState';
|
import CellState from './datatypes/CellState';
|
||||||
import Shape from "../geometry/shape/Shape";
|
import Shape from '../geometry/shape/Shape';
|
||||||
import graph from "../Graph";
|
import graph from '../Graph';
|
||||||
|
import CellArray from './datatypes/CellArray';
|
||||||
|
|
||||||
class TemporaryCellStates {
|
class TemporaryCellStates {
|
||||||
constructor(
|
constructor(
|
||||||
view: GraphView,
|
view: GraphView,
|
||||||
scale: number = 1,
|
scale: number = 1,
|
||||||
cells: Cell[],
|
cells: CellArray,
|
||||||
isCellVisibleFn: Function | null = null,
|
isCellVisibleFn: Function | null = null,
|
||||||
getLinkForCellState: Function | null = null
|
getLinkForCellState: Function | null = null
|
||||||
) {
|
) {
|
||||||
this.view = view;
|
this.view = view;
|
||||||
|
|
||||||
|
@ -31,17 +32,17 @@ class TemporaryCellStates {
|
||||||
this.oldBounds = view.getGraphBounds();
|
this.oldBounds = view.getGraphBounds();
|
||||||
this.oldStates = view.getStates();
|
this.oldStates = view.getStates();
|
||||||
this.oldScale = view.getScale();
|
this.oldScale = view.getScale();
|
||||||
this.oldDoRedrawShape = (<graph>view.graph).cellRenderer.doRedrawShape;
|
this.oldDoRedrawShape = view.graph.cellRenderer.doRedrawShape;
|
||||||
|
|
||||||
const self = this;
|
const self = this;
|
||||||
|
|
||||||
// Overrides doRedrawShape and paint shape to add links on shapes
|
// Overrides doRedrawShape and paint shape to add links on shapes
|
||||||
if (getLinkForCellState != null) {
|
if (getLinkForCellState != null) {
|
||||||
(<graph>view.graph).cellRenderer.doRedrawShape = (state: CellState) => {
|
view.graph.cellRenderer.doRedrawShape = (state: CellState) => {
|
||||||
const shape = <Shape>state?.shape;
|
const shape = <Shape>state?.shape;
|
||||||
const oldPaint = shape.paint;
|
const oldPaint = shape.paint;
|
||||||
|
|
||||||
shape.paint = c => {
|
shape.paint = (c) => {
|
||||||
const link = getLinkForCellState(state);
|
const link = getLinkForCellState(state);
|
||||||
if (link != null) {
|
if (link != null) {
|
||||||
c.setLink(link);
|
c.setLink(link);
|
||||||
|
@ -52,7 +53,7 @@ class TemporaryCellStates {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
(<Function>self.oldDoRedrawShape).apply((<graph>view.graph).cellRenderer, [state]);
|
(<Function>self.oldDoRedrawShape).apply(view.graph.cellRenderer, [state]);
|
||||||
shape.paint = oldPaint;
|
shape.paint = oldPaint;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -66,70 +67,53 @@ class TemporaryCellStates {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Creates space for new states
|
// Creates space for new states
|
||||||
view.setStates(new mxDictionary());
|
view.setStates(new Dictionary());
|
||||||
view.setScale(scale);
|
view.setScale(scale);
|
||||||
|
|
||||||
if (cells != null) {
|
view.resetValidationState();
|
||||||
view.resetValidationState();
|
let bbox = null;
|
||||||
let bbox = null;
|
|
||||||
|
|
||||||
// Validates the vertices and edges without adding them to
|
// Validates the vertices and edges without adding them to
|
||||||
// the model so that the original cells are not modified
|
// the model so that the original cells are not modified
|
||||||
for (const cell of cells) {
|
for (const cell of cells) {
|
||||||
const bounds = view.getBoundingBox(
|
const bounds = view.getBoundingBox(
|
||||||
view.validateCellState(<Cell>view.validateCell(<Cell>cell))
|
view.validateCellState(<Cell>view.validateCell(<Cell>cell))
|
||||||
);
|
);
|
||||||
if (bbox == null) {
|
if (bbox == null) {
|
||||||
bbox = bounds;
|
bbox = bounds;
|
||||||
} else {
|
} else {
|
||||||
bbox.add(bounds);
|
bbox.add(<Rectangle>bounds);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
view.setGraphBounds(bbox || new Rectangle());
|
|
||||||
}
|
}
|
||||||
|
view.setGraphBounds(bbox || new Rectangle());
|
||||||
}
|
}
|
||||||
|
|
||||||
oldValidateCellState: Function | null;
|
oldValidateCellState: Function | null;
|
||||||
|
|
||||||
oldDoRedrawShape: Function | null;
|
oldDoRedrawShape: Function | null;
|
||||||
|
|
||||||
/**
|
view: GraphView;
|
||||||
* Holds the width of the rectangle.
|
|
||||||
* @default 0
|
|
||||||
*/
|
|
||||||
// view: number;
|
|
||||||
view: GraphView | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the height of the rectangle.
|
* Holds the states of the rectangle.
|
||||||
* @default 0
|
|
||||||
*/
|
*/
|
||||||
// oldStates: number;
|
oldStates: Dictionary<string, CellState>;
|
||||||
oldStates: Dictionary | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the height of the rectangle.
|
* Holds the bounds of the rectangle.
|
||||||
* @default 0
|
|
||||||
*/
|
*/
|
||||||
// oldBounds: number;
|
oldBounds: Rectangle;
|
||||||
oldBounds: Rectangle | null = null;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds the height of the rectangle.
|
* Holds the scale of the rectangle.
|
||||||
* @default 0
|
|
||||||
*/
|
*/
|
||||||
oldScale: number = 0;
|
oldScale: number;
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds the height of the rectangle.
|
|
||||||
* @default 0
|
|
||||||
*/
|
|
||||||
// destroy(): void;
|
|
||||||
destroy(): void {
|
destroy(): void {
|
||||||
const view = <GraphView>this.view;
|
const view = this.view;
|
||||||
view.setScale(this.oldScale);
|
view.setScale(this.oldScale);
|
||||||
view.setStates(this.oldStates);
|
view.setStates(this.oldStates);
|
||||||
view.setGraphBounds(<Rectangle>this.oldBounds);
|
view.setGraphBounds(this.oldBounds);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
view.validateCellState = <Function>this.oldValidateCellState;
|
view.validateCellState = <Function>this.oldValidateCellState;
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import Cell from "./Cell";
|
import Cell from './Cell';
|
||||||
import Dictionary from "../../../util/Dictionary";
|
import Dictionary from '../../../util/Dictionary';
|
||||||
import mxObjectIdentity from "../../../util/mxObjectIdentity";
|
import ObjectIdentity from '../../../util/ObjectIdentity';
|
||||||
|
|
||||||
class CellArray extends Array<Cell> {
|
class CellArray extends Array<Cell> {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -25,12 +25,12 @@ class CellArray extends Array<Cell> {
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
map(arg0: any, ...args: any): CellArray {
|
map(arg0: any, ...args: any): CellArray {
|
||||||
return new CellArray(...<Cell[]>super.map(arg0, ...args));
|
return new CellArray(...(<Cell[]>super.map(arg0, ...args)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
filter(arg0: any, ...args: any): CellArray {
|
filter(arg0: any, ...args: any): CellArray {
|
||||||
return new CellArray(...<Cell[]>super.filter(arg0, ...args));
|
return new CellArray(...(<Cell[]>super.filter(arg0, ...args)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,10 +59,11 @@ class CellArray extends Array<Cell> {
|
||||||
* @param targets Boolean that specifies if target terminals should be contained
|
* @param targets Boolean that specifies if target terminals should be contained
|
||||||
* in the result. Default is true.
|
* in the result. Default is true.
|
||||||
*/
|
*/
|
||||||
getOpposites(terminal: Cell,
|
getOpposites(
|
||||||
sources: boolean=true,
|
terminal: Cell,
|
||||||
targets: boolean=true): CellArray {
|
sources: boolean = true,
|
||||||
|
targets: boolean = true
|
||||||
|
): CellArray {
|
||||||
const terminals = new CellArray();
|
const terminals = new CellArray();
|
||||||
|
|
||||||
for (let i = 0; i < this.length; i += 1) {
|
for (let i = 0; i < this.length; i += 1) {
|
||||||
|
@ -72,24 +73,14 @@ class CellArray extends Array<Cell> {
|
||||||
// Checks if the terminal is the source of
|
// Checks if the terminal is the source of
|
||||||
// the edge and if the target should be
|
// the edge and if the target should be
|
||||||
// stored in the result
|
// stored in the result
|
||||||
if (
|
if (source === terminal && target != null && target !== terminal && targets) {
|
||||||
source === terminal &&
|
|
||||||
target != null &&
|
|
||||||
target !== terminal &&
|
|
||||||
targets
|
|
||||||
) {
|
|
||||||
terminals.push(target);
|
terminals.push(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Checks if the terminal is the taget of
|
// Checks if the terminal is the taget of
|
||||||
// the edge and if the source should be
|
// the edge and if the source should be
|
||||||
// stored in the result
|
// stored in the result
|
||||||
else if (
|
else if (target === terminal && source != null && source !== terminal && sources) {
|
||||||
target === terminal &&
|
|
||||||
source != null &&
|
|
||||||
source !== terminal &&
|
|
||||||
sources
|
|
||||||
) {
|
|
||||||
terminals.push(source);
|
terminals.push(source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,9 +148,7 @@ class CellArray extends Array<Cell> {
|
||||||
* with all descendants.
|
* with all descendants.
|
||||||
* @param mapping Optional mapping for existing clones.
|
* @param mapping Optional mapping for existing clones.
|
||||||
*/
|
*/
|
||||||
cloneCells(includeChildren: boolean=true,
|
cloneCells(includeChildren: boolean = true, mapping: any = {}): CellArray {
|
||||||
mapping: any={}): CellArray {
|
|
||||||
|
|
||||||
const clones: CellArray = new CellArray();
|
const clones: CellArray = new CellArray();
|
||||||
|
|
||||||
for (const cell of this) {
|
for (const cell of this) {
|
||||||
|
@ -179,11 +168,8 @@ class CellArray extends Array<Cell> {
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
cloneCellImpl(cell: Cell,
|
cloneCellImpl(cell: Cell, mapping: any = {}, includeChildren: boolean): Cell {
|
||||||
mapping: any={},
|
const ident = ObjectIdentity.get(cell);
|
||||||
includeChildren: boolean): Cell {
|
|
||||||
|
|
||||||
const ident = <string>mxObjectIdentity.get(cell);
|
|
||||||
let clone = mapping ? mapping[ident] : null;
|
let clone = mapping ? mapping[ident] : null;
|
||||||
|
|
||||||
if (clone == null) {
|
if (clone == null) {
|
||||||
|
@ -194,11 +180,7 @@ class CellArray extends Array<Cell> {
|
||||||
const childCount = cell.getChildCount();
|
const childCount = cell.getChildCount();
|
||||||
|
|
||||||
for (let i = 0; i < childCount; i += 1) {
|
for (let i = 0; i < childCount; i += 1) {
|
||||||
const cloneChild = this.cloneCellImpl(
|
const cloneChild = this.cloneCellImpl(<Cell>cell.getChildAt(i), mapping, true);
|
||||||
<Cell>cell.getChildAt(i),
|
|
||||||
mapping,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
clone.insert(cloneChild);
|
clone.insert(cloneChild);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,14 +194,11 @@ class CellArray extends Array<Cell> {
|
||||||
*
|
*
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
restoreClone(clone: Cell,
|
restoreClone(clone: Cell, cell: Cell, mapping: any): void {
|
||||||
cell: Cell,
|
|
||||||
mapping: any): void {
|
|
||||||
|
|
||||||
const source = cell.getTerminal(true);
|
const source = cell.getTerminal(true);
|
||||||
|
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
const tmp = mapping[mxObjectIdentity.get(source)];
|
const tmp = mapping[ObjectIdentity.get(source)];
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
tmp.insertEdge(clone, true);
|
tmp.insertEdge(clone, true);
|
||||||
}
|
}
|
||||||
|
@ -227,7 +206,7 @@ class CellArray extends Array<Cell> {
|
||||||
|
|
||||||
const target = cell.getTerminal(false);
|
const target = cell.getTerminal(false);
|
||||||
if (target != null) {
|
if (target != null) {
|
||||||
const tmp = mapping[mxObjectIdentity.get(target)];
|
const tmp = mapping[ObjectIdentity.get(target)];
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
tmp.insertEdge(clone, false);
|
tmp.insertEdge(clone, false);
|
||||||
}
|
}
|
||||||
|
@ -235,11 +214,7 @@ class CellArray extends Array<Cell> {
|
||||||
|
|
||||||
const childCount = clone.getChildCount();
|
const childCount = clone.getChildCount();
|
||||||
for (let i = 0; i < childCount; i += 1) {
|
for (let i = 0; i < childCount; i += 1) {
|
||||||
this.restoreClone(
|
this.restoreClone(<Cell>clone.getChildAt(i), <Cell>cell.getChildAt(i), mapping);
|
||||||
<Cell>clone.getChildAt(i),
|
|
||||||
<Cell>cell.getChildAt(i),
|
|
||||||
mapping
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,9 @@ import GraphView from '../../view/GraphView';
|
||||||
import Shape from '../../geometry/shape/Shape';
|
import Shape from '../../geometry/shape/Shape';
|
||||||
import TextShape from '../../geometry/shape/node/TextShape';
|
import TextShape from '../../geometry/shape/node/TextShape';
|
||||||
import Dictionary from '../../../util/Dictionary';
|
import Dictionary from '../../../util/Dictionary';
|
||||||
|
import { NONE } from '../../../util/Constants';
|
||||||
|
|
||||||
import type { CellStateStyles } from '../../../types';
|
import type { CellStateStyles } from '../../../types';
|
||||||
import Image from "../../image/Image";
|
|
||||||
import {ALIGN_MIDDLE, NONE} from "../../../util/Constants";
|
|
||||||
import {getValue} from "../../../util/Utils";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxCellState
|
* Class: mxCellState
|
||||||
|
@ -210,20 +208,11 @@ class CellState extends Rectangle {
|
||||||
*/
|
*/
|
||||||
getPerimeterBounds(
|
getPerimeterBounds(
|
||||||
border: number = 0,
|
border: number = 0,
|
||||||
bounds: Rectangle = new Rectangle(
|
bounds: Rectangle = new Rectangle(this.x, this.y, this.width, this.height)
|
||||||
this.x,
|
|
||||||
this.y,
|
|
||||||
this.width,
|
|
||||||
this.height
|
|
||||||
)
|
|
||||||
) {
|
) {
|
||||||
if (
|
if (this.shape?.stencil?.aspect === 'fixed') {
|
||||||
this.shape &&
|
|
||||||
this.shape.stencil &&
|
|
||||||
this.shape.stencil.aspect === 'fixed'
|
|
||||||
) {
|
|
||||||
const aspect = this.shape.stencil.computeAspect(
|
const aspect = this.shape.stencil.computeAspect(
|
||||||
this.style,
|
this.shape,
|
||||||
bounds.x,
|
bounds.x,
|
||||||
bounds.y,
|
bounds.y,
|
||||||
bounds.width,
|
bounds.width,
|
||||||
|
@ -455,6 +444,7 @@ class CellState extends Rectangle {
|
||||||
isLoop(state: CellState) {
|
isLoop(state: CellState) {
|
||||||
const src = this.getVisibleTerminalState(true);
|
const src = this.getVisibleTerminalState(true);
|
||||||
const trg = this.getVisibleTerminalState(false);
|
const trg = this.getVisibleTerminalState(false);
|
||||||
|
|
||||||
return src && src === trg;
|
return src && src === trg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -470,10 +460,8 @@ class CellState extends Rectangle {
|
||||||
* @param state {@link mxCellState} whose vertical alignment should be
|
* @param state {@link mxCellState} whose vertical alignment should be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
getVerticalAlign(): string | null {
|
getVerticalAlign() {
|
||||||
return this.style != null
|
return this.style.verticalAlign;
|
||||||
? this.style.verticalAlign || ALIGN_MIDDLE
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -481,11 +469,14 @@ class CellState extends Rectangle {
|
||||||
*
|
*
|
||||||
* @param state {@link mxCellState} to check.
|
* @param state {@link mxCellState} to check.
|
||||||
*/
|
*/
|
||||||
isTransparentState(): boolean {
|
isTransparentState() {
|
||||||
let result = false;
|
let result = false;
|
||||||
const stroke = getValue(this.style, 'strokeColor', NONE);
|
|
||||||
const fill = getValue(this.style, 'fillColor', NONE);
|
const stroke = this.style.strokeColor;
|
||||||
result = stroke === NONE && fill === NONE && this.getImage(state) == null;
|
const fill = this.style.fillColor;
|
||||||
|
|
||||||
|
result = stroke === NONE && fill === NONE && !this.getImageSrc();
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -496,10 +487,8 @@ class CellState extends Rectangle {
|
||||||
*
|
*
|
||||||
* @param state {@link mxCellState} whose image URL should be returned.
|
* @param state {@link mxCellState} whose image URL should be returned.
|
||||||
*/
|
*/
|
||||||
getImage(): Image | null {
|
getImageSrc() {
|
||||||
return this.style != null
|
return this.style.image;
|
||||||
? this.style.image
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -510,10 +499,8 @@ class CellState extends Rectangle {
|
||||||
* @param state {@link mxCellState} whose indicator color should be
|
* @param state {@link mxCellState} whose indicator color should be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
getIndicatorColor(): string | null {
|
getIndicatorColor() {
|
||||||
return this.style != null
|
return this.style.indicatorColor;
|
||||||
? this.style.indicatorColor
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -524,10 +511,8 @@ class CellState extends Rectangle {
|
||||||
* @param state {@link mxCellState} whose indicator gradient color should be
|
* @param state {@link mxCellState} whose indicator gradient color should be
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
getIndicatorGradientColor(): string | null {
|
getIndicatorGradientColor() {
|
||||||
return this.style != null
|
return this.style.gradientColor;
|
||||||
? this.style.gradientColor
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -537,10 +522,8 @@ class CellState extends Rectangle {
|
||||||
*
|
*
|
||||||
* @param state {@link mxCellState} whose indicator shape should be returned.
|
* @param state {@link mxCellState} whose indicator shape should be returned.
|
||||||
*/
|
*/
|
||||||
getIndicatorShape(): string | null {
|
getIndicatorShape() {
|
||||||
return this.style != null
|
return this.style.indicatorShape;
|
||||||
? this.style.indicatorShape
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -550,10 +533,8 @@ class CellState extends Rectangle {
|
||||||
*
|
*
|
||||||
* @param state {@link mxCellState} whose indicator image should be returned.
|
* @param state {@link mxCellState} whose indicator image should be returned.
|
||||||
*/
|
*/
|
||||||
getIndicatorImage(): Image | null {
|
getIndicatorImageSrc() {
|
||||||
return this.style != null
|
return this.style.indicatorImage;
|
||||||
? this.style.indicatorImage
|
|
||||||
: null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,11 +77,7 @@ class EdgeHandler {
|
||||||
this.reset();
|
this.reset();
|
||||||
|
|
||||||
if (dirty) {
|
if (dirty) {
|
||||||
this.graph.cellRenderer.redraw(
|
this.graph.cellRenderer.redraw(this.state, false, state.view.isRendering());
|
||||||
this.state,
|
|
||||||
false,
|
|
||||||
state.view.isRendering()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -329,10 +325,7 @@ class EdgeHandler {
|
||||||
this.parentHighlight.redraw();
|
this.parentHighlight.redraw();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (pstate != null && pstate.parentHighlight === this.parentHighlight) {
|
||||||
pstate != null &&
|
|
||||||
pstate.parentHighlight === this.parentHighlight
|
|
||||||
) {
|
|
||||||
pstate.parentHighlight = null;
|
pstate.parentHighlight = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,18 +333,12 @@ class EdgeHandler {
|
||||||
this.parentHighlight = null;
|
this.parentHighlight = null;
|
||||||
}
|
}
|
||||||
} else if (this.parentHighlightEnabled && visible) {
|
} else if (this.parentHighlightEnabled && visible) {
|
||||||
if (
|
if (parent.isVertex() && pstate != null && pstate.parentHighlight == null) {
|
||||||
parent.isVertex() &&
|
|
||||||
pstate != null &&
|
|
||||||
pstate.parentHighlight == null
|
|
||||||
) {
|
|
||||||
this.parentHighlight = this.createParentHighlightShape(pstate);
|
this.parentHighlight = this.createParentHighlightShape(pstate);
|
||||||
// VML dialect required here for event transparency in IE
|
// VML dialect required here for event transparency in IE
|
||||||
this.parentHighlight.dialect = DIALECT_SVG;
|
this.parentHighlight.dialect = DIALECT_SVG;
|
||||||
this.parentHighlight.pointerEvents = false;
|
this.parentHighlight.pointerEvents = false;
|
||||||
this.parentHighlight.rotation = Number(
|
this.parentHighlight.rotation = Number(pstate.style.rotation || '0');
|
||||||
pstate.style.rotation || '0'
|
|
||||||
);
|
|
||||||
this.parentHighlight.init(this.graph.getView().getOverlayPane());
|
this.parentHighlight.init(this.graph.getView().getOverlayPane());
|
||||||
this.parentHighlight.redraw();
|
this.parentHighlight.redraw();
|
||||||
|
|
||||||
|
@ -390,8 +377,7 @@ class EdgeHandler {
|
||||||
|
|
||||||
// Updates preferHtml
|
// Updates preferHtml
|
||||||
this.preferHtml =
|
this.preferHtml =
|
||||||
this.state.text != null &&
|
this.state.text != null && this.state.text.node.parentNode === this.graph.container;
|
||||||
this.state.text.node.parentNode === this.graph.container;
|
|
||||||
|
|
||||||
if (!this.preferHtml) {
|
if (!this.preferHtml) {
|
||||||
// Checks source terminal
|
// Checks source terminal
|
||||||
|
@ -429,10 +415,7 @@ class EdgeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds a rectangular handle for the label position
|
// Adds a rectangular handle for the label position
|
||||||
this.label = new Point(
|
this.label = new Point(this.state.absoluteOffset.x, this.state.absoluteOffset.y);
|
||||||
this.state.absoluteOffset.x,
|
|
||||||
this.state.absoluteOffset.y
|
|
||||||
);
|
|
||||||
this.labelShape = this.createLabelHandleShape();
|
this.labelShape = this.createLabelHandleShape();
|
||||||
this.initBend(this.labelShape);
|
this.initBend(this.labelShape);
|
||||||
this.labelShape.setCursor(CURSOR_LABEL_HANDLE);
|
this.labelShape.setCursor(CURSOR_LABEL_HANDLE);
|
||||||
|
@ -525,7 +508,7 @@ class EdgeHandler {
|
||||||
null,
|
null,
|
||||||
this.getSelectionColor()
|
this.getSelectionColor()
|
||||||
);
|
);
|
||||||
shape.strokewidth = this.getSelectionStrokeWidth();
|
shape.strokeWidth = this.getSelectionStrokeWidth();
|
||||||
shape.isDashed = this.isSelectionDashed();
|
shape.isDashed = this.isSelectionDashed();
|
||||||
|
|
||||||
return shape;
|
return shape;
|
||||||
|
@ -616,10 +599,7 @@ class EdgeHandler {
|
||||||
let cell = super.getCell(me);
|
let cell = super.getCell(me);
|
||||||
|
|
||||||
// Checks for cell at preview point (with grid)
|
// Checks for cell at preview point (with grid)
|
||||||
if (
|
if ((cell === self.state.cell || cell == null) && self.currentPoint != null) {
|
||||||
(cell === self.state.cell || cell == null) &&
|
|
||||||
self.currentPoint != null
|
|
||||||
) {
|
|
||||||
cell = self.graph.getCellAt(self.currentPoint.x, self.currentPoint.y);
|
cell = self.graph.getCellAt(self.currentPoint.x, self.currentPoint.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -722,9 +702,7 @@ class EdgeHandler {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.isHandleEnabled(i)) {
|
if (this.isHandleEnabled(i)) {
|
||||||
bend.setCursor(
|
bend.setCursor(terminal ? CURSOR_TERMINAL_HANDLE : CURSOR_BEND_HANDLE);
|
||||||
terminal ? CURSOR_TERMINAL_HANDLE : CURSOR_BEND_HANDLE
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bends.push(bend);
|
bends.push(bend);
|
||||||
|
@ -842,12 +820,7 @@ class EdgeHandler {
|
||||||
createLabelHandleShape() {
|
createLabelHandleShape() {
|
||||||
if (this.labelHandleImage != null) {
|
if (this.labelHandleImage != null) {
|
||||||
const shape = new ImageShape(
|
const shape = new ImageShape(
|
||||||
new Rectangle(
|
new Rectangle(0, 0, this.labelHandleImage.width, this.labelHandleImage.height),
|
||||||
0,
|
|
||||||
0,
|
|
||||||
this.labelHandleImage.width,
|
|
||||||
this.labelHandleImage.height
|
|
||||||
),
|
|
||||||
this.labelHandleImage.src
|
this.labelHandleImage.src
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -879,8 +852,7 @@ class EdgeHandler {
|
||||||
bend.dialect = DIALECT_STRICTHTML;
|
bend.dialect = DIALECT_STRICTHTML;
|
||||||
bend.init(this.graph.container);
|
bend.init(this.graph.container);
|
||||||
} else {
|
} else {
|
||||||
bend.dialect =
|
bend.dialect = this.graph.dialect !== DIALECT_SVG ? DIALECT_MIXEDHTML : DIALECT_SVG;
|
||||||
this.graph.dialect !== DIALECT_SVG ? DIALECT_MIXEDHTML : DIALECT_SVG;
|
|
||||||
bend.init(this.graph.getView().getOverlayPane());
|
bend.init(this.graph.getView().getOverlayPane());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -913,12 +885,7 @@ class EdgeHandler {
|
||||||
const tol = !isMouseEvent(me.getEvent()) ? this.tolerance : 1;
|
const tol = !isMouseEvent(me.getEvent()) ? this.tolerance : 1;
|
||||||
const hit =
|
const hit =
|
||||||
this.allowHandleBoundsCheck && tol > 0
|
this.allowHandleBoundsCheck && tol > 0
|
||||||
? new Rectangle(
|
? new Rectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol)
|
||||||
me.getGraphX() - tol,
|
|
||||||
me.getGraphY() - tol,
|
|
||||||
2 * tol,
|
|
||||||
2 * tol
|
|
||||||
)
|
|
||||||
: null;
|
: null;
|
||||||
let minDistSq = null;
|
let minDistSq = null;
|
||||||
|
|
||||||
|
@ -928,8 +895,7 @@ class EdgeHandler {
|
||||||
shape.node != null &&
|
shape.node != null &&
|
||||||
shape.node.style.display !== 'none' &&
|
shape.node.style.display !== 'none' &&
|
||||||
shape.node.style.visibility !== 'hidden' &&
|
shape.node.style.visibility !== 'hidden' &&
|
||||||
(me.isSource(shape) ||
|
(me.isSource(shape) || (hit != null && utils.intersects(shape.bounds, hit)))
|
||||||
(hit != null && utils.intersects(shape.bounds, hit)))
|
|
||||||
) {
|
) {
|
||||||
const dx = me.getGraphX() - shape.bounds.getCenterX();
|
const dx = me.getGraphX() - shape.bounds.getCenterX();
|
||||||
const dy = me.getGraphY() - shape.bounds.getCenterY();
|
const dy = me.getGraphY() - shape.bounds.getCenterY();
|
||||||
|
@ -1019,11 +985,7 @@ class EdgeHandler {
|
||||||
this.snapPoint = new Point(b.getCenterX(), b.getCenterY());
|
this.snapPoint = new Point(b.getCenterX(), b.getCenterY());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.addEnabled && handle == null && this.isAddPointEvent(me.getEvent())) {
|
||||||
this.addEnabled &&
|
|
||||||
handle == null &&
|
|
||||||
this.isAddPointEvent(me.getEvent())
|
|
||||||
) {
|
|
||||||
this.addPoint(this.state, me.getEvent());
|
this.addPoint(this.state, me.getEvent());
|
||||||
me.consume();
|
me.consume();
|
||||||
} else if (handle != null && !me.isConsumed() && this.graph.isEnabled()) {
|
} else if (handle != null && !me.isConsumed() && this.graph.isEnabled()) {
|
||||||
|
@ -1058,8 +1020,7 @@ class EdgeHandler {
|
||||||
this.startY = y;
|
this.startY = y;
|
||||||
|
|
||||||
this.isSource = this.bends == null ? false : index === 0;
|
this.isSource = this.bends == null ? false : index === 0;
|
||||||
this.isTarget =
|
this.isTarget = this.bends == null ? false : index === this.bends.length - 1;
|
||||||
this.bends == null ? false : index === this.bends.length - 1;
|
|
||||||
this.isLabel = index === InternalEvent.LABEL_HANDLE;
|
this.isLabel = index === InternalEvent.LABEL_HANDLE;
|
||||||
|
|
||||||
if (this.isSource || this.isTarget) {
|
if (this.isSource || this.isTarget) {
|
||||||
|
@ -1067,8 +1028,7 @@ class EdgeHandler {
|
||||||
const terminal = cell.getTerminal(this.isSource);
|
const terminal = cell.getTerminal(this.isSource);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(terminal == null &&
|
(terminal == null && this.graph.isTerminalPointMovable(cell, this.isSource)) ||
|
||||||
this.graph.isTerminalPointMovable(cell, this.isSource)) ||
|
|
||||||
(terminal != null &&
|
(terminal != null &&
|
||||||
this.graph.isCellDisconnectable(cell, terminal, this.isSource))
|
this.graph.isCellDisconnectable(cell, terminal, this.isSource))
|
||||||
) {
|
) {
|
||||||
|
@ -1189,10 +1149,7 @@ class EdgeHandler {
|
||||||
const snapToTerminal = (terminal) => {
|
const snapToTerminal = (terminal) => {
|
||||||
if (terminal != null) {
|
if (terminal != null) {
|
||||||
snapToPoint(
|
snapToPoint(
|
||||||
new point(
|
new point(view.getRoutingCenterX(terminal), view.getRoutingCenterY(terminal))
|
||||||
view.getRoutingCenterX(terminal),
|
|
||||||
view.getRoutingCenterY(terminal)
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1245,8 +1202,7 @@ class EdgeHandler {
|
||||||
if (
|
if (
|
||||||
this.marker.highlight != null &&
|
this.marker.highlight != null &&
|
||||||
this.marker.highlight.state != null &&
|
this.marker.highlight.state != null &&
|
||||||
this.marker.highlight.state.cell ===
|
this.marker.highlight.state.cell === this.constraintHandler.currentFocus.cell
|
||||||
this.constraintHandler.currentFocus.cell
|
|
||||||
) {
|
) {
|
||||||
// Direct repaint needed if cell already highlighted
|
// Direct repaint needed if cell already highlighted
|
||||||
if (this.marker.highlight.shape.stroke !== 'transparent') {
|
if (this.marker.highlight.shape.stroke !== 'transparent') {
|
||||||
|
@ -1254,10 +1210,7 @@ class EdgeHandler {
|
||||||
this.marker.highlight.repaint();
|
this.marker.highlight.repaint();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.marker.markCell(
|
this.marker.markCell(this.constraintHandler.currentFocus.cell, 'transparent');
|
||||||
this.constraintHandler.currentFocus.cell,
|
|
||||||
'transparent'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const model = this.graph.getModel();
|
const model = this.graph.getModel();
|
||||||
|
@ -1267,12 +1220,8 @@ class EdgeHandler {
|
||||||
!this.isSource
|
!this.isSource
|
||||||
);
|
);
|
||||||
const otherCell = other != null ? other.cell : null;
|
const otherCell = other != null ? other.cell : null;
|
||||||
const source = this.isSource
|
const source = this.isSource ? this.constraintHandler.currentFocus.cell : otherCell;
|
||||||
? this.constraintHandler.currentFocus.cell
|
const target = this.isSource ? otherCell : this.constraintHandler.currentFocus.cell;
|
||||||
: otherCell;
|
|
||||||
const target = this.isSource
|
|
||||||
? otherCell
|
|
||||||
: this.constraintHandler.currentFocus.cell;
|
|
||||||
|
|
||||||
// Updates the error message of the handler
|
// Updates the error message of the handler
|
||||||
this.error = this.validateConnection(source, target);
|
this.error = this.validateConnection(source, target);
|
||||||
|
@ -1282,10 +1231,7 @@ class EdgeHandler {
|
||||||
result = this.constraintHandler.currentFocus;
|
result = this.constraintHandler.currentFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.error != null || (result != null && !this.isCellEnabled(result.cell))) {
|
||||||
this.error != null ||
|
|
||||||
(result != null && !this.isCellEnabled(result.cell))
|
|
||||||
) {
|
|
||||||
this.constraintHandler.reset();
|
this.constraintHandler.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1367,11 +1313,7 @@ class EdgeHandler {
|
||||||
const src = this.state.getVisibleTerminalState(true);
|
const src = this.state.getVisibleTerminalState(true);
|
||||||
|
|
||||||
if (src != null) {
|
if (src != null) {
|
||||||
const c = this.graph.getConnectionConstraint(
|
const c = this.graph.getConnectionConstraint(this.state, src, true);
|
||||||
this.state,
|
|
||||||
src,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Checks if point is not fixed
|
// Checks if point is not fixed
|
||||||
if (c == null || this.graph.getConnectionPoint(src, c) == null) {
|
if (c == null || this.graph.getConnectionPoint(src, c) == null) {
|
||||||
|
@ -1385,11 +1327,7 @@ class EdgeHandler {
|
||||||
const trg = this.state.getVisibleTerminalState(false);
|
const trg = this.state.getVisibleTerminalState(false);
|
||||||
|
|
||||||
if (trg != null) {
|
if (trg != null) {
|
||||||
const c = this.graph.getConnectionConstraint(
|
const c = this.graph.getConnectionConstraint(this.state, trg, false);
|
||||||
this.state,
|
|
||||||
trg,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
// Checks if point is not fixed
|
// Checks if point is not fixed
|
||||||
if (c == null || this.graph.getConnectionPoint(trg, c) == null) {
|
if (c == null || this.graph.getConnectionPoint(trg, c) == null) {
|
||||||
|
@ -1453,10 +1391,8 @@ class EdgeHandler {
|
||||||
const left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
|
const left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
|
||||||
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
||||||
|
|
||||||
const gridX =
|
const gridX = this.currentPoint.x - this.graph.container.scrollLeft + offset.x - left;
|
||||||
this.currentPoint.x - this.graph.container.scrollLeft + offset.x - left;
|
const gridY = this.currentPoint.y - this.graph.container.scrollTop + offset.y - top;
|
||||||
const gridY =
|
|
||||||
this.currentPoint.y - this.graph.container.scrollTop + offset.y - top;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.outlineConnect &&
|
this.outlineConnect &&
|
||||||
|
@ -1484,16 +1420,8 @@ class EdgeHandler {
|
||||||
? terminalState
|
? terminalState
|
||||||
: this.state.getVisibleTerminalState(false);
|
: this.state.getVisibleTerminalState(false);
|
||||||
|
|
||||||
let sourceConstraint = this.graph.getConnectionConstraint(
|
let sourceConstraint = this.graph.getConnectionConstraint(edge, sourceState, true);
|
||||||
edge,
|
let targetConstraint = this.graph.getConnectionConstraint(edge, targetState, false);
|
||||||
sourceState,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
let targetConstraint = this.graph.getConnectionConstraint(
|
|
||||||
edge,
|
|
||||||
targetState,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
let constraint = this.constraintHandler.currentConstraint;
|
let constraint = this.constraintHandler.currentConstraint;
|
||||||
|
|
||||||
|
@ -1528,13 +1456,11 @@ class EdgeHandler {
|
||||||
this.marker.highlight.shape.stroke = outline
|
this.marker.highlight.shape.stroke = outline
|
||||||
? OUTLINE_HIGHLIGHT_COLOR
|
? OUTLINE_HIGHLIGHT_COLOR
|
||||||
: 'transparent';
|
: 'transparent';
|
||||||
this.marker.highlight.shape.strokewidth =
|
this.marker.highlight.shape.strokewidth = OUTLINE_HIGHLIGHT_STROKEWIDTH / s / s;
|
||||||
OUTLINE_HIGHLIGHT_STROKEWIDTH / s / s;
|
|
||||||
this.marker.highlight.repaint();
|
this.marker.highlight.repaint();
|
||||||
} else if (this.marker.hasValidState()) {
|
} else if (this.marker.hasValidState()) {
|
||||||
this.marker.highlight.shape.stroke =
|
this.marker.highlight.shape.stroke =
|
||||||
me.getCell().isConnectable() &&
|
me.getCell().isConnectable() && this.marker.getValidState() !== me.getState()
|
||||||
this.marker.getValidState() !== me.getState()
|
|
||||||
? 'transparent'
|
? 'transparent'
|
||||||
: DEFAULT_VALID_COLOR;
|
: DEFAULT_VALID_COLOR;
|
||||||
this.marker.highlight.shape.strokewidth = HIGHLIGHT_STROKEWIDTH / s / s;
|
this.marker.highlight.shape.strokewidth = HIGHLIGHT_STROKEWIDTH / s / s;
|
||||||
|
@ -1550,10 +1476,8 @@ class EdgeHandler {
|
||||||
|
|
||||||
if (this.isSource || this.isTarget) {
|
if (this.isSource || this.isTarget) {
|
||||||
if (constraint != null && constraint.point != null) {
|
if (constraint != null && constraint.point != null) {
|
||||||
edge.style[this.isSource ? 'exitX' : 'entryX'] =
|
edge.style[this.isSource ? 'exitX' : 'entryX'] = constraint.point.x;
|
||||||
constraint.point.x;
|
edge.style[this.isSource ? 'exitY' : 'entryY'] = constraint.point.y;
|
||||||
edge.style[this.isSource ? 'exitY' : 'entryY'] =
|
|
||||||
constraint.point.y;
|
|
||||||
} else {
|
} else {
|
||||||
delete edge.style[this.isSource ? 'exitX' : 'entryX'];
|
delete edge.style[this.isSource ? 'exitX' : 'entryX'];
|
||||||
delete edge.style[this.isSource ? 'exitY' : 'entryY'];
|
delete edge.style[this.isSource ? 'exitY' : 'entryY'];
|
||||||
|
@ -1564,21 +1488,11 @@ class EdgeHandler {
|
||||||
edge.setVisibleTerminalState(targetState, false);
|
edge.setVisibleTerminalState(targetState, false);
|
||||||
|
|
||||||
if (!this.isSource || sourceState != null) {
|
if (!this.isSource || sourceState != null) {
|
||||||
edge.view.updateFixedTerminalPoint(
|
edge.view.updateFixedTerminalPoint(edge, sourceState, true, sourceConstraint);
|
||||||
edge,
|
|
||||||
sourceState,
|
|
||||||
true,
|
|
||||||
sourceConstraint
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.isTarget || targetState != null) {
|
if (!this.isTarget || targetState != null) {
|
||||||
edge.view.updateFixedTerminalPoint(
|
edge.view.updateFixedTerminalPoint(edge, targetState, false, targetConstraint);
|
||||||
edge,
|
|
||||||
targetState,
|
|
||||||
false,
|
|
||||||
targetConstraint
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this.isSource || this.isTarget) && terminalState == null) {
|
if ((this.isSource || this.isTarget) && terminalState == null) {
|
||||||
|
@ -1625,12 +1539,8 @@ class EdgeHandler {
|
||||||
this.index > InternalEvent.VIRTUAL_HANDLE
|
this.index > InternalEvent.VIRTUAL_HANDLE
|
||||||
) {
|
) {
|
||||||
if (this.customHandles != null) {
|
if (this.customHandles != null) {
|
||||||
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].processEvent(
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].processEvent(me);
|
||||||
me
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].positionChanged();
|
||||||
);
|
|
||||||
this.customHandles[
|
|
||||||
InternalEvent.CUSTOM_HANDLE - this.index
|
|
||||||
].positionChanged();
|
|
||||||
|
|
||||||
if (this.shape != null && this.shape.node != null) {
|
if (this.shape != null && this.shape.node != null) {
|
||||||
this.shape.node.style.display = 'none';
|
this.shape.node.style.display = 'none';
|
||||||
|
@ -1642,9 +1552,7 @@ class EdgeHandler {
|
||||||
} else {
|
} else {
|
||||||
this.points = this.getPreviewPoints(this.currentPoint, me);
|
this.points = this.getPreviewPoints(this.currentPoint, me);
|
||||||
let terminalState =
|
let terminalState =
|
||||||
this.isSource || this.isTarget
|
this.isSource || this.isTarget ? this.getPreviewTerminalState(me) : null;
|
||||||
? this.getPreviewTerminalState(me)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.constraintHandler.currentConstraint != null &&
|
this.constraintHandler.currentConstraint != null &&
|
||||||
|
@ -1655,9 +1563,7 @@ class EdgeHandler {
|
||||||
} else if (this.outlineConnect) {
|
} else if (this.outlineConnect) {
|
||||||
// Need to check outline before cloning terminal state
|
// Need to check outline before cloning terminal state
|
||||||
const outline =
|
const outline =
|
||||||
this.isSource || this.isTarget
|
this.isSource || this.isTarget ? this.isOutlineConnectEvent(me) : false;
|
||||||
? this.isOutlineConnectEvent(me)
|
|
||||||
: false;
|
|
||||||
|
|
||||||
if (outline) {
|
if (outline) {
|
||||||
terminalState = this.marker.highlight.state;
|
terminalState = this.marker.highlight.state;
|
||||||
|
@ -1693,9 +1599,7 @@ class EdgeHandler {
|
||||||
// Sets the color of the preview to valid or invalid, updates the
|
// Sets the color of the preview to valid or invalid, updates the
|
||||||
// points of the preview and redraws
|
// points of the preview and redraws
|
||||||
const color =
|
const color =
|
||||||
this.error == null
|
this.error == null ? this.marker.validColor : this.marker.invalidColor;
|
||||||
? this.marker.validColor
|
|
||||||
: this.marker.invalidColor;
|
|
||||||
this.setPreviewColor(color);
|
this.setPreviewColor(color);
|
||||||
this.abspoints = clone.absolutePoints;
|
this.abspoints = clone.absolutePoints;
|
||||||
this.active = true;
|
this.active = true;
|
||||||
|
@ -1813,9 +1717,7 @@ class EdgeHandler {
|
||||||
model.endUpdate();
|
model.endUpdate();
|
||||||
}
|
}
|
||||||
} else if (this.graph.isAllowDanglingEdges()) {
|
} else if (this.graph.isAllowDanglingEdges()) {
|
||||||
const pt = this.abspoints[
|
const pt = this.abspoints[this.isSource ? 0 : this.abspoints.length - 1];
|
||||||
this.isSource ? 0 : this.abspoints.length - 1
|
|
||||||
];
|
|
||||||
pt.x = this.roundLength(
|
pt.x = this.roundLength(
|
||||||
pt.x / this.graph.view.scale - this.graph.view.translate.x
|
pt.x / this.graph.view.scale - this.graph.view.translate.x
|
||||||
);
|
);
|
||||||
|
@ -2074,12 +1976,7 @@ class EdgeHandler {
|
||||||
geo = geo.clone();
|
geo = geo.clone();
|
||||||
geo.setTerminalPoint(point, isSource);
|
geo.setTerminalPoint(point, isSource);
|
||||||
model.setGeometry(edge, geo);
|
model.setGeometry(edge, geo);
|
||||||
this.graph.connectCell(
|
this.graph.connectCell(edge, null, isSource, new ConnectionConstraint());
|
||||||
edge,
|
|
||||||
null,
|
|
||||||
isSource,
|
|
||||||
new ConnectionConstraint()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
model.endUpdate();
|
model.endUpdate();
|
||||||
|
@ -2130,11 +2027,7 @@ class EdgeHandler {
|
||||||
*/
|
*/
|
||||||
// addPoint(state: mxCellState, evt: Event): void;
|
// addPoint(state: mxCellState, evt: Event): void;
|
||||||
addPoint(state, evt) {
|
addPoint(state, evt) {
|
||||||
const pt = utils.convertPoint(
|
const pt = utils.convertPoint(this.graph.container, getClientX(evt), getClientY(evt));
|
||||||
this.graph.container,
|
|
||||||
getClientX(evt),
|
|
||||||
getClientY(evt)
|
|
||||||
);
|
|
||||||
const gridEnabled = this.graph.isGridEnabledEvent(evt);
|
const gridEnabled = this.graph.isGridEnabledEvent(evt);
|
||||||
this.convertPoint(pt, gridEnabled);
|
this.convertPoint(pt, gridEnabled);
|
||||||
this.addPointAt(state, pt.x, pt.y);
|
this.addPointAt(state, pt.x, pt.y);
|
||||||
|
@ -2215,8 +2108,7 @@ class EdgeHandler {
|
||||||
let color = HANDLE_FILLCOLOR;
|
let color = HANDLE_FILLCOLOR;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(terminal != null &&
|
(terminal != null && !this.graph.isCellDisconnectable(cell, terminal, isSource)) ||
|
||||||
!this.graph.isCellDisconnectable(cell, terminal, isSource)) ||
|
|
||||||
(terminal == null && !this.graph.isTerminalPointMovable(cell, isSource))
|
(terminal == null && !this.graph.isTerminalPointMovable(cell, isSource))
|
||||||
) {
|
) {
|
||||||
color = LOCKED_HANDLE_FILLCOLOR;
|
color = LOCKED_HANDLE_FILLCOLOR;
|
||||||
|
@ -2278,10 +2170,7 @@ class EdgeHandler {
|
||||||
|
|
||||||
// Updates the handle for the label position
|
// Updates the handle for the label position
|
||||||
let b = this.labelShape.bounds;
|
let b = this.labelShape.bounds;
|
||||||
this.label = new Point(
|
this.label = new Point(this.state.absoluteOffset.x, this.state.absoluteOffset.y);
|
||||||
this.state.absoluteOffset.x,
|
|
||||||
this.state.absoluteOffset.y
|
|
||||||
);
|
|
||||||
this.labelShape.bounds = new Rectangle(
|
this.labelShape.bounds = new Rectangle(
|
||||||
Math.round(this.label.x - b.width / 2),
|
Math.round(this.label.x - b.width / 2),
|
||||||
Math.round(this.label.y - b.height / 2),
|
Math.round(this.label.y - b.height / 2),
|
||||||
|
@ -2378,9 +2267,7 @@ class EdgeHandler {
|
||||||
this.customHandles[i].shape.node.style.display = temp;
|
this.customHandles[i].shape.node.style.display = temp;
|
||||||
|
|
||||||
// Hides custom handles during text editing
|
// Hides custom handles during text editing
|
||||||
this.customHandles[
|
this.customHandles[i].shape.node.style.visibility = this.isCustomHandleVisible(
|
||||||
i
|
|
||||||
].shape.node.style.visibility = this.isCustomHandleVisible(
|
|
||||||
this.customHandles[i]
|
this.customHandles[i]
|
||||||
)
|
)
|
||||||
? ''
|
? ''
|
||||||
|
@ -2395,9 +2282,7 @@ class EdgeHandler {
|
||||||
* Returns true if the given custom handle is visible.
|
* Returns true if the given custom handle is visible.
|
||||||
*/
|
*/
|
||||||
isCustomHandleVisible(handle) {
|
isCustomHandleVisible(handle) {
|
||||||
return (
|
return !this.graph.isEditing() && this.state.view.graph.getSelectionCount() === 1;
|
||||||
!this.graph.isEditing() && this.state.view.graph.getSelectionCount() === 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2527,16 +2412,13 @@ class EdgeHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.shape != null && !utils.equalPoints(this.shape.points, this.abspoints)) {
|
||||||
this.shape != null &&
|
|
||||||
!utils.equalPoints(this.shape.points, this.abspoints)
|
|
||||||
) {
|
|
||||||
this.shape.apply(this.state);
|
this.shape.apply(this.state);
|
||||||
this.shape.points = this.abspoints.slice();
|
this.shape.points = this.abspoints.slice();
|
||||||
this.shape.scale = this.state.view.scale;
|
this.shape.scale = this.state.view.scale;
|
||||||
this.shape.isDashed = this.isSelectionDashed();
|
this.shape.isDashed = this.isSelectionDashed();
|
||||||
this.shape.stroke = this.getSelectionColor();
|
this.shape.stroke = this.getSelectionColor();
|
||||||
this.shape.strokewidth =
|
this.shape.strokeWidth =
|
||||||
this.getSelectionStrokeWidth() / this.shape.scale / this.shape.scale;
|
this.getSelectionStrokeWidth() / this.shape.scale / this.shape.scale;
|
||||||
this.shape.isShadow = false;
|
this.shape.isShadow = false;
|
||||||
this.shape.redraw();
|
this.shape.redraw();
|
||||||
|
|
|
@ -21,7 +21,7 @@ import {
|
||||||
import InternalEvent from '../../event/InternalEvent';
|
import InternalEvent from '../../event/InternalEvent';
|
||||||
import Shape from '../../geometry/shape/Shape';
|
import Shape from '../../geometry/shape/Shape';
|
||||||
import InternalMouseEvent from '../../event/InternalMouseEvent';
|
import InternalMouseEvent from '../../event/InternalMouseEvent';
|
||||||
import Image from '../../image/Image';
|
import Image from '../../image/ImageBox';
|
||||||
import Graph from '../../Graph';
|
import Graph from '../../Graph';
|
||||||
import CellState from '../datatypes/CellState';
|
import CellState from '../datatypes/CellState';
|
||||||
|
|
||||||
|
@ -33,11 +33,12 @@ import CellState from '../datatypes/CellState';
|
||||||
class VertexHandle {
|
class VertexHandle {
|
||||||
dependencies = ['snap', 'cells'];
|
dependencies = ['snap', 'cells'];
|
||||||
|
|
||||||
constructor(state: CellState,
|
constructor(
|
||||||
cursor: string | null = 'default',
|
state: CellState,
|
||||||
image: Image | null = null,
|
cursor: string | null = 'default',
|
||||||
shape: Shape | null = null) {
|
image: Image | null = null,
|
||||||
|
shape: Shape | null = null
|
||||||
|
) {
|
||||||
this.graph = state.view.graph;
|
this.graph = state.view.graph;
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.cursor = cursor != null ? cursor : this.cursor;
|
this.cursor = cursor != null ? cursor : this.cursor;
|
||||||
|
@ -221,12 +222,8 @@ class VertexHandle {
|
||||||
const tr = this.graph.view.translate;
|
const tr = this.graph.view.translate;
|
||||||
const shapeBounds = <Rectangle>this.shape.bounds;
|
const shapeBounds = <Rectangle>this.shape.bounds;
|
||||||
|
|
||||||
shapeBounds.x = Math.floor(
|
shapeBounds.x = Math.floor((pt.x + tr.x) * scale - shapeBounds.width / 2);
|
||||||
(pt.x + tr.x) * scale - shapeBounds.width / 2
|
shapeBounds.y = Math.floor((pt.y + tr.y) * scale - shapeBounds.height / 2);
|
||||||
);
|
|
||||||
shapeBounds.y = Math.floor(
|
|
||||||
(pt.y + tr.y) * scale - shapeBounds.height / 2
|
|
||||||
);
|
|
||||||
|
|
||||||
// Needed to force update of text bounds
|
// Needed to force update of text bounds
|
||||||
this.shape.redraw();
|
this.shape.redraw();
|
||||||
|
@ -240,8 +237,7 @@ class VertexHandle {
|
||||||
*/
|
*/
|
||||||
isHtmlRequired(): boolean {
|
isHtmlRequired(): boolean {
|
||||||
return (
|
return (
|
||||||
this.state.text != null &&
|
this.state.text != null && this.state.text.node.parentNode === this.graph.container
|
||||||
this.state.text.node.parentNode === this.graph.container
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ import mxClient from '../../../mxClient';
|
||||||
import { isMouseEvent, isShiftDown } from '../../../util/EventUtils';
|
import { isMouseEvent, isShiftDown } from '../../../util/EventUtils';
|
||||||
import Graph from '../../Graph';
|
import Graph from '../../Graph';
|
||||||
import CellState from '../datatypes/CellState';
|
import CellState from '../datatypes/CellState';
|
||||||
import Image from '../../image/Image';
|
import Image from '../../image/ImageBox';
|
||||||
import Cell from '../datatypes/Cell';
|
import Cell from '../datatypes/Cell';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -238,15 +238,9 @@ class VertexHandler {
|
||||||
// VML dialect required here for event transparency in IE
|
// VML dialect required here for event transparency in IE
|
||||||
this.selectionBorder.dialect = DIALECT_SVG;
|
this.selectionBorder.dialect = DIALECT_SVG;
|
||||||
this.selectionBorder.pointerEvents = false;
|
this.selectionBorder.pointerEvents = false;
|
||||||
this.selectionBorder.rotation = Number(
|
this.selectionBorder.rotation = Number(this.state.style.rotation || '0');
|
||||||
this.state.style.rotation || '0'
|
|
||||||
);
|
|
||||||
this.selectionBorder.init(this.graph.getView().getOverlayPane());
|
this.selectionBorder.init(this.graph.getView().getOverlayPane());
|
||||||
InternalEvent.redirectMouseEvents(
|
InternalEvent.redirectMouseEvents(this.selectionBorder.node, this.graph, this.state);
|
||||||
this.selectionBorder.node,
|
|
||||||
this.graph,
|
|
||||||
this.state
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.graph.isCellMovable(this.state.cell)) {
|
if (this.graph.isCellMovable(this.state.cell)) {
|
||||||
this.selectionBorder.setCursor(CURSOR_MOVABLE_VERTEX);
|
this.selectionBorder.setCursor(CURSOR_MOVABLE_VERTEX);
|
||||||
|
@ -357,9 +351,7 @@ class VertexHandler {
|
||||||
*/
|
*/
|
||||||
// isConstrainedEvent(me: mxMouseEvent): boolean;
|
// isConstrainedEvent(me: mxMouseEvent): boolean;
|
||||||
isConstrainedEvent(me) {
|
isConstrainedEvent(me) {
|
||||||
return (
|
return isShiftDown(me.getEvent()) || this.state.style.aspect === 'fixed';
|
||||||
isShiftDown(me.getEvent()) || this.state.style.aspect === 'fixed'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -448,7 +440,7 @@ class VertexHandler {
|
||||||
null,
|
null,
|
||||||
this.getSelectionColor()
|
this.getSelectionColor()
|
||||||
);
|
);
|
||||||
shape.strokewidth = this.getSelectionStrokeWidth();
|
shape.strokeWidth = this.getSelectionStrokeWidth();
|
||||||
shape.isDashed = this.isSelectionDashed();
|
shape.isDashed = this.isSelectionDashed();
|
||||||
|
|
||||||
return shape;
|
return shape;
|
||||||
|
@ -560,17 +552,9 @@ class VertexHandler {
|
||||||
return shape;
|
return shape;
|
||||||
}
|
}
|
||||||
if (index === InternalEvent.ROTATION_HANDLE) {
|
if (index === InternalEvent.ROTATION_HANDLE) {
|
||||||
return new EllipseShape(
|
return new EllipseShape(bounds, fillColor || HANDLE_FILLCOLOR, HANDLE_STROKECOLOR);
|
||||||
bounds,
|
|
||||||
fillColor || HANDLE_FILLCOLOR,
|
|
||||||
HANDLE_STROKECOLOR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return new RectangleShape(
|
return new RectangleShape(bounds, fillColor || HANDLE_FILLCOLOR, HANDLE_STROKECOLOR);
|
||||||
bounds,
|
|
||||||
fillColor || HANDLE_FILLCOLOR,
|
|
||||||
HANDLE_STROKECOLOR
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -604,19 +588,12 @@ class VertexHandler {
|
||||||
const tol = !isMouseEvent(me.getEvent()) ? this.tolerance : 1;
|
const tol = !isMouseEvent(me.getEvent()) ? this.tolerance : 1;
|
||||||
const hit =
|
const hit =
|
||||||
this.allowHandleBoundsCheck && tol > 0
|
this.allowHandleBoundsCheck && tol > 0
|
||||||
? new Rectangle(
|
? new Rectangle(me.getGraphX() - tol, me.getGraphY() - tol, 2 * tol, 2 * tol)
|
||||||
me.getGraphX() - tol,
|
|
||||||
me.getGraphY() - tol,
|
|
||||||
2 * tol,
|
|
||||||
2 * tol
|
|
||||||
)
|
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const checkShape = (shape) => {
|
const checkShape = (shape) => {
|
||||||
const st =
|
const st =
|
||||||
shape != null &&
|
shape != null && shape.constructor !== ImageShape && this.allowHandleBoundsCheck
|
||||||
shape.constructor !== ImageShape &&
|
|
||||||
this.allowHandleBoundsCheck
|
|
||||||
? shape.strokewidth + shape.svgStrokeTolerance
|
? shape.strokewidth + shape.svgStrokeTolerance
|
||||||
: null;
|
: null;
|
||||||
const real =
|
const real =
|
||||||
|
@ -720,8 +697,7 @@ class VertexHandler {
|
||||||
// start(x: number, y: number, index: number): void;
|
// start(x: number, y: number, index: number): void;
|
||||||
start(x, y, index) {
|
start(x, y, index) {
|
||||||
if (this.selectionBorder != null) {
|
if (this.selectionBorder != null) {
|
||||||
this.livePreviewActive =
|
this.livePreviewActive = this.livePreview && this.state.cell.getChildCount() === 0;
|
||||||
this.livePreview && this.state.cell.getChildCount() === 0;
|
|
||||||
this.inTolerance = true;
|
this.inTolerance = true;
|
||||||
this.childOffsetX = 0;
|
this.childOffsetX = 0;
|
||||||
this.childOffsetY = 0;
|
this.childOffsetY = 0;
|
||||||
|
@ -752,10 +728,7 @@ class VertexHandler {
|
||||||
this.preview = this.createSelectionShape(this.bounds);
|
this.preview = this.createSelectionShape(this.bounds);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!(
|
!(mxClient.IS_SVG && Number(this.state.style.rotation || '0') !== 0) &&
|
||||||
mxClient.IS_SVG &&
|
|
||||||
Number(this.state.style.rotation || '0') !== 0
|
|
||||||
) &&
|
|
||||||
this.state.text != null &&
|
this.state.text != null &&
|
||||||
this.state.text.node.parentNode === this.graph.container
|
this.state.text.node.parentNode === this.graph.container
|
||||||
) {
|
) {
|
||||||
|
@ -774,8 +747,7 @@ class VertexHandler {
|
||||||
const dx = pos.x - this.state.getCenterX();
|
const dx = pos.x - this.state.getCenterX();
|
||||||
const dy = pos.y - this.state.getCenterY();
|
const dy = pos.y - this.state.getCenterY();
|
||||||
|
|
||||||
this.startAngle =
|
this.startAngle = dx !== 0 ? (Math.atan(dy / dx) * 180) / Math.PI + 90 : 0;
|
||||||
dx !== 0 ? (Math.atan(dy / dx) * 180) / Math.PI + 90 : 0;
|
|
||||||
this.startDist = Math.sqrt(dx * dx + dy * dy);
|
this.startDist = Math.sqrt(dx * dx + dy * dy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -789,10 +761,7 @@ class VertexHandler {
|
||||||
this.labelShape.node.style.display = '';
|
this.labelShape.node.style.display = '';
|
||||||
} else if (this.sizers != null && this.sizers[index] != null) {
|
} else if (this.sizers != null && this.sizers[index] != null) {
|
||||||
this.sizers[index].node.style.display = '';
|
this.sizers[index].node.style.display = '';
|
||||||
} else if (
|
} else if (index <= InternalEvent.CUSTOM_HANDLE && this.customHandles != null) {
|
||||||
index <= InternalEvent.CUSTOM_HANDLE &&
|
|
||||||
this.customHandles != null
|
|
||||||
) {
|
|
||||||
this.customHandles[InternalEvent.CUSTOM_HANDLE - index].setVisible(true);
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - index].setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -801,9 +770,7 @@ class VertexHandler {
|
||||||
this.edgeHandlers = [];
|
this.edgeHandlers = [];
|
||||||
|
|
||||||
for (let i = 0; i < edges.length; i += 1) {
|
for (let i = 0; i < edges.length; i += 1) {
|
||||||
const handler = this.graph.selectionCellsHandler.getHandler(
|
const handler = this.graph.selectionCellsHandler.getHandler(edges[i]);
|
||||||
edges[i]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
this.edgeHandlers.push(handler);
|
this.edgeHandlers.push(handler);
|
||||||
|
@ -933,12 +900,8 @@ class VertexHandler {
|
||||||
if (!this.inTolerance) {
|
if (!this.inTolerance) {
|
||||||
if (this.index <= InternalEvent.CUSTOM_HANDLE) {
|
if (this.index <= InternalEvent.CUSTOM_HANDLE) {
|
||||||
if (this.customHandles != null) {
|
if (this.customHandles != null) {
|
||||||
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].processEvent(
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].processEvent(me);
|
||||||
me
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - this.index].active = true;
|
||||||
);
|
|
||||||
this.customHandles[
|
|
||||||
InternalEvent.CUSTOM_HANDLE - this.index
|
|
||||||
].active = true;
|
|
||||||
|
|
||||||
if (this.ghostPreview != null) {
|
if (this.ghostPreview != null) {
|
||||||
this.ghostPreview.apply(this.state);
|
this.ghostPreview.apply(this.state);
|
||||||
|
@ -1010,9 +973,7 @@ class VertexHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
const index =
|
const index =
|
||||||
this.rotationShape != null
|
this.rotationShape != null ? this.sizers.length - 2 : this.sizers.length - 1;
|
||||||
? this.sizers.length - 2
|
|
||||||
: this.sizers.length - 1;
|
|
||||||
this.moveSizerTo(this.sizers[index], point.x, point.y);
|
this.moveSizerTo(this.sizers[index], point.x, point.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1148,26 +1109,14 @@ class VertexHandler {
|
||||||
this.unscaledBounds.y = max.y;
|
this.unscaledBounds.y = max.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.unscaledBounds.x + this.unscaledBounds.width > max.x + max.width) {
|
||||||
this.unscaledBounds.x + this.unscaledBounds.width >
|
|
||||||
max.x + max.width
|
|
||||||
) {
|
|
||||||
this.unscaledBounds.width -=
|
this.unscaledBounds.width -=
|
||||||
this.unscaledBounds.x +
|
this.unscaledBounds.x + this.unscaledBounds.width - max.x - max.width;
|
||||||
this.unscaledBounds.width -
|
|
||||||
max.x -
|
|
||||||
max.width;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.unscaledBounds.y + this.unscaledBounds.height > max.y + max.height) {
|
||||||
this.unscaledBounds.y + this.unscaledBounds.height >
|
|
||||||
max.y + max.height
|
|
||||||
) {
|
|
||||||
this.unscaledBounds.height -=
|
this.unscaledBounds.height -=
|
||||||
this.unscaledBounds.y +
|
this.unscaledBounds.y + this.unscaledBounds.height - max.y - max.height;
|
||||||
this.unscaledBounds.height -
|
|
||||||
max.y -
|
|
||||||
max.height;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1211,12 +1160,8 @@ class VertexHandler {
|
||||||
this.bounds.y += dy3;
|
this.bounds.y += dy3;
|
||||||
|
|
||||||
// Rounds unscaled bounds to int
|
// Rounds unscaled bounds to int
|
||||||
this.unscaledBounds.x = this.roundLength(
|
this.unscaledBounds.x = this.roundLength(this.unscaledBounds.x + dx3 / scale);
|
||||||
this.unscaledBounds.x + dx3 / scale
|
this.unscaledBounds.y = this.roundLength(this.unscaledBounds.y + dy3 / scale);
|
||||||
);
|
|
||||||
this.unscaledBounds.y = this.roundLength(
|
|
||||||
this.unscaledBounds.y + dy3 / scale
|
|
||||||
);
|
|
||||||
this.unscaledBounds.width = this.roundLength(this.unscaledBounds.width);
|
this.unscaledBounds.width = this.roundLength(this.unscaledBounds.width);
|
||||||
this.unscaledBounds.height = this.roundLength(this.unscaledBounds.height);
|
this.unscaledBounds.height = this.roundLength(this.unscaledBounds.height);
|
||||||
|
|
||||||
|
@ -1370,15 +1315,12 @@ class VertexHandler {
|
||||||
this.customHandles[InternalEvent.CUSTOM_HANDLE - index] != null
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - index] != null
|
||||||
) {
|
) {
|
||||||
this.state.style = style;
|
this.state.style = style;
|
||||||
this.customHandles[
|
this.customHandles[InternalEvent.CUSTOM_HANDLE - index].positionChanged();
|
||||||
InternalEvent.CUSTOM_HANDLE - index
|
|
||||||
].positionChanged();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (index === InternalEvent.ROTATION_HANDLE) {
|
} else if (index === InternalEvent.ROTATION_HANDLE) {
|
||||||
if (this.currentAlpha != null) {
|
if (this.currentAlpha != null) {
|
||||||
const delta =
|
const delta = this.currentAlpha - (this.state.style.rotation || 0);
|
||||||
this.currentAlpha - (this.state.style.rotation || 0);
|
|
||||||
|
|
||||||
if (delta !== 0) {
|
if (delta !== 0) {
|
||||||
this.rotateCell(this.state.cell, delta);
|
this.rotateCell(this.state.cell, delta);
|
||||||
|
@ -1388,9 +1330,7 @@ class VertexHandler {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const gridEnabled = this.graph.isGridEnabledEvent(me.getEvent());
|
const gridEnabled = this.graph.isGridEnabledEvent(me.getEvent());
|
||||||
const alpha = utils.toRadians(
|
const alpha = utils.toRadians(this.state.style.rotation || '0');
|
||||||
this.state.style.rotation || '0'
|
|
||||||
);
|
|
||||||
const cos = Math.cos(-alpha);
|
const cos = Math.cos(-alpha);
|
||||||
const sin = Math.sin(-alpha);
|
const sin = Math.sin(-alpha);
|
||||||
|
|
||||||
|
@ -1579,20 +1519,14 @@ class VertexHandler {
|
||||||
|
|
||||||
if (geo != null) {
|
if (geo != null) {
|
||||||
if (index === InternalEvent.LABEL_HANDLE) {
|
if (index === InternalEvent.LABEL_HANDLE) {
|
||||||
const alpha = -utils.toRadians(
|
const alpha = -utils.toRadians(this.state.style.rotation || '0');
|
||||||
this.state.style.rotation || '0'
|
|
||||||
);
|
|
||||||
const cos = Math.cos(alpha);
|
const cos = Math.cos(alpha);
|
||||||
const sin = Math.sin(alpha);
|
const sin = Math.sin(alpha);
|
||||||
const { scale } = this.graph.view;
|
const { scale } = this.graph.view;
|
||||||
const pt = utils.getRotatedPoint(
|
const pt = utils.getRotatedPoint(
|
||||||
new Point(
|
new Point(
|
||||||
Math.round(
|
Math.round((this.labelShape.bounds.getCenterX() - this.startX) / scale),
|
||||||
(this.labelShape.bounds.getCenterX() - this.startX) / scale
|
Math.round((this.labelShape.bounds.getCenterY() - this.startY) / scale)
|
||||||
),
|
|
||||||
Math.round(
|
|
||||||
(this.labelShape.bounds.getCenterY() - this.startY) / scale
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
cos,
|
cos,
|
||||||
sin
|
sin
|
||||||
|
@ -1811,12 +1745,7 @@ class VertexHandler {
|
||||||
height = Math.abs(height);
|
height = Math.abs(height);
|
||||||
}
|
}
|
||||||
|
|
||||||
const result = new Rectangle(
|
const result = new Rectangle(left + tr.x * scale, top + tr.y * scale, width, height);
|
||||||
left + tr.x * scale,
|
|
||||||
top + tr.y * scale,
|
|
||||||
width,
|
|
||||||
height
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.minBounds != null) {
|
if (this.minBounds != null) {
|
||||||
result.width = Math.max(
|
result.width = Math.max(
|
||||||
|
@ -1924,18 +1853,13 @@ class VertexHandler {
|
||||||
|
|
||||||
// Hides custom handles during text editing
|
// Hides custom handles during text editing
|
||||||
this.customHandles[i].shape.node.style.visibility =
|
this.customHandles[i].shape.node.style.visibility =
|
||||||
this.handlesVisible &&
|
this.handlesVisible && this.isCustomHandleVisible(this.customHandles[i])
|
||||||
this.isCustomHandleVisible(this.customHandles[i])
|
|
||||||
? ''
|
? ''
|
||||||
: 'hidden';
|
: 'hidden';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.sizers != null && this.sizers.length > 0 && this.sizers[0] != null) {
|
||||||
this.sizers != null &&
|
|
||||||
this.sizers.length > 0 &&
|
|
||||||
this.sizers[0] != null
|
|
||||||
) {
|
|
||||||
if (this.index == null && this.manageSizers && this.sizers.length >= 8) {
|
if (this.index == null && this.manageSizers && this.sizers.length >= 8) {
|
||||||
// KNOWN: Tolerance depends on event type (eg. 0 for mouse events)
|
// KNOWN: Tolerance depends on event type (eg. 0 for mouse events)
|
||||||
const padding = this.getHandlePadding();
|
const padding = this.getHandlePadding();
|
||||||
|
@ -1990,9 +1914,7 @@ class VertexHandler {
|
||||||
'w-resize',
|
'w-resize',
|
||||||
];
|
];
|
||||||
|
|
||||||
const alpha = utils.toRadians(
|
const alpha = utils.toRadians(this.state.style.rotation || '0');
|
||||||
this.state.style.rotation || '0'
|
|
||||||
);
|
|
||||||
const cos = Math.cos(alpha);
|
const cos = Math.cos(alpha);
|
||||||
const sin = Math.sin(alpha);
|
const sin = Math.sin(alpha);
|
||||||
const da = Math.round((alpha * 4) / Math.PI);
|
const da = Math.round((alpha * 4) / Math.PI);
|
||||||
|
@ -2062,36 +1984,25 @@ class VertexHandler {
|
||||||
|
|
||||||
if (this.rotationShape != null) {
|
if (this.rotationShape != null) {
|
||||||
const alpha = utils.toRadians(
|
const alpha = utils.toRadians(
|
||||||
this.currentAlpha != null
|
this.currentAlpha != null ? this.currentAlpha : this.state.style.rotation || '0'
|
||||||
? this.currentAlpha
|
|
||||||
: this.state.style.rotation || '0'
|
|
||||||
);
|
);
|
||||||
const cos = Math.cos(alpha);
|
const cos = Math.cos(alpha);
|
||||||
const sin = Math.sin(alpha);
|
const sin = Math.sin(alpha);
|
||||||
|
|
||||||
const ct = new Point(this.state.getCenterX(), this.state.getCenterY());
|
const ct = new Point(this.state.getCenterX(), this.state.getCenterY());
|
||||||
const pt = utils.getRotatedPoint(
|
const pt = utils.getRotatedPoint(this.getRotationHandlePosition(), cos, sin, ct);
|
||||||
this.getRotationHandlePosition(),
|
|
||||||
cos,
|
|
||||||
sin,
|
|
||||||
ct
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.rotationShape.node != null) {
|
if (this.rotationShape.node != null) {
|
||||||
this.moveSizerTo(this.rotationShape, pt.x, pt.y);
|
this.moveSizerTo(this.rotationShape, pt.x, pt.y);
|
||||||
|
|
||||||
// Hides rotation handle during text editing
|
// Hides rotation handle during text editing
|
||||||
this.rotationShape.node.style.visibility =
|
this.rotationShape.node.style.visibility =
|
||||||
this.state.view.graph.isEditing() || !this.handlesVisible
|
this.state.view.graph.isEditing() || !this.handlesVisible ? 'hidden' : '';
|
||||||
? 'hidden'
|
|
||||||
: '';
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.selectionBorder != null) {
|
if (this.selectionBorder != null) {
|
||||||
this.selectionBorder.rotation = Number(
|
this.selectionBorder.rotation = Number(this.state.style.rotation || '0');
|
||||||
this.state.style.rotation || '0'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.edgeHandlers != null) {
|
if (this.edgeHandlers != null) {
|
||||||
|
@ -2107,9 +2018,7 @@ class VertexHandler {
|
||||||
* Returns true if the given custom handle is visible.
|
* Returns true if the given custom handle is visible.
|
||||||
*/
|
*/
|
||||||
isCustomHandleVisible(handle) {
|
isCustomHandleVisible(handle) {
|
||||||
return (
|
return !this.graph.isEditing() && this.state.view.graph.getSelectionCount() === 1;
|
||||||
!this.graph.isEditing() && this.state.view.graph.getSelectionCount() === 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2162,10 +2071,7 @@ class VertexHandler {
|
||||||
this.parentHighlight.redraw();
|
this.parentHighlight.redraw();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (
|
if (pstate != null && pstate.parentHighlight === this.parentHighlight) {
|
||||||
pstate != null &&
|
|
||||||
pstate.parentHighlight === this.parentHighlight
|
|
||||||
) {
|
|
||||||
pstate.parentHighlight = null;
|
pstate.parentHighlight = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2173,18 +2079,12 @@ class VertexHandler {
|
||||||
this.parentHighlight = null;
|
this.parentHighlight = null;
|
||||||
}
|
}
|
||||||
} else if (this.parentHighlightEnabled && visible) {
|
} else if (this.parentHighlightEnabled && visible) {
|
||||||
if (
|
if (parent.isVertex() && pstate != null && pstate.parentHighlight == null) {
|
||||||
parent.isVertex() &&
|
|
||||||
pstate != null &&
|
|
||||||
pstate.parentHighlight == null
|
|
||||||
) {
|
|
||||||
this.parentHighlight = this.createParentHighlightShape(pstate);
|
this.parentHighlight = this.createParentHighlightShape(pstate);
|
||||||
// VML dialect required here for event transparency in IE
|
// VML dialect required here for event transparency in IE
|
||||||
this.parentHighlight.dialect = DIALECT_SVG;
|
this.parentHighlight.dialect = DIALECT_SVG;
|
||||||
this.parentHighlight.pointerEvents = false;
|
this.parentHighlight.pointerEvents = false;
|
||||||
this.parentHighlight.rotation = Number(
|
this.parentHighlight.rotation = Number(pstate.style.rotation || '0');
|
||||||
pstate.style.rotation || '0'
|
|
||||||
);
|
|
||||||
this.parentHighlight.init(this.graph.getView().getOverlayPane());
|
this.parentHighlight.init(this.graph.getView().getOverlayPane());
|
||||||
this.parentHighlight.redraw();
|
this.parentHighlight.redraw();
|
||||||
|
|
||||||
|
@ -2207,10 +2107,7 @@ class VertexHandler {
|
||||||
|
|
||||||
if (this.preview.node.parentNode === this.graph.container) {
|
if (this.preview.node.parentNode === this.graph.container) {
|
||||||
this.preview.bounds.width = Math.max(0, this.preview.bounds.width - 1);
|
this.preview.bounds.width = Math.max(0, this.preview.bounds.width - 1);
|
||||||
this.preview.bounds.height = Math.max(
|
this.preview.bounds.height = Math.max(0, this.preview.bounds.height - 1);
|
||||||
0,
|
|
||||||
this.preview.bounds.height - 1
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.preview.rotation = Number(this.state.style.rotation || '0');
|
this.preview.rotation = Number(this.state.style.rotation || '0');
|
||||||
|
|
|
@ -19,7 +19,13 @@ import {
|
||||||
TOOLTIP_VERTICAL_OFFSET,
|
TOOLTIP_VERTICAL_OFFSET,
|
||||||
VALID_COLOR,
|
VALID_COLOR,
|
||||||
} from '../../util/Constants';
|
} from '../../util/Constants';
|
||||||
import utils, { convertPoint, getOffset, getRotatedPoint, getValue, toRadians } from '../../util/Utils';
|
import utils, {
|
||||||
|
convertPoint,
|
||||||
|
getOffset,
|
||||||
|
getRotatedPoint,
|
||||||
|
getValue,
|
||||||
|
toRadians,
|
||||||
|
} from '../../util/Utils';
|
||||||
import InternalMouseEvent from '../event/InternalMouseEvent';
|
import InternalMouseEvent from '../event/InternalMouseEvent';
|
||||||
import ImageShape from '../geometry/shape/node/ImageShape';
|
import ImageShape from '../geometry/shape/node/ImageShape';
|
||||||
import CellMarker from '../cell/CellMarker';
|
import CellMarker from '../cell/CellMarker';
|
||||||
|
@ -36,7 +42,7 @@ import {
|
||||||
isShiftDown,
|
isShiftDown,
|
||||||
} from '../../util/EventUtils';
|
} from '../../util/EventUtils';
|
||||||
import graph from '../Graph';
|
import graph from '../Graph';
|
||||||
import Image from '../image/Image';
|
import Image from '../image/ImageBox';
|
||||||
import CellState from '../cell/datatypes/CellState';
|
import CellState from '../cell/datatypes/CellState';
|
||||||
import Graph from '../Graph';
|
import Graph from '../Graph';
|
||||||
import ConnectionConstraint from './ConnectionConstraint';
|
import ConnectionConstraint from './ConnectionConstraint';
|
||||||
|
@ -201,8 +207,7 @@ type FactoryMethod = (source: Cell, target: Cell, style?: string) => Cell;
|
||||||
* the <mxCell> that represents the new edge.
|
* the <mxCell> that represents the new edge.
|
||||||
*/
|
*/
|
||||||
class ConnectionHandler extends EventSource {
|
class ConnectionHandler extends EventSource {
|
||||||
constructor(graph: Graph,
|
constructor(graph: Graph, factoryMethod: FactoryMethod | null = null) {
|
||||||
factoryMethod: FactoryMethod | null = null) {
|
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
|
@ -660,7 +665,7 @@ class ConnectionHandler extends EventSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
};
|
}
|
||||||
|
|
||||||
// Sets the highlight color according to validateConnection
|
// Sets the highlight color according to validateConnection
|
||||||
isValidState(state: CellState) {
|
isValidState(state: CellState) {
|
||||||
|
@ -696,11 +701,7 @@ class ConnectionHandler extends EventSource {
|
||||||
*
|
*
|
||||||
* Starts a new connection for the given state and coordinates.
|
* Starts a new connection for the given state and coordinates.
|
||||||
*/
|
*/
|
||||||
start(state: CellState,
|
start(state: CellState, x: number, y: number, edgeState: CellState): void {
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
edgeState: CellState): void {
|
|
||||||
|
|
||||||
this.previous = state;
|
this.previous = state;
|
||||||
this.first = new Point(x, y);
|
this.first = new Point(x, y);
|
||||||
this.edgeState = edgeState != null ? edgeState : this.createEdgeState(null);
|
this.edgeState = edgeState != null ? edgeState : this.createEdgeState(null);
|
||||||
|
@ -733,8 +734,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* cell - <mxCell> that represents the source terminal.
|
* cell - <mxCell> that represents the source terminal.
|
||||||
* me - <mxMouseEvent> that is associated with this call.
|
* me - <mxMouseEvent> that is associated with this call.
|
||||||
*/
|
*/
|
||||||
isValidSource(cell: Cell,
|
isValidSource(cell: Cell, me: InternalMouseEvent): boolean {
|
||||||
me: InternalMouseEvent): boolean {
|
|
||||||
return this.graph.isValidSource(cell);
|
return this.graph.isValidSource(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -765,8 +765,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* source - <mxCell> that represents the source terminal.
|
* source - <mxCell> that represents the source terminal.
|
||||||
* target - <mxCell> that represents the target terminal.
|
* target - <mxCell> that represents the target terminal.
|
||||||
*/
|
*/
|
||||||
validateConnection(source: Cell,
|
validateConnection(source: Cell, target: Cell): string {
|
||||||
target: Cell): string {
|
|
||||||
if (!this.isValidTarget(target)) {
|
if (!this.isValidTarget(target)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
@ -798,10 +797,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* state - <mxCellState> whose connect icons should be returned.
|
* state - <mxCellState> whose connect icons should be returned.
|
||||||
*/
|
*/
|
||||||
isMoveIconToFrontForState(state: CellState): boolean {
|
isMoveIconToFrontForState(state: CellState): boolean {
|
||||||
if (
|
if (state.text != null && state.text.node.parentNode === this.graph.container) {
|
||||||
state.text != null &&
|
|
||||||
state.text.node.parentNode === this.graph.container
|
|
||||||
) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return this.moveIconFront;
|
return this.moveIconFront;
|
||||||
|
@ -841,10 +837,7 @@ class ConnectionHandler extends EventSource {
|
||||||
|
|
||||||
// Move the icon back in the overlay pane
|
// Move the icon back in the overlay pane
|
||||||
if (this.moveIconBack && icon.node.previousSibling != null) {
|
if (this.moveIconBack && icon.node.previousSibling != null) {
|
||||||
icon.node.parentNode.insertBefore(
|
icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
|
||||||
icon.node,
|
|
||||||
icon.node.parentNode.firstChild
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -886,8 +879,7 @@ class ConnectionHandler extends EventSource {
|
||||||
*
|
*
|
||||||
* icons - Optional array of <mxImageShapes> to be redrawn.
|
* icons - Optional array of <mxImageShapes> to be redrawn.
|
||||||
*/
|
*/
|
||||||
redrawIcons(icons?: ImageShape[] | null,
|
redrawIcons(icons?: ImageShape[] | null, state?: CellState): void {
|
||||||
state?: CellState): void {
|
|
||||||
if (icons != null && icons[0] != null && state != null) {
|
if (icons != null && icons[0] != null && state != null) {
|
||||||
const pos = this.getIconPosition(icons[0], state);
|
const pos = this.getIconPosition(icons[0], state);
|
||||||
icons[0].bounds.x = pos.x;
|
icons[0].bounds.x = pos.x;
|
||||||
|
@ -897,8 +889,7 @@ class ConnectionHandler extends EventSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Document me! ===========================================================================================================
|
// TODO: Document me! ===========================================================================================================
|
||||||
getIconPosition(icon: ImageShape,
|
getIconPosition(icon: ImageShape, state: CellState): Point {
|
||||||
state: CellState): Point {
|
|
||||||
const { scale } = this.graph.getView();
|
const { scale } = this.graph.getView();
|
||||||
let cx = state.getCenterX();
|
let cx = state.getCenterX();
|
||||||
let cy = state.getCenterY();
|
let cy = state.getCenterY();
|
||||||
|
@ -909,9 +900,7 @@ class ConnectionHandler extends EventSource {
|
||||||
cx = size.width !== 0 ? state.x + (size.width * scale) / 2 : cx;
|
cx = size.width !== 0 ? state.x + (size.width * scale) / 2 : cx;
|
||||||
cy = size.height !== 0 ? state.y + (size.height * scale) / 2 : cy;
|
cy = size.height !== 0 ? state.y + (size.height * scale) / 2 : cy;
|
||||||
|
|
||||||
const alpha = toRadians(
|
const alpha = toRadians(getValue(state.style, 'rotation') || 0);
|
||||||
getValue(state.style, 'rotation') || 0
|
|
||||||
);
|
|
||||||
|
|
||||||
if (alpha !== 0) {
|
if (alpha !== 0) {
|
||||||
const cos = Math.cos(alpha);
|
const cos = Math.cos(alpha);
|
||||||
|
@ -1066,10 +1055,8 @@ class ConnectionHandler extends EventSource {
|
||||||
const left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
|
const left = (window.pageXOffset || doc.scrollLeft) - (doc.clientLeft || 0);
|
||||||
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
const top = (window.pageYOffset || doc.scrollTop) - (doc.clientTop || 0);
|
||||||
|
|
||||||
const gridX =
|
const gridX = this.currentPoint.x - this.graph.container.scrollLeft + offset.x - left;
|
||||||
this.currentPoint.x - this.graph.container.scrollLeft + offset.x - left;
|
const gridY = this.currentPoint.y - this.graph.container.scrollTop + offset.y - top;
|
||||||
const gridY =
|
|
||||||
this.currentPoint.y - this.graph.container.scrollTop + offset.y - top;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
this.outlineConnect &&
|
this.outlineConnect &&
|
||||||
|
@ -1089,15 +1076,12 @@ class ConnectionHandler extends EventSource {
|
||||||
* Updates the current state for a given mouse move event by using
|
* Updates the current state for a given mouse move event by using
|
||||||
* the <marker>.
|
* the <marker>.
|
||||||
*/
|
*/
|
||||||
updateCurrentState(me: InternalMouseEvent,
|
updateCurrentState(me: InternalMouseEvent, point: Point): void {
|
||||||
point: Point): void {
|
|
||||||
this.constraintHandler.update(
|
this.constraintHandler.update(
|
||||||
me,
|
me,
|
||||||
this.first == null,
|
this.first == null,
|
||||||
false,
|
false,
|
||||||
this.first == null || me.isSource(this.marker.highlight.shape)
|
this.first == null || me.isSource(this.marker.highlight.shape) ? null : point
|
||||||
? null
|
|
||||||
: point
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1109,8 +1093,7 @@ class ConnectionHandler extends EventSource {
|
||||||
if (
|
if (
|
||||||
this.marker.highlight != null &&
|
this.marker.highlight != null &&
|
||||||
this.marker.highlight.state != null &&
|
this.marker.highlight.state != null &&
|
||||||
this.marker.highlight.state.cell ===
|
this.marker.highlight.state.cell === this.constraintHandler.currentFocus.cell
|
||||||
this.constraintHandler.currentFocus.cell
|
|
||||||
) {
|
) {
|
||||||
// Direct repaint needed if cell already highlighted
|
// Direct repaint needed if cell already highlighted
|
||||||
if (this.marker.highlight.shape.stroke !== 'transparent') {
|
if (this.marker.highlight.shape.stroke !== 'transparent') {
|
||||||
|
@ -1118,10 +1101,7 @@ class ConnectionHandler extends EventSource {
|
||||||
this.marker.highlight.repaint();
|
this.marker.highlight.repaint();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.marker.markCell(
|
this.marker.markCell(this.constraintHandler.currentFocus.cell, 'transparent');
|
||||||
this.constraintHandler.currentFocus.cell,
|
|
||||||
'transparent'
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Updates validation state
|
// Updates validation state
|
||||||
|
@ -1137,8 +1117,7 @@ class ConnectionHandler extends EventSource {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
this.error != null ||
|
this.error != null ||
|
||||||
(this.currentState != null &&
|
(this.currentState != null && !this.isCellEnabled(this.currentState.cell))
|
||||||
!this.isCellEnabled(this.currentState.cell))
|
|
||||||
) {
|
) {
|
||||||
this.constraintHandler.reset();
|
this.constraintHandler.reset();
|
||||||
}
|
}
|
||||||
|
@ -1152,10 +1131,7 @@ class ConnectionHandler extends EventSource {
|
||||||
this.currentState = this.marker.getValidState();
|
this.currentState = this.marker.getValidState();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (this.currentState != null && !this.isCellEnabled(this.currentState.cell)) {
|
||||||
this.currentState != null &&
|
|
||||||
!this.isCellEnabled(this.currentState.cell)
|
|
||||||
) {
|
|
||||||
this.constraintHandler.reset();
|
this.constraintHandler.reset();
|
||||||
this.marker.reset();
|
this.marker.reset();
|
||||||
this.currentState = null;
|
this.currentState = null;
|
||||||
|
@ -1170,21 +1146,14 @@ class ConnectionHandler extends EventSource {
|
||||||
point = new point(me.getGraphX(), me.getGraphY());
|
point = new point(me.getGraphX(), me.getGraphY());
|
||||||
}
|
}
|
||||||
|
|
||||||
const constraint = this.graph.getOutlineConstraint(
|
const constraint = this.graph.getOutlineConstraint(point, this.currentState, me);
|
||||||
point,
|
|
||||||
this.currentState,
|
|
||||||
me
|
|
||||||
);
|
|
||||||
this.constraintHandler.setFocus(me, this.currentState, false);
|
this.constraintHandler.setFocus(me, this.currentState, false);
|
||||||
this.constraintHandler.currentConstraint = constraint;
|
this.constraintHandler.currentConstraint = constraint;
|
||||||
this.constraintHandler.currentPoint = point;
|
this.constraintHandler.currentPoint = point;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.outlineConnect) {
|
if (this.outlineConnect) {
|
||||||
if (
|
if (this.marker.highlight != null && this.marker.highlight.shape != null) {
|
||||||
this.marker.highlight != null &&
|
|
||||||
this.marker.highlight.shape != null
|
|
||||||
) {
|
|
||||||
const s = this.graph.view.scale;
|
const s = this.graph.view.scale;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -1192,7 +1161,7 @@ class ConnectionHandler extends EventSource {
|
||||||
this.constraintHandler.currentFocus != null
|
this.constraintHandler.currentFocus != null
|
||||||
) {
|
) {
|
||||||
this.marker.highlight.shape.stroke = OUTLINE_HIGHLIGHT_COLOR;
|
this.marker.highlight.shape.stroke = OUTLINE_HIGHLIGHT_COLOR;
|
||||||
this.marker.highlight.shape.strokewidth =
|
this.marker.highlight.shape.strokeWidth =
|
||||||
OUTLINE_HIGHLIGHT_STROKEWIDTH / s / s;
|
OUTLINE_HIGHLIGHT_STROKEWIDTH / s / s;
|
||||||
this.marker.highlight.repaint();
|
this.marker.highlight.repaint();
|
||||||
} else if (this.marker.hasValidState()) {
|
} else if (this.marker.hasValidState()) {
|
||||||
|
@ -1209,8 +1178,7 @@ class ConnectionHandler extends EventSource {
|
||||||
this.marker.highlight.shape.stroke = DEFAULT_VALID_COLOR;
|
this.marker.highlight.shape.stroke = DEFAULT_VALID_COLOR;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.marker.highlight.shape.strokewidth =
|
this.marker.highlight.shape.strokeWidth = HIGHLIGHT_STROKEWIDTH / s / s;
|
||||||
HIGHLIGHT_STROKEWIDTH / s / s;
|
|
||||||
this.marker.highlight.repaint();
|
this.marker.highlight.repaint();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1246,8 +1214,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* Called to snap the given point to the current preview. This snaps to the
|
* Called to snap the given point to the current preview. This snaps to the
|
||||||
* first point of the preview if alt is not pressed.
|
* first point of the preview if alt is not pressed.
|
||||||
*/
|
*/
|
||||||
snapToPreview(me: MouseEvent,
|
snapToPreview(me: MouseEvent, point: Point): void {
|
||||||
point: Point): void {
|
|
||||||
if (!isAltDown(me.getEvent()) && this.previous != null) {
|
if (!isAltDown(me.getEvent()) && this.previous != null) {
|
||||||
const tol = (this.graph.gridSize * this.graph.view.scale) / 2;
|
const tol = (this.graph.gridSize * this.graph.view.scale) / 2;
|
||||||
const tmp =
|
const tmp =
|
||||||
|
@ -1271,8 +1238,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* Handles the event by updating the preview edge or by highlighting
|
* Handles the event by updating the preview edge or by highlighting
|
||||||
* a possible source or target terminal.
|
* a possible source or target terminal.
|
||||||
*/
|
*/
|
||||||
mouseMove(sender: MouseEvent,
|
mouseMove(sender: MouseEvent, me: InternalMouseEvent): void {
|
||||||
me: InternalMouseEvent): void {
|
|
||||||
if (
|
if (
|
||||||
!me.isConsumed() &&
|
!me.isConsumed() &&
|
||||||
(this.ignoreMouseDown || this.first != null || !this.graph.isMouseDown)
|
(this.ignoreMouseDown || this.first != null || !this.graph.isMouseDown)
|
||||||
|
@ -1344,10 +1310,7 @@ class ConnectionHandler extends EventSource {
|
||||||
const h = this.selectedIcon.bounds.height;
|
const h = this.selectedIcon.bounds.height;
|
||||||
|
|
||||||
if (this.currentState != null && this.targetConnectImage) {
|
if (this.currentState != null && this.targetConnectImage) {
|
||||||
const pos = this.getIconPosition(
|
const pos = this.getIconPosition(this.selectedIcon, this.currentState);
|
||||||
this.selectedIcon,
|
|
||||||
this.currentState
|
|
||||||
);
|
|
||||||
this.selectedIcon.bounds.x = pos.x;
|
this.selectedIcon.bounds.x = pos.x;
|
||||||
this.selectedIcon.bounds.y = pos.y;
|
this.selectedIcon.bounds.y = pos.y;
|
||||||
} else {
|
} else {
|
||||||
|
@ -1402,10 +1365,7 @@ class ConnectionHandler extends EventSource {
|
||||||
if (this.currentState == null && this.movePreviewAway) {
|
if (this.currentState == null && this.movePreviewAway) {
|
||||||
let tmp = pt2;
|
let tmp = pt2;
|
||||||
|
|
||||||
if (
|
if (this.edgeState != null && this.edgeState.absolutePoints.length >= 2) {
|
||||||
this.edgeState != null &&
|
|
||||||
this.edgeState.absolutePoints.length >= 2
|
|
||||||
) {
|
|
||||||
const tmp2 = this.edgeState.absolutePoints[
|
const tmp2 = this.edgeState.absolutePoints[
|
||||||
this.edgeState.absolutePoints.length - 2
|
this.edgeState.absolutePoints.length - 2
|
||||||
];
|
];
|
||||||
|
@ -1476,10 +1436,7 @@ class ConnectionHandler extends EventSource {
|
||||||
me.consume();
|
me.consume();
|
||||||
} else if (!this.isEnabled() || !this.graph.isEnabled()) {
|
} else if (!this.isEnabled() || !this.graph.isEnabled()) {
|
||||||
this.constraintHandler.reset();
|
this.constraintHandler.reset();
|
||||||
} else if (
|
} else if (this.previous !== this.currentState && this.edgeState == null) {
|
||||||
this.previous !== this.currentState &&
|
|
||||||
this.edgeState == null
|
|
||||||
) {
|
|
||||||
this.destroyIcons();
|
this.destroyIcons();
|
||||||
|
|
||||||
// Sets the cursor on the current shape
|
// Sets the cursor on the current shape
|
||||||
|
@ -1507,18 +1464,13 @@ class ConnectionHandler extends EventSource {
|
||||||
me.consume();
|
me.consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (!this.graph.isMouseDown && this.currentState != null && this.icons != null) {
|
||||||
!this.graph.isMouseDown &&
|
|
||||||
this.currentState != null &&
|
|
||||||
this.icons != null
|
|
||||||
) {
|
|
||||||
let hitsIcon = false;
|
let hitsIcon = false;
|
||||||
const target = me.getSource();
|
const target = me.getSource();
|
||||||
|
|
||||||
for (let i = 0; i < this.icons.length && !hitsIcon; i += 1) {
|
for (let i = 0; i < this.icons.length && !hitsIcon; i += 1) {
|
||||||
hitsIcon =
|
hitsIcon =
|
||||||
target === this.icons[i].node ||
|
target === this.icons[i].node || target.parentNode === this.icons[i].node;
|
||||||
target.parentNode === this.icons[i].node;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hitsIcon) {
|
if (!hitsIcon) {
|
||||||
|
@ -1535,8 +1487,7 @@ class ConnectionHandler extends EventSource {
|
||||||
*
|
*
|
||||||
* Updates <edgeState>.
|
* Updates <edgeState>.
|
||||||
*/
|
*/
|
||||||
updateEdgeState(current: CellState,
|
updateEdgeState(current: CellState, constraint: CellState): void {
|
||||||
constraint: CellState): void {
|
|
||||||
// TODO: Use generic method for writing constraint to style
|
// TODO: Use generic method for writing constraint to style
|
||||||
if (this.sourceConstraint != null && this.sourceConstraint.point != null) {
|
if (this.sourceConstraint != null && this.sourceConstraint.point != null) {
|
||||||
this.edgeState.style.exitX = this.sourceConstraint.point.x;
|
this.edgeState.style.exitX = this.sourceConstraint.point.x;
|
||||||
|
@ -1551,10 +1502,7 @@ class ConnectionHandler extends EventSource {
|
||||||
delete this.edgeState.style.entryY;
|
delete this.edgeState.style.entryY;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.edgeState.absolutePoints = [
|
this.edgeState.absolutePoints = [null, this.currentState != null ? null : current];
|
||||||
null,
|
|
||||||
this.currentState != null ? null : current,
|
|
||||||
];
|
|
||||||
this.graph.view.updateFixedTerminalPoint(
|
this.graph.view.updateFixedTerminalPoint(
|
||||||
this.edgeState,
|
this.edgeState,
|
||||||
this.previous,
|
this.previous,
|
||||||
|
@ -1616,8 +1564,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* state - <mxCellState> that represents the target cell state.
|
* state - <mxCellState> that represents the target cell state.
|
||||||
* me - <mxMouseEvent> that represents the mouse move.
|
* me - <mxMouseEvent> that represents the mouse move.
|
||||||
*/
|
*/
|
||||||
getTargetPerimeterPoint(state: CellState,
|
getTargetPerimeterPoint(state: CellState, me: MouseEvent): Point {
|
||||||
me: MouseEvent): Point {
|
|
||||||
let result = null;
|
let result = null;
|
||||||
const { view } = state;
|
const { view } = state;
|
||||||
const targetPerimeter = view.getPerimeterFunction(state);
|
const targetPerimeter = view.getPerimeterFunction(state);
|
||||||
|
@ -1656,9 +1603,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* next - <mxPoint> that represents the next point along the previewed edge.
|
* next - <mxPoint> that represents the next point along the previewed edge.
|
||||||
* me - <mxMouseEvent> that represents the mouse move.
|
* me - <mxMouseEvent> that represents the mouse move.
|
||||||
*/
|
*/
|
||||||
getSourcePerimeterPoint(state: CellState,
|
getSourcePerimeterPoint(state: CellState, next: Point, me: MouseEvent): Point {
|
||||||
next: Point,
|
|
||||||
me: MouseEvent): Point {
|
|
||||||
let result = null;
|
let result = null;
|
||||||
const { view } = state;
|
const { view } = state;
|
||||||
const sourcePerimeter = view.getPerimeterFunction(state);
|
const sourcePerimeter = view.getPerimeterFunction(state);
|
||||||
|
@ -1677,12 +1622,7 @@ class ConnectionHandler extends EventSource {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let tmp = sourcePerimeter(
|
let tmp = sourcePerimeter(view.getPerimeterBounds(state), state, next, false);
|
||||||
view.getPerimeterBounds(state),
|
|
||||||
state,
|
|
||||||
next,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
if (theta !== 0) {
|
if (theta !== 0) {
|
||||||
|
@ -1715,9 +1655,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* icons - Array of currently displayed icons.
|
* icons - Array of currently displayed icons.
|
||||||
* me - <mxMouseEvent> that contains the mouse event.
|
* me - <mxMouseEvent> that contains the mouse event.
|
||||||
*/
|
*/
|
||||||
updateIcons(state: CellState,
|
updateIcons(state: CellState, icons: string[], me: InternalMouseEvent): void {
|
||||||
icons: string[],
|
|
||||||
me: InternalMouseEvent): void {
|
|
||||||
// empty
|
// empty
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1739,11 +1677,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* Adds the waypoint for the given event to <waypoints>.
|
* Adds the waypoint for the given event to <waypoints>.
|
||||||
*/
|
*/
|
||||||
addWaypointForEvent(me: InternalMouseEvent): void {
|
addWaypointForEvent(me: InternalMouseEvent): void {
|
||||||
let point = convertPoint(
|
let point = convertPoint(this.graph.container, me.getX(), me.getY());
|
||||||
this.graph.container,
|
|
||||||
me.getX(),
|
|
||||||
me.getY()
|
|
||||||
);
|
|
||||||
const dx = Math.abs(point.x - this.first.x);
|
const dx = Math.abs(point.x - this.first.x);
|
||||||
const dy = Math.abs(point.y - this.first.y);
|
const dy = Math.abs(point.y - this.first.y);
|
||||||
const addPoint =
|
const addPoint =
|
||||||
|
@ -1790,8 +1724,7 @@ class ConnectionHandler extends EventSource {
|
||||||
*
|
*
|
||||||
* Handles the event by inserting the new connection.
|
* Handles the event by inserting the new connection.
|
||||||
*/
|
*/
|
||||||
mouseUp(sender: InternalMouseEvent,
|
mouseUp(sender: InternalMouseEvent, me: InternalMouseEvent): void {
|
||||||
me: InternalMouseEvent): void {
|
|
||||||
if (!me.isConsumed() && this.isConnecting()) {
|
if (!me.isConsumed() && this.isConnecting()) {
|
||||||
if (this.waypointsEnabled && !this.isStopEvent(me)) {
|
if (this.waypointsEnabled && !this.isStopEvent(me)) {
|
||||||
this.addWaypointForEvent(me);
|
this.addWaypointForEvent(me);
|
||||||
|
@ -1907,7 +1840,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
updatePreview(valid: boolean): void {
|
updatePreview(valid: boolean): void {
|
||||||
this.shape.strokewidth = this.getEdgeWidth(valid);
|
this.shape.strokeWidth = this.getEdgeWidth(valid);
|
||||||
this.shape.stroke = this.getEdgeColor(valid);
|
this.shape.stroke = this.getEdgeColor(valid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1955,15 +1888,8 @@ class ConnectionHandler extends EventSource {
|
||||||
* dropTarget - <mxCell> that represents the cell under the mouse when it was
|
* dropTarget - <mxCell> that represents the cell under the mouse when it was
|
||||||
* released.
|
* released.
|
||||||
*/
|
*/
|
||||||
connect(source: Cell,
|
connect(source: Cell, target: Cell, evt: MouseEvent, dropTarget: Cell): void {
|
||||||
target: Cell,
|
if (target != null || this.isCreateTarget(evt) || this.graph.allowDanglingEdges) {
|
||||||
evt: MouseEvent,
|
|
||||||
dropTarget: Cell): void {
|
|
||||||
if (
|
|
||||||
target != null ||
|
|
||||||
this.isCreateTarget(evt) ||
|
|
||||||
this.graph.allowDanglingEdges
|
|
||||||
) {
|
|
||||||
// Uses the common parent of source and target or
|
// Uses the common parent of source and target or
|
||||||
// the default parent to insert the edge
|
// the default parent to insert the edge
|
||||||
const model = this.graph.getModel();
|
const model = this.graph.getModel();
|
||||||
|
@ -2036,12 +1962,7 @@ class ConnectionHandler extends EventSource {
|
||||||
|
|
||||||
if (edge != null) {
|
if (edge != null) {
|
||||||
// Updates the connection constraints
|
// Updates the connection constraints
|
||||||
this.graph.setConnectionConstraint(
|
this.graph.setConnectionConstraint(edge, source, true, this.sourceConstraint);
|
||||||
edge,
|
|
||||||
source,
|
|
||||||
true,
|
|
||||||
this.sourceConstraint
|
|
||||||
);
|
|
||||||
this.graph.setConnectionConstraint(
|
this.graph.setConnectionConstraint(
|
||||||
edge,
|
edge,
|
||||||
target,
|
target,
|
||||||
|
@ -2070,11 +1991,7 @@ class ConnectionHandler extends EventSource {
|
||||||
tmp = tmp.getParent();
|
tmp = tmp.getParent();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (tmp != null && tmp.parent != null && tmp.parent === edge.parent) {
|
||||||
tmp != null &&
|
|
||||||
tmp.parent != null &&
|
|
||||||
tmp.parent === edge.parent
|
|
||||||
) {
|
|
||||||
model.add(parent, edge, tmp.parent.getIndex(tmp));
|
model.add(parent, edge, tmp.parent.getIndex(tmp));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2110,10 +2027,7 @@ class ConnectionHandler extends EventSource {
|
||||||
this.originalPoint.x / s - t.x,
|
this.originalPoint.x / s - t.x,
|
||||||
this.originalPoint.y / s - t.y
|
this.originalPoint.y / s - t.y
|
||||||
)
|
)
|
||||||
: new Point(
|
: new Point(this.currentPoint.x / s - t.x, this.currentPoint.y / s - t.y);
|
||||||
this.currentPoint.x / s - t.x,
|
|
||||||
this.currentPoint.y / s - t.y
|
|
||||||
);
|
|
||||||
pt.x -= this.graph.panDx / this.graph.view.scale;
|
pt.x -= this.graph.panDx / this.graph.view.scale;
|
||||||
pt.y -= this.graph.panDy / this.graph.view.scale;
|
pt.y -= this.graph.panDy / this.graph.view.scale;
|
||||||
geo.setTerminalPoint(pt, false);
|
geo.setTerminalPoint(pt, false);
|
||||||
|
@ -2154,8 +2068,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* Selects the given edge after adding a new connection. The target argument
|
* Selects the given edge after adding a new connection. The target argument
|
||||||
* contains the target vertex if one has been inserted.
|
* contains the target vertex if one has been inserted.
|
||||||
*/
|
*/
|
||||||
selectCells(edge: Cell,
|
selectCells(edge: Cell, target: Cell): void {
|
||||||
target: Cell): void {
|
|
||||||
this.graph.setSelectionCell(edge);
|
this.graph.setSelectionCell(edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2166,13 +2079,14 @@ class ConnectionHandler extends EventSource {
|
||||||
* implementation does only use <createEdge> if <factoryMethod> is defined,
|
* implementation does only use <createEdge> if <factoryMethod> is defined,
|
||||||
* otherwise <mxGraph.insertEdge> will be used.
|
* otherwise <mxGraph.insertEdge> will be used.
|
||||||
*/
|
*/
|
||||||
insertEdge(parent: Cell,
|
insertEdge(
|
||||||
id: string,
|
parent: Cell,
|
||||||
value: any,
|
id: string,
|
||||||
source: Cell,
|
value: any,
|
||||||
target: Cell,
|
source: Cell,
|
||||||
style: string): Cell {
|
target: Cell,
|
||||||
|
style: string
|
||||||
|
): Cell {
|
||||||
if (this.factoryMethod == null) {
|
if (this.factoryMethod == null) {
|
||||||
return this.graph.insertEdge(parent, id, value, source, target, style);
|
return this.graph.insertEdge(parent, id, value, source, target, style);
|
||||||
}
|
}
|
||||||
|
@ -2194,8 +2108,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* evt - Mousedown event of the connect gesture.
|
* evt - Mousedown event of the connect gesture.
|
||||||
* source - <mxCell> that represents the source terminal.
|
* source - <mxCell> that represents the source terminal.
|
||||||
*/
|
*/
|
||||||
createTargetVertex(evt: MouseEvent,
|
createTargetVertex(evt: MouseEvent, source: Cell): Cell {
|
||||||
source: Cell): Cell {
|
|
||||||
// Uses the first non-relative source
|
// Uses the first non-relative source
|
||||||
let geo = source.getGeometry();
|
let geo = source.getGeometry();
|
||||||
|
|
||||||
|
@ -2267,10 +2180,7 @@ class ConnectionHandler extends EventSource {
|
||||||
* target - <mxCell> that represents the target terminal.
|
* target - <mxCell> that represents the target terminal.
|
||||||
* style - Optional style from the preview edge.
|
* style - Optional style from the preview edge.
|
||||||
*/
|
*/
|
||||||
createEdge(value?: any,
|
createEdge(value?: any, source?: Cell, target?: Cell, style?: string): Cell {
|
||||||
source?: Cell,
|
|
||||||
target?: Cell,
|
|
||||||
style?: string): Cell {
|
|
||||||
let edge = null;
|
let edge = null;
|
||||||
|
|
||||||
// Creates a new edge using the factoryMethod
|
// Creates a new edge using the factoryMethod
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* Updated to ES9 syntax by David Morrissey 2021
|
* Updated to ES9 syntax by David Morrissey 2021
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import Image from '../image/Image';
|
import Image from '../image/ImageBox';
|
||||||
import mxClient from '../../mxClient';
|
import mxClient from '../../mxClient';
|
||||||
import {
|
import {
|
||||||
DEFAULT_VALID_COLOR,
|
DEFAULT_VALID_COLOR,
|
||||||
|
@ -240,11 +240,7 @@ class ConstraintHandler {
|
||||||
this.reset();
|
this.reset();
|
||||||
};
|
};
|
||||||
|
|
||||||
InternalEvent.addListener(
|
InternalEvent.addListener(this.graph.container, 'mouseleave', this.resetHandler);
|
||||||
this.graph.container,
|
|
||||||
'mouseleave',
|
|
||||||
this.resetHandler
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const tol = this.getTolerance(me);
|
const tol = this.getTolerance(me);
|
||||||
|
@ -296,12 +292,7 @@ class ConstraintHandler {
|
||||||
if (
|
if (
|
||||||
(this.intersects(this.focusIcons[i], mouse, source, existingEdge) ||
|
(this.intersects(this.focusIcons[i], mouse, source, existingEdge) ||
|
||||||
(point != null &&
|
(point != null &&
|
||||||
this.intersects(
|
this.intersects(this.focusIcons[i], grid, source, existingEdge))) &&
|
||||||
this.focusIcons[i],
|
|
||||||
grid,
|
|
||||||
source,
|
|
||||||
existingEdge
|
|
||||||
))) &&
|
|
||||||
(minDistSq == null || tmp < minDistSq)
|
(minDistSq == null || tmp < minDistSq)
|
||||||
) {
|
) {
|
||||||
this.currentConstraint = this.constraints[i];
|
this.currentConstraint = this.constraints[i];
|
||||||
|
@ -358,12 +349,7 @@ class ConstraintHandler {
|
||||||
) {
|
) {
|
||||||
const state = this.graph.view.getState(this.currentFocus.cell);
|
const state = this.graph.view.getState(this.currentFocus.cell);
|
||||||
this.currentFocus = state;
|
this.currentFocus = state;
|
||||||
this.currentFocusArea = new Rectangle(
|
this.currentFocusArea = new Rectangle(state.x, state.y, state.width, state.height);
|
||||||
state.x,
|
|
||||||
state.y,
|
|
||||||
state.width,
|
|
||||||
state.height
|
|
||||||
);
|
|
||||||
|
|
||||||
for (let i = 0; i < this.constraints.length; i += 1) {
|
for (let i = 0; i < this.constraints.length; i += 1) {
|
||||||
const cp = this.graph.getConnectionPoint(state, this.constraints[i]);
|
const cp = this.graph.getConnectionPoint(state, this.constraints[i]);
|
||||||
|
@ -391,9 +377,7 @@ class ConstraintHandler {
|
||||||
// setFocus(me: mxMouseEvent, state: mxCellState, source: mxCell): void;
|
// setFocus(me: mxMouseEvent, state: mxCellState, source: mxCell): void;
|
||||||
setFocus(me, state, source) {
|
setFocus(me, state, source) {
|
||||||
this.constraints =
|
this.constraints =
|
||||||
state != null &&
|
state != null && !this.isStateIgnored(state, source) && state.cell.isConnectable()
|
||||||
!this.isStateIgnored(state, source) &&
|
|
||||||
state.cell.isConnectable()
|
|
||||||
? this.isEnabled()
|
? this.isEnabled()
|
||||||
? this.graph.getAllConnectionConstraints(state, source) || []
|
? this.graph.getAllConnectionConstraints(state, source) || []
|
||||||
: []
|
: []
|
||||||
|
@ -402,12 +386,7 @@ class ConstraintHandler {
|
||||||
// Only uses cells which have constraints
|
// Only uses cells which have constraints
|
||||||
if (this.constraints != null) {
|
if (this.constraints != null) {
|
||||||
this.currentFocus = state;
|
this.currentFocus = state;
|
||||||
this.currentFocusArea = new Rectangle(
|
this.currentFocusArea = new Rectangle(state.x, state.y, state.width, state.height);
|
||||||
state.x,
|
|
||||||
state.y,
|
|
||||||
state.width,
|
|
||||||
state.height
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.focusIcons != null) {
|
if (this.focusIcons != null) {
|
||||||
for (let i = 0; i < this.focusIcons.length; i += 1) {
|
for (let i = 0; i < this.focusIcons.length; i += 1) {
|
||||||
|
@ -440,10 +419,7 @@ class ConstraintHandler {
|
||||||
|
|
||||||
// Move the icon behind all other overlays
|
// Move the icon behind all other overlays
|
||||||
if (icon.node.previousSibling != null) {
|
if (icon.node.previousSibling != null) {
|
||||||
icon.node.parentNode.insertBefore(
|
icon.node.parentNode.insertBefore(icon.node, icon.node.parentNode.firstChild);
|
||||||
icon.node,
|
|
||||||
icon.node.parentNode.firstChild
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getState = () => {
|
const getState = () => {
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type EventProperties = Record<string, any>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxEventObject
|
* Class: mxEventObject
|
||||||
*
|
*
|
||||||
|
@ -29,9 +31,9 @@
|
||||||
* (end)
|
* (end)
|
||||||
*/
|
*/
|
||||||
class EventObject {
|
class EventObject {
|
||||||
constructor(name: string, ...args: any[]) {
|
constructor(name = '', ...args: any[]) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.properties = [];
|
this.properties = {};
|
||||||
|
|
||||||
if (!!args[0] && args[0].constructor === Object) {
|
if (!!args[0] && args[0].constructor === Object) {
|
||||||
// A literal object ({})
|
// A literal object ({})
|
||||||
|
@ -41,7 +43,7 @@ class EventObject {
|
||||||
} else {
|
} else {
|
||||||
// two-values [key, value, key, value, ...]
|
// two-values [key, value, key, value, ...]
|
||||||
for (let i = 0; i < args.length; i += 2) {
|
for (let i = 0; i < args.length; i += 2) {
|
||||||
if (args[i + 1] != null) {
|
if (args[i + 1] !== null) {
|
||||||
this.properties[args[i]] = args[i + 1];
|
this.properties[args[i]] = args[i + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,14 +55,14 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Holds the name.
|
* Holds the name.
|
||||||
*/
|
*/
|
||||||
name: string = '';
|
name: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: properties
|
* Variable: properties
|
||||||
*
|
*
|
||||||
* Holds the properties as an associative array.
|
* Holds the properties as an associative array.
|
||||||
*/
|
*/
|
||||||
properties: any = null;
|
properties: EventProperties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: consumed
|
* Variable: consumed
|
||||||
|
@ -74,7 +76,7 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns <name>.
|
* Returns <name>.
|
||||||
*/
|
*/
|
||||||
getName(): string {
|
getName() {
|
||||||
return this.name;
|
return this.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +85,7 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns <properties>.
|
* Returns <properties>.
|
||||||
*/
|
*/
|
||||||
getProperties(): any {
|
getProperties() {
|
||||||
return this.properties;
|
return this.properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns the property for the given key.
|
* Returns the property for the given key.
|
||||||
*/
|
*/
|
||||||
getProperty(key: string): any {
|
getProperty(key: string) {
|
||||||
return this.properties[key];
|
return this.properties[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,7 +103,7 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Returns true if the event has been consumed.
|
* Returns true if the event has been consumed.
|
||||||
*/
|
*/
|
||||||
isConsumed(): boolean {
|
isConsumed() {
|
||||||
return this.consumed;
|
return this.consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,7 +112,7 @@ class EventObject {
|
||||||
*
|
*
|
||||||
* Consumes the event.
|
* Consumes the event.
|
||||||
*/
|
*/
|
||||||
consume(): void {
|
consume() {
|
||||||
this.consumed = true;
|
this.consumed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,11 @@
|
||||||
|
|
||||||
import EventObject from './EventObject';
|
import EventObject from './EventObject';
|
||||||
|
|
||||||
|
type EventListener = {
|
||||||
|
funct: Function;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxEventSource
|
* Class: mxEventSource
|
||||||
*
|
*
|
||||||
|
@ -30,7 +35,7 @@ import EventObject from './EventObject';
|
||||||
* Constructs a new event source.
|
* Constructs a new event source.
|
||||||
*/
|
*/
|
||||||
class EventSource {
|
class EventSource {
|
||||||
constructor(eventSource: EventSource | null=null) {
|
constructor(eventSource: EventSource | null = null) {
|
||||||
this.eventSource = eventSource;
|
this.eventSource = eventSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,14 +46,14 @@ class EventSource {
|
||||||
* contains the event name followed by the respective listener for each
|
* contains the event name followed by the respective listener for each
|
||||||
* registered listener.
|
* registered listener.
|
||||||
*/
|
*/
|
||||||
eventListeners: ({funct: Function, name: string})[] = [];
|
eventListeners: EventListener[] = [];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: eventsEnabled
|
* Variable: eventsEnabled
|
||||||
*
|
*
|
||||||
* Specifies if events can be fired. Default is true.
|
* Specifies if events can be fired. Default is true.
|
||||||
*/
|
*/
|
||||||
eventsEnabled: boolean = true;
|
eventsEnabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: eventSource
|
* Variable: eventSource
|
||||||
|
@ -62,7 +67,7 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* Returns <eventsEnabled>.
|
* Returns <eventsEnabled>.
|
||||||
*/
|
*/
|
||||||
isEventsEnabled(): boolean {
|
isEventsEnabled() {
|
||||||
return this.eventsEnabled;
|
return this.eventsEnabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +76,7 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* Sets <eventsEnabled>.
|
* Sets <eventsEnabled>.
|
||||||
*/
|
*/
|
||||||
setEventsEnabled(value: boolean): void {
|
setEventsEnabled(value: boolean) {
|
||||||
this.eventsEnabled = value;
|
this.eventsEnabled = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +85,7 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* Returns <eventSource>.
|
* Returns <eventSource>.
|
||||||
*/
|
*/
|
||||||
getEventSource(): EventSource | null {
|
getEventSource() {
|
||||||
return this.eventSource;
|
return this.eventSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,7 +94,7 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* Sets <eventSource>.
|
* Sets <eventSource>.
|
||||||
*/
|
*/
|
||||||
setEventSource(value: EventSource): void {
|
setEventSource(value: EventSource) {
|
||||||
this.eventSource = value;
|
this.eventSource = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,13 +106,8 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* The parameters of the listener are the sender and an <mxEventObject>.
|
* The parameters of the listener are the sender and an <mxEventObject>.
|
||||||
*/
|
*/
|
||||||
addListener(name: string,
|
addListener(name: string, funct: (...args: any[]) => any) {
|
||||||
funct: (...args: any[]) => any): void {
|
this.eventListeners.push({ name, funct });
|
||||||
|
|
||||||
if (this.eventListeners == null) {
|
|
||||||
this.eventListeners = [];
|
|
||||||
}
|
|
||||||
this.eventListeners.push({name, funct});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -115,16 +115,14 @@ class EventSource {
|
||||||
*
|
*
|
||||||
* Removes all occurrences of the given listener from <eventListeners>.
|
* Removes all occurrences of the given listener from <eventListeners>.
|
||||||
*/
|
*/
|
||||||
removeListener(funct: (...args: any[]) => any): void {
|
removeListener(funct: (...args: any[]) => any) {
|
||||||
if (this.eventListeners != null) {
|
let i = 0;
|
||||||
let i = 0;
|
|
||||||
|
|
||||||
while (i < this.eventListeners.length) {
|
while (i < this.eventListeners.length) {
|
||||||
if (this.eventListeners[i].funct === funct) {
|
if (this.eventListeners[i].funct === funct) {
|
||||||
this.eventListeners.splice(i, 1);
|
this.eventListeners.splice(i, 1);
|
||||||
} else {
|
} else {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,21 +146,21 @@ class EventSource {
|
||||||
* sender - Optional sender to be passed to the listener. Default value is
|
* sender - Optional sender to be passed to the listener. Default value is
|
||||||
* the return value of <getEventSource>.
|
* the return value of <getEventSource>.
|
||||||
*/
|
*/
|
||||||
fireEvent(evt: EventObject, sender: any = null): void {
|
fireEvent(evt: EventObject, sender: any = null) {
|
||||||
if (this.eventListeners != null && this.isEventsEnabled()) {
|
if (this.isEventsEnabled()) {
|
||||||
if (evt == null) {
|
if (!evt) {
|
||||||
evt = new EventObject('');
|
evt = new EventObject('');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sender == null) {
|
if (!sender) {
|
||||||
sender = this.getEventSource();
|
sender = this.getEventSource();
|
||||||
}
|
}
|
||||||
if (sender == null) {
|
if (!sender) {
|
||||||
sender = this;
|
sender = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const eventListener of this.eventListeners) {
|
for (const eventListener of this.eventListeners) {
|
||||||
if (eventListener.name == null || eventListener.name === evt.getName()) {
|
if (eventListener.name === null || eventListener.name === evt.getName()) {
|
||||||
eventListener.funct.apply(this, [sender, evt]);
|
eventListener.funct.apply(this, [sender, evt]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,13 @@
|
||||||
* Updated to ES9 syntax by David Morrissey 2021
|
* Updated to ES9 syntax by David Morrissey 2021
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import {getClientX, getClientY, getSource, isMouseEvent, isPopupTrigger} from '../../util/EventUtils';
|
import {
|
||||||
|
getClientX,
|
||||||
|
getClientY,
|
||||||
|
getSource,
|
||||||
|
isMouseEvent,
|
||||||
|
isPopupTrigger,
|
||||||
|
} from '../../util/EventUtils';
|
||||||
import { isAncestorNode } from '../../util/DomUtils';
|
import { isAncestorNode } from '../../util/DomUtils';
|
||||||
import CellState from '../cell/datatypes/CellState';
|
import CellState from '../cell/datatypes/CellState';
|
||||||
import Shape from '../geometry/shape/Shape';
|
import Shape from '../geometry/shape/Shape';
|
||||||
|
@ -119,11 +125,8 @@ class InternalMouseEvent {
|
||||||
*
|
*
|
||||||
* Returns true if the given <mxShape> is the source of <evt>.
|
* Returns true if the given <mxShape> is the source of <evt>.
|
||||||
*/
|
*/
|
||||||
isSource(shape: Shape): boolean {
|
isSource(shape: Shape) {
|
||||||
if (shape != null) {
|
return shape ? isAncestorNode(shape.node, this.getSource()) : false;
|
||||||
return isAncestorNode(shape.node, this.getSource());
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +134,7 @@ class InternalMouseEvent {
|
||||||
*
|
*
|
||||||
* Returns <evt.clientX>.
|
* Returns <evt.clientX>.
|
||||||
*/
|
*/
|
||||||
getX(): number {
|
getX() {
|
||||||
return getClientX(this.getEvent());
|
return getClientX(this.getEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,7 +143,7 @@ class InternalMouseEvent {
|
||||||
*
|
*
|
||||||
* Returns <evt.clientY>.
|
* Returns <evt.clientY>.
|
||||||
*/
|
*/
|
||||||
getY(): number {
|
getY() {
|
||||||
return getClientY(this.getEvent());
|
return getClientY(this.getEvent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import Image from "../image/Image";
|
import Image from '../image/ImageBox';
|
||||||
import mxClient from "../../mxClient";
|
import mxClient from '../../mxClient';
|
||||||
import Graph from "../Graph";
|
import Graph from '../Graph';
|
||||||
import CellState from "../cell/datatypes/CellState";
|
import CellState from '../cell/datatypes/CellState';
|
||||||
import Cell from "../cell/datatypes/Cell";
|
import Cell from '../cell/datatypes/Cell';
|
||||||
import CellArray from "../cell/datatypes/CellArray";
|
import CellArray from '../cell/datatypes/CellArray';
|
||||||
import EventObject from "../event/EventObject";
|
import EventObject from '../event/EventObject';
|
||||||
import InternalEvent from "../event/InternalEvent";
|
import InternalEvent from '../event/InternalEvent';
|
||||||
import Geometry from "../geometry/Geometry";
|
import Geometry from '../geometry/Geometry';
|
||||||
import {getValue, toRadians} from "../../util/Utils";
|
import { getValue, toRadians } from '../../util/Utils';
|
||||||
import Rectangle from "../geometry/Rectangle";
|
import Rectangle from '../geometry/Rectangle';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GraphFoldingOptions
|
* GraphFoldingOptions
|
||||||
|
@ -25,21 +25,22 @@ import Rectangle from "../geometry/Rectangle";
|
||||||
* a cell is first collapsed.
|
* a cell is first collapsed.
|
||||||
*/
|
*/
|
||||||
type GraphFoldingOptions = {
|
type GraphFoldingOptions = {
|
||||||
foldingEnabled: boolean,
|
foldingEnabled: boolean;
|
||||||
collapsedImage: Image,
|
collapsedImage: Image;
|
||||||
expandedImage: Image,
|
expandedImage: Image;
|
||||||
collapseToPreferredSize: boolean,
|
collapseToPreferredSize: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
class GraphFolding {
|
class GraphFolding {
|
||||||
constructor(graph: Graph,
|
constructor(
|
||||||
options: GraphFoldingOptions = {
|
graph: Graph,
|
||||||
foldingEnabled: true,
|
options: GraphFoldingOptions = {
|
||||||
collapsedImage: new Image(`${mxClient.imageBasePath}/collapsed.gif`, 9, 9),
|
foldingEnabled: true,
|
||||||
expandedImage: new Image(`${mxClient.imageBasePath}/expanded.gif`, 9, 9),
|
collapsedImage: new Image(`${mxClient.imageBasePath}/collapsed.gif`, 9, 9),
|
||||||
collapseToPreferredSize: true,
|
expandedImage: new Image(`${mxClient.imageBasePath}/expanded.gif`, 9, 9),
|
||||||
}) {
|
collapseToPreferredSize: true,
|
||||||
|
}
|
||||||
|
) {
|
||||||
this.graph = graph;
|
this.graph = graph;
|
||||||
this.options = options;
|
this.options = options;
|
||||||
}
|
}
|
||||||
|
@ -53,8 +54,7 @@ class GraphFolding {
|
||||||
* the tooltip.
|
* the tooltip.
|
||||||
* @default 'collapse-expand'
|
* @default 'collapse-expand'
|
||||||
*/
|
*/
|
||||||
collapseExpandResource: string =
|
collapseExpandResource: string = mxClient.language != 'none' ? 'collapse-expand' : '';
|
||||||
mxClient.language != 'none' ? 'collapse-expand' : '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -64,10 +64,7 @@ class GraphFolding {
|
||||||
/**
|
/**
|
||||||
* Returns the cells which are movable in the given array of cells.
|
* Returns the cells which are movable in the given array of cells.
|
||||||
*/
|
*/
|
||||||
getFoldableCells(
|
getFoldableCells(cells: CellArray, collapse: boolean = false): CellArray | null {
|
||||||
cells: CellArray,
|
|
||||||
collapse: boolean = false
|
|
||||||
): CellArray | null {
|
|
||||||
return this.graph.model.filterCells(cells, (cell: Cell) => {
|
return this.graph.model.filterCells(cells, (cell: Cell) => {
|
||||||
return this.isCellFoldable(cell, collapse);
|
return this.isCellFoldable(cell, collapse);
|
||||||
});
|
});
|
||||||
|
@ -272,12 +269,7 @@ class GraphFolding {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
geo.alternateBounds = new Rectangle(
|
geo.alternateBounds = new Rectangle(0, 0, bounds.width, bounds.height);
|
||||||
0,
|
|
||||||
0,
|
|
||||||
bounds.width,
|
|
||||||
bounds.height
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (geo.alternateBounds != null) {
|
if (geo.alternateBounds != null) {
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
|
|
||||||
import Point from './Point';
|
import Point from './Point';
|
||||||
import Rectangle from './Rectangle';
|
import Rectangle from './Rectangle';
|
||||||
import utils, { equalPoints, getRotatedPoint, toRadians } from '../../util/Utils';
|
import { equalPoints, getRotatedPoint, toRadians } from '../../util/Utils';
|
||||||
import { clone } from '../../util/CloneUtils';
|
import { clone } from '../../util/CloneUtils';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,12 +74,7 @@ import { clone } from '../../util/CloneUtils';
|
||||||
* defines the absolute offset for the label inside the vertex or group.
|
* defines the absolute offset for the label inside the vertex or group.
|
||||||
*/
|
*/
|
||||||
class Geometry extends Rectangle {
|
class Geometry extends Rectangle {
|
||||||
constructor(
|
constructor(x = 0, y = 0, width = 0, height = 0) {
|
||||||
x: number = 0,
|
|
||||||
y: number = 0,
|
|
||||||
width: number = 0,
|
|
||||||
height: number = 0
|
|
||||||
) {
|
|
||||||
super(x, y, width, height);
|
super(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,9 @@
|
||||||
*/
|
*/
|
||||||
import Rectangle from '../Rectangle';
|
import Rectangle from '../Rectangle';
|
||||||
import Shape from './Shape';
|
import Shape from './Shape';
|
||||||
import mxSvgCanvas2D from '../../../util/canvas/mxSvgCanvas2D';
|
import SvgCanvas2D from '../../../util/canvas/SvgCanvas2D';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
import { NONE } from 'packages/core/src/util/Constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement an actor shape. If a custom shape with one
|
* Extends {@link Shape} to implement an actor shape. If a custom shape with one
|
||||||
|
@ -34,27 +36,21 @@ import mxSvgCanvas2D from '../../../util/canvas/mxSvgCanvas2D';
|
||||||
class Actor extends Shape {
|
class Actor extends Shape {
|
||||||
constructor(
|
constructor(
|
||||||
bounds: Rectangle | null = null,
|
bounds: Rectangle | null = null,
|
||||||
fill: string | null = null,
|
fill: ColorValue = NONE,
|
||||||
stroke: string | null = null,
|
stroke: ColorValue = NONE,
|
||||||
strokewidth: number = 1
|
strokeWidth: number = 1
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirects to redrawPath for subclasses to work.
|
* Redirects to redrawPath for subclasses to work.
|
||||||
*/
|
*/
|
||||||
paintVertexShape(
|
paintVertexShape(c: SvgCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
c.translate(x, y);
|
c.translate(x, y);
|
||||||
c.begin();
|
c.begin();
|
||||||
this.redrawPath(c, x, y, w, h);
|
this.redrawPath(c, x, y, w, h);
|
||||||
|
@ -64,13 +60,7 @@ class Actor extends Shape {
|
||||||
/**
|
/**
|
||||||
* Draws the path for this shape.
|
* Draws the path for this shape.
|
||||||
*/
|
*/
|
||||||
redrawPath(
|
redrawPath(c: SvgCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
const width = w / 3;
|
const width = w / 3;
|
||||||
c.moveTo(0, h);
|
c.moveTo(0, h);
|
||||||
c.curveTo(0, (3 * h) / 5, 0, (2 * h) / 5, w / 2, (2 * h) / 5);
|
c.curveTo(0, (3 * h) / 5, 0, (2 * h) / 5, w / 2, (2 * h) / 5);
|
||||||
|
|
|
@ -8,7 +8,6 @@ import Rectangle from '../Rectangle';
|
||||||
import {
|
import {
|
||||||
getBoundingBox,
|
getBoundingBox,
|
||||||
getDirectedBounds,
|
getDirectedBounds,
|
||||||
getValue,
|
|
||||||
isNotNullish,
|
isNotNullish,
|
||||||
mod,
|
mod,
|
||||||
} from '../../../util/Utils';
|
} from '../../../util/Utils';
|
||||||
|
@ -24,30 +23,22 @@ import {
|
||||||
SHADOW_OFFSET_Y,
|
SHADOW_OFFSET_Y,
|
||||||
} from '../../../util/Constants';
|
} from '../../../util/Constants';
|
||||||
import Point from '../Point';
|
import Point from '../Point';
|
||||||
import mxSvgCanvas2D from '../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from 'packages/core/src/util/canvas/AbstractCanvas2D';
|
||||||
|
import SvgCanvas2D from '../../../util/canvas/SvgCanvas2D';
|
||||||
import InternalEvent from '../../event/InternalEvent';
|
import InternalEvent from '../../event/InternalEvent';
|
||||||
import mxClient from '../../../mxClient';
|
import mxClient from '../../../mxClient';
|
||||||
import CellState from '../../cell/datatypes/CellState';
|
import CellState from '../../cell/datatypes/CellState';
|
||||||
import StencilShape from './node/StencilShape';
|
import StencilShape from './node/StencilShape';
|
||||||
import CellOverlay from '../../cell/CellOverlay';
|
import CellOverlay from '../../cell/CellOverlay';
|
||||||
|
import ImageBox from '../../image/ImageBox';
|
||||||
|
|
||||||
import type {
|
import type {
|
||||||
|
ArrowType,
|
||||||
CellStateStyles,
|
CellStateStyles,
|
||||||
ColorValue,
|
ColorValue,
|
||||||
DirectionValue,
|
DirectionValue,
|
||||||
GradientMap,
|
GradientMap,
|
||||||
} from '../../../types';
|
} from '../../../types';
|
||||||
import Image from '../../image/Image';
|
|
||||||
|
|
||||||
const toBool = (i: any) => {
|
|
||||||
if (i === 0) return false;
|
|
||||||
if (i === 1) return true;
|
|
||||||
if (i === '0') return false;
|
|
||||||
if (i === '1') return true;
|
|
||||||
if (String(i).toLowerCase() === 'true') return true;
|
|
||||||
if (String(i).toLowerCase() === 'false') return false;
|
|
||||||
return !!i;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base class for all shapes.
|
* Base class for all shapes.
|
||||||
|
@ -94,9 +85,14 @@ const toBool = (i: any) => {
|
||||||
*/
|
*/
|
||||||
class Shape {
|
class Shape {
|
||||||
constructor(stencil: StencilShape | null = null) {
|
constructor(stencil: StencilShape | null = null) {
|
||||||
|
// `stencil` is not null when instantiated directly,
|
||||||
|
// but can be null when instantiated through a child class.
|
||||||
if (stencil) {
|
if (stencil) {
|
||||||
this.stencil = stencil;
|
this.stencil = stencil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// moved from init()
|
||||||
|
this.node = this.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -109,13 +105,9 @@ class Shape {
|
||||||
*
|
*
|
||||||
* container - DOM node that will contain the shape.
|
* container - DOM node that will contain the shape.
|
||||||
*/
|
*/
|
||||||
init(container: SVGElement | null = null) {
|
init(container: SVGElement) {
|
||||||
if (!this.node) {
|
if (!this.node.parentNode) {
|
||||||
this.node = this.create();
|
container.appendChild(this.node);
|
||||||
|
|
||||||
if (container) {
|
|
||||||
container.appendChild(this.node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +117,7 @@ class Shape {
|
||||||
* Sets the styles to their default values.
|
* Sets the styles to their default values.
|
||||||
*/
|
*/
|
||||||
initStyles() {
|
initStyles() {
|
||||||
this.strokewidth = 1;
|
this.strokeWidth = 1;
|
||||||
this.rotation = 0;
|
this.rotation = 0;
|
||||||
this.opacity = 100;
|
this.opacity = 100;
|
||||||
this.fillOpacity = 100;
|
this.fillOpacity = 100;
|
||||||
|
@ -146,31 +138,31 @@ class Shape {
|
||||||
opacity = 100;
|
opacity = 100;
|
||||||
isDashed = false;
|
isDashed = false;
|
||||||
|
|
||||||
fill: string | null = null;
|
fill: ColorValue = NONE;
|
||||||
|
|
||||||
gradient: string | null = null;
|
gradient: ColorValue = NONE;
|
||||||
|
|
||||||
gradientDirection: string | null = null;
|
gradientDirection: DirectionValue = DIRECTION_EAST;
|
||||||
|
|
||||||
fillOpacity = 100;
|
fillOpacity = 100;
|
||||||
|
|
||||||
strokeOpacity: number | null = 100;
|
strokeOpacity = 100;
|
||||||
|
|
||||||
stroke: string | null = null;
|
stroke: ColorValue = NONE;
|
||||||
|
|
||||||
strokewidth: number | null = 1;
|
strokeWidth = 1;
|
||||||
|
|
||||||
spacing: number | null = null;
|
spacing = 0;
|
||||||
|
|
||||||
startSize: number | null = null;
|
startSize = 1;
|
||||||
|
|
||||||
endSize: number | null = null;
|
endSize = 1;
|
||||||
|
|
||||||
startArrow: string | null = null;
|
startArrow: ArrowType = NONE;
|
||||||
|
|
||||||
endArrow: string | null = null;
|
endArrow: ArrowType = NONE;
|
||||||
|
|
||||||
direction: DirectionValue | null = null;
|
direction: DirectionValue = DIRECTION_EAST;
|
||||||
|
|
||||||
flipH = false;
|
flipH = false;
|
||||||
|
|
||||||
|
@ -184,7 +176,7 @@ class Shape {
|
||||||
|
|
||||||
cursor = '';
|
cursor = '';
|
||||||
|
|
||||||
verticalTextRotation: number | null = null;
|
verticalTextRotation = 0;
|
||||||
|
|
||||||
oldGradients: GradientMap = {};
|
oldGradients: GradientMap = {};
|
||||||
|
|
||||||
|
@ -238,7 +230,7 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Holds the outermost DOM node that represents this shape.
|
* Holds the outermost DOM node that represents this shape.
|
||||||
*/
|
*/
|
||||||
node: SVGGElement | null = null;
|
node: SVGGElement;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: state
|
* Variable: state
|
||||||
|
@ -332,15 +324,15 @@ class Shape {
|
||||||
*/
|
*/
|
||||||
useSvgBoundingBox = true;
|
useSvgBoundingBox = true;
|
||||||
|
|
||||||
image: Image | null = null;
|
image: ImageBox | null = null;
|
||||||
|
|
||||||
indicatorColor: ColorValue = null;
|
indicatorColor: ColorValue = NONE;
|
||||||
|
|
||||||
indicatorStrokeColor: ColorValue = null;
|
indicatorStrokeColor: ColorValue = NONE;
|
||||||
|
|
||||||
indicatorGradientColor: ColorValue = null;
|
indicatorGradientColor: ColorValue = NONE;
|
||||||
|
|
||||||
indicatorDirection: DirectionValue = null;
|
indicatorDirection: DirectionValue = DIRECTION_EAST;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: isHtmlAllowed
|
* Function: isHtmlAllowed
|
||||||
|
@ -357,11 +349,11 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Returns 0, or 0.5 if <strokewidth> % 2 == 1.
|
* Returns 0, or 0.5 if <strokewidth> % 2 == 1.
|
||||||
*/
|
*/
|
||||||
getSvgScreenOffset() {
|
getSvgScreenOffset(): number {
|
||||||
const sw =
|
const sw =
|
||||||
this.stencil && this.stencil.strokewidth !== 'inherit'
|
this.stencil && this.stencil.strokeWidthValue !== 'inherit'
|
||||||
? Number(this.stencil.strokewidth)
|
? Number(this.stencil.strokeWidthValue)
|
||||||
: this.strokewidth ?? 0;
|
: this.strokeWidth ?? 0;
|
||||||
|
|
||||||
return mod(Math.max(1, Math.round(sw * this.scale)), 2) === 1 ? 0.5 : 0;
|
return mod(Math.max(1, Math.round(sw * this.scale)), 2) === 1 ? 0.5 : 0;
|
||||||
}
|
}
|
||||||
|
@ -398,8 +390,6 @@ class Shape {
|
||||||
* Creates and returns the SVG node(s) to represent this shape.
|
* Creates and returns the SVG node(s) to represent this shape.
|
||||||
*/
|
*/
|
||||||
redraw() {
|
redraw() {
|
||||||
if (!this.node) return;
|
|
||||||
|
|
||||||
this.updateBoundsFromPoints();
|
this.updateBoundsFromPoints();
|
||||||
|
|
||||||
if (this.visible && this.checkBounds()) {
|
if (this.visible && this.checkBounds()) {
|
||||||
|
@ -419,8 +409,6 @@ class Shape {
|
||||||
* Removes all child nodes and resets all CSS.
|
* Removes all child nodes and resets all CSS.
|
||||||
*/
|
*/
|
||||||
clear() {
|
clear() {
|
||||||
if (!this.node) return;
|
|
||||||
|
|
||||||
while (this.node.lastChild) {
|
while (this.node.lastChild) {
|
||||||
this.node.removeChild(this.node.lastChild);
|
this.node.removeChild(this.node.lastChild);
|
||||||
}
|
}
|
||||||
|
@ -435,18 +423,11 @@ class Shape {
|
||||||
const pts = this.points;
|
const pts = this.points;
|
||||||
|
|
||||||
if (pts.length > 0 && pts[0]) {
|
if (pts.length > 0 && pts[0]) {
|
||||||
this.bounds = new Rectangle(
|
this.bounds = new Rectangle(Math.round(pts[0].x), Math.round(pts[0].y), 1, 1);
|
||||||
Math.round(pts[0].x),
|
|
||||||
Math.round(pts[0].y),
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const pt of pts) {
|
for (const pt of pts) {
|
||||||
if (pt) {
|
if (pt) {
|
||||||
this.bounds.add(
|
this.bounds.add(new Rectangle(Math.round(pt.x), Math.round(pt.y), 1, 1));
|
||||||
new Rectangle(Math.round(pt.x), Math.round(pt.y), 1, 1)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -460,7 +441,7 @@ class Shape {
|
||||||
* change the rectangle in-place. This implementation returns the given rect.
|
* change the rectangle in-place. This implementation returns the given rect.
|
||||||
*/
|
*/
|
||||||
getLabelBounds(rect: Rectangle) {
|
getLabelBounds(rect: Rectangle) {
|
||||||
const d = getValue(this.style, 'direction', DIRECTION_EAST);
|
const d = this.style?.direction ?? DIRECTION_EAST;
|
||||||
let bounds = rect.clone();
|
let bounds = rect.clone();
|
||||||
|
|
||||||
// Normalizes argument for getLabelMargins hook
|
// Normalizes argument for getLabelMargins hook
|
||||||
|
@ -480,15 +461,11 @@ class Shape {
|
||||||
if (labelMargins) {
|
if (labelMargins) {
|
||||||
labelMargins = labelMargins.clone();
|
labelMargins = labelMargins.clone();
|
||||||
|
|
||||||
let flipH = toBool(getValue(this.style, 'flipH', false));
|
let flipH = this.style?.flipH ?? false;
|
||||||
let flipV = toBool(getValue(this.style, 'flipV', false));
|
let flipV = this.style?.flipV ?? false;
|
||||||
|
|
||||||
// Handles special case for vertical labels
|
// Handles special case for vertical labels
|
||||||
if (
|
if (this.state && this.state.text && this.state.text.isPaintBoundsInverted()) {
|
||||||
this.state &&
|
|
||||||
this.state.text &&
|
|
||||||
this.state.text.isPaintBoundsInverted()
|
|
||||||
) {
|
|
||||||
const tmp = labelMargins.x;
|
const tmp = labelMargins.x;
|
||||||
labelMargins.x = labelMargins.height;
|
labelMargins.x = labelMargins.height;
|
||||||
labelMargins.height = labelMargins.width;
|
labelMargins.height = labelMargins.width;
|
||||||
|
@ -540,8 +517,6 @@ class Shape {
|
||||||
* Updates the SVG or VML shape.
|
* Updates the SVG or VML shape.
|
||||||
*/
|
*/
|
||||||
redrawShape() {
|
redrawShape() {
|
||||||
if (!this.node) return;
|
|
||||||
|
|
||||||
const canvas = this.createCanvas();
|
const canvas = this.createCanvas();
|
||||||
|
|
||||||
if (canvas) {
|
if (canvas) {
|
||||||
|
@ -552,7 +527,7 @@ class Shape {
|
||||||
this.paint(canvas);
|
this.paint(canvas);
|
||||||
this.afterPaint(canvas);
|
this.afterPaint(canvas);
|
||||||
|
|
||||||
if (this.node !== canvas.root) {
|
if (this.node !== canvas.root && canvas.root) {
|
||||||
// Forces parsing in IE8 standards mode - slow! avoid
|
// Forces parsing in IE8 standards mode - slow! avoid
|
||||||
this.node.insertAdjacentHTML('beforeend', canvas.root.outerHTML);
|
this.node.insertAdjacentHTML('beforeend', canvas.root.outerHTML);
|
||||||
}
|
}
|
||||||
|
@ -570,7 +545,7 @@ class Shape {
|
||||||
const canvas = this.createSvgCanvas();
|
const canvas = this.createSvgCanvas();
|
||||||
|
|
||||||
if (canvas && this.outline) {
|
if (canvas && this.outline) {
|
||||||
canvas.setStrokeWidth(this.strokewidth);
|
canvas.setStrokeWidth(this.strokeWidth);
|
||||||
canvas.setStrokeColor(this.stroke);
|
canvas.setStrokeColor(this.stroke);
|
||||||
|
|
||||||
if (this.isDashed) {
|
if (this.isDashed) {
|
||||||
|
@ -596,7 +571,7 @@ class Shape {
|
||||||
createSvgCanvas() {
|
createSvgCanvas() {
|
||||||
if (!this.node) return null;
|
if (!this.node) return null;
|
||||||
|
|
||||||
const canvas = new mxSvgCanvas2D(this.node, false);
|
const canvas = new SvgCanvas2D(this.node, false);
|
||||||
canvas.strokeTolerance = this.pointerEvents ? this.svgStrokeTolerance : 0;
|
canvas.strokeTolerance = this.pointerEvents ? this.svgStrokeTolerance : 0;
|
||||||
canvas.pointerEventsValue = this.svgPointerEvents;
|
canvas.pointerEventsValue = this.svgPointerEvents;
|
||||||
|
|
||||||
|
@ -626,9 +601,9 @@ class Shape {
|
||||||
* Destroys the given canvas which was used for drawing. This implementation
|
* Destroys the given canvas which was used for drawing. This implementation
|
||||||
* increments the reference counts on all shared gradients used in the canvas.
|
* increments the reference counts on all shared gradients used in the canvas.
|
||||||
*/
|
*/
|
||||||
destroyCanvas(canvas: mxSvgCanvas2D) {
|
destroyCanvas(canvas: AbstractCanvas2D) {
|
||||||
// Manages reference counts
|
// Manages reference counts
|
||||||
if (canvas instanceof mxSvgCanvas2D) {
|
if (canvas instanceof SvgCanvas2D) {
|
||||||
// Increments ref counts
|
// Increments ref counts
|
||||||
for (const key in canvas.gradients) {
|
for (const key in canvas.gradients) {
|
||||||
const gradient = canvas.gradients[key];
|
const gradient = canvas.gradients[key];
|
||||||
|
@ -648,19 +623,19 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Invoked before paint is called.
|
* Invoked before paint is called.
|
||||||
*/
|
*/
|
||||||
beforePaint(c: mxSvgCanvas2D) {}
|
beforePaint(c: AbstractCanvas2D) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: afterPaint
|
* Function: afterPaint
|
||||||
*
|
*
|
||||||
* Invokes after paint was called.
|
* Invokes after paint was called.
|
||||||
*/
|
*/
|
||||||
afterPaint(c: mxSvgCanvas2D) {}
|
afterPaint(c: AbstractCanvas2D) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic rendering code.
|
* Generic rendering code.
|
||||||
*/
|
*/
|
||||||
paint(c: mxSvgCanvas2D) {
|
paint(c: AbstractCanvas2D) {
|
||||||
let strokeDrawn = false;
|
let strokeDrawn = false;
|
||||||
|
|
||||||
if (c && this.outline) {
|
if (c && this.outline) {
|
||||||
|
@ -705,20 +680,13 @@ class Shape {
|
||||||
let bg = null;
|
let bg = null;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(!this.stencil &&
|
(!this.stencil && this.points.length === 0 && this.shapePointerEvents) ||
|
||||||
this.points.length === 0 &&
|
|
||||||
this.shapePointerEvents) ||
|
|
||||||
(this.stencil && this.stencilPointerEvents)
|
(this.stencil && this.stencilPointerEvents)
|
||||||
) {
|
) {
|
||||||
const bb = this.createBoundingBox();
|
const bb = this.createBoundingBox();
|
||||||
|
|
||||||
if (bb && this.node) {
|
if (bb && this.node) {
|
||||||
bg = this.createTransparentSvgRectangle(
|
bg = this.createTransparentSvgRectangle(bb.x, bb.y, bb.width, bb.height);
|
||||||
bb.x,
|
|
||||||
bb.y,
|
|
||||||
bb.width,
|
|
||||||
bb.height
|
|
||||||
);
|
|
||||||
this.node.appendChild(bg);
|
this.node.appendChild(bg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -727,7 +695,7 @@ class Shape {
|
||||||
this.stencil.drawShape(c, this, x, y, w, h);
|
this.stencil.drawShape(c, this, x, y, w, h);
|
||||||
} else {
|
} else {
|
||||||
// Stencils have separate strokewidth
|
// Stencils have separate strokewidth
|
||||||
c.setStrokeWidth(this.strokewidth);
|
c.setStrokeWidth(this.strokeWidth);
|
||||||
|
|
||||||
if (this.points.length > 0) {
|
if (this.points.length > 0) {
|
||||||
// Paints edge shape
|
// Paints edge shape
|
||||||
|
@ -763,49 +731,30 @@ class Shape {
|
||||||
/**
|
/**
|
||||||
* Sets the state of the canvas for drawing the shape.
|
* Sets the state of the canvas for drawing the shape.
|
||||||
*/
|
*/
|
||||||
// configureCanvas(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
configureCanvas(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
configureCanvas(
|
let dash = NONE;
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
let dash = null;
|
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
dash = this.style.dashPattern;
|
dash = this.style.dashPattern;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.setAlpha(<number>this.opacity / 100);
|
c.setAlpha(this.opacity / 100);
|
||||||
c.setFillAlpha(<number>this.fillOpacity / 100);
|
c.setFillAlpha(this.fillOpacity / 100);
|
||||||
c.setStrokeAlpha(<number>this.strokeOpacity / 100);
|
c.setStrokeAlpha(this.strokeOpacity / 100);
|
||||||
|
|
||||||
// Sets alpha, colors and gradients
|
// Sets alpha, colors and gradients
|
||||||
if (this.isShadow != null) {
|
if (this.isShadow) {
|
||||||
c.setShadow(this.isShadow);
|
c.setShadow(this.isShadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dash pattern
|
// Dash pattern
|
||||||
if (this.isDashed != null) {
|
if (this.isDashed) {
|
||||||
c.setDashed(
|
c.setDashed(this.isDashed, this.style?.fixDash ?? false);
|
||||||
this.isDashed,
|
|
||||||
this.style != null
|
|
||||||
? toBool(getValue(this.style, 'fixDash', false))
|
|
||||||
: false
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dash != null) {
|
c.setDashPattern(dash);
|
||||||
c.setDashPattern(dash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
if (this.fill !== NONE && this.gradient !== NONE) {
|
||||||
this.fill != null &&
|
|
||||||
this.fill !== NONE &&
|
|
||||||
this.gradient &&
|
|
||||||
this.gradient !== NONE
|
|
||||||
) {
|
|
||||||
const b = this.getGradientBounds(c, x, y, w, h);
|
const b = this.getGradientBounds(c, x, y, w, h);
|
||||||
c.setGradient(
|
c.setGradient(
|
||||||
this.fill,
|
this.fill,
|
||||||
|
@ -828,14 +777,7 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Returns the bounding box for the gradient box for this shape.
|
* Returns the bounding box for the gradient box for this shape.
|
||||||
*/
|
*/
|
||||||
// getGradientBounds(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): mxRectangle;
|
getGradientBounds(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
getGradientBounds(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
return new Rectangle(x, y, w, h);
|
return new Rectangle(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -844,25 +786,12 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Sets the scale and rotation on the given canvas.
|
* Sets the scale and rotation on the given canvas.
|
||||||
*/
|
*/
|
||||||
// updateTransform(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
updateTransform(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
updateTransform(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
// NOTE: Currently, scale is implemented in state and canvas. This will
|
// NOTE: Currently, scale is implemented in state and canvas. This will
|
||||||
// move to canvas in a later version, so that the states are unscaled
|
// move to canvas in a later version, so that the states are unscaled
|
||||||
// and untranslated and do not need an update after zooming or panning.
|
// and untranslated and do not need an update after zooming or panning.
|
||||||
c.scale(this.scale);
|
c.scale(this.scale);
|
||||||
c.rotate(
|
c.rotate(this.getShapeRotation(), this.flipH, this.flipV, x + w / 2, y + h / 2);
|
||||||
this.getShapeRotation(),
|
|
||||||
this.flipH,
|
|
||||||
this.flipV,
|
|
||||||
x + w / 2,
|
|
||||||
y + h / 2
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -870,21 +799,10 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Paints the vertex shape.
|
* Paints the vertex shape.
|
||||||
*/
|
*/
|
||||||
// paintVertexShape(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintVertexShape(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
this.paintBackground(c, x, y, w, h);
|
this.paintBackground(c, x, y, w, h);
|
||||||
|
|
||||||
if (
|
if (!this.outline || !this.style || this.style.backgroundOutline === 0) {
|
||||||
!this.outline ||
|
|
||||||
this.style == null ||
|
|
||||||
toBool(getValue(this.style, 'backgroundOutline', 0) === false)
|
|
||||||
) {
|
|
||||||
c.setShadow(false);
|
c.setShadow(false);
|
||||||
this.paintForeground(c, x, y, w, h);
|
this.paintForeground(c, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
@ -895,55 +813,32 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Hook for subclassers. This implementation is empty.
|
* Hook for subclassers. This implementation is empty.
|
||||||
*/
|
*/
|
||||||
// paintBackground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintBackground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {}
|
||||||
paintBackground(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hook for subclassers. This implementation is empty.
|
* Hook for subclassers. This implementation is empty.
|
||||||
*/
|
*/
|
||||||
// paintForeground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintForeground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {}
|
||||||
paintForeground(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: paintEdgeShape
|
* Function: paintEdgeShape
|
||||||
*
|
*
|
||||||
* Hook for subclassers. This implementation is empty.
|
* Hook for subclassers. This implementation is empty.
|
||||||
*/
|
*/
|
||||||
// paintEdgeShape(c: mxAbstractCanvas2D, pts: mxPoint[]): void;
|
paintEdgeShape(c: AbstractCanvas2D, pts: Point[]) {}
|
||||||
paintEdgeShape(c: mxSvgCanvas2D, pts: Point[]): void {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: getArcSize
|
* Function: getArcSize
|
||||||
*
|
*
|
||||||
* Returns the arc size for the given dimension.
|
* Returns the arc size for the given dimension.
|
||||||
*/
|
*/
|
||||||
// getArcSize(w: number, h: number): number;
|
getArcSize(w: number, h: number) {
|
||||||
getArcSize(w: number, h: number): number {
|
|
||||||
let r = 0;
|
let r = 0;
|
||||||
|
|
||||||
if (toBool(getValue(this.style, 'absoluteArcSize', 0))) {
|
if (this.style?.absoluteArcSize === 0) {
|
||||||
r = Math.min(
|
r = Math.min(w / 2, Math.min(h / 2, (this.style?.arcSize ?? LINE_ARCSIZE) / 2));
|
||||||
w / 2,
|
|
||||||
Math.min(h / 2, getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const f = parseFloat(
|
const f = (this.style?.arcSize ?? RECTANGLE_ROUNDING_FACTOR * 100) / 100;
|
||||||
String(
|
|
||||||
getValue(this.style, 'arcSize', RECTANGLE_ROUNDING_FACTOR * 100) / 100
|
|
||||||
)
|
|
||||||
);
|
|
||||||
r = Math.min(w * f, h * f);
|
r = Math.min(w * f, h * f);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
@ -954,16 +849,15 @@ class Shape {
|
||||||
*
|
*
|
||||||
* Paints the glass gradient effect.
|
* Paints the glass gradient effect.
|
||||||
*/
|
*/
|
||||||
// paintGlassEffect(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number, arc: number): void;
|
|
||||||
paintGlassEffect(
|
paintGlassEffect(
|
||||||
c: mxSvgCanvas2D,
|
c: AbstractCanvas2D,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
arc: number
|
arc: number
|
||||||
) {
|
) {
|
||||||
const sw = Math.ceil((this.strokewidth ?? 0) / 2);
|
const sw = Math.ceil((this.strokeWidth ?? 0) / 2);
|
||||||
const size = 0.4;
|
const size = 0.4;
|
||||||
|
|
||||||
c.setGradient('#ffffff', '#ffffff', x, y, w, h * 0.6, 'south', 0.9, 0.1);
|
c.setGradient('#ffffff', '#ffffff', x, y, w, h * 0.6, 'south', 0.9, 0.1);
|
||||||
|
@ -994,7 +888,7 @@ class Shape {
|
||||||
* Paints the given points with rounded corners.
|
* Paints the given points with rounded corners.
|
||||||
*/
|
*/
|
||||||
addPoints(
|
addPoints(
|
||||||
c: mxSvgCanvas2D,
|
c: AbstractCanvas2D,
|
||||||
pts: Point[],
|
pts: Point[],
|
||||||
rounded: boolean = false,
|
rounded: boolean = false,
|
||||||
arcSize: number,
|
arcSize: number,
|
||||||
|
@ -1009,10 +903,7 @@ class Shape {
|
||||||
if (close && rounded) {
|
if (close && rounded) {
|
||||||
pts = pts.slice();
|
pts = pts.slice();
|
||||||
const p0 = pts[0];
|
const p0 = pts[0];
|
||||||
const wp = new Point(
|
const wp = new Point(pe.x + (p0.x - pe.x) / 2, pe.y + (p0.y - pe.y) / 2);
|
||||||
pe.x + (p0.x - pe.x) / 2,
|
|
||||||
pe.y + (p0.y - pe.y) / 2
|
|
||||||
);
|
|
||||||
pts.splice(0, 0, wp);
|
pts.splice(0, 0, wp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1096,15 +987,15 @@ class Shape {
|
||||||
|
|
||||||
this.spacing = 0;
|
this.spacing = 0;
|
||||||
|
|
||||||
this.fill = null;
|
this.fill = NONE;
|
||||||
this.gradient = null;
|
this.gradient = NONE;
|
||||||
this.gradientDirection = null;
|
this.gradientDirection = DIRECTION_EAST;
|
||||||
this.stroke = null;
|
this.stroke = NONE;
|
||||||
this.startSize = null;
|
this.startSize = 1;
|
||||||
this.endSize = null;
|
this.endSize = 1;
|
||||||
this.startArrow = null;
|
this.startArrow = NONE;
|
||||||
this.endArrow = null;
|
this.endArrow = NONE;
|
||||||
this.direction = null;
|
this.direction = DIRECTION_EAST;
|
||||||
|
|
||||||
this.isShadow = false;
|
this.isShadow = false;
|
||||||
this.isDashed = false;
|
this.isDashed = false;
|
||||||
|
@ -1151,81 +1042,35 @@ class Shape {
|
||||||
this.state = state;
|
this.state = state;
|
||||||
this.style = state.style;
|
this.style = state.style;
|
||||||
|
|
||||||
const ifNotNullElse = (value: any, defaultValue: any) => {
|
|
||||||
if (isNotNullish(value)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultValue;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.style) {
|
if (this.style) {
|
||||||
this.fill = ifNotNullElse(this.style.fillColor, this.fill);
|
this.fill = this.style.fillColor;
|
||||||
this.gradient = ifNotNullElse(this.style.gradientColor, this.gradient);
|
this.gradient = this.style.gradientColor;
|
||||||
this.gradientDirection = ifNotNullElse(
|
this.gradientDirection = this.style.gradientDirection;
|
||||||
this.style.gradientDirection,
|
this.opacity = this.style.opacity;
|
||||||
this.gradientDirection
|
this.fillOpacity = this.style.fillOpacity;
|
||||||
);
|
this.strokeOpacity = this.style.strokeOpacity;
|
||||||
this.opacity = ifNotNullElse(this.style.opacity, this.opacity);
|
this.stroke = this.style.strokeColor;
|
||||||
this.fillOpacity = ifNotNullElse(
|
this.strokeWidth = this.style.strokeWidth;
|
||||||
this.style.fillOpacity,
|
this.spacing = this.style.spacing;
|
||||||
this.fillOpacity
|
this.startSize = this.style.startSize;
|
||||||
);
|
this.endSize = this.style.endSize;
|
||||||
this.strokeOpacity = ifNotNullElse(
|
this.startArrow = this.style.startArrow;
|
||||||
this.style.strokeOpacity,
|
this.endArrow = this.style.endArrow;
|
||||||
this.strokeOpacity
|
this.rotation = this.style.rotation;
|
||||||
);
|
this.direction = this.style.direction;
|
||||||
this.stroke = ifNotNullElse(this.style.strokeColor, this.stroke);
|
this.flipH = this.style.flipH;
|
||||||
this.strokewidth = ifNotNullElse(
|
this.flipV = this.style.flipV;
|
||||||
this.style.strokeWidth,
|
|
||||||
this.strokewidth
|
|
||||||
);
|
|
||||||
this.spacing = ifNotNullElse(this.style.spacing, this.spacing);
|
|
||||||
this.startSize = ifNotNullElse(this.style.startSize, this.startSize);
|
|
||||||
this.endSize = ifNotNullElse(this.style.endSize, this.endSize);
|
|
||||||
this.startArrow = ifNotNullElse(this.style.startArrow, this.startArrow);
|
|
||||||
this.endArrow = ifNotNullElse(this.style.endArrow, this.endArrow);
|
|
||||||
this.rotation = ifNotNullElse(this.style.rotation, this.rotation);
|
|
||||||
this.direction = ifNotNullElse(this.style.direction, this.direction);
|
|
||||||
|
|
||||||
this.flipH = toBool(ifNotNullElse(this.style.flipH, 0));
|
if (this.direction === DIRECTION_NORTH || this.direction === DIRECTION_SOUTH) {
|
||||||
this.flipV = toBool(ifNotNullElse(this.style.flipV, 0));
|
|
||||||
|
|
||||||
// Legacy support for stencilFlipH/V
|
|
||||||
if (this.stencil) {
|
|
||||||
this.flipH = toBool(
|
|
||||||
ifNotNullElse(this.style.stencilFlipH, this.flipH || 0)
|
|
||||||
);
|
|
||||||
this.flipV = toBool(
|
|
||||||
ifNotNullElse(this.style.stencilFlipV, this.flipV || 0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (
|
|
||||||
this.direction === DIRECTION_NORTH ||
|
|
||||||
this.direction === DIRECTION_SOUTH
|
|
||||||
) {
|
|
||||||
const tmp = this.flipH;
|
const tmp = this.flipH;
|
||||||
this.flipH = this.flipV;
|
this.flipH = this.flipV;
|
||||||
this.flipV = tmp;
|
this.flipV = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.isShadow = toBool(ifNotNullElse(this.style.shadow, this.isShadow));
|
this.isShadow = this.style.shadow;
|
||||||
this.isDashed = toBool(ifNotNullElse(this.style.dashed, this.isDashed));
|
this.isDashed = this.style.dashed;
|
||||||
this.isRounded = toBool(
|
this.isRounded = this.style.rounded;
|
||||||
ifNotNullElse(this.style.rounded, this.isRounded)
|
this.glass = this.style.glass;
|
||||||
);
|
|
||||||
this.glass = toBool(ifNotNullElse(this.style.glass, this.glass));
|
|
||||||
|
|
||||||
if (this.fill === NONE) {
|
|
||||||
this.fill = null;
|
|
||||||
}
|
|
||||||
if (this.gradient === NONE) {
|
|
||||||
this.gradient = null;
|
|
||||||
}
|
|
||||||
if (this.stroke === NONE) {
|
|
||||||
this.stroke = null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1240,10 +1085,7 @@ class Shape {
|
||||||
*/
|
*/
|
||||||
setCursor(cursor: string) {
|
setCursor(cursor: string) {
|
||||||
this.cursor = cursor;
|
this.cursor = cursor;
|
||||||
|
this.node.style.cursor = cursor;
|
||||||
if (this.node) {
|
|
||||||
this.node.style.cursor = cursor;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1258,7 +1100,7 @@ class Shape {
|
||||||
/**
|
/**
|
||||||
* Hook for subclassers.
|
* Hook for subclassers.
|
||||||
*/
|
*/
|
||||||
isRoundable(c: mxSvgCanvas2D, x: number, y: number, w: number, h: number) {
|
isRoundable(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1271,7 +1113,7 @@ class Shape {
|
||||||
updateBoundingBox() {
|
updateBoundingBox() {
|
||||||
// Tries to get bounding box from SVG subsystem
|
// Tries to get bounding box from SVG subsystem
|
||||||
// LATER: Use getBoundingClientRect for fallback in VML
|
// LATER: Use getBoundingClientRect for fallback in VML
|
||||||
if (this.useSvgBoundingBox && this.node && this.node.ownerSVGElement) {
|
if (this.useSvgBoundingBox && this.node.ownerSVGElement) {
|
||||||
try {
|
try {
|
||||||
const b = this.node.getBBox();
|
const b = this.node.getBBox();
|
||||||
|
|
||||||
|
@ -1279,7 +1121,7 @@ class Shape {
|
||||||
this.boundingBox = new Rectangle(b.x, b.y, b.width, b.height);
|
this.boundingBox = new Rectangle(b.x, b.y, b.width, b.height);
|
||||||
|
|
||||||
// Adds strokeWidth
|
// Adds strokeWidth
|
||||||
this.boundingBox.grow(((this.strokewidth ?? 0) * this.scale) / 2);
|
this.boundingBox.grow(((this.strokeWidth ?? 0) * this.scale) / 2);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1316,8 +1158,7 @@ class Shape {
|
||||||
const bb = this.bounds.clone();
|
const bb = this.bounds.clone();
|
||||||
if (
|
if (
|
||||||
(this.stencil &&
|
(this.stencil &&
|
||||||
(this.direction === DIRECTION_NORTH ||
|
(this.direction === DIRECTION_NORTH || this.direction === DIRECTION_SOUTH)) ||
|
||||||
this.direction === DIRECTION_SOUTH)) ||
|
|
||||||
this.isPaintBoundsInverted()
|
this.isPaintBoundsInverted()
|
||||||
) {
|
) {
|
||||||
bb.rotate90();
|
bb.rotate90();
|
||||||
|
@ -1334,8 +1175,9 @@ class Shape {
|
||||||
bbox.width += Math.ceil(SHADOW_OFFSET_X * this.scale);
|
bbox.width += Math.ceil(SHADOW_OFFSET_X * this.scale);
|
||||||
bbox.height += Math.ceil(SHADOW_OFFSET_Y * this.scale);
|
bbox.height += Math.ceil(SHADOW_OFFSET_Y * this.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adds strokeWidth
|
// Adds strokeWidth
|
||||||
bbox.grow(((this.strokewidth ?? 0) * this.scale) / 2);
|
bbox.grow(((this.strokeWidth ?? 0) * this.scale) / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1368,7 +1210,7 @@ class Shape {
|
||||||
getTextRotation() {
|
getTextRotation() {
|
||||||
let rot = this.getRotation();
|
let rot = this.getRotation();
|
||||||
|
|
||||||
if (!toBool(getValue(this.style, 'horizontal', 1))) {
|
if (!(this.style?.horizontal ?? true)) {
|
||||||
rot += this.verticalTextRotation || -90; // WARNING WARNING!!!! ===============================================================================================
|
rot += this.verticalTextRotation || -90; // WARNING WARNING!!!! ===============================================================================================
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1383,14 +1225,12 @@ class Shape {
|
||||||
getShapeRotation() {
|
getShapeRotation() {
|
||||||
let rot = this.getRotation();
|
let rot = this.getRotation();
|
||||||
|
|
||||||
if (this.direction) {
|
if (this.direction === DIRECTION_NORTH) {
|
||||||
if (this.direction === DIRECTION_NORTH) {
|
rot += 270;
|
||||||
rot += 270;
|
} else if (this.direction === DIRECTION_WEST) {
|
||||||
} else if (this.direction === DIRECTION_WEST) {
|
rot += 180;
|
||||||
rot += 180;
|
} else if (this.direction === DIRECTION_SOUTH) {
|
||||||
} else if (this.direction === DIRECTION_SOUTH) {
|
rot += 90;
|
||||||
rot += 90;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return rot;
|
return rot;
|
||||||
|
@ -1413,6 +1253,8 @@ class Shape {
|
||||||
return rect;
|
return rect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
redrawHtmlShape() {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: setTransparentBackgroundImage
|
* Function: setTransparentBackgroundImage
|
||||||
*
|
*
|
||||||
|
@ -1450,16 +1292,14 @@ class Shape {
|
||||||
* node associated with the shape using <mxEvent.release>.
|
* node associated with the shape using <mxEvent.release>.
|
||||||
*/
|
*/
|
||||||
destroy() {
|
destroy() {
|
||||||
if (this.node) {
|
InternalEvent.release(this.node);
|
||||||
InternalEvent.release(this.node);
|
|
||||||
|
|
||||||
if (this.node.parentNode) {
|
if (this.node.parentNode) {
|
||||||
this.node.parentNode.removeChild(this.node);
|
this.node.parentNode.removeChild(this.node);
|
||||||
}
|
|
||||||
|
|
||||||
this.node = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.node.innerHTML = '';
|
||||||
|
|
||||||
// Decrements refCount and removes unused
|
// Decrements refCount and removes unused
|
||||||
this.releaseSvgGradients(this.oldGradients);
|
this.releaseSvgGradients(this.oldGradients);
|
||||||
this.oldGradients = {};
|
this.oldGradients = {};
|
||||||
|
|
|
@ -7,8 +7,9 @@
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import { ARROW_SIZE, ARROW_SPACING, ARROW_WIDTH } from '../../../../util/Constants';
|
import { ARROW_SIZE, ARROW_SPACING, ARROW_WIDTH } from '../../../../util/Constants';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement an arrow shape. The shape is used to represent edges, not vertices.
|
* Extends {@link Shape} to implement an arrow shape. The shape is used to represent edges, not vertices.
|
||||||
|
@ -16,31 +17,41 @@ import Point from '../../Point';
|
||||||
* This shape is registered under {@link mxConstants.SHAPE_ARROW} in {@link mxCellRenderer}.
|
* This shape is registered under {@link mxConstants.SHAPE_ARROW} in {@link mxCellRenderer}.
|
||||||
*/
|
*/
|
||||||
class Arrow extends Shape {
|
class Arrow extends Shape {
|
||||||
constructor(points, fill, stroke, strokewidth, arrowWidth, spacing, endSize) {
|
constructor(
|
||||||
|
points: Point[],
|
||||||
|
fill: ColorValue,
|
||||||
|
stroke: ColorValue,
|
||||||
|
strokeWidth = 1,
|
||||||
|
arrowWidth = ARROW_WIDTH,
|
||||||
|
spacing = ARROW_SPACING,
|
||||||
|
endSize = ARROW_SIZE
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth != null ? strokewidth : 1;
|
this.strokeWidth = strokeWidth;
|
||||||
this.arrowWidth = arrowWidth != null ? arrowWidth : ARROW_WIDTH;
|
this.arrowWidth = arrowWidth;
|
||||||
this.spacing = spacing != null ? spacing : ARROW_SPACING;
|
this.spacing = spacing;
|
||||||
this.endSize = endSize != null ? endSize : ARROW_SIZE;
|
this.endSize = endSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arrowWidth: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Augments the bounding box with the edge width and markers.
|
* Augments the bounding box with the edge width and markers.
|
||||||
*/
|
*/
|
||||||
augmentBoundingBox(bbox: Rectangle): void {
|
augmentBoundingBox(bbox: Rectangle) {
|
||||||
super.augmentBoundingBox(bbox);
|
super.augmentBoundingBox(bbox);
|
||||||
|
|
||||||
const w = Math.max(this.arrowWidth, this.endSize);
|
const w = Math.max(this.arrowWidth, this.endSize);
|
||||||
bbox.grow((w / 2 + this.strokewidth) * this.scale);
|
bbox.grow((w / 2 + this.strokeWidth) * this.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintEdgeShape(c: mxAbstractCanvas2D, pts: Point[]): void {
|
paintEdgeShape(c: AbstractCanvas2D, pts: Point[]) {
|
||||||
// Geometry of arrow
|
// Geometry of arrow
|
||||||
const spacing = ARROW_SPACING;
|
const spacing = ARROW_SPACING;
|
||||||
const width = ARROW_WIDTH;
|
const width = ARROW_WIDTH;
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import { ARROW_SIZE, ARROW_SPACING, ARROW_WIDTH, NONE } from '../../../../util/Constants';
|
import { ARROW_SIZE, ARROW_SPACING, ARROW_WIDTH, NONE } from '../../../../util/Constants';
|
||||||
import utils, { getNumber, getValue, relativeCcw } from '../../../../util/Utils';
|
import { relativeCcw } from '../../../../util/Utils';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import CellState from '../../../cell/datatypes/CellState';
|
import CellState from '../../../cell/datatypes/CellState';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement an new rounded arrow shape with support for waypoints and double arrows. The
|
* Extends {@link Shape} to implement an new rounded arrow shape with support for waypoints and double arrows. The
|
||||||
|
@ -19,37 +20,48 @@ import CellState from '../../../cell/datatypes/CellState';
|
||||||
* This shape is registered under {@link mxConstants.SHAPE_ARROW_CONNECTOR} in {@link mxCellRenderer}.
|
* This shape is registered under {@link mxConstants.SHAPE_ARROW_CONNECTOR} in {@link mxCellRenderer}.
|
||||||
*/
|
*/
|
||||||
class ArrowConnector extends Shape {
|
class ArrowConnector extends Shape {
|
||||||
constructor(points, fill, stroke, strokewidth, arrowWidth, spacing, endSize) {
|
constructor(
|
||||||
|
points: Point[],
|
||||||
|
fill: ColorValue,
|
||||||
|
stroke: ColorValue,
|
||||||
|
strokeWidth = 1,
|
||||||
|
arrowWidth = ARROW_WIDTH,
|
||||||
|
spacing = ARROW_SPACING,
|
||||||
|
endSize = ARROW_SIZE / 5
|
||||||
|
) {
|
||||||
super();
|
super();
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth != null ? strokewidth : 1;
|
this.strokeWidth = strokeWidth;
|
||||||
this.arrowWidth = arrowWidth != null ? arrowWidth : ARROW_WIDTH;
|
this.arrowWidth = arrowWidth;
|
||||||
this.arrowSpacing = spacing != null ? spacing : ARROW_SPACING;
|
this.arrowSpacing = spacing;
|
||||||
this.startSize = ARROW_SIZE / 5;
|
this.startSize = ARROW_SIZE / 5;
|
||||||
this.endSize = endSize != null ? endSize : ARROW_SIZE / 5;
|
this.endSize = endSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
arrowWidth: number;
|
||||||
|
arrowSpacing: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to use the SVG bounding box in SVG.
|
* Allows to use the SVG bounding box in SVG.
|
||||||
* @defaultValue `false` for performance reasons.
|
* @defaultValue `false` for performance reasons.
|
||||||
*/
|
*/
|
||||||
useSvgBoundingBox: boolean = true;
|
useSvgBoundingBox = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: isRoundable
|
* Function: isRoundable
|
||||||
*
|
*
|
||||||
* Hook for subclassers.
|
* Hook for subclassers.
|
||||||
*/
|
*/
|
||||||
isRoundable(): boolean {
|
isRoundable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overrides mxShape to reset spacing.
|
* Overrides mxShape to reset spacing.
|
||||||
*/
|
*/
|
||||||
resetStyles(): void {
|
resetStyles() {
|
||||||
super.resetStyles();
|
super.resetStyles();
|
||||||
this.arrowSpacing = ARROW_SPACING;
|
this.arrowSpacing = ARROW_SPACING;
|
||||||
}
|
}
|
||||||
|
@ -60,9 +72,9 @@ class ArrowConnector extends Shape {
|
||||||
apply(state: CellState): void {
|
apply(state: CellState): void {
|
||||||
super.apply(state);
|
super.apply(state);
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
this.startSize = getNumber(this.style, 'startSize', ARROW_SIZE / 5) * 3;
|
this.startSize = this.style.startSize * 3;
|
||||||
this.endSize = getNumber(this.style, 'endSize', ARROW_SIZE / 5) * 3;
|
this.endSize = this.style.endSize * 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,21 +94,18 @@ class ArrowConnector extends Shape {
|
||||||
w = Math.max(w, this.getEndArrowWidth());
|
w = Math.max(w, this.getEndArrowWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
bbox.grow((w / 2 + this.strokewidth) * this.scale);
|
bbox.grow((w / 2 + this.strokeWidth) * this.scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintEdgeShape(c: mxAbstractCanvas2D, pts: Point[]): void {
|
paintEdgeShape(c: AbstractCanvas2D, pts: Point[]): void {
|
||||||
// Geometry of arrow
|
// Geometry of arrow
|
||||||
let strokeWidth = this.strokewidth;
|
let strokeWidth = this.strokeWidth;
|
||||||
|
|
||||||
if (this.outline) {
|
if (this.outline) {
|
||||||
strokeWidth = Math.max(
|
strokeWidth = Math.max(1, this.style?.strokeWidth ?? 0);
|
||||||
1,
|
|
||||||
utils.getNumber(this.style, 'strokeWidth', this.strokewidth)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const startWidth = this.getStartArrowWidth() + strokeWidth;
|
const startWidth = this.getStartArrowWidth() + strokeWidth;
|
||||||
|
@ -226,7 +235,7 @@ class ArrowConnector extends Shape {
|
||||||
// Higher strokewidths require a larger minimum bend, 0.35 covers all but the most extreme cases
|
// Higher strokewidths require a larger minimum bend, 0.35 covers all but the most extreme cases
|
||||||
const strokeWidthFactor = Math.max(
|
const strokeWidthFactor = Math.max(
|
||||||
tmp,
|
tmp,
|
||||||
Math.min(this.strokewidth / 200 + 0.04, 0.35)
|
Math.min(this.strokeWidth / 200 + 0.04, 0.35)
|
||||||
);
|
);
|
||||||
const angleFactor =
|
const angleFactor =
|
||||||
pos !== 0 && isRounded
|
pos !== 0 && isRounded
|
||||||
|
@ -387,7 +396,18 @@ class ArrowConnector extends Shape {
|
||||||
*
|
*
|
||||||
* Paints the marker.
|
* Paints the marker.
|
||||||
*/
|
*/
|
||||||
paintMarker(c, ptX, ptY, nx, ny, size, arrowWidth, edgeWidth, spacing, initialMove) {
|
paintMarker(
|
||||||
|
c: AbstractCanvas2D,
|
||||||
|
ptX: number,
|
||||||
|
ptY: number,
|
||||||
|
nx: number,
|
||||||
|
ny: number,
|
||||||
|
size: number,
|
||||||
|
arrowWidth: number,
|
||||||
|
edgeWidth: number,
|
||||||
|
spacing: number,
|
||||||
|
initialMove: boolean
|
||||||
|
) {
|
||||||
const widthArrowRatio = edgeWidth / arrowWidth;
|
const widthArrowRatio = edgeWidth / arrowWidth;
|
||||||
const orthx = (edgeWidth * ny) / 2;
|
const orthx = (edgeWidth * ny) / 2;
|
||||||
const orthy = (-edgeWidth * nx) / 2;
|
const orthy = (-edgeWidth * nx) / 2;
|
||||||
|
@ -416,50 +436,50 @@ class ArrowConnector extends Shape {
|
||||||
/**
|
/**
|
||||||
* @returns whether the arrow is rounded
|
* @returns whether the arrow is rounded
|
||||||
*/
|
*/
|
||||||
isArrowRounded(): boolean {
|
isArrowRounded() {
|
||||||
return this.isRounded;
|
return this.isRounded;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the width of the start arrow
|
* @returns the width of the start arrow
|
||||||
*/
|
*/
|
||||||
getStartArrowWidth(): number {
|
getStartArrowWidth() {
|
||||||
return ARROW_WIDTH;
|
return ARROW_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the width of the end arrow
|
* @returns the width of the end arrow
|
||||||
*/
|
*/
|
||||||
getEndArrowWidth(): number {
|
getEndArrowWidth() {
|
||||||
return ARROW_WIDTH;
|
return ARROW_WIDTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns the width of the body of the edge
|
* @returns the width of the body of the edge
|
||||||
*/
|
*/
|
||||||
getEdgeWidth(): number {
|
getEdgeWidth() {
|
||||||
return ARROW_WIDTH / 3;
|
return ARROW_WIDTH / 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns whether the ends of the shape are drawn
|
* @returns whether the ends of the shape are drawn
|
||||||
*/
|
*/
|
||||||
isOpenEnded(): boolean {
|
isOpenEnded() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns whether the start marker is drawn
|
* @returns whether the start marker is drawn
|
||||||
*/
|
*/
|
||||||
isMarkerStart(): boolean {
|
isMarkerStart() {
|
||||||
return getValue(this.style, 'startArrow', NONE) !== NONE;
|
return (this.style?.startArrow ?? NONE) !== NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @returns whether the end marker is drawn
|
* @returns whether the end marker is drawn
|
||||||
*/
|
*/
|
||||||
isMarkerEnd(): boolean {
|
isMarkerEnd() {
|
||||||
return getValue(this.style, 'endArrow', NONE) !== NONE;
|
return (this.style?.endArrow ?? NONE) !== NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,12 @@
|
||||||
*/
|
*/
|
||||||
import { DEFAULT_MARKERSIZE, NONE } from '../../../../util/Constants';
|
import { DEFAULT_MARKERSIZE, NONE } from '../../../../util/Constants';
|
||||||
import Polyline from './Polyline';
|
import Polyline from './Polyline';
|
||||||
import utils, { getNumber, getValue } from '../../../../util/Utils';
|
import { getNumber } from '../../../../util/Utils';
|
||||||
import Marker from './Marker';
|
import Marker from './Marker';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link mxShape} to implement a connector shape.
|
* Extends {@link mxShape} to implement a connector shape.
|
||||||
|
@ -21,7 +22,7 @@ import Rectangle from '../../Rectangle';
|
||||||
* @extends {Polyline}
|
* @extends {Polyline}
|
||||||
*/
|
*/
|
||||||
class Connector extends Polyline {
|
class Connector extends Polyline {
|
||||||
constructor(points: Point[], stroke: string, strokewidth: number) {
|
constructor(points: Point[], stroke: ColorValue, strokewidth: number) {
|
||||||
super(points, stroke, strokewidth);
|
super(points, stroke, strokewidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +30,15 @@ class Connector extends Polyline {
|
||||||
* Updates the <boundingBox> for this shape using <createBoundingBox>
|
* Updates the <boundingBox> for this shape using <createBoundingBox>
|
||||||
* and augmentBoundingBox and stores the result in <boundingBox>.
|
* and augmentBoundingBox and stores the result in <boundingBox>.
|
||||||
*/
|
*/
|
||||||
updateBoundingBox(): void {
|
updateBoundingBox() {
|
||||||
this.useSvgBoundingBox = this.style != null && this.style.curved === 1;
|
this.useSvgBoundingBox = !!this.style?.curved;
|
||||||
super.updateBoundingBox();
|
super.updateBoundingBox();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintEdgeShape(c: mxAbstractCanvas2D, pts: Point[]): void {
|
paintEdgeShape(c: AbstractCanvas2D, pts: Point[]): void {
|
||||||
// The indirection via functions for markers is needed in
|
// The indirection via functions for markers is needed in
|
||||||
// order to apply the offsets before painting the line and
|
// order to apply the offsets before painting the line and
|
||||||
// paint the markers after painting the line.
|
// paint the markers after painting the line.
|
||||||
|
@ -51,11 +52,11 @@ class Connector extends Polyline {
|
||||||
c.setShadow(false);
|
c.setShadow(false);
|
||||||
c.setDashed(false);
|
c.setDashed(false);
|
||||||
|
|
||||||
if (sourceMarker != null) {
|
if (sourceMarker) {
|
||||||
sourceMarker();
|
sourceMarker();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (targetMarker != null) {
|
if (targetMarker) {
|
||||||
targetMarker();
|
targetMarker();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -63,14 +64,17 @@ class Connector extends Polyline {
|
||||||
/**
|
/**
|
||||||
* Prepares the marker by adding offsets in pts and returning a function to paint the marker.
|
* Prepares the marker by adding offsets in pts and returning a function to paint the marker.
|
||||||
*/
|
*/
|
||||||
createMarker(c: mxAbstractCanvas2D, pts: Point[], source: boolean): Marker {
|
createMarker(c: AbstractCanvas2D, pts: Point[], source: boolean) {
|
||||||
|
if (!this.style) return null;
|
||||||
|
|
||||||
let result = null;
|
let result = null;
|
||||||
const n = pts.length;
|
const n = pts.length;
|
||||||
const type = getValue(this.style, source ? 'startArrow' : 'endArrow');
|
const type = source ? this.style.startArrow : this.style.endArrow;
|
||||||
|
|
||||||
let p0 = source ? pts[1] : pts[n - 2];
|
let p0 = source ? pts[1] : pts[n - 2];
|
||||||
const pe = source ? pts[0] : pts[n - 1];
|
const pe = source ? pts[0] : pts[n - 1];
|
||||||
|
|
||||||
if (type != null && p0 != null && pe != null) {
|
if (type !== NONE && p0 !== null && pe !== null) {
|
||||||
let count = 1;
|
let count = 1;
|
||||||
|
|
||||||
// Uses next non-overlapping point
|
// Uses next non-overlapping point
|
||||||
|
@ -92,15 +96,11 @@ class Connector extends Polyline {
|
||||||
const unitX = dx / dist;
|
const unitX = dx / dist;
|
||||||
const unitY = dy / dist;
|
const unitY = dy / dist;
|
||||||
|
|
||||||
const size = getNumber(
|
const size = source ? this.style.startSize : this.style.endSize;
|
||||||
this.style,
|
|
||||||
source ? 'startSize' : 'endSize',
|
|
||||||
DEFAULT_MARKERSIZE
|
|
||||||
);
|
|
||||||
|
|
||||||
// Allow for stroke width in the end point used and the
|
// Allow for stroke width in the end point used and the
|
||||||
// orthogonal vectors describing the direction of the marker
|
// orthogonal vectors describing the direction of the marker
|
||||||
const filled = this.style[source ? 'startFill' : 'endFill'] !== 0;
|
const filled = source ? this.style.startFill : this.style.endFill;
|
||||||
|
|
||||||
result = Marker.createMarker(
|
result = Marker.createMarker(
|
||||||
c,
|
c,
|
||||||
|
@ -111,7 +111,7 @@ class Connector extends Polyline {
|
||||||
unitY,
|
unitY,
|
||||||
size,
|
size,
|
||||||
source,
|
source,
|
||||||
this.strokewidth,
|
this.strokeWidth,
|
||||||
filled
|
filled
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -122,17 +122,19 @@ class Connector extends Polyline {
|
||||||
/**
|
/**
|
||||||
* Augments the bounding box with the strokewidth and shadow offsets.
|
* Augments the bounding box with the strokewidth and shadow offsets.
|
||||||
*/
|
*/
|
||||||
augmentBoundingBox(bbox: Rectangle): void {
|
augmentBoundingBox(bbox: Rectangle) {
|
||||||
super.augmentBoundingBox(bbox);
|
super.augmentBoundingBox(bbox);
|
||||||
|
|
||||||
|
if (!this.style) return;
|
||||||
|
|
||||||
// Adds marker sizes
|
// Adds marker sizes
|
||||||
let size = 0;
|
let size = 0;
|
||||||
|
|
||||||
if (getValue(this.style, 'startArrow', NONE) !== NONE) {
|
if (this.style.startArrow !== NONE) {
|
||||||
size = getNumber(this.style, 'startSize', DEFAULT_MARKERSIZE) + 1;
|
size = getNumber(this.style, 'startSize', DEFAULT_MARKERSIZE) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (getValue(this.style, 'endArrow', NONE) !== NONE) {
|
if (this.style.endArrow !== NONE) {
|
||||||
size = Math.max(size, getNumber(this.style, 'endSize', DEFAULT_MARKERSIZE)) + 1;
|
size = Math.max(size, getNumber(this.style, 'endSize', DEFAULT_MARKERSIZE)) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,9 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement a horizontal line shape.
|
* Extends {@link Shape} to implement a horizontal line shape.
|
||||||
|
@ -15,12 +16,12 @@ import Rectangle from '../../Rectangle';
|
||||||
* @extends {Shape}
|
* @extends {Shape}
|
||||||
*/
|
*/
|
||||||
class Line extends Shape {
|
class Line extends Shape {
|
||||||
constructor(bounds: Rectangle, stroke: string, strokewidth: number, vertical: boolean) {
|
constructor(bounds: Rectangle, stroke: ColorValue, strokeWidth = 1, vertical = false) {
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth != null ? strokewidth : 1;
|
this.strokeWidth = strokeWidth;
|
||||||
this.vertical = vertical != null ? vertical : this.vertical;
|
this.vertical = vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -28,23 +29,17 @@ class Line extends Shape {
|
||||||
*
|
*
|
||||||
* Whether to paint a vertical line.
|
* Whether to paint a vertical line.
|
||||||
*/
|
*/
|
||||||
vertical = false;
|
vertical: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirects to redrawPath for subclasses to work.
|
* Redirects to redrawPath for subclasses to work.
|
||||||
* @param {mxAbstractCanvas2D} c
|
* @param {AbstractCanvas2D} c
|
||||||
* @param {number} x
|
* @param {number} x
|
||||||
* @param {number} y
|
* @param {number} y
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
paintVertexShape(
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
c: mxAbstractCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
c.begin();
|
c.begin();
|
||||||
|
|
||||||
if (this.vertical) {
|
if (this.vertical) {
|
||||||
|
|
|
@ -4,11 +4,15 @@
|
||||||
* Updated to ES9 syntax by David Morrissey 2021
|
* Updated to ES9 syntax by David Morrissey 2021
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
import { ArrowType } from 'packages/core/src/types';
|
||||||
|
import AbstractCanvas2D from 'packages/core/src/util/canvas/AbstractCanvas2D';
|
||||||
import {
|
import {
|
||||||
ARROW_CLASSIC,
|
ARROW_CLASSIC,
|
||||||
ARROW_CLASSIC_THIN,
|
ARROW_CLASSIC_THIN,
|
||||||
ARROW_DIAMOND,
|
ARROW_DIAMOND,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
|
import Point from '../../Point';
|
||||||
|
import Shape from '../Shape';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A static class that implements all markers for VML and SVG using a registry.
|
* A static class that implements all markers for VML and SVG using a registry.
|
||||||
|
@ -21,15 +25,13 @@ class Marker {
|
||||||
*
|
*
|
||||||
* Mapping: the attribute name on the object is the marker type, the associated value is the function to paint the marker
|
* Mapping: the attribute name on the object is the marker type, the associated value is the function to paint the marker
|
||||||
*/
|
*/
|
||||||
// static markers: object;
|
static markers: Record<string, Function> = {};
|
||||||
static markers = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a factory method that updates a given endpoint and returns a
|
* Adds a factory method that updates a given endpoint and returns a
|
||||||
* function to paint the marker onto the given canvas.
|
* function to paint the marker onto the given canvas.
|
||||||
*/
|
*/
|
||||||
// static addMarker(type: string, funct: Function): void;
|
static addMarker(type: string, funct: Function) {
|
||||||
static addMarker(type, funct) {
|
|
||||||
Marker.markers[type] = funct;
|
Marker.markers[type] = funct;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,9 +40,20 @@ class Marker {
|
||||||
*
|
*
|
||||||
* Returns a function to paint the given marker.
|
* Returns a function to paint the given marker.
|
||||||
*/
|
*/
|
||||||
static createMarker(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
|
static createMarker(
|
||||||
|
canvas: AbstractCanvas2D,
|
||||||
|
shape: Shape,
|
||||||
|
type: ArrowType,
|
||||||
|
pe: Point,
|
||||||
|
unitX: number,
|
||||||
|
unitY: number,
|
||||||
|
size: number,
|
||||||
|
source: boolean,
|
||||||
|
sw: number,
|
||||||
|
filled: boolean
|
||||||
|
) {
|
||||||
const funct = Marker.markers[type];
|
const funct = Marker.markers[type];
|
||||||
return funct != null
|
return funct
|
||||||
? funct(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled)
|
? funct(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled)
|
||||||
: null;
|
: null;
|
||||||
}
|
}
|
||||||
|
@ -50,10 +63,19 @@ class Marker {
|
||||||
* Adds the classic and block marker factory method.
|
* Adds the classic and block marker factory method.
|
||||||
*/
|
*/
|
||||||
(() => {
|
(() => {
|
||||||
function createArrow(widthFactor) {
|
function createArrow(widthFactor = 2) {
|
||||||
widthFactor = widthFactor != null ? widthFactor : 2;
|
return (
|
||||||
|
canvas: AbstractCanvas2D,
|
||||||
return (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) => {
|
shape: Shape,
|
||||||
|
type: ArrowType,
|
||||||
|
pe: Point,
|
||||||
|
unitX: number,
|
||||||
|
unitY: number,
|
||||||
|
size: number,
|
||||||
|
source: boolean,
|
||||||
|
sw: number,
|
||||||
|
filled: boolean
|
||||||
|
) => {
|
||||||
// The angle of the forward facing arrow sides against the x axis is
|
// The angle of the forward facing arrow sides against the x axis is
|
||||||
// 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
|
// 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
|
||||||
// only half the strokewidth is processed ).
|
// only half the strokewidth is processed ).
|
||||||
|
@ -103,10 +125,19 @@ class Marker {
|
||||||
Marker.addMarker('block', createArrow(2));
|
Marker.addMarker('block', createArrow(2));
|
||||||
Marker.addMarker('blockThin', createArrow(3));
|
Marker.addMarker('blockThin', createArrow(3));
|
||||||
|
|
||||||
function createOpenArrow(widthFactor) {
|
function createOpenArrow(widthFactor = 2) {
|
||||||
widthFactor = widthFactor != null ? widthFactor : 2;
|
return (
|
||||||
|
canvas: AbstractCanvas2D,
|
||||||
return (canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) => {
|
shape: Shape,
|
||||||
|
type: ArrowType,
|
||||||
|
pe: Point,
|
||||||
|
unitX: number,
|
||||||
|
unitY: number,
|
||||||
|
size: number,
|
||||||
|
source: boolean,
|
||||||
|
sw: number,
|
||||||
|
filled: boolean
|
||||||
|
) => {
|
||||||
// The angle of the forward facing arrow sides against the x axis is
|
// The angle of the forward facing arrow sides against the x axis is
|
||||||
// 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
|
// 26.565 degrees, 1/sin(26.565) = 2.236 / 2 = 1.118 ( / 2 allows for
|
||||||
// only half the strokewidth is processed ).
|
// only half the strokewidth is processed ).
|
||||||
|
@ -144,7 +175,18 @@ class Marker {
|
||||||
|
|
||||||
Marker.addMarker(
|
Marker.addMarker(
|
||||||
'oval',
|
'oval',
|
||||||
(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) => {
|
(
|
||||||
|
canvas: AbstractCanvas2D,
|
||||||
|
shape: Shape,
|
||||||
|
type: ArrowType,
|
||||||
|
pe: Point,
|
||||||
|
unitX: number,
|
||||||
|
unitY: number,
|
||||||
|
size: number,
|
||||||
|
source: boolean,
|
||||||
|
sw: number,
|
||||||
|
filled: boolean
|
||||||
|
) => {
|
||||||
const a = size / 2;
|
const a = size / 2;
|
||||||
|
|
||||||
const pt = pe.clone();
|
const pt = pe.clone();
|
||||||
|
@ -163,7 +205,18 @@ class Marker {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function diamond(canvas, shape, type, pe, unitX, unitY, size, source, sw, filled) {
|
function diamond(
|
||||||
|
canvas: AbstractCanvas2D,
|
||||||
|
shape: Shape,
|
||||||
|
type: ArrowType,
|
||||||
|
pe: Point,
|
||||||
|
unitX: number,
|
||||||
|
unitY: number,
|
||||||
|
size: number,
|
||||||
|
source: boolean,
|
||||||
|
sw: number,
|
||||||
|
filled: boolean
|
||||||
|
) {
|
||||||
// The angle of the forward facing arrow sides against the x axis is
|
// The angle of the forward facing arrow sides against the x axis is
|
||||||
// 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for
|
// 45 degrees, 1/sin(45) = 1.4142 / 2 = 0.7071 ( / 2 allows for
|
||||||
// only half the strokewidth is processed ). Or 0.9862 for thin diamond.
|
// only half the strokewidth is processed ). Or 0.9862 for thin diamond.
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
||||||
import utils, { getValue } from '../../../../util/Utils';
|
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxPolyline
|
* Class: mxPolyline
|
||||||
|
@ -31,42 +31,42 @@ import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
||||||
* 1. This is stored in <strokewidth>.
|
* 1. This is stored in <strokewidth>.
|
||||||
*/
|
*/
|
||||||
class Polyline extends Shape {
|
class Polyline extends Shape {
|
||||||
constructor(points: Point[], stroke: string, strokewidth: number) {
|
constructor(points: Point[], stroke: ColorValue, strokeWidth = 1) {
|
||||||
super();
|
super();
|
||||||
this.points = points;
|
this.points = points;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth != null ? strokewidth : 1;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns 0.
|
* Returns 0.
|
||||||
*/
|
*/
|
||||||
getRotation(): number {
|
getRotation() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns 0.
|
* Returns 0.
|
||||||
*/
|
*/
|
||||||
getShapeRotation(): number {
|
getShapeRotation() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns false.
|
* Returns false.
|
||||||
*/
|
*/
|
||||||
isPaintBoundsInverted(): boolean {
|
isPaintBoundsInverted() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintEdgeShape(c: mxAbstractCanvas2D, pts: Point[]): void {
|
paintEdgeShape(c: AbstractCanvas2D, pts: Point[]) {
|
||||||
const prev = c.pointerEventsValue;
|
const prev = c.pointerEventsValue;
|
||||||
c.pointerEventsValue = 'stroke';
|
c.pointerEventsValue = 'stroke';
|
||||||
|
|
||||||
if (this.style == null || this.style.curved != 1) {
|
if (!this.style || !this.style.curved) {
|
||||||
this.paintLine(c, pts, this.isRounded);
|
this.paintLine(c, pts, this.isRounded);
|
||||||
} else {
|
} else {
|
||||||
this.paintCurvedLine(c, pts);
|
this.paintCurvedLine(c, pts);
|
||||||
|
@ -77,8 +77,9 @@ class Polyline extends Shape {
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintLine(c: mxAbstractCanvas2D, pts: Point[], rounded?: boolean): void {
|
paintLine(c: AbstractCanvas2D, pts: Point[], rounded?: boolean) {
|
||||||
const arcSize = getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2;
|
const arcSize = this.style?.arcSize ?? LINE_ARCSIZE;
|
||||||
|
|
||||||
c.begin();
|
c.begin();
|
||||||
this.addPoints(c, pts, rounded, arcSize, false);
|
this.addPoints(c, pts, rounded, arcSize, false);
|
||||||
c.stroke();
|
c.stroke();
|
||||||
|
@ -87,7 +88,7 @@ class Polyline extends Shape {
|
||||||
/**
|
/**
|
||||||
* Paints the line shape.
|
* Paints the line shape.
|
||||||
*/
|
*/
|
||||||
paintCurvedLine(c: mxAbstractCanvas2D, pts: Point[]): void {
|
paintCurvedLine(c: AbstractCanvas2D, pts: Point[]) {
|
||||||
c.begin();
|
c.begin();
|
||||||
|
|
||||||
const pt = pts[0];
|
const pt = pts[0];
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import Actor from '../Actor';
|
import Actor from '../Actor';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -14,30 +14,18 @@ import Rectangle from '../../Rectangle';
|
||||||
* This shape is registered under {@link mxConstants.SHAPE_CLOUD} in {@link cellRenderer}.
|
* This shape is registered under {@link mxConstants.SHAPE_CLOUD} in {@link cellRenderer}.
|
||||||
*/
|
*/
|
||||||
class CloudShape extends Actor {
|
class CloudShape extends Actor {
|
||||||
constructor(
|
constructor(bounds: Rectangle, fill: string, stroke: string, strokeWidth = 1) {
|
||||||
bounds: Rectangle,
|
|
||||||
fill: string,
|
|
||||||
stroke: string,
|
|
||||||
strokewidth: number = 1
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the path for this shape.
|
* Draws the path for this shape.
|
||||||
*/
|
*/
|
||||||
// redrawPath(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
redrawPath(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
redrawPath(
|
|
||||||
c: mxAbstractCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
c.moveTo(0.25 * w, 0.25 * h);
|
c.moveTo(0.25 * w, 0.25 * h);
|
||||||
c.curveTo(0.05 * w, 0.25 * h, 0, 0.5 * h, 0.16 * w, 0.55 * h);
|
c.curveTo(0.05 * w, 0.25 * h, 0, 0.5 * h, 0.16 * w, 0.55 * h);
|
||||||
c.curveTo(0, 0.66 * h, 0.18 * w, 0.9 * h, 0.31 * w, 0.8 * h);
|
c.curveTo(0, 0.66 * h, 0.18 * w, 0.9 * h, 0.31 * w, 0.8 * h);
|
||||||
|
|
|
@ -5,10 +5,9 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import utils from '../../../../util/Utils';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
|
import { NONE } from 'packages/core/src/util/Constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement an cylinder shape. If a custom shape with one filled area and an overlay path is
|
* Extends {@link Shape} to implement an cylinder shape. If a custom shape with one filled area and an overlay path is
|
||||||
|
@ -17,52 +16,34 @@ import Rectangle from '../../Rectangle';
|
||||||
* This shape is registered under {@link mxConstants.SHAPE_CYLINDER} in {@link cellRenderer}.
|
* This shape is registered under {@link mxConstants.SHAPE_CYLINDER} in {@link cellRenderer}.
|
||||||
*/
|
*/
|
||||||
class CylinderShape extends Shape {
|
class CylinderShape extends Shape {
|
||||||
constructor(
|
constructor(bounds: Rectangle, fill: string, stroke: string, strokeWidth = 1) {
|
||||||
bounds: Rectangle,
|
|
||||||
fill: string,
|
|
||||||
stroke: string,
|
|
||||||
strokewidth: number = 1
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines the maximum height of the top and bottom part of the cylinder shape.
|
* Defines the maximum height of the top and bottom part of the cylinder shape.
|
||||||
*/
|
*/
|
||||||
// maxHeight: number;
|
|
||||||
maxHeight = 40;
|
maxHeight = 40;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets stroke tolerance to 0 for SVG.
|
* Sets stroke tolerance to 0 for SVG.
|
||||||
*/
|
*/
|
||||||
// svgStrokeTolerance: number;
|
|
||||||
svgStrokeTolerance = 0;
|
svgStrokeTolerance = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Redirects to redrawPath for subclasses to work.
|
* Redirects to redrawPath for subclasses to work.
|
||||||
*/
|
*/
|
||||||
// paintVertexShape(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintVertexShape(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
c.translate(x, y);
|
c.translate(x, y);
|
||||||
c.begin();
|
c.begin();
|
||||||
this.redrawPath(c, x, y, w, h, false);
|
this.redrawPath(c, x, y, w, h, false);
|
||||||
c.fillAndStroke();
|
c.fillAndStroke();
|
||||||
|
|
||||||
if (
|
if (!this.outline || !this.style || this.style.backgroundOutline === 0) {
|
||||||
!this.outline ||
|
|
||||||
this.style == null ||
|
|
||||||
utils.getValue(this.style, 'backgroundOutline', 0) == 0
|
|
||||||
) {
|
|
||||||
c.setShadow(false);
|
c.setShadow(false);
|
||||||
c.begin();
|
c.begin();
|
||||||
this.redrawPath(c, x, y, w, h, true);
|
this.redrawPath(c, x, y, w, h, true);
|
||||||
|
@ -73,17 +54,15 @@ class CylinderShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Redirects to redrawPath for subclasses to work.
|
* Redirects to redrawPath for subclasses to work.
|
||||||
*/
|
*/
|
||||||
// getCylinderSize(x: number, y: number, w: number, h: number): number;
|
getCylinderSize(x: number, y: number, w: number, h: number) {
|
||||||
getCylinderSize(x: number, y: number, w: number, h: number): number {
|
|
||||||
return Math.min(this.maxHeight, Math.round(h / 5));
|
return Math.min(this.maxHeight, Math.round(h / 5));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the path for this shape.
|
* Draws the path for this shape.
|
||||||
*/
|
*/
|
||||||
// redrawPath(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number, isForeground: boolean): void;
|
|
||||||
redrawPath(
|
redrawPath(
|
||||||
c: mxSvgCanvas2D,
|
c: AbstractCanvas2D,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
w: number,
|
w: number,
|
||||||
|
@ -92,10 +71,7 @@ class CylinderShape extends Shape {
|
||||||
): void {
|
): void {
|
||||||
const dy = this.getCylinderSize(x, y, w, h);
|
const dy = this.getCylinderSize(x, y, w, h);
|
||||||
|
|
||||||
if (
|
if ((isForeground && this.fill !== NONE) || (!isForeground && this.fill === NONE)) {
|
||||||
(isForeground && this.fill != null) ||
|
|
||||||
(!isForeground && this.fill == null)
|
|
||||||
) {
|
|
||||||
c.moveTo(0, dy);
|
c.moveTo(0, dy);
|
||||||
c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);
|
c.curveTo(0, 2 * dy, w, 2 * dy, w, dy);
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,7 @@
|
||||||
|
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import utils from '../../../../util/Utils';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement a double ellipse shape.
|
* Extends {@link Shape} to implement a double ellipse shape.
|
||||||
|
@ -39,32 +38,18 @@ import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
class DoubleEllipseShape extends Shape {
|
class DoubleEllipseShape extends Shape {
|
||||||
strokewidth: number;
|
constructor(bounds: Rectangle, fill: string, stroke: string, strokeWidth = 1) {
|
||||||
|
|
||||||
constructor(
|
|
||||||
bounds: Rectangle,
|
|
||||||
fill: string,
|
|
||||||
stroke: string,
|
|
||||||
strokewidth: number = 1
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the background.
|
* Paints the background.
|
||||||
*/
|
*/
|
||||||
// paintBackground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintBackground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintBackground(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
c.ellipse(x, y, w, h);
|
c.ellipse(x, y, w, h);
|
||||||
c.fillAndStroke();
|
c.fillAndStroke();
|
||||||
}
|
}
|
||||||
|
@ -72,20 +57,11 @@ class DoubleEllipseShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Paints the foreground.
|
* Paints the foreground.
|
||||||
*/
|
*/
|
||||||
// paintForeground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintForeground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintForeground(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
if (!this.outline) {
|
if (!this.outline) {
|
||||||
const margin = utils.getValue(
|
const margin =
|
||||||
this.style,
|
this.style?.margin ?? Math.min(3 + this.strokeWidth, Math.min(w / 5, h / 5));
|
||||||
'margin',
|
|
||||||
Math.min(3 + this.strokewidth, Math.min(w / 5, h / 5))
|
|
||||||
);
|
|
||||||
x += margin;
|
x += margin;
|
||||||
y += margin;
|
y += margin;
|
||||||
w -= 2 * margin;
|
w -= 2 * margin;
|
||||||
|
@ -103,16 +79,12 @@ class DoubleEllipseShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* @returns the bounds for the label.
|
* @returns the bounds for the label.
|
||||||
*/
|
*/
|
||||||
// getLabelBounds(rect: mxRectangle): mxRectangle;
|
|
||||||
getLabelBounds(rect: Rectangle) {
|
getLabelBounds(rect: Rectangle) {
|
||||||
const margin =
|
const margin =
|
||||||
utils.getValue(
|
this.style?.margin ??
|
||||||
this.style,
|
Math.min(
|
||||||
'margin',
|
3 + this.strokeWidth,
|
||||||
Math.min(
|
Math.min(rect.width / 5 / this.scale, rect.height / 5 / this.scale)
|
||||||
3 + this.strokewidth,
|
|
||||||
Math.min(rect.width / 5 / this.scale, rect.height / 5 / this.scale)
|
|
||||||
)
|
|
||||||
) * this.scale;
|
) * this.scale;
|
||||||
|
|
||||||
return new Rectangle(
|
return new Rectangle(
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,29 +13,18 @@ import Rectangle from '../../Rectangle';
|
||||||
* This shape is registered under mxConstants.SHAPE_ELLIPSE in mxCellRenderer.
|
* This shape is registered under mxConstants.SHAPE_ELLIPSE in mxCellRenderer.
|
||||||
*/
|
*/
|
||||||
class EllipseShape extends Shape {
|
class EllipseShape extends Shape {
|
||||||
constructor(
|
constructor(bounds: Rectangle, fill: string, stroke: string, strokeWidth = 1) {
|
||||||
bounds: Rectangle,
|
|
||||||
fill: string,
|
|
||||||
stroke: string,
|
|
||||||
strokewidth: number = 1
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the ellipse shape.
|
* Paints the ellipse shape.
|
||||||
*/
|
*/
|
||||||
paintVertexShape(
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
c.ellipse(x, y, w, h);
|
c.ellipse(x, y, w, h);
|
||||||
c.fillAndStroke();
|
c.fillAndStroke();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,8 @@
|
||||||
*/
|
*/
|
||||||
import Actor from '../Actor';
|
import Actor from '../Actor';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import utils, { getValue } from '../../../../util/Utils';
|
|
||||||
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the hexagon shape.
|
* Implementation of the hexagon shape.
|
||||||
|
@ -28,8 +27,9 @@ class HexagonShape extends Actor {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
redrawPath(c: mxSvgCanvas2D, x: number, y: number, w: number, h: number): void {
|
redrawPath(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
const arcSize = getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2;
|
const arcSize = (this.style?.arcSize ?? LINE_ARCSIZE) / 2;
|
||||||
|
|
||||||
this.addPoints(
|
this.addPoints(
|
||||||
c,
|
c,
|
||||||
[
|
[
|
||||||
|
|
|
@ -5,12 +5,12 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import utils from '../../../../util/Utils';
|
|
||||||
import RectangleShape from './RectangleShape';
|
import RectangleShape from './RectangleShape';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import CellState from '../../../cell/datatypes/CellState';
|
import CellState from '../../../cell/datatypes/CellState';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/SvgCanvas2D';
|
||||||
import CellOverlay from '../../../cell/CellOverlay';
|
import CellOverlay from '../../../cell/CellOverlay';
|
||||||
|
import { NONE } from 'packages/core/src/util/Constants';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link mxShape} to implement an image shape.
|
* Extends {@link mxShape} to implement an image shape.
|
||||||
|
@ -22,24 +22,21 @@ import CellOverlay from '../../../cell/CellOverlay';
|
||||||
class ImageShape extends RectangleShape {
|
class ImageShape extends RectangleShape {
|
||||||
constructor(
|
constructor(
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
image: string,
|
imageSrc: string,
|
||||||
fill: string = '#FFFFFF',
|
fill: string = '#FFFFFF',
|
||||||
stroke: string = '#000000',
|
stroke: string = '#000000',
|
||||||
strokewidth: number = 1
|
strokeWidth: number = 1
|
||||||
) {
|
) {
|
||||||
super();
|
super(bounds, fill, stroke, strokeWidth);
|
||||||
this.bounds = bounds;
|
|
||||||
this.image = image;
|
this.imageSrc = imageSrc;
|
||||||
this.fill = fill;
|
|
||||||
this.stroke = stroke;
|
|
||||||
this.strokewidth = strokewidth;
|
|
||||||
this.shadow = false;
|
this.shadow = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Document me!!
|
// TODO: Document me!!
|
||||||
shadow: boolean;
|
shadow: boolean;
|
||||||
|
|
||||||
image: string;
|
imageSrc: string;
|
||||||
|
|
||||||
// Used in mxCellRenderer
|
// Used in mxCellRenderer
|
||||||
overlay: CellOverlay | null = null;
|
overlay: CellOverlay | null = null;
|
||||||
|
@ -54,8 +51,7 @@ class ImageShape extends RectangleShape {
|
||||||
/**
|
/**
|
||||||
* Disables offset in IE9 for crisper image output.
|
* Disables offset in IE9 for crisper image output.
|
||||||
*/
|
*/
|
||||||
// getSvgScreenOffset(): number;
|
getSvgScreenOffset() {
|
||||||
getSvgScreenOffset(): number {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,19 +72,12 @@ class ImageShape extends RectangleShape {
|
||||||
apply(state: CellState) {
|
apply(state: CellState) {
|
||||||
super.apply(state);
|
super.apply(state);
|
||||||
|
|
||||||
this.fill = null;
|
this.fill = NONE;
|
||||||
this.stroke = null;
|
this.stroke = NONE;
|
||||||
this.gradient = null;
|
this.gradient = NONE;
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
this.preserveImageAspect =
|
this.preserveImageAspect = this.style.imageAspect;
|
||||||
utils.getNumber(this.style, 'imageAspect', 1) == 1;
|
|
||||||
|
|
||||||
// Legacy support for imageFlipH/V
|
|
||||||
this.flipH =
|
|
||||||
this.flipH || utils.getValue(this.style, 'imageFlipH', 0) == 1;
|
|
||||||
this.flipV =
|
|
||||||
this.flipV || utils.getValue(this.style, 'imageFlipV', 0) == 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +85,7 @@ class ImageShape extends RectangleShape {
|
||||||
* Returns true if HTML is allowed for this shape. This implementation always
|
* Returns true if HTML is allowed for this shape. This implementation always
|
||||||
* returns false.
|
* returns false.
|
||||||
*/
|
*/
|
||||||
// isHtmlAllowed(): boolean;
|
isHtmlAllowed() {
|
||||||
isHtmlAllowed(): boolean {
|
|
||||||
return !this.preserveImageAspect;
|
return !this.preserveImageAspect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +94,7 @@ class ImageShape extends RectangleShape {
|
||||||
* this shape. This implementation falls back to <createVml>
|
* this shape. This implementation falls back to <createVml>
|
||||||
* so that the HTML creation is optional.
|
* so that the HTML creation is optional.
|
||||||
*/
|
*/
|
||||||
// createHtml(): HTMLElement;
|
createHtml() {
|
||||||
createHtml(): HTMLElement {
|
|
||||||
const node = document.createElement('div');
|
const node = document.createElement('div');
|
||||||
node.style.position = 'absolute';
|
node.style.position = 'absolute';
|
||||||
return node;
|
return node;
|
||||||
|
@ -116,33 +103,19 @@ class ImageShape extends RectangleShape {
|
||||||
/**
|
/**
|
||||||
* Disables inherited roundable support.
|
* Disables inherited roundable support.
|
||||||
*/
|
*/
|
||||||
// isRoundable(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): boolean;
|
isRoundable(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
isRoundable(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): boolean {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic background painting implementation.
|
* Generic background painting implementation.
|
||||||
*/
|
*/
|
||||||
// paintVertexShape(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintVertexShape(
|
if (this.imageSrc && this.style) {
|
||||||
c: mxSvgCanvas2D,
|
const fill = this.style.imageBackground;
|
||||||
x: number,
|
const stroke = this.style.imageBorder;
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
if (this.image != null) {
|
|
||||||
const fill = utils.getValue(this.style, 'imageBackground', null);
|
|
||||||
let stroke = utils.getValue(this.style, 'imageBorder', null);
|
|
||||||
|
|
||||||
if (fill != null) {
|
if (fill !== NONE) {
|
||||||
// Stroke rendering required for shadow
|
// Stroke rendering required for shadow
|
||||||
c.setFillColor(fill);
|
c.setFillColor(fill);
|
||||||
c.setStrokeColor(stroke);
|
c.setStrokeColor(stroke);
|
||||||
|
@ -151,9 +124,7 @@ class ImageShape extends RectangleShape {
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlipH/V are implicit via mxShape.updateTransform
|
// FlipH/V are implicit via mxShape.updateTransform
|
||||||
c.image(x, y, w, h, this.image, this.preserveImageAspect, false, false);
|
c.image(x, y, w, h, this.imageSrc, this.preserveImageAspect, false, false);
|
||||||
|
|
||||||
stroke = utils.getValue(this.style, 'imageBorder', null);
|
|
||||||
|
|
||||||
if (stroke != null) {
|
if (stroke != null) {
|
||||||
c.setShadow(false);
|
c.setShadow(false);
|
||||||
|
|
|
@ -13,9 +13,11 @@ import {
|
||||||
ALIGN_RIGHT,
|
ALIGN_RIGHT,
|
||||||
ALIGN_TOP,
|
ALIGN_TOP,
|
||||||
DEFAULT_IMAGESIZE,
|
DEFAULT_IMAGESIZE,
|
||||||
|
NONE,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
import RectangleShape from './RectangleShape';
|
import RectangleShape from './RectangleShape';
|
||||||
import utils from '../../../../util/Utils';
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
import AbstractCanvas2D from 'packages/core/src/util/canvas/AbstractCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxLabel
|
* Class: mxLabel
|
||||||
|
@ -37,24 +39,29 @@ import utils from '../../../../util/Utils';
|
||||||
* strokewidth - Optional integer that defines the stroke width. Default is
|
* strokewidth - Optional integer that defines the stroke width. Default is
|
||||||
* 1. This is stored in <strokewidth>.
|
* 1. This is stored in <strokewidth>.
|
||||||
*/
|
*/
|
||||||
class Label extends RectangleShape {
|
class LabelShape extends RectangleShape {
|
||||||
constructor(bounds, fill, stroke, strokewidth) {
|
constructor(
|
||||||
super(bounds, fill, stroke, strokewidth);
|
bounds: Rectangle,
|
||||||
|
fill: ColorValue,
|
||||||
|
stroke: ColorValue,
|
||||||
|
strokeWidth: number
|
||||||
|
) {
|
||||||
|
super(bounds, fill, stroke, strokeWidth);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default width and height for the image.
|
* Default width and height for the image.
|
||||||
* @default mxConstants.DEFAULT_IMAGESIZE
|
* @default mxConstants.DEFAULT_IMAGESIZE
|
||||||
*/
|
*/
|
||||||
// imageSize: number;
|
|
||||||
imageSize = DEFAULT_IMAGESIZE;
|
imageSize = DEFAULT_IMAGESIZE;
|
||||||
|
|
||||||
|
imageSrc: string | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default value for image spacing
|
* Default value for image spacing
|
||||||
* @type {number}
|
* @type {number}
|
||||||
* @default 2
|
* @default 2
|
||||||
*/
|
*/
|
||||||
// spacing: number;
|
|
||||||
spacing = 2;
|
spacing = 2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,7 +69,6 @@ class Label extends RectangleShape {
|
||||||
* @type {number}
|
* @type {number}
|
||||||
* @default 10
|
* @default 10
|
||||||
*/
|
*/
|
||||||
// indicatorSize: number;
|
|
||||||
indicatorSize = 10;
|
indicatorSize = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -70,17 +76,17 @@ class Label extends RectangleShape {
|
||||||
* @default 2
|
* @default 2
|
||||||
* @type {number}
|
* @type {number}
|
||||||
*/
|
*/
|
||||||
// indicatorSpacing: number;
|
|
||||||
indicatorSpacing = 2;
|
indicatorSpacing = 2;
|
||||||
|
|
||||||
|
indicatorImageSrc: string | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the shape and the <indicator>.
|
* Initializes the shape and the <indicator>.
|
||||||
*/
|
*/
|
||||||
// init(container: HTMLElement): void;
|
init(container: SVGElement) {
|
||||||
init(container) {
|
|
||||||
super.init(container);
|
super.init(container);
|
||||||
|
|
||||||
if (this.indicatorShape != null) {
|
if (this.indicatorShape) {
|
||||||
this.indicator = new this.indicatorShape();
|
this.indicator = new this.indicatorShape();
|
||||||
this.indicator.dialect = this.dialect;
|
this.indicator.dialect = this.dialect;
|
||||||
this.indicator.init(this.node);
|
this.indicator.init(this.node);
|
||||||
|
@ -91,9 +97,8 @@ class Label extends RectangleShape {
|
||||||
* Reconfigures this shape. This will update the colors of the indicator
|
* Reconfigures this shape. This will update the colors of the indicator
|
||||||
* and reconfigure it if required.
|
* and reconfigure it if required.
|
||||||
*/
|
*/
|
||||||
// redraw(): void;
|
|
||||||
redraw() {
|
redraw() {
|
||||||
if (this.indicator != null) {
|
if (this.indicator) {
|
||||||
this.indicator.fill = this.indicatorColor;
|
this.indicator.fill = this.indicatorColor;
|
||||||
this.indicator.stroke = this.indicatorStrokeColor;
|
this.indicator.stroke = this.indicatorStrokeColor;
|
||||||
this.indicator.gradient = this.indicatorGradientColor;
|
this.indicator.gradient = this.indicatorGradientColor;
|
||||||
|
@ -107,13 +112,8 @@ class Label extends RectangleShape {
|
||||||
* Returns true for non-rounded, non-rotated shapes with no glass gradient and
|
* Returns true for non-rounded, non-rotated shapes with no glass gradient and
|
||||||
* no indicator shape.
|
* no indicator shape.
|
||||||
*/
|
*/
|
||||||
// isHtmlAllowed(): boolean;
|
|
||||||
isHtmlAllowed() {
|
isHtmlAllowed() {
|
||||||
return (
|
return super.isHtmlAllowed() && this.indicatorColor === NONE && !!this.indicatorShape;
|
||||||
super.isHtmlAllowed() &&
|
|
||||||
this.indicatorColor == null &&
|
|
||||||
this.indicatorShape == null
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -124,8 +124,7 @@ class Label extends RectangleShape {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
// paintForeground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintForeground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintForeground(c, x, y, w, h) {
|
|
||||||
this.paintImage(c, x, y, w, h);
|
this.paintImage(c, x, y, w, h);
|
||||||
this.paintIndicator(c, x, y, w, h);
|
this.paintIndicator(c, x, y, w, h);
|
||||||
super.paintForeground(c, x, y, w, h);
|
super.paintForeground(c, x, y, w, h);
|
||||||
|
@ -139,16 +138,15 @@ class Label extends RectangleShape {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
// paintImage(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintImage(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintImage(c, x, y, w, h) {
|
if (this.imageSrc) {
|
||||||
if (this.image != null) {
|
|
||||||
const bounds = this.getImageBounds(x, y, w, h);
|
const bounds = this.getImageBounds(x, y, w, h);
|
||||||
c.image(
|
c.image(
|
||||||
bounds.x,
|
bounds.x,
|
||||||
bounds.y,
|
bounds.y,
|
||||||
bounds.width,
|
bounds.width,
|
||||||
bounds.height,
|
bounds.height,
|
||||||
this.image,
|
this.imageSrc,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
|
@ -163,26 +161,12 @@ class Label extends RectangleShape {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
// getImageBounds(x: number, y: number, w: number, h: number): mxRectangle;
|
getImageBounds(x: number, y: number, w: number, h: number) {
|
||||||
getImageBounds(x, y, w, h) {
|
const align = this.style?.imageAlign ?? ALIGN_LEFT;
|
||||||
const align = utils.getValue(this.style, 'imageAlign', ALIGN_LEFT);
|
const valign = this.style?.verticalAlign ?? ALIGN_MIDDLE;
|
||||||
const valign = utils.getValue(
|
const width = this.style?.imageWidth ?? DEFAULT_IMAGESIZE;
|
||||||
this.style,
|
const height = this.style?.imageHeight ?? DEFAULT_IMAGESIZE;
|
||||||
'verticalAlign',
|
const spacing = this.style?.spacing ?? this.spacing + 5;
|
||||||
ALIGN_MIDDLE
|
|
||||||
);
|
|
||||||
const width = utils.getNumber(
|
|
||||||
this.style,
|
|
||||||
'imageWidth',
|
|
||||||
DEFAULT_IMAGESIZE
|
|
||||||
);
|
|
||||||
const height = utils.getNumber(
|
|
||||||
this.style,
|
|
||||||
'imageHeight',
|
|
||||||
DEFAULT_IMAGESIZE
|
|
||||||
);
|
|
||||||
const spacing =
|
|
||||||
utils.getNumber(this.style, 'spacing', this.spacing) + 5;
|
|
||||||
|
|
||||||
if (align === ALIGN_CENTER) {
|
if (align === ALIGN_CENTER) {
|
||||||
x += (w - width) / 2;
|
x += (w - width) / 2;
|
||||||
|
@ -213,19 +197,18 @@ class Label extends RectangleShape {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
// paintIndicator(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintIndicator(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintIndicator(c, x, y, w, h) {
|
if (this.indicator) {
|
||||||
if (this.indicator != null) {
|
|
||||||
this.indicator.bounds = this.getIndicatorBounds(x, y, w, h);
|
this.indicator.bounds = this.getIndicatorBounds(x, y, w, h);
|
||||||
this.indicator.paint(c);
|
this.indicator.paint(c);
|
||||||
} else if (this.indicatorImage != null) {
|
} else if (this.indicatorImageSrc) {
|
||||||
const bounds = this.getIndicatorBounds(x, y, w, h);
|
const bounds = this.getIndicatorBounds(x, y, w, h);
|
||||||
c.image(
|
c.image(
|
||||||
bounds.x,
|
bounds.x,
|
||||||
bounds.y,
|
bounds.y,
|
||||||
bounds.width,
|
bounds.width,
|
||||||
bounds.height,
|
bounds.height,
|
||||||
this.indicatorImage,
|
this.indicatorImageSrc,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
|
@ -241,24 +224,11 @@ class Label extends RectangleShape {
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
* @returns {Rectangle}
|
* @returns {Rectangle}
|
||||||
*/
|
*/
|
||||||
// getIndicatorBounds(x: number, y: number, w: number, h: number): mxRectangle;
|
getIndicatorBounds(x: number, y: number, w: number, h: number) {
|
||||||
getIndicatorBounds(x, y, w, h) {
|
const align = this.style?.imageAlign ?? ALIGN_LEFT;
|
||||||
const align = utils.getValue(this.style, 'imageAlign', ALIGN_LEFT);
|
const valign = this.style?.verticalAlign ?? ALIGN_MIDDLE;
|
||||||
const valign = utils.getValue(
|
const width = this.style?.indicatorWidth ?? this.indicatorSize;
|
||||||
this.style,
|
const height = this.style?.indicatorHeight ?? this.indicatorSize;
|
||||||
'verticalAlign',
|
|
||||||
ALIGN_MIDDLE
|
|
||||||
);
|
|
||||||
const width = utils.getNumber(
|
|
||||||
this.style,
|
|
||||||
'indicatorWidth',
|
|
||||||
this.indicatorSize
|
|
||||||
);
|
|
||||||
const height = utils.getNumber(
|
|
||||||
this.style,
|
|
||||||
'indicatorHeight',
|
|
||||||
this.indicatorSize
|
|
||||||
);
|
|
||||||
const spacing = this.spacing + 5;
|
const spacing = this.spacing + 5;
|
||||||
|
|
||||||
if (align === ALIGN_RIGHT) {
|
if (align === ALIGN_RIGHT) {
|
||||||
|
@ -285,16 +255,15 @@ class Label extends RectangleShape {
|
||||||
/**
|
/**
|
||||||
* Generic background painting implementation.
|
* Generic background painting implementation.
|
||||||
*/
|
*/
|
||||||
// redrawHtmlShape(): void;
|
|
||||||
redrawHtmlShape() {
|
redrawHtmlShape() {
|
||||||
super.redrawHtmlShape();
|
super.redrawHtmlShape();
|
||||||
|
|
||||||
// Removes all children
|
// Removes all children
|
||||||
while (this.node.hasChildNodes()) {
|
while (this.node.hasChildNodes()) {
|
||||||
this.node.removeChild(this.node.lastChild);
|
this.node.removeChild(this.node.lastChild as ChildNode);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.image != null) {
|
if (this.imageSrc && this.bounds) {
|
||||||
const node = document.createElement('img');
|
const node = document.createElement('img');
|
||||||
node.style.position = 'relative';
|
node.style.position = 'relative';
|
||||||
node.setAttribute('border', '0');
|
node.setAttribute('border', '0');
|
||||||
|
@ -313,11 +282,11 @@ class Label extends RectangleShape {
|
||||||
node.style.width = `${Math.round(bounds.width)}px`;
|
node.style.width = `${Math.round(bounds.width)}px`;
|
||||||
node.style.height = `${Math.round(bounds.height)}px`;
|
node.style.height = `${Math.round(bounds.height)}px`;
|
||||||
|
|
||||||
node.src = this.image;
|
node.src = this.imageSrc;
|
||||||
|
|
||||||
this.node.appendChild(node);
|
this.node.appendChild(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Label;
|
export default LabelShape;
|
||||||
|
|
|
@ -10,11 +10,10 @@ import {
|
||||||
NONE,
|
NONE,
|
||||||
RECTANGLE_ROUNDING_FACTOR,
|
RECTANGLE_ROUNDING_FACTOR,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
import utils from '../../../../util/Utils';
|
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import mxAbstractCanvas2D from '../../../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement a rectangle shape.
|
* Extends {@link Shape} to implement a rectangle shape.
|
||||||
|
@ -24,84 +23,58 @@ import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
||||||
*/
|
*/
|
||||||
class RectangleShape extends Shape {
|
class RectangleShape extends Shape {
|
||||||
constructor(
|
constructor(
|
||||||
bounds: Rectangle | null = null,
|
bounds: Rectangle,
|
||||||
fill: string | null = '#FFFFFF',
|
fill: ColorValue,
|
||||||
stroke: string | null = '#000000',
|
stroke: ColorValue,
|
||||||
strokewidth: number = 1
|
strokeWidth: number = 1
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Document me!
|
|
||||||
strokewidth: number;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true for non-rounded, non-rotated shapes with no glass gradient.
|
* Returns true for non-rounded, non-rotated shapes with no glass gradient.
|
||||||
*/
|
*/
|
||||||
// isHtmlAllowed(): boolean;
|
isHtmlAllowed() {
|
||||||
isHtmlAllowed(): boolean {
|
|
||||||
let events = true;
|
let events = true;
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
events = utils.getValue(this.style, 'pointerEvents', '1') == '1';
|
events = this.style.pointerEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
!this.isRounded &&
|
!this.isRounded &&
|
||||||
!this.glass &&
|
!this.glass &&
|
||||||
this.rotation === 0 &&
|
this.rotation === 0 &&
|
||||||
(events || (this.fill != null && this.fill !== NONE))
|
(events || this.fill !== NONE)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic background painting implementation.
|
* Generic background painting implementation.
|
||||||
*/
|
*/
|
||||||
// paintBackground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintBackground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintBackground(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
let events = true;
|
let events = true;
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
events = utils.getValue(this.style, 'pointerEvents', '1') == '1';
|
events = this.style.pointerEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (events || this.fill !== NONE || this.stroke !== NONE) {
|
||||||
events ||
|
if (!events && this.fill === NONE) {
|
||||||
(this.fill != null && this.fill !== NONE) ||
|
|
||||||
(this.stroke != null && this.stroke !== NONE)
|
|
||||||
) {
|
|
||||||
if (!events && (this.fill == null || this.fill === NONE)) {
|
|
||||||
c.pointerEvents = false;
|
c.pointerEvents = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isRounded) {
|
if (this.isRounded) {
|
||||||
let r = 0;
|
let r = 0;
|
||||||
|
|
||||||
if (utils.getValue(this.style, 'absoluteArcSize', 0) == '1') {
|
if (this.style?.absoluteArcSize ?? false) {
|
||||||
r = Math.min(
|
r = Math.min(w / 2, Math.min(h / 2, (this.style?.arcSize ?? LINE_ARCSIZE) / 2));
|
||||||
w / 2,
|
|
||||||
Math.min(
|
|
||||||
h / 2,
|
|
||||||
utils.getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const f =
|
const f = (this.style?.arcSize ?? RECTANGLE_ROUNDING_FACTOR * 100) / 100;
|
||||||
utils.getValue(
|
|
||||||
this.style,
|
|
||||||
'arcSize',
|
|
||||||
RECTANGLE_ROUNDING_FACTOR * 100
|
|
||||||
) / 100;
|
|
||||||
r = Math.min(w * f, h * f);
|
r = Math.min(w * f, h * f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,41 +90,22 @@ class RectangleShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Adds roundable support.
|
* Adds roundable support.
|
||||||
*/
|
*/
|
||||||
// isRoundable(c?: mxAbstractCanvas2D, x?: number, y?: number, w?: number, h?: number): boolean;
|
isRoundable(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
isRoundable(
|
|
||||||
c: mxAbstractCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): boolean {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic background painting implementation.
|
* Generic background painting implementation.
|
||||||
*/
|
*/
|
||||||
// paintForeground(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintForeground(c: AbstractCanvas2D, x: number, y: number, w: number, h: number): void {
|
||||||
paintForeground(
|
if (this.glass && !this.outline && this.fill !== NONE) {
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
if (
|
|
||||||
this.glass &&
|
|
||||||
!this.outline &&
|
|
||||||
this.fill != null &&
|
|
||||||
this.fill !== NONE
|
|
||||||
) {
|
|
||||||
this.paintGlassEffect(
|
this.paintGlassEffect(
|
||||||
c,
|
c,
|
||||||
x,
|
x,
|
||||||
y,
|
y,
|
||||||
w,
|
w,
|
||||||
h,
|
h,
|
||||||
this.getArcSize(w + this.strokewidth, h + this.strokewidth)
|
this.getArcSize(w + this.strokeWidth, h + this.strokeWidth)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,9 @@
|
||||||
*/
|
*/
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import utils from '../../../../util/Utils';
|
|
||||||
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement a rhombus (aka diamond) shape.
|
* Extends {@link Shape} to implement a rhombus (aka diamond) shape.
|
||||||
|
@ -18,17 +17,12 @@ import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
||||||
* @extends {Shape}
|
* @extends {Shape}
|
||||||
*/
|
*/
|
||||||
class RhombusShape extends Shape {
|
class RhombusShape extends Shape {
|
||||||
constructor(
|
constructor(bounds: Rectangle, fill: string, stroke: string, strokewidth: number = 1) {
|
||||||
bounds: Rectangle,
|
|
||||||
fill: string,
|
|
||||||
stroke: string,
|
|
||||||
strokewidth: number = 1
|
|
||||||
) {
|
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth;
|
this.strokeWidth = strokewidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,19 +41,12 @@ class RhombusShape extends Shape {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
// paintVertexShape(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintVertexShape(
|
|
||||||
c: mxSvgCanvas2D,
|
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
) {
|
|
||||||
const hw = w / 2;
|
const hw = w / 2;
|
||||||
const hh = h / 2;
|
const hh = h / 2;
|
||||||
|
|
||||||
const arcSize =
|
const arcSize = (this.style?.arcSize ?? LINE_ARCSIZE) / 2;
|
||||||
utils.getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2;
|
|
||||||
c.begin();
|
c.begin();
|
||||||
this.addPoints(
|
this.addPoints(
|
||||||
c,
|
c,
|
||||||
|
|
|
@ -9,18 +9,22 @@ import ConnectionConstraint from '../../../connection/ConnectionConstraint';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import Resources from '../../../../util/Resources';
|
import Resources from '../../../../util/Resources';
|
||||||
import utils, { getNumber, getValue, isNotNullish } from '../../../../util/Utils';
|
import { getNumber, getValue, isNotNullish } from '../../../../util/Utils';
|
||||||
import {
|
import {
|
||||||
|
ALIGN_LEFT,
|
||||||
|
ALIGN_TOP,
|
||||||
DIRECTION_NORTH,
|
DIRECTION_NORTH,
|
||||||
DIRECTION_SOUTH,
|
DIRECTION_SOUTH,
|
||||||
NODETYPE_ELEMENT,
|
NODETYPE_ELEMENT,
|
||||||
NONE,
|
NONE,
|
||||||
RECTANGLE_ROUNDING_FACTOR,
|
RECTANGLE_ROUNDING_FACTOR,
|
||||||
|
TEXT_DIRECTION_AUTO,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
import StencilShapeRegistry from './StencilShapeRegistry';
|
import StencilShapeRegistry from './StencilShapeRegistry';
|
||||||
import { getChildNodes, getTextContent } from '../../../../util/DomUtils';
|
import { getChildNodes, getTextContent } from '../../../../util/DomUtils';
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
|
import { AlignValue, ColorValue, VAlignValue } from 'packages/core/src/types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implements a generic shape which is based on a XML node as a description.
|
* Implements a generic shape which is based on a XML node as a description.
|
||||||
|
@ -107,7 +111,7 @@ class StencilShape extends Shape {
|
||||||
*
|
*
|
||||||
* Holds the strokewidth direction from the description.
|
* Holds the strokewidth direction from the description.
|
||||||
*/
|
*/
|
||||||
strokeWidth: string | null = null;
|
strokeWidthValue: string | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: parseDescription
|
* Function: parseDescription
|
||||||
|
@ -132,7 +136,7 @@ class StencilShape extends Shape {
|
||||||
// user-defined stroke-width). Note that the strokewidth is scaled
|
// user-defined stroke-width). Note that the strokewidth is scaled
|
||||||
// by the minimum scaling that is used to draw the shape (sx, sy).
|
// by the minimum scaling that is used to draw the shape (sx, sy).
|
||||||
const sw = this.desc.getAttribute('strokewidth');
|
const sw = this.desc.getAttribute('strokewidth');
|
||||||
this.strokeWidth = isNotNullish(sw) ? sw : '1';
|
this.strokeWidthValue = isNotNullish(sw) ? sw : '1';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,10 +148,10 @@ class StencilShape extends Shape {
|
||||||
parseConstraints() {
|
parseConstraints() {
|
||||||
const conns = this.desc.getElementsByTagName('connections')[0];
|
const conns = this.desc.getElementsByTagName('connections')[0];
|
||||||
|
|
||||||
if (conns != null) {
|
if (conns) {
|
||||||
const tmp = getChildNodes(conns);
|
const tmp = getChildNodes(conns);
|
||||||
|
|
||||||
if (tmp != null && tmp.length > 0) {
|
if (tmp.length > 0) {
|
||||||
this.constraints = [];
|
this.constraints = [];
|
||||||
|
|
||||||
for (let i = 0; i < tmp.length; i += 1) {
|
for (let i = 0; i < tmp.length; i += 1) {
|
||||||
|
@ -165,7 +169,7 @@ class StencilShape extends Shape {
|
||||||
parseConstraint(node: Element) {
|
parseConstraint(node: Element) {
|
||||||
const x = Number(node.getAttribute('x'));
|
const x = Number(node.getAttribute('x'));
|
||||||
const y = Number(node.getAttribute('y'));
|
const y = Number(node.getAttribute('y'));
|
||||||
const perimeter = node.getAttribute('perimeter') == '1';
|
const perimeter = node.getAttribute('perimeter') === '1';
|
||||||
const name = node.getAttribute('name');
|
const name = node.getAttribute('name');
|
||||||
|
|
||||||
return new ConnectionConstraint(new Point(x, y), perimeter, name);
|
return new ConnectionConstraint(new Point(x, y), perimeter, name);
|
||||||
|
@ -182,7 +186,7 @@ class StencilShape extends Shape {
|
||||||
let result = this.evaluateAttribute(node, attribute, shape);
|
let result = this.evaluateAttribute(node, attribute, shape);
|
||||||
const loc = node.getAttribute('localized');
|
const loc = node.getAttribute('localized');
|
||||||
|
|
||||||
if ((StencilShape.defaultLocalized && loc == null) || loc == '1') {
|
if ((StencilShape.defaultLocalized && !loc) || loc === '1') {
|
||||||
result = Resources.get(result);
|
result = Resources.get(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,10 +204,10 @@ class StencilShape extends Shape {
|
||||||
evaluateAttribute(node: Element, attribute: string, shape: Shape) {
|
evaluateAttribute(node: Element, attribute: string, shape: Shape) {
|
||||||
let result = node.getAttribute(attribute);
|
let result = node.getAttribute(attribute);
|
||||||
|
|
||||||
if (result == null) {
|
if (!result) {
|
||||||
const text = getTextContent(node);
|
const text = getTextContent(node);
|
||||||
|
|
||||||
if (text != null && StencilShape.allowEval) {
|
if (text && StencilShape.allowEval) {
|
||||||
const funct = eval(text);
|
const funct = eval(text);
|
||||||
|
|
||||||
if (typeof funct === 'function') {
|
if (typeof funct === 'function') {
|
||||||
|
@ -221,7 +225,7 @@ class StencilShape extends Shape {
|
||||||
* Draws this stencil inside the given bounds.
|
* Draws this stencil inside the given bounds.
|
||||||
*/
|
*/
|
||||||
drawShape(
|
drawShape(
|
||||||
canvas: mxSvgCanvas2D,
|
canvas: AbstractCanvas2D,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
|
@ -240,34 +244,20 @@ class StencilShape extends Shape {
|
||||||
const aspect = this.computeAspect(shape, x, y, w, h, direction);
|
const aspect = this.computeAspect(shape, x, y, w, h, direction);
|
||||||
const minScale = Math.min(aspect.width, aspect.height);
|
const minScale = Math.min(aspect.width, aspect.height);
|
||||||
const sw =
|
const sw =
|
||||||
this.strokeWidth == 'inherit'
|
this.strokeWidthValue === 'inherit'
|
||||||
? Number(getNumber(shape.style, 'strokeWidth', 1))
|
? Number(getNumber(shape.style, 'strokeWidth', 1))
|
||||||
: Number(this.strokeWidth) * minScale;
|
: Number(this.strokeWidthValue) * minScale;
|
||||||
canvas.setStrokeWidth(sw);
|
canvas.setStrokeWidth(sw);
|
||||||
|
|
||||||
// Draws a transparent rectangle for catching events
|
// Draws a transparent rectangle for catching events
|
||||||
if (
|
if (shape.style?.pointerEvents ?? false) {
|
||||||
shape.style != null &&
|
|
||||||
getValue(shape.style, 'pointerEvents', '0') == '1'
|
|
||||||
) {
|
|
||||||
canvas.setStrokeColor(NONE);
|
canvas.setStrokeColor(NONE);
|
||||||
canvas.rect(x, y, w, h);
|
canvas.rect(x, y, w, h);
|
||||||
canvas.stroke();
|
canvas.stroke();
|
||||||
canvas.setStrokeColor(shape.stroke);
|
canvas.setStrokeColor(shape.stroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.drawChildren(
|
this.drawChildren(canvas, shape, x, y, w, h, this.bgNode, aspect, false, true);
|
||||||
canvas,
|
|
||||||
shape,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
w,
|
|
||||||
h,
|
|
||||||
this.bgNode,
|
|
||||||
aspect,
|
|
||||||
false,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
this.drawChildren(
|
this.drawChildren(
|
||||||
canvas,
|
canvas,
|
||||||
shape,
|
shape,
|
||||||
|
@ -295,26 +285,26 @@ class StencilShape extends Shape {
|
||||||
* Draws this stencil inside the given bounds.
|
* Draws this stencil inside the given bounds.
|
||||||
*/
|
*/
|
||||||
drawChildren(
|
drawChildren(
|
||||||
canvas: mxSvgCanvas2D,
|
canvas: AbstractCanvas2D,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
x: number,
|
x: number,
|
||||||
y: number,
|
y: number,
|
||||||
w: number,
|
w: number,
|
||||||
h: number,
|
h: number,
|
||||||
node: Element | null,
|
node: Element | null,
|
||||||
aspect: string,
|
aspect: Rectangle,
|
||||||
disableShadow: boolean,
|
disableShadow: boolean,
|
||||||
paint: boolean
|
paint: boolean
|
||||||
) {
|
) {
|
||||||
if (node != null && w > 0 && h > 0) {
|
if (node && w > 0 && h > 0) {
|
||||||
let tmp = node.firstChild;
|
let tmp = node.firstChild as Element;
|
||||||
|
|
||||||
while (tmp != null) {
|
while (tmp) {
|
||||||
if (tmp.nodeType === NODETYPE_ELEMENT) {
|
if (tmp.nodeType === NODETYPE_ELEMENT) {
|
||||||
this.drawNode(canvas, shape, tmp, aspect, disableShadow, paint);
|
this.drawNode(canvas, shape, tmp, aspect, disableShadow, paint);
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp = tmp.nextSibling;
|
tmp = tmp.nextSibling as Element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -345,8 +335,7 @@ class StencilShape extends Shape {
|
||||||
let sx = w / this.w0;
|
let sx = w / this.w0;
|
||||||
let sy = h / this.h0;
|
let sy = h / this.h0;
|
||||||
|
|
||||||
const inverse =
|
const inverse = direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH;
|
||||||
direction === DIRECTION_NORTH || direction === DIRECTION_SOUTH;
|
|
||||||
|
|
||||||
if (inverse) {
|
if (inverse) {
|
||||||
sy = w / this.h0;
|
sy = w / this.h0;
|
||||||
|
@ -381,7 +370,7 @@ class StencilShape extends Shape {
|
||||||
* Draws this stencil inside the given bounds.
|
* Draws this stencil inside the given bounds.
|
||||||
*/
|
*/
|
||||||
drawNode(
|
drawNode(
|
||||||
canvas: mxSvgCanvas2D,
|
canvas: AbstractCanvas2D,
|
||||||
shape: Shape,
|
shape: Shape,
|
||||||
node: Element,
|
node: Element,
|
||||||
aspect: Rectangle,
|
aspect: Rectangle,
|
||||||
|
@ -410,10 +399,10 @@ class StencilShape extends Shape {
|
||||||
|
|
||||||
const arcSize = Number(node.getAttribute('arcSize'));
|
const arcSize = Number(node.getAttribute('arcSize'));
|
||||||
let pointCount = 0;
|
let pointCount = 0;
|
||||||
const segs = [];
|
const segs: Point[][] = [];
|
||||||
|
|
||||||
// Renders the elements inside the given path
|
// Renders the elements inside the given path
|
||||||
let childNode = node.firstChild;
|
let childNode = node.firstChild as Element;
|
||||||
|
|
||||||
while (childNode != null) {
|
while (childNode != null) {
|
||||||
if (childNode.nodeType === NODETYPE_ELEMENT) {
|
if (childNode.nodeType === NODETYPE_ELEMENT) {
|
||||||
|
@ -438,7 +427,7 @@ class StencilShape extends Shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
childNode = childNode.nextSibling;
|
childNode = childNode.nextSibling as Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!parseRegularly && pointCount > 0) {
|
if (!parseRegularly && pointCount > 0) {
|
||||||
|
@ -461,21 +450,14 @@ class StencilShape extends Shape {
|
||||||
|
|
||||||
if (parseRegularly) {
|
if (parseRegularly) {
|
||||||
// Renders the elements inside the given path
|
// Renders the elements inside the given path
|
||||||
let childNode = node.firstChild;
|
let childNode = node.firstChild as Element;
|
||||||
|
|
||||||
while (childNode != null) {
|
while (childNode) {
|
||||||
if (childNode.nodeType === NODETYPE_ELEMENT) {
|
if (childNode.nodeType === NODETYPE_ELEMENT) {
|
||||||
this.drawNode(
|
this.drawNode(canvas, shape, childNode, aspect, disableShadow, paint);
|
||||||
canvas,
|
|
||||||
shape,
|
|
||||||
childNode,
|
|
||||||
aspect,
|
|
||||||
disableShadow,
|
|
||||||
paint
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
childNode = childNode.nextSibling;
|
childNode = childNode.nextSibling as Element;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (name === 'close') {
|
} else if (name === 'close') {
|
||||||
|
@ -512,7 +494,7 @@ class StencilShape extends Shape {
|
||||||
Number(node.getAttribute('ry')) * sy,
|
Number(node.getAttribute('ry')) * sy,
|
||||||
Number(node.getAttribute('x-axis-rotation')),
|
Number(node.getAttribute('x-axis-rotation')),
|
||||||
Boolean(node.getAttribute('large-arc-flag')),
|
Boolean(node.getAttribute('large-arc-flag')),
|
||||||
Number(node.getAttribute('sweep-flag')),
|
Boolean(node.getAttribute('sweep-flag')),
|
||||||
x0 + Number(node.getAttribute('x')) * sx,
|
x0 + Number(node.getAttribute('x')) * sx,
|
||||||
y0 + Number(node.getAttribute('y')) * sy
|
y0 + Number(node.getAttribute('y')) * sy
|
||||||
);
|
);
|
||||||
|
@ -552,7 +534,7 @@ class StencilShape extends Shape {
|
||||||
);
|
);
|
||||||
} else if (name === 'image') {
|
} else if (name === 'image') {
|
||||||
if (!shape.outline) {
|
if (!shape.outline) {
|
||||||
const src = this.evaluateAttribute(node, 'src', shape);
|
const src = this.evaluateAttribute(node, 'src', shape) as string;
|
||||||
|
|
||||||
canvas.image(
|
canvas.image(
|
||||||
x0 + Number(node.getAttribute('x')) * sx,
|
x0 + Number(node.getAttribute('x')) * sx,
|
||||||
|
@ -567,10 +549,10 @@ class StencilShape extends Shape {
|
||||||
}
|
}
|
||||||
} else if (name === 'text') {
|
} else if (name === 'text') {
|
||||||
if (!shape.outline) {
|
if (!shape.outline) {
|
||||||
const str = this.evaluateTextAttribute(node, 'str', shape);
|
const str = this.evaluateTextAttribute(node, 'str', shape) as string;
|
||||||
let rotation = node.getAttribute('vertical') == '1' ? -90 : 0;
|
let rotation = node.getAttribute('vertical') == '1' ? -90 : 0;
|
||||||
|
|
||||||
if (node.getAttribute('align-shape') == '0') {
|
if (node.getAttribute('align-shape') === '0') {
|
||||||
const dr = shape.rotation;
|
const dr = shape.rotation;
|
||||||
|
|
||||||
// Depends on flipping
|
// Depends on flipping
|
||||||
|
@ -586,7 +568,7 @@ class StencilShape extends Shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rotation -= node.getAttribute('rotation');
|
rotation -= Number(node.getAttribute('rotation'));
|
||||||
|
|
||||||
canvas.text(
|
canvas.text(
|
||||||
x0 + Number(node.getAttribute('x')) * sx,
|
x0 + Number(node.getAttribute('x')) * sx,
|
||||||
|
@ -594,19 +576,22 @@ class StencilShape extends Shape {
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
str,
|
str,
|
||||||
node.getAttribute('align') || 'left',
|
(node.getAttribute('align') as AlignValue) || ALIGN_LEFT,
|
||||||
node.getAttribute('valign') || 'top',
|
(node.getAttribute('valign') as VAlignValue) || ALIGN_TOP,
|
||||||
false,
|
false,
|
||||||
'',
|
'',
|
||||||
null,
|
'auto',
|
||||||
false,
|
false,
|
||||||
rotation
|
rotation,
|
||||||
|
TEXT_DIRECTION_AUTO
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else if (name === 'include-shape') {
|
} else if (name === 'include-shape') {
|
||||||
const stencil = StencilShapeRegistry.getStencil(node.getAttribute('name'));
|
const stencil = StencilShapeRegistry.getStencil(
|
||||||
|
node.getAttribute('name') as string
|
||||||
|
);
|
||||||
|
|
||||||
if (stencil != null) {
|
if (stencil) {
|
||||||
const x = x0 + Number(node.getAttribute('x')) * sx;
|
const x = x0 + Number(node.getAttribute('x')) * sx;
|
||||||
const y = y0 + Number(node.getAttribute('y')) * sy;
|
const y = y0 + Number(node.getAttribute('y')) * sy;
|
||||||
const w = Number(node.getAttribute('w')) * sx;
|
const w = Number(node.getAttribute('w')) * sx;
|
||||||
|
@ -642,27 +627,27 @@ class StencilShape extends Shape {
|
||||||
canvas.setDashPattern(value);
|
canvas.setDashPattern(value);
|
||||||
}
|
}
|
||||||
} else if (name === 'strokecolor') {
|
} else if (name === 'strokecolor') {
|
||||||
canvas.setStrokeColor(node.getAttribute('color'));
|
canvas.setStrokeColor(node.getAttribute('color') as ColorValue);
|
||||||
} else if (name === 'linecap') {
|
} else if (name === 'linecap') {
|
||||||
canvas.setLineCap(node.getAttribute('cap'));
|
canvas.setLineCap(node.getAttribute('cap') as string);
|
||||||
} else if (name === 'linejoin') {
|
} else if (name === 'linejoin') {
|
||||||
canvas.setLineJoin(node.getAttribute('join'));
|
canvas.setLineJoin(node.getAttribute('join') as string);
|
||||||
} else if (name === 'miterlimit') {
|
} else if (name === 'miterlimit') {
|
||||||
canvas.setMiterLimit(Number(node.getAttribute('limit')));
|
canvas.setMiterLimit(Number(node.getAttribute('limit')));
|
||||||
} else if (name === 'fillcolor') {
|
} else if (name === 'fillcolor') {
|
||||||
canvas.setFillColor(node.getAttribute('color'));
|
canvas.setFillColor(node.getAttribute('color') as ColorValue);
|
||||||
} else if (name === 'alpha') {
|
} else if (name === 'alpha') {
|
||||||
canvas.setAlpha(node.getAttribute('alpha'));
|
canvas.setAlpha(Number(node.getAttribute('alpha')));
|
||||||
} else if (name === 'fillalpha') {
|
} else if (name === 'fillalpha') {
|
||||||
canvas.setAlpha(node.getAttribute('alpha'));
|
canvas.setAlpha(Number(node.getAttribute('alpha')));
|
||||||
} else if (name === 'strokealpha') {
|
} else if (name === 'strokealpha') {
|
||||||
canvas.setAlpha(node.getAttribute('alpha'));
|
canvas.setAlpha(Number(node.getAttribute('alpha')));
|
||||||
} else if (name === 'fontcolor') {
|
} else if (name === 'fontcolor') {
|
||||||
canvas.setFontColor(node.getAttribute('color'));
|
canvas.setFontColor(node.getAttribute('color') as ColorValue);
|
||||||
} else if (name === 'fontstyle') {
|
} else if (name === 'fontstyle') {
|
||||||
canvas.setFontStyle(node.getAttribute('style'));
|
canvas.setFontStyle(Number(node.getAttribute('style')));
|
||||||
} else if (name === 'fontfamily') {
|
} else if (name === 'fontfamily') {
|
||||||
canvas.setFontFamily(node.getAttribute('family'));
|
canvas.setFontFamily(node.getAttribute('family') as string);
|
||||||
} else if (name === 'fontsize') {
|
} else if (name === 'fontsize') {
|
||||||
canvas.setFontSize(Number(node.getAttribute('size')) * minScale);
|
canvas.setFontSize(Number(node.getAttribute('size')) * minScale);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ import {
|
||||||
NONE,
|
NONE,
|
||||||
RECTANGLE_ROUNDING_FACTOR,
|
RECTANGLE_ROUNDING_FACTOR,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
import utils from '../../../../util/Utils';
|
import { ColorValue } from 'packages/core/src/types';
|
||||||
|
import AbstractCanvas2D from 'packages/core/src/util/canvas/AbstractCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends {@link Shape} to implement a swimlane shape.
|
* Extends {@link Shape} to implement a swimlane shape.
|
||||||
|
@ -32,12 +33,12 @@ import utils from '../../../../util/Utils';
|
||||||
* @extends {Shape}
|
* @extends {Shape}
|
||||||
*/
|
*/
|
||||||
class SwimlaneShape extends Shape {
|
class SwimlaneShape extends Shape {
|
||||||
constructor(bounds, fill, stroke, strokewidth) {
|
constructor(bounds: Rectangle, fill: ColorValue, stroke: ColorValue, strokeWidth = 1) {
|
||||||
super();
|
super();
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
this.fill = fill;
|
this.fill = fill;
|
||||||
this.stroke = stroke;
|
this.stroke = stroke;
|
||||||
this.strokewidth = strokewidth != null ? strokewidth : 1;
|
this.strokeWidth = strokeWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,9 +48,10 @@ class SwimlaneShape extends Shape {
|
||||||
* @type {number}
|
* @type {number}
|
||||||
* @default 16
|
* @default 16
|
||||||
*/
|
*/
|
||||||
// imageSize: number;
|
|
||||||
imageSize = 16;
|
imageSize = 16;
|
||||||
|
|
||||||
|
imageSrc: string | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds roundable support.
|
* Adds roundable support.
|
||||||
* @param {mxAbstractCanvas2D} c
|
* @param {mxAbstractCanvas2D} c
|
||||||
|
@ -59,33 +61,27 @@ class SwimlaneShape extends Shape {
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
// isRoundable(c?: mxAbstractCanvas2D, x?: number, y?: number, w?: number, h?: number): boolean;
|
isRoundable(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
isRoundable(c, x, y, w, h) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bounding box for the gradient box for this shape.
|
* Returns the bounding box for the gradient box for this shape.
|
||||||
*/
|
*/
|
||||||
// getTitleSize(): number;
|
|
||||||
getTitleSize() {
|
getTitleSize() {
|
||||||
return Math.max(
|
return Math.max(0, this.style?.startSize ?? DEFAULT_STARTSIZE);
|
||||||
0,
|
|
||||||
utils.getValue(this.style, 'startSize', DEFAULT_STARTSIZE)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bounding box for the gradient box for this shape.
|
* Returns the bounding box for the gradient box for this shape.
|
||||||
*/
|
*/
|
||||||
// getLabelBounds(rect: mxRectangle): mxRectangle;
|
getLabelBounds(rect: Rectangle) {
|
||||||
getLabelBounds(rect) {
|
|
||||||
const start = this.getTitleSize();
|
const start = this.getTitleSize();
|
||||||
const bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
|
const bounds = new Rectangle(rect.x, rect.y, rect.width, rect.height);
|
||||||
const horizontal = this.isHorizontal();
|
const horizontal = this.isHorizontal();
|
||||||
|
|
||||||
const flipH = utils.getValue(this.style, 'flipH', 0) == 1;
|
const flipH = this.style?.flipH ?? false;
|
||||||
const flipV = utils.getValue(this.style, 'flipV', 0) == 1;
|
const flipV = this.style?.flipV ?? false;
|
||||||
|
|
||||||
// East is default
|
// East is default
|
||||||
const shapeVertical =
|
const shapeVertical =
|
||||||
|
@ -94,14 +90,10 @@ class SwimlaneShape extends Shape {
|
||||||
|
|
||||||
const realFlipH =
|
const realFlipH =
|
||||||
!realHorizontal &&
|
!realHorizontal &&
|
||||||
flipH !=
|
flipH !== (this.direction === DIRECTION_SOUTH || this.direction === DIRECTION_WEST);
|
||||||
(this.direction === DIRECTION_SOUTH ||
|
|
||||||
this.direction === DIRECTION_WEST);
|
|
||||||
const realFlipV =
|
const realFlipV =
|
||||||
realHorizontal &&
|
realHorizontal &&
|
||||||
flipV !=
|
flipV !== (this.direction === DIRECTION_SOUTH || this.direction === DIRECTION_WEST);
|
||||||
(this.direction === DIRECTION_SOUTH ||
|
|
||||||
this.direction === DIRECTION_WEST);
|
|
||||||
|
|
||||||
// Shape is horizontal
|
// Shape is horizontal
|
||||||
if (!shapeVertical) {
|
if (!shapeVertical) {
|
||||||
|
@ -128,8 +120,7 @@ class SwimlaneShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Returns the bounding box for the gradient box for this shape.
|
* Returns the bounding box for the gradient box for this shape.
|
||||||
*/
|
*/
|
||||||
// getGradientBounds(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): mxRectangle;
|
getGradientBounds(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
getGradientBounds(c, x, y, w, h) {
|
|
||||||
let start = this.getTitleSize();
|
let start = this.getTitleSize();
|
||||||
|
|
||||||
if (this.isHorizontal()) {
|
if (this.isHorizontal()) {
|
||||||
|
@ -145,22 +136,11 @@ class SwimlaneShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns the arcsize for the swimlane.
|
* Returns the arcsize for the swimlane.
|
||||||
*/
|
*/
|
||||||
getSwimlaneArcSize(w, h, start) {
|
getSwimlaneArcSize(w: number, h: number, start: number) {
|
||||||
if (utils.getValue(this.style, 'absoluteArcSize', 0) == '1') {
|
if (this.style?.absoluteArcSize ?? false) {
|
||||||
return Math.min(
|
return Math.min(w / 2, Math.min(h / 2, this.style?.arcSize ?? LINE_ARCSIZE / 2));
|
||||||
w / 2,
|
|
||||||
Math.min(
|
|
||||||
h / 2,
|
|
||||||
utils.getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
const f =
|
const f = (this.style?.arcSize ?? RECTANGLE_ROUNDING_FACTOR * 100) / 100;
|
||||||
utils.getValue(
|
|
||||||
this.style,
|
|
||||||
'arcSize',
|
|
||||||
RECTANGLE_ROUNDING_FACTOR * 100
|
|
||||||
) / 100;
|
|
||||||
|
|
||||||
return start * f * 3;
|
return start * f * 3;
|
||||||
}
|
}
|
||||||
|
@ -168,20 +148,17 @@ class SwimlaneShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Paints the swimlane vertex shape.
|
* Paints the swimlane vertex shape.
|
||||||
*/
|
*/
|
||||||
// isHorizontal(): boolean;
|
|
||||||
isHorizontal() {
|
isHorizontal() {
|
||||||
return utils.getValue(this.style, 'horizontal', 1) == 1;
|
return this.style?.horizontal ?? true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Paints the swimlane vertex shape.
|
* Paints the swimlane vertex shape.
|
||||||
*/
|
*/
|
||||||
// paintVertexShape(c: mxAbstractCanvas2D, x: number, y: number, w: number, h: number): void;
|
paintVertexShape(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
paintVertexShape(c, x, y, w, h) {
|
|
||||||
let start = this.getTitleSize();
|
let start = this.getTitleSize();
|
||||||
const fill = utils.getValue(this.style, 'swimlaneFillColor', NONE);
|
const fill = this.style?.swimlaneFillColor ?? NONE;
|
||||||
const swimlaneLine =
|
const swimlaneLine = this.style?.swimlaneLine ?? true;
|
||||||
utils.getValue(this.style, 'swimlaneLine', 1) == 1;
|
|
||||||
let r = 0;
|
let r = 0;
|
||||||
|
|
||||||
if (this.isHorizontal()) {
|
if (this.isHorizontal()) {
|
||||||
|
@ -200,17 +177,17 @@ class SwimlaneShape extends Shape {
|
||||||
this.paintRoundedSwimlane(c, x, y, w, h, start, r, fill, swimlaneLine);
|
this.paintRoundedSwimlane(c, x, y, w, h, start, r, fill, swimlaneLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
const sep = utils.getValue(this.style, 'separatorColor', NONE);
|
const sep = this.style?.separatorColor ?? NONE;
|
||||||
this.paintSeparator(c, x, y, w, h, start, sep);
|
this.paintSeparator(c, x, y, w, h, start, sep);
|
||||||
|
|
||||||
if (this.image != null) {
|
if (this.imageSrc) {
|
||||||
const bounds = this.getImageBounds(x, y, w, h);
|
const bounds = this.getImageBounds(x, y, w, h);
|
||||||
c.image(
|
c.image(
|
||||||
bounds.x - x,
|
bounds.x - x,
|
||||||
bounds.y - y,
|
bounds.y - y,
|
||||||
bounds.width,
|
bounds.width,
|
||||||
bounds.height,
|
bounds.height,
|
||||||
this.image,
|
this.imageSrc,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false
|
false
|
||||||
|
@ -228,16 +205,25 @@ class SwimlaneShape extends Shape {
|
||||||
*
|
*
|
||||||
* Paints the swimlane vertex shape.
|
* Paints the swimlane vertex shape.
|
||||||
*/
|
*/
|
||||||
paintSwimlane(c, x, y, w, h, start, fill, swimlaneLine) {
|
paintSwimlane(
|
||||||
|
c: AbstractCanvas2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
start: number,
|
||||||
|
fill: ColorValue,
|
||||||
|
swimlaneLine: boolean
|
||||||
|
) {
|
||||||
c.begin();
|
c.begin();
|
||||||
|
|
||||||
let events = true;
|
let events = true;
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
events = utils.getValue(this.style, 'pointerEvents', '1') == '1';
|
events = this.style.pointerEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!events && (this.fill == null || this.fill === NONE)) {
|
if (!events && this.fill === NONE) {
|
||||||
c.pointerEvents = false;
|
c.pointerEvents = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,16 +295,26 @@ class SwimlaneShape extends Shape {
|
||||||
*
|
*
|
||||||
* Paints the swimlane vertex shape.
|
* Paints the swimlane vertex shape.
|
||||||
*/
|
*/
|
||||||
paintRoundedSwimlane(c, x, y, w, h, start, r, fill, swimlaneLine) {
|
paintRoundedSwimlane(
|
||||||
|
c: AbstractCanvas2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
start: number,
|
||||||
|
r: number,
|
||||||
|
fill: ColorValue,
|
||||||
|
swimlaneLine: boolean
|
||||||
|
) {
|
||||||
c.begin();
|
c.begin();
|
||||||
|
|
||||||
let events = true;
|
let events = true;
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
events = utils.getValue(this.style, 'pointerEvents', '1') == '1';
|
events = this.style.pointerEvents;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!events && (this.fill == null || this.fill === NONE)) {
|
if (!events && this.fill === NONE) {
|
||||||
c.pointerEvents = false;
|
c.pointerEvents = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -398,7 +394,15 @@ class SwimlaneShape extends Shape {
|
||||||
*
|
*
|
||||||
* Paints the divider between swimlane title and content area.
|
* Paints the divider between swimlane title and content area.
|
||||||
*/
|
*/
|
||||||
paintDivider(c, x, y, w, h, start, shadow) {
|
paintDivider(
|
||||||
|
c: AbstractCanvas2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
start: number,
|
||||||
|
shadow: boolean
|
||||||
|
) {
|
||||||
if (!shadow) {
|
if (!shadow) {
|
||||||
c.setShadow(false);
|
c.setShadow(false);
|
||||||
}
|
}
|
||||||
|
@ -421,7 +425,15 @@ class SwimlaneShape extends Shape {
|
||||||
*
|
*
|
||||||
* Paints the vertical or horizontal separator line between swimlanes.
|
* Paints the vertical or horizontal separator line between swimlanes.
|
||||||
*/
|
*/
|
||||||
paintSeparator(c, x, y, w, h, start, color) {
|
paintSeparator(
|
||||||
|
c: AbstractCanvas2D,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
w: number,
|
||||||
|
h: number,
|
||||||
|
start: number,
|
||||||
|
color: ColorValue
|
||||||
|
) {
|
||||||
if (color !== NONE) {
|
if (color !== NONE) {
|
||||||
c.setStrokeColor(color);
|
c.setStrokeColor(color);
|
||||||
c.setDashed(true);
|
c.setDashed(true);
|
||||||
|
@ -443,15 +455,9 @@ class SwimlaneShape extends Shape {
|
||||||
/**
|
/**
|
||||||
* Paints the swimlane vertex shape.
|
* Paints the swimlane vertex shape.
|
||||||
*/
|
*/
|
||||||
// getImageBounds(x: number, y: number, w: number, h: number): mxRectangle;
|
getImageBounds(x: number, y: number, w: number, h: number) {
|
||||||
getImageBounds(x, y, w, h) {
|
|
||||||
if (this.isHorizontal()) {
|
if (this.isHorizontal()) {
|
||||||
return new Rectangle(
|
return new Rectangle(x + w - this.imageSize, y, this.imageSize, this.imageSize);
|
||||||
x + w - this.imageSize,
|
|
||||||
y,
|
|
||||||
this.imageSize,
|
|
||||||
this.imageSize
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return new Rectangle(x, y, this.imageSize, this.imageSize);
|
return new Rectangle(x, y, this.imageSize, this.imageSize);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,22 +24,31 @@ import {
|
||||||
LINE_HEIGHT,
|
LINE_HEIGHT,
|
||||||
NONE,
|
NONE,
|
||||||
TEXT_DIRECTION_AUTO,
|
TEXT_DIRECTION_AUTO,
|
||||||
|
TEXT_DIRECTION_DEFAULT,
|
||||||
TEXT_DIRECTION_LTR,
|
TEXT_DIRECTION_LTR,
|
||||||
TEXT_DIRECTION_RTL,
|
TEXT_DIRECTION_RTL,
|
||||||
WORD_WRAP,
|
WORD_WRAP,
|
||||||
} from '../../../../util/Constants';
|
} from '../../../../util/Constants';
|
||||||
import utils, {
|
import { getAlignmentAsPoint, getBoundingBox } from '../../../../util/Utils';
|
||||||
getAlignmentAsPoint,
|
|
||||||
getBoundingBox,
|
|
||||||
getValue,
|
|
||||||
} from '../../../../util/Utils';
|
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from '../../../../util/canvas/AbstractCanvas2D';
|
||||||
import Shape from '../Shape';
|
import Shape from '../Shape';
|
||||||
import Rectangle from '../../Rectangle';
|
import Rectangle from '../../Rectangle';
|
||||||
import CellState from '../../../cell/datatypes/CellState';
|
import CellState from '../../../cell/datatypes/CellState';
|
||||||
import { htmlEntities, replaceTrailingNewlines, trim } from '../../../../util/StringUtils';
|
import {
|
||||||
|
htmlEntities,
|
||||||
|
replaceTrailingNewlines,
|
||||||
|
trim,
|
||||||
|
} from '../../../../util/StringUtils';
|
||||||
import { isNode } from '../../../../util/DomUtils';
|
import { isNode } from '../../../../util/DomUtils';
|
||||||
|
import {
|
||||||
|
AlignValue,
|
||||||
|
ColorValue,
|
||||||
|
OverflowValue,
|
||||||
|
TextDirectionValue,
|
||||||
|
VAlignValue,
|
||||||
|
} from 'packages/core/src/types';
|
||||||
|
import SvgCanvas2D from 'packages/core/src/util/canvas/SvgCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extends mxShape to implement a text shape.
|
* Extends mxShape to implement a text shape.
|
||||||
|
@ -56,28 +65,27 @@ class TextShape extends Shape {
|
||||||
constructor(
|
constructor(
|
||||||
value: string,
|
value: string,
|
||||||
bounds: Rectangle,
|
bounds: Rectangle,
|
||||||
align: string = ALIGN_CENTER,
|
align: AlignValue = ALIGN_CENTER,
|
||||||
valign: string | null = ALIGN_MIDDLE,
|
valign: VAlignValue = ALIGN_MIDDLE,
|
||||||
color: string = 'black',
|
color = 'black',
|
||||||
family: string = DEFAULT_FONTFAMILY,
|
family = DEFAULT_FONTFAMILY,
|
||||||
size: number = DEFAULT_FONTSIZE,
|
size = DEFAULT_FONTSIZE,
|
||||||
fontStyle: number = DEFAULT_FONTSTYLE,
|
fontStyle = DEFAULT_FONTSTYLE,
|
||||||
spacing: number = 2,
|
spacing = 2,
|
||||||
spacingTop: number = 0,
|
spacingTop = 0,
|
||||||
spacingRight: number = 0,
|
spacingRight = 0,
|
||||||
spacingBottom: number = 0,
|
spacingBottom = 0,
|
||||||
spacingLeft: number = 0,
|
spacingLeft = 0,
|
||||||
horizontal: boolean = true,
|
horizontal = true,
|
||||||
background: string | null = null,
|
background = NONE,
|
||||||
border: string | null = null,
|
border = NONE,
|
||||||
wrap: boolean = false,
|
wrap = false,
|
||||||
clipped: boolean = false,
|
clipped = false,
|
||||||
overflow: string = 'visible',
|
overflow: OverflowValue = 'visible',
|
||||||
labelPadding: number = 0,
|
labelPadding = 0,
|
||||||
textDirection: string = DEFAULT_TEXT_DIRECTION
|
textDirection: TextDirectionValue = DEFAULT_TEXT_DIRECTION
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
valign = valign != null ? valign : ALIGN_MIDDLE;
|
|
||||||
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.bounds = bounds;
|
this.bounds = bounds;
|
||||||
|
@ -87,14 +95,11 @@ class TextShape extends Shape {
|
||||||
this.family = family;
|
this.family = family;
|
||||||
this.size = size;
|
this.size = size;
|
||||||
this.fontStyle = fontStyle;
|
this.fontStyle = fontStyle;
|
||||||
this.spacing = parseInt(String(spacing || 2));
|
this.spacing = spacing;
|
||||||
this.spacingTop = parseInt(String(spacing || 2)) + parseInt(String(spacingTop || 0));
|
this.spacingTop = spacing + spacingTop;
|
||||||
this.spacingRight =
|
this.spacingRight = spacing + spacingRight;
|
||||||
parseInt(String(spacing || 2)) + parseInt(String(spacingRight || 0));
|
this.spacingBottom = spacing + spacingBottom;
|
||||||
this.spacingBottom =
|
this.spacingLeft = spacing + spacingLeft;
|
||||||
parseInt(String(spacing || 2)) + parseInt(String(spacingBottom || 0));
|
|
||||||
this.spacingLeft =
|
|
||||||
parseInt(String(spacing || 2)) + parseInt(String(spacingLeft || 0));
|
|
||||||
this.horizontal = horizontal;
|
this.horizontal = horizontal;
|
||||||
this.background = background;
|
this.background = background;
|
||||||
this.border = border;
|
this.border = border;
|
||||||
|
@ -110,29 +115,29 @@ class TextShape extends Shape {
|
||||||
// TODO: Document me!
|
// TODO: Document me!
|
||||||
value: string | HTMLElement | SVGGElement | null;
|
value: string | HTMLElement | SVGGElement | null;
|
||||||
bounds: Rectangle;
|
bounds: Rectangle;
|
||||||
align: string = ALIGN_CENTER;
|
align: AlignValue;
|
||||||
valign: string = ALIGN_MIDDLE;
|
valign: VAlignValue;
|
||||||
color: string = 'black';
|
color: ColorValue;
|
||||||
family: string = DEFAULT_FONTFAMILY;
|
family: string;
|
||||||
size: number = DEFAULT_FONTSIZE;
|
size: number;
|
||||||
fontStyle: number = DEFAULT_FONTSTYLE;
|
fontStyle: number;
|
||||||
spacing: number = 2;
|
spacing: number;
|
||||||
spacingTop: number = 0;
|
spacingTop: number;
|
||||||
spacingRight: number = 0;
|
spacingRight: number;
|
||||||
spacingBottom: number = 0;
|
spacingBottom: number;
|
||||||
spacingLeft: number = 0;
|
spacingLeft: number;
|
||||||
horizontal: boolean = true;
|
horizontal: boolean;
|
||||||
background: string | null = null;
|
background: ColorValue;
|
||||||
border: string | null = null;
|
border: ColorValue;
|
||||||
wrap: boolean = false;
|
wrap: boolean;
|
||||||
clipped: boolean = false;
|
clipped: boolean;
|
||||||
overflow: string = 'visible';
|
overflow: OverflowValue;
|
||||||
labelPadding: number = 0;
|
labelPadding: number;
|
||||||
textDirection: string = DEFAULT_TEXT_DIRECTION;
|
textDirection: TextDirectionValue;
|
||||||
margin: Point | null = null;
|
margin: Point | null = null;
|
||||||
unrotatedBoundingBox: Rectangle | null = null;
|
unrotatedBoundingBox: Rectangle | null = null;
|
||||||
flipH: boolean = false;
|
flipH = false;
|
||||||
flipV: boolean = false;
|
flipV = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: baseSpacingTop
|
* Variable: baseSpacingTop
|
||||||
|
@ -140,7 +145,7 @@ class TextShape extends Shape {
|
||||||
* Specifies the spacing to be added to the top spacing. Default is 0. Use the
|
* Specifies the spacing to be added to the top spacing. Default is 0. Use the
|
||||||
* value 5 here to get the same label positions as in mxGraph 1.x.
|
* value 5 here to get the same label positions as in mxGraph 1.x.
|
||||||
*/
|
*/
|
||||||
baseSpacingTop: number = 0;
|
baseSpacingTop = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: baseSpacingBottom
|
* Variable: baseSpacingBottom
|
||||||
|
@ -148,21 +153,21 @@ class TextShape extends Shape {
|
||||||
* Specifies the spacing to be added to the bottom spacing. Default is 0. Use the
|
* Specifies the spacing to be added to the bottom spacing. Default is 0. Use the
|
||||||
* value 1 here to get the same label positions as in mxGraph 1.x.
|
* value 1 here to get the same label positions as in mxGraph 1.x.
|
||||||
*/
|
*/
|
||||||
baseSpacingBottom: number = 0;
|
baseSpacingBottom = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: baseSpacingLeft
|
* Variable: baseSpacingLeft
|
||||||
*
|
*
|
||||||
* Specifies the spacing to be added to the left spacing. Default is 0.
|
* Specifies the spacing to be added to the left spacing. Default is 0.
|
||||||
*/
|
*/
|
||||||
baseSpacingLeft: number = 0;
|
baseSpacingLeft = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: baseSpacingRight
|
* Variable: baseSpacingRight
|
||||||
*
|
*
|
||||||
* Specifies the spacing to be added to the right spacing. Default is 0.
|
* Specifies the spacing to be added to the right spacing. Default is 0.
|
||||||
*/
|
*/
|
||||||
baseSpacingRight: number = 0;
|
baseSpacingRight = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: replaceLinefeeds
|
* Variable: replaceLinefeeds
|
||||||
|
@ -170,14 +175,14 @@ class TextShape extends Shape {
|
||||||
* Specifies if linefeeds in HTML labels should be replaced with BR tags.
|
* Specifies if linefeeds in HTML labels should be replaced with BR tags.
|
||||||
* Default is true.
|
* Default is true.
|
||||||
*/
|
*/
|
||||||
replaceLinefeeds: boolean = true;
|
replaceLinefeeds = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: verticalTextRotation
|
* Variable: verticalTextRotation
|
||||||
*
|
*
|
||||||
* Rotation for vertical text. Default is -90 (bottom to top).
|
* Rotation for vertical text. Default is -90 (bottom to top).
|
||||||
*/
|
*/
|
||||||
verticalTextRotation: number = -90;
|
verticalTextRotation = -90;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: ignoreClippedStringSize
|
* Variable: ignoreClippedStringSize
|
||||||
|
@ -187,7 +192,7 @@ class TextShape extends Shape {
|
||||||
* true, then the bounding box will be set to <bounds>. Default is true.
|
* true, then the bounding box will be set to <bounds>. Default is true.
|
||||||
* <ignoreStringSize> has precedence over this switch.
|
* <ignoreStringSize> has precedence over this switch.
|
||||||
*/
|
*/
|
||||||
ignoreClippedStringSize: boolean = true;
|
ignoreClippedStringSize = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: ignoreStringSize
|
* Variable: ignoreStringSize
|
||||||
|
@ -196,7 +201,7 @@ class TextShape extends Shape {
|
||||||
* boundingBox will not ignore the actual size of the string, otherwise
|
* boundingBox will not ignore the actual size of the string, otherwise
|
||||||
* <bounds> will be used instead. Default is false.
|
* <bounds> will be used instead. Default is false.
|
||||||
*/
|
*/
|
||||||
ignoreStringSize: boolean = false;
|
ignoreStringSize = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: lastValue
|
* Variable: lastValue
|
||||||
|
@ -210,14 +215,14 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Specifies if caching for HTML labels should be enabled. Default is true.
|
* Specifies if caching for HTML labels should be enabled. Default is true.
|
||||||
*/
|
*/
|
||||||
cacheEnabled: boolean = true;
|
cacheEnabled = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: getSvgScreenOffset
|
* Function: getSvgScreenOffset
|
||||||
*
|
*
|
||||||
* Disables offset in IE9 for crisper image output.
|
* Disables offset in IE9 for crisper image output.
|
||||||
*/
|
*/
|
||||||
getSvgScreenOffset(): number {
|
getSvgScreenOffset() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,12 +231,12 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns true if the bounds are not null and all of its variables are numeric.
|
* Returns true if the bounds are not null and all of its variables are numeric.
|
||||||
*/
|
*/
|
||||||
checkBounds(): boolean {
|
checkBounds() {
|
||||||
return (
|
return (
|
||||||
!isNaN(this.scale) &&
|
!isNaN(this.scale) &&
|
||||||
isFinite(this.scale) &&
|
isFinite(this.scale) &&
|
||||||
this.scale > 0 &&
|
this.scale > 0 &&
|
||||||
this.bounds != null &&
|
this.bounds &&
|
||||||
!isNaN(this.bounds.x) &&
|
!isNaN(this.bounds.x) &&
|
||||||
!isNaN(this.bounds.y) &&
|
!isNaN(this.bounds.y) &&
|
||||||
!isNaN(this.bounds.width) &&
|
!isNaN(this.bounds.width) &&
|
||||||
|
@ -244,7 +249,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Generic rendering code.
|
* Generic rendering code.
|
||||||
*/
|
*/
|
||||||
paint(c: mxSvgCanvas2D, update: boolean = false): void {
|
paint(c: AbstractCanvas2D, update = false): void {
|
||||||
// Scale is passed-through to canvas
|
// Scale is passed-through to canvas
|
||||||
const s = this.scale;
|
const s = this.scale;
|
||||||
const x = this.bounds.x / s;
|
const x = this.bounds.x / s;
|
||||||
|
@ -292,14 +297,14 @@ class TextShape extends Shape {
|
||||||
? (<string>val).replace(/\n/g, '<br/>')
|
? (<string>val).replace(/\n/g, '<br/>')
|
||||||
: val;
|
: val;
|
||||||
|
|
||||||
let dir: string | null = this.textDirection;
|
let dir: TextDirectionValue = this.textDirection;
|
||||||
|
|
||||||
if (dir === TEXT_DIRECTION_AUTO && !realHtml) {
|
if (dir === TEXT_DIRECTION_AUTO && !realHtml) {
|
||||||
dir = this.getAutoDirection();
|
dir = this.getAutoDirection();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir !== TEXT_DIRECTION_LTR && dir !== TEXT_DIRECTION_RTL) {
|
if (dir !== TEXT_DIRECTION_LTR && dir !== TEXT_DIRECTION_RTL) {
|
||||||
dir = null;
|
dir = TEXT_DIRECTION_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
c.text(
|
c.text(
|
||||||
|
@ -333,19 +338,20 @@ class TextShape extends Shape {
|
||||||
this.lastValue === this.value &&
|
this.lastValue === this.value &&
|
||||||
(isNode(this.value) || this.dialect === DIALECT_STRICTHTML)
|
(isNode(this.value) || this.dialect === DIALECT_STRICTHTML)
|
||||||
) {
|
) {
|
||||||
// @ts-ignore
|
|
||||||
if (this.node.nodeName === 'DIV') {
|
if (this.node.nodeName === 'DIV') {
|
||||||
this.redrawHtmlShape();
|
this.redrawHtmlShape();
|
||||||
this.updateBoundingBox();
|
this.updateBoundingBox();
|
||||||
} else {
|
} else {
|
||||||
const canvas = this.createCanvas();
|
const canvas = this.createCanvas();
|
||||||
|
|
||||||
// Specifies if events should be handled
|
if (canvas) {
|
||||||
canvas.pointerEvents = this.pointerEvents;
|
// Specifies if events should be handled
|
||||||
|
canvas.pointerEvents = this.pointerEvents;
|
||||||
|
|
||||||
this.paint(canvas, true);
|
this.paint(canvas, true);
|
||||||
this.destroyCanvas(canvas);
|
this.destroyCanvas(canvas);
|
||||||
this.updateBoundingBox();
|
this.updateBoundingBox();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
super.redraw();
|
super.redraw();
|
||||||
|
@ -378,8 +384,8 @@ class TextShape extends Shape {
|
||||||
this.spacingBottom = 2;
|
this.spacingBottom = 2;
|
||||||
this.spacingLeft = 2;
|
this.spacingLeft = 2;
|
||||||
this.horizontal = true;
|
this.horizontal = true;
|
||||||
this.background = null;
|
this.background = NONE;
|
||||||
this.border = null;
|
this.border = NONE;
|
||||||
this.textDirection = DEFAULT_TEXT_DIRECTION;
|
this.textDirection = DEFAULT_TEXT_DIRECTION;
|
||||||
this.margin = null;
|
this.margin = null;
|
||||||
}
|
}
|
||||||
|
@ -397,31 +403,24 @@ class TextShape extends Shape {
|
||||||
const old = this.spacing;
|
const old = this.spacing;
|
||||||
super.apply(state);
|
super.apply(state);
|
||||||
|
|
||||||
if (this.style != null) {
|
if (this.style) {
|
||||||
this.fontStyle = this.style.fontStyle || this.fontStyle;
|
this.fontStyle = this.style.fontStyle;
|
||||||
this.family = getValue(this.style, 'fontFamily', this.family);
|
this.family = this.style.fontFamily;
|
||||||
this.size = getValue(this.style, 'fontSize', this.size);
|
this.size = this.style.fontSize;
|
||||||
this.color = getValue(this.style, 'fontColor', this.color);
|
this.color = this.style.fontColor;
|
||||||
this.align = getValue(this.style, 'align', this.align);
|
this.align = this.style.align;
|
||||||
this.valign = getValue(this.style, 'verticalAlign', this.valign);
|
this.valign = this.style.verticalAlign;
|
||||||
this.spacing = parseInt(getValue(this.style, 'spacing', this.spacing));
|
this.spacing = this.style.spacing;
|
||||||
this.spacingTop =
|
this.spacingTop = this.style.spacingTop;
|
||||||
parseInt(getValue(this.style, 'spacingTop', this.spacingTop - old)) +
|
this.spacingRight = this.style.spacingRight;
|
||||||
this.spacing;
|
this.spacingBottom = this.style.spacingBottom;
|
||||||
this.spacingRight =
|
this.spacingLeft = this.style.spacingLeft;
|
||||||
parseInt(getValue(this.style, 'spacingRight', this.spacingRight - old)) +
|
this.horizontal = this.style.horizontal;
|
||||||
this.spacing;
|
this.background = this.style.backgroundColor;
|
||||||
this.spacingBottom =
|
this.border = this.style.labelBorderColor;
|
||||||
parseInt(getValue(this.style, 'spacingBottom', this.spacingBottom - old)) +
|
this.textDirection = this.style.textDirection;
|
||||||
this.spacing;
|
this.opacity = this.style.textOpacity;
|
||||||
this.spacingLeft =
|
|
||||||
parseInt(getValue(this.style, 'spacingLeft', this.spacingLeft - old)) +
|
|
||||||
this.spacing;
|
|
||||||
this.horizontal = getValue(this.style, 'horizontal', this.horizontal);
|
|
||||||
this.background = getValue(this.style, 'backgroundColor', this.background);
|
|
||||||
this.border = getValue(this.style, 'labelBorderColor', this.border);
|
|
||||||
this.textDirection = getValue(this.style, 'textDirection', DEFAULT_TEXT_DIRECTION);
|
|
||||||
this.opacity = getValue(this.style, 'textOpacity', 100);
|
|
||||||
this.updateMargin();
|
this.updateMargin();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -437,14 +436,14 @@ class TextShape extends Shape {
|
||||||
* depending on the contents of <value>. This is not invoked for HTML, wrapped
|
* depending on the contents of <value>. This is not invoked for HTML, wrapped
|
||||||
* content or if <value> is a DOM node.
|
* content or if <value> is a DOM node.
|
||||||
*/
|
*/
|
||||||
getAutoDirection(): string {
|
getAutoDirection() {
|
||||||
// Looks for strong (directional) characters
|
// Looks for strong (directional) characters
|
||||||
const tmp = /[A-Za-z\u05d0-\u065f\u066a-\u06ef\u06fa-\u07ff\ufb1d-\ufdff\ufe70-\ufefc]/.exec(
|
const tmp = /[A-Za-z\u05d0-\u065f\u066a-\u06ef\u06fa-\u07ff\ufb1d-\ufdff\ufe70-\ufefc]/.exec(
|
||||||
<string>this.value
|
String(this.value)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Returns the direction defined by the character
|
// Returns the direction defined by the character
|
||||||
return tmp != null && tmp.length > 0 && tmp[0] > 'z'
|
return tmp && tmp.length > 0 && tmp[0] > 'z'
|
||||||
? TEXT_DIRECTION_RTL
|
? TEXT_DIRECTION_RTL
|
||||||
: TEXT_DIRECTION_LTR;
|
: TEXT_DIRECTION_LTR;
|
||||||
}
|
}
|
||||||
|
@ -457,9 +456,9 @@ class TextShape extends Shape {
|
||||||
getContentNode() {
|
getContentNode() {
|
||||||
let result = this.node;
|
let result = this.node;
|
||||||
|
|
||||||
if (result != null) {
|
if (result) {
|
||||||
// Rendered with no foreignObject
|
// Rendered with no foreignObject
|
||||||
if (result.ownerSVGElement == null) {
|
if (!result.ownerSVGElement) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
result = this.node.firstChild.firstChild;
|
result = this.node.firstChild.firstChild;
|
||||||
} else {
|
} else {
|
||||||
|
@ -468,6 +467,7 @@ class TextShape extends Shape {
|
||||||
result = result.firstChild.firstChild.firstChild.firstChild.firstChild;
|
result = result.firstChild.firstChild.firstChild.firstChild.firstChild;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -476,21 +476,17 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Updates the <boundingBox> for this shape using the given node and position.
|
* Updates the <boundingBox> for this shape using the given node and position.
|
||||||
*/
|
*/
|
||||||
updateBoundingBox(): void {
|
updateBoundingBox() {
|
||||||
let { node } = this;
|
let { node } = this;
|
||||||
this.boundingBox = this.bounds.clone();
|
this.boundingBox = this.bounds.clone();
|
||||||
const rot = this.getTextRotation();
|
const rot = this.getTextRotation();
|
||||||
|
|
||||||
const h =
|
const h = this.style?.labelPosition ?? ALIGN_CENTER;
|
||||||
this.style != null ? getValue(this.style, 'labelPosition', ALIGN_CENTER) : null;
|
const v = this.style?.verticalLabelPosition ?? ALIGN_MIDDLE;
|
||||||
const v =
|
|
||||||
this.style != null
|
|
||||||
? getValue(this.style, 'verticalLabelPosition', ALIGN_MIDDLE)
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!this.ignoreStringSize &&
|
!this.ignoreStringSize &&
|
||||||
node != null &&
|
node &&
|
||||||
this.overflow !== 'fill' &&
|
this.overflow !== 'fill' &&
|
||||||
(!this.clipped ||
|
(!this.clipped ||
|
||||||
!this.ignoreClippedStringSize ||
|
!this.ignoreClippedStringSize ||
|
||||||
|
@ -501,8 +497,8 @@ class TextShape extends Shape {
|
||||||
let oh = null;
|
let oh = null;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
node.firstChild != null &&
|
node.firstChild &&
|
||||||
node.firstChild.firstChild != null &&
|
node.firstChild.firstChild &&
|
||||||
node.firstChild.firstChild.nodeName === 'foreignObject'
|
node.firstChild.firstChild.nodeName === 'foreignObject'
|
||||||
) {
|
) {
|
||||||
// Uses second inner DIV for font metrics
|
// Uses second inner DIV for font metrics
|
||||||
|
@ -512,7 +508,6 @@ class TextShape extends Shape {
|
||||||
oh = node.offsetHeight * this.scale;
|
oh = node.offsetHeight * this.scale;
|
||||||
|
|
||||||
if (this.overflow === 'width') {
|
if (this.overflow === 'width') {
|
||||||
// @ts-ignore
|
|
||||||
ow = this.boundingBox.width;
|
ow = this.boundingBox.width;
|
||||||
} else {
|
} else {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -523,7 +518,7 @@ class TextShape extends Shape {
|
||||||
const b = node.getBBox();
|
const b = node.getBBox();
|
||||||
|
|
||||||
// Workaround for bounding box of empty string
|
// Workaround for bounding box of empty string
|
||||||
if (typeof this.value === 'string' && trim(this.value)?.length == 0) {
|
if (typeof this.value === 'string' && trim(this.value)?.length === 0) {
|
||||||
this.boundingBox = null;
|
this.boundingBox = null;
|
||||||
} else if (b.width === 0 && b.height === 0) {
|
} else if (b.width === 0 && b.height === 0) {
|
||||||
this.boundingBox = null;
|
this.boundingBox = null;
|
||||||
|
@ -537,12 +532,12 @@ class TextShape extends Shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ow != null && oh != null) {
|
if (ow && oh) {
|
||||||
this.boundingBox = new Rectangle(this.bounds.x, this.bounds.y, ow, oh);
|
this.boundingBox = new Rectangle(this.bounds.x, this.bounds.y, ow, oh);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.boundingBox != null) {
|
if (this.boundingBox) {
|
||||||
const margin = <Rectangle>this.margin;
|
const margin = <Rectangle>this.margin;
|
||||||
|
|
||||||
if (rot !== 0) {
|
if (rot !== 0) {
|
||||||
|
@ -581,7 +576,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns 0 to avoid using rotation in the canvas via updateTransform.
|
* Returns 0 to avoid using rotation in the canvas via updateTransform.
|
||||||
*/
|
*/
|
||||||
getShapeRotation(): number {
|
getShapeRotation() {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,10 +585,8 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns the rotation for the text label of the corresponding shape.
|
* Returns the rotation for the text label of the corresponding shape.
|
||||||
*/
|
*/
|
||||||
getTextRotation(): number {
|
getTextRotation() {
|
||||||
return this.state != null && this.state.shape != null
|
return this.state && this.state.shape ? this.state.shape.getTextRotation() : 0;
|
||||||
? this.state.shape.getTextRotation()
|
|
||||||
: 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -602,13 +595,8 @@ class TextShape extends Shape {
|
||||||
* Inverts the bounds if <mxShape.isBoundsInverted> returns true or if the
|
* Inverts the bounds if <mxShape.isBoundsInverted> returns true or if the
|
||||||
* horizontal style is false.
|
* horizontal style is false.
|
||||||
*/
|
*/
|
||||||
isPaintBoundsInverted(): boolean {
|
isPaintBoundsInverted() {
|
||||||
return (
|
return !this.horizontal && !!this.state && this.state.cell.isVertex();
|
||||||
!this.horizontal &&
|
|
||||||
this.state != null &&
|
|
||||||
// @ts-ignore
|
|
||||||
this.state.cell.isVertex()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -616,7 +604,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Sets the state of the canvas for drawing the shape.
|
* Sets the state of the canvas for drawing the shape.
|
||||||
*/
|
*/
|
||||||
configureCanvas(c: mxSvgCanvas2D, x: number, y: number, w: number, h: number): void {
|
configureCanvas(c: AbstractCanvas2D, x: number, y: number, w: number, h: number): void {
|
||||||
super.configureCanvas(c, x, y, w, h);
|
super.configureCanvas(c, x, y, w, h);
|
||||||
|
|
||||||
c.setFontColor(this.color);
|
c.setFontColor(this.color);
|
||||||
|
@ -691,7 +679,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
||||||
*/
|
*/
|
||||||
redrawHtmlShape(): void {
|
redrawHtmlShape() {
|
||||||
const w = Math.max(0, Math.round(this.bounds.width / this.scale));
|
const w = Math.max(0, Math.round(this.bounds.width / this.scale));
|
||||||
const h = Math.max(0, Math.round(this.bounds.height / this.scale));
|
const h = Math.max(0, Math.round(this.bounds.height / this.scale));
|
||||||
const flex =
|
const flex =
|
||||||
|
@ -699,9 +687,9 @@ class TextShape extends Shape {
|
||||||
`top: ${Math.round(this.bounds.y)}px; pointer-events: none; `;
|
`top: ${Math.round(this.bounds.y)}px; pointer-events: none; `;
|
||||||
const block = this.getTextCss();
|
const block = this.getTextCss();
|
||||||
const margin = <Point>this.margin;
|
const margin = <Point>this.margin;
|
||||||
const node = <SVGGElement>this.node;
|
const node = this.node;
|
||||||
|
|
||||||
mxSvgCanvas2D.createCss(
|
SvgCanvas2D.createCss(
|
||||||
w + 2,
|
w + 2,
|
||||||
h,
|
h,
|
||||||
this.align,
|
this.align,
|
||||||
|
@ -709,8 +697,8 @@ class TextShape extends Shape {
|
||||||
this.wrap,
|
this.wrap,
|
||||||
this.overflow,
|
this.overflow,
|
||||||
this.clipped,
|
this.clipped,
|
||||||
this.background != null ? htmlEntities(this.background, true) : null,
|
this.background !== NONE ? htmlEntities(this.background, true) : null,
|
||||||
this.border != null ? htmlEntities(this.border, true) : null,
|
this.border !== NONE ? htmlEntities(this.border, true) : null,
|
||||||
flex,
|
flex,
|
||||||
block,
|
block,
|
||||||
this.scale,
|
this.scale,
|
||||||
|
@ -745,7 +733,7 @@ class TextShape extends Shape {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (<number>this.opacity < 100) {
|
if (this.opacity < 100) {
|
||||||
block += `opacity: ${<number>this.opacity / 100}; `;
|
block += `opacity: ${<number>this.opacity / 100}; `;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +744,7 @@ class TextShape extends Shape {
|
||||||
this.value.outerHTML
|
this.value.outerHTML
|
||||||
: this.getHtmlValue();
|
: this.getHtmlValue();
|
||||||
|
|
||||||
if (node.firstChild == null) {
|
if (!node.firstChild) {
|
||||||
node.innerHTML = `<div><div>${html}</div></div>`;
|
node.innerHTML = `<div><div>${html}</div></div>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -773,7 +761,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Sets the inner HTML of the given element to the <value>.
|
* Sets the inner HTML of the given element to the <value>.
|
||||||
*/
|
*/
|
||||||
updateInnerHtml(elt: HTMLElement): void {
|
updateInnerHtml(elt: HTMLElement) {
|
||||||
if (isNode(this.value)) {
|
if (isNode(this.value)) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
elt.innerHTML = this.value.outerHTML;
|
elt.innerHTML = this.value.outerHTML;
|
||||||
|
@ -782,7 +770,7 @@ class TextShape extends Shape {
|
||||||
|
|
||||||
if (this.dialect !== DIALECT_STRICTHTML) {
|
if (this.dialect !== DIALECT_STRICTHTML) {
|
||||||
// LATER: Can be cached in updateValue
|
// LATER: Can be cached in updateValue
|
||||||
val = htmlEntities(<string>val, false);
|
val = htmlEntities(val, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles trailing newlines to make sure they are visible in rendering output
|
// Handles trailing newlines to make sure they are visible in rendering output
|
||||||
|
@ -799,8 +787,8 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
||||||
*/
|
*/
|
||||||
updateValue(): void {
|
updateValue() {
|
||||||
const node = <SVGGElement>this.node;
|
const node = this.node;
|
||||||
|
|
||||||
if (isNode(this.value)) {
|
if (isNode(this.value)) {
|
||||||
node.innerHTML = '';
|
node.innerHTML = '';
|
||||||
|
@ -809,32 +797,31 @@ class TextShape extends Shape {
|
||||||
let val = this.value as string;
|
let val = this.value as string;
|
||||||
|
|
||||||
if (this.dialect !== DIALECT_STRICTHTML) {
|
if (this.dialect !== DIALECT_STRICTHTML) {
|
||||||
val = htmlEntities(<string>val, false);
|
val = htmlEntities(val, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handles trailing newlines to make sure they are visible in rendering output
|
// Handles trailing newlines to make sure they are visible in rendering output
|
||||||
val = replaceTrailingNewlines(val, '<div><br></div>');
|
val = replaceTrailingNewlines(val, '<div><br></div>');
|
||||||
val = this.replaceLinefeeds ? val.replace(/\n/g, '<br/>') : val;
|
val = this.replaceLinefeeds ? val.replace(/\n/g, '<br/>') : val;
|
||||||
const bg =
|
const bg = this.background !== NONE ? this.background : null;
|
||||||
this.background != null && this.background !== NONE ? this.background : null;
|
const bd = this.border !== NONE ? this.border : null;
|
||||||
const bd = this.border != null && this.border !== NONE ? this.border : null;
|
|
||||||
|
|
||||||
if (this.overflow === 'fill' || this.overflow === 'width') {
|
if (this.overflow === 'fill' || this.overflow === 'width') {
|
||||||
if (bg != null) {
|
if (bg) {
|
||||||
node.style.backgroundColor = bg;
|
node.style.backgroundColor = bg;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bd != null) {
|
if (bd) {
|
||||||
node.style.border = `1px solid ${bd}`;
|
node.style.border = `1px solid ${bd}`;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let css = '';
|
let css = '';
|
||||||
|
|
||||||
if (bg != null) {
|
if (bg) {
|
||||||
css += `background-color:${htmlEntities(bg, true)};`;
|
css += `background-color:${htmlEntities(bg, true)};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bd != null) {
|
if (bd) {
|
||||||
css += `border:1px solid ${htmlEntities(bd, true)};`;
|
css += `border:1px solid ${htmlEntities(bd, true)};`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -873,7 +860,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
||||||
*/
|
*/
|
||||||
updateFont(node: HTMLElement | SVGGElement): void {
|
updateFont(node: HTMLElement | SVGGElement) {
|
||||||
const { style } = node;
|
const { style } = node;
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
|
@ -923,7 +910,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
* Updates the HTML node(s) to reflect the latest bounds and scale.
|
||||||
*/
|
*/
|
||||||
updateSize(node: HTMLElement, enableWrap: boolean = false): void {
|
updateSize(node: HTMLElement, enableWrap = false) {
|
||||||
const w = Math.max(0, Math.round(this.bounds.width / this.scale));
|
const w = Math.max(0, Math.round(this.bounds.width / this.scale));
|
||||||
const h = Math.max(0, Math.round(this.bounds.height / this.scale));
|
const h = Math.max(0, Math.round(this.bounds.height / this.scale));
|
||||||
const { style } = node;
|
const { style } = node;
|
||||||
|
@ -992,7 +979,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns the spacing as an <mxPoint>.
|
* Returns the spacing as an <mxPoint>.
|
||||||
*/
|
*/
|
||||||
updateMargin(): void {
|
updateMargin() {
|
||||||
this.margin = getAlignmentAsPoint(this.align, this.valign);
|
this.margin = getAlignmentAsPoint(this.align, this.valign);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1001,7 +988,7 @@ class TextShape extends Shape {
|
||||||
*
|
*
|
||||||
* Returns the spacing as an <mxPoint>.
|
* Returns the spacing as an <mxPoint>.
|
||||||
*/
|
*/
|
||||||
getSpacing(): Point {
|
getSpacing() {
|
||||||
let dx = 0;
|
let dx = 0;
|
||||||
let dy = 0;
|
let dy = 0;
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,8 @@
|
||||||
|
|
||||||
import Point from '../../Point';
|
import Point from '../../Point';
|
||||||
import Actor from '../Actor';
|
import Actor from '../Actor';
|
||||||
import utils, { getValue } from '../../../../util/Utils';
|
|
||||||
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
import { LINE_ARCSIZE } from '../../../../util/Constants';
|
||||||
import mxSvgCanvas2D from '../../../../util/canvas/mxSvgCanvas2D';
|
import AbstractCanvas2D from 'packages/core/src/util/canvas/AbstractCanvas2D';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of the triangle shape.
|
* Implementation of the triangle shape.
|
||||||
|
@ -25,7 +24,7 @@ class TriangleShape extends Actor {
|
||||||
* Adds roundable support.
|
* Adds roundable support.
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
isRoundable(): boolean {
|
isRoundable() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,15 +36,8 @@ class TriangleShape extends Actor {
|
||||||
* @param {number} w
|
* @param {number} w
|
||||||
* @param {number} h
|
* @param {number} h
|
||||||
*/
|
*/
|
||||||
redrawPath(
|
redrawPath(c: AbstractCanvas2D, x: number, y: number, w: number, h: number) {
|
||||||
c: mxSvgCanvas2D,
|
const arcSize = (this.style?.arcSize ?? LINE_ARCSIZE) / 2;
|
||||||
x: number,
|
|
||||||
y: number,
|
|
||||||
w: number,
|
|
||||||
h: number
|
|
||||||
): void {
|
|
||||||
const arcSize: number =
|
|
||||||
getValue(this.style, 'arcSize', LINE_ARCSIZE) / 2;
|
|
||||||
|
|
||||||
this.addPoints(
|
this.addPoints(
|
||||||
c,
|
c,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import Graph from "../Graph";
|
import Graph from '../Graph';
|
||||||
import ImageBundle from "../../util/image/ImageBundle";
|
import ImageBundle from './ImageBundle';
|
||||||
import ImageBundle from "./ImageBundle";
|
|
||||||
|
|
||||||
class GraphImage {
|
class GraphImage {
|
||||||
constructor(graph: Graph) {
|
constructor(graph: Graph) {
|
||||||
|
@ -19,14 +18,14 @@ class GraphImage {
|
||||||
/**
|
/**
|
||||||
* Adds the specified {@link ImageBundle}.
|
* Adds the specified {@link ImageBundle}.
|
||||||
*/
|
*/
|
||||||
addImageBundle(bundle: ImageBundle): void {
|
addImageBundle(bundle: ImageBundle) {
|
||||||
this.imageBundles.push(bundle);
|
this.imageBundles.push(bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the specified {@link ImageBundle}.
|
* Removes the specified {@link ImageBundle}.
|
||||||
*/
|
*/
|
||||||
removeImageBundle(bundle: ImageBundle): void {
|
removeImageBundle(bundle: ImageBundle) {
|
||||||
const tmp = [];
|
const tmp = [];
|
||||||
for (let i = 0; i < this.imageBundles.length; i += 1) {
|
for (let i = 0; i < this.imageBundles.length; i += 1) {
|
||||||
if (this.imageBundles[i] !== bundle) {
|
if (this.imageBundles[i] !== bundle) {
|
||||||
|
@ -40,11 +39,11 @@ class GraphImage {
|
||||||
* Searches all {@link imageBundles} for the specified key and returns the value
|
* Searches all {@link imageBundles} for the specified key and returns the value
|
||||||
* for the first match or null if the key is not found.
|
* for the first match or null if the key is not found.
|
||||||
*/
|
*/
|
||||||
getImageFromBundles(key: string): string {
|
getImageFromBundles(key: string) {
|
||||||
if (key != null) {
|
if (key) {
|
||||||
for (let i = 0; i < this.imageBundles.length; i += 1) {
|
for (let i = 0; i < this.imageBundles.length; i += 1) {
|
||||||
const image = this.imageBundles[i].getImage(key);
|
const image = this.imageBundles[i].getImage(key);
|
||||||
if (image != null) {
|
if (image) {
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,8 @@
|
||||||
*
|
*
|
||||||
* Constructs a new image.
|
* Constructs a new image.
|
||||||
*/
|
*/
|
||||||
class Image {
|
class ImageBox {
|
||||||
constructor(src: string,
|
constructor(src: string, width: number, height: number) {
|
||||||
width: number,
|
|
||||||
height: number) {
|
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.width = width;
|
this.width = width;
|
||||||
this.height = height;
|
this.height = height;
|
||||||
|
@ -28,21 +26,21 @@ class Image {
|
||||||
*
|
*
|
||||||
* String that specifies the URL of the image.
|
* String that specifies the URL of the image.
|
||||||
*/
|
*/
|
||||||
src: string | null = null;
|
src: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: width
|
* Variable: width
|
||||||
*
|
*
|
||||||
* Integer that specifies the width of the image.
|
* Integer that specifies the width of the image.
|
||||||
*/
|
*/
|
||||||
width: number | null = null;
|
width: number;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: height
|
* Variable: height
|
||||||
*
|
*
|
||||||
* Integer that specifies the height of the image.
|
* Integer that specifies the height of the image.
|
||||||
*/
|
*/
|
||||||
height: number | null = null;
|
height: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Image;
|
export default ImageBox;
|
|
@ -5,6 +5,13 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
type ImageMap = {
|
||||||
|
[key: string]: {
|
||||||
|
value: string;
|
||||||
|
fallback: Function;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class: mxImageBundle
|
* Class: mxImageBundle
|
||||||
*
|
*
|
||||||
|
@ -51,9 +58,9 @@
|
||||||
* all data URIs should be limited to 32 KB.
|
* all data URIs should be limited to 32 KB.
|
||||||
*/
|
*/
|
||||||
class ImageBundle {
|
class ImageBundle {
|
||||||
constructor(alt) {
|
constructor(alt = false) {
|
||||||
this.images = [];
|
this.images = {};
|
||||||
this.alt = alt != null ? alt : false;
|
this.alt = alt;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,14 +68,14 @@ class ImageBundle {
|
||||||
*
|
*
|
||||||
* Maps from keys to images.
|
* Maps from keys to images.
|
||||||
*/
|
*/
|
||||||
images: { [key: string]: { value: string; fallback: Function } } | null = null;
|
images: ImageMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Variable: alt
|
* Variable: alt
|
||||||
*
|
*
|
||||||
* Specifies if the fallback representation should be returned.
|
* Specifies if the fallback representation should be returned.
|
||||||
*/
|
*/
|
||||||
alt: boolean = null;
|
alt: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function: putImage
|
* Function: putImage
|
||||||
|
@ -87,13 +94,13 @@ class ImageBundle {
|
||||||
* or fallback, depending on <alt>. The fallback is returned if
|
* or fallback, depending on <alt>. The fallback is returned if
|
||||||
* <alt> is true, the value is returned otherwise.
|
* <alt> is true, the value is returned otherwise.
|
||||||
*/
|
*/
|
||||||
getImage(key: string): string {
|
getImage(key: string) {
|
||||||
let result = null;
|
let result = null;
|
||||||
|
|
||||||
if (key != null) {
|
if (key) {
|
||||||
const img = this.images[key];
|
const img = this.images[key];
|
||||||
|
|
||||||
if (img != null) {
|
if (img) {
|
||||||
result = this.alt ? img.fallback : img.value;
|
result = this.alt ? img.fallback : img.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* Type definitions from the typed-mxgraph project
|
* Type definitions from the typed-mxgraph project
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import mxAbstractCanvas2D from '../../util/canvas/mxAbstractCanvas2D';
|
import AbstractCanvas2D from '../../util/canvas/AbstractCanvas2D';
|
||||||
import CellState from '../cell/datatypes/CellState';
|
import CellState from '../cell/datatypes/CellState';
|
||||||
import Shape from '../geometry/shape/Shape';
|
import Shape from '../geometry/shape/Shape';
|
||||||
|
|
||||||
|
@ -41,13 +41,13 @@ class ImageExport {
|
||||||
/**
|
/**
|
||||||
* Specifies if overlays should be included in the export. Default is false.
|
* Specifies if overlays should be included in the export. Default is false.
|
||||||
*/
|
*/
|
||||||
includeOverlays: boolean = false;
|
includeOverlays = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given state and all its descendants to the given canvas.
|
* Draws the given state and all its descendants to the given canvas.
|
||||||
*/
|
*/
|
||||||
drawState(state: CellState, canvas: mxAbstractCanvas2D): void {
|
drawState(state: CellState, canvas: AbstractCanvas2D): void {
|
||||||
if (state != null) {
|
if (state) {
|
||||||
this.visitStatesRecursive(state, canvas, () => {
|
this.visitStatesRecursive(state, canvas, () => {
|
||||||
this.drawCellState(state, canvas);
|
this.drawCellState(state, canvas);
|
||||||
});
|
});
|
||||||
|
@ -66,8 +66,8 @@ class ImageExport {
|
||||||
*
|
*
|
||||||
* Visits the given state and all its descendants to the given canvas recursively.
|
* Visits the given state and all its descendants to the given canvas recursively.
|
||||||
*/
|
*/
|
||||||
visitStatesRecursive(state: CellState, canvas: mxAbstractCanvas2D, visitor: Function) {
|
visitStatesRecursive(state: CellState, canvas: AbstractCanvas2D, visitor: Function) {
|
||||||
if (state != null) {
|
if (state) {
|
||||||
visitor(state, canvas);
|
visitor(state, canvas);
|
||||||
|
|
||||||
const { graph } = state.view;
|
const { graph } = state.view;
|
||||||
|
@ -83,18 +83,18 @@ class ImageExport {
|
||||||
/**
|
/**
|
||||||
* Returns the link for the given cell state and canvas. This returns null.
|
* Returns the link for the given cell state and canvas. This returns null.
|
||||||
*/
|
*/
|
||||||
getLinkForCellState(state: CellState, canvas: mxAbstractCanvas2D): any {
|
getLinkForCellState(state: CellState, canvas: AbstractCanvas2D): any {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws the given state to the given canvas.
|
* Draws the given state to the given canvas.
|
||||||
*/
|
*/
|
||||||
drawCellState(state: CellState, canvas: mxAbstractCanvas2D): void {
|
drawCellState(state: CellState, canvas: AbstractCanvas2D): void {
|
||||||
// Experimental feature
|
// Experimental feature
|
||||||
const link = this.getLinkForCellState(state, canvas);
|
const link = this.getLinkForCellState(state, canvas);
|
||||||
|
|
||||||
if (link != null) {
|
if (link) {
|
||||||
canvas.setLink(link);
|
canvas.setLink(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ class ImageExport {
|
||||||
this.drawShape(state, canvas);
|
this.drawShape(state, canvas);
|
||||||
this.drawText(state, canvas);
|
this.drawText(state, canvas);
|
||||||
|
|
||||||
if (link != null) {
|
if (link) {
|
||||||
canvas.setLink(null);
|
canvas.setLink(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -112,7 +112,7 @@ class ImageExport {
|
||||||
*
|
*
|
||||||
* Draws the shape of the given state.
|
* Draws the shape of the given state.
|
||||||
*/
|
*/
|
||||||
drawShape(state: CellState, canvas: mxAbstractCanvas2D): void {
|
drawShape(state: CellState, canvas: AbstractCanvas2D): void {
|
||||||
if (state.shape instanceof Shape && state.shape.checkBounds()) {
|
if (state.shape instanceof Shape && state.shape.checkBounds()) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
|
|
||||||
|
@ -127,8 +127,8 @@ class ImageExport {
|
||||||
/**
|
/**
|
||||||
* Draws the text of the given state.
|
* Draws the text of the given state.
|
||||||
*/
|
*/
|
||||||
drawText(state: CellState, canvas: mxAbstractCanvas2D): void {
|
drawText(state: CellState, canvas: AbstractCanvas2D): void {
|
||||||
if (state.text != null && state.text.checkBounds()) {
|
if (state.text && state.text.checkBounds()) {
|
||||||
canvas.save();
|
canvas.save();
|
||||||
|
|
||||||
state.text.beforePaint(canvas);
|
state.text.beforePaint(canvas);
|
||||||
|
@ -145,7 +145,7 @@ class ImageExport {
|
||||||
* Draws the overlays for the given state. This is called if <includeOverlays>
|
* Draws the overlays for the given state. This is called if <includeOverlays>
|
||||||
* is true.
|
* is true.
|
||||||
*/
|
*/
|
||||||
drawOverlays(state: CellState, canvas: mxAbstractCanvas2D): void {
|
drawOverlays(state: CellState, canvas: AbstractCanvas2D): void {
|
||||||
if (state.overlays != null) {
|
if (state.overlays != null) {
|
||||||
state.overlays.visit((id, shape) => {
|
state.overlays.visit((id, shape) => {
|
||||||
if (shape instanceof Shape) {
|
if (shape instanceof Shape) {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import Cell from "../cell/datatypes/Cell";
|
import Cell from '../cell/datatypes/Cell';
|
||||||
import CellOverlay from "../cell/CellOverlay";
|
import CellOverlay from '../cell/CellOverlay';
|
||||||
import EventObject from "../event/EventObject";
|
import EventObject from '../event/EventObject';
|
||||||
import InternalEvent from "../event/InternalEvent";
|
import InternalEvent from '../event/InternalEvent';
|
||||||
import Image from "../image/Image";
|
import Image from '../image/ImageBox';
|
||||||
import InternalMouseEvent from "../event/InternalMouseEvent";
|
import InternalMouseEvent from '../event/InternalMouseEvent';
|
||||||
import Graph from "../Graph";
|
import Graph from '../Graph';
|
||||||
|
|
||||||
class Overlays {
|
class Overlays {
|
||||||
constructor(graph: Graph) {
|
constructor(graph: Graph) {
|
||||||
|
@ -82,13 +82,7 @@ class Overlays {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fireEvent(
|
this.fireEvent(
|
||||||
new EventObject(
|
new EventObject(InternalEvent.REMOVE_OVERLAY, 'cell', cell, 'overlay', overlay)
|
||||||
InternalEvent.REMOVE_OVERLAY,
|
|
||||||
'cell',
|
|
||||||
cell,
|
|
||||||
'overlay',
|
|
||||||
overlay
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
overlay = null;
|
overlay = null;
|
||||||
|
@ -184,18 +178,18 @@ class Overlays {
|
||||||
img = img != null ? img : this.warningImage;
|
img = img != null ? img : this.warningImage;
|
||||||
|
|
||||||
// Creates the overlay with the image and warning
|
// Creates the overlay with the image and warning
|
||||||
const overlay = new CellOverlay(
|
const overlay = new CellOverlay(img, `<font color=red>${warning}</font>`);
|
||||||
img,
|
|
||||||
`<font color=red>${warning}</font>`
|
|
||||||
);
|
|
||||||
|
|
||||||
// Adds a handler for single mouseclicks to select the cell
|
// Adds a handler for single mouseclicks to select the cell
|
||||||
if (isSelect) {
|
if (isSelect) {
|
||||||
overlay.addListener(InternalEvent.CLICK, (sender: any, evt: InternalMouseEvent) => {
|
overlay.addListener(
|
||||||
if (this.isEnabled()) {
|
InternalEvent.CLICK,
|
||||||
this.setSelectionCell(cell);
|
(sender: any, evt: InternalMouseEvent) => {
|
||||||
|
if (this.isEnabled()) {
|
||||||
|
this.setSelectionCell(cell);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sets and returns the overlay in the graph
|
// Sets and returns the overlay in the graph
|
||||||
|
|
|
@ -72,7 +72,7 @@ class CellHighlight {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Document me!!
|
// TODO: Document me!!
|
||||||
highlightColor: ColorValue = null;
|
highlightColor: ColorValue | null = null;
|
||||||
|
|
||||||
strokeWidth: number = 0;
|
strokeWidth: number = 0;
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ class CellHighlight {
|
||||||
*
|
*
|
||||||
* @param {string} color - String that represents the new highlight color.
|
* @param {string} color - String that represents the new highlight color.
|
||||||
*/
|
*/
|
||||||
setHighlightColor(color: ColorValue) {
|
setHighlightColor(color: ColorValue | null) {
|
||||||
this.highlightColor = color;
|
this.highlightColor = color;
|
||||||
|
|
||||||
if (this.shape) {
|
if (this.shape) {
|
||||||
|
@ -134,15 +134,10 @@ class CellHighlight {
|
||||||
this.shape = this.createShape();
|
this.shape = this.createShape();
|
||||||
this.repaint();
|
this.repaint();
|
||||||
|
|
||||||
const node = this.shape?.node;
|
const node = this.shape.node;
|
||||||
if (
|
|
||||||
!this.keepOnTop &&
|
if (!this.keepOnTop && node?.parentNode?.firstChild !== node) {
|
||||||
this.shape.node?.parentNode?.firstChild !== this.shape.node
|
node.parentNode.insertBefore(node, node.parentNode.firstChild);
|
||||||
) {
|
|
||||||
this.shape.node.parentNode.insertBefore(
|
|
||||||
this.shape.node,
|
|
||||||
this.shape.node.parentNode.firstChild
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -150,20 +145,20 @@ class CellHighlight {
|
||||||
* Creates and returns the highlight shape for the given state.
|
* Creates and returns the highlight shape for the given state.
|
||||||
*/
|
*/
|
||||||
createShape() {
|
createShape() {
|
||||||
const shape = <Shape>(
|
if (!this.state) return;
|
||||||
this.graph.cellRenderer.createShape(<CellState>this.state)
|
|
||||||
);
|
|
||||||
|
|
||||||
shape.svgStrokeTolerance = (<graph>this.graph).tolerance;
|
const shape = this.graph.cellRenderer.createShape(this.state);
|
||||||
shape.points = (<CellState>this.state).absolutePoints;
|
|
||||||
shape.apply(<CellState>this.state);
|
shape.svgStrokeTolerance = this.graph.tolerance;
|
||||||
|
shape.points = this.state.absolutePoints;
|
||||||
|
shape.apply(this.state);
|
||||||
shape.stroke = this.highlightColor;
|
shape.stroke = this.highlightColor;
|
||||||
shape.opacity = this.opacity;
|
shape.opacity = this.opacity;
|
||||||
shape.isDashed = this.dashed;
|
shape.isDashed = this.dashed;
|
||||||
shape.isShadow = false;
|
shape.isShadow = false;
|
||||||
|
|
||||||
shape.dialect = DIALECT_SVG;
|
shape.dialect = DIALECT_SVG;
|
||||||
shape.init((<graph>this.graph).getView().getOverlayPane());
|
shape.init(this.graph.getView().getOverlayPane());
|
||||||
InternalEvent.redirectMouseEvents(shape.node, this.graph, this.state);
|
InternalEvent.redirectMouseEvents(shape.node, this.graph, this.state);
|
||||||
|
|
||||||
if ((<graph>this.graph).dialect !== DIALECT_SVG) {
|
if ((<graph>this.graph).dialect !== DIALECT_SVG) {
|
||||||
|
@ -191,7 +186,7 @@ class CellHighlight {
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
if (this.graph.model.isEdge(this.state.cell)) {
|
if (this.graph.model.isEdge(this.state.cell)) {
|
||||||
this.shape.strokewidth = this.getStrokeWidth();
|
this.shape.strokeWidth = this.getStrokeWidth();
|
||||||
this.shape.points = this.state.absolutePoints;
|
this.shape.points = this.state.absolutePoints;
|
||||||
this.shape.outline = false;
|
this.shape.outline = false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -202,8 +197,7 @@ class CellHighlight {
|
||||||
this.state.height + 2 * this.spacing
|
this.state.height + 2 * this.spacing
|
||||||
);
|
);
|
||||||
this.shape.rotation = Number(this.state.style.rotation || '0');
|
this.shape.rotation = Number(this.state.style.rotation || '0');
|
||||||
this.shape.strokewidth =
|
this.shape.strokeWidth = <number>this.getStrokeWidth() / this.state.view.scale;
|
||||||
<number>this.getStrokeWidth() / this.state.view.scale;
|
|
||||||
this.shape.outline = true;
|
this.shape.outline = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
import Cell from "../cell/datatypes/Cell";
|
import Cell from '../cell/datatypes/Cell';
|
||||||
import CellArray from "../cell/datatypes/CellArray";
|
import CellArray from '../cell/datatypes/CellArray';
|
||||||
import Rectangle from "../geometry/Rectangle";
|
import Rectangle from '../geometry/Rectangle';
|
||||||
import InternalMouseEvent from "../event/InternalMouseEvent";
|
import InternalMouseEvent from '../event/InternalMouseEvent';
|
||||||
import graph from "../Graph";
|
import graph from '../Graph';
|
||||||
import mxClient from "../../mxClient";
|
import mxClient from '../../mxClient';
|
||||||
import SelectionChange from "./SelectionChange";
|
import SelectionChange from './SelectionChange';
|
||||||
import UndoableEdit from "../model/UndoableEdit";
|
import UndoableEdit from '../model/UndoableEdit';
|
||||||
import EventObject from "../event/EventObject";
|
import EventObject from '../event/EventObject';
|
||||||
import InternalEvent from "../event/InternalEvent";
|
import InternalEvent from '../event/InternalEvent';
|
||||||
import EventSource from "../event/EventSource";
|
import EventSource from '../event/EventSource';
|
||||||
import Dictionary from "../../util/Dictionary";
|
import Dictionary from '../../util/Dictionary';
|
||||||
import RootChange from "../model/RootChange";
|
import RootChange from '../model/RootChange';
|
||||||
import ChildChange from "../model/ChildChange";
|
import ChildChange from '../model/ChildChange';
|
||||||
|
|
||||||
class GraphSelection extends EventSource {
|
class GraphSelection extends EventSource {
|
||||||
constructor(graph: graph) {
|
constructor(graph: graph) {
|
||||||
|
@ -50,25 +50,27 @@ class GraphSelection extends EventSource {
|
||||||
*/
|
*/
|
||||||
singleSelection: boolean = false;
|
singleSelection: boolean = false;
|
||||||
|
|
||||||
|
// TODO: Document me!!
|
||||||
|
selectionModel: GraphSelection | null = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the {@link mxGraphSelectionModel} that contains the selection.
|
* Returns the {@link mxGraphSelectionModel} that contains the selection.
|
||||||
*/
|
*/
|
||||||
getSelectionModel(): mxGraphSelectionModel {
|
getSelectionModel() {
|
||||||
return <mxGraphSelectionModel>this.selectionModel;
|
return this.selectionModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@link mxSelectionModel} that contains the selection.
|
* Sets the {@link mxSelectionModel} that contains the selection.
|
||||||
*/
|
*/
|
||||||
setSelectionModel(selectionModel: mxGraphSelectionModel): void {
|
setSelectionModel(selectionModel: GraphSelection) {
|
||||||
this.selectionModel = selectionModel;
|
this.selectionModel = selectionModel;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns {@link singleSelection} as a boolean.
|
* Returns {@link singleSelection} as a boolean.
|
||||||
*/
|
*/
|
||||||
isSingleSelection(): boolean {
|
isSingleSelection() {
|
||||||
return this.singleSelection;
|
return this.singleSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +80,7 @@ class GraphSelection extends EventSource {
|
||||||
* @param {boolean} singleSelection Boolean that specifies the new value for
|
* @param {boolean} singleSelection Boolean that specifies the new value for
|
||||||
* {@link singleSelection}.
|
* {@link singleSelection}.
|
||||||
*/
|
*/
|
||||||
setSingleSelection(singleSelection: boolean): void {
|
setSingleSelection(singleSelection: boolean) {
|
||||||
this.singleSelection = singleSelection;
|
this.singleSelection = singleSelection;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,13 +230,19 @@ class GraphSelection extends EventSource {
|
||||||
* @param added Array of {@link Cell} to add to the selection.
|
* @param added Array of {@link Cell} to add to the selection.
|
||||||
* @param remove Array of {@link Cell} to remove from the selection.
|
* @param remove Array of {@link Cell} to remove from the selection.
|
||||||
*/
|
*/
|
||||||
changeSelection(added: CellArray | null=null,
|
changeSelection(
|
||||||
removed: CellArray | null=null): void {
|
added: CellArray | null = null,
|
||||||
|
removed: CellArray | null = null
|
||||||
|
): void {
|
||||||
if (
|
if (
|
||||||
(added != null && added.length > 0 && added[0] != null) ||
|
(added != null && added.length > 0 && added[0] != null) ||
|
||||||
(removed != null && removed.length > 0 && removed[0] != null)
|
(removed != null && removed.length > 0 && removed[0] != null)
|
||||||
) {
|
) {
|
||||||
const change = new SelectionChange(this, added || new CellArray(), removed || new CellArray());
|
const change = new SelectionChange(
|
||||||
|
this,
|
||||||
|
added || new CellArray(),
|
||||||
|
removed || new CellArray()
|
||||||
|
);
|
||||||
change.execute();
|
change.execute();
|
||||||
const edit = new UndoableEdit(this, false);
|
const edit = new UndoableEdit(this, false);
|
||||||
edit.add(change);
|
edit.add(change);
|
||||||
|
@ -491,8 +499,8 @@ class GraphSelection extends EventSource {
|
||||||
): void {
|
): void {
|
||||||
const cells = descendants
|
const cells = descendants
|
||||||
? parent.filterDescendants((cell: Cell) => {
|
? parent.filterDescendants((cell: Cell) => {
|
||||||
return cell != parent && this.graph.getView().getState(cell) != null;
|
return cell != parent && this.graph.getView().getState(cell) != null;
|
||||||
})
|
})
|
||||||
: parent.getChildren();
|
: parent.getChildren();
|
||||||
|
|
||||||
if (cells != null) {
|
if (cells != null) {
|
||||||
|
@ -589,7 +597,6 @@ class GraphSelection extends EventSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if any sibling of the given cell is selected.
|
* Returns true if any sibling of the given cell is selected.
|
||||||
*/
|
*/
|
||||||
|
@ -646,10 +653,7 @@ class GraphSelection extends EventSource {
|
||||||
for (let i = 0; i < changes.length; i += 1) {
|
for (let i = 0; i < changes.length; i += 1) {
|
||||||
const change = changes[i];
|
const change = changes[i];
|
||||||
|
|
||||||
if (
|
if (change.constructor !== RootChange && (ignoreFn == null || !ignoreFn(change))) {
|
||||||
change.constructor !== RootChange &&
|
|
||||||
(ignoreFn == null || !ignoreFn(change))
|
|
||||||
) {
|
|
||||||
let cell = null;
|
let cell = null;
|
||||||
|
|
||||||
if (change instanceof ChildChange) {
|
if (change instanceof ChildChange) {
|
||||||
|
@ -666,7 +670,6 @@ class GraphSelection extends EventSource {
|
||||||
return cells;
|
return cells;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes selection cells that are not in the model from the selection.
|
* Removes selection cells that are not in the model from the selection.
|
||||||
*/
|
*/
|
||||||
|
@ -695,5 +698,3 @@ class GraphSelection extends EventSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default GraphSelection;
|
export default GraphSelection;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -40,21 +40,16 @@ import InternalMouseEvent from '../event/InternalMouseEvent';
|
||||||
import StyleRegistry from '../style/StyleRegistry';
|
import StyleRegistry from '../style/StyleRegistry';
|
||||||
import graph from '../Graph';
|
import graph from '../Graph';
|
||||||
import Cell from '../cell/datatypes/Cell';
|
import Cell from '../cell/datatypes/Cell';
|
||||||
import Image from '../image/Image';
|
import Image from '../image/ImageBox';
|
||||||
import CurrentRootChange from './CurrentRootChange';
|
import CurrentRootChange from './CurrentRootChange';
|
||||||
import Model from '../model/Model';
|
import Model from '../model/Model';
|
||||||
import Shape from '../geometry/shape/Shape';
|
import Shape from '../geometry/shape/Shape';
|
||||||
import Geometry from '../geometry/Geometry';
|
import Geometry from '../geometry/Geometry';
|
||||||
import ConnectionConstraint from '../connection/ConnectionConstraint';
|
import ConnectionConstraint from '../connection/ConnectionConstraint';
|
||||||
import PopupMenuHandler from '../popups_menus/PopupMenuHandler';
|
import PopupMenuHandler from '../popups_menus/PopupMenuHandler';
|
||||||
import {
|
import { getClientX, getClientY, getSource, isConsumed } from '../../util/EventUtils';
|
||||||
getClientX,
|
|
||||||
getClientY,
|
|
||||||
getSource,
|
|
||||||
isConsumed,
|
|
||||||
} from '../../util/EventUtils';
|
|
||||||
import { clone } from '../../util/CloneUtils';
|
import { clone } from '../../util/CloneUtils';
|
||||||
import CellArray from "../cell/datatypes/CellArray";
|
import CellArray from '../cell/datatypes/CellArray';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @class GraphView
|
* @class GraphView
|
||||||
|
@ -135,8 +130,7 @@ class GraphView extends EventSource {
|
||||||
* being updated. If the resource for this key does not exist then the
|
* being updated. If the resource for this key does not exist then the
|
||||||
* value is used as the status message. Default is 'updatingDocument'.
|
* value is used as the status message. Default is 'updatingDocument'.
|
||||||
*/
|
*/
|
||||||
updatingDocumentResource =
|
updatingDocumentResource = mxClient.language !== 'none' ? 'updatingDocument' : '';
|
||||||
mxClient.language !== 'none' ? 'updatingDocument' : '';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies if string values in cell styles should be evaluated using
|
* Specifies if string values in cell styles should be evaluated using
|
||||||
|
@ -178,7 +172,7 @@ class GraphView extends EventSource {
|
||||||
*/
|
*/
|
||||||
translate = new Point();
|
translate = new Point();
|
||||||
|
|
||||||
states = new Dictionary<CellState>();
|
states = new Dictionary<string, CellState>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies if the style should be updated in each validation step. If this
|
* Specifies if the style should be updated in each validation step. If this
|
||||||
|
@ -243,13 +237,7 @@ class GraphView extends EventSource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.fireEvent(
|
this.fireEvent(
|
||||||
new EventObject(
|
new EventObject(InternalEvent.SCALE, 'scale', value, 'previousScale', previousScale)
|
||||||
InternalEvent.SCALE,
|
|
||||||
'scale',
|
|
||||||
value,
|
|
||||||
'previousScale',
|
|
||||||
previousScale
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -289,13 +277,10 @@ class GraphView extends EventSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fireEvent(
|
this.fireEvent(
|
||||||
new EventObject(
|
new EventObject(InternalEvent.TRANSLATE, {
|
||||||
InternalEvent.TRANSLATE,
|
translate: this.translate,
|
||||||
{
|
previousTranslate: previousTranslate,
|
||||||
translate: this.translate,
|
})
|
||||||
previousTranslate: previousTranslate,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -417,11 +402,7 @@ class GraphView extends EventSource {
|
||||||
const previousScale = this.scale;
|
const previousScale = this.scale;
|
||||||
const previousTranslate = new Point(this.translate.x, this.translate.y);
|
const previousTranslate = new Point(this.translate.x, this.translate.y);
|
||||||
|
|
||||||
if (
|
if (this.scale != scale || this.translate.x != dx || this.translate.y != dy) {
|
||||||
this.scale != scale ||
|
|
||||||
this.translate.x != dx ||
|
|
||||||
this.translate.y != dy
|
|
||||||
) {
|
|
||||||
this.scale = scale;
|
this.scale = scale;
|
||||||
|
|
||||||
this.translate.x = dx;
|
this.translate.x = dx;
|
||||||
|
@ -433,15 +414,12 @@ class GraphView extends EventSource {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fireEvent(
|
this.fireEvent(
|
||||||
new EventObject(
|
new EventObject(InternalEvent.SCALE_AND_TRANSLATE, {
|
||||||
InternalEvent.SCALE_AND_TRANSLATE,
|
scale: scale,
|
||||||
{
|
previousScale: previousScale,
|
||||||
scale: scale,
|
translate: this.translate,
|
||||||
previousScale: previousScale,
|
previousTranslate: previousTranslate,
|
||||||
translate: this.translate,
|
})
|
||||||
previousTranslate: previousTranslate,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,8 +537,7 @@ class GraphView extends EventSource {
|
||||||
validate(cell: Cell | null = null): void {
|
validate(cell: Cell | null = null): void {
|
||||||
const t0 = mxLog.enter('mxGraphView.validate');
|
const t0 = mxLog.enter('mxGraphView.validate');
|
||||||
window.status =
|
window.status =
|
||||||
Resources.get(this.updatingDocumentResource) ||
|
Resources.get(this.updatingDocumentResource) || this.updatingDocumentResource;
|
||||||
this.updatingDocumentResource;
|
|
||||||
|
|
||||||
this.resetValidationState();
|
this.resetValidationState();
|
||||||
|
|
||||||
|
@ -579,9 +556,7 @@ class GraphView extends EventSource {
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
this.setGraphBounds(
|
this.setGraphBounds(graphBounds != null ? graphBounds : this.getEmptyBounds());
|
||||||
graphBounds != null ? graphBounds : this.getEmptyBounds()
|
|
||||||
);
|
|
||||||
this.validateBackground();
|
this.validateBackground();
|
||||||
|
|
||||||
this.resetValidationState();
|
this.resetValidationState();
|
||||||
|
@ -595,10 +570,7 @@ class GraphView extends EventSource {
|
||||||
* {@link translate} with the size of 0 x 0.
|
* {@link translate} with the size of 0 x 0.
|
||||||
*/
|
*/
|
||||||
getEmptyBounds(): Rectangle {
|
getEmptyBounds(): Rectangle {
|
||||||
return new Rectangle(
|
return new Rectangle(this.translate.x * this.scale, this.translate.y * this.scale);
|
||||||
this.translate.x * this.scale,
|
|
||||||
this.translate.y * this.scale
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -634,9 +606,7 @@ class GraphView extends EventSource {
|
||||||
const childCount = state.cell.getChildCount();
|
const childCount = state.cell.getChildCount();
|
||||||
|
|
||||||
for (let i = 0; i < childCount; i += 1) {
|
for (let i = 0; i < childCount; i += 1) {
|
||||||
const bounds = this.getBoundingBox(
|
const bounds = this.getBoundingBox(this.getState(state.cell.getChildAt(i)));
|
||||||
this.getState(state.cell.getChildAt(i))
|
|
||||||
);
|
|
||||||
|
|
||||||
if (bounds != null) {
|
if (bounds != null) {
|
||||||
if (bbox == null) {
|
if (bbox == null) {
|
||||||
|
@ -675,10 +645,7 @@ class GraphView extends EventSource {
|
||||||
const bg = (<graph>this.graph).getBackgroundImage();
|
const bg = (<graph>this.graph).getBackgroundImage();
|
||||||
|
|
||||||
if (bg != null) {
|
if (bg != null) {
|
||||||
if (
|
if (this.backgroundImage == null || this.backgroundImage.imageSrc !== bg.src) {
|
||||||
this.backgroundImage == null ||
|
|
||||||
this.backgroundImage.image !== bg.src
|
|
||||||
) {
|
|
||||||
if (this.backgroundImage != null) {
|
if (this.backgroundImage != null) {
|
||||||
this.backgroundImage.destroy();
|
this.backgroundImage.destroy();
|
||||||
}
|
}
|
||||||
|
@ -734,15 +701,15 @@ class GraphView extends EventSource {
|
||||||
},
|
},
|
||||||
(evt: Event) => {
|
(evt: Event) => {
|
||||||
// Hides the tooltip if mouse is outside container
|
// Hides the tooltip if mouse is outside container
|
||||||
if (
|
if (graph.tooltipHandler != null && graph.tooltipHandler.isHideOnHover()) {
|
||||||
graph.tooltipHandler != null &&
|
|
||||||
graph.tooltipHandler.isHideOnHover()
|
|
||||||
) {
|
|
||||||
graph.tooltipHandler.hide();
|
graph.tooltipHandler.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graph.isMouseDown && !isConsumed(evt)) {
|
if (graph.isMouseDown && !isConsumed(evt)) {
|
||||||
graph.fireMouseEvent(InternalEvent.MOUSE_MOVE, new InternalMouseEvent(evt));
|
graph.fireMouseEvent(
|
||||||
|
InternalEvent.MOUSE_MOVE,
|
||||||
|
new InternalMouseEvent(evt)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(evt: Event) => {
|
(evt: Event) => {
|
||||||
|
@ -859,9 +826,7 @@ class GraphView extends EventSource {
|
||||||
state.invalid = false;
|
state.invalid = false;
|
||||||
|
|
||||||
if (state.style == null || state.invalidStyle) {
|
if (state.style == null || state.invalidStyle) {
|
||||||
state.style = (<graph>this.graph).getCellStyle(
|
state.style = (<graph>this.graph).getCellStyle(<Cell>state.cell);
|
||||||
<Cell>state.cell
|
|
||||||
);
|
|
||||||
state.invalidStyle = false;
|
state.invalidStyle = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -871,19 +836,13 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
state.setVisibleTerminalState(
|
state.setVisibleTerminalState(
|
||||||
<CellState>(
|
<CellState>(
|
||||||
this.validateCellState(
|
this.validateCellState(<Cell>this.getVisibleTerminal(cell, true), false)
|
||||||
<Cell>this.getVisibleTerminal(cell, true),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
state.setVisibleTerminalState(
|
state.setVisibleTerminalState(
|
||||||
<CellState>(
|
<CellState>(
|
||||||
this.validateCellState(
|
this.validateCellState(<Cell>this.getVisibleTerminal(cell, false), false)
|
||||||
<Cell>this.getVisibleTerminal(cell, false),
|
|
||||||
false
|
|
||||||
)
|
|
||||||
),
|
),
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
@ -892,11 +851,7 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
// Repaint happens immediately after the cell is validated
|
// Repaint happens immediately after the cell is validated
|
||||||
if (cell !== this.currentRoot && !state.invalid) {
|
if (cell !== this.currentRoot && !state.invalid) {
|
||||||
(<graph>this.graph).cellRenderer.redraw(
|
(<graph>this.graph).cellRenderer.redraw(state, false, this.isRendering());
|
||||||
state,
|
|
||||||
false,
|
|
||||||
this.isRendering()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Handles changes to invertex paintbounds after update of rendering shape
|
// Handles changes to invertex paintbounds after update of rendering shape
|
||||||
state.updateCachedBounds();
|
state.updateCachedBounds();
|
||||||
|
@ -943,9 +898,7 @@ class GraphView extends EventSource {
|
||||||
origin.y += (<Point>pState.origin).y;
|
origin.y += (<Point>pState.origin).y;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset = (<graph>this.graph).getChildOffsetForCell(
|
let offset = (<graph>this.graph).getChildOffsetForCell(<Cell>state.cell);
|
||||||
<Cell>state.cell
|
|
||||||
);
|
|
||||||
|
|
||||||
if (offset != null) {
|
if (offset != null) {
|
||||||
origin.x += offset.x;
|
origin.x += offset.x;
|
||||||
|
@ -956,9 +909,7 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
if (geo != null) {
|
if (geo != null) {
|
||||||
if (!state.cell.isEdge()) {
|
if (!state.cell.isEdge()) {
|
||||||
offset = <Point>(
|
offset = <Point>(geo.offset != null ? geo.offset : this.EMPTY_POINT);
|
||||||
(geo.offset != null ? geo.offset : this.EMPTY_POINT)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (geo.relative && pState != null) {
|
if (geo.relative && pState != null) {
|
||||||
if (pState.cell.isEdge()) {
|
if (pState.cell.isEdge()) {
|
||||||
|
@ -966,13 +917,9 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
if (origin != null) {
|
if (origin != null) {
|
||||||
origin.x +=
|
origin.x +=
|
||||||
origin.x / this.scale -
|
origin.x / this.scale - (<Point>pState.origin).x - this.translate.x;
|
||||||
(<Point>pState.origin).x -
|
|
||||||
this.translate.x;
|
|
||||||
origin.y +=
|
origin.y +=
|
||||||
origin.y / this.scale -
|
origin.y / this.scale - (<Point>pState.origin).y - this.translate.y;
|
||||||
(<Point>pState.origin).y -
|
|
||||||
this.translate.y;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
origin.x += geo.x * <number>pState.unscaledWidth + offset.x;
|
origin.x += geo.x * <number>pState.unscaledWidth + offset.x;
|
||||||
|
@ -1056,10 +1003,7 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
if (
|
if (
|
||||||
state.cell !== this.currentRoot &&
|
state.cell !== this.currentRoot &&
|
||||||
(pts == null ||
|
(pts == null || pts.length < 2 || pts[0] == null || pts[pts.length - 1] == null)
|
||||||
pts.length < 2 ||
|
|
||||||
pts[0] == null ||
|
|
||||||
pts[pts.length - 1] == null)
|
|
||||||
) {
|
) {
|
||||||
// This will remove edges with invalid points from the list of states in the view.
|
// This will remove edges with invalid points from the list of states in the view.
|
||||||
// Happens if the one of the terminals and the corresponding terminal point is null.
|
// Happens if the one of the terminals and the corresponding terminal point is null.
|
||||||
|
@ -1170,11 +1114,7 @@ class GraphView extends EventSource {
|
||||||
* @param source {@link mxCellState} which represents the source terminal.
|
* @param source {@link mxCellState} which represents the source terminal.
|
||||||
* @param target {@link mxCellState} which represents the target terminal.
|
* @param target {@link mxCellState} which represents the target terminal.
|
||||||
*/
|
*/
|
||||||
updateFixedTerminalPoints(
|
updateFixedTerminalPoints(edge: CellState, source: CellState, target: CellState): void {
|
||||||
edge: CellState,
|
|
||||||
source: CellState,
|
|
||||||
target: CellState
|
|
||||||
): void {
|
|
||||||
this.updateFixedTerminalPoint(
|
this.updateFixedTerminalPoint(
|
||||||
edge,
|
edge,
|
||||||
source,
|
source,
|
||||||
|
@ -1234,11 +1174,7 @@ class GraphView extends EventSource {
|
||||||
let pt = null;
|
let pt = null;
|
||||||
|
|
||||||
if (constraint != null) {
|
if (constraint != null) {
|
||||||
pt = (<graph>this.graph).getConnectionPoint(
|
pt = (<graph>this.graph).getConnectionPoint(terminal, constraint, false); // FIXME Rounding introduced bugs when calculating label positions -> , this.graph.isOrthogonal(edge));
|
||||||
terminal,
|
|
||||||
constraint,
|
|
||||||
false
|
|
||||||
); // FIXME Rounding introduced bugs when calculating label positions -> , this.graph.isOrthogonal(edge));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pt == null && terminal == null) {
|
if (pt == null && terminal == null) {
|
||||||
|
@ -1249,10 +1185,7 @@ class GraphView extends EventSource {
|
||||||
pt = geo.getTerminalPoint(source);
|
pt = geo.getTerminalPoint(source);
|
||||||
|
|
||||||
if (pt != null) {
|
if (pt != null) {
|
||||||
pt = new Point(
|
pt = new Point(s * (tr.x + pt.x + orig.x), s * (tr.y + pt.y + orig.y));
|
||||||
s * (tr.x + pt.x + orig.x),
|
|
||||||
s * (tr.y + pt.y + orig.y)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1325,21 +1258,11 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
// Restores previous bounds
|
// Restores previous bounds
|
||||||
if (srcBounds != null) {
|
if (srcBounds != null) {
|
||||||
src.setRect(
|
src.setRect(srcBounds.x, srcBounds.y, srcBounds.width, srcBounds.height);
|
||||||
srcBounds.x,
|
|
||||||
srcBounds.y,
|
|
||||||
srcBounds.width,
|
|
||||||
srcBounds.height
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trgBounds != null) {
|
if (trgBounds != null) {
|
||||||
trg.setRect(
|
trg.setRect(trgBounds.x, trgBounds.y, trgBounds.width, trgBounds.height);
|
||||||
trgBounds.x,
|
|
||||||
trgBounds.y,
|
|
||||||
trgBounds.width,
|
|
||||||
trgBounds.height
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} else if (points != null) {
|
} else if (points != null) {
|
||||||
for (let i = 0; i < points.length; i += 1) {
|
for (let i = 0; i < points.length; i += 1) {
|
||||||
|
@ -1388,16 +1311,8 @@ class GraphView extends EventSource {
|
||||||
source: CellState | null = null,
|
source: CellState | null = null,
|
||||||
target: CellState | null = null
|
target: CellState | null = null
|
||||||
): boolean {
|
): boolean {
|
||||||
const sc = (<graph>this.graph).getConnectionConstraint(
|
const sc = (<graph>this.graph).getConnectionConstraint(edge, source, true);
|
||||||
edge,
|
const tc = (<graph>this.graph).getConnectionConstraint(edge, target, false);
|
||||||
source,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
const tc = (<graph>this.graph).getConnectionConstraint(
|
|
||||||
edge,
|
|
||||||
target,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(points == null || points.length < 2) &&
|
(points == null || points.length < 2) &&
|
||||||
|
@ -1516,16 +1431,9 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
let border = parseFloat(edge.style.perimeterSpacing || 0);
|
let border = parseFloat(edge.style.perimeterSpacing || 0);
|
||||||
border += parseFloat(
|
border += parseFloat(
|
||||||
edge.style[
|
edge.style[source ? 'sourcePerimeterSpacing' : 'targetPerimeterSpacing'] || 0
|
||||||
source ? 'sourcePerimeterSpacing' : 'targetPerimeterSpacing'
|
|
||||||
] || 0
|
|
||||||
);
|
|
||||||
let pt = this.getPerimeterPoint(
|
|
||||||
start,
|
|
||||||
<Point>next,
|
|
||||||
alpha === 0 && orth,
|
|
||||||
border
|
|
||||||
);
|
);
|
||||||
|
let pt = this.getPerimeterPoint(start, <Point>next, alpha === 0 && orth, border);
|
||||||
|
|
||||||
if (alpha !== 0) {
|
if (alpha !== 0) {
|
||||||
const cos = Math.cos(alpha);
|
const cos = Math.cos(alpha);
|
||||||
|
@ -1553,10 +1461,7 @@ class GraphView extends EventSource {
|
||||||
const id = getValue(state.style, key);
|
const id = getValue(state.style, key);
|
||||||
|
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
const tmp = this.getState(
|
const tmp = this.getState((<graph>this.graph).getModel().getCell(id), false);
|
||||||
(<graph>this.graph).getModel().getCell(id),
|
|
||||||
false
|
|
||||||
);
|
|
||||||
|
|
||||||
// Only uses ports where a cell state exists
|
// Only uses ports where a cell state exists
|
||||||
if (tmp != null) {
|
if (tmp != null) {
|
||||||
|
@ -1641,8 +1546,7 @@ class GraphView extends EventSource {
|
||||||
* Returns the x-coordinate of the center point for automatic routing.
|
* Returns the x-coordinate of the center point for automatic routing.
|
||||||
*/
|
*/
|
||||||
getRoutingCenterX(state: CellState): number {
|
getRoutingCenterX(state: CellState): number {
|
||||||
const f =
|
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;
|
return state.getCenterX() + f * state.width;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1650,8 +1554,7 @@ class GraphView extends EventSource {
|
||||||
* Returns the y-coordinate of the center point for automatic routing.
|
* Returns the y-coordinate of the center point for automatic routing.
|
||||||
*/
|
*/
|
||||||
getRoutingCenterY(state: CellState): number {
|
getRoutingCenterY(state: CellState): number {
|
||||||
const f =
|
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;
|
return state.getCenterY() + f * state.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1986,8 +1889,7 @@ class GraphView extends EventSource {
|
||||||
if (dotprod <= 0.0) {
|
if (dotprod <= 0.0) {
|
||||||
projlenSq = 0;
|
projlenSq = 0;
|
||||||
} else {
|
} else {
|
||||||
projlenSq =
|
projlenSq = (dotprod * dotprod) / (xSegment * xSegment + ySegment * ySegment);
|
||||||
(dotprod * dotprod) / (xSegment * xSegment + ySegment * ySegment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let projlen = Math.sqrt(projlenSq);
|
let projlen = Math.sqrt(projlenSq);
|
||||||
|
@ -2139,11 +2041,7 @@ class GraphView extends EventSource {
|
||||||
* @param cell {@link mxCell} for which a new {@link CellState} should be created.
|
* @param cell {@link mxCell} for which a new {@link CellState} should be created.
|
||||||
*/
|
*/
|
||||||
createState(cell: Cell): CellState {
|
createState(cell: Cell): CellState {
|
||||||
return new CellState(
|
return new CellState(this, cell, (<graph>this.graph).getCellStyle(cell));
|
||||||
this,
|
|
||||||
cell,
|
|
||||||
(<graph>this.graph).getCellStyle(cell)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2290,9 +2188,7 @@ class GraphView extends EventSource {
|
||||||
// Dispatches the drop event to the graph which
|
// Dispatches the drop event to the graph which
|
||||||
// consumes and executes the source function
|
// consumes and executes the source function
|
||||||
const pt = convertPoint(container, x, y);
|
const pt = convertPoint(container, x, y);
|
||||||
state = (<GraphView>graph.view).getState(
|
state = (<GraphView>graph.view).getState(graph.getCellAt(pt.x, pt.y));
|
||||||
graph.getCellAt(pt.x, pt.y)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return state;
|
return state;
|
||||||
|
@ -2312,10 +2208,7 @@ class GraphView extends EventSource {
|
||||||
|
|
||||||
this.moveHandler = (evt: Event) => {
|
this.moveHandler = (evt: Event) => {
|
||||||
// Hides the tooltip if mouse is outside container
|
// Hides the tooltip if mouse is outside container
|
||||||
if (
|
if (graph.tooltipHandler != null && graph.tooltipHandler.isHideOnHover()) {
|
||||||
graph.tooltipHandler != null &&
|
|
||||||
graph.tooltipHandler.isHideOnHover()
|
|
||||||
) {
|
|
||||||
graph.tooltipHandler.hide();
|
graph.tooltipHandler.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2368,26 +2261,17 @@ class GraphView extends EventSource {
|
||||||
));
|
));
|
||||||
|
|
||||||
// For background image
|
// For background image
|
||||||
this.backgroundPane = document.createElementNS(
|
this.backgroundPane = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
'http://www.w3.org/2000/svg',
|
|
||||||
'g'
|
|
||||||
);
|
|
||||||
canvas.appendChild(this.backgroundPane);
|
canvas.appendChild(this.backgroundPane);
|
||||||
|
|
||||||
// Adds two layers (background is early feature)
|
// Adds two layers (background is early feature)
|
||||||
this.drawPane = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
this.drawPane = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
canvas.appendChild(this.drawPane);
|
canvas.appendChild(this.drawPane);
|
||||||
|
|
||||||
this.overlayPane = document.createElementNS(
|
this.overlayPane = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
'http://www.w3.org/2000/svg',
|
|
||||||
'g'
|
|
||||||
);
|
|
||||||
canvas.appendChild(this.overlayPane);
|
canvas.appendChild(this.overlayPane);
|
||||||
|
|
||||||
this.decoratorPane = document.createElementNS(
|
this.decoratorPane = document.createElementNS('http://www.w3.org/2000/svg', 'g');
|
||||||
'http://www.w3.org/2000/svg',
|
|
||||||
'g'
|
|
||||||
);
|
|
||||||
canvas.appendChild(this.decoratorPane);
|
canvas.appendChild(this.decoratorPane);
|
||||||
|
|
||||||
const root = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
const root = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
|
||||||
|
|
Loading…
Reference in New Issue