Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLionel LASKE <llaske@c2s.fr>2011-11-24 20:54:00 (GMT)
committer Lionel LASKE <llaske@c2s.fr>2011-11-24 20:54:00 (GMT)
commit6cdf287b3b5fe153ea7ccd9d852cda4d88fe7859 (patch)
tree6a8de1f239e534f80f7f07c7bdf043c14f3f6aac
parent129a7b6ba90bb201cf1a7ac97f100da81ec86d7f (diff)
Add zoom
-rw-r--r--MANIFEST5
-rw-r--r--activity.py42
-rw-r--r--src/person.py57
-rw-r--r--src/union.py32
-rw-r--r--sugardummy.py57
5 files changed, 145 insertions, 48 deletions
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(_('<ctrl>minus'))
+ tool.connect('clicked', self.zoom_out)
+ toolbar.insert(tool, -1)
+ tool = ToolButton('zoom-in')
+ tool.set_tooltip(_('Zoom in'))
+ tool.set_accelerator(_('<ctrl>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
+
+