sprotty
Version:
A next-gen framework for graphical views
154 lines • 6.18 kB
JavaScript
;
/********************************************************************************
* Copyright (c) 2018 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/
Object.defineProperty(exports, "__esModule", { value: true });
exports.edgeInProgressTargetHandleID = exports.edgeInProgressID = exports.SDanglingAnchorImpl = exports.SRoutingHandleImpl = exports.SConnectableElementImpl = exports.getRouteBounds = exports.getAbsoluteRouteBounds = exports.isConnectable = exports.connectableFeature = exports.SRoutableElementImpl = void 0;
const geometry_1 = require("sprotty-protocol/lib/utils/geometry");
const smodel_1 = require("../../base/model/smodel");
const model_1 = require("../bounds/model");
const delete_1 = require("../edit/delete");
const model_2 = require("../select/model");
const model_3 = require("../hover/model");
const model_4 = require("../move/model");
class SRoutableElementImpl extends smodel_1.SChildElementImpl {
constructor() {
super(...arguments);
this.routingPoints = [];
}
get source() {
return this.index.getById(this.sourceId);
}
get target() {
return this.index.getById(this.targetId);
}
get bounds() {
// this should also work for splines, which have the convex hull property
return this.routingPoints.reduce((bounds, routingPoint) => geometry_1.Bounds.combine(bounds, {
x: routingPoint.x,
y: routingPoint.y,
width: 0,
height: 0
}), geometry_1.Bounds.EMPTY);
}
}
exports.SRoutableElementImpl = SRoutableElementImpl;
exports.connectableFeature = Symbol('connectableFeature');
function isConnectable(element) {
return element.hasFeature(exports.connectableFeature) && element.canConnect;
}
exports.isConnectable = isConnectable;
function getAbsoluteRouteBounds(model, route = model.routingPoints) {
let bounds = getRouteBounds(route);
let current = model;
while (current instanceof smodel_1.SChildElementImpl) {
const parent = current.parent;
bounds = parent.localToParent(bounds);
current = parent;
}
return bounds;
}
exports.getAbsoluteRouteBounds = getAbsoluteRouteBounds;
function getRouteBounds(route) {
const bounds = { x: NaN, y: NaN, width: 0, height: 0 };
for (const point of route) {
if (isNaN(bounds.x)) {
bounds.x = point.x;
bounds.y = point.y;
}
else {
if (point.x < bounds.x) {
bounds.width += bounds.x - point.x;
bounds.x = point.x;
}
else if (point.x > bounds.x + bounds.width) {
bounds.width = point.x - bounds.x;
}
if (point.y < bounds.y) {
bounds.height += bounds.y - point.y;
bounds.y = point.y;
}
else if (point.y > bounds.y + bounds.height) {
bounds.height = point.y - bounds.y;
}
}
}
return bounds;
}
exports.getRouteBounds = getRouteBounds;
/**
* A connectable element is one that can have outgoing and incoming edges, i.e. it can be the source
* or target element of an edge. There are two kinds of connectable elements: nodes (`SNode`) and
* ports (`SPort`). A node represents a main entity, while a port is a connection point inside a node.
*/
class SConnectableElementImpl extends model_1.SShapeElementImpl {
constructor() {
super(...arguments);
this.strokeWidth = 0;
}
get anchorKind() {
return undefined;
}
/**
* The incoming edges of this connectable element. They are resolved by the index, which must
* be an `SGraphIndex` for efficient lookup.
*/
get incomingEdges() {
const allEdges = this.index.all().filter(e => e instanceof SRoutableElementImpl);
return allEdges.filter(e => e.targetId === this.id);
}
/**
* The outgoing edges of this connectable element. They are resolved by the index, which must
* be an `SGraphIndex` for efficient lookup.
*/
get outgoingEdges() {
const allEdges = this.index.all().filter(e => e instanceof SRoutableElementImpl);
return allEdges.filter(e => e.sourceId === this.id);
}
canConnect(routable, role) {
return true;
}
}
exports.SConnectableElementImpl = SConnectableElementImpl;
class SRoutingHandleImpl extends smodel_1.SChildElementImpl {
constructor() {
super(...arguments);
/** Whether the routing point is being dragged. */
this.editMode = false;
this.hoverFeedback = false;
this.selected = false;
}
/**
* SRoutingHandles are created using the constructor, so we hard-wire the
* default features
*/
hasFeature(feature) {
return SRoutingHandleImpl.DEFAULT_FEATURES.indexOf(feature) !== -1;
}
}
exports.SRoutingHandleImpl = SRoutingHandleImpl;
SRoutingHandleImpl.DEFAULT_FEATURES = [model_2.selectFeature, model_4.moveFeature, model_3.hoverFeedbackFeature];
class SDanglingAnchorImpl extends SConnectableElementImpl {
constructor() {
super();
this.type = 'dangling-anchor';
this.size = { width: 0, height: 0 };
}
}
exports.SDanglingAnchorImpl = SDanglingAnchorImpl;
SDanglingAnchorImpl.DEFAULT_FEATURES = [delete_1.deletableFeature];
exports.edgeInProgressID = 'edge-in-progress';
exports.edgeInProgressTargetHandleID = exports.edgeInProgressID + '-target-anchor';
//# sourceMappingURL=model.js.map