From 6cdf287b3b5fe153ea7ccd9d852cda4d88fe7859 Mon Sep 17 00:00:00 2001 From: Lionel LASKE Date: Thu, 24 Nov 2011 20:54:00 +0000 Subject: Add zoom --- diff --git a/MANIFEST b/MANIFEST index f8afdfa..a8478f6 100644 --- a/MANIFEST +++ b/MANIFEST @@ -3,12 +3,11 @@ setup.py activity.py MANIFEST COPYING +activity/roots-icon.svg +activity/activity.info src/union.py src/person.py src/partialdate.py src/guid.py src/const.py src/__init__.py -po/HelloWorld.pot -activity/roots-icon.svg -activity/activity.info diff --git a/activity.py b/activity.py index be240e1..5573f58 100644 --- a/activity.py +++ b/activity.py @@ -13,6 +13,8 @@ import src.const as const # Sugar import try: from sugar.activity import activity + from sugar.graphics.toolbutton import ToolButton + from gtk import Toolbar const.inSugar = True except ImportError: from sugardummy import * @@ -32,14 +34,28 @@ class RootsActivity(activity.Activity): # Create toolbox toolbox = activity.ActivityToolbox(self) + toolbar = Toolbar() + tool = ToolButton('zoom-out') + tool.set_tooltip(_('Zoom out')) + tool.set_accelerator(_('minus')) + tool.connect('clicked', self.zoom_out) + toolbar.insert(tool, -1) + tool = ToolButton('zoom-in') + tool.set_tooltip(_('Zoom in')) + tool.set_accelerator(_('equal')) + tool.connect('clicked', self.zoom_in) + toolbar.insert(tool, -1) + toolbox.add_toolbar(_('View'), toolbar) self.set_toolbox(toolbox) toolbox.show() # Create sample data + (self.initx, self.inity, self.initzoom) = (500, 50, 0) self.tree = self.init_family() - self.tree.compute_draw(500, 50) + self.tree.compute_draw(self.initx, self.inity) # Create drawing area + self.zoomlevel = 1 self.area = gtk.DrawingArea() self.area.set_size_request(600, 300) self.area.set_events(gtk.gdk.BUTTON_PRESS_MASK|gtk.gdk.BUTTON_RELEASE_MASK|gtk.gdk.BUTTON_MOTION_MASK|gtk.gdk.POINTER_MOTION_MASK) @@ -136,12 +152,13 @@ class RootsActivity(activity.Activity): if self.moving: # Compute translation (dx, dy) = (event.x-self.movingStart[0], event.y-self.movingStart[1]) + (self.initx, self.inity) = (self.initx+dx, self.inity+dy) for p in persons: p.translate(dx, dy) self.movingStart = (event.x, event.y) # Redraw - self.area.queue_draw_area(0, 0, self.area.allocation.width, self.area.allocation.height) + self.redraw() else: # Look if a person is under the cursor @@ -161,7 +178,28 @@ class RootsActivity(activity.Activity): self.area.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW)) self.moving = False + + def zoom_in(self, event): + "ToolBar button zoom in clicked" + self.initzoom = self.initzoom + 20 + self.redraw() + + + def zoom_out(self, event): + "ToolBar button zoom out clicked" + self.initzoom = self.initzoom - 20 + self.redraw() + + + def redraw(self): + "Redraw area" + self.tree.compute_draw(self.initx, self.inity) + for p in persons: + p.scale(self.initzoom) + self.area.queue_draw_area(0, 0, self.area.allocation.width, self.area.allocation.height) + + # Dummy call to allow running on Windows if not const.inSugar: RootsActivity(0) diff --git a/src/person.py b/src/person.py index a318266..094eeb8 100644 --- a/src/person.py +++ b/src/person.py @@ -5,13 +5,14 @@ import const # Constants -const._person_width = 80 -const._person_height = 30 -const._person_wmargin = 6 -const._person_hmargin = 16 +const._person_width = 120 +const._person_height = 48 +const._person_wmargin_ratio = 12 +const._person_hmargin_ratio = 2 const._male_color = (0, 0, 255) const._female_color = (255, 0, 0) -const._person_font = pango.FontDescription('Arial 8') +const._person_font = 'Arial' +const._person_fontsize = 8 # Set of person @@ -35,7 +36,7 @@ class Person: self.sex = 'F' self.parents = None self.unions = [] - (self.x, self.y) = (-1, -1) + (self.x0, self.y0, self.x1, self.y1, self.fontsize) = (-1, -1, -1, -1, const._person_fontsize) persons.append(self) @@ -73,7 +74,7 @@ class Person: def point_inside(self, x, y): "Test if point is inside the drawing" - return x >= self.x and x <= self.x+const._person_width and y >= self.y and y <= self.y+const._person_height + return x >= self.x0 and x <= self.x1 and y >= self.y0 and y <= self.y1 def draw_node(self, gc, pc): @@ -84,17 +85,17 @@ class Person: gc.set_source_rgb(*const._male_color) else: gc.set_source_rgb(*const._female_color) - gc.rectangle(self.x, self.y, const._person_width, const._person_height) + gc.rectangle(self.x0, self.y0, self.x1-self.x0, self.y1-self.y0) gc.stroke() # draw text layout = pango.Layout(pc) - layout.set_width(const._person_width*pango.SCALE) + layout.set_width(int(self.x1-self.x0)*pango.SCALE) layout.set_text(self.name) layout.set_alignment(pango.ALIGN_CENTER) layout.set_wrap(pango.WRAP_WORD) - layout.set_font_description(const._person_font) - gc.move_to(self.x, self.y) + layout.set_font_description(pango.FontDescription(const._person_font + " " + str(self.fontsize))) + gc.move_to(self.x0, self.y0) gc.show_layout(layout) @@ -102,35 +103,50 @@ class Person: "Compute person and its subtree draw starting at origin" # Set person position - (self.x, self.y) = (x, y) + (self.x0, self.y0) = (x, y) + (self.x1, self.y1) = (x+const._person_width, y+const._person_height) if self.unions != []: # Set union position + wmargin = const._person_width / const._person_wmargin_ratio + hmargin = const._person_height / const._person_hmargin_ratio for i, u in enumerate(self.unions): # Next union if i != 0: size = u.size_to_draw() - x = x + (size*const._person_width+size*const._person_wmargin)/2 + x = x + (size*const._person_width+size*wmargin)/2 # Set conjoint position if self.sex == 'M': opposite = u.mum else: opposite = u.dad - (opposite.x, opposite.y) = (x + const._person_width+const._person_wmargin, y) + (opposite.x0, opposite.y0) = (x + const._person_width+wmargin, y) + (opposite.x1, opposite.y1) = (opposite.x0 + const._person_width, opposite.y0 + const._person_height) # Set the union and childs of this union - u.compute_draw(x+const._person_width+(const._person_wmargin/2), y+const._person_height+const._person_hmargin) + u.compute_draw(x+const._person_width+(wmargin/2), y+const._person_height+hmargin) # Shift right size = u.size_to_draw() - x = x + (size*const._person_width+size*const._person_wmargin)/2 + x = x + (size*const._person_width+size*wmargin)/2 def translate(self, dx, dy): "Translate coordinate" - self.x = self.x + dx - self.y = self.y + dy + self.x0 = self.x0 + dx + self.y0 = self.y0 + dy + self.x1 = self.x1 + dx + self.y1 = self.y1 + dy + + def scale(self, scalerate): + "Scale coordinate and font" + self.x0 = self.x0 + ((self.x0 * scalerate) / 100) + self.y0 = self.y0 + ((self.y0 * scalerate) / 100) + self.x1 = self.x1 + ((self.x1 * scalerate) / 100) + self.y1 = self.y1 + ((self.y1 * scalerate) / 100) + self.fontsize = const._person_fontsize + (scalerate / 10) + def draw(self, gc, pc): "Draw person and its subtree in the graphical context" @@ -149,8 +165,3 @@ class Person: # Draw the union and childs of this union u.draw(gc, pc, i) - - - - - diff --git a/src/union.py b/src/union.py index afb7e47..05c3a2d 100644 --- a/src/union.py +++ b/src/union.py @@ -56,24 +56,25 @@ class Union: size = size + c.size_to_draw() # Compute origin + wmargin = const._person_width/const._person_wmargin_ratio if len(self.childs) == 1: x = x - (const._person_width)/2 else: - x = x - (size*const._person_width+(size-1)*const._person_wmargin)/2 + x = x - (size*const._person_width+(size-1)*wmargin)/2 # Draw each child for c in self.childs: # Draw the child c.compute_draw(x, y) size = c.size_to_draw() - x = x + (size*const._person_width+size*const._person_wmargin) + x = x + (size*const._person_width+size*wmargin) def draw(self, gc, pc, unionnumber): "Draw person and its subtree in the graphical context" # Draw link between parents - if self.dad.x < self.mum.x: + if self.dad.x0 < self.mum.x0: (left, right) = (self.dad, self.mum) if (unionnumber != 0): left = left.unions[unionnumber-1].mum @@ -81,25 +82,28 @@ class Union: (left, right) = (self.mum, self.dad) if (unionnumber != 0): left = left.unions[unionnumber-1].dad - gc.move_to(left.x+const._person_width, left.y+(const._person_height/2)) - gc.line_to(right.x, right.y+(const._person_height/2)) + width = left.x1 - left.x0 + height = left.y1 - left.y0 + wmargin = width / const._person_wmargin_ratio + hmargin = height / const._person_hmargin_ratio + gc.move_to(left.x0+width, left.y0+(height/2)) + gc.line_to(right.x0, right.y0+(height/2)) gc.set_source_rgb(*const._union_color) gc.stroke() - # Compute childs size - size = 0 - for c in self.childs: - size = size + c.size_to_draw() - # Draw each child + size = len(self.childs) for c in self.childs: # Draw the child c.draw(gc, pc) # Draw link to child - gc.move_to(right.x-(const._person_wmargin/2), right.y+(const._person_height/2)) - gc.line_to(right.x-(const._person_wmargin/2), right.y+const._person_height+(const._person_hmargin/2)) - gc.line_to(c.x+(const._person_width/2), right.y+const._person_height+(const._person_hmargin/2)) - gc.line_to(c.x+(const._person_width/2), c.y) + gc.move_to(right.x0-(wmargin/2), right.y0+(height/2)) + gc.line_to(right.x0-(wmargin/2), right.y0+height+(hmargin/2)) + if size == 1: + gc.line_to(right.x0-(wmargin/2), c.y0) + else: + gc.line_to(c.x0+(width/2), right.y0+height+(hmargin/2)) + gc.line_to(c.x0+(width/2), c.y0) gc.set_source_rgb(*const._union_color) gc.stroke() \ No newline at end of file diff --git a/sugardummy.py b/sugardummy.py index 21288c2..6a2f796 100644 --- a/sugardummy.py +++ b/sugardummy.py @@ -6,6 +6,8 @@ class activity: # Dummy class for Activity class Activity: + _canvas = None + _toobox = None def __init__(self, handle): self.window = gtk.Window() @@ -13,24 +15,67 @@ class activity: self.window.connect("destroy", gtk.main_quit) def set_canvas(self, canvas): - self.window.add(canvas) + self._canvas = canvas def show_all(self): + vbox = gtk.VBox(False) + vbox.pack_start(self._toolbox, True, True, 0) + vbox.pack_start(self._canvas, True, True, 0) + self.window.add(vbox) self.window.show_all() def create_pango_context(self): return gtk.Widget.create_pango_context(self.window) def set_toolbox(self, toolbox): - pass + self._toolbox = toolbox # Dummy class for Toolbox - class ActivityToolbox: + class ActivityToolbox(gtk.Toolbar): def __init__(self, window): - pass + gtk.Toolbar.__init__(self) + self.toolbars = {} def show(self): - pass - \ No newline at end of file + for t in self.toolbars.itervalues(): + for i in t.myitems: + action = gtk.Action(i.id, i.tooltip, i.tooltip, gtk.STOCK_INFO) + if 'clicked' in i.methods: + action.connect('activate', i.methods['clicked']) + item = action.create_tool_item() + gtk.Toolbar.insert(self, item, -1) + + def add_toolbar(self, name, toolbar): + self.toolbars[name] = toolbar + + +# Dummy class for Toolbar +class Toolbar: + + def __init__(self): + self.myitems = [] + + def insert(self, tool, index): + self.myitems.insert(index, tool) + + +# Dummy class for ToolButton +class ToolButton: + + def __init__(self, id): + self.id = id + self.tooltip = '' + self.methods = {} + + def set_tooltip(self, text): + self.tooltip = text + + def set_accelerator(self, key): + pass + + def connect(self, event, callback): + self.methods[event] = callback + + -- cgit v0.9.1