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