plastic_cup 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +23 -0
- data/Gemfile +7 -0
- data/Gemfile.lock +16 -0
- data/LICENSE +23 -0
- data/README.md +66 -0
- data/Rakefile +17 -0
- data/app/app_delegate.rb +17 -0
- data/app/resources/Default-568h@2x.png +0 -0
- data/lib/plastic_cup/base.rb +131 -0
- data/lib/plastic_cup/core_extensions/handlers.rb +27 -0
- data/lib/plastic_cup/dummy.rb +94 -0
- data/lib/plastic_cup/stylesheet.rb +16 -0
- data/lib/plastic_cup/version.rb +3 -0
- data/lib/plastic_cup.rb +12 -0
- data/plastic_cup.gemspec +23 -0
- data/spec/base_spec.rb +127 -0
- data/spec/core_extensions/handler_spec.rb +45 -0
- data/spec/stylesheet_spec.rb +41 -0
- metadata +71 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
NDNlZGZkMThkNzQwMmE0ZjU3OTU0M2RkNWI0NTljNGYzZDlkZGZiZg==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTNmMmI5M2QwZWM2NGY1YmZhNTU5YTNkZTFlMGY2OTJjZjlkMWVlZg==
|
7
|
+
!binary "U0hBNTEy":
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
NmM3ZDhkNmQzNjczOWI4ZjcwZDdmMjM3Njg3MTUxNjBiN2IxMWU4ODA1Mzk0
|
10
|
+
YTgxMjk5M2MyNTlkMGNkM2YzNjZkOGQ0Y2VkY2Y1OGY3NmRjODA5MjZmYmVl
|
11
|
+
OGFkNjQ2YzY0YjVlZmE2ZWIwNTY5Zjc3ZWY1YzRjMWJkNWJjOWY=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
NmI5NTgxNWVhMTMwODNhNWNlMGJjYjlhZjQ1MDdmZDkyM2I3YTVlMmVjZWZm
|
14
|
+
ZTgzMzFiNGZlM2RkZDY1N2Y5MzYyM2Y2M2VmMzEwOWNiZWFkYWJlMTY4NThi
|
15
|
+
NTcyY2RmZjEwNzVhZDE0MTU0ZjExODZlMjUzYTBhYzdiN2E3NDA=
|
data/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
*.gem
|
2
|
+
|
3
|
+
.repl_history
|
4
|
+
build
|
5
|
+
tags
|
6
|
+
app/pixate_code.rb
|
7
|
+
resources/*.nib
|
8
|
+
resources/*.momd
|
9
|
+
resources/*.storyboardc
|
10
|
+
.DS_Store
|
11
|
+
nbproject
|
12
|
+
.redcar
|
13
|
+
#*#
|
14
|
+
*~
|
15
|
+
*.sw[po]
|
16
|
+
.eprj
|
17
|
+
.sass-cache
|
18
|
+
.idea
|
19
|
+
.build
|
20
|
+
build-*
|
21
|
+
.dat*
|
22
|
+
.ruby-gemset
|
23
|
+
.ruby-version
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
Copyright (c) 2013, April
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without modification,
|
5
|
+
are permitted provided that the following conditions are met:
|
6
|
+
|
7
|
+
Redistributions of source code must retain the above copyright notice, this
|
8
|
+
list of conditions and the following disclaimer.
|
9
|
+
|
10
|
+
Redistributions in binary form must reproduce the above copyright notice, this
|
11
|
+
list of conditions and the following disclaimer in the documentation and/or
|
12
|
+
other materials provided with the distribution.
|
13
|
+
|
14
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
15
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
16
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
17
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
18
|
+
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
19
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
20
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
21
|
+
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
22
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
23
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
Plastic Cup
|
2
|
+
===========
|
3
|
+
|
4
|
+
Plastic Cup is a simplified version of Teacup, aiming at memory leak prevention.
|
5
|
+
It allow assigning properties to object by hash and define stylesheets, in a dummy way.
|
6
|
+
|
7
|
+
#### Usage
|
8
|
+
Style by Hash
|
9
|
+
```ruby
|
10
|
+
@button = PlasticCup::Base.style(UIButton.new, {title: 'Red', backgroundColor: UIColor.redColor})
|
11
|
+
```
|
12
|
+
|
13
|
+
Style by Stylesheet
|
14
|
+
```ruby
|
15
|
+
PlasticCup::Base.add_style_sheet(:red_button, {
|
16
|
+
title: 'Red',
|
17
|
+
backgroundColor: UIColor.redColor
|
18
|
+
})
|
19
|
+
@button = PlasticCup::Base.style(UIButton.new, :red_button)
|
20
|
+
```
|
21
|
+
|
22
|
+
Style with extend Stylesheet
|
23
|
+
```ruby
|
24
|
+
PlasticCup::Base.add_style_sheet(:round_button, {
|
25
|
+
layer: {
|
26
|
+
cornerRadius: 8
|
27
|
+
}
|
28
|
+
})
|
29
|
+
PlasticCup::Base.add_style_sheet(:green_button, {
|
30
|
+
extends: :round_button,
|
31
|
+
backgroundColor: UIColor.greenColor
|
32
|
+
}
|
33
|
+
@button = PlasticCup::Base.style(UIButton.new, :green_button)
|
34
|
+
```
|
35
|
+
|
36
|
+
If you define stylesheet outside methods, some values (e.g. UIFont) need to be in Proc form:
|
37
|
+
```ruby
|
38
|
+
PlasticCup::Base.add_style_sheet(:login_title, {
|
39
|
+
text: 'Login',
|
40
|
+
font: lambda {UIFont.systemFontOfSize(28)}
|
41
|
+
})
|
42
|
+
```
|
43
|
+
|
44
|
+
#### Important: Don't add handler inside any instance method
|
45
|
+
|
46
|
+
Will leak:
|
47
|
+
```ruby
|
48
|
+
def viewDidLoad
|
49
|
+
super
|
50
|
+
|
51
|
+
PlasticCup::Base.handler UIButton, :highlighted_image do |target, image|
|
52
|
+
target.setImage(image, forState: UIControlStateHighlighted)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
```
|
56
|
+
|
57
|
+
Will not leak:
|
58
|
+
```ruby
|
59
|
+
PlasticCup::Base.handler UIButton, :highlighted_image do |target, image|
|
60
|
+
target.setImage(image, forState: UIControlStateHighlighted)
|
61
|
+
end
|
62
|
+
|
63
|
+
def viewDidLoad
|
64
|
+
super
|
65
|
+
end
|
66
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
$:.unshift('/Library/RubyMotion/lib')
|
2
|
+
if ENV.fetch('platform', 'ios') == 'ios'
|
3
|
+
require 'motion/project/template/ios'
|
4
|
+
elsif ENV['platform'] == 'osx'
|
5
|
+
require 'motion/project/template/osx'
|
6
|
+
else
|
7
|
+
raise "Unsupported platform #{ENV['platform']}"
|
8
|
+
end
|
9
|
+
require 'bundler'
|
10
|
+
Bundler.require
|
11
|
+
|
12
|
+
Motion::Project::App.setup do |app|
|
13
|
+
# Use `rake config' to see complete project settings.
|
14
|
+
app.name = 'plastic cup'
|
15
|
+
app.identifier = 'com.tofugear.plasticcup'
|
16
|
+
app.specs_dir = "spec/"
|
17
|
+
end
|
data/app/app_delegate.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
|
3
|
+
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
4
|
+
return true if RUBYMOTION_ENV == 'test'
|
5
|
+
|
6
|
+
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
7
|
+
ctlr = MyController.new
|
8
|
+
@window.rootViewController = ctlr
|
9
|
+
@window.makeKeyAndVisible
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
class MyController < UIViewController
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
Binary file
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module PlasticCup
|
2
|
+
|
3
|
+
class Base
|
4
|
+
|
5
|
+
def self.style(target, style)
|
6
|
+
if style.is_a?(Hash)
|
7
|
+
apply_properties(target, style)
|
8
|
+
else
|
9
|
+
style_sheet = get_style_sheet(style)
|
10
|
+
unless style_sheet.nil?
|
11
|
+
extends = style_sheet.extends
|
12
|
+
final_style = {}
|
13
|
+
extends.each do |ext|
|
14
|
+
ext_style_sheet = get_style_sheet(ext)
|
15
|
+
final_style.merge!(ext_style_sheet.properties) unless ext_style_sheet.nil?
|
16
|
+
end
|
17
|
+
apply_properties(target, final_style.merge(style_sheet.properties))
|
18
|
+
end
|
19
|
+
end
|
20
|
+
target
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.add_style_sheet(name, properties)
|
24
|
+
styles[to_key(name)] = Stylesheet.new(properties)
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.get_style_sheet(style)
|
28
|
+
style_hash = styles[to_key(style)]
|
29
|
+
NSLog "WARNING: Style #{style} undefined." if style_hash.nil?
|
30
|
+
style_hash
|
31
|
+
end
|
32
|
+
|
33
|
+
# teacup/lib/teacup/handler.rb
|
34
|
+
def self.handler(klass, *style_names, &block)
|
35
|
+
if style_names.length == 0
|
36
|
+
raise TypeError.new "No style names assigned"
|
37
|
+
else
|
38
|
+
style_names.each do |style_name|
|
39
|
+
handlers[klass.name][to_key(style_name)] = block
|
40
|
+
end
|
41
|
+
end
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.to_key(key)
|
46
|
+
begin
|
47
|
+
key = key.to_sym
|
48
|
+
rescue NoMethodError
|
49
|
+
raise TypeError.new "#{key.inspect} is not a symbol"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.styles
|
54
|
+
@styles||={}
|
55
|
+
end
|
56
|
+
|
57
|
+
# teacup/lib/teacup/handler.rb
|
58
|
+
def self.handlers
|
59
|
+
@handlers ||= Hash.new{ |hash,klass| hash[klass] = {} }
|
60
|
+
end
|
61
|
+
|
62
|
+
protected
|
63
|
+
|
64
|
+
# teacup/lib/teacup/handler.rb
|
65
|
+
def self.apply_properties(target, properties)
|
66
|
+
klass = target.class
|
67
|
+
properties.each do |key, proxy_value|
|
68
|
+
value = if proxy_value.is_a?(Proc)
|
69
|
+
proxy_value.call
|
70
|
+
else
|
71
|
+
proxy_value
|
72
|
+
end
|
73
|
+
handled = false
|
74
|
+
klass.ancestors.each do |ancestor|
|
75
|
+
ancestor_name=ancestor.name
|
76
|
+
key = to_key(key)
|
77
|
+
if handlers[ancestor_name].has_key? key
|
78
|
+
handlers[ancestor_name][key].call(target, value)
|
79
|
+
handled = true
|
80
|
+
break
|
81
|
+
end
|
82
|
+
end
|
83
|
+
unless handled
|
84
|
+
# you can send methods to subviews (e.g. UIButton#titleLabel) and CALayers
|
85
|
+
# (e.g. UIView#layer) by assigning a hash to a style name.
|
86
|
+
if value.is_a?(Hash)
|
87
|
+
apply_properties(target.send(key), value)
|
88
|
+
else
|
89
|
+
if key =~ /^set[A-Z]/
|
90
|
+
assign = nil
|
91
|
+
setter = key.to_s + ':'
|
92
|
+
else
|
93
|
+
assign = key.to_s + '='
|
94
|
+
setter = 'set' + key.to_s.sub(/^./) {|c| c.capitalize} + ':'
|
95
|
+
end
|
96
|
+
|
97
|
+
apply_method(target, assign, setter, value)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# teacup/lib/teacup-ios/handler.rb
|
105
|
+
def self.apply_method(target, assign, setter, value)
|
106
|
+
if target.respondsToSelector(setter)
|
107
|
+
#NSLog "Calling target.#{setter}(#{value.inspect})"
|
108
|
+
target.send(setter, value)
|
109
|
+
elsif assign and target.respond_to?(assign)
|
110
|
+
#NSLog "Setting #{assign} #{value.inspect}"
|
111
|
+
target.send(assign, value)
|
112
|
+
else
|
113
|
+
NSLog "WARNING: Can't apply #{setter.inspect}#{assign and " or " + assign.inspect or ""} to #{target.inspect}"
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
# for testing
|
119
|
+
if RUBYMOTION_ENV == 'test'
|
120
|
+
def self.clear_style_sheets
|
121
|
+
@styles = nil
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.clear_handlers
|
125
|
+
@handlers = nil
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# teacup/lib/teacup-ios/core_extensions/teacup_handlers.rb
|
2
|
+
##|
|
3
|
+
##| UIButton
|
4
|
+
##|
|
5
|
+
PlasticCup::Base.handler UIButton, :title do |target, title|
|
6
|
+
if title.is_a?(NSAttributedString)
|
7
|
+
target.setAttributedTitle(title, forState: UIControlStateNormal)
|
8
|
+
else
|
9
|
+
target.setTitle(title.to_s, forState: UIControlStateNormal)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
PlasticCup::Base.handler UIButton, :image do |target, image|
|
14
|
+
target.setImage(image, forState: UIControlStateNormal)
|
15
|
+
end
|
16
|
+
|
17
|
+
PlasticCup::Base.handler UIButton, :backgroundImage do |target, background_image|
|
18
|
+
target.setBackgroundImage(background_image, forState: UIControlStateNormal)
|
19
|
+
end
|
20
|
+
|
21
|
+
PlasticCup::Base.handler UIButton, :titleColor do |target, color|
|
22
|
+
target.setTitleColor(color, forState: UIControlStateNormal)
|
23
|
+
end
|
24
|
+
|
25
|
+
PlasticCup::Base.handler UIButton, :titleFont, :font do |target, font|
|
26
|
+
target.titleLabel.font = font
|
27
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# teacup/lib/teacup-ios/dummy.rb
|
2
|
+
class DummyView < UIView
|
3
|
+
private
|
4
|
+
def dummy
|
5
|
+
setFrame(nil)
|
6
|
+
setOpaque(nil)
|
7
|
+
setClipsToBounds(nil)
|
8
|
+
setUserInteractionEnabled(nil)
|
9
|
+
UIView.appearanceWhenContainedIn(UIView, nil)
|
10
|
+
UIView.appearance
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DummyTableView < UITableView
|
15
|
+
private
|
16
|
+
def dummy
|
17
|
+
setAllowSelection(value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class DummyButton < UIButton
|
22
|
+
private
|
23
|
+
def dummy
|
24
|
+
setTitleEdgeInsets(nil)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class DummyScrollView < UIScrollView
|
29
|
+
private
|
30
|
+
def dummy
|
31
|
+
setPagingEnabled(nil)
|
32
|
+
setScrollEnabled(nil)
|
33
|
+
setShowsHorizontalScrollIndicator(nil)
|
34
|
+
setShowsVerticalScrollIndicator(nil)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
class DummyActivityIndicatorView < UIActivityIndicatorView
|
39
|
+
private
|
40
|
+
def dummy
|
41
|
+
setHidesWhenStopped(nil)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class DummyLabel < UILabel
|
46
|
+
private
|
47
|
+
def dummy
|
48
|
+
setAdjustsFontSizeToFitWidth(nil)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class DummyTextField < UITextField
|
53
|
+
private
|
54
|
+
def dummy
|
55
|
+
setSecureTextEntry(nil)
|
56
|
+
setReturnKeyType(nil)
|
57
|
+
setAutocapitalizationType(nil)
|
58
|
+
setAutocorrectionType(nil)
|
59
|
+
setSpellCheckingType(nil)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class DummyPickerView < UIPickerView
|
64
|
+
private
|
65
|
+
def dummy
|
66
|
+
setShowsSelectionIndicator(nil)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class DummyLayer < CALayer
|
71
|
+
private
|
72
|
+
def dummy
|
73
|
+
setCornerRadius(nil)
|
74
|
+
setTransform(nil)
|
75
|
+
setMasksToBounds(nil)
|
76
|
+
setShadowOffset(nil)
|
77
|
+
setShadowOpacity(nil)
|
78
|
+
setShadowRadius(nil)
|
79
|
+
setShadowOffset(nil)
|
80
|
+
setShadowColor(nil)
|
81
|
+
setShadowPath(nil)
|
82
|
+
setOpaque(nil)
|
83
|
+
setTranslucent(nil)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class DummySwitch < UISwitch
|
88
|
+
private
|
89
|
+
def dummy
|
90
|
+
on?
|
91
|
+
setOn(true)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module PlasticCup
|
2
|
+
|
3
|
+
class Stylesheet
|
4
|
+
|
5
|
+
attr_accessor :properties, :extends
|
6
|
+
|
7
|
+
def initialize(options={})
|
8
|
+
@extends = options.delete(:extends) || []
|
9
|
+
@extends = [@extends] if !@extends.is_a?(Array)
|
10
|
+
@extends.map!{|ext| Base.to_key(ext)}
|
11
|
+
@properties=options
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
data/lib/plastic_cup.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
unless defined?(Motion::Project::Config)
|
2
|
+
raise "This file must be required within a RubyMotion project Rakefile."
|
3
|
+
end
|
4
|
+
|
5
|
+
Motion::Project::App.setup do |app|
|
6
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'plastic_cup/*.rb')).each do |file|
|
7
|
+
app.files.unshift(file)
|
8
|
+
end
|
9
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'plastic_cup/*/*.rb')).each do |file|
|
10
|
+
app.files.unshift(file)
|
11
|
+
end
|
12
|
+
end
|
data/plastic_cup.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/plastic_cup/version.rb', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.name = 'plastic_cup'
|
6
|
+
gem.version = PlasticCup::VERSION
|
7
|
+
gem.licenses = ['BSD']
|
8
|
+
|
9
|
+
gem.authors = ['April Tsang']
|
10
|
+
gem.email = ['april@tofugear.com']
|
11
|
+
|
12
|
+
gem.description = <<-DESC
|
13
|
+
Plastic Cup is a simplified version of Teacup, aiming at memory leak prevention.
|
14
|
+
It allow assigning properties to object by hash and define stylesheets, in a dummy way.
|
15
|
+
DESC
|
16
|
+
|
17
|
+
gem.summary = 'A rubymotion gem for assigning properties to object by hash.'
|
18
|
+
gem.homepage = 'https://github.com/apriltg/plastic_cup'
|
19
|
+
|
20
|
+
gem.files = `git ls-files`.split($\)
|
21
|
+
gem.require_paths = ['lib']
|
22
|
+
gem.test_files = gem.files.grep(%r{^spec/})
|
23
|
+
end
|
data/spec/base_spec.rb
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
describe 'PlasticCup::Base' do
|
2
|
+
after do
|
3
|
+
PlasticCup::Base.clear_style_sheets
|
4
|
+
end
|
5
|
+
|
6
|
+
describe '#style' do
|
7
|
+
it 'should apply style to target by hash' do
|
8
|
+
view = PlasticCup::Base.style(UIView.new, {backgroundColor: UIColor.redColor})
|
9
|
+
view.backgroundColor.should == UIColor.redColor
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'should apply style by style sheet name' do
|
13
|
+
PlasticCup::Base.add_style_sheet(:my_style, {frame: [[10, 20], [30, 40]]})
|
14
|
+
button = PlasticCup::Base.style(UIButton.new, :my_style)
|
15
|
+
button.frame.should == CGRectMake(10, 20, 30, 40)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should apply style sheet including extends' do
|
19
|
+
PlasticCup::Base.add_style_sheet(:father, {backgroundColor: UIColor.redColor})
|
20
|
+
PlasticCup::Base.add_style_sheet(:mother, {text: 'Default Text', textAlignment: 2})
|
21
|
+
PlasticCup::Base.add_style_sheet(:my_style, {extends: [:father, :mother], numberOfLines: 3})
|
22
|
+
|
23
|
+
label = PlasticCup::Base.style(UILabel.new, :my_style)
|
24
|
+
|
25
|
+
label.backgroundColor.should == UIColor.redColor
|
26
|
+
label.textAlignment.should == 2
|
27
|
+
label.text.should == 'Default Text'
|
28
|
+
label.numberOfLines.should == 3
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'should override styles in parent style sheets' do
|
32
|
+
PlasticCup::Base.add_style_sheet(:father, {textColor: UIColor.blueColor, textAlignment: 2})
|
33
|
+
PlasticCup::Base.add_style_sheet(:mother, {text: 'Default Text', placeholder: 'This is placeholder'})
|
34
|
+
PlasticCup::Base.add_style_sheet(:my_style, {extends: [:father, :mother], text: 'My Text', textAlignment: 1})
|
35
|
+
|
36
|
+
field = PlasticCup::Base.style(UITextField.new, :my_style)
|
37
|
+
|
38
|
+
field.textColor.should == UIColor.blueColor
|
39
|
+
field.textAlignment.should == 1
|
40
|
+
field.text.should == 'My Text'
|
41
|
+
field.placeholder.should == 'This is placeholder'
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should override former style' do
|
45
|
+
button = PlasticCup::Base.style(UIBarButtonItem.new, {style: UIBarButtonItemStyleBordered, tintColor: UIColor.greenColor})
|
46
|
+
PlasticCup::Base.style(button, {style: UIBarButtonItemStyleDone})
|
47
|
+
|
48
|
+
button.style.should == UIBarButtonItemStyleDone
|
49
|
+
button.tintColor.should == UIColor.greenColor
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
|
54
|
+
describe '#add_style_sheet and #get_style_sheet' do
|
55
|
+
it 'should add style sheet by hash' do
|
56
|
+
PlasticCup::Base.add_style_sheet(:my_style, {text: 'My Text', textAlignment: 1})
|
57
|
+
style_sheet = PlasticCup::Base.get_style_sheet(:my_style)
|
58
|
+
style_sheet.properties.should == {text: 'My Text', textAlignment: 1}
|
59
|
+
end
|
60
|
+
|
61
|
+
it 'add style sheet should raise error if the name is not a symbol' do
|
62
|
+
lambda {
|
63
|
+
PlasticCup::Base.add_style_sheet(456, {text: 'My Text', textAlignment: 1})
|
64
|
+
}.
|
65
|
+
should.raise(TypeError).
|
66
|
+
message.should.match(/456 is not a symbol/)
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'get style sheet should raise error if the name is not a symbol' do
|
70
|
+
lambda {
|
71
|
+
PlasticCup::Base.get_style_sheet(789)
|
72
|
+
}.
|
73
|
+
should.raise(TypeError).
|
74
|
+
message.should.match(/789 is not a symbol/)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should add style sheet with one extend' do
|
78
|
+
PlasticCup::Base.add_style_sheet(:my_style, {extends: :father, text: 'My Text', textAlignment: 1})
|
79
|
+
style_sheet = PlasticCup::Base.get_style_sheet(:my_style)
|
80
|
+
style_sheet.properties.should == {text: 'My Text', textAlignment: 1}
|
81
|
+
style_sheet.extends.should == [:father]
|
82
|
+
end
|
83
|
+
|
84
|
+
it 'should add style sheet with multiple extends' do
|
85
|
+
PlasticCup::Base.add_style_sheet(:my_style, {extends: [:mother, :father], text: 'My Text', textAlignment: 1})
|
86
|
+
style_sheet = PlasticCup::Base.get_style_sheet(:my_style)
|
87
|
+
style_sheet.properties.should == {text: 'My Text', textAlignment: 1}
|
88
|
+
style_sheet.extends.should == [:mother, :father]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#handler' do
|
93
|
+
after do
|
94
|
+
#PlasticCup::Base.clear_handlers
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'should add custom style' do
|
98
|
+
PlasticCup::Base.handler UIAlertView, :add_title do |target, value|
|
99
|
+
target.addButtonWithTitle(value)
|
100
|
+
end
|
101
|
+
alert = PlasticCup::Base.style(UIAlertView.new, {add_title: 'New Title'})
|
102
|
+
alert.buttonTitleAtIndex(0).should == 'New Title'
|
103
|
+
PlasticCup::Base.style(alert, {add_title: 'Second Title'})
|
104
|
+
alert.buttonTitleAtIndex(1).should == 'Second Title'
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
describe '#apply_properties' do
|
110
|
+
it 'should apply properties in hash' do
|
111
|
+
cell = UITableViewCell.new
|
112
|
+
PlasticCup::Base.apply_properties(cell, {backgroundColor: UIColor.redColor, textLabel: {text: 'Cell Text', numberOfLines: 3}})
|
113
|
+
cell.backgroundColor.should == UIColor.redColor
|
114
|
+
cell.textLabel.text.should == 'Cell Text'
|
115
|
+
cell.textLabel.numberOfLines.should == 3
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should apply Proc value' do
|
119
|
+
label = UILabel.new
|
120
|
+
PlasticCup::Base.apply_properties(label, {font: lambda {UIFont.systemFontOfSize(77)}, textColor: UIColor.grayColor})
|
121
|
+
label.font.should == UIFont.systemFontOfSize(77)
|
122
|
+
label.textColor.should == UIColor.grayColor
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# TODO: add tests for string to symbol conversion
|
127
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
describe 'Handler Extensions' do
|
2
|
+
describe 'UIButton' do
|
3
|
+
|
4
|
+
it 'should handle :title for string' do
|
5
|
+
button = PlasticCup::Base.style(UIButton.new, {title: 'button title'})
|
6
|
+
button.titleForState(UIControlStateNormal).should == 'button title'
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should handle :title for attributed string' do
|
10
|
+
string = NSMutableAttributedString.alloc.initWithString('redblue')
|
11
|
+
string.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor, range: NSMakeRange(0,3))
|
12
|
+
string.addAttribute(NSForegroundColorAttributeName, value: UIColor.blueColor, range: NSMakeRange(3,4))
|
13
|
+
button = PlasticCup::Base.style(UIButton.new, {title: string})
|
14
|
+
|
15
|
+
button.attributedTitleForState(UIControlStateNormal).should == string
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'should handle :image' do
|
19
|
+
image = UIImage.imageNamed('Default-568h@2x.png')
|
20
|
+
button = PlasticCup::Base.style(UIButton.new, {image: image})
|
21
|
+
button.imageForState(UIControlStateNormal).should == image
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'should handle :backgroundImage' do
|
25
|
+
image = UIImage.imageNamed('Default-568h@2x.png')
|
26
|
+
button = PlasticCup::Base.style(UIButton.new, {backgroundImage: image})
|
27
|
+
button.backgroundImageForState(UIControlStateNormal).should == image
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should handle :titleColor' do
|
31
|
+
button = PlasticCup::Base.style(UIButton.new, {titleColor: UIColor.greenColor})
|
32
|
+
button.titleColorForState(UIControlStateNormal).should == UIColor.greenColor
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should handle :titleFont' do
|
36
|
+
button = PlasticCup::Base.style(UIButton.new, {titleFont: UIFont.systemFontOfSize(88)})
|
37
|
+
button.titleLabel.font.should == UIFont.systemFontOfSize(88)
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'should handle :font' do
|
41
|
+
button = PlasticCup::Base.style(UIButton.new, {font: UIFont.systemFontOfSize(88)})
|
42
|
+
button.titleLabel.font.should == UIFont.systemFontOfSize(88)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
describe 'PlasticCup::Stylesheet' do
|
2
|
+
|
3
|
+
it 'should have suitable accessors' do
|
4
|
+
style_sheet = PlasticCup::Stylesheet.new
|
5
|
+
style_sheet.extends.should == []
|
6
|
+
style_sheet.properties.should == {}
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should convert single extend to an array' do
|
10
|
+
style_sheet = PlasticCup::Stylesheet.new({extends: :parent_style})
|
11
|
+
style_sheet.extends.should == [:parent_style]
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should accept multiple extend styles name' do
|
15
|
+
style_sheet = PlasticCup::Stylesheet.new({extends: [:father_style, :mother_style]})
|
16
|
+
style_sheet.extends.should == [:father_style, :mother_style]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should not accept extend style name which is not a symbol' do
|
20
|
+
lambda {
|
21
|
+
PlasticCup::Stylesheet.new({extends: [:father_style, 123, :mother_style, 456]})
|
22
|
+
}.
|
23
|
+
should.raise(TypeError).
|
24
|
+
message.should.match(/123 is not a symbol/)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'should convert extend style name from String to Symbol' do
|
28
|
+
style_sheet = PlasticCup::Stylesheet.new({extends: [:father_style, 'mother_style']})
|
29
|
+
style_sheet.extends.should == [:father_style, :mother_style]
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'should initialize properties' do
|
33
|
+
style_sheet = PlasticCup::Stylesheet.new({style_a: 1, style_b: 2})
|
34
|
+
style_sheet.properties.should == {style_a: 1, style_b: 2}
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'should remove extends from properties' do
|
38
|
+
style_sheet = PlasticCup::Stylesheet.new({extends: :parent_style, color: UIColor.blueColor, text: 'Title'})
|
39
|
+
style_sheet.properties.should == {color: UIColor.blueColor, text: 'Title'}
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: plastic_cup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- April Tsang
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2013-08-21 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: ! 'Plastic Cup is a simplified version of Teacup, aiming at memory leak
|
14
|
+
prevention.
|
15
|
+
|
16
|
+
It allow assigning properties to object by hash and define stylesheets, in a dummy
|
17
|
+
way.
|
18
|
+
|
19
|
+
'
|
20
|
+
email:
|
21
|
+
- april@tofugear.com
|
22
|
+
executables: []
|
23
|
+
extensions: []
|
24
|
+
extra_rdoc_files: []
|
25
|
+
files:
|
26
|
+
- .gitignore
|
27
|
+
- Gemfile
|
28
|
+
- Gemfile.lock
|
29
|
+
- LICENSE
|
30
|
+
- README.md
|
31
|
+
- Rakefile
|
32
|
+
- app/app_delegate.rb
|
33
|
+
- app/resources/Default-568h@2x.png
|
34
|
+
- lib/plastic_cup.rb
|
35
|
+
- lib/plastic_cup/base.rb
|
36
|
+
- lib/plastic_cup/core_extensions/handlers.rb
|
37
|
+
- lib/plastic_cup/dummy.rb
|
38
|
+
- lib/plastic_cup/stylesheet.rb
|
39
|
+
- lib/plastic_cup/version.rb
|
40
|
+
- plastic_cup.gemspec
|
41
|
+
- spec/base_spec.rb
|
42
|
+
- spec/core_extensions/handler_spec.rb
|
43
|
+
- spec/stylesheet_spec.rb
|
44
|
+
homepage: https://github.com/apriltg/plastic_cup
|
45
|
+
licenses:
|
46
|
+
- BSD
|
47
|
+
metadata: {}
|
48
|
+
post_install_message:
|
49
|
+
rdoc_options: []
|
50
|
+
require_paths:
|
51
|
+
- lib
|
52
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
requirements: []
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 2.0.7
|
65
|
+
signing_key:
|
66
|
+
specification_version: 4
|
67
|
+
summary: A rubymotion gem for assigning properties to object by hash.
|
68
|
+
test_files:
|
69
|
+
- spec/base_spec.rb
|
70
|
+
- spec/core_extensions/handler_spec.rb
|
71
|
+
- spec/stylesheet_spec.rb
|