cairotest.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #!/usr/bin/env python
  2. from __future__ import division
  3. import gtk
  4. import cairo
  5. from math import radians
  6. from threading import Thread
  7. import src as mt
  8. def quit(*args):
  9. gtk.main_quit()
  10. class Rectangle(mt.RectangularWidget):
  11. def __init__(self, x, y, width, height, color=(1, 0, 0)):
  12. super(Rectangle, self).__init__(x, y, width, height)
  13. self.angle = 1.0
  14. self.color = color
  15. self.t = cairo.Matrix()
  16. self.t.translate(*self)
  17. self.on_drag(self.move)
  18. self.on_pinch(self.resize)
  19. #self.on_rotate(self.rotate)
  20. def move(self, g):
  21. self.translate(*g.get_translation())
  22. print 'drag rectangle', self
  23. refresh()
  24. def resize(self, g):
  25. print 'resize:', g.get_scale()
  26. self.t.scale(g.get_scale(), g.get_scale())
  27. refresh()
  28. def rotate(self, g):
  29. w, h = self.get_size()
  30. #self.t.translate(-w / 2, -h / 2)
  31. self.t.rotate(-g.get_angle())
  32. #self.t.translate(w / 2, h / 2)
  33. print tuple(g)
  34. x, y = g * .01
  35. print x, y
  36. #self.rot.translate(-x, -y)
  37. refresh()
  38. def get_transformation_matrix(self):
  39. t = cairo.Matrix()
  40. t.translate(*self)
  41. t.rotate(self.angle)
  42. t.scale(self.scale, self.scale)
  43. return t
  44. def draw(self, cr):
  45. w, h = self.get_size()
  46. cr.transform(self.t)
  47. cr.rectangle(0, 0, w, h)
  48. cr.set_source_rgb(*self.color)
  49. cr.fill()
  50. fullscreen = False
  51. W, H = mt.screen.screen_size
  52. def create_context_window(w, h, callback):
  53. def create_context(area, event):
  54. """Add Cairo context to GTK window and draw state."""
  55. global cr
  56. cr = area.window.cairo_create()
  57. draw()
  58. def move_window(win, event):
  59. """Synchronize root multi-touch widget with GTK window."""
  60. root.set_position(*event.get_coords())
  61. root.set_size(event.width, event.height)
  62. draw()
  63. def handle_key(win, event):
  64. """Handle key event. 'f' toggles fullscreen, 'q' exits the program."""
  65. if event.keyval >= 256:
  66. return
  67. key = chr(event.keyval)
  68. if key == 'f':
  69. global fullscreen
  70. (win.unfullscreen if fullscreen else win.fullscreen)()
  71. fullscreen = not fullscreen
  72. elif key == 'q':
  73. quit()
  74. # Root widget (will be synchronized with GTK window)
  75. global root
  76. root = mt.RectangularWidget(0, 0, w, h)
  77. # GTK window
  78. global window
  79. window = gtk.Window()
  80. window.set_title('Cairo test')
  81. window.connect('destroy', quit)
  82. window.connect('key-press-event', handle_key)
  83. window.connect('configure-event', move_window)
  84. window.connect('show', callback)
  85. # Drawing area, needed by cairo context for drawing
  86. area = gtk.DrawingArea()
  87. area.set_size_request(w, h)
  88. area.connect('expose-event', create_context)
  89. window.add(area)
  90. area.show()
  91. window.show()
  92. def draw(*args):
  93. if not cr:
  94. return
  95. # Background
  96. cr.rectangle(0, 0, *root.get_size())
  97. cr.set_source_rgb(0, 1, 0)
  98. cr.fill()
  99. # Drawable objects (use save and restore to allow transformations)
  100. for obj in draw_objects:
  101. cr.save()
  102. obj.draw(cr)
  103. cr.restore()
  104. def refresh():
  105. window.queue_draw()
  106. # Initialization
  107. window = cr = root = None
  108. draw_objects = []
  109. def on_show(window):
  110. def root_dtap(g): print 'double tapped on root'
  111. root.on_double_tap(root_dtap)
  112. # Create blue rectangle
  113. rect = Rectangle(300, 200, 250, 150, color=(0, 0, 1))
  114. draw_objects.append(rect)
  115. root.add_widget(rect)
  116. def rect_tap(g): print 'tapped on rectangle'
  117. rect.on_tap(rect_tap, propagate_up_event=False)
  118. if __name__ == '__main__':
  119. # Parse arguments
  120. from tests.parse_arguments import create_parser, parse_args
  121. parse_args(create_parser())
  122. # Create a window with a Cairo context in it and a multi-touch widget
  123. # syncronized with it
  124. create_context_window(640, 460, on_show)
  125. # Run multi-touch gesture server in separate thread
  126. server = mt.EventServer(root)
  127. mt_thread = Thread(target=server.start)
  128. mt_thread.daemon = True
  129. mt_thread.start()
  130. # Initialize threads in GTK so that the thread started above will work
  131. gtk.gdk.threads_init()
  132. # Start main loop in current thread
  133. gtk.main()