|
|
@@ -0,0 +1,148 @@
|
|
|
+#!/usr/bin/env python
|
|
|
+from __future__ import division
|
|
|
+import gtk
|
|
|
+import cairo
|
|
|
+from math import radians
|
|
|
+from threading import Thread
|
|
|
+
|
|
|
+import src as mt
|
|
|
+
|
|
|
+
|
|
|
+def quit(*args):
|
|
|
+ gtk.main_quit()
|
|
|
+
|
|
|
+
|
|
|
+class Rectangle(mt.RectangularWidget):
|
|
|
+ def __init__(self, x, y, width, height, color=(1, 0, 0)):
|
|
|
+ super(Rectangle, self).__init__(x, y, width, height)
|
|
|
+ self.angle = 0
|
|
|
+ self.scale = 1
|
|
|
+ self.color = color
|
|
|
+
|
|
|
+ def scale(self, angle):
|
|
|
+ self.scale *= scale
|
|
|
+
|
|
|
+ def rotate(self, angle):
|
|
|
+ self.angle += angle
|
|
|
+
|
|
|
+ def get_transformation_matrix(self):
|
|
|
+ t = cairo.Matrix()
|
|
|
+ t.translate(*self.get_position())
|
|
|
+ t.rotate(self.angle)
|
|
|
+ t.scale(self.scale, self.scale)
|
|
|
+ return t
|
|
|
+
|
|
|
+ def draw(self, cr):
|
|
|
+ cr.transform(self.get_transformation_matrix())
|
|
|
+ w, h = self.get_size()
|
|
|
+ cr.rectangle(-w / 2, -h / 2, w, h)
|
|
|
+ cr.set_source_rgb(*self.color)
|
|
|
+ cr.fill()
|
|
|
+
|
|
|
+
|
|
|
+fullscreen = False
|
|
|
+W, H = mt.screen.screen_size
|
|
|
+
|
|
|
+
|
|
|
+def create_context_window(w, h, callback):
|
|
|
+ def create_context(area, event):
|
|
|
+ """Add Cairo context to GTK window and draw initial state."""
|
|
|
+ global cr
|
|
|
+ #if cr:
|
|
|
+ # return
|
|
|
+ cr = area.window.cairo_create()
|
|
|
+ draw()
|
|
|
+
|
|
|
+ def move_window(win, event):
|
|
|
+ """Synchronize root multi-touch widget with GTK window."""
|
|
|
+ root.set_position(*event.get_coords())
|
|
|
+ root.set_size(event.width, event.height)
|
|
|
+ draw()
|
|
|
+
|
|
|
+ def handle_key(win, event):
|
|
|
+ """Handle key event. 'f' toggles fullscreen, 'q' exits the program."""
|
|
|
+ if event.keyval >= 256:
|
|
|
+ return
|
|
|
+
|
|
|
+ key = chr(event.keyval)
|
|
|
+
|
|
|
+ if key == 'f':
|
|
|
+ global fullscreen
|
|
|
+ (win.unfullscreen if fullscreen else win.fullscreen)()
|
|
|
+ fullscreen = not fullscreen
|
|
|
+ elif key == 'q':
|
|
|
+ quit()
|
|
|
+
|
|
|
+ # Root widget (will be synchronized with GTK window)
|
|
|
+ global root
|
|
|
+ root = mt.RectangularWidget(0, 0, w, h)
|
|
|
+
|
|
|
+ # GTK window
|
|
|
+ win = gtk.Window()
|
|
|
+ win.set_title('Cairo test')
|
|
|
+ win.connect('destroy', quit)
|
|
|
+ win.connect('key-press-event', handle_key)
|
|
|
+ win.connect('configure-event', move_window)
|
|
|
+ win.connect('show', callback)
|
|
|
+
|
|
|
+ # Drawing area, needed by cairo context for drawing
|
|
|
+ area = gtk.DrawingArea()
|
|
|
+ area.set_size_request(w, h)
|
|
|
+ area.connect('expose-event', create_context)
|
|
|
+
|
|
|
+ win.add(area)
|
|
|
+ area.show()
|
|
|
+ win.show()
|
|
|
+
|
|
|
+
|
|
|
+def draw():
|
|
|
+ # Background
|
|
|
+ cr.rectangle(0, 0, *root.get_size())
|
|
|
+ cr.set_source_rgb(0, 1, 0)
|
|
|
+ cr.fill()
|
|
|
+
|
|
|
+ # Drawable objects (use save and restore to allow transformations)
|
|
|
+ for obj in draw_objects:
|
|
|
+ #cr.save()
|
|
|
+ obj.draw(cr)
|
|
|
+ #cr.restore()
|
|
|
+
|
|
|
+
|
|
|
+# Initialization
|
|
|
+cr = root = None
|
|
|
+draw_objects = []
|
|
|
+
|
|
|
+
|
|
|
+def on_show(window):
|
|
|
+ def root_dtap(g): print 'double tapped on root'
|
|
|
+ root.on_double_tap(root_dtap)
|
|
|
+
|
|
|
+ # Create blue rectangle
|
|
|
+ rect = Rectangle(300, 200, 250, 150, color=(0, 0, 1))
|
|
|
+ draw_objects.append(rect)
|
|
|
+ root.add_widget(rect)
|
|
|
+
|
|
|
+ def rect_tap(g): print 'tapped on rectangle'
|
|
|
+ rect.on_tap(rect_tap, propagate_up_event=False)
|
|
|
+
|
|
|
+
|
|
|
+if __name__ == '__main__':
|
|
|
+ # Parse arguments
|
|
|
+ from tests.parse_arguments import create_parser, parse_args
|
|
|
+ parse_args(create_parser())
|
|
|
+
|
|
|
+ # Create a window with a Cairo context in it and a multi-touch widget
|
|
|
+ # syncronized with it
|
|
|
+ create_context_window(640, 460, on_show)
|
|
|
+
|
|
|
+ # Run multi-touch gesture server in separate thread
|
|
|
+ server = mt.EventServer(root)
|
|
|
+ mt_thread = Thread(target=server.start)
|
|
|
+ mt_thread.daemon = True
|
|
|
+ mt_thread.start()
|
|
|
+
|
|
|
+ # Initialize threads in GTK so that the thread started above will work
|
|
|
+ gtk.gdk.threads_init()
|
|
|
+
|
|
|
+ # Start main loop in current thread
|
|
|
+ gtk.main()
|