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

#!/usr/bin/env python

import gobject
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(self, 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(context, self.get_allocation())
				return False

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

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

def draw_circle(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()

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

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

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

if __name__ == '__main__':
	window = WindowCircle()
	vbox = gtk.VBox()
	vbox.add(ButtonCircle("This is a Button."))
	vbox.add(LabelCircle("This is a label."))
	window.add(vbox)
	window.show_all()
	gtk.main()