Below is the file 'scribbler.py' from this revision. You can also download the file.

#!/usr/bin/env python

import gobject
import cairo
import math
import gtk
import sys
import os

def ScribblerFactory(scribble_function):
	class Scribbler(gobject.GObjectMeta):
		def __new__(cls, name, bases, dict):
			def expose_handler(widget, event):
				context = widget.window.cairo_create()
				context.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
				context.clip()
				scribble_function(widget, context, widget.get_allocation())
				return False

			def our_init(self, *args, **kwargs):
				super(self.__class__, self).__init__(*args, **kwargs)
				self.connect_after("expose-event", expose_handler)

			dict['__init__']  = our_init
			return type.__new__(cls, name, bases, dict)
	return Scribbler

def draw_circle(widget, context, allocation):
	x = allocation.x + allocation.width / 2
	y = allocation.y + allocation.height / 2
	radius = min(allocation.width / 2, allocation.height / 2) - 5
	context.arc(x, y, radius, 0, 2 * math.pi)
	context.set_source_rgb(0, 0, 0)
	context.stroke()

def draw_flagamo(widget, context, allocation):
	context.set_source_rgb(1, 0, 0)
	context.set_line_width(5)
	context.rectangle(allocation.x + 5, allocation.y+ 5, allocation.width - 10, allocation.height - 10)
	context.move_to(allocation.x, allocation.y)
	context.line_to(allocation.x+allocation.width, allocation.y+allocation.height)
	context.move_to(allocation.x, allocation.y+allocation.height)
	context.line_to(allocation.x+allocation.width, allocation.y)
	context.stroke()

def draw_brand(widget, context, allocation):
	context.set_source_rgba(0.5, 0.5, 1, 0.5)
	context.select_font_face("Serif", cairo.FONT_SLANT_NORMAL, cairo.FONT_WEIGHT_BOLD)
	context.set_font_size(32)
	brand = '<branded by angry goats>'
	xb, yb, fw, fh = context.text_extents(brand)[:4]
	context.move_to(allocation.x + ((allocation.width - fw) / 2 - xb),
			allocation.y + ((allocation.height - fh) / 2 - yb))
	context.show_text(brand)

class BoxedTable(gtk.Table):
	__metaclass__ = ScribblerFactory(draw_flagamo)

class WindowCircle(gtk.Window):
	__metaclass__ = ScribblerFactory(draw_circle)

class ButtonCircle(gtk.Button):
	__metaclass__ = ScribblerFactory(draw_circle)

class LabelCircle(gtk.Label):
	__metaclass__ = ScribblerFactory(draw_circle)

class BrandedWindow(gtk.Window):
	__metaclass__ = ScribblerFactory(draw_brand)

if __name__ == '__main__':
	window = BrandedWindow()
	vbox = BoxedTable(2, 2)
	for i in xrange(4):
		vbox.attach(ButtonCircle("Button %d" % i), (i%2), (i%2)+1, (i/2), (i/2)+1)
	window.add(vbox)
	window.show_all()
	gtk.main()