sugarcube 0.19.0 → 0.19.2

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
@@ -1081,6 +1081,20 @@ end
1081
1081
  text_view.off :change, :end, :begin
1082
1082
  ```
1083
1083
 
1084
+ UILabel
1085
+ ----------
1086
+
1087
+ Added simple `fit_to_size` function to the label, which will start at the supplied font size
1088
+ and then squeeze down until all the text fits. This way you can assure any dynamic text will completely display
1089
+ in a given label frame.
1090
+
1091
+ The font size changes instead of the frame size.
1092
+ ```ruby
1093
+ #this will try to make the containing text fit at font size 40, but squeeze as needed.
1094
+ @label.fit_to_size(40)
1095
+ puts @label.font.pointSize # => Will be 40 or less depending on the font type and label frame.
1096
+ ```
1097
+
1084
1098
  UIBarButtonItem
1085
1099
  ----------------------
1086
1100
 
@@ -0,0 +1,49 @@
1
+ class UIControlController < UIViewController
2
+ attr :button1
3
+ attr :button2
4
+ attr :touched
5
+ attr :touched_count
6
+ attr :event
7
+ attr :touched_1
8
+ attr :touched_2
9
+
10
+ def reset
11
+ @touched = nil
12
+ @touched_count = 0
13
+ @event = nil
14
+ @touched_1 = false
15
+ @touched_2 = false
16
+ end
17
+
18
+ def loadView
19
+ super.tap do
20
+ @button1 = UIButton.rounded
21
+ @button1.setTitle('one', forState: :normal.uicontrolstate)
22
+ @button1.sizeToFit
23
+ @button1.center = self.view.center
24
+ self.view << @button1
25
+
26
+ @button2 = UIButton.rounded
27
+ @button2.setTitle('two', forState: :normal.uicontrolstate)
28
+ @button2.sizeToFit
29
+ @button2.center = [@button1.center.x, @button1.center.y + 30]
30
+ @button1.center = [@button1.center.x, @button1.center.y - 30]
31
+ self.view << @button2
32
+
33
+ @button1.on :touch { |sender,event|
34
+ @touched_1 = true
35
+ @touched = sender
36
+ @touched_count += 1
37
+ }
38
+
39
+ @button2.on :touch { |sender,event|
40
+ @touched_2 = true
41
+ @touched = sender
42
+ @touched_count += 1
43
+ }
44
+
45
+ reset
46
+ end
47
+ end
48
+
49
+ end
@@ -1,4 +1,10 @@
1
1
  class NSDate
2
+ # these formatters are used in `string_with_format`. Symbols are convertd to
3
+ # a string using string_with_format's templating, and strings are concatenated
4
+ # as-is
5
+ SugarCubeFormats = {
6
+ iso8601: [:yyyy, '-', :MM, '-', :dd, ' ', :HH, ':', :mm, ':', :ss, '.', :SSS]
7
+ }
2
8
 
3
9
  def self.from_components(components)
4
10
  date_components = NSDateComponents.new
@@ -18,12 +24,35 @@ class NSDate
18
24
  date_formatter.stringFromDate(self)
19
25
  end
20
26
 
27
+ # Pass in a format string or a Symbol. The Symbol must exist in
28
+ # NSDate::SugarCubeFormats.
29
+ #
30
+ # See
31
+ # <https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1>
32
+ # and
33
+ # <http://www.unicode.org/reports/tr35/tr35-19.html#Date_Format_Patterns>
34
+ # for more information about date format strings.
21
35
  def string_with_format(format)
22
- format_template = NSDateFormatter.dateFormatFromTemplate(format, options:0,
23
- locale:NSLocale.currentLocale)
24
- date_formatter = NSDateFormatter.new
25
- date_formatter.setDateFormat(format_template)
26
- date_formatter.stringFromDate(self)
36
+ if format.is_a?(Symbol)
37
+ formatters = SugarCubeFormats[format]
38
+ raise "No format found for #{format.inspect}" unless formatters
39
+ retval = ''
40
+ formatters.each do |formatter|
41
+ case formatter
42
+ when Symbol
43
+ retval << string_with_format(formatter.to_s)
44
+ when String
45
+ retval << formatter
46
+ end
47
+ end
48
+ return retval
49
+ else
50
+ format_template = NSDateFormatter.dateFormatFromTemplate(format, options:0,
51
+ locale:NSLocale.currentLocale)
52
+ date_formatter = NSDateFormatter.new
53
+ date_formatter.setDateFormat(format_template)
54
+ return date_formatter.stringFromDate(self)
55
+ end
27
56
  end
28
57
 
29
58
  def upto(last_date, delta={days: 1}, &block)
@@ -47,6 +47,22 @@ class Symbol
47
47
  }
48
48
 
49
49
  @css_colors = {
50
+ # for css_name to pick up on these colors, they need to be defined here
51
+ black: 0x000000,
52
+ blue: 0x0000ff,
53
+ brown: 0x996633,
54
+ cyan: 0x00ffff,
55
+ darkgray: 0x555555,
56
+ gray: 0x808080,
57
+ green: 0x00ff00,
58
+ lightgray: 0xaaaaaa,
59
+ magenta: 0xff00ff,
60
+ orange: 0xff8000,
61
+ purple: 0x800080,
62
+ red: 0xff0000,
63
+ yellow: 0xffff00,
64
+ white: 0xffffff,
65
+
50
66
  aliceblue: 0xf0f8ff,
51
67
  antiquewhite: 0xfaebd7,
52
68
  aqua: 0x00ffff,
@@ -176,22 +192,6 @@ class Symbol
176
192
  wheat: 0xf5deb3,
177
193
  whitesmoke: 0xf5f5f5,
178
194
  yellowgreen: 0x9acd32,
179
-
180
- # for to_s to pick up on these colors, they need to be defined here
181
- black: 0x000000,
182
- blue: 0x0000ff,
183
- brown: 0x996633,
184
- cyan: 0x00ffff,
185
- darkgray: 0x555555,
186
- gray: 0x808080,
187
- green: 0x00ff00,
188
- lightgray: 0xaaaaaa,
189
- magenta: 0xff00ff,
190
- orange: 0xff8000,
191
- purple: 0x800080,
192
- red: 0xff0000,
193
- yellow: 0xffff00,
194
- white: 0xffffff,
195
195
  }
196
196
 
197
197
  end
@@ -1,34 +1,11 @@
1
1
  class UIColor
2
+
2
3
  def to_s
3
- system_color = nil
4
- Symbol.uicolors.each_pair do |color, method|
5
- if UIColor.send(method) == self
6
- if self.alpha && self.alpha < 1
7
- system_color = "UIColor.#{method}(#{alpha})"
8
- else
9
- system_color = "UIColor.#{method}"
10
- end
11
- break
12
- end
13
- end
4
+ system_color = system_name
14
5
  return system_color if system_color
15
6
 
16
- if self.red && self.green && self.blue
17
- red = (self.red * 255).round << 16
18
- green = (self.green * 255).round << 8
19
- blue = (self.blue * 255).round
20
- my_color = red + green + blue
21
-
22
- inside = my_color.to_s(16)
23
- inside = '0x' + '0' * (6 - inside.length) + inside
24
-
25
- Symbol.css_colors.each_pair do |color, hex|
26
- if hex == my_color
27
- inside = color.inspect
28
- break
29
- end
30
- end
31
-
7
+ inside = self.css_name || self.hex
8
+ if inside
32
9
  if self.alpha < 1
33
10
  return "UIColor.color(#{inside}, #{alpha})"
34
11
  else
@@ -38,4 +15,18 @@ class UIColor
38
15
  super
39
16
  end
40
17
  end
18
+
19
+ def inspect
20
+ alpha_s = ((alpha || 1) < 1 ? "(#{alpha})" : '')
21
+ if system_name
22
+ return "UIColor.#{system_name}#{alpha_s}"
23
+ elsif hex
24
+ return "'#{hex}'.uicolor#{alpha_s}"
25
+ elsif css_name
26
+ return ":#{css_name}.uicolor#{alpha_s}"
27
+ else
28
+ super
29
+ end
30
+ end
31
+
41
32
  end
@@ -72,15 +72,61 @@ class UIColor
72
72
  _sugarcube_colors && _sugarcube_colors[:alpha]
73
73
  end
74
74
 
75
+ # returns the components OR'd together, as 32 bit RGB integer.
76
+ def to_i
77
+ if self.red && self.green && self.blue
78
+ red = (self.red * 255).round << 16
79
+ green = (self.green * 255).round << 8
80
+ blue = (self.blue * 255).round
81
+ return red + green + blue
82
+ else
83
+ return nil
84
+ end
85
+ end
86
+
87
+ # returns the components as an array of 32 bit RGB values
88
+ def to_a
89
+ if self.red && self.green && self.blue
90
+ red = (self.red * 255).round
91
+ green = (self.green * 255).round
92
+ blue = (self.blue * 255).round
93
+ return [red, green, blue]
94
+ else
95
+ return nil
96
+ end
97
+ end
98
+
99
+ def hex
100
+ my_color = self.to_i
101
+ if my_color
102
+ return '#' + my_color.to_s(16).rjust(6, '0')
103
+ else
104
+ nil
105
+ end
106
+ end
107
+
75
108
  # returns the closest css name
76
109
  def css_name
77
- found = Symbol.css_colors.map { |key, val| [key, _sugarcube_color_compare(self, val.uicolor)] }.inject{|c1,c2| c1[1] < c2[1] ? c1 : c2 }
78
- threshold = 0.03
79
- if found[1] > 0.03
80
- nil
81
- else
82
- found[0]
110
+ my_color = self.to_i
111
+ css_name = nil
112
+ Symbol.css_colors.each_pair do |color, hex|
113
+ if hex == my_color
114
+ css_name = color
115
+ break
116
+ end
117
+ end
118
+ return css_name
119
+ end
120
+
121
+ def system_name
122
+ system_color = nil
123
+ Symbol.uicolors.each_pair do |color, method|
124
+ if UIColor.send(method) == self
125
+ system_color = method
126
+ break
127
+ end
83
128
  end
129
+ return system_color.to_s
84
130
  end
85
131
 
86
132
  private
@@ -1,12 +1,6 @@
1
+ # Additions to UIControl to support jQuery-style `on` and `off` methods.
1
2
  class UIControl
2
3
 
3
- # event blocks need to be retained, and the addTarget method explicitly does
4
- # *not* retain `target`. This makes sure that callbacks are retained by
5
- # pushing the block onto a stack.
6
- def sugarcube_callbacks
7
- @sugarcube_callbacks ||= Hash.new { |hash, key| hash[key] = [] }
8
- end
9
-
10
4
  # Add event handlers to UIControls. See symbol.rb for the uicontrolevent
11
5
  # constant aliases.
12
6
  #
@@ -14,12 +8,17 @@ class UIControl
14
8
  # button = UIButton.alloc.initWithFrame([0, 0, 10, 10])
15
9
  # button.on(:touch) { my_code }
16
10
  # button.on(:touchupoutside, :touchcancel) { my_code }
11
+ # # up to two arguments can be passed in
12
+ # button.on(:touch) { |sender,touch_event| my_code }
17
13
  def on(*events, &block)
14
+ handler = SugarCube::UIControlCallbackHelper.new
15
+ handler.callback = block
16
+
18
17
  events.each do |event|
19
18
  event = event.uicontrolevent unless event.is_a? Fixnum
20
19
 
21
- sugarcube_callbacks[event].push block
22
- addTarget(block, action: :call, forControlEvents:event)
20
+ sugarcube_callbacks[event].push(handler)
21
+ addTarget(handler, action:'call:event:', forControlEvents:event)
23
22
  end
24
23
 
25
24
  self
@@ -40,12 +39,38 @@ class UIControl
40
39
  events.each do |event|
41
40
  event = event.uicontrolevent unless event.is_a? Fixnum
42
41
 
43
- sugarcube_callbacks[event].each do |block|
44
- self.removeTarget(block, action: :call, forControlEvents:event)
42
+ sugarcube_callbacks[event].each do |handler|
43
+ self.removeTarget(handler, action:'call:event:', forControlEvents:event)
45
44
  end
46
45
  sugarcube_callbacks.delete(event)
47
46
  end
48
47
  self
49
48
  end
50
49
 
50
+ # private
51
+ # event blocks need to be retained, and the addTarget method explicitly does
52
+ # *not* retain `target`. This makes sure that callbacks are retained by
53
+ # pushing the block onto a stack.
54
+ def sugarcube_callbacks
55
+ @sugarcube_callbacks ||= Hash.new { |hash, key| hash[key] = [] }
56
+ end
57
+
58
+ end
59
+
60
+
61
+ module SugarCube
62
+ class UIControlCallbackHelper
63
+ attr_accessor :callback
64
+
65
+ def call(sender, event:event)
66
+ case callback.arity
67
+ when 0
68
+ callback.call
69
+ when 1
70
+ callback.call(sender)
71
+ else
72
+ callback.call(sender, event)
73
+ end
74
+ end
75
+ end
51
76
  end
@@ -0,0 +1,22 @@
1
+ class UILabel
2
+
3
+ # forces the given text to fit inside the label's frame starting at a given font size
4
+ def fit_to_size(max_size)
5
+ #enforce word wrap
6
+ self.lineBreakMode = UILineBreakModeWordWrap
7
+
8
+ dynamic_font = self.font.fontWithSize(max_size + 2)
9
+ constraintSize = CGSizeMake(self.frame.size.width, 10000)
10
+
11
+ # does it fit yet?
12
+ begin
13
+ dynamic_font = dynamic_font.fontWithSize(dynamic_font.pointSize - 2)
14
+ current_size = self.text.sizeWithFont(dynamic_font, constrainedToSize:constraintSize, lineBreakMode:UILineBreakModeWordWrap)
15
+ end while self.frame.size.height <= current_size.height
16
+
17
+ #now set to font size we have settled on
18
+ self.font = dynamic_font
19
+
20
+ end
21
+
22
+ end
@@ -10,11 +10,11 @@ class UIView
10
10
  def attr_updates(*attrs)
11
11
  attr_accessor(*attrs)
12
12
  attrs.each do |attr|
13
- define_method(attr.setter) { |value|
14
- if instance_variable_get(attr.ivar) != value
13
+ define_method("#{attr}=") { |value|
14
+ if instance_variable_get("@#{attr}") != value
15
15
  setNeedsDisplay
16
16
  end
17
- instance_variable_set(attr.ivar, value)
17
+ instance_variable_set("@#{attr}", value)
18
18
  }
19
19
  end
20
20
  end
@@ -1,3 +1,3 @@
1
1
  module SugarCube
2
- Version = '0.19.0'
2
+ Version = '0.19.2'
3
3
  end
data/runtests CHANGED
@@ -1 +1 @@
1
- rake spec && rake spec retina=3.5 && rake spec retina=4
1
+ rake spec && rake spec retina=3.5 && rake spec retina=4 output=tap
data/spec/nsdate_spec.rb CHANGED
@@ -37,6 +37,10 @@ describe "NSDate" do
37
37
  @date.string_with_format("yyyyMMMMd HH:mm:ss").should == 'January 2, 2013, 12:15:30'
38
38
  end
39
39
 
40
+ it "should have an NSDate#string_with_format method (:iso8601)" do
41
+ @date.string_with_format(:iso8601).should == '2013-01-02 12:15:30.000'
42
+ end
43
+
40
44
  it "should have an NSDate#timezone method" do
41
45
  String.should === @date.timezone.name
42
46
  end
@@ -0,0 +1,46 @@
1
+ describe 'UIColor (CSS)' do
2
+
3
+ it "should have a #to_i method" do
4
+ UIColor.whiteColor.to_i.should == 16777215
5
+ UIColor.blackColor.to_i.should == 0
6
+ end
7
+
8
+ it "should have a #to_a method" do
9
+ UIColor.whiteColor.to_a.should == [255, 255, 255]
10
+ UIColor.blackColor.to_a.should == [0, 0, 0]
11
+ end
12
+
13
+ it "should have a #hex method" do
14
+ UIColor.whiteColor.hex.should == '#ffffff'
15
+ UIColor.blackColor.hex.should == '#000000'
16
+ end
17
+
18
+ it "should have a #system_name method" do
19
+ UIColor.whiteColor.system_name.should == 'whiteColor'
20
+ UIColor.blackColor.system_name.should == 'blackColor'
21
+ end
22
+
23
+ it "should return css color names" do
24
+ corrections = {
25
+ aqua: :cyan,
26
+ lime: :green,
27
+ fuchsia: :magenta,
28
+ }
29
+ Symbol.css_colors.each do |name, val|
30
+ name = corrections[name] || name
31
+
32
+ color = val.uicolor
33
+ color.css_name.should == name
34
+ end
35
+ end
36
+
37
+ it "should return UIColor objects" do
38
+ Symbol.uicolors.each do |name, method|
39
+ name.uicolor.should == UIColor.send(method)
40
+ end
41
+ Symbol.css_colors.each do |name, val|
42
+ name.uicolor.is_a?(UIColor).should == true
43
+ end
44
+ end
45
+
46
+ end
@@ -0,0 +1,36 @@
1
+ describe 'UIControl' do
2
+ tests UIControlController
3
+
4
+ before do
5
+ controller.reset
6
+ end
7
+
8
+ it 'should have two buttons' do
9
+ UIButton.should === controller.button1
10
+ UIButton.should === controller.button2
11
+ end
12
+
13
+ it 'button1 should respond to touches' do
14
+ controller.button1.sendActionsForControlEvents(:touch.uicontrolevent)
15
+ controller.touched.should == controller.button1
16
+ controller.touched_1.should == true
17
+ controller.touched_count.should == 1
18
+ end
19
+
20
+ it 'button2 should respond to touches' do
21
+ controller.button2.sendActionsForControlEvents(:touch.uicontrolevent)
22
+ controller.touched.should == controller.button2
23
+ controller.touched_2.should == true
24
+ controller.touched_count.should == 1
25
+ end
26
+
27
+ it 'should be able to share handlers with arity 1 (sender)' do
28
+ controller.button1.sendActionsForControlEvents(:touch.uicontrolevent)
29
+ controller.button2.sendActionsForControlEvents(:touch.uicontrolevent)
30
+ controller.touched.should == controller.button2
31
+ controller.touched_1.should == true
32
+ controller.touched_2.should == true
33
+ controller.touched_count.should == 2
34
+ end
35
+
36
+ end
@@ -0,0 +1,12 @@
1
+ describe "UILabel" do
2
+
3
+ it 'should have a #fit_to_size method' do
4
+ @label = UILabel.alloc.initWithFrame([[10, 10], [200, 40]])
5
+ @label.text = "Timeo Danaos et dona ferentes" * 10
6
+ @label.numberOfLines = 0
7
+ @label.fit_to_size(40)
8
+
9
+ @label.font.pointSize.should < 40
10
+ @label.font.pointSize.should > 0
11
+ end
12
+ 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.19.0
4
+ version: 0.19.2
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-03-17 00:00:00.000000000 Z
16
+ date: 2013-03-19 00:00:00.000000000 Z
17
17
  dependencies: []
18
18
  description: ! '== Description
19
19
 
@@ -49,6 +49,7 @@ files:
49
49
  - Rakefile
50
50
  - app/animation_chain_controller.rb
51
51
  - app/app_delegate.rb
52
+ - app/uicontrol_controller.rb
52
53
  - lib/sugarcube-568.rb
53
54
  - lib/sugarcube-568/uiimage.rb
54
55
  - lib/sugarcube-attributedstring.rb
@@ -104,6 +105,7 @@ files:
104
105
  - lib/sugarcube/uicontrol.rb
105
106
  - lib/sugarcube/uifont.rb
106
107
  - lib/sugarcube/uiimage.rb
108
+ - lib/sugarcube/uilabel.rb
107
109
  - lib/sugarcube/uipickerview.rb
108
110
  - lib/sugarcube/uisegmentedcontrol.rb
109
111
  - lib/sugarcube/uitableview.rb
@@ -146,10 +148,12 @@ files:
146
148
  - spec/timer_spec.rb
147
149
  - spec/uibarbuttonitem_spec.rb
148
150
  - spec/uicolor_components_spec.rb
149
- - spec/uicolor_css_spec.rb
151
+ - spec/uicolor_other_representations_spec.rb
150
152
  - spec/uicolor_spec.rb
153
+ - spec/uicontrol_spec.rb
151
154
  - spec/uiimage_color_at_spec.rb
152
155
  - spec/uiimage_scale_spec.rb
156
+ - spec/uilabel_spec.rb
153
157
  - spec/uiview_animation_spec.rb
154
158
  - spec/uiview_attr_updates_spec.rb
155
159
  - spec/uiview_spec.rb
@@ -206,10 +210,12 @@ test_files:
206
210
  - spec/timer_spec.rb
207
211
  - spec/uibarbuttonitem_spec.rb
208
212
  - spec/uicolor_components_spec.rb
209
- - spec/uicolor_css_spec.rb
213
+ - spec/uicolor_other_representations_spec.rb
210
214
  - spec/uicolor_spec.rb
215
+ - spec/uicontrol_spec.rb
211
216
  - spec/uiimage_color_at_spec.rb
212
217
  - spec/uiimage_scale_spec.rb
218
+ - spec/uilabel_spec.rb
213
219
  - spec/uiview_animation_spec.rb
214
220
  - spec/uiview_attr_updates_spec.rb
215
221
  - spec/uiview_spec.rb
@@ -1,23 +0,0 @@
1
- describe 'UIColor (CSS)' do
2
-
3
- it "should return css color names" do
4
- except_for = [:aqua, :fuchsia, :lime, :black, :blue, :brown, :cyan, :darkgray, :gray, :green, :lightgray, :magenta, :orange, :purple, :red, :yellow, :white]
5
- Symbol.css_colors.each do |name, val|
6
- next if except_for.include? name
7
-
8
- color = val.uicolor
9
- color.css_name.should == name
10
- color.to_s.should == "UIColor.color(#{name.inspect})"
11
- end
12
- end
13
-
14
- it "should return UIColor objects" do
15
- Symbol.uicolors.each do |name, method|
16
- name.uicolor.should == UIColor.send(method)
17
- end
18
- Symbol.css_colors.each do |name, val|
19
- name.uicolor.is_a?(UIColor).should == true
20
- end
21
- end
22
-
23
- end