From 8db37d787d4938d0f982c2676bfb4e52224afddd Mon Sep 17 00:00:00 2001 From: Manuel QuiƱones Date: Thu, 16 May 2013 11:36:56 +0000 Subject: Add drag by touch --- diff --git a/ImageView.py b/ImageView.py index 6219cd7..8b81ca9 100644 --- a/ImageView.py +++ b/ImageView.py @@ -70,6 +70,7 @@ class ImageViewer(Gtk.DrawingArea): self._target_point = None self._anchor_point = None + self._in_dragtouch = False self._in_zoomtouch = False self._zoomtouch_scale = 1 @@ -160,10 +161,56 @@ class ImageViewer(Gtk.DrawingArea): self._do_set_zoom(1) self._center_if_small() + def start_dragtouch(self, coords): + self._in_dragtouch = True + + prev_target_point = self._target_point + + # Set target point to the relative coordinates of this view. + alloc = self.get_parent().get_allocation() + self._target_point = (coords[1], coords[2]) + + # Calculate the new anchor point. + + prev_anchor_scaled = (self._anchor_point[0] * self._zoom, + self._anchor_point[1] * self._zoom) + + # This vector is the top left coordinate of the scaled image. + scaled_image_topleft = (prev_target_point[0] - prev_anchor_scaled[0], + prev_target_point[1] - prev_anchor_scaled[1]) + + anchor_scaled = (self._target_point[0] - scaled_image_topleft[0], + self._target_point[1] - scaled_image_topleft[1]) + + self._anchor_point = (int(anchor_scaled[0] * 1.0 / self._zoom), + int(anchor_scaled[1] * 1.0 / self._zoom)) + + self.queue_draw() + + def update_dragtouch(self, coords): + # Drag touch will be replaced by zoom touch if another finger + # is placed over the display. When the user finishes zoom + # touch, it will probably remove one finger after the other, + # and this method will be called. In that probable case, we + # need to start drag touch again. + if not self._in_dragtouch: + self.start_dragtouch(coords) + return + + self._target_point = (coords[1], coords[2]) + self.queue_draw() + + def finish_dragtouch(self, coords): + self._in_dragtouch = False + self._center_if_small() + def start_zoomtouch(self, center): self._in_zoomtouch = True self._zoomtouch_scale = 1 + # Zoom touch replaces drag touch. + self._in_dragtouch = False + prev_target_point = self._target_point # Set target point to the relative coordinates of this view. @@ -266,7 +313,7 @@ class ImageViewer(Gtk.DrawingArea): ctx.set_source_surface(self._surface, 0, 0) - if self._in_zoomtouch: + if self._in_zoomtouch or self._in_dragtouch: ctx.get_source().set_filter(cairo.FILTER_NEAREST) ctx.paint() diff --git a/ImageViewerActivity.py b/ImageViewerActivity.py index 78e5679..a72642e 100644 --- a/ImageViewerActivity.py +++ b/ImageViewerActivity.py @@ -28,6 +28,7 @@ import time import os import math from gi.repository import Gtk +from gi.repository import Gdk from gi.repository import GObject from sugar3.graphics.alert import NotifyAlert @@ -117,14 +118,21 @@ class ImageViewerActivity(activity.Activity): Gtk.PolicyType.ALWAYS) # Don't use the default kinetic scrolling, let the view do the - # pinch to zoom logic. + # drag-by-touch and pinch-to-zoom logic. self.scrolled_window.set_kinetic_scrolling(False) self.view = ImageView.ImageViewer() + + # Connect to the touch signal for performing drag-by-touch. + self.view.add_events(Gdk.EventMask.TOUCH_MASK) + self._touch_hid = self.view.connect('touch-event', + self.__touch_event_cb) self.scrolled_window.add_with_viewport(self.view) self.view.show() if GESTURES_AVAILABLE: + # Connect to the zoom signals for performing + # pinch-to-zoom. zoom_controller = SugarGestures.ZoomController() zoom_controller.attach(self, SugarGestures.EventControllerFlags.NONE) @@ -203,14 +211,28 @@ class ImageViewerActivity(activity.Activity): # Wait for a successful join before trying to get the document self.connect("joined", self._joined_cb) + def __touch_event_cb(self, widget, event): + coords = event.get_coords() + if event.type == Gdk.EventType.TOUCH_BEGIN: + self.view.start_dragtouch(coords) + elif event.type == Gdk.EventType.TOUCH_UPDATE: + self.view.update_dragtouch(coords) + elif event.type == Gdk.EventType.TOUCH_END: + self.view.finish_dragtouch(coords) + def __zoomtouch_began_cb(self, controller): self.view.start_zoomtouch(controller.get_center()) + # Don't listen to touch signals until pinch-to-zoom ends. + self.view.disconnect(self._touch_hid) + def __zoomtouch_changed_cb(self, controller, scale): self.view.update_zoomtouch(controller.get_center(), scale) def __zoomtouch_ended_cb(self, controller): self.view.finish_zoomtouch() + self._touch_hid = self.view.connect('touch-event', + self.__touch_event_cb) def _add_toolbar_buttons(self, toolbar_box): activity_button = ActivityToolbarButton(self) -- cgit v0.9.1