From 2a2c6ddeb656e1af5382b05ca85f052576b805ec Mon Sep 17 00:00:00 2001 From: Alon Levy Date: Sun, 4 Jan 2015 19:15:05 +0200 Subject: bubble property used, lacks animation (noticeably) --- src/client/model/core.js | 4 +- src/client/model/graph.js | 7 +- src/client/rz_core.js | 58 +++++----------- src/client/textanalysis.js | 3 +- src/client/view/graph_view.js | 158 +++++++++++++++++++++++++++++++++--------- 5 files changed, 150 insertions(+), 80 deletions(-) (limited to 'src/client') diff --git a/src/client/model/core.js b/src/client/model/core.js index 18aa2507..3eab1596 100644 --- a/src/client/model/core.js +++ b/src/client/model/core.js @@ -71,8 +71,8 @@ define(['util'], function(util) { // type if (undefined == node_spec.type) { - console.debug('create_node_from_spec: undefined type, falling back to \'empty\''); - node_spec.type = 'empty'; + console.debug('create_node_from_spec: undefined type, falling back to \'perm\''); + node_spec.type = 'perm'; } ret.type = node_spec.type; diff --git a/src/client/model/graph.js b/src/client/model/graph.js index 61797886..2c8298ad 100644 --- a/src/client/model/graph.js +++ b/src/client/model/graph.js @@ -688,14 +688,17 @@ function Graph(temporary) { return foundNodes; } - function clear() { + function clear(push_diff) { + push_diff = push_diff === undefined ? true : push_diff; id_to_node_map = {}; node_map = {} id_to_link_map = {}; link_map = {}; invalidate_links = true; invalidate_nodes = true; - // FIXME: push on diffBus? + if (push_diff) { + diffBus.push({}); // FIXME: better value + } } this.clear = clear; diff --git a/src/client/rz_core.js b/src/client/rz_core.js index bd1dc141..5c83407e 100644 --- a/src/client/rz_core.js +++ b/src/client/rz_core.js @@ -178,7 +178,7 @@ var svgInput = (function() { var zoomProgress = false; var zoomBus = new Bacon.Bus(); -var zoomProperty = zoomBus.toProperty(); +var zoom_property = zoomBus.toProperty(); zoomBus.push(zoomProgress); // set initial value function svg_click_handler(e) { @@ -263,20 +263,29 @@ var initDrawingArea = function () { $('svg').click(svg_click_handler); main_graph_view = graph_view.GraphView({ - vis: vis.append('g'), + parent_element: vis, graph_name: "main", graph: main_graph, - zoomProperty: zoomProperty, - forceEnabled: true, + zoom_property: zoom_property, + temporary: false, node_text_dx: node_text_dx, node_text_dy: node_text_dy, + svgInput: svgInput, + // FIXME: good place to animate bubble radius + bubble_property: edit_graph.diffBus.map(function () { + if (edit_graph.nodes().length == 0) { + return 0; + } else { + return 180; + } + }), }); edit_graph_view = graph_view.GraphView({ - vis: vis.append('g'), + parent_element: vis, graph_name: "edit", graph: edit_graph, - zoomProperty: zoomProperty, - forceEnabled: false, + zoom_property: zoom_property, + temporary: true, node_text_dx: node_text_dx, node_text_dy: node_text_dy, }); @@ -344,41 +353,6 @@ function canvas_handler_dblclick(){ }); } -function showNodeInfo(node, i) { - var closed = false; - - view.node_info.on_save(function(e, form_data) { - closed = true; - main_graph.update_node(node, form_data, function() { - var old_type = node.type, - new_type = form_data.type; - - }); - view.node_info.hide(); - return false; - }); - - // FIXME - attribute diff, ignore uninteresting diffs via filtering - main_graph.diffBus.onValue(function () { - if (closed) { - return Bacon.noMore; - } - view.node_info.show(node); - }); - - view.node_info.on_delete(function() { - var topo_diff = model_diff.new_topo_diff({ - node_set_rm: [node.id] - }); - console.log("closing node info"); - closed = true; - view.node_info.hide(); - main_graph.commit_and_tx_diff__topo(topo_diff); - }); - - view.node_info.show(node); -} - function update_view__graph(relayout) { main_graph_view.update_view(relayout); diff --git a/src/client/textanalysis.js b/src/client/textanalysis.js index a34aac7f..9729068d 100644 --- a/src/client/textanalysis.js +++ b/src/client/textanalysis.js @@ -443,7 +443,8 @@ var textAnalyser = function (newtext, finalize) { }); // REINITIALISE GRAPH (DUMB BUT IT WORKS) - edit_graph.clear(); + edit_graph.clear(false + /* don't push diff, avoid bubble on main_graph going to zero */); if (!finalize) { main_graph.markRelated(token_set_new_node_names); diff --git a/src/client/view/graph_view.js b/src/client/view/graph_view.js index baa321be..0db8fd97 100644 --- a/src/client/view/graph_view.js +++ b/src/client/view/graph_view.js @@ -25,33 +25,54 @@ * which resulted in overly complex (read: undefined/buggy) code. */ -define(['d3', 'Bacon', 'util', 'view/selection', 'view/helpers', 'model/diff'], -function(d3 , Bacon , util , selection , view_helpers, model_diff) { +define(['d3', 'Bacon', 'util', 'view/selection', 'view/helpers', 'model/diff', 'view/view'], +function(d3 , Bacon , util , selection , view_helpers, model_diff , view) { +/* + * Creates a new view on the given graph contained in an appended last child + * to the given parent node, parent + * + */ function GraphView(spec) { - var forceEnabled = spec.forceEnabled, - temporary = spec.forceEnabled, // graph wide variable, not per node/link - vis = spec.vis, + var temporary = spec.temporary, + force_enabled = !spec.temporary, + parent_element = spec.parent_element, graph_name = spec.graph_name, graph = spec.graph, - zoomProperty = spec.zoomProperty, + zoom_property = spec.zoom_property, node_text_dx = spec.node_text_dx, node_text_dy = spec.node_text_dy, + svgInput = spec.svgInput, + bubble_radius = 0, zoomInProgress = false, force, - drag; - - util.assert(vis !== undefined && graph_name !== undefined && - graph !== undefined && zoomProperty !== undefined && - (temporary !== undefined) && (forceEnabled !== undefined) && - node_text_dx !== undefined && node_text_dy !== undefined, + drag, + vis, + // FIXME - want to use parent_element + w = $(document.body).innerWidth(), + h = $(document.body).innerHeight(), + cx = w / 2, + cy = h / 2; + + util.assert(parent_element !== undefined && graph_name !== undefined && + graph !== undefined && zoom_property !== undefined && + temporary !== undefined && force_enabled !== undefined && + node_text_dx !== undefined && node_text_dy !== undefined && + (temporary || svgInput !== undefined), "missing spec variable"); - zoomProperty.onValue(function (val) { + zoom_property.onValue(function (val) { zoomInProgress = val; }); + if (spec.bubble_property) { + spec.bubble_property.onValue(function (r) { + bubble_radius = r; + update_view(false); + }); + } + graph.diffBus.onValue(function (diff) { var relayout = !temporary && (false == model_diff.is_attr_diff(diff)); if (relayout) { @@ -63,11 +84,48 @@ function GraphView(spec) { update_view(relayout); }); + function showNodeInfo(node, i) { + var closed = false; + + util.assert(!temporary, "cannot showNodeInfo on a temporary graph"); + + view.node_info.on_save(function(e, form_data) { + closed = true; + graph.update_node(node, form_data, function() { + var old_type = node.type, + new_type = form_data.type; + + }); + view.node_info.hide(); + return false; + }); + + // FIXME - attribute diff, ignore uninteresting diffs via filtering + graph.diffBus.onValue(function () { + if (closed) { + return Bacon.noMore; + } + view.node_info.show(node); + }); + + view.node_info.on_delete(function() { + var topo_diff = model_diff.new_topo_diff({ + node_set_rm: [node.id] + }); + console.log("closing node info"); + closed = true; + view.node_info.hide(); + graph.commit_and_tx_diff__topo(topo_diff); + }); + + view.node_info.show(node); + } + function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); d3.select(this).classed("dragging", true); d.dragstart = {clientX:d3.event.sourceEvent.clientX, clientY:d3.event.sourceEvent.clientY}; - if (forceEnabled) { + if (force_enabled) { force.stop(); } } @@ -84,7 +142,7 @@ function GraphView(spec) { if (d.dragstart.clientX - d3.event.sourceEvent.clientX != 0 || d.dragstart.clientY - d3.event.sourceEvent.clientY != 0) { tick(); - if (forceEnabled) { + if (force_enabled) { force.resume(); } } @@ -97,8 +155,10 @@ function GraphView(spec) { link_g, linktext, nodetext, - unselected_link_group = document.querySelector('#link-group'), - selected_link_group = document.querySelector('#selected-link-group'); + unselected_selector = '#' + graph_name + ' #link-group', + selected_selector = '#' + graph_name + ' #selected-link-group', + unselected_link_group = document.querySelector(unselected_selector), + selected_link_group = document.querySelector(selected_selector); relayout = relayout || true; @@ -145,7 +205,7 @@ function GraphView(spec) { link.selectAll('path.link') .attr('class', function(d) { - return [d.state, selection.selected_class(d), "link graph"].join(' '); + return [d.state || "perm", selection.selected_class(d), "link graph"].join(' '); }); link.exit().remove(); @@ -340,9 +400,9 @@ function GraphView(spec) { //Do something } - if (forceEnabled) { + if (force_enabled) { force.nodes(graph.nodes()) - .links(graph.links()) + .links(graph.links()); if (relayout) { force.alpha(0.1).start(); @@ -351,9 +411,27 @@ function GraphView(spec) { // and this is the simplest way tick(); } + } else { + start_layout_animation(); } } + function start_layout_animation() { + var interval_id, + count = 0, + on_interval = function() { + tick(); + count += 1; + if (count > 30) { + clearInterval(interval_id); + console.log('stopping layout animation'); + } + }; + console.log('starting layout animation'); + interval_id = setInterval(on_interval, 30); + on_interval(); + } + var debug_print = function(message) { var element = $(".debug"); if (element.length == 1) { @@ -366,7 +444,7 @@ function GraphView(spec) { function check_for_nan(x) { if (Number.isNaN(x)) { console.log('nan problem'); - if (forceEnabled) { + if (force_enabled) { force.stop(); } } @@ -389,20 +467,35 @@ function GraphView(spec) { graph.nodes().forEach(function(d, i) { var r, a; tempcounter++; - if (d.type==="chainlink") { - d.x = window.innerWidth / 2; - d.y = window.innerHeight / 2; + if (d.type === "chainlink") { + d.x = cx; + d.y = cy; } else { r = 60 + newnodes * 20; a = -Math.PI + Math.PI * 2 * (tempcounter-1) / newnodes + 0.3; - d.x = window.innerWidth / 2 + r * Math.cos(a); - d.y = window.innerHeight / 2 + r * Math.sin(a); + console.log(tempcounter); + d.x = cx + r * Math.cos(a); + d.y = cy + r * Math.sin(a); } check_for_nan(d.x); check_for_nan(d.y); }); } + function bubble_transform(d) { + if (bubble_radius == 0) { + return d; + } + console.log(graph_name + ': with bubble'); + var dx = d.x - cx, + dy = d.y - cy, + r = Math.sqrt(dx * dx + dy * dy), + a = Math.atan2(dx, dy); + // FIXME: r == 0 (or close enough) + return {x: cx + (r + bubble_radius) * Math.cos(a), + y: cy + (r + bubble_radius) * Math.sin(a)}; + } + function tick(e) { //console.log(e); //$(".debug").html(force.alpha()); @@ -420,7 +513,8 @@ function GraphView(spec) { if (check_for_nan(d.x) || check_for_nan(d.y)) { return; } - return "translate(" + d.x + "," + d.y + ")"; + var d2 = bubble_transform(d); + return "translate(" + d2.x + "," + d2.y + ")"; } if (temporary) { @@ -454,6 +548,8 @@ function GraphView(spec) { // SVG rendering order is last rendered on top, so to make sure // all links are below the nodes we group them under a single g + vis = parent_element.append("g"); + vis.attr("id", graph_name); vis.append("g").attr("id", "link-group"); vis.append("g").attr("id", "selected-link-group"); @@ -463,11 +559,7 @@ function GraphView(spec) { .on("drag", dragged) .on("dragend", dragended); - function init_force_layout(){ - var el = document.body; - var w = $(el).innerWidth(), - h = $(el).innerHeight(); - + function init_force_layout() { force = d3.layout.force() .distance(120) .gravity(0.12) @@ -477,7 +569,7 @@ function GraphView(spec) { .start(); } - if (forceEnabled) { + if (force_enabled) { init_force_layout(); } return { -- cgit v1.3.1