11
12
_gety = lambda y, radius, angle: y + sin(angle) * radius
12
13
_getxy = lambda center, radius, angle: (_getx(center[X], radius, angle), _gety(center[Y], radius, angle))
14
def sketch_arc(ctx, center, radius, offset, apperture):
17
angle2 = offset + apperture
18
corner1 = _getxy(center, radius, angle1)
19
corner2 = _getxy(center, radius, angle2)
23
ctx.arc(center[X], center[Y], radius, angle1, angle2)
24
ctx.line_to(center[X], center[Y])
26
def sketch_radius(ctx, center, radius, angle):
28
ctx.line_to(*_getxy(center, radius, angle))
31
class CairoPieChart(gtk.DrawingArea):
32
def __init__(self, values, getter):
33
super(CairoPieChart, self).__init__()
34
self.connect("expose-event", self._on_exposed)
41
def _on_exposed(self, me, evt):
44
def draw_slice(self, center, radius, offset, percentage, color, ctx):
46
apperture = percentage * math.pi * 2
48
ctx.set_source_color(color)
49
sketch_arc(ctx, center, radius, offset, apperture)
16
def __init__(self, center, radius, offset, apperture):
17
# the center of the slice
19
# the length of the radius
23
# relative angle of the slice
24
self.apperture = apperture
25
# apperture counting from 'o' to 'offset'
28
self.angle2 = offset + apperture
30
self.corner1 = _getxy(center, radius, self.angle1)
32
self.corner2 = _getxy(center, radius, self.angle2)
34
def split(self, parts):
35
apperture = self.apperture/parts
36
new_Slice = lambda x: Slice(self.center, self.radius, self.offset + x, apperture)
38
for x in range(parts):
42
def split2(self, parts):
43
apperture = self.apperture/parts
44
new_Slice = lambda x: Slice(self.center, self.radius, self.offset, apperture + x)
46
for x in range(parts):
51
def color_to_rgba(color, alpha=1.0):
53
Converts a GdkColor to a tuple in the rgba format.
54
You can pass an optional argument for the alpha,
55
since it defaults to 1.0.
57
return (color.red/65535.0,
62
def create_fade_pattern(p1, p2, r, g, b, a=1.0):
63
"""Creates a pattern that is fading."""
64
patt = cairo.LinearGradient(p1[0], p1[1], p2[0], p2[1])
65
patt.add_color_stop_rgba(0.0, r, g, b, 0)
66
patt.add_color_stop_rgba(0.7, r, g, b, .8)
67
patt.add_color_stop_rgba(0.0, r, g, b, 0)
71
def sketch_arc(ctx, s):
72
ctx.move_to(*s.center)
73
ctx.line_to(*s.corner1)
74
ctx.arc(s.center[X], s.center[Y], s.radius, s.angle1, s.angle2)
75
ctx.line_to(s.center[X], s.center[Y])
77
def sketch_radius(ctx, center, corner):
81
def _draw_interior(ctx, s, color):
83
ctx.set_source_color(color)
89
def _draw_interior_fade(ctx, s, color):
90
apperture_1 = s.apperture * 0.90
91
s1 = Slice(s.center, s.radius, s.offset, apperture_1)
92
s2 = Slice(s.center, s.radius, s.offset + apperture_1, s.apperture - apperture_1)
95
ctx.set_source_color(color)
101
rgba = list(color_to_rgba(color))
103
for small_s in s2.split2(8):
104
#ctx.set_source_color(color)
105
ctx.set_source_rgba(*rgba)
106
sketch_arc(ctx, small_s)
53
ctx.set_source_color(self.get_border_color())
54
sketch_radius(ctx, center, radius, offset)
57
def draw_background(self, center, radius, ctx):
58
ctx.set_source_color(self.style.bg[gtk.STATE_NORMAL])
59
ctx.arc(center[X], center[Y], radius, 0, TWO_PI)
62
def draw_border(self, center, radius, ctx):
63
ctx.set_source_color(self.get_border_color())
64
ctx.arc(center[X], center[Y], radius, 0, TWO_PI)
110
def draw_slice(ctx, center, radius, offset, percentage, color, border_color, fade=False):
111
# Obtain the apperture of the slice
112
offset *= math.pi * 2
113
apperture = percentage * math.pi * 2
114
s = Slice(center, radius, offset, apperture)
116
_draw_interior_fade(ctx, s, color)
118
_draw_interior(ctx, s, color)
121
ctx.set_source_color(border_color)
122
sketch_radius(ctx, s.center, s.corner1)
125
class CairoWidget(gtk.DrawingArea):
126
"""Base class for using cairo graphics"""
128
super(CairoWidget, self).__init__()
129
self.connect("expose-event",
130
lambda widget, evt: \
131
self.draw(self.window.cairo_create()))
68
133
def get_border_color(self):
69
134
return self.style.dark[gtk.STATE_NORMAL]
80
145
def get_background_color(self):
81
146
return self.style.bg[gtk.STATE_NORMAL]
149
raise NotImplementedError("You must implement 'draw(ctx)' method")
151
class CairoPieChart(CairoWidget):
152
"""Draws a group of slices that represent musics"""
153
def __init__(self, values, getter):
154
super(CairoPieChart, self).__init__()
161
def draw_slice(self, ctx, center, radius, offset, percentage, color):
162
draw_slice(ctx, center, radius, offset, percentage, color, self.get_border_color())
164
def draw_background(self, center, radius, ctx):
165
ctx.set_source_color(self.get_background_color())
166
ctx.arc(center[X], center[Y], radius, 0, TWO_PI)
169
def draw_border(self, center, radius, ctx):
170
ctx.set_source_color(self.get_border_color())
171
ctx.arc(center[X], center[Y], radius, 0, TWO_PI)
174
def get_color_for(self, index):
175
selected = index in self.selected
178
color = self.get_selected_background_color()
180
color = self.get_normal_background_color()
86
184
rect = self.allocation
87
186
radius = min(rect.width / 2.0, rect.height / 2.0) - 5
105
204
total = self.total
106
205
total = float(total)
209
# cycle for each slice
108
210
for index, val in enumerate(self.values):
211
# get the percentage each slice occupies
109
212
apperture = self.getter(val) / total
110
selected = index in self.selected
113
bg = self.get_selected_background_color()
115
bg = self.get_normal_background_color()
118
self.draw_slice(center, radius, offset, apperture, bg, ctx)
214
color = self.get_color_for(index)
215
self.draw_slice(ctx, center, radius, offset, apperture, color)
119
216
offset += apperture
122
bg = self.get_empty_background_color()
123
self.draw_slice(center, radius, offset, 1.0 - offset, bg, ctx)
219
color = self.get_empty_background_color()
220
self.draw_slice(ctx, center, radius, offset, 1.0 - offset, color)
125
222
self.draw_background(center, small_radius, ctx)
126
223
self.draw_border(center, small_radius, ctx)
127
224
self.draw_border(center, radius, ctx)
229
chart.values[0] += 0.1
230
chart.values[1] -= 0.1
231
if chart.values[1] < 0 or chart.values[0] > 22:
236
return chart.values[1] > 0
133
241
window = gtk.Window()
134
242
chart = CairoPieChart([10,12], lambda x: x)
136
244
chart.selected = [0]
138
chart.set_size_request(64, 64)
246
chart.set_size_request(256, 256)
140
248
btn = gtk.Button("Hi")