Fanchart: code cleanup, translate only on black dot, drag of center person possible

svn: r20267
This commit is contained in:
Benny Malengier 2012-08-26 19:56:44 +00:00
parent c1fd5d258a
commit 2031f90e12

View File

@ -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
@ -233,7 +233,7 @@ class FanChartWidget(Gtk.DrawingArea):
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,12 +454,12 @@ 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:
@ -492,24 +472,32 @@ class FanChartWidget(Gtk.DrawingArea):
# 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.queue_draw()
self.last_x, self.last_y = event.x, event.y self.last_x, self.last_y = event.x, event.y
self.queue_draw()
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):
if self.data[0][0][1]:
self.context_popup_callback(widget, event,
self.data[0][0][1].handle)
return True
else:
return False
# else, what to do on left click?
else:
# save the mouse location for movements # save the mouse location for movements
self.last_x, self.last_y = event.x, event.y self.last_x, self.last_y = event.x, event.y
return True return True
# Do things based on state, event.get_state(), or button, event.button
if event.button == 1: # left mouse #left click on person, prepare for expand/collapse or drag
if event.button == 1:
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