Author: onursumer
Date: 2011-03-25 03:05:16 -0700 (Fri, 25 Mar 2011)
New Revision: 24595

Modified:
   cytoscapeweb/branches/compound/html-template/compound.html
   cytoscapeweb/branches/compound/html-template/js/compound.js
   cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/GraphProxy.as
   
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
   
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/GraphMLConverter.as
   cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/ExternalMediator.as
   cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/GraphMediator.as
   
cytoscapeweb/branches/compound/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
Log:
Compound support for GraphML format is added to CytoscapeWeb. In order to add 
this support, mainly the GraphMLConverter class is modified to read the data 
from a DataSet containing GraphicsDataTable instances (similar to 
XGMMLConverter), instead of DataTable instances. This is required for the 
GraphMLConverter because the parent-child relationship is stored in the 
CompoundNodeSprite class, therefore it is not possible to construct sub-graphs 
by using only the raw data.

Also, parentId information is moved (as a class variable) to the 
CompoundNodeSprite class. This information was previously stored in the data 
object of the NodeSprite. Since we instantiate all nodes as CompoundNodeSprite 
instances, there is no need to put this information into the data object 
anymore.

Modified: cytoscapeweb/branches/compound/html-template/compound.html
===================================================================
--- cytoscapeweb/branches/compound/html-template/compound.html  2011-03-25 
00:40:20 UTC (rev 24594)
+++ cytoscapeweb/branches/compound/html-template/compound.html  2011-03-25 
10:05:16 UTC (rev 24595)
@@ -8,17 +8,31 @@
         <script type="text/javascript" src="js/AC_OETags.js"></script>
         <script type="text/javascript" src="js/json2.js"></script>
         <script type="text/javascript" src="js/cytoscapeweb.js"></script>
+        <script type="text/javascript" src="js/cytoscapeweb-file.js"></script>
         <script type="text/javascript" src="js/compound.js"></script>
         
+        <link rel="stylesheet" href="css/demo.css" type="text/css"/>
         <style>
             /* The Cytoscape Web container must have its dimensions set. */
             html, body { padding: 0; margin: 0; text-align: center; }
             #cytoscapeweb { width: 800px; height: 600px; border: 2px solid 
#333333; margin: 0 auto 0 auto;  }
         </style>
+        
     </head>
     
     <body>
         <h1>Compound Testing</h1>
+        <div id="toolbar">
+               <input id="in-object-model" type="button" value="Sample 
ObjectModel"></input>
+               <input id="in-graphml" type="button" value="Sample 
GraphML"></input>
+               <input id="to-graphml" type="button" value="To GraphML"></input>
+               <input id="to-xgmml" type="button" value="To XGMML"></input>
+               <input id="to-pdf" type="button" value="To PDF"></input>
+               <input id="to-svg" type="button" value="To SVG"></input>
+               <input id="to-png" type="button" value="To PNG"></input>
+               <input id="to-sif" type="button" value="To SIF"></input>
+               
+        </div>
         <div id="cytoscapeweb">
             Cytoscape Web will replace the contents of this div with your 
graph.
         </div>

Modified: cytoscapeweb/branches/compound/html-template/js/compound.js
===================================================================
--- cytoscapeweb/branches/compound/html-template/js/compound.js 2011-03-25 
00:40:20 UTC (rev 24594)
+++ cytoscapeweb/branches/compound/html-template/js/compound.js 2011-03-25 
10:05:16 UTC (rev 24595)
@@ -12,29 +12,7 @@
     nodeTooltipsEnabled: true,
     edgesMerged: false,
     //mouseDownToDragDelay: -1,
