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.uistate = uistate
|
||||
self.translating = False
|
||||
self.surface = None
|
||||
self.goto = None
|
||||
self.on_popup = callback_popup
|
||||
self.last_x, self.last_y = None, None
|
||||
@ -248,7 +249,15 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
||||
"""
|
||||
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):
|
||||
"""
|
||||
@ -749,7 +758,7 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
||||
return lambda x, y: \
|
||||
(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
|
||||
gradheight = 10
|
||||
starth = 15
|
||||
@ -924,6 +933,7 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
||||
diff_angle = (end_angle - start_angle) % (math.pi * 2.0)
|
||||
self.rotate_value -= math.degrees(diff_angle)
|
||||
self.last_x, self.last_y = event.x, event.y
|
||||
self.draw()
|
||||
self.queue_draw()
|
||||
return True
|
||||
|
||||
@ -954,8 +964,12 @@ class FanChartBaseWidget(Gtk.DrawingArea):
|
||||
return True
|
||||
if self.translating:
|
||||
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.draw()
|
||||
self.queue_draw()
|
||||
return True
|
||||
|
||||
@ -1207,27 +1221,39 @@ class FanChartWidget(FanChartBaseWidget):
|
||||
(person, parents, child, userdata) = childdata
|
||||
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.
|
||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
||||
To draw raw on the cairo context cr, set widget=None.
|
||||
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||
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
|
||||
halfdist = self.halfdist()
|
||||
if widget:
|
||||
if not cr: # Display
|
||||
if self.form == FORM_CIRCLE:
|
||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
||||
size_w = size_h = 2 * halfdist
|
||||
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:
|
||||
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)
|
||||
if widget:
|
||||
size_w_a = self.get_allocated_width()
|
||||
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()
|
||||
cr.translate(*self.center_xy)
|
||||
else:
|
||||
else: # printing
|
||||
self.center_xy = halfdist, halfdist
|
||||
cr.scale(scale, scale)
|
||||
cr.translate(halfdist, halfdist)
|
||||
|
||||
cr.save()
|
||||
@ -1262,7 +1288,7 @@ class FanChartWidget(FanChartBaseWidget):
|
||||
if child and self.childring:
|
||||
self.draw_childring(cr)
|
||||
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):
|
||||
cr.move_to(TRANSLATE_PX + CHILDRING_WIDTH, 0)
|
||||
@ -1460,6 +1486,7 @@ class FanChartWidget(FanChartBaseWidget):
|
||||
# no drag occured, expand or collapse the section
|
||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||
self._mouse_click = False
|
||||
self.draw()
|
||||
self.queue_draw()
|
||||
|
||||
class FanChartGrampsGUI:
|
||||
@ -1494,6 +1521,7 @@ class FanChartGrampsGUI:
|
||||
self.grad_start, self.grad_end,
|
||||
self.generic_filter, self.alpha_filter, self.form)
|
||||
self.fan.reset()
|
||||
self.fan.draw()
|
||||
self.fan.queue_draw()
|
||||
|
||||
def on_popup(self, obj, event, person_handle, family_handle=None):
|
||||
|
@ -359,23 +359,33 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
||||
cr.fill()
|
||||
cr.restore()
|
||||
|
||||
|
||||
def on_draw(self, widget, cr, scale=1.):
|
||||
def draw(self, cr=None, scale=1.0):
|
||||
"""
|
||||
The main method to do the drawing.
|
||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
||||
To draw raw on the cairo context cr, set widget=None.
|
||||
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||
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
|
||||
halfdist = self.halfdist()
|
||||
if widget:
|
||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
||||
if not cr: # Display
|
||||
size_w = size_h = 2 * halfdist
|
||||
|
||||
cr.scale(scale, scale)
|
||||
if widget:
|
||||
size_w_a = self.get_allocated_width()
|
||||
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()
|
||||
cr.translate(*self.center_xy)
|
||||
else:
|
||||
else: # printing
|
||||
self.center_xy = halfdist, halfdist
|
||||
cr.scale(scale, scale)
|
||||
cr.translate(halfdist, halfdist)
|
||||
|
||||
cr.save()
|
||||
@ -444,7 +454,7 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
||||
cr.restore()
|
||||
|
||||
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):
|
||||
"""
|
||||
@ -542,6 +552,7 @@ class FanChart2WayWidget(FanChartWidget, FanChartDescWidget):
|
||||
# no drag occured, expand or collapse the section
|
||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||
self._mouse_click = False
|
||||
self.draw()
|
||||
self.queue_draw()
|
||||
|
||||
def expand_parents(self, generation, selected, current):
|
||||
@ -624,4 +635,5 @@ class FanChart2WayGrampsGUI(FanChartGrampsGUI):
|
||||
self.generic_filter, self.alpha_filter,
|
||||
self.angle_algo, self.dupcolor)
|
||||
self.fan.reset()
|
||||
self.fan.draw()
|
||||
self.fan.queue_draw()
|
||||
|
@ -404,29 +404,40 @@ class FanChartDescWidget(FanChartBaseWidget):
|
||||
parent, userdata = parentdata
|
||||
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.
|
||||
If widget is given, we assume we draw in GTK3 and use the allocation.
|
||||
To draw raw on the cairo context cr, set widget=None.
|
||||
If cr is given, we assume we draw draw raw on the cairo context cr
|
||||
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
|
||||
halfdist = self.halfdist()
|
||||
if widget:
|
||||
if not cr: # Display
|
||||
if self.form == FORM_CIRCLE:
|
||||
self.set_size_request(2 * halfdist, 2 * halfdist)
|
||||
size_w = size_h = 2 * halfdist
|
||||
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:
|
||||
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)
|
||||
# when printing, we need not recalculate
|
||||
if widget:
|
||||
size_w_a = self.get_allocated_width()
|
||||
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()
|
||||
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()
|
||||
# Draw center person:
|
||||
@ -477,7 +488,7 @@ class FanChartDescWidget(FanChartBaseWidget):
|
||||
cr.restore()
|
||||
|
||||
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):
|
||||
"""
|
||||
@ -595,6 +606,7 @@ class FanChartDescWidget(FanChartBaseWidget):
|
||||
self.toggle_cell_state(self._mouse_click_cell_address)
|
||||
self._compute_angles(*self.rootangle_rad)
|
||||
self._mouse_click = False
|
||||
self.draw()
|
||||
self.queue_draw()
|
||||
|
||||
def toggle_cell_state(self, cell_address):
|
||||
@ -647,4 +659,5 @@ class FanChartDescGrampsGUI(FanChartGrampsGUI):
|
||||
self.generic_filter, self.alpha_filter, self.form,
|
||||
self.angle_algo, self.dupcolor)
|
||||
self.fan.reset()
|
||||
self.fan.draw()
|
||||
self.fan.queue_draw()
|
||||
|
@ -256,7 +256,8 @@ class FanChart2WayView(fanchart2way.FanChart2WayGrampsGUI, NavigationView):
|
||||
widthpx = 2 * self.fan.halfdist()
|
||||
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()
|
||||
|
||||
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
|
||||
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()
|
||||
|
||||
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
|
||||
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()
|
||||
|
||||
def on_childmenu_changed(self, obj, person_handle):
|
||||
|
Loading…
Reference in New Issue
Block a user