UNPKG

sprotty

Version:

A next-gen framework for graphical views

167 lines 8.33 kB
"use strict"; /******************************************************************************** * Copyright (c) 2019 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 ********************************************************************************/ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var PolylineEdgeRouter_1; Object.defineProperty(exports, "__esModule", { value: true }); exports.PolylineEdgeRouter = void 0; const inversify_1 = require("inversify"); const geometry_1 = require("sprotty-protocol/lib/utils/geometry"); const model_1 = require("./model"); const anchor_1 = require("./anchor"); const abstract_edge_router_1 = require("./abstract-edge-router"); let PolylineEdgeRouter = PolylineEdgeRouter_1 = class PolylineEdgeRouter extends abstract_edge_router_1.AbstractEdgeRouter { get kind() { return PolylineEdgeRouter_1.KIND; } getOptions(edge) { return { minimalPointDistance: 2, removeAngleThreshold: 0.1, standardDistance: 20, selfEdgeOffset: 0.25 }; } route(edge) { const source = edge.source; const target = edge.target; if (source === undefined || target === undefined) { return []; } let sourceAnchor; let targetAnchor; const options = this.getOptions(edge); const routingPoints = edge.routingPoints.length > 0 ? edge.routingPoints : []; this.cleanupRoutingPoints(edge, routingPoints, false, false); const rpCount = routingPoints !== undefined ? routingPoints.length : 0; if (rpCount === 0) { // Use the target center as start anchor reference const startRef = geometry_1.Bounds.center(target.bounds); sourceAnchor = this.getTranslatedAnchor(source, startRef, target.parent, edge, edge.sourceAnchorCorrection); // Use the source center as end anchor reference const endRef = geometry_1.Bounds.center(source.bounds); targetAnchor = this.getTranslatedAnchor(target, endRef, source.parent, edge, edge.targetAnchorCorrection); } else { // Use the first routing point as start anchor reference const p0 = routingPoints[0]; sourceAnchor = this.getTranslatedAnchor(source, p0, edge.parent, edge, edge.sourceAnchorCorrection); // Use the last routing point as end anchor reference const pn = routingPoints[rpCount - 1]; targetAnchor = this.getTranslatedAnchor(target, pn, edge.parent, edge, edge.targetAnchorCorrection); } const result = []; result.push({ kind: 'source', x: sourceAnchor.x, y: sourceAnchor.y }); for (let i = 0; i < rpCount; i++) { const p = routingPoints[i]; if (i > 0 && i < rpCount - 1 || i === 0 && geometry_1.Point.maxDistance(sourceAnchor, p) >= options.minimalPointDistance + (edge.sourceAnchorCorrection || 0) || i === rpCount - 1 && geometry_1.Point.maxDistance(p, targetAnchor) >= options.minimalPointDistance + (edge.targetAnchorCorrection || 0)) { result.push({ kind: 'linear', x: p.x, y: p.y, pointIndex: i }); } } result.push({ kind: 'target', x: targetAnchor.x, y: targetAnchor.y }); return this.filterEditModeHandles(result, edge, options); } /** * Remove routed points that are in edit mode and for which the angle between the preceding and * following points falls below a threshold. */ filterEditModeHandles(route, edge, options) { if (edge.children.length === 0) return route; let i = 0; while (i < route.length) { const curr = route[i]; if (curr.pointIndex !== undefined) { const handle = edge.children.find(child => child instanceof model_1.SRoutingHandleImpl && child.kind === 'junction' && child.pointIndex === curr.pointIndex); if (handle !== undefined && handle.editMode && i > 0 && i < route.length - 1) { const prev = route[i - 1], next = route[i + 1]; const prevDiff = { x: prev.x - curr.x, y: prev.y - curr.y }; const nextDiff = { x: next.x - curr.x, y: next.y - curr.y }; const angle = (0, geometry_1.angleBetweenPoints)(prevDiff, nextDiff); if (Math.abs(Math.PI - angle) < options.removeAngleThreshold) { route.splice(i, 1); continue; } } } i++; } return route; } createRoutingHandles(edge) { const rpCount = edge.routingPoints.length; this.addHandle(edge, 'source', 'routing-point', -2); this.addHandle(edge, 'line', 'volatile-routing-point', -1); for (let i = 0; i < rpCount; i++) { this.addHandle(edge, 'junction', 'routing-point', i); this.addHandle(edge, 'line', 'volatile-routing-point', i); } this.addHandle(edge, 'target', 'routing-point', rpCount); } getInnerHandlePosition(edge, route, handle) { if (handle.kind === 'line') { const { start, end } = this.findRouteSegment(edge, route, handle.pointIndex); if (start !== undefined && end !== undefined) return (0, geometry_1.centerOfLine)(start, end); } return undefined; } applyInnerHandleMoves(edge, moves) { moves.forEach(move => { const handle = move.handle; const points = edge.routingPoints; let index = handle.pointIndex; if (handle.kind === 'line') { // Upgrade to a proper routing point handle.kind = 'junction'; handle.type = 'routing-point'; points.splice(index + 1, 0, move.fromPosition || points[Math.max(index, 0)]); edge.children.forEach(child => { if (child instanceof model_1.SRoutingHandleImpl && (child === handle || child.pointIndex > index)) child.pointIndex++; }); this.addHandle(edge, 'line', 'volatile-routing-point', index); index++; this.addHandle(edge, 'line', 'volatile-routing-point', index); } if (index >= 0 && index < points.length) { points[index] = move.toPosition; } }); } }; exports.PolylineEdgeRouter = PolylineEdgeRouter; PolylineEdgeRouter.KIND = 'polyline'; __decorate([ (0, inversify_1.inject)(anchor_1.AnchorComputerRegistry), __metadata("design:type", anchor_1.AnchorComputerRegistry) ], PolylineEdgeRouter.prototype, "anchorRegistry", void 0); exports.PolylineEdgeRouter = PolylineEdgeRouter = PolylineEdgeRouter_1 = __decorate([ (0, inversify_1.injectable)() ], PolylineEdgeRouter); //# sourceMappingURL=polyline-edge-router.js.map