1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
import pygtk
pygtk.require('2.0')
import gobject
import pango
import gtk
from gtk import gdk
try:
import cairo
except ImportError:
pass
if gtk.pygtk_version < (2,3,93):
print "PyGtk 2.3.93 or later required for this example"
raise SystemExit
TEXT = 'A GtkWidget implemented in PyGTK'
BORDER_WIDTH = 10
class PyGtkWidget(gtk.Widget):
__gsignals__ = { 'realize': 'override',
'expose-event' : 'override',
'size-allocate': 'override',
'size-request': 'override',
}
def __init__(self):
gtk.Widget.__init__(self)
self.draw_gc = None
self.layout = self.create_pango_layout(TEXT)
self.layout.set_font_description(pango.FontDescription("sans serif 16"))
def do_realize(self):
self.set_flags(self.flags() | gtk.REALIZED)
self.window = gdk.Window(self.get_parent_window(),
width=self.allocation.width,
height=self.allocation.height,
window_type=gdk.WINDOW_CHILD,
wclass=gdk.INPUT_OUTPUT,
event_mask=self.get_events() | gdk.EXPOSURE_MASK)
if not hasattr(self.window, "cairo_create"):
self.draw_gc = gdk.GC(self.window,
line_width=5,
line_style=gdk.SOLID,
join_style=gdk.JOIN_ROUND)
self.window.set_user_data(self)
self.style.attach(self.window)
self.style.set_background(self.window, gtk.STATE_NORMAL)
self.window.move_resize(*self.allocation)
def do_unrealize(self):
self.window.set_user_data(None)
def do_size_request(self, requisition):
width, height = self.layout.get_size()
requisition.width = width // pango.SCALE + BORDER_WIDTH*4
requisition.height = height // pango.SCALE + BORDER_WIDTH*4
def do_size_allocate(self, allocation):
self.allocation = allocation
if self.flags() & gtk.REALIZED:
self.window.move_resize(*allocation)
def _expose_gdk(self, event):
x, y, w, h = self.allocation
self.window.draw_rectangle(self.draw_gc, False,
BORDER_WIDTH, BORDER_WIDTH,
w - BORDER_WIDTH * 2, h - BORDER_WIDTH * 2)
fontw, fonth = self.layout.get_pixel_size()
self.style.paint_layout(self.window, self.state, False,
event.area, self, "label",
(w - fontw) / 2, (h - fonth) / 2,
self.layout)
def _expose_cairo(self, event, cr):
x, y, w, h = self.allocation
cr.set_source_color(self.style.fg[self.state])
cr.rectangle(BORDER_WIDTH, BORDER_WIDTH,
w - 2*BORDER_WIDTH, h - 2*BORDER_WIDTH)
cr.set_line_width(5.0)
cr.set_line_join(cairo.LINE_JOIN_ROUND)
cr.stroke()
fontw, fonth = self.layout.get_pixel_size()
cr.move_to((w - fontw)/2, (h - fonth)/2)
cr.update_layout(self.layout)
cr.show_layout(self.layout)
def do_expose_event(self, event):
self.chain(event)
try:
cr = self.window.cairo_create()
except AttributeError:
return self._expose_gdk(event)
return self._expose_cairo(event, cr)
win = gtk.Window()
win.set_title(TEXT)
win.connect('delete-event', gtk.main_quit)
frame = gtk.Frame("Example frame")
win.add(frame)
w = PyGtkWidget()
frame.add(w)
win.show_all()
gtk.main()
|