Merge branch 'version-0.7' of https://github.com/clearsightstudio/ProMotion into version-0.7

This commit is contained in:
Steve Ross
2013-05-18 23:17:02 -07:00
21 changed files with 473 additions and 166 deletions

123
CUSTOM_VIEW_CONTROLLERS.md Normal file
View File

@@ -0,0 +1,123 @@
# Using your own UIViewControllers with ProMotion
Sometimes you want to inherit from a different UIViewController other than that provided by ProMotion.
**RubyMotion doesn't currently allow us to override built-in methods when including them as a module.**
And we really need to override `viewDidLoad` and others.
### Formotion
If you're including [Formotion](https://github.com/clayallsopp/formotion), just use the built-in
`PM::FormotionScreen` and provide a `table_data` method or a `form:` object on instantiation.
```ruby
class MyFormScreen < PM::FormotionScreen
title "My Form"
def table_data
{
sections: [{
title: "Register",
rows: [{
title: "Email",
key: :email,
placeholder: "me@mail.com",
type: :email,
auto_correction: :no,
auto_capitalization: :none
}, {
title: "Password",
key: :password,
placeholder: "required",
type: :string,
secure: true
}
}]
}
end
end
# elsewhere...
open MyFormScreen.new(nav_bar: true)
```
You can also instantiate the form screen with the form hash like Formotion is usually used:
```ruby
open MyFormScreen.new nav_bar: true, form: {
sections: [{
title: "Register",
rows: [{
title: "Email",
key: :email,
placeholder: "me@mail.com",
type: :email,
auto_correction: :no,
auto_capitalization: :none
}, {
title: "Password",
key: :password,
placeholder: "required",
type: :string,
secure: true
}
}]
}
```
### Custom UIViewController
```ruby
class EventsScreen < UIViewController
include PM::ScreenModule
# Required functions for ProMotion to work properly
def self.new(args = {})
s = self.alloc.initWithNibName(nil, bundle:nil) # Use your custom initializer if you want.
s.on_create(args)
s
end
def viewDidLoad
super
self.view_did_load if self.respond_to?(:view_did_load)
end
def viewWillAppear(animated)
super
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
end
def viewDidAppear(animated)
super
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
end
def viewWillDisappear(animated)
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
super
end
def viewDidDisappear(animated)
self.view_did_disappear(animated) if self.respond_to?("view_did_disappear:")
super
end
def shouldAutorotateToInterfaceOrientation(orientation)
self.should_rotate(orientation)
end
def shouldAutorotate
self.should_autorotate
end
def willRotateToInterfaceOrientation(orientation, duration:duration)
self.will_rotate(orientation, duration)
end
def didRotateFromInterfaceOrientation(orientation)
self.on_rotate
end
end
```

View File

@@ -1,7 +1,7 @@
PATH
remote: .
specs:
ProMotion (0.6.0)
ProMotion (0.6.1)
GEM
remote: https://rubygems.org/

10
PROMOTION_APPS.md Normal file
View File

@@ -0,0 +1,10 @@
### BigDay! Reminder App
Check out the free [BigDay! Reminder app](https://itunes.apple.com/us/app/bigday!/id571756685?ls=1&mt=8) on the
App Store to see what's possible. ClearSight Studio built the app for Kijome Software, a small app investment company.
### TipCounter App
[TipCounter](http://www.tipcounterapp.com) was built by [Matt Brewer](https://github.com/macfanatic/) for bartenders and servers to easily track their tips. Used ProMotion and the development was a lot of fun!
### Winston-Salem Crime Map
Have an interest in crime statistics and locations? Live in Winston-Salem, NC? This hyper-local and [open source](https://github.com/markrickert/WSCrime) RubyMotion app uses a mixture custom UIViewControllers and ProMotion for ease of attribute setting and adding views. Check it out [on the App Store](http://www.mohawkapps.com/winston-salem-crime-map/download/) or [fork it and contribute](https://github.com/markrickert/WSCrime)!

158
README.md
View File

@@ -56,15 +56,7 @@ This is pretty bare-bones, but we'll be building it out as we go along.
## Apps Built With ProMotion
### BigDay! Reminder App
Check out the free [BigDay! Reminder app](https://itunes.apple.com/us/app/bigday!/id571756685?ls=1&mt=8) on the
App Store to see what's possible. ClearSight Studio built the app for Kijome Software, a small app investment company.
### TipCounter App
[TipCounter](http://www.tipcounterapp.com) was built by [Matt Brewer](https://github.com/macfanatic/) for bartenders and servers to easily track their tips. Used ProMotion and the development was a lot of fun!
### Winston-Salem Crime Map
Have an interest in crime statistics and locations? Live in Winston-Salem, NC? This hyper-local and [open source](https://github.com/markrickert/WSCrime) RubyMotion app uses a mixture custom UIViewControllers and ProMotion for ease of attribute setting and adding views. Check it out [on the App Store](http://www.mohawkapps.com/winston-salem-crime-map/download/) or [fork it and contribute](https://github.com/markrickert/WSCrime)!
[View apps built with ProMotion (feel free to submit yours in a pull request!)](https://github.com/clearsightstudio/ProMotion/blob/master/PROMOTION_APPS.md)
# Getting Started
@@ -116,7 +108,7 @@ Run `bundle install` in Terminal to install ProMotion.
Go into your app/app_delegate.rb file and replace everything with the following:
```ruby
class AppDelegate < ProMotion::Delegate
class AppDelegate < PM::Delegate
def on_load(app, options)
open HomeScreen.new(nav_bar: true)
end
@@ -136,7 +128,7 @@ Create a folder in `/app` named `screens`. Create a file in that folder named `h
Now drop in this code:
```ruby
class HomeScreen < ProMotion::Screen
class HomeScreen < PM::Screen
title "Home"
def will_appear
@@ -160,7 +152,7 @@ Run `rake`. You should now see the simulator open with your home screen and a na
* Will auto-detect if you've loaded [motion-xray](https://github.com/colinta/motion-xray) and enable it.
* Added `open_split_screen` for iPad-supported apps (thanks @rheoli for your contributions to this)
* Added `refreshable` to TableScreens (thanks to @markrickert) for pull-to-refresh support.
* `ProMotion::AppDelegateParent` renamed to `ProMotion::Delegate` (`AppDelegateParent` is an alias)
* `PM::AppDelegateParent` renamed to `PM::Delegate` (`AppDelegateParent` is an alias)
* `set_attributes` and `add` now apply nested attributes recursively
* `set_attributes` and `add` now accept snake_case instead of camelCase methods (e.g., background_color)
* Added `add_to` method for adding views to any parent view. `remove` works with this normally.
@@ -172,7 +164,7 @@ Run `rake`. You should now see the simulator open with your home screen and a na
## Creating a basic screen
```ruby
class HomeScreen < ProMotion::Screen
class HomeScreen < PM::Screen
title "Home"
def on_load
@@ -194,7 +186,7 @@ end
```ruby
# In app/app_delegate.rb
class AppDelegate < ProMotion::Delegate
class AppDelegate < PM::Delegate
def on_load(app, options)
open MyHomeScreen.new(nav_bar: true)
end
@@ -205,7 +197,7 @@ end
```ruby
# In app/app_delegate.rb
class AppDelegate < ProMotion::Delegate
class AppDelegate < PM::Delegate
def on_load(app, options)
open_split_screen MenuScreen, DetailScreen
end
@@ -249,20 +241,30 @@ end
## Add navigation bar buttons
These two methods add the buttons to the top navigation bar of a screen. The `action:` lets you specify a method to
This method adds the buttons to the top navigation bar of a screen. The `action:` lets you specify a method to
call when that button is tapped, and you can pass in a UIBarButton style using `type:`.
```ruby
set_nav_bar_right_button "Save", action: :save_something, type: UIBarButtonItemStyleDone
set_nav_bar_left_button "Cancel", action: :return_to_some_other_screen, type: UIBarButtonItemStylePlain
set_nav_bar_button :right, title: "Save", action: :save_something, type: UIBarButtonItemStyleDone
set_nav_bar_button :left, title: "Cancel", action: :return_to_some_other_screen, type: UIBarButtonItemStylePlain
```
If you pass an instance of a `UIImage`, the `UIBarButton` will automatically display with that image instead of text. *Don't forget retina and landscape versions of your image!*
If you pass `:system` for the title, then you can get a system item. E.g.:
You can pass in an image with `image:`. *Don't forget retina and landscape versions of your image!*
```ruby
set_nav_bar_right_button nil, action: :add_something, system_icon: UIBarButtonSystemItemAdd
set_nav_bar_button :left, image: UIImage.imageNamed("cancel-button"), action: :cancel_something
```
You can also pass in a `system_icon` instead.
```ruby
set_nav_bar_button :right, system_icon: UIBarButtonSystemItemAdd, action: :add_something
```
Additionally, if you pass an instance of a `UIBarButtonItem`, the `UIBarButton` will automatically display that particular button item.
```ruby
set_nav_bar_button :left, button: UIBarButtonItem.alloc.initWithCustomView(button)
```
## Opening and closing screens
@@ -285,12 +287,16 @@ You can also open a screen as a modal.
```ruby
open SettingsScreen.new, modal: true
# Or... (this is equivalent)
open_modal SettingsScreen.new
```
You can pass in arguments to other screens if they have accessors:
```ruby
class HomeScreen < ProMotion::Screen
class HomeScreen < PM::Screen
# ...
def settings_button_tapped
@@ -298,7 +304,7 @@ class HomeScreen < ProMotion::Screen
end
end
class ProfileScreen < ProMotion::Screen
class ProfileScreen < PM::Screen
attr_accessor :user
def on_load
@@ -319,7 +325,7 @@ end
You can close a screen (modal or in a nav controller) and pass back arguments to the previous screen's "on_return" method:
```ruby
class ItemScreen < ProMotion::Screen
class ItemScreen < PM::Screen
# ...
def save_and_close
if @model.save
@@ -328,7 +334,7 @@ class ItemScreen < ProMotion::Screen
end
end
class MainScreen < ProMotion::Screen
class MainScreen < PM::Screen
# ...
def on_return(args = {})
if args[:model_saved]
@@ -344,7 +350,7 @@ It's common to want to open a screen in the same navigation controller if on iPh
in a separate detail view when on iPad. Here's a good way to do that.
```ruby
class MenuScreen < ProMotion::TableScreen
class MenuScreen < PM::TableScreen
# ...
def some_action
open SomeScreen.new, in_detail: true
@@ -407,7 +413,7 @@ add_to @some_parent_view, UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)),
You can create sectioned table screens easily with TableScreen, SectionedTableScreen, and GroupedTableScreen.
```ruby
class SettingsScreen < ProMotion::GroupedTableScreen
class SettingsScreen < PM::GroupedTableScreen
title "Settings"
def on_load
@@ -484,61 +490,7 @@ use only one section and set its value to `nil`. For example:
## Using your own UIViewController
Sometimes you want to inherit from a different UIViewController other than that provided by ProMotion,
such as when using [Formotion](https://github.com/clayallsopp/formotion). **RubyMotion doesn't currently
allow us to override built-in methods when including them as a module.** And we really need to override
`viewDidLoad` and others.
Fortunately, there's a workaround for that.
```ruby
class EventsScreen < Formotion::FormController # Can also be < UIViewController
include ProMotion::ScreenModule # Not TableScreenModule since we're using Formotion for that
# Required functions for ProMotion to work properly
def viewDidLoad
super
self.view_did_load if self.respond_to?(:view_did_load)
end
def viewWillAppear(animated)
super
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
end
def viewDidAppear(animated)
super
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
end
def viewWillDisappear(animated)
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
super
end
def viewDidDisappear(animated)
self.view_did_disappear(animated) if self.respond_to?("view_did_disappear:")
super
end
def shouldAutorotateToInterfaceOrientation(orientation)
self.should_rotate(orientation)
end
def shouldAutorotate
self.should_autorotate
end
def willRotateToInterfaceOrientation(orientation, duration:duration)
self.will_rotate(orientation, duration)
end
def didRotateFromInterfaceOrientation(orientation)
self.on_rotate
end
end
```
[Using your own UIViewController with ProMotion](https://github.com/clearsightstudio/ProMotion/blob/master/CUSTOM_VIEW_CONTROLLERS.md)
# Reference
@@ -602,18 +554,15 @@ end
</td>
</tr>
<tr>
<td>set_nav_bar_left_button(title, args = {})</td>
<td>set_nav_bar_button(side, args = {})</td>
<td>
Set a left nav bar button.<br />
`title` can be a `String` or a `UIImage`.
</td>
</tr>
<tr>
<td>set_nav_bar_right_button(title, args = {})</td>
<td>
Set a right nav bar button.<br />
`title` can be a `String` or a `UIImage`.
<img src="http://i.imgur.com/whbkc.png" />
Set a nav bar button.<br />
`side` can be :left or :right. `args` can include the following:<br />
title: "Button Title"<br />
image: (UIImage)<br />
system_icon: (UIBarButtonSystemItem)<br />
button: (UIBarButtonItem)<br />
</td>
</tr>
<tr>
@@ -727,6 +676,12 @@ end
Any accessors in <code>screen</code> can also be set in this hash.
</td>
</tr>
<tr>
<td>open_modal(screen, args = {})</td>
<td>
Same as <code>open HomeScreen, modal: true</code>
</td>
</tr>
<tr>
<td>open_split_screen(master, detail)</td>
<td>
@@ -810,7 +765,7 @@ def table_data
height: 50, # manually changes the cell's height
cell_style: UITableViewCellStyleSubtitle,
cell_identifier: "Cell",
cell_class: ProMotion::TableViewCell,
cell_class: PM::TableViewCell,
masks_to_bounds: true,
background_color: UIColor.whiteColor,
selection_style: UITableViewCellSelectionStyleGray,
@@ -916,7 +871,7 @@ end
</td>
<td>
Class method to output a colored console message.<br />
Example: <code>ProMotion::Console.log("This is red!", with_color: ProMotion::Console::RED_COLOR)</code>
Example: <code>PM::Console.log("This is red!", with_color: PM::Console::RED_COLOR)</code>
</td>
</tr>
</table>
@@ -929,7 +884,9 @@ Opening a ticket is usually the best and we respond to those pretty quickly.
# Contributing
I'm very open to ideas. Tweet me with your ideas or open a ticket (I don't mind!)
and let's discuss.
and let's discuss. **It's a good idea to run your idea by the committers before creating
a pull request.** We'll always consider your ideas carefully but not all ideas will be
incorporated.
## Working on Features
@@ -944,15 +901,16 @@ and let's discuss.
1. Fork the project
2. Create a feature branch
3. Code
4. Update or create new specs
4. Update or create new specs ** NOTE: your PR is far more likely to be merged if you include comprehensive tests! **
5. Make sure tests are passing by running `rake spec`
6. Submit pull request
7. Fame, adoration, kudos everywhere
7. Make a million little nitpicky changes that @jamonholmgren wants
8. Merged, then fame, adoration, kudos everywhere
## Primary Contributors
* Jamon Holmgren: [@jamonholmgren](https://twitter.com/jamonholmgren)
* Silas Matson: [@silasjmatson](https://twitter.com/silasjmatson)
* Matt Brewer: [@macfanatic](https://twitter.com/macfanatic)
* [Many others](https://github.com/clearsightstudio/ProMotion/graphs/contributors)

View File

@@ -10,10 +10,13 @@ module ProMotion
screen.send(:on_load) if screen.respond_to?(:on_load)
animated = args[:animated] || true
return self.split_screen.detail_screen = screen if args[:in_detail] && self.split_screen
return self.split_screen.master_screen = screen if args[:in_master] && self.split_screen
if args[:in_detail] && self.split_screen
self.split_screen.detail_screen = screen
if args[:close_all]
elsif args[:in_master] && self.split_screen
self.split_screen.master_screen = screen
elsif args[:close_all]
open_root_screen screen
elsif args[:modal]
@@ -25,11 +28,8 @@ module ProMotion
elsif self.navigation_controller
push_view_controller screen
elsif screen.respond_to?(:main_controller)
open_view_controller screen.main_controller
else
open_view_controller screen
open_root_screen screen
end
@@ -40,6 +40,10 @@ module ProMotion
app_delegate.open_root_screen(screen)
end
def open_modal(screen, args = {})
open screen, args.merge({ modal: true })
end
def app_delegate
UIApplication.sharedApplication.delegate
end
@@ -72,8 +76,9 @@ module ProMotion
end
end
def open_view_controller(vc)
app_delegate.load_root_view vc
def open_view_controller(screen)
PM.logger.deprecated "Use `open_root_screen` instead of the more ambiguous `open_view_controller`."
open_root_screen screen
end
def push_view_controller(vc, nav_controller=nil)
@@ -129,6 +134,8 @@ module ProMotion
screen.navigation_controller = vc if screen.respond_to?("navigation_controller=")
push_view_controller(screen, vc)
else
# TODO: This should probably open the vc, shouldn't it?
# This isn't well tested and needs to work better.
self.tab_bar.selectedIndex = vc.tabBarItem.tag
end

View File

@@ -19,7 +19,11 @@ module ProMotion
[ master, detail ].map { |s| s.on_load if s.respond_to?(:on_load) }
split_screen_controller master, detail
split = split_screen_controller master, detail
if args.has_key?(:icon) or args.has_key?(:title)
split.tabBarItem = create_tab_bar_item(args)
end
split
end
def open_split_screen(master, detail, args={})
@@ -39,4 +43,4 @@ module ProMotion
svc.detail_screen.navigationItem.leftBarButtonItem = nil
end
end
end
end

View File

@@ -6,13 +6,16 @@ module ProMotion
include ProMotion::ScreenTabs
include ProMotion::SplitScreen if NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].include?("2")
attr_accessor :parent_screen, :first_screen, :tab_bar_item, :tab_bar, :modal, :split_screen
attr_accessor :parent_screen, :first_screen, :tab_bar_item, :tab_bar, :modal, :split_screen, :title
def on_create(args = {})
unless self.is_a?(UIViewController)
raise StandardError.new("ERROR: Screens must extend UIViewController or a subclass of UIViewController.")
end
self.title = self.class.send(:get_title)
args.each do |k, v|
self.send("#{k}=", v) if self.respond_to?("#{k}=")
end
@@ -72,29 +75,36 @@ module ProMotion
set_nav_bar_button :left, args
end
# If you call set_nav_bar_button with a nil title and system_icon: UIBarButtonSystemItemAdd (or any other
# system icon), the button is initialized with a barButtonSystemItem instead of a title.
def set_nav_bar_button(side, args={})
args[:style] ||= UIBarButtonItemStyleBordered
args[:target] ||= self
args[:action] ||= nil
button_type = args[:image] || args[:button] || args[:system_icon] || args[:title] || "Button"
button = case args[:title]
when String
UIBarButtonItem.alloc.initWithTitle(args[:title], style: args[:style], target: args[:target], action: args[:action])
when UIImage
UIBarButtonItem.alloc.initWithImage(args[:title], style: args[:style], target: args[:target], action: args[:action])
when Symbol, NilClass
UIBarButtonItem.alloc.initWithBarButtonSystemItem(args[:system_icon], target: args[:target], action: args[:action]) if args[:system_icon]
else
PM.logger.error("Please supply a title string, a UIImage or :system.")
end
button = bar_button_item button_type, args
self.navigationItem.leftBarButtonItem = button if side == :left
self.navigationItem.rightBarButtonItem = button if side == :right
button
end
def bar_button_item(button_type, args)
case button_type
when UIBarButtonItem
button_type
when UIImage
UIBarButtonItem.alloc.initWithImage(button_type, style: args[:style], target: args[:target], action: args[:action])
when String
UIBarButtonItem.alloc.initWithTitle(button_type, style: args[:style], target: args[:target], action: args[:action])
else
if args[:system_icon]
UIBarButtonItem.alloc.initWithBarButtonSystemItem(args[:system_icon], target: args[:target], action: args[:action])
else
PM.logger.error("Please supply a title string, a UIImage or :system.")
end
end
end
# [DEPRECATED]
def view_controller=(vc)
@@ -136,15 +146,6 @@ module ProMotion
end
def on_disappear; end
def title
self.class.send(:get_title)
end
def title=(new_title)
self.class.title = new_title
super
end
def main_controller
self.navigation_controller || self
end

View File

@@ -0,0 +1,65 @@
module ProMotion
if defined?(Formotion) && defined?(Formotion::FormController)
class FormotionScreen < Formotion::FormController
include ProMotion::ScreenModule
def self.new(args = {})
s = self.alloc.initWithStyle(UITableViewStyleGrouped)
s.on_create(args) if s.respond_to?(:on_create)
if s.respond_to?(:table_data)
s.form = s.table_data
elsif args[:form]
s.form = args[:form]
else
PM.logger.error "PM::FormotionScreen requires a `table_data` method or form: to be passed into `new`."
end
s.tableView.allowsSelectionDuringEditing = true
s
end
def viewDidLoad
super
self.view_did_load if self.respond_to?(:view_did_load)
end
def viewWillAppear(animated)
super
self.view_will_appear(animated) if self.respond_to?(:view_will_appear)
end
def viewDidAppear(animated)
super
self.view_did_appear(animated) if self.respond_to?(:view_did_appear)
end
def viewWillDisappear(animated)
self.view_will_disappear(animated) if self.respond_to?(:view_will_disappear)
super
end
def viewDidDisappear(animated)
self.view_did_disappear(animated) if self.respond_to?(:view_did_disappear)
super
end
def shouldAutorotateToInterfaceOrientation(orientation)
self.should_rotate(orientation)
end
def shouldAutorotate
self.should_autorotate
end
def willRotateToInterfaceOrientation(orientation, duration:duration)
self.will_rotate(orientation, duration)
end
def didRotateFromInterfaceOrientation(orientation)
self.on_rotate
end
end
end
end

View File

@@ -1,3 +1,3 @@
module ProMotion
VERSION = "0.6.0" unless defined?(ProMotion::VERSION)
VERSION = "0.6.1" unless defined?(ProMotion::VERSION)
end

0
resources/list.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 104 B

After

Width:  |  Height:  |  Size: 104 B

View File

@@ -1,2 +1,3 @@
class BasicScreen < ProMotion::Screen
title "Basic"
end

View File

@@ -0,0 +1,3 @@
class DetailScreen < PM::Screen
title "Detail"
end

View File

@@ -0,0 +1,3 @@
class MasterScreen < PM::Screen
title "Master"
end

View File

@@ -0,0 +1,55 @@
class ScreenModuleViewController < UIViewController
include PM::ScreenModule
title 'Test Title'
# Get rid of such hackiness when RubyMotion bug is fixed...
def self.new(args = {})
s = self.alloc.initWithNibName(nil, bundle:nil)
s.on_create(args) if s.respond_to?(:on_create)
s
end
def viewDidLoad
super
self.view_did_load if self.respond_to?(:view_did_load)
end
def viewWillAppear(animated)
super
self.view_will_appear(animated) if self.respond_to?("view_will_appear:")
end
def viewDidAppear(animated)
super
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
end
def viewWillDisappear(animated)
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
super
end
def viewDidDisappear(animated)
if self.respond_to?("view_did_disappear:")
self.view_did_disappear(animated)
end
super
end
def shouldAutorotateToInterfaceOrientation(orientation)
self.should_rotate(orientation)
end
def shouldAutorotate
self.should_autorotate
end
def willRotateToInterfaceOrientation(orientation, duration:duration)
self.will_rotate(orientation, duration)
end
def didRotateFromInterfaceOrientation(orientation)
self.on_rotate
end
end

View File

@@ -1,9 +1,4 @@
class TestDelegate < ProMotion::Delegate
def on_load(app, options)
end
# Hack to make RM 2.0 work.
# Ref: http://hipbyte.myjetbrains.com/youtrack/issue/RM-136
def dealloc
end
end

View File

@@ -68,6 +68,15 @@ describe "screen helpers" do
@screen.navigationItem.leftBarButtonItem.image.should == image
end
it "should add a left UIBarButtonItem" do
@screen.set_nav_bar_left_button @screen.editButtonItem
@screen.navigationItem.leftBarButtonItem.class.should == UIBarButtonItem
end
it "should add a right UIBarButtonItem" do
@screen.set_nav_bar_right_button @screen.editButtonItem
@screen.navigationItem.rightBarButtonItem.class.should == UIBarButtonItem
end
end
describe "screen navigation" do
@@ -132,7 +141,7 @@ describe "screen helpers" do
it "should open a root screen if :close_all is provided" do
@screen.mock!(:open_root_screen) { |screen| screen.should.be.instance_of BasicScreen }
@screen.open_screen BasicScreen, close_all: true
@screen.open BasicScreen, close_all: true
end
it "should present a modal screen if :modal is provided" do
@@ -140,7 +149,15 @@ describe "screen helpers" do
screen.should.be.instance_of BasicScreen
animated.should == true
end
@screen.open_screen BasicScreen, modal: true
@screen.open BasicScreen, modal: true
end
it "should present a modal screen if open_modal is used" do
@screen.mock!(:present_modal_view_controller) do |screen, animated|
screen.should.be.instance_of BasicScreen
animated.should == true
end
@screen.open_modal BasicScreen
end
it "should open screen in tab bar if :in_tab is provided" do
@@ -149,28 +166,18 @@ describe "screen helpers" do
screen.should.be.instance_of BasicScreen
tab_name.should == 'my_tab'
end
@screen.open_screen BasicScreen, in_tab: 'my_tab'
@screen.open BasicScreen, in_tab: 'my_tab'
end
it "should pop onto navigation controller if current screen is on nav stack already" do
@screen.mock!(:push_view_controller) { |vc| vc.should.be.instance_of BasicScreen }
@screen.open_screen BasicScreen
@screen.open BasicScreen
end
it "should open the main controller if no options are provided" do
parent_screen = HomeScreen.new
nav_controller = ProMotion::NavigationController.new
new_screen = BasicScreen.new
new_screen.stub! :main_controller, return: nav_controller
parent_screen.mock!(:open_view_controller) { |vc| vc.should.be == nav_controller }
parent_screen.open_screen new_screen
end
it "should open the provided view controller if no other conditions are met" do
it "should open the provided view controller as root view if no other conditions are met" do
parent_screen = HomeScreen.new
new_screen = BasicScreen.new
parent_screen.mock!(:open_view_controller) { |vc| vc.should.be == new_screen }
parent_screen.mock!(:open_root_screen) { |vc| vc.should.be == new_screen }
parent_screen.open_screen new_screen
end

View File

@@ -0,0 +1,13 @@
describe "PM::ScreenModule" do
before { @subject = ScreenModuleViewController.new }
it 'should have PM::ScreenModule in ancestors' do
@subject.class.ancestors.include?(PM::ScreenModule).should == true
end
it 'should have a title from class method #title' do
@subject.title.should == 'Test Title'
end
end

View File

@@ -12,9 +12,18 @@ describe "screen properties" do
HomeScreen.get_title.should == 'Home'
end
it "should let the instance reset the title" do
it "should set default title on new instances" do
@screen.title.should == "Home"
end
it "should let the instance set its title" do
@screen.title = "instance method"
HomeScreen.get_title.should == 'instance method'
@screen.title.should == 'instance method'
end
it "should not let the instance reset the default title" do
@screen.title = "instance method"
HomeScreen.get_title.should != 'instance method'
end
it "should store debug mode" do

View File

@@ -6,10 +6,14 @@ describe "split screen in tab bar functionality" do
@master_screen = HomeScreen.new nav_bar: true
@detail_screen = BasicScreen.new nav_bar: true
@split_screen = @app.create_split_screen @master_screen, @detail_screen
@split_screen = @app.create_split_screen @master_screen, @detail_screen, icon: "list", title: "Spec"
@tab = @app.open_tab_bar @split_screen, HomeScreen, BasicScreen
end
after do
@split_screen.delegate = nil # dereference to avoid memory issue
end
it "should create a UISplitViewController" do
@split_screen.is_a?(UISplitViewController).should == true
end
@@ -45,5 +49,18 @@ describe "split screen in tab bar functionality" do
it "should set the tab bar first viewController to the split screen" do
@tab.viewControllers.first.should == @split_screen
end
it "should set the bar bar item for the split screen" do
@split_screen.tabBarItem.is_a?(UITabBarItem).should == true
end
it "should set the tab bar icon of the split screen" do
@split_screen.tabBarItem.image.is_a?(UIImage).should == true
end
it "should set the tab bar title of the split screen" do
@split_screen.tabBarItem.title.is_a?(String).should == true
@split_screen.tabBarItem.title.should == "Spec"
end
end
end

View File

@@ -10,6 +10,10 @@ describe "split screen `open` functionality" do
@split_screen = @app.open_split_screen @master_screen, @detail_screen_1
end
after do
@split_screen.delegate = nil # dereference to avoid memory issue
end
it "should open a new screen in the detail view" do
@master_screen.open @detail_screen_2, in_detail: true
@split_screen.detail_screen.should == @detail_screen_2
@@ -43,4 +47,4 @@ describe "split screen `open` functionality" do
home.navigation_controller.topViewController.should == child
end
end
end

View File

@@ -3,12 +3,16 @@ describe "split screen functionality" do
before do
@app = TestDelegate.new
@master_screen = HomeScreen.new nav_bar: true
@detail_screen = BasicScreen.new # no nav_bar on this one
@master_screen = MasterScreen.new nav_bar: true
@detail_screen = DetailScreen.new # no nav_bar on this one
@split_screen = @app.open_split_screen @master_screen, @detail_screen
end
after do
@split_screen.delegate = nil # dereference to avoid memory issue
end
it "should have created a split screen" do
@split_screen.should != nil
@split_screen.is_a?(UISplitViewController).should == true
@@ -22,14 +26,42 @@ describe "split screen functionality" do
@app.window.rootViewController.should == @split_screen
end
it "should set the first viewController to HomeScreen" do
it "should set the first viewController to MasterScreen" do
@split_screen.master_screen.should == @master_screen
@split_screen.viewControllers.first.should == @master_screen.main_controller
end
it "should set the second viewController to BasicScreen" do
it "should set the second viewController to DetailScreen" do
@split_screen.detail_screen.should == @detail_screen
@split_screen.viewControllers.last.should == @detail_screen.main_controller
end
end
it "should set the title on both screens" do
@master_screen.class.send(:get_title).should == "Master"
@master_screen.title.should == "Master"
@detail_screen.class.send(:get_title).should == "Detail"
@detail_screen.title.should == "Detail"
end
end
# Regression test for https://github.com/clearsightstudio/ProMotion/issues/74
describe "split screen with UIViewControllers with ScreenModule" do
before do
@app = TestDelegate.new
@master_screen = ScreenModuleViewController.new
@detail_screen = DetailScreen.new(nav_bar: true)
@split_screen = @app.open_split_screen @master_screen, @detail_screen
end
it "should set the title on both screens" do
@master_screen.class.send(:get_title).should == "Test Title"
@master_screen.title.should == "Test Title"
@detail_screen.class.send(:get_title).should == "Detail"
@detail_screen.title.should == "Detail"
end
end