sugarcube 1.1.0 → 1.3.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.
- data/Gemfile.lock +1 -1
- data/README.md +73 -10
- data/lib/sugarcube-animations/caanimation.rb +31 -0
- data/lib/sugarcube-animations/calayer.rb +7 -0
- data/lib/sugarcube-animations/uiview.rb +59 -34
- data/lib/sugarcube-attributedstring/nsattributedstring.rb +7 -0
- data/lib/sugarcube-color/nsstring.rb +1 -1
- data/lib/sugarcube-color/symbol.rb +2 -2
- data/lib/sugarcube-color/uicolor.rb +56 -10
- data/lib/sugarcube-corelocation/core_location.rb +12 -3
- data/lib/sugarcube-factories/uiactionsheet.rb +5 -4
- data/lib/sugarcube-factories/uialertview.rb +4 -5
- data/lib/sugarcube-image/ciimage.rb +2 -3
- data/lib/sugarcube-image/uiimage.rb +245 -97
- data/lib/sugarcube-nsdate/date_parser.rb +14 -12
- data/lib/sugarcube-nsdate/nsstring.rb +5 -0
- data/lib/sugarcube-nsdate/{fixnum.rb → numeric.rb} +12 -3
- data/lib/sugarcube-numbers/numeric.rb +7 -0
- data/lib/sugarcube-to_s/uilabel.rb +1 -1
- data/lib/sugarcube-to_s/uiview.rb +1 -2
- data/lib/sugarcube-uikit/uiview.rb +75 -5
- data/lib/sugarcube/version.rb +1 -1
- data/spec/nsattributedstring_spec.rb +4 -0
- data/spec/nsstring_files_spec.rb +18 -15
- data/spec/uiactionsheet_spec.rb +40 -2
- data/spec/uialertview_spec.rb +10 -3
- data/spec/uicolor_spec.rb +39 -0
- data/spec/uiimage_spec.rb +471 -0
- data/spec/uiview_spec.rb +90 -22
- metadata +9 -3
@@ -1,16 +1,18 @@
|
|
1
1
|
module SugarCube
|
2
2
|
module DateParser
|
3
|
+
module_function
|
4
|
+
|
3
5
|
# Parse a date string: E.g.:
|
4
6
|
#
|
5
7
|
# SugarCube::DateParser.parse_date "There is a date in here tomorrow at 9:00 AM"
|
6
8
|
#
|
7
9
|
# => 2013-02-20 09:00:00 -0800
|
8
|
-
def
|
10
|
+
def parse_date(date_string)
|
9
11
|
result = sugarcube_detect(date_string).first
|
10
12
|
if result
|
11
13
|
return result.date
|
12
14
|
else
|
13
|
-
return
|
15
|
+
return iso8601(date_string)
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
@@ -20,7 +22,7 @@ module SugarCube
|
|
20
22
|
#
|
21
23
|
# Caveat: This is implemented per Apple documentation. I've never really
|
22
24
|
# seen it work.
|
23
|
-
def
|
25
|
+
def parse_time_zone(date_string)
|
24
26
|
result = sugarcube_detect(date_string).first
|
25
27
|
result && result.timeZone
|
26
28
|
end
|
@@ -32,23 +34,17 @@ module SugarCube
|
|
32
34
|
# => 21600.0
|
33
35
|
#
|
34
36
|
# Divide by 3600.0 to get number of hours duration.
|
35
|
-
def
|
37
|
+
def parse_duration(date_string)
|
36
38
|
result = sugarcube_detect(date_string).first
|
37
39
|
result && result.send(:duration)
|
38
40
|
end
|
39
41
|
|
40
42
|
# Parse a date into a raw match array for further processing
|
41
|
-
def
|
43
|
+
def match(date_string)
|
42
44
|
sugarcube_detect(date_string)
|
43
45
|
end
|
44
46
|
|
45
|
-
|
46
|
-
def self.sugarcube_detect(date_string)
|
47
|
-
@@sugarcube_detector ||= NSDataDetector.dataDetectorWithTypes(NSTextCheckingTypeDate, error:Pointer.new(:object))
|
48
|
-
return @@sugarcube_detector.matchesInString(date_string, options:0, range:NSMakeRange(0, date_string.length))
|
49
|
-
end
|
50
|
-
|
51
|
-
def self.sugarcube_iso8601(date_string)
|
47
|
+
def iso8601(date_string)
|
52
48
|
@@sugarcube_iso_detectors ||= [
|
53
49
|
"yyyy-MM-dd'T'HH:mm:ss",
|
54
50
|
"yyyy-MM-dd'T'HH:mm:ssZ",
|
@@ -63,6 +59,12 @@ module SugarCube
|
|
63
59
|
return @@sugarcube_iso_detectors.inject(nil) { |date, formatter| date || formatter.dateFromString(date_string) }
|
64
60
|
end
|
65
61
|
|
62
|
+
def sugarcube_detect(date_string)
|
63
|
+
@@sugarcube_detector ||= NSDataDetector.dataDetectorWithTypes(NSTextCheckingTypeDate, error:Pointer.new(:object))
|
64
|
+
return @@sugarcube_detector.matchesInString(date_string, options:0, range:NSMakeRange(0, date_string.length))
|
65
|
+
end
|
66
|
+
private :sugarcube_detect
|
67
|
+
|
66
68
|
end
|
67
69
|
end
|
68
70
|
|
@@ -1,7 +1,7 @@
|
|
1
|
-
class
|
1
|
+
class Numeric
|
2
2
|
|
3
|
-
def
|
4
|
-
|
3
|
+
def nsdate
|
4
|
+
NSDate.dateWithTimeIntervalSince1970(self)
|
5
5
|
end
|
6
6
|
|
7
7
|
def before(date)
|
@@ -21,3 +21,12 @@ class Fixnum
|
|
21
21
|
end
|
22
22
|
|
23
23
|
end
|
24
|
+
|
25
|
+
|
26
|
+
class Fixnum
|
27
|
+
|
28
|
+
def nstimezone
|
29
|
+
NSTimeZone.timeZoneForSecondsFromGMT(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
class UIView
|
2
2
|
|
3
3
|
def to_s(options={})
|
4
|
-
options[:superview] = true if options[:superview].nil?
|
5
4
|
if self.respond_to? :stylename and self.stylename
|
6
5
|
suffix = ' stylename: ' + self.stylename.inspect
|
7
6
|
else
|
@@ -20,7 +19,7 @@ class UIView
|
|
20
19
|
"#{self.class.name}(##{self.object_id.to_s(16)}, #{SugarCube::Adjust::format_frame(self.frame)}" +
|
21
20
|
(inner ? ', ' + inner : '') +
|
22
21
|
')' +
|
23
|
-
(options
|
22
|
+
(options.fetch(:superview, true) && self.superview ? ", child of #{self.superview.class.name}(##{self.superview.object_id.to_s(16)})" : '') +
|
24
23
|
suffix
|
25
24
|
end
|
26
25
|
|
@@ -10,12 +10,12 @@ class UIView
|
|
10
10
|
def attr_updates(*attrs)
|
11
11
|
attr_accessor(*attrs)
|
12
12
|
attrs.each do |attr|
|
13
|
-
define_method("#{attr}=")
|
13
|
+
define_method("#{attr}=") do |value|
|
14
14
|
if instance_variable_get("@#{attr}") != value
|
15
15
|
setNeedsDisplay
|
16
16
|
end
|
17
17
|
instance_variable_set("@#{attr}", value)
|
18
|
-
|
18
|
+
end
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -80,7 +80,7 @@ class UIView
|
|
80
80
|
if use_content_size
|
81
81
|
UIGraphicsBeginImageContextWithOptions(contentSize, false, scale)
|
82
82
|
context = UIGraphicsGetCurrentContext()
|
83
|
-
subviews.each do |subview|
|
83
|
+
self.subviews.each do |subview|
|
84
84
|
CGContextSaveGState(context)
|
85
85
|
CGContextTranslateCTM(context, subview.frame.origin.x, subview.frame.origin.y)
|
86
86
|
subview.layer.renderInContext(context)
|
@@ -99,12 +99,82 @@ class UIView
|
|
99
99
|
|
100
100
|
# Returns the receiver's bounds in the coordinate system of `destination`
|
101
101
|
def convert_bounds(destination)
|
102
|
-
|
102
|
+
message = "The (ambiguously named) `convert_bounds` method has been deprecated, use `convert_frame_to` (or `convert_frame_from`)"
|
103
|
+
if defined?(SugarCube::Legacy)
|
104
|
+
SugarCube::Legacy.log(message)
|
105
|
+
else
|
106
|
+
NSLog(message)
|
107
|
+
end
|
108
|
+
return convert_frame_to(destination)
|
109
|
+
end
|
110
|
+
|
111
|
+
def convert_frame_to(destination)
|
112
|
+
return self.convertRect(CGRectMake(0, 0, self.frame.size.width, self.frame.size.height), toView:destination)
|
113
|
+
end
|
114
|
+
|
115
|
+
def convert_frame_from(source)
|
116
|
+
return self.convertRect(CGRectMake(0, 0, source.frame.size.width, source.frame.size.height), fromView:source)
|
103
117
|
end
|
104
118
|
|
105
119
|
# Returns the receiver's bounds in the coordinate system of `destination`
|
106
120
|
def convert_origin(destination)
|
107
|
-
|
121
|
+
message = "The (ambiguously named) `convert_origin` method has been deprecated, use `convert_origin_to` (or `convert_origin_from`)"
|
122
|
+
if defined?(SugarCube::Legacy)
|
123
|
+
SugarCube::Legacy.log(message)
|
124
|
+
else
|
125
|
+
NSLog(message)
|
126
|
+
end
|
127
|
+
return self.convert_origin_to(destination)
|
128
|
+
end
|
129
|
+
|
130
|
+
def convert_origin_to(destination)
|
131
|
+
return self.convertPoint([0, 0], toView:destination)
|
132
|
+
end
|
133
|
+
|
134
|
+
def convert_origin_from(source)
|
135
|
+
return self.convertPoint([0, 0], fromView:source)
|
136
|
+
end
|
137
|
+
|
138
|
+
# Easily get and set a UIView's frame properties
|
139
|
+
|
140
|
+
def x
|
141
|
+
self.frame.origin.x
|
142
|
+
end
|
143
|
+
|
144
|
+
def setX(newX)
|
145
|
+
newFrame = self.frame
|
146
|
+
newFrame.origin.x = newX
|
147
|
+
self.frame = newFrame
|
148
|
+
end
|
149
|
+
|
150
|
+
def y
|
151
|
+
self.frame.origin.y
|
152
|
+
end
|
153
|
+
|
154
|
+
def setY(newY)
|
155
|
+
newFrame = self.frame
|
156
|
+
newFrame.origin.y = newY
|
157
|
+
self.frame = newFrame
|
158
|
+
end
|
159
|
+
|
160
|
+
def height
|
161
|
+
self.frame.size.height
|
162
|
+
end
|
163
|
+
|
164
|
+
def setHeight(newHeight)
|
165
|
+
newFrame = self.frame
|
166
|
+
newFrame.size.height = newHeight
|
167
|
+
self.frame = newFrame
|
168
|
+
end
|
169
|
+
|
170
|
+
def width
|
171
|
+
self.frame.size.width
|
172
|
+
end
|
173
|
+
|
174
|
+
def setWidth(newWidth)
|
175
|
+
newFrame = self.frame
|
176
|
+
newFrame.size.width = newWidth
|
177
|
+
self.frame = newFrame
|
108
178
|
end
|
109
179
|
|
110
180
|
end
|
data/lib/sugarcube/version.rb
CHANGED
@@ -99,6 +99,10 @@ describe 'NSAttributeString' do
|
|
99
99
|
@subject.isEqualToAttributedString('test'.attrd.vertical_glyph_form(1)).should != true
|
100
100
|
end
|
101
101
|
|
102
|
+
it 'should have `letterpress`' do
|
103
|
+
@subject.isEqualToAttributedString('test'.attrd.letterpress).should != true
|
104
|
+
end
|
105
|
+
|
102
106
|
end
|
103
107
|
|
104
108
|
end
|
data/spec/nsstring_files_spec.rb
CHANGED
@@ -31,21 +31,21 @@ describe 'NSString' do
|
|
31
31
|
'little_square.png'.resource_exists?.should == true
|
32
32
|
'foo'.resource_exists?.should == false
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
describe "exists?" do
|
36
|
-
|
36
|
+
|
37
37
|
it "should not exists" do
|
38
38
|
"abc".exists?.should == false
|
39
39
|
end
|
40
|
-
|
40
|
+
|
41
41
|
it "should not exists" do
|
42
42
|
"abc".cache.exists?.should == false
|
43
43
|
end
|
44
|
-
|
44
|
+
|
45
45
|
it "should not exists" do
|
46
46
|
"abc".resource.exists?.should == false
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
describe "in document" do
|
50
50
|
before do
|
51
51
|
"abc".writeToFile "abc".document, atomically:true
|
@@ -53,12 +53,12 @@ describe 'NSString' do
|
|
53
53
|
after do
|
54
54
|
NSFileManager.defaultManager.removeItemAtPath "abc".document, error:nil
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
it "should be exists" do
|
58
58
|
"abc".exists?.should == true
|
59
59
|
end
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
describe "in cache" do
|
63
63
|
before do
|
64
64
|
"abc".writeToFile "abc".cache, atomically:true
|
@@ -66,7 +66,7 @@ describe 'NSString' do
|
|
66
66
|
after do
|
67
67
|
NSFileManager.defaultManager.removeItemAtPath "abc".cache, error:nil
|
68
68
|
end
|
69
|
-
|
69
|
+
|
70
70
|
it "should be exists" do
|
71
71
|
"abc".cache.exists?.should == true
|
72
72
|
end
|
@@ -79,9 +79,9 @@ describe 'NSString' do
|
|
79
79
|
end
|
80
80
|
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
describe "remove!" do
|
84
|
-
|
84
|
+
|
85
85
|
describe "in document" do
|
86
86
|
before do
|
87
87
|
"abc".writeToFile "abc".document, atomically:true
|
@@ -89,13 +89,13 @@ describe 'NSString' do
|
|
89
89
|
after do
|
90
90
|
NSFileManager.defaultManager.removeItemAtPath "abc".document, error:nil
|
91
91
|
end
|
92
|
-
|
92
|
+
|
93
93
|
it "should remove" do
|
94
94
|
"abc".remove!.should == nil
|
95
95
|
"abc".exists?.should == false
|
96
96
|
end
|
97
97
|
end
|
98
|
-
|
98
|
+
|
99
99
|
describe "in cache" do
|
100
100
|
before do
|
101
101
|
"abc".writeToFile "abc".cache, atomically:true
|
@@ -103,14 +103,14 @@ describe 'NSString' do
|
|
103
103
|
after do
|
104
104
|
NSFileManager.defaultManager.removeItemAtPath "abc".cache, error:nil
|
105
105
|
end
|
106
|
-
|
106
|
+
|
107
107
|
it "should remove" do
|
108
108
|
path = "abc".cache
|
109
109
|
path.remove!.should == nil
|
110
110
|
path.exists?.should == false
|
111
111
|
end
|
112
112
|
end
|
113
|
-
|
113
|
+
|
114
114
|
end
|
115
115
|
|
116
116
|
describe 'resource()' do
|
@@ -153,7 +153,10 @@ describe 'NSString' do
|
|
153
153
|
describe '"PkgInfo".resource_url' do
|
154
154
|
before { @it = "PkgInfo".resource_url.absoluteString }
|
155
155
|
it 'should start with "file://localhost/Users"' do
|
156
|
-
|
156
|
+
(
|
157
|
+
@it.hasPrefix("file://localhost/Users") ||
|
158
|
+
@it.hasPrefix("file:///Users")
|
159
|
+
).should == true
|
157
160
|
end
|
158
161
|
it 'should end with "SugarCube_spec.app/PkgInfo"' do
|
159
162
|
@it.hasSuffix("SugarCube_spec.app/PkgInfo").should == true
|
data/spec/uiactionsheet_spec.rb
CHANGED
@@ -249,13 +249,13 @@ describe 'UIActionSheet' do
|
|
249
249
|
proper_wait 0.6
|
250
250
|
end
|
251
251
|
|
252
|
-
it 'should call block with
|
252
|
+
it 'should call block with :cancel when cancel button is pressed' do
|
253
253
|
@alert.cancelButtonIndex.should == 3
|
254
254
|
@alert.dismissWithClickedButtonIndex(@alert.cancelButtonIndex, animated: false)
|
255
255
|
@touched.should == :cancel
|
256
256
|
end
|
257
257
|
|
258
|
-
it 'should call block with
|
258
|
+
it 'should call block with :destructive when destructive button is pressed' do
|
259
259
|
@alert.destructiveButtonIndex.should == 0
|
260
260
|
@alert.dismissWithClickedButtonIndex(@alert.destructiveButtonIndex, animated: false)
|
261
261
|
@touched.should == :destructive
|
@@ -276,4 +276,42 @@ describe 'UIActionSheet' do
|
|
276
276
|
|
277
277
|
end
|
278
278
|
|
279
|
+
describe 'with success handler defined' do
|
280
|
+
|
281
|
+
before do
|
282
|
+
@touched = nil
|
283
|
+
@alert = UIActionSheet.alert('test',
|
284
|
+
buttons: ['cancel', 'destructive', 'test1', 'test2'],
|
285
|
+
success: ->(button, index){ @touched, @touched_index = button, index },
|
286
|
+
)
|
287
|
+
proper_wait 0.6
|
288
|
+
end
|
289
|
+
|
290
|
+
it 'should not call block when cancel button is pressed' do
|
291
|
+
@alert.cancelButtonIndex.should == 3
|
292
|
+
@alert.dismissWithClickedButtonIndex(@alert.cancelButtonIndex, animated: false)
|
293
|
+
@touched.should == nil
|
294
|
+
end
|
295
|
+
|
296
|
+
it 'should not call block when destructive button is pressed' do
|
297
|
+
@alert.destructiveButtonIndex.should == 0
|
298
|
+
@alert.dismissWithClickedButtonIndex(@alert.destructiveButtonIndex, animated: false)
|
299
|
+
@touched.should == nil
|
300
|
+
end
|
301
|
+
|
302
|
+
it 'should call block with "test1" when first button is pressed' do
|
303
|
+
@alert.firstOtherButtonIndex.should == 1
|
304
|
+
@alert.dismissWithClickedButtonIndex(@alert.firstOtherButtonIndex, animated: false)
|
305
|
+
@touched.should == 'test1'
|
306
|
+
@touched_index.should == @alert.firstOtherButtonIndex
|
307
|
+
end
|
308
|
+
|
309
|
+
it 'should call block with "test2" when second button is pressed' do
|
310
|
+
@alert.dismissWithClickedButtonIndex(@alert.firstOtherButtonIndex + 1, animated: false)
|
311
|
+
@touched.should == 'test2'
|
312
|
+
@touched_index.should == @alert.firstOtherButtonIndex + 1
|
313
|
+
end
|
314
|
+
|
315
|
+
end
|
316
|
+
|
279
317
|
end
|
data/spec/uialertview_spec.rb
CHANGED
@@ -9,14 +9,14 @@ describe 'UIAlertView' do
|
|
9
9
|
|
10
10
|
it 'should have :show option (show: true)' do
|
11
11
|
alert = UIAlertView.alert('test', show: true)
|
12
|
-
proper_wait
|
12
|
+
proper_wait 1
|
13
13
|
alert.visible?.should == true
|
14
14
|
alert.dismissWithClickedButtonIndex(alert.firstOtherButtonIndex, animated: false)
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'should show by default' do
|
18
18
|
alert = UIAlertView.alert('test')
|
19
|
-
proper_wait
|
19
|
+
proper_wait 1
|
20
20
|
alert.visible?.should == true
|
21
21
|
alert.dismissWithClickedButtonIndex(alert.firstOtherButtonIndex, animated: false)
|
22
22
|
end
|
@@ -144,6 +144,10 @@ describe 'UIAlertView' do
|
|
144
144
|
)
|
145
145
|
end
|
146
146
|
|
147
|
+
after do
|
148
|
+
@alert.dismissWithClickedButtonIndex(@alert.cancelButtonIndex, animated: false)
|
149
|
+
end
|
150
|
+
|
147
151
|
it 'should work for :cancel' do
|
148
152
|
proper_wait 0.6
|
149
153
|
@alert.dismissWithClickedButtonIndex(@alert.cancelButtonIndex, animated: false)
|
@@ -167,13 +171,16 @@ describe 'UIAlertView' do
|
|
167
171
|
end
|
168
172
|
|
169
173
|
it 'should work with :secure_text_input' do
|
174
|
+
@called = false
|
170
175
|
alert = UIAlertView.alert('test', buttons: ['cancel', 'ok'], style: :secure_text_input) { |button, text|
|
176
|
+
@called = true
|
171
177
|
@text = text
|
172
178
|
}
|
173
179
|
proper_wait 0.6
|
174
180
|
alert.textFieldAtIndex(0).text = 'test text'
|
175
|
-
alert.dismissWithClickedButtonIndex(alert.
|
181
|
+
alert.dismissWithClickedButtonIndex(alert.firstOtherButtonIndex, animated: false)
|
176
182
|
|
183
|
+
@called.should == true
|
177
184
|
@text.should == 'test text'
|
178
185
|
end
|
179
186
|
|