sugarcube 0.16.9 → 0.18.0

Sign up to get free protection for your applications and to get access to all the features.
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
- "blue".uicolor # => UIColor.colorWithPatternImage(UIImage.imageNamed("blue"))
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 == 0x00f0f.uicolor. There's no way to tell the difference
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,12 @@
1
+ class AnimationChainController < UIViewController
2
+
3
+ def loadView
4
+ super.tap do
5
+ @label = 'Hi!'.uilabel
6
+ @label.center = self.view.center
7
+ @label.textColor = :white.uicolor
8
+ self.view << @label
9
+ end
10
+ end
11
+
12
+ end
@@ -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
@@ -22,7 +22,8 @@ class NSString
22
22
  end
23
23
 
24
24
  # @return [UIFont]
25
- def uifont(size=UIFont.systemFontSize)
25
+ def uifont(size=nil)
26
+ size ||= UIFont.systemFontSize
26
27
  UIFont.fontWithName(self, size:size)
27
28
  end
28
29
 
@@ -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=UIFont.systemFontSize)
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 = UIFont.send(font, size)
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)
@@ -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 = options[:size] || self.bounds.size.width
234
+ size ||= self.bounds.size.width
210
235
  delta_to([-size, 0], options, &after)
211
236
  when :right
212
- size = options[:size] || self.bounds.size.width
213
- delta_to([+size, 0], options, &after)
237
+ size ||= self.bounds.size.width
238
+ delta_to([size, 0], options, &after)
214
239
  when :up
215
- size = options[:size] || self.bounds.size.height
240
+ size ||= self.bounds.size.height
216
241
  delta_to([0, -size], options, &after)
217
242
  when :down
218
- size = options[:size] || self.bounds.size.height
219
- delta_to([0, +size], options, &after)
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
@@ -1,3 +1,3 @@
1
1
  module SugarCube
2
- Version = '0.16.9'
2
+ Version = '0.18.0'
3
3
  end
@@ -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
@@ -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.16.9
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-12 00:00:00.000000000 Z
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: