vue-diagram-editor-improved
Version:
Highly customizable diagram editor support for Vue.js
149 lines (132 loc) • 3.73 kB
JavaScript
import {ulid} from 'ulid';
import Coordinates from './Coordinates';
import Size from './Size';
/**
* @class Node
*/
export default class Node {
static PORT_HEIGHT = 18;
id = null;
title = null;
category = null;
state = null;
performer = null;
deletable = null;
color = null;
/**
* @type {Size}
*/
size = null;
/**
* @type {Coordinates}
*/
coordinates = null;
data = {}; // user object
portsIn = {
// default: { type: 'text', value: '' }
};
portsOut = {
// default: { type: 'text', value: '' }
};
/**
* @param {String} attr.id
* @param {String} attr.title
* @param {Coordinates} attr.coordinates
* @param {Size} attr.size
* @param {Object} attr.portsIn
* @param {Object} attr.portsOut
* @param {Object} attr.category
* @param {Object} attr.color
* @param {Object} attr.state
* @param {Object} attr.performer
* @param {Object} attr.deletable
*/
constructor(attr) {
this.id = Node.prepareProp('id', attr.id);
this.title = attr.title;
this.category = Node.prepareProp('category', attr.category);
this.state = Node.prepareProp('state', attr.state);
this.performer = Node.prepareProp('performer', attr.performer);
this.deletable = Node.prepareProp('deletable', attr.deletable);
this.coordinates = Node.prepareProp('coordinates', attr.coordinates);
this.color = Node.prepareProp('color', attr.color);
this.size = Node.prepareProp('size', attr.size);
this.data = Node.prepareProp('data', attr.data);
this.portsIn = Node.prepareProp('portsIn', attr.portsIn);
this.portsOut = Node.prepareProp('portsOut', attr.portsOut);
}
static prepareProp(name, value) {
switch (name) {
case 'id':
return value || ulid();
case 'coordinates':
return new Coordinates(value || {});
case 'size':
return new Size(value || {});
case 'portsIn':
case 'portsOut':
return Object.entries(value || {}).reduce((acc, [key, val]) => {
acc[key] = {
type: val.type || 'text',
value: val.value || ''
};
return acc;
}, {});
case 'data':
return value || {};
case 'category':
return value || "default";
case 'color':
return value || "#4249FF";
case 'state':
return value || null;
case 'performer':
return value || "CPU";
case 'deletable':
return value !== false;
default:
return value;
}
}
get portsHeight() {
return Math.max(Object.keys(this.portsIn).length, Object.keys(this.portsOut).length) * Node.PORT_HEIGHT;
}
get width() {
return this.size.width;
}
get height() {
return this.size.height;
}
get x() {
return this.coordinates.x;
}
get y() {
return this.coordinates.y;
}
get x1() {
return this.coordinates.x + this.size.width;
}
get y1() {
return this.coordinates.y + this.size.height;
}
getPortCoordinates(type, name) {
if (!['in', 'out'].includes(type)) throw new Error('Undefined port type ' + type);
const ports = Object.keys(type === 'in' ? this.portsIn : this.portsOut);
const index = ports.findIndex(portName => portName === name);
if (index === -1) {
throw new Error(`"${type}" port with name "${name}" is undefined!`);
}
return {
x: this.x + (type === 'out' ? this.width : 1),
y: this.y + this.height - (this.portsHeight - 2) + (index * Node.PORT_HEIGHT) + 1
};
}
/**
* @param {Node} a
* @param {Node} b
* @return {Boolean}
*/
static intersect(a, b) {
return !(a.x > b.x1 || b.x > a.x1 || a.y > b.y1 || b.y > a.y1);
}
}