teacup 0.0.1.pre → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -3
- data/CHANGES.md +26 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +1 -1
- data/LICENSE +26 -0
- data/README.md +383 -95
- data/Rakefile +8 -36
- data/app/app_delegate.rb +14 -0
- data/app/controllers/first_controller.rb +71 -0
- data/app/controllers/landscape_only_controller.rb +16 -0
- data/app/controllers/tableview_controller.rb +0 -0
- data/app/styles/main_styles.rb +111 -0
- data/app/views/custom_view.rb +4 -0
- data/lib/dummy.rb +56 -0
- data/lib/teacup/handler.rb +99 -0
- data/lib/teacup/layout.rb +22 -74
- data/lib/teacup/merge_defaults.rb +45 -0
- data/lib/teacup/style.rb +93 -0
- data/lib/teacup/stylesheet.rb +242 -0
- data/lib/teacup/stylesheet_extensions/rotation.rb +38 -0
- data/lib/teacup/version.rb +1 -1
- data/lib/teacup/z_core_extensions/ca_layer.rb +6 -0
- data/lib/teacup/z_core_extensions/ui_view.rb +119 -0
- data/lib/teacup/z_core_extensions/ui_view_controller.rb +179 -0
- data/lib/teacup/z_core_extensions/ui_view_getters.rb +34 -0
- data/lib/teacup/z_core_extensions/z_handlers.rb +57 -0
- data/lib/teacup.rb +16 -33
- data/samples/Hai/Rakefile +7 -2
- data/samples/Hai/app/app_delegate.rb +2 -2
- data/samples/Hai/app/hai_controller.rb +8 -4
- data/samples/Hai/styles/iphone.rb +40 -0
- data/spec/main_spec.rb +226 -0
- data/spec/style_spec.rb +171 -0
- data/spec/stylesheet_spec.rb +348 -0
- data/spec/view_spec.rb +103 -0
- data/teacup.gemspec +13 -13
- metadata +47 -46
- data/.rspec +0 -2
- data/lib/teacup/contributors.rb +0 -7
- data/lib/teacup/core_extensions/ui_view.rb +0 -4
- data/lib/teacup/core_extensions/ui_view_controller.rb +0 -62
- data/lib/teacup/style_sheet.rb +0 -195
- data/lib/teacup/view.rb +0 -123
- data/pkg/teacup-0.0.0.gem +0 -0
- data/pkg/teacup-0.0.1.gem +0 -0
- data/proposals/other/README.md +0 -45
- data/proposals/other/app/config/application.rb +0 -1
- data/proposals/other/app/config/boot.rb +0 -1
- data/proposals/other/app/config/initializers/twitter.rb +0 -7
- data/proposals/other/app/controllers/events_controller.rb +0 -28
- data/proposals/other/app/controllers/venues_controller.rb +0 -4
- data/proposals/other/app/db/README.md +0 -16
- data/proposals/other/app/db/migrations/20120514201043_create_events.rb +0 -9
- data/proposals/other/app/db/migrations/20120514201044_add_price_to_events.rb +0 -5
- data/proposals/other/app/db/migrations/20120514201045_create_venues.rb +0 -8
- data/proposals/other/app/db/schema.rb +0 -19
- data/proposals/other/app/models/event.rb +0 -14
- data/proposals/other/app/models/venue.rb +0 -3
- data/proposals/other/app/views/events/edit.ipad.rb +0 -8
- data/proposals/other/app/views/events/edit.iphone.rb +0 -7
- data/proposals/other/app/views/events/show.ipad.rb +0 -2
- data/proposals/other/app/views/events/show.iphone.rb +0 -3
- data/samples/Hai/styles/ipad.rb +0 -11
- data/samples/Hai/styles/ipad_vertical.rb +0 -3
- data/spec/spec_helper.rb +0 -5
- data/spec/teacup/contributions_spec.rb +0 -13
- data/spec/teacup/version_spec.rb +0 -9
data/lib/teacup.rb
CHANGED
@@ -1,41 +1,24 @@
|
|
1
1
|
unless defined?(Motion::Project::Config)
|
2
|
-
raise "
|
2
|
+
raise "The teacup gem must be required within a RubyMotion project Rakefile."
|
3
3
|
end
|
4
4
|
|
5
|
-
# In order that we can prepend our files to the load path after the user has
|
6
|
-
# configured their app.files, we need to run code *after* the user has set up
|
7
|
-
# their app.
|
8
|
-
#
|
9
|
-
# Unfortunately, the canonical place to require rubygems is at the top of the
|
10
|
-
# file (while we could just add to the instructions "please `require 'teacup'`
|
11
|
-
# at the bottom, that would be odd, and no-one would read the instructions).
|
12
|
-
#
|
13
|
-
# To this end, we tweak the App setup function so that whenever setup is called,
|
14
|
-
# we configure teacup after that.
|
15
|
-
#
|
16
|
-
# This is not great though, as other gems may (following the instructions at
|
17
|
-
# http://reality.hk/posts/2012/05/22/create-gems-for-rubymotion/) also call
|
18
|
-
# setup...
|
19
|
-
#
|
20
|
-
# For sanity reasons, we therefore delete teacup requires from the load order
|
21
|
-
# and re-add them to the front every single time {setup} is called.
|
22
|
-
#
|
23
|
-
# TODO: We should send a patch to rubymotion that adds first-class support for
|
24
|
-
# app.gems. These could then be required *after* the user has finished running
|
25
|
-
# the setup block, so that they can just run setup properly.
|
26
|
-
#
|
27
|
-
class << Motion::Project::App
|
28
5
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
6
|
+
Motion::Project::App.setup do |app|
|
7
|
+
# scans app.files until it finds app/ (the default)
|
8
|
+
# if found, it inserts just before those files, otherwise it will insert to
|
9
|
+
# the end of the list
|
10
|
+
insert_point = 0
|
11
|
+
app.files.each_index do |index|
|
12
|
+
file = app.files[index]
|
13
|
+
if file =~ /^(?:\.\/)?app\//
|
14
|
+
# found app/, so stop looking
|
15
|
+
break
|
36
16
|
end
|
17
|
+
insert_point = index + 1
|
37
18
|
end
|
38
19
|
|
39
|
-
|
40
|
-
|
20
|
+
app.files.insert(insert_point, File.join(File.dirname(__FILE__), 'dummy.rb'))
|
21
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'teacup/**/*.rb')).reverse.each do |file|
|
22
|
+
app.files.insert(insert_point, file)
|
23
|
+
end
|
41
24
|
end
|
data/samples/Hai/Rakefile
CHANGED
@@ -4,9 +4,14 @@ require 'motion/project'
|
|
4
4
|
Motion::Project::App.setup do |app|
|
5
5
|
app.name = 'Hai'
|
6
6
|
|
7
|
-
app.device_family = :
|
7
|
+
app.device_family = :iphone
|
8
8
|
|
9
|
-
app.files += Dir.glob(File.join(app.project_dir, '
|
9
|
+
app.files += Dir.glob(File.join(app.project_dir, '../../lib/**/*.rb'))
|
10
10
|
app.files += Dir.glob(File.join(app.project_dir, 'styles/**/*.rb'))
|
11
11
|
app.files += Dir.glob(File.join(app.project_dir, 'app/**/*.rb'))
|
12
|
+
app.files_dependencies './../../lib/teacup/layout.rb' => './../../lib/teacup/stylesheet.rb'
|
13
|
+
app.files_dependencies './../../lib/teacup/z_core_extensions/ui_view_controller.rb' => './../../lib/teacup/layout.rb'
|
14
|
+
app.files_dependencies './../../lib/teacup/z_core_extensions/ui_view.rb' => './../../lib/teacup/z_core_extensions/ui_view_controller.rb'
|
15
|
+
app.files_dependencies 'app/app_delegate.rb' => './../../lib/teacup/z_core_extensions/ui_view.rb'
|
16
|
+
app.files_dependencies 'app/hai_controller.rb' => './../../lib/teacup/z_core_extensions/ui_view.rb'
|
12
17
|
end
|
@@ -1,9 +1,9 @@
|
|
1
1
|
class AppDelegate
|
2
2
|
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
3
3
|
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
4
|
-
@window.rootViewController = HaiViewController.alloc.init
|
4
|
+
@window.rootViewController = HaiViewController.alloc.init
|
5
5
|
@window.makeKeyAndVisible
|
6
|
-
|
6
|
+
|
7
7
|
true
|
8
8
|
end
|
9
9
|
end
|
@@ -1,9 +1,13 @@
|
|
1
1
|
class HaiViewController < UIViewController
|
2
|
+
stylesheet :iphone
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
layout :hai do
|
5
|
+
subview(UILabel, :label)
|
6
|
+
subview(UILabel, :footer)
|
7
|
+
end
|
8
|
+
|
9
|
+
def shouldAutorotateToInterfaceOrientation(orientation)
|
10
|
+
autorotateToOrientation(orientation)
|
7
11
|
end
|
8
12
|
|
9
13
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
|
2
|
+
Teacup::Stylesheet.new(:iphone) do
|
3
|
+
label_color = UIColor.blueColor
|
4
|
+
|
5
|
+
style :hai,
|
6
|
+
landscape: true
|
7
|
+
|
8
|
+
style UILabel,
|
9
|
+
textColor: label_color
|
10
|
+
|
11
|
+
style :label,
|
12
|
+
text: 'Hai!',
|
13
|
+
backgroundColor: UIColor.whiteColor,
|
14
|
+
top: 10,
|
15
|
+
left: 100,
|
16
|
+
width: 50,
|
17
|
+
height: 20,
|
18
|
+
layer: {
|
19
|
+
transform: identity,
|
20
|
+
},
|
21
|
+
landscape_left: {
|
22
|
+
layer: {
|
23
|
+
transform: rotate(identity, pi/6, 0.3, 0.3, 0.3)
|
24
|
+
},
|
25
|
+
width: 75
|
26
|
+
}
|
27
|
+
|
28
|
+
style :footer,
|
29
|
+
text: 'brought to you by teacup',
|
30
|
+
backgroundColor: UIColor.lightGrayColor,
|
31
|
+
top: 440,
|
32
|
+
left: 120,
|
33
|
+
width: 200,
|
34
|
+
height: 20,
|
35
|
+
landscape: {
|
36
|
+
left: 280,
|
37
|
+
top: 280
|
38
|
+
}
|
39
|
+
|
40
|
+
end
|
data/spec/main_spec.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
describe "Application 'Teacup'" do
|
2
|
+
before do
|
3
|
+
UIDevice.currentDevice.beginGeneratingDeviceOrientationNotifications
|
4
|
+
@app = UIApplication.sharedApplication
|
5
|
+
@view_ctrlr = @app.windows[0].rootViewController
|
6
|
+
end
|
7
|
+
|
8
|
+
after do
|
9
|
+
UIDevice.currentDevice.endGeneratingDeviceOrientationNotifications
|
10
|
+
end
|
11
|
+
|
12
|
+
it "has one window" do
|
13
|
+
@app.windows.size.should == 1
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have a root view" do
|
17
|
+
view_ctrlr_view = @view_ctrlr.view
|
18
|
+
view_ctrlr_view.subviews.length.should == 1
|
19
|
+
view_ctrlr_view.subviews[0].class.should == CustomView
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "view controller" do
|
23
|
+
|
24
|
+
it "should be able to rotate" do
|
25
|
+
@view_ctrlr.shouldAutorotateToInterfaceOrientation(UIDeviceOrientationPortrait).should == true
|
26
|
+
@view_ctrlr.shouldAutorotateToInterfaceOrientation(UIDeviceOrientationLandscapeLeft).should == true
|
27
|
+
@view_ctrlr.shouldAutorotateToInterfaceOrientation(UIDeviceOrientationLandscapeRight).should == true
|
28
|
+
@view_ctrlr.shouldAutorotateToInterfaceOrientation(UIDeviceOrientationPortraitUpsideDown).should == false
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "root view" do
|
33
|
+
|
34
|
+
before do
|
35
|
+
@root_view = @app.windows[0].subviews[0]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "root view should be styled as 'root'" do
|
39
|
+
@root_view.stylename.should == :root
|
40
|
+
@root_view.frame.origin.x.should == 0
|
41
|
+
@root_view.frame.origin.y.should == 0
|
42
|
+
@root_view.frame.size.width.should == 320
|
43
|
+
@root_view.frame.size.height.should == 480
|
44
|
+
@root_view.backgroundColor.should == UIColor.yellowColor
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "background view" do
|
50
|
+
|
51
|
+
before do
|
52
|
+
@background = @app.windows[0].subviews[0].subviews[0]
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should be styled as :background" do
|
56
|
+
@background.stylename.should == :background
|
57
|
+
@background.frame.origin.x.should == 10
|
58
|
+
@background.frame.origin.y.should == 30
|
59
|
+
@background.frame.size.width.should == 300
|
60
|
+
@background.frame.size.height.should == 440
|
61
|
+
@background.backgroundColor.should == UIColor.darkGrayColor
|
62
|
+
end
|
63
|
+
|
64
|
+
it "background view should have subviews" do
|
65
|
+
@background.subviews.length.should == 3
|
66
|
+
@background.subviews[0].class.should == UILabel
|
67
|
+
@background.subviews[1].class.should == UILabel
|
68
|
+
@background.subviews[2].class.ancestors.include?(UIButton).should == true
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should not have styles overridden by base classes" do
|
72
|
+
@background.alpha.should == 0.5
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should have styles overridden orientation styles" do
|
76
|
+
@background.backgroundColor.should == UIColor.darkGrayColor
|
77
|
+
end
|
78
|
+
|
79
|
+
describe "background subviews" do
|
80
|
+
|
81
|
+
before do
|
82
|
+
@welcome = @background.subviews[0]
|
83
|
+
@footer = @background.subviews[1]
|
84
|
+
@button = @background.subviews[2]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should have all UILabels with color blue" do
|
88
|
+
@welcome.textColor.should == UIColor.blueColor
|
89
|
+
@footer.textColor.should == UIColor.blueColor
|
90
|
+
end
|
91
|
+
|
92
|
+
describe "welcome" do
|
93
|
+
it "should be styled as :welcome" do
|
94
|
+
@welcome.stylename.should == :welcome
|
95
|
+
@welcome.frame.origin.x.should == 10
|
96
|
+
@welcome.frame.origin.y.should == 40
|
97
|
+
@welcome.frame.size.width.should == 280
|
98
|
+
@welcome.frame.size.height.should == 20
|
99
|
+
@welcome.text.should == "Welcome to teacup"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe "footer" do
|
104
|
+
it "should be styled as :footer" do
|
105
|
+
@footer.stylename.should == :footer
|
106
|
+
@footer.frame.origin.x.should == 10
|
107
|
+
@footer.frame.origin.y.should == 410
|
108
|
+
@footer.frame.size.width.should == 280
|
109
|
+
@footer.frame.size.height.should == 20
|
110
|
+
@footer.text.should == "This is a teacup example"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe "button" do
|
115
|
+
it "should be styled as :next_message" do
|
116
|
+
@button.stylename.should == :next_message
|
117
|
+
@button.frame.origin.x.should == 150
|
118
|
+
@button.frame.origin.y.should == 370
|
119
|
+
@button.frame.size.width.should == 130
|
120
|
+
@button.frame.size.height.should == 20
|
121
|
+
@button.titleForState(UIControlStateNormal).should == "Next Message..."
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "background view in landscape" do
|
130
|
+
|
131
|
+
before do
|
132
|
+
@background = @app.windows[0].subviews[0].subviews[0]
|
133
|
+
@view_ctrlr.landscape_only
|
134
|
+
UIApplication.sharedApplication.setStatusBarOrientation(UIDeviceOrientationLandscapeLeft, animated:false)
|
135
|
+
end
|
136
|
+
|
137
|
+
it "should be in landscape" do
|
138
|
+
# the rest of these tests *pass*, but the device orientation isn't actually
|
139
|
+
# updated to be landscape yet... :-/
|
140
|
+
UIDevice.currentDevice.orientation.should > 0
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should be styled as :background - landscape" do
|
144
|
+
@background.stylename.should == :background
|
145
|
+
@background.frame.origin.x.should == 10
|
146
|
+
@background.frame.origin.y.should == 30
|
147
|
+
@background.frame.size.width.should == 460
|
148
|
+
@background.frame.size.height.should == 280
|
149
|
+
@background.backgroundColor.should == UIColor.lightGrayColor
|
150
|
+
end
|
151
|
+
|
152
|
+
it "should not have styles overridden by base classes" do
|
153
|
+
@background.alpha.should == 0.8
|
154
|
+
end
|
155
|
+
|
156
|
+
it "should have styles overridden orientation styles" do
|
157
|
+
@background.backgroundColor.should == UIColor.lightGrayColor
|
158
|
+
end
|
159
|
+
|
160
|
+
describe "background subviews in landscape" do
|
161
|
+
|
162
|
+
before do
|
163
|
+
@welcome = @background.subviews[0]
|
164
|
+
@footer = @background.subviews[1]
|
165
|
+
@button = @background.subviews[2]
|
166
|
+
end
|
167
|
+
|
168
|
+
describe "welcome" do
|
169
|
+
it "should be styled as :welcome - landscape" do
|
170
|
+
@welcome.stylename.should == :welcome
|
171
|
+
@welcome.frame.origin.x.should == 90
|
172
|
+
@welcome.frame.origin.y.should == 40
|
173
|
+
@welcome.frame.size.width.should == 280
|
174
|
+
@welcome.frame.size.height.should == 20
|
175
|
+
@welcome.text.should == "Welcome to teacup"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
describe "footer" do
|
180
|
+
it "should be styled as :footer - landscape" do
|
181
|
+
@footer.stylename.should == :footer
|
182
|
+
@footer.frame.origin.x.should == 90
|
183
|
+
@footer.frame.origin.y.should == 250
|
184
|
+
@footer.frame.size.width.should == 280
|
185
|
+
@footer.frame.size.height.should == 20
|
186
|
+
@footer.text.should == "This is a teacup example"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
describe "button" do
|
191
|
+
it "should be styled as :next_message - landscape" do
|
192
|
+
@button.stylename.should == :next_message
|
193
|
+
@button.frame.origin.x.should == 20
|
194
|
+
@button.frame.origin.y.should == 200
|
195
|
+
@button.frame.size.width.should == 130
|
196
|
+
@button.frame.size.height.should == 20
|
197
|
+
@button.titleForState(UIControlStateNormal).should == "Next Message..."
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "Stylesheet 'first'" do
|
208
|
+
before do
|
209
|
+
@stylesheet = Teacup::Stylesheet[:first]
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should exist" do
|
213
|
+
@stylesheet.nil?.should == false
|
214
|
+
end
|
215
|
+
|
216
|
+
it "should define some styles" do
|
217
|
+
@stylesheet.query(:footer)[:text].nil?.should == false
|
218
|
+
@stylesheet.query(:footer)[:text].should == "This is a teacup example"
|
219
|
+
end
|
220
|
+
|
221
|
+
it "should union the next_message styles" do
|
222
|
+
@stylesheet.query(:next_message)[:title].should == "Next Message..."
|
223
|
+
(@stylesheet.query(:next_message)[:portrait] ? true : false).should == false
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
data/spec/style_spec.rb
ADDED
@@ -0,0 +1,171 @@
|
|
1
|
+
describe "Teacup::Style" do
|
2
|
+
|
3
|
+
it "should be equal to a Hash" do
|
4
|
+
Teacup::Style.new.should == {}
|
5
|
+
end
|
6
|
+
|
7
|
+
it "should act like a Hash" do
|
8
|
+
style = Teacup::Style.new
|
9
|
+
style[:key] = :value
|
10
|
+
style[:key].should == :value
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should use orientation to override" do
|
14
|
+
style = Teacup::Style.new
|
15
|
+
style[:name] = :default
|
16
|
+
style[:landscape] = {
|
17
|
+
name: :landscape_name,
|
18
|
+
}
|
19
|
+
style[:portrait] = {
|
20
|
+
name: :portrait_name,
|
21
|
+
}
|
22
|
+
style[:upside_down] = {
|
23
|
+
name: :upside_down_name,
|
24
|
+
}
|
25
|
+
# no orientation, which ends up being portrait anyway.
|
26
|
+
style.build()[:name].should == :portrait_name
|
27
|
+
# landscape
|
28
|
+
style.build(nil, UIInterfaceOrientationLandscapeLeft)[:name].should == :landscape_name
|
29
|
+
|
30
|
+
# upside down
|
31
|
+
style.build(nil, UIInterfaceOrientationPortraitUpsideDown)[:name].should == :upside_down_name
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should look in extends" do
|
35
|
+
sheet = Teacup::Stylesheet.new do
|
36
|
+
style :extended,
|
37
|
+
key: :value
|
38
|
+
end
|
39
|
+
sheet.query(:extended)[:key].should == :value
|
40
|
+
|
41
|
+
style = Teacup::Style.new
|
42
|
+
style.stylename = :self
|
43
|
+
style.stylesheet = sheet
|
44
|
+
style[:extends] = :extended
|
45
|
+
style.build()[:key].should == :value
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should look in import" do
|
49
|
+
imported_sheet = Teacup::Stylesheet.new do
|
50
|
+
style :extended,
|
51
|
+
imported: :imported,
|
52
|
+
override: :overridden
|
53
|
+
end
|
54
|
+
|
55
|
+
sheet = Teacup::Stylesheet.new do
|
56
|
+
import imported_sheet
|
57
|
+
|
58
|
+
style :extended,
|
59
|
+
key: :value,
|
60
|
+
override: :override
|
61
|
+
end
|
62
|
+
sheet.query(:extended)[:key].should == :value
|
63
|
+
sheet.query(:extended)[:imported].should == :imported
|
64
|
+
sheet.query(:extended)[:override].should == :override
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should merge :extends properties' do
|
68
|
+
sheet = Teacup::Stylesheet.new do
|
69
|
+
style :style1,
|
70
|
+
a: 'a',
|
71
|
+
b: 'b'
|
72
|
+
end
|
73
|
+
style2 = Teacup::Style.new
|
74
|
+
style2.stylesheet = sheet
|
75
|
+
style2[:a] = 'A'
|
76
|
+
style2[:extends] = :style1
|
77
|
+
|
78
|
+
built = style2.build()
|
79
|
+
built[:a].should == 'A'
|
80
|
+
built[:b].should == 'b'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should merge hashes' do
|
84
|
+
sheet = Teacup::Stylesheet.new do
|
85
|
+
style :style1,
|
86
|
+
layer: { borderWidth: 20, opacity: 0.5 }
|
87
|
+
end
|
88
|
+
|
89
|
+
style2 = Teacup::Style.new
|
90
|
+
style2.stylesheet = sheet
|
91
|
+
style2[:layer] = { borderWidth: 10 }
|
92
|
+
style2[:extends] = :style1
|
93
|
+
|
94
|
+
built = style2.build()
|
95
|
+
built[:layer][:opacity].should == 0.5
|
96
|
+
built[:layer][:borderWidth].should == 10
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'should merge multiple extends' do
|
100
|
+
sheet = Teacup::Stylesheet.new do
|
101
|
+
style :style1,
|
102
|
+
layer: { borderWidth: 20 }
|
103
|
+
style :style2,
|
104
|
+
layer: { borderWidth: 10, opacity: 0.5 }
|
105
|
+
end
|
106
|
+
|
107
|
+
style3 = Teacup::Style.new
|
108
|
+
style3.stylesheet = sheet
|
109
|
+
style3[:extends] = [:style1, :style2]
|
110
|
+
|
111
|
+
built = style3.build()
|
112
|
+
built[:layer][:opacity].should == 0.5
|
113
|
+
built[:layer][:borderWidth].should == 20
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'should merge and flatten orientation rules' do
|
117
|
+
sheet = Teacup::Stylesheet.new do
|
118
|
+
style :style1,
|
119
|
+
portrait: { text: "ignored", tag: 1 }
|
120
|
+
end
|
121
|
+
|
122
|
+
style2 = Teacup::Style.new
|
123
|
+
style2.stylesheet = sheet
|
124
|
+
style2[:portrait] = { text: "text" }
|
125
|
+
style2[:extends] = :style1
|
126
|
+
|
127
|
+
built = style2.build(nil, UIInterfaceOrientationPortrait)
|
128
|
+
built[:tag].should == 1
|
129
|
+
built[:text].should == "text"
|
130
|
+
end
|
131
|
+
|
132
|
+
it 'should respect precedence rules' do
|
133
|
+
sheet = Teacup::Stylesheet.new do
|
134
|
+
style :style1,
|
135
|
+
portrait: { text: "extended", tag: 1 }
|
136
|
+
end
|
137
|
+
|
138
|
+
style2 = Teacup::Style.new
|
139
|
+
style2.stylesheet = sheet
|
140
|
+
style2[:text] = "text"
|
141
|
+
style2[:extends] = :style1
|
142
|
+
|
143
|
+
built = style2.build(nil, UIInterfaceOrientationPortrait)
|
144
|
+
built[:tag].should == 1
|
145
|
+
built[:text].should == "text"
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'should respect merge based on class inheritance' do
|
149
|
+
class Foo
|
150
|
+
attr_accessor :bar
|
151
|
+
end
|
152
|
+
|
153
|
+
class Bar < Foo
|
154
|
+
attr_accessor :baz
|
155
|
+
end
|
156
|
+
|
157
|
+
sheet = Teacup::Stylesheet.new do
|
158
|
+
style Foo,
|
159
|
+
bar: 'bar'
|
160
|
+
end
|
161
|
+
|
162
|
+
style = Teacup::Style.new
|
163
|
+
style.stylesheet = sheet
|
164
|
+
style[:baz] = 'baz'
|
165
|
+
|
166
|
+
built = style.build(Bar.new)
|
167
|
+
built[:bar].should == 'bar'
|
168
|
+
built[:baz].should == 'baz'
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|