Fix Fan charts for scrolling/resizing of window; bad rendering (#572)
Fixes #10381
This commit is contained in:
parent
babe13f811
commit
ae11eceef7
@ -120,6 +120,7 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
|||||||
self.dbstate = dbstate
|
self.dbstate = dbstate
|
||||||
self.uistate = uistate
|
self.uistate = uistate
|
||||||
self.translating = False
|
self.translating = False
|
||||||
|
self.surface = None
|
||||||
self.goto = None
|
self.goto = None
|
||||||
self.on_popup = callback_popup
|
self.on_popup = callback_popup
|
||||||
self.last_x, self.last_y = None, None
|
self.last_x, self.last_y = None, None
|
||||||
@ -248,7 +249,15 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
|||||||
"""
|
"""
|
||||||
callback to draw the fanchart
|
callback to draw the fanchart
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
if self.surface:
|
||||||
|
cr.set_source_surface(self.surface, 0, 0)
|
||||||
|
cr.paint()
|
||||||
|
|
||||||
|
def prt_draw(self, widget, cr, scale=1.0):
|
||||||
|
"""
|
||||||
|
method to allow direct drawing to cairo context for printing
|
||||||
|
"""
|
||||||
|
self.draw(cr=cr, scale=scale)
|
||||||
|
|
||||||
def people_generator(self):
|
def people_generator(self):
|
||||||
"""
|
"""
|
||||||
@ -749,7 +758,7 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
|||||||
return lambda x, y: \
|
return lambda x, y: \
|
||||||
(rho(y) * math.cos(phi(x)), rho(y) * math.sin(phi(x)))
|
(rho(y) * math.cos(phi(x)), rho(y) * math.sin(phi(x)))
|
||||||
|
|
||||||
def draw_gradient_legend(self, cr, widget, halfdist):
|
def draw_gradient_legend(self, cr, halfdist):
|
||||||
gradwidth = 10
|
gradwidth = 10
|
||||||
gradheight = 10
|
gradheight = 10
|
||||||
starth = 15
|
starth = 15
|
||||||
@ -924,6 +933,7 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
|||||||
diff_angle = (end_angle - start_angle) % (math.pi * 2.0)
|
diff_angle = (end_angle - start_angle) % (math.pi * 2.0)
|
||||||
self.rotate_value -= math.degrees(diff_angle)
|
self.rotate_value -= math.degrees(diff_angle)
|
||||||
self.last_x, self.last_y = event.x, event.y
|
self.last_x, self.last_y = event.x, event.y
|
||||||
|
self.draw()
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -954,8 +964,12 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
|||||||
return True
|
return True
|
||||||
if self.translating:
|
if self.translating:
|
||||||
self.translating = False
|
self.translating = False
|
||||||
|
else:
|
||||||
|
self.center_delta_xy = -1, 0
|
||||||
|
self.center_xy = self.center_xy_from_delta()
|
||||||
|
|
||||||
self.last_x, self.last_y = None, None
|
self.last_x, self.last_y = None, None
|
||||||
|
self.draw()
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
@ -1207,27 +1221,39 @@ class FanChartWidget(FanChartBaseWidget):
|
|||||||
(person, parents, child, userdata) = childdata
|
(person, parents, child, userdata) = childdata
|
||||||
yield (person, userdata)
|
yield (person, userdata)
|
||||||
|
|
||||||
def on_draw(self, widget, cr, scale=1.):
|
def draw(self, cr=None, scale=1.0):
|
||||||
"""
|
"""
|
||||||
The main method to do the drawing.
|
The main method to do the drawing.
|
||||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||||
To draw raw on the cairo context cr, set widget=None.
|
To draw in GTK3 and use the allocation, set cr=None.
|
||||||
|
Note: when drawing for display, to counter a Gtk issue with scrolling
|
||||||
|
or resizing the drawing window, we draw on a surface, then copy to the
|
||||||
|
drawing context when the Gtk 'draw' signal arrives.
|
||||||
"""
|
"""
|
||||||
# first do size request of what we will need
|
# first do size request of what we will need
|
||||||
halfdist = self.halfdist()
|
halfdist = self.halfdist()
|
||||||
if widget:
|
if not cr: # Display
|
||||||
if self.form == FORM_CIRCLE:
|
if self.form == FORM_CIRCLE:
|
||||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
size_w = size_h = 2 * halfdist
|
||||||
elif self.form == FORM_HALFCIRCLE:
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
self.set_size_request(2 * halfdist, halfdist + self.CENTER + PAD_PX)
|
size_w = 2 * halfdist
|
||||||
|
size_h = halfdist + self.CENTER + PAD_PX
|
||||||
elif self.form == FORM_QUADRANT:
|
elif self.form == FORM_QUADRANT:
|
||||||
self.set_size_request(halfdist + self.CENTER + PAD_PX, halfdist + self.CENTER + PAD_PX)
|
size_w = size_h = halfdist + self.CENTER + PAD_PX
|
||||||
|
|
||||||
cr.scale(scale, scale)
|
size_w_a = self.get_allocated_width()
|
||||||
if widget:
|
size_h_a = self.get_allocated_height()
|
||||||
|
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
|
||||||
|
size_w = self.get_allocated_width()
|
||||||
|
size_h = self.get_allocated_height()
|
||||||
|
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
|
||||||
|
size_w, size_h)
|
||||||
|
cr = cairo.Context(self.surface)
|
||||||
self.center_xy = self.center_xy_from_delta()
|
self.center_xy = self.center_xy_from_delta()
|
||||||
cr.translate(*self.center_xy)
|
cr.translate(*self.center_xy)
|
||||||
else:
|
else: # printing
|
||||||
|
self.center_xy = halfdist, halfdist
|
||||||
|
cr.scale(scale, scale)
|
||||||
cr.translate(halfdist, halfdist)
|
cr.translate(halfdist, halfdist)
|
||||||
|
|
||||||
cr.save()
|
cr.save()
|
||||||
@ -1262,7 +1288,7 @@ class FanChartWidget(FanChartBaseWidget):
|
|||||||
if child and self.childring:
|
if child and self.childring:
|
||||||
self.draw_childring(cr)
|
self.draw_childring(cr)
|
||||||
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
||||||
self.draw_gradient_legend(cr, widget, halfdist)
|
self.draw_gradient_legend(cr, halfdist)
|
||||||
|
|
||||||
def draw_childring(self, cr):
|
def draw_childring(self, cr):
|
||||||
cr.move_to(TRANSLATE_PX + CHILDRING_WIDTH, 0)
|
cr.move_to(TRANSLATE_PX + CHILDRING_WIDTH, 0)
|
||||||
@ -1460,6 +1486,7 @@ class FanChartWidget(FanChartBaseWidget):
|
|||||||
# no drag occured, expand or collapse the section
|
# no drag occured, expand or collapse the section
|
||||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
|
self.draw()
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
class FanChartGrampsGUI:
|
class FanChartGrampsGUI:
|
||||||
@ -1494,6 +1521,7 @@ class FanChartGrampsGUI:
|
|||||||
self.grad_start, self.grad_end,
|
self.grad_start, self.grad_end,
|
||||||
self.generic_filter, self.alpha_filter, self.form)
|
self.generic_filter, self.alpha_filter, self.form)
|
||||||
self.fan.reset()
|
self.fan.reset()
|
||||||
|
self.fan.draw()
|
||||||
self.fan.queue_draw()
|
self.fan.queue_draw()
|
||||||
|
|
||||||
def on_popup(self, obj, event, person_handle, family_handle=None):
|
def on_popup(self, obj, event, person_handle, family_handle=None):
|
||||||
|
@ -359,23 +359,33 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
|||||||
cr.fill()
|
cr.fill()
|
||||||
cr.restore()
|
cr.restore()
|
||||||
|
|
||||||
|
def draw(self, cr=None, scale=1.0):
|
||||||
def on_draw(self, widget, cr, scale=1.):
|
|
||||||
"""
|
"""
|
||||||
The main method to do the drawing.
|
The main method to do the drawing.
|
||||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||||
To draw raw on the cairo context cr, set widget=None.
|
To draw in GTK3 and use the allocation, set cr=None.
|
||||||
|
Note: when drawing for display, to counter a Gtk issue with scrolling
|
||||||
|
or resizing the drawing window, we draw on a surface, then copy to the
|
||||||
|
drawing context when the Gtk 'draw' signal arrives.
|
||||||
"""
|
"""
|
||||||
# first do size request of what we will need
|
# first do size request of what we will need
|
||||||
halfdist = self.halfdist()
|
halfdist = self.halfdist()
|
||||||
if widget:
|
if not cr: # Display
|
||||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
size_w = size_h = 2 * halfdist
|
||||||
|
|
||||||
cr.scale(scale, scale)
|
size_w_a = self.get_allocated_width()
|
||||||
if widget:
|
size_h_a = self.get_allocated_height()
|
||||||
|
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
|
||||||
|
size_w = self.get_allocated_width()
|
||||||
|
size_h = self.get_allocated_height()
|
||||||
|
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
|
||||||
|
size_w, size_h)
|
||||||
|
cr = cairo.Context(self.surface)
|
||||||
self.center_xy = self.center_xy_from_delta()
|
self.center_xy = self.center_xy_from_delta()
|
||||||
cr.translate(*self.center_xy)
|
cr.translate(*self.center_xy)
|
||||||
else:
|
else: # printing
|
||||||
|
self.center_xy = halfdist, halfdist
|
||||||
|
cr.scale(scale, scale)
|
||||||
cr.translate(halfdist, halfdist)
|
cr.translate(halfdist, halfdist)
|
||||||
|
|
||||||
cr.save()
|
cr.save()
|
||||||
@ -444,7 +454,7 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
|||||||
cr.restore()
|
cr.restore()
|
||||||
|
|
||||||
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
||||||
self.draw_gradient_legend(cr, widget, halfdist)
|
self.draw_gradient_legend(cr, halfdist)
|
||||||
|
|
||||||
def cell_address_under_cursor(self, curx, cury):
|
def cell_address_under_cursor(self, curx, cury):
|
||||||
"""
|
"""
|
||||||
@ -542,6 +552,7 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
|||||||
# no drag occured, expand or collapse the section
|
# no drag occured, expand or collapse the section
|
||||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
|
self.draw()
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def expand_parents(self, generation, selected, current):
|
def expand_parents(self, generation, selected, current):
|
||||||
@ -624,4 +635,5 @@ class FanChart2WayGrampsGUI(FanChartGrampsGUI):
|
|||||||
self.generic_filter, self.alpha_filter,
|
self.generic_filter, self.alpha_filter,
|
||||||
self.angle_algo, self.dupcolor)
|
self.angle_algo, self.dupcolor)
|
||||||
self.fan.reset()
|
self.fan.reset()
|
||||||
|
self.fan.draw()
|
||||||
self.fan.queue_draw()
|
self.fan.queue_draw()
|
||||||
|
@ -404,29 +404,40 @@ class FanChartDescWidget(FanChartBaseWidget):
|
|||||||
parent, userdata = parentdata
|
parent, userdata = parentdata
|
||||||
yield (parent, userdata)
|
yield (parent, userdata)
|
||||||
|
|
||||||
def on_draw(self, widget, cr, scale=1.):
|
def draw(self, cr=None, scale=1.0):
|
||||||
"""
|
"""
|
||||||
The main method to do the drawing.
|
The main method to do the drawing.
|
||||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||||
To draw raw on the cairo context cr, set widget=None.
|
To draw in GTK3 and use the allocation, set cr=None.
|
||||||
|
Note: when drawing for display, to counter a Gtk issue with scrolling
|
||||||
|
or resizing the drawing window, we draw on a surface, then copy to the
|
||||||
|
drawing context when the Gtk 'draw' signal arrives.
|
||||||
"""
|
"""
|
||||||
# first do size request of what we will need
|
# first do size request of what we will need
|
||||||
halfdist = self.halfdist()
|
halfdist = self.halfdist()
|
||||||
if widget:
|
if not cr: # Display
|
||||||
if self.form == FORM_CIRCLE:
|
if self.form == FORM_CIRCLE:
|
||||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
size_w = size_h = 2 * halfdist
|
||||||
elif self.form == FORM_HALFCIRCLE:
|
elif self.form == FORM_HALFCIRCLE:
|
||||||
self.set_size_request(2 * halfdist, halfdist + self.CENTER
|
size_w = 2 * halfdist
|
||||||
+ PAD_PX)
|
size_h = halfdist + self.CENTER + PAD_PX
|
||||||
elif self.form == FORM_QUADRANT:
|
elif self.form == FORM_QUADRANT:
|
||||||
self.set_size_request(halfdist + self.CENTER + PAD_PX,
|
size_w = size_h = halfdist + self.CENTER + PAD_PX
|
||||||
halfdist + self.CENTER + PAD_PX)
|
|
||||||
|
|
||||||
cr.scale(scale, scale)
|
size_w_a = self.get_allocated_width()
|
||||||
# when printing, we need not recalculate
|
size_h_a = self.get_allocated_height()
|
||||||
if widget:
|
self.set_size_request(max(size_w, size_w_a), max(size_h, size_h_a))
|
||||||
|
size_w = self.get_allocated_width()
|
||||||
|
size_h = self.get_allocated_height()
|
||||||
|
self.surface = cairo.ImageSurface(cairo.FORMAT_ARGB32,
|
||||||
|
size_w, size_h)
|
||||||
|
cr = cairo.Context(self.surface)
|
||||||
self.center_xy = self.center_xy_from_delta()
|
self.center_xy = self.center_xy_from_delta()
|
||||||
cr.translate(*self.center_xy)
|
cr.translate(*self.center_xy)
|
||||||
|
else: # printing
|
||||||
|
self.center_xy = halfdist, halfdist
|
||||||
|
cr.scale(scale, scale)
|
||||||
|
cr.translate(halfdist, halfdist)
|
||||||
|
|
||||||
cr.save()
|
cr.save()
|
||||||
# Draw center person:
|
# Draw center person:
|
||||||
@ -477,7 +488,7 @@ class FanChartDescWidget(FanChartBaseWidget):
|
|||||||
cr.restore()
|
cr.restore()
|
||||||
|
|
||||||
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
if self.background in [BACKGROUND_GRAD_AGE, BACKGROUND_GRAD_PERIOD]:
|
||||||
self.draw_gradient_legend(cr, widget, halfdist)
|
self.draw_gradient_legend(cr, halfdist)
|
||||||
|
|
||||||
def cell_address_under_cursor(self, curx, cury):
|
def cell_address_under_cursor(self, curx, cury):
|
||||||
"""
|
"""
|
||||||
@ -595,6 +606,7 @@ class FanChartDescWidget(FanChartBaseWidget):
|
|||||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||||
self._compute_angles(*self.rootangle_rad)
|
self._compute_angles(*self.rootangle_rad)
|
||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
|
self.draw()
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
|
|
||||||
def toggle_cell_state(self, cell_address):
|
def toggle_cell_state(self, cell_address):
|
||||||
@ -647,4 +659,5 @@ class FanChartDescGrampsGUI(FanChartGrampsGUI):
|
|||||||
self.generic_filter, self.alpha_filter, self.form,
|
self.generic_filter, self.alpha_filter, self.form,
|
||||||
self.angle_algo, self.dupcolor)
|
self.angle_algo, self.dupcolor)
|
||||||
self.fan.reset()
|
self.fan.reset()
|
||||||
|
self.fan.draw()
|
||||||
self.fan.queue_draw()
|
self.fan.queue_draw()
|
||||||
|
@ -256,7 +256,8 @@ class FanChart2WayView(fanchart2way.FanChart2WayGrampsGUI, NavigationView):
|
|||||||
widthpx = 2 * self.fan.halfdist()
|
widthpx = 2 * self.fan.halfdist()
|
||||||
heightpx = widthpx
|
heightpx = widthpx
|
||||||
|
|
||||||
prt = CairoPrintSave(widthpx, heightpx, self.fan.on_draw, self.uistate.window)
|
prt = CairoPrintSave(widthpx, heightpx, self.fan.prt_draw,
|
||||||
|
self.uistate.window)
|
||||||
prt.run()
|
prt.run()
|
||||||
|
|
||||||
def on_childmenu_changed(self, obj, person_handle):
|
def on_childmenu_changed(self, obj, person_handle):
|
||||||
|
@ -256,7 +256,8 @@ class FanChartDescView(fanchartdesc.FanChartDescGrampsGUI, NavigationView):
|
|||||||
heightpx = heightpx / 2 + self.fan.CENTER + fanchart.PAD_PX
|
heightpx = heightpx / 2 + self.fan.CENTER + fanchart.PAD_PX
|
||||||
widthpx = heightpx
|
widthpx = heightpx
|
||||||
|
|
||||||
prt = CairoPrintSave(widthpx, heightpx, self.fan.on_draw, self.uistate.window)
|
prt = CairoPrintSave(widthpx, heightpx, self.fan.prt_draw,
|
||||||
|
self.uistate.window)
|
||||||
prt.run()
|
prt.run()
|
||||||
|
|
||||||
def on_childmenu_changed(self, obj, person_handle):
|
def on_childmenu_changed(self, obj, person_handle):
|
||||||
|
@ -252,7 +252,8 @@ class FanChartView(fanchart.FanChartGrampsGUI, NavigationView):
|
|||||||
heightpx = heightpx / 2 + self.fan.CENTER + fanchart.PAD_PX
|
heightpx = heightpx / 2 + self.fan.CENTER + fanchart.PAD_PX
|
||||||
widthpx = heightpx
|
widthpx = heightpx
|
||||||
|
|
||||||
prt = CairoPrintSave(widthpx, heightpx, self.fan.on_draw, self.uistate.window)
|
prt = CairoPrintSave(widthpx, heightpx, self.fan.prt_draw,
|
||||||
|
self.uistate.window)
|
||||||
prt.run()
|
prt.run()
|
||||||
|
|
||||||
def on_childmenu_changed(self, obj, person_handle):
|
def on_childmenu_changed(self, obj, person_handle):
|
||||||
|
Loading…
Reference in New Issue
Block a user