Fanchart Feature: allow halfcircle and quadrant like in the drawreport
svn: r20352
This commit is contained in:
parent
4cc2af5eb6
commit
e56fc52e95
@ -86,8 +86,10 @@ def gender_code(is_male):
|
|||||||
|
|
||||||
PIXELS_PER_GENERATION = 50 # size of radius for generation
|
PIXELS_PER_GENERATION = 50 # size of radius for generation
|
||||||
BORDER_EDGE_WIDTH = 10 # empty white box size at edge to indicate parents
|
BORDER_EDGE_WIDTH = 10 # empty white box size at edge to indicate parents
|
||||||
|
CENTER = 50 # pixel radius of center
|
||||||
CHILDRING_WIDTH = 12 # width of the children ring inside the person
|
CHILDRING_WIDTH = 12 # width of the children ring inside the person
|
||||||
TRANSLATE_PX = 10 # size of the central circle, used to move the chart
|
TRANSLATE_PX = 10 # size of the central circle, used to move the chart
|
||||||
|
PAD_PX = 4 # padding with edges
|
||||||
|
|
||||||
BACKGROUND_SCHEME1 = 0
|
BACKGROUND_SCHEME1 = 0
|
||||||
BACKGROUND_SCHEME2 = 1
|
BACKGROUND_SCHEME2 = 1
|
||||||
@ -120,6 +122,10 @@ GENCOLOR = {
|
|||||||
MAX_AGE = 100
|
MAX_AGE = 100
|
||||||
GRADIENTSCALE = 5
|
GRADIENTSCALE = 5
|
||||||
|
|
||||||
|
FORM_CIRCLE = 0
|
||||||
|
FORM_HALFCIRCLE = 1
|
||||||
|
FORM_QUADRANT = 2
|
||||||
|
|
||||||
COLLAPSED = 0
|
COLLAPSED = 0
|
||||||
NORMAL = 1
|
NORMAL = 1
|
||||||
EXPANDED = 2
|
EXPANDED = 2
|
||||||
@ -185,15 +191,14 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
self.rotate_value = 90 # degrees, initially, 1st gen male on right half
|
self.rotate_value = 90 # degrees, initially, 1st gen male on right half
|
||||||
self.center_xy = [0, 0] # distance from center (x, y)
|
self.center_xy = [0, 0] # distance from center (x, y)
|
||||||
self.center = 50 # pixel radius of center
|
|
||||||
#default values
|
#default values
|
||||||
self.reset(None, 9, BACKGROUND_GRAD_GEN, True, True, 'Sans', '#0000FF',
|
self.reset(None, 9, BACKGROUND_GRAD_GEN, True, True, 'Sans', '#0000FF',
|
||||||
'#FF0000', None, 0.5)
|
'#FF0000', None, 0.5, FORM_CIRCLE)
|
||||||
self.set_size_request(120, 120)
|
self.set_size_request(120, 120)
|
||||||
|
|
||||||
def reset(self, root_person_handle, maxgen, background, childring,
|
def reset(self, root_person_handle, maxgen, background, childring,
|
||||||
radialtext, fontdescr, grad_start, grad_end,
|
radialtext, fontdescr, grad_start, grad_end,
|
||||||
filter, alpha_filter):
|
filter, alpha_filter, form):
|
||||||
"""
|
"""
|
||||||
Reset all of the data:
|
Reset all of the data:
|
||||||
root_person_handle = person to show
|
root_person_handle = person to show
|
||||||
@ -205,6 +210,7 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
grad_start, grad_end: colors to use for background procedure
|
grad_start, grad_end: colors to use for background procedure
|
||||||
filter = the person filter to apply to the people in the chart
|
filter = the person filter to apply to the people in the chart
|
||||||
alpha = the alpha transparency value (0-1) to apply to filtered out data
|
alpha = the alpha transparency value (0-1) to apply to filtered out data
|
||||||
|
form = the FORM_ constant for the fanchart
|
||||||
"""
|
"""
|
||||||
self.cache_fontcolor = {}
|
self.cache_fontcolor = {}
|
||||||
|
|
||||||
@ -216,6 +222,7 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
self.grad_end = grad_end
|
self.grad_end = grad_end
|
||||||
self.filter = filter
|
self.filter = filter
|
||||||
self.alpha_filter = alpha_filter
|
self.alpha_filter = alpha_filter
|
||||||
|
self.form = form
|
||||||
|
|
||||||
self.set_generations(maxgen)
|
self.set_generations(maxgen)
|
||||||
|
|
||||||
@ -334,8 +341,15 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
# name, person, parents?, children?
|
# name, person, parents?, children?
|
||||||
self.data[i] = [(None,) * 5] * 2 ** i
|
self.data[i] = [(None,) * 5] * 2 ** i
|
||||||
self.angle[i] = []
|
self.angle[i] = []
|
||||||
|
factor = 1
|
||||||
angle = 0
|
angle = 0
|
||||||
slice = 360.0 / (2 ** i)
|
if self.form == FORM_HALFCIRCLE:
|
||||||
|
factor = 1/2
|
||||||
|
angle = 90
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
angle = 180
|
||||||
|
factor = 1/4
|
||||||
|
slice = 360.0 / (2 ** i) * factor
|
||||||
gender = True
|
gender = True
|
||||||
for count in range(len(self.data[i])):
|
for count in range(len(self.data[i])):
|
||||||
# start, stop, male, state
|
# start, stop, male, state
|
||||||
@ -347,8 +361,15 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
"""
|
"""
|
||||||
Overridden method to handle size request events.
|
Overridden method to handle size request events.
|
||||||
"""
|
"""
|
||||||
|
if self.form == FORM_CIRCLE:
|
||||||
requisition.width = 2 * self.halfdist()
|
requisition.width = 2 * self.halfdist()
|
||||||
requisition.height = requisition.width
|
requisition.height = requisition.width
|
||||||
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
|
requisition.width = 2 * self.halfdist()
|
||||||
|
requisition.height = requisition.width / 2 + CENTER + PAD_PX
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
requisition.width = self.halfdist() + CENTER + PAD_PX
|
||||||
|
requisition.height = requisition.width
|
||||||
|
|
||||||
def do_get_preferred_width(self):
|
def do_get_preferred_width(self):
|
||||||
""" GTK3 uses width for height sizing model. This method will
|
""" GTK3 uses width for height sizing model. This method will
|
||||||
@ -386,8 +407,7 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
Compute the half radius of the circle
|
Compute the half radius of the circle
|
||||||
"""
|
"""
|
||||||
nrgen = self.nrgen()
|
nrgen = self.nrgen()
|
||||||
return PIXELS_PER_GENERATION * nrgen + self.center \
|
return PIXELS_PER_GENERATION * nrgen + CENTER + BORDER_EDGE_WIDTH
|
||||||
+ BORDER_EDGE_WIDTH
|
|
||||||
|
|
||||||
def on_draw(self, widget, cr, scale=1.):
|
def on_draw(self, widget, cr, scale=1.):
|
||||||
"""
|
"""
|
||||||
@ -397,17 +417,34 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
"""
|
"""
|
||||||
# first do size request of what we will need
|
# first do size request of what we will need
|
||||||
nrgen = self.nrgen()
|
nrgen = self.nrgen()
|
||||||
halfdist = PIXELS_PER_GENERATION * nrgen + self.center
|
halfdist = PIXELS_PER_GENERATION * nrgen + CENTER
|
||||||
|
if self.form == FORM_CIRCLE:
|
||||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
self.set_size_request(2 * halfdist, 2 * halfdist)
|
||||||
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
|
self.set_size_request(2 * halfdist, halfdist + CENTER + PAD_PX)
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
self.set_size_request(halfdist + CENTER + PAD_PX, halfdist + CENTER + PAD_PX)
|
||||||
|
|
||||||
#obtain the allocation
|
#obtain the allocation
|
||||||
alloc = self.get_allocation()
|
alloc = self.get_allocation()
|
||||||
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
||||||
|
if widget is None: # printing, use the size we need
|
||||||
|
w = 2 * halfdist
|
||||||
|
h = 2 * halfdist
|
||||||
|
|
||||||
cr.scale(scale, scale)
|
cr.scale(scale, scale)
|
||||||
if widget:
|
|
||||||
cr.translate(w/2. - self.center_xy[0], h/2. - self.center_xy[1])
|
if self.form == FORM_CIRCLE:
|
||||||
else:
|
self.center_x = w/2 - self.center_xy[0]
|
||||||
cr.translate(halfdist - self.center_xy[0], halfdist - self.center_xy[1])
|
self.center_y = h/2 - self.center_xy[1]
|
||||||
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
|
self.center_x = w/2. - self.center_xy[0]
|
||||||
|
self.center_y = h - CENTER - PAD_PX- self.center_xy[1]
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
self.center_x = CENTER + PAD_PX - self.center_xy[0]
|
||||||
|
self.center_y = h - CENTER - PAD_PX - self.center_xy[1]
|
||||||
|
cr.translate(self.center_x, self.center_y)
|
||||||
|
|
||||||
cr.save()
|
cr.save()
|
||||||
cr.rotate(self.rotate_value * math.pi/180)
|
cr.rotate(self.rotate_value * math.pi/180)
|
||||||
for generation in range(self.generations - 1, 0, -1):
|
for generation in range(self.generations - 1, 0, -1):
|
||||||
@ -422,23 +459,23 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
person, userdata)
|
person, userdata)
|
||||||
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, CENTER, 0, 2 * math.pi)
|
||||||
cr.move_to(0,0)
|
cr.move_to(0,0)
|
||||||
cr.fill()
|
cr.fill()
|
||||||
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, CENTER, 0, 2 * math.pi)
|
||||||
cr.stroke()
|
cr.stroke()
|
||||||
cr.restore()
|
cr.restore()
|
||||||
# Draw center person:
|
# Draw center person:
|
||||||
(text, person, parents, child, userdata) = self.data[0][0]
|
(text, person, parents, child, userdata) = self.data[0][0]
|
||||||
if person:
|
if person:
|
||||||
r, g, b, a = self.background_box(person, person.gender, 0, userdata)
|
r, g, b, a = self.background_box(person, person.gender, 0, userdata)
|
||||||
cr.arc(0, 0, self.center, 0, 2 * math.pi)
|
cr.arc(0, 0, CENTER, 0, 2 * math.pi)
|
||||||
cr.set_source_rgba(r/255, g/255, b/255, a)
|
cr.set_source_rgba(r/255, g/255, b/255, a)
|
||||||
cr.fill()
|
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, False,
|
self.draw_text(cr, name, CENTER - 10, 95, 455, False,
|
||||||
self.fontcolor(r, g, b), self.fontbold(a))
|
self.fontcolor(r, g, b), self.fontbold(a))
|
||||||
cr.restore()
|
cr.restore()
|
||||||
#draw center to move chart
|
#draw center to move chart
|
||||||
@ -465,7 +502,7 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
start_rad = start * math.pi/180
|
start_rad = start * math.pi/180
|
||||||
stop_rad = stop * math.pi/180
|
stop_rad = stop * math.pi/180
|
||||||
r, g, b, a = self.background_box(person, gender, generation, userdata)
|
r, g, b, a = self.background_box(person, gender, generation, userdata)
|
||||||
radius = generation * PIXELS_PER_GENERATION + self.center
|
radius = generation * PIXELS_PER_GENERATION + CENTER
|
||||||
# If max generation, and they have parents:
|
# If max generation, and they have parents:
|
||||||
if generation == self.generations - 1 and parents:
|
if generation == self.generations - 1 and parents:
|
||||||
# draw an indicator
|
# draw an indicator
|
||||||
@ -1004,7 +1041,12 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
alloc = self.get_allocation()
|
alloc = self.get_allocation()
|
||||||
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
||||||
if self.translating:
|
if self.translating:
|
||||||
|
if self.form == FORM_CIRCLE:
|
||||||
self.center_xy = w/2 - event.x, h/2 - event.y
|
self.center_xy = w/2 - event.x, h/2 - event.y
|
||||||
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
|
self.center_xy = w/2 - event.x, h - CENTER - PAD_PX - event.y
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
self.center_xy = CENTER + PAD_PX - event.x, h - CENTER - PAD_PX - event.y
|
||||||
else:
|
else:
|
||||||
cx = w/2 - self.center_xy[0]
|
cx = w/2 - self.center_xy[0]
|
||||||
cy = h/2 - self.center_xy[1]
|
cy = h/2 - self.center_xy[1]
|
||||||
@ -1030,20 +1072,20 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
generation >= self.generations outside of diagram
|
generation >= self.generations outside of diagram
|
||||||
"""
|
"""
|
||||||
# compute angle, radius, find out who would be there (rotated)
|
# compute angle, radius, find out who would be there (rotated)
|
||||||
alloc = self.get_allocation()
|
|
||||||
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
# center coordinate
|
||||||
cx = w/2 - self.center_xy[0]
|
cx = self.center_x
|
||||||
cy = h/2 - self.center_xy[1]
|
cy = self.center_y
|
||||||
radius = math.sqrt((curx - cx) ** 2 + (cury - cy) ** 2)
|
radius = math.sqrt((curx - cx) ** 2 + (cury - cy) ** 2)
|
||||||
if radius < TRANSLATE_PX:
|
if radius < TRANSLATE_PX:
|
||||||
generation = -1
|
generation = -1
|
||||||
elif (self.childring and self.childrenroot and
|
elif (self.childring and self.childrenroot and
|
||||||
radius < TRANSLATE_PX + CHILDRING_WIDTH):
|
radius < TRANSLATE_PX + CHILDRING_WIDTH):
|
||||||
generation = -2 # indication of one of the children
|
generation = -2 # indication of one of the children
|
||||||
elif radius < self.center:
|
elif radius < CENTER:
|
||||||
generation = 0
|
generation = 0
|
||||||
else:
|
else:
|
||||||
generation = int((radius - self.center)/PIXELS_PER_GENERATION) + 1
|
generation = int((radius - CENTER)/PIXELS_PER_GENERATION) + 1
|
||||||
|
|
||||||
rads = math.atan2( (cury - cy), (curx - cx) )
|
rads = math.atan2( (cury - cy), (curx - cx) )
|
||||||
if rads < 0: # second half of unit circle
|
if rads < 0: # second half of unit circle
|
||||||
@ -1131,7 +1173,14 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
self.translating = False
|
self.translating = False
|
||||||
alloc = self.get_allocation()
|
alloc = self.get_allocation()
|
||||||
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
||||||
|
if self.form == FORM_CIRCLE:
|
||||||
self.center_xy = w/2 - event.x, h/2 - event.y
|
self.center_xy = w/2 - event.x, h/2 - event.y
|
||||||
|
self.center_xy = w/2 - event.x, h/2 - event.y
|
||||||
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
|
self.center_xy = w/2 - event.x, h - CENTER - PAD_PX - event.y
|
||||||
|
elif self.form == FORM_QUADRANT:
|
||||||
|
self.center_xy = CENTER + PAD_PX - event.x, h - CENTER - PAD_PX - event.y
|
||||||
|
|
||||||
self.last_x, self.last_y = None, None
|
self.last_x, self.last_y = None, None
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
return True
|
return True
|
||||||
@ -1202,6 +1251,7 @@ class FanChartGrampsGUI(object):
|
|||||||
self.grad_end = '#FF0000'
|
self.grad_end = '#FF0000'
|
||||||
self.generic_filter = None # the filter to use. Named as in PageView
|
self.generic_filter = None # the filter to use. Named as in PageView
|
||||||
self.alpha_filter = 0.2 # transparency of filtered out values
|
self.alpha_filter = 0.2 # transparency of filtered out values
|
||||||
|
self.form = FORM_HALFCIRCLE
|
||||||
|
|
||||||
def set_fan(self, fan):
|
def set_fan(self, fan):
|
||||||
"""
|
"""
|
||||||
@ -1220,7 +1270,7 @@ class FanChartGrampsGUI(object):
|
|||||||
self.fan.reset(root_person_handle, self.maxgen, self.background, self.childring,
|
self.fan.reset(root_person_handle, self.maxgen, self.background, self.childring,
|
||||||
self.radialtext, self.fonttype,
|
self.radialtext, self.fonttype,
|
||||||
self.grad_start, self.grad_end,
|
self.grad_start, self.grad_end,
|
||||||
self.generic_filter, self.alpha_filter)
|
self.generic_filter, self.alpha_filter, self.form)
|
||||||
self.fan.queue_draw()
|
self.fan.queue_draw()
|
||||||
|
|
||||||
def on_popup(self, obj, event, person_handle):
|
def on_popup(self, obj, event, person_handle):
|
||||||
|
@ -58,10 +58,11 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView):
|
|||||||
#settings in the config file
|
#settings in the config file
|
||||||
CONFIGSETTINGS = (
|
CONFIGSETTINGS = (
|
||||||
('interface.fanview-maxgen', 9),
|
('interface.fanview-maxgen', 9),
|
||||||
('interface.fanview-background', 4),
|
('interface.fanview-background', fanchart.BACKGROUND_GRAD_GEN),
|
||||||
('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.fanview-form', fanchart.FORM_CIRCLE),
|
||||||
('interface.color-start-grad', '#ef2929'),
|
('interface.color-start-grad', '#ef2929'),
|
||||||
('interface.color-end-grad', '#3d37e9'),
|
('interface.color-end-grad', '#3d37e9'),
|
||||||
)
|
)
|
||||||
@ -84,6 +85,7 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView):
|
|||||||
|
|
||||||
self.grad_start = self._config.get('interface.color-start-grad')
|
self.grad_start = self._config.get('interface.color-start-grad')
|
||||||
self.grad_end = self._config.get('interface.color-end-grad')
|
self.grad_end = self._config.get('interface.color-end-grad')
|
||||||
|
self.form = self._config.get('interface.fanview-form')
|
||||||
|
|
||||||
dbstate.connect('active-changed', self.active_changed)
|
dbstate.connect('active-changed', self.active_changed)
|
||||||
dbstate.connect('database-changed', self.change_db)
|
dbstate.connect('database-changed', self.change_db)
|
||||||
@ -298,6 +300,12 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView):
|
|||||||
'interface.color-start-grad', col=1)
|
'interface.color-start-grad', col=1)
|
||||||
configdialog.add_color(table, _('End gradient/2nd color'), 4,
|
configdialog.add_color(table, _('End gradient/2nd color'), 4,
|
||||||
'interface.color-end-grad', col=1)
|
'interface.color-end-grad', col=1)
|
||||||
|
# form of the fan
|
||||||
|
configdialog.add_combo(table, _('Fan chart type'), 5,
|
||||||
|
'interface.fanview-form',
|
||||||
|
((0, _('Full Circle')), (1,_('Half Circle')),
|
||||||
|
(2, _('Quadrant'))),
|
||||||
|
callback=self.cb_update_form)
|
||||||
|
|
||||||
# options users should not change:
|
# options users should not change:
|
||||||
configdialog.add_checkbox(table,
|
configdialog.add_checkbox(table,
|
||||||
@ -339,6 +347,12 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView):
|
|||||||
self.background = val
|
self.background = val
|
||||||
self.update()
|
self.update()
|
||||||
|
|
||||||
|
def cb_update_form(self, obj, constant):
|
||||||
|
entry = obj.get_active()
|
||||||
|
self._config.set(constant, entry)
|
||||||
|
self.form = entry
|
||||||
|
self.update()
|
||||||
|
|
||||||
def cb_update_childrenring(self, client, cnxn_id, entry, data):
|
def cb_update_childrenring(self, client, cnxn_id, entry, data):
|
||||||
"""
|
"""
|
||||||
Called when the configuration menu changes the childrenring setting.
|
Called when the configuration menu changes the childrenring setting.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user