mirror of
https://github.com/zhigang1992/ProMotion.git
synced 2026-06-04 19:45:35 +08:00
Merge branch 'refs/heads/version-0.6' into version-0.6-tableview-fixes
* refs/heads/version-0.6: (25 commits) Added example to readme for cell height. Allow the user to specify individual cell height in the cell hash. If not specified, the cell with use the tableView.rowHeight property. Return element after set_attribute. Use snake_case for Objective-C methods. Fixes Issue #56. Fixing bug in set_nav_bar button methods README update for add improvements `set_easy_attributes` now working. autoresizingMask and frame are the first improvements this brings. Updated table screen specs Initial stab at tablescreen tests Minor refactors to clean up the screen module Added an method for adding any view to any other parent view with attributes. Closes issue #18. Huzzah! Works brilliantly in ios 6 and ios 5 now! Better handling of the callback param. Modify console log to name the actual on_refresh method they need to implement if they defined a different callback. Use more ruby syntax instead of Obj-C syntax. Add a warning if the user didn't implement the on_refresh method or they specified a callback method but didn't implement it. Made callback pattern more consistent. Made all strings configurable. Updated documentation. Better readme formatting for refreshable. fix readme typo. Make sure that we're running on ios6 or higher ...
This commit is contained in:
52
README.md
52
README.md
@@ -141,6 +141,7 @@ Run `rake`. You should now see the simulator open with your home screen and a na
|
||||
|
||||
* Added `open_split_screen` for iPad-supported apps (thanks @rheoli for your contributions to this)
|
||||
* `ProMotion::AppDelegateParent` renamed to `ProMotion::Delegate` (`AppDelegateParent` is an alias)
|
||||
* Added `add_to` method for adding views to any parent view. `remove` works with this normally.
|
||||
|
||||
# Usage
|
||||
|
||||
@@ -329,10 +330,17 @@ Any view item (UIView, UIButton, custom UIView subclasses, etc) can be added to
|
||||
`add` accepts a second argument which is a hash of attributes that get applied to the element before it is
|
||||
dropped into the view.
|
||||
|
||||
`add(view, attr={})`
|
||||
|
||||
```ruby
|
||||
@label = add UILabel.alloc.initWithFrame(CGRectMake(5, 5, 20, 20)), {
|
||||
@label = add UILabel.new, {
|
||||
text: "This is awesome!",
|
||||
font: UIFont.systemFontOfSize(18)
|
||||
font: UIFont.systemFontOfSize(18),
|
||||
resize: [ :left, :right, :top, :bottom, :width, :height ], # autoresizingMask
|
||||
left: 5, # These four attributes are used with CGRectMake
|
||||
top: 5,
|
||||
width: 20,
|
||||
height: 20
|
||||
}
|
||||
|
||||
@element = add UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
|
||||
@@ -341,9 +349,24 @@ dropped into the view.
|
||||
```
|
||||
|
||||
The `set_attributes` method is identical to add except that it does not add it to the current view.
|
||||
If you use snake_case and there isn't an existing method, it'll try camelCase. This allows you to
|
||||
use snake_case for Objective-C methods.
|
||||
|
||||
`set_attributes(view, attr={})`
|
||||
|
||||
```ruby
|
||||
@element = set_attributes UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
|
||||
# `background_color` is translated to `backgroundColor` automatically.
|
||||
background_color: UIColor.whiteColor
|
||||
}
|
||||
```
|
||||
|
||||
You can use `add_to` to add a view to any other view, not just the main view.
|
||||
|
||||
`add_to(parent_view, new_view, attr={})`
|
||||
|
||||
```ruby
|
||||
add_to @some_parent_view, UIView.alloc.initWithFrame(CGRectMake(0, 0, 20, 20)), {
|
||||
backgroundColor: UIColor.whiteColor
|
||||
}
|
||||
```
|
||||
@@ -684,6 +707,21 @@ end
|
||||
<td>searchable(placeholder: "placeholder text")</td>
|
||||
<td>Class method to make the current table searchable.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><pre><code>refreshable(
|
||||
callback: :on_refresh,
|
||||
pull_message: "Pull to refresh",
|
||||
refreshing: "Refreshing data…",
|
||||
updated_format: "Last updated at %s",
|
||||
updated_time_format: "%l:%M %p"
|
||||
)</code></pre></td>
|
||||
<td>Class method to make the current table refreshable.
|
||||
<p>All parameters are optional. If you do not specify a a callback, it will assume you've implemented an <code>on_refresh</code> method in your tableview.</p>
|
||||
<pre><code>def on_refresh
|
||||
# Code to start the refresh
|
||||
end</code></pre>
|
||||
<p>And after you're done with your asyncronous process, call <code>end_refreshing</code> to collapse the refresh view and update the last refreshed time and then <code>update_table_data</code>.</p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h3>table_data</h3>
|
||||
@@ -709,6 +747,7 @@ def table_data
|
||||
subtitle: "This is way too huge..see note",
|
||||
arguments: { data: [ "lots", "of", "data" ] },
|
||||
action: :tapped_cell_1,
|
||||
height: 50, # manually changes the cell's height
|
||||
cell_style: UITableViewCellStyleSubtitle,
|
||||
cell_identifier: "Cell",
|
||||
cell_class: ProMotion::TableViewCell,
|
||||
@@ -777,6 +816,15 @@ Opening a ticket is usually the best and we respond to those pretty quickly.
|
||||
I'm very open to ideas. Tweet me with your ideas or open a ticket (I don't mind!)
|
||||
and let's discuss.
|
||||
|
||||
## Working on Features
|
||||
|
||||
1. Clone the repos into `Your-Project/Vendor/ProMotion`
|
||||
2. Update your `Gemfile`to reference the project as `gem 'ProMotion', :path => "vendor/ProMotion/"`
|
||||
3. If you're also using [BubbleWrap](http://www.bubblewrap.io), add this line to your `Rakefile`: `app.detect_dependencies = false` *(This is a RubyMotion bug that should be resolved soon)*
|
||||
4. Run `bundle`
|
||||
5. Run `rake clean` and then `rake`
|
||||
6. Contribute!
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
1. Fork the project
|
||||
|
||||
2
Rakefile
2
Rakefile
@@ -12,7 +12,7 @@ Motion::Project::App.setup do |app|
|
||||
app.redgreen_style = :focused # :focused, :full
|
||||
|
||||
# Devices
|
||||
app.deployment_target = "5.0"
|
||||
app.deployment_target = "6.0"
|
||||
app.device_family = [:ipad] # so we can test split screen capability
|
||||
|
||||
app.detect_dependencies = true
|
||||
|
||||
@@ -1,2 +1,5 @@
|
||||
class AppDelegate
|
||||
def application(application, didFinishLaunchingWithOptions:launchOptions)
|
||||
return true if RUBYMOTION_ENV == 'test'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -14,7 +14,7 @@ class SplitViewController < UISplitViewController
|
||||
# set the button from the old detail screen to the new one
|
||||
button = detail_screen.navigationItem.leftBarButtonItem
|
||||
s.navigationItem.leftBarButtonItem = button
|
||||
|
||||
|
||||
self.viewControllers = [self.viewControllers.first, s.main_controller]
|
||||
end
|
||||
def screens=(s_array)
|
||||
|
||||
@@ -20,15 +20,15 @@ module ProMotion
|
||||
super
|
||||
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
|
||||
end
|
||||
|
||||
|
||||
def viewWillDisappear(animated)
|
||||
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
|
||||
super
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
def viewDidDisappear(animated)
|
||||
self.view_did_disappear(animated) if self.respond_to?("view_did_disappear:")
|
||||
super
|
||||
super
|
||||
end
|
||||
|
||||
def shouldAutorotateToInterfaceOrientation(orientation)
|
||||
@@ -42,7 +42,7 @@ module ProMotion
|
||||
def willRotateToInterfaceOrientation(orientation, duration:duration)
|
||||
self.will_rotate(orientation, duration)
|
||||
end
|
||||
|
||||
|
||||
def didRotateFromInterfaceOrientation(orientation)
|
||||
self.on_rotate
|
||||
end
|
||||
|
||||
@@ -20,17 +20,17 @@ module ProMotion
|
||||
super
|
||||
self.view_did_appear(animated) if self.respond_to?("view_did_appear:")
|
||||
end
|
||||
|
||||
|
||||
def viewWillDisappear(animated)
|
||||
self.view_will_disappear(animated) if self.respond_to?("view_will_disappear:")
|
||||
super
|
||||
super
|
||||
end
|
||||
|
||||
|
||||
def viewDidDisappear(animated)
|
||||
if self.respond_to?("view_did_disappear:")
|
||||
self.view_did_disappear(animated)
|
||||
end
|
||||
super
|
||||
super
|
||||
end
|
||||
|
||||
def shouldAutorotateToInterfaceOrientation(orientation)
|
||||
@@ -44,7 +44,7 @@ module ProMotion
|
||||
def willRotateToInterfaceOrientation(orientation, duration:duration)
|
||||
self.will_rotate(orientation, duration)
|
||||
end
|
||||
|
||||
|
||||
def didRotateFromInterfaceOrientation(orientation)
|
||||
self.on_rotate
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ module ProMotion
|
||||
include ProMotion::ScreenTabs
|
||||
include ProMotion::SplitScreen if NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].include?("2")
|
||||
attr_accessor :window
|
||||
|
||||
|
||||
def application(application, didFinishLaunchingWithOptions:launch_options)
|
||||
return true if RUBYMOTION_ENV == "test"
|
||||
|
||||
@@ -15,7 +15,7 @@ module ProMotion
|
||||
|
||||
true
|
||||
end
|
||||
|
||||
|
||||
def app_delegate
|
||||
UIApplication.sharedApplication.delegate
|
||||
end
|
||||
@@ -50,7 +50,7 @@ module ProMotion
|
||||
get_home_screen.send(:on_load) if get_home_screen.respond_to?(:on_load)
|
||||
load_root_screen get_home_screen
|
||||
end
|
||||
|
||||
|
||||
def get_home_screen
|
||||
@home_screen
|
||||
end
|
||||
|
||||
@@ -3,15 +3,15 @@ module ProMotion
|
||||
NAME = "RubyMotion::Console: "
|
||||
DEFAULT_COLOR = [ '', '' ]
|
||||
RED_COLOR = [ "\e[0;31m", "\e[0m" ] # Must be in double quotes
|
||||
GREEN_COLOR = [ "\e[0;32m", "\e[0m" ]
|
||||
PURPLE_COLOR = [ "\e[0;35m", "\e[0m" ]
|
||||
GREEN_COLOR = [ "\e[0;32m", "\e[0m" ]
|
||||
PURPLE_COLOR = [ "\e[0;35m", "\e[0m" ]
|
||||
|
||||
class << self
|
||||
def log(log, with_color:color)
|
||||
return if RUBYMOTION_ENV == "test"
|
||||
puts color[0] + NAME + log + color[1]
|
||||
end
|
||||
|
||||
|
||||
def log(log, withColor:color)
|
||||
return if RUBYMOTION_ENV == "test"
|
||||
warn "[DEPRECATION] `log(log, withColor:color)` is deprecated. Use `log(log, with_color:color)`"
|
||||
|
||||
@@ -1,19 +1,52 @@
|
||||
module ProMotion
|
||||
module ViewHelper
|
||||
def set_attributes(element, args = {})
|
||||
args.each do |k, v|
|
||||
if v.is_a? Hash
|
||||
sub_element = element.send(k)
|
||||
set_attributes sub_element, v
|
||||
elsif v.is_a? Array
|
||||
element.send("#{k}", *v) if element.respond_to?("#{k}")
|
||||
else
|
||||
element.send("#{k}=", v) if element.respond_to?("#{k}=")
|
||||
args.each { |k, v| set_attribute(element, k, v) }
|
||||
element
|
||||
end
|
||||
|
||||
def set_attribute(element, k, v)
|
||||
if v.is_a?(Hash) && element.respond_to?(k)
|
||||
sub_element = element.send(k)
|
||||
set_attributes sub_element, v
|
||||
elsif v.is_a?(Array) && element.respond_to?("#{k}")
|
||||
element.send("#{k}", *v)
|
||||
elsif element.respond_to?("#{k}=")
|
||||
element.send("#{k}=", v)
|
||||
else
|
||||
# Doesn't respond. Check if snake case.
|
||||
if k.to_s.include?("_")
|
||||
set_attribute(element, objective_c_method_name(k), v)
|
||||
end
|
||||
end
|
||||
element
|
||||
end
|
||||
|
||||
def objective_c_method_name(meth)
|
||||
meth.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
|
||||
end
|
||||
|
||||
def set_easy_attributes(parent, element, args={})
|
||||
attributes = {}
|
||||
|
||||
if args[:resize]
|
||||
attributes[:autoresizingMask] = UIViewAutoresizingNone
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleLeftMargin if args[:resize].include?(:left)
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleRightMargin if args[:resize].include?(:right)
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleTopMargin if args[:resize].include?(:top)
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleBottomMargin if args[:resize].include?(:bottom)
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleWidth if args[:resize].include?(:width)
|
||||
attributes[:autoresizingMask] |= UIViewAutoresizingFlexibleHeight if args[:resize].include?(:height)
|
||||
end
|
||||
|
||||
if [:left, :top, :width, :height].select{ |a| args[a] && args[a] != :auto }.length == 4
|
||||
attributes[:frame] = CGRectMake(args[:left], args[:top], args[:width], args[:height])
|
||||
end
|
||||
|
||||
set_attributes element, attributes
|
||||
element
|
||||
end
|
||||
|
||||
def frame_from_array(array)
|
||||
return CGRectMake(array[0], array[1], array[2], array[3]) if array.length == 4
|
||||
Console.log(" - frame_from_array expects an array with four elements: [x, y, width, height]", with_color: Console::RED_COLOR)
|
||||
@@ -32,5 +65,9 @@ module ProMotion
|
||||
end
|
||||
height
|
||||
end
|
||||
|
||||
def positioning_attributes(attr={})
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
42
lib/ProMotion/screen_helpers/_tables/_refreshable_table.rb
Normal file
42
lib/ProMotion/screen_helpers/_tables/_refreshable_table.rb
Normal file
@@ -0,0 +1,42 @@
|
||||
module ProMotion::MotionTable
|
||||
module RefreshableTable
|
||||
def make_refreshable(params={})
|
||||
pull_message = params[:pull_message] || "Pull to refresh"
|
||||
@refreshing = params[:refreshing] || "Refreshing data..."
|
||||
@updated_format = params[:updated_format] || "Last updated at %s"
|
||||
@updated_time_format = params[:updated_time_format] || "%l:%M %p"
|
||||
@refreshable_callback = params[:callback]|| :on_refresh
|
||||
|
||||
@refresh_control = UIRefreshControl.alloc.init
|
||||
@refresh_control.attributedTitle = NSAttributedString.alloc.initWithString(pull_message)
|
||||
@refresh_control.addTarget(self, action:'refreshView:', forControlEvents:UIControlEventValueChanged)
|
||||
self.refreshControl = @refresh_control
|
||||
end
|
||||
alias :makeRefreshable :make_refreshable
|
||||
|
||||
######### iOS methods, headless camel case #######
|
||||
|
||||
# UIRefreshControl Delegates
|
||||
def refreshView(refresh)
|
||||
refresh.attributedTitle = NSAttributedString.alloc.initWithString(@refreshing)
|
||||
if @refreshable_callback && self.respond_to?(@refreshable_callback)
|
||||
self.send(@refreshable_callback)
|
||||
else
|
||||
ProMotion::Console.log("ProMotion Warning: you must implement the '#{@refreshable_callback}' method in your TableScreen.", with_color: ProMotion::Console::RED_COLOR)
|
||||
end
|
||||
end
|
||||
|
||||
def start_refreshing
|
||||
return unless @refresh_control
|
||||
|
||||
@refresh_control.beginRefreshing
|
||||
end
|
||||
|
||||
def end_refreshing
|
||||
return unless @refresh_control
|
||||
|
||||
@refresh_control.attributedTitle = NSAttributedString.alloc.initWithString(sprintf(@updated_format, Time.now.strftime(@updated_time_format)))
|
||||
@refresh_control.endRefreshing
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -22,13 +22,13 @@ module ProMotion::MotionTable
|
||||
@contacts_search_display_controller.delegate = params[:delegate]
|
||||
@contacts_search_display_controller.searchResultsDataSource = params[:data_source]
|
||||
@contacts_search_display_controller.searchResultsDelegate = params[:search_results_delegate]
|
||||
|
||||
|
||||
self.table_view.tableHeaderView = search_bar
|
||||
end
|
||||
alias :makeSearchable :make_searchable
|
||||
|
||||
######### iOS methods, headless camel case #######
|
||||
|
||||
|
||||
def searchDisplayController(controller, shouldReloadTableForSearchString:search_string)
|
||||
@mt_filtered_data = nil
|
||||
@mt_filtered_data = []
|
||||
|
||||
@@ -7,6 +7,13 @@ module ProMotion::MotionTable
|
||||
if self.class.respond_to?(:get_searchable) && self.class.get_searchable
|
||||
self.make_searchable(content_controller: self, search_bar: self.class.get_searchable_params)
|
||||
end
|
||||
if self.class.respond_to?(:get_refreshable) && self.class.get_refreshable
|
||||
if defined?(UIRefreshControl)
|
||||
self.make_refreshable(self.class.get_refreshable_params)
|
||||
else
|
||||
ProMotion::Console.log("ProMotion Warning: to use the refresh control on < iOS 6, you need to include the Cocoapod 'CKRefreshControl'.", with_color: ProMotion::Console::RED_COLOR)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# @param [Array] Array of table data
|
||||
@@ -55,7 +62,7 @@ module ProMotion::MotionTable
|
||||
ProMotion::Console.log("Action not implemented: #{action.to_s}", with_color: ProMotion::Console::RED_COLOR)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def set_cell_attributes(element, args = {})
|
||||
args.each do |k, v|
|
||||
if v.is_a? Hash
|
||||
@@ -78,7 +85,7 @@ module ProMotion::MotionTable
|
||||
data_cell[:arguments] = {} unless data_cell[:arguments]
|
||||
data_cell[:arguments][:value] = switch.isOn if data_cell[:arguments].is_a? Hash
|
||||
data_cell[:accessory_action] ||= data_cell[:accessoryAction] # For legacy support
|
||||
|
||||
|
||||
trigger_action(data_cell[:accessory_action], data_cell[:arguments]) if data_cell[:accessory_action]
|
||||
end
|
||||
|
||||
@@ -105,14 +112,14 @@ module ProMotion::MotionTable
|
||||
# Set table_data_index if you want the right hand index column (jumplist)
|
||||
def sectionIndexTitlesForTableView(table_view)
|
||||
if self.respond_to?(:table_data_index)
|
||||
self.table_data_index
|
||||
self.table_data_index
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def remap_data_cell(data_cell)
|
||||
# Re-maps legacy data cell calls
|
||||
mappings = {
|
||||
cell_style: :cellStyle,
|
||||
mappings = {
|
||||
cell_style: :cellStyle,
|
||||
cell_identifier: :cellIdentifier,
|
||||
cell_class: :cellClass,
|
||||
masks_to_bounds: :masksToBounds,
|
||||
@@ -143,9 +150,9 @@ module ProMotion::MotionTable
|
||||
|
||||
data_cell = cell_at_section_and_index(indexPath.section, indexPath.row)
|
||||
return UITableViewCell.alloc.init unless data_cell
|
||||
|
||||
|
||||
data_cell = self.remap_data_cell(data_cell)
|
||||
|
||||
|
||||
data_cell[:cell_style] ||= UITableViewCellStyleDefault
|
||||
data_cell[:cell_identifier] ||= "Cell"
|
||||
cell_identifier = data_cell[:cell_identifier]
|
||||
@@ -154,7 +161,7 @@ module ProMotion::MotionTable
|
||||
table_cell = table_view.dequeueReusableCellWithIdentifier(cell_identifier)
|
||||
unless table_cell
|
||||
table_cell = data_cell[:cell_class].alloc.initWithStyle(data_cell[:cell_style], reuseIdentifier:cell_identifier)
|
||||
|
||||
|
||||
# Add optimizations here
|
||||
table_cell.layer.masksToBounds = true if data_cell[:masks_to_bounds]
|
||||
table_cell.backgroundColor = data_cell[:background_color] if data_cell[:background_color]
|
||||
@@ -165,7 +172,7 @@ module ProMotion::MotionTable
|
||||
if data_cell[:cell_class_attributes]
|
||||
set_cell_attributes table_cell, data_cell[:cell_class_attributes]
|
||||
end
|
||||
|
||||
|
||||
if data_cell[:accessory_view]
|
||||
table_cell.accessoryView = data_cell[:accessory_view]
|
||||
table_cell.accessoryView.autoresizingMask = UIViewAutoresizingFlexibleWidth
|
||||
@@ -254,6 +261,15 @@ module ProMotion::MotionTable
|
||||
return table_cell
|
||||
end
|
||||
|
||||
def tableView(tableView, heightForRowAtIndexPath:indexPath)
|
||||
cell = cell_at_section_and_index(indexPath.section, indexPath.row)
|
||||
if cell[:height]
|
||||
cell[:height].to_f
|
||||
else
|
||||
tableView.rowHeight
|
||||
end
|
||||
end
|
||||
|
||||
def tableView(table_view, didSelectRowAtIndexPath:indexPath)
|
||||
cell = cell_at_section_and_index(indexPath.section, indexPath.row)
|
||||
table_view.deselectRowAtIndexPath(indexPath, animated: true);
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
module ProMotion::MotionTable
|
||||
module GroupedTable
|
||||
include SectionedTable
|
||||
|
||||
include RefreshableTable
|
||||
|
||||
def table_view
|
||||
@table_view ||= UITableView.alloc.initWithFrame(self.view.frame, style:UITableViewStyleGrouped)
|
||||
@table_view.dataSource = self;
|
||||
|
||||
@@ -2,6 +2,7 @@ module ProMotion::MotionTable
|
||||
module PlainTable
|
||||
include SectionedTable
|
||||
include SearchableTable
|
||||
include RefreshableTable
|
||||
|
||||
def table_view
|
||||
@table_view ||= UITableView.alloc.initWithFrame(self.view.frame, style:UITableViewStylePlain)
|
||||
|
||||
@@ -1,28 +1,33 @@
|
||||
module ProMotion
|
||||
module ScreenElements
|
||||
include ProMotion::ViewHelper
|
||||
|
||||
def add(v, attrs = {})
|
||||
if attrs && attrs.length > 0
|
||||
set_attributes(v, attrs)
|
||||
end
|
||||
self.view.addSubview(v)
|
||||
v
|
||||
|
||||
def add(element, attrs = {})
|
||||
add_to self.view, element, attrs
|
||||
end
|
||||
alias :add_element :add
|
||||
alias :add_view :add
|
||||
|
||||
def remove(v)
|
||||
v.removeFromSuperview
|
||||
v = nil
|
||||
def remove(element)
|
||||
element.removeFromSuperview
|
||||
element = nil
|
||||
end
|
||||
alias :remove_element :remove
|
||||
alias :remove_view :remove
|
||||
|
||||
def add_to(parent_element, element, attrs = {})
|
||||
if attrs && attrs.length > 0
|
||||
set_attributes(element, attrs)
|
||||
set_easy_attributes(parent_element, element, attrs)
|
||||
end
|
||||
parent_element.addSubview element
|
||||
element
|
||||
end
|
||||
|
||||
def bounds
|
||||
return self.view.bounds
|
||||
end
|
||||
|
||||
|
||||
def frame
|
||||
return self.view.frame
|
||||
end
|
||||
|
||||
@@ -2,20 +2,20 @@ module ProMotion
|
||||
module ScreenNavigation
|
||||
|
||||
def open_screen(screen, args = {})
|
||||
|
||||
|
||||
# Apply properties to instance
|
||||
screen = setup_screen_for_open(screen, args)
|
||||
ensure_wrapper_controller_in_place(screen, args)
|
||||
|
||||
screen.send(:on_load) if screen.respond_to?(:on_load)
|
||||
screen.send(:on_load) if screen.respond_to?(:on_load)
|
||||
animated = args[:animated] || true
|
||||
|
||||
return self.split_screen.detail_screen = screen if args[:in_detail] && self.split_screen
|
||||
return self.split_screen.master_screen = screen if args[:in_master] && self.split_screen
|
||||
|
||||
|
||||
if args[:close_all]
|
||||
open_root_screen screen
|
||||
|
||||
|
||||
elsif args[:modal]
|
||||
present_modal_view_controller screen, animated
|
||||
|
||||
@@ -44,7 +44,7 @@ module ProMotion
|
||||
def app_delegate
|
||||
UIApplication.sharedApplication.delegate
|
||||
end
|
||||
|
||||
|
||||
def close_screen(args = {})
|
||||
args ||= {}
|
||||
args[:animated] ||= true
|
||||
@@ -58,7 +58,7 @@ module ProMotion
|
||||
|
||||
else
|
||||
Console.log("Tried to close #{self.to_s}; however, this screen isn't modal or in a nav bar.", withColor: Console::PURPLE_COLOR)
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
alias :close :close_screen
|
||||
@@ -95,7 +95,7 @@ module ProMotion
|
||||
screen.parent_screen = self if screen.respond_to?("parent_screen=")
|
||||
screen.title = args[:title] if args[:title] && screen.respond_to?("title=")
|
||||
screen.modal = args[:modal] if args[:modal] && screen.respond_to?("modal=")
|
||||
|
||||
|
||||
# Hide bottom bar?
|
||||
screen.hidesBottomBarWhenPushed = args[:hide_tab_bar] == true
|
||||
|
||||
|
||||
@@ -10,33 +10,33 @@ module ProMotion
|
||||
|
||||
screens.each do |s|
|
||||
s = s.new if s.respond_to?(:new)
|
||||
|
||||
|
||||
s.tabBarItem.tag = tag_index
|
||||
|
||||
|
||||
s.parent_screen = self if self.is_a?(UIViewController) && s.respond_to?("parent_screen=")
|
||||
s.tab_bar = tab_bar_controller if s.respond_to?("tab_bar=")
|
||||
|
||||
|
||||
vc = s.respond_to?(:main_controller) ? s.main_controller : s
|
||||
view_controllers << vc
|
||||
|
||||
|
||||
tag_index += 1
|
||||
|
||||
|
||||
s.on_load if s.respond_to?(:on_load)
|
||||
end
|
||||
|
||||
tab_bar_controller.viewControllers = view_controllers
|
||||
tab_bar_controller
|
||||
end
|
||||
|
||||
|
||||
# Open a UITabBarController with the specified screens as the
|
||||
# root view controller of the current app.
|
||||
# @param [Array] A comma-delimited list of screen classes or instances.
|
||||
# @return [UITabBarController]
|
||||
def open_tab_bar(*screens)
|
||||
tab_bar = tab_bar_controller(*screens)
|
||||
|
||||
|
||||
a = self.respond_to?(:load_root_screen) ? self : UIApplication.sharedApplication.delegate
|
||||
|
||||
|
||||
a.load_root_screen(tab_bar)
|
||||
tab_bar
|
||||
end
|
||||
@@ -66,12 +66,12 @@ module ProMotion
|
||||
title = tab[:title] if tab[:title]
|
||||
tab[:tag] ||= @current_tag ||= 0
|
||||
@current_tag = tab[:tag] + 1
|
||||
|
||||
|
||||
tab_bar_item = create_tab_bar_icon(tab[:system_icon], tab[:tag]) if tab[:system_icon]
|
||||
tab_bar_item = create_tab_bar_icon_custom(title, tab[:icon], tab[:tag]) if tab[:icon]
|
||||
|
||||
|
||||
tab_bar_item.badgeValue = tab[:badge_number].to_s unless tab[:badge_number].nil? || tab[:badge_number] <= 0
|
||||
|
||||
|
||||
return tab_bar_item
|
||||
end
|
||||
|
||||
|
||||
@@ -3,20 +3,20 @@ module ProMotion
|
||||
def split_screen_controller(master, detail)
|
||||
master_main = master.navigationController ? master.navigationController : master
|
||||
detail_main = detail.navigationController ? detail.navigationController : detail
|
||||
|
||||
|
||||
split = SplitViewController.alloc.init
|
||||
split.viewControllers = [ master_main, detail_main ]
|
||||
split.delegate = self
|
||||
|
||||
|
||||
split
|
||||
end
|
||||
|
||||
|
||||
def create_split_screen(master, detail, args={})
|
||||
master = master.new if master.respond_to?(:new)
|
||||
detail = detail.new if detail.respond_to?(:new)
|
||||
|
||||
|
||||
split = split_screen_controller(master, detail)
|
||||
|
||||
|
||||
[master, detail].each do |s|
|
||||
s.split_screen = split if s.respond_to?("split_screen=")
|
||||
s.on_load if s.respond_to?(:on_load)
|
||||
@@ -24,15 +24,15 @@ module ProMotion
|
||||
|
||||
split
|
||||
end
|
||||
|
||||
|
||||
def open_split_screen(master, detail, args={})
|
||||
split = create_split_screen(master, detail, args)
|
||||
open split, args
|
||||
split
|
||||
end
|
||||
|
||||
|
||||
# UISplitViewControllerDelegate methods
|
||||
|
||||
|
||||
def splitViewController(svc, willHideViewController: vc, withBarButtonItem: button, forPopoverController: pc)
|
||||
button.title = vc.title
|
||||
svc.detail_screen.navigationItem.leftBarButtonItem = button;
|
||||
|
||||
@@ -12,13 +12,13 @@ module ProMotion
|
||||
unless self.is_a?(UIViewController)
|
||||
raise StandardError.new("ERROR: Screens must extend UIViewController or a subclass of UIViewController.")
|
||||
end
|
||||
|
||||
|
||||
args.each do |k, v|
|
||||
self.send("#{k}=", v) if self.respond_to?("#{k}=")
|
||||
end
|
||||
|
||||
self.add_nav_bar if args[:nav_bar]
|
||||
self.table_setup if self.respond_to?(:table_setup)
|
||||
self.table_setup if self.respond_to?(:table_setup)
|
||||
self.on_init if self.respond_to?(:on_init)
|
||||
self
|
||||
end
|
||||
@@ -60,23 +60,26 @@ module ProMotion
|
||||
end
|
||||
|
||||
def set_nav_bar_right_button(title, args={})
|
||||
args[:style] ||= UIBarButtonItemStyleBordered
|
||||
args[:target] ||= self
|
||||
args[:action] ||= nil
|
||||
|
||||
right_button = UIBarButtonItem.alloc.initWithTitle(title, style: args[:style], target: args[:target], action: args[:action])
|
||||
self.navigationItem.rightBarButtonItem = right_button
|
||||
right_button
|
||||
args[:title] = title
|
||||
set_nav_bar_button :right, args
|
||||
end
|
||||
|
||||
def set_nav_bar_left_button(title, args={})
|
||||
args[:title] = title
|
||||
set_nav_bar_button :left, args
|
||||
end
|
||||
|
||||
def set_nav_bar_button(side, args={})
|
||||
args[:style] ||= UIBarButtonItemStyleBordered
|
||||
args[:target] ||= self
|
||||
args[:action] ||= nil
|
||||
|
||||
left_button = UIBarButtonItem.alloc.initWithTitle(title, style: args[:style], target: args[:target], action: args[:action])
|
||||
self.navigationItem.leftBarButtonItem = left_button
|
||||
left_button
|
||||
button = UIBarButtonItem.alloc.initWithTitle(args[:title], style: args[:style], target: args[:target], action: args[:action])
|
||||
|
||||
self.navigationItem.leftBarButtonItem = button if side == :left
|
||||
self.navigationItem.rightBarButtonItem = button if side == :right
|
||||
|
||||
button
|
||||
end
|
||||
|
||||
# [DEPRECATED]
|
||||
@@ -132,8 +135,7 @@ module ProMotion
|
||||
end
|
||||
|
||||
def main_controller
|
||||
return self.navigation_controller if self.navigation_controller
|
||||
self
|
||||
self.navigation_controller || self
|
||||
end
|
||||
|
||||
def view_controller
|
||||
@@ -186,7 +188,7 @@ module ProMotion
|
||||
end
|
||||
orientations
|
||||
end
|
||||
|
||||
|
||||
def supported_device_families
|
||||
NSBundle.mainBundle.infoDictionary["UIDeviceFamily"].map do |m|
|
||||
case m
|
||||
@@ -197,7 +199,7 @@ module ProMotion
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def supported_device_family?(family)
|
||||
supported_device_families.include?(family)
|
||||
end
|
||||
|
||||
@@ -2,13 +2,15 @@ module ProMotion
|
||||
module TableScreenModule
|
||||
include MotionTable::PlainTable
|
||||
include MotionTable::SearchableTable
|
||||
include MotionTable::RefreshableTable
|
||||
include ProMotion::ScreenModule
|
||||
|
||||
|
||||
def update_table_data
|
||||
self.update_table_view_data(table_data)
|
||||
end
|
||||
|
||||
module TableClassMethods
|
||||
# Searchable
|
||||
def searchable(params={})
|
||||
@searchable_params = params
|
||||
@searchable = true
|
||||
@@ -21,6 +23,21 @@ module ProMotion
|
||||
def get_searchable
|
||||
@searchable ||= false
|
||||
end
|
||||
|
||||
# Refreshable
|
||||
def refreshable(params = {})
|
||||
@refreshable_params = params
|
||||
@refreshable = true
|
||||
end
|
||||
|
||||
def get_refreshable
|
||||
@refreshable ||= false
|
||||
end
|
||||
|
||||
def get_refreshable_params
|
||||
@refreshable_params ||= nil
|
||||
end
|
||||
|
||||
end
|
||||
def self.included(base)
|
||||
base.extend(ClassMethods)
|
||||
|
||||
48
spec/helpers/table_screen.rb
Normal file
48
spec/helpers/table_screen.rb
Normal file
@@ -0,0 +1,48 @@
|
||||
class TableScreen < ProMotion::SectionedTableScreen
|
||||
|
||||
def on_load
|
||||
@tap_counter ||= 0
|
||||
end
|
||||
|
||||
def table_data
|
||||
[{
|
||||
title: "Your Account",
|
||||
cells: [
|
||||
{ title: "Increment", action: :increment_counter_by, arguments: { number: 3 } },
|
||||
{ title: "Add New Row", action: :add_tableview_row, accessibilityLabel: "Add New Row" },
|
||||
{ title: "Just another blank row" }
|
||||
]
|
||||
}, {
|
||||
title: "App Stuff",
|
||||
cells: [
|
||||
{ title: "Increment One", action: :increment_counter },
|
||||
{ title: "Feedback", remote_image: { url: "http://placekitten.com/100/100", placeholder: "some-local-image", size: 50, radius: 15 } }
|
||||
]
|
||||
}]
|
||||
end
|
||||
|
||||
def edit_profile(args={})
|
||||
args[:id]
|
||||
end
|
||||
|
||||
def add_tableview_row
|
||||
@data[0][:cells] << {
|
||||
title: "Dynamically Added"
|
||||
}
|
||||
update_table_data
|
||||
end
|
||||
|
||||
def increment_counter
|
||||
@tap_counter += 1
|
||||
end
|
||||
|
||||
def increment_counter_by(args)
|
||||
@tap_counter = @tap_counter + args[:number]
|
||||
end
|
||||
|
||||
def tap_counter
|
||||
@tap_counter
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
11
spec/helpers/table_screen_refreshable.rb
Normal file
11
spec/helpers/table_screen_refreshable.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class TableScreenRefreshable < TableScreen
|
||||
attr_accessor :on_refresh_called
|
||||
|
||||
refreshable
|
||||
|
||||
def on_refresh
|
||||
self.on_refresh_called = true
|
||||
end_refreshing
|
||||
end
|
||||
|
||||
end
|
||||
5
spec/helpers/table_screen_searchable.rb
Normal file
5
spec/helpers/table_screen_searchable.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class TableScreenSearchable < TableScreen
|
||||
|
||||
searchable
|
||||
|
||||
end
|
||||
@@ -6,23 +6,23 @@ describe "ios version" do
|
||||
end
|
||||
|
||||
it "#ios_version_is?" do
|
||||
@dummy.ios_version_is?(@dummy.ios_version).should == true
|
||||
@dummy.ios_version_is?(@dummy.ios_version).should.be.true
|
||||
end
|
||||
|
||||
it "#ios_version_greater?" do
|
||||
@dummy.ios_version_greater?('1.0').should == true
|
||||
@dummy.ios_version_greater?('1.0').should.be.true
|
||||
end
|
||||
|
||||
it "#ios_version_greater_eq?" do
|
||||
@dummy.ios_version_greater_eq?(@dummy.ios_version).should == true
|
||||
@dummy.ios_version_greater_eq?(@dummy.ios_version).should.be.true
|
||||
end
|
||||
|
||||
it "#ios_version_less?" do
|
||||
@dummy.ios_version_less?('9.0').should == true
|
||||
@dummy.ios_version_less?('9.0').should.be.true
|
||||
end
|
||||
|
||||
it "#ios_version_less_eq?" do
|
||||
@dummy.ios_version_less_eq?(@dummy.ios_version).should == true
|
||||
@dummy.ios_version_less_eq?(@dummy.ios_version).should.be.true
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@ describe "pro motion module" do
|
||||
it "should have 'PM' module" do
|
||||
should.not.raise(NameError) { PM }
|
||||
end
|
||||
|
||||
|
||||
it "should not allow screen inclusion into just any class" do
|
||||
dummy = DummyClass.new
|
||||
dummy.extend ProMotion::ScreenModule
|
||||
|
||||
@@ -24,8 +24,37 @@ describe "screen helpers" do
|
||||
@screen.view.subviews.count.should == 0
|
||||
end
|
||||
|
||||
it "should add a subview to another element" do
|
||||
sub_subview = UIView.alloc.initWithFrame CGRectZero
|
||||
@screen.add_to @subview, sub_subview
|
||||
@subview.subviews.include?(sub_subview).should == true
|
||||
end
|
||||
|
||||
it "should add a subview to another element with attributes" do
|
||||
sub_subview = UIView.alloc.initWithFrame CGRectZero
|
||||
@screen.add_to @subview, sub_subview, { backgroundColor: UIColor.redColor }
|
||||
@subview.subviews.last.backgroundColor.should == UIColor.redColor
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "nav bar buttons" do
|
||||
|
||||
before do
|
||||
@screen = HomeScreen.new(nav_bar: true)
|
||||
end
|
||||
|
||||
it "should add a left nav bar button" do
|
||||
@screen.set_nav_bar_left_button "Save", action: :save_something, type: UIBarButtonItemStyleDone
|
||||
@screen.navigationItem.leftBarButtonItem.class.should == UIBarButtonItem
|
||||
end
|
||||
|
||||
it "should add a right nav bar button" do
|
||||
@screen.set_nav_bar_right_button "Cancel", action: :return_to_some_other_screen, type: UIBarButtonItemStylePlain
|
||||
@screen.navigationItem.rightBarButtonItem.class.should == UIBarButtonItem
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "screen navigation" do
|
||||
|
||||
|
||||
@@ -2,48 +2,48 @@ describe "split screen in tab bar functionality" do
|
||||
|
||||
before do
|
||||
@app = TestDelegate.new
|
||||
|
||||
|
||||
@master_screen = HomeScreen.new nav_bar: true
|
||||
@detail_screen = BasicScreen.new nav_bar: true
|
||||
|
||||
|
||||
@split_screen = @app.create_split_screen @master_screen, @detail_screen
|
||||
@tab = @app.open_tab_bar @split_screen, HomeScreen, BasicScreen
|
||||
end
|
||||
|
||||
|
||||
it "should create a UISplitViewController" do
|
||||
@split_screen.is_a?(UISplitViewController).should == true
|
||||
end
|
||||
|
||||
|
||||
it "should have two viewControllers" do
|
||||
@split_screen.viewControllers.length.should == 2
|
||||
end
|
||||
|
||||
|
||||
it "should set the root view to the tab bar" do
|
||||
@app.window.rootViewController.should == @tab
|
||||
end
|
||||
|
||||
it "should return screens for the master_screen and detail_screen methods" do
|
||||
|
||||
it "should return screens for the master_screen and detail_screen methods" do
|
||||
@split_screen.master_screen.is_a?(PM::Screen).should == true
|
||||
@split_screen.detail_screen.is_a?(PM::Screen).should == true
|
||||
end
|
||||
|
||||
it "should return navigationControllers" do
|
||||
|
||||
it "should return navigationControllers" do
|
||||
@split_screen.viewControllers.first.is_a?(UINavigationController).should == true
|
||||
@split_screen.viewControllers.last.is_a?(UINavigationController).should == true
|
||||
end
|
||||
|
||||
|
||||
it "should set the first viewController to HomeScreen's main controller" do
|
||||
@split_screen.master_screen.should == @master_screen
|
||||
@split_screen.viewControllers.first.should == @master_screen.main_controller
|
||||
end
|
||||
|
||||
|
||||
it "should set the second viewController to BasicScreen's main controller" do
|
||||
@split_screen.detail_screen.should == @detail_screen
|
||||
@split_screen.viewControllers.last.should == @detail_screen.main_controller
|
||||
end
|
||||
|
||||
it "should set the tab bar first viewController to the split screen" do
|
||||
|
||||
it "should set the tab bar first viewController to the split screen" do
|
||||
@tab.viewControllers.first.should == @split_screen
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -2,45 +2,45 @@ describe "split screen `open` functionality" do
|
||||
|
||||
before do
|
||||
@app = TestDelegate.new
|
||||
|
||||
|
||||
@master_screen = HomeScreen.new nav_bar: true
|
||||
@detail_screen_1 = BasicScreen.new # no nav_bar on this one
|
||||
@detail_screen_2 = BasicScreen.new(nav_bar: true)
|
||||
|
||||
|
||||
@split_screen = @app.open_split_screen @master_screen, @detail_screen_1
|
||||
end
|
||||
|
||||
|
||||
it "should open a new screen in the detail view" do
|
||||
@master_screen.open @detail_screen_2, in_detail: true
|
||||
@split_screen.detail_screen.should == @detail_screen_2
|
||||
@split_screen.viewControllers.first.should == @master_screen.main_controller
|
||||
@split_screen.viewControllers.last.should == @detail_screen_2.main_controller
|
||||
end
|
||||
|
||||
|
||||
it "should open a new screen in the master view" do
|
||||
@detail_screen_1.open @detail_screen_2, in_master: true
|
||||
@split_screen.master_screen.should == @detail_screen_2
|
||||
@split_screen.viewControllers.first.should == @detail_screen_2.main_controller
|
||||
@split_screen.viewControllers.last.should == @detail_screen_1.main_controller
|
||||
end
|
||||
|
||||
|
||||
it "should open a new screen in the master view's navigation controller" do
|
||||
@master_screen.open @detail_screen_2
|
||||
@split_screen.detail_screen.should == @detail_screen_1 # no change
|
||||
@master_screen.navigationController.topViewController.should == @detail_screen_2
|
||||
end
|
||||
|
||||
|
||||
it "should open a new modal screen in the detail view" do
|
||||
@detail_screen_1.open @detail_screen_2, modal: true
|
||||
@split_screen.detail_screen.should == @detail_screen_1
|
||||
@detail_screen_1.presentedViewController.should == @detail_screen_2.main_controller
|
||||
end
|
||||
|
||||
it "should not interfere with normal non-split screen navigation" do
|
||||
|
||||
it "should not interfere with normal non-split screen navigation" do
|
||||
home = HomeScreen.new(nav_bar: true)
|
||||
child = BasicScreen.new
|
||||
home.open child, in_detail: true, in_master: true
|
||||
home.navigation_controller.topViewController.should == child
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
@@ -2,34 +2,34 @@ describe "split screen functionality" do
|
||||
|
||||
before do
|
||||
@app = TestDelegate.new
|
||||
|
||||
|
||||
@master_screen = HomeScreen.new nav_bar: true
|
||||
@detail_screen = BasicScreen.new # no nav_bar on this one
|
||||
|
||||
|
||||
@split_screen = @app.open_split_screen @master_screen, @detail_screen
|
||||
end
|
||||
|
||||
|
||||
it "should have created a split screen" do
|
||||
@split_screen.should != nil
|
||||
@split_screen.is_a?(UISplitViewController).should == true
|
||||
end
|
||||
|
||||
|
||||
it "should have two viewControllers" do
|
||||
@split_screen.viewControllers.length.should == 2
|
||||
end
|
||||
|
||||
|
||||
it "should set the root view to the UISplitScreenViewController" do
|
||||
@app.window.rootViewController.should == @split_screen
|
||||
end
|
||||
|
||||
|
||||
it "should set the first viewController to HomeScreen" do
|
||||
@split_screen.master_screen.should == @master_screen
|
||||
@split_screen.viewControllers.first.should == @master_screen.main_controller
|
||||
end
|
||||
|
||||
|
||||
it "should set the second viewController to BasicScreen" do
|
||||
@split_screen.detail_screen.should == @detail_screen
|
||||
@split_screen.viewControllers.last.should == @detail_screen.main_controller
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
72
spec/table_screen_spec.rb
Normal file
72
spec/table_screen_spec.rb
Normal file
@@ -0,0 +1,72 @@
|
||||
describe "table screens" do
|
||||
|
||||
describe "basic functionality" do
|
||||
|
||||
before do
|
||||
UIView.setAnimationsEnabled false # avoid animation issues
|
||||
|
||||
@screen = TableScreen.new
|
||||
@screen.on_load
|
||||
end
|
||||
|
||||
it "should display 2 sections" do
|
||||
@screen.tableView.numberOfSections.should == 2
|
||||
end
|
||||
|
||||
it "should have proper cell numbers" do
|
||||
@screen.tableView.numberOfRowsInSection(0).should == 3
|
||||
@screen.tableView.numberOfRowsInSection(1).should == 2
|
||||
end
|
||||
|
||||
it "should have a placeholder image in the last cell" do
|
||||
index_path = NSIndexPath.indexPathForRow(1, inSection: 1)
|
||||
|
||||
@screen.tableView(@screen.tableView, cellForRowAtIndexPath: index_path).imageView.class.should == UIImageView
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "search functionality" do
|
||||
|
||||
before do
|
||||
@screen = TableScreenSearchable.new
|
||||
@screen.on_load
|
||||
end
|
||||
|
||||
it "should be searchable" do
|
||||
@screen.class.get_searchable.should == true
|
||||
end
|
||||
|
||||
it "should create a search header" do
|
||||
@screen.table_view.tableHeaderView.class.should == UISearchBar
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "refresh functionality" do
|
||||
|
||||
# Note this test only works if on iOS 6+ or when using CKRefreshControl.
|
||||
|
||||
before do
|
||||
@screen = TableScreenRefreshable.new
|
||||
@screen.on_load
|
||||
end
|
||||
|
||||
it "should be refreshable" do
|
||||
@screen.class.get_refreshable.should == true
|
||||
end
|
||||
|
||||
it "should create a refresh object" do
|
||||
@screen.instance_variable_get("@refresh_control").class.should == UIRefreshControl
|
||||
end
|
||||
|
||||
it "should respond to start_refreshing and end_refreshing" do
|
||||
@screen.respond_to?(:start_refreshing).should == true
|
||||
@screen.respond_to?(:end_refreshing).should == true
|
||||
end
|
||||
|
||||
# Animations cause the refresh object to fail when tested. Test manually.
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -3,7 +3,7 @@ describe "view helpers" do
|
||||
def equal_rect(rect)
|
||||
->(obj) { CGRectEqualToRect obj, rect }
|
||||
end
|
||||
|
||||
|
||||
before do
|
||||
@dummy = UIView.alloc.initWithFrame CGRectZero
|
||||
@dummy.extend ProMotion::ViewHelper
|
||||
@@ -14,7 +14,7 @@ describe "view helpers" do
|
||||
end
|
||||
|
||||
it "#frame_from_array should return a valid CGRect" do
|
||||
@dummy.frame_from_array([0,0,320,480]).should equal_rect(CGRectMake(0,0,320,480))
|
||||
@dummy.frame_from_array([0,0,320,480]).should equal_rect(CGRectMake(0,0,320,480))
|
||||
end
|
||||
|
||||
it "should allow you to set attributes" do
|
||||
@@ -24,16 +24,16 @@ describe "view helpers" do
|
||||
|
||||
it "should allow you to set nested attributes" do
|
||||
layered_view = UIView.alloc.initWithFrame(CGRectMake(0, 0, 10, 10))
|
||||
|
||||
|
||||
@dummy.set_attributes layered_view, {
|
||||
layer: {
|
||||
backgroundColor: UIColor.redColor.CGColor
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layered_view.layer.backgroundColor.should == UIColor.redColor.CGColor
|
||||
end
|
||||
|
||||
|
||||
it "should allow you to set multiple nested attributes" do
|
||||
mask_layer = CAShapeLayer.layer
|
||||
layered_view = UIView.alloc.initWithFrame(CGRectMake(0, 0, 10, 10))
|
||||
@@ -45,10 +45,25 @@ describe "view helpers" do
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
layered_view.layer.mask.backgroundColor.should == UIColor.redColor.CGColor
|
||||
end
|
||||
|
||||
|
||||
it "should allow you to set snake_case attributes" do
|
||||
layered_view = UIView.alloc.initWithFrame(CGRectMake(0, 0, 10, 10))
|
||||
|
||||
@dummy.set_attributes layered_view, {
|
||||
layer: {
|
||||
background_color: UIColor.redColor.CGColor
|
||||
},
|
||||
content_mode: UIViewContentModeBottom
|
||||
}
|
||||
|
||||
layered_view.contentMode.should == UIViewContentModeBottom
|
||||
layered_view.layer.backgroundColor.should == UIColor.redColor.CGColor
|
||||
end
|
||||
|
||||
|
||||
describe "content height" do
|
||||
|
||||
before do
|
||||
@@ -67,4 +82,74 @@ describe "view helpers" do
|
||||
|
||||
end
|
||||
|
||||
describe "set_easy_attributes" do
|
||||
|
||||
before do
|
||||
@dummy = UIView.alloc.initWithFrame CGRectZero
|
||||
@dummy.extend ProMotion::ViewHelper
|
||||
|
||||
@parent = UIView.alloc.initWithFrame(CGRectMake(0, 0, 320, 480))
|
||||
@child = UIView.alloc.initWithFrame(CGRectZero)
|
||||
end
|
||||
|
||||
it "Should set the autoresizingMask for all" do
|
||||
@dummy.set_easy_attributes @parent, @child, {
|
||||
resize: [:left, :right, :top, :bottom, :width, :height]
|
||||
}
|
||||
|
||||
mask = UIViewAutoresizingFlexibleLeftMargin |
|
||||
UIViewAutoresizingFlexibleRightMargin |
|
||||
UIViewAutoresizingFlexibleTopMargin |
|
||||
UIViewAutoresizingFlexibleBottomMargin |
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight
|
||||
|
||||
@child.autoresizingMask.should == mask
|
||||
end
|
||||
|
||||
it "Should set the autoresizingMask for half" do
|
||||
@dummy.set_easy_attributes @parent, @child, {
|
||||
resize: [:left, :right, :top]
|
||||
}
|
||||
|
||||
mask = UIViewAutoresizingFlexibleLeftMargin |
|
||||
UIViewAutoresizingFlexibleRightMargin |
|
||||
UIViewAutoresizingFlexibleTopMargin
|
||||
|
||||
@child.autoresizingMask.should == mask
|
||||
end
|
||||
|
||||
it "Should set the autoresizingMask for the second half" do
|
||||
@dummy.set_easy_attributes @parent, @child, {
|
||||
resize: [:bottom, :width, :height]
|
||||
}
|
||||
|
||||
mask = UIViewAutoresizingFlexibleBottomMargin |
|
||||
UIViewAutoresizingFlexibleWidth |
|
||||
UIViewAutoresizingFlexibleHeight
|
||||
|
||||
@child.autoresizingMask.should == mask
|
||||
end
|
||||
|
||||
it "Should not set the autoresizingMask" do
|
||||
@dummy.set_easy_attributes @parent, @child, {}
|
||||
|
||||
mask = UIViewAutoresizingNone
|
||||
|
||||
@child.autoresizingMask.should == mask
|
||||
end
|
||||
|
||||
it "Should create a frame" do
|
||||
@dummy.set_easy_attributes @parent, @child, {
|
||||
left: 10,
|
||||
top: 20,
|
||||
width: 100,
|
||||
height: 50
|
||||
}
|
||||
|
||||
@child.frame.should == CGRectMake(10, 20, 100, 50)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user