From 21c25872641d5cd1f72352317b2d1666f240e809 Mon Sep 17 00:00:00 2001 From: ZitRo Date: Sun, 31 May 2015 18:25:41 +0300 Subject: [PATCH] diagram search enabled --- README.md | 6 ++- package.json | 2 +- web/css/classView.css | 19 +++++++ web/css/extras.css | 29 +++++++++++ web/index.html | 6 ++- web/js/CacheUMLExplorer.js | 4 +- web/js/ClassView.js | 103 +++++++++++++++++++++++++++++++++++++ 7 files changed, 164 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index c4bb065..3697186 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,13 @@ An UML Class explorer for InterSystems Caché. + Edit diagrams after build; + Export diagrams as an image; + View class methods code with syntax highlighting; -+ Zoom in and out, explore big packages and more. ++ Zoom in and out; ++ Search on diagram or in class tree; ++ Explore! ## Screenshots -![Demo](https://cloud.githubusercontent.com/assets/4989256/7898598/7d367720-070d-11e5-9177-dded6abf93e1.png) +![Demo](https://cloud.githubusercontent.com/assets/4989256/7902384/e7882a48-07c0-11e5-9c3f-7203a40263d2.png) ## Installation diff --git a/package.json b/package.json index e61105d..39aa711 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "CacheUMLExplorer", - "version": "0.12.1", + "version": "0.13.0", "description": "An UML Class explorer for InterSystems Caché", "directories": { "test": "test" diff --git a/web/css/classView.css b/web/css/classView.css index 700c6d7..ecf12e5 100644 --- a/web/css/classView.css +++ b/web/css/classView.css @@ -82,4 +82,23 @@ text { .line-clickable:hover { fill: red; +} + +.inlineSearchBlock { + display: inline-block; + vertical-align: bottom; +} + +#diagramSearch { + display: block; + box-sizing: border-box; + border: 1px solid gray; + border-radius: 5px; + width: 200px; + margin: 4px 0 4px 4px; + height: 22px; +} + +.element.highlighted { + outline: 4px solid rgba(255, 0, 0, 0.6); } \ No newline at end of file diff --git a/web/css/extras.css b/web/css/extras.css index edf9e7a..109667c 100644 --- a/web/css/extras.css +++ b/web/css/extras.css @@ -84,6 +84,35 @@ box-shadow: 0 0 5px 2px #ffcc1b; } +.icon.search:after { + content: ""; + position: absolute; + display: block; + width: 6px; + height: 6px; + left: 4px; + top: 4px; + border: 3px solid #fff; + background: transparent; + border-radius: 6px; +} + +.icon.search:before { + content: ""; + position: absolute; + display: block; + left: 14px; + top: 12px; + width: 3px; + height: 7px; + background: #fff; + -webkit-transform: rotate(-45deg); + -moz-transform: rotate(-45deg); + -ms-transform: rotate(-45deg); + -o-transform: rotate(-45deg); + transform: rotate(-45deg); +} + .icon.select { width: auto; color: white; diff --git a/web/index.html b/web/index.html index 1418cab..cd56662 100644 --- a/web/index.html +++ b/web/index.html @@ -29,7 +29,7 @@
- +
@@ -50,6 +50,10 @@
+
+ +
+
diff --git a/web/js/CacheUMLExplorer.js b/web/js/CacheUMLExplorer.js index df4f160..a1b6685 100644 --- a/web/js/CacheUMLExplorer.js +++ b/web/js/CacheUMLExplorer.js @@ -30,7 +30,9 @@ var CacheUMLExplorer = function (treeViewContainer, classViewContainer) { methodViewBounds: id("methodViewBounds"), namespaces: id("namespaces"), classTreeSearch: id("classTreeSearch"), - searchBlock: id("searchBlock") + searchBlock: id("searchBlock"), + diagramSearch: id("diagramSearch"), + diagramSearchButton: id("button.diagramSearch") }; this.UI = new UI(this); diff --git a/web/js/ClassView.js b/web/js/ClassView.js index 275c21c..b118d87 100644 --- a/web/js/ClassView.js +++ b/web/js/ClassView.js @@ -21,10 +21,29 @@ var ClassView = function (parent, container) { this.CLASS_DOC_PATH = "/csp/documatic/%25CSP.Documatic.cls"; this.SYMBOL_12_WIDTH = 6.6; + this.HIGHLIGHTED_VIEW = null; + this.SEARCH_INDEX = 0; + this.init(); }; +ClassView.prototype.highlightElement = function (jointElement) { + + if (this.HIGHLIGHTED_VIEW || (!jointElement && this.HIGHLIGHTED_VIEW)) { + this.HIGHLIGHTED_VIEW.unhighlight(); + this.HIGHLIGHTED_VIEW = null; + } + + if (!jointElement) return; + var view = this.paper.findViewByModel(jointElement); + if (!view) return; + + view.highlight(); + this.HIGHLIGHTED_VIEW = view; + +}; + ClassView.prototype.showLoader = function (html) { var d2; @@ -60,6 +79,9 @@ ClassView.prototype.resetView = function () { this.objects = []; this.paper.setOrigin(0, 0); this.graph.clear(); + this.HIGHLIGHTED_VIEW = null; + this.SEARCH_INDEX = 0; + this.cacheUMLExplorer.elements.diagramSearch.value = ""; }; @@ -268,6 +290,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) { var classParams = classMetaData["parameters"], classProps = classMetaData["properties"], classMethods = classMetaData["methods"], + keyWordsArray = [name], self = this; var classInstance = new joint.shapes.uml.Class({ @@ -283,6 +306,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) { params: (function (params) { var arr = [], n; for (n in params) { + keyWordsArray.push(n); arr.push({ text: n + (params[n]["type"] ? ": " + params[n]["type"] : "") }); @@ -292,6 +316,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) { attributes: (function (ps) { var arr = [], n; for (n in ps) { + keyWordsArray.push(n); arr.push({ text: n + (ps[n]["type"] ? ": " + ps[n]["type"] : ""), icons: self.getMethodIcons(ps[n]) @@ -302,6 +327,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) { methods: (function (met) { var arr = [], n; for (n in met) { + keyWordsArray.push(n); arr.push({ text: n + (met[n]["returns"] ? ": " + met[n]["returns"] : ""), styles: (function (t) { @@ -319,6 +345,7 @@ ClassView.prototype.createClassInstance = function (name, classMetaData) { SYMBOL_12_WIDTH: self.SYMBOL_12_WIDTH }); + classInstance.SEARCH_KEYWORDS = keyWordsArray.join(",").toLowerCase(); this.objects.push(classInstance); this.graph.addCell(classInstance); @@ -562,6 +589,69 @@ ClassView.prototype.zoom = function (delta) { }; +/** + * Focus on joint instance. + * @param jointInstance + */ +ClassView.prototype.focusOnInstance = function (jointInstance) { + + var bb = jointInstance.getBBox(); + + this.focusOnXY(bb.x + bb.width/2, bb.y + bb.height/2); + +}; + +/** + * Focus on x and y coordinates considering scale. + * @param {number} x + * @param {number} y + */ +ClassView.prototype.focusOnXY = function (x, y) { + + var sw = this.cacheUMLExplorer.elements.classViewContainer.offsetWidth, + sh = this.cacheUMLExplorer.elements.classViewContainer.offsetHeight, + scale = this.PAPER_SCALE; + + this.paper.setOrigin( + -(x * scale) + sw/2, + -(y * scale) + sh/2 + ); + +}; + +/** + * Find text on diagram and focus on element. + * + * @param {string} text + */ +ClassView.prototype.searchOnDiagram = function (text) { + + var p, found = [], o; + + if (!text) { + this.highlightElement(null); + return; + } + + text = text.toLowerCase(); + + for (p in this.objects) { + if (this.objects[p].SEARCH_KEYWORDS.indexOf(text) !== -1) { + found.push(this.objects[p]); + } + } + + if (found.length) { + o = found[this.SEARCH_INDEX % found.length]; + this.focusOnInstance(o); + this.highlightElement(o); + return; + } + + this.highlightElement(null); + +}; + ClassView.prototype.init = function () { var p, self = this, @@ -635,6 +725,19 @@ ClassView.prototype.init = function () { this.cacheUMLExplorer.elements.helpButton.addEventListener("click", function () { self.renderInfoGraphic(); }); + this.cacheUMLExplorer.elements.diagramSearch.addEventListener("input", function (e) { + self.searchOnDiagram((e.target || e.srcElement).value); + }); + this.cacheUMLExplorer.elements.diagramSearch.addEventListener("keydown", function (e) { + if (e.keyCode === 13) { + self.SEARCH_INDEX++; + self.searchOnDiagram((e.target || e.srcElement).value); + } + }); + this.cacheUMLExplorer.elements.diagramSearchButton.addEventListener("click", function () { + self.SEARCH_INDEX++; + self.searchOnDiagram(self.cacheUMLExplorer.elements.diagramSearch.value); + }); this.SYMBOL_12_WIDTH = (function () { var e = document.createElementNS("http://www.w3.org/2000/svg", "text"),