sugarcube 0.19.0 → 0.19.2

Sign up to get free protection for your applications and to get access to all the features.
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