summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.js16
-rw-r--r--src/model/graph.js106
-rw-r--r--src/rz_core.js99
-rw-r--r--src/view/selection.js80
4 files changed, 186 insertions, 115 deletions
diff --git a/src/main.js b/src/main.js
index b4f71001..feefcf57 100644
--- a/src/main.js
+++ b/src/main.js
@@ -1,5 +1,5 @@
-define(['textanalysis.ui', 'textanalysis', 'buttons', 'history', 'drag_n_drop', 'robot', 'model/core', 'rz_config', 'rz_core'],
-function(textanalysis_ui, textanalysis, buttons, history, drag_n_drop, robot, model_core, rz_config, rz_core) {
+define(['textanalysis.ui', 'textanalysis', 'buttons', 'history', 'drag_n_drop', 'robot', 'model/core', 'rz_config', 'rz_core', 'view/selection'],
+function(textanalysis_ui, textanalysis, buttons, history, drag_n_drop, robot, model_core, rz_config, rz_core, selection) {
function getParameterByName(name) {
name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
@@ -43,6 +43,18 @@ function(textanalysis_ui, textanalysis, buttons, history, drag_n_drop,
$('#search').focus();
}
};
+ // TODO: move me somewhere
+ $('#search').on('input', function(e) {
+ var text = this.value,
+ r = new RegExp(text.replace(' ', '|')); // TODO fails for quotes
+ console.log('search: ' + text);
+ if (text.length > 0) {
+ selection.byVisitors(function (n) { return n.name.match(r); });
+ } else {
+ selection.clear();
+ }
+ rz_core.update_view__graph(false);
+ });
// TODO: interaction between the hack above and this
model_core.init(rz_config);
textanalysis.init();
diff --git a/src/model/graph.js b/src/model/graph.js
index 6d13a83e..a71ba4c5 100644
--- a/src/model/graph.js
+++ b/src/model/graph.js
@@ -118,7 +118,7 @@ function Graph() {
* TODO: implement for d !== 1
*
*/
- this.getConnectedNodesAndLinks = function(n, d) {
+ this.getConnectedNodesAndLinks = function(chosen_nodes, d) {
var i = 0,
j = 0,
adjacentnode,
@@ -126,9 +126,7 @@ function Graph() {
link2,
ret = {'nodes':[], 'links':[]};
- $(".debug").html(n.state);
-
- if (n === undefined) {
+ if (chosen_nodes === undefined) {
console.log('getConnectedNodesAndLinks: bug: called with undefined node');
return;
}
@@ -137,38 +135,44 @@ function Graph() {
}
d = d || 1;
+ if (chosen_nodes.length === undefined) {
+ console.log('getConnectedNodesAndLinks: expected array');
+ }
+
while (i < links.length) {
link = links[i];
- // XXX: using name comparison because n might be stale
- if (compareNames(link.__src.name, n.name)) {
- adjacentnode = findNode(link.__dst.id, null);
- if (adjacentnode.state !== "temp") {
- ret.nodes.push({type: 'exit', node: adjacentnode});
- }
- ret.links.push({type: 'exit', link: link});
+ chosen_nodes.forEach(function (n) {
+ // XXX: using name comparison because n might be stale
+ if (compareNames(link.__src.name, n.name)) {
+ adjacentnode = findNode(link.__dst.id, null);
+ if (adjacentnode.state !== "temp") {
+ ret.nodes.push({type: 'exit', node: adjacentnode});
+ }
+ ret.links.push({type: 'exit', link: link});
- if (link.__dst.type === "chainlink") {
- while (j < links.length) {
- link2 = links[j];
- if (link.__dst.id === link2.__dst.id &&
- link2.__dst.type === "chainlink" &&
- link2.__dst.state !== "temp") {
- adjacentnode = findNode(link2.__src.id, null);
- if (adjacentnode.state !== "temp") {
- ret.nodes.push({type: 'enter', node: adjacentnode});
+ if (link.__dst.type === "chainlink") {
+ while (j < links.length) {
+ link2 = links[j];
+ if (link.__dst.id === link2.__dst.id &&
+ link2.__dst.type === "chainlink" &&
+ link2.__dst.state !== "temp") {
+ adjacentnode = findNode(link2.__src.id, null);
+ if (adjacentnode.state !== "temp") {
+ ret.nodes.push({type: 'enter', node: adjacentnode});
+ }
+ ret.links.push({type: 'enter', link: link2});
}
- ret.links.push({type: 'enter', link: link2});
+ j++;
}
- j++;
}
+ j=0;
}
- j=0;
- }
- if (compareNames(links[i].__dst.name, n.name)) {
- adjacentnode = findNode(links[i].__src.id, null);
- if (adjacentnode.state !== "temp") adjacentnode.state = "enter";
- links[i].state = "enter";
- }
+ if (compareNames(links[i].__dst.name, n.name)) {
+ adjacentnode = findNode(links[i].__src.id, null);
+ if (adjacentnode.state !== "temp") adjacentnode.state = "enter";
+ links[i].state = "enter";
+ }
+ });
i++;
}
return ret;
@@ -634,6 +638,50 @@ function Graph() {
var get_links = function() { return links; };
this.links = get_links;
+ function setRegularState() {
+ var x, node, link, s;
+
+ for (x in nodes) {
+ node = nodes[x];
+ s = node.state;
+ if (s === 'chosen' || s === 'enter' || s === 'exit') {
+ node.state = 'perm';
+ }
+ }
+ for (x in links) {
+ link = links[x];
+ s = link.state;
+ if (s === 'chosen' || s === 'enter' || s === 'exit') {
+ link.state = 'perm';
+ }
+ }
+ }
+ this.setRegularState = setRegularState;
+
+ this.findByVisitors = function(node_visitor, link_visitor) {
+ var n_length = nodes.length,
+ l_length = links.length,
+ selected = [],
+ i,
+ node,
+ link,
+ state;
+
+ if (!node_visitor) {
+ return;
+ }
+
+ for (i = 0 ; i < n_length; ++i) {
+ node = nodes[i];
+ if (node.state == 'temp') {
+ continue;
+ }
+ if (node_visitor(node)) {
+ selected.push(node);
+ }
+ }
+ return selected;
+ }
}
return {
diff --git a/src/rz_core.js b/src/rz_core.js
index 755f3364..83de9033 100644
--- a/src/rz_core.js
+++ b/src/rz_core.js
@@ -1,7 +1,7 @@
"use strict"
-define(['jquery', 'd3', 'consts', 'signal', 'util', 'model/graph', 'model/core', 'view/helpers', 'view/view', 'rz_observer'],
-function($, d3, consts, signal, util, model_graph, model_core, view_helpers, view, rz_observer) {
+define(['jquery', 'd3', 'consts', 'signal', 'util', 'model/graph', 'model/core', 'view/helpers', 'view/view', 'rz_observer', 'view/selection'],
+function($, d3, consts, signal, util, model_graph, model_core, view_helpers, view, rz_observer, selection) {
var addednodes = [];
@@ -24,10 +24,6 @@ var drag;
var force;
-// TODO hide inside a selection object? behavior? probably a good idea. route selection to it,
-// let it change state on nodes & links and query it for selection activity. (between 'select' and 'unselect')
-var selection; // boolean, true if there is a current selection
-
function recenterZoom() {
vis.attr("transform", "translate(0,0)scale(1)");
}
@@ -175,14 +171,6 @@ function canvas_handler_dblclick(){
});
}
-var node_selected = function(node) {
- return node.state == 'chosen' || node.state == 'enter' || node.state == 'exit';
-}
-
-var selected_class = function(node) {
- return selection ? (node_selected(node) ? "selected" : "notselected") : "";
-}
-
/**
* update view: graph
*/
@@ -212,7 +200,7 @@ function update_view__graph(no_relayout) {
.attr("markerHeight", 4)
.attr("orient", "auto")
.attr("class", function(d) {
- return selected_class(d);
+ return selection.selected_class(d);
})
.append("svg:path")
.attr("d", "M0,-5L10,0L0,5");
@@ -237,7 +225,7 @@ function update_view__graph(no_relayout) {
view.edge_info.hide();
});
view.edge_info.show(d);
- removeHighlight();
+ selection.clear();
highlight(src);
highlight(dst);
src.state = 'chosen';
@@ -248,12 +236,12 @@ function update_view__graph(no_relayout) {
link.attr("class", function(d, i){
var temp_and = (d.name && d.name.replace(/ /g,"")=="and" && d.state==="temp") ? "temp_and" : "";
- return ["graph link", temp_and, selected_class(d)].join(' ');
+ return ["graph link", temp_and, selection.selected_class(d)].join(' ');
});
link.selectAll('path.link')
.attr('class', function(d) {
- return [d.state, selected_class(d), "link graph"].join(' ');
+ return [d.state, selection.selected_class(d), "link graph"].join(' ');
});
link.exit().remove();
@@ -268,7 +256,7 @@ function update_view__graph(no_relayout) {
linktext.enter()
.append("text")
.attr("class", function(d) {
- return ["linklabel graph", selected_class(d)].join(' ');
+ return ["linklabel graph", selection.selected_class(d)].join(' ');
})
.attr("text-anchor", "middle")
.on("click", function(d, i) {
@@ -310,7 +298,7 @@ function update_view__graph(no_relayout) {
}
if (d.state !== "temp"){
editNode(this, d, i);
- removeHighlight();
+ selection.clear();
showInfo(this.node, i);
}
})
@@ -320,7 +308,7 @@ function update_view__graph(no_relayout) {
this.node = d;
})
.attr('class', function(d) {
- return ['node', selected_class(d)].join(' ');
+ return ['node', selection.selected_class(d)].join(' ');
});
nodetext = nodeEnter.insert("text")
@@ -360,10 +348,10 @@ function update_view__graph(no_relayout) {
}
d3.event.stopPropagation();
if(d.state!=="temp") {
- removeHighlight();
+ selection.clear();
showInfo(d, i);
} else {
- removeHighlight();
+ selection.clear();
}
update_view__graph(true);
});
@@ -390,7 +378,7 @@ function update_view__graph(no_relayout) {
})
.on("click", function(d, i) {
if(d.state!=="temp") {
- removeHighlight();
+ selection.clear();
showInfo(d, i);
}
});
@@ -580,66 +568,9 @@ function tick(e) {
node.attr('visibility', 'visible');
}
-function removeHighlight() {
- // TODO: stop manipulating state
- var nodes = graph.nodes(),
- links = graph.links(),
- k = 0, j = 0;
-
- selection = false;
- while (k < nodes.length) {
- if (nodes[k]['state'] === "enter" || nodes[k]['state'] === "exit" || nodes[k]['state'] === "chosen") {
- nodes[k]['state'] = "perm";
- }
- k++;
- }
- while (j < links.length) {
- links[j]['state'] = "perm";
- j++;
- }
-}
-
-function highlight(n)
-{
- var n,
- connected = graph.getConnectedNodesAndLinks(n, 1),
- i,
- node,
- link,
- data;
-
- selection = true;
- n.state = 'chosen';
-
- for (i = 0 ; i < connected.nodes.length ; ++i) {
- data = connected.nodes[i];
- node = data.node;
- switch (data.type) {
- case 'exit':
- node.state = 'exit';
- break;
- case 'enter':
- node.state = 'enter';
- break;
- };
- }
- for (i = 0 ; i < connected.links.length ; ++i) {
- data = connected.links[i];
- link = data.link;
- switch (data.type) {
- case 'exit':
- link.state = 'exit';
- break;
- case 'enter':
- link.state = 'enter';
- break;
- };
- }
-}
-
function showInfo(d, i) {
if (d.state !== "chosen" && d.state !== 'temp') {
- highlight(d);
+ selection.connectedComponent([d]);
view.node_info.show(d);
view.node_info.on_submit(function() {
if (d.type === "deliverable") {
@@ -658,7 +589,7 @@ function showInfo(d, i) {
}
});
} else {
- removeHighlight();
+ selection.clear();
view.node_info.hide();
}
update_view__graph(true);
@@ -669,7 +600,7 @@ function mousedown() {
$('.editinfo').css('left', 0);
$('.editlinkinfo').css('top', -100);
$('.editlinkinfo').css('left', 0);
- removeHighlight();
+ selection.clear();
view.hide();
update_view__graph(true);
}
diff --git a/src/view/selection.js b/src/view/selection.js
new file mode 100644
index 00000000..57f2443d
--- /dev/null
+++ b/src/view/selection.js
@@ -0,0 +1,80 @@
+define(['rz_core'],
+function(rz_core) {
+
+function get_rz_core()
+{
+ // circular dependency on rz_core, so require.js cannot solve it.
+ if (rz_core === undefined) {
+ rz_core = require('rz_core');
+ }
+ return rz_core;
+}
+
+var selection = false;
+
+function byVisitors(node_selector, link_selector) {
+ selection = true;
+ var selected_nodes = get_rz_core().graph.findByVisitors(node_selector, link_selector);
+
+ clear();
+ connectedComponent(selected_nodes);
+}
+
+function connectedComponent(nodes) {
+ var nodes,
+ connected = get_rz_core().graph.getConnectedNodesAndLinks(nodes, 1),
+ i,
+ node,
+ link,
+ data;
+
+ selection = true;
+ nodes.forEach(function (n) { n.state = 'chosen'; });
+
+ for (i = 0 ; i < connected.nodes.length ; ++i) {
+ data = connected.nodes[i];
+ node = data.node;
+ switch (data.type) {
+ case 'exit':
+ node.state = 'exit';
+ break;
+ case 'enter':
+ node.state = 'enter';
+ break;
+ };
+ }
+ for (i = 0 ; i < connected.links.length ; ++i) {
+ data = connected.links[i];
+ link = data.link;
+ switch (data.type) {
+ case 'exit':
+ link.state = 'exit';
+ break;
+ case 'enter':
+ link.state = 'enter';
+ break;
+ };
+ }
+}
+
+var node_selected = function(node) {
+ return node.state == 'chosen' || node.state == 'enter' || node.state == 'exit' || node.state == 'selected';
+}
+
+var selected_class = function(node) {
+ return selection ? (node_selected(node) ? "selected" : "notselected") : "";
+}
+
+var clear = function() {
+ selection = false;
+ get_rz_core().graph.setRegularState();
+}
+
+return {
+ 'byVisitors': byVisitors,
+ 'connectedComponent': connectedComponent,
+ 'clear': clear,
+ 'selected_class': selected_class,
+};
+
+});