ProMotion 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CONTRIBUTING.md +1 -1
  3. data/Gemfile +1 -0
  4. data/ProMotion.gemspec +14 -14
  5. data/README.md +26 -46
  6. data/Rakefile +13 -8
  7. data/lib/ProMotion.rb +2 -12
  8. data/lib/ProMotion/cocoatouch/navigation_controller.rb +11 -11
  9. data/lib/ProMotion/cocoatouch/split_view_controller.rb +4 -4
  10. data/lib/ProMotion/cocoatouch/tab_bar_controller.rb +5 -5
  11. data/lib/ProMotion/cocoatouch/table_view_cell.rb +2 -0
  12. data/lib/ProMotion/containers/split_screen.rb +4 -0
  13. data/lib/ProMotion/containers/tabs.rb +10 -8
  14. data/lib/ProMotion/delegate/delegate.rb +3 -0
  15. data/lib/ProMotion/delegate/delegate_module.rb +5 -0
  16. data/lib/ProMotion/extensions/conversions.rb +4 -4
  17. data/lib/ProMotion/map/map_screen.rb +4 -0
  18. data/lib/ProMotion/map/map_screen_module.rb +1 -1
  19. data/lib/ProMotion/screen/screen.rb +3 -0
  20. data/lib/ProMotion/screen/screen_module.rb +25 -1
  21. data/lib/ProMotion/screen/screen_navigation.rb +3 -3
  22. data/lib/ProMotion/table/cell/table_view_cell_module.rb +19 -3
  23. data/lib/ProMotion/table/grouped_table_screen.rb +5 -0
  24. data/lib/ProMotion/table/table.rb +5 -0
  25. data/lib/ProMotion/table/table_screen.rb +4 -0
  26. data/lib/ProMotion/version.rb +1 -1
  27. data/lib/ProMotion/view/styling.rb +22 -9
  28. data/lib/ProMotion/web/web_screen.rb +4 -0
  29. data/lib/ProMotion/web/web_screen_module.rb +1 -1
  30. data/spec/functional/func_image_title_screen.rb +20 -0
  31. data/spec/functional/func_image_view_title_screen.rb +20 -0
  32. data/spec/functional/func_screen_spec.rb +4 -0
  33. data/spec/functional/func_split_screen_spec.rb +7 -0
  34. data/spec/functional/func_view_title_screen.rb +21 -0
  35. data/spec/functional/func_web_screen_spec.rb +3 -3
  36. data/spec/helpers/image_title_screen.rb +15 -0
  37. data/spec/helpers/image_view_title_screen.rb +15 -0
  38. data/spec/helpers/map_screen.rb +4 -2
  39. data/spec/helpers/view_title_screen.rb +15 -0
  40. data/spec/helpers/web_screen.rb +7 -6
  41. data/spec/unit/map_spec.rb +10 -9
  42. data/spec/unit/screen_helpers_spec.rb +11 -7
  43. data/spec/unit/tables/table_module_spec.rb +1 -1
  44. data/spec/unit/view_helper_spec.rb +23 -6
  45. data/spec/unit/web_spec.rb +5 -5
  46. metadata +56 -47
  47. data/lib/ProMotion/thirdparty/formotion_screen.rb +0 -92
  48. data/spec/helpers/table_screen_formotion.rb +0 -50
  49. data/spec/unit/tables/formotion_screen_spec.rb +0 -37
@@ -1,20 +1,20 @@
1
1
  module ProMotion
2
2
  module Conversions
3
-
3
+
4
4
  # For converting, for example, from :contacts to UITabBarSystemItemContacts
5
5
  # Unfortunately, this only works if the symbol is defined in your code.
6
6
  # So, for now, we'll have to do it manually.
7
7
  def convert_symbol(symbol, prefix)
8
8
  Object.const_get("#{prefix}#{camel_case symbol}")
9
9
  end
10
-
10
+
11
11
  def objective_c_method_name(str)
12
12
  str.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
13
13
  end
14
-
14
+
15
15
  def camel_case(str)
16
16
  str.split('_').map(&:capitalize).join
17
17
  end
18
-
18
+
19
19
  end
20
20
  end
@@ -1,3 +1,7 @@
1
+ motion_require '../cocoatouch/view_controller'
2
+ motion_require '../screen/screen_module'
3
+ motion_require 'map_screen_module'
4
+
1
5
  module ProMotion
