From 6a9fcd2bc707969699db05c0be61865124661973 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 22 Sep 2006 20:13:06 +0000 Subject: add a hotspot for each pie segment git-svn-id: file:///home/lennart/svn/public/fring/trunk@12 d0d2c35f-0a1e-0410-abeb-dabff30a67ee --- src/fringlib/fringrenderer.py | 92 +++++++++++++++++++++++++++++++++++++------ src/fringlib/fringui.py | 3 +- 2 files changed, 80 insertions(+), 15 deletions(-) diff --git a/src/fringlib/fringrenderer.py b/src/fringlib/fringrenderer.py index a0d5a4b..fb9a876 100644 --- a/src/fringlib/fringrenderer.py +++ b/src/fringlib/fringrenderer.py @@ -6,18 +6,28 @@ import os class Hotspot: - def __init__(self, minpos, maxpos, folder): + def __init__(self, minpos, maxpos, path, size, percentage): self.minx,self.miny = minpos self.maxx,self.maxy = maxpos - self.folder = folder + self.path = path + self.size = size + self.percentage = percentage +class Segment: + def __init__(self, start, end, path, size): + self.start, self.end = start, end + self.path = path + self.size = size + + def percentage(self): + return self.end - self.start + class FringRenderer: def __init__(self): self.MAX_LEVEL = 1 - self.WIDTH, HEIGHT = 1024, 768 - self.WIDTH, HEIGHT = 1024, 768 + self.WIDTH, self.HEIGHT = 1024, 768 self.INNER_RADIUS = 100 self.RING_RADIUS = 60 self.RING_SPACE = 0 @@ -28,6 +38,7 @@ class FringRenderer: self.LABEL_UNTIL_RING = 0 self.hotspots = [] + self.lookup_data = [] def prepare_layouts(self,ctx): self.linklayout = ctx.create_layout() @@ -37,6 +48,13 @@ class FringRenderer: assert isinstance(data, sum_list) + if ring == 0: + self.lookup_data = [] + self.hotspots = [] + + while len(self.lookup_data) <= ring: + self.lookup_data.append([]) + CENTERX, CENTERY = self.WIDTH/2, self.HEIGHT/2 ctx.move_to(CENTERX, CENTERY) @@ -55,14 +73,16 @@ class FringRenderer: accumulated += value end = start_angle+(end_angle - start_angle)*1.0*accumulated/data.the_sum - + if end-start >= .01: + p = previouspath+os.sep+fn + self.lookup_data[ring].append(Segment(start, end, p, value)) + 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) @@ -108,16 +128,15 @@ class FringRenderer: ctx.set_line_width(self.LEG_LINE_WIDTH) ctx.stroke() - # write folder name and register a hotspot + # write path 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)) + self.__register_hotspot(p,value,end-start,x,y+(height/2),x+(width),y-(height/2)) else: ctx.set_source_rgb(0.5,0.5,0.5) @@ -138,13 +157,60 @@ class FringRenderer: for h in self.hotspots: if x >= h.minx and x <= h.maxx and \ y >= h.miny and y <= h.maxy: - return h.folder + return (h.path, h.size, h.percentage) + + def sqr(x): + return x*x - def __register_hotspot(self,folder,x0,y0,x1,y1): + CENTERX, CENTERY = self.WIDTH/2, self.HEIGHT/2 + radius = sqrt(sqr(x - CENTERX) + sqr(y - CENTERY)) + angle = atan2(y - CENTERY, x - CENTERX) + v = angle/(2*pi) + + if v < 0: + v+=1 + + if radius <= self.INNER_RADIUS: + return None + + # A simple bisection algorithm + + ring = int((radius - self.INNER_RADIUS)/(self.RING_RADIUS + self.RING_SPACE)) + try: + data = self.lookup_data[ring] + except IndexError: + return None + + minidx, maxidx = 0, len(data)-1 + p = int(maxidx*v) # Initial estimation + + while True: + assert p >= minidx + assert p <= maxidx + + d = data[p] + + if v <= d.start: + maxidx = p-1 + elif v <= d.end: + return (d.path, d.size, d.percentage()) + else: + minidx = p+1 + + if minidx > maxidx: + return None + + np = int((minidx+maxidx))/2 + + if np == p: + return None + + p = np + + def __register_hotspot(self,path,size,percentage,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 )) - + self.hotspots.append(Hotspot( (x0,y0), (x1,y1), path, size, percentage )) def hsv2rgb(self,h,s,v): if s<=0: diff --git a/src/fringlib/fringui.py b/src/fringlib/fringui.py index 592176c..cf94eaa 100644 --- a/src/fringlib/fringui.py +++ b/src/fringlib/fringui.py @@ -198,7 +198,6 @@ class UI( gtk.Window ): self.renderer.LABEL_UNTIL_RING = int(self.zoomfactor - 0.4) if self.zoomfactor < 0.8: self.renderer.LABEL_UNTIL_RING = -1 - self.renderer.hotspots = [] self.renderer.draw_segment(self.ctx, 0, 0, 1, 0, 1, self.data, self.path) self.image.queue_draw() self.__show_busy_cursor(-1) @@ -255,7 +254,7 @@ class UI( gtk.Window ): def __click_event(self, widget, event): f = self.renderer.get_hotspot_at(event.x, event.y) - if f is not None: self.open_folder(f) + if f is not None: self.open_folder(f[0]) def __scroll_event(self, widget, event): if event.direction is gtk.gdk.SCROLL_UP: -- cgit