changeset 1214:e55499f7505a

Fix the issues with multiple framelines - For multiple framelines, user move mouse from one frameline to another, the frame is not showed correctly. - Old implementation always draw normal frame on the frameline where mouse just leaving. - It is fixed by detecting leave-notify event and removing hover mark. - When user active a frame on a frameline that is not what old active frame is at, the old active frame is not deactivated. - It is fixed by calling frameline.deactive() of a frameline when a frame is activated on another frameline.
author Thinker K.F. Li <thinker@codemud.net>
date Wed, 05 Jan 2011 17:56:14 +0800
parents 86428aa657ab
children 8e372ae69010
files pyink/MBScene.py pyink/frameline.py
diffstat 2 files changed, 74 insertions(+), 48 deletions(-) [+]
line wrap: on
line diff
--- a/pyink/MBScene.py	Tue Jan 04 13:06:56 2011 +0800
+++ b/pyink/MBScene.py	Wed Jan 05 17:56:14 2011 +0800
@@ -448,16 +448,16 @@
     # This is here to monitor changes of scene node.
     def chg_scene_node(self, scene_node, start=None, end=None,
 			tween_type=None, ref=None):
-	if start:
+	if start is not None:
 	    scene_node.setAttribute('start', str(start))
 	    pass
-	if end:
+	if end is not None:
 	    scene_node.setAttribute('end', str(end))
 	    pass
-	if tween_type:
+	if tween_type is not None:
 	    scene_node.setAttribute('type', tween_type)
 	    pass
-	if ref:
+	if ref is not None:
 	    scene_node.setAttribute('ref', ref)
 	    pass
 	pass
@@ -537,18 +537,33 @@
     
     def __init__(self, *args, **kws):
 	super(MBScene_framelines, self).__init__(*args, **kws)
+	
+	self._last_mouse_over_frameline = None
+	self._last_active_frameline = None
 	pass
     
-    def _remove_active_frame(self,widget,event):
+    def _change_hover_frameline(self, widget, event):
         """
 	Hide all hover frames. This is a hack. We should use the lost focus
 	event instead in the future to reduce the overhead.
 	"""
-        for f in self._framelines:
-	    if f != widget:
-	        f.hide_hover()
-		pass
+	if self._last_mouse_over_frameline and \
+		widget != self._last_mouse_over_frameline:
+	    self._last_mouse_over_frameline.mouse_leave()
 	    pass
+	self._last_mouse_over_frameline = widget
+	pass
+
+    ## \brief Called for changing of active frame.
+    #
+    # This handle deactive previous frameline that owns an active frame when a
+    # frame in another frameline is activated.
+    def _change_active_frame(self, widget, frame, button):
+	if self._last_active_frameline and \
+		self._last_active_frameline != widget:
+	    self._last_active_frameline.deactive()
+	    pass
+	self._last_active_frameline = widget
 	pass
 
     ## \brief Add a frameline into the frameline box for the given layer.
@@ -578,7 +593,8 @@
 	line.label = label
 	line.layer_idx = layer_idx
 	line.connect(line.FRAME_BUT_PRESS, self.onCellClick)
-	line.connect('motion-notify-event', self._remove_active_frame)
+	line.connect('motion-notify-event', self._change_hover_frameline)
+	line.connect(frameline.FRAME_BUT_PRESS, self._change_active_frame)
 	pass
     
     ## \brief Remove the given frameline from the frameline box.
--- a/pyink/frameline.py	Tue Jan 04 13:06:56 2011 +0800
+++ b/pyink/frameline.py	Wed Jan 05 17:56:14 2011 +0800
@@ -223,12 +223,12 @@
         gc = self._gc
         gc.set_rgb_fg_color(color)
         
-        line_x1 = idx * self._frame_width
-        line_x2 = line_x1 + self._frame_width
+        line_x1 = idx * self._frame_width + 1
+        line_x2 = line_x1 + self._frame_width - 2
 
-        win.draw_line(gc, line_x1, 0, line_x1, w_h)
-        win.draw_line(gc, line_x2, 0, line_x2, w_h)
-        win.draw_line(gc, line_x1, w_h - 1, line_x2, w_h - 1)
+        win.draw_line(gc, line_x1, 0, line_x1, w_h - 2)
+        win.draw_line(gc, line_x2, 0, line_x2, w_h - 2)
+        win.draw_line(gc, line_x1, w_h - 2, line_x2, w_h - 2)
         win.draw_line(gc, line_x1, 0, line_x2, 0)
 	pass
 
@@ -261,13 +261,13 @@
         color = gtk.gdk.Color(*color_rgb)
         gc.set_rgb_fg_color(color)
 
-        line_x1 = frame_idx * self._frame_width + 1
-        line_x2 = line_x1 + self._frame_width - 2
+        line_x1 = frame_idx * self._frame_width + 2
+        line_x2 = line_x1 + self._frame_width - 4
         
-        win.draw_line(gc, line_x1, 1, line_x1, w_h - 2)
-        win.draw_line(gc, line_x2, 1, line_x2, w_h - 2)
+        win.draw_line(gc, line_x1, 1, line_x1, w_h - 3)
+        win.draw_line(gc, line_x2, 1, line_x2, w_h - 3)
         win.draw_line(gc, line_x1, 1, line_x2, 1)
-        win.draw_line(gc, line_x1, w_h - 2, line_x2, w_h - 2)
+        win.draw_line(gc, line_x1, w_h - 3, line_x2, w_h - 3)
         pass
     pass
 
@@ -295,6 +295,7 @@
         self._keys = []
         self._active_frame = -1
         self._drawing = False
+        self._last_hover = -1   # frame index of last hover
 	pass
 
     def _draw_keyframe(self, frame_idx):
@@ -427,9 +428,25 @@
     def _draw_hover_frame(self, frame_idx):
 	if not self._drawing:
 	    return
-	self._draw_hover(frame_idx)
-	pass
-    
+	
+        if self._last_hover != -1:
+            self._draw_frame(self._last_hover)
+	    if self._last_hover == self._active_frame:
+		self._draw_active_frame()
+		pass
+            pass
+	
+        if frame_idx < self._num_frames and frame_idx >= 0:
+            self._draw_hover(frame_idx)
+	    if self._last_hover == self._active_frame:
+		self._draw_active_frame()
+		pass
+	    self._last_hover = frame_idx
+	else:
+	    self._last_hover = -1
+	    pass
+        pass
+
     ## \brief Start future drawing actions
     #
     def start_drawing(self):
@@ -492,8 +509,8 @@
 	
         self.connect('button-press-event', self._press_hdl)
         self.connect('expose-event', self._fl_expose)
-        self.connect('motion-notify-event', self._motion_hdl)
-        self._last_hover = -1   # frame index of last hover
+        self.connect('motion-notify-event', self._motion_n_leave_hdl)
+        self.connect('leave-notify-event', self._motion_n_leave_hdl)
         pass
 
     def __len__(self):
@@ -566,32 +583,16 @@
         self.emit(frameline.FRAME_BUT_PRESS, frame, but)
         pass
     
-    def hide_hover(self):
-        if self._active_frame != self._last_hover:
-            self._draw_normal_frame(self._last_hover)
+    def _motion_n_leave_hdl(self, widget, event):
+	if event.type == gtk.gdk.LEAVE_NOTIFY:
+	    frame_idx = -1
+	else:
+	    frame_idx = int(event.x / self._frame_width)
 	    pass
+
+	self._draw_hover_frame(frame_idx)
 	pass
     
-    def _motion_hdl(self, widget, event):
-        frame_idx = int(event.x / self._frame_width)
-        if self._last_hover != -1:
-            self._draw_frame(self._last_hover)
-	    if self._last_hover == self._active_frame:
-		self._draw_active_frame()
-		pass
-            pass
-	
-        if frame_idx < self._num_frames and frame_idx >= 0:
-            self._draw_hover_frame(frame_idx)
-	    if self._last_hover == self._active_frame:
-		self._draw_active_frame()
-		pass
-	    self._last_hover = frame_idx
-	else:
-	    self._last_hover = -1
-	    pass
-        pass
-
     def _fl_expose(self, widget, event):
         win = self.window
 	self.start_drawing()
@@ -870,6 +871,15 @@
 	self._active_frame = -1
 	self._draw_all_frames()
         pass
+
+    ## \brief Called when mouse leave the widget.
+    #
+    # This is here for buggy pygtk.  It does not send leave-notify-event.  We
+    # need this to workaround.
+    #
+    def mouse_leave(self):
+	self._draw_hover_frame(-1)
+	pass
     pass
 
 if __name__ == '__main__':