ProMotion 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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