2
6
  class MapScreen < ViewController
3
7
  include ProMotion::ScreenModule
@@ -9,7 +9,7 @@ module ProMotion
9
9
  resize: [ :width, :height ],
10
10
  delegate: self
11
11
  }
12
-
12
+
13
13
  check_annotation_data
14
14
  @promotion_annotation_data = []
15
15
  set_up_start_position
@@ -1,3 +1,6 @@
1
+ motion_require '../cocoatouch/view_controller'
2
+ motion_require 'screen_module'
3
+
1
4
  module ProMotion
2
5
  class Screen < ViewController
3
6
  # You can inherit a screen from any UIViewController if you include the ScreenModule
@@ -1,3 +1,8 @@
1
+ motion_require 'screen_navigation'
2
+ motion_require '../view/styling'
3
+ motion_require '../containers/tabs'
4
+ motion_require '../containers/split_screen'
5
+
1
6
  module ProMotion
2
7
  module ScreenModule
3
8
  include ProMotion::ScreenNavigation
@@ -12,9 +17,11 @@ module ProMotion
12
17
  raise StandardError.new("ERROR: Screens must extend UIViewController or a subclass of UIViewController.")
13
18
  end
14
19
 
15
- self.title = self.class.send(:get_title)
20
+ resolve_title
21
+
16
22
  self.tab_bar_item = self.class.send(:get_tab_bar_item)
17
23
  self.refresh_tab_bar_item if self.tab_bar_item
24
+ self.class.send(:get_title)
18
25
 
19
26
  args.each { |k, v| self.send("#{k}=", v) if self.respond_to?("#{k}=") }
20
27
 
@@ -48,6 +55,18 @@ module ProMotion
48
55
  @navigationController = nav
49
56
  end
50
57
 
58
+ def resolve_title
59
+ if self.class.send(:get_title).kind_of? String
60
+ self.title = self.class.send(:get_title)
61
+ elsif self.class.send(:get_title).kind_of? UIView
62
+ self.navigationItem.titleView = self.class.send(:get_title)
63
+ elsif self.class.send(:get_title).kind_of? UIImage
64
+ self.navigationItem.titleView = UIImageView.alloc.initWithImage(self.class.send(:get_title))
65
+ else
66
+ PM.logger.warn("title expects string, UIView, or UIImage, but #{self.class.send(:get_title).class.to_s} given.")
67
+ end
68
+ end
69
+
51
70
  def add_nav_bar(args = {})
52
71
  self.navigationController ||= begin
53
72
  self.first_screen = true if self.respond_to?(:first_screen=)
@@ -120,6 +139,10 @@ module ProMotion
120
139
  end
121
140
  end
122
141
 
142
+ def parent_screen=(parent)
143
+ @parent_screen = WeakRef.new(parent)
144
+ end
145
+
123
146
  def first_screen?
124
147
  self.first_screen == true
125
148
  end
@@ -282,6 +305,7 @@ module ProMotion
282
305
  def title=(t)
283
306
  @title = t
284
307
  end
308
+
285
309
  def get_title
286
310
  @title ||= self.to_s
287
311
  end
@@ -18,7 +18,7 @@ module ProMotion
18
18
  open_root_screen screen
19
19
 
20
20
  elsif args[:modal]
21
- present_modal_view_controller screen, args[:animated]
21
+ present_modal_view_controller screen, args[:animated], args[:completion]
22
22
 
23
23
  elsif args[:in_tab] && self.tab_bar
24
24
  present_view_controller_in_tab_bar_controller screen, args[:in_tab]
@@ -117,8 +117,8 @@ module ProMotion
117
117
  end
118
118
  end
119
119
 
120
- def present_modal_view_controller(screen, animated)
121
- self.presentModalViewController((screen.navigationController || screen), animated:animated)
120
+ def present_modal_view_controller(screen, animated, completion)
121
+ self.presentViewController((screen.navigationController || screen), animated:animated, completion:completion)
122
122
  end
123
123
 
124
124
  def present_view_controller_in_tab_bar_controller(screen, tab_name)
@@ -1,3 +1,5 @@
1
+ motion_require '../../view/styling'
2
+
1
3
  module ProMotion
