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.