-    network: {
-       dataSchema: {
-               nodes: [ { name: "label", type: "string" } ],       
-               edges: [ { name: "label", type: "string" },
-                        { name: "weight", type: "number" } ]
-       },
-       data: {
-               nodes: [ { id: "n1", label: "n1", network: {
-                                               nodes: [ { id: "n11", label: 
"n11"},
-                                                        { id: "n12", label: 
"n12"},
-                                                        { id: "n13", label: 
"n13", network: {
-                                                                nodes: [{id: 
"n131", label: "n131"}]
-                                                               }
-                                                        }],
-                                           edges: [ { id: "e12", label: "e12", 
weight: 1.2, source: "n11", target: "n12" } ]
-                                       }
-                               },
-                        { id: "n2", label: "n2"},
-                        { id: "n3", label: "n3", network: { } } ],
-               edges: [ { id: "e1", label: "e1", weight: 1.1, source: "n1", 
target: "n2" } ]
-       }
-    },
-    
+    network: { }, // initial empty network
     visualStyle: {
         global: {
             backgroundColor: "#fefefe",
@@ -94,16 +72,107 @@
 window.onload = function()
 {
        // id of Cytoscape Web container div
-       var div_id = "cytoscapeweb";
-
+       var cw_div_id = "cytoscapeweb"
+       
        // init and draw
-       vis = new org.cytoscapeweb.Visualization(div_id);   
+       vis = new org.cytoscapeweb.Visualization(cw_div_id);   
 
+       initToolbar();
        vis.ready(initContextMenu);
        
+       //createMenu();
        vis.draw(options);
 };
 
+/**
+ * Creates a sample graphML data containing both simple and compound nodes.
+ *
+ */
+function createGraphmlData()
+{
+       var data = '<graphml 
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns 
http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd"; 
xmlns="http://graphml.graphdrawing.org/xmlns"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";>' +
+                                       '<key id="label" for="node" 
attr.name="label" attr.type="string"/>' +
+                                       '<key id="label" for="edge" 
attr.name="label" attr.type="string"/>' + 
+                                       '<key id="weight" for="edge" 
attr.name="weight" attr.type="double"/>' + 
+                                       '<graph edgedefault="undirected">' +
+                                               '<node id="n2">' +
+                                                       '<data 
key="label">n2</data>' +
+                                               '</node>' +
+                                               '<node id="n1">' +
+                                                       '<data 
key="label">n1</data>' +
+                                                       '<graph>' +
+                                                               '<node 
id="n12">' +
+                                                                       '<data 
key="label">n12</data>' +
+                                                               '</node>' +
+                                                               '<node 
id="n11">' +
+                                                                       '<data 
key="label">n11</data>' +
+                                                               '</node>' +
+                                                               '<node 
id="n13">' +
+                                                                       '<data 
key="label">n13</data>' +
+                                                                       
'<graph>' +
+                                                                               
'<node id="n131">' +
+                                                                               
        '<data key="label">n131</data>' +
+                                                                               
'</node>' +
+                                                                       
'</graph>' +
+                                                               '</node>' +
+                                                               '<edge id="e12" 
target="n12" source="n11">' +
+                                                                       '<data 
key="label">e12</data>' +
+                                                                       '<data 
key="weight">1.2</data>' +
+                                                               '</edge>' +
+                                                       '</graph>' +
+                                               '</node>' +
+                                               '<node id="n3">' +
+                                                       '<data 
key="label">n3</data>' +
+                                                       '<graph/>' +
+                                               '</node>' + 
+                                               '<edge id="e1" target="n2" 
source="n1">' +
+                                                       '<data 
key="label">e1</data>' +
+                                                       '<data 
key="weight">1.1</data>' +
+                                               '</edge>' +
+                                               '<edge id="e2" target="n12" 
source="n2">' +
+                                                       '<data 
key="label">e2</data>' +
+                                                       '<data 
key="weight">1.6</data>' +                                                      
 
+                                               '</edge>' +
+                                       '</graph>' +
+                               '</graphml>';
+       
+       return data;
+}
+
+/**
+ * Creates a sample network object model data containing both simple and
+ * compound nodes.
+ *
+ */
+function createObjectData()
+{
+       var data = {
+               dataSchema: {
+                       nodes: [ { name: "label", type: "string" } ],       
+                       edges: [ { name: "label", type: "string" },
+                                { name: "weight", type: "number" } ]
+               },
+               data: {
+                       nodes: [ { id: "n1", label: "n1", network: {
+                                                       nodes: [ { id: "n11", 
label: "n11"},
+                                                                { id: "n12", 
label: "n12"},
+                                                                { id: "n13", 
label: "n13", network: {
+                                                                        nodes: 
[{id: "n131", label: "n131"}]
+                                                                       }
+                                                                }],
+                                                   edges: [ { id: "e12", 
label: "e12", weight: 1.2, source: "n11", target: "n12" } ]
+                                               }
+                                       },
+                                { id: "n2", label: "n2"},
+                                { id: "n3", label: "n3", network: { } } ],
+                       edges: [ { id: "e1", label: "e1", weight: 1.1, source: 
"n1", target: "n2" },
+                                { id: "e2", label: "e2", weight: 1.6, source: 
"n2", target: "n12" }]
+               }
+       };
+       
+       return data;
+}
+
 /*
  *
  */
@@ -176,27 +245,133 @@
                if (items.length > 0) { vis.removeElements(items, true); }
        });
        
-       vis.addContextMenuItem("Export png", function(evt) {
-               vis.exportNetwork('png', 'export.php?type=png');
+       /* TODO import from input file
+       vis.addContextMenuItem("Import", function(evt) {
+               createOpen();
        });
+       */
+}
+
+function initToolbar()
+{
+       $("#in-object-model").click(function(evt) {
+        var network = createObjectData();
+        options.network = network;
+        vis.draw(options);
+    });
        
-       vis.addContextMenuItem("Export pdf", function(evt) {
-               vis.exportNetwork('pdf', 'export.php?type=pdf');
-       });
+       $("#in-graphml").click(function(evt) {
+        var network = createGraphmlData();
+        options.network = network;
+        vis.draw(options);
+    });
        
-       vis.addContextMenuItem("Export svg", function(evt) {
-               vis.exportNetwork('svg', 'export.php?type=svg');
-       });
+       $("#to-graphml").click(function(evt) {
+               vis.exportNetwork('graphml', 'export.php?type=xml');
+    });
        
-       vis.addContextMenuItem("Export xgmml", function(evt) {
+       $("#to-xgmml").click(function(evt) {
                vis.exportNetwork('xgmml', 'export.php?type=xml');
-       });
-       
-       vis.addContextMenuItem("Export graphml", function(evt) {
-               vis.exportNetwork('graphml', 'export.php?type=xml');
-       });
-       
-       vis.addContextMenuItem("Export sif", function(evt) {
+    });
+
+       $("#to-pdf").click(function(evt) {
+               vis.exportNetwork('pdf', 'export.php?type=pdf');
+    });
+
+       $("#to-png").click(function(evt) {
+               vis.exportNetwork('png', 'export.php?type=png');
+    });
+
+       $("#to-svg").click(function(evt) {
+               vis.exportNetwork('svg', 'export.php?type=svg');
+    });
+
+       $("#to-sif").click(function(evt) {
                vis.exportNetwork('sif', 'export.php?type=xml');
-       });
+    });
 }
+
+// TODO read from input file... 
+
+function createOpen(){
+    var opts = {
+            swfPath: path("Importer"),
+            flashInstallerPath: path("playerProductInstall"),
+            data: function(data){
+                       var network = data.string;
+                               var new_graph_options = {
+                                       network: network,
+                                   name: data.metadata.name,
+                                   description: "",
+                                   visualStyle: options.visualStyle,
+                                   //visualStyle: GRAPH_STYLES["Default"],
+                                   nodeLabelsVisible: true
+                               };
+
+                               open_graph(new_graph_options);
+                       },
+                       
+            ready: function(){
+                $("#open_file").trigger("available");
+            },
+            
+            typeFilter: function(){
+                return "*.graphml;*.xgmml;*.xml;*.sif";
+            },
+            binary: function(metadata){
+               return false; // to return data.string and not data.bytes
+               // TODO: if CYS support, check metadata.name.indexOf(".cys")
+            }
+        };
+        
+    new org.cytoscapeweb.demo.Importer("file_importer", opts);
+}
+
+
+function createMenu(){
+    $("#menu").children().remove(); // remove old menu if needed (we don't 
want two after a redraw)
+    $("#menu").append(      '<ul>\
+                                <li id="save_file"><label>Save 
file</label></li>\
+                                <li id="open_file"><label>Open 
file</label><span id="file_importer"></span></li>\
+                                \
+                                <li><label>Style</label>\
+                                    <ul>\
+                                        <li id="merge_edges" 
class="ui-menu-checkable"><label>Merge edges</label></li>\
+                                        <li id="show_node_labels" 
class="ui-menu-checkable"><label>Show node labels</label></li>\
+                                        <li id="show_edge_labels" 
class="ui-menu-checkable"><label>Show edge labels</label></li>\
+                                        <li>\
+                                            <label>Visualisation</label>\
+                                            <ul id="visual_style" 
class="ui-menu-one-checkable">\
+                                            </ul>\
+                                        </li>\
+                                    </ul>\
+                                </li>\
+                                \
+                                <li><label>Layout</label>\
+                                    <ul>\
+                                        <li 
id="recalculate_layout"><label>Recalculate layout</label></li>\
+                                        <li>\
+                                            <label>Mechanism</label>\
+                                            <ul id="layout_style" 
class="ui-menu-one-checkable">\
+                                            </ul>\
+                                        </li>\
+                                        <li 
id="layout_settings"><label>Settings...</label></li>\
+                                    </ul>\
+                                </li>\
+                            </ul>\
+                            ');
+
+    $("#menu").menu({
+       menuItemMaxWidth: 180,
+    });
+    
+    /*                        
+    $("#save_file").click(function(){
+        show_save_menu();
+    });
+    */
+                            
+    // menu should not span
+    var last_top_lvl_item = $("#menu > ul > li:last");
+    $("#menu").css( "min-width", last_top_lvl_item.offset().left + 
last_top_lvl_item.outerWidth(true) );
+}

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/GraphProxy.as
===================================================================
--- cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/GraphProxy.as     
2011-03-25 00:40:20 UTC (rev 24594)
+++ cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/GraphProxy.as     
2011-03-25 10:05:16 UTC (rev 24595)
@@ -878,26 +878,53 @@
             }
         }
         
-        public function getDataAsText(format:String="xgmml", 
options:Object=null):String {
-            var out:IDataOutput, nodesTable:DataTable, edgesTable:DataTable, 
dtSet:DataSet;
-            format = StringUtil.trim(format.toLowerCase());
-                        
-            if (format === "xgmml") {
-                nodesTable = new GraphicsDataTable(graphData.nodes, 
nodesSchema);
-                edgesTable = new 
GraphicsDataTable(graphData.group(Groups.REGULAR_EDGES), edgesSchema);
+        public function getDataAsText(format:String="xgmml", 
options:Object=null):String
+               {
+            var out:IDataOutput,
+                               nodesTable:DataTable,
+                               edgesTable:DataTable,
+                               dtSet:DataSet;
+            
+                       format = StringUtil.trim(format.toLowerCase());
+
+            if (format === "xgmml" ||
+                               format === "graphml")
+                       {
+                               // GraphicsDataTable is needed for both graphML 
and XGMML
+                               // formats, since we also require the 
information contained
+                               // in the DataSprite instances in addition to 
the raw data.
+                               
+                nodesTable = new GraphicsDataTable(graphData.nodes,
+                                       nodesSchema);
+                               
+                edgesTable = new GraphicsDataTable(
+                                       graphData.group(Groups.REGULAR_EDGES), 
edgesSchema);
+                               
                 dtSet = new DataSet(nodesTable, edgesTable);
-                out = new XGMMLConverter(configProxy.visualStyle).write(dtSet);
-            } else {
-                nodesTable = new DataTable(graphData.nodes.toDataArray(), 
nodesSchema);
-                edgesTable = new 
DataTable(graphData.group(Groups.REGULAR_EDGES).toDataArray(), edgesSchema);
+                               
+                               if (format === "xgmml")
+                               {
+                       out = new XGMMLConverter(
+                                               
configProxy.visualStyle).write(dtSet);
+                               }
+                               else
+                               {
+                                       out = new 
GraphMLConverter().write(dtSet);
+                               }
+            }
+                       else // convert to SIF (TODO: is it possible to support 
compounds?)
+                       {
+                nodesTable = new DataTable(graphData.nodes.toDataArray(),
+                                       nodesSchema);
+                               
+                               edgesTable = new DataTable(
+                                       
graphData.group(Groups.REGULAR_EDGES).toDataArray(),
+                                               edgesSchema);
+                               
                 dtSet = new DataSet(nodesTable, edgesTable);
-
-                if (format === "graphml") {
-                    out = new GraphMLConverter().write(dtSet);
-                } else {
-                    var interaction:String =  options != null ? 
options.interactionAttr : null;
-                    out = new SIFConverter(interaction).write(dtSet);
-                }
+                
+                               var interaction:String =  options != null ? 
options.interactionAttr : null;
+                               out = new 
SIFConverter(interaction).write(dtSet);
             }
 
             return "" + out;

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
===================================================================
--- 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
     2011-03-25 00:40:20 UTC (rev 24594)
+++ 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/ExternalObjectConverter.as
     2011-03-25 10:05:16 UTC (rev 24595)
@@ -70,7 +70,6 @@
         public static const TARGET:String = "target";
         public static const DIRECTED:String = "directed";
         public static const NETWORK:String = "network";
-               public static const PARENT_ID:String = "parentId";
                
         private static const NODE_ATTR:Object = {
             id: 1
@@ -188,16 +187,16 @@
                        // id information set by the readData function.
                        for each (cns in nodes)
                        {
-                               if (cns.data.parentId != null)
+                               if (cns.parentId != null)
                                {
-                                       parent = (lookup[cns.data.parentId] as 
CompoundNodeSprite); 
+                                       parent = (lookup[cns.parentId] as 
CompoundNodeSprite); 
                                        
                                        // add the current compound node as a 
child
                                        parent.addNode(cns);
                                        
                                        // TODO:debug
                                        trace("Node " + cns.data.id +
-                                               " added to " + 
cns.data.parentId);
+                                               " added to " + cns.parentId);
                                }
                        }
                        
@@ -264,7 +263,7 @@
                                // update parent id of the current node
                                if (parentId != null)
                                {
-                                       obj[PARENT_ID] = parentId;
+                                       cns.parentId = parentId;
                                }
                                
                                // add the node to the array of compound nodes

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/GraphMLConverter.as
===================================================================
--- 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/GraphMLConverter.as
    2011-03-25 00:40:20 UTC (rev 24594)
+++ 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/model/converters/GraphMLConverter.as
    2011-03-25 10:05:16 UTC (rev 24595)
@@ -34,13 +34,19 @@
        import flare.data.DataTable;
        import flare.data.DataUtil;
        import flare.data.converters.IDataConverter;
+       import flare.vis.data.DataSprite;
+       import flare.vis.data.EdgeSprite;
+       import flare.vis.data.NodeSprite;
        
        import flash.utils.ByteArray;
        import flash.utils.IDataInput;
        import flash.utils.IDataOutput;
        
+       import org.cytoscapeweb.model.GraphProxy;
+       import org.cytoscapeweb.model.data.GraphicsDataTable;
        import org.cytoscapeweb.util.Utils;
        import org.cytoscapeweb.util.methods.$each;
+       import org.cytoscapeweb.vis.data.CompoundNodeSprite;
 
        /**
         * Converts data between GraphML markup and flare DataSet instances.
@@ -132,8 +138,43 @@
                        // graph.@[EDGEDEF] = ed==DIRECTED ? DIRECTED : 
UNDIRECTED;
                        graph.@[EDGEDEF] = ed ? DIRECTED : UNDIRECTED;
                        // ############################################
-                       addData(graph, ds.nodes.data, ds.nodes.schema, NODE, 
NODE_ATTR);
-                       addData(graph, ds.edges.data, ds.edges.schema, EDGE, 
EDGE_ATTR);
+                       //addData(graph, ds.nodes.data, ds.nodes.schema, NODE, 
NODE_ATTR);
+                       //addData(graph, ds.edges.data, ds.edges.schema, EDGE, 
EDGE_ATTR);
+                       
+                       // init xml lookup <id, xml> which is needed to 
construct compound
+                       // structure correctly
+                       var lookup:Object = new Object();
+                       
+                       var nodes:Array = new Array();
+                       var edges:Array = new Array();
+                       var sprite:Object;
+                       
+                       // populate nodes array with NodeSprite instances
+                       for each (sprite in (ds.nodes as 
GraphicsDataTable).dataSprites)
+                       {
+                               nodes.push(sprite);
+                       }
+                       
+                       // populate edges array with EdgeSprite instances
+                       for each (sprite in (ds.edges as 
GraphicsDataTable).dataSprites)
+                       {
+                               edges.push(sprite);
+                       }
+                       
+                       // add node data
+                       addData(graph,
+                               nodes,
+                               ds.nodes.schema,
+                               NODE, NODE_ATTR,
+                               lookup);
+                       
+                       // add edge data
+                       addData(graph,
+                               edges,
+                               ds.edges.schema,
+                               EDGE, EDGE_ATTR,
+                               lookup);
+                       
                        graphml = graphml.appendChild(graph);
                        
                        if (output == null) output = new ByteArray();
@@ -187,13 +228,76 @@
                 // ############################################
             }
             
+                       var childNodes:XMLList = graphml.graph.child("node");
+                                               
+                       for each (var child:XML in childNodes)
+                       {
+                               trace("node: " + child.@[ID]);
+                       }
+                       
             // parse nodes
             var nodeList:XMLList = graphml..node;
-            for each (var node:XML in nodeList) {
+                       var nodeSprites:Array = new Array();
+                       var cns:CompoundNodeSprite;
+                       var node:XML;
+                       
+                       // for each node in the node list create a 
CompoundNodeSprite
+                       // instance and add it to the nodeSprites array.
+            for each (node in nodeList)
+                       {
                 id = node.@[ID].toString();
-                lookup[id] = (n = parseData(node, nodeSchema));
-                nodes.push(n);
+                //lookup[id] = (n = parseData(node, nodeSchema));
+                               n = parseData(node, nodeSchema)
+                //nodes.push(n);
+                               cns = new CompoundNodeSprite();
+                               cns.data = n;
+                               lookup[id] = cns;
+                               nodeSprites.push(cns);
             }
+                       
+                       var graphList:XMLList = graphml..graph;
+                       var graph:XML;
+                       var compound:XML
+                       
+                       // for each subgraph in the XML, initialize the 
CompoundNodeSprite
+                       // owning that subgraph.
+                       
+                       for each (graph in graphList)
+                       {
+                               // if the parent is GRAPHML, then the node is 
in the root graph.
+                               if (graph.parent().name() !== GRAPHML)
+                               {
+                                       compound = graph.parent();
+                                       id = compound.@[ID].toString();
+                                       cns = lookup[id] as CompoundNodeSprite;
+                                       
+                                       if (cns != null)
+                                       {
+                                               cns.initialize();
+                                       }
+                               }
+                       }
+                       
+                       // add each node to its parent if it is not a node in 
the root
+                       
+                       for each (node in nodeList)
+                       {
+                               graph = node.parent();
+                       
+                               // if the parent is GRAPHML, then the node is 
in the root graph.
+                               if (graph.parent().name() !== GRAPHML)
+                               {
+                                       compound = graph.parent();
+                                       id = compound.@[ID].toString();
+                                       cns = lookup[id] as CompoundNodeSprite;
+                                       id = node.@[ID].toString();
+                                       
+                                       if (cns != null)
+                                       {
+                                               cns.addNode(lookup[id] as 
CompoundNodeSprite);
+                                       }
+                               }
+                       }
             
             // parse edges
             var edgeList:XMLList = graphml..edge;
@@ -212,7 +316,8 @@
             }
             
             return new DataSet(
-                new DataTable(nodes, nodeSchema),
+                //new DataTable(nodes, nodeSchema),
+                               new DataTable(nodeSprites, nodeSchema),
                 new DataTable(edges, edgeSchema)
             );
         }
@@ -279,6 +384,226 @@
                        return xml;
                }
                
+               /**
+                * Adds the data of the sprites in the given array to the 
specified
+                * XML object. The given sprite array is supposed to contain 
DataSprite
+                * instances. Also, adds the given schema information to the 
XML. 
+                * 
+                * @param xml           target XML object to add data
+                * @param sprites       array of DataSprite instances   
+                * @param schema        DataSchema for nodes or edges
+                * @param tag           tag of the data (node, edge, etc.)
+                * @param attrs         list of XML attributes
+                * @param lookup        lookup map for <id, sprite> pairs
+                * @param parentId      optional parent id for recursive calls
+                */
+               private static function addData(xml:XML,
+                       tuples:Array,
+                       schema:DataSchema,
+                       tag:String,
+                       attrs:Object,
+                       lookup:Object,
+                       parentId:String = null):void
+               {
+                       // xml used when creating subgraphs for compound nodes
+                       var childXml:XML = null;
+                       
+                       /**
+                        * Function (as a variable) to append a child xml 
representing the
+                        * given tuple data to the target XML. If target is 
null, then
+                        * the xml is appended to the root xml.
+                        */
+                       var appendChild:Function = function(i:uint, 
+                                                                         
tuple:Object,
+                                                                         
target:XML = null):void
+                       {
+                               var x:XML = new XML("<"+tag+"/>");
+                               
+                               for (var name:String in tuple)
+                               {
+                                       var value:* = tuple[name];
+                                       var field:DataField = 
schema.getFieldByName(name);
+                                       if (field != null && value == 
field.defaultValue) continue;
+                                       
+                                       var dataType:int = field != null ? 
field.type : Utils.dataType(value);
+                                       var type:String = 
fromCW_Type(dataType); // GraphML type
+                                       
+                                       if (attrs.hasOwnProperty(name)) {
+                                               // add as attribute
+                                               x.@[name] = toString(value, 
dataType);
+                                       } else {
+                                               // add as data child tag
+                                               var data:XML = new XML(<data/>);
+                                               data.@[KEY] = name;
+                                               
data.appendChild(toString(value, dataType));
+                                               x.appendChild(data);
+                                       }
+                               }
+                               
+                               if (target == null)
+                               {
+                                       // append to the root xml
+                                       xml.appendChild(x);
+                               }
+                               else
+                               {
+                                       // append to the given xml
+                                       target.appendChild(x);
+                               }
+                               
+                               // update child xml
+                               childXml = x;
+                       };
+                       
+                       // array of compound nodes
+                       var compoundNodes:Array = new Array();
+                       
+                       // array of data (for both edges and simple nodes)
+                       var plainData:Array = new Array();
+                       
+                       // separate compound nodes and simple nodes if tuples 
are nodes.
+                       // separate intra-graph edges and inter-graph edges if 
tuples are
+                       // edges.
+                       
+                       for each (var ds:DataSprite in tuples)
+                       {
+                               if (ds is CompoundNodeSprite)
+                               {
+                                       // check if compound node is initialized
+                                       if ((ds as 
CompoundNodeSprite).isInitialized())
+                                       {
+                                               // if no parent id is provided, 
then we are iterating
+                                               // the root graph. Include only 
'parentless' compounds  
+                                               if (parentId == null)
+                                               {
+                                                       if((ds as 
CompoundNodeSprite).parentId == null)
+                                                       {
+                                                               
compoundNodes.push(ds);
+                                                       }
+                                               }
+                                               // if parent id is provided, it 
is safe to include all
+                                               // initialized compound nodes.
+                                               else
+                                               {
+                                                       compoundNodes.push(ds);
+                                               }
+                                       }
+                                       else
+                                       {
+                                               // If no parent id is provided 
include only parentless
+                                               // nodes' data.
+                                               if (parentId == null)
+                                               {
+                                                       if((ds as 
CompoundNodeSprite).parentId == null)
+                                                       {
+                                                               
plainData.push(ds.data);
+                                                       }
+                                               }
+                                               // if parent id is provided, it 
is safe to include data
+                                               else
+                                               {
+                                                       plainData.push(ds.data);
+                                               }
+                                       }
+                               }
+                               else if (ds is NodeSprite)
+                               {
+                                       // include only parentless nodes' data
+                                       if (parentId == null)
+                                       {
+                                               if (ds.data.parentId == null)
+                                               {
+                                                       plainData.push(ds.data);
+                                               }
+                                       }
+                                       // safe to include node data
+                                       else
+                                       {
+                                               plainData.push(ds.data);
+                                       }
+                               }
+                               else if (ds is EdgeSprite)
+                               {
+                                       var es:EdgeSprite =  ds as EdgeSprite;
+                                       var target:XML = null;
+                                       var sParentId:String;
+                                       var tParentId:String;
+                                       
+                                       if (es.source is CompoundNodeSprite
+                                               && es.target is 
CompoundNodeSprite)
+                                       {
+                                               sParentId = (es.source as 
CompoundNodeSprite).parentId;
+                                               tParentId = (es.target as 
CompoundNodeSprite).parentId;
+                                               
+                                               // if both source and target 
parents are in the same
+                                               // subgraph (i.e. in the same 
compound), then the edge
+                                               // information will be written 
to the corresponding
+                                               // subgraph.
+                                               if (sParentId != null &&
+                                                       tParentId != null &&
+                                                       sParentId == tParentId)
+                                               {
+                                                       // try to get the XML 
corresponding to the parent
+                                                       target = 
lookup[sParentId] as XML;
+                                               }
+                                       }
+                                       
+                                       // check if the target parent compound 
is valid
+                                       if (target != null)
+                                       {
+                                               appendChild(0, es.data, target);
+                                       }
+                                       else
+                                       {
+                                               // add the edge data to the 
array of data to be added
+                                               // to the root graph
+                                               plainData.push(es.data);
+                                       }
+                               }
+                       }
+                       
+                       // write simple node information to the xml
+                       $each(plainData, appendChild);
+                       
+                       var subgraph:XML;
+                       
+                       // for each compound node sprite, recursively write 
child node
+                       // information into a new subgraph
+                       
+                       for each (var cns:CompoundNodeSprite in compoundNodes)
+                       {
+                               // sub graph for child nodes & edges
+                               subgraph = new XML(<graph/>);
+                               
+                               // set edge definition (directed or undirected) 
of the subgraph 
+                               subgraph.@[EDGEDEF] = xml.@[EDGEDEF].toString();
+                               
+                               // construct a map for <id, graph> pairs in 
order to
+                               // use while writing edges                      
        
+                               lookup[cns.data.id] = subgraph;
+                               
+                               // add compound node data to the current graph 
+                               appendChild(0, cns.data);
+                               
+                               // recursively add child node data
+                               addData(subgraph,
+                                       cns.getNodes(),
+                                       schema,
+                                       tag,
+                                       attrs,
+                                       lookup,
+                                       cns.data.id);
+                               
+                               // add subgraph information to the current graph
+                               childXml.appendChild(subgraph);
+                       }
+               }
+               
+               /**
+                * Previous addData function which is not suitable for compound 
node
+                * structure.  
+                */
+               /*
                private static function addData(xml:XML, tuples:Array, 
schema:DataSchema, tag:String, attrs:Object):void {
                        $each(tuples, function(i:uint, tuple:Object):void {
                                var x:XML = new XML("<"+tag+"/>");
@@ -306,6 +631,7 @@
                                xml.appendChild(x);
                        });
                }
+               */
                
                // -- static helpers 
--------------------------------------------------
                

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/ExternalMediator.as
===================================================================
--- 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/ExternalMediator.as    
    2011-03-25 00:40:20 UTC (rev 24594)
+++ 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/ExternalMediator.as    
    2011-03-25 10:05:16 UTC (rev 24595)
@@ -445,6 +445,7 @@
                        var childMap:Object = new Object();
                        var childList:Array;
                        var node:NodeSprite;
+                       var parentId:String;
                        
                        if (items != null)
                        {
@@ -504,14 +505,30 @@
                                                        }
                                                }
                                                
+                                               if (ns is CompoundNodeSprite
+                                                       && (ns as 
CompoundNodeSprite).parentId != null)
+                                               {
+                                                       parentId = (ns as 
CompoundNodeSprite).parentId;
+                                               }
+                                               else if (ns.data.parentId != 
null)
+                                               {
+                                                       // TODO we always use 
CompoundNodeSprites, so
+                                                       // this condition will 
never be true
+                                                       parentId = 
ns.data.parentId;
+                                               }
+                                               else
+                                               {
+                                                       parentId = null;
+                                               }
+                                               
                                                // remove ns from its parent 
compound's children list 
                                                // if it is in a compound
-                                               
-                                               if (ns.data.parentId != null)
+                                                                               
        
+                                               if (parentId != null)
                                                {
                                                        // get the parent node
-                                                       cNodeSprite = 
this.graphProxy.getNode(
-                                                               
ns.data.parentId) as CompoundNodeSprite;
+                                                       cNodeSprite = 
this.graphProxy.getNode(parentId)
+                                                               as 
CompoundNodeSprite;
                                                        
                                                        // remove current node 
from the compound node
                                                        if (cNodeSprite != null)

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/GraphMediator.as
===================================================================
--- cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/GraphMediator.as   
2011-03-25 00:40:20 UTC (rev 24594)
+++ cytoscapeweb/branches/compound/src/org/cytoscapeweb/view/GraphMediator.as   
2011-03-25 10:05:16 UTC (rev 24595)
@@ -415,7 +415,7 @@
                                                
                                                // advance to the next parent 
node
                                                targetNode = 
this.graphProxy.getNode(
-                                                       
targetNode.data.parentId);
+                                                       (targetNode as 
CompoundNodeSprite).parentId);
                                        }
                                }
                        }
@@ -809,6 +809,9 @@
                                        n.props.label.y += amountY;
                                }
                                
+                               
+                               var parentId:String;
+                               
                                // update parent compound node(s) bounds if 
necessary
                                // if n is target node, then its parents may 
need to be updated.
                                // if n is a selected node, then other selected 
nodes' parents
@@ -820,11 +823,22 @@
                                if (n == target ||
                                        n.props.$selected)
                                {
-                                       ns = n
+                                       ns = n;
                                        
-                                       while (ns.data.parentId != null)
+                                       if (ns is CompoundNodeSprite)
+                                       {
+                                               parentId = (ns as 
CompoundNodeSprite).parentId; 
+                                       }
+                                       else
+                                       {
+                                               // TODO we always use 
CompoundNodeSprite instances,
+                                               // so this condition will never 
be true
+                                               parentId = ns.data.parentId
+                                       }
+                                       
+                                       while (parentId != null)
                                        {       
-                                               ns = 
this.graphProxy.getNode(ns.data.parentId);
+                                               ns = 
this.graphProxy.getNode(parentId);
                                                
                                                if ((ns != null) &&
                                                        (ns is 
CompoundNodeSprite))
@@ -841,10 +855,13 @@
                                                                // render the 
compound node with the new bounds
                                                                ns.render();
                                                        }
+                                                       
+                                                       parentId = (ns as 
CompoundNodeSprite).parentId;
                                                }
                                                else
                                                {
-                                                       break;
+                                                       // reached top, no more 
parent
+                                                       parentId = null;
                                                }
                                        }
                                }

Modified: 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
===================================================================
--- 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
  2011-03-25 00:40:20 UTC (rev 24594)
+++ 
cytoscapeweb/branches/compound/src/org/cytoscapeweb/vis/data/CompoundNodeSprite.as
  2011-03-25 10:05:16 UTC (rev 24595)
@@ -24,6 +24,7 @@
                 */
                private var _nodesMap:Object;
                
+               private var _parentId:String;
                private var _bounds:Rectangle;
                private var _leftMargin:Number;
                private var _rightMargin:Number;
@@ -92,7 +93,18 @@
                        _leftMargin = value;
                }
 
+               /**
+                * ID of the parent node containing this node sprite
+                */
+               public function get parentId():String
+               {
+                       return _parentId;
+               }
                
+               public function set parentId(value:String):void
+               {
+                       _parentId = value;
+               }
                
                
                
@@ -102,6 +114,7 @@
                {
                        this._nodesMap = null;
                        this._bounds = null;
+                       this._parentId = null;
                }
                
                // ====================== [ PUBLIC FUNCTIONS ] 
=========================
@@ -140,13 +153,26 @@
                 */
                public function addNode(ns:NodeSprite) : void
                {
+                       // check if the node is initialized
                        if (this._nodesMap != null)
                        {
                                // add the node to the child node list of this 
node
                                this._nodesMap[ns.data.id] = ns;
                        
                                // set the parent id of the added node
-                               ns.data.parentId = this.data.id;
+                               
+                               if (ns is CompoundNodeSprite)
+                               {
+                                       // if a CompoundNodeSprite instance is 
added set the 
+                                       // corresponding field for parent id.
+                                       (ns as CompoundNodeSprite).parentId = 
this.data.id; 
+                               }
+                               else
+                               {
+                                       // TODO what to do if a NodeSprite is 
added? 
+                                       ns.data.parentId = this.data.id;
+                               }
+                               
                        }
                }
                
@@ -158,13 +184,31 @@
                 */ 
                public function removeNode(ns:NodeSprite) : void
                {
+                       var parentId:String;
+                       
+                       if (ns is CompoundNodeSprite)
+                       {
+                               parentId = (ns as CompoundNodeSprite).parentId;
+                       }
+                       else
+                       {
+                               parentId = ns.data.id;
+                       }
+                       
                        // check if given node is a child of this compound
                        if (this._nodesMap != null &&
-                               ns.data.parentId == this.data.id)
+                               parentId == this.data.id)
                        {
                                // reset the parent id of the removed node
-                               ns.data.parentId = null;
-                       
+                               if (ns is CompoundNodeSprite)
+                               {
+                                       (ns as CompoundNodeSprite).parentId = 
null;
+                               }
+                               else
+                               {
+                                       ns.data.parentId = null;
+                               }
+                               
                                // remove the node from the list of child nodes 
                                delete this._nodesMap[ns.data.id];
                        }
@@ -204,10 +248,6 @@
                        // the new bounds
                        this.x = bounds.x + (bounds.width / 2);
                        this.y = bounds.y + (bounds.height / 2);
-                       
-                       trace("[ub] bounds: " + bounds);
-                       trace("[ub] this._bounds: " + _bounds);
-                       
                }
                
                public function resetBounds() : void

-- 
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