diff --git a/README.md b/README.md
index 45090ee..0967e6e 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# CacheUMLExplorer
-An UML Class explorer for InterSystems Caché. It can build UML class diagram for any class in Caché.
+An UML Class explorer for InterSystems Caché. It can build UML class diagram for any class or even for whole package in Caché.
## Screenshots
diff --git a/cache/projectTemplate.xml b/cache/projectTemplate.xml
index 2906f58..632c8fa 100644
--- a/cache/projectTemplate.xml
+++ b/cache/projectTemplate.xml
@@ -4,15 +4,55 @@
Class contains methods that return structured class data.
-63663,69939
+63668,773.59952
63653,67019.989197
+
+1
+%ZEN.proxyObject
+ level) {
+ set level = level + 1
+ set resp = ##class(%ZEN.proxyObject).%New()
+ do objects.GetAt(level - 1).%DispatchSetProperty($LISTGET(parts, level - 1), resp)
+ do objects.SetAt(resp, level)
+ }
+ if ($LISTLENGTH(parts) = level) {
+ do resp.%DispatchSetProperty($LISTGET(parts, level), classes.Data("Hidden"))
+ }
+ set lastParts = parts
+ }
+
+ quit objects.GetAt(1)
+]]>
+
+
1
classDefinition:%Dictionary.ClassDefinition
%ZEN.proxyObject
do oMeth.%DispatchSetProperty("returns", classDefinition.Methods.GetAt(i).ReturnType)
}
- return oClass
+ set oParameters = ##class(%ZEN.proxyObject).%New()
+ set oClass.parameters = oParameters
+ set count = classDefinition.Parameters.Count()
+ for i = 1:1:count {
+ set oPar = ##class(%ZEN.proxyObject).%New()
+ do oParameters.%DispatchSetProperty(classDefinition.Parameters.GetAt(i).Name, oPar)
+ do oPar.%DispatchSetProperty("type", classDefinition.Parameters.GetAt(i).Type)
+ }
+
+ quit oClass
+]]>
+
+
+
+1
+typeName:%String
+%String
+
@@ -50,7 +114,7 @@ Class contains methods that return structured class data.
}
set oInherit = oData.inheritance.%DispatchGetProperty(baseClassDefinition.Name)
for i=1:1:$LISTLENGTH(superParts) {
- set className = $LISTGET(superParts, i)
+ set className = ..extendClassFromType($LISTGET(superParts, i))
do oInherit.%DispatchSetProperty(className, 1)
if (oData.classes.%DispatchGetProperty(className) = "") {
set cdef = ##class(%Dictionary.ClassDefinition).%OpenId(className)
@@ -60,13 +124,14 @@ Class contains methods that return structured class data.
}
}
}
- return $$$OK
+ quit $$$OK
]]>
1
baseClassDefinition:%Dictionary.ClassDefinition
+%ZEN.proxyObject
do ..collectInheritance(oData, baseClassDefinition)
- return oData
+ quit oData
+]]>
+
+
+
+1
+rootPackageName:%String
+%ZEN.proxyObject
+
-
+
-
-
-
+
+
+
@@ -94,7 +185,7 @@ Class contains methods that return structured class data.
REST interface for UMLExplorer
%CSP.REST
-63663,76166.562046
+63667,85509.960346
63648,30450.187229
@@ -107,6 +198,7 @@ REST interface for UMLExplorer
+
]]>
@@ -117,37 +209,7 @@ Method returns whole class tree visible in the current namespace.
1
%Status
level) {
- set level = level + 1
- set resp = ##class(%ZEN.proxyObject).%New()
- do objects.GetAt(level - 1).%DispatchSetProperty($LISTGET(parts, level - 1), resp)
- do objects.SetAt(resp, level)
- }
- if ($LISTLENGTH(parts) = level) {
- do resp.%DispatchSetProperty($LISTGET(parts, level), classes.Data("Hidden"))
- }
- set lastParts = parts
- }
-
- do objects.GetAt(1).%ToJSON(, "ou")
+ do ##class(UMLExplorer.ClassView).getClassTree().%ToJSON(, "ou")
return $$$OK
]]>
@@ -167,6 +229,19 @@ Returns classTree by given class name
]]>
+
+
+Returns all package class trees by given package name
+1
+packageName:%String
+%Status
+
+
+
Method to test accessibility of REST interface.
diff --git a/gulpfile.js b/gulpfile.js
index 6ae71fa..8117730 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -4,6 +4,7 @@ var gulp = require("gulp"),
concat = require("gulp-concat"),
uglify = require("gulp-uglify"),
wrap = require("gulp-wrap"),
+ stripComments = require("gulp-strip-comments"),
addsrc = require('gulp-add-src'),
minifyCSS = require("gulp-minify-css"),
htmlReplace = require("gulp-html-replace"),
@@ -14,6 +15,7 @@ var gulp = require("gulp"),
rename = require("gulp-rename");
var banner = [
+ "",
"/** <%= pkg.name %>",
" ** <%= pkg.description %>",
" ** @author <%= pkg.author %>",
@@ -29,11 +31,10 @@ gulp.task("clean", function () {
.pipe(clean());
});
-gulp.task("gatherScripts", ["clean"], function () {
- return gulp.src("web/js/*.js")
- .pipe(concat("CacheUMLExplorer.js"))
- .pipe(replace(/\/\*\{\{replace:version}}\*\//, "\"" + pkg["version"] + "\""))
- .pipe(wrap("CacheUMLExplorer = (function(){<%= contents %> return CacheUMLExplorer;}());"))
+gulp.task("gatherLibs", ["clean"], function () {
+ return gulp.src([
+ "web/jsLib/joint.shapes.uml.js"
+ ])
.pipe(uglify({
output: {
ascii_only: true,
@@ -41,12 +42,29 @@ gulp.task("gatherScripts", ["clean"], function () {
max_line_len: 30000
}
}))
- .pipe(header(banner, { pkg: pkg }))
.pipe(addsrc.prepend([
"web/jsLib/joint.min.js",
- "web/jsLib/joint.shapes.uml.js",
"web/jsLib/joint.layout.DirectedGraph.min.js"
]))
+ .pipe(stripComments({ safe: true }))
+ .pipe(concat("CacheUMLExplorer.js"))
+ .pipe(gulp.dest("build/web/js/"));
+});
+
+gulp.task("gatherScripts", ["clean", "gatherLibs"], function () {
+ return gulp.src("web/js/*.js")
+ .pipe(concat("CacheUMLExplorer.js"))
+ .pipe(replace(/[^\s]+\/\*build.replace:(.*)\*\//g, "$1"))
+ .pipe(wrap("CacheUMLExplorer = (function(){<%= contents %> return CacheUMLExplorer;}());"))
+ .pipe(uglify({
+ output: {
+ ascii_only: true,
+ width: 30000,
+ max_line_len: 30000
+ }
+ }))
+ .pipe(header(banner, { pkg: pkg }))
+ .pipe(addsrc.prepend("build/web/js/CacheUMLExplorer.js"))
.pipe(concat("CacheUMLExplorer.js"))
.pipe(gulp.dest("build/web/js/"));
});
@@ -90,7 +108,7 @@ gulp.task("exportCacheXML", [
/\{\{replace:js}}/,
function () { return fs.readFileSync("build/web/js/CacheUMLExplorer.js", "utf-8"); }
))
- .pipe(rename(function (path) { path.basename += "-v" + pkg["version"]; }))
+ .pipe(rename(function (path) { path.basename = "CacheUMLExplorer-v" + pkg["version"]; }))
.pipe(gulp.dest("build/Cache"));
});
diff --git a/package.json b/package.json
index 213f0b0..e33b3eb 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "CacheUMLExplorer",
- "version": "0.2",
+ "version": "0.3.0",
"description": "An UML Class explorer for InterSystems Caché",
"directories": {
"test": "test"
@@ -17,6 +17,7 @@
"gulp-minify-css": "^0.3.11",
"gulp-rename": "^1.2.0",
"gulp-replace": "^0.5.0",
+ "gulp-strip-comments": "^1.0.1",
"gulp-uglify": "^1.0.1",
"gulp-wrap": "^0.5.0",
"gulp-zip": "^2.0.2"
diff --git a/web/css/extras.css b/web/css/extras.css
index ca75777..13c99ae 100644
--- a/web/css/extras.css
+++ b/web/css/extras.css
@@ -33,8 +33,8 @@
width: 30px;
height: 30px;
border-radius: 15px;
- background: white;
- box-shadow: 0 0 5px white;
+ background: whitesmoke;
+ box-shadow: 0 0 5px whitesmoke;
z-index: 1;
}
@@ -60,4 +60,112 @@
100% {
transform: rotate(360deg);
}
+}
+
+.icon {
+ display: inline-block;
+ background-color: #333;
+ border-radius: 12px;
+ width: 24px;
+ height: 24px;
+ position: relative;
+ cursor: pointer;
+ -webkit-transition: all .2s ease;
+ -moz-transition: all .2s ease;
+ -o-transition: all .2s ease;
+ transition: all .2s ease;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.icon:hover {
+ box-shadow: 0 0 5px 2px #ffcc1b;
+}
+
+.icon.plus:before {
+ content: "";
+ background-color: #fff;
+ width: 4px;
+ height: 14px;
+ border-radius: 1px;
+ position: absolute;
+ top: 5px;
+ left: 10px;
+}
+
+.icon.plus:after {
+ content: "";
+ background-color: #fff;
+ width: 14px;
+ height: 4px;
+ border-radius: 1px;
+ position: absolute;
+ top: 10px;
+ left: 5px;
+}
+
+.icon.minus:after {
+ content: "";
+ background-color: #fff;
+ width: 14px;
+ height: 4px;
+ border-radius: 1px;
+ position: absolute;
+ top: 10px;
+ left: 5px;
+}
+
+.icon.scaleNormal:after {
+ content: "1:1";
+ position: absolute;
+ color: #fff;
+ text-align: center;
+ font-weight: 900;
+ font-family: monospace;
+ font-size: 10px;
+ width: 100%;
+ top: 6px;
+ left: 0;
+}
+
+.icon.list {
+ position: relative;
+ width: 30px;
+ height: 20px;
+ background-color: transparent;
+}
+
+.icon.list:before {
+ content: "";
+ top: 8px;
+ width: 18px;
+ height: 4px;
+ left: 8px;
+ box-shadow: inset 0 0 0 32px black, 0 -7px 0 0 black, 0 7px 0 0 black;
+ position: absolute;
+}
+
+.icon.list:after {
+ content: "";
+ left: 0;
+ top: 8px;
+ width: 4px;
+ height: 4px;
+ box-shadow: inset 0 0 0 32px black, 0 -7px 0 0 black, 0 7px 0 0 black;
+ position: absolute;
+ -webkit-transition: all .2s ease;
+ -moz-transition: all .2s ease;
+ -o-transition: all .2s ease;
+ transition: all .2s ease;
+}
+
+.icon.list:hover {
+ box-shadow: none;
+}
+
+.icon.list:hover:after {
+ left: 4px;
+ box-shadow: inset 0 0 0 32px #ffcc1b, 0 -7px 0 0 #ffcc1b, 0 7px 0 0 #ffcc1b;
}
\ No newline at end of file
diff --git a/web/css/interface.css b/web/css/interface.css
index 7228824..5f4bc80 100644
--- a/web/css/interface.css
+++ b/web/css/interface.css
@@ -29,12 +29,18 @@ html, body {
position: absolute;
top: 0;
left: 0;
- width: 100%;
padding: .5em;
font-weight: 600;
font-size: 18pt;
}
+.ui-toolBar {
+ position: absolute;
+ bottom: 0;
+ right: 0;
+ padding: .5em;
+}
+
#className {
text-shadow: 1px 1px 0 white, -1px -1px 0 white, 1px -1px 0 white, -1px 1px 0 white;
}
\ No newline at end of file
diff --git a/web/css/treeView.css b/web/css/treeView.css
index 91afac9..eb231b2 100644
--- a/web/css/treeView.css
+++ b/web/css/treeView.css
@@ -12,10 +12,11 @@
}
.tv-class-name.selected {
- box-shadow: inset 0 0 2px 2px deepskyblue;
+ box-shadow: inset 0 0 2px 2px #ffcc1b;
}
.tv-class-name, .tv-package-name {
+ position: relative;
padding: 3px;
cursor: pointer;
border-radius: 5px;
@@ -26,11 +27,15 @@
}
.tv-class-name:hover, .tv-package-name:hover {
- background: #b9ffff;
+ background: #ffcc1b;
font-weight: 900;
padding-left: 30px;
}
+.tv-package-name:hover {
+ background: #7dcdeb;
+}
+
.tv-package-name {
position: relative;
padding-left: 20px;
@@ -96,4 +101,15 @@
.tv-package .tv-package-content {
padding-left: 20px;
+}
+
+.tv-rightListIcon {
+ position: absolute !important;
+ top: 3px;
+ opacity: 0;
+ right: 0;
+}
+
+.tv-package-name:hover .tv-rightListIcon {
+ opacity: 1;
}
\ No newline at end of file
diff --git a/web/index.html b/web/index.html
index 0e2baca..4b1ca2d 100644
--- a/web/index.html
+++ b/web/index.html
@@ -2,7 +2,7 @@
- Caché UML explorer
+ Cache UML explorer
@@ -32,6 +32,11 @@
+
diff --git a/web/js/CacheUMLExplorer.js b/web/js/CacheUMLExplorer.js
index c39648b..c84cf91 100644
--- a/web/js/CacheUMLExplorer.js
+++ b/web/js/CacheUMLExplorer.js
@@ -11,7 +11,10 @@ var CacheUMLExplorer = function (treeViewContainer, classViewContainer) {
this.elements = {
className: document.getElementById("className"),
treeViewContainer: treeViewContainer,
- classViewContainer: classViewContainer
+ classViewContainer: classViewContainer,
+ zoomInButton: document.getElementById("button.zoomIn"),
+ zoomOutButton: document.getElementById("button.zoomOut"),
+ zoomNormalButton: document.getElementById("button.zoomNormal")
};
this.source = new Source();
diff --git a/web/js/ClassTree.js b/web/js/ClassTree.js
index 658a25c..32df7e9 100644
--- a/web/js/ClassTree.js
+++ b/web/js/ClassTree.js
@@ -34,8 +34,6 @@ ClassTree.prototype.removeLoader = function () {
ClassTree.prototype.classSelected = function (element, className) {
- var self = this;
-
this.SELECTED_CLASS_NAME = className;
if (element !== this.SELECTED_ELEMENT) {
@@ -52,6 +50,22 @@ ClassTree.prototype.classSelected = function (element, className) {
};
+ClassTree.prototype.packageSelected = function (element, packageName) {
+
+ if (element !== this.SELECTED_ELEMENT) {
+ if (this.SELECTED_ELEMENT) this.SELECTED_ELEMENT.classList.remove("selected");
+ this.SELECTED_ELEMENT = element;
+ }
+
+ if (!element.classList.contains("selected")) {
+ element.classList.add("selected");
+ this.cacheUMLExplorer.classView.loadPackage(packageName);
+ }
+
+ this.cacheUMLExplorer.elements.className.textContent = packageName;
+
+};
+
ClassTree.prototype.updateTree = function (treeObject) {
var self = this,
@@ -80,7 +94,7 @@ ClassTree.prototype.updateTree = function (treeObject) {
var append = function (rootElement, elementName, isPackage, path) {
var el1 = div(),
- el2, el3;
+ el2, el3, el4;
if (isPackage) {
el1.className = "tv-package";
@@ -88,6 +102,11 @@ ClassTree.prototype.updateTree = function (treeObject) {
(el3 = div()).className = "tv-package-content";
el1.appendChild(el2); el1.appendChild(el3);
el2.addEventListener("click", packageClick);
+ el2.appendChild(el4 = div());
+ el4.className = "tv-rightListIcon icon list";
+ el4.addEventListener("click", function () {
+ self.packageSelected(el1, (path ? path + "." : path) + elementName);
+ });
} else {
el1.className = "tv-class-name";
el1.textContent = elementName;
diff --git a/web/js/ClassView.js b/web/js/ClassView.js
index 9206663..ee2e270 100644
--- a/web/js/ClassView.js
+++ b/web/js/ClassView.js
@@ -14,6 +14,10 @@ var ClassView = function (parent, container) {
this.links = [];
this.objects = [];
+ this.PAPER_SCALE = 1;
+ this.MIN_PAPER_SCALE = 0.2;
+ this.MAX_PAPER_SCALE = 5;
+
this.init();
};
@@ -56,10 +60,59 @@ ClassView.prototype.resetView = function () {
};
+/**
+ * @param {string} name
+ * @param classMetaData
+ * @returns {joint.shapes.uml.Class}
+ */
+ClassView.prototype.createClassInstance = function (name, classMetaData) {
+
+ var attrArr, methArr,
+ classParams = classMetaData["parameters"],
+ classProps = classMetaData["properties"],
+ classMethods = classMetaData["methods"];
+
+ var insertString = function (array, string) {
+ string.match(/.{1,44}/g).forEach(function (p) {
+ array.push(p);
+ });
+ };
+
+ return new joint.shapes.uml.Class({
+ name: name,
+ attributes: attrArr = (function (params, ps) {
+ var arr = [], n;
+ for (n in params) {
+ insertString(arr, n + (params[n]["type"] ? ": " + params[n]["type"] : ""));
+ }
+ for (n in ps) {
+ insertString(
+ arr,
+ (ps[n]["private"] ? "- " : "+ ") + n
+ + (ps[n]["type"] ? ": " + ps[n]["type"] : "")
+ );
+ }
+ return arr;
+ })(classParams, classProps),
+ methods: methArr = (function (ps) {
+ var arr = [], n;
+ for (n in ps) {
+ insertString(arr, "+ " + n + (ps[n]["returns"] ? ": " + ps[n]["returns"] : ""));
+ }
+ return arr;
+ })(classMethods),
+ size: {
+ width: 300,
+ height: Math.max(attrArr.length*12.1, 15) + Math.max(methArr.length*12.1, 15) + 40
+ }
+ });
+
+};
+
ClassView.prototype.render = function (data) {
- var p, pp, className, classProps, classMethods, classInstance,
- uml = joint.shapes.uml, attrArr, methArr, relFrom, relTo,
+ var p, pp, className, classInstance,
+ uml = joint.shapes.uml, relFrom, relTo,
classes = {}, connector;
if (!data["classes"]) {
@@ -68,36 +121,7 @@ ClassView.prototype.render = function (data) {
}
for (className in data["classes"]) {
- classProps = data["classes"][className]["properties"];
- classMethods = data["classes"][className]["methods"];
-
- classInstance = new uml.Class({
- name: className,
- attributes: attrArr = (function (ps) {
- var arr = [], n, s;
- for (n in ps) {
- s = (ps[n]["private"] ? "- " : "+ ") + n + ": " + ps[n]["type"];
- s.match(/.{1,44}/g).forEach(function (p) {
- arr.push(p);
- });
- }
- return arr;
- })(classProps),
- methods: methArr = (function (ps) {
- var arr = [], n, s;
- for (n in ps) {
- s = "+ " + n + (ps[n]["returns"] ? ": " + ps[n]["returns"] : "");
- s.match(/.{1,44}/g).forEach(function (p) {
- arr.push(p);
- });
- }
- return arr;
- })(classMethods),
- size: {
- width: 300,
- height: Math.max(attrArr.length*12.1, 15) + Math.max(methArr.length*12.1, 15) + 40
- }
- });
+ classInstance = this.createClassInstance(className, data["classes"][className]);
this.objects.push(classInstance);
classes[className] = {
instance: classInstance
@@ -108,7 +132,7 @@ ClassView.prototype.render = function (data) {
}
for (p in data["inheritance"]) {
- relFrom = classes[p].instance;
+ relFrom = (classes[p] || {}).instance;
for (pp in data["inheritance"][p]) {
relTo = (classes[pp] || {}).instance;
if (relFrom && relTo) {
@@ -149,7 +173,25 @@ ClassView.prototype.loadClass = function (className) {
self.removeLoader();
if (err) {
self.showLoader("Unable to get " + self.cacheUMLExplorer.classTree.SELECTED_CLASS_NAME);
- console.error(err);
+ console.error.call(console, err);
+ } else {
+ self.cacheUMLExplorer.classView.render(data);
+ }
+ });
+
+};
+
+ClassView.prototype.loadPackage = function (packageName) {
+
+ var self = this;
+
+ this.showLoader();
+ this.cacheUMLExplorer.source.getPackageView(packageName, function (err, data) {
+ //console.log(data);
+ self.removeLoader();
+ if (err) {
+ self.showLoader("Unable to get package " + packageName);
+ console.error.call(console, err);
} else {
self.cacheUMLExplorer.classView.render(data);
}
@@ -161,6 +203,33 @@ ClassView.prototype.updateSizes = function () {
this.paper.setDimensions(this.container.offsetWidth, this.container.offsetHeight);
};
+/**
+ * Scale view according to delta.
+ *
+ * @param {number|string} delta
+ */
+ClassView.prototype.zoom = function (delta) {
+
+ var scaleOld = this.PAPER_SCALE, scaleDelta;
+ if (typeof delta === "number") {
+ this.PAPER_SCALE += delta *Math.min(
+ 0.5,
+ Math.abs(this.PAPER_SCALE - (delta < 0 ? this.MIN_PAPER_SCALE : this.MAX_PAPER_SCALE))/2
+ );
+ } else {
+ this.PAPER_SCALE = 1;
+ }
+ this.paper.scale(this.PAPER_SCALE, this.PAPER_SCALE);
+ scaleDelta = this.PAPER_SCALE - scaleOld;
+ this.paper.setOrigin(
+ this.paper.options.origin.x
+ - scaleDelta*this.cacheUMLExplorer.elements.classViewContainer.offsetWidth/2,
+ this.paper.options.origin.y
+ - scaleDelta*this.cacheUMLExplorer.elements.classViewContainer.offsetHeight/2
+ );
+
+};
+
ClassView.prototype.init = function () {
var p, self = this,
@@ -216,6 +285,18 @@ ClassView.prototype.init = function () {
this.cacheUMLExplorer.elements.classViewContainer.addEventListener("mousemove", moveHandler);
this.cacheUMLExplorer.elements.classViewContainer.addEventListener("touchmove", moveHandler);
+ this.cacheUMLExplorer.elements.classViewContainer.addEventListener("mousewheel", function (e) {
+ self.zoom(Math.max(-1, Math.min(1, (e.wheelDelta || -e.detail))));
+ });
+ this.cacheUMLExplorer.elements.zoomInButton.addEventListener("click", function () {
+ self.zoom(1);
+ });
+ this.cacheUMLExplorer.elements.zoomOutButton.addEventListener("click", function () {
+ self.zoom(-1);
+ });
+ this.cacheUMLExplorer.elements.zoomNormalButton.addEventListener("click", function () {
+ self.zoom(null);
+ });
//var classes = {
//
diff --git a/web/js/Source.js b/web/js/Source.js
index 72fdfbb..f66b3d3 100644
--- a/web/js/Source.js
+++ b/web/js/Source.js
@@ -1,6 +1,7 @@
var Source = function () {
- this.URL = "http://localhost:57773/UMLExplorer";
+ this.URL = window.location.protocol + "//" + window.location.hostname + ":" +
+ 57773/*build.replace:window.location.port*/ + "/UMLExplorer";
};
@@ -25,6 +26,17 @@ Source.prototype.getClassView = function (className, callback) {
};
+/**
+ * Return class view.
+ * @param {string} packageName
+ * @param {Source~dataCallback} callback
+ */
+Source.prototype.getPackageView = function (packageName, callback) {
+
+ lib.load(this.URL + "/GetPackageView/" + encodeURIComponent(packageName), null, callback);
+
+};
+
/**
* This callback handles data received directly from server.
* @callback Source~dataCallback
diff --git a/web/jsLib/joint.layout.DirectedGraph.min.js b/web/jsLib/joint.layout.DirectedGraph.min.js
index e3ee1bf..fe2b704 100644
--- a/web/jsLib/joint.layout.DirectedGraph.min.js
+++ b/web/jsLib/joint.layout.DirectedGraph.min.js
@@ -1,4 +1,4 @@
-/*! JointJS v0.9.3 - JavaScript diagramming library 2015-02-03
+/* JointJS v0.9.3 - JavaScript diagramming library 2015-02-03
This Source Code Form is subject to the terms of the Mozilla Public
diff --git a/web/jsLib/joint.shapes.uml.js b/web/jsLib/joint.shapes.uml.js
index b9adfc3..3f90237 100644
--- a/web/jsLib/joint.shapes.uml.js
+++ b/web/jsLib/joint.shapes.uml.js
@@ -1,4 +1,4 @@
-/*! JointJS v0.9.3 - JavaScript diagramming library 2015-02-03
+/* JointJS v0.9.3 - JavaScript diagramming library 2015-02-03
This Source Code Form is subject to the terms of the Mozilla Public
@@ -40,9 +40,9 @@ joint.shapes.uml.Class = joint.shapes.basic.Generic.extend({
attrs: {
rect: { 'width': 200 },
- '.uml-class-name-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#3498db' },
- '.uml-class-attrs-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#2980b9' },
- '.uml-class-methods-rect': { 'stroke': 'black', 'stroke-width': 2, 'fill': '#2980b9' },
+ '.uml-class-name-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#3498db' },
+ '.uml-class-attrs-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#2980b9' },
+ '.uml-class-methods-rect': { 'stroke': 'black', 'stroke-width': 1, 'fill': '#2980b9' },
'.uml-class-name-text': {
'ref': '.uml-class-name-rect', 'ref-y': .5, 'ref-x': .5, 'text-anchor': 'middle', 'y-alignment': 'middle', 'font-weight': 'bold',