walt 0.1

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.
Files changed (48) hide show
  1. data/.gitignore +14 -0
  2. data/CHANGELOG.md +3 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +61 -0
  5. data/LICENSE +26 -0
  6. data/README.md +193 -0
  7. data/Rakefile +17 -0
  8. data/app/app_delegate.rb +71 -0
  9. data/examples/Apple/.gitignore +13 -0
  10. data/examples/Apple/Rakefile +14 -0
  11. data/examples/Apple/app/app_delegate.rb +99 -0
  12. data/examples/Apple/spec/main_spec.rb +9 -0
  13. data/examples/Apple/vendor/Podfile.lock +11 -0
  14. data/examples/Bouncing/.gitignore +13 -0
  15. data/examples/Bouncing/Rakefile +14 -0
  16. data/examples/Bouncing/app/app_delegate.rb +49 -0
  17. data/examples/Bouncing/spec/main_spec.rb +9 -0
  18. data/examples/Bouncing/vendor/Podfile.lock +11 -0
  19. data/lib/walt.rb +27 -0
  20. data/lib/walt/animation.rb +124 -0
  21. data/lib/walt/animation_set.rb +64 -0
  22. data/lib/walt/asset/asset.rb +79 -0
  23. data/lib/walt/asset/image.rb +48 -0
  24. data/lib/walt/asset/text.rb +64 -0
  25. data/lib/walt/operation/base.rb +60 -0
  26. data/lib/walt/operation/fade.rb +35 -0
  27. data/lib/walt/operation/move.rb +73 -0
  28. data/lib/walt/operation/rotate.rb +41 -0
  29. data/lib/walt/operation/scale.rb +41 -0
  30. data/lib/walt/patch/ui_color.rb +5 -0
  31. data/lib/walt/support/attr_default.rb +16 -0
  32. data/lib/walt/support/const_get.rb +60 -0
  33. data/lib/walt/support/font.rb +87 -0
  34. data/lib/walt/version.rb +3 -0
  35. data/lib/walt/walt.rb +53 -0
  36. data/spec/animation_set_spec.rb +49 -0
  37. data/spec/animation_spec.rb +128 -0
  38. data/spec/asset/image_spec.rb +16 -0
  39. data/spec/asset/text_spec.rb +24 -0
  40. data/spec/asset_spec.rb +11 -0
  41. data/spec/main_spec.rb +9 -0
  42. data/spec/operation/fade_spec.rb +25 -0
  43. data/spec/operation/move_spec.rb +43 -0
  44. data/spec/operation_spec.rb +26 -0
  45. data/spec/support_spec.rb +46 -0
  46. data/vendor/Podfile.lock +11 -0
  47. data/walt.gemspec +21 -0
  48. metadata +172 -0
@@ -0,0 +1,9 @@
1
+ describe "Application 'Apple'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+
2
+ PODS:
3
+ - AFNetworking (1.1.0)
4
+
5
+ DEPENDENCIES:
6
+ - AFNetworking
7
+
8
+ SPEC CHECKSUMS:
9
+ AFNetworking: 761a418233d280c1e0580bcb76ff9cb4c3073d17
10
+
11
+ COCOAPODS: 0.16.0
@@ -0,0 +1,13 @@
1
+ .repl_history
2
+ build
3
+ tags
4
+ resources/*.nib
5
+ resources/*.momd
6
+ resources/*.storyboardc
7
+ .DS_Store
8
+ nbproject
9
+ .redcar
10
+ #*#
11
+ *~
12
+ *.sw[po]
13
+ .eprj
@@ -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
@@ -0,0 +1,9 @@
1
+ describe "Application 'Bouncing'" do
2
+ before do
3
+ @app = UIApplication.sharedApplication
4
+ end
5
+
6
+ it "has one window" do
7
+ @app.windows.size.should == 1
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+
2
+ PODS:
3
+ - AFNetworking (1.1.0)
4
+
5
+ DEPENDENCIES:
6
+ - AFNetworking
7
+
8
+ SPEC CHECKSUMS:
9
+ AFNetworking: 761a418233d280c1e0580bcb76ff9cb4c3073d17
10
+
11
+ COCOAPODS: 0.16.0
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