walt 0.1

Sign up to get free protection for your applications and to get access to all the features.
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,64 @@
1
+ =begin
2
+ {
3
+ text: "This goes on the screen",
4
+ text_color: "ff0000",
5
+ background_color: "00ff00",
6
+ number_of_lines: 2,
7
+ text_alignment: :center,
8
+ font: "MarkerFelt" # see support/font.rb
9
+ attributes: {...} # see support/font.rb
10
+ }
11
+ =end
12
+ module Walt
13
+ class TextAsset < Asset
14
+ PROPERTIES = [:text, :text_color, :background_color, :number_of_lines, :font, :attributes, :text_alignment]
15
+ attr_accessor *PROPERTIES
16
+
17
+ attr_default :content_mode, [UIViewContentModeRedraw]
18
+ attr_default :text_color, UIColor.blackColor
19
+ attr_default :background_color, UIColor.clearColor
20
+ attr_default :number_of_lines, 1
21
+
22
+ def initialize(params = {})
23
+ super
24
+
25
+ params.is_a?(NSDictionary) && params.each do |key, value|
26
+ if PROPERTIES.include?(key.to_sym)
27
+ self.send("#{key}=", value)
28
+ end
29
+ end
30
+ end
31
+
32
+ def view
33
+ @view ||= UILabel.alloc.initWithFrame(CGRectZero).tap do |view|
34
+ view.frame = [self.position || CGPointZero, self.size || CGSizeZero]
35
+ view.contentMode = self.view_content_mode
36
+ view.clipsToBounds = self.clips_to_bounds
37
+ view.text = self.text
38
+ view.textColor = self.text_color.to_color
39
+ view.backgroundColor = self.background_color.to_color
40
+ view.numberOfLines = self.number_of_lines
41
+ view.font = Walt::Font.make(self.font) if self.font
42
+ view.textAlignment = Walt::Support.constant("UITextAlignment", self.text_alignment) if self.text_alignment
43
+
44
+ if self.attributes
45
+ attributes = Walt::Font.attributes(self.attributes)
46
+ view.font = attributes[UITextAttributeFont] if attributes[UITextAttributeFont]
47
+ view.textColor = attributes[UITextAttributeTextColor] if attributes[UITextAttributeTextColor]
48
+ view.shadowColor = attributes[UITextAttributeTextShadowColor] if attributes[UITextAttributeTextShadowColor]
49
+ if attributes[UITextAttributeTextShadowOffset]
50
+ view.shadowOffset = CGSizeMake(self.attributes[:shadow_offset][:x], self.attributes[:shadow_offset][:y])
51
+ end
52
+ end
53
+
54
+ if !self.size
55
+ view.sizeToFit
56
+ end
57
+
58
+ Dispatch::Queue.main.async do
59
+ self.on_ready(true)
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,60 @@
1
+ =begin
2
+ {
3
+ type: :move,
4
+ id: :one
5
+ }
6
+ =end
7
+
8
+ module Walt
9
+ module Operation
10
+ class Base
11
+ extend Walt::Support::AttrDefault
12
+
13
+ PROPERTIES = [:id, :type]
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
+ def setup(view, animation)
25
+ # do initial before animation
26
+ end
27
+
28
+ def finalize(view, animation = nil)
29
+ # do whatever occurs during the animation
30
+ end
31
+ end
32
+
33
+ module_function
34
+ def for(hash)
35
+ # Check classes in module for corresponding operation
36
+ type = hash[:type] || hash["type"]
37
+
38
+ # Check for the form {operation_type: :id}
39
+ if !type
40
+ type = (hash.keys.map(&:to_s) | self.operation_types)[0]
41
+ hash[:id] = (hash[type] || hash[type.to_sym])
42
+ hash[:type] = type
43
+ end
44
+
45
+ if type.is_a?(Symbol) || type.is_a?(String)
46
+ string = "#{type.to_s.downcase}_operation".camelize
47
+ if not const_defined? string
48
+ raise "Invalid Operation value for operation #{hash.inspect}. Create a class called #{string}."
49
+ end
50
+ return Walt::Operation.const_get(string).new(hash)
51
+ end
52
+
53
+ self.new(hash)
54
+ end
55
+
56
+ def operation_types
57
+ Walt::Operation.constants(false).select { |constant_name| constant_name =~ /Operation$/ }.collect! { |op| op.to_s.gsub("Operation", "").underscore }
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,35 @@
1
+ =begin
2
+ {
3
+ from: 0.0,
4
+ to: 0.8
5
+ }
6
+ =end
7
+
8
+ module Walt
9
+ module Operation
10
+ class FadeOperation < Base
11
+ PROPERTIES = [:from, :to]
12
+ attr_accessor *PROPERTIES
13
+
14
+ def initialize(params = {})
15
+ super
16
+
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
+ def setup(view, animation)
25
+ if self.from
26
+ view.alpha = self.from
27
+ end
28
+ end
29
+
30
+ def finalize(view, animation)
31
+ view.alpha = self.to
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,73 @@
1
+ =begin
2
+ {
3
+ from: [0, 0],
4
+ to: [10, 20]
5
+ }
6
+
7
+ {
8
+ from: 100,
9
+ to: 200,
10
+ axis: :y
11
+ }
12
+ =end
13
+
14
+ module Walt
15
+ module Operation
16
+ class MoveOperation < Base
17
+ PROPERTIES = [:from, :to, :axis]
18
+ attr_accessor *PROPERTIES
19
+
20
+ attr_default :axis, :x
21
+
22
+ def initialize(params = {})
23
+ super
24
+
25
+ if axis = (params[:axis] || params["axis"])
26
+ self.axis = axis
27
+ end
28
+
29
+ params.each do |key, value|
30
+ if PROPERTIES.include?(key.to_sym)
31
+ self.send("#{key}=", value)
32
+ end
33
+ end
34
+ end
35
+
36
+ ["from", "to"].each do |point|
37
+ define_method("#{point}=") do |new_point|
38
+ _point = new_point
39
+ case new_point
40
+ when Numeric
41
+ if self.axis.to_sym == :x
42
+ _point = [new_point, nil]
43
+ else
44
+ _point = [nil, new_point]
45
+ end
46
+ when CGPoint
47
+ _point = [new_point.x, new_point.y]
48
+ when NSArray
49
+ else
50
+ raise "Invalid class for #{point}=: #{new_point.inspect}"
51
+ end
52
+ instance_variable_set("@#{point}", _point)
53
+ end
54
+ end
55
+
56
+ def setup(view, animation)
57
+ if self.from
58
+ origin = view.frame.origin
59
+ origin.x = (self.from[0] || origin.x)
60
+ origin.y = (self.from[1] || origin.y)
61
+ view.frame = [origin, view.frame.size]
62
+ end
63
+ end
64
+
65
+ def finalize(view, animation)
66
+ origin = view.frame.origin
67
+ origin.x = (self.to[0] || origin.x)
68
+ origin.y = (self.to[1] || origin.y)
69
+ view.frame = [origin, view.frame.size]
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+ =begin
2
+ {
3
+ from: 0,
4
+ to: 45
5
+ }
6
+ =end
7
+
8
+ module Walt
9
+ module Operation
10
+ class RotateOperation < Base
11
+ PROPERTIES = [:from, :to]
12
+ attr_accessor *PROPERTIES
13
+
14
+ def initialize(params = {})
15
+ super
16
+
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
+ def finalize(view, animation)
25
+ rotate = CABasicAnimation.animationWithKeyPath("transform.rotation")
26
+
27
+ from = self.from || view.instance_variable_get("@__last_rotation") || 0
28
+ rotate.fromValue = NSNumber.numberWithFloat(from)
29
+
30
+ rotate.toValue = NSNumber.numberWithFloat(self.to * Math::PI / 180)
31
+ view.instance_variable_set("@__last_rotation", rotate.toValue.to_f)
32
+
33
+ rotate.duration = animation.duration
34
+ rotate.removedOnCompletion = false
35
+ rotate.fillMode = KCAFillModeForwards
36
+
37
+ view.layer.addAnimation(rotate, forKey:nil)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,41 @@
1
+ =begin
2
+ {
3
+ from: 1.0,
4
+ to: 1.2
5
+ }
6
+ =end
7
+
8
+ module Walt
9
+ module Operation
10
+ class ScaleOperation < Base
11
+ PROPERTIES = [:from, :to]
12
+ attr_accessor *PROPERTIES
13
+
14
+ def initialize(params = {})
15
+ super
16
+
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
+ def finalize(view, animation)
25
+ scale = CABasicAnimation.animationWithKeyPath("transform.scale")
26
+
27
+ from = self.from || view.instance_variable_get("@__last_scale") || 1.0
28
+ scale.fromValue = NSNumber.numberWithFloat(from)
29
+
30
+ scale.toValue = NSNumber.numberWithFloat(self.to)
31
+ view.instance_variable_set("@__last_scale", scale.toValue.to_f)
32
+
33
+ scale.duration = animation.duration
34
+ scale.removedOnCompletion = false
35
+ scale.fillMode = KCAFillModeForwards
36
+
37
+ view.layer.addAnimation(scale, forKey:nil)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,5 @@
1
+ class UIColor
2
+ def to_color
3
+ self
4
+ end
5
+ end
@@ -0,0 +1,16 @@
1
+ module Walt
2
+ module Support
3
+ module AttrDefault
4
+ def attr_default(attribute, default)
5
+ attr_accessor attribute
6
+ define_method(attribute) do
7
+ ivar = "@#{attribute}"
8
+ if !instance_variable_defined?(ivar)
9
+ instance_variable_set(ivar, default)
10
+ end
11
+ instance_variable_get(ivar)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,60 @@
1
+ module Walt
2
+ module Support
3
+ module_function
4
+
5
+ =begin
6
+ Constant.for("UIViewAnimationOption", value)
7
+ =end
8
+
9
+ def constant(base, value)
10
+ return value if value.is_a? Numeric
11
+ value = value.to_s.camelize
12
+ Kernel.const_get("#{base}#{value}")
13
+ end
14
+
15
+ private
16
+ def hack
17
+ [
18
+ UIViewAnimationOptionLayoutSubviews,
19
+ UIViewAnimationOptionAllowUserInteraction,
20
+ UIViewAnimationOptionBeginFromCurrentState,
21
+ UIViewAnimationOptionRepeat,
22
+ UIViewAnimationOptionAutoreverse,
23
+ UIViewAnimationOptionOverrideInheritedDuration,
24
+ UIViewAnimationOptionOverrideInheritedCurve,
25
+ UIViewAnimationOptionAllowAnimatedContent,
26
+ UIViewAnimationOptionShowHideTransitionViews,
27
+ UIViewAnimationOptionCurveEaseInOut,
28
+ UIViewAnimationOptionCurveEaseIn,
29
+ UIViewAnimationOptionCurveEaseOut,
30
+ UIViewAnimationOptionCurveLinear,
31
+ UIViewAnimationOptionTransitionNone,
32
+ UIViewAnimationOptionTransitionFlipFromLeft,
33
+ UIViewAnimationOptionTransitionFlipFromRight,
34
+ UIViewAnimationOptionTransitionCurlUp,
35
+ UIViewAnimationOptionTransitionCurlDown,
36
+ UIViewAnimationOptionTransitionCrossDissolve,
37
+ UIViewAnimationOptionTransitionFlipFromTop,
38
+ UIViewAnimationOptionTransitionFlipFromBottom,
39
+
40
+ UIViewContentModeScaleToFill,
41
+ UIViewContentModeScaleAspectFit,
42
+ UIViewContentModeScaleAspectFill,
43
+ UIViewContentModeRedraw,
44
+ UIViewContentModeCenter,
45
+ UIViewContentModeTop,
46
+ UIViewContentModeBottom,
47
+ UIViewContentModeLeft,
48
+ UIViewContentModeRight,
49
+ UIViewContentModeTopLeft,
50
+ UIViewContentModeTopRight,
51
+ UIViewContentModeBottomLeft,
52
+ UIViewContentModeBottomRight,
53
+
54
+ UITextAlignmentLeft,
55
+ UITextAlignmentRight,
56
+ UITextAlignmentCenter
57
+ ]
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,87 @@
1
+ module Walt
2
+ module Font
3
+ module_function
4
+
5
+ def bold(size)
6
+ Font.make(:bold, size)
7
+ end
8
+
9
+ def system(size)
10
+ Font.make(:system, size)
11
+ end
12
+
13
+ def italic(size)
14
+ Font.make(:italic, size)
15
+ end
16
+
17
+ # Create font with params:
18
+ # String => The name of the font
19
+ # Hash => {
20
+ # size: Integer,
21
+ # name: String (see above)
22
+ # }
23
+ def make(params = {}, *args)
24
+ if params.is_a?(UIFont)
25
+ return params
26
+ end
27
+
28
+ _font = nil
29
+ if params.is_a?(NSString)
30
+ params = {name: params}
31
+ end
32
+ if args && args[0]
33
+ params.merge!({size: args[0]})
34
+ end
35
+ params[:size] ||= UIFont.systemFontSize
36
+ if [:system, :bold, :italic].member?(params[:name])
37
+ case params[:name]
38
+ when :system
39
+ _font = UIFont.systemFontOfSize(params[:size].to_f)
40
+ when :bold
41
+ _font = UIFont.boldSystemFontOfSize(params[:size].to_f)
42
+ when :italic
43
+ _font = UIFont.italicSystemFontOfSize(params[:size].to_f)
44
+ end
45
+ end
46
+
47
+ if !_font
48
+ begin
49
+ _font = UIFont.fontWithName(params[:name], size: params[:size])
50
+ rescue
51
+ end
52
+ end
53
+
54
+ if !_font
55
+ raise "Invalid font for parameters: #{params.inspect} args #{args.inspect}"
56
+ end
57
+
58
+ _font
59
+ end
60
+
61
+ # Create font attributes with keys:
62
+ # {
63
+ # font: String or Hash (see Font.make),
64
+ # color: String,
65
+ # shadow_color: String,
66
+ # shadow_offset: {
67
+ # x: Integer,
68
+ # y: Integer
69
+ # }
70
+ # }
71
+ def attributes(params = {})
72
+ _attributes = {}
73
+
74
+ _attributes[UITextAttributeFont] = Font.make(params[:font]) if params[:font]
75
+ _attributes[UITextAttributeTextColor] = params[:color].to_color if params[:color]
76
+ _attributes[UITextAttributeTextShadowColor] = params[:shadow_color].to_color if params[:shadow_color]
77
+ _attributes[UITextAttributeTextShadowOffset] = begin
78
+ x = params[:shadow_offset][:x]
79
+ y = params[:shadow_offset][:y]
80
+ offset = UIOffsetMake(x,y)
81
+ NSValue.valueWithUIOffset(offset)
82
+ end if params[:shadow_offset]
83
+
84
+ _attributes
85
+ end
86
+ end
87
+ end