Fanchart: a single function to compute box and font color

svn: r20331
This commit is contained in:
Benny Malengier 2012-09-05 08:32:11 +00:00
parent 781cdcb6f4
commit bccc6f4d75
3 changed files with 45 additions and 27 deletions

View File

@ -452,6 +452,8 @@ def color_graph_box(alive=False, gender=gen.lib.Person.MALE):
## print 'border unknown alive', rgb_to_hex((143/256.0, 89/256.0, 2/256.0)) ## print 'border unknown alive', rgb_to_hex((143/256.0, 89/256.0, 2/256.0))
## print 'empty', rgb_to_hex((211/256.0, 215/256.0, 207/256.0)) ## print 'empty', rgb_to_hex((211/256.0, 215/256.0, 207/256.0))
# color functions. For hsv and hls values, use import colorsys !
def hex_to_rgb_float(value): def hex_to_rgb_float(value):
""" """
Convert a hexademical value #FF00FF to rgb. Returns tuple of float between Convert a hexademical value #FF00FF to rgb. Returns tuple of float between

View File

@ -180,6 +180,8 @@ class FanChartWidget(Gtk.DrawingArea):
""" """
Reset all of the data on where/how slices appear, and if they are expanded. Reset all of the data on where/how slices appear, and if they are expanded.
""" """
self.cache_fontcolor = {}
self.radialtext = radialtext self.radialtext = radialtext
self.childring = childring self.childring = childring
self.background = background self.background = background
@ -287,7 +289,8 @@ class FanChartWidget(Gtk.DrawingArea):
if state in [self.NORMAL, self.EXPANDED]: if state in [self.NORMAL, self.EXPANDED]:
self.draw_person(cr, gender_code(male), self.draw_person(cr, gender_code(male),
text, start, stop, text, start, stop,
generation, state, parents, child, person) generation, state, parents, child,
person)
cr.set_source_rgb(1, 1, 1) # white cr.set_source_rgb(1, 1, 1) # white
cr.move_to(0,0) cr.move_to(0,0)
cr.arc(0, 0, self.center, 0, 2 * math.pi) cr.arc(0, 0, self.center, 0, 2 * math.pi)
@ -296,13 +299,18 @@ class FanChartWidget(Gtk.DrawingArea):
cr.set_source_rgb(0, 0, 0) # black cr.set_source_rgb(0, 0, 0) # black
cr.arc(0, 0, self.center, 0, 2 * math.pi) cr.arc(0, 0, self.center, 0, 2 * math.pi)
cr.stroke() cr.stroke()
cr.restore()
# Draw center person: # Draw center person:
(text, person, parents, child) = self.data[0][0] (text, person, parents, child) = self.data[0][0]
cr.restore()
if person: if person:
r, g, b = self.background_box(person, person.gender, 0)
cr.arc(0, 0, self.center, 0, 2 * math.pi)
cr.set_source_rgb(r/255, g/255, b/255)
cr.fill()
cr.save() cr.save()
name = name_displayer.display(person) name = name_displayer.display(person)
self.draw_text(cr, name, self.center - 10, 95, 455) self.draw_text(cr, name, self.center - 10, 95, 455, False,
self.fontcolor(r,g,b))
cr.restore() cr.restore()
#draw center to move chart #draw center to move chart
cr.set_source_rgb(0, 0, 0) # black cr.set_source_rgb(0, 0, 0) # black
@ -315,7 +323,6 @@ class FanChartWidget(Gtk.DrawingArea):
if child and self.childring: if child and self.childring:
self.drawchildring(cr) self.drawchildring(cr)
def prepare_background_box(self): def prepare_background_box(self):
""" """
Method that is called every reset of the chart, to precomputed values Method that is called every reset of the chart, to precomputed values
@ -339,8 +346,7 @@ class FanChartWidget(Gtk.DrawingArea):
(1-x) * cstart_hsv[1] + x * cend_hsv[1], (1-x) * cstart_hsv[1] + x * cend_hsv[1],
(1-x) * cstart_hsv[2] + x * cend_hsv[2], (1-x) * cstart_hsv[2] + x * cend_hsv[2],
) for x in divs] ) for x in divs]
self.colors = [(int(255*r), int(255*g), int(255*b)) self.colors = [(255*r, 255*g, 255*b) for r, g, b in rgb_colors]
for r, g, b in rgb_colors]
else: else:
# known colors per generation, set or compute them # known colors per generation, set or compute them
self.colors = self.GENCOLOR[self.background] self.colors = self.GENCOLOR[self.background]
@ -350,6 +356,11 @@ class FanChartWidget(Gtk.DrawingArea):
determine red, green, blue value of background of the box of person, determine red, green, blue value of background of the box of person,
which has gender gender, and is in ring generation which has gender gender, and is in ring generation
""" """
if generation == 0 and self.background in [self.BACKGROUND_GENDER,
self.BACKGROUND_GRAD_GEN, self.BACKGROUND_SCHEME1,
self.BACKGROUND_SCHEME2]:
# white for center person:
return (255, 255, 255)
if self.background == self.BACKGROUND_GENDER: if self.background == self.BACKGROUND_GENDER:
try: try:
alive = probably_alive(person, self.dbstate.db) alive = probably_alive(person, self.dbstate.db)
@ -358,12 +369,29 @@ class FanChartWidget(Gtk.DrawingArea):
backgr, border = gui.utils.color_graph_box(alive, person.gender) backgr, border = gui.utils.color_graph_box(alive, person.gender)
r, g, b = gui.utils.hex_to_rgb(backgr) r, g, b = gui.utils.hex_to_rgb(backgr)
else: else:
if self.background == self.BACKGROUND_GRAD_GEN and generation < 0:
generation = 0
r, g, b = self.colors[generation % len(self.colors)] r, g, b = self.colors[generation % len(self.colors)]
if gender == gen.lib.Person.MALE: if gender == gen.lib.Person.MALE:
r *= .9 r *= .9
g *= .9 g *= .9
b *= .9 b *= .9
return r, g, b return r, g, b
def fontcolor(self, r, g, b):
"""
return the font color based on the r, g, b of the background
"""
try:
return self.cache_fontcolor[(r, g, b)]
except KeyError:
hls = colorsys.rgb_to_hls(r/255, g/255, b/255)
# we use the lightness value to determine white or black font
if hls[1] > 0.4:
self.cache_fontcolor[(r, g, b)] = (0, 0, 0)
else:
self.cache_fontcolor[(r, g, b)] = (255, 255, 255)
return self.cache_fontcolor[(r, g, b)]
def draw_person(self, cr, gender, name, start, stop, generation, def draw_person(self, cr, gender, name, start, stop, generation,
state, parents, child, person): state, parents, child, person):
@ -415,7 +443,8 @@ class FanChartWidget(Gtk.DrawingArea):
if self.radialtext and generation >= 6: if self.radialtext and generation >= 6:
radial = True radial = True
radstart = radius - self.PIXELS_PER_GENERATION + 4 radstart = radius - self.PIXELS_PER_GENERATION + 4
self.draw_text(cr, name, radstart, start, stop, radial) self.draw_text(cr, name, radstart, start, stop, radial,
self.fontcolor(r, g, b))
cr.restore() cr.restore()
def drawchildring(self, cr): def drawchildring(self, cr):
@ -456,26 +485,14 @@ class FanChartWidget(Gtk.DrawingArea):
cr.set_line_width(1) cr.set_line_width(1)
cr.stroke() cr.stroke()
#now fill #now fill
if self.background == self.BACKGROUND_GENDER: person = self.dbstate.db.get_person_from_handle(child_handle)
person = self.dbstate.db.get_person_from_handle(child_handle) r, g, b = self.background_box(person, person.gender, -1)
try:
alive = probably_alive(person, self.dbstate.db)
except RuntimeError:
alive = False
backgr, border = gui.utils.color_graph_box(alive, child_gender)
r, g, b = gui.utils.hex_to_rgb(backgr)
else:
#children in color as parents
r,g,b = self.colors[1]
if child_gender == gen.lib.Person.MALE:
r *= .9
g *= .9
b *= .9
_childpath(cr) _childpath(cr)
cr.set_source_rgb(r/255., g/255., b/255.) cr.set_source_rgb(r/255., g/255., b/255.)
cr.fill() cr.fill()
def draw_text(self, cr, text, radius, start, stop, radial=False): def draw_text(self, cr, text, radius, start, stop, radial=False,
fontcolor=(0, 0, 0)):
""" """
Display text at a particular radius, between start and stop Display text at a particular radius, between start and stop
degrees. degrees.
@ -484,6 +501,7 @@ class FanChartWidget(Gtk.DrawingArea):
font = Pango.FontDescription(self.fontdescr) font = Pango.FontDescription(self.fontdescr)
fontsize = self.fontsize fontsize = self.fontsize
font.set_size(fontsize * Pango.SCALE) font.set_size(fontsize * Pango.SCALE)
cr.set_source_rgb(fontcolor[0], fontcolor[1], fontcolor[2])
if radial and self.radialtext: if radial and self.radialtext:
cr.save() cr.save()
layout = self.create_pango_layout(text) layout = self.create_pango_layout(text)
@ -531,7 +549,6 @@ class FanChartWidget(Gtk.DrawingArea):
txlen -= 1 txlen -= 1
else: else:
cont = False cont = False
cr.set_source_rgb(0, 0, 0) # black
# offset for cairo-font system is 90 # offset for cairo-font system is 90
if start > 179: if start > 179:
pos = start + degoffsetheight + 90 - 90 pos = start + degoffsetheight + 90 - 90
@ -586,7 +603,6 @@ class FanChartWidget(Gtk.DrawingArea):
break break
cr.save() cr.save()
cr.set_source_rgb(0, 0, 0) # black
cr.rotate(pos * math.pi / 180) cr.rotate(pos * math.pi / 180)
pos = pos + degneed pos = pos + degneed
# Inform Pango to re-layout the text with the new transformation # Inform Pango to re-layout the text with the new transformation

View File

@ -64,8 +64,8 @@ class FanChartView(FanChartGrampsGUI, NavigationView):
('interface.fanview-childrenring', True), ('interface.fanview-childrenring', True),
('interface.fanview-radialtext', True), ('interface.fanview-radialtext', True),
('interface.fanview-font', 'Sans'), ('interface.fanview-font', 'Sans'),
('interface.color-start-grad', '#0000FF'), ('interface.color-start-grad', '#ef2929'),
('interface.color-end-grad', '#FF0000'), ('interface.color-end-grad', '#3d37e9'),
) )
def __init__(self, pdata, dbstate, uistate, nav_group=0): def __init__(self, pdata, dbstate, uistate, nav_group=0):
self.dbstate = dbstate self.dbstate = dbstate