This problem seems harder to address than Issue 135. I fixed it on my machine with some quick and dirty workarounds. I am not hurrying to fix this issue in this post.
Labyrinth 0.4 have rudimentary zooming capability and the SVN trunk version made some improvement, but still buggy. As for the SVN version, when mouse wheel is scrolled, what actually happened is as follows: 1. The cursor point (I mean the point where the mouse cursor is pointing at) moves to the center of the window. 2. The view zooms, with the center of the window as an fixed point(the point that doesn't move when zooming). A good zooming expects the "cursor point" to be the "fixed point". This point should not move while other points move towards this point when zooming out, and move away from this point when zooming in. Look at how "zooming" is currently implemented: in MMapArea.py: def scroll (self, widget, event): scale = self.scale_fac # Backup the old scale factor if event.direction == gtk.gdk.SCROLL_UP: self.scale_fac*=1.2 # update to new scale factor coords = self.transform_coords(event.x, event.y) # get the "user" coordinates of mouse-pointer geom = self.window.get_geometry() # get the window size ( in "device" coords ) middle = self.transform_coords(geom[2]/2.0, geom[3]/2.0) # get window center and transform into "user" coords self.translation[0] -= coords[0] - middle[0] # move the "cursor point" to the center of the window self.translation[1] -= coords[1] - middle[1] # and y coordinate elif event.direction == gtk.gdk.SCROLL_DOWN: self.scale_fac/=1.2 self.undo.add_undo (UndoManager.UndoAction (self, UndoManager.TRANSFORM_CANVAS, \ self.undo_transform_cb, scale, self.scale_fac, self.translation, self.translation)) self.invalidate() See the problem? After zooming, the "cursor point" is moved to the center of the window. That is not expected to happen. And another problem is that zooming-in and zooming-out are also assymetric. Zooming-out does not move self.translation. This is also incorrect. But I will not go for a quick workaround here. Instead, let's look at the draw() function: In MMapArea.py: def draw (self, event, context): '''Draw the map and all the associated thoughts''' area = event.area ... # some initializations alloc = self.get_allocation () context.translate(alloc.width/2., alloc.height/2.) context.scale(self.scale_fac, self.scale_fac) context.translate(-alloc.width/2., -alloc.height/2.) context.translate(self.translation[0], self.translation[1]) # attention here. ... # other drawings follows There are four transformations: three translate()'s and one scale()'s. These can be interpreted as four operations done sequentially (in the reversed order of the code). I think the problem is in the self.translation. What does self.translation denotes? According to the above operations, self.translation is merely an "ACTION" that should be performed as the first step of coordinates transformation. Does self.translation have other meanings? I found that the point (-self.translation[0], -self.translation[1]) lies in the top-left corner of the window when self.scale_fac==1. Though I have found "where" self.translation is, I think it is a "weird" point that haunts around on the "user" canvas. We can use other denotion instead of the currently used self.translation. Let's introduce another attribute self.central_point_of_view. It satisfies the following condition: 1. self.central_point_of_view is a point on the "user" coordinates. 2. When translating from "user" coordinates to the "device" coordinates self.central_point_of_view should always be translated to the center of the window, and not affected by self.scale_fac and the size of the window. The effect of this change will be: 1. When panning the view-area (i.e. hold the middle mouse-button and move), self.central_point_of_view should be moved in the opposite direction of self.translation 2. The translation steps in the draw() method should become: context.translate(alloc.width/2., alloc.height/2.) context.scale(self.scale_fac, self.scale_fac) context.translate(-self.central_point_of_view[0],-self.central_point_of_view[1]) # note the negative sign. 3. When scaling (move the mouse-wheel), the code would become: def scroll (self, widget, event): scale = self.scale_fac if event.direction == gtk.gdk.SCROLL_UP: self.scale_fac*=1.2 elif event.direction == gtk.gdk.SCROLL_DOWN: self.scale_fac/=1.2 coords = self.transform_coords(event.x, event.y) # geom = self.window.get_geometry() # middle = self.transform_coords(geom[2]/2.0, geom[3]/2.0) # These are not needed. middle is always self.central_point_of_view def move_position(mouse, middle): """ Since we are moving x-coord and y-coord in the same way, I create a function """ old_delta = middle - mouse new_delta = old_delta / 1.2 # suppose we zoom in. Yes, zoom IN new_middle = mouse+new_delta return new_middle self.central_point_of_view[0] = move_position(coords[0],self.central_point_of_view[0]) self.central_point_of_view[1] = move_position(coords[1],self.central_point_of_view[1]) How move_position() works? If we zoom-in while keeping the current "mouse point" fixed, then the self.central_point_of_view moves towards the "mouse point" in the "user" coords, because zooming-in means that the same on-screen distance worths less in the "user" coords. And there is a side-effect when we use self.central_point_of_view instead of self.translation. When we resize the window, the result becomes different. Now the central point keeps fixed while in the past the top-left point was fixed. Currently self.translation is referenced all around the code. It should be taken seriously whether to introduce self.central_point_of_view and remove self.translation. Summary: 1. The current implementation of scroll() is obviously incorrect. 2. The self.translation is strange. It is difficult to understand and difficult to use. 3. Introducing self.central_point_of_view will simplify coordinate handling, but will result in many code-changes. Kunshan Wang --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Labyrinth Discussion" group. To post to this group, send email to labyrinth-devel@googlegroups.com To unsubscribe from this group, send email to labyrinth-devel+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/labyrinth-devel?hl=en -~----------~----~----~----~------~----~------~--~---