Bladeren bron

Fixed offset positioning of events/areas.

Taddeus Kroes 13 jaren geleden
bovenliggende
commit
a7a2067c57
3 gewijzigde bestanden met toevoegingen van 44 en 34 verwijderingen
  1. 29 24
      src/area.py
  2. 1 1
      src/driver.py
  3. 14 9
      src/event.py

+ 29 - 24
src/area.py

@@ -8,9 +8,9 @@ from abc import ABCMeta, abstractmethod
 
 class Area(Positionable, Logger):
     """
-    Abstract class for area implementations. A area represents a 2D object
-    on the screen in which gestures can occur.  Handlers for a specific gesture
-    type can be bound to a area.
+    Abstract class for area implementations. A area represents a 2D object on
+    the screen in which gestures can occur. Handlers for specific gesture types
+    can be bound to a area.
     """
     __metaclass__ = ABCMeta
 
@@ -36,34 +36,32 @@ class Area(Positionable, Logger):
 
         return self
 
-    def get_screen_offset(self):
+    def get_screen_position(self):
         """
         Get the position relative to the screen.
         """
-        root = self.get_root_area()
-        return root + self.get_offset(root)
+        if not self.parent:
+            return self.get_position()
+
+        return self.get_position() + self.parent.get_screen_position()
 
-    def get_offset(self, offset_parent=None):
+    def get_root_position(self):
         """
-        Get the position relative to an offset parent. If no offset parent is
-        specified, the position relative to the root area is returned. The
-        position of the root area itself is (0, 0).
+        Get the position relative to the root area.
         """
-        if not offset_parent:
-            offset_parent = self.get_root_area()
-
         if not self.parent:
-            if offset_parent is self:
-                return 0, 0
+            return Positionable(0, 0)
 
-            ox, oy = offset_paret
-            x = y = 0
-        else:
-            ox, oy = offset_parent
-            x = self.x
-            y = self.y
+        return self.get_position() + self.parent.get_root_position()
 
-        return x - ox, y - oy
+    def get_offset(self, offset_area):
+        """
+        Get the position relative to an ancestor area.
+        """
+        if self.parent == offset_area:
+            return self.get_position()
+
+        return self.get_position() + self.parent.get_offset(offset_area)
 
     def add_area(self, area):
         """
@@ -180,7 +178,7 @@ class Area(Positionable, Logger):
         child_found = False
 
         if self.children:
-            event.set_offset(self.get_offset())
+            event.set_area(self)
 
             # Delegate to children in reverse order because areas that are
             # added later, should be placed over previously added siblings
@@ -196,11 +194,18 @@ class Area(Positionable, Logger):
             self.propagate_event(event)
 
     def propagate_event(self, event):
+        """
+        Delagate an event to all gesture trackers (immediate propagation), then
+        propagate it to the parent area (if any). Propagation can be stopped by
+        a tracker.
+        """
+        event.set_area(self)
+
         for tracker in self.trackers:
             tracker.handle_event(event)
 
             if event.is_immediate_propagation_stopped():
-                break
+                return
 
         if self.parent and not event.is_propagation_stopped():
             self.parent.propagate_event(event)

+ 1 - 1
src/driver.py

@@ -22,7 +22,7 @@ class EventDriver(Logger):
         area tree.
         """
         if self.root_area.contains_event(event):
-            event.set_root_area(self.root_area)
+            event.set_area(self.root_area)
             self.root_area.delegate_event(event)
 
     def start(self):

+ 14 - 9
src/event.py

@@ -16,7 +16,7 @@ class Event(Positionable):
         super(Event, self).__init__(*touch_object)
         self.touch_object = touch_object
         self.stopped = self.stopped_immidiate = False
-        self.offset = Positionable(0, 0)
+        self.area = None
 
     def __getattr__(self, name):
         if name in OBJECT_NAMES \
@@ -26,16 +26,21 @@ class Event(Positionable):
         raise AttributeError("'%s' object has no attribute '%s'"
                              % (self.__class__.__name__, name))
 
-    def get_offset(self):
-        return self - self.offset
+    def set_area(self, area):
+        self.area = area
 
-    def set_offset(self, offset):
-        self.offset.set_position(*offset)
+    def get_area(self):
+        return self.area
 
-    def set_root_area(self, area):
-        x, y = area
-        self.x -= x
-        self.y -= y
+    def get_root_position(self):
+        return self.get_offset(self.area.get_root_area())
+
+    def get_position(self):
+        return self.get_offset(self.area)
+
+    def get_offset(self, area):
+        ox, oy = area.get_screen_position()
+        return Positionable(self.x - ox, self.y - oy)
 
     def get_type(self):
         return self._type