Fanchart: code cleanup, translate only on black dot, drag of center person possible
svn: r20267
This commit is contained in:
parent
c1fd5d258a
commit
2031f90e12
@ -80,7 +80,7 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
(191,222,252),
|
(191,222,252),
|
||||||
(183,219,197),
|
(183,219,197),
|
||||||
(206,246,209))
|
(206,246,209))
|
||||||
|
TRANSLATE_PX = 10
|
||||||
COLLAPSED = 0
|
COLLAPSED = 0
|
||||||
NORMAL = 1
|
NORMAL = 1
|
||||||
EXPANDED = 2
|
EXPANDED = 2
|
||||||
@ -232,8 +232,8 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
cr.restore()
|
cr.restore()
|
||||||
if child: # has at least one child
|
if child: # has at least one child
|
||||||
cr.set_source_rgb(0, 0, 0) # black
|
cr.set_source_rgb(0, 0, 0) # black
|
||||||
cr.move_to(0,0)
|
cr.move_to(0, 0)
|
||||||
cr.arc(0, 0, 10, 0, 2 * math.pi)
|
cr.arc(0, 0, self.TRANSLATE_PX, 0, 2 * math.pi)
|
||||||
cr.move_to(0,0)
|
cr.move_to(0,0)
|
||||||
cr.fill()
|
cr.fill()
|
||||||
fontw, fonth = self.layout.get_pixel_size()
|
fontw, fonth = self.layout.get_pixel_size()
|
||||||
@ -393,6 +393,8 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
self.shrink_parents(generation + 1, selected+1, current)
|
self.shrink_parents(generation + 1, selected+1, current)
|
||||||
|
|
||||||
def change_slice(self, generation, selected):
|
def change_slice(self, generation, selected):
|
||||||
|
if generation < 1:
|
||||||
|
return
|
||||||
gstart, gstop, gmale, gstate = self.angle[generation][selected]
|
gstart, gstop, gmale, gstate = self.angle[generation][selected]
|
||||||
if gstate == self.NORMAL: # let's expand
|
if gstate == self.NORMAL: # let's expand
|
||||||
if gmale:
|
if gmale:
|
||||||
@ -442,30 +444,8 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
def on_mouse_move(self, widget, event):
|
def on_mouse_move(self, widget, event):
|
||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
if self.last_x is None or self.last_y is None:
|
if self.last_x is None or self.last_y is None:
|
||||||
alloc = self.get_allocation()
|
# while mouse is moving, we must update the tooltip based on person
|
||||||
x, y, w, h = alloc.x, alloc.y, alloc.width, alloc.height
|
generation, selected = self.person_under_cursor(event.x, event.y)
|
||||||
cx = w/2 - self.center_xy[0]
|
|
||||||
cy = h/2 - self.center_xy[1]
|
|
||||||
radius = math.sqrt((event.x - cx) ** 2 + (event.y - cy) ** 2)
|
|
||||||
selected = None
|
|
||||||
if radius < self.center:
|
|
||||||
generation = 0
|
|
||||||
selected = 0
|
|
||||||
else:
|
|
||||||
generation = int((radius - self.center) /
|
|
||||||
self.pixels_per_generation) + 1
|
|
||||||
rads = math.atan2( (event.y - cy), (event.x - cx) )
|
|
||||||
if rads < 0: # second half of unit circle
|
|
||||||
rads = math.pi + (math.pi + rads)
|
|
||||||
pos = ((rads/(math.pi * 2) - self.rotate_value/360.) * 360.0) % 360
|
|
||||||
if (0 < generation < self.generations):
|
|
||||||
for p in range(len(self.angle[generation])):
|
|
||||||
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
|
|
||||||
tooltip = ""
|
tooltip = ""
|
||||||
if selected is not None:
|
if selected is not None:
|
||||||
text, person, parents, child = self.data[generation][selected]
|
text, person, parents, child = self.data[generation][selected]
|
||||||
@ -474,42 +454,50 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
self.set_tooltip_text(tooltip)
|
self.set_tooltip_text(tooltip)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
#translate or rotate should happen
|
||||||
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:
|
||||||
self.center_xy = w/2 - event.x, h/2 - event.y
|
self.center_xy = w/2 - event.x, h/2 - event.y
|
||||||
self.queue_draw()
|
else:
|
||||||
return True
|
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]
|
# get the angles of the two points from the center:
|
||||||
# get the angles of the two points from the center:
|
start_angle = math.atan2(event.y - cy, event.x - cx)
|
||||||
start_angle = math.atan2(event.y - cy, event.x - cx)
|
end_angle = math.atan2(self.last_y - cy, self.last_x - cx)
|
||||||
end_angle = math.atan2(self.last_y - cy, self.last_x - cx)
|
if start_angle < 0: # second half of unit circle
|
||||||
if start_angle < 0: # second half of unit circle
|
start_angle = math.pi + (math.pi + start_angle)
|
||||||
start_angle = math.pi + (math.pi + start_angle)
|
if end_angle < 0: # second half of unit circle
|
||||||
if end_angle < 0: # second half of unit circle
|
end_angle = math.pi + (math.pi + end_angle)
|
||||||
end_angle = math.pi + (math.pi + end_angle)
|
# now look at change in angle:
|
||||||
# now look at change in angle:
|
diff_angle = (end_angle - start_angle) % (math.pi * 2.0)
|
||||||
diff_angle = (end_angle - start_angle) % (math.pi * 2.0)
|
self.rotate_value -= diff_angle * 180.0/ math.pi
|
||||||
self.rotate_value -= diff_angle * 180.0/ math.pi
|
self.last_x, self.last_y = event.x, event.y
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
self.last_x, self.last_y = event.x, event.y
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_mouse_down(self, widget, event):
|
def person_under_cursor(self, curx, cury):
|
||||||
|
"""
|
||||||
|
Determine the generation and the position in the generation at
|
||||||
|
position x and y.
|
||||||
|
generation = -1 on center black dot
|
||||||
|
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()
|
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
|
||||||
self.translating = False # keep track of up/down/left/right movement
|
|
||||||
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]
|
||||||
radius = math.sqrt((event.x - cx) ** 2 + (event.y - cy) ** 2)
|
radius = math.sqrt((curx - cx) ** 2 + (cury - cy) ** 2)
|
||||||
if radius < self.center:
|
if radius < self.TRANSLATE_PX:
|
||||||
|
generation = -1
|
||||||
|
elif radius < self.center:
|
||||||
generation = 0
|
generation = 0
|
||||||
else:
|
else:
|
||||||
generation = int((radius - self.center) /
|
generation = int((radius - self.center) /
|
||||||
self.pixels_per_generation) + 1
|
self.pixels_per_generation) + 1
|
||||||
rads = math.atan2( (event.y - cy), (event.x - cx) )
|
|
||||||
|
rads = math.atan2( (cury - cy), (curx - cx) )
|
||||||
if rads < 0: # second half of unit circle
|
if rads < 0: # second half of unit circle
|
||||||
rads = math.pi + (math.pi + rads)
|
rads = math.pi + (math.pi + rads)
|
||||||
pos = ((rads/(math.pi * 2) - self.rotate_value/360.) * 360.0) % 360
|
pos = ((rads/(math.pi * 2) - self.rotate_value/360.) * 360.0) % 360
|
||||||
@ -525,51 +513,54 @@ class FanChartWidget(Gtk.DrawingArea):
|
|||||||
if start <= pos <= stop:
|
if start <= pos <= stop:
|
||||||
selected = p
|
selected = p
|
||||||
break
|
break
|
||||||
# Handle the click:
|
elif generation == 0:
|
||||||
if generation == 0:
|
selected = 0
|
||||||
# left mouse on center:
|
return generation, selected
|
||||||
|
|
||||||
|
def on_mouse_down(self, widget, event):
|
||||||
|
self.translating = False # keep track of up/down/left/right movement
|
||||||
|
generation, selected = self.person_under_cursor(event.x, event.y)
|
||||||
|
|
||||||
|
# left mouse on center dot, we translate on left click
|
||||||
|
if generation == -1:
|
||||||
if event.button == 1: # left mouse
|
if event.button == 1: # left mouse
|
||||||
# save the mouse location for movements
|
# save the mouse location for movements
|
||||||
self.translating = True
|
self.translating = True
|
||||||
self.last_x, self.last_y = event.x, event.y
|
self.last_x, self.last_y = event.x, event.y
|
||||||
return True
|
return True
|
||||||
if selected is None: # clicked in open area, or center
|
|
||||||
if radius < self.center:
|
#click in open area, prepare for a rotate
|
||||||
# right mouse
|
if selected is None:
|
||||||
if gui.utils.is_right_click(event):
|
# save the mouse location for movements
|
||||||
if self.data[0][0][1]:
|
self.last_x, self.last_y = event.x, event.y
|
||||||
self.context_popup_callback(widget, event,
|
return True
|
||||||
self.data[0][0][1].handle)
|
|
||||||
return True
|
#left click on person, prepare for expand/collapse or drag
|
||||||
else:
|
if event.button == 1:
|
||||||
return False
|
|
||||||
# else, what to do on left click?
|
|
||||||
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.get_state(), or button, event.button
|
|
||||||
if event.button == 1: # left mouse
|
|
||||||
self._mouse_click = True
|
self._mouse_click = True
|
||||||
self._mouse_click_gen = generation
|
self._mouse_click_gen = generation
|
||||||
self._mouse_click_sel = selected
|
self._mouse_click_sel = selected
|
||||||
return False
|
return False
|
||||||
elif gui.utils.is_right_click(event):
|
|
||||||
|
#right click on person, context menu
|
||||||
|
# Do things based on state, event.get_state(), or button, event.button
|
||||||
|
if gui.utils.is_right_click(event):
|
||||||
text, person, parents, child = self.data[generation][selected]
|
text, person, parents, child = self.data[generation][selected]
|
||||||
if person and self.context_popup_callback:
|
if person and self.context_popup_callback:
|
||||||
self.context_popup_callback(widget, event, person.handle)
|
self.context_popup_callback(widget, event, person.handle)
|
||||||
return True
|
return True
|
||||||
self.queue_draw()
|
|
||||||
return True
|
return False
|
||||||
|
|
||||||
def on_mouse_up(self, widget, event):
|
def on_mouse_up(self, widget, event):
|
||||||
# Done with mouse movement
|
|
||||||
if self._mouse_click:
|
if self._mouse_click:
|
||||||
|
# no drag occured, expand or collapse the section
|
||||||
self.change_slice(self._mouse_click_gen, self._mouse_click_sel)
|
self.change_slice(self._mouse_click_gen, self._mouse_click_sel)
|
||||||
self._mouse_click = False
|
self._mouse_click = False
|
||||||
self.queue_draw()
|
self.queue_draw()
|
||||||
return True
|
return True
|
||||||
if self.last_x is None or self.last_y is None:
|
if self.last_x is None or self.last_y is None:
|
||||||
|
# No translate or rotate
|
||||||
return True
|
return True
|
||||||
if self.translating:
|
if self.translating:
|
||||||
self.translating = False
|
self.translating = False
|
||||||
|
Loading…
Reference in New Issue
Block a user