import gtk
import gobject

class CellRendererButton( gtk.CellRendererText ):
	__gproperties__ = { "callable": ( gobject.TYPE_PYOBJECT,
                                      "callable property",
                                      "callable property",
                                      gobject.PARAM_READWRITE ) }
	_button_width = 40
	_button_height = 30

	def __init__( self ):
		self.__gobject_init__()
		gtk.CellRendererText.__init__( self )
		self.set_property( "xalign", 0.5 )
		self.set_property( "mode", gtk.CELL_RENDERER_MODE_ACTIVATABLE )
		self.callable = None
		self.table = None
	# __init__()


	def do_set_property( self, pspec, value ):
		if pspec.name == "callable":
			if callable( value ):
				self.callable = value
			else:
				raise TypeError( "callable property must be callable!" )
		else:
			raise AttributeError( "Unknown property %s" % pspec.name )
	# do_set_property()


	def do_get_property( self, pspec ):
		if pspec.name == "callable":
			return self.callable
		else:
			raise AttributeError( "Unknown property %s" % pspec.name )
	# do_get_property()


	def do_get_size( self, wid, cell_area ):
		xpad = self.get_property( "xpad" )
		ypad = self.get_property( "ypad" )

		if not cell_area:
			x, y = 0, 0
			w = 2 * xpad + self._button_width
			h = 2 * ypad + self._button_height
		else:
			w = 2 * xpad + cell_area.width
			h = 2 * ypad + cell_area.height

			xalign = self.get_property( "xalign" )
			yalign = self.get_property( "yalign" )

			x = max( 0, xalign * ( cell_area.width - w ) )
			y = max( 0, yalign * ( cell_area.height - h ) )

		return ( x, y, w, h )
	# do_get_size()


	def do_render( self, window, wid, bg_area, cell_area, expose_area, flags ):
		if not window:
			return

		xpad = self.get_property( "xpad" )
		ypad = self.get_property( "ypad" )

		x, y, w, h = self.get_size( wid, cell_area )

#		if flags & gtk.CELL_RENDERER_SELECTED :
#			state = gtk.STATE_ACTIVE
#			shadow = gtk.SHADOW_OUT
		if flags & gtk.CELL_RENDERER_PRELIT :
			state = gtk.STATE_PRELIGHT
			shadow = gtk.SHADOW_ETCHED_OUT
		else :
			state = gtk.STATE_NORMAL
			shadow = gtk.SHADOW_OUT
		wid.get_style().paint_box( window, state, shadow, cell_area,
					                 wid, "button",
					                 cell_area.x + x + xpad,
					                 cell_area.y + y + ypad,
					                 w - 6, h - 6 )
		flags = flags & ~gtk.STATE_SELECTED
		gtk.CellRendererText.do_render( self, window, wid, bg_area,
					                      (cell_area[0], cell_area[1] + ypad, cell_area[2],cell_area[3]), expose_area, flags )
    # do_render()

	def do_activate( self, event, wid, path, bg_area, cell_area, flags ):
		cb = self.get_property( "callable" )
		if cb != None :
			cb (path)
		return True
# _CellRendererButton


gobject.type_register( CellRendererButton )


if __name__ == "__main__":

	class Tree(gtk.TreeView):
		def __init__(self):
			self.store = gtk.ListStore(gobject.TYPE_STRING,
							              gobject.TYPE_PYOBJECT)
			gtk.TreeView.__init__(self)
			self.set_size_request(300, 200)
			self.set_model(self.store)
			self.set_headers_visible(True)
			#self.get_selection().set_mode(gtk.SELECTION_NONE)

			rend = gtk.CellRendererText()
			column = gtk.TreeViewColumn('First', rend, text=0)
			self.append_column(column)

			rend = CellRendererButton()
			column = gtk.TreeViewColumn('Second', rend, text=0, callable=1)
			self.append_column(column)        

		def insert(self, name):
			iter = self.store.append()
			self.store.set(iter, 0, name, 1, self.callback)

		def callback(self, path) :
			print self,"callback()", path, self.store.get_value(self.store.get_iter(path), 0)

	w = gtk.Window()
	w.set_position(gtk.WIN_POS_CENTER)
	w.connect('delete-event', gtk.main_quit)
	t = Tree()
	t.insert('foo')
	t.insert('bar')
	t.insert('baz')
	w.add(t)

	w.show_all()
	gtk.main()


