walt 0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +14 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +61 -0
- data/LICENSE +26 -0
- data/README.md +193 -0
- data/Rakefile +17 -0
- data/app/app_delegate.rb +71 -0
- data/examples/Apple/.gitignore +13 -0
- data/examples/Apple/Rakefile +14 -0
- data/examples/Apple/app/app_delegate.rb +99 -0
- data/examples/Apple/spec/main_spec.rb +9 -0
- data/examples/Apple/vendor/Podfile.lock +11 -0
- data/examples/Bouncing/.gitignore +13 -0
- data/examples/Bouncing/Rakefile +14 -0
- data/examples/Bouncing/app/app_delegate.rb +49 -0
- data/examples/Bouncing/spec/main_spec.rb +9 -0
- data/examples/Bouncing/vendor/Podfile.lock +11 -0
- data/lib/walt.rb +27 -0
- data/lib/walt/animation.rb +124 -0
- data/lib/walt/animation_set.rb +64 -0
- data/lib/walt/asset/asset.rb +79 -0
- data/lib/walt/asset/image.rb +48 -0
- data/lib/walt/asset/text.rb +64 -0
- data/lib/walt/operation/base.rb +60 -0
- data/lib/walt/operation/fade.rb +35 -0
- data/lib/walt/operation/move.rb +73 -0
- data/lib/walt/operation/rotate.rb +41 -0
- data/lib/walt/operation/scale.rb +41 -0
- data/lib/walt/patch/ui_color.rb +5 -0
- data/lib/walt/support/attr_default.rb +16 -0
- data/lib/walt/support/const_get.rb +60 -0
- data/lib/walt/support/font.rb +87 -0
- data/lib/walt/version.rb +3 -0
- data/lib/walt/walt.rb +53 -0
- data/spec/animation_set_spec.rb +49 -0
- data/spec/animation_spec.rb +128 -0
- data/spec/asset/image_spec.rb +16 -0
- data/spec/asset/text_spec.rb +24 -0
- data/spec/asset_spec.rb +11 -0
- data/spec/main_spec.rb +9 -0
- data/spec/operation/fade_spec.rb +25 -0
- data/spec/operation/move_spec.rb +43 -0
- data/spec/operation_spec.rb +26 -0
- data/spec/support_spec.rb +46 -0
- data/vendor/Podfile.lock +11 -0
- data/walt.gemspec +21 -0
- metadata +172 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$:.unshift("/Library/RubyMotion/lib")
|
3
|
+
require 'motion/project'
|
4
|
+
$:.unshift("../../lib")
|
5
|
+
require '../../lib/walt'
|
6
|
+
|
7
|
+
Motion::Project::App.setup do |app|
|
8
|
+
# Use `rake config' to see complete project settings.
|
9
|
+
app.name = 'Bouncing'
|
10
|
+
|
11
|
+
app.pods do
|
12
|
+
pod "AFNetworking"
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
3
|
+
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
4
|
+
|
5
|
+
@window.makeKeyAndVisible
|
6
|
+
|
7
|
+
url = "http://upload.wikimedia.org/wikipedia/commons/7/7a/Basketball.png"
|
8
|
+
assets = (0..4).collect {|i| {
|
9
|
+
id: "ball_#{i}",
|
10
|
+
url: url,
|
11
|
+
size: [50, 50],
|
12
|
+
position: [i*50 + i*10, 0]
|
13
|
+
} }
|
14
|
+
|
15
|
+
height = UIScreen.mainScreen.bounds.size.height
|
16
|
+
points = [height - 50, height - 150, height - 50, height - 100, height - 50]
|
17
|
+
|
18
|
+
make_point_animation = lambda {|id, index|
|
19
|
+
after = (index < (points.length - 1)) ? make_point_animation.call(id, index+1) : nil
|
20
|
+
h = {
|
21
|
+
duration: 0.5 / (index + 1).to_f + rand(),
|
22
|
+
operations: [{
|
23
|
+
move: id,
|
24
|
+
to: points[index],
|
25
|
+
axis: :y
|
26
|
+
}, {
|
27
|
+
rotate: id,
|
28
|
+
to: rand() * 90
|
29
|
+
}],
|
30
|
+
after: after
|
31
|
+
}
|
32
|
+
h.delete(:after) if after.nil?
|
33
|
+
h
|
34
|
+
}
|
35
|
+
|
36
|
+
animations = []
|
37
|
+
assets.each_with_index do |asset, i|
|
38
|
+
animations << make_point_animation.call(asset[:id], 0)
|
39
|
+
end
|
40
|
+
|
41
|
+
Walt.animate(
|
42
|
+
assets: assets,
|
43
|
+
animations: animations,
|
44
|
+
in: @window
|
45
|
+
)
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
end
|
data/lib/walt.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require "walt/version"
|
2
|
+
require 'bubble-wrap/core'
|
3
|
+
require 'motion-cocoapods'
|
4
|
+
|
5
|
+
BW.require File.expand_path('../walt/support/**/*.rb', __FILE__) do
|
6
|
+
end
|
7
|
+
|
8
|
+
BW.require File.expand_path('../walt/**/*.rb', __FILE__) do
|
9
|
+
end
|
10
|
+
|
11
|
+
Motion::Project::App.setup do |app|
|
12
|
+
depends = {}
|
13
|
+
|
14
|
+
['fade','move'].each {|file|
|
15
|
+
_f = File.expand_path("../walt/operation/#{file}.rb", __FILE__)
|
16
|
+
depends[_f] ||= []
|
17
|
+
depends[_f] << File.expand_path("../walt/operation/base.rb", __FILE__)
|
18
|
+
}
|
19
|
+
|
20
|
+
['image'].each {|file|
|
21
|
+
_f = File.expand_path("../walt/asset/#{file}.rb", __FILE__)
|
22
|
+
depends[_f] ||= []
|
23
|
+
depends[_f] << File.expand_path("../walt/asset/asset.rb", __FILE__)
|
24
|
+
}
|
25
|
+
|
26
|
+
app.files_dependencies depends
|
27
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
=begin
|
2
|
+
{
|
3
|
+
delay: 0.5,
|
4
|
+
duration: 2.5,
|
5
|
+
# array of integers or symbols corresponding to UIViewAnimationOptions
|
6
|
+
options: [:curve_ease_in, :autoreverse]
|
7
|
+
operations: [{
|
8
|
+
# see operation/base.rb
|
9
|
+
type: :move,
|
10
|
+
from: 0,
|
11
|
+
to: 40,
|
12
|
+
id: :one
|
13
|
+
}],
|
14
|
+
after: {
|
15
|
+
# another animation object
|
16
|
+
}
|
17
|
+
}
|
18
|
+
=end
|
19
|
+
|
20
|
+
module Walt
|
21
|
+
class Animation
|
22
|
+
extend Walt::Support::AttrDefault
|
23
|
+
|
24
|
+
PROPERTIES = [:delay, :duration, :after, :operations, :options]
|
25
|
+
attr_accessor *PROPERTIES
|
26
|
+
|
27
|
+
def initialize(params = {})
|
28
|
+
params.each do |key, value|
|
29
|
+
if PROPERTIES.include?(key.to_sym)
|
30
|
+
self.send("#{key}=", value)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def after=(after)
|
36
|
+
_after = after
|
37
|
+
case after
|
38
|
+
when Walt::Animation
|
39
|
+
when NSDictionary
|
40
|
+
_after = Walt::Animation.new(after)
|
41
|
+
else
|
42
|
+
raise "Invalid class for after animation #{after.inspect}"
|
43
|
+
end
|
44
|
+
|
45
|
+
@after = _after
|
46
|
+
end
|
47
|
+
|
48
|
+
attr_default :operations, []
|
49
|
+
def operations=(operations)
|
50
|
+
_operations = []
|
51
|
+
operations.each do |op|
|
52
|
+
case op
|
53
|
+
when Walt::Operation::Base
|
54
|
+
_operations << op
|
55
|
+
when NSDictionary
|
56
|
+
_operations << Walt::Operation.for(op)
|
57
|
+
else
|
58
|
+
raise "Invalid class for operation #{op.inspect}"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
@operations = _operations
|
62
|
+
end
|
63
|
+
|
64
|
+
attr_default :assets, {}
|
65
|
+
def assets=(assets)
|
66
|
+
_assets = {}
|
67
|
+
case assets
|
68
|
+
when NSArray
|
69
|
+
assets.each do |asset|
|
70
|
+
_asset = (asset.is_a?(Walt::Asset) ? asset : Walt::Asset.for(asset))
|
71
|
+
_assets[_asset.id] = _asset
|
72
|
+
end
|
73
|
+
when NSDictionary
|
74
|
+
assets.each do |key, value|
|
75
|
+
asset = value
|
76
|
+
_asset = (asset.is_a?(Walt::Asset) ? asset : Walt::Asset.for(asset))
|
77
|
+
_assets[_asset.id] = _asset
|
78
|
+
end
|
79
|
+
else
|
80
|
+
raise "Not a valid class for assets: #{assets.inspect}"
|
81
|
+
end
|
82
|
+
@assets = _assets
|
83
|
+
end
|
84
|
+
|
85
|
+
attr_default :options, [UIViewAnimationOptionCurveEaseInOut]
|
86
|
+
def options=(options)
|
87
|
+
_options = options.is_a?(NSArray) ? options : [options]
|
88
|
+
@options = _options
|
89
|
+
end
|
90
|
+
|
91
|
+
def animation_options
|
92
|
+
int = 0
|
93
|
+
self.options.each { |i| int = int | Walt::Support.constant("UIViewAnimationOption", i)}
|
94
|
+
int
|
95
|
+
end
|
96
|
+
|
97
|
+
def animate
|
98
|
+
@operations_completed = 0
|
99
|
+
self.operations.each do |operation|
|
100
|
+
asset = self.assets[operation.id]
|
101
|
+
if !asset
|
102
|
+
raise "No asset found for operation #{operation} id #{operation.id}"
|
103
|
+
end
|
104
|
+
|
105
|
+
operation.setup(asset.view, self)
|
106
|
+
|
107
|
+
UIView.animateWithDuration(self.duration,
|
108
|
+
delay:self.delay.to_f,
|
109
|
+
options:self.animation_options,
|
110
|
+
animations:lambda {
|
111
|
+
operation.finalize(asset.view, self)
|
112
|
+
},
|
113
|
+
completion:lambda { |completed|
|
114
|
+
@operations_completed += 1
|
115
|
+
if @operations_completed == self.operations.count && self.after
|
116
|
+
self.after.assets = self.assets
|
117
|
+
self.after.animate
|
118
|
+
end
|
119
|
+
}
|
120
|
+
)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
=begin
|
2
|
+
{
|
3
|
+
# array of assets (see asset/asset.rb) or UIViews
|
4
|
+
assets: [{...}],
|
5
|
+
# array of animations (see animation.rb)
|
6
|
+
animations: [{...}]
|
7
|
+
}
|
8
|
+
=end
|
9
|
+
module Walt
|
10
|
+
class AnimationSet
|
11
|
+
extend Walt::Support::AttrDefault
|
12
|
+
|
13
|
+
PROPERTIES = [:animations, :assets]
|
14
|
+
attr_accessor *PROPERTIES
|
15
|
+
|
16
|
+
def initialize(params = {})
|
17
|
+
params.each do |key, value|
|
18
|
+
if PROPERTIES.include?(key.to_sym)
|
19
|
+
self.send("#{key}=", value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
attr_default :animations, []
|
25
|
+
def animations=(animations)
|
26
|
+
_animations = animations && animations.collect do |animation|
|
27
|
+
case animation
|
28
|
+
when Walt::Animation
|
29
|
+
animation
|
30
|
+
when NSDictionary
|
31
|
+
Walt::Animation.new(animation)
|
32
|
+
else
|
33
|
+
raise "Invalid class for animation #{animation.inspect}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
@animations = _animations
|
37
|
+
end
|
38
|
+
|
39
|
+
attr_default :assets, []
|
40
|
+
def assets=(assets)
|
41
|
+
_assets = assets && assets.collect do |asset|
|
42
|
+
case asset
|
43
|
+
when Walt::Asset
|
44
|
+
asset
|
45
|
+
when NSDictionary
|
46
|
+
Walt::Asset.for(asset)
|
47
|
+
when UIView
|
48
|
+
Walt::Asset.for(asset)
|
49
|
+
else
|
50
|
+
raise "Invalid class for asset #{asset.inspect}"
|
51
|
+
end
|
52
|
+
asset
|
53
|
+
end
|
54
|
+
@assets = _assets
|
55
|
+
end
|
56
|
+
|
57
|
+
def animate
|
58
|
+
self.animations.each do |animation|
|
59
|
+
animation.assets = self.assets
|
60
|
+
animation.animate
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
=begin
|
2
|
+
{
|
3
|
+
id: :one,
|
4
|
+
size: [100,100],
|
5
|
+
position: [10, 10],
|
6
|
+
# array of integers or symbols corresponding to UIViewContentMode
|
7
|
+
content_mode: [:scale_to_fill, :top],
|
8
|
+
clips_to_bounds: true,
|
9
|
+
background_color: "0088ff"
|
10
|
+
}
|
11
|
+
=end
|
12
|
+
|
13
|
+
module Walt
|
14
|
+
class Asset
|
15
|
+
extend Walt::Support::AttrDefault
|
16
|
+
|
17
|
+
PROPERTIES = [:id, :position, :size, :view, :content_mode, :clips_to_bounds, :background_color]
|
18
|
+
attr_accessor *PROPERTIES
|
19
|
+
|
20
|
+
def self.for(params = {})
|
21
|
+
if params.is_a?(NSDictionary) && params[:url]
|
22
|
+
Walt::ImageAsset.new(params)
|
23
|
+
elsif params.is_a?(NSDictionary) && params[:text]
|
24
|
+
Walt::TextAsset.new(params)
|
25
|
+
else
|
26
|
+
self.new(params)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def initialize(params = {})
|
31
|
+
case params
|
32
|
+
when UIView
|
33
|
+
self.view = params
|
34
|
+
when NSDictionary
|
35
|
+
params.each do |key, value|
|
36
|
+
if PROPERTIES.include?(key.to_sym)
|
37
|
+
self.send("#{key}=", value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
attr_default :clips_to_bounds, false
|
44
|
+
|
45
|
+
attr_default :content_mode, [UIViewContentModeScaleToFill]
|
46
|
+
def content_mode=(content_mode)
|
47
|
+
_content_mode = content_mode.is_a?(NSArray) ? content_mode : [content_mode]
|
48
|
+
@content_mode = _content_mode
|
49
|
+
end
|
50
|
+
|
51
|
+
def view_content_mode
|
52
|
+
int = 0
|
53
|
+
self.content_mode.each { |i| int = int | Walt::Support.constant("UIViewContentMode", i)}
|
54
|
+
int
|
55
|
+
end
|
56
|
+
|
57
|
+
def view
|
58
|
+
@view ||= UIView.alloc.initWithFrame(CGRectZero).tap do |view|
|
59
|
+
view.frame = [self.position || CGPointZero, self.size || CGSizeZero]
|
60
|
+
view.backgroundColor = self.background_color.to_color if self.background_color
|
61
|
+
view.contentMode = self.view_content_mode
|
62
|
+
view.clipsToBounds = self.clips_to_bounds
|
63
|
+
Dispatch::Queue.main.async do
|
64
|
+
self.on_ready(true)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_ready(trigger = false, &callback)
|
70
|
+
@on_ready_callbacks ||= []
|
71
|
+
if callback
|
72
|
+
@on_ready_callbacks << callback
|
73
|
+
elsif trigger
|
74
|
+
@on_ready_callbacks.each {|c| c.call(self)}
|
75
|
+
@on_ready_callbacks = []
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
=begin
|
2
|
+
{
|
3
|
+
url: "http://mysite.com/pic.jpg"
|
4
|
+
}
|
5
|
+
=end
|
6
|
+
|
7
|
+
module Walt
|
8
|
+
class ImageAsset < Asset
|
9
|
+
PROPERTIES = [:url]
|
10
|
+
attr_accessor *PROPERTIES
|
11
|
+
|
12
|
+
def initialize(params = {})
|
13
|
+
super
|
14
|
+
|
15
|
+
params.is_a?(NSDictionary) && params.each do |key, value|
|
16
|
+
if PROPERTIES.include?(key.to_sym)
|
17
|
+
self.send("#{key}=", value)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def view
|
23
|
+
if !@view
|
24
|
+
@view = UIImageView.alloc.initWithFrame(CGRectZero)
|
25
|
+
@view.frame = [self.position || CGPointZero, self.size || CGSizeZero]
|
26
|
+
@view.contentMode = self.view_content_mode
|
27
|
+
@view.clipsToBounds = self.clips_to_bounds
|
28
|
+
url = NSURL.URLWithString(self.url)
|
29
|
+
@view.setImageWithURLRequest(NSURLRequest.requestWithURL(url),
|
30
|
+
placeholderImage:nil,
|
31
|
+
success: lambda {|request, response, image|
|
32
|
+
@view.image = image
|
33
|
+
if !self.size
|
34
|
+
@view.sizeToFit
|
35
|
+
end
|
36
|
+
Dispatch::Queue.main.async do
|
37
|
+
self.on_ready(true)
|
38
|
+
end
|
39
|
+
},
|
40
|
+
failure: lambda {|request, response, error|
|
41
|
+
|
42
|
+
})
|
43
|
+
@view
|
44
|
+
end
|
45
|
+
@view
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|