teacup 2.3.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: cfe17cc290b5832599be8594c185cf67699aa667
4
- data.tar.gz: 6a6c4ac9230c4d1292b5b81feb344035de230a13
3
+ metadata.gz: 4821b6532d8a60017501696bb0ba85647b46974b
4
+ data.tar.gz: 00a8be407b48a624e3e07c735122871029228bc4
5
5
  SHA512:
6
- metadata.gz: 689b8e6bcbe6a90f24684fb78258fe3b30f605c6f41eb8e1cbee7614033e1348a4be371d716c8a1d99fa6357e9e97c705444f2ad07bb928fce16adeca6f25001
7
- data.tar.gz: 9ebc65ac66f076e60a2816780ce425078da8b331f60bcb415e2ccd774fdf76c40a1c8c5b13e933664b0a9f79e91db5faac6c8c8b4a431c0e4cc87b20a3fc2110
6
+ metadata.gz: 4ed282b7d63702e9ffc0c72a2a5ea436ca989f41111d1c5e13172376da27160216c43806884f7fe0dd49e62fa6ca528c4a1cf12431c06817da41fed2458cbb4b
7
+ data.tar.gz: 7f61cfc625f369c9e53802b9aa28e3a1f016f888fc9936505942c4b093febcf02a9ea2edb120d5ec9daf92121d52c54a400326ebaead379ade403bd82b1ee125
data/README.md CHANGED
@@ -63,7 +63,7 @@ require 'teacup'
63
63
  class MyController < UIViewController
64
64
  stylesheet :main_screen
65
65
 
66
- layout do
66
+ def teacup_layout
67
67
  subview(UIButton, :hi_button)
68
68
  end
69
69
  end
@@ -103,7 +103,7 @@ other GUI system ever*. :-|
103
103
  class MyController < TeacupWindowController
104
104
  stylesheet :main_window
105
105
 
106
- layout do
106
+ def teacup_layout
107
107
  subview(NSButton, :hi_button)
108
108
  end
109
109
  end
@@ -139,6 +139,36 @@ Teacup supports [Pixate][] and [NUI][], too, so you can use those systems for
139
139
  styling and Teacup to manage your view hierarchy and apply auto-layout
140
140
  constraints. Teacup can also integrate with the [motion-layout][] gem!
141
141
 
142
+ ### Changes in 3.0
143
+
144
+ There is one significant change in version 3.0. In every version of Teacup
145
+ prior (from 0.2.0 to 2.3.0) the controller layout was usually created by calling
146
+ a class method called `layout`. It was discovered, embarrassingly late, that
147
+ this system is causing memory leaks. To fix it we had to remove this feature
148
+ altogether. So if you are looking at old Teacup examples, you will see this
149
+ block syntax that is no longer offered. It is easy to update to 3.0, though:
150
+
151
+ ```ruby
152
+ # <= 2.3.0
153
+ class MyController < UIViewController
154
+ layout(:root_stylename) do # <= this block is what caused the memory leak!
155
+ # teacup code goes here
156
+ end
157
+ end
158
+
159
+ # 3.0
160
+ class MyController < UIViewController
161
+ def teacup_layout # in 3.0 we just changed it to be a method
162
+ # introduced in 3.0, this is how you assign a stylename to the root view
163
+ root(:root_stylename, { background: UIColor.blueColor })
164
+ # teacup code goes here - no other code changes necessary
165
+ end
166
+ # actually, this method still works as long as you don't pass a block. It's
167
+ # the same as calling `root(stylename, {})`
168
+ layout(:root_stylename, {})
169
+ end
170
+ ```
171
+
142
172
  ### Table of Contents
143
173
 
