teacup 1.3.4 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. data/Gemfile +1 -1
  2. data/Gemfile.lock +3 -3
  3. data/README.md +1172 -319
  4. data/Rakefile +8 -1
  5. data/app/app_delegate.rb +1 -1
  6. data/app/controllers/appearance_controller.rb +13 -0
  7. data/app/controllers/landscape_only_controller.rb +1 -1
  8. data/app/controllers/{first_controller.rb → main_controller.rb} +4 -3
  9. data/app/controllers/motion_layout_controller.rb +22 -0
  10. data/app/styles/appearance.rb +24 -0
  11. data/app/styles/main_styles.rb +8 -6
  12. data/app/views/custom_view.rb +1 -0
  13. data/lib/teacup/calculations.rb +2 -2
  14. data/lib/teacup/{z_core_extensions → core_extensions}/ca_layer.rb +0 -0
  15. data/lib/teacup/core_extensions/view_getters.rb +61 -0
  16. data/lib/teacup/handler.rb +14 -14
  17. data/lib/teacup/layout.rb +94 -17
  18. data/lib/teacup/stylesheet.rb +61 -26
  19. data/lib/teacup/stylesheet_extensions/transform.rb +88 -0
  20. data/lib/teacup/teacup_controller.rb +122 -0
  21. data/lib/teacup/teacup_util.rb +12 -7
  22. data/lib/teacup/teacup_view.rb +329 -0
  23. data/lib/teacup/version.rb +1 -1
  24. data/lib/teacup-ios/appearance.rb +96 -0
  25. data/lib/teacup-ios/core_extensions/teacup_handlers.rb +183 -0
  26. data/lib/teacup-ios/core_extensions/ui_view.rb +30 -0
  27. data/lib/teacup-ios/core_extensions/ui_view_controller.rb +110 -0
  28. data/lib/{dummy.rb → teacup-ios/dummy.rb} +2 -6
  29. data/lib/teacup-ios/handler.rb +23 -0
  30. data/lib/{teacup → teacup-ios}/style.rb +9 -10
  31. data/lib/teacup-ios/stylesheet_extensions/autoresize.rb +169 -0
  32. data/lib/{teacup/stylesheet_extensions/geometry.rb → teacup-ios/stylesheet_extensions/device.rb} +0 -0
  33. data/lib/teacup-osx/core_extensions/ns_view.rb +39 -0
  34. data/lib/teacup-osx/core_extensions/ns_view_controller.rb +21 -0
  35. data/lib/teacup-osx/core_extensions/ns_window.rb +39 -0
  36. data/lib/teacup-osx/core_extensions/ns_window_controller.rb +29 -0
  37. data/lib/{teacup/z_core_extensions/z_handlers.rb → teacup-osx/core_extensions/teacup_handlers.rb} +30 -47
  38. data/lib/teacup-osx/dummy.rb +80 -0
  39. data/lib/teacup-osx/handler.rb +16 -0
  40. data/lib/teacup-osx/style.rb +83 -0
  41. data/lib/teacup-osx/style_extensions/autoresize.rb +169 -0
  42. data/lib/teacup.rb +12 -11
  43. data/samples/Tweets/Gemfile +4 -0
  44. data/samples/Tweets/Gemfile.lock +16 -0
  45. data/samples/Tweets/README +7 -0
  46. data/samples/Tweets/Rakefile +9 -0
  47. data/samples/Tweets/app/app_delegate.rb +18 -0
  48. data/samples/Tweets/app/data_parser.rb +10 -0
  49. data/samples/Tweets/app/json_parser.rb +12 -0
  50. data/samples/Tweets/app/main_window.rb +99 -0
  51. data/samples/Tweets/app/menu.rb +108 -0
  52. data/samples/Tweets/app/stylesheet.rb +21 -0
  53. data/samples/Tweets/app/tweet.rb +11 -0
  54. data/samples/Tweets/resources/Credits.rtf +29 -0
  55. data/samples/Tweets/spec/main_spec.rb +9 -0
  56. data/samples/teacup-osx/.gitignore +1 -0
  57. data/samples/teacup-osx/Gemfile +4 -0
  58. data/samples/teacup-osx/Gemfile.lock +16 -0
  59. data/samples/teacup-osx/Rakefile +9 -0
  60. data/samples/teacup-osx/app/app_delegate.rb +23 -0
  61. data/samples/teacup-osx/app/controller.rb +11 -0
  62. data/samples/teacup-osx/app/menu.rb +108 -0
  63. data/samples/teacup-osx/app/window.rb +12 -0
  64. data/samples/teacup-osx/resources/Credits.rtf +29 -0
  65. data/samples/teacup-osx/resources/teacup.png +0 -0
  66. data/samples/teacup-osx/spec/main_spec.rb +9 -0
  67. data/spec/ios/appearance_spec.rb +18 -0
  68. data/spec/{calculations_spec.rb → ios/calculations_spec.rb} +0 -0
  69. data/spec/{constraints_spec.rb → ios/constraints_spec.rb} +0 -0
  70. data/spec/{custom_class_spec.rb → ios/custom_class_spec.rb} +0 -0
  71. data/spec/{gradient_spec.rb → ios/gradient_spec.rb} +1 -1
  72. data/spec/ios/layout_module_spec.rb +54 -0
  73. data/spec/ios/layout_spec.rb +50 -0
  74. data/spec/{main_spec.rb → ios/main_spec.rb} +52 -13
  75. data/spec/ios/motion_layout_spec.rb +44 -0
  76. data/spec/{present_modal_spec.rb → ios/present_modal_spec.rb} +0 -0
  77. data/spec/{style_spec.rb → ios/style_spec.rb} +1 -1
  78. data/spec/ios/stylesheet_extensions/autoresize_spec.rb +50 -0
  79. data/spec/{stylesheet_spec.rb → ios/stylesheet_spec.rb} +12 -0
  80. data/spec/{ui_view_getters_spec.rb → ios/ui_view_getters_spec.rb} +0 -0
  81. data/spec/{uiswitch_spec.rb → ios/uiswitch_spec.rb} +0 -0
  82. data/spec/{view_spec.rb → ios/view_spec.rb} +23 -2
  83. metadata +85 -35
  84. data/lib/teacup/stylesheet_extensions/autoresize.rb +0 -39
  85. data/lib/teacup/stylesheet_extensions/rotation.rb +0 -37
  86. data/lib/teacup/z_core_extensions/ui_view.rb +0 -262
  87. data/lib/teacup/z_core_extensions/ui_view_controller.rb +0 -263
  88. data/lib/teacup/z_core_extensions/ui_view_getters.rb +0 -58
@@ -1,262 +0,0 @@
1
- # Teacup's UIView extensions defines some utility functions for UIView that
2
- # enable a lot of the magic for Teacup::Layout.
3
-
4
- # Users of teacup should be able to ignore the contents of this file for
5
- # the most part.
6
- class UIView
7
- include Teacup::Layout
8
-
9
- # The current stylename that is used to look up properties in the stylesheet.
10
- attr_reader :stylename
11
-
12
- # Any class that includes Teacup::Layout gets a `layout` method, which assigns
13
- # itself as the 'teacup_next_responder'.
14
- attr_accessor :teacup_next_responder
15
-
16
- # Enable debug messages for this object
17
- attr_accessor :debug
18
-
19
- # Alter the stylename of this view.
20
- #
21
- # This will cause new styles to be applied from the stylesheet.
22
- #
23
- # @param Symbol stylename
24
- def stylename=(new_stylename)
25
- @stylename = new_stylename
26
- restyle!
27
- end
28
-
29
- # Alter the stylesheet of this view.
30
- #
31
- # This will cause new styles to be applied using the current stylename,
32
- # and will recurse into subviews.
33
- #
34
- # If you would prefer that a given UIView object does not inherit the
35
- # stylesheet from its parents, override the 'stylesheet' method to
36
- # return the correct value at all times.
37
- #
38
- # @param Teacup::Stylesheet stylesheet.
39
- def stylesheet=(new_stylesheet)
40
- should_restyle = Teacup.should_restyle_and_block
41
-
42
- @stylesheet = new_stylesheet
43
-
44
- if should_restyle
45
- Teacup.should_restyle!
46
- restyle!
47
- end
48
- end
49
-
50
- def stylesheet
51
- if @stylesheet.is_a? Symbol
52
- @stylesheet = Teacup::Stylesheet[@stylesheet]
53
- end
54
- # is a stylesheet assigned explicitly?
55
- retval = @stylesheet
56
- return retval if retval
57
-
58
- # the 'teacup_next_responder' is assigned in the `layout` method, and links
59
- # any views created there to the custom class (could be a controller, could
60
- # be any class that includes Teacup::Layout). That responder is checked
61
- # next, but only if it wouldn't result in a circular loop.
62
- if ! retval && @teacup_next_responder && teacup_next_responder != self
63
- retval = @teacup_next_responder.stylesheet
64
- end
65
-
66
- # lastly, go up the chain; either a controller or superview
67
- if ! retval && nextResponder && nextResponder.respond_to?(:stylesheet)
68
- retval = nextResponder.stylesheet
69
- end
70
-
71
- return retval
72
- end
73
-
74
- def restyle!(orientation=nil)
75
- if Teacup.should_restyle?
76
- if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
77
- style(stylesheet.query(stylename, self, orientation))
78
- end
79
- subviews.each{ |subview| subview.restyle!(orientation) }
80
- end
81
- end
82
-
83
- def get_ns_constraints
84
- # gets the array of Teacup::Constraint objects
85
- my_constraints = (@teacup_constraints || []).map { |constraint, relative_to|
86
- if constraint.is_a?(Teacup::Constraint)
87
- constraint
88
- else
89
- if relative_to == true
90
- Teacup::Constraint.from_sym(constraint)
91
- else
92
- Teacup::Constraint.from_sym(constraint, relative_to)
93
- end
94
- end
95
- }.flatten.tap{ |my_constraints|
96
- unless my_constraints.empty?
97
- self.setTranslatesAutoresizingMaskIntoConstraints(false)
98
- end
99
- }.map do |original_constraint|
100
- constraint = original_constraint.copy
101
-
102
- case original_constraint.target
103
- when UIView
104
- constraint.target = original_constraint.target
105
- when :self
106
- constraint.target = self
107
- when :superview
108
- constraint.target = self.superview
109
- when Symbol, String
110
- container = self
111
- constraint.target = nil
112
- while container && constraint.target.nil?
113
- constraint.target = container.viewWithStylename(original_constraint.target)
114
- container = container.superview
115
- end
116
- end
117
-
118
- case original_constraint.relative_to
119
- when nil
120
- constraint.relative_to = nil
121
- when UIView
122
- constraint.relative_to = original_constraint.relative_to
123
- when :self
124
- constraint.relative_to = self
125
- when :superview
126
- constraint.relative_to = self.superview
127
- when Symbol, String
128
- # TODO: this re-checks lots of views - everytime it goes up to the
129
- # superview, it checks all the leaves again.
130
- container = self
131
- constraint.relative_to = nil
132
- while container && constraint.relative_to.nil?
133
- constraint.relative_to = container.viewWithStylename(original_constraint.relative_to)
134
- container = container.superview
135
- end
136
- end
137
-
138
- if original_constraint.relative_to && ! constraint.relative_to
139
- puts "Could not find #{original_constraint.relative_to.inspect}"
140
- container = self
141
- tab = ' '
142
- while container && constraint.relative_to.nil?
143
- tab << '->'
144
- puts "#{tab} #{container.stylename.inspect}"
145
- container = container.superview
146
- end
147
- end
148
-
149
- # the return value, for the map
150
- constraint.nslayoutconstraint
151
- end
152
-
153
- # now add all che child constraints
154
- subviews.each do |subview|
155
- my_constraints.concat(subview.get_ns_constraints)
156
- end
157
-
158
- my_constraints
159
- end
160
-
161
- def apply_constraints
162
- if @teacup_added_constraints
163
- @teacup_added_constraints.each do |constraint|
164
- self.removeConstraint(constraint)
165
- end
166
- end
167
- @teacup_added_constraints = nil
168
- all_constraints = get_ns_constraints
169
-
170
- return if all_constraints.empty?
171
-
172
- @teacup_added_constraints = []
173
- all_constraints.each do |ns_constraint|
174
- @teacup_added_constraints << ns_constraint
175
- self.addConstraint(ns_constraint)
176
- end
177
- end
178
-
179
- # Animate a change to a new stylename.
180
- #
181
- # This is equivalent to wrapping a call to .stylename= inside
182
- # UIView.beginAnimations.
183
- #
184
- # @param Symbol the new stylename
185
- # @param Options the options for the animation (may include the
186
- # duration and the curve)
187
- #
188
- def animate_to_stylename(stylename, options={})
189
- return if self.stylename == stylename
190
-
191
- UIView.beginAnimations(nil, context: nil)
192
- # TODO: This should be in a style-sheet!
193
- UIView.setAnimationDuration(options[:duration]) if options[:duration]
194
- UIView.setAnimationCurve(options[:curve]) if options[:curve]
195
- UIView.setAnimationDelay(options[:delay]) if options[:delay]
196
- self.stylename = stylename
197
- UIView.commitAnimations
198
- end
199
-
200
- # Animate a change to new styles
201
- #
202
- # This is equivalent to wrapping a call to .style() inside
203
- # UIView.beginAnimations.
204
- #
205
- # @param Hash the new styles and options for the animation
206
- #
207
- def animate_to_style(style)
208
- UIView.beginAnimations(nil, context: nil)
209
- UIView.setAnimationDuration(style[:duration]) if style[:duration]
210
- UIView.setAnimationCurve(style[:curve]) if style[:curve]
211
- UIView.setAnimationDelay(style[:delay]) if style[:delay]
212
- style(style)
213
- UIView.commitAnimations
214
- end
215
-
216
- # Apply style properties to this element.
217
- #
218
- # Takes a hash of properties such as may have been read from a stylesheet
219
- # or passed as parameters to {Teacup::Layout#layout}, and applies them to
220
- # the element.
221
- #
222
- # Does a little bit of magic (that may be split out as 'sugarcube') to
223
- # make properties work as you'd expect.
224
- #
225
- # If you try and assign something in properties that is not supported,
226
- # a warning message will be emitted.
227
- #
228
- # @param Hash the properties to set.
229
- def style(properties)
230
- if properties.key?(:constraints)
231
- add_uniq_constraints(properties.delete(:constraints))
232
- end
233
-
234
- Teacup.apply_hash self, properties
235
-
236
- self.setNeedsDisplay
237
- self.setNeedsLayout
238
- end
239
-
240
- def top_level_view
241
- return self
242
- end
243
-
244
- def add_uniq_constraints(constraint)
245
- @teacup_constraints ||= {}
246
-
247
- if constraint.is_a? Array
248
- constraint.each { |constraint|
249
- add_uniq_constraints(constraint)
250
- }
251
- elsif constraint.is_a? Hash
252
- constraint.each { |sym, relative_to|
253
- @teacup_constraints[sym] = relative_to
254
- }
255
- elsif constraint.is_a?(Teacup::Constraint) || constraint.is_a?(Symbol)
256
- @teacup_constraints[constraint] = true
257
- else
258
- raise "Unsupported constraint: #{constraint.inspect}"
259
- end
260
- end
261
-
262
- end
@@ -1,263 +0,0 @@
1
- # Adds methods to the UIViewController class to make defining a layout and
2
- # stylesheet very easy. Also provides rotation methods that analyze
3
- class UIViewController
4
- include Teacup::Layout
5
-
6
- class << self
7
- attr_reader :layout_definition
8
-
9
- # Define the layout of a controller's view.
10
- #
11
- # This function is analogous to Teacup::Layout#layout, though it is
12
- # designed so you can create an entire layout in a declarative manner in
13
- # your controller.
14
- #
15
- # The hope is that this declarativeness will allow us to automatically
16
- # deal with common iOS programming tasks (like releasing views when
17
- # low-memory conditions occur) for you. This is still not implemented
18
- # though.
19
- #
20
- # @param name The stylename for your controller's view.
21
- #
22
- # @param properties Any extra styles that you want to apply.
23
- #
24
- # @param &block The block in which you should define your layout.
25
- # It will be instance_exec'd in the context of a
26
- # controller instance.
27
- #
28
- # @example
29
- # MyViewController < UIViewController
30
- # layout :my_view do
31
- # subview UILabel, title: "Test"
32
- # subview UITextField, {
33
- # frame: [[200, 200], [100, 100]]
34
- # delegate: self
35
- # }
36
- # subview UIView, :shiny_thing) {
37
- # subview UIView, :centre_of_shiny_thing
38
- # }
39
- # end
40
- # end
41
- #
42
- def layout(stylename=nil, properties={}, &block)
43
- @layout_definition = [stylename, properties, block]
44
- end
45
-
46
- def stylesheet(new_stylesheet=nil)
47
- if new_stylesheet.nil?
48
- return @stylesheet
49
- end
50
-
51
- @stylesheet = new_stylesheet
52
- end
53
-
54
- end # class << self
55
-
56
- # Assigning a new stylesheet triggers {restyle!}.
57
- #
58
- # Assigning a stylesheet is an *alternative* to returning a Stylesheet in
59
- # the {stylesheet} method. Note that {restyle!} calls {stylesheet}, so while
60
- # assigning a stylesheet will trigger {restyle!}, your stylesheet will not
61
- # be picked up if you don't return it in a custom stylesheet method.
62
- #
63
- # @return Teacup::Stylesheet
64
- #
65
- # @example
66
- #
67
- # stylesheet = Teacup::Stylesheet[:ipadhorizontal]
68
- # stylesheet = :ipadhorizontal
69
- def stylesheet=(new_stylesheet)
70
- super
71
- if self.viewLoaded?
72
- self.view.restyle!
73
- end
74
- end
75
-
76
- def top_level_view
77
- return self.view
78
- end
79
-
80
-
81
- # Instantiate the layout from the class, and then call layoutDidLoad.
82
- #
83
- # If you want to use Teacup in your controller, please hook into layoutDidLoad,
84
- # not viewDidLoad.
85
- def viewDidLoad
86
- # look for a layout_definition in the list of ancestors
87
- layout_definition = nil
88
- my_stylesheet = self.stylesheet
89
- parent_class = self.class
90
- while parent_class != NSObject and not (layout_definition && my_stylesheet)
91
- if not my_stylesheet and parent_class.respond_to?(:stylesheet)
92
- my_stylesheet = parent_class.stylesheet
93
- end
94
-
95
- if not layout_definition and parent_class.respond_to?(:layout_definition)
96
- layout_definition = parent_class.layout_definition
97
- end
98
- parent_class = parent_class.superclass
99
- end
100
-
101
- should_restyle = Teacup.should_restyle_and_block
102
-
103
- if my_stylesheet and not self.stylesheet
104
- self.stylesheet = my_stylesheet
105
- end
106
-
107
- if layout_definition
108
- stylename, properties, block = layout_definition
109
- layout(view, stylename, properties, &block)
110
- end
111
-
112
- if should_restyle
113
- Teacup.should_restyle!
114
- self.view.restyle!
115
- end
116
-
117
- if defined? NSLayoutConstraint
118
- self.view.apply_constraints
119
- end
120
-
121
- layoutDidLoad
122
- end
123
-
124
- def layoutDidLoad
125
- true
126
- end
127
-
128
- # This method *used* to be useful for the `shouldAutorotateToOrientation`
129
- # method, but the iOS 6 update deprecates that method. Instead, use the
130
- # `supportedInterfaceOrientations` and return `autorotateMask`.
131
- def autorotateToOrientation(orientation)
132
- if view.stylesheet and view.stylesheet.is_a?(Teacup::Stylesheet) and view.stylename
133
- properties = view.stylesheet.query(view.stylename, self, orientation)
134
-
135
- # check for orientation-specific properties
136
- case orientation
137
- when UIInterfaceOrientationPortrait
138
- # portrait is "on" by default, must be turned off explicitly
139
- if properties.supports?(:portrait) == nil and properties.supports?(:upside_up) == nil
140
- return true
141
- end
142
-
143
- return (properties.supports?(:portrait) or properties.supports?(:upside_up))
144
- when UIInterfaceOrientationPortraitUpsideDown
145
- if UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPhone
146
- # iphone must have an explicit upside-down style, otherwise this returns
147
- # false
148
- return properties.supports?(:upside_down)
149
- else
150
- # ipad can just have a portrait style
151
- return (properties.supports?(:portrait) or properties.supports?(:upside_down))
152
- end
153
- when UIInterfaceOrientationLandscapeLeft
154
- return (properties.supports?(:landscape) or properties.supports?(:landscape_left))
155
- when UIInterfaceOrientationLandscapeRight
156
- return (properties.supports?(:landscape) or properties.supports?(:landscape_right))
157
- end
158
-
159
- return false
160
- end
161
-
162
- # returns the system default
163
- if device == UIUserInterfaceIdiomPhone
164
- return orientation != UIInterfaceOrientationPortraitUpsideDown
165
- else
166
- return true
167
- end
168
- end
169
-
170
- # You can use this method in `supportedInterfaceOrientations`, and it will
171
- # query the stylesheet for the supported orientations, based on what
172
- # orientations are defined. At a minimum, to opt-in to this feature, you'll
173
- # need to define styles like `style :root, landscape: true`
174
- def autorotateMask
175
- device = UIDevice.currentDevice.userInterfaceIdiom
176
- if view.stylesheet and view.stylesheet.is_a?(Teacup::Stylesheet) and view.stylename
177
- properties = view.stylesheet.query(view.stylename, self, orientation)
178
-
179
- orientations = 0
180
- if properties.supports?(:portrait) or properties.supports?(:upside_up)
181
- orientations |= UIInterfaceOrientationPortrait
182
- end
183
-
184
- if device == UIUserInterfaceIdiomPhone
185
- # :portrait does not imply upside_down on the iphone
186
- if properties.supports?(:upside_down)
187
- orientations |= UIInterfaceOrientationPortraitUpsideDown
188
- end
189
- else
190
- # but does on the ipad
191
- if properties.supports?(:portrait) or properties.supports?(:upside_down)
192
- orientations |= UIInterfaceOrientationPortraitUpsideDown
193
- end
194
- end
195
-
196
- if properties.supports?(:landscape) or properties.supports?(:landscape_left)
197
- orientations |= UIInterfaceOrientationLandscapeLeft
198
- end
199
-
200
- if properties.supports?(:landscape) or properties.supports?(:landscape_right)
201
- orientations |= UIInterfaceOrientationLandscapeRight
202
- end
203
-
204
- if orientations == 0
205
- orientations |= UIInterfaceOrientationPortrait
206
- end
207
- return orientations
208
- end
209
-
210
- # returns the system default
211
- if device == UIUserInterfaceIdiomPhone
212
- return UIInterfaceOrientationMaskAllButUpsideDown
213
- else
214
- return UIInterfaceOrientationMaskAll
215
- end
216
- end
217
-
218
- # restyles the view! be careful about putting styles in your stylesheet that
219
- # you change in your controller. anything that might change over time should
220
- # be applied in your controller using `style`
221
- def willAnimateRotationToInterfaceOrientation(orientation, duration:duration)
222
- view.restyle!(orientation)
223
- end
224
-
225
- ##|
226
- ##| Motion-Layout support
227
- ##|
228
-
229
- # Calling this method uses Nick Quaranto's motion-layout gem to provide ASCII
230
- # art style access to autolayout. It assigns all the subviews by stylename,
231
- # and assigns `self.view` as the target view. Beyond that, it's up to you to
232
- # implement the layout methods:
233
- #
234
- # auto do
235
- # metrics 'margin' => 20
236
- # vertical "|-[top]-margin-[bottom]-|"
237
- # horizontal "|-margin-[top]-margin-|"
238
- # horizontal "|-margin-[bottom]-margin-|"
239
- # end
240
- def auto(layout_view=self.view, layout_subviews={}, &layout_block)
241
- raise "gem install 'motion-layout'" unless defined? Motion::Layout
242
-
243
- Teacup.get_subviews(self.view).each do |view|
244
- if view.stylename && ! layout_subviews[view.stylename.to_s]
245
- layout_subviews[view.stylename.to_s] = view
246
- end
247
- end
248
-
249
- Motion::Layout.new do |layout|
250
- layout.view layout_view
251
- layout.subviews layout_subviews
252
- layout.instance_eval(&layout_block)
253
- end
254
- end
255
-
256
- end
257
-
258
-
259
- def Teacup.get_subviews(target)
260
- [target] + target.subviews.map { |subview|
261
- get_subviews(subview).select{ |v| v.stylename }
262
- }.flatten
263
- end
@@ -1,58 +0,0 @@
1
- # Methods to retrieve a subview using the stylename as a key
2
- # Kinda similar to jQuery-style $(el).find('stylename')
3
- class UIView
4
-
5
- # get one subview by stylename or class. If the receiver matches, it will be
6
- # returned
7
- # my_view.viewWithStylename :button => #<UIButton..>
8
- # my_view.viewWithStylename UIButton => #<UIButton..>
9
- def viewWithStylename name_or_class
10
- return self if self._teacup_check_stylename(name_or_class)
11
-
12
- view = subviews.find { |view| view._teacup_check_stylename(name_or_class) }
13
- return view if view
14
-
15
- # found_subview will get assigned to the view we want, but the subview is
16
- # what is returned.
17
- found_subview = nil
18
- view = subviews.find { |subview| found_subview = subview.viewWithStylename(name_or_class) }
19
- return found_subview if view
20
-
21
- return nil # couldn't find it
22
- end
23
-
24
- # get all subviews by stylename or class
25
- # my_view.viewsWithStylename :button => [#<UIButton..>, #<UIButton...>]
26
- # my_view.viewsWithStylename UIButton => [#<UIButton..>, #<UIButton...>]
27
- def viewsWithStylename name_or_class
28
- retval = []
29
- retval << self if self._teacup_check_stylename(name_or_class)
30
-
31
- search_views = [].concat(self.subviews)
32
- # ewww, a traditional for loop! the search_views array is modified in place,
33
- # and `each` and other methods don't like that.
34
- index = 0
35
- while index < search_views.length
36
- view = search_views[index]
37
- if view._teacup_check_stylename(name_or_class)
38
- retval << view
39
- end
40
- search_views.concat(view.subviews)
41
- index += 1
42
- end
43
-
44
- return retval
45
- end
46
-
47
- def _teacup_check_stylename(name_or_class)
48
- if name_or_class.is_a? Class
49
- return self.is_a?(name_or_class)
50
- elsif stylename == name_or_class
51
- return true
52
- elsif stylesheet.is_a?(Teacup::Stylesheet)
53
- return stylesheet.extends_style?(self.stylename, name_or_class)
54
- end
55
- return false
56
- end
57
-
58
- end