From 39a9e678c2bb3d8a93b1e86377d0d334c5306348 Mon Sep 17 00:00:00 2001 From: Frederic Back Date: Fri, 22 Sep 2006 13:40:20 +0000 Subject: * Made a first python package git-svn-id: file:///home/lennart/svn/public/fring/trunk@4 d0d2c35f-0a1e-0410-abeb-dabff30a67ee --- src/fringlib/fringrenderer.py | 221 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 src/fringlib/fringrenderer.py (limited to 'src/fringlib/fringrenderer.py') diff --git a/src/fringlib/fringrenderer.py b/src/fringlib/fringrenderer.py new file mode 100644 index 0000000..a0d5a4b --- /dev/null +++ b/src/fringlib/fringrenderer.py @@ -0,0 +1,221 @@ +import cairo +import pango +from math import * +from fringwalker import sum_list +import os + +class Hotspot: + + def __init__(self, minpos, maxpos, folder): + self.minx,self.miny = minpos + self.maxx,self.maxy = maxpos + self.folder = folder + + +class FringRenderer: + + def __init__(self): + self.MAX_LEVEL = 1 + self.WIDTH, HEIGHT = 1024, 768 + self.WIDTH, HEIGHT = 1024, 768 + self.INNER_RADIUS = 100 + self.RING_RADIUS = 60 + self.RING_SPACE = 0 + self.RINGS_MAX = 4 + self.LINE_WIDTH = .5 + self.LEG_LINE_WIDTH = 1 + + self.LABEL_UNTIL_RING = 0 + + self.hotspots = [] + + def prepare_layouts(self,ctx): + self.linklayout = ctx.create_layout() + self.linklayout.set_font_description(pango.FontDescription("sans 10")) + + def draw_segment(self,ctx, ring, start_angle, end_angle, start_hue, end_hue, data, previouspath=""): + + assert isinstance(data, sum_list) + + CENTERX, CENTERY = self.WIDTH/2, self.HEIGHT/2 + ctx.move_to(CENTERX, CENTERY) + + if ring == 0: + self._draw_centered_text(ctx, self._pretty_size(data.the_sum)) + + n = len(data.data) + i = 0 + + accumulated = 0 + last = start_angle + + for fn, d in data.data: + start = last + value = self._list_value(d) + accumulated += value + + end = start_angle+(end_angle - start_angle)*1.0*accumulated/data.the_sum + + if end-start >= .01: + + v = start_hue + (end_hue-start_hue)*1.0*i/n + color = self._choose_color(start_hue + (end_hue-start_hue)*1.0*i/n, ring) + + r = self.INNER_RADIUS + ring * (self.RING_RADIUS + self.RING_SPACE) + + ctx.move_to(CENTERX+r*cos(start*2*pi), CENTERY+r*sin(start*2*pi)) + ctx.arc(CENTERX, CENTERY, r+self.RING_RADIUS, start*2*pi, end*2*pi) + ctx.arc_negative(CENTERX, CENTERY, r, end*2*pi, start*2*pi) + ctx.close_path() + + ctx.set_line_width(self.LINE_WIDTH) + ctx.set_source_rgb(*color) + ctx.fill_preserve() + + ctx.set_source_rgb(0, 0, 0) + ctx.stroke() + + if isinstance(d, sum_list) and ring+1 < self.RINGS_MAX: + self.draw_segment(ctx, ring+1, start, end, v, + start_hue + (end_hue-start_hue)*1.0*(i+1)/n, d, + previouspath+os.sep+fn) + + r += self.RING_RADIUS/2 + middle = CENTERX+r*cos((start+end)*pi), CENTERY+r*sin((start+end)*pi) + + if ring <= 0: + ctx.move_to(*middle) + + leg_radius = self.INNER_RADIUS + (self.RINGS_MAX+1) * (self.RING_RADIUS + self.RING_SPACE) + leg_radius -= (self.RING_RADIUS + self.RING_SPACE) / 2 + + ctx.line_to(CENTERX+leg_radius*cos((start+end)*pi), CENTERY+leg_radius*sin((start+end)*pi)) + + if cos((start+end)*pi) >= 0: + x = self.WIDTH/2 + leg_radius + align_x = 1 + else: + x = self.WIDTH/2 - leg_radius + align_x = 0 + + # get line target point + y = CENTERY+leg_radius*sin((start+end)*pi) + xmod = 2*(align_x*2-1) + + # draw line + ctx.line_to(x, y) + ctx.set_source_rgb(.5, .5, .5) + ctx.set_line_width(self.LEG_LINE_WIDTH) + ctx.stroke() + + # write folder name and register a hotspot + ctx.move_to(x+xmod,y) + + # register a hotspot ONLY if directory + if isinstance(d, sum_list): + ctx.set_source_rgb(0,0,1) + width,height = self._draw_centered_text(ctx, fn, align_x) + link = previouspath+os.sep+fn + if align_x == 0: width *= -1 + self.__register_hotspot(link,x,y+(height/2),x+(width),y-(height/2)) + + else: + ctx.set_source_rgb(0.5,0.5,0.5) + width,height = self._draw_centered_text(ctx, fn, align_x) + + + if ring <= self.LABEL_UNTIL_RING: + ctx.move_to(*middle) + ctx.set_source_rgb(0, 0, 0) + + # write relative and absolute disk usage + self._draw_centered_text2(ctx, "%.0f%%" % ((end-start)*100), self._pretty_size(value)) + + last = end + i += 1 + + def get_hotspot_at(self,x,y): + for h in self.hotspots: + if x >= h.minx and x <= h.maxx and \ + y >= h.miny and y <= h.maxy: + return h.folder + + def __register_hotspot(self,folder,x0,y0,x1,y1): + if x1 < x0: x0,x1 = x1,x0 # swap + if y1 < y0: y0,y1 = y1,y0 + self.hotspots.append(Hotspot( (x0,y0), (x1,y1), folder )) + + + def hsv2rgb(self,h,s,v): + if s<=0: + return 255*v,255*v,255*v + + h=6.0*(h%1.0) + f=h-int(h) + p=int(255*v*(1.0-s)) + q=int(255*v*(1.0-(s*f))) + t=int(255*v*(1.0-(s*(1.0-f)))) + v=int(255*v) + + return ((v,t,p), + (q,v,p), + (p,v,t), + (p,q,v), + (t,p,v), + (v,p,q))[int(h)] + + def _list_value(self,l): + if isinstance(l, sum_list): + return l.the_sum + return l + + + def _pretty_size(self,size): + if size >= 1024*1024*1024: + return "%.1f GiB" % round(size/1024/1024/1024.0) + elif size >= 1024*1024: + return "%.1f MiB" % round(size/1024/1024.0) + elif size >= 1024: + return "%.1f KiB" % round(size/1024.0) + else: + return "%u B" % size + + + def _choose_color(self,v, ring): + color = self.hsv2rgb(v, .61, 1-ring*0.1) + return color[0]/256.0, color[1]/256.0, color[2]/256.0, + + + def _draw_centered_text(self,ctx, text, align_x = .5, align_y = .5): + try: text = unicode(text) + except: return + + self.linklayout.set_text(text) + width,height = self.linklayout.get_pixel_size() + ctx.rel_move_to(-width*(1-align_x), -height*align_y) + ctx.show_layout(self.linklayout) + return width,height + + + def _draw_centered_text2(self,ctx, text1, text2): + try: + text1 = unicode(text1) + text2 = unicode(text2) + except: return + + extents1 = ctx.text_extents(text1) + extents2 = ctx.text_extents(text2) + + h = max((extents1[3], extents2[3])) + + p = ctx.get_current_point() + ctx.rel_move_to(-extents1[2]/2, -1) + ctx.show_text(text1) + + ctx.move_to(*p) + ctx.rel_move_to(-extents2[2]/2, h+1) + ctx.show_text(text2) + + + + -- cgit