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
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
"""
RoundedWidgets.py
April 22, 2011
Custom widgets that have rounded edges
"""
import logging
import math
from gi.repository import Gdk, GdkPixbuf, GObject, Gtk
from Theme import Color
logger = logging.getLogger("RoundedWidgets")
# Angles in pi/2 increments
A0 = 0
A1 = math.pi / 2.0
A2 = math.pi
A3 = 3.0 * math.pi / 2.0
A4 = 2.0 * math.pi
def draw_rounded_box(cr, x, y, width, height, radius):
"""Draws a rounded box to a cairo context, but doesn't fill or stroke it
so it can be used as a clipping region as well."""
x1 = x
y1 = y
w = width
h = height
x2 = x1 + w
y2 = y1 + h
r = radius
cr.move_to(x1 + r, y1)
cr.line_to(x2 - r, y1)
cr.arc(x2 - r, y1 + r, r, A3, A4)
cr.line_to(x2, y2 - r)
cr.arc(x2 - r, y2 - r, r, A0, A1)
cr.line_to(x1 + r, y2)
cr.arc(x1 + r, y2 - r, r, A1, A2)
cr.line_to(x1, y1 + r)
cr.arc(x1 + r, y1 + r, r, A2, A3)
class RoundedBox(Gtk.Box):
"""A simple container that draws a solid background with rounded edges"""
BACKGROUND_COLOR = Color("#fff")
def __init__(self, radius = 10):
GObject.GObject.__init__(self)
self._radius = radius
self.set_double_buffered(False)
self.set_redraw_on_allocate(True)
def set_radius(self, radius):
"""Sets the radius of the curved edges of this box"""
self._radius = radius
self.queue_draw()
def get_radius(self):
"""Gets the radius of the curved edges of this box"""
return self._radius
def do_expose_event(self, event):
"""Draws the background and propagates the event to the children"""
window = self.get_window()
alloc = self.get_allocation()
cr = window.cairo_create()
# Set the clipping region
cr.rectangle(event.area.x, event.area.y, event.area.width,
event.area.height)
cr.clip()
#TODO: Fix this hack
color = RoundedBox.BACKGROUND_COLOR
cr.set_source_rgb(color.red, color.green, color.blue)
# Draw the rounded box
draw_rounded_box(cr, alloc.x, alloc.y, alloc.width, alloc.height,
self._radius)
cr.fill()
# Propagate the event to the children
for child in self.get_children():
self.propagate_expose(child, event)
class RoundedIcon(Gtk.Widget):
"""Draws a pixbuf with rounded edges"""
def __init__(self, pixbuf = None, radius = 10):
GObject.GObject.__init__(self)
self._pixbuf = pixbuf
self._radius = radius
self.set_has_window(False)
self.set_double_buffered(False)
self.set_redraw_on_allocate(True)
def set_from_pixbuf(self, pixbuf):
"""Sets the icon from a pixbuf"""
self._pixbuf = pixbuf
def do_expose_event(self, event):
"""Draws the pixbuf"""
pixbuf = self._pixbuf
if pixbuf == None:
return
window = self.get_window()
alloc = self.get_allocation()
cr = window.cairo_create()
w = pixbuf.get_width()
h = pixbuf.get_height()
if alloc.width < w or alloc.height < h:
self.set_size_request(w, h)
return
cr.translate(alloc.x, alloc.y)
draw_rounded_box(cr, 0, 0,
w, h,
self._radius)
cr.clip()
Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)
cr.paint()
|