teacup 0.0.1.pre → 0.3.1

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.
Files changed (67) hide show
  1. data/.gitignore +5 -3
  2. data/CHANGES.md +26 -0
  3. data/Gemfile +2 -0
  4. data/Gemfile.lock +1 -1
  5. data/LICENSE +26 -0
  6. data/README.md +383 -95
  7. data/Rakefile +8 -36
  8. data/app/app_delegate.rb +14 -0
  9. data/app/controllers/first_controller.rb +71 -0
  10. data/app/controllers/landscape_only_controller.rb +16 -0
  11. data/app/controllers/tableview_controller.rb +0 -0
  12. data/app/styles/main_styles.rb +111 -0
  13. data/app/views/custom_view.rb +4 -0
  14. data/lib/dummy.rb +56 -0
  15. data/lib/teacup/handler.rb +99 -0
  16. data/lib/teacup/layout.rb +22 -74
  17. data/lib/teacup/merge_defaults.rb +45 -0
  18. data/lib/teacup/style.rb +93 -0
  19. data/lib/teacup/stylesheet.rb +242 -0
  20. data/lib/teacup/stylesheet_extensions/rotation.rb +38 -0
  21. data/lib/teacup/version.rb +1 -1
  22. data/lib/teacup/z_core_extensions/ca_layer.rb +6 -0
  23. data/lib/teacup/z_core_extensions/ui_view.rb +119 -0
  24. data/lib/teacup/z_core_extensions/ui_view_controller.rb +179 -0
  25. data/lib/teacup/z_core_extensions/ui_view_getters.rb +34 -0
  26. data/lib/teacup/z_core_extensions/z_handlers.rb +57 -0
  27. data/lib/teacup.rb +16 -33
  28. data/samples/Hai/Rakefile +7 -2
  29. data/samples/Hai/app/app_delegate.rb +2 -2
  30. data/samples/Hai/app/hai_controller.rb +8 -4
  31. data/samples/Hai/styles/iphone.rb +40 -0
  32. data/spec/main_spec.rb +226 -0
  33. data/spec/style_spec.rb +171 -0
  34. data/spec/stylesheet_spec.rb +348 -0
  35. data/spec/view_spec.rb +103 -0
  36. data/teacup.gemspec +13 -13
  37. metadata +47 -46
  38. data/.rspec +0 -2
  39. data/lib/teacup/contributors.rb +0 -7
  40. data/lib/teacup/core_extensions/ui_view.rb +0 -4
  41. data/lib/teacup/core_extensions/ui_view_controller.rb +0 -62
  42. data/lib/teacup/style_sheet.rb +0 -195
  43. data/lib/teacup/view.rb +0 -123
  44. data/pkg/teacup-0.0.0.gem +0 -0
  45. data/pkg/teacup-0.0.1.gem +0 -0
  46. data/proposals/other/README.md +0 -45
  47. data/proposals/other/app/config/application.rb +0 -1
  48. data/proposals/other/app/config/boot.rb +0 -1
  49. data/proposals/other/app/config/initializers/twitter.rb +0 -7
  50. data/proposals/other/app/controllers/events_controller.rb +0 -28
  51. data/proposals/other/app/controllers/venues_controller.rb +0 -4
  52. data/proposals/other/app/db/README.md +0 -16
  53. data/proposals/other/app/db/migrations/20120514201043_create_events.rb +0 -9
  54. data/proposals/other/app/db/migrations/20120514201044_add_price_to_events.rb +0 -5
  55. data/proposals/other/app/db/migrations/20120514201045_create_venues.rb +0 -8
  56. data/proposals/other/app/db/schema.rb +0 -19
  57. data/proposals/other/app/models/event.rb +0 -14
  58. data/proposals/other/app/models/venue.rb +0 -3
  59. data/proposals/other/app/views/events/edit.ipad.rb +0 -8
  60. data/proposals/other/app/views/events/edit.iphone.rb +0 -7
  61. data/proposals/other/app/views/events/show.ipad.rb +0 -2
  62. data/proposals/other/app/views/events/show.iphone.rb +0 -3
  63. data/samples/Hai/styles/ipad.rb +0 -11
  64. data/samples/Hai/styles/ipad_vertical.rb +0 -3
  65. data/spec/spec_helper.rb +0 -5
  66. data/spec/teacup/contributions_spec.rb +0 -13
  67. data/spec/teacup/version_spec.rb +0 -9
@@ -0,0 +1,242 @@
1
+ module Teacup
2
+ # Stylesheets in Teacup act as a central configuration mechanism,
3
+ # they have two aims:
4
+ #
5
+ # 1. Allow you to store "Details" away from the main body of your code.
6
+ # (controllers shouldn't have to be filled with style rules)
7
+ # 2. Allow you to easily re-use configuration in many places.
8
+ #
9
+ # The API really provides only two methods, {Stylesheet#style} to store properties
10
+ # on the Stylesheet; and {Stylesheet#query} to get them out again:
11
+ #
12
+ # @example
13
+ # stylesheet = Teacup::Stylesheet.new
14
+ # stylesheet.style :buttons, :corners => :rounded
15
+ # # => nil
16
+ # stylesheet.query :buttons
17
+ # # => {:corners => :rounded}
18
+ #
19
+ # In addition to this, two separate mechanisms are provided for sharing
20
+ # configuration within stylesheets.
21
+ #
22
+ # Firstly, if you set the ':extends' property for a given stylename, then on lookup
23
+ # the Stylesheet will merge the properties for the ':extends' stylename into the return
24
+ # value. Conflicts are resolved so that properties with the original stylename
25
+ # are resolved in its favour.
26
+ #
27
+ # @example
28
+ # Teacup::Stylesheet.new(:ipad) do
29
+ # style :button,
30
+ # backgroundImage: UIImage.imageNamed("big_red_shiny_button"),
31
+ # top: 100
32
+ #
33
+ # style :ok_button, extends: :button,
34
+ # title: "OK!",
35
+ # top: 200
36
+ #
37
+ # end
38
+ # Teacup::Stylesheet[:ipad].query(:ok_button)
39
+ # # => {backgroundImage: UIImage.imageNamed("big_red_shiny_button"), top: 200, title: "OK!"}
40
+ #
41
+ # Secondly, you can import Stylesheets into each other, in exactly the same way as you
42
+ # can include Modules into each other in Ruby. This allows you to share rules between
43
+ # Stylesheets.
44
+ #
45
+ # As you'd expect, conflicts are resolved so that the Stylesheet on which you
46
+ # call query has the highest precedence.
47
+ #
48
+ # @example
49
+ # Teacup::Stylesheet.new(:ipad) do
50
+ # style :ok_button,
51
+ # title: "OK!"
52
+ # end
53
+ #
54
+ # Teacup::Stylesheet.new(:ipadvertical) do
55
+ # import :ipad
56
+ # style :ok_button,
57
+ # width: 80
58
+ # end
59
+ # Teacup::Stylesheet[:ipadvertical].query(:ok_button)
60
+ # # => {title: "OK!", width: 80}
61
+ #
62
+ # The two merging mechanisms are considered independently, so you can override
63
+ # a property both in a ':extends' rule, and also in an imported Stylesheet. In such a
64
+ # a case the Stylesheet inclusion conflicts are resolved independently; and then in
65
+ # a second phase, the ':extends' chain is flattened.
66
+ #
67
+ class Stylesheet
68
+ attr_reader :name
69
+
70
+ class << self
71
+ def stylesheets
72
+ @stylesheets ||= {}
73
+ end
74
+
75
+ def [] name
76
+ stylesheets[name]
77
+ end
78
+
79
+ def []= name, stylesheet
80
+ stylesheets[name] = stylesheet
81
+ end
82
+ end
83
+
84
+ # Create a new Stylesheet.
85
+ #
86
+ # If a name is provided then a new constant will be created using that name.
87
+ #
88
+ # @param name, The (optional) name to give.
89
+ # @param &block, The body of the Stylesheet instance_eval'd.
90
+ #
91
+ # @example
92
+ # Teacup::Stylesheet.new(:ipadvertical) do
93
+ # import :ipadbase
94
+ # style :continue_button,
95
+ # top: 50
96
+ # end
97
+ #
98
+ # Teacup::Stylesheet[:ipadvertical].query(:continue_button)
99
+ # # => {top: 50}
100
+ #
101
+ def initialize(name=nil, &block)
102
+ if name
103
+ @name = name.to_sym
104
+ Teacup::Stylesheet[@name] = self
105
+ end
106
+
107
+ # we just store the block for now, because some classes are not "ready"
108
+ # for instance, calling `UIFont.systemFontOfSize()` will cause the
109
+ # application to crash. We will lazily-load this block in `query`, and
110
+ # then set it to nil.
111
+ @block = block
112
+ end
113
+
114
+ # Include another Stylesheet into this one, the rules defined
115
+ # within it will have lower precedence than those defined here
116
+ # in the case that they share the same keys.
117
+ #
118
+ # @param Symbol|Teacup::Stylesheet the name of the stylesheet,
119
+ # or the stylesheet to include.
120
+ #
121
+ # When defining a stylesheet declaratively, it is better to use the symbol
122
+ # that represents a stylesheet, as the constant may not be defined yet:
123
+ #
124
+ # @example
125
+ # Teacup::Stylesheet.new(:ipadvertical) do
126
+ # import :ipadbase
127
+ # import :verticaltweaks
128
+ # end
129
+ #
130
+ #
131
+ # If you are using anonymous stylesheets however, then it will be necessary
132
+ # to pass an actual stylesheet object.
133
+ #
134
+ # @example
135
+ # @stylesheet.import(base_stylesheet)
136
+ #
137
+ def import(name_or_stylesheet)
138
+ imported << name_or_stylesheet
139
+ end
140
+
141
+ # Get the properties defined for the given stylename, in this Stylesheet and
142
+ # all those that have been imported.
143
+ #
144
+ # The Style class handles precedence rules, and extending via `:extends` and
145
+ # `import`. If needs the orientation in order to merge and remove the
146
+ # appropriate orientation styles.
147
+ #
148
+ # @param Symbol stylename, the stylename to look up.
149
+ # @return Hash[Symbol, *] the resulting properties.
150
+ # @example
151
+ # Teacup::Stylesheet[:ipadbase].query(:continue_button)
152
+ # # => {backgroundImage: UIImage.imageNamed("big_red_shiny_button"), title: "Continue!", top: 50}
153
+ def query(stylename, target=nil, orientation=nil, seen={})
154
+ return {} if seen[self]
155
+
156
+ # the block handed to Stylesheet#new is not run immediately - it is run
157
+ # the first time the stylesheet is queried. This fixes bugs related to
158
+ # some resources (fonts) not available when the application is first
159
+ # started. The downside is that @instance variables and variables that
160
+ # should be closed over are not.
161
+ if @block
162
+ instance_eval &@block
163
+ @block = nil
164
+ end
165
+ seen[self] = true
166
+
167
+ styles[stylename].build(target, orientation, seen)
168
+ end
169
+
170
+ # Add a set of properties for a given stylename or multiple stylenames.
171
+ #
172
+ # @param Symbol, *stylename
173
+ # @param Hash[Symbol, Object], properties
174
+ #
175
+ # @example
176
+ # Teacup::Stylesheet.new(:ipadbase) do
177
+ # style :pretty_button,
178
+ # backgroundImage: UIImage.imageNamed("big_red_shiny_button")
179
+ #
180
+ # style :continue_button, extends: :pretty_button,
181
+ # title: "Continue!",
182
+ # top: 50
183
+ # end
184
+ def style(*queries)
185
+ if queries[-1].is_a? Hash
186
+ properties = queries.pop
187
+ else
188
+ # empty style declarations are allowed
189
+ return
190
+ end
191
+
192
+ queries.each do |stylename|
193
+ # merge into styles[stylename], new properties "win"
194
+ Teacup::merge_defaults(properties, styles[stylename], styles[stylename])
195
+ end
196
+ end
197
+
198
+ # A unique and hopefully meaningful description of this Object.
199
+ #
200
+ # @return String
201
+ def inspect
202
+ "Teacup::Stylesheet[#{name.inspect}] = #{styles.inspect}"
203
+ end
204
+
205
+ # The array of Stylesheets that have been imported into this one.
206
+ #
207
+ # @return Array[Stylesheet]
208
+ def imported_stylesheets
209
+ imported.map do |name_or_stylesheet|
210
+ if name_or_stylesheet.is_a? Teacup::Stylesheet
211
+ name_or_stylesheet
212
+ elsif Teacup::Stylesheet.stylesheets.has_key? name_or_stylesheet
213
+ Teacup::Stylesheet.stylesheets[name_or_stylesheet]
214
+ else
215
+ raise "Teacup tried to import Stylesheet #{name_or_stylesheet.inspect} into Stylesheet[#{self.name.inspect}], but it didn't exist"
216
+ end
217
+ end
218
+ end
219
+
220
+ protected
221
+
222
+ # The list of Stylesheets or names that have been imported into this one.
223
+ #
224
+ # @return Array[Symbol|Stylesheet]
225
+ def imported
226
+ @imported ||= []
227
+ end
228
+
229
+ # The actual contents of this stylesheet as a Hash from stylename to properties.
230
+ #
231
+ # @return Hash[Symbol, Hash]
232
+ def styles
233
+ @styles ||= Hash.new{ |_styles, stylename|
234
+ @styles[stylename] = Style.new
235
+ @styles[stylename].stylename = stylename
236
+ @styles[stylename].stylesheet = self
237
+ @styles[stylename]
238
+ }
239
+ end
240
+
241
+ end
242
+ end
@@ -0,0 +1,38 @@
1
+
2
+ module Teacup
3
+
4
+ class Stylesheet
5
+ def identity
6
+ [1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1]
7
+ end
8
+
9
+ def pi
10
+ 3.1415926
11
+ end
12
+
13
+ # rotates the "up & down" direction. The bottom of the view will rotate
14
+ # towards the user as angle increases.
15
+ def flip matrix, angle
16
+ CATransform3DRotate(matrix, angle, 1, 0, 0)
17
+ end
18
+
19
+ # rotates the "left & right" direction. The right side of the view will
20
+ # rotate towards the user as angle increases.
21
+ def twist matrix, angle
22
+ CATransform3DRotate(matrix, angle, 0, 1, 0)
23
+ end
24
+
25
+ # spins, along the z axis. This is probably the one you want, for
26
+ # "spinning" a view like you might a drink coaster or paper napkin.
27
+ def spin matrix, angle
28
+ CATransform3DRotate(matrix, angle, 0, 0, 1)
29
+ end
30
+
31
+ # rotates the layer arbitrarily
32
+ def rotate matrix, angle, x, y, z
33
+ CATransform3DRotate(matrix, angle, x, y, z)
34
+ end
35
+
36
+ end
37
+
38
+ end
@@ -1,5 +1,5 @@
1
1
  module Teacup
2
2
 
3
- VERSION = '0.0.1'
3
+ VERSION = '0.3.1'
4
4
 
5
5
  end
@@ -0,0 +1,6 @@
1
+ # adds the `debug` property to CALayer
2
+ class CALayer
3
+
4
+ attr_accessor :debug
5
+
6
+ end
@@ -0,0 +1,119 @@
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
+ # Enable debug messages for this object
13
+ attr_accessor :debug
14
+
15
+ # The current stylesheet will be looked at when properties are needed. It
16
+ # is loaded lazily, so that assignment can occur before the Stylesheet has
17
+ # been created.
18
+ def stylesheet
19
+ if Symbol === @stylesheet
20
+ @stylesheet = Teacup::Stylesheet[@stylesheet]
21
+ end
22
+
23
+ @stylesheet
24
+ end
25
+
26
+ # Alter the stylename of this view.
27
+ #
28
+ # This will cause new styles to be applied from the stylesheet.
29
+ #
30
+ # @param Symbol stylename
31
+ def stylename=(new_stylename)
32
+ @stylename = new_stylename
33
+ restyle!
34
+ end
35
+
36
+ # Alter the stylesheet of this view.
37
+ #
38
+ # This will cause new styles to be applied using the current stylename,
39
+ # and will recurse into subviews.
40
+ #
41
+ # If you would prefer that a given UIView object does not inherit the
42
+ # stylesheet from its parents, override the 'stylesheet' method to
43
+ # return the correct value at all times.
44
+ #
45
+ # @param Teacup::Stylesheet stylesheet.
46
+ def stylesheet=(new_stylesheet)
47
+ @stylesheet = new_stylesheet
48
+ restyle!
49
+ subviews.each{ |subview| subview.stylesheet = new_stylesheet }
50
+ end
51
+
52
+ def restyle!(orientation=nil)
53
+ style(stylesheet.query(stylename, self, orientation)) if stylesheet
54
+ subviews.each{ |subview| subview.restyle!(orientation) }
55
+ end
56
+
57
+ # Animate a change to a new stylename.
58
+ #
59
+ # This is equivalent to wrapping a call to .stylename= inside
60
+ # UIView.beginAnimations.
61
+ #
62
+ # @param Symbol the new stylename
63
+ # @param Options the options for the animation (may include the
64
+ # duration and the curve)
65
+ #
66
+ def animate_to_stylename(stylename, options={})
67
+ return if self.stylename == stylename
68
+
69
+ UIView.beginAnimations(nil, context: nil)
70
+ # TODO: This should be in a style-sheet!
71
+ UIView.setAnimationDuration(options[:duration]) if options[:duration]
72
+ UIView.setAnimationCurve(options[:curve]) if options[:curve]
73
+ self.stylename = stylename
74
+ UIView.commitAnimations
75
+ end
76
+
77
+ # Animate a change to new styles
78
+ #
79
+ # This is equivalent to wrapping a call to .style() inside
80
+ # UIView.beginAnimations.
81
+ #
82
+ # @param Hash the new styles and options for the animation
83
+ #
84
+ def animate_to_style(style)
85
+ UIView.beginAnimations(nil, context: nil)
86
+ UIView.setAnimationDuration(style[:duration]) if style[:duration]
87
+ UIView.setAnimationCurve(style[:curve]) if style[:curve]
88
+ style(style)
89
+ UIView.commitAnimations
90
+ end
91
+
92
+ # Apply style properties to this element.
93
+ #
94
+ # Takes a hash of properties such as may have been read from a stylesheet
95
+ # or passed as parameters to {Teacup::Layout#layout}, and applies them to
96
+ # the element.
97
+ #
98
+ # Does a little bit of magic (that may be split out as 'sugarcube') to
99
+ # make properties work as you'd expect.
100
+ #
101
+ # If you try and assign something in properties that is not supported,
102
+ # a warning message will be emitted.
103
+ #
104
+ # @param Hash the properties to set.
105
+ def style(properties, orientation=nil)
106
+ Teacup.apply_hash self, properties
107
+ properties.each do |key, value|
108
+ Teacup.apply self, key, value
109
+ end
110
+
111
+ self.setNeedsDisplay
112
+ self.setNeedsLayout
113
+ end
114
+
115
+ def top_level_view
116
+ return self
117
+ end
118
+
119
+ end
@@ -0,0 +1,179 @@
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
+ # Returns a stylesheet to use to style the contents of this controller's
57
+ # view. You can also assign a stylesheet to {stylesheet=}, which will in
58
+ # turn call {restyle!}.
59
+ #
60
+ # This method will be queried each time {restyle!} is called, and also
61
+ # implicitly whenever Teacup needs to draw your layout (currently only at
62
+ # view load time).
63
+ #
64
+ # @return Teacup::Stylesheet
65
+ #
66
+ # @example
67
+ #
68
+ # def stylesheet
69
+ # if [UIDeviceOrientationLandscapeLeft,
70
+ # UIDeviceOrientationLandscapeRight].include?(UIDevice.currentDevice.orientation)
71
+ # Teacup::Stylesheet[:ipad]
72
+ # else
73
+ # Teacup::Stylesheet[:ipadvertical]
74
+ # end
75
+ # end
76
+ def stylesheet
77
+ @stylesheet
78
+ end
79
+
80
+ # Assigning a new stylesheet triggers {restyle!}, so do this during a
81
+ # rotation to get your different layouts applied.
82
+ #
83
+ # Assigning a stylesheet is an *alternative* to returning a Stylesheet in
84
+ # the {stylesheet} method. Note that {restyle!} calls {stylesheet}, so while
85
+ # assigning a stylesheet will trigger {restyle!}, your stylesheet will not
86
+ # be picked up if you don't return it in a custom stylesheet method.
87
+ #
88
+ # @return Teacup::Stylesheet
89
+ #
90
+ # @example
91
+ #
92
+ # stylesheet = Teacup::Stylesheet[:ipadhorizontal]
93
+ # stylesheet = :ipadhorizontal
94
+ def stylesheet=(new_stylesheet)
95
+ @stylesheet = new_stylesheet
96
+ if view
97
+ view.stylesheet = new_stylesheet
98
+ view.restyle!
99
+ end
100
+ end
101
+
102
+ def top_level_view
103
+ return self.view
104
+ end
105
+
106
+
107
+ # Instantiate the layout from the class, and then call layoutDidLoad.
108
+ #
109
+ # If you want to use Teacup in your controller, please hook into layoutDidLoad,
110
+ # not viewDidLoad.
111
+ def viewDidLoad
112
+
113
+ if not self.stylesheet
114
+ self.stylesheet = self.class.stylesheet
115
+ end
116
+
117
+ if self.class.layout_definition
118
+ stylename, properties, block = self.class.layout_definition
119
+ layout(view, stylename, properties, &block)
120
+ end
121
+
122
+ layoutDidLoad
123
+ end
124
+
125
+ def viewWillAppear(animated)
126
+ self.view.restyle!
127
+ end
128
+
129
+ def layoutDidLoad
130
+ true
131
+ end
132
+
133
+ # The compiling mechanisms combined with how UIKit works of rubymotion do
134
+ # not allow the `shouldAutorotateToInterfaceOrientation` method to be
135
+ # overridden in modules/extensions. So instead, HERE is the code for what
136
+ # `shouldAutorotateToInterfaceOrientation` should look like if you want
137
+ # to use the teacup rotation stuff. Call this method from your own
138
+ # `shouldAutorotateToInterfaceOrientation` method.
139
+ #
140
+ # the teacup developers apologize for any inconvenience. :-)
141
+ def autorotateToOrientation(orientation)
142
+ if view.stylesheet and view.stylename
143
+ properties = view.stylesheet.query(view.stylename, self, orientation)
144
+
145
+ # check for orientation-specific properties
146
+ case orientation
147
+ when UIInterfaceOrientationPortrait
148
+ # portrait is "on" by default, must be turned off explicitly
149
+ if properties.supports?(:portrait) == nil and properties.supports?(:upside_up) == nil
150
+ return true
151
+ end
152
+
153
+ return (properties.supports?(:portrait) or properties.supports?(:upside_up))
154
+ when UIInterfaceOrientationPortraitUpsideDown
155
+ if UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPhone
156
+ # iphone must have an explicit upside-down style, otherwise this returns
157
+ # false
158
+ return properties.supports?(:upside_down)
159
+ else
160
+ # ipad can just have a portrait style
161
+ return (properties.supports?(:portrait) or properties.supports?(:upside_down))
162
+ end
163
+ when UIInterfaceOrientationLandscapeLeft
164
+ return (properties.supports?(:landscape) or properties.supports?(:landscape_left))
165
+ when UIInterfaceOrientationLandscapeRight
166
+ return (properties.supports?(:landscape) or properties.supports?(:landscape_right))
167
+ end
168
+
169
+ return false
170
+ end
171
+
172
+ return orientation == UIInterfaceOrientationPortrait
173
+ end
174
+
175
+ def willAnimateRotationToInterfaceOrientation(orientation, duration:duration)
176
+ view.restyle!(orientation)
177
+ end
178
+
179
+ end
@@ -0,0 +1,34 @@
1
+ # Methods to retrieve a subview using the stylename as a key
2
+ # Kinda similar to jQuery-style $().find('stylename')
3
+ class UIView
4
+
5
+ # get one stylesheet by stylename
6
+ # my_view[:button] :button => #<UIButton..>
7
+ def viewWithStylename name
8
+ subviews.each do |view|
9
+ if view.stylename == name
10
+ return view
11
+ end
12
+ end
13
+ subviews.each do |view|
14
+ if v = view.viewWithStylename(name)
15
+ return v
16
+ end
17
+ end
18
+ nil # couldn't find it
19
+ end
20
+
21
+ # get stylesheets by stylename
22
+ # my_view.all :button => [#<UIButton..>, #<UIButton...>]
23
+ def viewsWithStylename name
24
+ r = []
25
+ subviews.each do |view|
26
+ if view.stylename == name
27
+ r.push name
28
+ end
29
+ r += view.viewsWithStylename name
30
+ end
31
+ r
32
+ end
33
+
34
+ end
@@ -0,0 +1,57 @@
1
+ ##|
2
+ ##| UIView.frame
3
+ ##|
4
+ Teacup.handler UIView, :left, :x { |view, x|
5
+ f = view.frame
6
+ f.origin.x = x
7
+ view.frame = f
8
+ }
9
+
10
+ Teacup.handler UIView, :right { |view, r|
11
+ f = view.frame
12
+ f.origin.x = r - f.size.width
13
+ view.frame = f
14
+ }
15
+
16
+ Teacup.handler UIView, :top, :y { |view, y|
17
+ f = view.frame
18
+ f.origin.y = y
19
+ view.frame = f
20
+ }
21
+
22
+ Teacup.handler UIView, :bottom { |view, b|
23
+ f = view.frame
24
+ f.origin.y = b - f.size.height
25
+ view.frame = f
26
+ }
27
+
28
+ Teacup.handler UIView, :width { |view, w|
29
+ f = view.frame
30
+ f.size.width = w
31
+ view.frame = f
32
+ }
33
+
34
+ Teacup.handler UIView, :height { |view, h|
35
+ f = view.frame
36
+ f.size.height = h
37
+ view.frame = f
38
+ }
39
+
40
+ Teacup.handler UIView, :origin { |view, origin|
41
+ f = view.frame
42
+ f.origin = origin
43
+ view.frame = f
44
+ }
45
+
46
+ Teacup.handler UIView, :size { |view, size|
47
+ f = view.frame
48
+ f.size = size
49
+ view.frame = f
50
+ }
51
+
52
+ ##|
53
+ ##| UIButton
54
+ ##|
55
+ Teacup.handler UIButton, :title { |view, title|
56
+ view.setTitle(title, forState: UIControlStateNormal)
57
+ }