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

Conflicts:
	.travis.yml
	Rakefile
This commit is contained in:
Steve Ross
2015-03-03 19:28:01 -08:00
32 changed files with 378 additions and 106 deletions

View File

@@ -3,7 +3,7 @@ before_install:
- (ruby --version)
- sudo chown -R travis ~/Library/RubyMotion
- mkdir -p ~/Library/RubyMotion/build
- sudo motion update --cache-version=3.6
- sudo motion update
gemfile:
- Gemfile
script:

View File

@@ -14,6 +14,7 @@ Over 30 developers have contributed to ProMotion. We love it when ProMotion user
3. Code
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 `bundle exec rake spec`
6. Submit pull request to `master`
7. Make a million little nitpicky changes that @jamonholmgren wants
8. Merged, then fame, adoration, kudos everywhere
6. Update relevant documentation in `./docs`
7. Submit pull request to `master`
8. Make a million little nitpicky changes that @jamonholmgren wants
9. Merged, then fame, adoration, kudos everywhere

View File

@@ -68,16 +68,16 @@ end
|Screens|Navigation Bars|Tab Bars|
|---|---|---|
|![ProMotion Screen](https://f.cloud.github.com/assets/1479215/1534021/060aaaac-4c8f-11e3-903c-743e54252222.png)|![ProMotion Nav Bar](https://f.cloud.github.com/assets/1479215/1534077/db39aab6-4c8f-11e3-83f7-e03d52ac615d.png)|![ProMotion Tabs](https://f.cloud.github.com/assets/1479215/1534115/9f4c4cd8-4c90-11e3-9285-96ac253facda.png)|
|[![ProMotion Screen](https://f.cloud.github.com/assets/1479215/1534021/060aaaac-4c8f-11e3-903c-743e54252222.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Screen/)|[![ProMotion Nav Bar](https://f.cloud.github.com/assets/1479215/1534077/db39aab6-4c8f-11e3-83f7-e03d52ac615d.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Screen/#set_nav_bar_buttonside-args)|[![ProMotion Tabs](https://f.cloud.github.com/assets/1479215/1534115/9f4c4cd8-4c90-11e3-9285-96ac253facda.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Tabs/)|
|Table Screens|Grouped Tables|Searchable|Refreshable|
|---|---|---|---|
|![ProMotion TableScreen](https://f.cloud.github.com/assets/1479215/1534137/ed71e864-4c90-11e3-98aa-ed96049f5407.png)|![Grouped Table Screen](https://f.cloud.github.com/assets/1479215/1589973/61a48610-5281-11e3-85ac-abee99bf73ad.png)|![Searchable](https://f.cloud.github.com/assets/1479215/1534299/20cc05c6-4c93-11e3-92ca-9ee39c044457.png)|![Refreshable](https://f.cloud.github.com/assets/1479215/1534317/5a14ef28-4c93-11e3-8e9e-f8c08d8464f8.png)|
|[![ProMotion TableScreen](https://f.cloud.github.com/assets/1479215/1534137/ed71e864-4c90-11e3-98aa-ed96049f5407.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/)|[![Grouped Table Screen](https://f.cloud.github.com/assets/1479215/1589973/61a48610-5281-11e3-85ac-abee99bf73ad.png)](https://gist.github.com/jamonholmgren/382a6cf9963c5f0b2248)|[![Searchable](https://f.cloud.github.com/assets/1479215/1534299/20cc05c6-4c93-11e3-92ca-9ee39c044457.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/#searchableplaceholder-placeholder-text)|[![Refreshable](https://f.cloud.github.com/assets/1479215/1534317/5a14ef28-4c93-11e3-8e9e-f8c08d8464f8.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/#refreshableoptions)|
|iPad SplitScreens|Map Screens|Web Screens|
|---|---|---|
|![ProMotion SplitScreens](https://f.cloud.github.com/assets/1479215/1534507/0edb8dd4-4c96-11e3-9896-d4583d0ed161.png)|![MapScreen](https://f.cloud.github.com/assets/1479215/1534628/f7dbf7e8-4c97-11e3-8817-4c2a58824771.png)|![ProMotion WebScreen](https://f.cloud.github.com/assets/1479215/1534631/ffe1b36a-4c97-11e3-8c8f-c7b14e26182d.png)|
|[![ProMotion SplitScreens](https://f.cloud.github.com/assets/1479215/1534507/0edb8dd4-4c96-11e3-9896-d4583d0ed161.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20SplitScreen/)|[![MapScreen](https://f.cloud.github.com/assets/1479215/1534628/f7dbf7e8-4c97-11e3-8817-4c2a58824771.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20MapScreen/)|[![ProMotion WebScreen](https://f.cloud.github.com/assets/1479215/1534631/ffe1b36a-4c97-11e3-8c8f-c7b14e26182d.png)](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20WebScreen/)|
#### ...and much more.
@@ -105,7 +105,7 @@ This release includes several new features and is backwards compatible with all
# Apps built on ProMotion
[Apps built on ProMotion](https://github.com/clearsightstudio/ProMotion/wiki/Apps-built-on-ProMotion)
[Apps built on ProMotion](http://promotion.readthedocs.org/en/master/ProMotion%20Apps/)
##Your app
@@ -115,7 +115,7 @@ Tweet [@jamonholmgren](https://twitter.com/jamonholmgren) if you built an app in
We've created a comprehensive and always updated wiki with code examples, usage examples, and API reference.
### [ProMotion API Reference](https://github.com/clearsightstudio/ProMotion/wiki)
### [ProMotion API Reference](http://promotion.readthedocs.org/en/master/)
# Help

View File

@@ -1,9 +1,5 @@
# -*- coding: utf-8 -*-
RM_VERSION = "3.6" # Update .travis.yml too
unless File.exist?("/Library/RubyMotion#{RM_VERSION}/lib")
abort "Couldn't find RubyMotion #{RM_VERSION}. Run `sudo motion update --cache-version=#{RM_VERSION}`."
end
$:.unshift("/Library/RubyMotion#{RM_VERSION}/lib")
$:.unshift("/Library/RubyMotion/lib")
require 'motion/project/template/ios'
require 'bundler'
Bundler.require(:development)

View File

@@ -1,3 +1,5 @@
class DetailScreen < PM::Screen
title "Detail"
nav_bar_button :right, title: "More", style: :plain, action: :back
end

View File

@@ -1,11 +1,13 @@
class FunctionalScreen < PM::Screen
attr_accessor :button_was_triggered
attr_accessor :button2_was_triggered
attr_accessor :on_back_fired
title "Functional"
def will_appear
self.button_was_triggered = false
self.button2_was_triggered = false
add UILabel.alloc.initWithFrame([[ 10, 10 ], [ 300, 40 ]]), { text: "Label Here" }
end
@@ -13,6 +15,10 @@ class FunctionalScreen < PM::Screen
self.button_was_triggered = true
end
def triggered_button2
self.button2_was_triggered = true
end
def on_back
@on_back_fired = true
end

View File

@@ -1,4 +1,4 @@
class TabScreen < PM::Screen
title "Tab"
tab_bar_item title: "Tab Item", item: "list"
tab_bar_item title: "Tab Item", item: "list", image_insets: [5,5,5,5]
end

View File

@@ -1,8 +1,7 @@
class TestDelegate < ProMotion::Delegate
status_bar false
attr_accessor :called_on_load, :called_will_load, :called_on_activate, :called_will_deactivate, :called_on_enter_background, :called_will_enter_foreground, :called_on_unload
attr_accessor :called_on_load, :called_will_load, :called_on_activate, :called_will_deactivate, :called_on_enter_background, :called_will_enter_foreground, :called_on_unload, :called_on_tab_selected
def on_load(app, options)
self.called_on_load = true
end
@@ -31,4 +30,7 @@ class TestDelegate < ProMotion::Delegate
self.called_on_unload = true
end
def on_tab_selected(vc)
self.called_on_tab_selected = true
end
end

View File

@@ -1,6 +1,6 @@
class TestTableScreen < ProMotion::TableScreen
attr_accessor :tap_counter, :cell_was_deleted, :got_index_path, :cell_was_moved, :got_will_display_header
attr_accessor :tap_counter, :cell_was_deleted, :got_index_path, :cell_was_moved
title 'Test title'
tab_bar_item title: 'Test tab title', item: 'test'
row_height :auto, estimated: 97
@@ -136,12 +136,20 @@ class TestTableScreen < ProMotion::TableScreen
end
end
def on_cell_moved(args={})
self.cell_was_moved = args
def will_display_header(view, section)
@got_will_display_header = {view: view, section: section}
end
def table_header_view
UIImageView.alloc.initWithImage(UIImage.imageNamed('test'))
end
def table_footer_view
UIView.alloc.initWithFrame(CGRectZero)
end
def on_cell_moved(args={})
self.cell_was_moved = args
end
end

View File

@@ -49,6 +49,41 @@ end
### Methods
#### app
Returns the `UIApplication.sharedApplication`
```ruby
# Instead of
UIApplication.sharedApplication.someMethod
# Use
app.someMethod
```
#### app_delegate
Returns the `UIApplication.sharedApplication.delegate`
```ruby
# Instead of
UIApplication.sharedApplication.delegate.someMethod
# Use
app_delegate.someMethod
```
#### app_window
Returns the current `app_delegate`s `UIWindow.
```ruby
app_window.addSubview someView
```
### try(method, *args)
Sends `method(*args)` to the current screen if the current screen will `respond_to?(method)`
#### modal?
Returns if the screen was opened in a modal window.
@@ -100,7 +135,7 @@ end
#### on_present
Runs just after the screen is pushed onto the navigation controller.
Runs just after the screen is pushed onto the navigation controller.
```ruby
def on_present
@@ -176,6 +211,20 @@ end
The code above will add a "cancel" back button to `MyScreenChild` when it is opened as a descendant of `MyScreen`.
#### set_nav_bar_buttons(side, button_array)
Allows you to set multiple buttons on one side of the nav bar with a single method call. The second parameter should be an array of any mixture of UIBarButtonItem instances and hash constructors used in set_nav_bar_button
```ruby
set_nav_bar_buttons :right, [{
custom_view: my_custom_view_button
},{
title: "Tasks",
image: UIImage.imageNamed("whatever"),
action: nil
}]
```
#### set_toolbar_items(buttons = [], animated = true)
Uses an array to set the navigation controllers toolbar items and shows the toolbar. Uses the same hash formatted parameters as `set_nav_bar_button`. When calling this method, the toolbar will automatically be shown (even if the screen was created without a toolbar). Use the `animated` parameter to specify if the toolbar showing should be animated or not.
@@ -292,7 +341,7 @@ open_modal ModalScreen.new(nav_bar: true,
presentation_style: UIModalPresentationFormSheet)
# From any screen (same as `open_root_screen`)
open HomeScreen.new(nav_bar: true), close_all: true
open HomeScreen.new(nav_bar: true), close_all: true
# Opening a screen in a different tab or split view screen
open DetailScreen.new, in_tab: "Tab name" # if you're in a tab bar
@@ -417,7 +466,7 @@ end
#### status_bar(style=nil, args={animation: UIStatusBarAnimationSlide})
Set the properties of the applications' status bar. Options for style are: `:none`, `:light` and `:default`. The animation argument should be a `UIStatusBarAnimation` (or `:none` / `:fade` / `:slide`) and is used to hide or show the status bar when appropriate and defaults to `:slide`.
Set the properties of the applications' status bar. Options for style are: `:none`, `:light` and `:default`. The animation argument should be a `UIStatusBarAnimation` (or `:none` / `:fade` / `:slide`) and is used to hide or show the status bar when appropriate and defaults to `:slide`.
```ruby
class MyScreen < PM::Screen
@@ -430,6 +479,18 @@ class MyScreenWithADarkColoredNavBar < PM::Screen
# ...
end
```
#### nav_bar_button(position, button_options)
Creates a nav bar button in the specified position with the given options
```ruby
class HomeScreen < PM::Screen
nav_bar_button :left, title: "Back", style: :plain, action: :back
# ...
end
```
---
### Accessors
@@ -455,4 +516,4 @@ Alias for self.view.bounds
#### frame
Alias for self.view.frame
Alias for self.view.frame

View File

@@ -58,7 +58,7 @@ Example of a `PM::GroupedTableScreen`: https://gist.github.com/jamonholmgren/382
### Methods
#### table_data
Method that is called to get the table's cell data and build the table.
It consists of an array of cell sections, each of which contain an array of cells.
@@ -178,15 +178,15 @@ class MyTableScreen < PM::TableScreen
}
end
}]
update_table_data
end
end
def table_data
@table_data ||= []
end
def tapped_item(item)
open ItemDetailScreen.new(item: item)
end
@@ -241,7 +241,7 @@ end
#### table_header_view
You can give the table a custom header view (this is different from a section header view) by defining:
You can give the table a custom header view (this is different from a section header view, which is below) by defining:
```ruby
def table_header_view
@@ -251,12 +251,35 @@ end
This is useful for information that needs to only be at the very top of a table.
#### will_display_header(view)
You can customize the section header views just before they are displayed on the table. This is different from table header view, which is above.
```ruby
def will_display_header(view)
view.tintColor = UIColor.redColor
view.textLabel.setTextColor(UIColor.blueColor)
end
```
#### table_footer_view
You can give the table a custom header view (this is different from a section footer view) by defining:
```ruby
def table_footer_view
# Return a UIView subclass here and it will be set at the bottom of the table.
end
```
This is useful for information that needs to only be at the very bottom of a table.
---
### Class Methods
#### searchable(placeholder: "placeholder text")
Class method to make the current table searchable.
```ruby
@@ -267,6 +290,14 @@ end
![Searchable Image](http://clrsight.co/jh/Screen_Shot_2014-06-21_at_9.01.09_PM.png)
To initially hide the search bar behind the nav bar until the user scrolls it into view, use `hide_initially`.
```ruby
class MyTableScreen < PM::TableScreen
searchable hide_initially: true
end
```
You can prevent any table cell from being included in search results by setting the cell attribute `searchable` to `false` like this:
```ruby
@@ -319,19 +350,19 @@ end
Class method to make the current table have pull-to-refresh. All parameters are optional.
If you do not specify a callback, it will assume you've implemented an <code>on_refresh</code>
method in your tableview.
method in your tableview.
![](https://camo.githubusercontent.com/fa0ac0a77e6170cca72f03f9ad2273c5b165e83d/68747470733a2f2f662e636c6f75642e6769746875622e636f6d2f6173736574732f313437393231352f313533343331372f35613134656632382d346339332d313165332d386539652d6638633038643834363466382e706e67)
```ruby
class MyTableScreen < PM::TableScreen
refreshable callback: :on_refresh,
pull_message: "Pull to refresh",
refreshing: "Refreshing data…",
updated_format: "Last updated at %s",
updated_time_format: "%l:%M %p"
def on_refresh
MyItems.pull_from_server do |items|
@my_items = items
@@ -339,7 +370,7 @@ class MyTableScreen < PM::TableScreen
update_table_data
end
end
end
```
@@ -414,4 +445,4 @@ The argument passed to `on_cell_moved` is a hash in the form of:
# Your other cell attributes
}
}
```
```

View File

@@ -24,7 +24,7 @@ It's recommended to use this method in your `on_init` method OR set it using the
```ruby
def on_init
set_tab_bar_item item: "custom_item_5", title: "Custom"
set_tab_bar_item system_item: :more
set_tab_bar_item system_item: :more
# :more, :favorites, :featured, :top_rated, :recents, :contacts,
# :history, :bookmarks, :search, :downloads, :most_recent, :most_viewed
end
@@ -53,6 +53,19 @@ open_tab "About"
open_tab 3 # fourth tab is opened
```
#### on_tab_selected(view_controller)
Provides a hook that is triggered when a tab is selected and passes in the view controller that has been displayed.
Keep in mind that this could be a UINavigationController or other wrapper, so to get the screen
you may need to request `view_controller.topViewController`.
```ruby
def on_tab_selected(view_controller)
# Do some action
view_controller.topViewController # => current screen
end
```
### Class Methods
#### tab_bar_item(args={})
@@ -62,7 +75,7 @@ Class method that sets the screen's default tab bar item.
```ruby
class TabScreen < PM::Screen
title "Tab"
tab_bar_item title: "Tab Item", item: "list"
tab_bar_item title: "Tab Item", item: "list", image_insets: [5,5,5,5]
end
```

View File

@@ -17,7 +17,11 @@ Motion::Project::App.setup do |app|
"#{core_lib}/table/cell/table_view_cell_module.rb" => [ "#{core_lib}/styling/styling.rb" ],
"#{core_lib}/delegate/delegate.rb" => [ "#{core_lib}/delegate/delegate_parent.rb" ],
"#{core_lib}/delegate/delegate_parent.rb" => [ "#{core_lib}/delegate/delegate_module.rb" ],
"#{core_lib}/delegate/delegate_module.rb" => [ "#{core_lib}/tabs/tabs.rb", "#{core_lib}/ipad/split_screen.rb" ],
"#{core_lib}/delegate/delegate_module.rb" => [
"#{core_lib}/support/support.rb",
"#{core_lib}/tabs/tabs.rb",
"#{core_lib}/ipad/split_screen.rb"
],
"#{core_lib}/screen/screen.rb" => [ "#{core_lib}/screen/screen_module.rb" ],
"#{core_lib}/screen/screen_module.rb" => [ "#{core_lib}/screen/screen_navigation.rb" ],
"#{core_lib}/table/data/table_data.rb" => [ "#{core_lib}/table/table.rb" ],

View File

@@ -1,6 +1,8 @@
module ProMotion
class TabBarController < UITabBarController
attr_accessor :pm_tab_delegate
def self.new(*screens)
tab_bar_controller = alloc.init
@@ -15,6 +17,7 @@ module ProMotion
end
tab_bar_controller.viewControllers = view_controllers
tab_bar_controller.delegate = tab_bar_controller
tab_bar_controller
end
@@ -27,6 +30,9 @@ module ProMotion
if selected_tab_vc
self.selectedViewController = selected_tab_vc
on_tab_selected_try(selected_tab_vc)
selected_tab_vc
else
PM.logger.error "Unable to open tab #{tab.to_s} -- not found."
nil
@@ -38,6 +44,9 @@ module ProMotion
end
# Cocoa touch methods below
def tabBarController(tbc, didSelectViewController: vc)
on_tab_selected_try(vc)
end
def shouldAutorotate
current_view_controller_try(:shouldAutorotate)
@@ -53,6 +62,12 @@ module ProMotion
private
def on_tab_selected_try(vc)
if pm_tab_delegate && pm_tab_delegate.respond_to?("on_tab_selected:")
pm_tab_delegate.send(:on_tab_selected, vc)
end
end
def current_view_controller
selectedViewController || viewControllers.first
end

View File

@@ -1,5 +1,6 @@
module ProMotion
module DelegateModule
include ProMotion::Support
include ProMotion::Tabs
include ProMotion::SplitScreen if UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad
@@ -42,18 +43,6 @@ module ProMotion
try :on_open_url, { url: url, source_app: source_app, annotation: annotation }
end
def app
UIApplication.sharedApplication
end
def app_delegate
self
end
def app_window
window
end
def ui_window
(defined?(Motion) && defined?(Motion::Xray) && defined?(Motion::Xray::XrayWindow)) ? Motion::Xray::XrayWindow : UIWindow
end
@@ -83,10 +72,6 @@ module ProMotion
self.class.send(:apply_status_bar)
end
def try(method, *args)
send(method, *args) if respond_to?(method)
end
public
module ClassMethods

View File

@@ -18,8 +18,8 @@ module ProMotion
end
def set_nav_bar_button(side, args={})
button = create_toolbar_button(args)
button.setTintColor args[:tint_color] if args[:tint_color]
button = (args.is_a?(UIBarButtonItem)) ? args : create_toolbar_button(args)
button.setTintColor args[:tint_color] if args.is_a?(Hash) && args[:tint_color]
self.navigationItem.leftBarButtonItem = button if side == :left
self.navigationItem.rightBarButtonItem = button if side == :right
@@ -28,6 +28,13 @@ module ProMotion
button
end
def set_nav_bar_buttons(side, buttons=[])
buttons = buttons.map{ |b| b.is_a?(UIBarButtonItem) ? b : create_toolbar_button(b) }.reverse
self.navigationItem.setLeftBarButtonItems(buttons) if side == :left
self.navigationItem.setRightBarButtonItems(buttons) if side == :right
end
# TODO: In PM 2.1+, entirely remove this deprecated method.
def set_nav_bar_left_button(title, args={})
PM.logger.deprecated "set_nav_bar_right_button and set_nav_bar_left_button have been removed. Use set_nav_bar_button :right/:left instead."

View File

@@ -1,5 +1,6 @@
module ProMotion
module ScreenModule
include ProMotion::Support
include ProMotion::ScreenNavigation
include ProMotion::Styling
include ProMotion::NavBarModule
@@ -13,6 +14,7 @@ module ProMotion
resolve_title
apply_properties(args)
add_nav_bar(args) if args[:nav_bar]
add_nav_bar_buttons
tab_bar_setup
try :screen_setup
try :on_init
@@ -46,6 +48,10 @@ module ProMotion
end
end
def add_nav_bar_buttons
set_nav_bar_button(self.class.get_nav_bar_button[:side], self.class.get_nav_bar_button) if self.class.get_nav_bar_button
end
def status_bar_hidden(hidden)
UIApplication.sharedApplication.setStatusBarHidden(hidden, withAnimation:self.class.status_bar_animation)
end
@@ -166,10 +172,6 @@ module ProMotion
return self.view_or_self.frame
end
def try(method, *args)
send(method, *args) if respond_to?(method)
end
private
def apply_properties(args)
@@ -229,6 +231,15 @@ module ProMotion
def status_bar_animation
@status_bar_animation || UIStatusBarAnimationSlide
end
def nav_bar_button(side, args={})
@nav_bar_button_args = args
@nav_bar_button_args[:side] = side
end
def get_nav_bar_button
@nav_bar_button_args
end
end
def self.included(base)

View File

@@ -1,5 +1,6 @@
module ProMotion
module ScreenNavigation
include ProMotion::Support
def open_screen(screen, args = {})
args = { animated: true }.merge(args)
@@ -32,14 +33,6 @@ module ProMotion
open screen, args.merge({ modal: true })
end
def app
UIApplication.sharedApplication
end
def app_delegate
UIApplication.sharedApplication.delegate
end
def close_screen(args = {})
args ||= {}
args = { sender: args } unless args.is_a?(Hash)
@@ -61,12 +54,15 @@ module ProMotion
alias :close :close_screen
def send_on_return(args = {})
if self.parent_screen && self.parent_screen.respond_to?(:on_return)
return unless self.parent_screen
if self.parent_screen.respond_to?(:on_return)
if args && self.parent_screen.method(:on_return).arity != 0
self.parent_screen.send(:on_return, args)
else
self.parent_screen.send(:on_return)
end
elsif self.parent_screen.private_methods.include?(:on_return)
PM.logger.warn "#{self.parent_screen.inspect} has an `on_return` method, but it is private and not callable from the closing screen."
end
end

View File

@@ -0,0 +1,21 @@
module ProMotion
module Support
def app
UIApplication.sharedApplication
end
def app_delegate
UIApplication.sharedApplication.delegate
end
def app_window
UIApplication.sharedApplication.delegate.window
end
def try(method, *args)
send(method, *args) if respond_to?(method)
end
end
end

View File

@@ -35,7 +35,7 @@ module ProMotion
end
def set_title
set_attributed_text(self.textLabel, data_cell[:title])
set_attributed_text(self.textLabel, data_cell[:title]) if data_cell[:title]
end
def set_subtitle

View File

@@ -16,7 +16,7 @@ module ProMotion
@table_search_display_controller.searchResultsDataSource = params[:data_source]
@table_search_display_controller.searchResultsDelegate = params[:search_results_delegate]
self.table_view.tableHeaderView = search_bar
self.tableView.tableHeaderView = search_bar
end
alias :makeSearchable :make_searchable

View File

@@ -15,7 +15,7 @@ module ProMotion
def screen_setup
check_table_data
set_up_header_view
set_up_header_footer_views
set_up_searchable
set_up_refreshable
set_up_longpressable
@@ -30,13 +30,15 @@ module ProMotion
@promotion_table_data ||= TableData.new(table_data, table_view, setup_search_method)
end
def set_up_header_view
if self.respond_to?(:table_header_view)
header_view = self.table_header_view
if header_view.is_a? UIView
self.tableView.tableHeaderView = header_view
else
PM.logger.warn "Table header views must be a UIView."
def set_up_header_footer_views
[:header, :footer].each do |hf_view|
if self.respond_to?("table_#{hf_view}_view".to_sym)
view = self.send("table_#{hf_view}_view")
if view.is_a? UIView
self.tableView.send(camelize("set_table_#{hf_view}_view:"), view)
else
PM.logger.warn "Table #{hf_view} view must be a UIView."
end
end
end
end
@@ -44,6 +46,9 @@ module ProMotion
def set_up_searchable
if self.class.respond_to?(:get_searchable) && self.class.get_searchable
self.make_searchable(content_controller: self, search_bar: self.class.get_searchable_params)
if self.class.get_searchable_params[:hide_initially]
self.tableView.contentOffset = CGPointMake(0, self.searchDisplayController.searchBar.frame.size.height)
end
end
end
@@ -307,6 +312,17 @@ module ProMotion
end
end
def tableView(tableView, willDisplayHeaderView:view, forSection:section)
action = :will_display_header
if respond_to?(action)
case self.method(action).arity
when 0 then self.send(action)
when 2 then self.send(action, view, section)
else self.send(action, view)
end
end
end
protected
def map_cell_editing_style(symbol)

View File

@@ -4,6 +4,7 @@ module ProMotion
def open_tab_bar(*screens)
self.tab_bar = PM::TabBarController.new(screens)
self.tab_bar.pm_tab_delegate = WeakRef.new(self)
delegate = self.respond_to?(:open_root_screen) ? self : UIApplication.sharedApplication.delegate
@@ -67,6 +68,7 @@ module ProMotion
tab_bar_item = create_tab_bar_item_custom(title, tab[:item], current_tag) if tab[:item]
tab_bar_item.badgeValue = tab[:badge_number].to_s unless tab[:badge_number].nil? || tab[:badge_number] <= 0
tab_bar_item.imageInsets = tab[:image_insets] if tab[:image_insets]
tab_bar_item
end

View File

@@ -79,11 +79,6 @@ describe "PM::Delegate" do
@subject.application(UIApplication.sharedApplication, openURL: url, sourceApplication:sourceApplication, annotation: annotation)
end
it "should have an awesome convenience method for UIApplication.sharedApplication" do
@subject.app.should == UIApplication.sharedApplication
end
end
# iOS 7 ONLY tests

View File

@@ -88,6 +88,11 @@ describe "screen helpers" do
end
end
it "allows setting a nav_bar_button with a class method" do
screen = DetailScreen.new(nav_bar: true)
screen.navigationItem.rightBarButtonItem.class.should == UIBarButtonItem
end
end
describe "screen navigation" do

View File

@@ -131,10 +131,6 @@ describe "screen properties" do
@screen.shouldAutorotateToInterfaceOrientation(UIInterfaceOrientationMaskPortrait)
end
it "should have an awesome convenience method for UIApplication.sharedApplication" do
@screen.app.should == UIApplication.sharedApplication
end
describe "iOS lifecycle methods" do
it "-viewDidLoad" do

View File

@@ -1,46 +1,53 @@
describe "split screen functionality" do
before do
@app = TestDelegate.new
def master_screen
@master_screen ||= MasterScreen.new nav_bar: true
end
@master_screen = MasterScreen.new nav_bar: true
@detail_screen = DetailScreen.new # no nav_bar on this one
def detail_screen
@detail_screen ||= DetailScreen.new # no nav_bar on this one
end
@split_screen = @app.open_split_screen @master_screen, @detail_screen
def app
@app ||= TestDelegate.new
end
def split_screen
@split_screen ||= app.open_split_screen master_screen, detail_screen
end
after do
@split_screen.delegate = nil # dereference to avoid memory issue
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
split_screen.should != nil
split_screen.is_a?(UISplitViewController).should == true
end
it "should have two viewControllers" do
@split_screen.viewControllers.length.should == 2
split_screen.viewControllers.length.should == 2
end
it "should set the root view to the UISplitScreenViewController" do
@app.window.rootViewController.should == @split_screen
app.window.rootViewController.should == split_screen
end
it "should set the first viewController to MasterScreen" do
@split_screen.master_screen.should == @master_screen
@split_screen.viewControllers.first.should == (@master_screen.navigationController || @master_screen)
split_screen.master_screen.should == master_screen
split_screen.viewControllers.first.should == (master_screen.navigationController || master_screen)
end
it "should set the second viewController to DetailScreen" do
@split_screen.detail_screen.should == @detail_screen
@split_screen.viewControllers.last.should == (@detail_screen.navigationController || @detail_screen)
split_screen.detail_screen.should == detail_screen
split_screen.viewControllers.last.should == (detail_screen.navigationController || detail_screen)
end
it "should set the title on both screens" do
@master_screen.class.title.should == "Master"
@master_screen.title.should == "Master"
@detail_screen.class.title.should == "Detail"
@detail_screen.title.should == "Detail"
master_screen.class.title.should == "Master"
master_screen.title.should == "Master"
detail_screen.class.title.should == "Detail"
detail_screen.title.should == "Detail"
end
end

45
spec/unit/support_spec.rb Normal file
View File

@@ -0,0 +1,45 @@
describe "PM::Support" do
before do
@app = TestDelegate.new
@screen = BasicScreen.new
@tab_screen = TabScreen.new
@table_screen = TestTableScreen.new
@web_screen = TestWebScreen.new
end
it "has a convenience method for UIApplication.sharedApplication" do
@app.app.should == UIApplication.sharedApplication
@screen.app.should == UIApplication.sharedApplication
@tab_screen.app.should == UIApplication.sharedApplication
@table_screen.app.should == UIApplication.sharedApplication
@web_screen.app.should == UIApplication.sharedApplication
end
it "has a convenience method for UIApplication.sharedApplication.delegate" do
@app.app_delegate.should == UIApplication.sharedApplication.delegate
@screen.app_delegate.should == UIApplication.sharedApplication.delegate
@tab_screen.app_delegate.should == UIApplication.sharedApplication.delegate
@table_screen.app_delegate.should == UIApplication.sharedApplication.delegate
@web_screen.app_delegate.should == UIApplication.sharedApplication.delegate
end
it "has a convenience method for UIApplication.sharedApplication.delegate.window" do
@app.app_window.should == UIApplication.sharedApplication.delegate.window
@screen.app_window.should == UIApplication.sharedApplication.delegate.window
@tab_screen.app_window.should == UIApplication.sharedApplication.delegate.window
@table_screen.app_window.should == UIApplication.sharedApplication.delegate.window
@web_screen.app_window.should == UIApplication.sharedApplication.delegate.window
end
it "has a try method" do
@app.try(:some_method).should == nil
@screen.try(:some_method).should == nil
@tab_screen.try(:some_method).should == nil
@table_screen.try(:some_method).should == nil
@web_screen.try(:some_method).should == nil
end
end

View File

@@ -19,6 +19,17 @@ describe "PM::Tabs" do
app.window.rootViewController.should.be.kind_of UITabBarController
end
it "should set the the pm_tab_delegate to the opener" do
tab_bar.pm_tab_delegate.should.equal(app)
tab_bar.delegate.should.equal(tab_bar)
end
it "should call on_tab_selected when a tab is selected" do
tab_bar.pm_tab_delegate.called_on_tab_selected = false
@screen1.open_tab "Screen 2"
tab_bar.pm_tab_delegate.called_on_tab_selected.should.be.true
end
it "should have four tabs" do
tab_bar.viewControllers.length.should == 4
end

View File

@@ -25,6 +25,10 @@ describe "tab bar functionality" do
@tab_bar.tabBar.items.first.title.should == "Tab Item"
end
it "should allow setting image insets" do
@tab_bar.tabBar.items.first.imageInsets.should == UIEdgeInsetsMake(5,5,5,5)
end
it "should have set the others to their respective titles" do
@tab_bar.tabBar.items[1].title.should == "Basic"
@tab_bar.tabBar.items[2].title.should == "Home"

View File

@@ -175,6 +175,10 @@ describe "PM::Table module" do
@subject.tableView.tableHeaderView.class.should == UIImageView
end
it "should have a footer view" do
@subject.tableView.tableFooterView.class.should == UIView
end
describe("section with custom title_view") do
it "should use the correct class for section view" do
@@ -196,4 +200,19 @@ describe "PM::Table module" do
end
end
describe "header view modifications" do
it "should call will_display_header" do
header = @subject.tableView(@subject.table_view, viewForHeaderInSection: 4)
@subject.tableView(@subject.table_view, willDisplayHeaderView:header, forSection:1)
@subject.got_will_display_header.tap do |h|
h.nil?.should == false
h[:section].should == 1
h[:view].should == header
end
end
end
end

View File

@@ -80,6 +80,19 @@ describe "table screens" do
@screen.tableView.tableHeaderView.should.be.kind_of UISearchBar
end
it "should not hide the search bar initally by default" do
@screen.tableView.contentOffset.should == CGPointMake(0,0)
end
it "should allow hiding the search bar initally" do
class HiddenSearchScreen < TableScreenSearchable
searchable hide_initially: true
end
screen = HiddenSearchScreen.new
screen.on_load
screen.tableView.contentOffset.should == CGPointMake(0,screen.searchDisplayController.searchBar.frame.size.height)
end
end
describe "refresh functionality" do