Author: clopes
Date: 2011-10-19 12:13:46 -0700 (Wed, 19 Oct 2011)
New Revision: 27236

Modified:
   cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js
   
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/controller/RemoveItemsCommand.as
   cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
   
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
   cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/ExternalMediator.as
   cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/GraphMediator.as
   
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/NodeRenderer.as
   
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
Log:
Fixed compound node not getting back to a "regular" node state after deleting 
all of its children.
Refactored addElements (moved logic to GraphProxy and GraphMediator) and fixed 
compound nodes not being removed from cache after deleting them. Also fixed 
listeners disposal (when removing elements), to prevent memory leaks.

Modified: cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js   2011-10-19 
18:57:46 UTC (rev 27235)
+++ cytoscapeweb/trunk/cytoscapeweb/html-template/js/tests.js   2011-10-19 
19:13:46 UTC (rev 27236)
@@ -541,7 +541,7 @@
     test("Visual Style--transparent nodes", function() {
        vis.visualStyle({ 
                global: { backgroundColor: "transparent" },
-               nodes: { color: "transparent" },
+               nodes: { color: "transparent", compoundColor: "transparent" },
                edges: { color: "transparent" }
        });
        same(vis.visualStyle().global.backgroundColor, "#ffffff", "Visual Style 
backgroundColor color");

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/controller/RemoveItemsCommand.as
===================================================================
--- 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/controller/RemoveItemsCommand.as
       2011-10-19 18:57:46 UTC (rev 27235)
+++ 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/controller/RemoveItemsCommand.as
       2011-10-19 19:13:46 UTC (rev 27236)
@@ -49,9 +49,10 @@
                 
                 if (items == null) {
                     items = [];
-                    if (group === Groups.NODES || group === Groups.NONE) items 
= items.concat(graphProxy.nodes);
-                    if (group === Groups.EDGES || group === Groups.NONE) items 
= items.concat(graphProxy.edges);
-                    
+                    if (group === Groups.NODES || group === Groups.NONE)
+                        items = items.concat(graphProxy.nodes);
+                    if (group === Groups.EDGES || group === Groups.NONE)
+                        items = items.concat(graphProxy.edges);
                 } else {
                     items = graphProxy.getDataSpriteList(items, group);
                 }

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as    
2011-10-19 18:57:46 UTC (rev 27235)
+++ cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/GraphProxy.as    
2011-10-19 19:13:46 UTC (rev 27236)
@@ -756,69 +756,19 @@
         
         public function remove(items:Array):void {
             for each (var ds:DataSprite in items) {
-                if (ds is NodeSprite) {
-                    removeNode(NodeSprite(ds));
+                if (ds is CompoundNodeSprite) {
+                    removeNode(ds as CompoundNodeSprite);
                 } else {
-                    removeEdge(EdgeSprite(ds));
+                    removeEdge(ds as EdgeSprite);
                 }
             }
+            
             // Reset auto-increment ID lookup:
             if (nodes.length === 0) _ids[Groups.NODES] = 0;
             if (edges.length === 0) _ids[Groups.EDGES] = 0;
             if (mergedEdges.length === 0) _ids[Groups.MERGED_EDGES] = 0;
         }
         
-        public function removeNode(n:NodeSprite):void {
-            if (n == null) return;
-            deleteCache(n);
-            
-            if (n.props.$selected) 
graphData.group(Groups.SELECTED_NODES).remove(n);
-            
-            var filterList:DataList = graphData.group(Groups.FILTERED_NODES);
-            if (filterList != null) filterList.remove(n);
-       
-            // Also remove its linked edges:
-            var edges:Array = [];
-            n.visitEdges(function(e:EdgeSprite):Boolean {
-                edges.push(e);
-                return false;
-            }, NodeSprite.GRAPH_LINKS);
-            remove(edges);
-            
-            graphData.removeNode(n);
-        }
-        
-        public function removeEdge(e:EdgeSprite):void {
-            if (e == null) return;
-            deleteCache(e);
-            
-            // Delete edge:
-            graphData.removeEdge(e);
-            
-            // Delete or update related objects:
-            if (e.props.$merged) {
-                // MERGED...
-                // Delete children ("regular") edges:
-                var children:Array = e.props.$edges;
-                if (children.length > 0) remove(children);
-            } else {
-                // REGULAR EDGE:
-                // Update or delete the interaction:
-                var inter:InteractionVO = getInteraction(e.source, e.target);
-                
-                if (inter != null) {
-                    var edgeCount:int = inter.edges.length;
-                    
-                    if (edgeCount > 0) {
-                        inter.update(edgesSchema);
-                    } else {
-                        delete _interactions[inter.key];
-                        removeEdge(inter.mergedEdge);
-                    }
-                }
-            }
-        }
-
         public function loadGraph(network:*, layout:*):void {
             try {
                 var ds:DataSet;
@@ -935,6 +885,95 @@
         
         // ========[ PRIVATE METHODS 
]==============================================================
         
+        private function removeNode(n:CompoundNodeSprite):void {
+            if (n == null) return;
+            var stack:Array = [n], edges:Array;
+            var child:CompoundNodeSprite, parent:CompoundNodeSprite;
+            
+            while (stack.length > 0) {
+                n = stack.pop();
+                if (n.props.$deleted) continue;
+                
+                trace("Deleting Node (" + n.data.id + ")...");
+                deleteCache(n);
+           
+                // Remove children:
+                if (n.nodesCount > 0) {
+                    for each (child in n.getNodes()) {
+                        if (!child.props.$deleted) stack.push(child);
+                    }
+                }
+                
+                // Remove it from its parent, if it is a child:
+                if (n.data.parent != null) {
+                    parent = getNode(n.data.parent);
+                    if (parent != null) {
+                        parent.removeNode(n);
+                        
+                        if (parent.nodesCount === 0) {
+                            
graphData.group(Groups.COMPOUND_NODES).remove(parent);
+                        }
+                    }
+                }
+           
+                // Also remove its linked edges:
+                edges = [];
+                n.visitEdges(function(e:EdgeSprite):Boolean {
+                    edges.push(e);
+                    return false;
+                }, NodeSprite.GRAPH_LINKS);
+                remove(edges);
+                
+                graphData.removeNode(n);
+                n.props.$deleted = true;
+            }
+        }
+        
+        private function removeEdge(e:EdgeSprite):void {
+            var stack:Array = [e], children:Array;
+            var child:EdgeSprite, parent:EdgeSprite;
+            var inter:InteractionVO;
+            
+            while (stack.length > 0) {
+                e = stack.pop();
+                if (e.props.$deleted) continue;
+                
+                trace("Deleting Edge (" + e.data.id + ")...");
+                
+                inter = getInteraction(e.source, e.target);
+                
+                // Delete edge:
+                deleteCache(e);
+                graphData.removeEdge(e);
+                e.props.$deleted = true;
+            
+                // Delete or update related objects:
+                if (e.props.$merged) {
+                    // MERGED...
+                    // Delete children ("regular") edges:
+                    children = e.props.$edges;
+                    
+                    if (children.length > 0) {
+                        for each (child in children) {
+                            if (!child.props.$deleted) stack.push(child);
+                        }
+                    }
+                    
+                    delete _interactions[inter.key];
+                } else {
+                    // REGULAR EDGE:
+                    // Update or delete the interaction:
+                    if (inter != null) {
+                        if (inter.edges.length > 0) {
+                            inter.update(edgesSchema);
+                        } else {
+                            stack.push(inter.mergedEdge);
+                        }
+                    }
+                }
+            }
+        }
+        
         /**
          * Create a mapping of nodes and edges, with their IDs as key,
          * in order to make it easier to get them later.
@@ -981,6 +1020,12 @@
                 fl = graphData.group(Groups.FILTERED_NODES);
                 if (fl != null) fl.remove(ds);
                 
+                // Also remove parent from compound group, if it has no 
children:
+                var parent:CompoundNodeSprite = this.getNode(ds.data.parent);
+                if (parent != null && parent.nodesCount === 0) {
+                    graphData.group(Groups.COMPOUND_NODES).remove(parent);
+                    trace(">> removed compound from group >> "+parent.data.id);
+                }
             } else if (ds is EdgeSprite) {
                 delete _edgesMap[ds.data.id];
 

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
===================================================================
--- 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
    2011-10-19 18:57:46 UTC (rev 27235)
+++ 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/model/data/InteractionVO.as
    2011-10-19 19:13:46 UTC (rev 27236)
@@ -93,7 +93,10 @@
         public function get edges():Array {
             var edges:Array = [];
             node1.visitEdges(function(e:EdgeSprite):Boolean {
-                if (!e.props.$merged && hasNodes(e.source, e.target)) 
edges.push(e);
+                if (!e.props.$merged && hasNodes(e.source, e.target)) {
+                    e.props.$parent = _mergedEdge;
+                    edges.push(e);
+                }
                 return false;
             }, loop ? NodeSprite.IN_LINKS : NodeSprite.GRAPH_LINKS);
             

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/ExternalMediator.as
===================================================================
--- 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/ExternalMediator.as   
    2011-10-19 18:57:46 UTC (rev 27235)
+++ 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/ExternalMediator.as   
    2011-10-19 19:13:46 UTC (rev 27236)
@@ -51,7 +51,6 @@
     import org.cytoscapeweb.model.data.VisualStyleVO;
     import org.cytoscapeweb.model.error.CWError;
     import org.cytoscapeweb.model.methods.error;
-    import org.cytoscapeweb.util.CompoundNodes;
     import org.cytoscapeweb.util.ExternalFunctions;
     import org.cytoscapeweb.util.Groups;
     import org.cytoscapeweb.vis.data.CompoundNodeSprite;
@@ -555,84 +554,6 @@
         private function removeElements(group:String=Groups.NONE,
                                         items:Array=null, 
                                         
updateVisualMappers:Boolean=false):void {
-            var id:*;
-            var ns:NodeSprite;
-            var cns:CompoundNodeSprite;
-            
-            var childMap:Object = new Object();
-            var childList:Array;
-            var node:NodeSprite;
-            var parentId:String;
-            
-            if (items != null) {
-                // for each item to be removed check whether it is a compound
-                // node or not
-                
-                for each (var item:* in items) {
-                    if (item != null)  {
-                        id = item;
-                        
-                        if (item.hasOwnProperty("data") && item.data.id != 
null) {
-                            id = item.data.id;
-                        }
-                    }
-                    
-                    ns = this.graphProxy.getNode(id);
-                    
-                    if (ns != null) {
-                        if (ns is CompoundNodeSprite) {
-                            cns = (ns as CompoundNodeSprite);
-                            
-                            // if ns is also selected then add non-selected
-                            // children of the compound to the list of nodes
-                            // to be removed
-                            if (ns.props.$selected) {
-                                childList = CompoundNodes.getChildren(cns,
-                                                                      
CompoundNodes.NON_SELECTED);
-                            } else {
-                                // otherwise add all children of the compound
-                                // to the list of nodes to be removed
-                                childList = CompoundNodes.getChildren( cns);
-                            }
-                            
-                            //update map of child nodes to be removed
-                            for each (node in childList) {
-                                // assuming node.data.id is not null
-                                childMap[node.data.id] = node;
-                            }
-                            
-                            for each (node in cns.getNodes()) {
-                                // remove each node from the compound node,
-                                // this also resets the parent id of the node
-                                cns.removeNode(node);
-                            }
-                        }
-                        
-                        parentId = ns.data.parent;
-                        
-                        // remove ns from its parent compound's children list 
-                        // if it is in a compound
-                                            
-                        if (parentId != null) {
-                            // get the parent node
-                            cns = this.graphProxy.getNode(parentId)
-                                as CompoundNodeSprite;
-                            
-                            // remove current node from the compound node
-                            if (cns != null) {
-                                cns.removeNode(ns);
-                            }
-                        }
-                        
-                    }
-                }
-                
-                // update items with the new list of nodes to be removed
-                for each (node in childMap) {
-                    items.push(node);
-                }
-            }
-            
             sendNotification(ApplicationFacade.REMOVE_ITEMS,
                              { group: group, items: items, 
updateVisualMappers: updateVisualMappers });
         }

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/GraphMediator.as
===================================================================
--- cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/GraphMediator.as  
2011-10-19 18:57:46 UTC (rev 27235)
+++ cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/GraphMediator.as  
2011-10-19 19:13:46 UTC (rev 27236)
@@ -306,18 +306,66 @@
         }
         
         public function dispose(items:Array):void {
+            var ds:DataSprite, n:CompoundNodeSprite, child:CompoundNodeSprite;
+            var e:EdgeSprite, me:EdgeSprite;
+            var stack:Array = items.concat();
+            var mergedEdges:Array = [];
+            
             // Remove event listeners:
-            for each (var ds:DataSprite in items) {
+            while (stack.length > 0) {
+                ds = stack.pop();
+                if (ds.props.$disposed) continue;
+                
+                trace("Disposing " + ds + " (" + ds.data.id + ")...");
                 disposeDataSprite(ds);
                 
-                if (ds is NodeSprite) {
+                if (ds is CompoundNodeSprite) {
+                    n = ds as CompoundNodeSprite;
+                    
                     // Also dispose its linked edges:
-                    NodeSprite(ds).visitEdges(function(e:EdgeSprite):Boolean {
-                        disposeDataSprite(e);
+                    n.visitEdges(function(e:EdgeSprite):Boolean {
+                        if (!e.props.$disposed) stack.push(e);
                         return false;
                     });
+                    
+                    if (n.nodesCount > 0) {
+                        for each (child in n.getNodes()) {
+                            if (!child.props.$disposed) stack.push(child);
+                        }
+                    }
+                } else if (ds is EdgeSprite) { 
+                    if (ds.props.$merged && ds.props.$edges != null) {
+                        for each (e in ds.props.$edges) {
+                            if (!e.props.$disposed) stack.push(e);
+                        }
+                    } else if (ds.props.$parent != null) {
+                        // save for later disposal...
+                        if (!ds.props.$parent.props.$disposed)
+                            mergedEdges.push(ds.props.$parent);
+                    }
                 }
             }
+            
+            var shallDispose:Boolean;
+            
+            // Finally dispose "empty" mergedEdges:
+            for each (me in mergedEdges) {
+                if (!me.props.$disposed) {
+                    shallDispose = true;
+                    
+                    for each (e in me.props.$edges) {
+                        if (!e.props.$disposed) {
+                            shallDispose = false;
+                            break;
+                        }
+                    }
+                    
+                    if (shallDispose) {
+                        trace("Disposing merged Edge (" + me.data.id + ")...");
+                        disposeDataSprite(me);
+                    }
+                }
+            }
         }
         
         public function zoomGraphTo(scale:Number):void {
@@ -729,8 +777,7 @@
             } else {
                 if (target is CompoundNodeSprite) {
                     children = children.concat(
-                        CompoundNodes.getChildren(
-                            target as CompoundNodeSprite));
+                        CompoundNodes.getChildren(target as 
CompoundNodeSprite));
                 }
                 
                 children = children.concat([target]);
@@ -746,7 +793,6 @@
             var n:CompoundNodeSprite;
             
             // drag all necessary nodes
-            
             for each (n in nodes) {
                 if (n != target) {
                     n.x += amountX;
@@ -777,8 +823,7 @@
                         ns = this.graphProxy.getNode(parentId);
                         
                         if (ns != null) {
-                            // only update if the parent is not also being
-                            // dragged
+                            // only update if the parent is not also being 
dragged
                             if (!ns.props.$selected || (n == target && 
!n.props.$selected)) {
                                 // update the bounds of the compound node
                                 this.vis.updateCompoundBounds(ns);
@@ -797,8 +842,7 @@
                 
                 // update bound coordinates of dragged compound nodes
                 if (n is CompoundNodeSprite) {
-                    if ((n as CompoundNodeSprite).bounds != null)
-                    {
+                    if ((n as CompoundNodeSprite).bounds != null) {
                         (n as CompoundNodeSprite).bounds.x += amountX;
                         (n as CompoundNodeSprite).bounds.y += amountY;
                     }
@@ -950,6 +994,7 @@
             
             // Avoinding errors in case the tooltip is about to be shown:
             ds.dispatchEvent(new MouseEvent(MouseEvent.MOUSE_OUT, true, false, 
0, 0, vis));
+            ds.props.$disposed = true;
         }
         
         private function updateCursor():void {

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/NodeRenderer.as
===================================================================
--- 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/NodeRenderer.as
    2011-10-19 18:57:46 UTC (rev 27235)
+++ 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/view/render/NodeRenderer.as
    2011-10-19 19:13:46 UTC (rev 27236)
@@ -87,7 +87,7 @@
         // ========[ PUBLIC METHODS 
]===============================================================
         
         /** @inheritDoc */
-        public override function render(d:DataSprite):void {trace("RENDER 
NODE: " + d.data.id);
+        public override function render(d:DataSprite):void {
             try {
                 // Using a bit mask to avoid transparent mdes when 
fillcolor=0xffffffff.
                 // See https://sourceforge.net/forum/message.php?msg_id=7393265

Modified: 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
===================================================================
--- 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
 2011-10-19 18:57:46 UTC (rev 27235)
+++ 
cytoscapeweb/trunk/cytoscapeweb/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
 2011-10-19 19:13:46 UTC (rev 27236)
@@ -183,7 +183,7 @@
                        this._nodesMap[ns.data.id] = ns;
                        // set the parent id of the added node
                        ns.data.parent = this.data.id;
-                       _nodesCount++;
+                       this._nodesCount++;
                }
                
                /**
@@ -199,7 +199,11 @@
                                delete ns.data.parent;
                                // remove the node from the list of child nodes 
                                delete this._nodesMap[ns.data.id];
-                               _nodesCount--;
+                               this._nodesCount--;
+                               
+                               if (this._nodesCount === 0) { // not a compound 
node anymore
+                                   this._nodesMap = null;
+                               }
                        }
                }
                

-- 
You received this message because you are subscribed to the Google Groups 
"cytoscape-cvs" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/cytoscape-cvs?hl=en.

Reply via email to