bubble-wrap 1.2.0 → 1.3.0.osx
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 +8 -8
- data/CHANGELOG.md +4 -2
- data/Gemfile.lock +1 -1
- data/README.md +217 -7
- data/Rakefile +23 -2
- data/lib/bubble-wrap/camera.rb +10 -6
- data/lib/bubble-wrap/core.rb +14 -1
- data/lib/bubble-wrap/ext/motion_project_app.rb +8 -0
- data/lib/bubble-wrap/font.rb +3 -1
- data/lib/bubble-wrap/http.rb +2 -0
- data/lib/bubble-wrap/loader.rb +17 -2
- data/lib/bubble-wrap/location.rb +9 -6
- data/lib/bubble-wrap/media.rb +10 -6
- data/lib/bubble-wrap/test.rb +6 -1
- data/lib/bubble-wrap/ui.rb +5 -2
- data/lib/bubble-wrap/version.rb +2 -7
- data/motion/core.rb +6 -1
- data/motion/core/app.rb +3 -64
- data/motion/core/device.rb +0 -55
- data/motion/core/device/{camera.rb → ios/camera.rb} +0 -0
- data/motion/core/device/{camera_wrapper.rb → ios/camera_wrapper.rb} +0 -0
- data/motion/core/device/ios/screen.rb +75 -0
- data/motion/core/device/osx/screen.rb +18 -0
- data/motion/core/device/screen.rb +1 -69
- data/motion/core/ios/app.rb +71 -0
- data/motion/core/ios/device.rb +59 -0
- data/motion/core/osx/app.rb +15 -0
- data/motion/core/osx/device.rb +6 -0
- data/motion/core/string.rb +3 -2
- data/motion/http.rb +0 -364
- data/motion/http/query.rb +367 -0
- data/motion/http/response.rb +32 -0
- data/motion/test_suite_delegate.rb +58 -0
- data/motion/ui/ui_alert_view.rb +169 -0
- data/motion/ui/ui_bar_button_item.rb +55 -53
- data/motion/util/constants.rb +34 -32
- data/samples/alert/.gitignore +16 -0
- data/samples/alert/Gemfile +3 -0
- data/samples/alert/Rakefile +10 -0
- data/samples/alert/app/app_delegate.rb +8 -0
- data/samples/alert/app/controllers/alert_view_controller.rb +74 -0
- data/samples/alert/resources/Default-568h@2x.png +0 -0
- data/samples/alert/spec/main_spec.rb +9 -0
- data/samples/media/.gitignore +16 -0
- data/samples/media/Rakefile +11 -0
- data/samples/media/app/app_delegate.rb +8 -0
- data/samples/media/app/controllers/play_controller.rb +46 -0
- data/samples/media/resources/Default-568h@2x.png +0 -0
- data/samples/media/resources/test.mp3 +0 -0
- data/samples/media/spec/main_spec.rb +9 -0
- data/samples/osx/Gemfile +3 -0
- data/samples/osx/Gemfile.lock +10 -0
- data/samples/osx/Rakefile +11 -0
- data/samples/osx/app/app_delegate.rb +69 -0
- data/samples/osx/app/menu.rb +108 -0
- data/samples/osx/resources/Credits.rtf +29 -0
- data/samples/osx/spec/main_spec.rb +9 -0
- data/spec/motion/core/app_spec.rb +5 -164
- data/spec/motion/core/device/{camera_spec.rb → ios/camera_spec.rb} +0 -0
- data/spec/motion/core/device/{camera_wrapper_spec.rb → ios/camera_wrapper_spec.rb} +0 -0
- data/spec/motion/core/device/ios/device_spec.rb +74 -0
- data/spec/motion/core/device/{screen_spec.rb → ios/screen_spec.rb} +2 -1
- data/spec/motion/core/device/osx/screen_spec.rb +26 -0
- data/spec/motion/core/device_spec.rb +0 -71
- data/spec/motion/core/ios/app_spec.rb +180 -0
- data/spec/motion/core/kvo_spec.rb +23 -7
- data/spec/motion/core/ns_index_path_spec.rb +10 -2
- data/spec/motion/core/osx/app_spec.rb +15 -0
- data/spec/motion/core/string_spec.rb +11 -5
- data/spec/motion/core_spec.rb +13 -2
- data/spec/motion/http/query_spec.rb +731 -0
- data/spec/motion/http/response_spec.rb +44 -0
- data/spec/motion/http_spec.rb +0 -722
- data/spec/motion/{core → ui}/gestures_spec.rb +0 -0
- data/spec/motion/ui/ui_alert_view_spec.rb +1188 -0
- data/spec/motion/{core → ui}/ui_bar_button_item_spec.rb +80 -24
- data/spec/motion/{core → ui}/ui_control_spec.rb +0 -0
- data/spec/motion/util/constants_spec.rb +4 -4
- metadata +86 -26
@@ -0,0 +1,169 @@
|
|
1
|
+
module BW
|
2
|
+
class UIAlertView < ::UIAlertView
|
3
|
+
@callbacks = [
|
4
|
+
:will_present,
|
5
|
+
:did_present,
|
6
|
+
:on_system_cancel,
|
7
|
+
:enable_first_other_button?,
|
8
|
+
:on_click,
|
9
|
+
:will_dismiss,
|
10
|
+
:did_dismiss
|
11
|
+
]
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_reader :callbacks
|
15
|
+
|
16
|
+
def new(options = {}, &block)
|
17
|
+
view = alloc.initWithTitle(options[:title],
|
18
|
+
message: options[:message],
|
19
|
+
delegate: nil,
|
20
|
+
cancelButtonTitle: nil,
|
21
|
+
otherButtonTitles: nil
|
22
|
+
)
|
23
|
+
|
24
|
+
Array(options[:buttons]).each { |title| view.addButtonWithTitle(title) }
|
25
|
+
|
26
|
+
view.style = options[:style]
|
27
|
+
view.delegate = view
|
28
|
+
view.cancel_button_index = options[:cancel_button_index]
|
29
|
+
|
30
|
+
view.instance_variable_set(:@handlers, {})
|
31
|
+
options[:on_click] ||= block
|
32
|
+
|
33
|
+
callbacks.each do |callback|
|
34
|
+
view.send(callback, &options[callback]) if options[callback]
|
35
|
+
end
|
36
|
+
|
37
|
+
view
|
38
|
+
end
|
39
|
+
|
40
|
+
def default(options = {}, &block)
|
41
|
+
options = { buttons: "OK" }.merge!(options)
|
42
|
+
new(options.merge!(style: :default), &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def plain_text_input(options = {}, &block)
|
46
|
+
options = { buttons: ["Cancel", "OK"], cancel_button_index: 0 }.merge!(options)
|
47
|
+
new(options.merge!(style: :plain_text_input), &block)
|
48
|
+
end
|
49
|
+
|
50
|
+
def secure_text_input(options = {}, &block)
|
51
|
+
options = { buttons: ["Cancel", "OK"], cancel_button_index: 0 }.merge!(options)
|
52
|
+
new(options.merge!(style: :secure_text_input), &block)
|
53
|
+
end
|
54
|
+
|
55
|
+
def login_and_password_input(options = {}, &block)
|
56
|
+
options = { buttons: ["Cancel", "Log in"], cancel_button_index: 0 }.merge!(options)
|
57
|
+
new(options.merge!(style: :login_and_password_input), &block)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def style
|
62
|
+
alertViewStyle
|
63
|
+
end
|
64
|
+
|
65
|
+
def style=(value)
|
66
|
+
self.alertViewStyle = Constants.get("UIAlertViewStyle", value) if value
|
67
|
+
end
|
68
|
+
|
69
|
+
def cancel_button_index
|
70
|
+
cancelButtonIndex
|
71
|
+
end
|
72
|
+
|
73
|
+
def cancel_button_index=(value)
|
74
|
+
self.cancelButtonIndex = value if value
|
75
|
+
end
|
76
|
+
|
77
|
+
###############################################################################################
|
78
|
+
|
79
|
+
attr_accessor :clicked_button
|
80
|
+
protected :clicked_button=
|
81
|
+
|
82
|
+
class ClickedButton
|
83
|
+
def initialize(alert, index)
|
84
|
+
@index = index
|
85
|
+
@title = alert.buttonTitleAtIndex(index)
|
86
|
+
@cancel = alert.cancelButtonIndex == index
|
87
|
+
end
|
88
|
+
|
89
|
+
attr_reader :index, :title
|
90
|
+
def cancel?; @cancel end
|
91
|
+
end
|
92
|
+
|
93
|
+
###############################################################################################
|
94
|
+
|
95
|
+
attr_reader :handlers
|
96
|
+
protected :handlers
|
97
|
+
|
98
|
+
callbacks.each do |callback|
|
99
|
+
define_method(callback) do |&block|
|
100
|
+
return handlers[callback] unless block
|
101
|
+
|
102
|
+
handlers[callback] = block if block
|
103
|
+
self
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# UIAlertViewDelegate protocol ################################################################
|
108
|
+
|
109
|
+
def willPresentAlertView(alert)
|
110
|
+
alert.clicked_button = nil
|
111
|
+
handlers[:will_present].call(alert) if handlers[:will_present]
|
112
|
+
end
|
113
|
+
|
114
|
+
def didPresentAlertView(alert)
|
115
|
+
alert.clicked_button = nil
|
116
|
+
handlers[:did_present].call(alert) if handlers[:did_present]
|
117
|
+
end
|
118
|
+
|
119
|
+
def alertViewCancel(alert)
|
120
|
+
alert.clicked_button = nil
|
121
|
+
handlers[:on_system_cancel].call(alert) if handlers[:on_system_cancel]
|
122
|
+
end
|
123
|
+
|
124
|
+
def alertViewShouldEnableFirstOtherButton(alert)
|
125
|
+
alert.clicked_button = nil
|
126
|
+
handlers[:enable_first_other_button?].call(alert) if handlers[:enable_first_other_button?]
|
127
|
+
end
|
128
|
+
|
129
|
+
def alertView(alert, clickedButtonAtIndex:index)
|
130
|
+
alert.clicked_button = ClickedButton.new(alert, index)
|
131
|
+
handlers[:on_click].call(alert) if handlers[:on_click]
|
132
|
+
end
|
133
|
+
|
134
|
+
def alertView(alert, willDismissWithButtonIndex:index)
|
135
|
+
alert.clicked_button = ClickedButton.new(alert, index)
|
136
|
+
handlers[:will_dismiss].call(alert) if handlers[:will_dismiss]
|
137
|
+
end
|
138
|
+
|
139
|
+
def alertView(alert, didDismissWithButtonIndex:index)
|
140
|
+
alert.clicked_button = ClickedButton.new(alert, index)
|
141
|
+
handlers[:did_dismiss].call(alert) if handlers[:did_dismiss]
|
142
|
+
end
|
143
|
+
|
144
|
+
###############################################################################################
|
145
|
+
|
146
|
+
def plain_text_field
|
147
|
+
textFieldAtIndex(0) if style == UIAlertViewStylePlainTextInput
|
148
|
+
end
|
149
|
+
|
150
|
+
def secure_text_field
|
151
|
+
textFieldAtIndex(0) if style == UIAlertViewStyleSecureTextInput
|
152
|
+
end
|
153
|
+
|
154
|
+
def login_text_field
|
155
|
+
textFieldAtIndex(0) if style == UIAlertViewStyleLoginAndPasswordInput
|
156
|
+
end
|
157
|
+
|
158
|
+
def password_text_field
|
159
|
+
textFieldAtIndex(1) if style == UIAlertViewStyleLoginAndPasswordInput
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
Constants.register(
|
164
|
+
UIAlertViewStyleDefault,
|
165
|
+
UIAlertViewStylePlainTextInput,
|
166
|
+
UIAlertViewStyleSecureTextInput,
|
167
|
+
UIAlertViewStyleLoginAndPasswordInput
|
168
|
+
)
|
169
|
+
end
|
@@ -1,68 +1,70 @@
|
|
1
1
|
module BW
|
2
|
-
|
3
|
-
|
2
|
+
class UIBarButtonItem < ::UIBarButtonItem
|
3
|
+
class << self
|
4
|
+
def styled(type, *objects, &block)
|
5
|
+
action = block ? :call : nil
|
6
|
+
object = objects.size == 1 ? objects.first : objects
|
7
|
+
style = Constants.get("UIBarButtonItemStyle", type)
|
4
8
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
+
item = if object.is_a?(String)
|
10
|
+
alloc.initWithTitle(object,
|
11
|
+
style:style,
|
12
|
+
target:block,
|
13
|
+
action:action
|
14
|
+
)
|
15
|
+
elsif object.is_a?(UIImage)
|
16
|
+
alloc.initWithImage(object,
|
17
|
+
style:style,
|
18
|
+
target:block,
|
19
|
+
action:action
|
20
|
+
)
|
21
|
+
elsif object.is_a?(Array) && object.size == 2 && object.all? { |o| o.is_a?(UIImage) }
|
22
|
+
alloc.initWithImage(object[0],
|
23
|
+
landscapeImagePhone:object[1],
|
24
|
+
style:style,
|
25
|
+
target:block,
|
26
|
+
action:action
|
27
|
+
)
|
28
|
+
else
|
29
|
+
raise ArgumentError, "invalid object - #{object.inspect}"
|
30
|
+
end
|
9
31
|
|
10
|
-
|
11
|
-
|
12
|
-
style:style,
|
13
|
-
target:block,
|
14
|
-
action:action
|
15
|
-
)
|
16
|
-
elsif object.is_a?(UIImage)
|
17
|
-
::UIBarButtonItem.alloc.initWithImage(object,
|
18
|
-
style:style,
|
19
|
-
target:block,
|
20
|
-
action:action
|
21
|
-
)
|
22
|
-
elsif object.is_a?(Array) && object.size == 2 && object.all? { |o| o.is_a?(UIImage) }
|
23
|
-
::UIBarButtonItem.alloc.initWithImage(object[0],
|
24
|
-
landscapeImagePhone:object[1],
|
25
|
-
style:style,
|
26
|
-
target:block,
|
27
|
-
action:action
|
28
|
-
)
|
29
|
-
else
|
30
|
-
raise ArgumentError, "invalid object - #{object.inspect}"
|
32
|
+
item.instance_variable_set(:@target, block)
|
33
|
+
item
|
31
34
|
end
|
32
35
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
+
def system(type, &block)
|
37
|
+
action = block ? :call : nil
|
38
|
+
system_item = Constants.get("UIBarButtonSystemItem", type)
|
36
39
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
+
item = alloc.initWithBarButtonSystemItem(system_item, target:block, action:action)
|
41
|
+
item.instance_variable_set(:@target, block)
|
42
|
+
item
|
43
|
+
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
item.instance_variable_set(:@target, block)
|
46
|
-
item
|
47
|
-
end
|
45
|
+
def custom(view, &block)
|
46
|
+
view.when_tapped(true, &block) if block
|
47
|
+
alloc.initWithCustomView(view)
|
48
|
+
end
|
48
49
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
50
|
+
def new(options = {}, &block)
|
51
|
+
if options[:styled]
|
52
|
+
args = options.values_at(:title, :image, :landscape).compact
|
53
|
+
return styled(options[:styled], *args, &block)
|
54
|
+
end
|
53
55
|
|
54
|
-
|
55
|
-
if options[:styled]
|
56
|
-
args = options.values_at(:title, :image, :landscape).compact
|
57
|
-
return styled(options[:styled], *args, &block)
|
58
|
-
end
|
56
|
+
return system(options[:system], &block) if options[:system]
|
59
57
|
|
60
|
-
|
58
|
+
return custom(options[:custom], &block) if options[:custom]
|
59
|
+
return custom(options[:view], &block) if options[:view]
|
61
60
|
|
62
|
-
|
63
|
-
|
61
|
+
raise ArgumentError, "invalid options - #{options.inspect}"
|
62
|
+
end
|
64
63
|
|
65
|
-
|
64
|
+
def build(options = {}, &block)
|
65
|
+
NSLog "[DEPRECATED - BW::UIBarButtonItem.build] please use .new instead."
|
66
|
+
new(options, &block)
|
67
|
+
end
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
data/motion/util/constants.rb
CHANGED
@@ -1,38 +1,40 @@
|
|
1
1
|
# Stupid hack because the RubyMotion dependency detection has a bug.
|
2
|
-
module
|
3
|
-
|
2
|
+
module BubbleWrap
|
3
|
+
module Constants
|
4
|
+
module_function
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
# Looks like RubyMotiononly adds UIKit constants
|
7
|
+
# at compile time. If you don't use these
|
8
|
+
# directly in your code, they don't get added
|
9
|
+
# to Kernel and Constants.get crashes.
|
10
|
+
# Examples
|
11
|
+
# Constants.register UIReturnKeyDone, UIReturnKeyNext
|
12
|
+
def register(*ui_constants)
|
13
|
+
# do nothing, just get the constants in the code
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
16
|
+
# @param [String] base of the constant
|
17
|
+
# @param [Integer, NSArray, String, Symbol] the suffix of the constant
|
18
|
+
# when NSArray, will return the bitmask of all suffixes in the array
|
19
|
+
# @return [Integer] the constant for this base and suffix
|
20
|
+
# Examples
|
21
|
+
# get("UIReturnKey", :done) => UIReturnKeyDone == 9
|
22
|
+
# get("UIReturnKey", "done") => UIReturnKeyDone == 9
|
23
|
+
# get("UIReturnKey", 9) => 9
|
24
|
+
# get("UIImagePickerControllerSourceType", ["photo_library", "camera", "saved_photos_album"]) => 3
|
25
|
+
def get(base, *values)
|
26
|
+
value = values.size == 1 ? values.first : values.flatten
|
27
|
+
case value
|
28
|
+
when Numeric
|
29
|
+
value.to_i
|
30
|
+
when NSArray
|
31
|
+
value.reduce { |i, j|
|
32
|
+
get(base, i) | get(base, j)
|
33
|
+
}
|
34
|
+
else
|
35
|
+
value = value.to_s.camelize
|
36
|
+
Kernel.const_get("#{base}#{value}")
|
37
|
+
end
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
3
|
+
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
4
|
+
@window.rootViewController = AlertViewController.alloc.init
|
5
|
+
@window.makeKeyAndVisible
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
class AlertViewController < UIViewController
|
2
|
+
attr_reader :text_view
|
3
|
+
attr_reader :buttons
|
4
|
+
attr_reader :alerts
|
5
|
+
|
6
|
+
def init
|
7
|
+
super.tap do
|
8
|
+
@text_view = build_text_view
|
9
|
+
|
10
|
+
@buttons = []
|
11
|
+
@alerts = []
|
12
|
+
|
13
|
+
[:default, :plain_text_input, :secure_text_input, :login_and_password_input].each do |style|
|
14
|
+
@buttons << build_button(style.to_s)
|
15
|
+
@alerts << built_alert(style)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def viewDidLoad
|
21
|
+
super
|
22
|
+
|
23
|
+
self.view.backgroundColor = UIColor.grayColor
|
24
|
+
|
25
|
+
self.view.addSubview(self.text_view)
|
26
|
+
|
27
|
+
self.buttons.each_with_index do |button, index|
|
28
|
+
self.view.addSubview(button)
|
29
|
+
|
30
|
+
button.when(UIControlEventTouchUpInside) { self.alerts[index].show }
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def build_text_view
|
35
|
+
text_view = UITextView.alloc.initWithFrame([[0, 0], [320, 194]])
|
36
|
+
text_view.editable = false
|
37
|
+
text_view.text = "Waiting..."
|
38
|
+
text_view
|
39
|
+
end
|
40
|
+
|
41
|
+
def build_button(title)
|
42
|
+
button = UIButton.buttonWithType(UIButtonTypeRoundedRect)
|
43
|
+
button.setTitle(title, forState:UIControlStateNormal)
|
44
|
+
|
45
|
+
rect = self.buttons.empty? ? CGRectMake(20, 150, 280, 44) : self.buttons.last.frame
|
46
|
+
button.frame = [[rect.origin.x, rect.origin.y + rect.size.height + 20], rect.size]
|
47
|
+
|
48
|
+
button
|
49
|
+
end
|
50
|
+
|
51
|
+
def built_alert(method)
|
52
|
+
options = {
|
53
|
+
:title => method,
|
54
|
+
:will_present => build_callback(:will_present, method),
|
55
|
+
:did_present => build_callback(:did_present, method),
|
56
|
+
:on_click => build_callback(:on_click, method),
|
57
|
+
:will_dismiss => build_callback(:will_dismiss, method),
|
58
|
+
:did_dismiss => build_callback(:did_dismiss, method)
|
59
|
+
}
|
60
|
+
BW::UIAlertView.send(method, options)
|
61
|
+
end
|
62
|
+
|
63
|
+
def build_callback(name, method)
|
64
|
+
lambda do |alert|
|
65
|
+
message = []
|
66
|
+
message << "\n\n" + method.to_s if name == :will_present
|
67
|
+
message << "\n" + name.to_s
|
68
|
+
message << "\n" + alert.clicked_button.inspect if alert.clicked_button
|
69
|
+
|
70
|
+
self.text_view.text += message.join
|
71
|
+
self.text_view.selectedRange = NSMakeRange(self.text_view.text.length, 0)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|