Skip to content

Commit

Permalink
description display for elements on hover, edit fixes, SQL query expa…
Browse files Browse the repository at this point in the history
…nded display
nikitaeverywhere committed Oct 17, 2015
1 parent f6c760b commit ee901c1
Showing 7 changed files with 129 additions and 83 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ An UML Class explorer for InterSystems Caché.

## Screenshots

![Demo](https://cloud.githubusercontent.com/assets/4989256/9852547/890543f8-5b07-11e5-9dc3-a539e33b2058.png)
![Demo](https://cloud.githubusercontent.com/assets/4989256/10561433/30415858-7531-11e5-97c6-6623d2b6ab30.png)

## Installation

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "CacheUMLExplorer",
"version": "1.4.1",
"version": "1.5.1",
"description": "An UML Class explorer for InterSystems Caché",
"directories": {
"test": "test"
17 changes: 16 additions & 1 deletion web/css/hoverMessage.css
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
.hoverMessage {

box-sizing: border-box;
white-space: pre-line;
background: rgba(255, 255, 255, 0.9);
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
border: 1px solid dimgray;
padding: .3em;
overflow: hidden;
line-height: 1em;
max-height: 10em;

}

.line-hoverable {
cursor: pointer;
-webkit-transition: all .5s ease;
-moz-transition: all .5s ease;
-o-transition: all .5s ease;
transition: all .5s ease;
}

.line-hoverable:hover {
fill: red;
}

.hoverContainer {
@@ -16,5 +30,6 @@
left: 0;
top: 0;
padding: 20px;
cursor: pointer;

}
134 changes: 60 additions & 74 deletions web/js/ClassView.js
Original file line number Diff line number Diff line change
@@ -279,37 +279,6 @@ ClassView.prototype.filterInherits = function (data) {
"%DataType": true
};

// inheritance: { "ClassName": { "IHCN": 1, ... }, ... }
// inherit isDataType & classType if not set for inherited classes
//var rec = function (className) {
// if (!(cls = data.classes[className])) return { isDataType: null, classType: null };
// var c, res = { isDataType: cls.isDataType || null, classType: cls.classType || null}, resi, cls;
// if (className === "%DeepSee.ListingTable") console.log("-------", res);
// if (data.inheritance[className]) {
// for (c in data.inheritance[className]) {
// resi = undefined;
// if (data.classes[c]) {
// if (data.classes[c].isDataType) resi = {
// isDataType: data.classes[c].isDataType,
// classType: data.classes[c].classType || null
// }; else if (data.classes[c].classType) {
// res.classType = data.classes[c].classType;
// }
// }
// if (!resi) resi = rec(c);
// if (className === "Aviation.Cubes.Aircraft.Listing") console.log(c, resi);
// if (res.isDataType === null) { res.isDataType = resi.isDataType; }
// if (res.classType === null) { res.classType = resi.classType; }
// }
// }
// if (res.isDataType !== null && !cls.isDataType) { cls.isDataType = res.isDataType; }
// if (res.classType !== null && !cls.classType) { cls.classType = res.classType; }
// return res;
//};
//for (p1 in data.classes) {
// rec(p1);
//}

var f = function (p) {
return filter.hasOwnProperty(p) || (data.classes[p] || {})["isDataType"] ||
lib.obj(((data.classes[p] || {}).super || "").split(",")).hasOwnProperty("%DataType");
@@ -341,33 +310,6 @@ ClassView.prototype.getClassSigns = function (classMetaData) {

var signs = [], ct;

// todo: preprocess class type before diagram load
//if (classMetaData["classType"] || sup) {
// ct = classMetaData["classType"];
// if (sup.hasOwnProperty("%Library.Persistent") || sup.hasOwnProperty("%Persistent")) {
// ct = "Persistent";
// }
// if (sup.hasOwnProperty("%Library.SerialObject") || sup.hasOwnProperty("%SerialObject")) {
// ct = "Serial";
// }
// if (
// sup.hasOwnProperty("%Library.RegisteredObject")
// || sup.hasOwnProperty("%RegisteredObject")
// ) {
// ct = "Registered";
// }
// if (sup.hasOwnProperty("%Library.DataType") || sup.hasOwnProperty("%DataType")) {
// ct = "Datatype";
// }
// if (ct) {
// CT = ct;
// signs.push({
// icon: lib.image.greenPill,
// text: lib.capitalize(ct),
// textStyle: "fill:rgb(130,0,255)"
// });
// }
//}
if (ct = classMetaData["$classType"]) {
if (ct !== "Serial" && ct !== "Registered" && ct !== "Persistent" && ct !== "DataType") {
signs.push({
@@ -459,6 +401,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
keyWordsArray.push(n);
arr.push({
text: n + (params[n]["Type"] ? ": " + params[n]["Type"] : ""),
hover: params[n]["Description"] || "",
icons: self.getPropertyIcons(params[n])
});
}
@@ -470,6 +413,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
keyWordsArray.push(n);
arr.push({
text: n + (ps[n]["Type"] ? ": " + ps[n]["Type"] : ""),
hover: ps[n]["Description"] || "",
icons: self.getPropertyIcons(ps[n])
});
}
@@ -487,6 +431,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
clickHandler: (function (n) {
return function () { self.showMethodCode(name, n); }
})(n),
hover: met[n]["Description"] || "",
icons: self.getPropertyIcons(met[n])
});
}
@@ -499,7 +444,10 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {
arr.push({
text: n,
icons: self.getPropertyIcons(qrs[n]),
hover: qrs[n]["SqlQuery"]
hover: qrs[n]["SqlQuery"],
clickHandler: (function (q, className) {
return function () { self.showQuery(className, q); }
})(qrs[n], name)
});
}
return arr;
@@ -519,26 +467,58 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) {

ClassView.prototype.showMethodCode = function (className, methodName) {

var self = this,
els = this.cacheUMLExplorer.elements;
var self = this;

this.cacheUMLExplorer.source.getMethod(className, methodName, function (err, data) {
if (err || data.error) {
self.cacheUMLExplorer.UI.displayMessage("Unable to get method \"" + methodName + "\"!");
return;
}
els.methodLabel.textContent = className + ": " + methodName + "("
self.showPanel({
header: className + ": " + methodName + "("
+ (data["arguments"] || "").replace(/,/g, ", ").replace(/:/g, ": ") + ")"
+ (data["returns"] ? ": " + data["returns"] : "");
els.methodDescription.innerHTML = data["description"] || "";
els.methodCode.innerHTML = lib.highlightCOS(data["code"] || "");
els.methodViewBounds.style.height =
els.classView.offsetHeight - els.methodViewBounds.offsetTop + "px";
els.methodCodeView.classList.add("active");
+ (data["returns"] ? ": " + data["returns"] : ""),
comment: data["description"],
body: lib.highlightCOS(data["code"] || "")
});
});

};

ClassView.prototype.showQuery = function (className, queryData) {

queryData = queryData || {};

this.showPanel({
header: "##class(" + className + ")." + queryData["Name"] + "("
+ (queryData["FormalSpec"] || "").replace(/,/g, ", ").replace(/:/g, ": ") + ")",
comment: queryData["Description"],
body: lib.highlightSQL(queryData["SqlQuery"] || "")
});

};

/**
* Show panel filled with given HTML contents.
* @param {string} data.header
* @param {string} [data.comment]
* @param {string} data.body
*/
ClassView.prototype.showPanel = function (data) {

var els = this.cacheUMLExplorer.elements;

data = data || {};

els.methodLabel.textContent = data.header || "";
els.methodDescription.innerHTML = data.comment || "";
els.methodCode.innerHTML = data.body || "";
els.methodViewBounds.style.height =
els.classView.offsetHeight - els.methodViewBounds.offsetTop + "px";
els.methodCodeView.classList.add("active");

};

ClassView.prototype.hideMethodCode = function () {

this.cacheUMLExplorer.elements.methodCodeView.classList.remove("active");
@@ -870,7 +850,8 @@ ClassView.prototype.init = function () {
this.graph.on("change:position", function (object) {
if (_.contains(self.objects, object))
for (p in self.links) {
self.paper.findViewByModel(self.links[p]).update();
var link = self.paper.findViewByModel(self.links[p]);
if (link) link.update(); // removed links, should be in todo
}
});

@@ -955,13 +936,18 @@ ClassView.prototype.init = function () {
ClassView.prototype.onRendered = function () {

[].slice.call(document.querySelectorAll(".line-hoverable")).forEach(function (el) {
var hm = new HoverMessage(el.getAttribute("hovertext"));
var hm = new HoverMessage(el.getAttribute("hovertext"), el["clickHandler"] || null),
APPEAR_TIMEOUT = 500, tm = 0;
el.addEventListener("mouseover", function (e) {
hm.attach(e.pageX || e.clientX, e.pageY || e.clientY);
if (tm) clearTimeout(tm);
tm = setTimeout(function () {
clearTimeout(tm);
hm.attach(e.pageX || e.clientX, e.pageY || e.clientY);
}, APPEAR_TIMEOUT);
});
el.addEventListener("mouseout", function () {
clearTimeout(tm);
});
//el.addEventListener("mouseout", function () {
// hm.detach();
//});
});

};
18 changes: 13 additions & 5 deletions web/js/HoverMessage.js
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
var HoverMessage = function (text) {
var HoverMessage = function (text, clickHandler) {

var self = this;

this.clickHandler = typeof clickHandler === "function" ? clickHandler : function () {};
this.element = document.createElement("div");
this.element.className = "hoverMessage";
this.element.textContent = text;
this.element.innerHTML = text;
this.container = document.createElement("div");
this.container.className = "hoverContainer";
this.container.appendChild(this.element);

this.container.addEventListener("mouseout", function (event) {
var e = event.toElement || event.relatedTarget;
if (e.parentNode == this || e == this) return;
if (e && ((function check (e, t) { // if one of the parents is this object
if (e === t) return true;
if (!e.parentNode) return false;
return check(e.parentNode, t);
})(e, this))) return;
self.detach();
});
this.container.addEventListener("click", function () {
self.clickHandler();
});

};

HoverMessage.prototype.attach = function (screenX, screenY) {

var e = this.container,
w = Math.min(400, window.innerWidth/2);
var e = this.container, w;

document.body.appendChild(e);
e.style.width = (w = Math.min(e.offsetWidth, window.innerWidth/2)) + "px";
e.style.top = (screenY - e.offsetHeight + 15) + "px";
36 changes: 36 additions & 0 deletions web/js/Lib.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion web/jsLib/joint.js
Original file line number Diff line number Diff line change
@@ -17230,9 +17230,10 @@ if ( typeof window === "object" && typeof window.document === "object" ) {
}
if (typeof lines[i]["clickHandler"] === "function") {
tspan.node.addEventListener("click", lines[i]["clickHandler"]);
tspan.node["clickHandler"] = lines[i]["clickHandler"];
tspan.addClass('line-clickable');
}
if (typeof lines[i]["hover"] === "string") {
if (lines[i]["hover"] && typeof lines[i]["hover"] === "string") {
tspan.addClass('line-hoverable');
tspan.node.setAttribute("hovertext", lines[i]["hover"]);
}

0 comments on commit ee901c1

Please sign in to comment.