cha_work 0.1
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 +7 -0
- data/README.md +23 -0
- data/lib/cha_work.rb +13 -0
- data/lib/cha_work/ChaMenu/cha_menu.rb +93 -0
- data/lib/cha_work/basic.rb +556 -0
- data/lib/cha_work/chawork.rb +34 -0
- data/lib/cha_work/msg.rb +26 -0
- data/lib/cha_work/persistence.rb +58 -0
- data/lib/cha_work/sugar/fixnum.rb +30 -0
- data/lib/cha_work/sugar/notificationcenter.rb +22 -0
- data/lib/cha_work/sugar/nsdate.rb +261 -0
- data/lib/cha_work/sugar/nsstring.rb +73 -0
- data/lib/cha_work/sugar/symbol.rb +865 -0
- data/lib/cha_work/sugar/time.rb +81 -0
- data/lib/cha_work/sugar/uiactionsheet.rb +189 -0
- data/lib/cha_work/sugar/uibutton.rb +7 -0
- data/lib/cha_work/sugar/uicontrol.rb +99 -0
- data/lib/cha_work/sugar/uiimageview.rb +4 -0
- data/lib/cha_work/sugar/uilabel.rb +21 -0
- data/lib/cha_work/sugar/uitableview.rb +13 -0
- data/lib/cha_work/sugar/uiview.rb +306 -0
- data/lib/cha_work/sugar/uiviewcontroller.rb +18 -0
- data/lib/cha_work/table/table.rb +151 -0
- data/lib/cha_work/table/table_screen.rb +6 -0
- data/lib/cha_work/version.rb +3 -0
- metadata +81 -0
@@ -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,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,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
|