5
Custom widgets that have rounded edges
11
from gi.repository import Gdk, GdkPixbuf, GObject, Gtk
13
logger = logging.getLogger("RoundedWidgets")
15
# Angles in pi/2 increments
19
A3 = 3.0 * math.pi / 2.0
22
def draw_rounded_box(cr, x, y, width, height, radius):
23
"""Draws a rounded box to a cairo context, but doesn't fill or stroke it
24
so it can be used as a clipping region as well."""
33
cr.move_to(x1 + r, y1)
34
cr.line_to(x2 - r, y1)
35
cr.arc(x2 - r, y1 + r, r, A3, A4)
36
cr.line_to(x2, y2 - r)
37
cr.arc(x2 - r, y2 - r, r, A0, A1)
38
cr.line_to(x1 + r, y2)
39
cr.arc(x1 + r, y2 - r, r, A1, A2)
40
cr.line_to(x1, y1 + r)
41
cr.arc(x1 + r, y1 + r, r, A2, A3)
43
class RoundedBox(Gtk.Box):
44
"""A simple container that draws a solid background with rounded edges"""
45
def __init__(self, r = 0.75, g = 0.75, b = 0.75, radius = 10):
46
GObject.GObject.__init__(self)
53
self.set_double_buffered(False)
54
self.set_redraw_on_allocate(True)
56
def set_color(self, r, g, b):
57
"""Sets the background color of this box"""
64
"""Gets the background color of this box as a tuple (r, g, b)"""
65
return (self._r, self._g, self._b)
67
def set_radius(self, radius):
68
"""Sets the radius of the curved edges of this box"""
73
"""Gets the radius of the curved edges of this box"""
76
def do_expose_event(self, event):
77
"""Draws the background and propagates the event to the children"""
78
window = self.get_window()
79
alloc = self.get_allocation()
80
cr = window.cairo_create()
82
# Set the clipping region
83
cr.rectangle(event.area.x, event.area.y, event.area.width,
87
cr.set_source_rgb(self._r, self._g, self._b)
89
# Draw the rounded box
90
draw_rounded_box(cr, alloc.x, alloc.y, alloc.width, alloc.height,
94
# Propagate the event to the children
95
for child in self.get_children():
96
self.propagate_expose(child, event)
98
class RoundedIcon(Gtk.Widget):
99
"""Draws a pixbuf with rounded edges"""
100
def __init__(self, pixbuf = None, radius = 10):
101
GObject.GObject.__init__(self)
103
self._pixbuf = pixbuf
104
self._radius = radius
106
self.set_has_window(False)
107
self.set_double_buffered(False)
108
self.set_redraw_on_allocate(True)
110
def set_from_pixbuf(self, pixbuf):
111
"""Sets the icon from a pixbuf"""
112
self._pixbuf = pixbuf
114
def do_expose_event(self, event):
115
"""Draws the pixbuf"""
116
pixbuf = self._pixbuf
120
window = self.get_window()
121
alloc = self.get_allocation()
122
cr = window.cairo_create()
124
w = pixbuf.get_width()
125
h = pixbuf.get_height()
127
if alloc.width < w or alloc.height < h:
128
self.set_size_request(w, h)
131
cr.translate(alloc.x, alloc.y)
133
draw_rounded_box(cr, 0, 0,
138
Gdk.cairo_set_source_pixbuf(cr, pixbuf, 0, 0)