Skip to content

Instantly share code, notes, and snippets.

@scottferg
Created October 21, 2009 21:28
Show Gist options
  • Save scottferg/215471 to your computer and use it in GitHub Desktop.
Save scottferg/215471 to your computer and use it in GitHub Desktop.
import pygtk
pygtk.require("2.0")
import gtk
import gtk.glade
import gobject
import cairo
import math
# Create a GTK+ widget on which we will draw using Cairo
class Graph(gtk.DrawingArea):
# Draw in response to an expose-event
__gsignals__ = {'expose-event': 'override'}
# Handle the expose-event by drawing
def do_expose_event(self, event):
# Create the cairo context
context = self.window.cairo_create()
# Restrict Cairo to the exposed area; avoid extra work
context.rectangle(event.area.x,
event.area.y,
event.area.width,
event.area.height)
context.clip()
self.draw(context, *self.window.get_size())
def draw(self, context, width, height):
# Fill the background with gray
context.set_source_rgb(255, 255, 255)
context.rectangle(0, 0, width, height)
context.fill()
axisColor = []
axisColor.append([0.47, 0.1, 0.65])
axisColor.append([0.4, 0.4, 0])
axisColor.append([0.65, 0.43, 0.1])
axisColor.append([0.18, 0.05, 0.97])
self.setAxisColor = lambda count: context.set_source_rgb(axisColor[count][0], axisColor[count][1], axisColor[count][2])
self.drawnNodes = {}
for node,children in self.commitList.items():
self._drawGraph(node, 15, height / 2, context)
def _drawGraph(self, node, offset, height, context, parentNode = None):
# Iterate over each node in the list
# If the node has children, recursively pull the child from the
# overall list, and then draw it's children, and continue to traverse
# the path.
#
# Log each node and it's coordinates as it is drawn, so that it can be
# connected later if necessary
try:
self.drawnNodes[node]
# Node has already been drawn
return
except KeyError:
pass
# Draw commits in black
radius = min(5, 5)
context.set_source_rgb(0, 0, 0)
context.arc(offset + 5, height / 2, radius, 0, 2 * math.pi)
# Grab the current position
self.drawnNodes[node] = (x, y) = context.get_current_point()
context.stroke()
# If we have a parent, connect to it with a line
if parentNode:
origin = self.drawnNodes[node]
destination = self.drawnNodes[parentNode]
print 'Current: %s and Y: %s' % (node, origin[1])
print 'Parent: %s and Y: %s' % (parentNode, destination[1])
self.setAxisColor(1)
# If both nodes are at the same height draw a line
if origin[1] == destination[1]:
context.move_to(origin[0] - 10, origin[1])
context.line_to(destination[0], destination[1])
else:
context.curve_to(origin[0] - 7, origin[1] + 5,
origin[0] - 15, origin[1],
destination[0], destination[1])
context.stroke()
# Draw the children
for child in self.commitList[node]:
self._drawGraph(child, offset + 20, height, context, node)
height = height - 50
return
def __init__(self, commitList):
super(gtk.DrawingArea, self).__init__()
self.commitList = commitList
def drawCairoGraph(commitList):
window= gtk.Window()
window.connect('delete-event', lambda w, q: gtk.main_quit())
widget = Graph(commitList)
widget.show()
window.set_default_size(350, 350)
window.add(widget)
window.present()
gtk.main()
def buildCommitList():
graph = {'A': ['B'],
'B': ['C'],
'C': ['D', 'E'],
'D': ['F'],
'E': ['F', 'K'],
'F': ['G'],
'G': ['H', 'I'],
'H': ['J'],
'I': ['J'],
'J': [],
'K': []
}
return graph
if __name__ == '__main__':
drawCairoGraph(buildCommitList())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment