mirror of
https://github.com/zhigang1992/ProMotion.git
synced 2026-05-13 10:07:02 +08:00
Merge pull request #622 from clearsightstudio/version-2.3
Version 2.3 Megalopullus request
This commit is contained in:
@@ -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
|
||||
|
||||
39
README.md
39
README.md
@@ -69,54 +69,57 @@ 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.
|
||||
|
||||
# Getting Started
|
||||
|
||||
1. Check out the [Getting Started Guide](https://github.com/clearsightstudio/ProMotion/wiki/Guide:-Getting-Started) in the wiki
|
||||
1. Check out the [Getting Started Guide](https://github.com/clearsightstudio/ProMotion/blob/master/docs/Guides/Guide%20-%20Getting%20Started.md)
|
||||
2. Watch the excellent [MotionInMotion screencast about ProMotion](https://motioninmotion.tv/screencasts/8) (very reasonably priced subscription required)
|
||||
3. Follow a tutorial: [Building an ESPN app using RubyMotion, ProMotion, and TDD](http://jamonholmgren.com/building-an-espn-app-using-rubymotion-promotion-and-tdd)
|
||||
4. Read the updated and exhaustive [Wiki](https://github.com/clearsightstudio/ProMotion/wiki)
|
||||
4. Read the [Documentation](https://github.com/clearsightstudio/ProMotion/blob/master/docs)
|
||||
|
||||
# Changelog
|
||||
|
||||
## Version 2.2.0
|
||||
## Version 2.3.0
|
||||
|
||||
This release includes several new features and is backwards compatible with all 2.x releases.
|
||||
|
||||
* PM::TableScreen: You can now set a custom table view header view ([thanks Mark Rickert](https://github.com/clearsightstudio/ProMotion/pull/556))
|
||||
* PM::TableScreen refreshable: Refresh controls now show when programmatically initiating refresh ([thanks Mark Rickert](https://github.com/clearsightstudio/ProMotion/pull/569))
|
||||
* PM::TableScreen: Added reorderable ([thanks Mark Rickert](https://github.com/clearsightstudio/ProMotion/pull/569))
|
||||
* PM::TableScreen: Added auto height feature ([thanks Carlin Isaacson](https://github.com/clearsightstudio/ProMotion/pull/574))
|
||||
* PM::Screen: The navigation controller bottom toolbar will auto-hide when passed nil or false ([thanks Mark Rickert](https://github.com/clearsightstudio/ProMotion/pull/577))
|
||||
* PM::Screen: You can now choose a status bar style ([thanks Mark Rickert](https://github.com/clearsightstudio/ProMotion/pull/563))
|
||||
* Added `on_load` and `on_styled` hooks for UIViews that implement those methods ([Jamon Holmgren](https://github.com/clearsightstudio/ProMotion/pull/567))
|
||||
* Fixed an issue where cell properties would be applied twice unnecessarily ([Jamon Holmgren](https://github.com/clearsightstudio/ProMotion/pull/573))
|
||||
* PR #618 Allow search bar to be hidden initially
|
||||
* PR #606 Adds capability for table_footer_view
|
||||
* PR #602 Add image inset support for tab bar item
|
||||
* PR #595 Feature/support module
|
||||
* PR #582 Allow setting of multiple nav bar buttons instead of just one left an one right
|
||||
* PR #581 Adds on_tab_selected
|
||||
* PR #579 implemented nav_bar_button class method RE #272
|
||||
* PR #565 Adds header_will_display method to PM::TableScreen
|
||||
* PR #663 Adds `on_load` back to cell dequeue code
|
||||
* PR #641 Custom search for PM::TableScreen
|
||||
* PR #658 Fix cell height issue
|
||||
|
||||
# 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
|
||||
## Your app
|
||||
|
||||
Tweet [@jamonholmgren](https://twitter.com/jamonholmgren) if you built an app in ProMotion and want it included!
|
||||
Open a pull request!
|
||||
|
||||
# API Reference
|
||||
|
||||
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 Documentation](https://github.com/clearsightstudio/ProMotion/blob/master/docs)
|
||||
|
||||
# Help
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -94,3 +94,46 @@ class TableScreenSearchable < TestTableScreen
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class TableScreenStabbySearchable < TableScreenSearchable
|
||||
searchable with: -> (cell, search_string) {
|
||||
result = true
|
||||
search_string.split(/\s+/).each {|term|
|
||||
result &&= cell[:properties][:searched_title].downcase.strip.include?(term.downcase.strip)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
def build_cell(title)
|
||||
{
|
||||
title: title,
|
||||
subtitle: @subtitle.to_s,
|
||||
action: :update_subtitle,
|
||||
properties: {
|
||||
searched_title: "#{title} - stabby"
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
class TableScreenSymbolSearchable < TableScreenSearchable
|
||||
searchable with: :custom_search
|
||||
|
||||
def custom_search(cell, search_string)
|
||||
result = true
|
||||
search_string.split(/\s+/).all? {|term|
|
||||
cell[:properties][:searched_title].downcase.strip.include?(term.downcase.strip)
|
||||
}
|
||||
end
|
||||
|
||||
def build_cell(title)
|
||||
{
|
||||
title: title,
|
||||
subtitle: @subtitle.to_s,
|
||||
action: :update_subtitle,
|
||||
properties: {
|
||||
searched_title: "#{title} - symbol"
|
||||
}
|
||||
}
|
||||
end
|
||||
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
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
## Welcome to the ProMotion wiki!
|
||||
## Welcome to the ProMotion docs!
|
||||
|
||||
Documentation is targeting ProMotion 2.2.0. Any exceptions will be noted.
|
||||
Documentation is targeting ProMotion 2.3.x. Any exceptions will be noted.
|
||||
|
||||
If you have a problem with *any* of the documentation, *please* [open an issue](https://github.com/clearsightstudio/ProMotion/issues) so we can resolve it quickly.
|
||||
|
||||
### Getting Started
|
||||
|
||||
#### [Getting Started with ProMotion](https://github.com/clearsightstudio/ProMotion/wiki/Guide:-Getting-Started)
|
||||
#### [Getting Started with ProMotion](./Guides/Guide - Getting Started.md)
|
||||
|
||||
Everything you need to know to install ProMotion and create your first iPhone app.
|
||||
|
||||
@@ -60,22 +60,22 @@ end
|
||||
|
||||
Fired just before the app loads. Not usually necessary.
|
||||
|
||||
#### on_activate
|
||||
|
||||
Fires when the app becomes active.
|
||||
|
||||
#### will_deactivate
|
||||
|
||||
Fires when the app is about to become inactive.
|
||||
|
||||
#### on_enter_background
|
||||
#### on_activate
|
||||
|
||||
Fires when the app enters the background.
|
||||
Fires when the app becomes active.
|
||||
|
||||
#### will_enter_foreground
|
||||
|
||||
Fires just before the app enters the foreground.
|
||||
|
||||
#### on_enter_background
|
||||
|
||||
Fires when the app enters the background.
|
||||
|
||||
#### open_tab_bar(*screens)
|
||||
|
||||
Opens a UITabBarController with the specified screens as the root view controller of the current app.
|
||||
@@ -95,7 +95,7 @@ Opens a UISplitScreenViewController with the specified screens as the root view
|
||||
|
||||
```ruby
|
||||
def on_load(app, options)
|
||||
open_split_screen MasterScreen, DetailScreen,
|
||||
open_split_screen MasterScreen, DetailScreen,
|
||||
icon: "split-icon", title: "Split Screen Title" # optional
|
||||
end
|
||||
```
|
||||
@@ -158,4 +158,4 @@ References the root screen for the app.
|
||||
def some_method
|
||||
self.home_screen #=> PM::Screen instance
|
||||
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
|
||||
@@ -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")
|
||||
|
||||
#### searchable(placeholder: "placeholder text", with: -> (cell, search_string){})
|
||||
|
||||
Class method to make the current table searchable.
|
||||
|
||||
```ruby
|
||||
@@ -265,8 +288,41 @@ class MyTableScreen < PM::TableScreen
|
||||
end
|
||||
```
|
||||
|
||||
Without a `with:` specifier, search is performed on the `title` attribute, and
|
||||
the `search_text` attribute, if present. If you want to create a custom search
|
||||
method, specify it as the value of the `with` key (`find_by`, `search_by` and `filter_by`
|
||||
are aliases). E.g.:
|
||||
|
||||
```ruby
|
||||
class MyTableScreen < PM::TableScreen
|
||||
searchable placeholder: "Search This Table", with: -> (cell, search_string){
|
||||
cell[:properties][:some_obscure_attribute].strip.downcase.include? search_string.strip.downcase
|
||||
}
|
||||
end
|
||||
```
|
||||
|
||||
or if you want to create a version that is less resistant to refactoring:
|
||||
|
||||
```ruby
|
||||
class MyTableScreen < PM::TableScreen
|
||||
searchable placeholder: "Search This Table", with: :custom_search_method
|
||||
|
||||
def custom_search_method(cell, search_string)
|
||||
cell[:properties][:some_obscure_attribute].strip.downcase.include? search_string.strip.downcase
|
||||
end
|
||||
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 +375,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 +395,7 @@ class MyTableScreen < PM::TableScreen
|
||||
update_table_data
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
```
|
||||
|
||||
@@ -414,4 +470,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?(:weakref_alive?) && pm_tab_delegate.weakref_alive? && 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 :on_init
|
||||
try :screen_setup
|
||||
@@ -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)
|
||||
|
||||
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
|
||||
|
||||
@@ -2,16 +2,16 @@ module ProMotion
|
||||
class TableData
|
||||
include ProMotion::Table::Utils
|
||||
|
||||
attr_accessor :data, :filtered_data, :search_string, :original_search_string, :filtered, :table_view
|
||||
attr_accessor :data, :filtered_data, :search_string, :original_search_string, :filtered, :table_view, :search_params
|
||||
|
||||
def initialize(data, table_view)
|
||||
def initialize(data, table_view, search_action = nil)
|
||||
@search_action ||= search_action
|
||||
self.data = data
|
||||
self.table_view = WeakRef.new(table_view)
|
||||
end
|
||||
|
||||
def section(index)
|
||||
s = sections.at(index)
|
||||
s || { title: nil, cells: [] }
|
||||
sections.at(index) || { cells: [] }
|
||||
end
|
||||
|
||||
def sections
|
||||
@@ -39,6 +39,10 @@ module ProMotion
|
||||
section(to.section)[:cells].insert(to.row, section(from.section)[:cells].delete_at(from.row))
|
||||
end
|
||||
|
||||
def default_search(cell, search_string)
|
||||
cell[:searchable] != false && "#{cell[:title]}\n#{cell[:search_text]}".downcase.strip.include?(search_string.downcase.strip)
|
||||
end
|
||||
|
||||
def search(search_string)
|
||||
start_searching(search_string)
|
||||
|
||||
@@ -46,7 +50,11 @@ module ProMotion
|
||||
new_section = {}
|
||||
|
||||
new_section[:cells] = section[:cells].map do |cell|
|
||||
cell[:searchable] != false && "#{cell[:title]}\n#{cell[:search_text]}".downcase.strip.include?(self.search_string) ? cell : nil
|
||||
if @search_action
|
||||
@search_action.call(cell, search_string)
|
||||
else
|
||||
self.default_search(cell, search_string)
|
||||
end ? cell : nil
|
||||
end.compact
|
||||
|
||||
if new_section[:cells] && new_section[:cells].length > 0
|
||||
|
||||
@@ -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
|
||||
@@ -27,16 +27,18 @@ module ProMotion
|
||||
end
|
||||
|
||||
def promotion_table_data
|
||||
@promotion_table_data ||= TableData.new(table_data, table_view)
|
||||
@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,23 @@ 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
|
||||
|
||||
def setup_search_method
|
||||
params = self.class.get_searchable_params
|
||||
if params.nil?
|
||||
return nil
|
||||
else
|
||||
@search_method || begin
|
||||
params = self.class.get_searchable_params
|
||||
@search_action = params[:with] || params[:find_by] || params[:search_by] || params[:filter_by]
|
||||
@search_action = method(@search_action) if @search_action.is_a?(Symbol) || @search_action.is_a?(String)
|
||||
@search_action
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -136,9 +155,9 @@ module ProMotion
|
||||
new_cell.extend(PM::TableViewCellModule) unless new_cell.is_a?(PM::TableViewCellModule)
|
||||
new_cell.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin
|
||||
new_cell.clipsToBounds = true # fix for changed default in 7.1
|
||||
new_cell.send(:on_load) if new_cell.respond_to?(:on_load)
|
||||
new_cell
|
||||
end
|
||||
|
||||
table_cell.setup(data_cell, self) if table_cell.respond_to?(:setup)
|
||||
table_cell.send(:on_reuse) if !new_cell && table_cell.respond_to?(:on_reuse)
|
||||
table_cell
|
||||
@@ -167,42 +186,42 @@ module ProMotion
|
||||
end
|
||||
|
||||
########## Cocoa touch methods #################
|
||||
def numberOfSectionsInTableView(table_view)
|
||||
def numberOfSectionsInTableView(_)
|
||||
self.promotion_table_data.sections.length
|
||||
end
|
||||
|
||||
# Number of cells
|
||||
def tableView(table_view, numberOfRowsInSection: section)
|
||||
def tableView(_, numberOfRowsInSection: section)
|
||||
self.promotion_table_data.section_length(section)
|
||||
end
|
||||
|
||||
def tableView(table_view, titleForHeaderInSection: section)
|
||||
def tableView(_, titleForHeaderInSection: section)
|
||||
section = promotion_table_data.section(section)
|
||||
section && section[:title]
|
||||
end
|
||||
|
||||
# Set table_data_index if you want the right hand index column (jumplist)
|
||||
def sectionIndexTitlesForTableView(table_view)
|
||||
def sectionIndexTitlesForTableView(_)
|
||||
return if self.promotion_table_data.filtered
|
||||
return self.table_data_index if self.respond_to?(:table_data_index)
|
||||
nil
|
||||
end
|
||||
|
||||
def tableView(table_view, cellForRowAtIndexPath: index_path)
|
||||
def tableView(_, cellForRowAtIndexPath: index_path)
|
||||
params = index_path_to_section_index(index_path: index_path)
|
||||
data_cell = self.promotion_table_data.cell(section: params[:section], index: params[:index])
|
||||
return UITableViewCell.alloc.init unless data_cell
|
||||
create_table_cell(data_cell)
|
||||
end
|
||||
|
||||
def tableView(table_view, willDisplayCell: table_cell, forRowAtIndexPath: index_path)
|
||||
def tableView(_, willDisplayCell: table_cell, forRowAtIndexPath: index_path)
|
||||
data_cell = self.promotion_table_data.cell(index_path: index_path)
|
||||
table_cell.send(:will_display) if table_cell.respond_to?(:will_display)
|
||||
table_cell.send(:restyle!) if table_cell.respond_to?(:restyle!) # Teacup compatibility
|
||||
end
|
||||
|
||||
def tableView(table_view, heightForRowAtIndexPath: index_path)
|
||||
(self.promotion_table_data.cell(index_path: index_path)[:height] || table_view.rowHeight).to_f
|
||||
def tableView(_, heightForRowAtIndexPath: index_path)
|
||||
(self.promotion_table_data.cell(index_path: index_path)[:height] || tableView.rowHeight).to_f
|
||||
end
|
||||
|
||||
def tableView(table_view, didSelectRowAtIndexPath: index_path)
|
||||
@@ -211,18 +230,18 @@ module ProMotion
|
||||
trigger_action(data_cell[:action], data_cell[:arguments], index_path) if data_cell[:action]
|
||||
end
|
||||
|
||||
def tableView(table_view, editingStyleForRowAtIndexPath: index_path)
|
||||
def tableView(_, editingStyleForRowAtIndexPath: index_path)
|
||||
data_cell = self.promotion_table_data.cell(index_path: index_path, unfiltered: true)
|
||||
map_cell_editing_style(data_cell[:editing_style])
|
||||
end
|
||||
|
||||
def tableView(table_view, commitEditingStyle: editing_style, forRowAtIndexPath: index_path)
|
||||
def tableView(_, commitEditingStyle: editing_style, forRowAtIndexPath: index_path)
|
||||
if editing_style == UITableViewCellEditingStyleDelete
|
||||
delete_row(index_path)
|
||||
end
|
||||
end
|
||||
|
||||
def tableView(tableView, canMoveRowAtIndexPath:index_path)
|
||||
def tableView(_, canMoveRowAtIndexPath:index_path)
|
||||
data_cell = self.promotion_table_data.cell(index_path: index_path, unfiltered: true)
|
||||
|
||||
if (!data_cell[:moveable].nil? || data_cell[:moveable].is_a?(Symbol)) && data_cell[:moveable] != false
|
||||
@@ -232,7 +251,7 @@ module ProMotion
|
||||
end
|
||||
end
|
||||
|
||||
def tableView(tableView, targetIndexPathForMoveFromRowAtIndexPath:source_index_path, toProposedIndexPath:proposed_destination_index_path)
|
||||
def tableView(_, targetIndexPathForMoveFromRowAtIndexPath:source_index_path, toProposedIndexPath:proposed_destination_index_path)
|
||||
data_cell = self.promotion_table_data.cell(index_path: source_index_path, unfiltered: true)
|
||||
|
||||
if data_cell[:moveable] == :section && source_index_path.section != proposed_destination_index_path.section
|
||||
@@ -242,7 +261,7 @@ module ProMotion
|
||||
end
|
||||
end
|
||||
|
||||
def tableView(tableView, moveRowAtIndexPath:from_index_path, toIndexPath:to_index_path)
|
||||
def tableView(_, moveRowAtIndexPath:from_index_path, toIndexPath:to_index_path)
|
||||
self.promotion_table_data.move_cell(from_index_path, to_index_path)
|
||||
|
||||
if self.respond_to?("on_cell_moved:")
|
||||
@@ -259,11 +278,11 @@ module ProMotion
|
||||
end
|
||||
end
|
||||
|
||||
def tableView(tableView, sectionForSectionIndexTitle: title, atIndex: index)
|
||||
def tableView(table_view, sectionForSectionIndexTitle: title, atIndex: index)
|
||||
return index unless ["{search}", UITableViewIndexSearch].include?(self.table_data_index[0])
|
||||
|
||||
if index == 0
|
||||
tableView.scrollRectToVisible(CGRectMake(0.0, 0.0, 1.0, 1.0), animated: false)
|
||||
table_view.scrollRectToVisible(CGRectMake(0.0, 0.0, 1.0, 1.0), animated: false)
|
||||
NSNotFound
|
||||
else
|
||||
index - 1
|
||||
@@ -276,7 +295,7 @@ module ProMotion
|
||||
end
|
||||
|
||||
# Section view methods
|
||||
def tableView(table_view, viewForHeaderInSection: index)
|
||||
def tableView(_, viewForHeaderInSection: index)
|
||||
section = promotion_table_data.section(index)
|
||||
view = section[:title_view]
|
||||
view = section[:title_view].new if section[:title_view].respond_to?(:new)
|
||||
@@ -284,7 +303,7 @@ module ProMotion
|
||||
view
|
||||
end
|
||||
|
||||
def tableView(table_view, heightForHeaderInSection: index)
|
||||
def tableView(_, heightForHeaderInSection: index)
|
||||
section = promotion_table_data.section(index)
|
||||
if section[:title_view] || section[:title].to_s.length > 0
|
||||
section[:title_view_height] || tableView.sectionHeaderHeight
|
||||
@@ -293,6 +312,17 @@ module ProMotion
|
||||
end
|
||||
end
|
||||
|
||||
def 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
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
module ProMotion
|
||||
VERSION = "2.2.2" unless defined?(ProMotion::VERSION)
|
||||
VERSION = "2.3.0" unless defined?(ProMotion::VERSION)
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
site_name: ProMotion Documentation
|
||||
theme: readthedocs
|
||||
pages:
|
||||
- ["index.md", "Welcome"]
|
||||
- ["README.md", "Welcome"]
|
||||
- ["Guide - Getting Started.md", "Guide - Getting Started"]
|
||||
- ["Guide - Making Your Own Screens.md", "Guide - Making Your Own Screens"]
|
||||
- ["Tutorials, Screencasts, Articles, Presentations.md", "Tutorials, Screencasts, Articles, Presentations"]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -58,4 +58,49 @@ describe "Searchable table spec" do
|
||||
controller.searchDisplayController(controller, didLoadSearchResultsTableView: tableView)
|
||||
end
|
||||
|
||||
describe "custom search" do
|
||||
before do
|
||||
@stabby_controller = TableScreenStabbySearchable.new
|
||||
@proc_controller = TableScreenSymbolSearchable.new
|
||||
end
|
||||
|
||||
after do
|
||||
@stabby_controller = nil
|
||||
@proc_controller = nil
|
||||
end
|
||||
|
||||
it "should allow searching for all the 'New' states using a custom search proc" do
|
||||
@stabby_controller.searchDisplayController(@stabby_controller, shouldReloadTableForSearchString:"New Stabby")
|
||||
@stabby_controller.tableView(@stabby_controller.tableView, numberOfRowsInSection:0).should == 4
|
||||
rows = @stabby_controller.promotion_table_data.search("New stabby")
|
||||
rows.first[:cells].length.should == 4
|
||||
rows.first[:cells].each do |row|
|
||||
# Starts with "New" and ends with "stabby"
|
||||
row[:properties][:searched_title].should.match(/^New(.+)?stabby$/)
|
||||
end
|
||||
end
|
||||
|
||||
it "should allow searching for all the 'New' states using a symbol as a search proc" do
|
||||
@proc_controller.searchDisplayController(@proc_controller, shouldReloadTableForSearchString:"New Symbol")
|
||||
cell_count = @proc_controller.tableView(@proc_controller.tableView, numberOfRowsInSection:0)
|
||||
cell_count.should == 4
|
||||
rows = @proc_controller.promotion_table_data.search("New Symbol")
|
||||
rows.first[:cells].length.should == 4
|
||||
rows.first[:cells].each do |row|
|
||||
# Starts with "New" and ends with "symbol"
|
||||
row[:properties][:searched_title].should.match(/^New(.+)?symbol$/)
|
||||
end
|
||||
end
|
||||
|
||||
it "custom searches empty with stabby proc if there is no match" do
|
||||
@stabby_controller.searchDisplayController(@stabby_controller, shouldReloadTableForSearchString:"Totally Bogus")
|
||||
@stabby_controller.tableView(@stabby_controller.tableView, numberOfRowsInSection:0).should == 0
|
||||
end
|
||||
|
||||
it "custom searches empty with symbol for proc if there is no match" do
|
||||
@proc_controller.searchDisplayController(@proc_controller, shouldReloadTableForSearchString:"Totally Bogus")
|
||||
@proc_controller.tableView(@proc_controller.tableView, numberOfRowsInSection:0).should == 0
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -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