Start working on tree2graph
Start working on tree2graph
diff --git a/tree2graph.py b/tree2graph.py
new file mode 100644
index 0000000..2ffd146
--- /dev/null
+++ b/tree2graph.py
@@ -0,0 +1,122 @@
+import plistlib
+import sys
+
+"""
+FORMAT OF TREE INPUT:
+
+The tree is unserialized from a new-line separated text file. Each line
+corresponds to a node. The format of the line is as follows:
+<number of children>:<node value>\n
+
+The parser will look at <number of children> and will take that many lines
+following the current one as the child values for the nodes. This should be
+generated by a pre-order traversal of the tree. Pseudocode:
+
+ SerializeTree(TreeNode n) {
+ print n.children.Count()
+ print ':'
+ print n.value
+ print '\n'
+ foreach (TreeNode c in n.children) {
+ SerializeTree(c)
+ }
+ }
+
+The result, on stdout, will be an OmniGraffle 5 Plist document.
+"""
+
+class TreeNode(object):
+ """A tree node."""
+ def __init__(self, value):
+ super(TreeNode, self).__init__()
+ self.value = value
+ self.children = list()
+ self.num_children = 0
+ self.parent = None
+
+def _ParseNode(string):
+ """Parses a stringified node into a TreeNode object."""
+ last = len(string) - 1
+ if string[last] == '\n':
+ string = string[0:last]
+
+ pos = string.find(':')
+
+ node = TreeNode(string[pos+1:])
+ node.num_children = int(string[0:pos])
+ return node
+
+def _HelpReadTree(parent, nlist):
+ """Recursively joins children with their parents."""
+ if parent.num_children == 0:
+ return
+
+ for i in range(0, parent.num_children):
+ child = nlist.pop(0)
+ parent.children.append(child)
+ _HelpReadTree(child, nlist)
+
+def ReadTree(flat_nodes):
+ """Reads a list of flattened, serialized nodes and creates a tree with a
+ TreeNode root."""
+ nodes = map(_ParseNode, flat_nodes)
+ root = nodes[0]
+ _HelpReadTree(root, nodes[1:])
+ return root
+
+def _CreateGraffleNode(node, graphic_id):
+ """Creates a node for an OmniGraffle document."""
+ graf = dict()
+ graf['ID'] = graphic_id
+ graf['Class'] = "ShapedGraphic"
+ graf['Shape'] = "Circle"
+ graf['Text'] = {"Text": "{\rtf1\ansi " + node.value + "}"}
+ graf['Bounds'] = "{{0,0},{50,50}}"
+ return graf
+
+def _CreateGraffleLink(target, dest, graphic_id):
+ """Creates a OmniGraffle link between to graffle nodes (created via
+ _CreateGraffleLink())."""
+ graf = dict()
+ graf['ID'] = graphic_id
+ graf['Class'] = "LineGraphic"
+ graf['Head'] = {"ID": target['ID']}
+ graf['Tail'] = {"ID": dest['ID']}
+ graf['Style'] = {
+ "storke": {
+ 'HeadArrow' : "FilledArrow",
+ 'LineType' : 1,
+ 'TailArrow' : 0
+ }
+ }
+ return graf
+
+def CreateGraffle(root):
+ """Creates a dictionary, representing an OmniGraffle document."""
+ doc = dict()
+ doc['AutoAdjust'] = True
+ doc['BackgroundGraphic'] = {
+ "Class" : "SolidGraphic",
+ "ID" : 2
+ }
+ doc['CanvasOrigin'] = "{0,0}"
+ doc['GraphDocumentVersion'] = 6
+ doc['OutlineStyle'] = "Basic"
+ doc['PageBreaks'] = False
+ doc['LayoutInfo'] = {
+ 'Animate' : False,
+ 'AutoLayout' : 2,
+ 'LineLength' : 0.5,
+ 'circoMinDist' : 15,
+ 'circoSeparation' : 0,
+ 'layoutEngine' : "dot"
+ }
+ return doc
+
+def Main():
+ """Reads from stdin the serialized tree structure and assembles a tree."""
+ nodes = sys.stdin.readlines()
+ root = ReadTree(nodes)
+
+if __name__ == '__main__':
+ Main()