2
4
  module TableViewCellModule
3
5
  include Styling
@@ -63,18 +65,22 @@ module ProMotion
63
65
 
64
66
  def set_remote_image
65
67
  if data_cell[:remote_image]
66
- if self.imageView.respond_to?("setImageWithURL:placeholderImage:")
68
+ if self.imageView.respond_to?("setImageWithURL:placeholder:")
67
69
  url = data_cell[:remote_image][:url]
68
70
  url = NSURL.URLWithString(url) unless url.is_a?(NSURL)
69
71
  placeholder = data_cell[:remote_image][:placeholder]
70
72
  placeholder = UIImage.imageNamed(placeholder) if placeholder.is_a?(String)
71
73
 
72
74
  self.image_size = data_cell[:remote_image][:size] if data_cell[:remote_image][:size] && self.respond_to?("image_size=")
73
- self.imageView.setImageWithURL(url, placeholderImage: placeholder)
75
+ self.imageView.setImageWithURL(url, placeholder: placeholder)
74
76
  self.imageView.layer.masksToBounds = true
75
77
  self.imageView.layer.cornerRadius = data_cell[:remote_image][:radius] if data_cell[:remote_image].has_key?(:radius)
78
+ self.imageView.contentMode = map_content_mode_symbol(data_cell[:remote_image][:content_mode]) if data_cell[:remote_image].has_key?(:content_mode)
79
+ elsif self.imageView.respond_to?("setImageWithURL:placeholderImage:")
80
+ # TODO - Remove this in next major release
81
+ PM.logger.deprecated "The SDWebImage cocoapod is deprecated. Please replace it with 'JMImageCache'."
76
82
  else
77
- PM.logger.error "ProMotion Warning: to use remote_image with TableScreen you need to include the CocoaPod 'SDWebImage'."
83
+ PM.logger.error "ProMotion Warning: to use remote_image with TableScreen you need to include the CocoaPod 'JMImageCache'."
78
84
  end
79
85
  end
80
86
  self
@@ -152,5 +158,15 @@ module ProMotion
152
158
  def set_selection_style
153
159
  self.selectionStyle = UITableViewCellSelectionStyleNone if data_cell[:no_select]
154
160
  end
161
+
162
+ def map_content_mode_symbol(symbol)
163
+ content_mode = {
164
+ scale_to_fill: UIViewContentModeScaleToFill,
165
+ scale_aspect_fit: UIViewContentModeScaleAspectFit,
166
+ scale_aspect_fill: UIViewContentModeScaleAspectFill,
167
+ mode_redraw: UIViewContentModeRedraw
168
+ }[symbol] if symbol.is_a?(Symbol)
169
+ content_mode || symbol
170
+ end
155
171
  end
156
172
  end
@@ -1,3 +1,8 @@
1
+ motion_require '../cocoatouch/table_view_controller'
2
+ motion_require '../screen/screen_module'
3
+ motion_require 'table'
4
+ motion_require 'grouped_table'
5
+
1
6
  module ProMotion
2
7
  class GroupedTableScreen < TableViewController
3
8
  include ProMotion::ScreenModule
@@ -1,3 +1,8 @@
1
+ motion_require '../view/styling'
2
+ motion_require 'extensions/searchable'
3
+ motion_require 'extensions/refreshable'
4
+ motion_require 'extensions/indexable'
5
+
1
6
  module ProMotion
2
7
  module Table
3
8
 
@@ -1,3 +1,7 @@
1
+ motion_require '../cocoatouch/table_view_controller'
2
+ motion_require '../screen/screen_module'
3
+ motion_require 'table'
4
+
1
5
  module ProMotion
2
6
  class TableScreen < TableViewController
3
7
  include ProMotion::ScreenModule
@@ -1,3 +1,3 @@
1
1
  module ProMotion
2
- VERSION = "1.1.2" unless defined?(ProMotion::VERSION)
2
+ VERSION = "1.2.0" unless defined?(ProMotion::VERSION)
3
3
  end
@@ -1,3 +1,5 @@
1
+ motion_require '../extensions/conversions'
2
+
1
3
  module ProMotion
2
4
  module Styling
3
5
  include Conversions
@@ -45,17 +47,28 @@ module ProMotion
45
47
  element
46
48
  end
47
49
 
