cha_work 0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,81 @@
1
+ class Numeric
2
+
3
+ def milliseconds
4
+ self / 1000.0
5
+ end
6
+ alias millisecond milliseconds
7
+ alias millisecs milliseconds
8
+ alias millisec milliseconds
9
+
10
+ def in_milliseconds
11
+ self * 1000
12
+ end
13
+
14
+ def seconds
15
+ self
16
+ end
17
+ alias second seconds
18
+ alias sec seconds
19
+ alias secs seconds
20
+
21
+ def in_seconds
22
+ self
23
+ end
24
+
25
+ def minutes
26
+ self * 60
27
+ end
28
+ alias minute minutes
29
+ alias min minutes
30
+ alias mins minutes
31
+
32
+ def in_minutes
33
+ self / 1.minute.to_f
34
+ end
35
+
36
+ def hours
37
+ self * 3600
38
+ end
39
+ alias hour hours
40
+
41
+ def in_hours
42
+ self / 1.hour.to_f
43
+ end
44
+
45
+ def days
46
+ self.hours * 24
47
+ end
48
+ alias day days
49
+
50
+ def in_days
51
+ self / 1.day.to_f
52
+ end
53
+
54
+ def weeks
55
+ self.days * 7
56
+ end
57
+ alias week weeks
58
+
59
+ def in_weeks
60
+ self / 1.week.to_f
61
+ end
62
+
63
+ def months
64
+ self.days * 30
65
+ end
66
+ alias month months
67
+
68
+ def in_months
69
+ self / 1.month.to_f
70
+ end
71
+
72
+ def years
73
+ self.days * 365
74
+ end
75
+ alias year years
76
+
77
+ def in_years
78
+ self / 1.year.to_f
79
+ end
80
+
81
+ end
@@ -0,0 +1,189 @@
1
+ class UIActionSheet
2
+
3
+ # For the purposes of whether the cancel or success handler gets called, the
4
+ # first button is considered the 'cancel' button, the second button is the
5
+ # 'destructive' button, and the rest are plain old buttons.
6
+ #
7
+ # If you use just one block, it will be used for *all* of the buttons.
8
+ #
9
+ # @example
10
+ # # use a different handler for each button type
11
+ # UIActionSheet.alert("title",
12
+ # buttons: %w"Cancel Delete No-way",
13
+ # cancel: proc{ puts "nevermind" },
14
+ # destructive: proc{ puts "OHHH YEAAH!" },
15
+ # success: proc{ |pressed| puts "pressed: #{pressed}" },
16
+ # )
17
+ # # use one handler for all buttons
18
+ # UIActionSheet.alert("title", buttons: [...]) { |button| }
19
+ def self.alert(title, options={}, &block)
20
+ if title.is_a?(NSDictionary)
21
+ options = title
22
+ title = options[:title]
23
+ end
24
+
25
+ # create the delegate
26
+ delegate = ChaWork::ActionSheetDelegate.new
27
+ delegate.on_default = block
28
+ delegate.on_success = options[:success]
29
+ delegate.on_destructive = options[:destructive]
30
+ delegate.on_cancel = options[:cancel]
31
+ delegate.send(:retain)
32
+
33
+ args = [title] # initWithTitle:
34
+ args << delegate # delegate:
35
+
36
+ buttons = (options[:buttons] || []).freeze
37
+ if buttons.empty?
38
+ buttons = [] # an empty Hash becomes an Array
39
+
40
+ # cancelButtonTitle:
41
+ buttons << nil
42
+
43
+ # destructiveButtonTitle
44
+ buttons << nil
45
+
46
+ # otherButtonTitles:
47
+ buttons << 'OK'
48
+ elsif buttons.length == 1 && (options[:cancel] || options[:destructive])
49
+ raise 'If you only have one button, use a :success handler, not :cancel or :destructive'
50
+ end
51
+
52
+ # the button titles, mapped to how UIActionSheet orders them. These are
53
+ # passed to the success handler.
54
+ buttons_mapped = {}
55
+
56
+ # cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:
57
+ # uses localized buttons in the actual alert
58
+ if buttons.is_a?(NSDictionary)
59
+ button_keys = buttons.keys
60
+ if buttons.key?(:cancel)
61
+ args << (buttons[:cancel] && NSBundle.mainBundle.localizedStringForKey(buttons[:cancel], value: nil, table: nil))
62
+ else
63
+ args << nil
64
+ end
65
+ if buttons.key?(:destructive)
66
+ args << (buttons[:destructive] && NSBundle.mainBundle.localizedStringForKey(buttons[:destructive], value: nil, table: nil))
67
+ else
68
+ args << nil
69
+ end
70
+ args.concat(buttons.select { |k, m| k != :cancel && k != :destructive }.map { |k, m| m && NSBundle.mainBundle.localizedStringForKey(m, value: nil, table: nil) })
71
+ else
72
+ button_keys = buttons
73
+ args.concat(buttons.map { |m| m && NSBundle.mainBundle.localizedStringForKey(m, value: nil, table: nil) })
74
+ end
75
+ args << nil # otherButtonTitles:..., nil
76
+
77
+ if args[2] && args[3] # cancel && destructive buttons
78
+ buttons_mapped[0] = button_keys[1] # destructiveIndex == 0, button == 1
79
+ buttons_mapped[button_keys.length - 1] = button_keys[0] # cancelIndex == last, button == 0
80
+ # from first+1 to last-1
81
+ button_keys[2..-1].each_with_index do |button,index|
82
+ buttons_mapped[index + 1] = button
83
+ end
84
+ elsif args[3] # destructive button
85
+ buttons_mapped[0] = button_keys[1] # destructiveIndex == 0, button == 1
86
+ # from first+1 to last-1
87
+ buttons[2..-1].each_with_index do |button,index|
88
+ buttons_mapped[index + 1] = button
89
+ end
90
+ elsif args[2] # cancel button
91
+ buttons_mapped[buttons.length - 2] = button_keys[0] # cancelIndex == last, button == 0
92
+ button_keys[2..-1].each_with_index do |button,index|
93
+ buttons_mapped[index] = button
94
+ end
95
+ else
96
+ button_keys[2..-1].each_with_index do |button,index|
97
+ buttons_mapped[index] = button
98
+ end
99
+ end
100
+ delegate.buttons = buttons_mapped
101
+
102
+ alert = self.alloc
103
+ alert.send('initWithTitle:delegate:cancelButtonTitle:destructiveButtonTitle:otherButtonTitles:', *args)
104
+
105
+ if options.key?(:style)
106
+ style = options[:style]
107
+ if style.respond_to?(:uiactionstyle)
108
+ style = style.uiactionstyle
109
+ end
110
+ alert.actionSheetStyle = style
111
+ end
112
+
113
+ if options.fetch(:show, true)
114
+ if options.key?(:from)
115
+ from = options[:from]
116
+ else
117
+ from = UIApplication.sharedApplication.windows[0]
118
+ end
119
+
120
+ case from
121
+ when CGRect
122
+ view = options.fetch(:view, UIApplication.sharedApplication.windows[0])
123
+ alert.showFromRect(from, inView: view, animated: true)
124
+ when UIBarButtonItem
125
+ alert.showFromBarButtonItem(from, animated: true)
126
+ when UIToolbar
127
+ alert.showFromToolbar(from)
128
+ when UITabBar
129
+ alert.showFromTabBar(from)
130
+ when UIView
131
+ alert.showInView(from)
132
+ else
133
+ raise "Unknown :from option #{from.inspect}"
134
+ end
135
+ end
136
+
137
+ alert
138
+ end
139
+
140
+ def <<(title)
141
+ addButtonWithTitle(title)
142
+ end
143
+
144
+ private
145
+ def dummy
146
+ self.initWithTitle(nil, delegate:nil, cancelButtonTitle:nil, destructiveButtonTitle:nil, otherButtonTitles:nil)
147
+ end
148
+
149
+ end
150
+
151
+
152
+ module ChaWork
153
+ class ActionSheetDelegate
154
+ attr_accessor :buttons
155
+ attr_accessor :on_default
156
+ attr_accessor :on_cancel
157
+ attr_accessor :on_destructive
158
+ attr_accessor :on_success
159
+
160
+ def actionSheet(alert, didDismissWithButtonIndex: index)
161
+ handler = nil
162
+ if index == alert.destructiveButtonIndex && on_destructive
163
+ handler = on_destructive
164
+ elsif index == alert.cancelButtonIndex && on_cancel
165
+ handler = on_cancel
166
+ elsif index != alert.destructiveButtonIndex && index != alert.cancelButtonIndex && on_success
167
+ handler = on_success
168
+ end
169
+ handler ||= on_default
170
+
171
+ if handler
172
+ if handler.arity == 0
173
+ handler.call
174
+ else
175
+ button = buttons[index]
176
+
177
+ if handler.arity == 1
178
+ handler.call(button)
179
+ else
180
+ handler.call(button, index)
181
+ end
182
+ end
183
+ end
184
+
185
+ self.send(:autorelease)
186
+ end
187
+
188
+ end
189
+ end
@@ -0,0 +1,7 @@
1
+ class UIButton
2
+
3
+ def title=(text)
4
+ self.setTitle(text, forState:UIControlStateNormal)
5
+ self
6
+ end
7
+ end
@@ -0,0 +1,99 @@
1
+ # Additions to UIControl to support jQuery-style `on` and `off` methods.
2
+ class UIControl
3
+
4
+ # Add event handlers to UIControls. See symbol.rb for the uicontrolevent
5
+ # constant aliases.
6
+ #
7
+ # @example
8
+ # button = UIButton.alloc.initWithFrame([0, 0, 10, 10])
9
+ # button.on(:touch) { my_code }
10
+ # button.on(:touch_up_outside, :touch_cancel) { my_code }
11
+ # # up to two arguments can be passed in
12
+ # button.on(:touch) { |sender,touch_event| my_code }
13
+ def on(*events, &block)
14
+ handler = ChaWork::UIControlCallbackHelper.new(block)
15
+
16
+ events.each do |event|
17
+ event = event.uicontrolevent if event.respond_to?(:uicontrolevent)
18
+
19
+ sugarcube_callbacks(event).push(handler)
20
+ self.addTarget(handler, action:'call:event:', forControlEvents:event)
21
+ end
22
+
23
+ self
24
+ end
25
+
26
+ # Removes all events that were bound with `on`. See symbol.rb for the
27
+ # uicontrolevent constant aliases.
28
+ #
29
+ # @example
30
+ # button.off(:touch)
31
+ # button.off(:touch_up_outside, :touch_cancel)
32
+ # button.off # all events
33
+ def off(*events)
34
+ if events.length == 0
35
+ events = sugarcube_callbacks.keys
36
+ end
37
+
38
+ events.each do |event|
39
+ event = event.uicontrolevent if event.respond_to?(:uicontrolevent)
40
+
41
+ sugarcube_callbacks(event).each do |handler|
42
+ self.removeTarget(handler, action:'call:event:', forControlEvents:event)
43
+ end
44
+ sugarcube_callbacks.delete(event)
45
+ end
46
+
47
+ self
48
+ end
49
+
50
+ # Useful during testing, or to simulate a button press.
51
+ #
52
+ # @example
53
+ # button.trigger(:touch)
54
+ # button.trigger(:touch_drag_outside, :touch_drag_exits)
55
+ def trigger(*events)
56
+ event_mask = 0
57
+ events.each do |event|
58
+ event = event.uicontrolevent if event.respond_to?(:uicontrolevent)
59
+ event_mask |= event
60
+ end
61
+ sendActionsForControlEvents(event_mask)
62
+ end
63
+
64
+ private
65
+ # event blocks need to be retained, and the addTarget method explicitly does
66
+ # *not* retain `target`. This makes sure that callbacks are retained by
67
+ # pushing the block onto a stack.
68
+ def sugarcube_callbacks(event=nil)
69
+ @sugarcube_callbacks ||= {}
70
+ if event
71
+ @sugarcube_callbacks[event] ||= []
72
+ return @sugarcube_callbacks[event]
73
+ else
74
+ return @sugarcube_callbacks
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+
81
+ module ChaWork
82
+ class UIControlCallbackHelper
83
+
84
+ def initialize(callback)
85
+ @callback = callback.respond_to?('weak!') ? callback.weak! : callback
86
+ end
87
+
88
+ def call(sender, event:event)
89
+ case @callback.arity
90
+ when 0
91
+ @callback.call
92
+ when 1
93
+ @callback.call(sender)
94
+ else
95
+ @callback.call(sender, event)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,4 @@
1
+ class UIImageView
2
+
3
+
4
+ end
@@ -0,0 +1,21 @@
1
+ class UILabel
2
+
3
+ def on
4
+ self.becomeFirstResponder
5
+ end
6
+
7
+ def off
8
+ self.resignFirstResponder
9
+ end
10
+
11
+ def color(value)
12
+ self.textColor = value.class == UIColor ? value : value.uicolor
13
+ self
14
+ end
15
+
16
+ def size(value)
17
+ self.font = UIFont.systemFontOfSize(value)
18
+ self
19
+ end
20
+
21
+ end
@@ -0,0 +1,13 @@
1
+ class UITableView
2
+ class << self
3
+
4
+ def plain(frame=[[0, 0], [0, 0]])
5
+ UITableView.alloc.initWithFrame(frame, style: UITableViewStylePlain)
6
+ end
7
+
8
+ def grouped(frame=[[0, 0], [0, 0]])
9
+ UITableView.alloc.initWithFrame(frame, style: UITableViewStyleGrouped)
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,306 @@
1
+ class UIView
2
+
3
+ class << self
4
+
5
+ def attr_updates(*attrs)
6
+ attr_accessor(*attrs)
7
+ attrs.each do |attr|
8
+ define_method("#{attr}=") do |value|
9
+ if instance_variable_get("@#{attr}") != value
10
+ setNeedsDisplay
11
+ end
12
+ willChangeValueForKey(attr)
13
+ instance_variable_set("@#{attr}", value)
14
+ didChangeValueForKey(attr)
15
+ end
16
+ end
17
+ end
18
+
19
+ end
20
+
21
+ # superview << view
22
+ # => superview.addSubview(view)
23
+ def <<(view)
24
+ self.addSubview(view)
25
+ return self
26
+ end
27
+
28
+
29
+ def show
30
+ self.hidden = false
31
+ return self
32
+ end
33
+
34
+ def hide
35
+ self.hidden = true
36
+ return self
37
+ end
38
+
39
+ # Easily take a snapshot of a `UIView`.
40
+ #
41
+ # Calling `uiimage` with no arguments will return the image based on the
42
+ # `bounds` of the image. In the case of container views (notably
43
+ # `UIScrollView` and its children) this does not include the entire contents,
44
+ # which is something you probably want.
45
+ #
46
+ # If you pass a truthy value to this method, it will use the `contentSize` of
47
+ # the view instead of the `bounds`, and it will draw all the child views, not
48
+ # just those that are visible in the viewport.
49
+ #
50
+ # It is guaranteed that `true` and `:all` will always have this behavior. In
51
+ # the future, if this argument becomes something that accepts multiple values,
52
+ # those two are sacred.
53
+ def uiimage(use_content_size=false)
54
+ if use_content_size
55
+ UIGraphicsBeginImageContextWithOptions(contentSize, false, 0.0)
56
+ context = UIGraphicsGetCurrentContext()
57
+ self.subviews.each do |subview|
58
+ CGContextSaveGState(context)
59
+ CGContextTranslateCTM(context, subview.frame.origin.x, subview.frame.origin.y)
60
+ subview.layer.renderInContext(context)
61
+ CGContextRestoreGState(context)
62
+ end
63
+ image = UIGraphicsGetImageFromCurrentImageContext()
64
+ UIGraphicsEndImageContext()
65
+ else
66
+ UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0.0)
67
+ if self.respond_to?('drawViewHierarchyInRect:afterScreenUpdates:')
68
+ self.drawViewHierarchyInRect(self.bounds, afterScreenUpdates: true)
69
+ else
70
+ layer.renderInContext(UIGraphicsGetCurrentContext())
71
+ end
72
+ image = UIGraphicsGetImageFromCurrentImageContext()
73
+ UIGraphicsEndImageContext()
74
+ end
75
+ return image
76
+ end
77
+
78
+ # A generic gesture adder, but accepts a block like the other gesture methods
79
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
80
+ # @param options [Hash] method/value pairs to call on the gesture.
81
+ # @overload on_gesture(recognizer)
82
+ # Adds the gesture to the view, and yields the block when the gesture is recognized
83
+ # @overload on_gesture(recognizer_class)
84
+ # Instantiates a gesture and adds it to the view.
85
+ # @example Using a UIGestureRecognizer class
86
+ # view.on_gesture(UISwipeGestureRecognizer, direction: UISwipeGestureRecognizerDirectionLeft) { puts "swiped left" }
87
+ # @example Using a UIGestureRecognizer instance
88
+ # gesture = UISwipeGestureRecognizer
89
+ # gesture.direction = UISwipeGestureRecognizerDirectionLeft
90
+ # view.on_gesture(gesture) { puts "swiped left" }
91
+ def on_gesture(klass, options={}, &proc)
92
+ if klass.is_a? UIGestureRecognizer
93
+ recognizer = klass
94
+ recognizer.addTarget(self, action:'sugarcube_handle_gesture:')
95
+ else
96
+ recognizer = klass.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
97
+ end
98
+
99
+ options.each do |method, value|
100
+ recognizer.send(method, value)
101
+ end
102
+ sugarcube_add_gesture(proc, recognizer)
103
+ end
104
+
105
+ def off_gestures
106
+ if @sugarcube_recognizers
107
+ @sugarcube_recognizers.each do |recognizer, proc|
108
+ self.removeGestureRecognizer(recognizer)
109
+ end
110
+ @sugarcube_recognizers = nil
111
+ end
112
+
113
+ self
114
+ end
115
+
116
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
117
+ # @overload on_tap(taps)
118
+ # @param taps [Fixnum] Number of taps
119
+ # @overload on_tap(options)
120
+ # @option options [Fixnum] :taps Number of taps before gesture is recognized
121
+ # @option options [Fixnum] :fingers Number of fingers before gesture is recognized
122
+ def on_tap(taps_or_options=nil, &proc)
123
+ taps = nil
124
+ fingers = nil
125
+
126
+ if taps_or_options
127
+ if taps_or_options.is_a? Hash
128
+ taps = taps_or_options[:taps] || taps
129
+ fingers = taps_or_options[:fingers] || fingers
130
+ else
131
+ taps = taps_or_options
132
+ end
133
+ end
134
+
135
+ recognizer = UITapGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
136
+ recognizer.numberOfTapsRequired = taps if taps
137
+ recognizer.numberOfTouchesRequired = fingers if fingers
138
+ sugarcube_add_gesture(proc, recognizer)
139
+ end
140
+
141
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
142
+ def on_pinch(&proc)
143
+ recognizer = UIPinchGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
144
+ sugarcube_add_gesture(proc, recognizer)
145
+ end
146
+
147
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
148
+ def on_rotate(&proc)
149
+ recognizer = UIRotationGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
150
+ sugarcube_add_gesture(proc, recognizer)
151
+ end
152
+
153
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
154
+ # @overload on_swipe(taps)
155
+ # @param direction [Fixnum] Direction of swipe
156
+ # @overload on_swipe(options)
157
+ # @option options [Fixnum] :fingers Number of fingers before gesture is recognized
158
+ # @option options [Fixnum, Symbol] :direction Direction of swipe, as a UISwipeGestureRecognizerDirection constant or a symbol (`:left, :right, :up, :down`)
159
+ def on_swipe(direction_or_options=nil, &proc)
160
+ direction = nil
161
+ fingers = nil
162
+
163
+ if direction_or_options
164
+ if direction_or_options.is_a? Hash
165
+ direction = direction_or_options[:direction] || direction
166
+ fingers = direction_or_options[:fingers] || fingers
167
+ else
168
+ direction = direction_or_options
169
+ end
170
+ end
171
+
172
+ case direction
173
+ when :left
174
+ direction = UISwipeGestureRecognizerDirectionLeft
175
+ when :right
176
+ direction = UISwipeGestureRecognizerDirectionRight
177
+ when :up
178
+ direction = UISwipeGestureRecognizerDirectionUp
179
+ when :down
180
+ direction = UISwipeGestureRecognizerDirectionDown
181
+ end
182
+
183
+ recognizer = UISwipeGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
184
+ recognizer.direction = direction if direction
185
+ recognizer.numberOfTouchesRequired = fingers if fingers
186
+ sugarcube_add_gesture(proc, recognizer)
187
+ end
188
+
189
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
190
+ # @overload on_tap(taps)
191
+ # @param taps [Fixnum] Number of taps
192
+ # @overload on_tap(options)
193
+ # @option options [Fixnum] :min_fingers Minimum number of fingers for gesture to be recognized
194
+ # @option options [Fixnum] :max_fingers Maximum number of fingers for gesture to be recognized
195
+ # @option options [Fixnum] :fingers If min_fingers or max_fingers is not assigned, this will be the default.
196
+ def on_pan(fingers_or_options=nil, &proc)
197
+ fingers = nil
198
+ min_fingers = nil
199
+ max_fingers = nil
200
+
201
+ if fingers_or_options
202
+ if fingers_or_options.is_a? Hash
203
+ fingers = fingers_or_options[:fingers] || fingers
204
+ min_fingers = fingers_or_options[:min_fingers] || min_fingers
205
+ max_fingers = fingers_or_options[:max_fingers] || max_fingers
206
+ else
207
+ fingers = fingers_or_options
208
+ end
209
+ end
210
+
211
+ # if fingers is assigned, but not min/max, assign it as a default
212
+ min_fingers ||= fingers
213
+ max_fingers ||= fingers
214
+
215
+ recognizer = UIPanGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
216
+ recognizer.maximumNumberOfTouches = min_fingers if min_fingers
217
+ recognizer.minimumNumberOfTouches = max_fingers if max_fingers
218
+ sugarcube_add_gesture(proc, recognizer)
219
+ end
220
+
221
+ # @yield [recognizer] Handles the gesture event, and passes the recognizer instance to the block.
222
+ # @overload on_press(duration)
223
+ # @param duration [Fixnum] How long in seconds before gesture is recognized
224
+ # @overload on_tap(options)
225
+ # @option options [Fixnum] :duration How long in seconds before gesture is recognized
226
+ # @option options [Fixnum] :taps Number of taps before gesture is recognized
227
+ # @option options [Fixnum] :fingers Number of fingers before gesture is recognized
228
+ def on_press(duration_or_options=nil, &proc)
229
+ duration = nil
230
+ taps = nil
231
+ fingers = nil
232
+
233
+ if duration_or_options
234
+ if duration_or_options.is_a? Hash
235
+ duration = duration_or_options[:duration] || duration
236
+ taps = duration_or_options[:taps] || taps
237
+ fingers = duration_or_options[:fingers] || fingers
238
+ else
239
+ duration = duration_or_options
240
+ end
241
+ end
242
+
243
+ recognizer = UILongPressGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture:')
244
+ recognizer.minimumPressDuration = duration if duration
245
+ recognizer.numberOfTapsRequired = taps if taps
246
+ recognizer.numberOfTouchesRequired = fingers if fingers
247
+ sugarcube_add_gesture(proc, recognizer)
248
+ end
249
+
250
+ def on_press_begin(duration_or_options=nil, &proc)
251
+ duration = nil
252
+ taps = nil
253
+ fingers = nil
254
+
255
+ if duration_or_options
256
+ if duration_or_options.is_a? Hash
257
+ duration = duration_or_options[:duration] || duration
258
+ taps = duration_or_options[:taps] || taps
259
+ fingers = duration_or_options[:fingers] || fingers
260
+ else
261
+ duration = duration_or_options
262
+ end
263
+ end
264
+
265
+ recognizer = UILongPressGestureRecognizer.alloc.initWithTarget(self, action:'sugarcube_handle_gesture_long_press_on_begin:')
266
+ recognizer.minimumPressDuration = duration if duration
267
+ recognizer.numberOfTapsRequired = taps if taps
268
+ recognizer.numberOfTouchesRequired = fingers if fingers
269
+ sugarcube_add_gesture(proc, recognizer)
270
+ end
271
+
272
+
273
+ private
274
+ def sugarcube_handle_gesture(recognizer)
275
+ handler = @sugarcube_recognizers[recognizer]
276
+ if handler.arity == 0
277
+ handler.call
278
+ else
279
+ handler.call(recognizer)
280
+ end
281
+ end
282
+ def sugarcube_handle_gesture_long_press_on_begin(recognizer)
283
+ if recognizer.state==UIGestureRecognizerStateBegan
284
+ handler = @sugarcube_recognizers[recognizer]
285
+ if handler.arity == 0
286
+ handler.call
287
+ else
288
+ handler.call(recognizer)
289
+ end
290
+ end
291
+ end
292
+
293
+ # Adds the recognizer and keeps a strong reference to the Proc object.
294
+ def sugarcube_add_gesture(proc, recognizer)
295
+ unless self.userInteractionEnabled?
296
+ puts("SugarCube: userInteractionEnabled is false on #{self.inspect}. Adding a gesture will have no effect.")
297
+ end
298
+ self.addGestureRecognizer(recognizer)
299
+
300
+ @sugarcube_recognizers = {} unless @sugarcube_recognizers
301
+ @sugarcube_recognizers[recognizer] = proc.respond_to?('weak!') ? proc.weak! : proc
302
+
303
+ recognizer
304
+ end
305
+
306
+ end