ProMotion 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.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/ProMotion.gemspec +19 -0
- data/README.md +337 -0
- data/Rakefile +2 -0
- data/lib/ProMotion.rb +5 -0
- data/lib/ProMotion/version.rb +3 -0
- metadata +55 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jamon Holmgren
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/ProMotion.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/ProMotion/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Jamon Holmgren"]
|
6
|
+
gem.email = ["jamon@clearsightstudio.com"]
|
7
|
+
gem.description = "ProMotion is a new way to organize RubyMotion apps."
|
8
|
+
gem.summary = "ProMotion is a new way to organize RubyMotion apps. Instead of dealing
|
9
|
+
with UIViewControllers and UIViews, you work with Screens. Screens are
|
10
|
+
a logical way to think of your app."
|
11
|
+
gem.homepage = ""
|
12
|
+
|
13
|
+
gem.files = `git ls-files`.split($\)
|
14
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
16
|
+
gem.name = "ProMotion"
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
gem.version = ProMotion::VERSION
|
19
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,337 @@
|
|
1
|
+
# ProMotion
|
2
|
+
|
3
|
+
**Please note: this is a proof of concept and does not yet work.**
|
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.
|
8
|
+
|
9
|
+
Typical /app file structure:
|
10
|
+
|
11
|
+
app
|
12
|
+
screens
|
13
|
+
photos
|
14
|
+
list_photos_screen.rb
|
15
|
+
show_photo_screen.rb
|
16
|
+
edit_photo_screen.rb
|
17
|
+
home_screen.rb
|
18
|
+
settings_screen.rb
|
19
|
+
models
|
20
|
+
views
|
21
|
+
app_delegate.rb
|
22
|
+
|
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
|
+
## Usage
|
47
|
+
|
48
|
+
It's easy to load your first view with a navigation bar (the view is opened in a UINavigationController):
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# In /app/app_delegate.rb:
|
52
|
+
class AppDelegate
|
53
|
+
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
54
|
+
@window = HomeScreen.open_with_nav_bar
|
55
|
+
|
56
|
+
true
|
57
|
+
end
|
58
|
+
end
|
59
|
+
```
|
60
|
+
|
61
|
+
Screens are pretty straightforward. You extend ProMotion::Screen and provide a title and an on_load method.
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# In /app/screens/home_screen.rb:
|
65
|
+
class HomeScreen < ProMotion::Screen
|
66
|
+
# Set the title for use in nav bars and other containers
|
67
|
+
title "Home"
|
68
|
+
|
69
|
+
# Called when this view is first "opened" and allows you to set up your view
|
70
|
+
def on_load
|
71
|
+
@default_image = add_image(:default_image, src: "default.png", frame: [10, 50, 100, 100])
|
72
|
+
end
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
In on_load, you can add images, buttons, labels, custom views to your screen.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
# In /app/screens/home_screen.rb:
|
80
|
+
class HomeScreen < ProMotion::Screen
|
81
|
+
# Set the title for use in nav bars and other containers
|
82
|
+
title "Home"
|
83
|
+
|
84
|
+
# Called when this view is first "opened" and allows you to set up your view
|
85
|
+
def on_load
|
86
|
+
# Add view items as instance vars so you can access them in other methods
|
87
|
+
|
88
|
+
# This adds a right nav bar button. on_tap allows you to set a method to call when it's tapped.
|
89
|
+
@right_bar_button = add_right_nav_button(label: "Save", on_tap: :save)
|
90
|
+
|
91
|
+
# Helper function for adding a button
|
92
|
+
@settings_button = add_button(label: "Settings", frame: [10, 10, 100, 30])
|
93
|
+
|
94
|
+
# Helper function for adding an image
|
95
|
+
@default_image = add_image(:default_image, src: "default.png", frame: [10, 50, 100, 100])
|
96
|
+
|
97
|
+
# You can also add custom UIViews through the add_view method.
|
98
|
+
@custom_view = add_view(ChatView.alloc.initWithFrame(CGRectMake(10, 300, 40, 40)))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
```
|
102
|
+
|
103
|
+
View items can be bound to events (like jQuery) and run methods or run a block.
|
104
|
+
|
105
|
+
```ruby
|
106
|
+
# settings_pushed is executed when the button is tapped
|
107
|
+
@settings_button = add_button(label: "Settings", frame: [10, 10, 100, 30])
|
108
|
+
@settings_button.on(:tap, :settings_pushed)
|
109
|
+
|
110
|
+
# This demonstrates a block
|
111
|
+
@settings_button.on(:tap) do
|
112
|
+
# Do something
|
113
|
+
end
|
114
|
+
|
115
|
+
# This button passes in arguments to the method when it's tapped
|
116
|
+
@edit_button = add_button(label: "Edit", frame: [10, 10, 100, 30])
|
117
|
+
@edit_button.on(:tap, :edit_pushed, id: 4)
|
118
|
+
```
|
119
|
+
|
120
|
+
To open other screens, just call their "open" method:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
def settings_button_tapped
|
124
|
+
SettingsScreen.open
|
125
|
+
end
|
126
|
+
```
|
127
|
+
|
128
|
+
You can pass in arguments to those screens if they have accessors:
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
# /app/screens/settings_screen.rb
|
132
|
+
class SettingsScreen < ProMotion::Screen
|
133
|
+
attr_accessor :user_type
|
134
|
+
|
135
|
+
def on_load
|
136
|
+
if self.user_type == "Admin"
|
137
|
+
# Stuff
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
# ...
|
142
|
+
end
|
143
|
+
|
144
|
+
# /app/screens/home_screen.rb
|
145
|
+
class HomeScreen < ProMotion::Screen
|
146
|
+
# ...
|
147
|
+
|
148
|
+
def settings_button_tapped
|
149
|
+
SettingsScreen.open(user_type: "Admin")
|
150
|
+
end
|
151
|
+
end
|
152
|
+
```
|
153
|
+
|
154
|
+
When you're done with a screen, just close it:
|
155
|
+
|
156
|
+
```ruby
|
157
|
+
def save_and_close
|
158
|
+
if @model.save
|
159
|
+
self.close
|
160
|
+
end
|
161
|
+
end
|
162
|
+
```
|
163
|
+
|
164
|
+
If you want to pass arguments back to the previous screen, go for it.
|
165
|
+
|
166
|
+
```ruby
|
167
|
+
class SettingsScreen < ProMotion::Screen
|
168
|
+
# ...
|
169
|
+
|
170
|
+
def save_and_close
|
171
|
+
self.close(saved_changes: true)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
class MainScreen < ProMotion::Screen
|
176
|
+
# ...
|
177
|
+
|
178
|
+
def on_return(args = {})
|
179
|
+
if args[:saved_changes]
|
180
|
+
self.reload_something
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
```
|
185
|
+
|
186
|
+
You can create sectioned table screens easily.
|
187
|
+
|
188
|
+
```ruby
|
189
|
+
class HomeScreen < ProMotion::Screen
|
190
|
+
title "Home"
|
191
|
+
|
192
|
+
# Defaults to :normal. :plain_table, :grouped_table are options.
|
193
|
+
screen_type :grouped_table
|
194
|
+
|
195
|
+
def on_load
|
196
|
+
# No need to set anything up, really
|
197
|
+
end
|
198
|
+
|
199
|
+
# If you define your screen_type as some sort of table, this gets called to get the data.
|
200
|
+
# You can also refresh the table data manually by calling `self.reload_table_data`
|
201
|
+
def table_data
|
202
|
+
# You can create a new table section here and add cells to it like so:
|
203
|
+
@account_section = add_section(label: "Your Account")
|
204
|
+
@account_section.add_cell(title: "Edit Profile", action: :edit_profile, arguments: { account_id: @account.id })
|
205
|
+
@account_section.add_cell(title: "Log Out", action: :log_out)
|
206
|
+
|
207
|
+
# Or just pass back an array with everything defined and we'll build it for you:
|
208
|
+
[{
|
209
|
+
title: "Your Account",
|
210
|
+
cells: [
|
211
|
+
{ title: "Edit Profile", action: :edit_profile },
|
212
|
+
{ title: "Log Out", action: :log_out },
|
213
|
+
{ title: "Notification Settings", action: :notification_settings }
|
214
|
+
]
|
215
|
+
}, {
|
216
|
+
title: "App Stuff",
|
217
|
+
cells: [
|
218
|
+
{ title: "About", action: :show_about },
|
219
|
+
{ title: "Feedback", action: :show_feedback }
|
220
|
+
]
|
221
|
+
}]
|
222
|
+
end
|
223
|
+
end
|
224
|
+
```
|
225
|
+
|
226
|
+
Here's a full demo of a screen:
|
227
|
+
|
228
|
+
```ruby
|
229
|
+
# In /app/screens/home_screen.rb:
|
230
|
+
|
231
|
+
class HomeScreen < ProMotion::Screen
|
232
|
+
# Accessors allow screens to set parameters when opening this screen
|
233
|
+
attr_accessor :foo
|
234
|
+
|
235
|
+
# Set the title for use in nav bars and other containers
|
236
|
+
title "Home"
|
237
|
+
|
238
|
+
# Defaults to :normal. :plain_table, :grouped_table are options.
|
239
|
+
screen_type :plain_table
|
240
|
+
|
241
|
+
# Called when this view is first "opened" and allows you to set up your view
|
242
|
+
def on_load
|
243
|
+
# Add view items as instance vars so you can access them in other methods
|
244
|
+
# This adds a right nav bar button. on_tap allows you to set a method to call when it's tapped.
|
245
|
+
@right_bar_button = add_right_nav_button(label: "Save", on_tap: :save)
|
246
|
+
|
247
|
+
# Helper function for adding a button
|
248
|
+
@settings_button = add_button(label: "Settings", frame: [10, 10, 100, 30])
|
249
|
+
|
250
|
+
# View items can be bound to events (like jQuery) and run methods or run a block.
|
251
|
+
@settings_button.on(:tap, :settings_pushed)
|
252
|
+
@settings_button.on(:tapHold) do
|
253
|
+
# Do something
|
254
|
+
end
|
255
|
+
|
256
|
+
# Helper function for adding an image
|
257
|
+
@default_image = add_image(:default_image, src: "default.png", frame: [10, 50, 100, 100])
|
258
|
+
|
259
|
+
# This button passes in arguments to the method when it's tapped
|
260
|
+
@edit_button = add_button(label: "Edit", frame: [10, 10, 100, 30])
|
261
|
+
@edit_button.on(:tap, :edit_pushed, id: 4)
|
262
|
+
|
263
|
+
# You can also add custom UIViews through the add_view method.
|
264
|
+
@custom_view = add_view(ChatView.alloc.initWithFrame(CGRectMake(10, 300, 40, 40)))
|
265
|
+
end
|
266
|
+
|
267
|
+
# If you define your screen_type as some sort of table, this gets called to get the data.
|
268
|
+
# You can also refresh the table data manually by calling `self.reload_table_data`
|
269
|
+
def table_data
|
270
|
+
# You can create a new table section here and add cells to it like so:
|
271
|
+
@account_section = add_section(label: "Your Account")
|
272
|
+
@account_section.add_cell(title: "Edit Profile", action: :edit_profile, arguments: { account_id: @account.id })
|
273
|
+
@account_section.add_cell(title: "Log Out", action: :log_out)
|
274
|
+
|
275
|
+
# Or just pass back an array with everything defined and we'll build it for you:
|
276
|
+
[{
|
277
|
+
title: "Your Account",
|
278
|
+
cells: [
|
279
|
+
{ title: "Edit Profile", action: :edit_profile },
|
280
|
+
{ title: "Log Out", action: :log_out },
|
281
|
+
{ title: "Notification Settings", action: :notification_settings }
|
282
|
+
]
|
283
|
+
}, {
|
284
|
+
title: "App Stuff",
|
285
|
+
cells: [
|
286
|
+
{ title: "About", action: :show_about },
|
287
|
+
{ title: "Feedback", action: :show_feedback }
|
288
|
+
]
|
289
|
+
}]
|
290
|
+
end
|
291
|
+
|
292
|
+
# Custom method, invoked when tapping something with this as the action
|
293
|
+
def save
|
294
|
+
# Assuming some sort of ORM, like ParseModel
|
295
|
+
@my_model.save
|
296
|
+
|
297
|
+
# When you want to close the current view (usually in a navigation controller), just run this.
|
298
|
+
self.close
|
299
|
+
|
300
|
+
# You can also pass back arguments to the previous view as you close.
|
301
|
+
# If the previous screen has an `on_return` method, this will be passed into that method
|
302
|
+
self.close(did_stuff: true)
|
303
|
+
end
|
304
|
+
|
305
|
+
# This is called any time a screen "above" this screen is closed. args = {} is required.
|
306
|
+
def on_return(args = {})
|
307
|
+
if args[:did_stuff]
|
308
|
+
# Refresh?
|
309
|
+
end
|
310
|
+
end
|
311
|
+
|
312
|
+
# Custom method
|
313
|
+
def settings_pushed
|
314
|
+
# Just open a settings screen
|
315
|
+
SettingsScreen.open
|
316
|
+
end
|
317
|
+
|
318
|
+
def close_pushed
|
319
|
+
self.close
|
320
|
+
end
|
321
|
+
|
322
|
+
# Custom method with passed in arguments
|
323
|
+
def edit_pushed(args)
|
324
|
+
# Open a screen and set some of its attributes
|
325
|
+
EditScreen.open(id: args[:id])
|
326
|
+
end
|
327
|
+
end
|
328
|
+
```
|
329
|
+
|
330
|
+
|
331
|
+
## Contributing
|
332
|
+
|
333
|
+
1. Fork it
|
334
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
335
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
336
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
337
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/ProMotion.rb
ADDED
metadata
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ProMotion
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jamon Holmgren
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-08-30 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: ProMotion is a new way to organize RubyMotion apps.
|
15
|
+
email:
|
16
|
+
- jamon@clearsightstudio.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE
|
24
|
+
- ProMotion.gemspec
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- lib/ProMotion.rb
|
28
|
+
- lib/ProMotion/version.rb
|
29
|
+
homepage: ''
|
30
|
+
licenses: []
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
requirements: []
|
48
|
+
rubyforge_project:
|
49
|
+
rubygems_version: 1.8.24
|
50
|
+
signing_key:
|
51
|
+
specification_version: 3
|
52
|
+
summary: ProMotion is a new way to organize RubyMotion apps. Instead of dealing with
|
53
|
+
UIViewControllers and UIViews, you work with Screens. Screens are a logical way
|
54
|
+
to think of your app.
|
55
|
+
test_files: []
|