teacup 1.0.4 → 1.2.2
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.
- data/.gitignore +1 -0
- data/Gemfile.lock +2 -2
- data/app/custom_class.rb +22 -0
- data/lib/teacup/layout.rb +10 -4
- data/lib/teacup/style.rb +28 -11
- data/lib/teacup/stylesheet_extensions/autoresize.rb +1 -1
- data/lib/teacup/version.rb +1 -1
- data/lib/teacup/z_core_extensions/ui_view.rb +39 -5
- data/lib/teacup/z_core_extensions/ui_view_controller.rb +9 -18
- data/lib/teacup/z_core_extensions/ui_view_getters.rb +18 -15
- data/spec/custom_class_spec.rb +23 -0
- data/spec/main_spec.rb +2 -2
- data/spec/style_spec.rb +29 -1
- metadata +5 -2
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
teacup (1.
|
4
|
+
teacup (1.2.2)
|
5
5
|
rake
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: http://rubygems.org/
|
9
9
|
specs:
|
10
10
|
diff-lcs (1.1.3)
|
11
|
-
rake (0.
|
11
|
+
rake (10.0.2)
|
12
12
|
rspec (2.10.0)
|
13
13
|
rspec-core (~> 2.10.0)
|
14
14
|
rspec-expectations (~> 2.10.0)
|
data/app/custom_class.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Teacup::Stylesheet.new :custom do
|
2
|
+
style :container,
|
3
|
+
frame: [[0, 0], [100, 20]]
|
4
|
+
|
5
|
+
style :label,
|
6
|
+
text: 'custom label',
|
7
|
+
frame: [[0, 0], [100, 20]]
|
8
|
+
end
|
9
|
+
|
10
|
+
class CustomTeacupClass
|
11
|
+
include Teacup::Layout
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
self.stylesheet = :custom
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_container
|
18
|
+
layout(UIView, :container) do
|
19
|
+
subview(UILabel, :label)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/teacup/layout.rb
CHANGED
@@ -116,9 +116,9 @@ module Teacup
|
|
116
116
|
# prevents the calling of restyle! until we return to this method
|
117
117
|
should_restyle = Teacup.should_restyle_and_block
|
118
118
|
|
119
|
-
|
120
|
-
|
121
|
-
|
119
|
+
# assign the 'teacup_next_responder', which is queried for a stylesheet if
|
120
|
+
# one is not explicitly assigned to the view
|
121
|
+
view.teacup_next_responder = self
|
122
122
|
view.stylename = name
|
123
123
|
if properties
|
124
124
|
view.style(properties) if properties
|
@@ -126,7 +126,13 @@ module Teacup
|
|
126
126
|
|
127
127
|
if block_given?
|
128
128
|
superview_chain << view
|
129
|
-
|
129
|
+
begin
|
130
|
+
instance_exec(view, &block) if block_given?
|
131
|
+
rescue NoMethodError => e
|
132
|
+
NSLog("Exception executing layout(#{view.inspect}) in #{self.inspect} (stylesheet=#{stylesheet})")
|
133
|
+
raise e
|
134
|
+
end
|
135
|
+
|
130
136
|
superview_chain.pop
|
131
137
|
end
|
132
138
|
|
data/lib/teacup/style.rb
CHANGED
@@ -28,60 +28,77 @@ module Teacup
|
|
28
28
|
supports[orientation_key]
|
29
29
|
end
|
30
30
|
|
31
|
-
def build(target=nil,
|
32
|
-
properties = Style.new
|
31
|
+
def build(target=nil, rotation_orientation=nil, seen={})
|
32
|
+
properties = Style.new
|
33
33
|
properties.stylename = self.stylename
|
34
34
|
properties.stylesheet = self.stylesheet
|
35
35
|
|
36
|
-
#
|
37
|
-
|
36
|
+
# if we have an orientation, only apply those styles. otherwise apply the
|
37
|
+
# entire style, including the current orientation.
|
38
|
+
if rotation_orientation
|
39
|
+
# in order to preserve the "local-first" override, we need to *delete*
|
40
|
+
# the keys in imported_stylesheets and extended_properties that are
|
41
|
+
# present in this style - even though we don't ultimately *apply* the
|
42
|
+
# styles
|
43
|
+
delete_keys = self.keys
|
44
|
+
orientation = rotation_orientation
|
45
|
+
else
|
46
|
+
delete_keys = []
|
47
|
+
properties.update(self)
|
38
48
|
orientation = UIApplication.sharedApplication.statusBarOrientation
|
39
49
|
end
|
40
50
|
|
41
51
|
# first, move orientation settings into properties "base" level.
|
42
52
|
if orientation
|
43
53
|
Overrides[orientation].each do |orientation_key|
|
44
|
-
if override =
|
54
|
+
if override = self[orientation_key]
|
45
55
|
# override is first, so it takes precedence
|
46
56
|
if override.is_a? Hash
|
47
57
|
Teacup::merge_defaults override, properties, properties
|
48
58
|
end
|
49
|
-
properties.supports[orientation_key] = !!override
|
50
59
|
end
|
51
60
|
end
|
52
61
|
end
|
53
62
|
|
54
63
|
# delete all of them from `properties`
|
55
64
|
Orientations.each do |orientation_key|
|
56
|
-
if
|
65
|
+
if self[orientation_key]
|
57
66
|
properties.supports[orientation_key] = true
|
58
67
|
end
|
68
|
+
properties.delete(orientation_key)
|
59
69
|
end
|
60
70
|
|
61
71
|
# now we can merge extends, and importing. before merging, these will go
|
62
72
|
# through the same process that we just finished on the local style
|
63
73
|
if stylesheet && stylesheet.is_a?(Teacup::Stylesheet)
|
64
74
|
stylesheet.imported_stylesheets.reverse.each do |stylesheet|
|
65
|
-
imported_properties = stylesheet.query(self.stylename, target,
|
75
|
+
imported_properties = stylesheet.query(self.stylename, target, rotation_orientation, seen)
|
76
|
+
delete_keys.each do |key|
|
77
|
+
imported_properties.delete(key)
|
78
|
+
end
|
66
79
|
Teacup::merge_defaults! properties, imported_properties
|
67
80
|
end
|
68
81
|
|
69
|
-
if also_includes =
|
82
|
+
if also_includes = self[:extends]
|
70
83
|
also_includes = [also_includes] unless also_includes.is_a? Array
|
71
84
|
|
72
85
|
# turn style names into Hashes by querying them on the stylesheet
|
73
86
|
# (this does not pass `seen`, because this is a new query)
|
74
87
|
also_includes.each do |also_include|
|
75
|
-
extended_properties = stylesheet.query(also_include, target,
|
88
|
+
extended_properties = stylesheet.query(also_include, target, rotation_orientation)
|
89
|
+
delete_keys.each do |key|
|
90
|
+
extended_properties.delete(key)
|
91
|
+
end
|
76
92
|
Teacup::merge_defaults! properties, extended_properties
|
77
93
|
end
|
78
94
|
end
|
95
|
+
properties.delete(:extends)
|
79
96
|
|
80
97
|
# if we know the class of the target, we can apply styles via class
|
81
98
|
# inheritance. We do not pass `target` in this case.
|
82
99
|
if target
|
83
100
|
target.class.ancestors.each do |ancestor|
|
84
|
-
extended_properties = stylesheet.query(ancestor, nil,
|
101
|
+
extended_properties = stylesheet.query(ancestor, nil, rotation_orientation)
|
85
102
|
Teacup::merge_defaults!(properties, extended_properties)
|
86
103
|
end
|
87
104
|
end
|
data/lib/teacup/version.rb
CHANGED
@@ -9,6 +9,10 @@ class UIView
|
|
9
9
|
# The current stylename that is used to look up properties in the stylesheet.
|
10
10
|
attr_reader :stylename
|
11
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
|
+
|
12
16
|
# Enable debug messages for this object
|
13
17
|
attr_accessor :debug
|
14
18
|
|
@@ -19,7 +23,7 @@ class UIView
|
|
19
23
|
# @param Symbol stylename
|
20
24
|
def stylename=(new_stylename)
|
21
25
|
@stylename = new_stylename
|
22
|
-
restyle!
|
26
|
+
restyle!
|
23
27
|
end
|
24
28
|
|
25
29
|
# Alter the stylesheet of this view.
|
@@ -36,7 +40,6 @@ class UIView
|
|
36
40
|
should_restyle = Teacup.should_restyle_and_block
|
37
41
|
|
38
42
|
@stylesheet = new_stylesheet
|
39
|
-
subviews.each{ |subview| subview.set_stylesheet_quickly(new_stylesheet) }
|
40
43
|
|
41
44
|
if should_restyle
|
42
45
|
Teacup.should_restyle!
|
@@ -44,9 +47,25 @@ class UIView
|
|
44
47
|
end
|
45
48
|
end
|
46
49
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
50
|
+
def stylesheet
|
51
|
+
super
|
52
|
+
# is a stylesheet assigned explicitly?
|
53
|
+
retval = @stylesheet
|
54
|
+
|
55
|
+
# the 'teacup_next_responder' is assigned in the `layout` method, and links
|
56
|
+
# any views created there to the custom class (could be a controller, could
|
57
|
+
# be any class that includes Teacup::Layout). That responder is checked
|
58
|
+
# next, but only if it wouldn't result in a circular loop.
|
59
|
+
if ! retval && @teacup_next_responder && teacup_next_responder != self
|
60
|
+
retval = @teacup_next_responder.stylesheet
|
61
|
+
end
|
62
|
+
|
63
|
+
# lastly, go up the chain; either a controller or superview
|
64
|
+
if ! retval && nextResponder
|
65
|
+
retval = nextResponder.stylesheet
|
66
|
+
end
|
67
|
+
|
68
|
+
return retval
|
50
69
|
end
|
51
70
|
|
52
71
|
def restyle!(orientation=nil)
|
@@ -94,6 +113,8 @@ class UIView
|
|
94
113
|
end
|
95
114
|
|
96
115
|
case original_constraint.relative_to
|
116
|
+
when nil
|
117
|
+
constraint.relative_to = nil
|
97
118
|
when UIView
|
98
119
|
constraint.relative_to = original_constraint.relative_to
|
99
120
|
when :self
|
@@ -111,6 +132,17 @@ class UIView
|
|
111
132
|
end
|
112
133
|
end
|
113
134
|
|
135
|
+
if original_constraint.relative_to && ! constraint.relative_to
|
136
|
+
puts "Could not find #{original_constraint.relative_to.inspect}"
|
137
|
+
container = self
|
138
|
+
tab = ' '
|
139
|
+
while container && constraint.relative_to.nil?
|
140
|
+
tab << '->'
|
141
|
+
puts "#{tab} #{container.stylename.inspect}"
|
142
|
+
container = container.superview
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
114
146
|
# the return value, for the map
|
115
147
|
constraint.nslayoutconstraint
|
116
148
|
end
|
@@ -157,6 +189,7 @@ class UIView
|
|
157
189
|
# TODO: This should be in a style-sheet!
|
158
190
|
UIView.setAnimationDuration(options[:duration]) if options[:duration]
|
159
191
|
UIView.setAnimationCurve(options[:curve]) if options[:curve]
|
192
|
+
UIView.setAnimationDelay(options[:delay]) if options[:delay]
|
160
193
|
self.stylename = stylename
|
161
194
|
UIView.commitAnimations
|
162
195
|
end
|
@@ -172,6 +205,7 @@ class UIView
|
|
172
205
|
UIView.beginAnimations(nil, context: nil)
|
173
206
|
UIView.setAnimationDuration(style[:duration]) if style[:duration]
|
174
207
|
UIView.setAnimationCurve(style[:curve]) if style[:curve]
|
208
|
+
UIView.setAnimationDelay(options[:delay]) if options[:delay]
|
175
209
|
style(style)
|
176
210
|
UIView.commitAnimations
|
177
211
|
end
|
@@ -69,8 +69,8 @@ class UIViewController
|
|
69
69
|
# stylesheet = :ipadhorizontal
|
70
70
|
def stylesheet=(new_stylesheet)
|
71
71
|
@stylesheet = new_stylesheet
|
72
|
-
if self.
|
73
|
-
self.view.
|
72
|
+
if self.viewLoaded?
|
73
|
+
self.view.restyle!
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
@@ -99,36 +99,27 @@ class UIViewController
|
|
99
99
|
parent_class = parent_class.superclass
|
100
100
|
end
|
101
101
|
|
102
|
+
should_restyle = Teacup.should_restyle_and_block
|
103
|
+
|
102
104
|
if my_stylesheet and not self.stylesheet
|
103
105
|
self.stylesheet = my_stylesheet
|
104
106
|
end
|
105
107
|
|
106
108
|
if layout_definition
|
107
109
|
stylename, properties, block = layout_definition
|
108
|
-
should_restyle = Teacup.should_restyle_and_block
|
109
110
|
layout(view, stylename, properties, &block)
|
110
|
-
Teacup.should_restyle! if should_restyle
|
111
111
|
end
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
if should_restyle
|
114
|
+
Teacup.should_restyle!
|
115
|
+
self.view.restyle!
|
116
|
+
end
|
117
117
|
|
118
|
-
def viewWillAppear(animated)
|
119
|
-
old_viewWillAppear(animated)
|
120
|
-
self.view.restyle! unless @teacup_view_appeared
|
121
118
|
if defined? NSLayoutConstraint
|
122
119
|
self.view.apply_constraints
|
123
120
|
end
|
124
|
-
@teacup_view_appeared = true
|
125
|
-
end
|
126
121
|
|
127
|
-
|
128
|
-
|
129
|
-
def viewDidDisappear(animated)
|
130
|
-
old_viewDidDisappear(animated)
|
131
|
-
@teacup_view_appeared = false
|
122
|
+
layoutDidLoad
|
132
123
|
end
|
133
124
|
|
134
125
|
def layoutDidLoad
|
@@ -1,22 +1,21 @@
|
|
1
1
|
# Methods to retrieve a subview using the stylename as a key
|
2
|
-
# Kinda similar to jQuery-style $().find('stylename')
|
2
|
+
# Kinda similar to jQuery-style $(el).find('stylename')
|
3
3
|
class UIView
|
4
4
|
|
5
|
-
# get one subview by stylename or class
|
5
|
+
# get one subview by stylename or class. If the receiver matches, it will be
|
6
|
+
# returned
|
6
7
|
# my_view.viewWithStylename :button => #<UIButton..>
|
7
8
|
# my_view.viewWithStylename UIButton => #<UIButton..>
|
8
9
|
def viewWithStylename name_or_class
|
9
|
-
if name_or_class
|
10
|
-
|
11
|
-
|
12
|
-
view = subviews.find { |view| view.stylename == name_or_class }
|
13
|
-
end
|
10
|
+
return self if self._teacup_check_stylename(name_or_class)
|
11
|
+
|
12
|
+
view = subviews.find { |view| view._teacup_check_stylename(name_or_class) }
|
14
13
|
return view if view
|
15
14
|
|
16
15
|
# found_subview will get assigned to the view we want, but the subview is
|
17
16
|
# what is returned.
|
18
17
|
found_subview = nil
|
19
|
-
view = subviews.find {|subview| found_subview = subview.viewWithStylename(name_or_class) }
|
18
|
+
view = subviews.find { |subview| found_subview = subview.viewWithStylename(name_or_class) }
|
20
19
|
return found_subview if view
|
21
20
|
|
22
21
|
nil # couldn't find it
|
@@ -27,17 +26,21 @@ class UIView
|
|
27
26
|
# my_view.viewsWithStylename UIButton => [#<UIButton..>, #<UIButton...>]
|
28
27
|
def viewsWithStylename name_or_class
|
29
28
|
r = []
|
29
|
+
r << self if self._teacup_check_stylename(name_or_class)
|
30
|
+
|
30
31
|
subviews.each do |view|
|
31
|
-
if name_or_class
|
32
|
-
if view.is_a? name_or_class
|
33
|
-
r << view
|
34
|
-
end
|
35
|
-
elsif view.stylename == name_or_class
|
36
|
-
r << view
|
37
|
-
end
|
32
|
+
r << view if view._teacup_check_stylename(name_or_class)
|
38
33
|
r.concat view.viewsWithStylename name_or_class
|
39
34
|
end
|
40
35
|
r
|
41
36
|
end
|
42
37
|
|
38
|
+
def _teacup_check_stylename(name_or_class)
|
39
|
+
if name_or_class.is_a? Class
|
40
|
+
self.is_a? name_or_class
|
41
|
+
else
|
42
|
+
self.stylename == name_or_class
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
43
46
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
describe "Any class that includes Teacup::Layout" do
|
2
|
+
before do
|
3
|
+
@subject = CustomTeacupClass.new
|
4
|
+
end
|
5
|
+
|
6
|
+
it "should be able to have a stylesheet" do
|
7
|
+
@subject.stylesheet.class.should == Teacup::Stylesheet
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be able to layout and create views" do
|
11
|
+
@subject.create_container.should != nil
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a container and label that are styled" do
|
15
|
+
container = @subject.create_container
|
16
|
+
container.frame.size.width.should == 100
|
17
|
+
container.frame.size.height.should == 20
|
18
|
+
container.subviews.length.should == 1
|
19
|
+
label = container.subviews[0]
|
20
|
+
label.text.should == 'custom label'
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/main_spec.rb
CHANGED
@@ -25,9 +25,9 @@ describe "Application 'Teacup'" do
|
|
25
25
|
it "root view should be styled as :root" do
|
26
26
|
@root_view.stylename.should == :root
|
27
27
|
@root_view.frame.origin.x.should == 0
|
28
|
-
@root_view.frame.origin.y.should ==
|
28
|
+
@root_view.frame.origin.y.should == 20
|
29
29
|
@root_view.frame.size.width.should == 320
|
30
|
-
@root_view.frame.size.height.should ==
|
30
|
+
@root_view.frame.size.height.should == 460
|
31
31
|
@root_view.backgroundColor.should == UIColor.yellowColor
|
32
32
|
end
|
33
33
|
|
data/spec/style_spec.rb
CHANGED
@@ -136,6 +136,7 @@ describe "Teacup::Style" do
|
|
136
136
|
it 'should respect precedence rules' do
|
137
137
|
sheet = Teacup::Stylesheet.new do
|
138
138
|
style :style1,
|
139
|
+
landscape: { tag: 1 },
|
139
140
|
portrait: { text: "extended", tag: 1 }
|
140
141
|
end
|
141
142
|
|
@@ -144,9 +145,13 @@ describe "Teacup::Style" do
|
|
144
145
|
style2[:text] = "text"
|
145
146
|
style2[:extends] = :style1
|
146
147
|
|
148
|
+
built = style2.build(nil)
|
149
|
+
built[:tag].should == 1
|
150
|
+
built[:text].should == 'text'
|
151
|
+
|
147
152
|
built = style2.build(nil, UIInterfaceOrientationPortrait)
|
148
153
|
built[:tag].should == 1
|
149
|
-
built[:text].should ==
|
154
|
+
built[:text].should == nil
|
150
155
|
end
|
151
156
|
|
152
157
|
it 'should respect merge based on class inheritance' do
|
@@ -172,4 +177,27 @@ describe "Teacup::Style" do
|
|
172
177
|
built[:baz].should == 'baz'
|
173
178
|
end
|
174
179
|
|
180
|
+
it 'should not apply default styles when orientation is specified ' do
|
181
|
+
sheet = Teacup::Stylesheet.new do
|
182
|
+
style :style1,
|
183
|
+
top: 10,
|
184
|
+
left: 8,
|
185
|
+
landscape: { width: 100 },
|
186
|
+
portrait: { width: 100 }
|
187
|
+
style :style2,
|
188
|
+
top: 10,
|
189
|
+
left: 8,
|
190
|
+
landscape: { width: 100 },
|
191
|
+
portrait: { width: 100 }
|
192
|
+
end
|
193
|
+
|
194
|
+
style3 = Teacup::Style.new
|
195
|
+
style3.stylesheet = sheet
|
196
|
+
|
197
|
+
built = style3.build(UIInterfaceOrientationPortrait)
|
198
|
+
built[:top].should == nil
|
199
|
+
built[:left].should == nil
|
200
|
+
built[:width].should == nil
|
201
|
+
end
|
202
|
+
|
175
203
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: teacup
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-02-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -70,6 +70,7 @@ files:
|
|
70
70
|
- app/controllers/first_controller.rb
|
71
71
|
- app/controllers/landscape_only_controller.rb
|
72
72
|
- app/controllers/tableview_controller.rb
|
73
|
+
- app/custom_class.rb
|
73
74
|
- app/styles/main_styles.rb
|
74
75
|
- app/views/custom_view.rb
|
75
76
|
- lib/dummy.rb
|
@@ -101,6 +102,7 @@ files:
|
|
101
102
|
- samples/Hai/spec/main_spec.rb
|
102
103
|
- samples/Hai/styles/iphone.rb
|
103
104
|
- samples/README.md
|
105
|
+
- spec/custom_class_spec.rb
|
104
106
|
- spec/main_spec.rb
|
105
107
|
- spec/style_spec.rb
|
106
108
|
- spec/stylesheet_spec.rb
|
@@ -133,6 +135,7 @@ signing_key:
|
|
133
135
|
specification_version: 3
|
134
136
|
summary: A community-driven DSL for creating user interfaces on iOS.
|
135
137
|
test_files:
|
138
|
+
- spec/custom_class_spec.rb
|
136
139
|
- spec/main_spec.rb
|
137
140
|
- spec/style_spec.rb
|
138
141
|
- spec/stylesheet_spec.rb
|