UNPKG

markgojs

Version:

Interactive diagrams, charts, and graphs, such as trees, flowcharts, orgcharts, UML, BPMN, or business diagrams

408 lines (407 loc) 17.3 kB
var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "../release/go"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); /* * Copyright (C) 1998-2019 by Northwoods Software Corporation. All Rights Reserved. */ var go = require("../release/go"); /** * @constructor * @extends Tool * @class * This GeometryReshapingTool class allows for a Shape's Geometry to be modified by the user * via the dragging of tool handles. * This does not handle Links, whose routes should be reshaped by the LinkReshapingTool. * The {@link #reshapeObjectName} needs to identify the named {@link Shape} within the * selected {@link Part}. * If the shape cannot be found or if its {@link Shape#geometry} is not of type {@link Geometry#Path}, * this will not show any GeometryReshaping {@link Adornment}. * At the current time this tool does not support adding or removing {@link PathSegment}s to the Geometry. */ var GeometryReshapingTool = /** @class */ (function (_super) { __extends(GeometryReshapingTool, _super); function GeometryReshapingTool() { var _this = _super.call(this) || this; /** @type {string} */ _this._reshapeObjectName = 'SHAPE'; //??? can't add Part.reshapeObjectName property // there's no Part.reshapeAdornmentTemplate either // internal state /** @type {GraphObject} */ _this._handle = null; /** @type {Shape} */ _this._adornedShape = null; /** @type {Geometry} */ _this._originalGeometry = null; // in case the tool is cancelled and the UndoManager is not enabled var h = new go.Shape(); h.figure = "Diamond"; h.desiredSize = new go.Size(7, 7); h.fill = "lightblue"; h.stroke = "dodgerblue"; h.cursor = "move"; _this._handleArchetype = h; _this.name = "GeometryReshaping"; return _this; } Object.defineProperty(GeometryReshapingTool.prototype, "handleArchetype", { /** * A small GraphObject used as a reshape handle for each segment. * The default GraphObject is a small blue diamond. * @name GeometryReshapingTool#handleArchetype * @function. * @return {GraphObject} */ get: function () { return this._handleArchetype; }, set: function (value) { this._handleArchetype = value; }, enumerable: true, configurable: true }); Object.defineProperty(GeometryReshapingTool.prototype, "reshapeObjectName", { /** * The name of the GraphObject to be reshaped. * @name GeometryReshapingTool#reshapeObjectName * @function. * @return {string} */ get: function () { return this._reshapeObjectName; }, set: function (value) { this._reshapeObjectName = value; }, enumerable: true, configurable: true }); Object.defineProperty(GeometryReshapingTool.prototype, "handle", { /** * This read-only property returns the {@link GraphObject} that is the tool handle being dragged by the user. * This will be contained by an {@link Adornment} whose category is "GeometryReshaping". * Its {@link Adornment#adornedObject} is the same as the {@link #adornedShape}. * @name GeometryReshapingTool#handle * @function. * @return {GraphObject} */ get: function () { return this._handle; }, enumerable: true, configurable: true }); Object.defineProperty(GeometryReshapingTool.prototype, "adornedShape", { /** * Gets the {@link Shape} that is being reshaped. * This must be contained within the selected Part. * @name GeometryReshapingTool#adornedShape * @function. * @return {Shape} */ get: function () { return this._adornedShape; }, enumerable: true, configurable: true }); Object.defineProperty(GeometryReshapingTool.prototype, "originalGeometry", { /** * This read-only property remembers the original value for {@link Shape#geometry}, * so that it can be restored if this tool is cancelled. * @name GeometryReshapingTool#originalGeometry * @function. * @return {Geometry} */ get: function () { return this._originalGeometry; }, enumerable: true, configurable: true }); /** * Show an {@link Adornment} with a reshape handle at each point of the geometry. * Don't show anything if {@link #reshapeObjectName} doesn't identify a {@link Shape} * that has a {@link Shape#geometry} of type {@link Geometry#Path}. * @this {GeometryReshapingTool} * @param {Part} part the part. */ GeometryReshapingTool.prototype.updateAdornments = function (part) { if (part === null || part instanceof go.Link) return; // this tool never applies to Links if (part.isSelected && !this.diagram.isReadOnly) { var selelt = part.findObject(this.reshapeObjectName); if (selelt instanceof go.Shape && selelt.actualBounds.isReal() && selelt.isVisibleObject() && part.canReshape() && part.actualBounds.isReal() && part.isVisible() && selelt.geometry.type === go.Geometry.Path) { var adornment = part.findAdornment(this.name); if (adornment === null) { adornment = this.makeAdornment(selelt); } if (adornment !== null) { // update the position/alignment of each handle var geo = selelt.geometry; var b = geo.bounds; // update the size of the adornment adornment.findObject("BODY").desiredSize = b.size; adornment.elements.each(function (h) { if (h._typ === undefined) return; var fig = geo.figures.elt(h._fig); var seg = fig.segments.elt(h._seg); var x = 0; var y = 0; switch (h._typ) { case 0: x = fig.startX; y = fig.startY; break; case 1: x = seg.endX; y = seg.endY; break; case 2: x = seg.point1X; y = seg.point1Y; break; case 3: x = seg.point2X; y = seg.point2Y; break; } var bw = b.width; if (bw === 0) bw = 0.001; var bh = b.height; if (bh === 0) bh = 0.001; h.alignment = new go.Spot(Math.max(0, Math.min((x - b.x) / bw, 1)), Math.max(0, Math.min((y - b.y) / bh, 1))); }); part.addAdornment(this.name, adornment); adornment.location = selelt.getDocumentPoint(go.Spot.TopLeft); adornment.angle = selelt.getDocumentAngle(); return; } } } part.removeAdornment(this.name); }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.makeAdornment = function (selelt) { var adornment = new go.Adornment(); adornment.type = go.Panel.Spot; adornment.locationObjectName = "BODY"; adornment.locationSpot = new go.Spot(0, 0, -selelt.strokeWidth / 2, -selelt.strokeWidth / 2); var h = new go.Shape(); h.name = "BODY"; h.fill = null; h.stroke = null; h.strokeWidth = 0; adornment.add(h); var geo = selelt.geometry; // requires Path Geometry, checked above in updateAdornments for (var f = 0; f < geo.figures.count; f++) { var fig = geo.figures.elt(f); for (var g = 0; g < fig.segments.count; g++) { var seg = fig.segments.elt(g); var h; if (g === 0) { h = this.makeHandle(selelt, fig, seg); if (h !== null) { h._typ = 0; h._fig = f; h._seg = g; adornment.add(h); } } h = this.makeHandle(selelt, fig, seg); if (h !== null) { h._typ = 1; h._fig = f; h._seg = g; adornment.add(h); } if (seg.type === go.PathSegment.QuadraticBezier || seg.type === go.PathSegment.Bezier) { h = this.makeHandle(selelt, fig, seg); if (h !== null) { h._typ = 2; h._fig = f; h._seg = g; adornment.add(h); } if (seg.type === go.PathSegment.Bezier) { h = this.makeHandle(selelt, fig, seg); if (h !== null) { h._typ = 3; h._fig = f; h._seg = g; adornment.add(h); } } } } } adornment.category = this.name; adornment.adornedObject = selelt; return adornment; }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.makeHandle = function (selelt, fig, seg) { var h = this.handleArchetype; if (h === null) return null; return h.copy(); }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.canStart = function () { if (!this.isEnabled) return false; var diagram = this.diagram; if (diagram === null || diagram.isReadOnly) return false; if (!diagram.allowReshape) return false; if (!diagram.lastInput.left) return false; var h = this.findToolHandleAt(diagram.firstInput.documentPoint, this.name); return (h !== null); }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.doActivate = function () { var diagram = this.diagram; if (diagram === null) return; this._handle = this.findToolHandleAt(diagram.firstInput.documentPoint, this.name); if (this._handle === null) return; var shape = this.handle.part.adornedObject; if (!shape) return; this._adornedShape = shape; diagram.isMouseCaptured = true; this.startTransaction(this.name); this._originalGeometry = shape.geometry; this.isActive = true; }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.doDeactivate = function () { this.stopTransaction(); this._handle = null; this._adornedShape = null; var diagram = this.diagram; if (diagram !== null) diagram.isMouseCaptured = false; this.isActive = false; }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.doCancel = function () { var shape = this._adornedShape; if (shape !== null) { // explicitly restore the original route, in case !UndoManager.isEnabled shape.geometry = this._originalGeometry; } this.stopTool(); }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.doMouseMove = function () { var diagram = this.diagram; if (this.isActive && diagram !== null) { var newpt = this.computeReshape(diagram.lastInput.documentPoint); this.reshape(newpt); } }; ; /** * @this {GeometryReshapingTool} */ GeometryReshapingTool.prototype.doMouseUp = function () { var diagram = this.diagram; if (this.isActive && diagram !== null) { var newpt = this.computeReshape(diagram.lastInput.documentPoint); this.reshape(newpt); this.transactionResult = this.name; // success } this.stopTool(); }; ; /** * @expose * @this {GeometryReshapingTool} * @param {Point} newPoint the value of the call to {@link #computeReshape}. */ GeometryReshapingTool.prototype.reshape = function (newPoint) { var shape = this.adornedShape; var locpt = shape.getLocalPoint(newPoint); var geo = shape.geometry.copy(); shape.desiredSize = new go.Size(NaN, NaN); // set the desiredSize once we've gotten our Geometry so we don't clobber var type = this.handle._typ; if (type === undefined) return; var fig = geo.figures.elt(this.handle._fig); var seg = fig.segments.elt(this.handle._seg); switch (type) { case 0: fig.startX = locpt.x; fig.startY = locpt.y; break; case 1: seg.endX = locpt.x; seg.endY = locpt.y; break; case 2: seg.point1X = locpt.x; seg.point1Y = locpt.y; break; case 3: seg.point2X = locpt.x; seg.point2Y = locpt.y; break; } var offset = geo.normalize(); // avoid any negative coordinates in the geometry shape.geometry = geo; // modify the Shape var part = shape.part; // move the Part holding the Shape if (!part.locationSpot.equals(go.Spot.Center)) { // but only if the locationSpot isn't Center part.move(part.position.copy().subtract(offset)); } this.updateAdornments(part); // update any Adornments of the Part this.diagram.maybeUpdate(); // force more frequent drawing for smoother looking behavior }; ; /** * @expose * @this {GeometryReshapingTool} * @param {Point} p the point where the handle is being dragged. * @return {Point} */ GeometryReshapingTool.prototype.computeReshape = function (p) { return p; // no constraints on the points }; ; return GeometryReshapingTool; }(go.Tool)); exports.GeometryReshapingTool = GeometryReshapingTool; });