48
- def content_height(view)
49
- height = 0
50
- view.subviews.each do |sub_view|
51
- next if sub_view.isHidden
52
- y = sub_view.frame.origin.y
53
- h = sub_view.frame.size.height
54
- if (y + h) > height
55
- height = y + h
50
+ def content_max(view, mode = :height)
51
+ return 0 if view.subviews.empty?
52
+
53
+ sizes = view.subviews.map do |sub_view|
54
+ if sub_view.isHidden
55
+ 0
56
+ elsif mode == :height
57
+ sub_view.frame.origin.y + sub_view.frame.size.height
58
+ else
59
+ sub_view.frame.origin.x + sub_view.frame.size.width
56
60
  end
57
61
  end
58
- height
62
+
63
+ sizes.max
64
+ end
65
+
66
+ def content_height(view)
67
+ content_max(view, :height)
68
+ end
69
+
70
+ def content_width(view)
71
+ content_max(view, :width)
59
72
  end
60
73
 
61
74
  def closest_parent(type, this_view = nil)
@@ -1,3 +1,7 @@
1
+ motion_require '../cocoatouch/view_controller'
2
+ motion_require '../screen/screen_module'
3
+ motion_require 'web_screen_module'
4
+
1
5
  module ProMotion
2
6
  class WebScreen < ViewController
3
7
  include ProMotion::ScreenModule
@@ -79,7 +79,7 @@ module ProMotion
79
79
  end
80
80
 
81
81
  def html
82
- self.webview.stringByEvaluatingJavaScriptFromString("document.documentElement.outerHTML")
82
+ evaluate("document.documentElement.outerHTML")
83
83
  end
84
84
 
85
85
  def evaluate(js)
@@ -0,0 +1,20 @@
1
+ describe "ProMotion::Screen UIImage title functionality" do
2
+ tests PM::Screen
3
+
4
+ # Override controller to properly instantiate
5
+ def controller
6
+ rotate_device to: :portrait, button: :bottom
7
+ @image_title_screen ||= ImageTitleScreen.new(nav_bar: true)
8
+ @root_screen = @image_title_screen
9
+ @image_title_screen.navigationController
10
+ end
11
+
12
+ after do
13
+ @controller = nil
14
+ @root_screen = nil
15
+ end
16
+
17
+ it "should allow an image title" do
18
+ @root_screen.navigationItem.titleView.should.be.kind_of UIImageView
19
+ end
20
+ end
@@ -0,0 +1,20 @@
1
+ describe "ProMotion::Screen UIImageView title functionality" do
2
+ tests PM::Screen
3
+
4
+ # Override controller to properly instantiate
5
+ def controller
6
+ rotate_device to: :portrait, button: :bottom
7
+ @image_title_screen ||= ImageViewTitleScreen.new(nav_bar: true)
8
+ @root_screen = @image_title_screen
9
+ @image_title_screen.navigationController
10
+ end
11
+
12
+ after do
13
+ @controller = nil
14
+ @root_screen = nil
15
+ end
16
+
17
+ it "should allow an image title" do
18
+ @root_screen.navigationItem.titleView.should.be.kind_of UIImageView
19
+ end
20
+ end
@@ -18,6 +18,10 @@ describe "ProMotion::Screen functional" do
18
18
  view("Functional").should.be.kind_of UINavigationItemView
19
19
  end
20
20
 
21
+ it "should allow a string title" do
22
+ views(UINavigationItemView).include?(UIImageView).should.not.be.true
23
+ end
24
+
21
25
  it "should allow setting a left nav bar button" do
22
26
  @root_screen.set_nav_bar_button :left, title: "Cool", action: :triggered_button
23
27
  tap("Cool")
@@ -71,4 +71,11 @@ describe "Split screen functional" do
71
71
  @detail.navigationItem.leftBarButtonItem.title.should == test_title
72
72
  end
73
73
 
74
+ it "should override the default swipe action, that reveals the menu" do
75
+ rotate_device to: :portrait, button: :bottom
76
+
77
+ @controller = @app.open_split_screen @master, @detail, swipe: false
78
+ @app.home_screen.presentsWithGesture.should == false
79
+ end
80
+
74
81
  end
