From ed48e3bcd89009f83f73d06418eef2f75de55170 Mon Sep 17 00:00:00 2001 From: Albert Zuendorf Date: Tue, 27 Feb 2018 16:11:16 +0100 Subject: [PATCH] minor --- Editor.html | 1 + diagramstyle.css | 332 ++ drawer.js | 1018 ++++++ graph.js | 2775 +++++++++++++++++ .../org/sdmlib/replication/startjava.bat | 5 + .../org/sdmlib/replication/startjava.sh | 9 + .../resources/org/sdmlib/sdmlib.png | Bin 0 -> 782 bytes 7 files changed, 4140 insertions(+) create mode 100644 Editor.html create mode 100644 diagramstyle.css create mode 100644 drawer.js create mode 100644 graph.js create mode 100644 out/production/resources/org/sdmlib/replication/startjava.bat create mode 100644 out/production/resources/org/sdmlib/replication/startjava.sh create mode 100644 out/production/resources/org/sdmlib/sdmlib.png diff --git a/Editor.html b/Editor.html new file mode 100644 index 000000000..fa62f54ff --- /dev/null +++ b/Editor.html @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/diagramstyle.css b/diagramstyle.css new file mode 100644 index 000000000..79be0354e --- /dev/null +++ b/diagramstyle.css @@ -0,0 +1,332 @@ +@charset 'UTF-8'; +.Board{ + position: relative; + overflow: hidden; + width: 800px; height: 800px; + border: 1px solid rgb(204, 204, 204); +} +.ClassEditor{ + width: 100%; + height: 100%; + min-height: 100%; + min-width: 100%; + border: 1px solid black; + vertical-align: middle; + text-align:center; +} +.Error{ + border-color: #f00; + color: #f00; + box-shadow: inset 0 3px 4px #888; +} +.Ok{ + border-color: #009B00; + box-shadow: inset 0 3px 4px #888; +} +.Add{ + border-color: yellow; + box-shadow: inset 0 3px 4px #888; +} +.code_box { + position: absolute; + width:400px; + height:300px; + border: 1px solid #c2e1f5; + right:8px; + bottom: 56px; + text-align: left; +} +.code_box:before { + top: 100%; + right:0px; + border: solid transparent; + content: " "; + position: absolute; + border-top-color: #c2e1f5; + border-width: 20px; +} +.Toolbar { + background : #F4F4F4; + background-image: linear-gradient(#696969 1px, rgba(255,255,255,0) 0%); + background-position: 3px 2px; + background-size: 1px 5px; + background-repeat: repeat-y; + border-bottom: 1px solid #696969; + border-right: 1px solid #999999; + position:fixed; + bottom:6px; +} +.Itembar { + background : #F4F4F4; + background-image: linear-gradient(#696969 1px, rgba(255,255,255,0) 0%); + background-position: 3px 2px; + background-size: 1px 5px; + background-repeat: repeat-y; + border-bottom: 1px solid #696969; + border-right: 1px solid #999999; + position:fixed; + right:6px; + top:30px; +} +.CodeView { + background : #F4F4F4; + position:fixed; + bottom:9px; + right:7px; + width:30px; + height:30px; +} +.pi { + padding-top:5px; + cursor:hand; +} +.ChoiceBox{ + position:absolute; + height:80px; + border:1px solid black; + overflow-y: scroll; + overflow-x: hidden; +} +.ChoiceBox div{ + height:20px; + width:100%; + cursor:pointer; +} +.ChoiceBox div.alt{ + background:#F5F5F5; +} +.ChoiceBox div:hover{ + background:#8EB8FD; +} + +.classdiagram{ + border: 1px solid rgb(187, 187, 187); + position: absolute; +} +.objectdiagram{ + border: 1px solid rgb(187, 187, 187); + position: absolute; +} + +.classElement{ + border: 1px solid rgb(187, 187, 187); + /*background-color: rgb(221, 221, 221);*/ + position: absolute; + background:#ffffff; +} +.classElement table{ + border-spacing:0; + cursor: hand; +} + +.classElement th{ + background-image: linear-gradient(left, white 0%, lightgray 50%); + background-image: linear-gradient(top, white 0%, lightgray 50%); + background-image: linear-gradient(45deg, white 0%, lightgray 50%); + height:20px; +} + +.classElement .first{ + border-top: 1px solid black; +} +.classElement .methods{ + margin-left:10px; + padding-left:10px; + padding-right:10px; + text-align:left; + vertical-align:top; +} +.classElement .attributes{ + margin-left:10px; + padding-left:10px; + padding-right:10px; + text-align:left; + vertical-align:top; +} + +.objectElement{ + border: 1px solid rgb(187, 187, 187); + /*background-color: rgb(221, 221, 221);*/ + position: absolute; + background:#ffffff; +} +.objectElement table{ + border-spacing:0; + cursor: hand; +} +.objectElement th{ + background-image: linear-gradient(left, white 0%, lightgray 50%); + background-image: linear-gradient(top, white 0%, lightgray 50%); + background-image: linear-gradient(45deg, white 0%, lightgray 50%); +} +.objectElement .first{ + border-top: 1px solid black; +} + +.ToolButton{ + background: #eeeeee; /* Old browsers */ + background: -moz-linear-gradient(top, #eeeeee 0%, #aaaaaa 50%, #e5e5e5 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#eeeeee), color-stop(50%,#aaaaaa), color-stop(100%,#e5e5e5)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, #eeeeee 0%,#aaaaaa 50%,#e5e5e5 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, #eeeeee 0%,#aaaaaa 50%,#e5e5e5 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, #eeeeee 0%,#aaaaaa 50%,#e5e5e5 100%); /* IE10+ */ + background: linear-gradient(to bottom, #eeeeee 0%,#aaaaaa 50%,#e5e5e5 100%); /* W3C */ + border-radius: 20px; + -webkit-box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.75); + -moz-box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.75); + box-shadow: 2px 2px 5px 0 rgba(0,0,0,0.75); + cursor:pointer; +} + +.EdgeInfo{ + position: absolute; +} + +.patternElement{ + border: 1px solid rgb(187, 187, 187); + /*background-color: rgb(221, 221, 221);*/ + position: absolute; + background:lightblue; +} +.patternElement table{ + border-spacing:0; + + cursor: hand; +} +.patternElement .head{ + text-align:center; +} +.patternElement th{ + padding-left:10px; + padding-right:10px; +} +.patternElement .first{ + border-top: 1px solid black; +} +.lineElement { + z-index : 42; + border-bottom: 1px solid black; +} +.lineRaster{ + border-right: 1px dotted rgba(0,0,0,0.3); + border-bottom: 1px dotted rgba(0,0,0,0.3); + width: 1px; + height: 1px; + position:absolute; +} + +.infoBox{ + border: 1px solid rgb(187, 187, 187); + position: absolute; +} +.draggable { + cursor: move; +} +.selection{ + cursor: hand; + opacity:0; +} +.selection:hover{ + cursor: hand; + opacity:0.3; + fill: #FF9; +} +.saveBtn:hover{ + opacity:0.75; + cursor: hand; +} +.btn:hover{ + opacity:0.75; + cursor: pointer; +} + +.hand{ + cursor: pointer; +} +.saveBtn{ + fill:url(#reflect); + filter: drop-shadow(5px 5px 2px black); +} + +.draggable{ +} + +.draggable:hover{ + border:1px dashed black; + -moz-border-radius: 8px;-webkit-border-radius: 8px;border-radius: 8px; + cursor: move; + opacity:0.50; + fill:#ddd; +} +.hljs-line-numbers { + text-align: right; + border-right: 1px solid #ccc; + color: #999; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} +code[data-lang]:before{display:none;content:attr(data-lang);font-size:.75em;line-height:1;text-transform:uppercase;color:#999; + position:relative;float:right; +} +code:hover[data-lang]:before{display:block} +pre .title {text-align:center} + +.conum[data-value]:after {content: attr(data-value);} +.conum[data-value] { + display: inline-block; + color: #fff!important; + background-color: rgba(0,0,0,.8); + -webkit-border-radius: 100px; + border-radius: 100px; + text-align: center; + font-size: 8px; + width: 10px; + height: 10px; + line-height: 10px; + font-family: "Open Sans","DejaVu Sans",sans-serif; + font-style: normal; + font-weight: bold; +} +.symbol { + font-size: 0.9em; + font-family: Times New Roman; + border-radius: 1em; + padding-left: .6em; + padding-right: .6em; + font-weight: bolder; + float:left; + color: white; + background-color: #4E5A56; + -webkit-margin-after:0; + -webkit-margin-before:0; +} + +.icon-info { background-color: #3229CF; } +.icon-error { background: #e64943; font-family: Consolas; } +.icon-tick { background: #13c823; } +.icon-excl { background: #ffd54b; color: black; } + +.icon-info:before { content: 'i'; } +.icon-error:before { content: 'x'; } +.icon-tick:before { content: '\002713'; } +.notify { + display:flex; + background-color:#e3f7fc; + color:#555; + border:.1em solid; + border-color: #8ed9f6; + border-radius:10px; + font-size:1.1em; + padding:10px 10px 10px 10px; + margin:10px; + float:none; + cursor: default; +} +.notify-text { margin-left:10px;white-space:nowrap;} +.notify-yellow { background: #fff8c4; border-color: #f7deae; } +.notify-red { background: #ffecec; border-color: #fad9d7; } +.notify-green { background: #e9ffd9; border-color: #D1FAB6; } \ No newline at end of file diff --git a/drawer.js b/drawer.js new file mode 100644 index 000000000..0b8eb26ac --- /dev/null +++ b/drawer.js @@ -0,0 +1,1018 @@ +/* + NetworkParser + Copyright (c) 2011 - 2015, Stefan Lindel + All rights reserved. + + Licensed under the EUPL, Version 1.1 or (as soon they + will be approved by the European Commission) subsequent + versions of the EUPL (the "Licence"); + You may not use this work except in compliance with the Licence. + You may obtain a copy of the Licence at: + + http://ec.europa.eu/idabc/eupl5 + + Unless required by applicable law or agreed to in + writing, software distributed under the Licence is + distributed on an "AS IS" basis, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. + See the Licence for the specific language governing + permissions and limitations under the Licence. +*/ + +/*jslint node: true, newcap:true, nomen: true, continue: true */ + +// VERSION: 2015.09.15 10:40 +/*global GraphUtil: false, SymbolLibary: false, svgConverter: false, jsPDF: false, document:false */ +"use strict"; +var ObjectCreate = Object.create || function (o) {var F = function () {}; F.prototype = o; return new F(); }; + +var Drawer = function (typ) {this.util = new GraphUtil(typ); this.symbolLib = new SymbolLibary(); }; +Drawer.prototype.clearBoard = function () {}; +Drawer.prototype.setPos = function (item, x, y) {item.x = x; item.y = y; }; +Drawer.prototype.setSize = function (item, x, y) {item.width = x; item.height = y; }; +Drawer.prototype.getColor = function (style, defaultColor) { + if (style) { + if (style.toLowerCase() === "create") { + return "#008000"; + } + if (style.toLowerCase() === "destroy") { + return "#a00000"; + } + if (style.toLowerCase() === "nac") { + return "#FE3E3E"; + } + if (style.indexOf("#") === 0) { + return style; + } + } + if (defaultColor) { + return defaultColor; + } + return "#000"; +}; +Drawer.prototype.removeToolItems = function (board) { + var i; + for (i = 0; i < this.toolitems.length; i += 1) { + this.toolitems[i].close(); + if (this.toolitems[i].showed) { + board.removeChild(this.toolitems[i]); + this.toolitems[i].showed = false; + } + } +}; +Drawer.prototype.createImage = function (node) { + var n, img; + node.model = node; + if (this.symbolLib.isSymbol(node)) { + return this.symbolLib.draw(null, node); + } + n = {tag: "img", model: node, src: node.src}; + if (node.width || node.height) { + n.width = node.width; + n.height = node.height; + } else { + n.xmlns = "http://www.w3.org/1999/xhtml"; + } + img = this.util.create(n); + if (!node.width && !node.height) { + this.model.appendImage(img); + return null; + } + return img; +}; +Drawer.prototype.showToolItems = function (board) { + var i; + for (i = 0; i < this.toolitems.length; i += 1) { + board.appendChild(this.toolitems[i]); + this.toolitems[i].showed = true; + } +}; +Drawer.prototype.isInTool = function (x, y, ox, oy) { + var i, g, gx, gy, gw, gh; + // Mode x,y + x -= ox; + y -= oy; + for (i = 0; i < this.toolitems.length; i += 1) { + g = this.toolitems[i]; + if (!g.offsetWidth && g.tool) { + gx = g.tool.x; + gy = g.tool.y; + gw = g.tool.width + gx; + gh = g.tool.height + gy; + } else { + gx = g.offsetLeft; + gy = g.offsetTop; + gw = g.offsetWidth + gx; + gh = g.offsetHeight + gy; + } + if (x >= gx && x <= gw && y >= gy && y <= gh) { + return true; + } + } + return false; +}; +Drawer.prototype.createBoard = function (node, graph, listener) { + var i, that = this, board; + this.model = graph; + this.toolitems = []; + if (listener) { + for (i = 0; i < listener.length; i += 1) { + this.toolitems.push(listener[i]); + } + } + board = this.util.create(node); + node.model = graph; + board.setAttribute('class', "Board"); + board.rasterElements = []; + board.saveShow = false; + board.onmouseover = function () { + that.showToolItems(board); + }; + board.onmouseout = function (event) { + var left = board.offsetLeft, top = board.offsetTop, x = Math.floor(event.pageX), y = Math.floor(event.pageY); + if (!left) { + if (board.parentNode) { + left = board.parentNode.offsetLeft; + } else { + left = 0; + } + } + if (!top) { + if (board.parentNode) { + top = board.parentNode.offsetTop; + } else { + top = 0; + } + } + if (!that.isInTool(x, y, left, top)) { + that.removeToolItems(board); + } + }; + return board; +}; +Drawer.prototype.getButtons = function (graph, notTyp) { + var i, buttons = [], btn, func, that = this, item, typ, node; + if (graph && graph.model.options) { + item = graph.model.options.buttons; + func = function (e) { + var t = e.currentTarget.type; + that.model.initDrawer(t); + that.model.layout(); + }; + for (i = 0; i < item.length; i += 1) { + typ = item[i]; + if (typ !== notTyp) { + node = {type: "Button", value: typ, y: 8, x: 2, height: 28, width: 60}; + btn = this.symbolLib.draw(this, node); + btn.style.verticalAlign = "top"; + this.util.bind(btn, "mousedown", func); + btn.type = typ; + buttons.push(btn); + } + } + } + if (notTyp === "HTML" && !graph.noButtons && graph.model.id) { + func = function (e) { + var t = e.currentTarget.value; + if (t === "Save") { + that.model.SavePosition(); + } else if (t === "Load") { + that.model.LoadPosition(); + } + }; + + btn = {type: "Dropdown", x: 2, y: 8, width: 120, elements: ["Save", "Load"], activText: "Localstorage", action: func}; + item = this.symbolLib.draw(this, btn); + buttons.push(item); + } + return buttons; +}; +// ###################################################### HTMLDrawer #################################################################################### +Drawer.HTMLDrawer = function () { Drawer.call(this); }; +Drawer.HTMLDrawer.prototype = ObjectCreate(Drawer.prototype); +Drawer.HTMLDrawer.prototype.setPos = function (item, x, y) {item.style.left = x + "px"; item.style.top = y + "px"; }; +Drawer.HTMLDrawer.prototype.setSize = function (item, x, y) {item.style.width = x + "px"; item.style.height = y + "px"; }; +Drawer.HTMLDrawer.prototype.getSize = function (item) {return {x: item.clientWidth, y: item.clientHeight}; }; +Drawer.HTMLDrawer.prototype.getBoard = function (graph) { + return this.createBoard({tag: "div"}, graph, this.getButtons(graph, "HTML")); +}; +Drawer.HTMLDrawer.prototype.createCell = function (parent, tag, node, innerHTML, typ) { + var tr = this.util.create({"tag": 'tr'}), cell; + cell = this.util.create({"tag": tag, $font: true, value: innerHTML}); + this.model.createElement(cell, typ, node); + tr.appendChild(cell); + parent.appendChild(tr); + return cell; +}; +Drawer.HTMLDrawer.prototype.getNode = function (node, draw) { + var first, z, cell, item, model, htmlElement = this.util.create({tag: "div", model: node}); + model = this.model.model; + if (node.type === "patternobject") { + htmlElement.className = "patternElement"; + } else if (this.symbolLib.isSymbol(node)) { + return this.symbolLib.draw(null, node); + } + if (node.type === "classdiagram") { + htmlElement.className = "classdiagram"; + } else if (node.type === "objectdiagram") { + htmlElement.className = "objectdiagram"; + } else if (model.type.toLowerCase() === "objectdiagram") { + htmlElement.className = "objectElement"; + } else { + htmlElement.className = "classElement"; + } + this.setPos(htmlElement, node.x, node.y); + htmlElement.style.zIndex = 5000; + + if (node.type === "objectdiagram" || node.type === "classdiagram") { + node.left = node.top = 30; + node.$gui = htmlElement; + if (draw) { + this.model.draw(node); + htmlElement.style.borderColor = "red"; + if (node.style && node.style.toLowerCase() === "nac") { + htmlElement.appendChild(this.symbolLib.draw(null, {type: "stop", x: 0, y: 0})); + } + } else { + this.model.layout(0, 0, node); + } + this.setSize(htmlElement, node.$gui.style.width, node.$gui.style.height); + return htmlElement; + } + this.model.createElement(htmlElement, "class", node); + if (node.content) { + node.content.width = node.content.width || 0; + node.content.height = node.content.height || 0; + if (node.content.src) { + item = this.createImage(node.content); + if (!item) {return null; } + htmlElement.appendChild(item); + return htmlElement; + } + if (node.content.html) { + htmlElement.innerHTML = node.content.html; + return htmlElement; + } + } + item = this.util.create({tag: 'table', border: "0"}); + item.style.width = "100%"; + item.style.height = "100%"; + htmlElement.appendChild(item); + if (node.head$src) { + cell = this.createCell(item, "td", node); + cell.style.textAlign = "center"; + if (!node.head$img) { + node.head$img = {}; + node.head$img.src = node.head$src; + node.head$img.width = node.head$width; + node.head$img.height = node.head$height; + } + z = this.createImage(node.head$img); + if (z) { + cell.appendChild(z); + } + } + if (node.headinfo) { + this.createCell(item, "td", node, node.headinfo).className = "head"; + } + + if (model.type.toLowerCase() === "objectdiagram") { + z = node.id.charAt(0).toLowerCase() + node.id.slice(1); + } else { + z = node.id; + } + if (node.href) { + z = "" + z + ""; + } + cell = this.createCell(item, "th", node, z, "id"); + if (model.type.toLowerCase() === "objectdiagram") { + cell.style.textDecorationLine = "underline"; + } + cell = null; + if (node.attributes) { + first = true; + for (z = 0; z < node.attributes.length; z += 1) { + var color=""; + var attr = node.attributes[z]; + if(attr.indexOf("[")>=0){ + color = " " + attr.substring(attr.indexOf("[")+1, attr.indexOf("]")); + attr = attr.substring(0, attr.indexOf("["))+attr.substring(attr.indexOf("]")+1); + } + cell = this.createCell(item, "td", node, attr, "attribute"); + if (!first) { + cell.className = 'attributes'+color; + } else { + cell.className = 'attributes first'+color; + first = false; + } + } + } + if (node.methods) { + first = true; + for (z = 0; z < node.methods.length; z += 1) { + cell = this.createCell(item, "td", node, node.methods[z], "method"); + if (!first) { + cell.className = 'methods'; + } else { + cell.className = 'methods first'; + first = false; + } + } + } + if (!cell) { + cell = this.createCell(item, "td", node, " "); + cell.className = 'first'; + this.model.createElement(cell, "empty", node); + } + htmlElement.appendChild(item); + htmlElement.node = node; + node.$gui = htmlElement; + return htmlElement; +}; +Drawer.HTMLDrawer.prototype.getInfo = function (item, text, angle, style) { + var info = this.util.create({tag: "div", $font: true, model: item, "class": "EdgeInfo", value: text, style: "color:" + this.getColor(style, "#CCC")}); + + if (angle !== 0) { + info.style.transform = "rotate(" + angle + "deg)"; + info.style.msTransform = info.style.MozTransform = info.style.WebkitTransform = info.style.OTransform = "rotate(" + angle + "deg)"; + } + this.setPos(info, item.x, item.y); + this.model.createElement(info, "info", item); + return info; +}; +Drawer.HTMLDrawer.prototype.getLine = function (x1, y1, x2, y2, lineStyle) { + var temp, angle, length, line; + if (x2 < x1) { + temp = x1; + x1 = x2; + x2 = temp; + temp = y1; + y1 = y2; + y2 = temp; + } + // Formula for the distance between two points + // http://www.mathopenref.com/coorddist.html + length = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)); + + line = this.util.create({tag: "div", "class": "lineElement", style: {width: length + "px", position: "absolute", zIndex: 42}}); + line.style.borderBottomStyle = lineStyle; + + angle = Math.atan((y1 - y2) / (x1 - x2)); + if (x1 === x2) { + angle = Math.atan((y1 - y2) / (x1 - x2)) * -1; + } + line.style.top = y1 + 0.5 * length * Math.sin(angle) + "px"; + line.style.left = x1 - 0.5 * length * (1 - Math.cos(angle)) + "px"; + line.style.transform = "rotate(" + angle + "rad)"; + line.style.msTransform = line.style.MozTransform = line.style.WebkitTransform = line.style.OTransform = "rotate(" + angle + "rad)"; + return line; +}; +Drawer.HTMLDrawer.prototype.createPath = function (close, fill, path, angle) { + var line, i; + if (fill === "none") { + line = this.util.create({tag: "div"}); + for (i = 1; i < path.length; i += 1) { + line.appendChild(this.getLine(path[i - 1].x, path[i - 1].y, path[i].x, path[i].y)); + } + if (close) { + line.appendChild(this.getLine(path[path.length - 1].x, path[path.length - 1].y, path[0].x, path[0].y)); + } + return line; + } + line = this.util.create({tag: "div", style: {position: "absolute", left: path[0].x - 8, top: path[0].y, transform: "rotate(" + angle + "rad)"}}); + line.appendChild(this.util.create({tag: "div", style: {background: "#000", width: 8, height: 8, transform: "rotate(45rad) skew(170deg, 170deg)"}})); + return line; +}; +// ###################################################### SVG #################################################################################### +Drawer.SVGDrawer = function () {Drawer.call(this, "http://www.w3.org/2000/svg"); this.showButton = true; }; +Drawer.SVGDrawer.prototype = ObjectCreate(Drawer.prototype); +Drawer.SVGDrawer.prototype.getWidth = function (label) { + var board, width, text = this.util.create({tag: "text", $font: true, value: label}); + text.setAttribute("width", "5px"); + board = this.model.board; + board.appendChild(text); + width = text.getBoundingClientRect().width; + board.removeChild(text); + return width; +}; +Drawer.SVGDrawer.prototype.drawDef = function () { + var child, def = this.util.create({tag: "defs"}); + + child = this.util.create({tag: "filter", id: "drop-shadow"}); + child.appendChild(this.util.create({tag: "feGaussianBlur", "in": "SourceAlpha", result: "blur-out", stdDeviation: 2})); + child.appendChild(this.util.create({tag: "feOffset", "in": "blur-out", dx: 2, dy: 2})); + child.appendChild(this.util.create({tag: "feBlend", "in": "SourceGraphic", mode: "normal"})); + def.appendChild(child); + child = this.util.create({tag: "linearGradient", id: "reflect", x1: "0%", x2: "0%", y1: "50%", y2: "0%", spreadMethod: "reflect"}); + child.appendChild(this.util.create({tag: "stop", "stop-color": "#aaa", offset: "0%"})); + child.appendChild(this.util.create({tag: "stop", "stop-color": "#eee", offset: "100%"})); + def.appendChild(child); + + child = this.util.create({tag: "linearGradient", id: "classelement", x1: "0%", x2: "100%", y1: "100%", y2: "0%"}); + child.appendChild(this.util.create({tag: "stop", "stop-color": "#ffffff", offset: "0"})); + child.appendChild(this.util.create({tag: "stop", "stop-color": "#d3d3d3", offset: "1"})); + def.appendChild(child); + return def; + +}; +Drawer.SVGDrawer.prototype.getBoard = function (graph) { + var hasJS, buttons, board, node, list, that = this; + list = ["HTML", "SVG", "PNG"]; + hasJS = typeof (svgConverter); + if (hasJS !== "undefined") { + hasJS = typeof (svgConverter); + list.push(hasJS !== "undefined" ? "EPS" : ""); + hasJS = typeof (jsPDF); + list.push(hasJS !== "undefined" ? "PDF" : ""); + } + buttons = []; + + + if (this.showButton) { + buttons = this.getButtons(graph, "SVG"); + node = {type: "Dropdown", x: 66, y: 8, minheight: 28, maxheight: 28, width: 80, elements: list, activText: "Save", action: function (e) {that.removeToolItems(that.board); that.model.SaveAs(e.currentTarget.value); }}; + buttons.push(this.symbolLib.draw(this, node)); + } + board = this.createBoard({tag: "svg", "xmlns:svg": "http://www.w3.org/2000/svg", "xmlns:xlink": "http://www.w3.org/1999/xlink"}, graph, buttons); + board.appendChild(this.drawDef()); + this.board = board; + + return board; +}; +Drawer.SVGDrawer.prototype.setSize = function (item, x, y) { + x = this.util.getValue(x); + y = this.util.getValue(y); + item.setAttribute("width", x); + item.setAttribute("height", y); + item.style.width = Math.ceil(x); + item.style.height = Math.ceil(y); +}; +Drawer.SVGDrawer.prototype.getNode = function (node, draw) { + var rect, typ, z, x, y, id, textWidth, g, item, width, height, that = this, symbolLib = new SymbolLibary(); + if (symbolLib.isSymbol(node)) { + return symbolLib.draw(this, node); + } + if (node.content) { + node.content.width = node.content.width || 0; + node.content.height = node.content.height || 0; + if (node.content.src) { + item = this.createImage(node.content); + if (!item) {return null; } + return item; + } + g = this.util.create({tag: "g", model: node}); + if (node.content.svg) { + g.setAttribute('transform', "translate(" + node.x + " " + node.y + ")"); + g.innerHTML = node.content$svg; + return g; + } + if (node.content.html) { + g.setAttribute('transform', "translate(" + node.x + " " + node.y + ")"); + g.innerHTML = node.content$svg; + return g; + } + } + g = this.util.create({tag: "g", model: node}); + if (node.type === "objectdiagram" || node.type === "classdiagram") { + if (node.status === "close") { + width = this.getWidth(node.minid || node.id) + 30; + height = 40; + this.addChild(node, g, this.util.create({tag: "text", $font: true, "text-anchor": "left", "x": (node.x + 2), "y": node.y + 12, value: node.minid || node.id })); + } else { + node.left = node.top = 30; + node.$gui = g; + if (draw) { + this.model.draw(node); + } else { + this.model.layout(0, 0, node); + } + + width = this.util.getValue(node.$gui.style.width); + height = this.util.getValue(node.$gui.style.height); + if (node.style && node.style.toLowerCase() === "nac") { + this.addChild(node, g, this.createGroup(node, symbolLib.drawStop(node))); + } + } + this.setSize(g, width, height); + this.addChild(node, g, this.util.create({tag: "rect", "width": width, "height": height, "fill": "none", "strokeWidth": "1px", "stroke": this.getColor(node.style, "#CCC"), "x": node.getX(), "y": node.getY(), "class": "draggable"})); + if (width > 0 && width !== node.width) {node.width = width; } + if (node.status === "close") { + // Open Button + item = this.createGroup(node, symbolLib.drawMax({x: (node.x + width - 20), y: node.y})); + node.height = height; + } else { + item = this.createGroup(node, symbolLib.drawMin({x: (node.x + width - 20), y: node.y})); + } + item.setAttribute("class", "hand"); + + this.util.bind(item, "mousedown", function (e) { + var name; + if (node.status === "close") { + node.status = "open"; + that.model.redrawNode(node); + } else { + node.status = "close"; + // try to cleanup + for (name in node.nodes) { + if (node.nodes.hasOwnProperty(name)) { + node.nodes[name].$gui = null; + } + } + that.model.redrawNode(node); + } + if (e.stopPropagation) {e.stopPropagation(); } + if (e.cancelBubble !== null) {e.cancelBubble = true; } + }); + g.appendChild(item); + this.model.createElement(g, "class", node); + return g; + } + + if (node.content$plain) { + return this.util.create({tag: "text", $font: true, "text-anchor": "left", "x": (node.x + 10), value: node.content$plain}); + } + + width = 0; + height = 40; + + if (this.model.model.type.toLowerCase() === "objectdiagram") { + id = node.id.charAt(0).toLowerCase() + node.id.slice(1); + } else { + id = node.id; + if (node.counter) { + id += " (" + node.counter + ")"; + } + } + textWidth = this.getWidth(id); + + width = Math.max(width, textWidth); + if (node.attributes && node.attributes.length > 0) { + height = height + node.attributes.length * 25; + for (z = 0; z < node.attributes.length; z += 1) { + width = Math.max(width, this.getWidth(node.attributes[z])); + } + } else { + height += 20; + } + if (node.methods && node.methods.length > 0) { + height = height + node.methods.length * 25; + for (z = 0; z < node.methods.length; z += 1) { + width = Math.max(width, this.getWidth(node.methods[z])); + } + } + width += 20; + + y = node.getY(); + x = node.getX(); + + this.model.createElement(g, "class", node); + rect = {tag: "rect", "width": width, "height": height, "x": x, "y": y, "fill": "#fff", "class": "draggable"}; + typ = node.type.toLowerCase(); + if (typ === "patternobject") { + rect.fill = "lightblue"; + } + + rect.stroke = this.getColor(node.style); + g.appendChild(this.util.create(rect)); + + if (typ !== "patternobject") { + g.appendChild(this.util.create({tag: "rect", rx: 0, "x": x, "y": y, "width": width, height: 30, fill: "none", style: "fill:url(#classelement);"})); + } + + item = this.util.create({tag: "text", $font: true, "text-anchor": "right", "x": x + width / 2 - textWidth / 2, "y": y + 20, "width": textWidth}); + + if (this.model.model.type.toLowerCase() === "objectdiagram") { + item.setAttribute("text-decoration", "underline"); + } + item.appendChild(document.createTextNode(id)); + + g.appendChild(item); + g.appendChild(this.util.create({tag: "line", x1: x, y1: y + 30, x2: x + width, y2: y + 30, stroke: rect.stroke})); + y += 50; + + if (node.attributes) { + for (z = 0; z < node.attributes.length; z += 1) { + g.appendChild(this.util.create({tag: "text", $font: true, "text-anchor": "left", "width": width, "x": (x + 10), "y": y, value: node.attributes[z]})); + y += 20; + } + if (node.attributes.length > 0) { + y -= 10; + } + } + if (node.methods && node.methods.length > 0) { + g.appendChild(this.util.create({tag: "line", x1: x, y1: y, x2: x + width, y2: y, stroke: "#000"})); + y += 20; + for (z = 0; z < node.methods.length; z += 1) { + g.appendChild(this.util.create({tag: "text", $font: true, "text-anchor": "left", "width": width, "x": x + 10, "y": y, value: node.methods[z]})); + y += 20; + } + } + return g; +}; +Drawer.SVGDrawer.prototype.addChild = function (node, parent, child) { + child.setAttribute("class", "draggable"); + parent.appendChild(child); + this.model.createElement(child, "class", node); +}; +Drawer.SVGDrawer.prototype.getInfo = function (item, text, angle, style) { + var child, group, i, items = text.split("\n"); + if (items.length > 1) { + group = this.util.create({tag: "g", "class": "draggable", rotate: angle, model: item}); + for (i = 0; i < items.length; i += 1) { + child = this.util.create({tag: "text", $font: true, "text-anchor": "left", "x": item.x, "y": item.y + (item.height * i), fill: this.getColor(style, "#000")}); + child.appendChild(document.createTextNode(items[i])); + group.appendChild(child); + } + this.model.createElement(group, "info", item); + return group; + } + group = this.util.create({tag: "text", "#$font": true, "text-anchor": "left", "x": item.x, "y": item.y, value: text, "id": item.id, "class": "draggable", rotate: angle, model: item, fill: this.getColor(style, "#000")}); + this.model.createElement(group, "info", item); + return group; +}; +Drawer.SVGDrawer.prototype.getLine = function (x1, y1, x2, y2, lineStyle, style) { + var line = this.util.create({tag: "line", 'x1': x1, 'y1': y1, 'x2': x2, 'y2': y2, "stroke": this.getColor(style)}); + if (lineStyle && lineStyle.toLowerCase() === "dotted") { + line.setAttribute("stroke-miterlimit", "4"); + line.setAttribute("stroke-dasharray", "1,1"); + } + return line; +}; +Drawer.SVGDrawer.prototype.createPath = function (close, fill, path, angle) { + var i, d = "M" + path[0].x + " " + path[0].y; + for (i = 1; i < path.length; i += 1) { + d = d + "L " + path[i].x + " " + path[i].y; + } + if (close) { + d = d + " Z"; + } + return this.util.create({tag: "path", "d": d, "fill": fill, stroke: "#000", "stroke-width": "1px"}); +}; +Drawer.SVGDrawer.prototype.createGroup = function (node, group, parent) { + var func, y, yr, z, box, item, transform, that = this, i, g = this.util.create({tag: "g"}), offsetX = 0, offsetY = 0; + if (parent) { + offsetX = group.x; + offsetY = group.y; + } else { + parent = g; + } + transform = "translate(" + group.x + " " + group.y + ")"; + if (group.scale) { transform += " scale(" + group.scale + ")"; } + if (group.rotate) { transform += " rotate(" + group.rotate + ")"; } + g.setAttribute('transform', transform); + g.setAttribute("height", group.height); + g.setAttribute("width", group.width); + + for (i = 0; i < group.items.length; i += 1) { + g.appendChild(this.util.create(group.items[i])); + } + if (!node.height) { + node.height = group.height; + } + if (!node.minheight) { + node.minheight = node.height; + } + if (!node.maxheight) { + node.maxheight = node.height; + } + + if (node.elements) { + for (i = 0; i < node.elements.length; i += 1) { + if (!node.elements[i] && node.elements[i].length < 1) { + node.elements.splice(i, 1); + i -= 1; + } + } + box = this.util.create({tag: "g"}); + z = node.elements.length * 25 + 6; + box.appendChild(this.util.create({tag: "rect", rx: 0, x: offsetX, y: (offsetY + 28), width: 60, height: z, stroke: "#000", fill: "#fff", opacity: "0.7"})); + node.maxheight = z + node.minheight; + + parent.elements = node.elements; + parent.activ = this.util.create({tag: "text", $font: true, "text-anchor": "left", "width": 60, "x": (10 + offsetX), "y": 20, value: node.activText}); + g.appendChild(parent.activ); + y = offsetY + 46; + yr = offsetY + 28; + + func = function (event) { + parent.activ.textContent = event.currentTarget.value; + }; + for (z = 0; z < node.elements.length; z += 1) { + box.appendChild(this.util.create({tag: "text", $font: true, "text-anchor": "left", "width": 60, "x": 10, "y": y, value: node.elements[z]})); + item = box.appendChild(this.util.create({tag: "rect", rx: 0, x: offsetX, y: yr, width: 60, height: 24, stroke: "none", "class": "selection"})); + item.value = node.elements[z]; + if (node.action) { + item.onclick = node.action; + } else { + item.onclick = func; + } + y += 26; + yr += 26; + } + parent.choicebox = box; + } + parent.tool = node; + parent.onclick = function () { + if (parent.status === "close") { + parent.open(); + } else { + parent.close(); + } + }; + parent.close = function () { + if (parent.status === "open") { + this.removeChild(parent.choicebox); + } + parent.status = "close"; + parent.tool.height = parent.tool.minheight; + that.setSize(parent, parent.tool.width + parent.tool.x + 10, parent.tool.height + parent.tool.y + 10); + }; + parent.open = function () { + if (this.tagName === "svg") { + return; + } + if (parent.status === "close") { + this.appendChild(parent.choicebox); + } + parent.status = "open"; + parent.tool.height = parent.tool.maxheight; + that.setSize(parent, parent.tool.width + parent.tool.x + 10, parent.tool.height + parent.tool.y + 10); + }; + parent.close(); + + return g; +}; +// Example Items +// {tag: "path", d: ""} +// {tag: "rect", width:46, height:34} +// {tag: "ellipse", width:23, height:4} +// {tag: "line", x1:650, y1:-286, x2:650, y2:-252} +// {tag: "circle", r:5, x:12, y:0} +// {tag: "image", height: 30, width: 50, content$src: hallo} +// {tag: "text", "text-anchor": "left", x: "10"} +var SymbolLibary = function () {}; +SymbolLibary.prototype.upFirstChar = function (txt) {return txt.charAt(0).toUpperCase() + txt.slice(1).toLowerCase(); }; +SymbolLibary.prototype.create = function (node, drawer) { + if (this.isSymbol(node)) { + return this.draw(drawer, node); + } + return null; +}; +SymbolLibary.prototype.isSymbol = function (node) { + var fn = this[this.getName(node)]; + return typeof fn === "function"; +}; +SymbolLibary.prototype.getName = function (node) { + if (node.type) { + return "draw" + this.upFirstChar(node.type); + } + if (node.src) { + return "draw" + this.upFirstChar(node.src); + } + return "drawNode"; +}; +SymbolLibary.prototype.draw = function (drawer, node) { + var group, board, item, fn = this[this.getName(node)]; + if (typeof fn === "function") { + group = fn.apply(this, [node]); + if (!drawer || typeof drawer.createGroup !== "function") { + drawer = new Drawer.SVGDrawer(); + drawer.showButton = false; + board = drawer.getBoard(null); + board.setAttribute("style", "border:none;"); + drawer.setSize(board, node.width + node.x + 10, node.height + node.y + 10); + item = drawer.createGroup(node, group, board); + board.appendChild(item); + return board; + } + return drawer.createGroup(node, group); + } +}; +SymbolLibary.prototype.drawSmily = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 100, + height: 100, + items: [ + {tag: "path", stroke: "black", fill: "none", d: "m49.01774,25.64542a24.5001,24.5 0 1 1 -49.0001,0a24.5001,24.5 0 1 1 49.0001,0z"}, + {tag: "path", d: "m8,31.5c16,20 32,0.3 32,0.3"}, + {tag: "path", d: "m19.15,20.32a1.74,2.52 0 1 1 -3.49,0a1.74,2.52 0 1 1 3.49,0z"}, + {tag: "path", d: "m33,20.32a1.74,2.52 0 1 1 -3.48,0a1.74,2.52 0 1 1 3.48,0z"}, + {tag: "path", d: "m5.57,31.65c3.39,0.91 4.03,-2.20 4.03,-2.20"}, + {tag: "path", d: "m43,32c-3,0.91 -4,-2.20 -4.04,-2.20"} + ] + }; +}; +SymbolLibary.prototype.drawDatabase = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 100, + height: 100, + items: [ + {tag: "path", stroke: "black", fill: "none", d: "m0,6.26c0,-6.26 25.03,-6.26 25.03,0l0,25.82c0,6.26 -25.03,6.26 -25.03,0l0,-25.82z"}, + {tag: "path", stroke: "black", fill: "none", d: "m0,6.26c0,4.69 25.03,4.69 25.03,0m-25.03,2.35c0,4.69 25.03,4.69 25.03,0m-25.03,2.35c0,4.69 25.03,4.69 25.03,0"} + ] + }; +}; +SymbolLibary.prototype.drawLetter = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 100, + height: 50, + items: [ + {tag: "path", stroke: "black", fill: "none", d: "m1,1l22,0l0,14l-22,0l0,-14z"}, + {tag: "path", stroke: "black", fill: "none", d: "m1.06,1.14l10.94,6.81l10.91,-6.91"} + ] + }; +}; +SymbolLibary.prototype.drawMobilphone = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 25, + height: 50, + items: [ + {tag: "path", d: "m 4.2 0.5 15.61 0c 2 0 3.7 1.65 3.7 3.7l 0 41.6c 0 2-1.65 3.7-3.7 3.7l-15.6 0c-2 0-3.7-1.6-3.7-3.7l 0-41.6c 0-2 1.6-3.7 3.7-3.7z", fill: "none", stroke: "black"}, + {tag: "path", d: "m 12.5 2.73a 0.5 0.5 0 1 1-1 0 0.5 0.5 0 1 1 1 0z"}, + {tag: "path", d: "m 14 46a 2 2 0 1 1-4 0 2 2 0 1 1 4 0z"}, + {tag: "path", d: "m 8 5 7 0"}, + {tag: "path", d: "m 1.63 7.54 20.73 0 0 34-20.73 0z"} + ] + }; +}; +SymbolLibary.prototype.drawWall = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 25, + height: 50, + items: [ + {tag: "path", d: "m26,45.44l-5,3.56l-21,-9l0,-36.41l5,-3.56l20.96,9l-0,36.4z"}, + {tag: "path", stroke: "white", d: "m2.21,11l18.34,7.91m-14.46,-12.57l0,6.3m8.2,21.74l0,6.35m-8.6,-10l0,6.351m4.1,-10.67l0,6.3m4.8,-10.2l0,6.3m-8.87,-10.23l0,6.35m4.78,-10.22l0,6.35m-8,14.5l18.34,7.91m-18.34,-13.91l18.34,7.91m-18.34,-13.91l18.34,7.91m-18.34,-13.91l18.34,7.91m0,-13l0,34m-18.23,-41.84l18.3,8m0,0.11l5,-3.57"} + ] + }; +}; +SymbolLibary.prototype.drawActor = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 25, + height: 50, + items: [ + {tag: "line", stroke: "#000", x1: "12", y1: "10", x2: "12", y2: "30"}, + {tag: "circle", stroke: "#000", cy: "5", cx: "12", r: "5"}, + {tag: "line", stroke: "#000", y2: "18", x2: "25", y1: "18", x1: "0"}, + {tag: "line", stroke: "#000", y2: "39", x2: "5", y1: "30", x1: "12"}, + {tag: "line", stroke: "#000", y2: "39", x2: "20", y1: "30", x1: "12"} + ] + }; +}; +SymbolLibary.prototype.drawLamp = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 25, + height: 50, + items: [ + {tag: "path", d: "m 22.47 10.58c-6.57 0-11.89 5.17-11.89 11.54 0 2.35 0.74 4.54 2 6.36 2 4 4.36 5.63 4.42 10.4l 11.15 0c 0.12-4.9 2.5-6.8 4.43-10.4 1.39-1.5 1.8-4.5 1.8-6.4 0-6.4-5.3-11.5-11.9-11.5z", fill: "white", stroke: "black"}, + {tag: "path", d: "m 18.4 40 8 0c 0.58 0 1 0.5 1 1 0 0.6-0.5 1-1 1l-8 0c-0.6 0-1-0.47-1-1 0-0.58 0.47-1 1-1z"}, + {tag: "path", d: "m 18.4 42.7 8 0c 0.58 0 1 0.47 1 1 0 0.58-0.47 1-1 1l-8 0c-0.58 0-1-0.47-1-1 0-0.58 0.46-1 1-1z"}, + {tag: "path", d: "m 18.4 45.3 8 0c 0.58 0 1 0.47 1 1 0 0.58-0.47 1-1 1l-8 0c-0.58 0-1-0.47-1-1 0-0.58 0.46-1 1-1z"}, + {tag: "path", d: "m 19.5 48c 0.37 0.8 1 1.3 1.9 1.7 0.6 0.3 1.5 0.3 2 0 0.8-0.3 1.4-0.8 1.9-1.8z"}, + {tag: "path", d: "m 6 37.5 4.2-4c 0.3-0.3 0.8-0.3 1 0 0.3 0.3 0.3 0.8 0 1.1l-4.2 4c-0.3 0.3-0.8 0.3-1.1 0-0.3-0.3-0.3-0.8 0-1z"}, + {tag: "path", d: "m 39 37.56-4.15-4c-0.3-0.3-0.8-0.3-1 0-0.3 0.3-0.3 0.8 0 1l 4.2 4c 0.3 0.3 0.8 0.3 1 0 0.3-0.3 0.3-0.8 0-1z"}, + {tag: "path", d: "m 38 23 5.8 0c 0.4 0 0.8-0.3 0.8-0.8 0-0.4-0.3-0.8-0.8-0.8l-5.8 0c-0.4 0-0.8 0.3-0.8 0.8 0 0.4 0.3 0.8 0.8 0.8z"}, + {tag: "path", d: "m 1.3 23 6 0c 0.4 0 0.8-0.3 0.8-0.8 0-0.4-0.3-0.8-0.8-0.8l-5.9 0c-0.4 0-0.8 0.3-0.8 0.8 0 0.4 0.3 0.8 0.8 0.8z"}, + {tag: "path", d: "m 34.75 11.2 4-4.1c 0.3-0.3 0.3-0.8 0-1-0.3-0.3-0.8-0.3-1 0l-4 4.1c-0.3 0.3-0.3 0.8 0 1 0.3 0.3 0.8 0.3 1 0z"}, + {tag: "path", d: "m 11.23 10-4-4c-0.3-0.3-0.8-0.3-1 0-0.3 0.3-0.3 0.8 0 1l 4.2 4c 0.3 0.3 0.8 0.3 1 0 0.3-0.3 0.3-0.8 0-1z"}, + {tag: "path", d: "m 21.64 1.3 0 5.8c 0 0.4 0.3 0.8 0.8 0.8 0.4 0 0.8-0.3 0.8-0.8l 0-5.8c 0-0.4-0.3-0.8-0.8-0.8-0.4 0-0.8 0.3-0.8 0.8z"}, + {tag: "path", d: "m 26.1 24.3c-0.5 0-1 0.2-1.3 0.4-1.1 0.6-2 3-2.27 3.5-0.26-0.69-1.14-2.9-2.2-3.5-0.7-0.4-2-0.7-2.5 0-0.6 0.8 0.2 2.2 0.9 2.9 1 0.9 3.9 0.9 3.9 0.9 0 0 0 0 0 0 0.54 0 2.8 0 3.7-0.9 0.7-0.7 1.5-2 0.9-2.9-0.2-0.3-0.7-0.4-1.2-0.4z"}, + {tag: "path", d: "m 22.5 28.57 0 10.7"} + ] + }; +}; +SymbolLibary.prototype.drawStop = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 30, + height: 30, + items: [ + {tag: "path", fill: "#FFF", "stroke-width": "2", stroke: "#B00", d: "m 6,6 a 14,14 0 1 0 0.06,-0.06 z m 0,0 20,21"} + ] + }; +}; +SymbolLibary.prototype.drawMin = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 20, + height: 20, + items: [ + {tag: "path", fill: "white", stroke: "#000", "stroke-width": 0.2, "stroke-linejoin": "round", d: "m 0,0 19,0 0,19 -19,0 z"}, + {tag: "path", fill: "none", stroke: "#000", "stroke-width": "1px", "stroke-linejoin": "miter", d: "m 4,10 13,-0.04"} + ] + }; +}; +SymbolLibary.prototype.drawArrow = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 20, + height: 20, + rotate: node.rotate, + items: [ + {tag: "path", fill: "#000", stroke: "#000", d: "M 0,0 10,4 0,9 z"} + ] + }; +}; +SymbolLibary.prototype.drawMax = function (node) { + return { + x: node.x || 0, + y: node.y || 0, + width: 20, + height: 20, + items: [ + {tag: "path", fill: "white", stroke: "#000", "stroke-width": 0.2, "stroke-linejoin": "round", "stroke-dashoffset": 2, "stroke-dasharray": "4.8,4.8", d: "m 0,0 4.91187,0 5.44643,0 9.11886,0 0,19.47716 -19.47716,0 0,-15.88809 z"}, + {tag: "path", fill: "none", stroke: "#000", "stroke-width": "1px", "stroke-linejoin": "miter", d: "m 4,10 6,0.006 0.02,5 0.01,-11 -0.03,6.02 c 2,-0.01 4,-0.002 6,0.01"} + ] + }; +}; +SymbolLibary.prototype.drawButton = function (node) { + var btnX, btnY, btnWidth, btnHeight, btnValue; + + btnX = node.x || 0; + btnY = node.y || 0; + btnWidth = node.width || 60; + btnHeight = node.height || 28; + btnValue = node.value || ""; + return { + x: btnX, + y: btnY, + width: 60, + height: 28, + items: [ + {tag: "rect", rx: 8, x: 0, y: 0, width: btnWidth, height: btnHeight, stroke: "#000", filter: "url(#drop-shadow)", "class": "saveBtn"}, + {tag: "text", $font: true, x: 10, y: 18, fill: "black", value: btnValue, "class": "hand"} + ] + }; +}; +SymbolLibary.prototype.drawDropdown = function (node) { + var btnX, btnY, btnWidth, btnHeight; + + btnX = node.x || 0; + btnY = node.y || 0; + btnWidth = node.width || 60; + btnHeight = node.height || 28; + return { + x: btnX, + y: btnY, + width: btnWidth, + height: btnHeight, + items: [ + {tag: "rect", rx: 0, x: 0, y: 0, width: btnWidth - 20, height: btnHeight, stroke: "#000", fill: "none"}, + {tag: "rect", rx: 2, x: btnWidth - 20, y: 0, width: 20, height: 28, stroke: "#000", "class": "saveBtn"}, + {tag: "path", style: "fill:#000000;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1", d: "m " + (btnWidth - 15) + ",13 10,0 L " + (btnWidth - 10) + ",20 z"} + ] + }; +}; +SymbolLibary.prototype.drawClassicon = function (node) { + var btnX, btnY, btnWidth, btnHeight; + + btnX = node.x || 0; + btnY = node.y || 0; + btnWidth = node.width || 60; + btnHeight = node.height || 28; + return { + x: btnX, + y: btnY, + width: btnWidth, + height: btnHeight, + items: [ + {tag: "path", d: "m0,0l10.78832,0l0,4.49982l-10.78832,0.19999l0,9.19963l10.78832,0l0,-9.49962l-10.78832,0.19999l0,-4.59982z", style: "fill:none;stroke:#000000;"}, + {tag: "path", d: "m25.68807,0l10.78832,0l0,4.49982l-10.78832,0.19999l0,9.19963l10.78832,0l0,-9.49962l-10.78832,0.2l0,-4.59982z", style: "fill:none;stroke:#000000;"}, + {tag: "line", x1: 11, y1: 7, x2: 25, y2: 7, stroke: "#000"} + ] + }; +}; +SymbolLibary.prototype.drawEdgeicon = function (node) { + var btnX, btnY, btnWidth, btnHeight; + + btnX = node.x || 0; + btnY = node.y || 0; + btnWidth = node.width || 30; + btnHeight = node.height || 35; + return { + x: btnX, + y: btnY, + width: btnWidth, + height: btnHeight, + items: [ + {tag: "path", d: "M2,10 20,10 20,35 2,35 Z M2,17 20,17 M20,10 28,5 28,9 M 28.5,4.7 24,4", style: "fill:none;stroke:#000000;transform:scale(0.4);"} + ] + }; +}; diff --git a/graph.js b/graph.js new file mode 100644 index 000000000..0d7ff0b24 --- /dev/null +++ b/graph.js @@ -0,0 +1,2775 @@ +/* + NetworkParser + Copyright (c) 2011 - 2014, Stefan Lindel + All rights reserved. + + Licensed under the EUPL, Version 1.1 or (as soon they + will be approved by the European Commission) subsequent + versions of the EUPL (the "Licence"); + You may not use this work except in compliance with the Licence. + You may obtain a copy of the Licence at: + + http://ec.europa.eu/idabc/eupl5 + + Unless required by applicable law or agreed to in + writing, software distributed under the Licence is + distributed on an "AS IS" basis, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either + express or implied. + See the Licence for the specific language governing + permissions and limitations under the Licence. +*/ +// VERSION: 2015.11.09 20:21 + +//var uniId = 0; +//function generateId() { return uniId++; }; +//Object.prototype.uniId = function () { +// var newId = generateId(); +// this.uniId = function () { return newId; }; +// return newId; +//};vars: true +/*jslint forin:true, newcap:true, node: true, continue: true */ +/*jshint forin:true, laxbreak: true, newcap: false, node: true, nomen: true, -W089, -W079 */ + +/*global document: false, window: false, navigator: false, unescape: false, Edge: false, DagreLayout: false, Drawer: false */ +/*global jsPDF: false, svgConverter: false, Image: false, Blob: false, dagre: false, SymbolLibary: false */ +/*global FileReader:false, java:false, ChoiceBox:false */ +"use strict"; +var ObjectCreate = Object.create || function (o) {var F = function () {}; F.prototype = o; return new F(); }; + +/* Pos */ +var Pos = function (x, y, id) {this.x = Math.round(x || 0); this.y = Math.round(y || 0); if (id) {this.$id = id; } }; +/* GraphUtil */ +var GraphUtil = function (ns) {if (ns) {this.ns = ns; } }; +GraphUtil.prototype.copy = function (ref, src, full, replace) { + if (src) { + var i; + for (i in src) { + if (!src.hasOwnProperty(i) || typeof (src[i]) === "function") { + continue; + } + if (i.charAt(0) === "$") { + if (full) {ref[i] = src[i]; } + continue; + } + if (typeof (src[i]) === "object") { + if (replace) { + ref[i] = src[i]; + continue; + } + if (!ref[i]) { + if (src[i] instanceof Array) { + ref[i] = []; + } else { + ref[i] = {}; + } + } + this.copy(ref[i], src[i], full); + } else { + if (src[i] === "") { + continue; + } + ref[i] = src[i]; + } + } + if (src.width) {ref.$startWidth = src.width; } + if (src.height) {ref.$startHeight = src.height; } + } + return ref; +}; +GraphUtil.prototype.minJson = function (target, src, ref) { + var i, temp, value; + for (i in src) { + if (!src.hasOwnProperty(i) || typeof (src[i]) === "function") { + continue; + } + if (src[i] === null || src[i] === "" || src[i] === 0 || src[i] === false || i.charAt(0) === "$") { + continue; + } + value = src[i]; + if (value instanceof GraphUtil.Options || ref !== null) { + if (typeof (value) === "object") { + temp = (value instanceof Array) ? [] : {}; + if (ref) { + value = this.minJson(temp, value, ref[i]); + } else { + value = this.minJson(temp, value, new GraphUtil.Options()); + } + } + if (ref && value === ref[i]) { + continue; + } + } + if (typeof (value) === "object") { + if (value instanceof Array && value.length < 1) { + continue; + } + if (value instanceof Array) { + target[i] = this.minJson([], value); + } else { + temp = this.minJson({}, value); + if (JSON.stringify(temp, null, "") === "{}") { + continue; + } + target[i] = temp; + } + } else { + target[i] = value; + } + } + return target; +}; +GraphUtil.prototype.bind = function (el, eventName, eventHandler) { + if (el.addEventListener) { + el.addEventListener(eventName, eventHandler, false); + } else if (el.attachEvent) { + el.attachEvent('on' + eventName, eventHandler); + } +}; +GraphUtil.prototype.create = function (node) { + var style, item, xmlns, key, tag, k; + if (document.createElementNS && (node.xmlns || this.ns)) { + if (node.xmlns) { + xmlns = node.xmlns; + } else { + xmlns = this.ns; + } + if (node.tag === "img" && xmlns === "http://www.w3.org/2000/svg") { + item = document.createElementNS(xmlns, "image"); + item.setAttribute('xmlns:xlink', "http://www.w3.org/1999/xlink"); + item.setAttributeNS("http://www.w3.org/1999/xlink", 'href', node.src); + } else { + item = document.createElementNS(xmlns, node.tag); + } + } else { + item = document.createElement(node.tag); + } + + tag = node.tag.toLowerCase(); + for (key in node) { + if (!node.hasOwnProperty(key)) { + continue; + } + k = key.toLowerCase(); + if (node[key] === null) { + continue; + } + if (k === 'tag' || k.charAt(0) === '$' || k === 'model') { + continue; + } + if (k.charAt(0) === '#') { + item[k.substring(1)] = node[key]; + continue; + } + if (k === 'rotate') { + item.setAttribute("transform", "rotate(" + node[key] + "," + node.model.x + "," + node.model.y + ")"); + continue; + } + if (k === 'value') { + if (!node[key]) { + continue; + } + if (tag !== "input") { + if (tag === "text") {// SVG + item.appendChild(document.createTextNode(node[key])); + } else { + item.innerHTML = node[key]; + } + } else { + item[key] = node[key]; + } + continue; + } + if (k.indexOf("on") === 0) { + this.bind(item, k.substring(2), node[key]); + continue; + } + if (k.indexOf("-") >= 0) { + item.style[key] = node[key]; + } else { + if (k === "style" && typeof (node[key]) === "object") { + for (style in node[key]) { + if (!node[key].hasOwnProperty(style)) { + continue; + } + if (node[key][style]) { + if ("transform" === style) { + item.style.transform = node[key][style]; + item.style.msTransform = item.style.MozTransform = item.style.WebkitTransform = item.style.OTransform = node[key][style]; + } else { + item.style[style] = node[key][style]; + } + } + } + } else { + item.setAttribute(key, node[key]); + } + } + } + if (node.$font) { + if (this.model && this.model.options && this.model.options.font) { + for (key in this.model.options.font) { + if (!this.model.options.font.hasOwnProperty(key)) { + continue; + } + if (this.model.options.font[key]) { + if (item.style) { + item.style[key] = this.model.options.font[key]; + } else { + item.setAttribute(key, this.model.options.font[key]); + } + } + } + } + } + if (node.$parent) { + node.$parent.appendChild(item); + } + + if (node.model) { + item.model = node.model; + } + return item; +}; +GraphUtil.prototype.getModelNode = function (element) { + if (!element.model) { + if (element.parentElement) { + return this.getModelNode(element.parentElement); + } + return null; + } + return element; +}; +GraphUtil.prototype.getValue = function (value) {return parseInt(("0" + value).replace("px", ""), 10); }; +GraphUtil.prototype.isIE = function () {return document.all && !window.opera; }; +GraphUtil.prototype.isFireFox = function () {return navigator.userAgent.toLowerCase().indexOf('firefox') > -1; }; +GraphUtil.prototype.isOpera = function () {return navigator.userAgent.indexOf("Opera") > -1; }; +GraphUtil.prototype.getEventX = function (event) {return (this.isIE) ? window.event.clientX : event.pageX; }; +GraphUtil.prototype.getEventY = function (event) {return (this.isIE) ? window.event.clientY : event.pageY; }; +GraphUtil.prototype.set = function (id, value) {if (value) {this[id] = value; } }; +GraphUtil.prototype.selectText = function (text) { + var selection, range; + if (this.isIE()) { + range = document.body.createTextRange(); + range.moveToElementText(text); + range.select(); + } else if (this.isFireFox() || this.isOpera()) { + selection = window.getSelection(); + range = document.createRange(); + range.selectNodeContents(text); + selection.removeAllRanges(); + selection.addRange(range); + } +}; +GraphUtil.prototype.sizeHTML = function (html, node) { + if (!html) {return; } + if (this.$parent) { + return this.$parent.sizeHTML(html, node); + } + this.board.appendChild(html); + var rect = html.getBoundingClientRect(); + this.board.removeChild(html); + if (node) { + if (!node.$startWidth) { + node.width = Math.round(rect.width); + } + if (!node.$startHeight) { + node.height = Math.round(rect.height); + } + } + return rect; +}; +GraphUtil.prototype.hasClass = function (ele, cls) {return ele.className.indexOf(cls) > 0; }; +GraphUtil.prototype.addClass = function (ele, cls) {if (!this.hasClass(ele, cls)) { + ele.className = ele.className + " " + cls; +} }; +GraphUtil.prototype.removeClass = function (ele, cls) { + if (this.hasClass(ele, cls)) { + var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)'); + ele.className = ele.className.replace(reg, ' '); + } +}; +/* Info */ +GraphUtil.Info = function (info, parent, edge) { + this.type = "Info"; + if (typeof (info) === "string") { + this.id = info; + } else { + if (info.property) {this.property = info.property; } + if (info.cardinality) {this.cardinality = info.cardinality; } + this.id = info.id; + } + this.x = this.y = this.width = this.height = 0; + this.$center = new Pos(); + this.custom = false; + this.$parent = parent; + this.$edge = edge; + this.$isdraggable = true; +}; +GraphUtil.Info.prototype.getX = function () {return this.x; }; +GraphUtil.Info.prototype.getY = function () {return this.y; }; + +GraphUtil.Line = function (source, target, line, style) {this.source = source; this.target = target; this.line = line; this.style = style; }; +GraphUtil.Line.Format = {SOLID: "SOLID", DOTTED: "DOTTED"}; +/* Options */ +GraphUtil.Options = function () { + this.raster = false; + this.addBorder = true; + this.display = "svg"; + this.font = {"font-size": "10px", "font-family": "Verdana"}; + this.layout = {name: "Dagre", rankDir: "TB", nodesep: 10}; // Dagre TB, LR + this.CardinalityInfo = true; + this.propertyinfo = true; + this.rotatetext = true; + this.linetyp = "center"; + this.buttons = ["HTML", "SVG"]; // ["HTML", "SVG", "PNG", "PDF"] +}; +/* Node */ +var GraphNode = function (id) { + this.type = "node"; + this.id = id; + this.$edges = []; + this.attributes = []; + this.methods = []; + this.$parent = null; + this.x = this.y = this.width = this.height = 0; + this.$isdraggable = true; +}; +GraphNode.prototype = ObjectCreate(GraphUtil.prototype); +GraphNode.prototype.getX = function () {if (this.$parent) {return this.$parent.getX() + this.x; } return this.x; }; +GraphNode.prototype.getY = function () {if (this.$parent) {return this.$parent.getY() + this.y; } return this.y; }; +GraphNode.prototype.getEdges = function () {return this.$edges; }; +GraphNode.prototype.clear = function () {this.$RIGHT = this.$LEFT = this.$UP = this.$DOWN = 0; }; +GraphNode.prototype.removeFromBoard = function (board) {if (this.$gui) {board.removeChild(this.$gui); this.$gui = null; } }; +GraphNode.prototype.isClosed = function () { + if (this.status === "close") { + return true; + } + if (this.$parent) {return this.$parent.isClosed(); } + return false; +}; +GraphNode.prototype.getShowed = function () { + if (this.status === "close") { + if (!this.$parent.isClosed()) { + return this; + } + } + if (this.isClosed()) { + return this.$parent.getShowed(); + } + return this; +}; +var GraphModel = function (json, options) { + this.type = "classdiagram"; + this.$isdraggable = true; + json = json || {}; + this.left = json.left || 0; + this.top = json.top || 0; + this.x = this.y = this.width = this.height = 0; + if (json.minid) { + this.minid = json.minid; + } + this.$nodeCount = 0; + this.nodes = {}; + this.edges = []; + json = json || {}; + this.type = json.type || "classdiagram"; + this.set("id", json.id); + this.options = this.copy(this.copy(new GraphUtil.Options(), json.options), options, true, true); + this["package"] = ""; + this.set("info", json.info); + this.set("style", json.style); + var i; + if (json.nodes) { + for (i = 0; i < json.nodes.length; i += 1) { + this.addNode(json.nodes[i]); + } + } + if (json.edges) { + for (i = 0; i < json.edges.length; i += 1) { + this.addEdgeModel(json.edges[i]); + } + } +}; +GraphModel.prototype = ObjectCreate(GraphNode.prototype); +GraphModel.prototype.clear = function () { + var i; + GraphNode.prototype.clear.call(this); + for (i in this.nodes) { + if (!this.nodes.hasOwnProperty(i)) { + continue; + } + this.nodes[i].clear(); + } +}; +GraphModel.prototype.addEdgeModel = function (e) { + var edge, type = e.type || "edge"; + type = type.charAt(0).toUpperCase() + type.substring(1).toLowerCase(); + if (typeof window[type] === "function") { + edge = new window[type](); + } else { + edge = new Edge(); + } + edge.source = new GraphUtil.Info(e.source, this, edge); + edge.target = new GraphUtil.Info(e.target, this, edge); + edge.$sNode = this.getNode(edge.source.id, true); + edge.$sNode.$edges.push(edge); + + if (e.info) { + if (typeof (e.info) === "string") { + edge.info = {id: e.info}; + } else { + edge.info = {id: e.info.id, property: e.info.property, cardinality: e.info.cardinality}; + } + } + edge.$parent = this; + edge.set("style", e.style); + edge.set("counter", e.counter); + + edge.$tNode = this.getNode(edge.target.id, true); + edge.$tNode.$edges.push(edge); + + this.edges.push(edge); + return edge; +}; +GraphModel.prototype.addEdge = function (source, target) { + var edge = new Edge(); + edge.source = this.addNode(source); + edge.target = this.addNode(target); + return this.addEdgeModel(edge); +}; +GraphModel.prototype.addNode = function (node) { + /* testing if node is already existing in the graph */ + if (typeof (node) === "string") { + node = {id: node, type: "node"}; + } + node.type = node.type || "node"; + node.type = node.type.toLowerCase(); + if (!(node.id)) { + node.id = node.type + "$" + (this.$nodeCount + 1); + } + if (this.nodes[node.id] !== undefined) { + return this.nodes[node.id]; + } + if (node.type.indexOf("diagram", node.type.length - 7) !== -1) { + node = new GraphModel(node, new GraphUtil.Options()); + } else { + node = this.copy(new GraphNode(), node); + } + this.nodes[node.id] = node; + node.$parent = this; + this.$nodeCount += 1; + return this.nodes[node.id]; +}; +GraphModel.prototype.removeEdge = function (idSource, idTarget) { + var z, e; + for (z = 0; z < this.edges.length; z += 1) { + e = this.edges[z]; + if (e.$sNode.id === idSource && e.$tNode.id === idTarget) { + this.edges.splice(z, 1); + z -= 1; + } else if (e.$tNode.id === idSource && e.$sNode.id === idTarget) { + this.edges.splice(z, 1); + z -= 1; + } + } +}; +GraphModel.prototype.removeNode = function (id) { + delete (this.nodes[id]); + var i; + for (i = 0; i < this.edges.length; i += 1) { + if (this.edges[i].$sNode.id === id || this.edges[i].$tNode.id === id) { + this.edges.splice(i, 1); + i -= 1; + } + } +}; +GraphModel.prototype.getNode = function (id, isSub, deep) { + var n, i, r; + deep = deep || 0; + if (this.nodes[id]) { + return this.nodes[id]; + } + if (!isSub) { + return this.addNode(id); + } + for (i in this.nodes) { + if (!this.nodes.hasOwnProperty(i)) { + continue; + } + n = this.nodes[i]; + if (n instanceof GraphModel) { + r = n.getNode(id, isSub, deep + 1); + if (r) { + return r; + } + } + } + if (deep === 0) { + return this.addNode(id); + } + return null; +}; +GraphModel.prototype.toJson = function () {return this.copy({}, this); }; +GraphModel.prototype.createElement = function (element, typ) {this.$parent.createElement(element, typ); }; +GraphModel.prototype.removeFromBoard = function (board) { + if (this.$gui) { + board.removeChild(this.$gui); + this.$gui = null; + } +}; +GraphModel.prototype.resize = function (mode) {}; +GraphModel.prototype.getEdges = function () {return this.edges; }; +GraphModel.prototype.calcLines = function (drawer) { + var i, n, sourcePos, e, ownAssoc = []; + for (i in this.nodes) { + if (!this.nodes.hasOwnProperty(i) || typeof (this.nodes[i]) === "function") { + continue; + } + this.nodes[i].clear(); + } + for (i = 0; i < this.edges.length; i += 1) { + e = this.edges[i]; + if (!e.calculate(this.$gui, drawer)) { + ownAssoc.push(e); + } + } + for (i = 0; i < ownAssoc.length; i += 1) { + ownAssoc[i].calcOwnEdge(); + sourcePos = ownAssoc[i].getCenterPosition(ownAssoc[i].$sNode, ownAssoc[i].$start); + ownAssoc[i].calcInfoPos(sourcePos, ownAssoc[i].$sNode, ownAssoc[i].source); + + sourcePos = ownAssoc[i].getCenterPosition(ownAssoc[i].$tNode, ownAssoc[i].$end); + ownAssoc[i].calcInfoPos(sourcePos, ownAssoc[i].$tNode, ownAssoc[i].target); + } +}; +GraphModel.prototype.validateModel = function () { + var e, z, n, id, node, list; + if (this.type === "classdiagram") { + list = this.edges; + for (e = 0; e < list.length; e += 1) { + node = list[e].$sNode; + z = node.id.indexOf(":"); + if (z > 0) { + id = node.id.substring(z + 1); + n = this.getNode(id, true, 1); + delete (this.nodes[node.id]); + this.edges[e].source.id = id; + if (n) { + this.edges[e].$sNode = n; + } else { + node.id = id; + this.nodes[node.id] = node; + } + } + node = list[e].$tNode; + z = node.id.indexOf(":"); + if (z > 0) { + id = node.id.substring(z + 1); + n = this.getNode(id, true, 1); + delete (this.nodes[node.id]); + this.edges[e].target.id = id; + if (n) { + this.edges[e].$tNode = n; + } else { + node.id = id; + this.nodes[node.id] = node; + } + } + if (!list[e].source.cardinality) { + list[e].source.cardinality = "one"; + } + if (!list[e].target.cardinality) { + list[e].target.cardinality = "one"; + } + // Refactoring Edges for same property and type set cardinality + for (z = e + 1; z < list.length; z += 1) { + id = typeof (java); + if (!(id === typeof list[z])) { + continue; + } + if (this.validateEdge(list[e], list[z])) { + list[e].target.cardinality = "many"; + list.splice(z, 1); + z -= 1; + } else if (this.validateEdge(list[z], list[e])) { + list[e].source.cardinality = "many"; + list.splice(z, 1); + z -= 1; + } + } + } + } +}; +GraphModel.prototype.validateEdge = function (sEdge, tEdge) { + return (sEdge.source.id === tEdge.source.id && sEdge.target.id === tEdge.target.id) && (sEdge.source.property === tEdge.source.property && sEdge.target.property === tEdge.target.property); +}; +// ######################################################### Graph ######################################################### +var Graph = function (json, options) { + this.x = this.y = this.width = this.height = 0; + json = json || {}; + json.top = json.top || 50; + json.left = json.left || 10; + this.model = new GraphModel(json, options); + this.initLayouts(); + this.loader = new GraphUtil.Loader(this); + this.initOption(); +}; +Graph.prototype = ObjectCreate(GraphNode.prototype); +Graph.prototype.initOption = function (typ, value) { + this.init = true; + if (this.model.options.display.toLowerCase() === "html") { + this.drawer = new Drawer.HTMLDrawer(); + } else { + this.initDrawer("svg"); + } + var i, layout = this.layouts[0]; + + for (i = 0; i < this.layouts.length; i += 1) { + if (this.layouts[i].name === this.model.options.layout.name.toLowerCase()) { + layout = this.layouts[i]; + break; + } + } + this.layouter = layout.value; + if (this.model.options.canvasid) { + this.root = document.getElementById(this.model.options.canvasid); + } + if (this.root) { + if (this.model.options.clearCanvas) { + for (i = this.root.children.length - 1; i >= 0; i -= 1) { + this.root.removeChild(this.root.children[i]); + } + } + } else { + this.root = document.createElement("div"); + if (this.model.options.canvasid) { + this.root.id = this.model.options.canvasid; + } + document.body.appendChild(this.root); + } +}; +Graph.prototype.addOption = function (typ, value) { + this.model.options[typ] = value; + this.init = false; +}; +Graph.prototype.initLayouts = function () { this.layouts = [{name: "dagre", value: new DagreLayout()}]; }; +Graph.prototype.initInfo = function (edge, info) { + if (!this.model.options.CardinalityInfo && !this.model.options.propertyinfo) { + return null; + } + var infoTxt = edge.getInfo(info); + if (infoTxt.length > 0) { + this.sizeHTML(this.drawer.getInfo(info, infoTxt, 0), info); + } + return infoTxt; +}; +Graph.prototype.clearBoard = function (onlyElements) { + var i, n; + if (this.board) { + this.clearLines(this.model); + for (i in this.model.nodes) { + if (!this.model.nodes.hasOwnProperty(i)) { + continue; + } + n = this.model.nodes[i]; + if (this.board.children.length > 0) { + n.removeFromBoard(this.board); + } + n.$RIGHT = n.$LEFT = n.$UP = n.$DOWN = 0; + } + if (!onlyElements) { + this.root.removeChild(this.board); + } + } + if (!onlyElements && this.drawer) { + this.drawer.clearBoard(); + } +}; +Graph.prototype.addNode = function (node) {return this.model.addNode(node); }; +Graph.prototype.addEdge = function (source, target) {return this.model.addEdge(source, target); }; +Graph.prototype.removeNode = function (id) {return this.model.removeNode(id); }; +Graph.prototype.calcLines = function (model) { + model = model || this.model; + model.calcLines(this.drawer); +}; +Graph.prototype.drawLines = function (model) { + this.clearLines(model); + var i, e, startShow, endShow, items = [], id; + for (i = 0; i < model.edges.length; i += 1) { + e = model.edges[i]; + startShow = !e.$sNode.isClosed(); + endShow = !e.$tNode.isClosed(); + if (startShow && endShow) { + e.draw(this.board, this.drawer); + } else if ((startShow && !endShow) || (!startShow && endShow)) { + id = e.$sNode.getShowed().id + "-" + e.$tNode.getShowed().id; + if (items.indexOf(id) < 0) { + items.push(id); + e.draw(this.board, this.drawer); + } + } + } +}; +Graph.prototype.clearLines = function (model) { + var i; + for (i = 0; i < model.edges.length; i += 1) { + model.edges[i].removeFromBoard(this.board); + } +}; +Graph.prototype.MinMax = function (node, min, max) { + max.x = Math.max(max.x, node.x + Number(node.width) + 10); + max.y = Math.max(max.y, node.y + Number(node.height) + 10); + min.x = Math.max(min.x, node.x); + min.y = Math.max(min.y, node.y); +}; +Graph.prototype.resize = function (model) { + var nodes, n, max, i, min = new Pos(); + max = new Pos(model.minSize.x, model.minSize.y); + nodes = model.nodes; + for (i in nodes) { + if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") { + continue; + } + n = nodes[i]; + this.moveToRaster(n); + this.MinMax(n, min, max); + } + this.calcLines(model); + for (i = 0; i < model.edges.length; i += 1) { + n = model.edges[i]; + this.MinMax(n.source, min, max); + this.MinMax(n.target, min, max); + } + model.height = max.y; + model.width = max.x; + this.drawer.setSize(model.$gui, max.x, max.y); + if (model.options.raster) { + this.drawRaster(); + } + this.drawLines(model); + return max; +}; +Graph.prototype.drawRaster = function () { + var width, height, line, i; + while (this.board.rasterElements.length > 0) { + this.board.removeChild(this.board.rasterElements.pop()); + } + width = this.board.style.width.replace("px", ""); + height = this.board.style.height.replace("px", ""); + + for (i = 10; i < width; i += 10) { + line = this.drawer.getLine(i, 0, i, height, null, "#ccc"); + line.setAttribute("className", "lineRaster"); + this.board.rasterElements.push(line); + this.board.appendChild(line); + } + for (i = 10; i < height; i += 10) { + line = this.drawer.getLine(0, i, width, i, null, "#ccc"); + line.setAttribute("className", "lineRaster"); + this.board.rasterElements.push(line); + this.board.appendChild(line); + } +}; +Graph.prototype.draw = function (model, width, height) { + var i, n, nodes = model.nodes; + if (model.options.addBorder) { + for (i in nodes) { + if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") { + continue; + } + n = nodes[i]; + if (model.left > 0 || model.top > 0) { + n.x += model.left; + n.y += model.top; + } + } + model.options.addBorder = false; + } + model.minSize = new Pos(width || 0, height || 0); + if (this.loader.abort && this.loader.images.length > 0) { + return; + } + this.resize(model); + for (i in nodes) { + if (!nodes.hasOwnProperty(i) || typeof (nodes[i]) === "function") { + continue; + } + n = nodes[i]; + n.$gui = this.drawer.getNode(n, true); + model.$gui.appendChild(n.$gui); + } +}; +Graph.prototype.moveToRaster = function (node) { + if (this.model.options.raster) { + node.x = parseInt(node.x / 10, 10) * 10; + node.y = parseInt(node.y / 10, 10) * 10; + if (node.$gui) { + this.drawer.setPos(node.$gui, node.x, node.y); + } + } +}; +Graph.prototype.initGraph = function (model) { + var i, n, isDiag, html, e; + model.validateModel(); + for (i in model.nodes) { + if (typeof (model.nodes[i]) === "function") { + continue; + } + n = model.nodes[i]; + isDiag = n.type.indexOf("diagram", n.type.length - 7) !== -1; + if (isDiag) { + this.initGraph(n); + } + html = this.drawer.getNode(n); + if (html) { + this.sizeHTML(html, n); + if (isDiag) { + n.$center = new Pos(n.x + (n.width / 2), n.y + (n.height / 2)); + } + } + } + for (i = 0; i < model.edges.length; i += 1) { + e = model.edges[i]; + this.initInfo(e, e.source); + this.initInfo(e, e.target); + } +}; +Graph.prototype.layout = function (minwidth, minHeight, model) { + if (!this.init) { + this.initOption(); + } + if (model) { + this.initGraph(model); + } else { + model = this.model; + this.initDrawer(); + this.initGraph(model); + } + if (this.loader.images.length < 1) { + this.layouter.layout(this, model, Math.max(minwidth || 0, 100), Math.max(minHeight || 0, 100)); + } else { + this.loader.width = minwidth; + this.loader.height = minHeight; + } +}; +Graph.prototype.createElement = function (element, typ, node) { + var that = this; + element.node = node; + this.bind(element, "mousedown", function (e) {that.startDrag(e); }); +}; +Graph.prototype.appendImage = function (img) { + this.loader.add(img); +}; +// ######################################################### DRAG AND DROP ######################################################### +Graph.prototype.initDragAndDrop = function () { + this.objDrag = null; + this.mouse = new Pos(); + this.offset = new Pos(); + this.startObj = new Pos(); + var that = this; + this.bind(this.board, "mousemove", function (e) {that.doDrag(e); }); + this.bind(this.board, "mouseup", function (e) {that.stopDrag(e); }); + this.bind(this.board, "mouseout", function (e) {that.stopDrag(e); }); +}; +Graph.prototype.setSelectable = function (node, value) { + if (node.nodeType === 1) { + if (value) { + node.setAttribute("unselectable", value); + } else { + node.removeAttribute("unselectable"); + } + } + var child = node.firstChild; + while (child) { + this.setSelectable(child, value); + child = child.nextSibling; + } +}; +Graph.prototype.getDragNode = function (node) { + if (node.model) { + if (!node.model.$isdraggable) { + return null; + } + return node; + } + if (node.parentElement.model) { + if (!node.parentElement.model.$isdraggable) { + return null; + } + return node.parentElement; + } + return null; +}; +Graph.prototype.startDrag = function (event) { + var graph, i, n = this.getDragNode(event.currentTarget); + if (!n) { + return; + } + if (this.objDrag) { + return; + } + this.objDrag = n; + graph = this.objDrag.parentElement; + if (graph) { + for (i = 0; i < graph.children.length; i += 1) { + this.setSelectable(graph.children[i], "on"); + } + } + this.offset.x = this.isIE ? window.event.clientX : event.pageX; + this.offset.y = this.isIE ? window.event.clientY : event.pageY; + this.startObj.x = this.objDrag.model.x; + this.startObj.y = this.objDrag.model.y; +}; +Graph.prototype.doDrag = function (event) { + var x, y; + this.mouse.x = this.isIE ? window.event.clientX : event.pageX; + this.mouse.y = this.isIE ? window.event.clientY : event.pageY; + + if (this.objDrag !== null) { + x = (this.mouse.x - this.offset.x) + this.startObj.x; + y = (this.mouse.y - this.offset.y) + this.startObj.y; + + if (this.model.options.display === "svg") { + x = x - this.startObj.x; + y = y - this.startObj.y; + this.objDrag.setAttribute('transform', "translate(" + x + " " + y + ")"); + } else { + this.drawer.setPos(this.objDrag, x, y); + if (this.objDrag.model) { + this.objDrag.model.x = x; + this.objDrag.model.y = y; + this.objDrag.model.$parent.resize(this.model); + } + } + } +}; +Graph.prototype.stopDrag = function (event) { + var x, y, z, item, entry, parent, pos; + if (!this.objDrag) { + return; + } + if (!(event.type === "mouseup" || event.type === "mouseout") && !event.currentTarget.isdraggable) { + return; + } + if (event.type === "mouseout") { + x = this.isIE ? window.event.clientX : event.pageX; + y = this.isIE ? window.event.clientY : event.pageY; + if (x < this.board.offsetWidth && y < this.board.offsetHeight) { + return; + } + } + item = this.objDrag; + this.objDrag = null; + entry = item.parentElement; + if (entry) { + for (z = 0; z < entry.children.length; z += 1) { + this.setSelectable(entry.children[z], null); + } + } + parent = item.parentElement; + if (item.model) { + if (this.model.options.display === "svg") { + if (item.getAttributeNS(null, "transform")) { + z = item.getAttributeNS(null, "transform"); + if (z.substring(0, 6) !== "rotate") { + pos = z.slice(10, -1).split(' '); + item.model.x = item.model.x + Number(pos[0]); + item.model.y = item.model.y + Number(pos[1]); + } + } + item.model.$center = new Pos(item.model.x + (item.model.width / 2), item.model.y + (item.model.height / 2)); + parent.removeChild(item); + if (item.model.board) { + item.model.board = null; + } + } else { + this.board.removeChild(item); + } + + if (item.model.type === "Info") { + item.model.custom = true; + item.model.$edge.removeElement(item); + entry = item.model.$edge.getInfo(item.model); + item.model.$edge.drawText(this.board, this.drawer, entry, item.model); + } else { + item.model.$gui = this.drawer.getNode(item.model, true); + if (item.model.$gui) { + parent.appendChild(item.model.$gui); + } + entry = item.model.getEdges(); + for (z = 0; z < entry.length; z += 1) { + entry[z].source.custom = false; + entry[z].target.custom = false; + } + } + parent = item.model.$parent; + entry = parent; + while (entry) { + this.resize(entry); + entry = entry.$parent; + } + if (parent.$parent) { + this.redrawNode(parent, true); + this.resize(this.model); + } else { + this.resize(parent); + } + } +}; +Graph.prototype.redrawNode = function (node, draw) { + var infoTxt, parent = node.$gui.parentElement; + parent.removeChild(node.$gui); + if (node.board) { + node.board = null; + } + if (node.type === "Info") { + infoTxt = node.edge.getInfo(node.node); + node.edge.drawText(this.board, this.drawer, infoTxt, node.node); + } else { + node.$gui = this.drawer.getNode(node, draw); + if (node.$gui) { + parent.appendChild(node.$gui); + } + } + node.$center = new Pos(node.x + (node.width / 2), node.y + (node.height / 2)); + this.resize(node.$parent); +}; +Graph.prototype.initDrawer = function (typ) { + if (typ) { + typ = typ.toLowerCase(); + if (this.model.options.display === typ) { + return; + } + this.model.options.display = typ; + } else { + typ = this.model.options.display; + } + this.clearBoard(); + if (typ === "html") { + this.drawer = new Drawer.HTMLDrawer(); + } else if (typ === "svg") { + this.drawer = new Drawer.SVGDrawer(); + } + this.board = this.drawer.getBoard(this); + this.model.$gui = this.board; + this.initDragAndDrop(); + this.root.appendChild(this.board); +}; +Graph.prototype.serializeXmlNode = function (xmlNode) { + if (window.XMLSerializer !== undefined) { + return (new window.XMLSerializer()).serializeToString(xmlNode); + } + if (xmlNode.xml !== undefined) { + return xmlNode.xml; + } + return xmlNode.outerHTML; +}; +Graph.prototype.utf8$to$b64 = function (str) { + return window.btoa(unescape(encodeURIComponent(str))); +}; +Graph.prototype.ExportPDF = function () { + var converter, pdf = new jsPDF('l','px',[this.model.width, this.model.height]); + converter = new svgConverter(this.board, pdf, {removeInvalid: false}); + pdf.save('Download.pdf'); +}; +Graph.prototype.ExportEPS = function () { + var converter, doc = new svgConverter.jsEPS({inverting: true}); + converter = new svgConverter(this.board, doc, {removeInvalid: false}); + doc.save(); +}; +Graph.prototype.ExportPNG = function () { + var canvas, context, a, image = new Image(); + image.src = 'data:image/svg+xml;base64,' + this.utf8$to$b64(this.serializeXmlNode(this.board)); + image.onload = function () { + canvas = document.createElement('canvas'); + canvas.width = image.width; + canvas.height = image.height; + context = canvas.getContext('2d'); + context.drawImage(image, 0, 0); + a = document.createElement('a'); + a.download = "download.png"; + a.href = canvas.toDataURL('image/png'); + a.click(); + }; +}; +Graph.prototype.SaveAs = function (typ) { + typ = typ.toLowerCase(); + if (typ === "svg") { + this.Save("image/svg+xml", this.serializeXmlNode(this.board), "download.svg"); + } else if (typ === "html") { + this.ExportHTML(); + } else if (typ === "png") { + this.ExportPNG(); + } else if (typ === "pdf") { + this.ExportPDF(); + } else if (typ === "eps") { + this.ExportEPS(); + } +}; +Graph.prototype.SavePosition = function () { + var data = [], node, id; + for (id in this.model.nodes) { + node = this.model.nodes[id]; + data.push({id: node.id, x: node.x, y: node.y}); + } + if (window.localStorage && this.model.id) { + window.localStorage.setItem(this.model.id, JSON.stringify(data)); + } +}; +Graph.prototype.LoadPosition = function () { + if (this.model.id && window.localStorage) { + var node, id, data = window.localStorage.getItem(this.model.id); + if (data) { + data = JSON.parse(data); + for (id in data) { + node = data[id]; + if (this.model.nodes[node.id]) { + this.model.nodes[node.id].x = node.x; + this.model.nodes[node.id].y = node.y; + } + } + this.clearBoard(true); + this.draw(this.model); + } + } +}; +Graph.prototype.Save = function (typ, data, name) { + var a = document.createElement("a"); + a.href = window.URL.createObjectURL(new Blob([data], {type: typ})); + a.download = name; + a.click(); +}; +Graph.prototype.ExportHTML = function () { + var data, json = this.model.toJson(); + data = "" + document.head.innerHTML.trim() + "