diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e696012..7f6a25d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 diff --git a/README.md b/README.md index 8da803d..23c4455 100644 --- a/README.md +++ b/README.md @@ -69,54 +69,57 @@ 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. # 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 diff --git a/app/test_screens/detail_screen.rb b/app/test_screens/detail_screen.rb index 000805a..c42cf0b 100644 --- a/app/test_screens/detail_screen.rb +++ b/app/test_screens/detail_screen.rb @@ -1,3 +1,5 @@ class DetailScreen < PM::Screen title "Detail" + + nav_bar_button :right, title: "More", style: :plain, action: :back end diff --git a/app/test_screens/functional_screen.rb b/app/test_screens/functional_screen.rb index 4373cc6..7adf7da 100644 --- a/app/test_screens/functional_screen.rb +++ b/app/test_screens/functional_screen.rb @@ -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 diff --git a/app/test_screens/tab_screen.rb b/app/test_screens/tab_screen.rb index 6eeb47a..8c17042 100644 --- a/app/test_screens/tab_screen.rb +++ b/app/test_screens/tab_screen.rb @@ -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 diff --git a/app/test_screens/table_screen_searchable.rb b/app/test_screens/table_screen_searchable.rb index 8650886..80d2b87 100644 --- a/app/test_screens/table_screen_searchable.rb +++ b/app/test_screens/table_screen_searchable.rb @@ -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 diff --git a/app/test_screens/test_delegate.rb b/app/test_screens/test_delegate.rb index 8ce4c4d..6be621d 100644 --- a/app/test_screens/test_delegate.rb +++ b/app/test_screens/test_delegate.rb @@ -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 diff --git a/app/test_screens/test_table_screen.rb b/app/test_screens/test_table_screen.rb index ed03b33..27c1508 100644 --- a/app/test_screens/test_table_screen.rb +++ b/app/test_screens/test_table_screen.rb @@ -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 diff --git a/docs/Guide - Getting Started.md b/docs/Guides/Guide - Getting Started.md similarity index 100% rename from docs/Guide - Getting Started.md rename to docs/Guides/Guide - Getting Started.md diff --git a/docs/Guide - Making Your Own Screens.md b/docs/Guides/Guide - Making Your Own Screens.md similarity index 100% rename from docs/Guide - Making Your Own Screens.md rename to docs/Guides/Guide - Making Your Own Screens.md diff --git a/docs/Migration Guide - ProMotion-1.2-to-2.0.md b/docs/Guides/Migration Guide - ProMotion-1.2-to-2.0.md similarity index 100% rename from docs/Migration Guide - ProMotion-1.2-to-2.0.md rename to docs/Guides/Migration Guide - ProMotion-1.2-to-2.0.md diff --git a/docs/index.md b/docs/README.md similarity index 92% rename from docs/index.md rename to docs/README.md index fa14fc0..b818b22 100644 --- a/docs/index.md +++ b/docs/README.md @@ -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. diff --git a/docs/API Reference - Command Line Tool.md b/docs/Reference/API Reference - Command Line Tool.md similarity index 100% rename from docs/API Reference - Command Line Tool.md rename to docs/Reference/API Reference - Command Line Tool.md diff --git a/docs/API Reference - ProMotion Delegate.md b/docs/Reference/API Reference - ProMotion Delegate.md similarity index 98% rename from docs/API Reference - ProMotion Delegate.md rename to docs/Reference/API Reference - ProMotion Delegate.md index 6c04cc4..a6ac1b6 100644 --- a/docs/API Reference - ProMotion Delegate.md +++ b/docs/Reference/API Reference - ProMotion Delegate.md @@ -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 -``` \ No newline at end of file +``` diff --git a/docs/API Reference - ProMotion Logger.md b/docs/Reference/API Reference - ProMotion Logger.md similarity index 100% rename from docs/API Reference - ProMotion Logger.md rename to docs/Reference/API Reference - ProMotion Logger.md diff --git a/docs/API Reference - ProMotion MapScreen.md b/docs/Reference/API Reference - ProMotion MapScreen.md similarity index 100% rename from docs/API Reference - ProMotion MapScreen.md rename to docs/Reference/API Reference - ProMotion MapScreen.md diff --git a/docs/API Reference - ProMotion PushNotification.md b/docs/Reference/API Reference - ProMotion PushNotification.md similarity index 100% rename from docs/API Reference - ProMotion PushNotification.md rename to docs/Reference/API Reference - ProMotion PushNotification.md diff --git a/docs/API Reference - ProMotion Screen.md b/docs/Reference/API Reference - ProMotion Screen.md similarity index 85% rename from docs/API Reference - ProMotion Screen.md rename to docs/Reference/API Reference - ProMotion Screen.md index 490797c..47ed575 100644 --- a/docs/API Reference - ProMotion Screen.md +++ b/docs/Reference/API Reference - ProMotion Screen.md @@ -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 diff --git a/docs/API Reference - ProMotion SplitScreen.md b/docs/Reference/API Reference - ProMotion SplitScreen.md similarity index 100% rename from docs/API Reference - ProMotion SplitScreen.md rename to docs/Reference/API Reference - ProMotion SplitScreen.md diff --git a/docs/API Reference - ProMotion Styling.md b/docs/Reference/API Reference - ProMotion Styling.md similarity index 100% rename from docs/API Reference - ProMotion Styling.md rename to docs/Reference/API Reference - ProMotion Styling.md diff --git a/docs/API Reference - ProMotion Table - Cell Options.md b/docs/Reference/API Reference - ProMotion Table - Cell Options.md similarity index 100% rename from docs/API Reference - ProMotion Table - Cell Options.md rename to docs/Reference/API Reference - ProMotion Table - Cell Options.md diff --git a/docs/API Reference - ProMotion TableScreen.md b/docs/Reference/API Reference - ProMotion TableScreen.md similarity index 85% rename from docs/API Reference - ProMotion TableScreen.md rename to docs/Reference/API Reference - ProMotion TableScreen.md index e0eefdb..724f6e1 100644 --- a/docs/API Reference - ProMotion TableScreen.md +++ b/docs/Reference/API Reference - ProMotion TableScreen.md @@ -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 +``` + ![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 +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 on_refresh -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 +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 } } -``` \ No newline at end of file +``` diff --git a/docs/API Reference - ProMotion Tabs.md b/docs/Reference/API Reference - ProMotion Tabs.md similarity index 82% rename from docs/API Reference - ProMotion Tabs.md rename to docs/Reference/API Reference - ProMotion Tabs.md index 52ae13c..f72508e 100644 --- a/docs/API Reference - ProMotion Tabs.md +++ b/docs/Reference/API Reference - ProMotion Tabs.md @@ -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 ``` diff --git a/docs/API Reference - ProMotion WebScreen.md b/docs/Reference/API Reference - ProMotion WebScreen.md similarity index 100% rename from docs/API Reference - ProMotion WebScreen.md rename to docs/Reference/API Reference - ProMotion WebScreen.md diff --git a/lib/ProMotion.rb b/lib/ProMotion.rb index 369cc42..1abb5b3 100644 --- a/lib/ProMotion.rb +++ b/lib/ProMotion.rb @@ -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" ], diff --git a/lib/ProMotion/cocoatouch/tab_bar_controller.rb b/lib/ProMotion/cocoatouch/tab_bar_controller.rb index a5dc3af..42e9c41 100644 --- a/lib/ProMotion/cocoatouch/tab_bar_controller.rb +++ b/lib/ProMotion/cocoatouch/tab_bar_controller.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 diff --git a/lib/ProMotion/delegate/delegate_module.rb b/lib/ProMotion/delegate/delegate_module.rb index 2ba3e63..dec357a 100644 --- a/lib/ProMotion/delegate/delegate_module.rb +++ b/lib/ProMotion/delegate/delegate_module.rb @@ -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 diff --git a/lib/ProMotion/screen/nav_bar_module.rb b/lib/ProMotion/screen/nav_bar_module.rb index cade970..dba8722 100644 --- a/lib/ProMotion/screen/nav_bar_module.rb +++ b/lib/ProMotion/screen/nav_bar_module.rb @@ -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." diff --git a/lib/ProMotion/screen/screen_module.rb b/lib/ProMotion/screen/screen_module.rb index 9bef7ce..0846f39 100644 --- a/lib/ProMotion/screen/screen_module.rb +++ b/lib/ProMotion/screen/screen_module.rb @@ -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) diff --git a/lib/ProMotion/screen/screen_navigation.rb b/lib/ProMotion/screen/screen_navigation.rb index 1005bd3..c60d746 100644 --- a/lib/ProMotion/screen/screen_navigation.rb +++ b/lib/ProMotion/screen/screen_navigation.rb @@ -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) diff --git a/lib/ProMotion/support/support.rb b/lib/ProMotion/support/support.rb new file mode 100644 index 0000000..d87e08d --- /dev/null +++ b/lib/ProMotion/support/support.rb @@ -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 diff --git a/lib/ProMotion/table/cell/table_view_cell_module.rb b/lib/ProMotion/table/cell/table_view_cell_module.rb index c4963ee..8032826 100644 --- a/lib/ProMotion/table/cell/table_view_cell_module.rb +++ b/lib/ProMotion/table/cell/table_view_cell_module.rb @@ -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 diff --git a/lib/ProMotion/table/data/table_data.rb b/lib/ProMotion/table/data/table_data.rb index ede4717..417ad87 100644 --- a/lib/ProMotion/table/data/table_data.rb +++ b/lib/ProMotion/table/data/table_data.rb @@ -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 diff --git a/lib/ProMotion/table/extensions/searchable.rb b/lib/ProMotion/table/extensions/searchable.rb index 784a6c3..84dd946 100644 --- a/lib/ProMotion/table/extensions/searchable.rb +++ b/lib/ProMotion/table/extensions/searchable.rb @@ -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 diff --git a/lib/ProMotion/table/table.rb b/lib/ProMotion/table/table.rb index 67ca434..5cbdbc1 100644 --- a/lib/ProMotion/table/table.rb +++ b/lib/ProMotion/table/table.rb @@ -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) diff --git a/lib/ProMotion/tabs/tabs.rb b/lib/ProMotion/tabs/tabs.rb index 3937595..678fc90 100644 --- a/lib/ProMotion/tabs/tabs.rb +++ b/lib/ProMotion/tabs/tabs.rb @@ -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 diff --git a/lib/ProMotion/version.rb b/lib/ProMotion/version.rb index 1e424f5..baab489 100644 --- a/lib/ProMotion/version.rb +++ b/lib/ProMotion/version.rb @@ -1,3 +1,3 @@ module ProMotion - VERSION = "2.2.2" unless defined?(ProMotion::VERSION) + VERSION = "2.3.0" unless defined?(ProMotion::VERSION) end diff --git a/mkdocs.yml b/mkdocs.yml index 838ae4d..a8a0f3d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -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"] diff --git a/spec/unit/delegate_spec.rb b/spec/unit/delegate_spec.rb index b5d023f..714885f 100644 --- a/spec/unit/delegate_spec.rb +++ b/spec/unit/delegate_spec.rb @@ -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 diff --git a/spec/unit/screen_helpers_spec.rb b/spec/unit/screen_helpers_spec.rb index a4d8ac6..04c07b4 100644 --- a/spec/unit/screen_helpers_spec.rb +++ b/spec/unit/screen_helpers_spec.rb @@ -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 diff --git a/spec/unit/screen_spec.rb b/spec/unit/screen_spec.rb index ffd3b35..368ffd3 100644 --- a/spec/unit/screen_spec.rb +++ b/spec/unit/screen_spec.rb @@ -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 diff --git a/spec/unit/searchable_table_spec.rb b/spec/unit/searchable_table_spec.rb index 8ee6183..491d4e8 100644 --- a/spec/unit/searchable_table_spec.rb +++ b/spec/unit/searchable_table_spec.rb @@ -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 diff --git a/spec/unit/split_screen_spec.rb b/spec/unit/split_screen_spec.rb index df211da..b02b31b 100644 --- a/spec/unit/split_screen_spec.rb +++ b/spec/unit/split_screen_spec.rb @@ -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 diff --git a/spec/unit/support_spec.rb b/spec/unit/support_spec.rb new file mode 100644 index 0000000..8a083d8 --- /dev/null +++ b/spec/unit/support_spec.rb @@ -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 + + diff --git a/spec/unit/tab_bar_spec.rb b/spec/unit/tab_bar_spec.rb index 27bf271..9d892f3 100644 --- a/spec/unit/tab_bar_spec.rb +++ b/spec/unit/tab_bar_spec.rb @@ -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 diff --git a/spec/unit/tab_spec.rb b/spec/unit/tab_spec.rb index 3e9cc33..172b249 100644 --- a/spec/unit/tab_spec.rb +++ b/spec/unit/tab_spec.rb @@ -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" diff --git a/spec/unit/tables/table_module_spec.rb b/spec/unit/tables/table_module_spec.rb index 3b7e597..bf08b6b 100644 --- a/spec/unit/tables/table_module_spec.rb +++ b/spec/unit/tables/table_module_spec.rb @@ -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 diff --git a/spec/unit/tables/table_screen_spec.rb b/spec/unit/tables/table_screen_spec.rb index eb9871b..33d83aa 100644 --- a/spec/unit/tables/table_screen_spec.rb +++ b/spec/unit/tables/table_screen_spec.rb @@ -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