From 290189d892861a30fb97cefe9197cd2194e89594 Mon Sep 17 00:00:00 2001 From: Manuel Kaufmann Date: Mon, 29 Oct 2012 20:13:15 +0000 Subject: Zoom Gesture zooms through the gesture's center When two fingers are used to zoom in/out the image, the center of the gesture is used to zoom the image through it. Signed-off-by: Manuel Kaufmann Signed-off-by: Agustin Zubiaga --- diff --git a/ImageView.py b/ImageView.py index cbc5516..f20910c 100644 --- a/ImageView.py +++ b/ImageView.py @@ -71,9 +71,15 @@ class ImageViewer(Gtk.DrawingArea): self._angle_ori = 0.0 self._fast = True self._redraw_id = None - self._is_touching = False self._switched = False + # zoom with fixed point + self._is_touching = False + self._touch_center = False + self._old_zoom = None + self._xofs = 0 + self._yofs = 0 + def do_get_property(self, pspec): if pspec.name == 'zoom': return self.zoom @@ -167,20 +173,6 @@ class ImageViewer(Gtk.DrawingArea): y = int((rect.height - h) / 2) ctx.translate(x, y) - if self._is_touching: - if self._switched: - w, h = h, w - - if rect.height < h: - vadj = int((h - rect.height) / 2) - vadjustment = scrolled_window.get_vadjustment() - vadjustment.set_value(vadj) - - if rect.width < w: - hadj = int((w - rect.width) / 2) - hadjustment = scrolled_window.get_hadjustment() - hadjustment.set_value(hadj) - if self.zoom != 1: logging.error('Scaling: %s', self.zoom) ctx.scale(self.zoom, self.zoom) @@ -218,6 +210,69 @@ class ImageViewer(Gtk.DrawingArea): self._switched = True self.set_size_request(w, h) + self._scroll_image() + + def _scroll_image(self): + # based on Eye Of GNOME code + + w = int(self.surface.get_width() * self.zoom) + h = int(self.surface.get_height() * self.zoom) + + old_width = int(self.surface.get_width() * self._old_zoom) + old_height = int(self.surface.get_height() * self._old_zoom) + + scrolled_window = self.get_parent() + rect = scrolled_window.get_allocation() + + if self._switched: + # TODO: zoom with fixed point does not work properly when + # the image is rotated + return + + if self._is_touching: + zoom_x_anchor = self._touch_center[1] / rect.width + zoom_y_anchor = self._touch_center[2] / rect.height + else: + zoom_x_anchor = 0.5 + zoom_y_anchor = 0.5 + + vadjustment = scrolled_window.get_vadjustment() + step_inc = vadjustment.get_step_increment() + page_inc = vadjustment.get_page_increment() + + if old_height < rect.height: + cy = zoom_y_anchor * old_height / self._old_zoom + else: + cy = (self._yofs + zoom_y_anchor * rect.height) / self._old_zoom + + if h < rect.height: + self._yofs = 0 + else: + self._yofs = math.floor(cy * self.zoom - \ + zoom_y_anchor * rect.height + 0.5) + + vadj = max(0, min(self._yofs, h - rect.height)) + vadjustment.configure(vadj, 0, h, step_inc, page_inc, + rect.height) + + hadjustment = scrolled_window.get_hadjustment() + step_inc = hadjustment.get_step_increment() + page_inc = hadjustment.get_page_increment() + + if old_width < rect.width: + cx = zoom_x_anchor * old_width / self._old_zoom + else: + cx = (self._xofs + zoom_x_anchor * rect.width) / self._old_zoom + + if w < rect.width: + self._xofs = 0 + else: + self._xofs = math.floor(cx * self.zoom - \ + zoom_x_anchor * rect.width + 0.5) + + hadj = max(0, min(self._xofs, w - rect.width)) + hadjustment.configure(hadj, 0, w, step_inc, page_inc, + rect.width) def set_zoom(self, zoom): self._optimal_zoom_flag = False @@ -302,6 +357,7 @@ class ImageViewer(Gtk.DrawingArea): return zoom def _set_zoom(self, zoom): + self._old_zoom = self.zoom self.zoom = zoom self._redraw() self.emit('zoom-changed') diff --git a/ImageViewerActivity.py b/ImageViewerActivity.py index 0c51699..4850116 100644 --- a/ImageViewerActivity.py +++ b/ImageViewerActivity.py @@ -123,6 +123,8 @@ class ImageViewerActivity(activity.Activity): zoom_controller = SugarGestures.ZoomController() zoom_controller.connect('scale-changed', self.__scale_changed_cb) + zoom_controller.connect('began', + self.__scale_began_cb) zoom_controller.attach(self, SugarGestures.EventControllerFlags.NONE) @@ -208,12 +210,16 @@ class ImageViewerActivity(activity.Activity): # Wait for a successful join before trying to get the document self.connect("joined", self._joined_cb) + def __scale_began_cb(self, controller): + self.view._zoom_ori = self.view.zoom + def __scale_changed_cb(self, controller, scale): if scale != self._last_scale: self._last_scale = scale logging.error('Scale changed %f', scale) self.view._is_touching = True + self.view._touch_center = controller.get_center() self.view.set_zoom_relative(scale) def handle_view_source(self): -- cgit v0.9.1