Commit 3c8c49a4 authored by UVA Multi-touch's avatar UVA Multi-touch

Started fixing cairo test program.

parent 918eb1b3
...@@ -27,6 +27,8 @@ class Area(Positionable, Logger): ...@@ -27,6 +27,8 @@ class Area(Positionable, Logger):
self.parent = None self.parent = None
self.children = [] self.children = []
self.delegate_queue = {}
def get_root_area(self): def get_root_area(self):
""" """
Traverse up in the area tree to find the root area. Traverse up in the area tree to find the root area.
...@@ -36,24 +38,24 @@ class Area(Positionable, Logger): ...@@ -36,24 +38,24 @@ class Area(Positionable, Logger):
return self return self
def get_screen_position(self): def get_screen_offset(self):
""" """
Get the position relative to the screen. Get the position relative to the screen.
""" """
if not self.parent: if not self.parent:
return self.get_position() return self.get_position()
ox, oy = self.parent.get_screen_position() ox, oy = self.parent.get_screen_offset()
return ox + self.x, oy + self.y return ox + self.x, oy + self.y
def get_root_position(self): def get_root_offset(self):
""" """
Get the position relative to the root area. Get the position relative to the root area.
""" """
if not self.parent: if not self.parent:
return 0, 0 return 0, 0
ox, oy = self.parent.get_root_position() ox, oy = self.parent.get_root_offset()
return ox + self.x, oy + self.y return ox + self.x, oy + self.y
def get_offset(self, offset_area): def get_offset(self, offset_area):
...@@ -178,23 +180,19 @@ class Area(Positionable, Logger): ...@@ -178,23 +180,19 @@ class Area(Positionable, Logger):
propagation, return so that its siblings and the parent area will not propagation, return so that its siblings and the parent area will not
delegate the event to their trackers. delegate the event to their trackers.
""" """
child_found = False event.add_offset(*self.get_position())
#print 'delegated in %s: %s' % (self, event)
if self.children: if self.children:
# Delegate to children in reverse order because areas that are # Delegate to children in reverse order because areas that are
# added later, should be placed over previously added siblings # added later, should be placed over previously added siblings
for child in reversed(self.children): delegate_to = [c for c in self.children
event.set_area(self) if c.contains_event(event)]
if child.contains_event(event):
child_found = True
child.delegate_event(event)
if event.is_propagation_stopped(): if delegate_to:
return self.delegate_queue[event] = delegate_to
if not child_found: self.propagate_event(event)
self.propagate_event(event)
def propagate_event(self, event): def propagate_event(self, event):
""" """
...@@ -202,7 +200,14 @@ class Area(Positionable, Logger): ...@@ -202,7 +200,14 @@ class Area(Positionable, Logger):
propagate it to the parent area (if any). Propagation can be stopped by propagate it to the parent area (if any). Propagation can be stopped by
a tracker. a tracker.
""" """
event.set_area(self) if event in self.delegate_queue:
child = self.delegate_queue[event].pop()
if not self.delegate_queue[event]:
del self.delegate_queue[event]
child.delegate_event(event)
return
for tracker in self.trackers: for tracker in self.trackers:
tracker.handle_event(event) tracker.handle_event(event)
...@@ -211,6 +216,8 @@ class Area(Positionable, Logger): ...@@ -211,6 +216,8 @@ class Area(Positionable, Logger):
return return
if self.parent and not event.is_propagation_stopped(): if self.parent and not event.is_propagation_stopped():
event.add_offset(-self.x, -self.y)
#print 'propagated to %s: %s' % (self.parent, event)
self.parent.propagate_event(event) self.parent.propagate_event(event)
def handle_gesture(self, gesture): def handle_gesture(self, gesture):
......
...@@ -21,7 +21,8 @@ class EventDriver(Logger): ...@@ -21,7 +21,8 @@ class EventDriver(Logger):
Delegate an event that has been triggered by the event driver to the Delegate an event that has been triggered by the event driver to the
area tree. area tree.
""" """
self.root_area.delegate_event(event) if self.root_area.contains_event(event):
self.root_area.delegate_event(event)
def start(self): def start(self):
""" """
......
...@@ -18,7 +18,6 @@ class Event(Positionable): ...@@ -18,7 +18,6 @@ class Event(Positionable):
super(Event, self).__init__(*touch_object) super(Event, self).__init__(*touch_object)
self.touch_object = touch_object self.touch_object = touch_object
self.stopped = self.stopped_immidiate = False self.stopped = self.stopped_immidiate = False
self.area = None
def __getattr__(self, name): def __getattr__(self, name):
if name in OBJECT_NAMES \ if name in OBJECT_NAMES \
...@@ -28,22 +27,6 @@ class Event(Positionable): ...@@ -28,22 +27,6 @@ class Event(Positionable):
raise AttributeError("'%s' object has no attribute '%s'" raise AttributeError("'%s' object has no attribute '%s'"
% (self.__class__.__name__, name)) % (self.__class__.__name__, name))
def set_area(self, area):
self.area = area
def get_area(self):
return self.area
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 self.x - ox, self.y - oy
def get_type(self): def get_type(self):
return self._type return self._type
......
...@@ -19,7 +19,7 @@ class Positionable(object): ...@@ -19,7 +19,7 @@ class Positionable(object):
return repr(self) return repr(self)
def __iter__(self): def __iter__(self):
return iter((self.x, self.y)) return iter(self.get_position())
def __add__(self, other): def __add__(self, other):
ox, oy = other ox, oy = other
...@@ -38,19 +38,24 @@ class Positionable(object): ...@@ -38,19 +38,24 @@ class Positionable(object):
def __pow__(self, exp): def __pow__(self, exp):
return Positionable(self.x ** exp, self.y ** exp) return Positionable(self.x ** exp, self.y ** exp)
def get_position(self):
return self.x, self.y
def set_position(self, x, y): def set_position(self, x, y):
self.x = x self.x = x
self.y = y self.y = y
def get_position(self): def add_offset(self, add_x, add_y):
return self.x, self.y self.x -= add_x
self.y -= add_y
def distance_to(self, other): def distance_to(self, other):
""" """
Calculate the Pythagorian distance from this positionable to another. Calculate the Pythagorian distance from this positionable to another.
""" """
x, y = self.get_position()
ox, oy = other ox, oy = other
return ((ox - self.x) ** 2 + (oy - self.y) ** 2) ** .5 return ((ox - x) ** 2 + (oy - y) ** 2) ** .5
def translate(self, x, y): def translate(self, x, y):
self.set_position(self.x + x, self.y + y) self.set_position(self.x + x, self.y + y)
...@@ -78,6 +83,10 @@ class MovingPositionable(Positionable): ...@@ -78,6 +83,10 @@ class MovingPositionable(Positionable):
Positionable.set_position(self, x, y) Positionable.set_position(self, x, y)
def add_offset(self, add_x, add_y):
Positionable.add_offset(self, add_x, add_y)
self.prev.add_offset(add_x, add_y)
def get_previous_position(self): def get_previous_position(self):
return self.prev return self.prev
...@@ -106,9 +115,9 @@ class MovingPositionable(Positionable): ...@@ -106,9 +115,9 @@ class MovingPositionable(Positionable):
positionable. positionable.
""" """
px, py = self.prev px, py = self.prev
return Positionable(self.x - px, self.y - py) return self.x - px, self.y - py
def movement_distance(self): def translation_distance(self):
return self.distance_to(self.prev) return self.distance_to(self.prev)
......
...@@ -86,7 +86,7 @@ class TapTracker(GestureTracker): ...@@ -86,7 +86,7 @@ class TapTracker(GestureTracker):
self.last_tap = None self.last_tap = None
def on_point_down(self, event): def on_point_down(self, event):
self.reg[event.point.get_id()] = time.time(), event self.reg[event.point.get_id()] = time.time(), event.get_position()
def on_point_move(self, event): def on_point_move(self, event):
oid = event.point.get_id() oid = event.point.get_id()
......
...@@ -10,10 +10,11 @@ class RotationGesture(Gesture, Positionable): ...@@ -10,10 +10,11 @@ class RotationGesture(Gesture, Positionable):
""" """
_type = 'rotate' _type = 'rotate'
def __init__(self, event, centroid, angle): def __init__(self, event, centroid, angle, n=1):
Gesture.__init__(self, event) Gesture.__init__(self, event)
Positionable.__init__(self, *centroid.get_position()) Positionable.__init__(self, *centroid.get_position())
self.angle = angle self.angle = angle
self.n = n
def __str__(self): def __str__(self):
return '<RotationGesture at (%s, %s) angle=%s>' \ return '<RotationGesture at (%s, %s) angle=%s>' \
...@@ -30,10 +31,11 @@ class PinchGesture(Gesture, Positionable): ...@@ -30,10 +31,11 @@ class PinchGesture(Gesture, Positionable):
""" """
_type = 'pinch' _type = 'pinch'
def __init__(self, event, centroid, scale): def __init__(self, event, centroid, scale, n=1):
Gesture.__init__(self, event) Gesture.__init__(self, event)
Positionable.__init__(self, *centroid.get_position()) Positionable.__init__(self, *centroid.get_position())
self.scale = scale self.scale = scale
self.n = n
def __str__(self): def __str__(self):
return '<PinchGesture at (%s, %s) scale=%s>' \ return '<PinchGesture at (%s, %s) scale=%s>' \
...@@ -80,11 +82,9 @@ class TransformationTracker(GestureTracker): ...@@ -80,11 +82,9 @@ class TransformationTracker(GestureTracker):
self.points = [] self.points = []
# Current and previous centroid of all touch points # Current and previous centroid of all touch points
self.prev_centroid = self.centroid = None self.centroid = None
def update_centroid(self): def update_centroid(self):
self.prev_centroid = self.centroid
if not self.points: if not self.points:
self.centroid = None self.centroid = None
return return
...@@ -102,9 +102,6 @@ class TransformationTracker(GestureTracker): ...@@ -102,9 +102,6 @@ class TransformationTracker(GestureTracker):
else: else:
self.centroid = MovingPositionable(x, y) self.centroid = MovingPositionable(x, y)
#wx, wy = self.area.get_screen_offset()
#self.centroid.translate(-wx, -wy)
def on_point_down(self, event): def on_point_down(self, event):
self.points.append(event.point) self.points.append(event.point)
self.update_centroid() self.update_centroid()
...@@ -118,26 +115,26 @@ class TransformationTracker(GestureTracker): ...@@ -118,26 +115,26 @@ class TransformationTracker(GestureTracker):
l = len(self.points) l = len(self.points)
if l > 1: if l > 1:
offset_centroid = self.centroid - self.area.get_screen_offset()
print self.centroid, self.area, offset_centroid
# Rotation (around the previous centroid) # Rotation (around the previous centroid)
rotation = point.rotation_around(self.centroid) / l rotation = point.rotation_around(self.centroid) / l
self.trigger(RotationGesture(event, self.centroid, rotation)) self.trigger(RotationGesture(event, offset_centroid, rotation, l))
# Scale # Scale
prev = point.get_previous_position().distance_to(self.centroid) prev = self.centroid.distance_to(point.get_previous_position())
dist = point.distance_to(self.centroid) dist = self.centroid.distance_to(point)
dist = prev + (dist - prev) / l dist = prev + (dist - prev) / l
scale = dist / prev scale = dist / prev
self.trigger(PinchGesture(event, self.centroid, scale)) self.trigger(PinchGesture(event, offset_centroid, scale, l))
# Update centroid before movement can be detected # Update centroid before movement can be detected
self.update_centroid() self.update_centroid()
# Movement using multiple touch points # Movement using multiple touch points
self.trigger(DragGesture(event, self.centroid, self.trigger(DragGesture(event, self.centroid,
self.centroid.translation(), l)) self.centroid.translation(), l))
else:
# Movement using one touch point
self.trigger(DragGesture(event, point, point.translation()))
def on_point_up(self, event): def on_point_up(self, event):
if event.point not in self.points: if event.point not in self.points:
......
...@@ -8,54 +8,70 @@ from threading import Thread ...@@ -8,54 +8,70 @@ from threading import Thread
import src as mt import src as mt
def quit(*args):
gtk.main_quit()
class Rectangle(mt.RectangularArea): class Rectangle(mt.RectangularArea):
def __init__(self, x, y, width, height, color=(1, 0, 0)): def __init__(self, x, y, width, height, color=(1, 0, 0)):
super(Rectangle, self).__init__(x, y, width, height) super(Rectangle, self).__init__(x, y, width, height)
self.angle = 1.0 self.w = width
self.h = height
self.scale = 1
self.angle = 0
self.color = color self.color = color
self.t = cairo.Matrix() self.t = cairo.Matrix()
self.t.translate(*self) self.t.translate(x, y)
self.on_drag(self.move) self.on_drag(self.move)
self.on_pinch(self.resize) self.on_pinch(self.resize)
#self.on_rotate(self.rotate) self.on_rotate(self.rotate)
def move(self, g): def move(self, g):
print 'move:', g
self.translate(*g.get_translation()) self.translate(*g.get_translation())
print 'drag rectangle', self self.ttrans(*g.get_translation())
refresh() refresh()
def resize(self, g): def resize(self, g):
print 'resize:', g.get_scale() print 'resize:', g
self.t.scale(g.get_scale(), g.get_scale())
x, y = g.get_position()
scale = g.get_scale()
self.ttrans(x, y)
self.tscale(scale)
self.ttrans(-x, -y)
self.width *= scale
self.height *= scale
refresh() refresh()
def rotate(self, g): def rotate(self, g):
w, h = self.get_size() print 'rotate:', g
#self.t.translate(-w / 2, -h / 2)
self.t.rotate(-g.get_angle()) x, y = g.get_position()
#self.t.translate(w / 2, h / 2) self.ttrans(x, y)
print tuple(g) self.trot(-g.get_angle())
x, y = g * .01 self.ttrans(-x, -y)
print x, y
#self.rot.translate(-x, -y)
refresh() refresh()
def get_transformation_matrix(self): def ttrans(self, tx, ty):
t = cairo.Matrix() t = cairo.Matrix()
t.translate(*self) t.translate(tx, ty)
t.rotate(self.angle) self.t = t * self.t
t.scale(self.scale, self.scale) #self.t = self.t * t
return t
def tscale(self, s):
t = cairo.Matrix()
t.scale(s, s)
self.t = t * self.t
def trot(self, a):
t = cairo.Matrix()
t.rotate(a)
self.t = t * self.t
def draw(self, cr): def draw(self, cr):
w, h = self.get_size()
cr.transform(self.t) cr.transform(self.t)
cr.rectangle(0, 0, w, h) cr.rectangle(0, 0, self.w, self.h)
cr.set_source_rgb(*self.color) cr.set_source_rgb(*self.color)
cr.fill() cr.fill()
...@@ -134,6 +150,10 @@ def refresh(): ...@@ -134,6 +150,10 @@ def refresh():
window.queue_draw() window.queue_draw()
def quit(*args):
gtk.main_quit()
# Initialization # Initialization
window = cr = root = None window = cr = root = None
draw_objects = [] draw_objects = []
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment