(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("d3")); else if(typeof define === 'function' && define.amd) define("graphDiagram", ["d3"], factory); else if(typeof exports === 'object') exports["graphDiagram"] = factory(require("d3")); else root["graphDiagram"] = factory(root["d3"]); })(window, function(__WEBPACK_EXTERNAL_MODULE_d3__) { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/index.ts"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./src/graphDiagram/GraphDiagram.ts": /*!******************************************!*\ !*** ./src/graphDiagram/GraphDiagram.ts ***! \******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(/*! d3 */ "d3"); class GraphDiagram { static parsePixels(fontSize) { let result = 0; if (fontSize) { result = parseFloat(fontSize.slice(0, -2)); } else { // console.log(`parsePixels: `, fontSize); } return result; } static measureTextDimensions(text, fontSize, fontFamily) { var fontSize = fontSize; var fontFamily = fontFamily; var canvasSelection = d3.select("#textMeasuringCanvas").data([this]); canvasSelection.enter().append("canvas") .attr("id", "textMeasuringCanvas"); var canvas = document.getElementById('textMeasuringCanvas'); //canvasSelection.node(); //HTMLCanvasElement var context = canvas.getContext("2d"); context.font = "normal normal normal " + fontSize + "/normal " + fontFamily; return context.measureText(text).width; } static hasProperties(entity) { return entity.model.properties.list({ exclude: [GraphDiagram.MODEL_ID_KEY] }).length > 0; } } GraphDiagram.MODEL_ID_KEY = 'MODEL_ID'; exports.default = GraphDiagram; /***/ }), /***/ "./src/graphDiagram/arrow/CurvedArrowOutline.ts": /*!******************************************************!*\ !*** ./src/graphDiagram/arrow/CurvedArrowOutline.ts ***! \******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class CurvedArrowOutline { constructor(startRadius, endRadius, endCentre, minOffset, arrowWidth, headWidth, headLength) { this.startRadius = startRadius; this.endRadius = endRadius; this.endCentre = endCentre; this.minOffset = minOffset; this.arrowWidth = arrowWidth; this.headWidth = headWidth; this.headLength = headLength; this.radiusRatio = startRadius / (endRadius + headLength); this.homotheticCenter = -endCentre * this.radiusRatio / (1 - this.radiusRatio); if (endRadius + headLength > startRadius) { this.offsetAngle = minOffset / startRadius; this.startAttach = { x: Math.cos(this.offsetAngle) * (startRadius), y: Math.sin(this.offsetAngle) * (startRadius) }; this.endAttach = this.intersectWithOtherCircle(this.startAttach, endRadius + headLength, endCentre, -1); } else { this.offsetAngle = minOffset / endRadius; this.endAttach = { x: endCentre - Math.cos(this.offsetAngle) * (endRadius + headLength), y: Math.sin(this.offsetAngle) * (endRadius + headLength) }; this.startAttach = this.intersectWithOtherCircle(this.endAttach, startRadius, 0, 1); } this.g1 = -this.startAttach.x / this.startAttach.y, this.c1 = this.startAttach.y + (this.square(this.startAttach.x) / this.startAttach.y), this.g2 = -(this.endAttach.x - this.endCentre) / this.endAttach.y, this.c2 = this.endAttach.y + (this.endAttach.x - this.endCentre) * this.endAttach.x / this.endAttach.y; this.cx = (this.c1 - this.c2) / (this.g2 - this.g1); this.cy = this.g1 * this.cx + this.c1; this.arcRadius = Math.sqrt(this.square(this.cx - this.startAttach.x) + this.square(this.cy - this.startAttach.y)); this.shaftRadius = this.arrowWidth / 2; this.headRadius = this.headWidth / 2; this.outline = [ "M", this.startTangent(-this.shaftRadius), "L", this.startTangent(this.shaftRadius), "A", this.arcRadius - this.shaftRadius, this.arcRadius - this.shaftRadius, 0, 0, minOffset > 0 ? 0 : 1, this.endTangent(-this.shaftRadius), "L", this.endTangent(-this.headRadius), "L", this.endNormal(headLength), "L", this.endTangent(this.headRadius), "L", this.endTangent(this.shaftRadius), "A", this.arcRadius + this.shaftRadius, this.arcRadius + this.shaftRadius, 0, 0, minOffset < 0 ? 0 : 1, this.startTangent(-this.shaftRadius) ].join(" "); this.apex = { x: this.cx, y: this.cy > 0 ? this.cy - this.arcRadius : this.cy + this.arcRadius }; } square(l) { return l * l; } intersectWithOtherCircle(fixedPoint, radius, xCenter, polarity) { var gradient = fixedPoint.y / (fixedPoint.x - this.homotheticCenter); var hc = fixedPoint.y - gradient * fixedPoint.x; var A = 1 + this.square(gradient); var B = 2 * (gradient * hc - xCenter); var C = this.square(hc) + this.square(xCenter) - this.square(radius); var intersection = { x: (-B + polarity * Math.sqrt(this.square(B) - 4 * A * C)) / (2 * A) }; intersection.y = (intersection.x - this.homotheticCenter) * gradient; return intersection; } startTangent(dr) { var dx = (dr < 0 ? -1 : 1) * Math.sqrt(this.square(dr) / (1 + this.square(this.g1))); var dy = this.g1 * dx; return [ this.startAttach.x + dx, this.startAttach.y + dy ].join(","); } endTangent(dr) { var dx = (dr < 0 ? -1 : 1) * Math.sqrt(this.square(dr) / (1 + this.square(this.g2))); var dy = this.g2 * dx; return [ this.endAttach.x + dx, this.endAttach.y + dy ].join(","); } endNormal(dc) { var dx = (dc < 0 ? -1 : 1) * Math.sqrt(this.square(dc) / (1 + this.square(1 / this.g2))); var dy = dx / this.g2; return [ this.endAttach.x + dx, this.endAttach.y - dy ].join(","); } } exports.default = CurvedArrowOutline; /***/ }), /***/ "./src/graphDiagram/arrow/HorizontalArrowOutline.ts": /*!**********************************************************!*\ !*** ./src/graphDiagram/arrow/HorizontalArrowOutline.ts ***! \**********************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class HorizontalArrowOutline { constructor(start, end, arrowWidth) { this.shaftRadius = arrowWidth / 2; this.headRadius = arrowWidth * 2; this.headLength = this.headRadius * 2; this.shoulder = start < end ? end - this.headLength : end + this.headLength; this.outline = [ "M", start, this.shaftRadius, "L", this.shoulder, this.shaftRadius, "L", this.shoulder, this.headRadius, "L", end, 0, "L", this.shoulder, -this.headRadius, "L", this.shoulder, -this.shaftRadius, "L", start, -this.shaftRadius, "Z" ].join(" "); this.apex = { x: start + (this.shoulder - start) / 2, y: 0 }; } } exports.default = HorizontalArrowOutline; /***/ }), /***/ "./src/graphDiagram/bubble/Bubble.ts": /*!*******************************************!*\ !*** ./src/graphDiagram/bubble/Bubble.ts ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class Bubble { constructor(entity) { this.entity = entity; } } Bubble.speechBubblePath = function (textSize, style, margin, padding) { var width = textSize.width, height = textSize.height; var styles = { diagonal: [ "M", 0, 0, "L", margin + padding, margin, "L", margin + width + padding, margin, "A", padding, padding, 0, 0, 1, margin + width + padding * 2, margin + padding, "L", margin + width + padding * 2, margin + height + padding, "A", padding, padding, 0, 0, 1, margin + width + padding, margin + height + padding * 2, "L", margin + padding, margin + height + padding * 2, "A", padding, padding, 0, 0, 1, margin, margin + height + padding, "L", margin, margin + padding, "Z" ], horizontal: [ "M", 0, 0, "L", margin, -padding, "L", margin, -height / 2, "A", padding, padding, 0, 0, 1, margin + padding, -height / 2 - padding, "L", margin + width + padding, -height / 2 - padding, "A", padding, padding, 0, 0, 1, margin + width + padding * 2, -height / 2, "L", margin + width + padding * 2, height / 2, "A", padding, padding, 0, 0, 1, margin + width + padding, height / 2 + padding, "L", margin + padding, height / 2 + padding, "A", padding, padding, 0, 0, 1, margin, height / 2, "L", margin, padding, "Z" ], vertical: [ "M", 0, 0, "L", -padding, margin, "L", -width / 2, margin, "A", padding, padding, 0, 0, 0, -width / 2 - padding, margin + padding, "L", -width / 2 - padding, margin + height + padding, "A", padding, padding, 0, 0, 0, -width / 2, margin + height + padding * 2, "L", width / 2, margin + height + padding * 2, "A", padding, padding, 0, 0, 0, width / 2 + padding, margin + height + padding, "L", width / 2 + padding, margin + padding, "A", padding, padding, 0, 0, 0, width / 2, margin, "L", padding, margin, "Z" ] }; return styles[style].join(" "); }; exports.default = Bubble; /***/ }), /***/ "./src/graphDiagram/bubble/NodeSpeechBubble.ts": /*!*****************************************************!*\ !*** ./src/graphDiagram/bubble/NodeSpeechBubble.ts ***! \*****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(/*! d3 */ "d3"); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); const Bubble_1 = __webpack_require__(/*! ./Bubble */ "./src/graphDiagram/bubble/Bubble.ts"); class NodeSpeechBubble extends Bubble_1.default { constructor(node, radius) { super(node); var relatedNodes = []; node.model.relationshipList().forEach(function (relationship) { if (relationship.start === node) { relatedNodes.push(relationship.end); } if (relationship.end === node) { relatedNodes.push(relationship.start); } }); var orientation = NodeSpeechBubble.chooseNodeSpeechBubbleOrientation(node, relatedNodes); var properties = node.properties; var propertyKeysWidth = d3.max(properties.listEditable(), function (property) { return GraphDiagram_1.default.measureTextDimensions(property.key + ": ", node.properties.style("font-size"), node.properties.style("font-family")); }); var propertyValuesWidth = d3.max(properties.listEditable(), function (property) { return GraphDiagram_1.default.measureTextDimensions(property.value, node.properties.style("font-size"), node.properties.style("font-family")); }); var textSize = { width: parseFloat(propertyKeysWidth) + parseFloat(propertyValuesWidth), height: properties.listEditable().length * GraphDiagram_1.default.parsePixels(properties.style("font-size")) }; var mirror = "scale(" + orientation.mirrorX + "," + orientation.mirrorY + ") "; var margin = GraphDiagram_1.default.parsePixels(properties.style("margin")); var padding = GraphDiagram_1.default.parsePixels(properties.style("padding")); var diagonalRadius = radius.mid() * Math.sqrt(2) / 2; var nodeOffsetOptions = { diagonal: { attach: { x: diagonalRadius, y: diagonalRadius }, textCorner: { x: margin + padding, y: margin + padding } }, horizontal: { attach: { x: radius.mid(), y: 0 }, textCorner: { x: margin + padding, y: -textSize.height / 2 } }, vertical: { attach: { x: 0, y: radius.mid() }, textCorner: { x: -textSize.width / 2, y: margin + padding } } }; var nodeCenterOffset = nodeOffsetOptions[orientation.style].attach; var textCorner = nodeOffsetOptions[orientation.style].textCorner; var translate = "translate(" + (node.ex() + nodeCenterOffset.x * orientation.mirrorX) + "," + (node.ey() + nodeCenterOffset.y * orientation.mirrorY) + ") "; var textOrigin = { x: parseFloat(propertyKeysWidth) + orientation.mirrorX * (textCorner.x) - (orientation.mirrorX == -1 ? textSize.width : 0), y: orientation.mirrorY * (textCorner.y) - (orientation.mirrorY == -1 ? textSize.height : 0) }; var boundingPadding = padding + node.model.parameters.speechBubbleStrokeWidth / 2; var boundingBox = { x: node.ex() + (nodeCenterOffset.x + textCorner.x - boundingPadding) * orientation.mirrorX, y: node.ey() + (nodeCenterOffset.y + textCorner.y - boundingPadding) * orientation.mirrorY, width: orientation.mirrorX * (textSize.width + (boundingPadding * 2)), height: orientation.mirrorY * (textSize.height + (boundingPadding * 2)) }; this.properties = properties.listEditable().map(function (property) { return { keyText: property.key + ": ", valueText: property.value, textOrigin: textOrigin, style: node.style(), entity: node }; }); this.style = node.style(); this.groupTransform = translate; this.outlineTransform = mirror; this.outlinePath = Bubble_1.default.speechBubblePath(textSize, orientation.style, margin, padding), this.boundingBox = boundingBox; } } NodeSpeechBubble.chooseNodeSpeechBubbleOrientation = function (focusNode, relatedNodes) { var orientations = [ { key: "WEST", style: "horizontal", mirrorX: -1, mirrorY: 1, angle: 180 }, { key: "NORTH-WEST", style: "diagonal", mirrorX: -1, mirrorY: -1, angle: -135 }, { key: "NORTH", style: "vertical", mirrorX: 1, mirrorY: -1, angle: -90 }, { key: "NORTH-EAST", style: "diagonal", mirrorX: 1, mirrorY: -1, angle: -45 }, { key: "EAST", style: "horizontal", mirrorX: 1, mirrorY: 1, angle: 0 }, { key: "SOUTH-EAST", style: "diagonal", mirrorX: 1, mirrorY: 1, angle: 45 }, { key: "SOUTH", style: "vertical", mirrorX: 1, mirrorY: 1, angle: 90 }, { key: "SOUTH-WEST", style: "diagonal", mirrorX: -1, mirrorY: 1, angle: 135 } ]; orientations.forEach(function (orientation) { orientation.closest = 180; }); relatedNodes.forEach(function (relatedNode) { orientations.forEach(function (orientation) { var angle = Math.abs(focusNode.angleTo(relatedNode) - orientation.angle); if (angle > 180) { angle = 360 - angle; } if (angle < orientation.closest) { orientation.closest = angle; } }); }); var maxAngle = 0; var bestOrientation = orientations[0]; orientations.forEach(function (orientation) { if (orientation.closest > maxAngle) { maxAngle = orientation.closest; bestOrientation = orientation; } }); return bestOrientation; }; exports.default = NodeSpeechBubble; /***/ }), /***/ "./src/graphDiagram/bubble/RelationshipSpeechBubble.ts": /*!*************************************************************!*\ !*** ./src/graphDiagram/bubble/RelationshipSpeechBubble.ts ***! \*************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(/*! d3 */ "d3"); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); const Bubble_1 = __webpack_require__(/*! ./Bubble */ "./src/graphDiagram/bubble/Bubble.ts"); class RelationshipSpeechBubble extends Bubble_1.default { constructor(relationship, apex) { super(relationship); var properties = relationship.properties; var fontSize = relationship.properties.style("font-size"); var fontFamily = relationship.properties.style("font-family"); var orientation = RelationshipSpeechBubble.chooseRelationshipSpeechBubbleOrientation(relationship); var propertyKeysWidth = d3.max(properties.listEditable(), function (property) { return GraphDiagram_1.default.measureTextDimensions(property.key + ": ", fontSize, fontFamily); }); var propertyValuesWidth = d3.max(properties.listEditable(), function (property) { return GraphDiagram_1.default.measureTextDimensions(property.value, fontSize, fontFamily); }); var textSize = { width: propertyKeysWidth + propertyValuesWidth, height: properties.listEditable().length * GraphDiagram_1.default.parsePixels(properties.style("font-size")) }; var margin = GraphDiagram_1.default.parsePixels(properties.style("margin")); var padding = GraphDiagram_1.default.parsePixels(properties.style("padding")); var mirror = "scale(" + orientation.mirrorX + "," + orientation.mirrorY + ") "; var nodeOffsetOptions = { diagonal: { textCorner: { x: margin + padding, y: margin + padding } }, horizontal: { textCorner: { x: margin + padding, y: -textSize.height / 2 } }, vertical: { textCorner: { x: -textSize.width / 2, y: margin + padding } } }; var textCorner = nodeOffsetOptions[orientation.style].textCorner; var dx = relationship.end.ex() - relationship.start.ex(); var dy = relationship.end.ey() - relationship.start.ey(); var h = Math.sqrt(dx * dx + dy * dy); var midPoint = { x: relationship.start.ex() + (apex.x * dx - apex.y * dy) / h, y: relationship.start.ey() + (apex.x * dy + apex.y * dx) / h }; var translate = "translate(" + midPoint.x + "," + midPoint.y + ") "; var textOrigin = { x: propertyKeysWidth + orientation.mirrorX * (textCorner.x) - (orientation.mirrorX == -1 ? textSize.width : 0), y: orientation.mirrorY * (textCorner.y) - (orientation.mirrorY == -1 ? textSize.height : 0) }; var boundingPadding = padding + relationship.model.parameters.speechBubbleStrokeWidth / 2; var boundingBox = { x: midPoint.x + (textCorner.x - boundingPadding) * orientation.mirrorX, y: midPoint.y + (textCorner.y - boundingPadding) * orientation.mirrorY, width: orientation.mirrorX * (textSize.width + (boundingPadding * 2)), height: orientation.mirrorY * (textSize.height + (boundingPadding * 2)) }; this.properties = properties.listEditable().map(function (property) { return { keyText: property.key + ": ", valueText: property.value, textOrigin: textOrigin, style: relationship.style(), entity: relationship }; }); this.style = relationship.style(); this.entity = relationship; this.groupTransform = translate; this.outlineTransform = mirror; this.outlinePath = Bubble_1.default.speechBubblePath(textSize, orientation.style, margin, padding); this.boundingBox = boundingBox; } static chooseRelationshipSpeechBubbleOrientation(relationship) { var orientations = { EAST: { style: "horizontal", mirrorX: 1, mirrorY: 1, angle: 0 }, SOUTH_EAST: { style: "diagonal", mirrorX: 1, mirrorY: 1, angle: 45 }, SOUTH: { style: "vertical", mirrorX: 1, mirrorY: 1, angle: 90 }, SOUTH_WEST: { style: "diagonal", mirrorX: -1, mirrorY: 1, angle: 135 }, WEST: { style: "horizontal", mirrorX: -1, mirrorY: 1, angle: 180 } }; var relationshipAngle = relationship.start.angleTo(relationship.end); var positiveAngle = relationshipAngle > 0 ? relationshipAngle : relationshipAngle + 180; if (positiveAngle > 175 || positiveAngle < 5) { return orientations.SOUTH; } else if (positiveAngle < 85) { return orientations.SOUTH_WEST; } else if (positiveAngle < 90) { return orientations.WEST; } else if (positiveAngle === 90) { return relationshipAngle > 0 ? orientations.WEST : orientations.EAST; } else if (positiveAngle < 95) { return orientations.EAST; } else { return orientations.SOUTH_EAST; } } } exports.default = RelationshipSpeechBubble; /***/ }), /***/ "./src/graphDiagram/diagram/Diagram.ts": /*!*********************************************!*\ !*** ./src/graphDiagram/diagram/Diagram.ts ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(/*! d3 */ "d3"); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); const Layout_1 = __webpack_require__(/*! ../layout/Layout */ "./src/graphDiagram/layout/Layout.ts"); const Scaling_1 = __webpack_require__(/*! ../scaling/Scaling */ "./src/graphDiagram/scaling/Scaling.ts"); var thiz; class Diagram { constructor() { this._renderPropertyBubblesFlag = true; this._overlay = function (layoutModel, view) { }; this._scaling = Scaling_1.default.sizeSvgToFitDiagram; thiz = this; } overlay(behaviour) { this._overlay = behaviour; return this; } ; scaling(scalingFunction) { this._scaling = scalingFunction; return this; } ; toggleRenderPropertyBubblesFlag() { this._renderPropertyBubblesFlag = !this._renderPropertyBubblesFlag; } renderNodes(nodes, view) { function nodeClasses(d) { let result = d.model.class().join(" ") + " " + "node-id-" + d.model.id + ` node-base node-type-${d.model.caption}`; return result; } var circles = view.selectAll("circle.node").data(nodes); circles.exit().remove(); var circlesEnter = circles.enter().append("svg:circle") .attr("class", nodeClasses) .merge(circles) .attr("r", function (node) { return node.radius.mid(); }) .attr("fill", function (node) { return node.model.style("background-color"); }) .attr("stroke", function (node) { return node.model.style("border-color"); }) .attr("stroke-width", function (node) { return node.model.style("border-width"); }) .attr("cx", function (node) { var ex = node.model.ex(); return ex; }) .attr("cy", function (node) { return node.model.ey(); }); function captionClasses(line) { return "caption " + line.node.model.class().join(" ") + " " + "node-id-" + line.node.model.id + ` node-type-${line.node.model.caption}`; } var nodesWithCaptions = nodes.filter(function (node) { return node.model.displayCaption; }); var captionGroups = view.selectAll("g.caption") .data(nodesWithCaptions); captionGroups.exit().remove(); var captionGroupsEnter = captionGroups.enter().append("g") .attr("class", "caption"); var captionGroupsMerge = captionGroups.merge(captionGroupsEnter); var captions = captionGroupsMerge.selectAll("text.caption") .data(function (node) { var data = node.captionLines.map(function (line) { return { node: node, caption: line }; }); return data; }); captions.exit().remove(); var captionsEnter = captions.enter().append("svg:text") .attr("class", captionClasses); var captionsMerge = captions.merge(captionsEnter); captionsMerge .attr("text-anchor", "middle") .attr("alignment-baseline", "central") .attr("x", function (line) { return line.node.model.ex(); }) .attr("y", function (line, i) { return line.node.model.ey() + (i - (line.node.captionLines.length - 1) / 2) * line.node.captionLineHeight; }) .attr("fill", function (line) { return line.node.model.style("color"); }) .attr("font-size", function (line) { return line.node.model.style("font-size"); }) .attr("font-family", function (line) { return line.node.model.style("font-family"); }) .text(function (line) { return line.caption; }); } renderRelationships(relationshipGroups, view) { function translateToStartNodeCenterAndRotateToRelationshipAngle(r) { var angle = r.start.model.angleTo(r.end.model); return "translate(" + r.start.model.ex() + "," + r.start.model.ey() + ") rotate(" + angle + ")"; } function rotateIfRightToLeft(r) { return r.end.model.isLeftOf(r.start.model) ? "rotate(180)" : null; } function side(r) { return r.end.model.isLeftOf(r.start.model) ? -1 : 1; } function relationshipClasses(d) { var r = d.model; return r.class().join(" "); } var relatedNodesGroup = view.selectAll("g.related-pair") .data(relationshipGroups); relatedNodesGroup.exit().remove(); var relatedNodesGroupEnter = relatedNodesGroup.enter().append("svg:g") .attr("class", "related-pair"); var relatedNodesGroupMerge = relatedNodesGroup.merge(relatedNodesGroupEnter); var relationshipGroup = relatedNodesGroupMerge.selectAll("g.relationship") .data(function (d) { return d; }); relationshipGroup.exit().remove(); var relationshipGroupEnter = relationshipGroup.enter().append("svg:g") .attr("class", relationshipClasses); var relationshipGroupMerge = relationshipGroup.merge(relationshipGroupEnter); relationshipGroupMerge .attr("transform", translateToStartNodeCenterAndRotateToRelationshipAngle); var relationshipPath = relationshipGroupMerge.selectAll("path.relationship") .data(function (d) { return [d]; }); var relationshipPathEnter = relationshipPath.enter().append("svg:path") .attr("class", relationshipClasses); var relationshipPathMerge = relationshipPath.merge(relationshipPathEnter); relationshipPathMerge .attr("d", function (d) { return d.arrow.outline; }) .attr("fill", function (node) { return node.model.style("background-color"); }) .attr("stroke", function (node) { return node.model.style("border-color"); }) .attr("stroke-width", function (node) { return node.model.style("border-width"); }); function relationshipWithRelationshipType(d) { return [d].filter(function (d) { return d.model.relationshipType; }); } var relationshipType = relationshipGroupMerge.selectAll("text.type") .data(relationshipWithRelationshipType); relationshipType.exit().remove(); var relationshipTypeEnter = relationshipType.enter().append("svg:text") .attr("class", "type") .attr("text-anchor", "middle") .attr("baseline-shift", "30%") .attr("alignment-baseline", "alphabetic"); var relationshipTypeMerge = relationshipType.merge(relationshipTypeEnter); relationshipTypeMerge .attr("transform", rotateIfRightToLeft) .attr("x", function (d) { return side(d) * d.arrow.apex.x; }) .attr("y", function (d) { return side(d) * d.arrow.apex.y; }) .attr("font-size", function (d) { return d.model.style("font-size"); }) .attr("font-family", function (d) { return d.model.style("font-family"); }) .text(function (d) { return d.model.relationshipType; }); } renderPropertyBubbles(entities, descriminator, view) { var entitiesWithProperties = entities.filter(GraphDiagram_1.default.hasProperties); var propertiesData = entitiesWithProperties.map(function (entity) { return entity.propertiesBubble; }); var speechBubbleGroup = view.selectAll("g.speech-bubble." + descriminator + "-speech-bubble") .data(propertiesData); speechBubbleGroup.exit().remove(); var speechBubbleGroupEnter = speechBubbleGroup.enter().append("svg:g") .attr("class", "speech-bubble " + descriminator + "-speech-bubble"); var speechBubbleGroupMerge = speechBubbleGroup.merge(speechBubbleGroupEnter); speechBubbleGroupMerge .attr("transform", function (speechBubble) { return speechBubble.groupTransform; }); // toggle visibility of property bubbles if (thiz._renderPropertyBubblesFlag) { speechBubbleGroupMerge.attr("display", "block"); } else { speechBubbleGroupMerge.attr("display", "none"); } var speechBubbleOutline = speechBubbleGroupMerge.selectAll("path.speech-bubble-outline") .data(function (d) { return [d]; }); speechBubbleOutline.exit().remove(); var speechBubbleOutlineEnter = speechBubbleOutline.enter().append("svg:path") .attr("class", "speech-bubble-outline"); var speechBubbleOutlineMerge = speechBubbleOutline.merge(speechBubbleOutlineEnter); speechBubbleOutlineMerge .attr("transform", function (speechBubble) { return speechBubble.outlineTransform; }) .attr("d", function (speechBubble) { return speechBubble.outlinePath; }) .attr("fill", function (speechBubble) { return speechBubble.entity.properties.style("background-color"); }) .attr("stroke", function (speechBubble) { return speechBubble.entity.properties.style("border-color"); }) .attr("stroke-width", function (speechBubble) { return speechBubble.entity.properties.style("border-width"); }); var propertyKeys = speechBubbleGroupMerge.selectAll("text.speech-bubble-content.property-key") .data(function (speechBubble) { return speechBubble.properties; }); propertyKeys.exit().remove(); var propertyKeysEnter = propertyKeys.enter().append("svg:text") .attr("class", "speech-bubble-content property-key"); var propertyKeysEnterMerge = propertyKeys.merge(propertyKeysEnter); propertyKeysEnterMerge .attr("x", function (properties) { return properties.textOrigin.x; }) .attr("y", function (properties, i) { return (i + 0.5) * GraphDiagram_1.default.parsePixels(properties.entity.properties.style("font-size")) + properties.textOrigin.y; }) .attr("alignment-baseline", "central") .attr("text-anchor", "end") .attr("font-size", function (properties) { return properties.entity.properties.style("font-size"); }) .attr("font-family", function (properties) { return properties.entity.properties.style("font-family"); }) .attr("xml:space", "preserve") .text(function (properties) { return properties.keyText; }); var propertyValues = speechBubbleGroupMerge.selectAll("text.speech-bubble-content.property-value") .data(function (speechBubble) { return speechBubble.properties; }); propertyValues.exit().remove(); var propertyValuesEnter = propertyValues.enter().append("svg:text") .attr("class", "speech-bubble-content property-value"); var propertyValuesMerge = propertyValues.merge(propertyValuesEnter); propertyValuesMerge .attr("x", function (properties) { return properties.textOrigin.x; }) .attr("y", function (properties, i) { return (i + 0.5) * GraphDiagram_1.default.parsePixels(properties.entity.properties.style("font-size")) + properties.textOrigin.y; }) .attr("alignment-baseline", "central") .attr("font-size", function (properties) { return properties.entity.properties.style("font-size"); }) .attr("font-family", function (properties) { return properties.entity.properties.style("font-family"); }) .text(function (properties) { return properties.valueText; }); } render(selection) { selection.each(function (model) { var view = d3.select(this); thiz.layout = new Layout_1.default(model); var layoutModel = thiz.layout.layoutModel; function layer(name) { var layer = view.selectAll("g.layer." + name).data([name]); var layerEnter = layer.enter().append("g") .attr("class", "layer " + name); var result = layer.merge(layerEnter); return result; } thiz.renderRelationships(layoutModel.relationshipGroups, layer("relationships")); thiz.renderNodes(layoutModel.nodes, layer("nodes")); thiz.renderPropertyBubbles(layoutModel.nodes, "node", layer("node_properties")); thiz.renderPropertyBubbles(layoutModel.relationships, "relationship", layer("relationship_properties")); if (thiz._overlay) { thiz._overlay(layoutModel, layer("overlay")); } if (thiz._scaling) { thiz._scaling(layoutModel, view); } }); } } exports.default = Diagram; /***/ }), /***/ "./src/graphDiagram/layout/Layout.ts": /*!*******************************************!*\ !*** ./src/graphDiagram/layout/Layout.ts ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); //import NodeSpeechBubble from '../bubble/NodeSpeechBubble'; //import RelationshipSpeechBubble from '../bubble/RelationshipSpeechBubble'; const LayoutRelationship_1 = __webpack_require__(/*! ./LayoutRelationship */ "./src/graphDiagram/layout/LayoutRelationship.ts"); const LayoutNode_1 = __webpack_require__(/*! ./LayoutNode */ "./src/graphDiagram/layout/LayoutNode.ts"); const HorizontalArrowOutline_1 = __webpack_require__(/*! ../arrow/HorizontalArrowOutline */ "./src/graphDiagram/arrow/HorizontalArrowOutline.ts"); const CurvedArrowOutline_1 = __webpack_require__(/*! ../arrow/CurvedArrowOutline */ "./src/graphDiagram/arrow/CurvedArrowOutline.ts"); class Layout { constructor(graphModel) { this.nodesById = new Map(); this.layoutModel = { graphModel: graphModel, nodes: [], relationships: [], relationshipGroups: [] }; graphModel.nodeList().forEach((node) => { // var measurement: any = Layout.wrapAndMeasureCaption( node ); //FUNKY //TODO var layoutNode = new LayoutNode_1.default(node); this.nodesById.set(node.id, layoutNode); this.layoutModel.nodes.push(layoutNode); }); graphModel.groupedRelationshipList().forEach((group) => { var nominatedStart = group[0].start; var offsetStep = GraphDiagram_1.default.parsePixels(group[0].style("margin")); var relationshipGroup = []; for (var i = 0; i < group.length; i++) { var relationship = group[i]; var offset = (relationship.start === nominatedStart ? 1 : -1) * offsetStep * (i - (group.length - 1) / 2); // console.log(`groupedRelationshipList: offset: ${offset}`); var start = this.nodesById.get(relationship.start.id); var end = this.nodesById.get(relationship.end.id); var arrow = this.horizontalArrow(relationship, start, end, offset); var layoutRelationship = new LayoutRelationship_1.default(relationship, start, end, arrow); relationshipGroup.push(layoutRelationship); this.layoutModel.relationships.push(layoutRelationship); } this.layoutModel.relationshipGroups.push(relationshipGroup); }); } horizontalArrow(relationship, start, end, offset) { var length = start.model.distanceTo(end.model); var arrowWidth = GraphDiagram_1.default.parsePixels(relationship.style("width")); if (offset === 0) { return new HorizontalArrowOutline_1.default(start.radius.startRelationship(), (length - end.radius.endRelationship()), arrowWidth); } return new CurvedArrowOutline_1.default(start.radius.startRelationship(), end.radius.endRelationship(), length, offset, arrowWidth, arrowWidth * 4, arrowWidth * 4); } } exports.default = Layout; /***/ }), /***/ "./src/graphDiagram/layout/LayoutEntity.ts": /*!*************************************************!*\ !*** ./src/graphDiagram/layout/LayoutEntity.ts ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class LayoutEntity { constructor(entity) { this.model = entity; this.propertiesBubble = {}; } } exports.default = LayoutEntity; /***/ }), /***/ "./src/graphDiagram/layout/LayoutModel.ts": /*!************************************************!*\ !*** ./src/graphDiagram/layout/LayoutModel.ts ***! \************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class layoutModel { constructor(model) { this.graphModel = model; this.nodes = []; this.relationships = []; this.relationshipGroups = []; } } exports.default = layoutModel; /***/ }), /***/ "./src/graphDiagram/layout/LayoutNode.ts": /*!***********************************************!*\ !*** ./src/graphDiagram/layout/LayoutNode.ts ***! \***********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); const LayoutEntity_1 = __webpack_require__(/*! ../layout/LayoutEntity */ "./src/graphDiagram/layout/LayoutEntity.ts"); const NodeSpeechBubble_1 = __webpack_require__(/*! ../bubble/NodeSpeechBubble */ "./src/graphDiagram/bubble/NodeSpeechBubble.ts"); const Radius_1 = __webpack_require__(/*! ../layout/Radius */ "./src/graphDiagram/layout/Radius.ts"); class LayoutNode extends LayoutEntity_1.default { constructor(graphNode) { super(graphNode); this.class = graphNode.class; this.x = graphNode.ex(); this.y = graphNode.ey(); let captionMeasurements = this.wrapAndMeasureCaption(graphNode); this.radius = captionMeasurements.radius; this.captionLines = captionMeasurements.captionLines; this.captionLineHeight = captionMeasurements.captionLineHeight; this.propertiesBubble = new NodeSpeechBubble_1.default(graphNode, captionMeasurements.radius); } wrapAndMeasureCaption(node) { // function measure( text: string ) // { // return GraphDiagram.measureTextDimensions( text, node ); // } // console.log(node, node.style(), node.style("font-size")); var lineHeight = GraphDiagram_1.default.parsePixels(node.style("font-size")); // console.log(lineHeight); var insideRadius = 0; var captionLines = []; if (node.displayCaption) { var padding = GraphDiagram_1.default.parsePixels(node.style("padding")); var fontSize = node.properties.style("font-size"); var fontFamily = node.properties.style("font-family"); var totalWidth = GraphDiagram_1.default.measureTextDimensions(node.displayCaption, fontSize, fontFamily); var idealRadius = Math.sqrt(totalWidth * lineHeight / Math.PI); var idealRows = idealRadius * 2 / lineHeight; function idealLength(row) { var rowOffset = lineHeight * (row - idealRows) / 2; return Math.sqrt(idealRadius * idealRadius - rowOffset * rowOffset) * 2; } var words = node.displayCaption.split(" "); var currentLine = words.shift(); while (words.length > 0) { if (GraphDiagram_1.default.measureTextDimensions(currentLine, fontSize, fontFamily) > idealLength(captionLines.length)) { captionLines.push(currentLine); currentLine = words.shift(); } else { currentLine += " " + words.shift(); } } captionLines.push(currentLine); for (var row = 0; row < captionLines.length; row++) { var width = GraphDiagram_1.default.measureTextDimensions(captionLines[row], fontSize, fontFamily) / 2; var middleRow = (captionLines.length - 1) / 2; var rowOffset = lineHeight * (row > middleRow ? (row - middleRow + 0.5) : (row - middleRow - 0.5)); insideRadius = padding + Math.max(Math.sqrt(width * width + rowOffset * rowOffset), insideRadius); } } let minWidthProperty = node.style("min-width") ? node.style("min-width") : "30px"; var minRadius = GraphDiagram_1.default.parsePixels(minWidthProperty) / 2; if (minRadius > insideRadius) { insideRadius = minRadius; } var radius = new Radius_1.default(node.model, insideRadius); radius.border = GraphDiagram_1.default.parsePixels(node.style("border-width")); radius.margin = GraphDiagram_1.default.parsePixels(node.style("margin")); return { radius: radius, captionLines: captionLines, captionLineHeight: lineHeight }; } } exports.default = LayoutNode; /***/ }), /***/ "./src/graphDiagram/layout/LayoutRelationship.ts": /*!*******************************************************!*\ !*** ./src/graphDiagram/layout/LayoutRelationship.ts ***! \*******************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const LayoutEntity_1 = __webpack_require__(/*! ../layout/LayoutEntity */ "./src/graphDiagram/layout/LayoutEntity.ts"); const RelationshipSpeechBubble_1 = __webpack_require__(/*! ../bubble/RelationshipSpeechBubble */ "./src/graphDiagram/bubble/RelationshipSpeechBubble.ts"); class LayoutRelationship extends LayoutEntity_1.default { constructor(graphRelationship, start, end, arrow) { super(graphRelationship); this.start = start; this.end = end; this.arrow = arrow; this.propertiesBubble = new RelationshipSpeechBubble_1.default(graphRelationship, arrow.apex); this.model = graphRelationship; } } exports.default = LayoutRelationship; /***/ }), /***/ "./src/graphDiagram/layout/Radius.ts": /*!*******************************************!*\ !*** ./src/graphDiagram/layout/Radius.ts ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class Radius { constructor(model, insideRadius) { this.insideRadius = insideRadius; this.borderWidth = model.parameters.nodeStrokeWidth; this.arrowMargin = model.parameters.nodeStartMargin; } inside(insideRadius) { if (arguments.length == 1) { this.insideRadius = insideRadius; return this; } return this.insideRadius; } ; get border() { return this.borderWidth; } set border(borderWidth) { this.borderWidth = borderWidth; } ; get margin() { return this.arrowMargin; } set margin(arrowMargin) { this.arrowMargin = arrowMargin; } ; mid() { return this.insideRadius + this.borderWidth / 2; } ; outside() { return this.insideRadius + this.borderWidth; } ; startRelationship() { return this.insideRadius + this.borderWidth + this.arrowMargin; } ; endRelationship() { return this.insideRadius + this.borderWidth + this.arrowMargin; } ; } exports.default = Radius; ; /***/ }), /***/ "./src/graphDiagram/markup/Markup.ts": /*!*******************************************!*\ !*** ./src/graphDiagram/markup/Markup.ts ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const d3 = __webpack_require__(/*! d3 */ "d3"); const Model_1 = __webpack_require__(/*! ../model/Model */ "./src/graphDiagram/model/Model.ts"); const SimpleStyle_1 = __webpack_require__(/*! ../model/SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); class Markup { static parseAll(selection) { var models = []; selection.each(function () { var selx = d3.select(this); var modelx = Markup.parse(selx); // console.log(this, selx, modelx); // debugger; models.push(modelx); }); return models; } static parseProperties(entity, debug = false) { return function () { var propertiesMarkup = d3.select(this); if (debug) { console.log(`parseProperties:`, entity, this, propertiesMarkup); } var elements = propertiesMarkup.selectAll("dt, dd"); var currentKey; elements.each(function () { if (this.nodeName.toLowerCase() === "dt") { currentKey = d3.select(this).text(); } else if (currentKey && this.nodeName.toLowerCase() === "dd") { entity.properties.set(currentKey, d3.select(this).text()); } }); SimpleStyle_1.default.copyStyles(entity.properties, propertiesMarkup, debug); }; } static parse(selection, modelId) { var model = new Model_1.default(modelId); if (selection.attr("data-internal-scale")) { model.internalScale = selection.attr("data-internal-scale"); } if (selection.attr("data-external-scale")) { model.externalScale = selection.attr("data-external-scale"); } var nodePrototype = selection.append("li").attr("class", "node"); var nodePropertiesPrototype = nodePrototype.append("dl").attr("class", "properties"); SimpleStyle_1.default.copyStyles(model.stylePrototype.node, nodePrototype); SimpleStyle_1.default.copyStyles(model.stylePrototype.nodeProperties, nodePropertiesPrototype); nodePrototype.remove(); var relationshipPrototype = selection.append("li").attr("class", "relationship"); var relationshipPropertiesPrototype = relationshipPrototype.append("dl").attr("class", "properties"); SimpleStyle_1.default.copyStyles(model.stylePrototype.relationship, relationshipPrototype); SimpleStyle_1.default.copyStyles(model.stylePrototype.relationshipProperties, relationshipPropertiesPrototype); relationshipPrototype.remove(); selection.selectAll(".node").each(function () { var nodeMarkup = d3.select(this); //TODO var id = nodeMarkup.attr("data-node-id"); var node = model.createNode(id); node.class(nodeMarkup.attr("class") || ""); node.x = parseFloat(nodeMarkup.attr("data-x")); node.y = parseFloat(nodeMarkup.attr("data-y")); nodeMarkup.select("span.caption").each(function () { node.caption = d3.select(this).text(); //TODO }); nodeMarkup.select("dl.properties").each(Markup.parseProperties(node)); SimpleStyle_1.default.copyStyles(node, nodeMarkup); }); selection.selectAll(".relationship").each(function () { // console.log(`parsing relationship:`, this) var relationshipMarkup = d3.select(this); //TODO var fromId = parseFloat(relationshipMarkup.attr("data-from")); var toId = parseFloat(relationshipMarkup.attr("data-to")); var relationship = model.createRelationship(model.lookupNode(fromId), model.lookupNode(toId)); relationship.class(relationshipMarkup.attr("class") || ""); relationshipMarkup.select("span.type").each(function () { relationship.relationshipType = d3.select(this).text(); // console.log(`span.type:`, this, relationship.relationshipType); }); // console.log(`relationshipMarkup:`, relationshipMarkup, relationship.relationshipType); var temp = relationshipMarkup.select("dl.properties").each(Markup.parseProperties(relationship, false)); // console.log(temp); SimpleStyle_1.default.copyStyles(relationship, relationshipMarkup, false); // console.log(relationship); }); return model; } static format(model, container) { var ul = container.append("ul") .attr("class", "graph-diagram-markup") .attr("data-internal-scale", model.internalScale) .attr("data-external-scale", model.externalScale); function formatProperties(entity, li) { if (entity.properties.list().length > 0) { var dl = li.append("dl") .attr("class", "properties"); entity.properties.list().forEach(function (property) { dl.append("dt") .text(property.key); dl.append("dd") .text(property.value); }); } } model.nodeList().forEach(function (node) { var li = ul.append("li") .attr("class", node.class().join(" ")) .attr("data-node-id", node.id) .attr("data-x", node.x) .attr("data-y", node.y); if (node.caption) { li.append("span") .attr("class", "caption") .text(node.caption); } formatProperties(node, li); }); model.relationshipList().forEach(function (relationship) { var li = ul.append("li") .attr("class", relationship.class().join(" ")) .attr("data-from", relationship.start.id) .attr("data-to", relationship.end.id); if (relationship.relationshipType) { li.append("span") .attr("class", "type") .text(relationship.relationshipType); } formatProperties(relationship, li); }); } } exports.default = Markup; /***/ }), /***/ "./src/graphDiagram/model/DataTypes.ts": /*!*********************************************!*\ !*** ./src/graphDiagram/model/DataTypes.ts ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class DataTypes { } exports.DataTypes = DataTypes; /***/ }), /***/ "./src/graphDiagram/model/Entity.ts": /*!******************************************!*\ !*** ./src/graphDiagram/model/Entity.ts ***! \******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); class Entity { constructor(model) { // public index: number; this.classes = []; this.model = model; this._label = ""; this._entityType = ""; } style(cssPropertyKey, cssPropertyValue) { return this._style.style(cssPropertyKey, cssPropertyValue); } class(classesString) { if (arguments.length == 1) { this.classes = classesString.split(" ").filter((className) => { return className.length > 0 && className != this._entityType; }); return this; } return [this._entityType].concat(this.classes); } ; set caption(captionText) { this._label = captionText; } get caption() { return this._label; } set label(labelText) { this._label = labelText; } get label() { return this._label; } get displayCaption() { return this.displayLabel; } get displayLabel() { let name = this.properties.has('name'); if (name) { return `${this._label}: ${name}`; } else { return this._label; } } get properties() { if (this.model.id) { this._properties.set(GraphDiagram_1.default.MODEL_ID_KEY, this.model.id); } return this._properties; } } exports.default = Entity; /***/ }), /***/ "./src/graphDiagram/model/Model.ts": /*!*****************************************!*\ !*** ./src/graphDiagram/model/Model.ts ***! \*****************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const SimpleStyle_1 = __webpack_require__(/*! ./SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); const d3 = __webpack_require__(/*! d3 */ "d3"); const Node_1 = __webpack_require__(/*! ./Node */ "./src/graphDiagram/model/Node.ts"); const Relationship_1 = __webpack_require__(/*! ./Relationship */ "./src/graphDiagram/model/Relationship.ts"); class Model { /* .graph-diagram-markup { font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; } .graph-diagram-markup .node { font-size: 14px; margin: 5px; padding: 5px; min-width: 30px; background-color: #f7f7f9; border: 1px solid rgba(0, 0, 0, 0.3); } .graph-diagram-markup .relationship { font-size: 14px; width: 2px; margin: 10px; background-color: rgba(0, 0, 0, 0.3); border: none; } .graph-diagram-markup .properties { font-size: 14px; margin: 12px; padding: 4px; background-color: white; border: 1px solid rgba(0, 0, 0, 0.5); } */ constructor(id) { this.nodes = new Map(); this.relationships = new Map(); this.highestNodeIndex = 0; this.highestRelationshipIndex = 0; this.parameters = { radius: 50, nodeStrokeWidth: 8, nodeStartMargin: 11, nodeEndMargin: 11, speechBubbleMargin: 20, speechBubblePadding: 10, speechBubbleStrokeWidth: 3, snapTolerance: 20 }; this._internalScale = 1; this._externalScale = 1; if (id) { this._id = id; } this.stylePrototype = { node: new SimpleStyle_1.default({ 'min-width': '30px', 'font-size': '14px', 'font-family': '"Helvetica Neue", Helvetica, Arial, sans-serif', 'padding': '5px', 'border-width': '1px', 'border-color': 'rgba(0, 0, 0, 0.3)', 'margin': '5px', 'background-color': '#f7f7f9', 'border': '1px solid rgba(0, 0, 0, 0.3)' }), nodeProperties: new SimpleStyle_1.default({ 'font-size': '14px', 'font-family': '"Helvetica Neue", Helvetica, Arial, sans-serif', 'padding': '4px', 'margin': '12px', 'background-color': 'white', 'border': '1px solid rgba(0, 0, 0, 0.5)', 'border-color': 'rgba(0, 0, 0, 0.5)', 'border-width': '1px' }), relationship: new SimpleStyle_1.default({ 'font-size': '14px', 'font-family': '"Helvetica Neue", Helvetica, Arial, sans-serif', 'width': '2px', 'border-width': '3px', 'margin': '10px', 'background-color': 'rgba(0, 0, 0, 0.3)', 'border': 'none' }), relationshipProperties: new SimpleStyle_1.default({ 'font-size': '14px', 'font-family': '"Helvetica Neue", Helvetica, Arial, sans-serif', 'padding': '4px', 'margin': '12px', 'background-color': 'white', 'border': '1px solid rgba(0, 0, 0, 0.5)', 'border-color': 'rgba(0, 0, 0, 0.5)', 'border-width': '1px' }) }; } toString() { let result = 'Model:\n'; let obj = { highestNodeIndex: this.highestNodeIndex, highestRelationshipIndex: this.highestRelationshipIndex, nodeCount: this.nodes.size, relationshipCount: this.relationships.size, nodeStylePrototype: this.stylePrototype.node.style(), }; result += JSON.stringify(obj); return result; } summary() { let obj = { highestNodeIndex: this.highestNodeIndex, highestRelationshipIndex: this.highestRelationshipIndex, nodeCount: this.nodes.size, relationshipCount: this.relationships.size, nodePropertiesStylePrototype: this.stylePrototype.nodeProperties.style(), relationshipPropertiesStylePrototype: this.stylePrototype.relationshipProperties.style(), }; return obj; } generateNodeIndex() { while (this.nodes.get(`${this.highestNodeIndex}`)) { this.highestNodeIndex++; } return this.highestNodeIndex; } createNode(optionalId) { var node = new Node_1.default(this); // node.index = this.generateNodeIndex(); // var nodeId: string = optionalId || `${this.generateNodeIndex()}`; node.id = optionalId || `${this.generateNodeIndex()}`; this.nodes.set(node.id, node); return node; } ; reassignNodeId(node, newId) { let result = null; if (!this.nodes.get(newId)) { this.nodes.delete(node.id); node.id = newId; this.nodes.set(node.id, node); result = node; } return result; } deleteNode(node) { // this.relationships = this.relationships.filter(function (relationship) { // return !(relationship.start === node || relationship.end == node); // }); this.relationships.forEach((relationship, id, map) => { if ((relationship.start === node) || (relationship.end === node)) { this.relationships.delete(id); } }); this.nodes.delete(node.id); } ; deleteRelationship(relationship) { //this.relationships.splice(this.relationships.indexOf(relationship), 1); this.relationships.delete(relationship.id); } ; generateRelationshipIndex() { while (this.relationships.get(`${this.highestRelationshipIndex}`)) { this.highestRelationshipIndex++; } return this.highestRelationshipIndex; } createRelationship(start, end, optionalId) { var relationship = new Relationship_1.default(this, start, end); // relationship.index = this.generateRelationshipIndex(); // var relationshipId: string = optionalId || `${relationship.index }`; relationship.id = optionalId || `${this.generateRelationshipIndex()}`; this.relationships.set(relationship.id, relationship); return relationship; } ; reassignRelationshipId(relationship, newId) { let result = null; if (!this.relationships.get(newId)) { this.relationships.delete(relationship.id); relationship.id = newId; this.relationships.set(relationship.id, relationship); result = relationship; } return result; } nodeList() { return Array.from(this.nodes.values()); } ; lookupNode(nodeId) { return this.nodes.get(`${nodeId}`); } ; relationshipList() { return Array.from(this.relationships.values()); } ; groupedRelationshipList() { var groups = {}; this.relationships.forEach((relationship, id, map) => { var nodeIds = [relationship.start.id, relationship.end.id].sort(); var group = groups[nodeIds]; if (!group) { group = groups[nodeIds] = []; } if (relationship.start.id < relationship.end.id) { group.push(relationship); } else { group.splice(0, 0, relationship); } }); return d3.values(groups); } ; set id(id) { this._id = id; } get id() { return this._id; } set internalScale(newScale) { this._internalScale = newScale; //NOTE parseFloat(newScale); } ; get internalScale() { return this._internalScale; } set externalScale(newScale) { this._externalScale = newScale; //NOTE parseFloat(newScale); } ; get externalScale() { return this._externalScale; } } exports.default = Model; ; /***/ }), /***/ "./src/graphDiagram/model/ModelToCypher.ts": /*!*************************************************!*\ !*** ./src/graphDiagram/model/ModelToCypher.ts ***! \*************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class ModelToCypher { static convert(model) { var statements = []; model.nodeList().forEach((node) => { statements.push("(" + ModelToCypher.quote(node.id) + " :" + ModelToCypher.quote(node.caption || "Node") + " " + ModelToCypher.render(ModelToCypher.props(node)) + ") "); }); model.relationshipList().forEach((rel) => { statements.push("(" + ModelToCypher.quote(rel.start.id) + ")-[:`" + ModelToCypher.quote(rel.relationshipType || "RELATED_TO") + "` " + ModelToCypher.render(ModelToCypher.props(rel)) + "]->(" + ModelToCypher.quote(rel.end.id) + ")"); }); if (statements.length == 0) return ""; return "CREATE \n " + statements.join(",\n "); } static props(element) { var props = {}; element.properties.list().forEach((property) => { props[property.key] = property.value; }); return props; } static isIdentifier(name) { return /^[_a-zA-Z]\w*$/.test(name); } static quote(name) { return ModelToCypher.isIdentifier(name) ? name : "`" + name + "`"; } static render(props) { var res = ""; for (var key in props) { if (res.length > 0) res += ","; if (props.hasOwnProperty(key)) { res += ModelToCypher.quote(key) + ":"; var value = props[key]; res += typeof value == "string" && value[0] != "'" && value[0] != '"' ? "'" + value + "'" : value; } } return res.length == 0 ? "" : "{" + res + "}"; } } exports.default = ModelToCypher; /***/ }), /***/ "./src/graphDiagram/model/ModelToD3.ts": /*!*********************************************!*\ !*** ./src/graphDiagram/model/ModelToD3.ts ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const __1 = __webpack_require__(/*! ../.. */ "./src/index.ts"); const DataTypes_1 = __webpack_require__(/*! ./DataTypes */ "./src/graphDiagram/model/DataTypes.ts"); class ModelToD3 { constructor() { this.dataTypes = new DataTypes_1.DataTypes(); // included to force DataTypes to be included in d.ts } static convert(model) { let graph = { nodes: [], links: [] }; model.nodeList().forEach((node) => { let nodeData = { id: node.id, group: 1, properties: node.properties.toJSON(), labels: [node.caption], position: node.position }; graph.nodes.push(nodeData); }); model.relationshipList().forEach((relationship) => { let relationshipData = { source: relationship.start.id, target: relationship.end.id, value: 1, id: relationship.id, type: relationship.relationshipType, startNode: relationship.start.id, endNode: relationship.end.id, properties: relationship.properties.toJSON(), linknum: 1 }; graph.links.push(relationshipData); }); return graph; } static parseD3(data, modelId, origin) { var model = new __1.Model(modelId); data.nodes.forEach((nodeData) => { let newNode = model.createNode(nodeData.id); if (origin) { newNode.x = origin.x; newNode.y = origin.y; } if (nodeData.position && nodeData.position.x && nodeData.position.y) { newNode.x = nodeData.position.x; newNode.y = nodeData.position.y; } newNode.caption = nodeData.labels[0]; let properties = nodeData.properties; for (let key in properties) { if (properties.hasOwnProperty(key)) { newNode.properties.set(key, properties[key]); } } }); data.links.forEach((linkData) => { let fromId = linkData.startNode; let toId = linkData.endNode; let newRelationship = model.createRelationship(model.lookupNode(fromId), model.lookupNode(toId), linkData.id); newRelationship.relationshipType = linkData.type; let properties = linkData.properties; for (let key in properties) { if (properties.hasOwnProperty(key)) { newRelationship.properties.set(key, properties[key]); } } }); return model; } } exports.default = ModelToD3; /***/ }), /***/ "./src/graphDiagram/model/Node.ts": /*!****************************************!*\ !*** ./src/graphDiagram/model/Node.ts ***! \****************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Entity_1 = __webpack_require__(/*! ./Entity */ "./src/graphDiagram/model/Entity.ts"); const Properties_1 = __webpack_require__(/*! ./Properties */ "./src/graphDiagram/model/Properties.ts"); const SimpleStyle_1 = __webpack_require__(/*! ./SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); class Node extends Entity_1.default { constructor(model) { super(model); this.position = {}; this.radius = 25; //TODO get the actual radius, i.e. from LayoutNode this._entityType = "node"; this._properties = new Properties_1.default(model.stylePrototype.nodeProperties); this._style = new SimpleStyle_1.default(model.stylePrototype.node); } set x(x) { this.position.x = Number(x); } ; get x() { return this.position.x; } set y(y) { this.position.y = Number(y); } get y() { return this.position.y; } // funky usage precludes get/set for now ex() { return this.position.x * this.model.internalScale; } // funky usage precludes get/set for now ey() { return this.position.y * this.model.internalScale; } distanceTo(node) { var dx = node.x - this.x; var dy = node.y - this.y; return Math.sqrt(dx * dx + dy * dy) * this.model.internalScale; } snap(position, field, node) { var ideal = position[field]; var closestNode; var closestDistance = Number.MAX_VALUE; for (var nodeId in this.model.nodes) { if (this.model.nodes.hasOwnProperty(nodeId)) { var candidateNode = this.model.nodes[nodeId]; if (candidateNode != node) { // console.log(`Node: snap: field: ${field}`) var distance = 0; if (field == "x") { distance = Math.abs(candidateNode.x - ideal); } else if (field == "y") { distance = Math.abs(candidateNode.y - ideal); } // var distance = Math.abs(candidateNode[field]() - ideal); //TODO find a better way to reference accessors of Node if (distance < closestDistance) { closestNode = candidateNode; closestDistance = distance; } } } } if (closestDistance < this.model.parameters.snapTolerance) { if (field == "x") { return closestNode.x; } else if (field == "y") { return closestNode.y; } } else { if (field == "x") { return position.x; } else if (field == "y") { return position.y; } } } drag(dx, dy) { if (!this.prototypePosition) { this.prototypePosition = { x: this.position.x, y: this.position.y }; } this.prototypePosition.x += dx / this.model.internalScale; this.prototypePosition.y += dy / this.model.internalScale; this.position.x = this.snap(this.prototypePosition, "x", this); //TODO this.position.y = this.snap(this.prototypePosition, "y", this); //TODO // console.log(this.position, this.prototypePosition, this.model.internalScale); } dragEnd() { this.prototypePosition = undefined; // console.log(this.position, this.prototypePosition); } // distance() { // var dx = this.node.x - this.x; // var dy = this.node.y - this.y; // return Math.sqrt(dx * dx + dy * dy) * this.model.internalScale; // }; angleTo(node) { var dx = node.x - this.x; var dy = node.y - this.y; return Math.atan2(dy, dx) * 180 / Math.PI; } ; isLeftOf(node) { return this.x < node.x; } ; } exports.default = Node; /***/ }), /***/ "./src/graphDiagram/model/Properties.ts": /*!**********************************************!*\ !*** ./src/graphDiagram/model/Properties.ts ***! \**********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); const SimpleStyle_1 = __webpack_require__(/*! ./SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); class Properties { constructor(stylePrototype) { this._propertiesMap = new Map(); this._style = new SimpleStyle_1.default(stylePrototype); } style(cssPropertyKey, cssPropertyValue) { return this._style.style(cssPropertyKey, cssPropertyValue); } list(options) { let exclude; if (options) { exclude = options.exclude; } let result = []; this._propertiesMap.forEach((value, key) => { if (!exclude || exclude.indexOf(key) == -1) { result.push({ key: key, value: value }); } }); return result; } ; listEditable() { return this.list({ exclude: [GraphDiagram_1.default.MODEL_ID_KEY] }); } toJSON() { let properties = {}; this.list().forEach((propertyObj) => { properties[propertyObj.key] = propertyObj.value; }); return properties; } toString() { return JSON.stringify(this.list()); } set(key, value) { // if (!this.values[key]) { // this.keys.push(key); // } // this.values[key] = value; this._propertiesMap.set(key, value); return this; } ; has(property) { return this._propertiesMap.get(property); } clearAll() { // this.keys = []; // this.values = {}; this._propertiesMap = new Map(); } ; } exports.default = Properties; ; /***/ }), /***/ "./src/graphDiagram/model/Relationship.ts": /*!************************************************!*\ !*** ./src/graphDiagram/model/Relationship.ts ***! \************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const Entity_1 = __webpack_require__(/*! ./Entity */ "./src/graphDiagram/model/Entity.ts"); const Properties_1 = __webpack_require__(/*! ./Properties */ "./src/graphDiagram/model/Properties.ts"); const SimpleStyle_1 = __webpack_require__(/*! ./SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); class Relationship extends Entity_1.default { constructor(model, start, end) { super(model); this._entityType = "relationship"; this.start = start; this.end = end; this._properties = new Properties_1.default(model.stylePrototype.relationshipProperties); this._style = new SimpleStyle_1.default(model.stylePrototype.relationship); } set relationshipType(relationshipTypeText) { this._relationshipType = relationshipTypeText; } get relationshipType() { return this._relationshipType; } reverse() { var oldStart = this.start; this.start = this.end; this.end = oldStart; } } exports.default = Relationship; /***/ }), /***/ "./src/graphDiagram/model/SimpleStyle.ts": /*!***********************************************!*\ !*** ./src/graphDiagram/model/SimpleStyle.ts ***! \***********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); class SimpleStyle { constructor(stylePrototype) { this._styles = {}; if (stylePrototype && (stylePrototype instanceof SimpleStyle)) { let styleMap = stylePrototype.style(); // console.log(`styleMap:`, styleMap); for (let key in styleMap) { if (styleMap.hasOwnProperty(key)) { this._styles[key] = styleMap[key]; } } } else { let styleMap = stylePrototype; // console.log(`styleMap:`, styleMap); for (let key in styleMap) { this._styles[key] = styleMap[key]; } } } style(cssPropertyKey, cssPropertyValue) { // console.log(`SimpleStyle: style: ${cssPropertyKey}, ${cssPropertyValue}`, arguments, this); if (cssPropertyKey && cssPropertyValue) { this._styles[cssPropertyKey] = cssPropertyValue; return this; } else if (cssPropertyKey) { return this._styles[cssPropertyKey]; } else { return this._styles; } } static copyStyle(entity, computedStyle, cssPropertyKey, backupCssPropertyKey, debug = false) { var propertyValue = computedStyle.getPropertyValue(cssPropertyKey); if (!propertyValue) { propertyValue = computedStyle.getPropertyValue(backupCssPropertyKey); } if (debug) { console.log(` ${cssPropertyKey}: ${propertyValue}`); } entity.style(cssPropertyKey, propertyValue); } static copyStyles(entity, markup, debug = false) { var computedStyle = window.getComputedStyle(markup.node()); if (debug) { console.log(`copyStyles from: `, markup.node()); } SimpleStyle.copyStyle(entity, computedStyle, "width", "width", debug); SimpleStyle.copyStyle(entity, computedStyle, "min-width", "min-width", debug); SimpleStyle.copyStyle(entity, computedStyle, "font-family", "font-family", debug); SimpleStyle.copyStyle(entity, computedStyle, "font-size", "font-size", debug); SimpleStyle.copyStyle(entity, computedStyle, "margin", "margin-top", debug); SimpleStyle.copyStyle(entity, computedStyle, "padding", "padding-top", debug); SimpleStyle.copyStyle(entity, computedStyle, "color", "color", debug); SimpleStyle.copyStyle(entity, computedStyle, "background-color", "background-color", debug); SimpleStyle.copyStyle(entity, computedStyle, "border-width", "border-top-width", debug); SimpleStyle.copyStyle(entity, computedStyle, "border-style", "border-top-style", debug); SimpleStyle.copyStyle(entity, computedStyle, "border-color", "border-top-color", debug); } } exports.default = SimpleStyle; // export default class SimpleStyle { // private _style: any; // // constructor(stylePrototype?: any) { // this._style = this.styleSet(stylePrototype); // } // // get style(): any { // return this._style; // } // // styleSet(stylePrototype?: any) { // var styles = {}; // // if (stylePrototype) { // var styleMap = stylePrototype.style(); // for (var key in styleMap) { // if (styleMap.hasOwnProperty(key)) { // styles[key] = styleMap[key]; // } // } // } // // return function(cssPropertyKey: string, cssPropertyValue: string) { // if (arguments.length == 2) { // styles[cssPropertyKey] = cssPropertyValue; // return this; // } // if (arguments.length == 1) { // return styles[cssPropertyKey]; // } // return styles; // } // } // } /***/ }), /***/ "./src/graphDiagram/scaling/Scaling.ts": /*!*********************************************!*\ !*** ./src/graphDiagram/scaling/Scaling.ts ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ../GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); // export type ViewDimensions = { // width: number; // height: number; // } class Scaling { static nodeBox(node) { var margin = node.radius.outside(); let graphNode = node.model; return { x1: graphNode.ex() - margin, y1: graphNode.ey() - margin, x2: graphNode.ex() + margin, y2: graphNode.ey() + margin }; } ; static boxNormalise(box) { return { x1: box.width > 0 ? box.x : box.x + box.width, y1: box.height > 0 ? box.y : box.y + box.height, x2: box.width < 0 ? box.x : box.x + box.width, y2: box.height < 0 ? box.y : box.y + box.height }; } ; static boxUnion(boxes) { if (boxes.length < 1) { return { x1: 0, y1: 0, x2: 0, y2: 0 }; } return boxes.reduce(function (previous, current) { return { x1: Math.min(previous.x1, current.x1), y1: Math.min(previous.y1, current.y1), x2: Math.max(previous.x2, current.x2), y2: Math.max(previous.y2, current.y2) }; }); } ; static smallestContainingBox(layoutModel) { function boundingBox(entity) { return entity.propertiesBubble.boundingBox; } var bounds = Scaling.boxUnion(layoutModel.nodes.map(Scaling.nodeBox) .concat(layoutModel.nodes.filter(GraphDiagram_1.default.hasProperties).map(boundingBox) .map(Scaling.boxNormalise)) .concat(layoutModel.relationships.filter(GraphDiagram_1.default.hasProperties).map(boundingBox) .map(Scaling.boxNormalise))); return { x: bounds.x1, y: bounds.y1, width: (bounds.x2 - bounds.x1), height: (bounds.y2 - bounds.y1) }; } static centeredOrScaledViewBox(viewDimensions, diagramExtent) { var xScale = diagramExtent.width / viewDimensions.width; var yScale = diagramExtent.height / viewDimensions.height; var scaleFactor = xScale < 1 && yScale < 1 ? 1 : (xScale > yScale ? xScale : yScale); return { x: ((diagramExtent.width - viewDimensions.width * scaleFactor) / 2) + diagramExtent.x, y: ((diagramExtent.height - viewDimensions.height * scaleFactor) / 2) + diagramExtent.y, width: viewDimensions.width * scaleFactor, height: viewDimensions.height * scaleFactor }; } ; static effectiveBox(viewBox, viewSize) { if (viewBox.width / viewSize.width > viewBox.height / viewSize.height) { return { x: viewBox.x, y: viewBox.y - ((viewBox.width * viewSize.height / viewSize.width) - viewBox.height) / 2, width: viewBox.width, height: viewBox.width * viewSize.height / viewSize.width }; } else { return { x: viewBox.x - ((viewBox.height * viewSize.width / viewSize.height) - viewBox.width) / 2, y: viewBox.y, width: viewBox.height * viewSize.width / viewSize.height, height: viewBox.height }; } } static viewDimensions(view) { var svgElement = view.node(); return { x: 0, y: 0, width: svgElement.clientWidth, height: svgElement.clientHeight }; } static centerOrScaleDiagramToFitSvg(layoutModel, view) { var box = Scaling.centeredOrScaledViewBox(Scaling.viewDimensions(view), Scaling.smallestContainingBox(layoutModel)); view .attr("viewBox", [box.x, box.y, box.width, box.height].join(" ")); } ; static centerOrScaleDiagramToFitWindow(layoutModel, view) { var windowDimensions = { x: 0, y: 0, width: window.innerWidth, height: window.innerHeight }; var box = Scaling.centeredOrScaledViewBox(windowDimensions, Scaling.smallestContainingBox(layoutModel)); view .attr("width", windowDimensions.width) .attr("height", windowDimensions.height) .attr("viewBox", [box.x, box.y, box.width, box.height].join(" ")); } ; static centerOrScaleDiagramToFitSvgSmooth(layoutModel, view) { var box = Scaling.centeredOrScaledViewBox(Scaling.viewDimensions(view), Scaling.smallestContainingBox(layoutModel)); view .transition() .attr("viewBox", [box.x, box.y, box.width, box.height].join(" ")); } ; static fitsInside(extent, box) { return extent.x >= box.x && extent.y >= box.y && extent.x + extent.width <= box.x + box.width && extent.y + extent.height <= box.y + box.height; } static growButDoNotShrink(layoutModel, view) { var currentViewBoxAttr = view.attr("viewBox"); if (currentViewBoxAttr === null) { // Scaling.centeredOrScaledViewBox(layoutModel, view); //FUNKY //TODO } else { var currentDimensions = currentViewBoxAttr.split(" ").map(parseFloat); var currentBox = { x: currentDimensions[0], y: currentDimensions[1], width: currentDimensions[2], height: currentDimensions[3] }; var diagramExtent = Scaling.smallestContainingBox(layoutModel); var box; if (Scaling.fitsInside(diagramExtent, Scaling.effectiveBox(currentBox, Scaling.viewDimensions(view)))) { box = currentBox; } else { var idealBox = Scaling.centeredOrScaledViewBox(Scaling.viewDimensions(view), diagramExtent); box = { x: Math.min(currentBox.x, idealBox.x), y: Math.min(currentBox.y, idealBox.y), width: Math.max(currentBox.x + currentBox.width, idealBox.x + idealBox.width) - Math.min(currentBox.x, idealBox.x), height: Math.max(currentBox.y + currentBox.height, idealBox.y + idealBox.height) - Math.min(currentBox.y, idealBox.y) }; } view .attr("viewBox", [box.x, box.y, box.width, box.height].join(" ")); } } ; static sizeSvgToFitDiagram(layoutModel, view) { var box = Scaling.smallestContainingBox(layoutModel); view .attr("viewBox", [box.x, box.y, box.width, box.height].join(" ")) .attr("width", box.width * layoutModel.graphModel.externalScale) .attr("height", box.height * layoutModel.graphModel.externalScale); } ; } exports.default = Scaling; /***/ }), /***/ "./src/index.ts": /*!**********************!*\ !*** ./src/index.ts ***! \**********************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const GraphDiagram_1 = __webpack_require__(/*! ./graphDiagram/GraphDiagram */ "./src/graphDiagram/GraphDiagram.ts"); exports.GraphDiagram = GraphDiagram_1.default; const Diagram_1 = __webpack_require__(/*! ./graphDiagram/diagram/Diagram */ "./src/graphDiagram/diagram/Diagram.ts"); exports.Diagram = Diagram_1.default; const Markup_1 = __webpack_require__(/*! ./graphDiagram/markup/Markup */ "./src/graphDiagram/markup/Markup.ts"); exports.Markup = Markup_1.default; const Model_1 = __webpack_require__(/*! ./graphDiagram/model/Model */ "./src/graphDiagram/model/Model.ts"); exports.Model = Model_1.default; const ModelToCypher_1 = __webpack_require__(/*! ./graphDiagram/model/ModelToCypher */ "./src/graphDiagram/model/ModelToCypher.ts"); exports.ModelToCypher = ModelToCypher_1.default; const ModelToD3_1 = __webpack_require__(/*! ./graphDiagram/model/ModelToD3 */ "./src/graphDiagram/model/ModelToD3.ts"); exports.ModelToD3 = ModelToD3_1.default; const Node_1 = __webpack_require__(/*! ./graphDiagram/model/Node */ "./src/graphDiagram/model/Node.ts"); exports.Node = Node_1.default; const SimpleStyle_1 = __webpack_require__(/*! ./graphDiagram/model/SimpleStyle */ "./src/graphDiagram/model/SimpleStyle.ts"); exports.SimpleStyle = SimpleStyle_1.default; const CurvedArrowOutline_1 = __webpack_require__(/*! ./graphDiagram/arrow/CurvedArrowOutline */ "./src/graphDiagram/arrow/CurvedArrowOutline.ts"); exports.CurvedArrowOutline = CurvedArrowOutline_1.default; const Relationship_1 = __webpack_require__(/*! ./graphDiagram/model/Relationship */ "./src/graphDiagram/model/Relationship.ts"); exports.Relationship = Relationship_1.default; const Scaling_1 = __webpack_require__(/*! ./graphDiagram/scaling/Scaling */ "./src/graphDiagram/scaling/Scaling.ts"); exports.Scaling = Scaling_1.default; const Layout_1 = __webpack_require__(/*! ./graphDiagram/layout/Layout */ "./src/graphDiagram/layout/Layout.ts"); exports.Layout = Layout_1.default; const LayoutModel_1 = __webpack_require__(/*! ./graphDiagram/layout/LayoutModel */ "./src/graphDiagram/layout/LayoutModel.ts"); exports.LayoutModel = LayoutModel_1.default; const LayoutNode_1 = __webpack_require__(/*! ./graphDiagram/layout/LayoutNode */ "./src/graphDiagram/layout/LayoutNode.ts"); exports.LayoutNode = LayoutNode_1.default; const LayoutRelationship_1 = __webpack_require__(/*! ./graphDiagram/layout/LayoutRelationship */ "./src/graphDiagram/layout/LayoutRelationship.ts"); exports.LayoutRelationship = LayoutRelationship_1.default; const DataTypes_1 = __webpack_require__(/*! ./graphDiagram/model/DataTypes */ "./src/graphDiagram/model/DataTypes.ts"); exports.DataTypes = DataTypes_1.DataTypes; /***/ }), /***/ "d3": /*!*********************!*\ !*** external "d3" ***! \*********************/ /*! no static exports found */ /***/ (function(module, exports) { module.exports = __WEBPACK_EXTERNAL_MODULE_d3__; /***/ }) /******/ }); }); //# sourceMappingURL=index.js.map