basic topology rendering widget using pintura and static dependencies
61
public/Pintura/css/colours.css
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
#menu {
|
||||||
|
color:#fff!important;
|
||||||
|
background-color:#000!important
|
||||||
|
}
|
||||||
|
.dark-grey-background {
|
||||||
|
color:black;
|
||||||
|
background:#aaa;
|
||||||
|
}
|
||||||
|
.light-grey-background {
|
||||||
|
color:black;
|
||||||
|
background:#ddd;
|
||||||
|
}
|
||||||
|
.blue-grey-background {
|
||||||
|
color:white;
|
||||||
|
background:#607d8b;
|
||||||
|
}
|
||||||
|
.floating-panel-item {
|
||||||
|
font-size:12px;
|
||||||
|
}
|
||||||
|
#floating-panel-list-div {
|
||||||
|
background:#aaa;
|
||||||
|
}
|
||||||
|
.floating-panel-list {
|
||||||
|
background:grey;
|
||||||
|
border:none;
|
||||||
|
}
|
||||||
|
.w3-ul li {
|
||||||
|
border-bottom:0px;
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
background:#607d8b;
|
||||||
|
border-right:thick solid white;
|
||||||
|
}
|
||||||
|
.component-type-name {
|
||||||
|
color:black;
|
||||||
|
font-size:12px;
|
||||||
|
}
|
||||||
|
.floating-panel-name {
|
||||||
|
font-size:12px;
|
||||||
|
}
|
||||||
|
.dark-font {
|
||||||
|
color:black;
|
||||||
|
}
|
||||||
|
.dropdown-menu {
|
||||||
|
border:medium solid black;
|
||||||
|
background:#607d8b;
|
||||||
|
border:medium solid black;
|
||||||
|
border-width: 1px 1px 1px 1px;
|
||||||
|
}
|
||||||
|
.dropdown-menu h4 {
|
||||||
|
color:white;
|
||||||
|
}
|
||||||
|
.dropdown-menu a {
|
||||||
|
color: black;
|
||||||
|
background:#ddd;
|
||||||
|
font-size:14px;
|
||||||
|
}
|
||||||
|
.dropdown-menu a:hover {
|
||||||
|
background:#bbb;
|
||||||
|
color: white;
|
||||||
|
}
|
84
public/Pintura/css/svg.css
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
.bar {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlighted-node:hover {
|
||||||
|
stroke: #ff0;
|
||||||
|
}
|
||||||
|
|
||||||
|
line {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.line {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
.terminal-connnode {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.terminal-toponode {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.conduct {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.unknown {
|
||||||
|
stroke: #f0f;
|
||||||
|
stroke-width: 1px;
|
||||||
|
height: 20px;
|
||||||
|
width: 20px;
|
||||||
|
}
|
||||||
|
.acline {
|
||||||
|
stroke: #000;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
#backing {
|
||||||
|
fill: whitesmoke;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Below here are SVG elements that we don't want the user to interact with
|
||||||
|
therefore we disable pointer events */
|
||||||
|
|
||||||
|
.svglabel {
|
||||||
|
visibility: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||||
|
-moz-user-select: none; /* Firefox all */
|
||||||
|
-ms-user-select: none; /* IE 10+ */
|
||||||
|
}
|
||||||
|
.svglabel-high {
|
||||||
|
visibility: visible;
|
||||||
|
font-size: 12px;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
text-anchor: right;
|
||||||
|
fill: black;
|
||||||
|
stroke-width: 1px;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||||
|
-moz-user-select: none; /* Firefox all */
|
||||||
|
-ms-user-select: none; /* IE 10+ */
|
||||||
|
}
|
||||||
|
.gridLine {
|
||||||
|
stroke: #aaa;
|
||||||
|
stroke-width: 1px;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||||
|
-moz-user-select: none; /* Firefox all */
|
||||||
|
-ms-user-select: none; /* IE 10+ */
|
||||||
|
}
|
||||||
|
.gridLabel {
|
||||||
|
font-size: 8px;
|
||||||
|
font-family: "sans-serif";
|
||||||
|
fill: grey;
|
||||||
|
stroke-width: 0px;
|
||||||
|
pointer-events: none;
|
||||||
|
-webkit-user-select: none; /* Chrome all / Safari all */
|
||||||
|
-moz-user-select: none; /* Firefox all */
|
||||||
|
-ms-user-select: none; /* IE 10+ */
|
||||||
|
}
|
1225
public/Pintura/images/Pintura_logo.svg
Normal file
After Width: | Height: | Size: 65 KiB |
24
public/Pintura/images/brea.svg
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="4" y="4" height="16" width="16" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
<line x1="4" y1="12" x2="8" y2="12" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
<line x1="8" y1="12" x2="14" y2="8" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
<line x1="15" y1="12" x2="20" y2="12" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
21
public/Pintura/images/conn.svg
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="27" width="27" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle id="circle" cx="13" cy="14" r="6" fill-opacity="1" stroke="black" stroke-width="1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 909 B |
22
public/Pintura/images/cons.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<polygon points="7,10 17,10 12,24" style="fill:black;stroke:black;stroke-width:1" />
|
||||||
|
<line x1="12" y1="3" x2="12" y2="22" style="fill:black;stroke:black;stroke-width:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 991 B |
27
public/Pintura/images/net.svg
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="36" width="36" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<pattern id="diagonalHatch" width="8" height="8" patternUnits="userSpaceOnUse">
|
||||||
|
<line x1="0" y1="0" x2="8" y2="8" style="stroke:black; stroke-width:1" />
|
||||||
|
<line x1="8" y1="0" x2="0" y2="8" style="stroke:black; stroke-width:1" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<rect x="6" y="6" width="24" height="24" style="fill:url(#diagonalHatch);stroke:black;stroke-width:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
32
public/Pintura/images/sol.svg
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="36" width="36" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<marker id="arrow" markerWidth="10" markerHeight="10" refX="0" refY="3" orient="auto" markerUnits="strokeWidth">
|
||||||
|
<path d="M0,2 L0,4 L2,3 z" fill="#000" />
|
||||||
|
</marker>
|
||||||
|
<pattern id="diagonalHatch" width="8" height="8" patternUnits="userSpaceOnUse">
|
||||||
|
<line x1="8" y1="0" x2="0" y2="8" style="stroke:black; stroke-width:1" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
<line x1="8" y1="8" x2="12" y2="12" stroke="#000" stroke-width="3" marker-end="url(#arrow)" />
|
||||||
|
<line x1="16" y1="8" x2="20" y2="12" stroke="#000" stroke-width="3" marker-end="url(#arrow)" />
|
||||||
|
<rect x="6" y="18" width="24" height="12" style="fill:url(#diagonalHatch);stroke:black;stroke-width:1" />
|
||||||
|
<rect x="6" y="6" width="24" height="24" style="fill:none;stroke:black;stroke-width:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.6 KiB |
22
public/Pintura/images/sync.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle id="circle" cx="12" cy="12" r="10" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
<path d="M4 12 C 6 5, 10 5, 12 12 S 19 19, 20 12" stroke="black" fill="transparent"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1,000 B |
21
public/Pintura/images/term.svg
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<rect x="8" y="8" width="8" height="8" style="fill:black;stroke:black;stroke-width:1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 904 B |
22
public/Pintura/images/topo.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="12" width="12" xmlns="http://www.w3.org/2000/svg" stroke-width="1">
|
||||||
|
<circle cx="6" cy="6" r="1" fill-opacity="1" stroke="black" stroke-width="1" />
|
||||||
|
<rect x="0" y="0" height="12" width="12" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1,009 B |
22
public/Pintura/images/trans.svg
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
<?xml version="1.0"?>
|
||||||
|
<!--
|
||||||
|
Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
Authors: Richard Marston
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
in the top level directory of this source tree.
|
||||||
|
-->
|
||||||
|
<svg height="24" width="24" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<circle id="leftcircle" cx="13" cy="10" r="7" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
<circle id="rightcircle" cx="13" cy="14" r="7" fill-opacity="0" stroke="black" stroke-width="1" />
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1,016 B |
197
public/Pintura/js/cimjson.js
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
* Authors: Richard Marston
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
* in the top level directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cimjson = cimjson || (function() {
|
||||||
|
|
||||||
|
const imageNames = {
|
||||||
|
"cim:ACLineSegment": "images/term.svg",
|
||||||
|
"cim:Terminal": "images/term.svg",
|
||||||
|
"cim:Breaker": "images/brea.svg",
|
||||||
|
"cim:ConnectivityNode": "images/conn.svg",
|
||||||
|
"cim:EnergyConsumer": "images/cons.svg",
|
||||||
|
"cim:EquivalentInjection": "images/cons.svg",
|
||||||
|
"cim:ExternalNetworkInjection": "images/net.svg",
|
||||||
|
"cim:PowerTransformer": "images/trans.svg",
|
||||||
|
"cim:SolarGeneratingUnit": "images/solar.svg",
|
||||||
|
"cim:SynchronousMachine": "images/sync.svg",
|
||||||
|
"cim:TopologicalNode": "images/topo.svg",
|
||||||
|
"cim:TransformerWinding": "images/trans.svg",
|
||||||
|
};
|
||||||
|
|
||||||
|
const PinturaDiagramObjectPoints = "Pintura:DiagramObjectPoints";
|
||||||
|
|
||||||
|
var getImageName = function(type) {
|
||||||
|
return imageNames[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
var convertDiagramObjectToTemplateFormat = function(diagramObject, graph, categoryGraphName, diagramList) {
|
||||||
|
|
||||||
|
let originalPoints = diagramObject[PinturaDiagramObjectPoints];
|
||||||
|
let preOffsetPoints = [];
|
||||||
|
let imagePoints = [];
|
||||||
|
let labelPoint;
|
||||||
|
let object;
|
||||||
|
let categoryGraph = graph[categoryGraphName];
|
||||||
|
const imageHeight = 12;
|
||||||
|
const imageWidth = 12;
|
||||||
|
if (diagramObject["cim:DiagramObject.IdentifiedObject"] != undefined) {
|
||||||
|
let rdfId = diagramObject["cim:DiagramObject.IdentifiedObject"]["rdf:resource"].substring(1);
|
||||||
|
for (let index in originalPoints) {
|
||||||
|
let point = originalPoints[index];
|
||||||
|
preOffsetPoints.push(
|
||||||
|
{
|
||||||
|
"x": parseInt(point["cim:DiagramObjectPoint.xPosition"]).toString(),
|
||||||
|
"y": parseInt(point["cim:DiagramObjectPoint.yPosition"]).toString()
|
||||||
|
});
|
||||||
|
imagePoints.push(
|
||||||
|
{
|
||||||
|
"imageHeight" : imageHeight.toString(),
|
||||||
|
"imageWidth" : imageWidth.toString(),
|
||||||
|
"x" : (parseInt(point["cim:DiagramObjectPoint.xPosition"]) - (imageWidth/2)).toString(),
|
||||||
|
"y" : (parseInt(point["cim:DiagramObjectPoint.yPosition"]) - (imageHeight/2)).toString()
|
||||||
|
});
|
||||||
|
};
|
||||||
|
labelPoint = {
|
||||||
|
"x": (parseInt(preOffsetPoints[0].x) + (imageWidth/2)).toString(),
|
||||||
|
"y": (parseInt(preOffsetPoints[0].y) - (imageHeight/2)).toString()
|
||||||
|
};
|
||||||
|
object =
|
||||||
|
{
|
||||||
|
"pintura:image" : getImageName(categoryGraphName),
|
||||||
|
"pintura:rdfId" : rdfId,
|
||||||
|
"pintura:points" : imagePoints,
|
||||||
|
"pintura:label" : {
|
||||||
|
"text": categoryGraph[rdfId]["cim:IdentifiedObject.name"],
|
||||||
|
"x" : labelPoint.x,
|
||||||
|
"y" : labelPoint.y
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (preOffsetPoints.length > 1) {
|
||||||
|
if (object["pintura:line"] == null) {
|
||||||
|
object["pintura:line"] = [];
|
||||||
|
}
|
||||||
|
let line = {
|
||||||
|
"x1": preOffsetPoints[0].x,
|
||||||
|
"y1": preOffsetPoints[0].y,
|
||||||
|
"x2": preOffsetPoints[1].x,
|
||||||
|
"y2": preOffsetPoints[1].y
|
||||||
|
};
|
||||||
|
object["pintura:line"].push(line);
|
||||||
|
preOffsetPoints.shift()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let diagram = diagramObject["cim:DiagramObject.Diagram"]["rdf:resource"].substring(1);
|
||||||
|
if (diagramList[diagram] === undefined){
|
||||||
|
diagramList[diagram] = { "pintura:name" : graph["cim:Diagram"][diagram]["cim:IdentifiedObject.name"] };
|
||||||
|
}
|
||||||
|
if (diagramObject["cim:DiagramObject.IdentifiedObject"]) {
|
||||||
|
let identifiedObject = diagramObject["cim:DiagramObject.IdentifiedObject"]["rdf:resource"].substring(1);
|
||||||
|
if (diagramList[diagram]["components"] === undefined){
|
||||||
|
diagramList[diagram]["components"] = {};
|
||||||
|
}
|
||||||
|
if (diagramList[diagram]["components"][categoryGraphName] === undefined){
|
||||||
|
diagramList[diagram]["components"][categoryGraphName] = {};
|
||||||
|
}
|
||||||
|
diagramList[diagram]["components"][categoryGraphName][identifiedObject] = object;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var convertToTemplatableFormat = function(diagramObjects, graph) {
|
||||||
|
|
||||||
|
let output = { 'Diagram' : {} };
|
||||||
|
let diagramList = output['Diagram'];
|
||||||
|
|
||||||
|
for (categoryGraphName in imageNames) {
|
||||||
|
|
||||||
|
let categoryGraph = graph[categoryGraphName];
|
||||||
|
for (let key in categoryGraph) {
|
||||||
|
let diagramObject = diagramObjects[key];
|
||||||
|
if (diagramObject != undefined) {
|
||||||
|
convertDiagramObjectToTemplateFormat(diagramObject, graph, categoryGraphName, diagramList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
};
|
||||||
|
|
||||||
|
var indexDiagramGraphByComponentType = function(input) {
|
||||||
|
/*
|
||||||
|
* Index the diagram object graph by the identified object's id so we don't
|
||||||
|
* have to go hunting for the referenced object inside the diagram objects.
|
||||||
|
*/
|
||||||
|
let graph = {};
|
||||||
|
for (let key in input) {
|
||||||
|
let diagramObject = input[key];
|
||||||
|
let diagram = diagramObject["cim:DiagramObject.Diagram"]["rdf:resource"].substring(1);
|
||||||
|
if (diagramObject["cim:DiagramObject.IdentifiedObject"]) {
|
||||||
|
let identifiedObject = input[key]["cim:DiagramObject.IdentifiedObject"]["rdf:resource"].substring(1);
|
||||||
|
graph[identifiedObject] = input[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
};
|
||||||
|
|
||||||
|
var addDiagramObjectPointsToDiagramObjects = function(diagramObjectPointGraph, diagramObjectGraph){
|
||||||
|
for (let key in diagramObjectPointGraph) {
|
||||||
|
mergeMatchingDataIntoParentNodeArray(diagramObjectPointGraph[key], "cim:DiagramObjectPoint.DiagramObject", diagramObjectGraph, PinturaDiagramObjectPoints);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create link to a member of an array of e.g. points
|
||||||
|
*/
|
||||||
|
var mergeMatchingDataIntoParentNodeArray = function(node, matchingElement, destinationGraph, destinationElement) {
|
||||||
|
if (node[matchingElement]) {
|
||||||
|
let id = node[matchingElement]["rdf:resource"].substr(1);
|
||||||
|
if (destinationGraph[id]) {
|
||||||
|
if (destinationGraph[id][destinationElement] === undefined) {
|
||||||
|
destinationGraph[id][destinationElement] = [];
|
||||||
|
}
|
||||||
|
destinationGraph[id][destinationElement].push(node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Could not find destination "+matchingElement+" to merge into "+destinationElement+".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log("Could not find matching element "+matchingElement+" to merge "+destinationElement+" into .");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var getTemplateJson = function(graph) {
|
||||||
|
let updatedDiagramObjects = JSON.parse(JSON.stringify(graph['cim:DiagramObject']));
|
||||||
|
let diagramObjectPoints = graph['cim:DiagramObjectPoint'];
|
||||||
|
addDiagramObjectPointsToDiagramObjects(diagramObjectPoints, updatedDiagramObjects);
|
||||||
|
|
||||||
|
let diagramObjectsByIdentifiedObjects = indexDiagramGraphByComponentType(updatedDiagramObjects);
|
||||||
|
|
||||||
|
templateReadyFormat = convertToTemplatableFormat(diagramObjectsByIdentifiedObjects, graph);
|
||||||
|
|
||||||
|
return templateReadyFormat;
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
getTemplateJson,
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = {
|
||||||
|
cimjson
|
||||||
|
};
|
||||||
|
}
|
140
public/Pintura/js/cimsvg.js
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
* Authors: Richard Marston
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
* in the top level directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cimsvg = cimsvg || (function() {
|
||||||
|
|
||||||
|
var svgNode = null;
|
||||||
|
var xmlNode = null;
|
||||||
|
var pinturaNode = null;
|
||||||
|
var sidebarNode = null;
|
||||||
|
|
||||||
|
function handler() {
|
||||||
|
//console.log(this.getResponseHeader('content-type'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var includeFile = function(fileName, callback) {
|
||||||
|
let dom = svgNode.ownerDocument;
|
||||||
|
let newTag = dom.createElement("script");
|
||||||
|
newTag.type = "text/javascript";
|
||||||
|
newTag.src=fileName;
|
||||||
|
if ( callback != undefined ) {
|
||||||
|
newTag.onload=function() {
|
||||||
|
callback();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
svgNode.parentElement.appendChild(newTag);
|
||||||
|
};
|
||||||
|
|
||||||
|
var applyTemplate = function(data) {
|
||||||
|
var template = Handlebars.templates['cim2svg'];
|
||||||
|
return template(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadFile = function(fileContents) {
|
||||||
|
if (cimxml.moreXmlData(fileContents)) {
|
||||||
|
baseJson = cimxml.getBaseJson();
|
||||||
|
templateJson = cimjson.getTemplateJson(baseJson);
|
||||||
|
svgNode.ownerDocument.getElementById('diagrams').innerHTML = applyTemplate(templateJson);
|
||||||
|
if(sidebarNode != null) {
|
||||||
|
cimmenu.populateSidebar(sidebarNode, templateJson);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var setFileCount = function(count) {
|
||||||
|
cimxml.setRdfFileCount(count);
|
||||||
|
};
|
||||||
|
|
||||||
|
var isNode = false;
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
isNode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var updateComponent = function(type, id, attribute, value) {
|
||||||
|
cimxml.updateComponentInBaseJson(type, id, attribute, value)
|
||||||
|
baseJson = cimxml.getBaseJson();
|
||||||
|
templateJson = cimjson.getTemplateJson(baseJson);
|
||||||
|
if (attribute === "cim:IdentifiedObject.name") {
|
||||||
|
buttonId = '#' + id + "-sidebar-button"
|
||||||
|
button = sidebarNode.querySelector(buttonId)
|
||||||
|
button.innerHTML = value;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var loadXml = function(fileName, callback) {
|
||||||
|
// Create a connection to the file.
|
||||||
|
var Connect = new XMLHttpRequest();
|
||||||
|
// Define which file to open and
|
||||||
|
Connect.open("GET", fileName, true);
|
||||||
|
Connect.setRequestHeader("Content-Type", "text/xml");
|
||||||
|
Connect.onreadystatechange = handler;
|
||||||
|
Connect.onload = function (e) {
|
||||||
|
if(Connect.readyState === 4) {
|
||||||
|
if(Connect.status === 200) {
|
||||||
|
callback(Connect.responseXML);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log(Connect.statusText);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// send the request.
|
||||||
|
Connect.send(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
init : function(svg, sidebar, componentAttributes, componentCreation) {
|
||||||
|
svgNode = svg;
|
||||||
|
sidebarNode = sidebar;
|
||||||
|
includeFile("handlebars.runtime.js", function() {
|
||||||
|
includeFile("src/cimview.js", function() {
|
||||||
|
cimview.init(svgNode);
|
||||||
|
if(sidebarNode != undefined) {
|
||||||
|
includeFile("src/cimmenu.js", function() {
|
||||||
|
cimmenu.init(componentAttributes)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
includeFile("templates/template.js", function(){
|
||||||
|
includeFile("src/cimxml.js", function(){
|
||||||
|
includeFile("src/cimjson.js", function(){});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
loadXml("templates/generated_add_components/menu.xml", function(xml){
|
||||||
|
if(componentCreation != undefined) {
|
||||||
|
accordion = componentCreation.querySelector('#component-creation-list-div')
|
||||||
|
accordion.innerHTML = xml.documentElement.innerHTML;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setSVG : function(svg) {
|
||||||
|
svgNode = svg;
|
||||||
|
},
|
||||||
|
loadFile,
|
||||||
|
setFileCount,
|
||||||
|
updateComponent,
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
||||||
|
if (cimsvg.isNode) {
|
||||||
|
module.exports = {
|
||||||
|
cimsvg
|
||||||
|
}
|
||||||
|
}
|
208
public/Pintura/js/cimview.js
Normal file
|
@ -0,0 +1,208 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
* Authors: Richard Marston
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
* in the top level directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cimview = cimview || (function() {
|
||||||
|
|
||||||
|
var svgNode = null;
|
||||||
|
|
||||||
|
var zoomSizes = [
|
||||||
|
{ width: 1024, height: 768 },
|
||||||
|
{ width: 920, height: 690 },
|
||||||
|
{ width: 816, height: 612 },
|
||||||
|
{ width: 712, height: 532 },
|
||||||
|
{ width: 608, height: 456 },
|
||||||
|
{ width: 504, height: 378 },
|
||||||
|
{ width: 400, height: 300 },
|
||||||
|
];
|
||||||
|
|
||||||
|
var zoomLevel = 0;
|
||||||
|
|
||||||
|
var zoomToLevel = function(level) {
|
||||||
|
zoomLevel = level;
|
||||||
|
let rect = getViewBox();
|
||||||
|
centreOfGrid = { x: rect.x + rect.width / 2, y: rect.y + rect.height / 2 };
|
||||||
|
rect.width = zoomSizes[level].width;
|
||||||
|
rect.height = zoomSizes[level].height;
|
||||||
|
rect.x = centreOfGrid.x - (rect.width / 2);
|
||||||
|
rect.y = centreOfGrid.y - (rect.height / 2);
|
||||||
|
setViewBox(rect);
|
||||||
|
};
|
||||||
|
|
||||||
|
var zoomOut = function() {
|
||||||
|
let level = zoomLevel-1;
|
||||||
|
if (level < 0) {
|
||||||
|
level = 0;
|
||||||
|
}
|
||||||
|
zoomToLevel(level);
|
||||||
|
//document.getElementById("zoomer").value=level;
|
||||||
|
};
|
||||||
|
|
||||||
|
var zoomIn = function() {
|
||||||
|
let level = zoomLevel+1;
|
||||||
|
let lastIndex = zoomSizes.length-1;
|
||||||
|
if (level > lastIndex) {
|
||||||
|
level = lastIndex;
|
||||||
|
}
|
||||||
|
zoomToLevel(level);
|
||||||
|
//document.getElementById("zoomer").value=level;
|
||||||
|
};
|
||||||
|
|
||||||
|
var pan = function(point) {
|
||||||
|
let rect = getViewBox();
|
||||||
|
rect.x += point.x;
|
||||||
|
rect.y += point.y;
|
||||||
|
setViewBox(rect);
|
||||||
|
};
|
||||||
|
|
||||||
|
var clearGrid = function() {
|
||||||
|
let oldLines = Array.from(svgNode.getElementsByClassName("gridLine"));
|
||||||
|
oldLines.forEach(function(key) {
|
||||||
|
key.remove();
|
||||||
|
});
|
||||||
|
let oldLabels = Array.from(svgNode.getElementsByClassName("gridLabel"));
|
||||||
|
oldLabels.forEach(function(key) {
|
||||||
|
key.remove();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var createLocationMarker = function(id, loc, x, y) {
|
||||||
|
let grid = svgNode.ownerDocument.getElementById("grid");
|
||||||
|
let textAttributes = {
|
||||||
|
"x": x,
|
||||||
|
"y": y,
|
||||||
|
"class": "gridLabel",
|
||||||
|
"id": id,
|
||||||
|
};
|
||||||
|
let text = createSvgTag("text", textAttributes);
|
||||||
|
text.innerHTML = loc;
|
||||||
|
grid.appendChild(text);
|
||||||
|
};
|
||||||
|
|
||||||
|
var createGridLine = function(x1, y1, x2, y2) {
|
||||||
|
let grid = svgNode.ownerDocument.getElementById("grid");
|
||||||
|
let lineAttributes = {
|
||||||
|
"x1": x1,
|
||||||
|
"x2": x2,
|
||||||
|
"y1": y1,
|
||||||
|
"y2": y2,
|
||||||
|
"class": "gridLine",
|
||||||
|
};
|
||||||
|
let line = createSvgTag("line", lineAttributes);
|
||||||
|
grid.appendChild(line);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a tag in the svg namespace
|
||||||
|
*/
|
||||||
|
const createSvgTag = function(tagname, attributes) {
|
||||||
|
let xmlns="http://www.w3.org/2000/svg";
|
||||||
|
let newTag = svgNode.ownerDocument.createElementNS(xmlns, tagname);
|
||||||
|
for (let key in attributes) {
|
||||||
|
newTag.setAttribute(key, attributes[key]);
|
||||||
|
}
|
||||||
|
return newTag;
|
||||||
|
};
|
||||||
|
|
||||||
|
var calculateStartOffset = function(distanceFromOrigin, gridSize) {
|
||||||
|
let offset;
|
||||||
|
if (distanceFromOrigin < 0) {
|
||||||
|
offset = distanceFromOrigin - ( distanceFromOrigin % gridSize );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
offset = distanceFromOrigin + gridSize - ( distanceFromOrigin % gridSize );
|
||||||
|
}
|
||||||
|
return offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
var createGrid = function() {
|
||||||
|
clearGrid();
|
||||||
|
let gridSize = 100;
|
||||||
|
let viewBoxRect = getViewBox();
|
||||||
|
/* horizontal lines */
|
||||||
|
let startOffsetY = calculateStartOffset(viewBoxRect.y, gridSize);
|
||||||
|
let startOffsetX = calculateStartOffset(viewBoxRect.x, gridSize);
|
||||||
|
for (let i=0; i<(viewBoxRect.height/gridSize); i++) {
|
||||||
|
let yval = i*gridSize+startOffsetY;
|
||||||
|
createGridLine(viewBoxRect.x, yval, viewBoxRect.width+viewBoxRect.x, yval);
|
||||||
|
createLocationMarker(yval+"y", yval.toString(), viewBoxRect.x+10, yval+20);
|
||||||
|
}
|
||||||
|
/* vertical lines */
|
||||||
|
for (let i=0; i<(viewBoxRect.width/gridSize); i++) {
|
||||||
|
let xval = i*gridSize+startOffsetX;
|
||||||
|
createGridLine(xval, viewBoxRect.y, xval, viewBoxRect.height+viewBoxRect.y);
|
||||||
|
createLocationMarker(xval+"x", xval.toString(), xval+10, viewBoxRect.y+20);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var getViewBox = function() {
|
||||||
|
let rect = {};
|
||||||
|
viewBoxString = svgNode.getAttribute("viewBox");
|
||||||
|
viewBoxElements = viewBoxString.split(" ");
|
||||||
|
rect.x = parseInt(viewBoxElements[0]);
|
||||||
|
rect.y = parseInt(viewBoxElements[1]);
|
||||||
|
rect.width = parseInt(viewBoxElements[2]);
|
||||||
|
rect.height = parseInt(viewBoxElements[3]);
|
||||||
|
return rect;
|
||||||
|
};
|
||||||
|
|
||||||
|
var setViewBox = function(rect) {
|
||||||
|
let viewBoxString = rect.x+" "+rect.y+" "+rect.width+" "+rect.height;
|
||||||
|
svgNode.setAttribute("viewBox", viewBoxString);
|
||||||
|
let bg = svgNode.ownerDocument.getElementById("backing");
|
||||||
|
bg.setAttribute("x", rect.x);
|
||||||
|
bg.setAttribute("y", rect.y);
|
||||||
|
bg.setAttribute("width", "100%");
|
||||||
|
bg.setAttribute("height", "100%");
|
||||||
|
createGrid();
|
||||||
|
};
|
||||||
|
|
||||||
|
var clearDisplay = function() {
|
||||||
|
while (svgNode.firstChild) {
|
||||||
|
svgNode.removeChild(svgNode.firstChild);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var hideAllLabels = function() {
|
||||||
|
Array.from(svgNode.getElementsByClassName("svglabel")).forEach(function (label) {
|
||||||
|
label.setAttributeNS(null, "visibility", "hidden");
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
var init = function(svg) {
|
||||||
|
svgNode = svg;
|
||||||
|
let rect = { x: "-100", y: "-100", width: "1024", height: "768" };
|
||||||
|
setViewBox(rect);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Specify the functions that this module exports
|
||||||
|
*/
|
||||||
|
return {
|
||||||
|
init,
|
||||||
|
pan,
|
||||||
|
zoomIn,
|
||||||
|
zoomOut,
|
||||||
|
};
|
||||||
|
|
||||||
|
}());
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = {
|
||||||
|
cimview
|
||||||
|
}
|
||||||
|
}
|
253
public/Pintura/js/cimxml.js
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
/*
|
||||||
|
* Copyright © 2016-2017, RWTH Aachen University
|
||||||
|
* Authors: Richard Marston
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU General Public License is in the LICENSE file
|
||||||
|
* in the top level directory of this source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var cimxml = cimxml || (function() {
|
||||||
|
|
||||||
|
var xmlDoc;
|
||||||
|
var rdfFileCount = 0;
|
||||||
|
var rdfFileReceived = 0;
|
||||||
|
var jsonBaseData = null;
|
||||||
|
const xmlnsString = "xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#' xmlns:cim='http://iec.ch/TC57/2012/CIM-schema-cim16#' xmlns:md='http://iec.ch/TC57/61970-552/ModelDescription/1#' xmlns:entsoe='http://entsoe.eu/Secretariat/ProfileExtension/2#'";
|
||||||
|
|
||||||
|
var getRawXML = function() {
|
||||||
|
return xmlDoc;
|
||||||
|
};
|
||||||
|
|
||||||
|
var getBaseJson = function() {
|
||||||
|
return jsonBaseData;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a small data item into XML and add it to a node
|
||||||
|
*/
|
||||||
|
var addChild = function(object, name, doc, owner) {
|
||||||
|
|
||||||
|
let child;
|
||||||
|
if (typeof object == "object") {
|
||||||
|
child = doc.createElement(name);
|
||||||
|
child.setAttribute("rdf:resource", object["rdf:resource"]);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
child = doc.createElement(name);
|
||||||
|
child.innerHTML = object;
|
||||||
|
}
|
||||||
|
owner.appendChild(child);
|
||||||
|
};
|
||||||
|
|
||||||
|
var copyXmlDataIntoObject = function(object, node) {
|
||||||
|
|
||||||
|
let childNodes = node.children;
|
||||||
|
for (let childIndex = 0; childIndex < childNodes.length; childIndex++) {
|
||||||
|
let thisChild = childNodes[childIndex];
|
||||||
|
if (thisChild.nodeType == Node.ELEMENT_NODE) {
|
||||||
|
if (thisChild.attributes.length > 0) {
|
||||||
|
object[thisChild.nodeName] = { "rdf:resource": thisChild.getAttribute("rdf:resource")};
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
object[thisChild.nodeName] = thisChild.innerHTML;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var importXmlNodeIntoGraph = function(graph, nodeCategory, node, id) {
|
||||||
|
|
||||||
|
let thisObject = { };
|
||||||
|
|
||||||
|
thisObject['rdfid'] = id
|
||||||
|
|
||||||
|
copyXmlDataIntoObject(thisObject, node);
|
||||||
|
|
||||||
|
if (!graph[nodeCategory]) {
|
||||||
|
graph[nodeCategory] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add the new object to the graph */
|
||||||
|
let categoryGraph = graph[nodeCategory];
|
||||||
|
categoryGraph[id] = thisObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
var importAboutDataIntoGraph = function(graph, nodeCategory, thisNode, id) {
|
||||||
|
|
||||||
|
if (graph[nodeCategory] && graph[nodeCategory][id]) {
|
||||||
|
let thisObject = graph[nodeCategory][id].about = [];
|
||||||
|
copyXmlDataIntoObject(thisObject, thisNode);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What is the rdf:ID attribute for this node
|
||||||
|
*/
|
||||||
|
var getRdfId = function(node) {
|
||||||
|
|
||||||
|
let rdfId = node.getAttribute("rdf:ID");
|
||||||
|
return rdfId;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* What is the rdf:about attribute for this node
|
||||||
|
*/
|
||||||
|
var getRdfAbout = function(node) {
|
||||||
|
|
||||||
|
let rdfAbout = node.getAttribute("rdf:about");
|
||||||
|
return rdfAbout;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Clear the buffer of XML data that we use to handle multiple file imports
|
||||||
|
*/
|
||||||
|
var clearXmlData = function() {
|
||||||
|
|
||||||
|
xmlDoc = null;
|
||||||
|
};
|
||||||
|
|
||||||
|
var xmlns = function(){
|
||||||
|
|
||||||
|
return xmlnsString;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Function to create a JSON document from an RDF (XML) DOM.
|
||||||
|
* RDF is a shallow xml format so we don"t have to dig too
|
||||||
|
* deep, a node will only ever have children or attributes.
|
||||||
|
*/
|
||||||
|
var createObjectGraphFromXml = function( xmlData ) {
|
||||||
|
|
||||||
|
let graph = {};
|
||||||
|
let topLevelNodes = xmlData.documentElement.childNodes;
|
||||||
|
|
||||||
|
/* loop through all of the top level nodes */
|
||||||
|
for (let topLevelIndex=0; topLevelIndex<topLevelNodes.length; topLevelIndex++) {
|
||||||
|
let thisNode = topLevelNodes[topLevelIndex];
|
||||||
|
if (thisNode.nodeType == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
/* find out what type of node we are reading */
|
||||||
|
let nodeCategory = thisNode.nodeName;
|
||||||
|
let id = getRdfId(thisNode);
|
||||||
|
if (id) {
|
||||||
|
importXmlNodeIntoGraph(graph, nodeCategory, thisNode, id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we need all of the rdf:id nodes before importing the rdf:about nodes */
|
||||||
|
for (let topLevelIndex=0; topLevelIndex<topLevelNodes.length; topLevelIndex++) {
|
||||||
|
let thisNode = topLevelNodes[topLevelIndex];
|
||||||
|
if (thisNode.nodeType == Node.ELEMENT_NODE)
|
||||||
|
{
|
||||||
|
/* find out what type of node we are reading */
|
||||||
|
let nodeCategory = thisNode.nodeName;
|
||||||
|
let id = getRdfAbout(thisNode);
|
||||||
|
if (id) {
|
||||||
|
importAboutDataIntoGraph(graph, nodeCategory, thisNode, id.substr(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return graph;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tell this module how many pieces the data will be arriving in
|
||||||
|
*/
|
||||||
|
var setRdfFileCount = function(count) {
|
||||||
|
|
||||||
|
rdfFileCount = count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Have we received all the data files yet?
|
||||||
|
*/
|
||||||
|
var checkIfParseReady = function() {
|
||||||
|
|
||||||
|
if (rdfFileReceived > 0) {
|
||||||
|
if (rdfFileCount == rdfFileReceived) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Here comes some more data
|
||||||
|
*/
|
||||||
|
var moreXmlData = function(text, draw=true) {
|
||||||
|
|
||||||
|
if (!xmlDoc) {
|
||||||
|
xmlDoc = getDOM("<rdf:RDF "+xmlns()+"/>");
|
||||||
|
}
|
||||||
|
|
||||||
|
let newDoc = getDOM(text);
|
||||||
|
let nodes = newDoc.documentElement.childNodes;
|
||||||
|
for (let i = 0; i < nodes.length; i++) {
|
||||||
|
if (nodes[i].nodeType == Node.ELEMENT_NODE) {
|
||||||
|
if (nodes[i].nodeName != "md:FullModel") {
|
||||||
|
xmlDoc.documentElement.appendChild(nodes[i].cloneNode(true));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rdfFileReceived++;
|
||||||
|
if (checkIfParseReady()) {
|
||||||
|
jsonBaseData = createObjectGraphFromXml(xmlDoc);
|
||||||
|
rdfFileReceived = 0;
|
||||||
|
rdfFileCount = 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Different method of getting DOM required for some platforms
|
||||||
|
*/
|
||||||
|
var getDOM = function(text) {
|
||||||
|
|
||||||
|
let newDoc;
|
||||||
|
if ( window.DOMParser ) {
|
||||||
|
newDoc = ( new DOMParser() ).parseFromString( text, "application/xml" );
|
||||||
|
}
|
||||||
|
else if( window.ActiveXObject ) {
|
||||||
|
let xmlObject = new ActiveXObject( "Microsoft.XMLDOM" );
|
||||||
|
xmlObject.async = false;
|
||||||
|
xmlObject.loadXML( text );
|
||||||
|
newDoc = xmlObject;
|
||||||
|
xmlObject = undefined;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
throw new Error( "Cannot find an XML parser!" );
|
||||||
|
}
|
||||||
|
return newDoc;
|
||||||
|
};
|
||||||
|
|
||||||
|
var updateComponentInBaseJson = function(type, id, attribute, value) {
|
||||||
|
jsonBaseData[type][id][attribute] = value
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
getBaseJson,
|
||||||
|
setRdfFileCount,
|
||||||
|
clearXmlData,
|
||||||
|
moreXmlData,
|
||||||
|
getRawXML,
|
||||||
|
updateComponentInBaseJson,
|
||||||
|
};
|
||||||
|
}());
|
||||||
|
|
||||||
|
if (typeof module !== 'undefined' && module.exports) {
|
||||||
|
module.exports = {
|
||||||
|
cimxml
|
||||||
|
};
|
||||||
|
}
|
1468
public/Pintura/js/handlebars.runtime.js
Normal file
2521
public/Pintura/templates/template.js
Normal file
|
@ -27,5 +27,12 @@
|
||||||
To begin the development, run `npm start`.
|
To begin the development, run `npm start`.
|
||||||
To create a production bundle, use `npm run build`.
|
To create a production bundle, use `npm run build`.
|
||||||
-->
|
-->
|
||||||
|
<link rel="stylesheet" href="%PUBLIC_URL%/Pintura/css/svg.css"/>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/js/cimsvg.js"></script>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/js/cimview.js"></script>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/js/cimxml.js"></script>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/js/cimjson.js"></script>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/js/handlebars.runtime.js"></script>
|
||||||
|
<script type="text/javascript" src="%PUBLIC_URL%/Pintura/templates/template.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
84
src/components/widget-topology.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
/**
|
||||||
|
* File: widget-topology.js
|
||||||
|
* Author: Ricardo Hernandez-Montoya <rhernandez@gridhound.de>
|
||||||
|
* Date: 08.01.2018
|
||||||
|
*
|
||||||
|
* This file is part of VILLASweb.
|
||||||
|
*
|
||||||
|
* VILLASweb is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* VILLASweb is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with VILLASweb. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
const pinturaGridStyle = {
|
||||||
|
display: 'none'
|
||||||
|
}
|
||||||
|
|
||||||
|
class WidgetTopology extends React.Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.input = null;
|
||||||
|
this.svgElem = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
if (this.svgElem) {
|
||||||
|
window.cimsvg.setSVG(this.svgElem);
|
||||||
|
window.cimview.init(this.svgElem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fileReader(e) {
|
||||||
|
let files = e.target.files;
|
||||||
|
if (files) {
|
||||||
|
window.cimxml.clearXmlData()
|
||||||
|
window.cimsvg.setFileCount(files.length);
|
||||||
|
for (var i=0, f; i < files.length; i++) {
|
||||||
|
f=files[i];
|
||||||
|
if (!f) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(e) {
|
||||||
|
var contents = e.target.result;
|
||||||
|
window.cimsvg.loadFile(contents);
|
||||||
|
};
|
||||||
|
reader.readAsText(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
|
||||||
|
let svgLabelStyles = {
|
||||||
|
'fontSize': '10pt',
|
||||||
|
'fill': 'white'
|
||||||
|
}
|
||||||
|
|
||||||
|
return (<div>
|
||||||
|
<input id="fileopen" ref={ c => this.input = c} type="file" multiple="true" onChange={ e => this.fileReader(e)} />
|
||||||
|
<svg ref={ c => this.svgElem = c }width={this.props.widget.width} height={this.props.widget.height}>
|
||||||
|
<rect id="backing"/>
|
||||||
|
<g id="grid" style={pinturaGridStyle} />
|
||||||
|
<g id="diagrams"/>
|
||||||
|
<g>
|
||||||
|
<rect id="testbutton" onClick={ e => console.log('I (%o) was clicked!') } x="2" y="6" width="70" height="20" />
|
||||||
|
<text className="svglabel-high" style={svgLabelStyles} x="8" y="20">Click Me!</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</div>);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default WidgetTopology;
|
|
@ -482,6 +482,7 @@ class Visualization extends React.Component {
|
||||||
<ToolboxItem name="Gauge" type="widget" />
|
<ToolboxItem name="Gauge" type="widget" />
|
||||||
<ToolboxItem name="Box" type="widget" />
|
<ToolboxItem name="Box" type="widget" />
|
||||||
<ToolboxItem name="HTML" type="html" />
|
<ToolboxItem name="HTML" type="html" />
|
||||||
|
<ToolboxItem name="Topology" type="widget" />
|
||||||
|
|
||||||
<div className="section-buttons-group-right">
|
<div className="section-buttons-group-right">
|
||||||
{ editingControls }
|
{ editingControls }
|
||||||
|
|
|
@ -43,6 +43,7 @@ import WidgetSlider from '../components/widget-slider';
|
||||||
import WidgetGauge from '../components/widget-gauge';
|
import WidgetGauge from '../components/widget-gauge';
|
||||||
import WidgetBox from '../components/widget-box';
|
import WidgetBox from '../components/widget-box';
|
||||||
import WidgetHTML from '../components/widget-html';
|
import WidgetHTML from '../components/widget-html';
|
||||||
|
import WidgetTopology from '../components/widget-topology';
|
||||||
|
|
||||||
import '../styles/widgets.css';
|
import '../styles/widgets.css';
|
||||||
|
|
||||||
|
@ -188,6 +189,8 @@ class Widget extends React.Component {
|
||||||
element = <WidgetBox widget={widget} editing={this.props.editing} />
|
element = <WidgetBox widget={widget} editing={this.props.editing} />
|
||||||
} else if (widget.type === 'HTML') {
|
} else if (widget.type === 'HTML') {
|
||||||
element = <WidgetHTML widget={widget} editing={this.props.editing} />
|
element = <WidgetHTML widget={widget} editing={this.props.editing} />
|
||||||
|
} else if (widget.type === 'Topology') {
|
||||||
|
element = <WidgetTopology widget={widget} editing={this.props.editing} />
|
||||||
}
|
}
|
||||||
|
|
||||||
const widgetClasses = classNames({
|
const widgetClasses = classNames({
|
||||||
|
|