plastic_cup 0.0.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.
- 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
|