lib/motion/events.rb in rm-extensions-0.4.0 vs lib/motion/events.rb in rm-extensions-0.4.1
- old
+ new
@@ -8,20 +8,20 @@
@rmext_events_proxy ||= EventsProxy.new(self)
end
# register a callback when an event is triggered on this object.
def rmext_on(object, event, &block)
- object.rmext_events_proxy.on(event, inContext:self, withBlock:block)
+ object.rmext_events_proxy.on(event, limit:-1, inContext:self, withBlock:block)
end
def rmext_now_and_on(object, event, &block)
object.rmext_events_proxy.now_and_on(event, inContext:self, withBlock:block)
end
# register a callback when an event is triggered on this object and remove it after it fires once
def rmext_once(object, event, &block)
- object.rmext_events_proxy.once(event, inContext:self, withBlock:block)
+ object.rmext_events_proxy.on(event, limit:1, inContext:self, withBlock:block)
end
# remove a specific callback for an event on object
def rmext_off(object, event, &block)
if object.rmext_events_proxy?
@@ -66,54 +66,54 @@
# deallocated, so the events can be cleaned up.
class EventsProxy
def initialize(obj)
@weak_object = WeakRef.new(obj)
- @desc = obj.inspect
@events = NSMapTable.weakToStrongObjectsMapTable
@listenings = NSHashTable.weakObjectsHashTable
if ::RMExtensions.debug?
- p "created EventsProxy(#{@desc})"
+ p "CREATED EventsProxy: #{@weak_object.rmext_object_desc}"
end
end
def dealloc
@did_dealloc = true
cleanup
if ::RMExtensions.debug?
- p "dealloc EventsProxy(#{@desc})"
+ p "DEALLOC EventsProxy: #{@weak_object.rmext_object_desc}"
end
super
end
def cleanup
off_all
off_all_context
true
end
- def on(event, inContext:context, withBlock:block)
+ def on(event, limit:limit, inContext:context, withBlock:block)
return if event.nil? || block.nil?
event = event.to_s
context ||= self.class
unless context_events = @events.objectForKey(context)
context_events = {}
@events.setObject(context_events, forKey:context)
end
unless context_event_blocks = context_events.objectForKey(event)
- context_event_blocks = []
+ context_event_blocks = {}
context_events.setObject(context_event_blocks, forKey:event)
end
block.weak!
- context_event_blocks.addObject block
+ context_event_blocks[block] = limit
# i.e.: controller/view listening_to model
context.rmext_events_proxy.listening_to(@weak_object)
end
+ # this is called in the reverse direction than normal
def listening_to(object)
if ::RMExtensions.debug?
- p "listening_to object", object.class, "from context", @weak_object.class
+ p "CONTEXT:", @weak_object.rmext_object_desc, "LISTENING TO:", object.rmext_object_desc
end
@listenings.addObject(object)
end
def now_and_on(event, inContext:context, withBlock:block)
@@ -123,32 +123,23 @@
res.value = nil
res.target = @weak_object
res.event = event
block.call(res)
end
- on(event, inContext:context, withBlock:block)
+ on(event, limit:-1, inContext:context, withBlock:block)
end
def off(event, inContext:context, withBlock:block)
return if event.nil? || block.nil?
event = event.to_s
context ||= self.class
return unless context_events = @events.objectForKey(context)
return unless context_event_blocks = context_events.objectForKey(event)
- context_event_blocks.removeObject block
+ context_event_blocks.delete block
nil
end
- def once(event, inContext:context, withBlock:block)
- block.weak!
- once_block = lambda do |opts|
- off(event, inContext:context, withBlock:once_block)
- block.call(opts)
- end
- on(event, inContext:context, withBlock:once_block)
- end
-
def off_all
@events.removeAllObjects
end
def off_context(context)
@@ -156,23 +147,18 @@
end
def off_all_context
while object = @listenings.anyObject
if ::RMExtensions.debug?
- p "remove object", object.class, "from context", @weak_object.class
+ p "CONTEXT:", @weak_object.rmext_object_desc, "UNLISTENING TO:", object.rmext_object_desc
end
@listenings.removeObject(object)
object.rmext_events_proxy.off_context(@weak_object)
end
end
def trigger(event, value)
- # m_desc = nil
- # if ::RMExtensions.debug?
- # m_desc = "~~> EventsProxy(#{@desc})#trigger(#{event}, #{value.inspect.split(" ").first }>)"
- # p "called", m_desc
- # end
rmext_inline_or_on_main_q do
next if @did_dealloc
next if event.nil?
event = event.to_s
keyEnumerator = @events.keyEnumerator
@@ -181,20 +167,30 @@
contexts.push context
end
while context = contexts.pop
if context_events = @events.objectForKey(context)
if event_blocks = context_events[event]
- blocks = [] + event_blocks
- # if ::RMExtensions.debug?
- # p "blocks.size", blocks.size, m_desc
- # end
- while blk = blocks.pop
+ blocks = event_blocks.keys
+ if ::RMExtensions.debug?
+ p "TRIGGER:", event, "OBJECT:", @weak_object.rmext_object_desc, "CONTEXT:", context.rmext_object_desc, "BLOCKS SIZE:", blocks.size
+ end
+ while block = blocks.pop
+ limit = event_blocks[block]
res = EventResponse.new
res.context = context
res.value = value
res.target = @weak_object
res.event = event
- blk.call(res)
+ block.call(res)
+ if limit == 1
+ # off
+ if ::RMExtensions.debug?
+ p "LIMIT REACHED:", event, "OBJECT:", @weak_object.rmext_object_desc, "CONTEXT:", context.rmext_object_desc
+ end
+ off(event, inContext:context, withBlock:block)
+ elsif limit > 1
+ context_events[block] -= 1
+ end
end
end
end
end
end