cairotest.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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 = 0
  14. self.scale = 1
  15. self.color = color
  16. def scale(self, angle):
  17. self.scale *= scale
  18. def rotate(self, angle):
  19. self.angle += angle
  20. def get_transformation_matrix(self):
  21. t = cairo.Matrix()
  22. t.translate(*self.get_position())
  23. t.rotate(self.angle)
  24. t.scale(self.scale, self.scale)
  25. return t
  26. def draw(self, cr):
  27. cr.transform(self.get_transformation_matrix())
  28. w, h = self.get_size()
  29. cr.rectangle(-w / 2, -h / 2, w, h)
  30. cr.set_source_rgb(*self.color)
  31. cr.fill()
  32. fullscreen = False
  33. W, H = mt.screen.screen_size
  34. def create_context_window(w, h, callback):
  35. def create_context(area, event):
  36. """Add Cairo context to GTK window and draw initial state."""
  37. global cr
  38. #if cr:
  39. # return
  40. cr = area.window.cairo_create()
  41. draw()
  42. def move_window(win, event):
  43. """Synchronize root multi-touch widget with GTK window."""
  44. root.set_position(*event.get_coords())
  45. root.set_size(event.width, event.height)
  46. draw()
  47. def handle_key(win, event):
  48. """Handle key event. 'f' toggles fullscreen, 'q' exits the program."""
  49. if event.keyval >= 256:
  50. return
  51. key = chr(event.keyval)
  52. if key == 'f':
  53. global fullscreen
  54. (win.unfullscreen if fullscreen else win.fullscreen)()
  55. fullscreen = not fullscreen
  56. elif key == 'q':
  57. quit()
  58. # Root widget (will be synchronized with GTK window)
  59. global root
  60. root = mt.RectangularWidget(0, 0, w, h)
  61. # GTK window
  62. win = gtk.Window()
  63. win.set_title('Cairo test')
  64. win.connect('destroy', quit)
  65. win.connect('key-press-event', handle_key)
  66. win.connect('configure-event', move_window)
  67. win.connect('show', callback)
  68. # Drawing area, needed by cairo context for drawing
  69. area = gtk.DrawingArea()
  70. area.set_size_request(w, h)
  71. area.connect('expose-event', create_context)
  72. win.add(area)
  73. area.show()
  74. win.show()
  75. def draw():
  76. # Background
  77. cr.rectangle(0, 0, *root.get_size())
  78. cr.set_source_rgb(0, 1, 0)
  79. cr.fill()
  80. # Drawable objects (use save and restore to allow transformations)
  81. for obj in draw_objects:
  82. #cr.save()
  83. obj.draw(cr)
  84. #cr.restore()
  85. # Initialization
  86. cr = root = None
  87. draw_objects = []
  88. def on_show(window):
  89. def root_dtap(g): print 'double tapped on root'
  90. root.on_double_tap(root_dtap)
  91. # Create blue rectangle
  92. rect = Rectangle(300, 200, 250, 150, color=(0, 0, 1))
  93. draw_objects.append(rect)
  94. root.add_widget(rect)
  95. def rect_tap(g): print 'tapped on rectangle'
  96. rect.on_tap(rect_tap, propagate_up_event=False)
  97. if __name__ == '__main__':
  98. # Parse arguments
  99. from tests.parse_arguments import create_parser, parse_args
  100. parse_args(create_parser())
  101. # Create a window with a Cairo context in it and a multi-touch widget
  102. # syncronized with it
  103. create_context_window(640, 460, on_show)
  104. # Run multi-touch gesture server in separate thread
  105. server = mt.EventServer(root)
  106. mt_thread = Thread(target=server.start)
  107. mt_thread.daemon = True
  108. mt_thread.start()
  109. # Initialize threads in GTK so that the thread started above will work
  110. gtk.gdk.threads_init()
  111. # Start main loop in current thread
  112. gtk.main()