ProMotion-XLForm 0.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.
- checksums.yaml +7 -0
- data/README.md +227 -0
- data/lib/ProMotion-XLForm.rb +22 -0
- data/lib/ProMotion/XLForm/cells/xl_form_image_selector_cell.rb +227 -0
- data/lib/ProMotion/XLForm/value_transformer.rb +18 -0
- data/lib/ProMotion/XLForm/xl_form.rb +232 -0
- data/lib/ProMotion/XLForm/xl_form_class_methods.rb +11 -0
- data/lib/ProMotion/XLForm/xl_form_module.rb +9 -0
- data/lib/ProMotion/XLForm/xl_form_patch.rb +29 -0
- data/lib/ProMotion/XLForm/xl_form_screen.rb +168 -0
- data/lib/ProMotion/XLForm/xl_form_view_controller.rb +54 -0
- data/lib/ProMotion/XLForm/xl_sub_form_screen.rb +43 -0
- metadata +111 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: b72f5d70e733afcd851aff9900f8b13b19fbed0b
|
|
4
|
+
data.tar.gz: 2b63d7b46c59924fb9839f45e2f358a135f34028
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 341ac2b44c3f2f74cf667351d087d6ee239ef4237fe5fb690c8dd4736ff941c23f164fb8c095e367230155c42b728ef36775b2a44fb9b3b757425da8ee92407f
|
|
7
|
+
data.tar.gz: 63926ccbdea5af6926c5f75de41415d6eae24b797421f29c7e4aafe508d34628bf859532ea49aa02572994b08423816d35e33c1398017570e6ab6aa9d8a9d1c0
|
data/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# ProMotion-XLForm
|
|
2
|
+
|
|
3
|
+
ProMotion-XLForm provides a PM::XLFormScreen for [ProMotion](https://github.com/clearsightstudio/ProMotion) powered by the CocoaPod [XLForm](https://github.com/xmartlabs/XLForm).
|
|
4
|
+
|
|
5
|
+
## Warning
|
|
6
|
+
This gem is currently in very early-stage. Use it at your own risk :)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```ruby
|
|
11
|
+
gem 'ProMotion-form'
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Then:
|
|
15
|
+
|
|
16
|
+
```sh-session
|
|
17
|
+
$ bundle
|
|
18
|
+
$ rake pod:install
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
`PM::XLFormScreen` include `PM::ScreenModule` so you'll have all ProMotion methods available.
|
|
24
|
+
|
|
25
|
+
To create a form, create a new `PM::XLFormScreen` and implement `form_data`.
|
|
26
|
+
|
|
27
|
+
```ruby
|
|
28
|
+
class TestFormScreen < PM::XLFormScreen
|
|
29
|
+
def form_data
|
|
30
|
+
[
|
|
31
|
+
{
|
|
32
|
+
title: 'Account information',
|
|
33
|
+
cells: [
|
|
34
|
+
{
|
|
35
|
+
title: 'Email',
|
|
36
|
+
name: :email,
|
|
37
|
+
type: :email,
|
|
38
|
+
placeholder: 'Enter your email',
|
|
39
|
+
required: true
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
title: 'Name',
|
|
43
|
+
name: :name,
|
|
44
|
+
type: :text,
|
|
45
|
+
value: 'Default value'
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
title: 'Sex',
|
|
49
|
+
name: :sex,
|
|
50
|
+
type: :selector_push,
|
|
51
|
+
options: {
|
|
52
|
+
male: 'Male',
|
|
53
|
+
female: 'Female',
|
|
54
|
+
other: 'Other'
|
|
55
|
+
}
|
|
56
|
+
]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Available types
|
|
64
|
+
* :text
|
|
65
|
+
* :name
|
|
66
|
+
* :url
|
|
67
|
+
* :email
|
|
68
|
+
* :password
|
|
69
|
+
* :number
|
|
70
|
+
* :phone
|
|
71
|
+
* :twitter
|
|
72
|
+
* :account
|
|
73
|
+
* :integer
|
|
74
|
+
* :decimal
|
|
75
|
+
* :textview
|
|
76
|
+
* :selector_push
|
|
77
|
+
* :selector_popover
|
|
78
|
+
* :selector_action_sheet
|
|
79
|
+
* :selector_alert_view
|
|
80
|
+
* :selector_picker_view
|
|
81
|
+
* :selector_picker_view_inline
|
|
82
|
+
* :multiple_selector
|
|
83
|
+
* :multiple_selector_popover
|
|
84
|
+
* :selector_left_right
|
|
85
|
+
* :selector_segmented_control
|
|
86
|
+
* :date_inline
|
|
87
|
+
* :datetime_inline
|
|
88
|
+
* :time_inline
|
|
89
|
+
* :countdown_timer_inline
|
|
90
|
+
* :date
|
|
91
|
+
* :datetime
|
|
92
|
+
* :time
|
|
93
|
+
* :countdown_timer
|
|
94
|
+
* :datepicker
|
|
95
|
+
* :picker
|
|
96
|
+
* :slider
|
|
97
|
+
* :check
|
|
98
|
+
* :switch
|
|
99
|
+
* :button
|
|
100
|
+
* :info
|
|
101
|
+
* :step_counter
|
|
102
|
+
* :image
|
|
103
|
+
|
|
104
|
+
### Class options
|
|
105
|
+
|
|
106
|
+
```ruby
|
|
107
|
+
class TestFormScreen < PM::XLFormScreen
|
|
108
|
+
|
|
109
|
+
form_options required: :asterisks, # add an asterisk to required fields
|
|
110
|
+
on_save: :'save_form:', # will be called when you touch save
|
|
111
|
+
on_cancel: :cancel_form # will be called when you touch cancel
|
|
112
|
+
|
|
113
|
+
def save_form(values)
|
|
114
|
+
mp values
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def cancel_form
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Getting values
|
|
123
|
+
|
|
124
|
+
You can get the values of your form with `values`. You can also get validation errors with `validation_errors` and check if the form is valid with `valid?`
|
|
125
|
+
|
|
126
|
+
### Events
|
|
127
|
+
|
|
128
|
+
`on_change`, `on_add` and `on_remove` are available for cells, `on_add` and `on_remove` are available for sections.
|
|
129
|
+
|
|
130
|
+
```ruby
|
|
131
|
+
{
|
|
132
|
+
title: 'Sex',
|
|
133
|
+
name: :sex,
|
|
134
|
+
type: :selector_push,
|
|
135
|
+
options: {
|
|
136
|
+
male: 'Male',
|
|
137
|
+
female: 'Female',
|
|
138
|
+
other: 'Other'
|
|
139
|
+
},
|
|
140
|
+
on_change: lambda do |old_value, new_value|
|
|
141
|
+
puts "Changed from #{old_value} to #{new_value}"
|
|
142
|
+
end
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### Multivalued Sections (Insert, Delete, Reorder rows)
|
|
147
|
+
|
|
148
|
+
```ruby
|
|
149
|
+
{
|
|
150
|
+
title: 'Multiple value',
|
|
151
|
+
name: :multi_values,
|
|
152
|
+
options: [:insert, :delete, :reorder],
|
|
153
|
+
cells: [
|
|
154
|
+
{
|
|
155
|
+
title: 'Add a new tag',
|
|
156
|
+
name: :tag,
|
|
157
|
+
type: :text
|
|
158
|
+
}
|
|
159
|
+
]
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
### Custom Selectors
|
|
164
|
+
|
|
165
|
+
You can create a custom _subform_ with a few options
|
|
166
|
+
|
|
167
|
+
```ruby
|
|
168
|
+
{
|
|
169
|
+
title: 'Custom',
|
|
170
|
+
name: :custom,
|
|
171
|
+
cells: [
|
|
172
|
+
{
|
|
173
|
+
title: 'Some text',
|
|
174
|
+
name: :some_text,
|
|
175
|
+
type: :text
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
title: 'Other text',
|
|
179
|
+
name: :some_other_text,
|
|
180
|
+
type: :text
|
|
181
|
+
}
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
By default, the cell will print a `Hash.inspect` of your _subcells_. You can change this by creating a valueTransformer and set `value_transformer:`.
|
|
187
|
+
|
|
188
|
+
```ruby
|
|
189
|
+
{
|
|
190
|
+
title: 'Custom',
|
|
191
|
+
name: :custom,
|
|
192
|
+
value_transformer: MyValueTransformer
|
|
193
|
+
cells: []
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
class MyValueTransformer < PM::ValueTransformer
|
|
197
|
+
def transformedValue(value)
|
|
198
|
+
return nil if value.nil?
|
|
199
|
+
|
|
200
|
+
str = []
|
|
201
|
+
str << value['some_text'] if value['some_text']
|
|
202
|
+
str << value['some_other_text'] if value['some_other_text']
|
|
203
|
+
|
|
204
|
+
str.join(',')
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
For a more advanced custom selector, you can set `view_controller_class:`. See [XLForm documentation](https://github.com/xmartlabs/XLForm/#custom-selectors---selector-row-with-a-custom-selector-view-controller) for more informations.
|
|
210
|
+
|
|
211
|
+
## Todo
|
|
212
|
+
- Validations
|
|
213
|
+
- Tests
|
|
214
|
+
- A lot of other things :)
|
|
215
|
+
|
|
216
|
+
## Contributing
|
|
217
|
+
|
|
218
|
+
1. Fork it
|
|
219
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
220
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
221
|
+
4. Make some specs pass
|
|
222
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
|
223
|
+
6. Create new Pull Request
|
|
224
|
+
|
|
225
|
+
## License
|
|
226
|
+
|
|
227
|
+
Released under the [MIT license](LICENSE).
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# encoding: utf-8
|
|
2
|
+
unless defined?(Motion::Project::Config)
|
|
3
|
+
raise "ProMotion-XLForm must be required within a RubyMotion project."
|
|
4
|
+
end
|
|
5
|
+
require 'motion-cocoapods'
|
|
6
|
+
|
|
7
|
+
Motion::Project::App.setup do |app|
|
|
8
|
+
lib_dir_path = File.dirname(File.expand_path(__FILE__))
|
|
9
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/cells/xl_form_image_selector_cell.rb")
|
|
10
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form_class_methods.rb")
|
|
11
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form_module.rb")
|
|
12
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form_view_controller.rb")
|
|
13
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form.rb")
|
|
14
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form_screen.rb")
|
|
15
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_sub_form_screen.rb")
|
|
16
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/xl_form_patch.rb")
|
|
17
|
+
app.files << File.join(lib_dir_path, "ProMotion/XLForm/value_transformer.rb")
|
|
18
|
+
|
|
19
|
+
app.pods do
|
|
20
|
+
pod 'XLForm', '~> 3.0.0'
|
|
21
|
+
end
|
|
22
|
+
end
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
class XLFormImageSelectorCell < XLFormBaseCell
|
|
2
|
+
|
|
3
|
+
attr_accessor :imageview, :text_label
|
|
4
|
+
|
|
5
|
+
def configure
|
|
6
|
+
super
|
|
7
|
+
@image_height = 100.0
|
|
8
|
+
@image_width = 100.0
|
|
9
|
+
self.selectionStyle = UITableViewCellSelectionStyleNone
|
|
10
|
+
self.backgroundColor = UIColor.whiteColor
|
|
11
|
+
self.separatorInset = UIEdgeInsetsZero
|
|
12
|
+
|
|
13
|
+
self.contentView.addSubview(imageview)
|
|
14
|
+
self.contentView.addSubview(text_label)
|
|
15
|
+
text_label.addObserver(self, forKeyPath: "text", options: NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew, context: 0)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def update
|
|
19
|
+
text_label.text = self.rowDescriptor.title
|
|
20
|
+
imageview.image = self.rowDescriptor.value
|
|
21
|
+
|
|
22
|
+
text_label.setFont(UIFont.preferredFontForTextStyle(UIFontTextStyleBody))
|
|
23
|
+
text_label.sizeToFit
|
|
24
|
+
updateConstraints
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.formDescriptorCellHeightForRowDescriptor(_)
|
|
28
|
+
120.0
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def formDescriptorCellDidSelectedWithFormController(controller)
|
|
32
|
+
if NSFoundationVersionNumber <= NSFoundationVersionNumber_iOS_7_1
|
|
33
|
+
alert = UIAlertController.alertControllerWithTitle(self.rowDescriptor.selectorTitle,
|
|
34
|
+
message: nil,
|
|
35
|
+
preferredStyle: UIAlertControllerStyleActionSheet)
|
|
36
|
+
|
|
37
|
+
alert.addAction(UIAlertAction.actionWithTitle(NSLocalizedString("Choose From Library", nil),
|
|
38
|
+
style: UIAlertActionStyleDefault,
|
|
39
|
+
handler: lambda { |_|
|
|
40
|
+
self.formViewController.dismissViewControllerAnimated(true,
|
|
41
|
+
completion: -> {
|
|
42
|
+
open_picker(UIImagePickerControllerSourceTypePhotoLibrary)
|
|
43
|
+
})
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceTypeCamera)
|
|
47
|
+
alert.addAction(UIAlertAction.actionWithTitle(NSLocalizedString("Take Photo", nil),
|
|
48
|
+
style: UIAlertActionStyleDefault,
|
|
49
|
+
handler: lambda { |_|
|
|
50
|
+
self.formViewController.dismissViewControllerAnimated(true,
|
|
51
|
+
completion: -> {
|
|
52
|
+
open_picker(UIImagePickerControllerSourceTypeCamera)
|
|
53
|
+
})
|
|
54
|
+
}))
|
|
55
|
+
end
|
|
56
|
+
if self.formViewController.presentedViewController
|
|
57
|
+
self.formViewController.dismissViewControllerAnimated(true,
|
|
58
|
+
completion: -> {
|
|
59
|
+
self.formViewController.presentViewController(alert, animated: true, completion: nil)
|
|
60
|
+
})
|
|
61
|
+
else
|
|
62
|
+
self.formViewController.presentViewController(alert, animated: true, completion: nil)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
else
|
|
66
|
+
if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceTypeCamera)
|
|
67
|
+
action_sheet = UIActionSheet.alloc.initWithTitle(self.rowDescriptor.selectorTitle,
|
|
68
|
+
delegate: self,
|
|
69
|
+
cancelButtonTitle: NSLocalizedString("Cancel", nil),
|
|
70
|
+
destructiveButtonTitle: nil,
|
|
71
|
+
otherButtonTitles: NSLocalizedString("Choose From Library", nil), NSLocalizedString("Take Photo", nil), nil)
|
|
72
|
+
else
|
|
73
|
+
action_sheet = UIActionSheet.alloc.initWithTitle(self.rowDescriptor.selectorTitle,
|
|
74
|
+
delegate: self,
|
|
75
|
+
cancelButtonTitle: NSLocalizedString("Cancel", nil),
|
|
76
|
+
destructiveButtonTitle: nil,
|
|
77
|
+
otherButtonTitles: NSLocalizedString("Choose From Library", nil), nil)
|
|
78
|
+
end
|
|
79
|
+
action_sheet.tag = self.tag
|
|
80
|
+
action_sheet.showInView(self.formViewController.view)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def updateConstraints
|
|
85
|
+
ui_components = { "image" => imageview, "text" => text_label }
|
|
86
|
+
|
|
87
|
+
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-16-[text]", options: 0, metrics: 0, views: ui_components))
|
|
88
|
+
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-6-[text]", options: 0, metrics: 0, views: ui_components))
|
|
89
|
+
|
|
90
|
+
self.contentView.addConstraint(NSLayoutConstraint.constraintWithItem(imageview,
|
|
91
|
+
attribute: NSLayoutAttributeTop,
|
|
92
|
+
relatedBy: NSLayoutRelationEqual,
|
|
93
|
+
toItem: self.contentView,
|
|
94
|
+
attribute: NSLayoutAttributeTop,
|
|
95
|
+
multiplier: 1.0,
|
|
96
|
+
constant: 10.0))
|
|
97
|
+
|
|
98
|
+
self.contentView.addConstraint(NSLayoutConstraint.constraintWithItem(imageview,
|
|
99
|
+
attribute: NSLayoutAttributeBottom,
|
|
100
|
+
relatedBy: NSLayoutRelationEqual,
|
|
101
|
+
toItem: self.contentView,
|
|
102
|
+
attribute: NSLayoutAttributeBottom,
|
|
103
|
+
multiplier: 1.0,
|
|
104
|
+
constant: -10.0))
|
|
105
|
+
|
|
106
|
+
self.contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[image(width)]", options: 0, metrics: { "width" => @image_width }, views: ui_components))
|
|
107
|
+
self.contentView.addConstraint(NSLayoutConstraint.constraintWithItem(imageview,
|
|
108
|
+
attribute: NSLayoutAttributeCenterX,
|
|
109
|
+
relatedBy: NSLayoutRelationEqual,
|
|
110
|
+
toItem: self.contentView,
|
|
111
|
+
attribute: NSLayoutAttributeCenterX,
|
|
112
|
+
multiplier: 1.0,
|
|
113
|
+
constant: 0.0))
|
|
114
|
+
super
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# trick to force the status bar to be hidden when presenting the UIImagePickerViewController
|
|
118
|
+
def navigationController(_, willShowViewController: _, animated: _)
|
|
119
|
+
UIApplication.sharedApplication.setStatusBarHidden true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def setImageValue(image)
|
|
123
|
+
self.rowDescriptor.value = image
|
|
124
|
+
imageview.image = image
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def observeValueForKeyPath(key_path, ofObject: object, change: change, context: _)
|
|
128
|
+
if object == text_label && key_path == "text"
|
|
129
|
+
if change[NSKeyValueChangeKindKey] == NSKeyValueChangeSetting
|
|
130
|
+
text_label.sizeToFit
|
|
131
|
+
frame = text_label.frame
|
|
132
|
+
frame.origin = [16, 4]
|
|
133
|
+
text_label.frame = frame
|
|
134
|
+
self.contentView.needsUpdateConstraints
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def dealloc
|
|
140
|
+
text_label.removeObserver(self, forKeyPath: "text")
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
# UIActionSheetDelegate
|
|
144
|
+
def actionSheet(action_sheet, clickedButtonAtIndex: button_index)
|
|
145
|
+
return if button_index == action_sheet.cancelButtonIndex
|
|
146
|
+
|
|
147
|
+
title = action_sheet.buttonTitleAtIndex(button_index)
|
|
148
|
+
|
|
149
|
+
case title
|
|
150
|
+
when NSLocalizedString("Choose From Library", nil)
|
|
151
|
+
open_picker(UIImagePickerControllerSourceTypePhotoLibrary)
|
|
152
|
+
when NSLocalizedString("Take Photo", nil)
|
|
153
|
+
open_picker(UIImagePickerControllerSourceTypeCamera)
|
|
154
|
+
else
|
|
155
|
+
return
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def open_picker(source)
|
|
160
|
+
image_picker = UIImagePickerController.alloc.init
|
|
161
|
+
image_picker.delegate = self
|
|
162
|
+
image_picker.allowsEditing = true
|
|
163
|
+
image_picker.sourceType = source
|
|
164
|
+
|
|
165
|
+
if UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad
|
|
166
|
+
if @popover_controller && @popover_controller.isPopoverVisible
|
|
167
|
+
@popover_controller.dismissPopoverAnimated(true)
|
|
168
|
+
end
|
|
169
|
+
@popover_controller = UIPopoverController.alloc.initWithContentViewController(image_picker)
|
|
170
|
+
Dispatch::Queue.main.async do
|
|
171
|
+
@popover_controller.presentPopoverFromRect(self.contentView.frame,
|
|
172
|
+
inView: self.formViewController.view,
|
|
173
|
+
permittedArrowDirections: UIPopoverArrowDirectionAny,
|
|
174
|
+
animated: true)
|
|
175
|
+
end
|
|
176
|
+
else
|
|
177
|
+
if self.formViewController.presentedViewController
|
|
178
|
+
self.formViewController.dismissViewControllerAnimated(true,
|
|
179
|
+
completion: -> {
|
|
180
|
+
self.formViewController.presentViewController(image_picker,
|
|
181
|
+
animated: true,
|
|
182
|
+
completion: nil)
|
|
183
|
+
})
|
|
184
|
+
else
|
|
185
|
+
self.formViewController.presentViewController(image_picker,
|
|
186
|
+
animated: true,
|
|
187
|
+
completion: nil)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# UIImagePickerControllerDelegate
|
|
193
|
+
def imagePickerController(_, didFinishPickingMediaWithInfo: info)
|
|
194
|
+
editedImage = info[UIImagePickerControllerEditedImage]
|
|
195
|
+
originalImage = info[UIImagePickerControllerOriginalImage]
|
|
196
|
+
if editedImage
|
|
197
|
+
imageToUse = editedImage
|
|
198
|
+
else
|
|
199
|
+
imageToUse = originalImage
|
|
200
|
+
end
|
|
201
|
+
setImageValue(imageToUse)
|
|
202
|
+
|
|
203
|
+
if UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad
|
|
204
|
+
if @popover_controller and @popover_controller.isPopoverVisible
|
|
205
|
+
@popover_controller.dismissPopoverAnimated(true)
|
|
206
|
+
end
|
|
207
|
+
else
|
|
208
|
+
self.formViewController.dismissViewControllerAnimated(true, completion: nil)
|
|
209
|
+
end
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
# Properties
|
|
213
|
+
def imageview
|
|
214
|
+
return @imageview if @imageview
|
|
215
|
+
|
|
216
|
+
@imageview = UIImageView.autolayoutView
|
|
217
|
+
@imageview.layer.masksToBounds = true
|
|
218
|
+
@imageview.contentMode = UIViewContentModeScaleAspectFit
|
|
219
|
+
@imageview
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def text_label
|
|
223
|
+
return @text_label if @text_label
|
|
224
|
+
@text_label = UILabel.autolayoutView
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
module ProMotion
|
|
2
|
+
class ValueTransformer
|
|
3
|
+
def self.transformedValueClass
|
|
4
|
+
NSString
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def self.allowsReverseTransformation
|
|
8
|
+
false
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def transformedValue(value)
|
|
12
|
+
return nil if value.nil?
|
|
13
|
+
|
|
14
|
+
# best effort
|
|
15
|
+
value.inspect
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
module ProMotion
|
|
2
|
+
class XLForm
|
|
3
|
+
|
|
4
|
+
attr_reader :form_data
|
|
5
|
+
|
|
6
|
+
def initialize(form_data, opts={})
|
|
7
|
+
@form_data = form_data
|
|
8
|
+
@title = opts[:title] || ''
|
|
9
|
+
@required = opts[:required]
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def build
|
|
13
|
+
form = XLFormDescriptor.formDescriptorWithTitle(@title)
|
|
14
|
+
form.addAsteriskToRequiredRowsTitle = (@required == :asterisks)
|
|
15
|
+
|
|
16
|
+
form_data.each do |section_data|
|
|
17
|
+
title = section_data[:title]
|
|
18
|
+
|
|
19
|
+
options = parse_section_options(section_data[:options])
|
|
20
|
+
insert_mode = section_insert_mode(section_data[:insert_mode])
|
|
21
|
+
|
|
22
|
+
section = XLFormSectionDescriptor.formSectionWithTitle(title, sectionOptions: options, sectionInsertMode: insert_mode)
|
|
23
|
+
if options.nonzero?
|
|
24
|
+
tag = section_data[:name]
|
|
25
|
+
mp("MutliValued section with no :name option", force_color: :red) unless tag
|
|
26
|
+
if tag.respond_to? :to_s
|
|
27
|
+
tag = tag.to_s
|
|
28
|
+
end
|
|
29
|
+
section.multivaluedTag = tag
|
|
30
|
+
end
|
|
31
|
+
section.footerTitle = section_data[:footer] if section_data[:footer]
|
|
32
|
+
|
|
33
|
+
add_proc section, :on_add, section_data[:on_add] if section_data[:on_add]
|
|
34
|
+
add_proc section, :on_remove, section_data[:on_remove] if section_data[:on_remove]
|
|
35
|
+
|
|
36
|
+
form.addFormSection(section)
|
|
37
|
+
|
|
38
|
+
section_data[:cells].each do |cell_data|
|
|
39
|
+
tag = cell_data[:name]
|
|
40
|
+
mp("Cell with no :name option", force_color: :red) unless tag
|
|
41
|
+
if tag.respond_to? :to_s
|
|
42
|
+
tag = tag.to_s
|
|
43
|
+
end
|
|
44
|
+
title = cell_data[:title]
|
|
45
|
+
type = cell_data[:type]
|
|
46
|
+
if type.nil? and cell_data[:cells]
|
|
47
|
+
type = :selector_push
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
cell = XLFormRowDescriptor.formRowDescriptorWithTag(tag, rowType: row_type(type), title: title)
|
|
51
|
+
|
|
52
|
+
cell.required = cell_data[:required]
|
|
53
|
+
|
|
54
|
+
properties = cell_data[:properties] || {}
|
|
55
|
+
|
|
56
|
+
# placeholder
|
|
57
|
+
cell.cellConfigAtConfigure.setObject(cell_data[:placeholder], forKey: "textField.placeholder") if cell_data[:placeholder]
|
|
58
|
+
|
|
59
|
+
# slider
|
|
60
|
+
if cell_data[:type] == :slider
|
|
61
|
+
min = properties[:min]
|
|
62
|
+
max = properties[:max]
|
|
63
|
+
step = properties[:step]
|
|
64
|
+
cell.cellConfigAtConfigure.setObject(min, forKey: "slider.minimumValue") if min
|
|
65
|
+
cell.cellConfigAtConfigure.setObject(max, forKey: "slider.maximumValue") if max
|
|
66
|
+
cell.cellConfigAtConfigure.setObject(step, forKey: "steps") if step
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# dates
|
|
70
|
+
if [:date_inline, :datetime_inline, :time_inline, :date, :datetime, :time, :datepicker].include? cell_data[:type]
|
|
71
|
+
min = properties[:min]
|
|
72
|
+
max = properties[:max]
|
|
73
|
+
cell.cellConfigAtConfigure.setObject(min, forKey: "minimumDate") if min
|
|
74
|
+
cell.cellConfigAtConfigure.setObject(max, forKey: "maximumDate") if max
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
cell_class = cell_data[:cell_class]
|
|
78
|
+
|
|
79
|
+
# image
|
|
80
|
+
if cell_data[:type] == :image
|
|
81
|
+
cell_class = XLFormImageSelectorCell if cell_class.nil?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
cell.cellClass = cell_class if cell_class
|
|
85
|
+
|
|
86
|
+
# subcells
|
|
87
|
+
if cell_data[:cells]
|
|
88
|
+
cell.action.viewControllerClass = ProMotion::XLSubFormScreen
|
|
89
|
+
cell.action.cells = cell_data[:cells]
|
|
90
|
+
cell.valueTransformer = ProMotion::ValueTransformer
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# also accept default XLForm viewControllerClass
|
|
94
|
+
cell.action.viewControllerClass = cell_data[:view_controller_class] if cell_data[:view_controller_class]
|
|
95
|
+
cell.valueTransformer = cell_data[:value_transformer] if cell_data[:value_transformer]
|
|
96
|
+
|
|
97
|
+
# callbacks
|
|
98
|
+
add_proc cell, :on_change, cell_data[:on_change] if cell_data[:on_change]
|
|
99
|
+
add_proc cell, :on_add, cell_data[:on_add] if cell_data[:on_add]
|
|
100
|
+
add_proc cell, :on_remove, cell_data[:on_remove] if cell_data[:on_remove]
|
|
101
|
+
|
|
102
|
+
cell.selectorTitle = cell_data[:selector_title] if cell_data[:selector_title]
|
|
103
|
+
options = parse_options(cell_data[:options])
|
|
104
|
+
cell.selectorOptions = options
|
|
105
|
+
|
|
106
|
+
value = cell_data[:value]
|
|
107
|
+
if value and options
|
|
108
|
+
options.each do |opt|
|
|
109
|
+
if opt.formValue == value
|
|
110
|
+
value = opt
|
|
111
|
+
break
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
cell.value = value if value
|
|
117
|
+
|
|
118
|
+
cell.disabled = !cell_data[:enabled] if cell_data[:enabled]
|
|
119
|
+
|
|
120
|
+
section.addFormRow(cell)
|
|
121
|
+
|
|
122
|
+
# multi sections
|
|
123
|
+
if section.multivaluedTag
|
|
124
|
+
cell.action.required = @required
|
|
125
|
+
section.multivaluedRowTemplate = cell.copy
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
form
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def get_callback(row, event)
|
|
134
|
+
return if @blocks.nil? or @blocks[row].nil? or @blocks[row][event].nil?
|
|
135
|
+
|
|
136
|
+
@blocks[row][event]
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
private
|
|
140
|
+
|
|
141
|
+
def add_proc(tag, event, block)
|
|
142
|
+
@blocks ||= {}
|
|
143
|
+
@blocks[tag] ||= {}
|
|
144
|
+
@blocks[tag][event] = block.respond_to?('weak!') ? block.weak! : block
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def parse_options(options)
|
|
148
|
+
return nil if options.nil? or options.empty?
|
|
149
|
+
|
|
150
|
+
options.map do |key, text|
|
|
151
|
+
val = key
|
|
152
|
+
if val.is_a? Symbol
|
|
153
|
+
val = val.to_s
|
|
154
|
+
end
|
|
155
|
+
XLFormOptionsObject.formOptionsObjectWithValue(val, displayText: text)
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def parse_section_options(options)
|
|
160
|
+
return section_options(:none) if options.nil?
|
|
161
|
+
|
|
162
|
+
opts = section_options(:none)
|
|
163
|
+
options.each do |opt|
|
|
164
|
+
opts |= section_options(opt)
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
opts
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def section_insert_mode(symbol)
|
|
171
|
+
{
|
|
172
|
+
last_row: XLFormSectionInsertModeLastRow,
|
|
173
|
+
button: XLFormSectionInsertModeButton
|
|
174
|
+
}[symbol] || symbol || XLFormSectionInsertModeLastRow
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def section_options(symbol)
|
|
178
|
+
{
|
|
179
|
+
none: XLFormSectionOptionNone,
|
|
180
|
+
insert: XLFormSectionOptionCanInsert,
|
|
181
|
+
delete: XLFormSectionOptionCanDelete,
|
|
182
|
+
reorder: XLFormSectionOptionCanReorder
|
|
183
|
+
}[symbol] || symbol || XLFormSectionOptionNone
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
def row_type(symbol)
|
|
187
|
+
{
|
|
188
|
+
text: XLFormRowDescriptorTypeText,
|
|
189
|
+
name: XLFormRowDescriptorTypeName,
|
|
190
|
+
url: XLFormRowDescriptorTypeURL,
|
|
191
|
+
email: XLFormRowDescriptorTypeEmail,
|
|
192
|
+
password: XLFormRowDescriptorTypePassword,
|
|
193
|
+
number: XLFormRowDescriptorTypeNumber,
|
|
194
|
+
phone: XLFormRowDescriptorTypePhone,
|
|
195
|
+
twitter: XLFormRowDescriptorTypeTwitter,
|
|
196
|
+
account: XLFormRowDescriptorTypeAccount,
|
|
197
|
+
integer: XLFormRowDescriptorTypeInteger,
|
|
198
|
+
decimal: XLFormRowDescriptorTypeDecimal,
|
|
199
|
+
textview: XLFormRowDescriptorTypeTextView,
|
|
200
|
+
selector_push: XLFormRowDescriptorTypeSelectorPush,
|
|
201
|
+
selector_popover: XLFormRowDescriptorTypeSelectorPopover,
|
|
202
|
+
selector_action_sheet: XLFormRowDescriptorTypeSelectorActionSheet,
|
|
203
|
+
selector_alert_view: XLFormRowDescriptorTypeSelectorAlertView,
|
|
204
|
+
selector_picker_view: XLFormRowDescriptorTypeSelectorPickerView,
|
|
205
|
+
selector_picker_view_inline: XLFormRowDescriptorTypeSelectorPickerViewInline,
|
|
206
|
+
multiple_selector: XLFormRowDescriptorTypeMultipleSelector,
|
|
207
|
+
multiple_selector_popover: XLFormRowDescriptorTypeMultipleSelectorPopover,
|
|
208
|
+
selector_left_right: XLFormRowDescriptorTypeSelectorLeftRight,
|
|
209
|
+
selector_segmented_control: XLFormRowDescriptorTypeSelectorSegmentedControl,
|
|
210
|
+
date_inline: XLFormRowDescriptorTypeDateInline,
|
|
211
|
+
datetime_inline: XLFormRowDescriptorTypeDateTimeInline,
|
|
212
|
+
time_inline: XLFormRowDescriptorTypeTimeInline,
|
|
213
|
+
countdown_timer_inline: XLFormRowDescriptorTypeCountDownTimerInline,
|
|
214
|
+
date: XLFormRowDescriptorTypeDate,
|
|
215
|
+
datetime: XLFormRowDescriptorTypeDateTime,
|
|
216
|
+
time: XLFormRowDescriptorTypeTime,
|
|
217
|
+
countdown_timer: XLFormRowDescriptorTypeCountDownTimer,
|
|
218
|
+
datepicker: XLFormRowDescriptorTypeDatePicker,
|
|
219
|
+
picker: XLFormRowDescriptorTypePicker,
|
|
220
|
+
slider: XLFormRowDescriptorTypeSlider,
|
|
221
|
+
check: XLFormRowDescriptorTypeBooleanCheck,
|
|
222
|
+
switch: XLFormRowDescriptorTypeBooleanSwitch,
|
|
223
|
+
button: XLFormRowDescriptorTypeButton,
|
|
224
|
+
info: XLFormRowDescriptorTypeInfo,
|
|
225
|
+
step_counter: XLFormRowDescriptorTypeStepCounter,
|
|
226
|
+
image: 'XLFormRowDescriptorTypeImage'
|
|
227
|
+
}[symbol] || symbol
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
end
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Monkey patch
|
|
2
|
+
class XLFormAction
|
|
3
|
+
|
|
4
|
+
attr_accessor :cells
|
|
5
|
+
attr_accessor :required
|
|
6
|
+
|
|
7
|
+
alias :old_copyWithZone :copyWithZone
|
|
8
|
+
|
|
9
|
+
def copyWithZone(zone)
|
|
10
|
+
action_copy = old_copyWithZone(zone)
|
|
11
|
+
|
|
12
|
+
action_copy.cells = self.cells.copy
|
|
13
|
+
action_copy.required = self.required
|
|
14
|
+
action_copy
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
class XLFormRowDescriptor
|
|
19
|
+
|
|
20
|
+
alias :old_copyWithZone :copyWithZone
|
|
21
|
+
|
|
22
|
+
def copyWithZone(zone)
|
|
23
|
+
row_descriptor_copy = old_copyWithZone(zone)
|
|
24
|
+
|
|
25
|
+
row_descriptor_copy.valueTransformer = self.valueTransformer
|
|
26
|
+
row_descriptor_copy
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
end
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
module ProMotion
|
|
2
|
+
class XLFormScreen < XlFormViewController
|
|
3
|
+
include ProMotion::ScreenModule
|
|
4
|
+
include ProMotion::XLFormModule
|
|
5
|
+
|
|
6
|
+
attr_reader :form_object
|
|
7
|
+
|
|
8
|
+
def viewDidLoad
|
|
9
|
+
super
|
|
10
|
+
update_form_data
|
|
11
|
+
|
|
12
|
+
form_options = self.class.get_form_options
|
|
13
|
+
|
|
14
|
+
if form_options[:on_cancel]
|
|
15
|
+
on_cancel = form_options[:on_cancel]
|
|
16
|
+
title = NSLocalizedString('Cancel', nil)
|
|
17
|
+
item = :cancel
|
|
18
|
+
if on_cancel.is_a? Hash
|
|
19
|
+
title = on_cancel[:title] if on_cancel[:title]
|
|
20
|
+
item = on_cancel[:item] if on_cancel[:item]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
set_nav_bar_button :left, {
|
|
24
|
+
system_item: item,
|
|
25
|
+
title: title,
|
|
26
|
+
action: 'on_cancel:'
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
if form_options[:on_save]
|
|
31
|
+
on_cancel = form_options[:on_save]
|
|
32
|
+
title = NSLocalizedString('Save', nil)
|
|
33
|
+
item = :save
|
|
34
|
+
if on_cancel.is_a? Hash
|
|
35
|
+
title = on_cancel[:title] if on_cancel[:title]
|
|
36
|
+
item = on_cancel[:item] if on_cancel[:item]
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
set_nav_bar_button :right, {
|
|
40
|
+
system_item: item,
|
|
41
|
+
title: title,
|
|
42
|
+
action: 'on_save:'
|
|
43
|
+
}
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def form_data
|
|
48
|
+
PM.logger.info "You need to implement a `form_data` method in #{self.class.to_s}."
|
|
49
|
+
[]
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def update_form_data
|
|
53
|
+
form_options = self.class.get_form_options
|
|
54
|
+
title = self.class.title
|
|
55
|
+
required = form_options[:required]
|
|
56
|
+
|
|
57
|
+
@form_builder = PM::XLForm.new(self.form_data,
|
|
58
|
+
{
|
|
59
|
+
title: title,
|
|
60
|
+
required: required
|
|
61
|
+
})
|
|
62
|
+
@form_object = @form_builder.build
|
|
63
|
+
self.form = @form_object
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def values
|
|
67
|
+
values = {}
|
|
68
|
+
formValues.each do |key, value|
|
|
69
|
+
if value.is_a? XLFormOptionsObject
|
|
70
|
+
value = value.formValue
|
|
71
|
+
end
|
|
72
|
+
values[key] = value
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
values
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def valid?
|
|
79
|
+
validation_errors.empty?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
alias :validation_errors :formValidationErrors
|
|
83
|
+
|
|
84
|
+
def display_errors
|
|
85
|
+
return if valid?
|
|
86
|
+
|
|
87
|
+
errors = validation_errors.map do |error|
|
|
88
|
+
error.localizedDescription
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
if NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_7_1
|
|
92
|
+
alert = UIAlertController.alertControllerWithTitle(NSLocalizedString('Error', nil),
|
|
93
|
+
message: errors.join(', '),
|
|
94
|
+
preferredStyle: UIAlertControllerStyleAlert)
|
|
95
|
+
action = UIAlertAction.actionWithTitle(NSLocalizedString('OK', nil),
|
|
96
|
+
style: UIAlertActionStyleDefault,
|
|
97
|
+
handler: nil)
|
|
98
|
+
alert.addAction(action)
|
|
99
|
+
presentViewController(alert, animated: true, completion: nil)
|
|
100
|
+
else
|
|
101
|
+
alert = UIAlertView.new
|
|
102
|
+
alert.title = NSLocalizedString('Error', nil)
|
|
103
|
+
alert.message = errors.join(', ')
|
|
104
|
+
alert.show
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
protected
|
|
109
|
+
def on_cancel(_)
|
|
110
|
+
form_options = self.class.get_form_options
|
|
111
|
+
if form_options[:on_cancel]
|
|
112
|
+
on_cancel = form_options[:on_cancel]
|
|
113
|
+
if on_cancel.is_a? Hash
|
|
114
|
+
on_cancel = on_cancel[:action]
|
|
115
|
+
end
|
|
116
|
+
try on_cancel
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def on_save(_)
|
|
121
|
+
unless valid?
|
|
122
|
+
display_errors
|
|
123
|
+
return
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
form_options = self.class.get_form_options
|
|
127
|
+
if form_options[:on_save]
|
|
128
|
+
on_save = form_options[:on_save]
|
|
129
|
+
if on_save.is_a? Hash
|
|
130
|
+
on_save = on_save[:action]
|
|
131
|
+
end
|
|
132
|
+
try on_save, values
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
## XLFormDescriptorDelegate
|
|
137
|
+
def formSectionHasBeenAdded(section, atIndex: _)
|
|
138
|
+
super
|
|
139
|
+
callback = @form_builder.get_callback(section, :on_add)
|
|
140
|
+
callback.call if callback
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def formSectionHasBeenRemoved(section, atIndex: _)
|
|
144
|
+
super
|
|
145
|
+
callback = @form_builder.get_callback(section, :on_remove)
|
|
146
|
+
callback.call if callback
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
def formRowHasBeenAdded(row, atIndexPath: _)
|
|
150
|
+
super
|
|
151
|
+
callback = @form_builder.get_callback(row, :on_add)
|
|
152
|
+
callback.call if callback
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
def formRowHasBeenRemoved(row, atIndexPath: _)
|
|
156
|
+
super
|
|
157
|
+
callback = @form_builder.get_callback(row, :on_remove)
|
|
158
|
+
callback.call if callback
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def formRowDescriptorValueHasChanged(row, oldValue: old_value, newValue: new_value)
|
|
162
|
+
super
|
|
163
|
+
callback = @form_builder.get_callback(row, :on_change)
|
|
164
|
+
callback.call(old_value, new_value) if callback
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
end
|
|
168
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
module ProMotion
|
|
2
|
+
class XlFormViewController < XLFormViewController
|
|
3
|
+
def self.new(args = {})
|
|
4
|
+
s = self.alloc.init
|
|
5
|
+
s.screen_init(args) if s.respond_to?(:screen_init)
|
|
6
|
+
s
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def loadView
|
|
10
|
+
self.respond_to?(:load_view) ? self.load_view : super
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def viewDidLoad
|
|
14
|
+
super
|
|
15
|
+
self.view_did_load if self.respond_to?(:view_did_load)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def viewWillAppear(animated)
|
|
19
|
+
super
|
|
20
|
+
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def viewDidAppear(animated)
|
|
24
|
+
super
|
|
25
|
+
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def viewWillDisappear(animated)
|
|
29
|
+
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
|
|
30
|
+
super
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def viewDidDisappear(animated)
|
|
34
|
+
self.view_did_disappear(animated) if self.respond_to?("view_did_disappear:")
|
|
35
|
+
super
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def shouldAutorotateToInterfaceOrientation(orientation)
|
|
39
|
+
self.should_rotate(orientation)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def shouldAutorotate
|
|
43
|
+
self.should_autorotate
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def willRotateToInterfaceOrientation(orientation, duration:duration)
|
|
47
|
+
self.will_rotate(orientation, duration)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def didRotateFromInterfaceOrientation(orientation)
|
|
51
|
+
self.on_rotate
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module ProMotion
|
|
2
|
+
class XLSubFormScreen < XLFormScreen
|
|
3
|
+
attr_accessor :rowDescriptor
|
|
4
|
+
|
|
5
|
+
def form_data
|
|
6
|
+
[
|
|
7
|
+
{
|
|
8
|
+
title: rowDescriptor.title,
|
|
9
|
+
cells: rowDescriptor.action.cells.map do |cell|
|
|
10
|
+
tag = cell[:name]
|
|
11
|
+
if tag.respond_to? :to_s
|
|
12
|
+
tag = tag.to_s
|
|
13
|
+
end
|
|
14
|
+
if rowDescriptor and rowDescriptor.value and rowDescriptor.value[tag]
|
|
15
|
+
cell.merge({ value: rowDescriptor.value[tag] })
|
|
16
|
+
else
|
|
17
|
+
cell
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
}
|
|
21
|
+
]
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update_form_data
|
|
25
|
+
title = rowDescriptor.title
|
|
26
|
+
required = rowDescriptor.action.required
|
|
27
|
+
|
|
28
|
+
@form_builder = PM::XLForm.new(self.form_data,
|
|
29
|
+
{
|
|
30
|
+
title: title,
|
|
31
|
+
required: required
|
|
32
|
+
})
|
|
33
|
+
@form_object = @form_builder.build
|
|
34
|
+
self.form = @form_object
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
## XLFormDescriptorDelegate
|
|
38
|
+
def formRowDescriptorValueHasChanged(row, oldValue: old_value, newValue: new_value)
|
|
39
|
+
super
|
|
40
|
+
rowDescriptor.value = values
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: ProMotion-XLForm
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.0.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Benjamin Michotte
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-07-23 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: ProMotion
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '2.0'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - "~>"
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '2.0'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: motion-cocoapods
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - "~>"
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.4'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - "~>"
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.4'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: motion-redgreen
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0.1'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0.1'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: rake
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
description: Adds XLForm screen support to ProMotion.
|
|
70
|
+
email:
|
|
71
|
+
- bmichotte@gmail.com
|
|
72
|
+
executables: []
|
|
73
|
+
extensions: []
|
|
74
|
+
extra_rdoc_files: []
|
|
75
|
+
files:
|
|
76
|
+
- README.md
|
|
77
|
+
- lib/ProMotion-XLForm.rb
|
|
78
|
+
- lib/ProMotion/XLForm/cells/xl_form_image_selector_cell.rb
|
|
79
|
+
- lib/ProMotion/XLForm/value_transformer.rb
|
|
80
|
+
- lib/ProMotion/XLForm/xl_form.rb
|
|
81
|
+
- lib/ProMotion/XLForm/xl_form_class_methods.rb
|
|
82
|
+
- lib/ProMotion/XLForm/xl_form_module.rb
|
|
83
|
+
- lib/ProMotion/XLForm/xl_form_patch.rb
|
|
84
|
+
- lib/ProMotion/XLForm/xl_form_screen.rb
|
|
85
|
+
- lib/ProMotion/XLForm/xl_form_view_controller.rb
|
|
86
|
+
- lib/ProMotion/XLForm/xl_sub_form_screen.rb
|
|
87
|
+
homepage: https://github.com/bmichotte/ProMotion-XLForm
|
|
88
|
+
licenses:
|
|
89
|
+
- MIT
|
|
90
|
+
metadata: {}
|
|
91
|
+
post_install_message:
|
|
92
|
+
rdoc_options: []
|
|
93
|
+
require_paths:
|
|
94
|
+
- lib
|
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - ">="
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '0'
|
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
101
|
+
requirements:
|
|
102
|
+
- - ">="
|
|
103
|
+
- !ruby/object:Gem::Version
|
|
104
|
+
version: '0'
|
|
105
|
+
requirements: []
|
|
106
|
+
rubyforge_project:
|
|
107
|
+
rubygems_version: 2.2.3
|
|
108
|
+
signing_key:
|
|
109
|
+
specification_version: 4
|
|
110
|
+
summary: Adds PM::XLFormScreen support to ProMotion, similar to ProMotion-form.
|
|
111
|
+
test_files: []
|