sugarcube 0.16.9 → 0.18.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/README.md +85 -3
- data/app/animation_chain_controller.rb +12 -0
- data/lib/sugarcube/animation_chain.rb +66 -0
- data/lib/sugarcube/nsattributedstring.rb +247 -0
- data/lib/sugarcube/nsstring.rb +2 -1
- data/lib/sugarcube/symbol.rb +8 -2
- data/lib/sugarcube/uiview.rb +62 -37
- data/lib/sugarcube/version.rb +1 -1
- data/lib/sugarcube-unholy/ivar.rb +8 -0
- data/spec/nsattributedstring_spec.rb +149 -0
- data/spec/nsstring_spec.rb +6 -6
- data/spec/uiview_animation_chain_spec.rb +61 -0
- data/spec/uiview_attr_updates_spec.rb +54 -0
- data/spec/unholy_spec.rb +8 -0
- metadata +11 -2
data/README.md
CHANGED
@@ -129,6 +129,41 @@ distance.miles # => 0.932056427001953
|
|
129
129
|
10000.string_with_style(:currency) # => "$10,000.00"
|
130
130
|
```
|
131
131
|
|
132
|
+
NSAttributedString
|
133
|
+
---------
|
134
|
+
|
135
|
+
These become pretty fun! Check out `nsattributedstring_spec.rb` for all the
|
136
|
+
supported attributes (in theory they are all supported, but there's weird
|
137
|
+
issues with missing constants).
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
'test'.nsattributedstring({}) #=> NSAttributedString.alloc.initWithString('test', attributes:{})
|
141
|
+
'test'.attrd # => alias for `nsattributedstring`
|
142
|
+
'test'.bold # => NSAttributedString.alloc.initWithString('test', attributes:{NSFontAttributeName => :bold.uifont})
|
143
|
+
'test'.italic # => NSAttributedString.alloc.initWithString('test', attributes:{NSFontAttributeName => :italic.uifont})
|
144
|
+
'test'.underline # => NSAttributedString.alloc.initWithString('test', attributes:{NSUnderlineStyleAttributeName => NSUnderlineStyleSingle})
|
145
|
+
|
146
|
+
# you can chain 'em, too.
|
147
|
+
'test'.bold.underline
|
148
|
+
# If you look up NSAttributedString Application Kit Additions, you can see all
|
149
|
+
# the constants. Each of those has a method on NSAttributedString.
|
150
|
+
|
151
|
+
# you can add 'em, but the FIRST one MUST be an NSAttributedString
|
152
|
+
'test'.attrd + '-ing'.italic
|
153
|
+
|
154
|
+
# And there's where it gets FUN:
|
155
|
+
('This'.italic + ' is going to be ' + 'FUN'.bold).underline
|
156
|
+
```
|
157
|
+
|
158
|
+
And you can easily turn this into a label!
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
view << (("We just met\n".attrd +
|
162
|
+
"and this is " + "CRAZY".italic + "\n"
|
163
|
+
"But here's my " + "id_rsa.pub".code + " file,\n" +
|
164
|
+
"so give me SSH access.").uilabel
|
165
|
+
```
|
166
|
+
|
132
167
|
NSCoder
|
133
168
|
---------
|
134
169
|
|
@@ -418,7 +453,7 @@ NSError.new('Error Message', code: 404, userInfo: { warnings: ['blabla'] })
|
|
418
453
|
```ruby
|
419
454
|
# UIImage from name
|
420
455
|
"my_image".uiimage # => UIImage.imageNamed("my_image")
|
421
|
-
"
|
456
|
+
"pattern".uicolor == "pattern".uiimage.uicolor # => UIColor.colorWithPatternImage(UIImage.imageNamed("pattern"))
|
422
457
|
|
423
458
|
# UIFont from name
|
424
459
|
"my_font".uifont # => UIFont.fontWithName("my_font", size:UIFont.systemFontSize)
|
@@ -428,9 +463,8 @@ NSError.new('Error Message', code: 404, userInfo: { warnings: ['blabla'] })
|
|
428
463
|
"blue".uicolor == :blue.uicolor # => UIColor.blueColor
|
429
464
|
"#ff00ff".uicolor == :fuchsia.uicolor == 0xff00ff.uicolor # => UIColor.colorWithRed(1.0, green:0.0, blue:1.0, alpha:1.0)
|
430
465
|
"#f0f".uicolor(0.5) == :fuchsia.uicolor(0.5) == 0xff00ff.uicolor(0.5) # => UIColor.colorWithRed(1.0, green:1.0, blue:1.0, alpha:0.5)
|
431
|
-
# note: 0xf0f.uicolor ==
|
466
|
+
# note: 0xf0f.uicolor == 0x000f0f.uicolor. There's no way to tell the difference
|
432
467
|
# at run time between those two Fixnum literals.
|
433
|
-
"my_image".uicolor == "my_image".uiimage.uicolor # => UIColor.colorWithPatternImage(UIImage.imageNamed("my_image"))
|
434
468
|
|
435
469
|
# NSLocalizedString from string
|
436
470
|
"hello".localized # => NSBundle.mainBundle.localizedStringForKey("hello", value:nil, table:nil)
|
@@ -647,6 +681,25 @@ self.view.hide # => self.hidden = true
|
|
647
681
|
my_view.uiimage
|
648
682
|
```
|
649
683
|
|
684
|
+
When defining a UIView subclass, you often have attributes that affect your
|
685
|
+
`drawRect` method (99% of the time, ALL the attributes affect drawing, right?).
|
686
|
+
So SugarCube adds a `attr_updates` method, which creates an attribute identical
|
687
|
+
to `attr_accessor` but the setter calls setNeedsDisplay if the new value != the
|
688
|
+
old value.
|
689
|
+
|
690
|
+
```ruby
|
691
|
+
class NiftyView < UIView
|
692
|
+
attr_updates :insets, :pattern
|
693
|
+
|
694
|
+
def drawRect(rect)
|
695
|
+
# ...
|
696
|
+
end
|
697
|
+
end
|
698
|
+
|
699
|
+
nifty_view.pattern = 'my_pattern' # => setNeedsDisplay gets called
|
700
|
+
nifty_view.pattern = 'my_pattern' # => setNeedsDisplay doesn't get called, because the value didn't change.
|
701
|
+
```
|
702
|
+
|
650
703
|
###### Animations
|
651
704
|
|
652
705
|
jQuery-like animation methods. They accept a "completed" callback handler that
|
@@ -716,6 +769,35 @@ view.slide(:left, 20) {
|
|
716
769
|
}
|
717
770
|
```
|
718
771
|
|
772
|
+
But isn't that ugly! Use an animation chain!
|
773
|
+
|
774
|
+
```ruby
|
775
|
+
UIView.animation_chain {
|
776
|
+
view.slide(:left, 20)
|
777
|
+
}.and_then {
|
778
|
+
view.slide(:up, 20)
|
779
|
+
}.and_then {
|
780
|
+
view.slide(:right, 20)
|
781
|
+
}.and_then {
|
782
|
+
view.slide(:down, 20)
|
783
|
+
}.and_then {
|
784
|
+
view.fade_out
|
785
|
+
}.start
|
786
|
+
```
|
787
|
+
|
788
|
+
Chains can also be written like this:
|
789
|
+
|
790
|
+
|
791
|
+
```ruby
|
792
|
+
chain = UIView.animation_chain
|
793
|
+
chain << proc { view.slide(:left, 20) }
|
794
|
+
chain << proc { view.slide(:up, 20) }
|
795
|
+
chain << proc { view.slide(:right, 20) }
|
796
|
+
chain << proc { view.slide(:down, 20) }
|
797
|
+
chain << proc { view.fade_out }
|
798
|
+
chain.start
|
799
|
+
```
|
800
|
+
|
719
801
|
##### View factories
|
720
802
|
|
721
803
|
###### UIButton
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module SugarCube
|
2
|
+
class AnimationChain
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def chains
|
6
|
+
@chains ||= []
|
7
|
+
end
|
8
|
+
|
9
|
+
def start_chain(chain)
|
10
|
+
chains << chain
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop_chain(chain)
|
14
|
+
chains ||= []
|
15
|
+
@chains.delete(chain)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@blocks = []
|
22
|
+
end
|
23
|
+
|
24
|
+
def wait(duration)
|
25
|
+
and_then(duration: duration) {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def and_then(options=nil, &block)
|
29
|
+
if options
|
30
|
+
options = options.dup
|
31
|
+
else
|
32
|
+
options = {}
|
33
|
+
end
|
34
|
+
@blocks << [options, block]
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def << block
|
39
|
+
and_then(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
def do_next
|
43
|
+
return nil if @block_index >= @blocks.length
|
44
|
+
|
45
|
+
options, _ = @blocks[@block_index]
|
46
|
+
@after_block = ->(completed){
|
47
|
+
self.do_next || AnimationChain.stop_chain(self)
|
48
|
+
}
|
49
|
+
options[:after] = @after_block
|
50
|
+
|
51
|
+
UIView.animate(options) {
|
52
|
+
_, block = @blocks[@block_index]
|
53
|
+
block.call
|
54
|
+
@block_index += 1
|
55
|
+
}
|
56
|
+
true
|
57
|
+
end
|
58
|
+
|
59
|
+
def start
|
60
|
+
AnimationChain.start_chain(self)
|
61
|
+
@block_index = 0
|
62
|
+
do_next
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
class NSString
|
2
|
+
|
3
|
+
def bold(size=nil)
|
4
|
+
font = :bold.uifont(size)
|
5
|
+
nsattributedstring({NSFontAttributeName => font})
|
6
|
+
end
|
7
|
+
|
8
|
+
def italic(size=nil)
|
9
|
+
font = :italic.uifont(size)
|
10
|
+
nsattributedstring({NSFontAttributeName => font})
|
11
|
+
end
|
12
|
+
|
13
|
+
def monospace(size=nil)
|
14
|
+
font = :monospace.uifont(size)
|
15
|
+
nsattributedstring({NSFontAttributeName => font})
|
16
|
+
end
|
17
|
+
|
18
|
+
def underline(underline_style=nil)
|
19
|
+
underline_style ||= NSUnderlineStyleSingle
|
20
|
+
nsattributedstring({NSUnderlineStyleAttributeName => underline_style})
|
21
|
+
end
|
22
|
+
|
23
|
+
def nsattributedstring(attributes={})
|
24
|
+
NSAttributedString.alloc.initWithString(self, attributes: attributes)
|
25
|
+
end
|
26
|
+
alias attrd nsattributedstring
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class NSMutableString
|
32
|
+
|
33
|
+
def nsattributedstring(attributes={})
|
34
|
+
NSMutableAttributedString.alloc.initWithString(self, attributes: attributes)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
class NSAttributedString
|
41
|
+
NSSuperscriptAttributeName = 'NSSuperscript'
|
42
|
+
NSAttachmentAttributeName = 'NSAttachment'
|
43
|
+
NSBaselineOffsetAttributeName = 'NSBaselineOffset'
|
44
|
+
NSLinkAttributeName = 'NSLink'
|
45
|
+
NSUnderlineColorAttributeName = 'NSUnderlineColor'
|
46
|
+
NSStrikethroughColorAttributeName = 'NSStrikethroughColor'
|
47
|
+
NSObliquenessAttributeName = 'NSObliqueness'
|
48
|
+
NSExpansionAttributeName = 'NSExpansion'
|
49
|
+
NSCursorAttributeName = 'NSCursor'
|
50
|
+
NSToolTipAttributeName = 'NSToolTip'
|
51
|
+
NSMarkedClauseSegmentAttributeName = 'NSMarkedClauseSegment'
|
52
|
+
NSWritingDirectionAttributeName = 'NSWritingDirection'
|
53
|
+
NSTextAlternativesAttributeName = 'NSTextAlternatives'
|
54
|
+
|
55
|
+
def dummy
|
56
|
+
self.foo = NSFontAttributeName
|
57
|
+
self.foo = NSParagraphStyleAttributeName
|
58
|
+
self.foo = NSForegroundColorAttributeName
|
59
|
+
self.foo = NSUnderlineStyleAttributeName
|
60
|
+
self.foo = NSSuperscriptAttributeName
|
61
|
+
self.foo = NSBackgroundColorAttributeName
|
62
|
+
self.foo = NSAttachmentAttributeName
|
63
|
+
self.foo = NSLigatureAttributeName
|
64
|
+
self.foo = NSBaselineOffsetAttributeName
|
65
|
+
self.foo = NSKernAttributeName
|
66
|
+
self.foo = NSLinkAttributeName
|
67
|
+
self.foo = NSStrokeWidthAttributeName
|
68
|
+
self.foo = NSStrokeColorAttributeName
|
69
|
+
self.foo = NSUnderlineColorAttributeName
|
70
|
+
self.foo = NSStrikethroughStyleAttributeName
|
71
|
+
self.foo = NSStrikethroughColorAttributeName
|
72
|
+
self.foo = NSShadowAttributeName
|
73
|
+
self.foo = NSObliquenessAttributeName
|
74
|
+
self.foo = NSExpansionAttributeName
|
75
|
+
self.foo = NSCursorAttributeName
|
76
|
+
self.foo = NSToolTipAttributeName
|
77
|
+
self.foo = NSMarkedClauseSegmentAttributeName
|
78
|
+
self.foo = NSWritingDirectionAttributeName
|
79
|
+
self.foo = NSVerticalGlyphFormAttributeName
|
80
|
+
self.foo = NSTextAlternativesAttributeName
|
81
|
+
|
82
|
+
self.foo = NSLeftTextAlignment
|
83
|
+
self.foo = NSRightTextAlignment
|
84
|
+
self.foo = NSCenterTextAlignment
|
85
|
+
self.foo = NSJustifiedTextAlignment
|
86
|
+
self.foo = NSNaturalTextAlignment
|
87
|
+
end
|
88
|
+
|
89
|
+
def to_s
|
90
|
+
string
|
91
|
+
end
|
92
|
+
|
93
|
+
def bold(size=nil)
|
94
|
+
font = :bold.uifont(size)
|
95
|
+
self.font(font)
|
96
|
+
end
|
97
|
+
|
98
|
+
def italic(size=nil)
|
99
|
+
font = :italic.uifont(size)
|
100
|
+
self.font(font)
|
101
|
+
end
|
102
|
+
|
103
|
+
def underlined
|
104
|
+
underline(NSUnderlinePatternSolid)
|
105
|
+
end
|
106
|
+
|
107
|
+
# @param font [UIFont] Optional, defaults to UIFont.systemFontOfSize(UIFont.systemFontSize)
|
108
|
+
# @return [UILabel]
|
109
|
+
def uilabel
|
110
|
+
UILabel.alloc.initWithFrame([[0, 0], [0, 0]]).tap { |label|
|
111
|
+
label.attributedText = self
|
112
|
+
label.backgroundColor = :clear.uicolor
|
113
|
+
label.sizeToFit
|
114
|
+
}
|
115
|
+
end
|
116
|
+
|
117
|
+
def font(value)
|
118
|
+
with_attributes({NSFontAttributeName => value.uifont})
|
119
|
+
end
|
120
|
+
|
121
|
+
def paragraph_style(value)
|
122
|
+
with_attributes({NSParagraphStyleAttributeName => value})
|
123
|
+
end
|
124
|
+
|
125
|
+
def foreground_color(value)
|
126
|
+
with_attributes({NSForegroundColorAttributeName => value})
|
127
|
+
end
|
128
|
+
alias color foreground_color
|
129
|
+
|
130
|
+
def underline_style(value)
|
131
|
+
with_attributes({NSUnderlineStyleAttributeName => value})
|
132
|
+
end
|
133
|
+
|
134
|
+
def superscript(value)
|
135
|
+
with_attributes({NSSuperscriptAttributeName => value})
|
136
|
+
end
|
137
|
+
|
138
|
+
def background_color(value)
|
139
|
+
with_attributes({NSBackgroundColorAttributeName => value})
|
140
|
+
end
|
141
|
+
alias bg_color background_color
|
142
|
+
|
143
|
+
def attachment(value)
|
144
|
+
with_attributes({NSAttachmentAttributeName => value})
|
145
|
+
end
|
146
|
+
|
147
|
+
def ligature(value)
|
148
|
+
with_attributes({NSLigatureAttributeName => value})
|
149
|
+
end
|
150
|
+
|
151
|
+
def baseline_offset(value)
|
152
|
+
with_attributes({NSBaselineOffsetAttributeName => value})
|
153
|
+
end
|
154
|
+
|
155
|
+
def kern(value)
|
156
|
+
with_attributes({NSKernAttributeName => value})
|
157
|
+
end
|
158
|
+
|
159
|
+
def link(value)
|
160
|
+
with_attributes({NSLinkAttributeName => value})
|
161
|
+
end
|
162
|
+
|
163
|
+
def stroke_width(value)
|
164
|
+
with_attributes({NSStrokeWidthAttributeName => value})
|
165
|
+
end
|
166
|
+
|
167
|
+
def stroke_color(value)
|
168
|
+
with_attributes({NSStrokeColorAttributeName => value})
|
169
|
+
end
|
170
|
+
|
171
|
+
def underline_color(value)
|
172
|
+
with_attributes({NSUnderlineColorAttributeName => value})
|
173
|
+
end
|
174
|
+
|
175
|
+
def strikethrough_style(value)
|
176
|
+
with_attributes({NSStrikethroughStyleAttributeName => value})
|
177
|
+
end
|
178
|
+
|
179
|
+
def strikethrough_color(value)
|
180
|
+
with_attributes({NSStrikethroughColorAttributeName => value})
|
181
|
+
end
|
182
|
+
|
183
|
+
def shadow(value)
|
184
|
+
with_attributes({NSShadowAttributeName => value})
|
185
|
+
end
|
186
|
+
|
187
|
+
def obliqueness(value)
|
188
|
+
with_attributes({NSObliquenessAttributeName => value})
|
189
|
+
end
|
190
|
+
|
191
|
+
def expansion(value)
|
192
|
+
with_attributes({NSExpansionAttributeName => value})
|
193
|
+
end
|
194
|
+
|
195
|
+
def cursor(value)
|
196
|
+
with_attributes({NSCursorAttributeName => value})
|
197
|
+
end
|
198
|
+
|
199
|
+
def tool_tip(value)
|
200
|
+
with_attributes({NSToolTipAttributeName => value})
|
201
|
+
end
|
202
|
+
|
203
|
+
def marked_clause_segment(value)
|
204
|
+
with_attributes({NSMarkedClauseSegmentAttributeName => value})
|
205
|
+
end
|
206
|
+
|
207
|
+
def writing_direction(value)
|
208
|
+
with_attributes({NSWritingDirectionAttributeName => value})
|
209
|
+
end
|
210
|
+
|
211
|
+
def vertical_glyph_form(value)
|
212
|
+
with_attributes({NSVerticalGlyphFormAttributeName => value})
|
213
|
+
end
|
214
|
+
|
215
|
+
def text_alternatives(value)
|
216
|
+
with_attributes({NSTextAlternativesAttributeName => value})
|
217
|
+
end
|
218
|
+
|
219
|
+
def with_attributes(attributes)
|
220
|
+
retval = NSMutableAttributedString.alloc.initWithAttributedString(self)
|
221
|
+
retval.addAttributes(attributes, range:[0, self.length])
|
222
|
+
retval
|
223
|
+
end
|
224
|
+
|
225
|
+
def nsattributedstring
|
226
|
+
self
|
227
|
+
end
|
228
|
+
|
229
|
+
def +(attributedstring)
|
230
|
+
NSMutableAttributedString.alloc.initWithAttributedString(self) + attributedstring
|
231
|
+
end
|
232
|
+
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
class NSMutableAttributedString
|
237
|
+
|
238
|
+
def with_attributes(attributes)
|
239
|
+
self.addAttributes(attributes, range:[0, self.length])
|
240
|
+
self
|
241
|
+
end
|
242
|
+
|
243
|
+
def +(attributedstring)
|
244
|
+
self.appendAttributedString(attributedstring.nsattributedstring)
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
data/lib/sugarcube/nsstring.rb
CHANGED
data/lib/sugarcube/symbol.rb
CHANGED
@@ -207,6 +207,7 @@ class Symbol
|
|
207
207
|
system: :"systemFontOfSize:",
|
208
208
|
bold: :"boldSystemFontOfSize:",
|
209
209
|
italic: :"italicSystemFontOfSize:",
|
210
|
+
monospace: 'Monaco',
|
210
211
|
}
|
211
212
|
|
212
213
|
@font_sizes = {
|
@@ -654,14 +655,19 @@ class Symbol
|
|
654
655
|
end
|
655
656
|
alias uigesturestate uigesturerecognizerstate
|
656
657
|
|
657
|
-
def uifont(size=
|
658
|
+
def uifont(size=nil)
|
659
|
+
size ||= UIFont.systemFontSize
|
658
660
|
# system fonts
|
659
661
|
if Symbol.system_fonts.has_key? self
|
660
662
|
font = look_in(Symbol.system_fonts)
|
661
663
|
if size.is_a? Symbol
|
662
664
|
size = Symbol.font_sizes.fetch(size).uifontsize
|
663
665
|
end
|
664
|
-
font
|
666
|
+
if font.is_a?(Symbol)
|
667
|
+
font = UIFont.send(font, size)
|
668
|
+
else
|
669
|
+
font.uifont(size)
|
670
|
+
end
|
665
671
|
else
|
666
672
|
size = look_in(font_sizes).uifontsize
|
667
673
|
font = UIFont.systemFontOfSize(size)
|
data/lib/sugarcube/uiview.rb
CHANGED
@@ -1,10 +1,65 @@
|
|
1
1
|
class UIView
|
2
2
|
|
3
3
|
class << self
|
4
|
+
|
4
5
|
# returns the first responder, starting at the Window and searching every subview
|
5
6
|
def first_responder
|
6
7
|
UIApplication.sharedApplication.keyWindow.first_responder
|
7
8
|
end
|
9
|
+
|
10
|
+
def attr_updates(*attrs)
|
11
|
+
attr_accessor(*attrs)
|
12
|
+
attrs.each do |attr|
|
13
|
+
define_method(attr.setter) { |value|
|
14
|
+
if instance_variable_get(attr.ivar) != value
|
15
|
+
setNeedsDisplay
|
16
|
+
end
|
17
|
+
instance_variable_set(attr.ivar, value)
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# If options is a Numeric, it is used as the duration. Otherwise, duration
|
23
|
+
# is an option, and defaults to 0.3. All the transition methods work this
|
24
|
+
# way.
|
25
|
+
def animate(options={}, &animations)
|
26
|
+
if options.is_a? Numeric
|
27
|
+
duration = options
|
28
|
+
options = {}
|
29
|
+
else
|
30
|
+
duration = options[:duration] || 0.3
|
31
|
+
end
|
32
|
+
|
33
|
+
after_animations = options[:after]
|
34
|
+
if after_animations
|
35
|
+
if after_animations.arity == 0
|
36
|
+
after_adjusted = ->(finished){ after_animations.call }
|
37
|
+
else
|
38
|
+
after_adjusted = after_animations
|
39
|
+
end
|
40
|
+
else
|
41
|
+
after_adjusted = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
UIView.animateWithDuration( duration,
|
45
|
+
delay: options[:delay] || 0,
|
46
|
+
options: options[:options] || UIViewAnimationOptionCurveEaseInOut,
|
47
|
+
animations: proc,
|
48
|
+
completion: after_adjusted
|
49
|
+
)
|
50
|
+
nil
|
51
|
+
end
|
52
|
+
|
53
|
+
# Animation chains are great for consecutive animation blocks. Each chain can
|
54
|
+
# take the same options that UIView##animate take.
|
55
|
+
def animation_chain(options={}, &first)
|
56
|
+
chain = SugarCube::AnimationChain.new
|
57
|
+
if first
|
58
|
+
chain.and_then(options, &first)
|
59
|
+
end
|
60
|
+
return chain
|
61
|
+
end
|
62
|
+
|
8
63
|
end
|
9
64
|
|
10
65
|
# returns the first responder, or nil if it cannot be found
|
@@ -57,37 +112,6 @@ class UIView
|
|
57
112
|
self
|
58
113
|
end
|
59
114
|
|
60
|
-
# If options is a Numeric, it is used as the duration. Otherwise, duration
|
61
|
-
# is an option, and defaults to 0.3. All the transition methods work this
|
62
|
-
# way.
|
63
|
-
def self.animate(options={}, &animations)
|
64
|
-
if options.is_a? Numeric
|
65
|
-
duration = options
|
66
|
-
options = {}
|
67
|
-
else
|
68
|
-
duration = options[:duration] || 0.3
|
69
|
-
end
|
70
|
-
|
71
|
-
after_animations = options[:after]
|
72
|
-
if after_animations
|
73
|
-
if after_animations.arity == 0
|
74
|
-
after_adjusted = proc { |finished| after_animations.call }
|
75
|
-
else
|
76
|
-
after_adjusted = proc { |finished| after_animations.call(finished) }
|
77
|
-
end
|
78
|
-
else
|
79
|
-
after_adjusted = nil
|
80
|
-
end
|
81
|
-
|
82
|
-
UIView.animateWithDuration( duration,
|
83
|
-
delay: options[:delay] || 0,
|
84
|
-
options: options[:options] || UIViewAnimationOptionCurveEaseInOut,
|
85
|
-
animations: proc,
|
86
|
-
completion: after_adjusted
|
87
|
-
)
|
88
|
-
nil
|
89
|
-
end
|
90
|
-
|
91
115
|
# Same as UIView##animate, but acts on self
|
92
116
|
def animate(options={}, &animations)
|
93
117
|
if options.is_a? Numeric
|
@@ -204,19 +228,20 @@ class UIView
|
|
204
228
|
options = {size: options}
|
205
229
|
end
|
206
230
|
|
231
|
+
size = options[:size]
|
207
232
|
case direction
|
208
233
|
when :left
|
209
|
-
size
|
234
|
+
size ||= self.bounds.size.width
|
210
235
|
delta_to([-size, 0], options, &after)
|
211
236
|
when :right
|
212
|
-
size
|
213
|
-
delta_to([
|
237
|
+
size ||= self.bounds.size.width
|
238
|
+
delta_to([size, 0], options, &after)
|
214
239
|
when :up
|
215
|
-
size
|
240
|
+
size ||= self.bounds.size.height
|
216
241
|
delta_to([0, -size], options, &after)
|
217
242
|
when :down
|
218
|
-
size
|
219
|
-
delta_to([0,
|
243
|
+
size ||= self.bounds.size.height
|
244
|
+
delta_to([0, size], options, &after)
|
220
245
|
else
|
221
246
|
raise "Unknown direction #{direction.inspect}"
|
222
247
|
end
|
data/lib/sugarcube/version.rb
CHANGED
@@ -5,6 +5,10 @@ class Symbol
|
|
5
5
|
self.to_s.ivar
|
6
6
|
end
|
7
7
|
|
8
|
+
def setter
|
9
|
+
self.to_s.setter
|
10
|
+
end
|
11
|
+
|
8
12
|
def cvar
|
9
13
|
self.to_s.cvar
|
10
14
|
end
|
@@ -18,6 +22,10 @@ class NSString
|
|
18
22
|
"@#{self}"
|
19
23
|
end
|
20
24
|
|
25
|
+
def setter
|
26
|
+
"#{self}="
|
27
|
+
end
|
28
|
+
|
21
29
|
def cvar
|
22
30
|
"@@#{self}"
|
23
31
|
end
|
@@ -0,0 +1,149 @@
|
|
1
|
+
describe 'NSAttributeString' do
|
2
|
+
|
3
|
+
describe 'NSString attribute string methods' do
|
4
|
+
|
5
|
+
it 'should have #bold' do
|
6
|
+
subject = 'test'.bold
|
7
|
+
NSAttributedString.should === subject
|
8
|
+
subject.attributesAtIndex(0, effectiveRange:nil).should == {'NSFont' => :bold.uifont}
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should have #italic' do
|
12
|
+
subject = 'test'.italic
|
13
|
+
NSAttributedString.should === subject
|
14
|
+
subject.attributesAtIndex(0, effectiveRange:nil).should == {'NSFont' => :italic.uifont}
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should have #monospace' do
|
18
|
+
subject = 'test'.monospace
|
19
|
+
NSAttributedString.should === subject
|
20
|
+
subject.attributesAtIndex(0, effectiveRange:nil).should == {'NSFont' => :monospace.uifont}
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should have #underline' do
|
24
|
+
subject = 'test'.underline
|
25
|
+
NSAttributedString.should === subject
|
26
|
+
subject.attributesAtIndex(0, effectiveRange:nil).should == {'NSUnderline' => NSUnderlineStyleSingle}
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "should support all attribute names" do
|
32
|
+
before do
|
33
|
+
@subject = 'test'.attrd
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should be sane" do
|
37
|
+
@subject.isEqualToAttributedString('test'.attrd).should == true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should have `font`' do
|
41
|
+
@subject.isEqualToAttributedString('test'.attrd.font(:bold.uifont)).should != true
|
42
|
+
@subject.isEqualToAttributedString('test'.attrd.font('Helvetica')).should != true
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'should have `paragraph_style`' do
|
46
|
+
@subject.isEqualToAttributedString('test'.attrd.paragraph_style(NSMutableParagraphStyle.alloc.init.tap{|s| s.alignment = UITextAlignmentRight })).should != true
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should have `foreground_color`' do
|
50
|
+
@subject.isEqualToAttributedString('test'.attrd.foreground_color(UIColor.redColor)).should != true
|
51
|
+
@subject.isEqualToAttributedString('test'.attrd.color(UIColor.redColor)).should != true
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'should have `underline_style`' do
|
55
|
+
@subject.isEqualToAttributedString('test'.attrd.underline_style(NSUnderlineStyleSingle)).should != true
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'should have `superscript`' do
|
59
|
+
@subject.isEqualToAttributedString('test'.attrd.superscript(1)).should != true
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'should have `background_color`' do
|
63
|
+
@subject.isEqualToAttributedString('test'.attrd.background_color(UIColor.redColor)).should != true
|
64
|
+
@subject.isEqualToAttributedString('test'.attrd.bg_color(UIColor.redColor)).should != true
|
65
|
+
end
|
66
|
+
|
67
|
+
# don't care about:
|
68
|
+
# it 'should have `attachment`' do
|
69
|
+
# @subject.isEqualToAttributedString('test'.attrd.attachment()).should != true
|
70
|
+
# end
|
71
|
+
|
72
|
+
it 'should have `ligature`' do
|
73
|
+
@subject.isEqualToAttributedString('test'.attrd.ligature(2)).should != true
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should have `baseline_offset`' do
|
77
|
+
@subject.isEqualToAttributedString('test'.attrd.baseline_offset(1)).should != true
|
78
|
+
end
|
79
|
+
|
80
|
+
it 'should have `kern`' do
|
81
|
+
@subject.isEqualToAttributedString('test'.attrd.kern(1)).should != true
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should have `link`' do
|
85
|
+
@subject.isEqualToAttributedString('test'.attrd.link('http://github.com'.nsurl)).should != true
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'should have `stroke_width`' do
|
89
|
+
@subject.isEqualToAttributedString('test'.attrd.stroke_width(1)).should != true
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should have `stroke_color`' do
|
93
|
+
@subject.isEqualToAttributedString('test'.attrd.stroke_color(UIColor.redColor)).should != true
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should have `underline_color`' do
|
97
|
+
@subject.isEqualToAttributedString('test'.attrd.underline_color(UIColor.redColor)).should != true
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'should have `strikethrough_style`' do
|
101
|
+
@subject.isEqualToAttributedString('test'.attrd.strikethrough_style(NSUnderlineStyleSingle)).should != true
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should have `strikethrough_color`' do
|
105
|
+
@subject.isEqualToAttributedString('test'.attrd.strikethrough_color(UIColor.redColor)).should != true
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'should have `shadow`' do
|
109
|
+
@subject.isEqualToAttributedString('test'.attrd.shadow(NSShadow.alloc.init.tap{|s|s.shadowOffset = [1,1]})).should != true
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should have `obliqueness`' do
|
113
|
+
@subject.isEqualToAttributedString('test'.attrd.obliqueness(0.5)).should != true
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should have `expansion`' do
|
117
|
+
@subject.isEqualToAttributedString('test'.attrd.expansion(1)).should != true
|
118
|
+
end
|
119
|
+
|
120
|
+
# don't care about:
|
121
|
+
# it 'should have `cursor`' do
|
122
|
+
# @subject.isEqualToAttributedString('test'.attrd.cursor()).should != true
|
123
|
+
# end
|
124
|
+
|
125
|
+
it 'should have `tool_tip`' do
|
126
|
+
@subject.isEqualToAttributedString('test'.attrd.tool_tip('test')).should != true
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should have `marked_clause_segment`' do
|
130
|
+
@subject.isEqualToAttributedString('test'.attrd.marked_clause_segment(1)).should != true
|
131
|
+
end
|
132
|
+
|
133
|
+
# don't care about:
|
134
|
+
# it 'should have `writing_direction`' do
|
135
|
+
# @subject.isEqualToAttributedString('test'.attrd.writing_direction()).should != true
|
136
|
+
# end
|
137
|
+
|
138
|
+
it 'should have `vertical_glyph_form`' do
|
139
|
+
@subject.isEqualToAttributedString('test'.attrd.vertical_glyph_form(1)).should != true
|
140
|
+
end
|
141
|
+
|
142
|
+
# don't care about:
|
143
|
+
# it 'should have `text_alternatives`' do
|
144
|
+
# @subject.isEqualToAttributedString('test'.attrd.text_alternatives()).should != true
|
145
|
+
# end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
data/spec/nsstring_spec.rb
CHANGED
@@ -52,9 +52,9 @@ describe "NSString" do
|
|
52
52
|
str = 'test'
|
53
53
|
str_size = str.sizeWithFont(UIFont.systemFontOfSize(UIFont.labelFontSize))
|
54
54
|
label = str.uilabel
|
55
|
-
label.size.width == str_size.width
|
56
|
-
label.size.height == str_size.height
|
57
|
-
label.backgroundColor == UIColor.clearColor
|
55
|
+
label.size.width.should == str_size.width
|
56
|
+
label.size.height.should == str_size.height
|
57
|
+
label.backgroundColor.should == UIColor.clearColor
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should have a #uilabel(font) method" do
|
@@ -63,9 +63,9 @@ describe "NSString" do
|
|
63
63
|
str_size = str.sizeWithFont(font)
|
64
64
|
label = str.uilabel(font)
|
65
65
|
label.font.should == font
|
66
|
-
label.size.width == str_size.width
|
67
|
-
label.size.height == str_size.height
|
68
|
-
label.backgroundColor == UIColor.clearColor
|
66
|
+
label.size.width.should == str_size.width
|
67
|
+
label.size.height.should == str_size.height
|
68
|
+
label.backgroundColor.should == UIColor.clearColor
|
69
69
|
end
|
70
70
|
|
71
71
|
it "should have a #escape_url method" do
|
@@ -0,0 +1,61 @@
|
|
1
|
+
describe "SugarCube::AnimationChain" do
|
2
|
+
tests SugarCube::AnimationChainController
|
3
|
+
|
4
|
+
it "should have a view" do
|
5
|
+
controller.view.should != nil
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should support chains" do
|
9
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
10
|
+
@variable_a = nil
|
11
|
+
@variable_b = nil
|
12
|
+
UIView.animation_chain(duration:0.1){
|
13
|
+
@variable_a = 'a'
|
14
|
+
}.and_then(duration: 0.1){
|
15
|
+
@variable_b = 'b'
|
16
|
+
}.start
|
17
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
18
|
+
|
19
|
+
wait 0.3 {
|
20
|
+
@variable_a.should == 'a'
|
21
|
+
@variable_b.should == 'b'
|
22
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should support multiple chains" do
|
27
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
28
|
+
@variable_a = nil
|
29
|
+
@variable_b = nil
|
30
|
+
UIView.animation_chain(duration:0.1, delay:0.1){
|
31
|
+
@variable_a = 'a'
|
32
|
+
}.start
|
33
|
+
UIView.animation_chain(duration:0.1, delay:0.1){
|
34
|
+
@variable_b = 'b'
|
35
|
+
}.start
|
36
|
+
SugarCube::AnimationChain.chains.length.should == 2
|
37
|
+
|
38
|
+
wait 0.3 {
|
39
|
+
@variable_a.should == 'a'
|
40
|
+
@variable_b.should == 'b'
|
41
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should support << syntax" do
|
46
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
47
|
+
@variable_a = nil
|
48
|
+
@variable_b = nil
|
49
|
+
chain = UIView.animation_chain
|
50
|
+
chain << proc { @variable_a = 'a' } << proc { @variable_b = 'b' }
|
51
|
+
chain.start
|
52
|
+
SugarCube::AnimationChain.chains.length.should == 1
|
53
|
+
|
54
|
+
wait 0.3 {
|
55
|
+
@variable_a.should == 'a'
|
56
|
+
@variable_b.should == 'b'
|
57
|
+
SugarCube::AnimationChain.chains.length.should == 0
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class AttrUpdatesTest < UIView
|
2
|
+
|
3
|
+
attr_updates :color
|
4
|
+
attr :did_update
|
5
|
+
|
6
|
+
def setNeedsDisplay
|
7
|
+
@did_update = true
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def reset!
|
12
|
+
@did_update = false
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'UIView##attr_updates' do
|
18
|
+
|
19
|
+
it 'should assign the ivar' do
|
20
|
+
subject = AttrUpdatesTest.new
|
21
|
+
subject.color = :red
|
22
|
+
subject.color.should == :red
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should reset did_update' do
|
26
|
+
subject = AttrUpdatesTest.new
|
27
|
+
subject.reset!
|
28
|
+
subject.did_update.should == false
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should cause setNeedsDisplay to be called' do
|
32
|
+
subject = AttrUpdatesTest.new
|
33
|
+
subject.reset!
|
34
|
+
subject.did_update.should == false
|
35
|
+
subject.color = :red # value changed from nil
|
36
|
+
subject.color.should == :red
|
37
|
+
subject.did_update.should == true
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should not cause setNeedsDisplay to be called if the value doesn\'t change' do
|
41
|
+
subject = AttrUpdatesTest.new
|
42
|
+
subject.reset!
|
43
|
+
subject.did_update.should == false
|
44
|
+
subject.color = :red # value changed from nil
|
45
|
+
subject.color.should == :red
|
46
|
+
subject.did_update.should == true
|
47
|
+
subject.reset!
|
48
|
+
subject.did_update.should == false
|
49
|
+
subject.color = :red # same value, so no update
|
50
|
+
subject.color.should == :red
|
51
|
+
subject.did_update.should == false
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
data/spec/unholy_spec.rb
CHANGED
@@ -4,10 +4,18 @@ describe "Sanity" do
|
|
4
4
|
:name.ivar.should == '@name'
|
5
5
|
end
|
6
6
|
|
7
|
+
it "should have Symbol#setter" do
|
8
|
+
:name.setter.should == 'name='
|
9
|
+
end
|
10
|
+
|
7
11
|
it "should have String#ivar" do
|
8
12
|
'another'.ivar.should == '@another'
|
9
13
|
end
|
10
14
|
|
15
|
+
it "should have String#setter" do
|
16
|
+
'another'.setter.should == 'another='
|
17
|
+
end
|
18
|
+
|
11
19
|
it "should have Symbol#cvar" do
|
12
20
|
:name.cvar.should == '@@name'
|
13
21
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sugarcube
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2013-02-
|
16
|
+
date: 2013-02-15 00:00:00.000000000 Z
|
17
17
|
dependencies: []
|
18
18
|
description: ! '== Description
|
19
19
|
|
@@ -47,6 +47,7 @@ files:
|
|
47
47
|
- LICENSE
|
48
48
|
- README.md
|
49
49
|
- Rakefile
|
50
|
+
- app/animation_chain_controller.rb
|
50
51
|
- app/app_delegate.rb
|
51
52
|
- lib/sugarcube-568.rb
|
52
53
|
- lib/sugarcube-568/uiimage.rb
|
@@ -57,6 +58,7 @@ files:
|
|
57
58
|
- lib/sugarcube.rb
|
58
59
|
- lib/sugarcube/activesupport.rb
|
59
60
|
- lib/sugarcube/adjust.rb
|
61
|
+
- lib/sugarcube/animation_chain.rb
|
60
62
|
- lib/sugarcube/calayer.rb
|
61
63
|
- lib/sugarcube/core_graphics.rb
|
62
64
|
- lib/sugarcube/core_location.rb
|
@@ -65,6 +67,7 @@ files:
|
|
65
67
|
- lib/sugarcube/modal.rb
|
66
68
|
- lib/sugarcube/notifications.rb
|
67
69
|
- lib/sugarcube/nsarray.rb
|
70
|
+
- lib/sugarcube/nsattributedstring.rb
|
68
71
|
- lib/sugarcube/nscoder.rb
|
69
72
|
- lib/sugarcube/nsdata.rb
|
70
73
|
- lib/sugarcube/nsdate.rb
|
@@ -125,6 +128,7 @@ files:
|
|
125
128
|
- spec/fixnum_spec.rb
|
126
129
|
- spec/notification_spec.rb
|
127
130
|
- spec/nsarray_spec.rb
|
131
|
+
- spec/nsattributedstring_spec.rb
|
128
132
|
- spec/nscoder_spec.rb
|
129
133
|
- spec/nsdata_spec.rb
|
130
134
|
- spec/nsdate_spec.rb
|
@@ -138,7 +142,9 @@ files:
|
|
138
142
|
- spec/uicolor_spec.rb
|
139
143
|
- spec/uiimage_color_at_spec.rb
|
140
144
|
- spec/uiimage_scale_spec.rb
|
145
|
+
- spec/uiview_animation_chain_spec.rb
|
141
146
|
- spec/uiview_animation_spec.rb
|
147
|
+
- spec/uiview_attr_updates_spec.rb
|
142
148
|
- spec/uiview_spec.rb
|
143
149
|
- spec/unholy_spec.rb
|
144
150
|
- sugarcube.gemspec
|
@@ -177,6 +183,7 @@ test_files:
|
|
177
183
|
- spec/fixnum_spec.rb
|
178
184
|
- spec/notification_spec.rb
|
179
185
|
- spec/nsarray_spec.rb
|
186
|
+
- spec/nsattributedstring_spec.rb
|
180
187
|
- spec/nscoder_spec.rb
|
181
188
|
- spec/nsdata_spec.rb
|
182
189
|
- spec/nsdate_spec.rb
|
@@ -190,7 +197,9 @@ test_files:
|
|
190
197
|
- spec/uicolor_spec.rb
|
191
198
|
- spec/uiimage_color_at_spec.rb
|
192
199
|
- spec/uiimage_scale_spec.rb
|
200
|
+
- spec/uiview_animation_chain_spec.rb
|
193
201
|
- spec/uiview_animation_spec.rb
|
202
|
+
- spec/uiview_attr_updates_spec.rb
|
194
203
|
- spec/uiview_spec.rb
|
195
204
|
- spec/unholy_spec.rb
|
196
205
|
has_rdoc:
|