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