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 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: