teacup 1.3.4 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +3 -3
- data/README.md +1172 -319
- data/Rakefile +8 -1
- data/app/app_delegate.rb +1 -1
- data/app/controllers/appearance_controller.rb +13 -0
- data/app/controllers/landscape_only_controller.rb +1 -1
- data/app/controllers/{first_controller.rb → main_controller.rb} +4 -3
- data/app/controllers/motion_layout_controller.rb +22 -0
- data/app/styles/appearance.rb +24 -0
- data/app/styles/main_styles.rb +8 -6
- data/app/views/custom_view.rb +1 -0
- data/lib/teacup/calculations.rb +2 -2
- data/lib/teacup/{z_core_extensions → core_extensions}/ca_layer.rb +0 -0
- data/lib/teacup/core_extensions/view_getters.rb +61 -0
- data/lib/teacup/handler.rb +14 -14
- data/lib/teacup/layout.rb +94 -17
- data/lib/teacup/stylesheet.rb +61 -26
- data/lib/teacup/stylesheet_extensions/transform.rb +88 -0
- data/lib/teacup/teacup_controller.rb +122 -0
- data/lib/teacup/teacup_util.rb +12 -7
- data/lib/teacup/teacup_view.rb +329 -0
- data/lib/teacup/version.rb +1 -1
- data/lib/teacup-ios/appearance.rb +96 -0
- data/lib/teacup-ios/core_extensions/teacup_handlers.rb +183 -0
- data/lib/teacup-ios/core_extensions/ui_view.rb +30 -0
- data/lib/teacup-ios/core_extensions/ui_view_controller.rb +110 -0
- data/lib/{dummy.rb → teacup-ios/dummy.rb} +2 -6
- data/lib/teacup-ios/handler.rb +23 -0
- data/lib/{teacup → teacup-ios}/style.rb +9 -10
- data/lib/teacup-ios/stylesheet_extensions/autoresize.rb +169 -0
- data/lib/{teacup/stylesheet_extensions/geometry.rb → teacup-ios/stylesheet_extensions/device.rb} +0 -0
- data/lib/teacup-osx/core_extensions/ns_view.rb +39 -0
- data/lib/teacup-osx/core_extensions/ns_view_controller.rb +21 -0
- data/lib/teacup-osx/core_extensions/ns_window.rb +39 -0
- data/lib/teacup-osx/core_extensions/ns_window_controller.rb +29 -0
- data/lib/{teacup/z_core_extensions/z_handlers.rb → teacup-osx/core_extensions/teacup_handlers.rb} +30 -47
- data/lib/teacup-osx/dummy.rb +80 -0
- data/lib/teacup-osx/handler.rb +16 -0
- data/lib/teacup-osx/style.rb +83 -0
- data/lib/teacup-osx/style_extensions/autoresize.rb +169 -0
- data/lib/teacup.rb +12 -11
- data/samples/Tweets/Gemfile +4 -0
- data/samples/Tweets/Gemfile.lock +16 -0
- data/samples/Tweets/README +7 -0
- data/samples/Tweets/Rakefile +9 -0
- data/samples/Tweets/app/app_delegate.rb +18 -0
- data/samples/Tweets/app/data_parser.rb +10 -0
- data/samples/Tweets/app/json_parser.rb +12 -0
- data/samples/Tweets/app/main_window.rb +99 -0
- data/samples/Tweets/app/menu.rb +108 -0
- data/samples/Tweets/app/stylesheet.rb +21 -0
- data/samples/Tweets/app/tweet.rb +11 -0
- data/samples/Tweets/resources/Credits.rtf +29 -0
- data/samples/Tweets/spec/main_spec.rb +9 -0
- data/samples/teacup-osx/.gitignore +1 -0
- data/samples/teacup-osx/Gemfile +4 -0
- data/samples/teacup-osx/Gemfile.lock +16 -0
- data/samples/teacup-osx/Rakefile +9 -0
- data/samples/teacup-osx/app/app_delegate.rb +23 -0
- data/samples/teacup-osx/app/controller.rb +11 -0
- data/samples/teacup-osx/app/menu.rb +108 -0
- data/samples/teacup-osx/app/window.rb +12 -0
- data/samples/teacup-osx/resources/Credits.rtf +29 -0
- data/samples/teacup-osx/resources/teacup.png +0 -0
- data/samples/teacup-osx/spec/main_spec.rb +9 -0
- data/spec/ios/appearance_spec.rb +18 -0
- data/spec/{calculations_spec.rb → ios/calculations_spec.rb} +0 -0
- data/spec/{constraints_spec.rb → ios/constraints_spec.rb} +0 -0
- data/spec/{custom_class_spec.rb → ios/custom_class_spec.rb} +0 -0
- data/spec/{gradient_spec.rb → ios/gradient_spec.rb} +1 -1
- data/spec/ios/layout_module_spec.rb +54 -0
- data/spec/ios/layout_spec.rb +50 -0
- data/spec/{main_spec.rb → ios/main_spec.rb} +52 -13
- data/spec/ios/motion_layout_spec.rb +44 -0
- data/spec/{present_modal_spec.rb → ios/present_modal_spec.rb} +0 -0
- data/spec/{style_spec.rb → ios/style_spec.rb} +1 -1
- data/spec/ios/stylesheet_extensions/autoresize_spec.rb +50 -0
- data/spec/{stylesheet_spec.rb → ios/stylesheet_spec.rb} +12 -0
- data/spec/{ui_view_getters_spec.rb → ios/ui_view_getters_spec.rb} +0 -0
- data/spec/{uiswitch_spec.rb → ios/uiswitch_spec.rb} +0 -0
- data/spec/{view_spec.rb → ios/view_spec.rb} +23 -2
- metadata +85 -35
- data/lib/teacup/stylesheet_extensions/autoresize.rb +0 -39
- data/lib/teacup/stylesheet_extensions/rotation.rb +0 -37
- data/lib/teacup/z_core_extensions/ui_view.rb +0 -262
- data/lib/teacup/z_core_extensions/ui_view_controller.rb +0 -263
- 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
|