From 23b9a9174006e341a507539b7da897816f4d739e Mon Sep 17 00:00:00 2001
From: jos
Date: Thu, 21 May 2015 16:05:52 +0200
Subject: [PATCH] Implemented attribute mapping for DOT language attributes
---
.../dotLanguage/data/cellular_automata.gv.txt | 2 +-
.../dotLanguage/data/computer_network.gv.txt | 4 +-
.../data/dotLanguage/dotPlayground.html | 12 ++-
lib/network/dotparser.js | 76 ++++++++++++++++++-
4 files changed, 87 insertions(+), 7 deletions(-)
diff --git a/examples/network/categories/data/dotLanguage/data/cellular_automata.gv.txt b/examples/network/categories/data/dotLanguage/data/cellular_automata.gv.txt
index 495d7db7..5e48093f 100644
--- a/examples/network/categories/data/dotLanguage/data/cellular_automata.gv.txt
+++ b/examples/network/categories/data/dotLanguage/data/cellular_automata.gv.txt
@@ -3,7 +3,7 @@ digraph G {
// unrecognized attributes are ignored
node[width=.25,height=.375,fontsize=15]
- node [shape=filled fillcolor=#F1AAF0]
+ node [shape=filled color=#FF00FF fillcolor=#F1AAF0]
0-> 0 ;
1-> 1 ;
2-> 2 ;
diff --git a/examples/network/categories/data/dotLanguage/data/computer_network.gv.txt b/examples/network/categories/data/dotLanguage/data/computer_network.gv.txt
index 03f631a2..cd49095c 100644
--- a/examples/network/categories/data/dotLanguage/data/computer_network.gv.txt
+++ b/examples/network/categories/data/dotLanguage/data/computer_network.gv.txt
@@ -1,7 +1,7 @@
digraph topology
{
- node[shape=circle fontSize=12]
- edge[length=170 fontSize=12]
+ node[shape=circle fontsize=12]
+ edge[length=170 fontsize=12]
"10.0.255.1" -> "10.0.255.3"[label="1.000"];
"10.0.255.1" -> "10.0.255.2"[label="1.000"];
"10.0.255.1" -> "10.0.255.2"[label="1.000"];
diff --git a/examples/network/categories/data/dotLanguage/dotPlayground.html b/examples/network/categories/data/dotLanguage/dotPlayground.html
index a4c002dc..f9b08652 100644
--- a/examples/network/categories/data/dotLanguage/dotPlayground.html
+++ b/examples/network/categories/data/dotLanguage/dotPlayground.html
@@ -10,6 +10,7 @@
@@ -101,11 +111,9 @@
The examples marked with a star (*) come straight from the GraphViz gallery.
-
-
diff --git a/lib/network/dotparser.js b/lib/network/dotparser.js
index 647ff63b..2e4c461a 100644
--- a/lib/network/dotparser.js
+++ b/lib/network/dotparser.js
@@ -16,6 +16,18 @@ function parseDOT (data) {
return parseGraph();
}
+// mapping of attributes from DOT (the keys) to vis.js (the values)
+var ATTR_MAPPING = {
+ 'fontsize': 'font.size',
+ 'fontcolor': 'font.color',
+ 'labelfontcolor': 'font.color',
+ 'fontname': 'font.face',
+ 'color': ['color.border', 'color.background'],
+ 'fillcolor': 'color.background',
+ 'tooltip': 'title',
+ 'labeltooltip': 'title'
+};
+
// token types enumeration
var TOKENTYPE = {
NULL : 0,
@@ -726,6 +738,63 @@ function forEach2(array1, array2, fn) {
}
}
+/**
+ * Set a nested property on an object
+ * When nested objects are missing, they will be created.
+ * For example setProp({}, 'font.color', 'red') will return {font: {color: 'red'}}
+ * @param {Object} object
+ * @param {string} path A dot separated string like 'font.color'
+ * @param {*} value Value for the property
+ * @return {Object} Returns the original object, allows for chaining.
+ */
+function setProp(object, path, value) {
+ var names = path.split('.');
+ var prop = names.pop();
+
+ // traverse over the nested objects
+ var obj = object;
+ for (var i = 0; i < names.length; i++) {
+ var name = names[i];
+ if (!(name in obj)) {
+ obj[name] = {};
+ }
+ obj = obj[name];
+ }
+
+ // set the property value
+ obj[prop] = value;
+
+ return object;
+}
+
+/**
+ * Convert an object with DOT attributes to their vis.js equivalents.
+ * @param {Object} attr Object with DOT attributes
+ * @return {Object} Returns an object with vis.js attributes
+ */
+function convertAttr (attr) {
+ var converted = {};
+
+ for (var prop in attr) {
+ if (attr.hasOwnProperty(prop)) {
+ var mapping = ATTR_MAPPING[prop];
+ if (Array.isArray(mapping)) {
+ mapping.forEach(function (mapping_i) {
+ setProp(converted, mapping_i, attr[prop]);
+ })
+ }
+ else if (typeof mapping === 'string') {
+ setProp(converted, mapping, attr[prop]);
+ }
+ else {
+ setProp(converted, prop, attr[prop]);
+ }
+ }
+ }
+
+ return converted;
+}
+
/**
* Convert a string containing a graph in DOT language into a map containing
* with nodes and edges in the format of graph.
@@ -748,7 +817,7 @@ function DOTToGraph (data) {
id: dotNode.id,
label: String(dotNode.label || dotNode.id)
};
- merge(graphNode, dotNode.attr);
+ merge(graphNode, convertAttr(dotNode.attr));
if (graphNode.image) {
graphNode.shape = 'image';
}
@@ -768,7 +837,7 @@ function DOTToGraph (data) {
from: dotEdge.from,
to: dotEdge.to
};
- merge(graphEdge, dotEdge.attr);
+ merge(graphEdge, convertAttr(dotEdge.attr));
graphEdge.arrows = (dotEdge.type === '->') ? 'to' : undefined;
return graphEdge;
@@ -785,6 +854,9 @@ function DOTToGraph (data) {
}
}
+ // TODO: support of solid/dotted/dashed edges (attr = 'style')
+ // TODO: support for attributes 'dir' and 'arrowhead' (edge arrows)
+
if (dotEdge.to instanceof Object) {
to = dotEdge.to.nodes;
}