lib/under_os/ui/utils/events.rb in under-os-1.2.1 vs lib/under_os/ui/utils/events.rb in under-os-1.3.0
- old
+ new
@@ -4,24 +4,24 @@
module UnderOs::UI::Events
def on(event, *args, &block)
return event.map{|e,b| self.on(e,&b)}[0] || self if event.is_a?(Hash)
- event, recognizer = find_recognizer_from(event)
-
- @_.addGestureRecognizer(recognizer.alloc.initWithTarget(self, action: :emit)) if recognizer
@_.userInteractionEnabled = true
+ event = add_ui_event_listener(event)
+
UnderOs::Events::Listeners.add(self, event, *args, block)
end
def off(event)
UnderOs::Events::Listeners.remove(self, event)
end
def emit(*event)
if event.is_a?(UIGestureRecognizer)
+ event, r = find_recognizer_from(event.class)
event = Event.new(self, event)
else
event = Event.new(self, *event)
end
@@ -30,12 +30,109 @@
def on=(hash)
on hash
end
+ class TouchListeners
+ def self.listeners
+ @listeners ||= Hash.new{ |h,k| h[k] = [] }
+ end
+
+ def self.add(eventname, view)
+ listeners[eventname] << view
+ end
+
+ def self.notify(eventname, event)
+ listeners[eventname].each do |view|
+ if eventname == :touchmove # being nice and throttling the touchmove events
+ return if @__working
+ @__working = true
+ end
+
+ touches = touches_for_view(view, event)
+
+ view.emit(eventname, touches: touches) if touches.size > 0
+
+ @__working = false
+ end
+ end
+
+ def self.touches_for_view(view, event)
+ frame = view._.frame
+ touches = []
+
+ event.allTouches.each do |touch|
+ if point = touch_inside_of(frame, touch)
+ touches << Touch.new(view, point)
+ end
+ end
+
+ touches
+ end
+
+ def self.touch_inside_of(frame, touch)
+ point = touch.locationInView(nil)
+ point = nil if point.x < frame.origin.x ||
+ point.y < frame.origin.y ||
+ point.x > frame.origin.x + frame.size.width ||
+ point.y > frame.origin.y + frame.size.height
+
+ point
+ end
+
+ class Touch
+ attr_reader :view, :position
+
+ def initialize(view, position)
+ @view = view
+ @position = position
+ end
+
+ def pageX
+ position.x
+ end
+
+ def pageY
+ position.y
+ end
+
+ def viewX
+ @position.x - view._.frame.origin.x
+ end
+
+ def viewY
+ @position.y - view._.frame.origin.y
+ end
+
+ def inspect
+ "#<Touch x=#{pageX} y=#{pageY}"
+ end
+ end
+ end
+
private
+ def add_ui_event_listener(event)
+ event = event.to_sym if event.is_a?(String)
+ event = try_add_touch_event_listener(event)
+ event, recognizer = find_recognizer_from(event)
+
+ @_.addGestureRecognizer(recognizer.alloc.initWithTarget(self, action: :emit)) if recognizer
+
+ event
+ end
+
+ TOUCH_EVENTS = [:touchstart, :touchmove, :touchend, :touchcancel]
+
+ def try_add_touch_event_listener(event)
+ if TOUCH_EVENTS.include?(event)
+ UnderOs::UI::Events::TouchListeners.add(event, self)
+ end
+
+ event
+ end
+
RECOGNIZERS = {
tap: UITapGestureRecognizer,
pinch: UIPinchGestureRecognizer,
rotate: UIRotationGestureRecognizer,
swipe: UISwipeGestureRecognizer,
@@ -43,12 +140,10 @@
press: UILongPressGestureRecognizer
}
# tries to figure event name and gesture recognizer
def find_recognizer_from(event)
- event = event.to_sym if event.is_a?(String)
-
if event.is_a?(Class) && event < UIGestureRecognizer
recognizer = event
if recognizer.respond_to?(:event_name)
event = recognizer.event_name
@@ -66,10 +161,10 @@
class Event < UnderOs::Events::Event
attr_reader :target
def initialize(view, event, params={})
@target = view
- event, r = view.__send__ :find_recognizer_from, event.class if event.is_a?(UIGestureRecognizer)
+
super event, params
end
end
end