فهرست منبع

Separated GTK+ event window into a separate layer.

Taddeus Kroes 13 سال پیش
والد
کامیت
0c55af1061
4فایلهای تغییر یافته به همراه60 افزوده شده و 13 حذف شده
  1. 22 0
      src/area.py
  2. 2 0
      src/areas.py
  3. 9 11
      tests/testapp.py
  4. 27 2
      tests/utils.py

+ 22 - 0
src/area.py

@@ -29,6 +29,8 @@ class Area(Positionable, Logger):
 
         self.delegate_queue = {}
 
+        self.update_handlers = []
+
     def get_root_area(self):
         """
         Traverse up in the area tree to find the root area.
@@ -230,3 +232,23 @@ class Area(Positionable, Logger):
         """
         for handler in self.handlers.get(gesture.get_type(), ()):
             handler(gesture)
+
+    def on_update(self, handler):
+        self.update_handlers.append(handler)
+
+    def update(self):
+        """
+        Call update handlers of this area and all children, so that the
+        underlying subtree knows about changes in geometry and can redraw.
+        """
+        for handler in self.update_handlers:
+            if handler():
+                return True
+
+        for child in self.children:
+            if child.update():
+                return True
+
+    def set_position(self, x, y):
+        Positionable.set_position(self, x, y)
+        self.update()

+ 2 - 0
src/areas.py

@@ -21,6 +21,7 @@ class RectangularArea(Area):
     def set_size(self, width, height):
         self.width = width
         self.height = height
+        self.update()
 
     def get_size(self):
         return self.width, self.height
@@ -48,6 +49,7 @@ class CircularArea(Area):
 
     def set_radius(self, radius):
         self.radius = radius
+        self.update()
 
     def get_radius(self):
         return self.radius

+ 9 - 11
tests/testapp.py

@@ -5,7 +5,7 @@ from threading import Thread
 from math import pi, tan
 
 import src as mt
-from utils import BoundingBoxArea, Flick, FlickThread
+from utils import BoundingBoxArea, Flick, FlickThread, GtkEventWindow
 
 
 RED = 1, 0, 0
@@ -120,11 +120,9 @@ def create_context_window(w, h, callback):
         cr = area.window.cairo_create()
         draw()
 
-    def move_window(win, event):
-        """Synchronize root multi-touch area with GTK window."""
-        root.set_position(*event.get_coords())
-        root.set_size(event.width, event.height)
-        overlay.set_size(event.width, event.height)
+    def update_window():
+        """Synchronize overlay with GTK window."""
+        overlay.set_size(*window.get_size())
         refresh()
 
     def handle_key(win, event):
@@ -151,18 +149,18 @@ def create_context_window(w, h, callback):
             quit()
 
     # Root area (will be synchronized with GTK window)
-    global root, overlay
-    root = mt.RectangularArea(0, 0, w, h)
+    global overlay
     overlay = mt.RectangularArea(0, 0, w, h)
 
     # GTK window
-    global window
-    window = gtk.Window()
+    global window, root
+    window = GtkEventWindow()
     window.set_title('Cairo test')
     window.connect('destroy', quit)
     window.connect('key-press-event', handle_key)
-    window.connect('configure-event', move_window)
     window.connect('show', callback)
+    window.on_update(update_window)
+    root = window.get_area()
 
     if fullscreen:
         window.fullscreen()

+ 27 - 2
tests/utils.py

@@ -2,6 +2,7 @@ from __future__ import division
 from time import sleep
 from threading import Thread
 from numpy import array, diag, dot, cos, sin, asarray, column_stack, c_
+from gtk import Window
 
 from src import RectangularArea
 
@@ -36,11 +37,16 @@ class BoundingBoxArea(RectangularArea):
     def update_bounds(self):
         min_x, min_y = self.points.min(1)
         max_x, max_y = self.points.max(1)
-        self.set_size(max_x - min_x, max_y - min_y)
+        width = max_x - min_x
+        height = max_y - min_y
 
         if min_x or min_y:
-            self.translate(min_x, min_y)
+            self.width = width
+            self.height = height
             self.translate_points(-min_x, -min_y)
+            self.translate(min_x, min_y)
+        elif width != self.width or height != self.height:
+            self.set_size(width, height)
 
 
 FLICK_UPDATE_RATE = 30
@@ -114,3 +120,22 @@ def inside_shape(p, verts):
             inside = not inside
 
     return inside
+
+
+class GtkEventWindow(Window):
+    def __init__(self, width=0, height=0):
+        Window.__init__(self)
+        self.area = RectangularArea(0, 0, width, height)
+        self.connect('configure-event', self.sync_area)
+
+    def get_area(self):
+        return self.area
+
+    def on_update(self, handler):
+        self.area.on_update(handler)
+
+    def sync_area(self, win, event):
+        """Synchronize root multi-touch area with GTK window."""
+        self.area.width = event.width
+        self.area.height = event.height
+        self.area.set_position(*event.get_coords())