mirror of
https://github.com/zhigang1992/ProMotion.git
synced 2026-04-24 04:15:49 +08:00
Merge branch 'version-2.3' of https://github.com/clearsightstudio/ProMotion into search_with
Conflicts: .travis.yml Rakefile
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
10
README.md
10
README.md
@@ -68,16 +68,16 @@ end
|
||||
|
||||
|Screens|Navigation Bars|Tab Bars|
|
||||
|---|---|---|
|
||||
||||
|
||||
|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Screen/)|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Screen/#set_nav_bar_buttonside-args)|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20Tabs/)|
|
||||
|
||||
|Table Screens|Grouped Tables|Searchable|Refreshable|
|
||||
|---|---|---|---|
|
||||
|||||
|
||||
|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/)|[](https://gist.github.com/jamonholmgren/382a6cf9963c5f0b2248)|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/#searchableplaceholder-placeholder-text)|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20TableScreen/#refreshableoptions)|
|
||||
|
||||
|
||||
|iPad SplitScreens|Map Screens|Web Screens|
|
||||
|---|---|---|
|
||||
||||
|
||||
|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20SplitScreen/)|[](http://promotion.readthedocs.org/en/master/API%20Reference%20-%20ProMotion%20MapScreen/)|[](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
|
||||
|
||||
|
||||
6
Rakefile
6
Rakefile
@@ -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)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
class DetailScreen < PM::Screen
|
||||
title "Detail"
|
||||
|
||||
nav_bar_button :right, title: "More", style: :plain, action: :back
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||

|
||||
|
||||
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.
|
||||
|
||||

|
||||
|
||||
```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
|
||||
}
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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" ],
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
21
lib/ProMotion/support/support.rb
Normal file
21
lib/ProMotion/support/support.rb
Normal 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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
45
spec/unit/support_spec.rb
Normal 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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user