On 02/03/2016 03:37 PM, Pavel Vomacka wrote:
Hello,

I'm sending a patch for review. This patch adds pan and zoom functionality to the topology graph. The page remembers old position and size of the graph. So, it keeps these settings after refreshing the page.

The patch is in atachement.

Pavel Vomacka


Hello,

I found one small bug during developing another features so I'm sending a new patch. There were situations when you turned off the fixed state of node by doubleclick but the node stayed at the same place. This behaviour was caused by missing layout.resume() in the dragended event handler.

I also forgot to add a link to the ticket. So, here it is: https://fedorahosted.org/freeipa/ticket/5502 .

The new patch is in atachement.

--
Pavel^3 Vomacka
>From 58e89820a1df635f5ec3ee1bbbaabb3f237b478c Mon Sep 17 00:00:00 2001
From: Pavel Vomacka <pvoma...@redhat.com>
Date: Wed, 3 Feb 2016 15:22:47 +0100
Subject: [PATCH] Add pan and zoom functionality to the topology graph

Add zooming and panning functionality to the topology graph. Also the page rememberes
the old setting of the graph position and size. So, after refreshing the graph has
the same position and size as it had before.

https://fedorahosted.org/freeipa/ticket/5502
---
 install/ui/src/freeipa/topology_graph.js | 97 ++++++++++++++++++++++++++++++--
 1 file changed, 91 insertions(+), 6 deletions(-)

diff --git a/install/ui/src/freeipa/topology_graph.js b/install/ui/src/freeipa/topology_graph.js
index 23c7f6221a1e54770dcf08b3ebfc0b0a42810700..8d8876f9063abe20c4fbb7f13a490a6b9c12569b 100644
--- a/install/ui/src/freeipa/topology_graph.js
+++ b/install/ui/src/freeipa/topology_graph.js
@@ -74,20 +74,42 @@ topology_graph.TopoGraph = declare([Evented], {
      * @param  {Array} suffixes array of suffixes
      */
     update: function(nodes, links, suffixes) {
+        var that = this;
+
+        var curr_trasform = this._get_stored_transformation();
+
+        // adds zoom behavior to the svg
+        var zoom = d3.behavior.zoom()
+            .translate(curr_trasform.translate)
+            .scale(curr_trasform.scale)
+            .scaleExtent([0.2, 1])
+            .on("zoom", zoomed);
+
         // delete all from svg
         this._svg.selectAll("*").remove();
         this._svg.attr('width', this.width)
-                 .attr('height', this.height);
+                 .attr('height', this.height)
+                 .call(zoom);
+
+        function zoomed() {
+            that._svg.selectAll('g.shapes')
+                .attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
+            that._store_current_transformation();
+        }
 
         this.links = links;
         this.nodes = nodes;
         this.suffixes = suffixes;
 
         // load saved coordinates
+        // node.fixed internally uses numbers instead of booleans
+        // this  is useful when you need to store the original value and set
+        // the node temporarily fixed
         for (var i=0,l=nodes.length; i<l; i++) {
             var node = nodes[i];
+            node.fixed = 0;
             if (this._get_local_storage_attr(node.id, 'fixed') === 'true') {
-                node.fixed = true;
+                node.fixed = 1;
                 node.x = Number(this._get_local_storage_attr(node.id, 'x'));
                 node.y = Number(this._get_local_storage_attr(node.id, 'y'));
             }
@@ -97,8 +119,8 @@ topology_graph.TopoGraph = declare([Evented], {
         this._define_shapes();
 
         // handles to link and node element groups
-        this._path = this._svg.append('svg:g').selectAll('path');
-        this._circle = this._svg.append('svg:g').selectAll('g');
+        this._path = this._svg.append('svg:g').classed('shapes', true).selectAll('path');
+        this._circle = this._svg.append('svg:g').classed('shapes', true).selectAll('g');
 
         this._selected_link = null;
         this._mouseup_node = null;
@@ -147,6 +169,34 @@ topology_graph.TopoGraph = declare([Evented], {
         }
     },
 
+    _store_current_transformation: function(d) {
+        this._set_local_storage_attr("svg_", "translate", d3.event.translate);
+        this._set_local_storage_attr("svg_", "scale", d3.event.scale);
+    },
+
+    _get_stored_transformation: function(d) {
+        var current_translate = this._get_local_storage_attr("svg_", "translate");
+        var current_scale = this._get_local_storage_attr("svg_", "scale");
+
+        if (current_translate) {
+            var temp_translate = current_translate.split(",");
+            temp_translate[0] = parseInt(temp_translate[0], 10);
+            temp_translate[1] = parseInt(temp_translate[1], 10);
+            current_translate = temp_translate;
+        } else {
+            current_translate = [0, 0];
+        }
+
+        if (!current_scale) {
+            current_scale = 1;
+        }
+
+        return {
+            translate: current_translate,
+            scale: current_scale
+        };
+    },
+
     /**
      * Simulation tick which
      *
@@ -339,13 +389,42 @@ topology_graph.TopoGraph = declare([Evented], {
             }
         );
 
+        var drag = d3.behavior.drag()
+            .on("dragstart", dragstarted)
+            .on("drag", dragged)
+            .on("dragend", dragended);
+
+        function dragstarted(d) {
+            d3.event.sourceEvent.stopPropagation();
+            // Store the original value of fixed and set the node fixed.
+            d.fixed = d.fixed << 1;
+            d.fixed |= 1;
+        }
+
+        function dragged(d) {
+            d.px = d3.event.x;
+            d.py = d3.event.y;
+            d3.select(this).attr('transform', "translate(" + d.x + ", " + d.y + ")");
+            self._layout.resume();
+        }
+
+        function dragended(d) {
+            // Restore old value of fixed.
+            d.fixed = d.fixed >> 1;
+            self._layout.resume();
+        }
+
         // add new nodes
         var g = this._circle.enter()
             .append('svg:g')
             .on("dblclick", function(d) {
-                d.fixed = !d.fixed;
+                // Stops propagation dblclick event to the zoom behavior.
+                d3.event.preventDefault();
+                d3.event.stopPropagation();
+                //xor operation switch value of fixed from 1 to 0 and vice versa
+                d.fixed = d.fixed ^ 1;
             })
-            .call(self._layout.drag);
+            .call(drag);
 
         g.append('svg:circle')
             .attr('class', 'node')
@@ -369,6 +448,12 @@ topology_graph.TopoGraph = declare([Evented], {
 
         // remove old nodes
         self._circle.exit().remove();
+
+        // get previously set position and scale of the graph and move current
+        // graph to the proper position
+        var trans = self._get_stored_transformation();
+        self._svg.selectAll('g.shapes')
+            .attr('transform', 'translate(' + trans.translate + ')scale(' + trans.scale + ')');
     },
 
     constructor: function(spec) {
-- 
2.5.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to