Speed ups: cache names---don't re-lookup name; added outer edge to indicate parents; removed simple access

svn: r11714
This commit is contained in:
Doug Blank 2009-01-25 11:19:13 +00:00
parent 2018064fe1
commit d2b481b1a3

View File

@ -58,10 +58,13 @@ if gtk.pygtk_version < (2,3,93):
#
#-------------------------------------------------------------------------
from BasicUtils import name_displayer
from Simple import SimpleAccess
from gettext import gettext as _
from DataViews import Gramplet, register
from gen.lib import Person
import gen.lib
def gender_code(is_male):
if is_male: return 1
return 0
#-------------------------------------------------------------------------
#
@ -127,7 +130,7 @@ class FanChartWidget(gtk.Widget):
self.angle = {}
self.data = {}
for i in range(self.generations):
self.data[i] = [None for j in range(2 ** i)]
self.data[i] = [(None, None, None) for j in range(2 ** i)]
self.angle[i] = []
angle = 0
slice = 360.0 / (2 ** i)
@ -205,14 +208,13 @@ class FanChartWidget(gtk.Widget):
cr.rotate(self.rotate_value * math.pi/180)
for generation in range(self.generations - 1, 0, -1):
for p in range(len(self.data[generation])):
person = self.data[generation][p]
(text, person, parents) = self.data[generation][p]
if person:
start, stop, male, state = self.angle[generation][p]
name = name_displayer.display(person)
gender = person.get_gender()
if state in [self.NORMAL, self.EXPANDED]:
self.draw_person(cr, gender, name, start, stop,
generation, state)
self.draw_person(cr, gender_code(male),
text, start, stop,
generation, state, parents)
cr.set_source_rgb(1, 1, 1) # white
cr.move_to(0,0)
cr.arc(0, 0, self.center, 0, 2 * math.pi)
@ -222,7 +224,7 @@ class FanChartWidget(gtk.Widget):
cr.arc(0, 0, self.center, 0, 2 * math.pi)
cr.stroke()
# Draw center person:
person = self.data[0][0]
(text, person, parents) = self.data[0][0]
cr.restore()
if person:
cr.save()
@ -234,7 +236,8 @@ class FanChartWidget(gtk.Widget):
cr.update_layout(self.layout)
cr.show_layout(self.layout)
def draw_person(self, cr, gender, name, start, stop, generation, state):
def draw_person(self, cr, gender, name, start, stop, generation,
state, parents):
"""
Display the piece of pie for a given person. start and stop
are in degrees.
@ -243,12 +246,25 @@ class FanChartWidget(gtk.Widget):
start_rad = start * math.pi/180
stop_rad = stop * math.pi/180
r,g,b = self.GENCOLOR[generation % len(self.GENCOLOR)]
if gender == Person.MALE:
if gender == gen.lib.Person.MALE:
r -= r * .10
g -= g * .10
b -= b * .10
cr.set_source_rgb(r/255., g/255., b/255.)
radius = generation * self.pixels_per_generation + self.center
# If max generation, and they have parents:
if generation == self.generations - 1 and parents:
# draw an indicator
cr.move_to(0, 0)
#cr.set_source_rgba(1, 0.2, 0.2, 0.6) # pink
cr.set_source_rgb(255, 255, 255) # white
cr.arc(0, 0, radius + 5, start_rad, stop_rad)
cr.fill()
cr.move_to(0, 0)
cr.set_source_rgb(0, 0, 0) # black
cr.arc(0, 0, radius + 5, start_rad, stop_rad)
cr.line_to(0, 0)
cr.stroke()
cr.set_source_rgb(r/255., g/255., b/255.)
cr.move_to(0, 0)
cr.arc(0, 0, radius, start_rad, stop_rad)
cr.move_to(0, 0)
@ -263,6 +279,7 @@ class FanChartWidget(gtk.Widget):
else: # EXPANDED
cr.set_line_width(3)
cr.stroke()
cr.set_line_width(1)
if self.last_x == None or self.last_y == None:
self.draw_text(cr, name, radius - self.pixels_per_generation/2,
start, stop)
@ -461,25 +478,27 @@ class FanChartWidget(gtk.Widget):
selected = None
if (0 < generation < self.generations):
for p in range(len(self.angle[generation])):
start, stop, male, state = self.angle[generation][p]
if state == self.COLLAPSED: continue
if start <= pos <= stop:
selected = p
break
if selected == None: # click in open area
# save the mouse location for movements
if self.data[generation][p][1]: # there is a person there
start, stop, male, state = self.angle[generation][p]
if state == self.COLLAPSED: continue
if start <= pos <= stop:
selected = p
break
# Handle the click:
if selected == None: # clicked in open area
if radius < self.center:
print "TODO: select children"
print "TODO: select child, spouse"
self.queue_draw()
return True
else:
# save the mouse location for movements
self.last_x, self.last_y = event.x, event.y
return True
# Do things based on state, event.state, or button, event.button
if event.button == 1: # left mouse
self.change_slice(generation, selected)
elif event.button == 3: # right mouse
person = self.data[generation][selected]
text, person, parents = self.data[generation][selected]
if person and self.right_click_callback:
self.right_click_callback(person)
self.queue_draw()
@ -490,7 +509,6 @@ class FanChartGramplet(Gramplet):
The Gramplet code that realizes the FanChartWidget.
"""
def init(self):
self.sa = SimpleAccess(self.dbstate.db)
self.set_tooltip("Click to expand/contract person\nRight-click to make person active")
self.generations = 6
self.gui.fan = FanChartWidget(self.generations,
@ -501,42 +519,88 @@ class FanChartGramplet(Gramplet):
# Make sure it is visible:
self.gui.fan.show()
def db_changed(self):
"""
Method called when database changes.
"""
# reset the db connection
self.sa = SimpleAccess(self.dbstate.db)
def active_changed(self, handle):
"""
Method called when active person changes.
"""
# Reset everything but rotation angle (leave it as is)
self.gui.fan.reset_generations()
self.update()
def have_parents(self, person):
"""
Returns True if a person has parents.
"""
if person:
m = self.get_parent(person, "female")
f = self.get_parent(person, "male")
return m != None or f != None
return False
def get_parent(self, person, gender):
"""
Get the father if gender == "male", or get mother otherwise.
"""
if person:
parent_handle_list = person.get_parent_family_handle_list()
if parent_handle_list:
family_id = parent_handle_list[0]
family = self.dbstate.db.get_family_from_handle(family_id)
if family:
if gender == "male":
person_handle = gen.lib.Family.get_father_handle(family)
else:
person_handle = gen.lib.Family.get_mother_handle(family)
if person_handle:
return self.dbstate.db.get_person_from_handle(person_handle)
return None
def main(self):
"""
Fill the data structures with the active data. This initializes all
data.
"""
self.gui.fan.data[0][0] = self.dbstate.get_active_person()
self.gui.fan.reset_generations()
person = self.dbstate.get_active_person()
if not person:
name = None
else:
name = name_displayer.display(person)
parents = self.have_parents(person)
self.gui.fan.data[0][0] = (name, person, parents)
for current in range(1, self.generations):
parent = 0
for p in self.gui.fan.data[current - 1]:
self.gui.fan.data[current][parent] = self.sa.father(p)
if self.gui.fan.data[current][parent] is None:
# name, person, parents
for (n,p,q) in self.gui.fan.data[current - 1]:
# Get father's details:
person = self.get_parent(p, "male")
if person:
name = name_displayer.display(person)
else:
name = None
if current == self.generations - 1:
parents = self.have_parents(person)
else:
parents = None
self.gui.fan.data[current][parent] = (name, person, parents)
if person is None:
# start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1
self.gui.fan.data[current][parent] = self.sa.mother(p)
if self.gui.fan.data[current][parent] is None:
# start,stop,male/left,state
# Get mother's details:
person = self.get_parent(p, "female")
if person:
name = name_displayer.display(person)
else:
name = None
parents = self.have_parents(person)
self.gui.fan.data[current][parent] = (name, person, parents)
if person is None:
# start,stop,male/right,state
self.gui.fan.angle[current][parent][3] = self.gui.fan.COLLAPSED
parent += 1
self.gui.fan.queue_draw()
#-------------------------------------------------------------------------
#
# Register the Gramplet