ngx-diagrams
Version:
This library was generated with [Angular CLI](https://github.com/angular/angular-cli) version 7.2.0.
2,103 lines (2,087 loc) • 130 kB
JavaScript
import { EventEmitter, Component, ChangeDetectionStrategy, Renderer2, ChangeDetectorRef, Input, Output, ViewChild, ViewContainerRef, ElementRef, NgModule, Injectable, ComponentFactoryResolver, RendererFactory2, ɵɵdefineInjectable, ɵɵinject } from '@angular/core';
import { Subject, BehaviorSubject, ReplaySubject, combineLatest } from 'rxjs';
import { tap, takeUntil, map, filter, mapTo, distinctUntilChanged, take, delay } from 'rxjs/operators';
import { flatMap, uniq, some } from 'lodash';
import { CommonModule } from '@angular/common';
import { graphlib, layout } from 'dagre';
/**
* @fileoverview added by tsickle
* Generated from: lib/utils/tool-kit.util.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/** @enum {number} */
const LOG_LEVEL = {
'LOG': 0,
'ERROR': 1,
};
LOG_LEVEL[LOG_LEVEL['LOG']] = 'LOG';
LOG_LEVEL[LOG_LEVEL['ERROR']] = 'ERROR';
// @internal
/** @type {?} */
let __DEV__ = true;
// @internal
/** @type {?} */
let __LOG__ = LOG_LEVEL.ERROR;
/**
* @return {?}
*/
function enableDiagramProdMode() {
__DEV__ = false;
}
// @internal
/**
* @param {?} level
* @return {?}
*/
function setLogLevel(level) {
__LOG__ = level;
}
// @internal
/**
* @return {?}
*/
function isDev() {
return __DEV__;
}
// @internal
/**
* @param {?} message
* @param {?=} level
* @param {...?} args
* @return {?}
*/
function log(message, level = LOG_LEVEL.LOG, ...args) {
if (isDev() && __LOG__ === level) {
if (__LOG__ === LOG_LEVEL.ERROR) {
console.error(message, ...args);
}
console.log(message, ...args);
}
}
/**
* rxjs log operator
* \@internal
* @param {?} message
* @param {?=} level
* @param {...?} args
* @return {?}
*/
function withLog(message, level = LOG_LEVEL.LOG, ...args) {
return (/**
* @template T
* @param {?} source
* @return {?}
*/
(source) => (isDev() ? source.pipe(tap((/**
* @param {?} val
* @return {?}
*/
val => log(message, level, val, ...args)))) : source));
}
/**
* Generates a unique ID
* @return {?}
*/
function UID() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (/**
* @param {?} c
* @return {?}
*/
c => {
/** @type {?} */
const r = (Math.random() * 16) | 0;
/** @type {?} */
const v = c === 'x' ? r : (r & 0x3) | 0x8;
return v.toString(16);
}));
}
/**
* @template T
* @param {?} val
* @return {?}
*/
function isArray(val) {
return Array.isArray(val);
}
/**
* @param {?} val
* @return {?}
*/
function isString(val) {
return typeof val === 'string';
}
/**
* @param {?} val
* @return {?}
*/
function isFunction(val) {
return typeof val === 'function';
}
// @internal
/**
* @param {?} v
* @return {?}
*/
function isNil(v) {
return v === null || v === undefined;
}
/**
* @template T
* @param {?} value
* @return {?}
*/
function coerceArray(value) {
if (isNil(value)) {
return [];
}
return Array.isArray(value) ? value : [value];
}
/**
* @template T
* @param {?} map
* @return {?}
*/
function mapToArray(map) {
/** @type {?} */
const result = [];
for (const key in map) {
if (!isNil(map[key])) {
result.push(map[key]);
}
}
return result;
}
/**
* @template T
* @param {?} arr
* @return {?}
*/
function arrayToMap(arr) {
/** @type {?} */
const result = {};
for (const val of arr) {
if (!isNil(val)) {
result[val.id] = val;
}
}
return result;
}
/**
* @param {?} firstPoint
* @param {?} lastPoint
* @return {?}
*/
function generateLinePath(firstPoint, lastPoint) {
return `M${firstPoint.x$},${firstPoint.y} L ${lastPoint.x$},${lastPoint.y}`;
}
/**
* @param {?} firstPoint
* @param {?} lastPoint
* @param {?=} curvy
* @return {?}
*/
function generateCurvePath(firstPoint, lastPoint, curvy = 0) {
/** @type {?} */
const isHorizontal = Math.abs(firstPoint.x - lastPoint.x) > Math.abs(firstPoint.y - lastPoint.y);
/** @type {?} */
const curvyX = isHorizontal ? curvy : 0;
/** @type {?} */
const curvyY = isHorizontal ? 0 : curvy;
return `M${firstPoint.x},${firstPoint.y} C ${firstPoint.x + curvyX},${firstPoint.y + curvyY}
${lastPoint.x - curvyX},${lastPoint.y - curvyY} ${lastPoint.x},${lastPoint.y}`;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/interfaces/event.interface.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// region events
/**
* @template T
*/
class BaseEvent {
/**
* @param {?} entity
*/
constructor(entity) {
this.id = UID();
this.entity = entity;
this.entityId = entity.id;
this.firing = true;
this.stopPropagation = (/**
* @return {?}
*/
() => (this.firing = false));
}
}
if (false) {
/** @type {?} */
BaseEvent.prototype.entity;
/** @type {?} */
BaseEvent.prototype.entityId;
/** @type {?} */
BaseEvent.prototype.stopPropagation;
/** @type {?} */
BaseEvent.prototype.firing;
/** @type {?} */
BaseEvent.prototype.id;
}
/**
* @template T
*/
class LockEvent extends BaseEvent {
/**
* @param {?} entity
* @param {?=} locked
*/
constructor(entity, locked = false) {
super(entity);
this.locked = locked;
}
}
if (false) {
/** @type {?} */
LockEvent.prototype.locked;
}
/**
* @template P, T
*/
class ParentChangeEvent extends BaseEvent {
/**
* @param {?} entity
* @param {?} parent
*/
constructor(entity, parent) {
super(entity);
this.parent = parent;
}
}
if (false) {
/** @type {?} */
ParentChangeEvent.prototype.parent;
}
/**
* @template T
*/
class SelectionEvent extends BaseEvent {
/**
* @param {?} entity
* @param {?} selected
*/
constructor(entity, selected) {
super(entity);
this.isSelected = selected;
}
}
if (false) {
/** @type {?} */
SelectionEvent.prototype.isSelected;
}
/**
* @template T
*/
class PaintedEvent extends BaseEvent {
/**
* @param {?} entity
* @param {?=} painted
*/
constructor(entity, painted = false) {
super(entity);
this.isPainted = painted;
}
}
if (false) {
/** @type {?} */
PaintedEvent.prototype.isPainted;
}
/**
* @record
*/
function DestroyOptions() { }
if (false) {
/** @type {?|undefined} */
DestroyOptions.prototype.propagate;
/** @type {?|undefined} */
DestroyOptions.prototype.emit;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/base.entity.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class BaseEntity {
/**
* @param {?=} id
* @param {?=} logPrefix
*/
constructor(id, logPrefix = '') {
this._destroyed = new Subject();
this._destroyed$ = this._destroyed.asObservable();
this._locked = new BehaviorSubject(false);
this._locked$ = this._locked.asObservable();
this._id = id || UID();
this._logPrefix = `${logPrefix}`;
}
/**
* @return {?}
*/
get id() {
return this._id;
}
/**
* @param {?} id
* @return {?}
*/
set id(id) {
this._id = id;
}
/**
* @param {?} message
* @param {...?} args
* @return {?}
*/
log(message, ...args) {
log(`${this._logPrefix} ${message}: `, LOG_LEVEL.LOG, ...args);
}
/**
* @param {?} message
* @param {...?} args
* @return {?}
*/
withLog(message, ...args) {
return withLog(`${this._logPrefix} ${message}: `, LOG_LEVEL.LOG, ...args);
}
/**
* @return {?}
*/
getLocked() {
return this._locked.getValue();
}
/**
* @param {?=} locked
* @return {?}
*/
setLocked(locked = true) {
this._locked.next(locked);
}
// tslint:disable-next-line
/**
* @param {?=} lookupTable
* @param {?=} clone
* @return {?}
*/
doClone(lookupTable = {}, clone) {
/*noop*/
}
/**
* @param {?=} lookupTable
* @return {?}
*/
clone(lookupTable = {}) {
// try and use an existing clone first
if (lookupTable[this.id]) {
return lookupTable[this.id];
}
/** @type {?} */
const clone = Object.assign({}, this);
clone.id = UID();
// clone.clearListeners();
lookupTable[this.id] = clone;
this.doClone(lookupTable, clone);
return clone;
}
/**
* @return {?}
*/
lockChanges() {
return this._locked$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} locked
* @return {?}
*/
locked => new LockEvent(this, locked))), this.withLog('lockChanges'));
}
/**
* @param {?=} options
* @return {?}
*/
destroy(options) {
/** @type {?} */
const defaultOptions = Object.assign({ emit: true, propagate: true }, options);
this.log('entity destroyed');
this._destroyed.next(defaultOptions);
this._destroyed.complete();
}
/**
* @return {?}
*/
onEntityDestroy() {
return this._destroyed$.pipe(filter((/**
* @param {?} opts
* @return {?}
*/
opts => opts.emit)), mapTo(new BaseEvent(this)));
}
}
if (false) {
/**
* @type {?}
* @private
*/
BaseEntity.prototype._id;
/**
* a prefix to make logs more easier
* @type {?}
* @private
*/
BaseEntity.prototype._logPrefix;
/**
* @type {?}
* @private
*/
BaseEntity.prototype._destroyed;
/**
* @type {?}
* @private
*/
BaseEntity.prototype._destroyed$;
/**
* @type {?}
* @private
*/
BaseEntity.prototype._locked;
/**
* @type {?}
* @private
*/
BaseEntity.prototype._locked$;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/base.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @template X
*/
class BaseModel extends BaseEntity {
/**
* @param {?=} type
* @param {?=} id
* @param {?=} logPrefix
*/
constructor(type, id, logPrefix = '[Base]') {
super(id, logPrefix);
this._parent = new BehaviorSubject(null);
this._parent$ = this._parent.asObservable();
this._selected = new BehaviorSubject(false);
this._selected$ = this._selected.asObservable();
this._painted = new BehaviorSubject(false);
this._painted$ = this._painted.asObservable();
this._type = type;
}
/**
* @return {?}
*/
getParent() {
return this._parent.getValue();
}
/**
* @param {?} parent
* @return {?}
*/
setParent(parent) {
this._parent.next(parent);
}
/**
* @return {?}
*/
parentChanges() {
return this._parent$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} p
* @return {?}
*/
p => new ParentChangeEvent(this, p))));
}
/**
* @return {?}
*/
getPainted() {
return this._painted.getValue();
}
/**
* @param {?=} painted
* @return {?}
*/
setPainted(painted = true) {
this._painted.next(painted);
}
/**
* @return {?}
*/
paintChanges() {
return this._painted$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} p
* @return {?}
*/
p => new PaintedEvent(this, p))));
}
/**
* @return {?}
*/
getType() {
return this._type;
}
/**
* @return {?}
*/
getSelected() {
return this._selected.getValue();
}
/**
* @return {?}
*/
selectSelected() {
return this._selected.asObservable();
}
/**
* @param {?=} selected
* @return {?}
*/
setSelected(selected = true) {
this._selected.next(selected);
}
/**
* @return {?}
*/
selectionChanges() {
return this._selected$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} s
* @return {?}
*/
s => new SelectionEvent(this, s))), this.withLog('selectionChanges'));
}
/**
* @return {?}
*/
getSelectedEntities() {
return this._selected.value ? [this] : [];
}
}
if (false) {
/**
* @type {?}
* @private
*/
BaseModel.prototype._type;
/**
* @type {?}
* @private
*/
BaseModel.prototype._parent;
/**
* @type {?}
* @private
*/
BaseModel.prototype._parent$;
/**
* @type {?}
* @private
*/
BaseModel.prototype._selected;
/**
* @type {?}
* @private
*/
BaseModel.prototype._selected$;
/**
* @type {?}
* @private
*/
BaseModel.prototype._painted;
/**
* @type {?}
* @private
*/
BaseModel.prototype._painted$;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/node.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @template P
*/
class NodeModel extends BaseModel {
/**
* @param {?=} nodeType
* @param {?=} id
* @param {?=} extras
* @param {?=} x
* @param {?=} y
* @param {?=} width
* @param {?=} height
* @param {?=} logPrefix
*/
constructor(nodeType = 'default', id, extras = {}, x = 0, y = 0, width = 0, height = 0, logPrefix = '[Node]') {
super(nodeType, id, logPrefix);
this._extras = new BehaviorSubject(extras);
this._ports = new BehaviorSubject({});
this._dimensions = new BehaviorSubject({ width, height });
this._coords = new BehaviorSubject({ x, y });
this.extras$ = this._extras.asObservable();
this.ports$ = this._ports.asObservable();
this.coords$ = this._coords.asObservable();
this.dimensions$ = this._dimensions.asObservable();
}
/**
* @return {?}
*/
getCoords() {
return this._coords.getValue();
}
/**
* @param {?} __0
* @return {?}
*/
setCoords({ x, y }) {
const { x: oldX, y: oldY } = this.getCoords();
Object.values(this._ports.getValue()).forEach((/**
* @param {?} port
* @return {?}
*/
port => {
Object.values(port.getLinks()).forEach((/**
* @param {?} link
* @return {?}
*/
link => {
/** @type {?} */
const point = link.getPointForPort(port);
const { x: pointX, y: pointY } = point.getCoords();
point.setCoords({ x: pointX + x - oldX, y: pointY + y - oldY });
}));
}));
this._coords.next({ x, y });
}
// TODO: implement better transition on auto arrange!
/**
* @param {?} __0
* @return {?}
*/
transitionToCoords({ x, y }) {
// const transitionCompleted = new ReplaySubject(1);
// let { x: oldX, y: oldY } = this.getCoords();
// console.log(x, y, oldX, oldY);
// interval(0)
// .pipe(takeUntil(transitionCompleted))
// .subscribe(
// () => {
// if (oldX < x) {
// oldX++;
// } else if (oldX > x) {
// oldX--;
// }
// if (y > oldY) {
// oldY++;
// } else if (y < oldY) {
// oldY--;
// }
// Object.values(this._ports.getValue()).forEach(port => {
// Object.values(port.getLinks()).forEach(link => {
// const point = link.getPointForPort(port);
// const { x: pointX, y: pointY } = point.getCoords();
// point.setCoords({ x: pointX + x - oldX, y: pointY + y - oldY });
// });
// });
// this._coords.next({ x: oldX, y: oldY });
// if (x === oldX && y === oldY) {
// transitionCompleted.next(true);
// transitionCompleted.complete();
// }
// },
// err => {
// console.error(err);
// },
// () => {
// console.log('finished transition');
// }
// );
}
// TODO: override selectionChanges and replace this with it (convert to rx)
/**
* @return {?}
*/
getSelectedEntities() {
/** @type {?} */
let entities = super.getSelectedEntities();
// add the points of each link that are selected here
if (this.getSelected()) {
Object.values(this._ports.getValue()).forEach((/**
* @param {?} port
* @return {?}
*/
port => {
/** @type {?} */
const links = Object.values(port.getLinks());
entities = entities.concat(links.map((/**
* @param {?} link
* @return {?}
*/
link => {
return link.getPointForPort(port);
})));
}));
}
this.log('selectedEntities', entities);
return entities;
}
// TODO: map to BaseEvent
/**
* @return {?}
*/
coordsChanges() {
return this.coords$.pipe(takeUntil(this.onEntityDestroy()));
}
/**
* @return {?}
*/
selectCoords() {
return this.coords$.pipe(takeUntil(this.onEntityDestroy()), distinctUntilChanged());
}
/**
* @return {?}
*/
selectX() {
return this.selectCoords().pipe(map((/**
* @param {?} c
* @return {?}
*/
c => c.x)), this.withLog('selectX'), distinctUntilChanged());
}
/**
* @return {?}
*/
selectY() {
return this.selectCoords().pipe(map((/**
* @param {?} c
* @return {?}
*/
c => c.y)), this.withLog('selectY'), distinctUntilChanged());
}
/**
* Assign a port to the node and set the node as its getParent
* @param {?} port
* @return {?} the inserted port
*/
addPort(port) {
port.setParent(this);
this._ports.next(Object.assign({}, this._ports.value, { [port.id]: port }));
return port;
}
/**
* @param {?} id
* @return {?}
*/
getPort(id) {
return this._ports.value[id];
}
/**
* @param {?=} selector
* @return {?}
*/
selectPorts(selector) {
// TODO: implement selector
// TODO: create coerce func
return this.ports$.pipe(takeUntil(this.onEntityDestroy()), distinctUntilChanged(), map((/**
* @param {?} ports
* @return {?}
*/
ports => mapToArray(ports))), this.withLog('selectPorts'));
}
/**
* @param {?=} ids
* @return {?}
*/
getPorts(ids) {
return this._ports.getValue();
}
/**
* @param {?} __0
* @return {?}
*/
setDimensions({ width, height }) {
this._dimensions.next({ width, height });
}
/**
* @return {?}
*/
getDimensions() {
return this._dimensions.getValue();
}
// TODO: return BaseEvent extension
/**
* @return {?}
*/
dimensionChanges() {
return this.dimensions$.pipe(takeUntil(this.onEntityDestroy()), distinctUntilChanged(), this.withLog('DimensionChanges'));
}
/**
* @return {?}
*/
getHeight() {
return this._dimensions.getValue().height;
}
/**
* @return {?}
*/
getWidth() {
return this._dimensions.getValue().width;
}
/**
* @return {?}
*/
selectWidth() {
return this.dimensions$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} d
* @return {?}
*/
d => d.width)), distinctUntilChanged(), this.withLog('selectWidth'));
}
/**
* @return {?}
*/
selectHeight() {
return this.dimensions$.pipe(takeUntil(this.onEntityDestroy()), map((/**
* @param {?} d
* @return {?}
*/
d => d.width)), distinctUntilChanged(), this.withLog('selectHeight'));
}
/**
* @param {?} extras
* @return {?}
*/
setExtras(extras) {
this._extras.next(extras);
}
/**
* @return {?}
*/
getExtras() {
return this._extras.getValue();
}
/**
* @template E
* @param {?=} selector
* @return {?}
*/
selectExtras(selector) {
// TODO: impl selector
return this.extras$.pipe(takeUntil(this.onEntityDestroy()), distinctUntilChanged());
}
}
if (false) {
/** @type {?} */
NodeModel.prototype.id;
/** @type {?} */
NodeModel.prototype.diagramEngine;
/**
* @type {?}
* @private
*/
NodeModel.prototype._extras;
/**
* @type {?}
* @private
*/
NodeModel.prototype._ports;
/**
* @type {?}
* @private
*/
NodeModel.prototype._coords;
/**
* @type {?}
* @private
*/
NodeModel.prototype._dimensions;
/**
* @type {?}
* @private
*/
NodeModel.prototype.extras$;
/**
* @type {?}
* @private
*/
NodeModel.prototype.ports$;
/**
* @type {?}
* @private
*/
NodeModel.prototype.coords$;
/**
* @type {?}
* @private
*/
NodeModel.prototype.dimensions$;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/point.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class PointModel extends BaseModel {
/**
* @param {?} link
* @param {?} __1
*/
constructor(link, { x, y }) {
super();
this._coords = new BehaviorSubject({ x, y });
this.coords$ = this._coords.asObservable();
this.setParent(link);
}
/**
* @return {?}
*/
isConnectedToPort() {
return this.getParent().getPortForPoint(this) !== null;
}
/**
* @return {?}
*/
getLink() {
return this.getParent();
}
/**
* @param {?=} options
* @return {?}
*/
destroy(options) {
if (this.getParent) {
this.getParent().removePoint(this);
}
super.destroy(options);
}
/**
* @param {?} newCoords
* @return {?}
*/
setCoords(newCoords) {
this._coords.next(Object.assign({}, this._coords.getValue(), newCoords));
}
/**
* @return {?}
*/
selectCoords() {
return this.coords$.pipe(takeUntil(this.onEntityDestroy()), distinctUntilChanged());
}
/**
* @return {?}
*/
getCoords() {
return this._coords.getValue();
}
/**
* @return {?}
*/
selectX() {
return this.selectCoords().pipe(map((/**
* @param {?} c
* @return {?}
*/
c => c.x)), distinctUntilChanged());
}
/**
* @return {?}
*/
selectY() {
return this.selectCoords().pipe(map((/**
* @param {?} c
* @return {?}
*/
c => c.y)), distinctUntilChanged());
}
}
if (false) {
/**
* @type {?}
* @private
*/
PointModel.prototype._coords;
/**
* @type {?}
* @private
*/
PointModel.prototype.coords$;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/link.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class LinkModel extends BaseModel {
/**
* @param {?=} linkType
* @param {?=} id
*/
constructor(linkType = 'default', id) {
super(linkType, id);
this.label = new BehaviorSubject(null);
this.points = [new PointModel(this, { x: 0, y: 0 }), new PointModel(this, { x: 0, y: 0 })];
this.extras = {};
this.sourcePort = null;
this.targetPort = null;
}
/**
* @param {?} name
* @return {?}
*/
setName(name) {
this.name = name;
}
/**
* @return {?}
*/
getName() {
return this.name;
}
/**
* @return {?}
*/
getExtras() {
return this.extras;
}
/**
* @param {?} extras
* @return {?}
*/
setExtras(extras) {
this.extras = extras;
}
/**
* @param {?=} options
* @return {?}
*/
destroy(options) {
if (this.sourcePort) {
this.sourcePort.removeLink(this);
}
if (this.targetPort) {
this.targetPort.removeLink(this);
}
super.destroy(options);
}
/**
* @param {?=} lookupTable
* @param {?=} clone
* @return {?}
*/
doClone(lookupTable = {}, clone) {
clone.setPoints(this.getPoints().map((/**
* @param {?} point
* @return {?}
*/
(point) => {
return point.clone(lookupTable);
})));
if (this.sourcePort) {
clone.setSourcePort(this.sourcePort.clone(lookupTable));
}
if (this.targetPort) {
clone.setTargetPort(this.targetPort.clone(lookupTable));
}
}
/**
* @param {?} point
* @return {?}
*/
isLastPoint(point) {
/** @type {?} */
const index = this.getPointIndex(point);
return index === this.points.length - 1;
}
/**
* @param {?} point
* @return {?}
*/
getPointIndex(point) {
return this.points.indexOf(point);
}
/**
* @param {?} id
* @return {?}
*/
getPointModel(id) {
for (const point of this.points) {
if (point.id === id) {
return point;
}
}
return null;
}
/**
* @param {?} point
* @return {?}
*/
getPortForPoint(point) {
if (this.sourcePort !== null && this.getFirstPoint().id === point.id) {
return this.sourcePort;
}
if (this.targetPort !== null && this.getLastPoint().id === point.id) {
return this.targetPort;
}
return null;
}
/**
* @param {?} port
* @return {?}
*/
getPointForPort(port) {
if (this.sourcePort !== null && this.sourcePort.id === port.id) {
return this.getFirstPoint();
}
if (this.targetPort !== null && this.targetPort.id === port.id) {
return this.getLastPoint();
}
return null;
}
/**
* @return {?}
*/
getFirstPoint() {
return this.points[0];
}
/**
* @return {?}
*/
getLastPoint() {
return this.points[this.points.length - 1];
}
/**
* @param {?} port
* @return {?}
*/
setSourcePort(port) {
if (port !== null) {
port.addLink(this);
}
if (this.sourcePort !== null) {
this.sourcePort.removeLink(this);
}
this.sourcePort = port;
}
/**
* @return {?}
*/
getSourcePort() {
return this.sourcePort;
}
/**
* @return {?}
*/
getTargetPort() {
return this.targetPort;
}
/**
* @param {?} port
* @return {?}
*/
setTargetPort(port) {
if (port !== null) {
port.addLink(this);
}
if (this.targetPort !== null) {
this.targetPort.removeLink(this);
}
this.targetPort = port;
}
/**
* @param {?} __0
* @return {?}
*/
point({ x, y }) {
return this.addPoint(this.generatePoint({ x, y }));
}
/**
* @return {?}
*/
getPoints() {
return this.points;
}
/**
* @param {?} points
* @return {?}
*/
setPoints(points) {
points.forEach((/**
* @param {?} point
* @return {?}
*/
point => {
point.setParent(this);
}));
this.points = points;
}
/**
* @param {?} label
* @return {?}
*/
setLabel(label) {
label.setParent(this);
this.label.next(label);
label.setPainted();
}
/**
* @return {?}
*/
selectLabel() {
return this.label.asObservable();
}
/**
* @return {?}
*/
getLabel() {
return this.label.getValue();
}
/**
* @return {?}
*/
resetLabel() {
/** @type {?} */
const currentLabel = this.label.getValue();
if (currentLabel) {
currentLabel.setParent(null);
currentLabel.setPainted(false);
}
this.label.next(null);
}
/**
* @param {?} pointModel
* @return {?}
*/
removePoint(pointModel) {
this.points.splice(this.getPointIndex(pointModel), 1);
}
/**
* @param {?} pointModel
* @return {?}
*/
removePointsBefore(pointModel) {
this.points.splice(0, this.getPointIndex(pointModel));
}
/**
* @param {?} pointModel
* @return {?}
*/
removePointsAfter(pointModel) {
this.points.splice(this.getPointIndex(pointModel) + 1);
}
/**
* @return {?}
*/
removeMiddlePoints() {
if (this.points.length > 2) {
this.points.splice(0, this.points.length - 2);
}
}
/**
* @template P
* @param {?} pointModel
* @param {?=} index
* @return {?}
*/
addPoint(pointModel, index = 1) {
pointModel.setParent(this);
this.points.splice(index, 0, pointModel);
return pointModel;
}
/**
* @param {?} __0
* @return {?}
*/
generatePoint({ x = 0, y = 0 }) {
return new PointModel(this, { x, y });
}
}
if (false) {
/** @type {?} */
LinkModel.prototype.diagramEngine;
/**
* @type {?}
* @private
*/
LinkModel.prototype.name;
/**
* @type {?}
* @private
*/
LinkModel.prototype.sourcePort;
/**
* @type {?}
* @private
*/
LinkModel.prototype.targetPort;
/**
* @type {?}
* @private
*/
LinkModel.prototype.points;
/**
* @type {?}
* @private
*/
LinkModel.prototype.extras;
/**
* @type {?}
* @private
*/
LinkModel.prototype.label;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/port.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class PortModel extends BaseModel {
/**
* @param {?} name
* @param {?=} type
* @param {?=} id
* @param {?=} maximumLinks
* @param {?=} linkType
*/
constructor(name, type, id, maximumLinks, linkType) {
super(type, id);
this.name = name;
this.links$ = new BehaviorSubject({});
this.maximumLinks = maximumLinks;
this.x$ = new BehaviorSubject(0);
this.y$ = new BehaviorSubject(0);
this.height$ = new BehaviorSubject(0);
this.width$ = new BehaviorSubject(0);
this.linkType = linkType;
}
/**
* @return {?}
*/
getNode() {
return this.getParent();
}
/**
* @return {?}
*/
getName() {
return this.name;
}
/**
* @return {?}
*/
selectX() {
return this.x$.asObservable();
}
/**
* @return {?}
*/
selectY() {
return this.y$.asObservable();
}
/**
* @return {?}
*/
getY() {
return this.y$.getValue();
}
/**
* @return {?}
*/
getX() {
return this.x$.getValue();
}
/**
* @return {?}
*/
getHeight() {
return this.height$.getValue();
}
/**
* @return {?}
*/
getWidth() {
return this.width$.getValue();
}
/**
* @return {?}
*/
getMaximumLinks() {
return this.maximumLinks;
}
/**
* @param {?} maximumLinks
* @return {?}
*/
setMaximumLinks(maximumLinks) {
this.maximumLinks = maximumLinks;
}
/**
* @return {?}
*/
getLinkType() {
return this.linkType;
}
/**
* @param {?} type
* @return {?}
*/
setLinkType(type) {
this.linkType = type;
}
/**
* @param {?} link
* @return {?}
*/
removeLink(link) {
/** @type {?} */
const links = this.links$.getValue();
delete links[link.id];
this.links$.next(Object.assign({}, links));
}
/**
* @param {?} link
* @return {?}
*/
addLink(link) {
this.links$.next(Object.assign({}, this.links$.value, { [link.id]: link }));
}
/**
* @return {?}
*/
getLinks() {
return this.links$.getValue();
}
/**
* @return {?}
*/
selectLinks() {
return this.links$.asObservable();
}
/**
* @param {?} __0
* @return {?}
*/
updateCoords({ x, y, width, height }) {
this.x$.next(x);
this.y$.next(y);
this.width$.next(width);
this.height$.next(height);
}
/**
* @param {?} port
* @return {?}
*/
canLinkToPort(port) {
return true;
}
/**
* @return {?}
*/
isLocked() {
return super.getLocked();
}
/**
* @return {?}
*/
createLinkModel() {
/** @type {?} */
const numberOfLinks = Object.keys(this.links$.getValue()).length;
if (this.maximumLinks === 1 && numberOfLinks >= 1) {
/** @type {?} */
const linkToRemove = Object.values(this.links$.getValue())[0];
linkToRemove.destroy();
return null;
}
else if (numberOfLinks >= this.maximumLinks) {
// for the moment we will remove the first link by default
/** @type {?} */
const linkToRemove = Object.values(this.links$.getValue())[0];
linkToRemove.destroy();
return null;
}
return null;
}
}
if (false) {
/**
* @type {?}
* @private
*/
PortModel.prototype.name;
/**
* @type {?}
* @private
*/
PortModel.prototype.links$;
/**
* @type {?}
* @private
*/
PortModel.prototype.maximumLinks;
/**
* @type {?}
* @private
*/
PortModel.prototype.linkType;
/**
* @type {?}
* @private
*/
PortModel.prototype.x$;
/**
* @type {?}
* @private
*/
PortModel.prototype.y$;
/**
* @type {?}
* @private
*/
PortModel.prototype.width$;
/**
* @type {?}
* @private
*/
PortModel.prototype.height$;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/models/diagram.model.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class DiagramModel extends BaseEntity {
/**
* @param {?} diagramEngine
* @param {?=} id
*/
constructor(diagramEngine, id) {
super(id);
this.diagramEngine = diagramEngine;
this.nodes$ = new BehaviorSubject({});
this.links$ = new BehaviorSubject({});
this.zoom$ = new BehaviorSubject(100);
this.offsetX$ = new BehaviorSubject(0);
this.offsetY$ = new BehaviorSubject(0);
this.gridSize$ = new BehaviorSubject(0);
}
// TODO: support the following events for links and nodes
// removed, updated<positionChanged/dataChanged>, added
/**
* @return {?}
*/
getNodes() {
return this.nodes$.getValue();
}
/**
* @param {?} id
* @return {?}
*/
getNode(id) {
return this.nodes$.getValue()[id];
}
/**
* @param {?} id
* @return {?}
*/
getLink(id) {
return this.links$.getValue()[id];
}
/**
* @return {?}
*/
getLinks() {
return this.links$.getValue();
}
/**
* Add a node to the diagram
* @param {?} node
* @return {?} Inserted Node
*/
addNode(node) {
this.nodes$.next(Object.assign({}, this.nodes$.value, { [node.id]: node }));
return node;
}
/**
* Delete a node from the diagram
* @param {?} nodeOrId
* @return {?}
*/
deleteNode(nodeOrId) {
/** @type {?} */
const nodeID = typeof nodeOrId === 'string' ? nodeOrId : nodeOrId.id;
// TODO: delete all related links
/** @type {?} */
const updNodes = Object.assign({}, this.nodes$.value);
delete updNodes[nodeID];
this.nodes$.next(updNodes);
}
/**
* Get nodes behaviour subject, use `.getValue()` for snapshot
* @return {?}
*/
selectNodes() {
return this.nodes$.asObservable();
}
/**
* Add link
* @param {?} link
* @return {?} Newly created link
*/
addLink(link) {
this.links$.next(Object.assign({}, this.links$.value, { [link.id]: link }));
return link;
}
/**
* Delete link
* @param {?} linkOrId
* @return {?}
*/
deleteLink(linkOrId) {
/** @type {?} */
const linkID = typeof linkOrId === 'string' ? linkOrId : linkOrId.id;
/** @type {?} */
const updLinks = Object.assign({}, this.links$.value);
delete updLinks[linkID];
this.links$.next(updLinks);
}
/**
* Get links behaviour subject, use `.getValue()` for snapshot
* @return {?}
*/
selectLinks() {
return this.links$.asObservable();
}
/**
* Serialize the diagram model
* @returns diagram model as a string
*/
// serialize(): string {
// return JSON.stringify(this.model);
// }
/**
* Load into the diagram model a serialized diagram
* @param {?} x
* @param {?} y
* @return {?}
*/
// deserialize(serializedModel: string) {
// this.model = JSON.parse(serializedModel);
// }
setOffset(x, y) {
this.offsetX$.next(x);
this.offsetY$.next(y);
}
/**
* @param {?} x
* @return {?}
*/
setOffsetX(x) {
this.offsetX$.next(x);
}
/**
* @return {?}
*/
getOffsetX() {
return this.offsetX$.getValue();
}
/**
* @return {?}
*/
selectOffsetX() {
return this.offsetX$.asObservable();
}
/**
* @param {?} y
* @return {?}
*/
setOffsetY(y) {
this.offsetY$.next(y);
}
/**
* @return {?}
*/
getOffsetY() {
return this.offsetY$.getValue();
}
/**
* @return {?}
*/
selectOffsetY() {
return this.offsetY$.asObservable();
}
/**
* @param {?} z
* @return {?}
*/
setZoomLevel(z) {
this.zoom$.next(z);
}
/**
* @return {?}
*/
getZoomLevel() {
return this.zoom$.getValue();
}
/**
* @return {?}
*/
selectZoomLevel() {
return this.zoom$.asObservable();
}
/**
* @return {?}
*/
getDiagramEngine() {
return this.diagramEngine;
}
/**
* @param {?=} ignore
* @return {?}
*/
clearSelection(ignore = null) {
this.getSelectedItems().forEach((/**
* @param {?} element
* @return {?}
*/
element => {
if (ignore && ignore.id === element.id) {
return;
}
element.setSelected(false);
}));
}
/**
* @param {?} __0
* @return {?}
*/
getGridPosition({ x, y }) {
/** @type {?} */
const gridSize = this.gridSize$.getValue();
if (gridSize === 0) {
return { x, y };
}
return {
x: gridSize * Math.floor((x + gridSize / 2) / gridSize),
y: gridSize * Math.floor((y + gridSize / 2) / gridSize)
};
}
/**
* @param {...?} filters
* @return {?}
*/
getSelectedItems(...filters) {
if (!Array.isArray(filters)) {
filters = [filters];
}
/** @type {?} */
let items = [];
// run through nodes
items = items.concat(flatMap(this.nodes$.getValue(), (/**
* @param {?} node
* @return {?}
*/
node => {
return node.getSelectedEntities();
})));
// find all the links
items = items.concat(flatMap(this.links$.getValue(), (/**
* @param {?} link
* @return {?}
*/
link => {
return link.getSelectedEntities();
})));
// find all points
items = items.concat(flatMap(this.links$.getValue(), (/**
* @param {?} link
* @return {?}
*/
link => {
return flatMap(link.getPoints(), (/**
* @param {?} point
* @return {?}
*/
point => {
return point.getSelectedEntities();
}));
})));
items = uniq(items);
if (filters.length > 0) {
items = uniq(items).filter((/**
* @param {?} item
* @return {?}
*/
(item) => {
if (filters.includes('node') && item instanceof NodeModel) {
return true;
}
if (filters.includes('link') && item instanceof LinkModel) {
return true;
}
if (filters.includes('port') && item instanceof PortModel) {
return true;
}
if (filters.includes('point') && item instanceof PointModel) {
return true;
}
return false;
}));
}
return items;
}
/**
* @param {...?} models
* @return {?}
*/
addAll(...models) {
models.forEach((/**
* @param {?} model
* @return {?}
*/
model => {
if (model instanceof LinkModel) {
this.addLink(model);
}
else if (model instanceof NodeModel) {
this.addNode(model);
}
}));
return models;
}
}
if (false) {
/** @type {?} */
DiagramModel.prototype.links$;
/** @type {?} */
DiagramModel.prototype.nodes$;
/** @type {?} */
DiagramModel.prototype.zoom$;
/** @type {?} */
DiagramModel.prototype.offsetX$;
/** @type {?} */
DiagramModel.prototype.offsetY$;
/** @type {?} */
DiagramModel.prototype.gridSize$;
/**
* @type {?}
* @private
*/
DiagramModel.prototype.diagramEngine;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/base.action.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class BaseAction {
/**
* @param {?} mouseX
* @param {?} mouseY
*/
constructor(mouseX, mouseY) {
this.mouseX = mouseX;
this.mouseY = mouseY;
this.ms = new Date().getTime();
}
}
if (false) {
/** @type {?} */
BaseAction.prototype.mouseX;
/** @type {?} */
BaseAction.prototype.mouseY;
/** @type {?} */
BaseAction.prototype.ms;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/move-canvas.action.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class MoveCanvasAction extends BaseAction {
/**
* @param {?} mouseX
* @param {?} mouseY
* @param {?} diagramModel
*/
constructor(mouseX, mouseY, diagramModel) {
super(mouseX, mouseY);
this.initialOffsetX = diagramModel.getOffsetX();
this.initialOffsetY = diagramModel.getOffsetY();
}
}
if (false) {
/** @type {?} */
MoveCanvasAction.prototype.initialOffsetX;
/** @type {?} */
MoveCanvasAction.prototype.initialOffsetY;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/selecting.action.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class SelectingAction extends BaseAction {
/**
* @param {?} mouseX
* @param {?} mouseY
*/
constructor(mouseX, mouseY) {
super(mouseX, mouseY);
this.mouseX2 = mouseX;
this.mouseY2 = mouseY;
}
/**
* @return {?}
*/
getBoxDimensions() {
this.dimensions = {
left: this.mouseX2 > this.mouseX ? this.mouseX : this.mouseX2,
top: this.mouseY2 > this.mouseY ? this.mouseY : this.mouseY2,
width: Math.abs(this.mouseX2 - this.mouseX),
height: Math.abs(this.mouseY2 - this.mouseY),
right: this.mouseX2 < this.mouseX ? this.mouseX : this.mouseX2,
bottom: this.mouseY2 < this.mouseY ? this.mouseY : this.mouseY2
};
return this.dimensions;
}
/**
* @param {?} __0
* @param {?} diagramModel
* @return {?}
*/
containsElement({ x, y }, diagramModel) {
/** @type {?} */
const z = diagramModel.getZoomLevel() / 100.0;
/** @type {?} */
const dimensions = this.getBoxDimensions();
return (x * z + diagramModel.getOffsetX() > dimensions.left &&
x * z + diagramModel.getOffsetX() < dimensions.right &&
y * z + diagramModel.getOffsetY() > dimensions.top &&
y * z + diagramModel.getOffsetY() < dimensions.bottom);
}
}
if (false) {
/** @type {?} */
SelectingAction.prototype.mouseX2;
/** @type {?} */
SelectingAction.prototype.mouseY2;
/** @type {?} */
SelectingAction.prototype.dimensions;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/move-items.action.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class MoveItemsAction extends BaseAction {
/**
* @param {?} mouseX
* @param {?} mouseY
* @param {?} diagramEngine
*/
constructor(mouseX, mouseY, diagramEngine) {
super(mouseX, mouseY);
this.moved = false;
/** @type {?} */
let selectedItems = diagramEngine.getDiagramModel().getSelectedItems();
// dont allow items which are locked to move and links which generate their position based on points.
selectedItems = selectedItems.filter((/**
* @param {?} item
* @return {?}
*/
item => {
return !diagramEngine.isModelLocked(item) && !(item instanceof LinkModel);
}));
this.selectionModels = selectedItems.map((/**
* @param {?} item
* @return {?}
*/
(item) => {
const { x: initialX, y: initialY } = item.getCoords();
return {
model: item,
initialX,
initialY
};
}));
}
}
if (false) {
/** @type {?} */
MoveItemsAction.prototype.selectionModels;
/** @type {?} */
MoveItemsAction.prototype.moved;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/links-created.action.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
// TODO: refactor into entity-created.action, and fire every time a new entity is created!
class LinkCreatedAction extends BaseAction {
/**
* @param {?} mouseX
* @param {?} mouseY
* @param {?} link
*/
constructor(mouseX, mouseY, link) {
super(mouseX, mouseY);
this.sourcePort = link.getSourcePort();
this.targetPort = link.getTargetPort();
this.link = link;
}
/**
* @return {?}
*/
getOutPortNode() {
return this.sourcePort.getParent();
}
/**
* @return {?}
*/
getInPortNode() {
return this.targetPort.getParent();
}
}
if (false) {
/** @type {?} */
LinkCreatedAction.prototype.sourcePort;
/** @type {?} */
LinkCreatedAction.prototype.targetPort;
/** @type {?} */
LinkCreatedAction.prototype.link;
}
/**
* @fileoverview added by tsickle
* Generated from: lib/actions/index.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
/**
* @fileoverview added by tsickle
* Generated from: lib/containers/diagram/diagram.component.ts
* @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
*/
class NgxDiagramComponent {
/**
* @param {?} renderer
* @param {?} cdRef
*/
constructor(renderer, cdRef) {
this.renderer = renderer;
this.cdRef = cdRef;
this.allowCanvasZoon = true;
this.allowCanvasTranslation = true;
this.inverseZoom = true;
this.allowLooseLinks = true;
this.actionStartedFiring = new EventEmitter();
th