ProMotion 0.0.2 → 0.1.0
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.
- data/.gitignore +2 -1
- data/Gemfile +2 -0
- data/ProMotion.gemspec +3 -2
- data/README.md +85 -229
- data/Rakefile +15 -0
- data/app/app_delegate.rb +5 -0
- data/app/screens/home_screen.rb +10 -0
- data/app/screens/test_screen.rb +10 -0
- data/lib/ProMotion.rb +9 -3
- data/lib/ProMotion/AppDelegate.rb +55 -2
- data/lib/ProMotion/Console.rb +19 -0
- data/lib/ProMotion/ProMotion.rb +3 -0
- data/lib/ProMotion/classes/Element.rb +14 -0
- data/lib/ProMotion/classes/Screen.rb +239 -0
- data/lib/ProMotion/classes/TableScreen.rb +47 -0
- data/lib/ProMotion/ext/NavigationController.rb +5 -0
- data/lib/ProMotion/ext/TableViewController.rb +21 -0
- data/lib/ProMotion/ext/ViewController.rb +21 -0
- data/lib/ProMotion/helpers/MeasureHelper.rb +17 -0
- data/lib/ProMotion/helpers/TabBar.rb +30 -0
- data/lib/ProMotion/helpers/motion-table/console.rb +26 -0
- data/lib/ProMotion/helpers/motion-table/first/searchable_table.rb +56 -0
- data/lib/ProMotion/helpers/motion-table/first/sectioned_table.rb +108 -0
- data/lib/ProMotion/helpers/motion-table/grouped_table.rb +12 -0
- data/lib/ProMotion/helpers/motion-table/plain_table.rb +13 -0
- data/lib/ProMotion/version.rb +1 -1
- metadata +25 -8
- data/lib/ProMotion/Screen.rb +0 -11
data/.gitignore
CHANGED
data/Gemfile
CHANGED
data/ProMotion.gemspec
CHANGED
@@ -4,10 +4,10 @@ require File.expand_path('../lib/ProMotion/version', __FILE__)
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
5
|
gem.authors = ["Jamon Holmgren", "Silas Matson", "ClearSight Studio"]
|
6
6
|
gem.email = ["jamon@clearsightstudio.com"]
|
7
|
-
gem.description = "ProMotion is a new way to organize RubyMotion apps.
|
7
|
+
gem.description = "ProMotion is a new way to organize RubyMotion apps."
|
8
8
|
gem.summary = "
|
9
9
|
ProMotion is a new way to organize RubyMotion apps. Instead of dealing
|
10
|
-
with UIViewControllers
|
10
|
+
with UIViewControllers, you work with Screens. Screens are
|
11
11
|
a logical way to think of your app -- similar in some ways to Storyboards.
|
12
12
|
"
|
13
13
|
gem.homepage = "https://github.com/clearsightstudio/ProMotion"
|
@@ -18,4 +18,5 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.name = "ProMotion"
|
19
19
|
gem.require_paths = ["lib"]
|
20
20
|
gem.version = ProMotion::VERSION
|
21
|
+
# gem.add_dependency("motion-table", "~> 0.1.6")
|
21
22
|
end
|
data/README.md
CHANGED
@@ -1,10 +1,7 @@
|
|
1
|
-
# ProMotion
|
1
|
+
# ProMotion - A new way to organize RubyMotion apps.
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
ProMotion is a new way to organize RubyMotion apps. Instead of dealing
|
6
|
-
with UIViewControllers and UIViews, you work with Screens. Screens are
|
7
|
-
a logical way to think of your app.
|
3
|
+
ProMotion introduces a new object called "Screens". Screens have a one-to-one relationship
|
4
|
+
with your app's screens and can (usually) take the place of view controllers.
|
8
5
|
|
9
6
|
Typical /app file structure:
|
10
7
|
|
@@ -17,273 +14,159 @@ Typical /app file structure:
|
|
17
14
|
home_screen.rb
|
18
15
|
settings_screen.rb
|
19
16
|
models
|
17
|
+
view_controllers
|
20
18
|
views
|
21
19
|
app_delegate.rb
|
22
20
|
|
23
|
-
The "views" folder contains custom view components, written in normal RubyMotion. "models" can be whatever ORM you're using.
|
24
|
-
|
25
|
-
### What about MVC?
|
26
|
-
|
27
|
-
I'm a big believer in MVC (I'm a Rails developer, too). I found that most of the time working in RubyMotion seems to happen
|
28
|
-
in the ViewControllers. This pattern may be best for simpler, smaller apps.
|
29
|
-
|
30
|
-
This is a proof of concept. I'd really appreciate feedback on it at my email address (jamon@clearsightstudio.com) or Twitter (@jamonholmgren).
|
31
|
-
|
32
|
-
## Installation
|
33
|
-
|
34
|
-
Add this line to your application's Gemfile:
|
35
|
-
|
36
|
-
gem 'ProMotion'
|
37
|
-
|
38
|
-
And then execute:
|
39
|
-
|
40
|
-
$ bundle
|
41
|
-
|
42
|
-
Or install it yourself as:
|
43
|
-
|
44
|
-
$ gem install ProMotion
|
45
|
-
|
46
21
|
## Usage
|
47
22
|
|
48
|
-
|
23
|
+
Loading your home screen:
|
49
24
|
|
50
25
|
```ruby
|
51
|
-
# In /app/app_delegate.rb (note that AppDelegate extends ProMotion::
|
52
|
-
class AppDelegate < ProMotion::
|
53
|
-
def
|
54
|
-
|
55
|
-
|
56
|
-
true
|
26
|
+
# In /app/app_delegate.rb (note that AppDelegate extends ProMotion::AppDelegateParent)
|
27
|
+
class AppDelegate < ProMotion::AppDelegateParent
|
28
|
+
def on_load(options)
|
29
|
+
open_screen MyHomeScreen.new(nav_bar: true)
|
57
30
|
end
|
58
31
|
end
|
59
32
|
```
|
60
33
|
|
61
|
-
|
34
|
+
Creating a basic screen:
|
62
35
|
|
63
36
|
```ruby
|
64
|
-
# In /app/screens/home_screen.rb:
|
65
37
|
class HomeScreen < ProMotion::Screen
|
66
|
-
# Set the title for use in nav bars and other containers
|
67
38
|
title "Home"
|
68
39
|
|
69
|
-
# Called when this screen is first "opened" and allows you to set up your view components
|
70
40
|
def on_load
|
71
|
-
|
41
|
+
# Set up the elements in your view with add_element:
|
42
|
+
@label = add_element UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20)), {
|
43
|
+
text: "This is awesome!",
|
44
|
+
font: UIFont.UIFont.systemFontOfSize(18)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def on_appear
|
49
|
+
# Refresh the data if you want
|
72
50
|
end
|
73
51
|
end
|
74
52
|
```
|
75
53
|
|
76
|
-
|
54
|
+
Creating a tabbed bar:
|
77
55
|
|
78
56
|
```ruby
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def on_load
|
85
|
-
# Add view items as instance vars so you can access them in other methods
|
86
|
-
|
87
|
-
# This adds a right nav bar button. on_tap allows you to set a method to call when it's tapped.
|
88
|
-
@right_bar_button = add_right_nav_button(label: "Save", on_tap: :save)
|
89
|
-
|
90
|
-
# Helper function for adding a button
|
91
|
-
@settings_button = add_button(label: "Settings", frame: [10, 10, 100, 30])
|
92
|
-
|
93
|
-
# Helper function for adding an image
|
94
|
-
@default_image = add_image(:default_image, src: "default.png", frame: [10, 50, 100, 100])
|
95
|
-
|
96
|
-
# You can also add custom UIViews through the add_view method.
|
97
|
-
@custom_view = add_view(ChatView.alloc.initWithFrame(CGRectMake(10, 300, 40, 40)))
|
98
|
-
end
|
57
|
+
def on_load(options)
|
58
|
+
@home = MyHomeScreen.new(nav_bar: true)
|
59
|
+
@settings = SettingsScreen.new
|
60
|
+
@contact = ContactScreen.new(nav_bar: true)
|
61
|
+
open_tab_bar @home, @settings, @contact
|
99
62
|
end
|
100
63
|
```
|
101
64
|
|
102
|
-
|
65
|
+
Any view item (UIView, UIButton, etc) can be used with add_element.
|
66
|
+
The second argument is a hash of settings that get applied to the
|
67
|
+
element before it is dropped into the view.
|
103
68
|
|
104
69
|
```ruby
|
105
|
-
|
106
|
-
|
107
|
-
|
70
|
+
@label = add_element UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20)), {
|
71
|
+
text: "This is awesome!",
|
72
|
+
font: UIFont.UIFont.systemFontOfSize(18)
|
73
|
+
}
|
74
|
+
```
|
108
75
|
|
109
|
-
|
110
|
-
@settings_button.on(:tap) do
|
111
|
-
# Do something
|
112
|
-
end
|
76
|
+
Add a nav_bar button and a tab_bar icon:
|
113
77
|
|
114
|
-
|
115
|
-
|
116
|
-
|
78
|
+
```ruby
|
79
|
+
add_right_nav_button(label: "Save", action: :save)
|
80
|
+
set_tab_bar_item(title: "Contacts", system_icon: UITabBarSystemItemContacts)
|
117
81
|
```
|
118
82
|
|
119
|
-
|
83
|
+
Open a new screen:
|
120
84
|
|
121
85
|
```ruby
|
122
86
|
def settings_button_tapped
|
123
87
|
# ...with a class...
|
124
|
-
|
88
|
+
open_screen SettingsScreen
|
125
89
|
|
126
90
|
# ...or with an instance...
|
127
|
-
@settings_screen = SettingsScreen.new
|
128
|
-
|
129
|
-
|
130
|
-
# ...or if you like...
|
131
|
-
open SettingsScreen.new
|
91
|
+
@settings_screen = SettingsScreen.new
|
92
|
+
open_screen @settings_screen
|
132
93
|
end
|
133
94
|
```
|
134
95
|
|
135
|
-
You can pass in arguments to
|
96
|
+
You can pass in arguments to other screens if they have accessors:
|
136
97
|
|
137
98
|
```ruby
|
138
|
-
# /app/screens/settings_screen.rb
|
139
|
-
class SettingsScreen < ProMotion::Screen
|
140
|
-
attr_accessor :user_type
|
141
|
-
|
142
|
-
def on_load
|
143
|
-
if self.user_type == "Admin"
|
144
|
-
# Stuff
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
# ...
|
149
|
-
end
|
150
|
-
|
151
|
-
# /app/screens/home_screen.rb
|
152
99
|
class HomeScreen < ProMotion::Screen
|
153
100
|
# ...
|
154
101
|
|
155
102
|
def settings_button_tapped
|
156
|
-
|
103
|
+
open_screen ProfileScreen.new(user: some_user)
|
157
104
|
end
|
158
105
|
end
|
159
|
-
```
|
160
106
|
|
161
|
-
|
107
|
+
class ProfileScreen < ProMotion::Screen
|
108
|
+
attr_accessor :user
|
162
109
|
|
163
|
-
|
164
|
-
|
165
|
-
if @model.save
|
166
|
-
close
|
110
|
+
def on_load
|
111
|
+
self.user # => some_user instance
|
167
112
|
end
|
168
113
|
end
|
114
|
+
|
169
115
|
```
|
170
116
|
|
171
|
-
|
117
|
+
Close a screen, passing back arguments to the previous screen's "on_return" method:
|
172
118
|
|
173
119
|
```ruby
|
174
|
-
class
|
120
|
+
class ItemScreen
|
175
121
|
# ...
|
176
|
-
|
177
122
|
def save_and_close
|
178
|
-
|
123
|
+
if @model.save
|
124
|
+
close_screen(model_saved: true)
|
125
|
+
end
|
179
126
|
end
|
180
127
|
end
|
181
128
|
|
182
129
|
class MainScreen < ProMotion::Screen
|
183
130
|
# ...
|
184
|
-
|
185
131
|
def on_return(args = {})
|
186
|
-
if args[:
|
132
|
+
if args[:model_saved]
|
187
133
|
self.reload_something
|
188
134
|
end
|
189
135
|
end
|
190
136
|
end
|
191
137
|
```
|
192
138
|
|
193
|
-
|
139
|
+
Use a custom view controller:
|
194
140
|
|
195
141
|
```ruby
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
#
|
200
|
-
|
201
|
-
|
202
|
-
def on_load
|
203
|
-
# No need to set anything up, really
|
204
|
-
end
|
205
|
-
|
206
|
-
# If you define your screen_type as some sort of table, this gets called to get the data.
|
207
|
-
# You can also refresh the table data manually by calling `self.reload_table_data`
|
208
|
-
def table_data
|
209
|
-
# You can create a new table section here and add cells to it like so:
|
210
|
-
@account_section = add_section(label: "Your Account")
|
211
|
-
@account_section.add_cell(title: "Edit Profile", action: :edit_profile, arguments: { account_id: @account.id })
|
212
|
-
@account_section.add_cell(title: "Log Out", action: :log_out)
|
213
|
-
|
214
|
-
# Or just pass back an array with everything defined and we'll build it for you:
|
215
|
-
[{
|
216
|
-
title: "Your Account",
|
217
|
-
cells: [
|
218
|
-
{ title: "Edit Profile", action: :edit_profile },
|
219
|
-
{ title: "Log Out", action: :log_out },
|
220
|
-
{ title: "Notification Settings", action: :notification_settings }
|
221
|
-
]
|
222
|
-
}, {
|
223
|
-
title: "App Stuff",
|
224
|
-
cells: [
|
225
|
-
{ title: "About", action: :show_about },
|
226
|
-
{ title: "Feedback", action: :show_feedback }
|
227
|
-
]
|
228
|
-
}]
|
229
|
-
end
|
142
|
+
def on_load
|
143
|
+
set_view_controller MyCustomViewController
|
144
|
+
|
145
|
+
# Note: on_appear will not fire when using a custom
|
146
|
+
# view controller.
|
230
147
|
end
|
231
148
|
```
|
232
149
|
|
233
|
-
|
150
|
+
The helper add_element takes a
|
234
151
|
|
235
|
-
|
236
|
-
# In /app/screens/home_screen.rb:
|
152
|
+
You can create sectioned table screens easily. TableScreen, SectionedTableScreen, GroupedTableScreen
|
237
153
|
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
# Set the title for use in nav bars and other containers
|
243
|
-
title "Home"
|
244
|
-
|
245
|
-
# Defaults to :normal. :plain_table, :grouped_table are options.
|
246
|
-
screen_type :plain_table
|
154
|
+
```ruby
|
155
|
+
class SettingsScreen < ProMotion::GroupedTableScreen
|
156
|
+
title "Settings"
|
247
157
|
|
248
|
-
# Called when this screen is first "opened" and allows you to set up your view components
|
249
158
|
def on_load
|
250
|
-
|
251
|
-
|
252
|
-
@right_bar_button = add_right_nav_button(label: "Save", on_tap: :save)
|
253
|
-
|
254
|
-
# Helper function for adding a button
|
255
|
-
@settings_button = add_button(label: "Settings", frame: [10, 10, 100, 30])
|
256
|
-
|
257
|
-
# View items can be bound to events (like jQuery) and run methods or run a block.
|
258
|
-
@settings_button.on(:tap, :settings_pushed)
|
259
|
-
@settings_button.on(:tapHold) do
|
260
|
-
# Do something
|
261
|
-
end
|
262
|
-
|
263
|
-
# Helper function for adding an image
|
264
|
-
@default_image = add_image(:default_image, src: "default.png", frame: [10, 50, 100, 100])
|
265
|
-
|
266
|
-
# This button passes in arguments to the method when it's tapped
|
267
|
-
@edit_button = add_button(label: "Edit", frame: [10, 10, 100, 30])
|
268
|
-
@edit_button.on(:tap, :edit_pushed, id: 4)
|
269
|
-
|
270
|
-
# You can also add custom UIViews through the add_view method.
|
271
|
-
@custom_view = add_view(ChatView.alloc.initWithFrame(CGRectMake(10, 300, 40, 40)))
|
159
|
+
add_right_nav_button(label: "Save", action: :save)
|
160
|
+
set_tab_bar_item(title: "Settings", icon: "settings.png")
|
272
161
|
end
|
273
|
-
|
274
|
-
#
|
275
|
-
#
|
162
|
+
|
163
|
+
# table_data is automatically called. Use this format in the return value.
|
164
|
+
# Grouped tables are the same as plain tables
|
276
165
|
def table_data
|
277
|
-
# You can create a new table section here and add cells to it like so:
|
278
|
-
@account_section = add_section(label: "Your Account")
|
279
|
-
@account_section.add_cell(title: "Edit Profile", action: :edit_profile, arguments: { account_id: @account.id })
|
280
|
-
@account_section.add_cell(title: "Log Out", action: :log_out)
|
281
|
-
|
282
|
-
# Or just pass back an array with everything defined and we'll build it for you:
|
283
166
|
[{
|
284
167
|
title: "Your Account",
|
285
168
|
cells: [
|
286
|
-
{ title: "Edit Profile", action: :edit_profile },
|
169
|
+
{ title: "Edit Profile", action: :edit_profile, arguments: { id: 3 } },
|
287
170
|
{ title: "Log Out", action: :log_out },
|
288
171
|
{ title: "Notification Settings", action: :notification_settings }
|
289
172
|
]
|
@@ -296,52 +179,25 @@ class HomeScreen < ProMotion::Screen
|
|
296
179
|
}]
|
297
180
|
end
|
298
181
|
|
299
|
-
#
|
300
|
-
def
|
301
|
-
|
302
|
-
@my_model.save
|
303
|
-
|
304
|
-
# When you want to close the current screen (usually in a navigation controller), just run this.
|
305
|
-
close
|
306
|
-
|
307
|
-
# You can also pass back arguments to the previous screen as you close.
|
308
|
-
# If the previous screen has an `on_return` method, this will be passed into that method
|
309
|
-
close(did_stuff: true)
|
182
|
+
# This method allows you to create a "jumplist", the index on the right side of the table
|
183
|
+
def table_data_index
|
184
|
+
return ["A", "B", "C"]
|
310
185
|
end
|
311
|
-
|
312
|
-
#
|
313
|
-
def
|
314
|
-
|
315
|
-
# Refresh?
|
316
|
-
end
|
317
|
-
end
|
318
|
-
|
319
|
-
# Custom method
|
320
|
-
def settings_pushed
|
321
|
-
# Just open a settings screen
|
322
|
-
open SettingsScreen
|
323
|
-
|
324
|
-
# If you prefer to pass in an instance, that works too:
|
325
|
-
open SettingsScreen.new
|
326
|
-
end
|
327
|
-
|
328
|
-
def close_pushed
|
329
|
-
close
|
330
|
-
end
|
331
|
-
|
332
|
-
# Custom method with passed in arguments
|
333
|
-
def edit_pushed(args)
|
334
|
-
# Open a screen and set some of its attributes
|
335
|
-
open EditScreen.new(id: args[:id])
|
186
|
+
|
187
|
+
# Your table cells, when tapped, will execute the corresponding actions and pass in arguments:
|
188
|
+
def edit_profile(arguments)
|
189
|
+
# ...
|
336
190
|
end
|
337
191
|
end
|
338
192
|
```
|
339
193
|
|
194
|
+
### What about MVC?
|
195
|
+
|
196
|
+
I'm a big believer in MVC (I'm a Rails developer, too). I found that most of the time working in RubyMotion seems to happen
|
197
|
+
in the ViewControllers and views are mainly custom elements. This pattern may be best for simpler, smaller apps.
|
198
|
+
|
199
|
+
Feedback welcome via twitter @jamonholmgren.
|
340
200
|
|
341
201
|
## Contributing
|
342
202
|
|
343
|
-
|
344
|
-
2. Create your feature branch (`git checkout -b my-new-feature`)
|
345
|
-
3. Commit your changes (`git commit -am 'Added some feature'`)
|
346
|
-
4. Push to the branch (`git push origin my-new-feature`)
|
347
|
-
5. Create new Pull Request
|
203
|
+
I'm really looking for feedback. Tweet me with your ideas or open a ticket (I don't mind!) and let's discuss.
|