rm-extensions 0.4.5 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/motion/accessors.rb +20 -0
- data/lib/motion/events.rb +141 -95
- data/lib/motion/util.rb +2 -2
- data/lib/rm-extensions/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5508660ca09f24056f99da66f92638543dd64bbb
|
4
|
+
data.tar.gz: 4d03e2678ca57e1906faf277637ede4029d677b1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 36069726b1441e036f165666810d61e9a6c1e1df5c8ac16e1ca9ead8d00ec8a7beca81f3d5b2ee22201654155e82842ed91ebb4b1ce8892ca67d386f621f44fa
|
7
|
+
data.tar.gz: 264354fcf310ccca5b4b7f729b1a1f79fe3b90ea9145ebdf195c7fea8381def8619acfde5fad8a25be4f1c125b1e7093985b1eedb32a9f6de2236b9182e192f6
|
data/lib/motion/accessors.rb
CHANGED
@@ -19,6 +19,26 @@ module RMExtensions
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
# creates an +attr_accessor+ like behavior, but the objects are
|
23
|
+
# stored in an NSMapTable with strong keys (the attrs) and
|
24
|
+
# weak values. If the value deallocates, it becomes nil, unlike
|
25
|
+
# a traditional WeakRef.
|
26
|
+
# does not conform to KVO like attr_accessor does.
|
27
|
+
def rmext_zeroing_weak_attr_accessor(*attrs)
|
28
|
+
attrs.each do |attr|
|
29
|
+
define_method(attr) do
|
30
|
+
if @__zeroing_weak_holders
|
31
|
+
@__zeroing_weak_holders.objectForKey(attr)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
define_method("#{attr}=") do |val|
|
35
|
+
@__zeroing_weak_holders ||= NSMapTable.strongToWeakObjectsMapTable
|
36
|
+
@__zeroing_weak_holders.setObject(val, forKey:attr)
|
37
|
+
val
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
22
42
|
end
|
23
43
|
|
24
44
|
end
|
data/lib/motion/events.rb
CHANGED
@@ -4,56 +4,59 @@ module RMExtensions
|
|
4
4
|
|
5
5
|
module Events
|
6
6
|
|
7
|
-
def
|
8
|
-
@
|
7
|
+
def rmext_events_from_proxy
|
8
|
+
@rmext_events_from_proxy ||= EventsFromProxy.new(self)
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
12
|
-
|
11
|
+
def rmext_events_from_proxy?
|
12
|
+
!!@rmext_events_from_proxy
|
13
13
|
end
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
object.rmext_events_proxy.on(event, limit:-1, inContext:self, withBlock:block)
|
15
|
+
def rmext_events_to_proxy
|
16
|
+
@rmext_events_to_proxy ||= EventsToProxy.new(self)
|
18
17
|
end
|
19
18
|
|
20
|
-
def
|
21
|
-
|
19
|
+
def rmext_events_to_proxy?
|
20
|
+
!!@rmext_events_to_proxy
|
22
21
|
end
|
23
22
|
|
24
|
-
# register a callback when an event is triggered on this object
|
25
|
-
def
|
26
|
-
|
23
|
+
# register a callback when an event is triggered on this object.
|
24
|
+
def rmext_on(event, opts={}, &block)
|
25
|
+
rmext_events_from_proxy.on(event, opts, &block)
|
27
26
|
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
if object.rmext_events_proxy?
|
32
|
-
object.rmext_events_proxy.off(event, inContext:self, withBlock:block)
|
33
|
-
end
|
28
|
+
def rmext_now_and_on(event, opts={}, &block)
|
29
|
+
rmext_events_from_proxy.now_and_on(event, opts, &block)
|
34
30
|
end
|
35
31
|
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
32
|
+
# register a callback when an event is triggered on this object and remove it after it fires once
|
33
|
+
def rmext_once(event, opts={}, &block)
|
34
|
+
opts[:limit] = 1
|
35
|
+
rmext_events_from_proxy.on(event, opts, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
# @model.rmext_off(:fire, self) # remove :fire in context "self"
|
39
|
+
# @model.rmext_off(:fire, &block) # remove :fire for specific handler
|
40
|
+
# @model.rmext_off(:fire) # remove all :fire in all knowns contexts
|
41
|
+
# @model.rmext_off(self) # remove all events in context "self"
|
42
|
+
# @model.rmext_off # remove all events in all known contexts
|
43
|
+
def rmext_off(event=nil, context=nil, &block)
|
44
|
+
if rmext_events_from_proxy?
|
45
|
+
rmext_events_from_proxy.off(event, context, &block)
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
if @rmext_events_proxy
|
49
|
-
@rmext_events_proxy.off_all
|
49
|
+
# remove all event callbacks from other objects in this object's "self"
|
50
|
+
def rmext_cleanup
|
51
|
+
if rmext_events_to_proxy?
|
52
|
+
rmext_events_to_proxy.cleanup
|
50
53
|
end
|
51
54
|
end
|
52
55
|
|
53
56
|
# trigger an event with value on this object
|
54
57
|
def rmext_trigger(event, value=nil)
|
55
|
-
if
|
56
|
-
|
58
|
+
if rmext_events_from_proxy?
|
59
|
+
rmext_events_from_proxy.trigger(event, value)
|
57
60
|
end
|
58
61
|
end
|
59
62
|
|
@@ -65,39 +68,80 @@ module RMExtensions
|
|
65
68
|
attr_accessor :context, :value, :target, :event
|
66
69
|
end
|
67
70
|
|
68
|
-
# Proxy
|
69
|
-
#
|
70
|
-
#
|
71
|
-
|
71
|
+
# Proxy object used to hold the firing objects that this real object's
|
72
|
+
# "self" owns handlers for.
|
73
|
+
# Can be used to cleanup all handlers across all firing objects that have
|
74
|
+
# the hanlder's owner (Proc#owner) == this real object.
|
75
|
+
# Does not need to perform deallocation logic as nothing is retained
|
76
|
+
# and the real object will fall out of the cooresponding EventsFromProxy
|
77
|
+
# automatically.
|
78
|
+
class EventsToProxy
|
79
|
+
|
80
|
+
rmext_zeroing_weak_attr_accessor :weak_object
|
81
|
+
|
82
|
+
def initialize(obj)
|
83
|
+
self.weak_object = obj
|
84
|
+
@has_handlers_for = NSHashTable.weakObjectsHashTable
|
85
|
+
end
|
86
|
+
|
87
|
+
def has_handlers_for!(firing_object)
|
88
|
+
if ::RMExtensions.debug?
|
89
|
+
p "CONTEXT:", weak_object.rmext_object_desc, "LISTENING TO:", firing_object.rmext_object_desc
|
90
|
+
end
|
91
|
+
@has_handlers_for.addObject(firing_object)
|
92
|
+
end
|
93
|
+
|
94
|
+
def cleanup(firing_object=nil)
|
95
|
+
# p "cleanup caller", caller
|
96
|
+
if firing_object
|
97
|
+
if @has_handlers_for.containsObject(firing_object)
|
98
|
+
if ::RMExtensions.debug?
|
99
|
+
p "CONTEXT:", weak_object.rmext_object_desc, "UNLISTENING TO:", firing_object.rmext_object_desc
|
100
|
+
end
|
101
|
+
@has_handlers_for.removeObject(firing_object)
|
102
|
+
firing_object.rmext_off(weak_object)
|
103
|
+
end
|
104
|
+
else
|
105
|
+
while firing_object = @has_handlers_for.anyObject
|
106
|
+
if ::RMExtensions.debug?
|
107
|
+
p "CONTEXT:", weak_object.rmext_object_desc, "UNLISTENING TO:", firing_object.rmext_object_desc
|
108
|
+
end
|
109
|
+
@has_handlers_for.removeObject(firing_object)
|
110
|
+
firing_object.rmext_off(weak_object)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
true
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
# Proxy class used to hold the actual handlers and contexts of handlers.
|
119
|
+
# When the real class deallocates, all handlers are removed.
|
120
|
+
class EventsFromProxy
|
121
|
+
|
122
|
+
rmext_zeroing_weak_attr_accessor :weak_object
|
72
123
|
|
73
124
|
def initialize(obj)
|
74
|
-
|
125
|
+
self.weak_object = obj
|
75
126
|
@events = NSMapTable.weakToStrongObjectsMapTable
|
76
|
-
@listenings = NSHashTable.weakObjectsHashTable
|
77
127
|
if ::RMExtensions.debug?
|
78
|
-
p "CREATED
|
128
|
+
p "CREATED #{className}: #{weak_object.rmext_object_desc}"
|
79
129
|
end
|
80
130
|
end
|
81
131
|
|
82
132
|
def dealloc
|
83
|
-
@did_dealloc = true
|
84
|
-
|
133
|
+
# @did_dealloc = true
|
134
|
+
off
|
85
135
|
if ::RMExtensions.debug?
|
86
|
-
p "DEALLOC
|
136
|
+
p "DEALLOC #{className}: #{weak_object.rmext_object_desc}"
|
87
137
|
end
|
88
138
|
super
|
89
139
|
end
|
90
140
|
|
91
|
-
def
|
92
|
-
off_all
|
93
|
-
off_all_context
|
94
|
-
true
|
95
|
-
end
|
96
|
-
|
97
|
-
def on(event, limit:limit, inContext:context, withBlock:block)
|
141
|
+
def on(event, opts={}, &block)
|
98
142
|
return if event.nil? || block.nil?
|
99
143
|
event = event.to_s
|
100
|
-
context
|
144
|
+
context = block.owner
|
101
145
|
unless context_events = @events.objectForKey(context)
|
102
146
|
context_events = {}
|
103
147
|
@events.setObject(context_events, forKey:context)
|
@@ -107,64 +151,66 @@ module RMExtensions
|
|
107
151
|
context_events.setObject(context_event_blocks, forKey:event)
|
108
152
|
end
|
109
153
|
block.weak!
|
110
|
-
context_event_blocks[block] = limit
|
111
|
-
# i.e.: controller/view
|
112
|
-
context.
|
113
|
-
end
|
114
|
-
|
115
|
-
# this is called in the reverse direction than normal
|
116
|
-
def listening_to(object)
|
117
|
-
if ::RMExtensions.debug?
|
118
|
-
p "CONTEXT:", @weak_object.rmext_object_desc, "LISTENING TO:", object.rmext_object_desc
|
119
|
-
end
|
120
|
-
@listenings.addObject(object)
|
154
|
+
context_event_blocks[block] = opts[:limit] || -1
|
155
|
+
# i.e.: controller/view has handlers for object
|
156
|
+
context.rmext_events_to_proxy.has_handlers_for!(weak_object)
|
121
157
|
end
|
122
158
|
|
123
|
-
def now_and_on(event,
|
159
|
+
def now_and_on(event, opts={}, &block)
|
124
160
|
rmext_inline_or_on_main_q do
|
125
161
|
res = EventResponse.new
|
126
|
-
res.context =
|
162
|
+
res.context = block.owner
|
127
163
|
res.value = nil
|
128
|
-
res.target =
|
164
|
+
res.target = weak_object
|
129
165
|
res.event = event
|
130
166
|
block.call(res)
|
131
167
|
end
|
132
|
-
on(event,
|
133
|
-
end
|
134
|
-
|
135
|
-
def off(event, inContext:context, withBlock:block)
|
136
|
-
return if event.nil? || block.nil?
|
137
|
-
event = event.to_s
|
138
|
-
context ||= self.class
|
139
|
-
return unless context_events = @events.objectForKey(context)
|
140
|
-
return unless context_event_blocks = context_events.objectForKey(event)
|
141
|
-
context_event_blocks.delete block
|
142
|
-
nil
|
143
|
-
end
|
144
|
-
|
145
|
-
def off_all
|
146
|
-
@events.removeAllObjects
|
168
|
+
on(event, opts, &block)
|
147
169
|
end
|
148
170
|
|
149
|
-
def
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
171
|
+
def off(event=nil, context=nil, &block)
|
172
|
+
if event.is_a?(String) || event.is_a?(Symbol)
|
173
|
+
event = event.to_s
|
174
|
+
if context
|
175
|
+
# remove all handlers for the given event in the given context
|
176
|
+
if context_events = @events.objectForKey(context)
|
177
|
+
context_events.delete(event)
|
178
|
+
end
|
179
|
+
elsif block
|
180
|
+
# remove the one block for the event in the blocks #owner
|
181
|
+
context = block.owner
|
182
|
+
if context_events = @events.objectForKey(context)
|
183
|
+
if context_event_blocks = context_events.objectForKey(event)
|
184
|
+
context_event_blocks.delete block
|
185
|
+
end
|
186
|
+
end
|
187
|
+
else
|
188
|
+
# remove all handlers for the event in all contexts known
|
189
|
+
keyEnumerator = @events.keyEnumerator
|
190
|
+
contexts = []
|
191
|
+
while context = keyEnumerator.nextObject
|
192
|
+
contexts.push context
|
193
|
+
end
|
194
|
+
while context = contexts.pop
|
195
|
+
if context_events = @events.objectForKey(context)
|
196
|
+
context_events.delete event
|
197
|
+
end
|
198
|
+
end
|
161
199
|
end
|
200
|
+
elsif event
|
201
|
+
# event is really a context. remove all events and handlers for the context
|
202
|
+
context = event
|
203
|
+
@events.removeObjectForKey(context)
|
204
|
+
else
|
205
|
+
# remove everything
|
206
|
+
@events.removeAllObjects
|
162
207
|
end
|
208
|
+
nil
|
163
209
|
end
|
164
210
|
|
165
211
|
def trigger(event, value)
|
166
212
|
rmext_inline_or_on_main_q do
|
167
|
-
next if @did_dealloc
|
213
|
+
# next if @did_dealloc
|
168
214
|
next if event.nil?
|
169
215
|
event = event.to_s
|
170
216
|
keyEnumerator = @events.keyEnumerator
|
@@ -177,24 +223,24 @@ module RMExtensions
|
|
177
223
|
if event_blocks = context_events[event]
|
178
224
|
blocks = event_blocks.keys
|
179
225
|
if ::RMExtensions.debug?
|
180
|
-
p "TRIGGER:", event, "OBJECT:",
|
226
|
+
p "TRIGGER:", event, "OBJECT:", weak_object.rmext_object_desc, "CONTEXT:", context.rmext_object_desc, "BLOCKS SIZE:", blocks.size
|
181
227
|
end
|
182
228
|
while block = blocks.pop
|
183
229
|
limit = event_blocks[block]
|
184
230
|
res = EventResponse.new
|
185
231
|
res.context = context
|
186
232
|
res.value = value
|
187
|
-
res.target =
|
233
|
+
res.target = weak_object
|
188
234
|
res.event = event
|
189
235
|
block.call(res)
|
190
236
|
if limit == 1
|
191
237
|
# off
|
192
238
|
if ::RMExtensions.debug?
|
193
|
-
p "LIMIT REACHED:", event, "OBJECT:",
|
239
|
+
p "LIMIT REACHED:", event, "OBJECT:", weak_object.rmext_object_desc, "CONTEXT:", context.rmext_object_desc
|
194
240
|
end
|
195
|
-
off(event,
|
241
|
+
off(event, context, &block)
|
196
242
|
elsif limit > 1
|
197
|
-
|
243
|
+
event_blocks[block] -= 1
|
198
244
|
end
|
199
245
|
end
|
200
246
|
end
|
data/lib/motion/util.rb
CHANGED
@@ -34,7 +34,7 @@ module RMExtensions
|
|
34
34
|
if ::RMExtensions::LongTask.outstanding_tasks.size.zero?
|
35
35
|
rmext_block_on_main_q(block)
|
36
36
|
else
|
37
|
-
|
37
|
+
::RMExtensions::LongTask.rmext_once(:all_complete) do |opts|
|
38
38
|
block.call
|
39
39
|
end
|
40
40
|
end
|
@@ -115,7 +115,7 @@ module RMExtensions
|
|
115
115
|
if @tracking
|
116
116
|
::RMExtensions::LongTask.outstanding_queue.sync do
|
117
117
|
::RMExtensions::LongTask.outstanding_tasks.delete(self)
|
118
|
-
::RMExtensions::LongTask.internal do |internal_task|
|
118
|
+
::RMExtensions::LongTask.internal("check for all complete") do |internal_task|
|
119
119
|
rmext_on_main_q do
|
120
120
|
if ::RMExtensions::LongTask.outstanding_tasks.size.zero?
|
121
121
|
::RMExtensions::LongTask.rmext_trigger(:all_complete)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rm-extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe Noon
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-01-
|
11
|
+
date: 2014-01-28 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Extensions and helpers for dealing with various areas of rubymotion
|
14
14
|
email:
|