--- /dev/null
+#!/usr/bin/env python
+
+# Copyright (C) 2011-2012 Neil Brown <neilb@suse.de>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+# FingerScroll is a simple widget to wrap around TextView
+# so that the TextBuffer can be scrolled with finger-wipes.
+# Each wipe is either horizontal or vertical, not both.
+
+import gtk
+
+class FingerScroll:
+ def __init__(self, child, scale):
+ self.hadj = gtk.Adjustment()
+ self.vadj = gtk.Adjustment()
+ self.scale = scale
+ self.child = child
+ self.child.set_scroll_adjustments(self.hadj, self.vadj)
+
+ self.child.add_events(gtk.gdk.POINTER_MOTION_MASK
+ | gtk.gdk.POINTER_MOTION_HINT_MASK
+ | gtk.gdk.BUTTON_PRESS_MASK
+ | gtk.gdk.BUTTON_RELEASE_MASK)
+ self.child.connect("button_press_event", self.press)
+ self.child.connect("button_release_event", self.release)
+ self.child.connect("motion_notify_event", self.motion)
+ self.drag_start = None
+ print "done setup"
+
+ def press(self, w, ev):
+ print "press"
+ w.stop_emission("button_press_event")
+
+ self.drag_start = int(ev.x), int(ev.y)
+ self.xstart = self.hadj.value
+ self.ystart = self.vadj.value
+
+ def release(self, w, ev):
+ self.drag_start = None
+ w.stop_emission("button_release_event")
+
+ def motion(self, w, ev):
+ if self.drag_start == None:
+ return
+
+ if ev.is_hint:
+ x, y, state = ev.window.get_pointer()
+ else:
+ x = ev.x
+ y = ev.y
+ x = int(x)
+ y = int(y)
+ dx = x - self.drag_start[0]
+ dy = y - self.drag_start[1]
+ dy = dy / self.scale
+ dx = dx / self.scale
+ newx, newy = self.xstart, self.ystart
+ if abs(dx) > abs(dy):
+ newx = newx - dx
+ else:
+ newy = newy - dy
+
+ if newx >= self.hadj.upper - self.hadj.page_size:
+ newx = self.hadj.upper - self.hadj.page_size
+ if newx <= self.hadj.lower: newx = self.hadj.lower
+ if newy >= self.vadj.upper - self.vadj.page_size:
+ newy = self.vadj.upper - self.vadj.page_size
+ if newy <= self.vadj.lower: newy = self.vadj.lower
+ self.hadj.value = newx
+ self.vadj.value = newy
+ w.stop_emission("motion_notify_event")
+
+if __name__ == "__main__":
+ # test app for FingerScroll
+ import sys
+ w = gtk.Window(gtk.WINDOW_TOPLEVEL)
+ w.connect("destroy", lambda w: gtk.main_quit())
+ w.set_title("FingerScroll test")
+ w.show()
+ w.set_default_size(200,200)
+
+ sw = FingerScroll(); sw.show()
+ w.add(sw)
+
+ b = sw.get_buffer()
+
+ f = open(sys.argv[-1], "r")
+ l = f.readline()
+ while len(l):
+ b.insert(b.get_end_iter(), l)
+ l = f.readline()
+
+ gtk.main()
+
+