diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.js | 16 | ||||
| -rw-r--r-- | src/model/graph.js | 106 | ||||
| -rw-r--r-- | src/rz_core.js | 99 | ||||
| -rw-r--r-- | src/view/selection.js | 80 |
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, +}; + +}); |