@@ -0,0 +1,21 @@
1
+ describe "ProMotion::Screen UIView title functionality" do
2
+ tests PM::Screen
3
+
4
+ # Override controller to properly instantiate
5
+ def controller
6
+ rotate_device to: :portrait, button: :bottom
7
+ @image_title_screen ||= ViewTitleScreen.new(nav_bar: true)
8
+ @root_screen = @image_title_screen
9
+ @image_title_screen.navigationController
10
+ end
11
+
12
+ after do
13
+ @controller = nil
14
+ @root_screen = nil
15
+ end
16
+
17
+ it "should allow an image title" do
18
+ @root_screen.navigationItem.titleView.should.not.be.kind_of UIImageView
19
+ @root_screen.navigationItem.titleView.should.be.kind_of UIView
20
+ end
21
+ end
@@ -23,7 +23,7 @@ describe "ProMotion::TestWebScreen functionality" do
23
23
  @webscreen.set_content(file_name)
24
24
 
25
25
  @loaded_file = File.read(File.join(NSBundle.mainBundle.resourcePath, file_name))
26
- wait_for_change @webscreen, 'load_finished' do
26
+ wait_for_change @webscreen, 'is_load_finished' do
27
27
  @webscreen.html.delete("\n").should == @loaded_file.delete("\n")
28
28
  end
29
29
  end
@@ -33,7 +33,7 @@ describe "ProMotion::TestWebScreen functionality" do
33
33
  to_return(body: %q{Google! <form action="/search">%}, content_type: "text/html")
34
34
 
35
35
  @webscreen.open_url(NSURL.URLWithString("https://www.google.com/"))
36
- wait_for_change @webscreen, 'load_finished' do
36
+ wait_for_change @webscreen, 'is_load_finished' do
37
37
  @webscreen.html.include?('<form action="/search"').should == true
38
38
  end
39
39
  end
@@ -41,7 +41,7 @@ describe "ProMotion::TestWebScreen functionality" do
41
41
  it "should manipulate the webscreen contents with javascript" do
42
42
  @webscreen.set_content('<h1 id="cool">Something Cool</h1>')
43
43
 
44
- wait_for_change @webscreen, 'load_finished' do
44
+ wait_for_change @webscreen, 'is_load_finished' do
45
45
  @webscreen.evaluate('document.getElementById("cool").innerHTML = "Changed"')
46
46
  @webscreen.html.should =~ /<h1 id="cool">Changed<\/h1>/
47
47
  end
@@ -0,0 +1,15 @@
1
+ class ImageTitleScreen < PM::Screen
2
+ attr_accessor :button_was_triggered
3
+
4
+ title UIImage.imageNamed('test.png')
5
+
6
+ def will_appear
7
+ self.button_was_triggered = false
8
+ add UILabel.alloc.initWithFrame([[ 10, 10 ], [ 300, 40 ]]),
9
+ text: "Label Here"
10
+ end
11
+
12
+ def triggered_button
13
+ self.button_was_triggered = true
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ class ImageViewTitleScreen < PM::Screen
2
+ attr_accessor :button_was_triggered
3
+
4
+ title UIImageView.alloc.initWithImage(UIImage.imageNamed('test.png'))
5
+
6
+ def will_appear
7
+ self.button_was_triggered = false
8
+ add UILabel.alloc.initWithFrame([[ 10, 10 ], [ 300, 40 ]]),
9
+ text: "Label Here"
10
+ end
11
+
12
+ def triggered_button
13
+ self.button_was_triggered = true
14
+ end
15
+ end
@@ -1,6 +1,6 @@
1
1
  class TestMapScreen < PM::MapScreen
2
2
 
3
- attr_accessor :infinite_loop_points
3
+ attr_accessor :infinite_loop_points, :request_complete
4
4
 
5
5
  start_position latitude: 35.090648651123, longitude: -82.965972900391, radius: 4
6
6
  title "Gorges State Park, NC"
@@ -43,7 +43,9 @@ class TestMapScreen < PM::MapScreen
43
43
  end
44
44
 
45
45
  def lookup_infinite_loop
46
- look_up_address address: "1 Infinite Loop" do |points, error|
46
+ self.request_complete = false
47
+ self.look_up_address address: "1 Infinite Loop" do |points, error|
48
+ self.request_complete = true
47
49
  self.infinite_loop_points = points
48
50
  end
49
51
  end