You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

91 lines
3.3 KiB

  1. import sys
  2. class Renderer(object):
  3. def __init__(self, getleft, getright,
  4. getred, getstart, getend, nil):
  5. self.getleft = getleft
  6. self.getright = getright
  7. self.getred = getred
  8. self.getstart = getstart
  9. self.getend = getend
  10. self.nil = nil
  11. # Rendering
  12. def __render_dot_node(self, node, max_depth = 20):
  13. from nilmdb.utils.printf import sprintf
  14. """Render a single node and its children into a dot graph fragment"""
  15. if max_depth == 0:
  16. return ""
  17. if node is self.nil:
  18. return ""
  19. def c(red):
  20. if red:
  21. return 'color="#ff0000", style=filled, fillcolor="#ffc0c0"'
  22. else:
  23. return 'color="#000000", style=filled, fillcolor="#c0c0c0"'
  24. s = sprintf("%d [label=\"%g\\n%g\", %s];\n",
  25. id(node),
  26. self.getstart(node), self.getend(node),
  27. c(self.getred(node)))
  28. if self.getleft(node) is self.nil:
  29. s += sprintf("L%d [label=\"-\", %s];\n", id(node), c(False))
  30. s += sprintf("%d -> L%d [label=L];\n", id(node), id(node))
  31. else:
  32. s += sprintf("%d -> %d [label=L];\n",
  33. id(node),id(self.getleft(node)))
  34. if self.getright(node) is self.nil:
  35. s += sprintf("R%d [label=\"-\", %s];\n", id(node), c(False))
  36. s += sprintf("%d -> R%d [label=R];\n", id(node), id(node))
  37. else:
  38. s += sprintf("%d -> %d [label=R];\n",
  39. id(node), id(self.getright(node)))
  40. s += self.__render_dot_node(self.getleft(node), max_depth-1)
  41. s += self.__render_dot_node(self.getright(node), max_depth-1)
  42. return s
  43. def render_dot(self, rootnode, title = "Tree"):
  44. """Render the entire tree as a dot graph"""
  45. return ("digraph rbtree {\n"
  46. + self.__render_dot_node(rootnode)
  47. + "}\n");
  48. def render_dot_live(self, rootnode, title = "Tree"):
  49. """Render the entiretree as a dot graph, live GTK view"""
  50. import gtk
  51. import gtk.gdk
  52. sys.path.append("/usr/share/xdot")
  53. import xdot
  54. xdot.Pen.highlighted = lambda pen: pen
  55. s = ("digraph rbtree {\n"
  56. + self.__render_dot_node(rootnode)
  57. + "}\n");
  58. window = xdot.DotWindow()
  59. window.set_dotcode(s)
  60. window.set_title(title + " - any key to close")
  61. window.connect('destroy', gtk.main_quit)
  62. def quit(widget, event):
  63. if not event.is_modifier:
  64. window.destroy()
  65. gtk.main_quit()
  66. window.widget.connect('key-press-event', quit)
  67. gtk.main()
  68. class RBTreeRenderer(Renderer):
  69. def __init__(self, tree):
  70. Renderer.__init__(self,
  71. lambda node: node.left,
  72. lambda node: node.right,
  73. lambda node: node.red,
  74. lambda node: node.start,
  75. lambda node: node.end,
  76. tree.nil)
  77. self.tree = tree
  78. def render(self, title = "RBTree", live = True):
  79. if live:
  80. return Renderer.render_dot_live(self, self.tree.getroot(), title)
  81. else:
  82. return Renderer.render_dot(self, self.tree.getroot(), title)