motion-wizard 0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +74 -0
- data/Rakefile +1 -0
- data/lib/motion-wizard.rb +9 -0
- data/lib/motion-wizard/animation_strategy/base_animation_strategy.rb +25 -0
- data/lib/motion-wizard/animation_strategy/ios7_slide_left_to_right.rb +18 -0
- data/lib/motion-wizard/animation_strategy/ios7_slide_right_to_left.rb +18 -0
- data/lib/motion-wizard/animation_strategy/left_to_right.rb +10 -0
- data/lib/motion-wizard/animation_strategy/none.rb +11 -0
- data/lib/motion-wizard/animation_strategy/right_to_left.rb +10 -0
- data/lib/motion-wizard/animation_strategy/slide_animation.rb +21 -0
- data/lib/motion-wizard/controllers/content_controller.rb +17 -0
- data/lib/motion-wizard/controllers/wizard_view_controller.rb +143 -0
- data/lib/motion-wizard/lib/forwardable.rb +12 -0
- data/lib/motion-wizard/views/index_item_view.rb +53 -0
- data/lib/motion-wizard/views/wizard_navigation_bar.rb +55 -0
- data/motion-wizard.gemspec +22 -0
- data/samples/wizard-1/.gitignore +16 -0
- data/samples/wizard-1/Gemfile +8 -0
- data/samples/wizard-1/Rakefile +18 -0
- data/samples/wizard-1/app/app_delegate.rb +8 -0
- data/samples/wizard-1/app/controllers/steps_view_controller.rb +92 -0
- data/samples/wizard-1/app/controllers/wizard_1_view_controller.rb +28 -0
- data/samples/wizard-1/app/views/styles/steps.rb +128 -0
- data/samples/wizard-1/app/views/styles/wizard_1_view_controller.rb +42 -0
- data/samples/wizard-1/resources/Default-568h@2x.png +0 -0
- data/samples/wizard-1/spec/main_spec.rb +9 -0
- data/samples/wizard-2/.gitignore +16 -0
- data/samples/wizard-2/Gemfile +8 -0
- data/samples/wizard-2/Rakefile +22 -0
- data/samples/wizard-2/app/app_delegate.rb +10 -0
- data/samples/wizard-2/app/controllers/steps_view_controller.rb +59 -0
- data/samples/wizard-2/app/controllers/wizard_2_view_controller.rb +29 -0
- data/samples/wizard-2/app/views/my_custom_index_item_view.rb +25 -0
- data/samples/wizard-2/app/views/styles/handlers.rb +7 -0
- data/samples/wizard-2/app/views/styles/index_item.rb +36 -0
- data/samples/wizard-2/app/views/styles/steps.rb +67 -0
- data/samples/wizard-2/app/views/styles/wizard_view_controller.rb +4 -0
- data/samples/wizard-2/resources/Default-568h@2x.png +0 -0
- data/samples/wizard-2/resources/background-568h@2x.png +0 -0
- data/samples/wizard-2/resources/background.png +0 -0
- data/samples/wizard-2/resources/background@2x.png +0 -0
- data/samples/wizard-2/resources/button.png +0 -0
- data/samples/wizard-2/spec/main_spec.rb +9 -0
- data/wizard-1.gif +0 -0
- data/wizard-2.gif +0 -0
- metadata +120 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module MotionWizard
|
2
|
+
class IndexItem < UIView
|
3
|
+
attr_reader :label, :label_wrapper
|
4
|
+
|
5
|
+
def init
|
6
|
+
super
|
7
|
+
create_label
|
8
|
+
create_label_wrapper
|
9
|
+
@label_wrapper.addSubview(@label)
|
10
|
+
addSubview(@label_wrapper)
|
11
|
+
|
12
|
+
initialize_callbacks
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_label
|
17
|
+
@label = UILabel.alloc.init
|
18
|
+
@label.textAlignment = NSTextAlignmentCenter
|
19
|
+
@label.origin = [0, 0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_label_wrapper
|
23
|
+
@label_wrapper = UIView.alloc.init
|
24
|
+
@label_wrapper.origin = [0, 0]
|
25
|
+
@label_wrapper.backgroundColor = UIColor.clearColor
|
26
|
+
end
|
27
|
+
|
28
|
+
def initialize_callbacks
|
29
|
+
when_selected do
|
30
|
+
@original_text = @label.text
|
31
|
+
@label.text = "[#{@label.text}]"
|
32
|
+
end
|
33
|
+
|
34
|
+
when_unselected { @label.text = @original_text}
|
35
|
+
end
|
36
|
+
|
37
|
+
def when_selected(&block)
|
38
|
+
@when_selected = block
|
39
|
+
end
|
40
|
+
|
41
|
+
def when_unselected(&block)
|
42
|
+
@when_unselected = block
|
43
|
+
end
|
44
|
+
|
45
|
+
def select
|
46
|
+
@when_selected.call
|
47
|
+
end
|
48
|
+
|
49
|
+
def unselect
|
50
|
+
@when_unselected.call
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module MotionWizard
|
2
|
+
class WizardNavigationBar < UIView
|
3
|
+
def init_with_number_of_steps(number_of_steps, wizard_controller)
|
4
|
+
self.init
|
5
|
+
@number_of_steps = number_of_steps
|
6
|
+
@index_items = []
|
7
|
+
@wizard_controller = WeakRef.new(wizard_controller)
|
8
|
+
create_index_items
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
def create_index_items
|
13
|
+
@number_of_steps.times do |i|
|
14
|
+
index_item = @wizard_controller.create_index_item_at(i)
|
15
|
+
@index_items << index_item
|
16
|
+
addSubview(index_item)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def select(index)
|
21
|
+
@index_items[@selected_step].unselect if @selected_step && @index_items[@selected_step].respond_to?(:unselect)
|
22
|
+
@selected_step = index
|
23
|
+
@index_items[@selected_step].select if @selected_step && @index_items[@selected_step].respond_to?(:select)
|
24
|
+
end
|
25
|
+
|
26
|
+
def setFrame(frame)
|
27
|
+
super
|
28
|
+
resize_indexes
|
29
|
+
end
|
30
|
+
|
31
|
+
def reset!
|
32
|
+
remove_all_index_items
|
33
|
+
create_index_items
|
34
|
+
resize_indexes
|
35
|
+
end
|
36
|
+
|
37
|
+
def remove_all_index_items
|
38
|
+
@index_items.each{|i| i.removeFromSuperview}
|
39
|
+
@index_items.clear
|
40
|
+
end
|
41
|
+
|
42
|
+
def resize_indexes
|
43
|
+
return unless @number_of_steps
|
44
|
+
index_width = (self.frame.size.width).to_f / @number_of_steps
|
45
|
+
@index_items.each_with_index do |index_item, i|
|
46
|
+
index_item.frame = [[index_width*i, 0], [index_width, self.size.height]]
|
47
|
+
setup_index_item_at(index_item, i)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def setup_index_item_at(index_item, i)
|
52
|
+
@wizard_controller.setup_index_item_at(index_item, i)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "motion-wizard"
|
7
|
+
spec.version = "0.1"
|
8
|
+
spec.authors = ["Ignacio Piantanida"]
|
9
|
+
spec.email = ["ijpiantanida@gmail.com"]
|
10
|
+
spec.description = "An small library to create wizard like views controllers"
|
11
|
+
spec.summary = "An small library to create wizard like views"
|
12
|
+
spec.homepage = "https://github.com/ijpiantanida/motion-wizard"
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files`.split($/)
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
21
|
+
spec.add_development_dependency "rake"
|
22
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
$:.unshift("/Library/RubyMotion/lib")
|
3
|
+
require 'motion/project/template/ios'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'bundler'
|
7
|
+
Bundler.require
|
8
|
+
require 'sugarcube-repl'
|
9
|
+
require 'sugarcube-color'
|
10
|
+
require 'sugarcube-events'
|
11
|
+
require 'sugarcube-constants'
|
12
|
+
rescue LoadError
|
13
|
+
end
|
14
|
+
|
15
|
+
Motion::Project::App.setup do |app|
|
16
|
+
# Use `rake config' to see complete project settings.
|
17
|
+
app.name = 'wizard-1'
|
18
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class AppDelegate
|
2
|
+
def application(application, didFinishLaunchingWithOptions: launchOptions)
|
3
|
+
@window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
|
4
|
+
@window.rootViewController = Wizard1ViewController.alloc.init
|
5
|
+
@window.makeKeyAndVisible
|
6
|
+
true
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class Step1ViewController < UIViewController
|
2
|
+
stylesheet :step_1
|
3
|
+
|
4
|
+
layout :step do
|
5
|
+
@text_field = subview(UITextField, :text_field)
|
6
|
+
@button = subview(UIButton, :button)
|
7
|
+
end
|
8
|
+
|
9
|
+
def viewWillAppear(animated)
|
10
|
+
super
|
11
|
+
@button.on(:touch){ self.next(step_1_text: @text_field.text) }
|
12
|
+
end
|
13
|
+
|
14
|
+
def viewWillDisappear(animated)
|
15
|
+
super
|
16
|
+
@button.off(:touch)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Step2ViewController < UIViewController
|
21
|
+
stylesheet :step_2
|
22
|
+
|
23
|
+
layout :step do
|
24
|
+
@text_field = subview(UITextField, :text_field)
|
25
|
+
@next_button = subview(UIButton, :next_button)
|
26
|
+
@back_button = subview(UIButton, :back_button)
|
27
|
+
end
|
28
|
+
|
29
|
+
def viewWillAppear(animated)
|
30
|
+
super
|
31
|
+
@next_button.on(:touch) {self.next(step_2_text: @text_field.text)}
|
32
|
+
@back_button.on(:touch) {self.previous}
|
33
|
+
end
|
34
|
+
|
35
|
+
def viewWillDisappear(animated)
|
36
|
+
super
|
37
|
+
@next_button.off(:touch)
|
38
|
+
@back_button.off(:touch)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class Step3ViewController < UIViewController
|
43
|
+
stylesheet :step_3
|
44
|
+
|
45
|
+
layout :step do
|
46
|
+
subview(UILabel, :label)
|
47
|
+
@next_button = subview(UIButton, :next_button)
|
48
|
+
@back_button = subview(UIButton, :back_button)
|
49
|
+
end
|
50
|
+
|
51
|
+
def viewWillAppear(animated)
|
52
|
+
super
|
53
|
+
@next_button.on(:touch) {self.next}
|
54
|
+
@back_button.on(:touch) {self.previous}
|
55
|
+
end
|
56
|
+
|
57
|
+
def viewWillDisappear(animated)
|
58
|
+
super
|
59
|
+
@next_button.off(:touch)
|
60
|
+
@back_button.off(:touch)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
class Step4ViewController < UIViewController
|
65
|
+
stylesheet :step_4
|
66
|
+
|
67
|
+
layout :step do
|
68
|
+
subview(UILabel, :label)
|
69
|
+
@step_1_data = subview(UILabel, :step_1_data)
|
70
|
+
@step_2_data = subview(UILabel, :step_2_data)
|
71
|
+
@reset_button = subview(UIButton, :reset_button)
|
72
|
+
@finish_button = subview(UIButton, :finish_button)
|
73
|
+
@start_over_button = subview(UIButton, :start_over_button)
|
74
|
+
end
|
75
|
+
|
76
|
+
def viewWillAppear(animated)
|
77
|
+
super
|
78
|
+
@step_1_data.text = "Step 1: #{self.wizard_data[:step_1_text]}"
|
79
|
+
@step_2_data.text = "Step 2: #{self.wizard_data[:step_2_text]}"
|
80
|
+
|
81
|
+
@start_over_button.on(:touch) {self.go_to_step(0)}
|
82
|
+
@reset_button.on(:touch) {self.reset!}
|
83
|
+
@finish_button.on(:touch) {self.next}
|
84
|
+
end
|
85
|
+
|
86
|
+
def viewWillDisappear(animated)
|
87
|
+
super
|
88
|
+
@start_over_button.off(:touch)
|
89
|
+
@reset_button.off(:touch)
|
90
|
+
@finish_button.off(:touch)
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Wizard1ViewController < MotionWizard::WizardViewController
|
2
|
+
steps Step1ViewController,
|
3
|
+
Step2ViewController,
|
4
|
+
Step3ViewController,
|
5
|
+
Step4ViewController
|
6
|
+
|
7
|
+
stylesheet :wizard_view_controller
|
8
|
+
|
9
|
+
layout :wizard_view_controller
|
10
|
+
|
11
|
+
def setup_index_item_at(index_item, index)
|
12
|
+
layout(index_item, :index_item)
|
13
|
+
index_item.when_selected{ index_item.animate_to_stylename(:index_item_selected) }
|
14
|
+
index_item.when_unselected do
|
15
|
+
UIView.animateWithDuration(0.5,
|
16
|
+
animations: -> {
|
17
|
+
layout(index_item, :index_item)
|
18
|
+
}, completion: ->(_){
|
19
|
+
layout(index_item, :index_item_unselected)
|
20
|
+
})
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def when_finished
|
26
|
+
App.alert("Now you can do whatever you like with this #{wizard_data}")
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
Teacup::Stylesheet.new :steps do
|
2
|
+
style :step,
|
3
|
+
backgroundColor: :white.uicolor
|
4
|
+
|
5
|
+
style :big_button,
|
6
|
+
size: ["100% - 40", 35],
|
7
|
+
center_x: "50%",
|
8
|
+
backgroundColor: [103,189,71].uicolor
|
9
|
+
|
10
|
+
end
|
11
|
+
|
12
|
+
Teacup::Stylesheet.new :step_1 do
|
13
|
+
import :steps
|
14
|
+
|
15
|
+
style :text_field,
|
16
|
+
placeholder: "Put some text here",
|
17
|
+
size: ["100% - 40", 35],
|
18
|
+
top: 130,
|
19
|
+
center_x: "50%",
|
20
|
+
textAlignment: NSTextAlignmentCenter,
|
21
|
+
contentVerticalAlignment: UIControlContentVerticalAlignmentCenter,
|
22
|
+
layer: {
|
23
|
+
borderWidth: 1,
|
24
|
+
cornerRadius: 5
|
25
|
+
}
|
26
|
+
|
27
|
+
style :button,
|
28
|
+
extends: :big_button,
|
29
|
+
title: "And tap here...",
|
30
|
+
top: 180
|
31
|
+
end
|
32
|
+
|
33
|
+
Teacup::Stylesheet.new :step_2 do
|
34
|
+
import :steps
|
35
|
+
|
36
|
+
style :text_field,
|
37
|
+
placeholder: "Also add some text here",
|
38
|
+
size: ["100% - 40", 35],
|
39
|
+
top: 130,
|
40
|
+
center_x: "50%",
|
41
|
+
textAlignment: NSTextAlignmentCenter,
|
42
|
+
contentVerticalAlignment: UIControlContentVerticalAlignmentCenter,
|
43
|
+
layer: {
|
44
|
+
borderWidth: 1,
|
45
|
+
cornerRadius: 5
|
46
|
+
}
|
47
|
+
|
48
|
+
style :base_button,
|
49
|
+
size: ["50% - 40", 35],
|
50
|
+
backgroundColor: [103,189,71].uicolor
|
51
|
+
|
52
|
+
style :next_button,
|
53
|
+
extends: :base_button,
|
54
|
+
title: ">",
|
55
|
+
origin: ["50% + 10", 180]
|
56
|
+
|
57
|
+
style :back_button,
|
58
|
+
extends: :base_button,
|
59
|
+
title: "<",
|
60
|
+
origin: [20, 180]
|
61
|
+
end
|
62
|
+
|
63
|
+
Teacup::Stylesheet.new :step_3 do
|
64
|
+
import :steps
|
65
|
+
|
66
|
+
style :label,
|
67
|
+
text: "Not much to do around here",
|
68
|
+
size: ["100% - 40", 35],
|
69
|
+
top: 130,
|
70
|
+
center_x: "50%",
|
71
|
+
textAlignment: NSTextAlignmentCenter,
|
72
|
+
textColor: [103,189,71].uicolor
|
73
|
+
|
74
|
+
style :base_button,
|
75
|
+
size: ["50% - 40", 35],
|
76
|
+
backgroundColor: [103,189,71].uicolor
|
77
|
+
|
78
|
+
style :next_button,
|
79
|
+
extends: :base_button,
|
80
|
+
title: ">",
|
81
|
+
origin: ["50% + 10", 180]
|
82
|
+
|
83
|
+
style :back_button,
|
84
|
+
extends: :base_button,
|
85
|
+
title: "<",
|
86
|
+
origin: [20, 180]
|
87
|
+
end
|
88
|
+
|
89
|
+
Teacup::Stylesheet.new :step_4 do
|
90
|
+
import :steps
|
91
|
+
|
92
|
+
style :label,
|
93
|
+
text: "End of the journey",
|
94
|
+
size: ["100% - 40", 35],
|
95
|
+
top: 130,
|
96
|
+
center_x: "50%",
|
97
|
+
textAlignment: NSTextAlignmentCenter,
|
98
|
+
textColor: [103,189,71].uicolor
|
99
|
+
|
100
|
+
style :data,
|
101
|
+
size: ["100% - 40", 35],
|
102
|
+
center_x: "50%",
|
103
|
+
textAlignment: NSTextAlignmentCenter,
|
104
|
+
textColor: [103,189,71].uicolor
|
105
|
+
|
106
|
+
style :step_1_data,
|
107
|
+
extends: :data,
|
108
|
+
top: 180
|
109
|
+
|
110
|
+
style :step_2_data,
|
111
|
+
extends: :data,
|
112
|
+
top: 220
|
113
|
+
|
114
|
+
style :reset_button,
|
115
|
+
extends: :big_button,
|
116
|
+
title: "Reset!",
|
117
|
+
top: 320
|
118
|
+
|
119
|
+
style :start_over_button,
|
120
|
+
extends: :big_button,
|
121
|
+
title: "Start over!",
|
122
|
+
top: 360
|
123
|
+
|
124
|
+
style :finish_button,
|
125
|
+
extends: :big_button,
|
126
|
+
title: "Finish",
|
127
|
+
top: 400
|
128
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
Teacup::Stylesheet.new :wizard_view_controller do
|
2
|
+
style :wizard_view_controller,
|
3
|
+
backgroundColor: :white.uicolor
|
4
|
+
|
5
|
+
style :index_item,
|
6
|
+
height: 10,
|
7
|
+
center_y: "100%",
|
8
|
+
backgroundColor: [103,189,71].uicolor,
|
9
|
+
label_wrapper:{
|
10
|
+
backgroundColor: [103,189,71].uicolor,
|
11
|
+
size: [50, 50],
|
12
|
+
center: ["50%", "50%"],
|
13
|
+
layer: {
|
14
|
+
cornerRadius: 25
|
15
|
+
}
|
16
|
+
},
|
17
|
+
label: {
|
18
|
+
backgroundColor: :clear.uicolor,
|
19
|
+
textColor: :white.uicolor,
|
20
|
+
size: ["100%", 20],
|
21
|
+
center: ["50%", "50%"]
|
22
|
+
}
|
23
|
+
|
24
|
+
style :index_item_unseleted,
|
25
|
+
extends: :index_item,
|
26
|
+
layer: {
|
27
|
+
borderWidth: 0
|
28
|
+
}
|
29
|
+
|
30
|
+
style :index_item_selected,
|
31
|
+
label_wrapper:{
|
32
|
+
backgroundColor: :white.uicolor,
|
33
|
+
layer: {
|
34
|
+
borderWidth: 2,
|
35
|
+
borderColor: [103,189,71].uicolor.CGColor
|
36
|
+
}
|
37
|
+
},
|
38
|
+
label: {
|
39
|
+
textColor: [103,189,71].uicolor
|
40
|
+
}
|
41
|
+
|
42
|
+
end
|