Improve relation tree visualizations
Change-Id: I99c414a61f48ad237746f54885ca7ef6afadb6dd
diff --git a/Gruntfile.js b/Gruntfile.js
index 15dc4cc..1ca8362 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -118,7 +118,7 @@
'dev/scss/sidebar/sidebar.scss',
'dev/scss/header/{header,hint,menu,searchbar,vc,datepicker}.scss',
'dev/scss/main/{alertify,koralquery,highlight,kwic,logos,tagger,' +
- 'main,matchinfo,pagination,query,'+
+ 'main,matchinfo,tree,pagination,query,'+
'resultinfo,sidebar,tutorial}.scss'
],
tasks: ['sass'],
diff --git a/dev/demo/relations.html b/dev/demo/relations.html
index d651988..89abf06 100644
--- a/dev/demo/relations.html
+++ b/dev/demo/relations.html
@@ -5,43 +5,22 @@
<script data-main="relationsdemo.js" src="../js/lib/require.js" async="async"></script>
<link type="text/css" rel="stylesheet" href="../css/kalamar.css" />
<style>
- tspan, text {
- font-size: 11pt;
- stroke-width: 0;
- line-height: 100%;
- stroke-opacity:0;
- padding-right: 3pt
- fill: black;
- }
- /*
- svg.relTree g > text > tspan {
- text-anchor: middle;
- }
- */
- g.arcs text {
- font-size: 9pt;
- fill: blue;
- }
- path {
- stroke-width: 2;
- stroke: black;
- fill: none;
- }
- path.anchor {
- stroke: green;
- z-index: 20;
- }
- marker > path {
- fill-opacity:1;
- fill: black;
- }
- marker {
- overflow:visible
- }
</style>
</head>
<body>
- <div id="tree"></div>
+ <div id="search">
+ <ol>
+ <li class="active action">
+ <div class="matchinfo">
+ <div class="matchtree">
+ <div id="treeRel"></div>
+ <div id="treeHier"></div>
+ </div>
+ </div>
+ </li>
+ </ol>
+ </div>
+
</body>
</html>
diff --git a/dev/demo/relationsdemo.js b/dev/demo/relationsdemo.js
index 17fcfb3..12d536c 100644
--- a/dev/demo/relationsdemo.js
+++ b/dev/demo/relationsdemo.js
@@ -1,10 +1,69 @@
+var treeSnippet =
+ "<span class=\"context-left\"></span>" +
+ "<span class=\"match\">" +
+ " <span title=\"xip/c:MC\">" +
+ " <span title=\"xip/c:TOP\">" +
+ " <span title=\"xip/c:PP\">" +
+ " <span title=\"xip/c:PREP\">Mit</span>" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:DET\">dieser</span>" +
+ " <span title=\"xip/c:NPA\">" +
+ " <span title=\"xip/c:NOUN\">Methode</span>" +
+ " </span>" +
+ " </span>" +
+ " </span>" +
+ " <span title=\"xip/c:VERB\">ist</span>" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:PRON\">es</span>" +
+ " </span>" +
+ " <span title=\"xip/c:AP\">" +
+ " <span title=\"xip/c:ADV\">nun</span>" +
+ " <span title=\"xip/c:ADJ\">möglich</span>" +
+ " </span>" +
+ " <span title=\"xip/c:ADV\">z. B.</span>" +
+ " <span title=\"xip/c:NPA\">" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:NOUN\">Voice</span>" +
+ " </span>" +
+ " </span>" + "(" +
+ " <span title=\"xip/c:INS\">" +
+ " <span title=\"xip/c:NPA\">" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:NOUN\">Sprache</span>" +
+ " </span>" +
+ " </span>" +
+ " </span>" + ")" +
+ " <span title=\"xip/c:VERB\">bevorzugt</span>" +
+ " <span title=\"xip/c:PP\">" +
+ " <span title=\"xip/c:PREP\">in</span>" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:PRON\">der</span>" +
+ " </span>" +
+ " <span title=\"xip/c:NPA\">" +
+ " <span title=\"xip/c:NP\">" +
+ " <span title=\"xip/c:NOUN\">Bridge</span>" +
+ " </span>" +
+ " </span>" +
+ " </span>" +
+ " <span title=\"xip/c:INFC\">" +
+ " <span title=\"xip/c:INS\">" +
+ " <span title=\"xip/c:VERB\">weiterzugeben</span>" +
+ " </span>" +
+ " </span>" +
+ " </span>" +
+ " </span>" +
+ "</span>" +
+ "<span class=\"context-right\"></span>";
+
requirejs.config({
- baseUrl: '../js/src'
+ baseUrl: '../js/src',
+ paths : {
+ 'lib': '../lib'
+ }
});
-require(['match/relations'], function (relClass) {
+require(['match/relations', 'match/tree'], function (relClass, treeClass) {
var rel = relClass.create();
- document.getElementById("tree").appendChild(rel.element());
/*
* Start and end may be spans, i.e. arrays
@@ -31,6 +90,13 @@
.addRel({ start: [5,6], end: 7, label: "g" })
.addRel({ start: 4, end: [6,8], label: "f", direction: "bi" })
;
-
+
+ document.getElementById("treeRel").appendChild(rel.element());
+
+ // Todo: Probably rename to rel.draw()
rel.show();
+
+ var tree = treeClass.create(treeSnippet);
+ document.getElementById("treeHier").appendChild(tree.element());
});
+
diff --git a/dev/js/src/match/relations.js b/dev/js/src/match/relations.js
index f79d189..5193635 100644
--- a/dev/js/src/match/relations.js
+++ b/dev/js/src/match/relations.js
@@ -29,24 +29,30 @@
return this;
},
+
// This is a shorthand for SVG element creation
_c : function (tag) {
return document.createElementNS(svgNS, tag);
},
+
// Returns the center point of the requesting token
_tokenPoint : function (node) {
var box = node.getBoundingClientRect();
return box.x + (box.width / 2);
},
+
+ // Draws an anchor
_drawAnchor : function (anchor) {
+
+ // Calculate the span of the first and last token, the anchor spans
var firstBox = this._tokenElements[anchor.first].getBoundingClientRect();
var lastBox = this._tokenElements[anchor.last].getBoundingClientRect();
- var startPos = firstBox.left;
- var endPos = lastBox.right;
-
+ var startPos = firstBox.left - this.offsetLeft;
+ var endPos = lastBox.right - this.offsetLeft;
+
var y = this._y + (anchor.overlaps * this.anchorDiff) - this.anchorStart;
var l = this._c('path');
@@ -80,8 +86,12 @@
endPos = this._tokenPoint(this._tokenElements[arc.last]);
};
+ startPos -= this.offsetLeft;
+ endPos -= this.offsetLeft;
+
var g = this._c("g");
var p = g.appendChild(this._c("path"));
+ p.setAttribute('class', 'edge');
// Create arc
var middle = Math.abs(endPos - startPos) / 2;
@@ -279,7 +289,7 @@
var g = svg.appendChild(this._c("g"));
/*
- * Generate token list
+ * Create token list
*/
var text = g.appendChild(this._c("text"));
text.setAttribute("text-anchor", "start");
@@ -307,18 +317,26 @@
tspan.setAttribute("dx", this.tokenSep);
};
+ var globalBoundingBox = g.getBoundingClientRect();
+ this.offsetLeft = globalBoundingBox.left;
+
var arcs = g.appendChild(this._c("g"));
arcs.classList.add("arcs");
-
+
+ // Sort arcs if not sorted yet
if (this._sortedArcs === undefined) {
this._sortArcs();
};
var i;
+
+ // Draw all anchors
for (i in this._sortedAnchors) {
arcs.appendChild(this._drawAnchor(this._sortedAnchors[i]));
};
-
+
+
+ // draw all arcs
for (i in this._sortedArcs) {
arcs.appendChild(this._drawArc(this._sortedArcs[i]));
};
diff --git a/dev/scss/main/main.scss b/dev/scss/main/main.scss
index e73bce3..f6d1b7a 100644
--- a/dev/scss/main/main.scss
+++ b/dev/scss/main/main.scss
@@ -1,7 +1,8 @@
@import "highlight"; // JSON highlighting
@import "kwic"; // Kwic view information
@import "logos"; // Logo images
-@import "matchinfo"; // Match table and tree
+@import "matchinfo"; // Match table
+@import "tree"; // Tree view
@import "pagination"; // Pagination
@import "query"; // View query
@import "resultinfo"; // Information on results
diff --git a/dev/scss/main/matchinfo.scss b/dev/scss/main/matchinfo.scss
index 4446fc8..dd6bd9c 100644
--- a/dev/scss/main/matchinfo.scss
+++ b/dev/scss/main/matchinfo.scss
@@ -336,54 +336,3 @@
}
-/**
- * SVG tree
- */
-path.edge {
- stroke: $darker-orange;
- stroke-width: 2px;
- fill: none;
-}
-
-g.root rect.empty {
- stroke: $darker-orange;
- fill: $darker-orange;
- stroke-width: 2px;
-}
-
-g.middle rect {
- stroke: $darker-orange;
- stroke-width: 2px;
- fill: $middle-orange;
-}
-
-g.middle.mark {
- rect {
- fill: $darker-orange;
- }
- > text {
- fill: $light-orange;
- > tspan {
- stroke: $light-orange;
- }
- }
-}
-
-
-g.leaf.mark text > tspan {
- font-weight: bold;
-}
-
-g.leaf > rect {
- display: none;
-}
-
-g > text > tspan {
- text-anchor: middle;
- font-size: 9pt;
-}
-
-g.leaf > text > tspan {
- font-size: 10pt;
- overflow: visible;
-}
diff --git a/dev/scss/main/tree.scss b/dev/scss/main/tree.scss
new file mode 100644
index 0000000..eb58b3a
--- /dev/null
+++ b/dev/scss/main/tree.scss
@@ -0,0 +1,69 @@
+@charset "utf-8";
+@import "../util";
+
+/**
+ * SVG tree
+ */
+path.edge {
+ stroke: $darker-orange;
+ stroke-width: 2px;
+ fill: none;
+}
+
+marker#arr {
+ overflow: visible;
+ path {
+ fill-opacity:1;
+ stroke-width: 2;
+ stroke: $darkest-orange;
+ fill: $darkest-orange;
+ }
+}
+
+path.anchor {
+ stroke: $darkest-orange;
+ z-index: 20;
+}
+
+g.root rect.empty {
+ stroke: $darker-orange;
+ fill: $darker-orange;
+ stroke-width: 2px;
+}
+
+g.middle rect {
+ stroke: $darker-orange;
+ stroke-width: 2px;
+ fill: $middle-orange;
+}
+
+g.middle.mark {
+ rect {
+ fill: $darker-orange;
+ }
+ > text {
+ fill: $light-orange;
+ > tspan {
+ stroke: $light-orange;
+ }
+ }
+}
+
+
+g.leaf.mark text > tspan {
+ font-weight: bold;
+}
+
+g.leaf > rect {
+ display: none;
+}
+
+g > text > tspan {
+ text-anchor: middle;
+ font-size: 9pt;
+}
+
+g.leaf > text > tspan {
+ font-size: 10pt;
+ overflow: visible;
+}