144
174
  * [Layouts](#layouts) — define your views
@@ -178,17 +208,18 @@ iOS, and `NSWindowController`, `NSViewController`, and `NSView` on OS X. These
178
208
  classes can take advantage of the view-hierarchy DSL.
179
209
 
180
210
  You saw an example in the primer, using the
181
- `UIViewController`/`NSWindowController` class method `layout`. This is a helper
182
- function that stores the layout code. A more direct example might look like
183
- this:
211
+ `UIViewController`/`NSWindowController` class method `layout` and the
212
+ `teacup_layout` method. You could just as easily use Teacup's DSL to create
213
+ your views from a `loadView` method, for instance you might want to use a
214
+ custom view subclass as your root view. An example might look like this:
184
215
 
185
216
  ```ruby
186
217
  # controller example
187
218
  class MyController < UIViewController
188
219
 
189
- def viewDidLoad
190
- # we will modify the controller's `view`, assigning it the stylename `:root`
191
- layout(self.view, :root) do
220
+ def loadView
221
+ # we will create the controller's view, assigning it the stylename :root
222
+ self.view = layout(FancyView, :root) do
192
223
  # these subviews will be added to `self.view`
193
224
  subview(UIToolbar, :toolbar)
194
225
  subview(UIButton, :hi_button)
@@ -243,9 +274,11 @@ The reason it is so easy to define view hierarchies in Teacup is because the
243
274
  ```ruby
244
275
  subview(UIView, :container) do # create a UIView instance and give it the stylename :container
245
276
  subview(UIView, :inputs) do # create another container
277
+ # these views will be added to the :inputs view
246
278
  @email_input = subview(UITextField, :email_input)
247
279
  @password_input = subview(UITextField, :password_input)
248
280
  end
281
+ # this view will be added to :container
249
282
  subview(UIButton.buttonWithType(UIButtonTypeRoundedRect), :submit_button)
250
283
  end
251
284
  ```
@@ -255,7 +288,7 @@ to add your *own view helpers*! I refer to this as a "partials" system, but
255
288
  really it's just Ruby code (and isn't that the best system?).
256
289
 
257
290
  ```ruby
258
- # the methods you add here will be available in UIView/NSview,
291
+ # the methods you add here will be available in UIView/NSView,
259
292
  # UIViewController/NSViewController/NSWindowController, and any of your own
260
293
  # classes that `include Teacup::Layout`
261
294
  module Teacup::Layout
@@ -297,7 +330,7 @@ end
297
330
  ```ruby
298
331
  class MyController < UIViewController
299
332
 
300
- layout do
333
+ def teacup_layout
301
334
  @button1 = button()
302
335
  @button2 = button(:blue_button)
303
336
  @button3 = button_with_icon(UIImage.imageNamed('email_icon'), 'Email')
@@ -306,31 +339,14 @@ class MyController < UIViewController
306
339
  end
307
340
  ```
308
341
 
309
- The `Controller##layout` method that has been used so far is going to be
310
- the first or second thing you add to a controller when you are building an app
311
- with Teacup. It's method signature is
312
-
313
- ```ruby
314
- # defined in teacup/teacup_controller.rb as Teacup::Controller module
315
- UIViewController.layout(stylename=nil, styles={}, &block)
316
- NSViewController.layout(stylename=nil, styles={}, &block)
317
- NSWindowController.layout(stylename=nil, styles={}, &block)
318
- ```
319
-
320
- * `stylename` is the stylename you want applied to your controller's `self.view`
321
- object.
322
- * `styles` are *rarely* applied here, but one common use case is when you assign
323
- a custom view in `loadView`, and you want to apply settings to it. I find it
324
- cleaner to move this code into the body of the `layout` block, though.
325
- * `&block` is the most important - it is the layout code that will be called
326
- during `viewDidLoad`.
342
+ The `Controller#teacup_layout` method is going to be the first or second thing
343
+ you add to a controller when you are building an app with Teacup. Inside you
344
+ will add subviews using `subview` *or* you can create a view using the `layout`
345
+ method (`subview` delegates most of its work to `layout`)
327
346
 
328
347
  After the views have been added and styles have been applied Teacup calls the
329
348
  `layoutDidLoad` method. If you need to perform some additional initialization
330
- on your views, you should do it in this method. If you use the `layout` block
331
- the styles have not yet been applied. Frames will not be set, text and titles
332
- will be empty, and images will not have images. This all happens at the *end*
333
- of the `layout` block.
349
+ on your views, you can do it in this method.
334
350
 
335
351
  Stylesheets
336
352
  -----------
@@ -418,7 +434,7 @@ class MainController < UIViewController
418
434
 
419
435
  stylesheet :main # <= assigns the stylesheet named :main to this controller
420
436
 
421
- layout do
437
+ def teacup_layout
422
438
  subview(UILabel, :h1) # <= :h1 is the stylename
423
439
  end
424
440
 
@@ -442,7 +458,7 @@ We can tackle this a couple ways. You can apply "last-minute" styles in the
442
458
  `layout` and `subview` methods:
443
459
 
444
460
  ```ruby
445
- layout do
461
+ def teacup_layout
446
462
  subview(UILabel, :h1,
447
463
  # the `subview` and `layout` methods can apply styles
448
464
  text: "Omg, it's full of stars"
@@ -473,7 +489,7 @@ not all our labels say "OMG", but we want to use our font from the `:h1` style.
473
489
  We can tell the `:main_header` style that it `extends` the `:h1` style:
474
490
 
475
491
  ```ruby
476
- layout do
492
+ def teacup_layout
477
493
  subview(UILabel, :main_header)
478
494
  end
479
495
 
@@ -936,7 +952,7 @@ springs and struts. And honestly, I recommend you try using the
936
952
 
937
953
  But at the end of the day, once you really understand the auto-layout system
938
954
  that Apple released in iOS 6, you can build your UIs to be responsive to
939
- different devices, orientations, and sizes. UIs built with auto-layout do not
955
+ different devices, orientations, and sizes. UIs built with auto-layout not
940
956
  usually need to adjust anything during a rotation. The constraints take *care*
941
957
  of it all. It's impressive.
942
958
 
@@ -1007,7 +1023,7 @@ Teacup stylenames assigned to your views will be used in the dictionary that the
1007
1023
  ASCII-based system relies on.
1008
1024
 
1009
1025
  ```ruby
1010
- layout do
1026
+ def teacup_layout
1011
1027
  subview(UIView, :view_a)
1012
1028
  subview(UIView, :view_b)
1013
1029
  subview(UIView, :view_c)
@@ -1214,7 +1230,8 @@ class SomeController < UIViewController
1214
1230
 
1215
1231
  stylesheet :some_view
1216
1232
 
1217
- layout :root do
1233
+ def teacup_layout
1234
+ root(:root)
1218
1235
  subview(UITextField, :field)
1219
1236
  @search = subview(UITextField, :search)
1220
1237
  end
@@ -1298,7 +1315,7 @@ okay, because we have a chance to add these styles in the `subview` and `layout`
1298
1315
  methods.
1299
1316
 
1300
1317
  ```ruby
1301
- layout do
1318
+ def teacup_layout
1302
1319
  subview(UITableView, delegate: self)
1303
1320
  end
1304
1321
  ```
@@ -1309,7 +1326,7 @@ stylesheet is not necessarily applied immediately, these styles could be
1309
1326
  overwritten before they take effect.
1310
1327
 
1311
1328
  ```ruby
1312
- layout do
1329
+ def teacup_layout
1313
1330
  table_view = subview(UITableView, :tableview, delegate: self,
1314
1331
  font: UIFont.boldSystemFontOfSize(10) # the stylesheet could override this during rotation
1315
1332
  )
@@ -1328,7 +1345,7 @@ More examples!
1328
1345
  ```ruby
1329
1346
  class MyController < UIViewController
1330
1347
  stylesheet :my_sheet
1331
- layout do
1348
+ def teacup_layout
1332
1349
  subview(UILabel, :label, text: 'overrides')
1333
1350
  end
1334
1351
  end
@@ -1387,7 +1404,7 @@ appear on many screens in an app. You should not shy away from adding teacup's
1387
1404
 
1388
1405
  If you are using your controller as your table view dataSource, the `subview`
1389
1406
  and `layout` methods continue to work as you expect them to. This is for the
1390
- case when you are using a helper class.
1407
+ case when you are using a helper class as the dataSource and/or delegate.
1391
1408
 
1392
1409
  ```ruby
1393
1410
  class TableHelper
@@ -96,7 +96,11 @@ module Teacup
96
96
  # if we know the class of the target, we can apply styles via class
97
97
  # inheritance.
98
98
  if target_class
99
- target_class.class.ancestors.each do |ancestor|
99
+ unless target_class.is_a?(Class)
100
+ target_class = target_class.class
101
+ end
102
+
103
+ target_class.ancestors.each do |ancestor|
100
104
  extended_properties = stylesheet.query(ancestor, nil, rotation_orientation)
101
105
  Teacup::merge_defaults!(properties, extended_properties)
102
106
  end
@@ -10,7 +10,7 @@ module Teacup
10
10
  # orientation is completely ignored on OS X, but the Teacup code was written
11
11
  # to support them, and it was easier to ignore the orientation system than
12
12
  # refactor it out of the shared code base.
13
- def build(target=nil, rotation_orientation=nil, seen={})
13
+ def build(target_class=nil, rotation_orientation=nil, seen={})
14
14
  properties = Style.new
15
15
  properties.stylename = self.stylename
16
16
  properties.stylesheet = self.stylesheet
@@ -24,7 +24,7 @@ module Teacup
24
24
  # local style
25
25
  if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
26
26
  stylesheet.imported_stylesheets.reverse.each do |stylesheet|
27
- imported_properties = stylesheet.query(self.stylename, target, rotation_orientation, seen)
27
+ imported_properties = stylesheet.query(self.stylename, target_class, rotation_orientation, seen)
28
28
  delete_keys.each do |key|
29
29
  imported_properties.delete(key)
30
30
  end
@@ -37,7 +37,7 @@ module Teacup
37
37
  # turn style names into Hashes by querying them on the stylesheet
38
38
  # (this does not pass `seen`, because this is a new query)
39
39
  also_includes.each do |also_include|
40
- extended_properties = stylesheet.query(also_include, target, rotation_orientation)
40
+ extended_properties = stylesheet.query(also_include, target_class, rotation_orientation)
41
41
  delete_keys.each do |key|
42
42
  extended_properties.delete(key)
43
43
  end
@@ -46,10 +46,14 @@ module Teacup
46
46
  end
47
47
  properties.delete(:extends)
48
48
 
49
- # if we know the class of the target, we can apply styles via class
50
- # inheritance. We do not pass `target` in this case.
51
- if target
52
- target.class.ancestors.each do |ancestor|
49
+ # if we know the class of the target_class, we can apply styles via class
50
+ # inheritance. We do not pass `target_class` in this case.
51
+ if target_class
52
+ unless target_class.is_a?(Class)
53
+ target_class = target_class.class
54
+ end
55
+
56
+ target_class.ancestors.each do |ancestor|
53
57
  extended_properties = stylesheet.query(ancestor, nil, rotation_orientation)
54
58
  Teacup::merge_defaults!(properties, extended_properties)
55
59
  end
@@ -158,7 +158,7 @@ module Teacup
158
158
  begin
159
159
  # yield will not work if this is defined in the context of the
160
160
  # UIViewController `layout` class method.
161
- instance_exec(view, &block)
161
+ yield view
162
162
  rescue NoMethodError => e
163
163
  NSLog("Exception executing layout(#{view.inspect}) in #{self.inspect} (stylesheet=#{stylesheet})")
164
164
  raise e
@@ -127,12 +127,15 @@ module Teacup
127
127
  # @stylesheet_cache object is manipulated directly (to invalidate entries,
128
128
  # or the entire cache)
129
129
  def stylesheet_cache
130
- @stylesheet_cache ||= Hash.new do |by_stylename,_stylename|
131
- by_stylename[_stylename] = Hash.new do |by_target_class,_target_class|
132
- by_orientation = {}
133
- by_target_class[_target_class] = by_orientation
134
- end
135
- end
130
+ @stylesheet_cache ||= Hash.new(&lambda do |by_stylename,_stylename|
131
+ by_stylename[_stylename] = Hash.new(&lambda do |by_target_class,_target_class|
132
+ if _target_class && ! _target_class.is_a?(Class)
133
+ _target_class = _target_class.class
134
+ end
135
+
136
+ by_target_class[_target_class] = {}
137
+ end.weak!)
138
+ end.weak!)
136
139
  end
137
140
 
138
141
  def get_stylesheet_cache(stylename, target_class, orientation)
@@ -27,7 +27,8 @@ module Teacup
27
27
  #
28
28
  # @example
29
29
  # class MyViewController < UIViewController
30
- # layout :my_view do
30
+ # def teacup_layout
31
+ # root :my_view
31
32
  # subview UILabel, title: "Test"
32
33
  # subview UITextField, {
33
34
  # frame: [[200, 200], [100, 100]]
@@ -39,8 +40,25 @@ module Teacup
39
40
  # end
40
41
  # end
41
42
  #
42
- def layout(stylename=nil, properties={}, &block)
43
- @layout_definition = [stylename, properties, block]
43
+ def layout(stylename=nil, properties={})
44
+ if block_given?
45
+ msg = <<-MSG
46
+ Time to update your syntax!
47
+
48
+ It was discovered that passing a block to the Controller##layout was causing
49
+ irreparable memory leaks. The only recourse is to use a new syntax and remove
50
+ the old functionality.
51
+
52
+ If you need to assign a stylename to the root view, you can still do this using
53
+ `layout :stylename`, but you cannot pass a block to this class method any
54
+ longer.
55
+
56
+ Instead, define a method called `teacup_layout` and create your views there. No
57
+ other changes are required.
58
+ MSG
59
+ raise msg
60
+ end
61
+ @layout_definition = [stylename, properties]
44
62
  end
45
63
 
46
64
  end
@@ -61,8 +79,8 @@ module Teacup
61
79
  #
62
80
  # @example
63
81
  #
64
- # stylesheet = Teacup::Stylesheet[:ipadhorizontal]
65
- # stylesheet = :ipadhorizontal
82
+ # stylesheet = Teacup::Stylesheet[:main]
83
+ # stylesheet = :main
66
84
  def stylesheet=(new_stylesheet)
67
85
  super
68
86
  if self.viewLoaded?
@@ -70,6 +88,19 @@ module Teacup
70
88
  end
71
89
  end
72
90
 
91
+ def root(stylename=nil, properties={})
92
+ if stylename.is_a?(NSDictionary)
93
+ properties = stylename
94
+ stylename = nil
95
+ end
96
+
97
+ if stylename || properties
98
+ layout(top_level_view, stylename, properties)
99
+ else
100
+ top_level_view
101
+ end
102
+ end
103
+
73
104
  # Instantiate the layout from the class, and then call layoutDidLoad.
74
105
  #
75
106
  # If you want to use Teacup in your controller, please hook into layoutDidLoad,
@@ -97,8 +128,12 @@ module Teacup
97
128
  end
98
129
 
99
130
  if layout_definition
100
- stylename, properties, block = layout_definition
101
- layout(top_level_view, stylename, properties, &block)
131
+ stylename, properties = layout_definition
132
+ layout(top_level_view, stylename, properties)
133
+ end
134
+
135
+ if respond_to?(:teacup_layout)
136
+ teacup_layout
102
137
  end
103
138
 
104
139
  layoutDidLoad
@@ -1,5 +1,5 @@
1
1
  module Teacup
2
2
 
3
- VERSION = '2.3.0'
3
+ VERSION = '3.0.0'
4
4
 
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: teacup
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 3.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - the rubymotion community
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-05 00:00:00.000000000 Z
11
+ date: 2014-07-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: |
14
14
  Teacup is a community-driven DSL for RubyMotion. It has CSS-like styling, and
@@ -67,6 +67,7 @@ files:
67
67
  - spec/ios/gradient_spec.rb
68
68
  - spec/ios/layout_module_spec.rb
69
69
  - spec/ios/layout_spec.rb
70
+ - spec/ios/limelight_spec.rb
70
71
  - spec/ios/main_spec.rb
71
72
  - spec/ios/memory_leak_spec.rb
72
73
  - spec/ios/motion_layout_spec.rb
@@ -79,7 +80,6 @@ files:
79
80
  - spec/ios/ui_view_getters_spec.rb
80
81
  - spec/ios/uiswitch_spec.rb
81
82
  - spec/ios/view_spec.rb
82
- - spec/limelight_spec.rb
83
83
  homepage: https://github.com/rubymotion/teacup
84
84
  licenses:
85
85
  - BSD
@@ -114,6 +114,7 @@ test_files:
114
114
  - spec/ios/gradient_spec.rb
115
115
  - spec/ios/layout_module_spec.rb
116
116
  - spec/ios/layout_spec.rb
117
+ - spec/ios/limelight_spec.rb
117
118
  - spec/ios/main_spec.rb
118
119
  - spec/ios/memory_leak_spec.rb
119
120
  - spec/ios/motion_layout_spec.rb
@@ -126,4 +127,3 @@ test_files:
126
127
  - spec/ios/ui_view_getters_spec.rb
127
128
  - spec/ios/uiswitch_spec.rb
128
129
  - spec/ios/view_spec.rb
129
- - spec/limelight_spec.rb