ProMotion 1.2.1 → 2.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +36 -10
  3. data/lib/ProMotion.rb +11 -2
  4. data/lib/ProMotion/cocoatouch/ns_string.rb +5 -0
  5. data/lib/ProMotion/cocoatouch/ns_url.rb +5 -0
  6. data/lib/ProMotion/cocoatouch/tab_bar_controller.rb +5 -7
  7. data/lib/ProMotion/cocoatouch/table_view_cell.rb +0 -16
  8. data/lib/ProMotion/cocoatouch/table_view_controller.rb +2 -3
  9. data/lib/ProMotion/cocoatouch/view_controller.rb +3 -6
  10. data/lib/ProMotion/delegate/delegate.rb +0 -3
  11. data/lib/ProMotion/delegate/delegate_module.rb +24 -20
  12. data/lib/ProMotion/{containers → ipad}/split_screen.rb +30 -32
  13. data/lib/ProMotion/{logger.rb → logger/logger.rb} +6 -5
  14. data/lib/ProMotion/screen/nav_bar_module.rb +126 -0
  15. data/lib/ProMotion/screen/screen.rb +0 -3
  16. data/lib/ProMotion/screen/screen_module.rb +54 -177
  17. data/lib/ProMotion/screen/screen_navigation.rb +29 -40
  18. data/lib/ProMotion/{view → styling}/styling.rb +17 -47
  19. data/lib/ProMotion/table/cell/table_view_cell_module.rb +76 -123
  20. data/lib/ProMotion/table/data/table_data.rb +1 -1
  21. data/lib/ProMotion/table/extensions/longpressable.rb +24 -0
  22. data/lib/ProMotion/table/extensions/refreshable.rb +1 -0
  23. data/lib/ProMotion/table/grouped_table_screen.rb +0 -5
  24. data/lib/ProMotion/table/table.rb +63 -83
  25. data/lib/ProMotion/table/table_screen.rb +0 -4
  26. data/lib/ProMotion/{containers → tabs}/tabs.rb +20 -21
  27. data/lib/ProMotion/version.rb +1 -1
  28. data/lib/ProMotion/web/web_screen.rb +0 -4
  29. data/lib/ProMotion/web/web_screen_module.rb +8 -5
  30. data/spec/functional/func_screen_spec.rb +14 -18
  31. data/spec/functional/func_split_screen_spec.rb +2 -2
  32. data/spec/functional/func_table_screen_spec.rb +54 -40
  33. data/spec/functional/func_web_screen_spec.rb +12 -17
  34. data/spec/helpers/test_helper.rb +27 -0
  35. data/spec/unit/delegate_spec.rb +4 -67
  36. data/spec/unit/image_title_screen.rb +9 -0
  37. data/spec/unit/image_view_title_screen.rb +9 -0
  38. data/spec/unit/load_view_spec.rb +27 -0
  39. data/spec/unit/main_spec.rb +0 -6
  40. data/spec/unit/screen_helpers_spec.rb +23 -17
  41. data/spec/unit/screen_spec.rb +21 -17
  42. data/spec/unit/searchable_table_spec.rb +55 -0
  43. data/spec/unit/split_screen_in_tab_bar_spec.rb +5 -5
  44. data/spec/unit/split_screen_spec.rb +4 -4
  45. data/spec/unit/tab_bar_spec.rb +79 -0
  46. data/spec/unit/tab_spec.rb +11 -5
  47. data/spec/unit/tables/table_module_spec.rb +22 -8
  48. data/spec/unit/tables/table_screen_spec.rb +1 -1
  49. data/spec/unit/tables/table_view_cell_spec.rb +16 -16
  50. data/spec/unit/view_helper_spec.rb +6 -81
  51. data/spec/unit/view_title_screen.rb +10 -0
  52. data/spec/unit/web_spec.rb +31 -37
  53. metadata +37 -111
  54. data/.gitignore +0 -33
  55. data/.travis.yml +0 -4
  56. data/CONTRIBUTING.md +0 -20
  57. data/Gemfile +0 -5
  58. data/LICENSE +0 -22
  59. data/ProMotion.gemspec +0 -30
  60. data/Rakefile +0 -66
  61. data/app/app_delegate.rb +0 -7
  62. data/app/screens/basic_screen.rb +0 -15
  63. data/lib/ProMotion/delegate/delegate_notifications.rb +0 -70
  64. data/lib/ProMotion/extensions/conversions.rb +0 -20
  65. data/lib/ProMotion/map/map_screen.rb +0 -10
  66. data/lib/ProMotion/map/map_screen_annotation.rb +0 -65
  67. data/lib/ProMotion/map/map_screen_module.rb +0 -212
  68. data/lib/ProMotion/push_notification/push_notification.rb +0 -58
  69. data/resources/WebScreen.html +0 -6
  70. data/resources/list.png +0 -0
  71. data/resources/test.png +0 -0
  72. data/spec/functional/func_image_title_screen.rb +0 -20
  73. data/spec/functional/func_image_view_title_screen.rb +0 -20
  74. data/spec/functional/func_map_screen_spec.rb +0 -162
  75. data/spec/functional/func_searchable_table_spec.rb +0 -56
  76. data/spec/functional/func_tab_bar_spec.rb +0 -78
  77. data/spec/functional/func_view_title_screen.rb +0 -21
  78. data/spec/helpers/basic_screen.rb +0 -3
  79. data/spec/helpers/custom_title_view.rb +0 -4
  80. data/spec/helpers/detail_screen.rb +0 -3
  81. data/spec/helpers/dummy_class.rb +0 -3
  82. data/spec/helpers/functional_screen.rb +0 -15
  83. data/spec/helpers/home_screen.rb +0 -19
  84. data/spec/helpers/image_title_screen.rb +0 -15
  85. data/spec/helpers/image_view_title_screen.rb +0 -15
  86. data/spec/helpers/map_screen.rb +0 -53
  87. data/spec/helpers/master_screen.rb +0 -3
  88. data/spec/helpers/present_screen.rb +0 -26
  89. data/spec/helpers/screen_module_view_controller.rb +0 -55
  90. data/spec/helpers/tab_screen.rb +0 -4
  91. data/spec/helpers/table_screen.rb +0 -117
  92. data/spec/helpers/table_screen_indexable.rb +0 -18
  93. data/spec/helpers/table_screen_refreshable.rb +0 -11
  94. data/spec/helpers/table_screen_searchable.rb +0 -72
  95. data/spec/helpers/test_delegate.rb +0 -34
  96. data/spec/helpers/test_delegate_colors.rb +0 -17
  97. data/spec/helpers/view_title_screen.rb +0 -15
  98. data/spec/helpers/web_screen.rb +0 -23
  99. data/spec/unit/map_spec.rb +0 -71
@@ -1,9 +1,5 @@
1
- motion_require '../extensions/conversions'
2
-
3
1
  module ProMotion
4
2
  module Styling
5
- include Conversions
6
-
7
3
  def set_attributes(element, args = {})
8
4
  args = get_attributes_from_symbol(args)
9
5
  args.each { |k, v| set_attribute(element, k, v) }
@@ -13,7 +9,9 @@ module ProMotion
13
9
  def set_attribute(element, k, v)
14
10
  return element unless element
15
11
 
16
- if v.is_a?(Hash) && element.respond_to?(k)
12
+ if !element.is_a?(CALayer) && v.is_a?(Hash) && element.respond_to?("#{k}=")
13
+ element.send("#{k}=", v)
14
+ elsif v.is_a?(Hash) && element.respond_to?(k)
17
15
  sub_element = element.send(k)
18
16
  set_attributes(sub_element, v) if sub_element
19
17
  elsif element.respond_to?("#{k}=")
@@ -22,35 +20,13 @@ module ProMotion
22
20
  element.send("#{k}", *v)
23
21
  else
24
22
  # Doesn't respond. Check if snake case.
25
- if k.to_s.include?("_")
26
- set_attribute(element, objective_c_method_name(k), v)
27
- end
23
+ set_attribute(element, camelize(k), v) if k.to_s.include?("_")
28
24
  end
29
25
  element
30
26
  end
31
27
 
32
- def set_easy_attributes(parent, element, args={})
33
- attributes = {}
34
-
35
- if args[:resize]
36
- attributes[:autoresizingMask] = UIViewAutoresizingNone
37
- args[:resize].each { |r| attributes[:autoresizingMask] |= map_resize_symbol(r) }
38
- end
39
-
40
- args[:left] = args.delete(:x) if args[:x]
41
- args[:top] = args.delete(:y) if args[:y]
42
- if [:left, :top, :width, :height].select{ |a| args[a] && args[a] != :auto }.length == 4
43
- attributes[:frame] = CGRectMake(args[:left], args[:top], args[:width], args[:height])
44
- end
45
-
46
- set_attributes element, attributes
47
- element
48
- end
49
-
50
28
  def content_max(view, mode = :height)
51
- return 0 if view.subviews.empty?
52
-
53
- sizes = view.subviews.map do |sub_view|
29
+ view.subviews.map do |sub_view|
54
30
  if sub_view.isHidden
55
31
  0
56
32
  elsif mode == :height
@@ -58,9 +34,7 @@ module ProMotion
58
34
  else
59
35
  sub_view.frame.origin.x + sub_view.frame.size.width
60
36
  end
61
- end
62
-
63
- sizes.max
37
+ end.max.to_f
64
38
  end
65
39
 
66
40
  def content_height(view)
@@ -71,8 +45,9 @@ module ProMotion
71
45
  content_max(view, :width)
72
46
  end
73
47
 
48
+ # iterate up the view hierarchy to find the parent element
49
+ # of "type" containing this view
74
50
  def closest_parent(type, this_view = nil)
75
- # iterate up the view hierarchy to find the parent element of "type" containing this view
76
51
  this_view ||= view_or_self.superview
77
52
  while this_view != nil do
78
53
  return this_view if this_view.is_a? type
@@ -84,23 +59,16 @@ module ProMotion
84
59
  def add(element, attrs = {})
85
60
  add_to view_or_self, element, attrs
86
61
  end
87
- alias :add_element :add
88
- alias :add_view :add
89
62
 
90
63
  def remove(elements)
91
64
  Array(elements).each(&:removeFromSuperview)
92
65
  end
93
- alias :remove_element :remove
94
- alias :remove_view :remove
95
66
 
96
67
  def add_to(parent_element, elements, attrs = {})
97
68
  attrs = get_attributes_from_symbol(attrs)
98
69
  Array(elements).each do |element|
99
70
  parent_element.addSubview element
100
- if attrs && attrs.length > 0
101
- set_attributes(element, attrs)
102
- set_easy_attributes(parent_element, element, attrs)
103
- end
71
+ set_attributes(element, attrs) if attrs && attrs.length > 0
104
72
  end
105
73
  elements
106
74
  end
@@ -130,14 +98,16 @@ module ProMotion
130
98
  raise ArgumentError
131
99
  end
132
100
 
133
- if colors.size == 3
134
- rgb_color(colors[0], colors[1], colors[2])
135
- else
136
- raise ArgumentError
137
- end
101
+ raise ArgumentError unless colors.size == 3
102
+ rgb_color(colors[0], colors[1], colors[2])
103
+ end
104
+
105
+ # Turns a snake_case string into a camelCase string.
106
+ def camelize(str)
107
+ str.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
138
108
  end
139
109
 
140
- protected
110
+ protected
141
111
 
142
112
  def get_attributes_from_symbol(attrs)
143
113
  return attrs if attrs.is_a?(Hash)
@@ -1,5 +1,3 @@
1
- motion_require '../../view/styling'
2
-
3
1
  module ProMotion
4
2
  module TableViewCellModule
5
3
  include Styling
@@ -10,163 +8,118 @@ module ProMotion
10
8
  self.table_screen = WeakRef.new(screen)
11
9
  self.data_cell = data_cell
12
10
 
13
- # TODO: Some of these need to go away. Unnecessary overhead.
14
- set_cell_attributes
15
- set_accessory_view
11
+ check_deprecated_styles
12
+ set_styles
13
+ set_title
16
14
  set_subtitle
17
15
  set_image
18
16
  set_remote_image
19
- set_subviews
20
- set_details
21
- set_styles
17
+ set_accessory_view
22
18
  set_selection_style
23
-
24
- self
25
19
  end
26
20
 
27
- def set_cell_attributes
28
- data_cell_attributes = data_cell.dup
29
- [:image, :accessory_action, :editing_style].each { |k| data_cell_attributes.delete(k) }
30
- set_attributes self, data_cell_attributes
31
- self
32
- end
21
+ protected
33
22
 
34
- def set_accessory_view
35
- if data_cell[:accessory]
36
- if data_cell[:accessory][:view] == :switch
37
- switch_view = UISwitch.alloc.initWithFrame(CGRectZero)
38
- switch_view.setAccessibilityLabel(data_cell[:accessory][:accessibility_label] || data_cell[:title])
39
- switch_view.addTarget(self.table_screen, action: "accessory_toggled_switch:", forControlEvents:UIControlEventValueChanged)
40
- switch_view.on = !!data_cell[:accessory][:value]
41
- self.accessoryView = switch_view
42
- elsif data_cell[:accessory][:view]
43
- self.accessoryView = data_cell[:accessory][:view]
44
- self.accessoryView.autoresizingMask = UIViewAutoresizingFlexibleWidth
45
- end
46
- else
47
- self.accessoryView = nil
23
+ # TODO: Remove this in ProMotion 2.1. Just for migration purposes.
24
+ def check_deprecated_styles
25
+ whitelist = [ :title, :subtitle, :image, :remote_image, :accessory, :selection_style, :action, :arguments, :cell_style, :cell_class, :cell_identifier, :editing_style, :search_text, :keep_selection, :height ]
26
+ if (data_cell.keys - whitelist).length > 0
27
+ PM.logger.deprecated("In #{self.table_screen.class.to_s}#table_data, you should set :#{(data_cell.keys - whitelist).join(", :")} in a `styles:` hash. See TableScreen documentation.")
48
28
  end
29
+ end
30
+
31
+ def set_styles
32
+ set_attributes self, data_cell[:style] if data_cell[:style]
33
+ end
49
34
 
50
- self
35
+ def set_title
36
+ set_attributed_text(self.textLabel, data_cell[:title])
51
37
  end
52
38
 
53
39
  def set_subtitle
54
- if data_cell[:subtitle] && self.detailTextLabel
55
- if data_cell[:subtitle].is_a? NSAttributedString
56
- self.detailTextLabel.attributedText = data_cell[:subtitle]
57
- else
58
- self.detailTextLabel.text = data_cell[:subtitle]
59
- end
60
- self.detailTextLabel.backgroundColor = UIColor.clearColor
61
- self.detailTextLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth
62
- end
63
- self
40
+ return unless data_cell[:subtitle] && self.detailTextLabel
41
+ set_attributed_text(self.detailTextLabel, data_cell[:subtitle])
42
+ self.detailTextLabel.backgroundColor = UIColor.clearColor
43
+ self.detailTextLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth
64
44
  end
65
45
 
66
46
  def set_remote_image
67
- if data_cell[:remote_image]
68
- if self.imageView.respond_to?("setImageWithURL:placeholder:")
69
- url = data_cell[:remote_image][:url]
70
- url = NSURL.URLWithString(url) unless url.is_a?(NSURL)
71
- placeholder = data_cell[:remote_image][:placeholder]
72
- placeholder = UIImage.imageNamed(placeholder) if placeholder.is_a?(String)
73
-
74
- self.image_size = data_cell[:remote_image][:size] if data_cell[:remote_image][:size] && self.respond_to?("image_size=")
75
- self.imageView.setImageWithURL(url, placeholder: placeholder)
76
- self.imageView.layer.masksToBounds = true
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'."
82
- else
83
- PM.logger.error "ProMotion Warning: to use remote_image with TableScreen you need to include the CocoaPod 'JMImageCache'."
84
- end
85
- end
86
- self
47
+ return unless data_cell[:remote_image] && jm_image_cache?
48
+
49
+ self.imageView.image = remote_placeholder
50
+ JMImageCache.sharedCache.imageForURL(data_cell[:remote_image][:url].to_url, completionBlock:proc { |downloaded_image|
51
+ self.imageView.image = downloaded_image
52
+ self.setNeedsLayout
53
+ })
54
+
55
+ self.imageView.layer.masksToBounds = true
56
+ self.imageView.layer.cornerRadius = data_cell[:remote_image][:radius] if data_cell[:remote_image][:radius]
57
+ self.imageView.contentMode = map_content_mode_symbol(data_cell[:remote_image][:content_mode]) if data_cell[:remote_image][:content_mode]
87
58
  end
88
59
 
89
60
  def set_image
90
- if data_cell[:image]
91
-
92
- cell_image = data_cell[:image].is_a?(Hash) ? data_cell[:image][:image] : data_cell[:image]
93
- cell_image = UIImage.imageNamed(cell_image) if cell_image.is_a?(String)
61
+ return unless data_cell[:image]
62
+ cell_image = data_cell[:image].is_a?(Hash) ? data_cell[:image][:image] : data_cell[:image]
63
+ cell_image = UIImage.imageNamed(cell_image) if cell_image.is_a?(String)
64
+ self.imageView.layer.masksToBounds = true
65
+ self.imageView.image = cell_image
66
+ self.imageView.layer.cornerRadius = data_cell[:image][:radius] if data_cell[:image].is_a?(Hash) && data_cell[:image][:radius]
67
+ end
94
68
 
95
- self.imageView.layer.masksToBounds = true
96
- self.imageView.image = cell_image
97
- self.imageView.layer.cornerRadius = data_cell[:image][:radius] if data_cell[:image].is_a?(Hash) && data_cell[:image][:radius]
69
+ def set_accessory_view
70
+ return self.accessoryView = nil unless data_cell[:accessory] && data_cell[:accessory][:view]
71
+ if data_cell[:accessory][:view] == :switch
72
+ self.accessoryView = switch_view
73
+ else
74
+ self.accessoryView = data_cell[:accessory][:view]
75
+ self.accessoryView.autoresizingMask = UIViewAutoresizingFlexibleWidth
98
76
  end
99
- self
100
77
  end
101
78
 
102
- def set_subviews
103
- tag_number = 0
104
- Array(data_cell[:subviews]).each do |view|
105
- # Remove an existing view at that tag number
106
- tag_number += 1
107
- existing_view = self.viewWithTag(tag_number)
108
- existing_view.removeFromSuperview if existing_view
109
-
110
- # Add the subview if it exists
111
- if view
112
- view.tag = tag_number
113
- self.addSubview view
114
- end
115
- end
116
- self
79
+ def set_selection_style
80
+ self.selectionStyle = map_selection_style_symbol(data_cell[:selection_style]) if data_cell[:selection_style]
117
81
  end
118
82
 
119
- def set_details
120
- if data_cell[:details]
121
- self.addSubview data_cell[:details][:image]
122
- end
123
- self
83
+ private
84
+
85
+ def jm_image_cache?
86
+ return true if self.imageView.respond_to?("setImageWithURL:placeholder:")
87
+ PM.logger.error "ProMotion Warning: to use remote_image with TableScreen you need to include the CocoaPod 'JMImageCache'."
88
+ false
124
89
  end
125
90
 
126
- def set_styles
127
- if data_cell[:styles] && data_cell[:styles][:label] && data_cell[:styles][:label][:frame]
128
- ui_label = false
129
- self.contentView.subviews.each do |view|
130
- if view.is_a? UILabel
131
- ui_label = true
132
- view.text = data_cell[:styles][:label][:text]
133
- end
134
- end
135
-
136
- unless ui_label == true
137
- label ||= UILabel.alloc.initWithFrame(CGRectZero)
138
- set_attributes label, data_cell[:styles][:label]
139
- self.contentView.addSubview label
140
- end
141
-
142
- # TODO: What is this and why is it necessary?
143
- self.textLabel.textColor = UIColor.clearColor
144
- else
145
- cell_title = data_cell[:title]
146
- cell_title ||= ""
147
- self.textLabel.backgroundColor = UIColor.clearColor
148
- if cell_title.is_a? NSAttributedString
149
- self.textLabel.attributedText = cell_title
150
- else
151
- self.textLabel.text = cell_title
152
- end
153
- end
91
+ def remote_placeholder
92
+ UIImage.imageNamed(data_cell[:remote_image][:placeholder]) if data_cell[:remote_image][:placeholder].is_a?(String)
93
+ end
154
94
 
155
- self
95
+ def switch_view
96
+ switch = UISwitch.alloc.initWithFrame(CGRectZero)
97
+ switch.setAccessibilityLabel(data_cell[:accessory][:accessibility_label] || data_cell[:title])
98
+ switch.addTarget(self.table_screen, action: "accessory_toggled_switch:", forControlEvents:UIControlEventValueChanged)
99
+ switch.on = !!data_cell[:accessory][:value]
100
+ switch
156
101
  end
157
102
 
158
- def set_selection_style
159
- self.selectionStyle = UITableViewCellSelectionStyleNone if data_cell[:no_select]
103
+ def set_attributed_text(label, text)
104
+ text.is_a?(NSAttributedString) ? label.attributedText = text : label.text = text
160
105
  end
161
106
 
162
107
  def map_content_mode_symbol(symbol)
163
- content_mode = {
108
+ {
164
109
  scale_to_fill: UIViewContentModeScaleToFill,
165
110
  scale_aspect_fit: UIViewContentModeScaleAspectFit,
166
111
  scale_aspect_fill: UIViewContentModeScaleAspectFill,
167
112
  mode_redraw: UIViewContentModeRedraw
168
- }[symbol] if symbol.is_a?(Symbol)
169
- content_mode || symbol
113
+ }[symbol] || symbol
114
+ end
115
+
116
+ def map_selection_style_symbol(symbol)
117
+ {
118
+ none: UITableViewCellSelectionStyleNone,
119
+ blue: UITableViewCellSelectionStyleBlue,
120
+ gray: UITableViewCellSelectionStyleGray,
121
+ default: UITableViewCellSelectionStyleDefault
122
+ }[symbol] || symbol
170
123
  end
171
124
  end
172
125
  end
@@ -4,7 +4,7 @@ module ProMotion
4
4
 
5
5
  def initialize(data, table_view)
6
6
  self.data = data
7
- self.table_view = table_view
7
+ self.table_view = WeakRef.new(table_view)
8
8
  end
9
9
 
10
10
  def section(index)
@@ -0,0 +1,24 @@
1
+ module ProMotion
2
+ module Table
3
+ module Longpressable
4
+ def make_longpressable(params={})
5
+ params = {
6
+ min_duration: 1.0
7
+ }.merge(params)
8
+
9
+ long_press_gesture = UILongPressGestureRecognizer.alloc.initWithTarget(self, action:"on_long_press:")
10
+ long_press_gesture.minimumPressDuration = params[:min_duration]
11
+ long_press_gesture.delegate = self
12
+ self.table_view.addGestureRecognizer(long_press_gesture)
13
+ end
14
+
15
+ def on_long_press(gesture)
16
+ return unless gesture.state == UIGestureRecognizerStateBegan
17
+ gesture_point = gesture.locationInView(table_view)
18
+ index_path = table_view.indexPathForRowAtPoint(gesture_point)
19
+ data_cell = self.promotion_table_data.cell(index_path: index_path)
20
+ trigger_action(data_cell[:long_press_action], data_cell[:arguments]) if data_cell[:long_press_action]
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,6 +1,7 @@
1
1
  module ProMotion
2
2
  module Table
3
3
  module Refreshable
4
+
4
5
  def make_refreshable(params={})
5
6
  pull_message = params[:pull_message] || "Pull to refresh"
6
7
  @refreshing = params[:refreshing] || "Refreshing data..."
@@ -1,8 +1,3 @@
1
- motion_require '../cocoatouch/table_view_controller'
2
- motion_require '../screen/screen_module'
3
- motion_require 'table'
4
- motion_require 'grouped_table'
5
-
6
1
  module ProMotion
7
2
  class GroupedTableScreen < TableViewController
8
3
  include ProMotion::ScreenModule
@@ -1,15 +1,10 @@
1
- motion_require '../view/styling'
2
- motion_require 'extensions/searchable'
3
- motion_require 'extensions/refreshable'
4
- motion_require 'extensions/indexable'
5
-
6
1
  module ProMotion
7
2
  module Table
8
-
9
3
  include ProMotion::Styling
10
4
  include ProMotion::Table::Searchable
11
5
  include ProMotion::Table::Refreshable
12
6
  include ProMotion::Table::Indexable
7
+ include ProMotion::Table::Longpressable
13
8
 
14
9
  attr_reader :promotion_table_data
15
10
 
@@ -21,6 +16,7 @@ module ProMotion
21
16
  check_table_data
22
17
  set_up_searchable
23
18
  set_up_refreshable
19
+ set_up_longpressable
24
20
  end
25
21
 
26
22
  def check_table_data
@@ -47,6 +43,12 @@ module ProMotion
47
43
  end
48
44
  end
49
45
 
46
+ def set_up_longpressable
47
+ if self.class.respond_to?(:get_longpressable) && self.class.get_longpressable
48
+ self.make_longpressable(self.class.get_longpressable_params)
49
+ end
50
+ end
51
+
50
52
  def searching?
51
53
  self.promotion_table_data.filtered
52
54
  end
@@ -62,31 +64,13 @@ module ProMotion
62
64
  def update_table_view_data(data)
63
65
  self.promotion_table_data.data = data
64
66
  table_view.reloadData
65
- end
66
-
67
- # Methods to retrieve data
68
-
69
- def section_at_index(index)
70
- self.promotion_table_data.section(index)
71
- end
72
-
73
- def cell_at_section_and_index(section, index)
74
- self.promotion_table_data.cell(section: section, index: index)
67
+ @table_search_display_controller.searchResultsTableView.reloadData if searching?
75
68
  end
76
69
 
77
70
  def trigger_action(action, arguments)
78
- if self.respond_to?(action)
79
- expected_arguments = self.method(action).arity
80
- if expected_arguments == 0
81
- self.send(action)
82
- elsif expected_arguments == 1 || expected_arguments == -1
83
- self.send(action, arguments)
84
- else
85
- PM.logger.warn "#{action} expects #{expected_arguments} arguments. Maximum number of required arguments for an action is 1."
86
- end
87
- else
88
- PM.logger.info "Action not implemented: #{action.to_s}"
89
- end
71
+ return PM.logger.info "Action not implemented: #{action.to_s}" unless self.respond_to?(action)
72
+ return self.send(action) if self.method(action).arity == 0
73
+ self.send(action, arguments)
90
74
  end
91
75
 
92
76
  def accessory_toggled_switch(switch)
@@ -94,20 +78,16 @@ module ProMotion
94
78
  index_path = closest_parent(UITableView, table_cell).indexPathForCell(table_cell)
95
79
 
96
80
  if index_path
97
- data_cell = cell_at_section_and_index(index_path.section, index_path.row)
81
+ data_cell = promotion_table_data.cell(section: index_path.section, index: index_path.row)
98
82
  data_cell[:accessory][:arguments] ||= {}
99
83
  data_cell[:accessory][:arguments][:value] = switch.isOn if data_cell[:accessory][:arguments].is_a?(Hash)
100
-
101
84
  trigger_action(data_cell[:accessory][:action], data_cell[:accessory][:arguments]) if data_cell[:accessory][:action]
102
85
  end
103
86
  end
104
87
 
105
88
  def delete_row(index_paths, animation = nil)
106
- animation = map_row_animation_symbol(animation)
107
- index_paths = [index_paths] if index_paths.kind_of?(NSIndexPath)
108
89
  deletable_index_paths = []
109
-
110
- index_paths.each do |index_path|
90
+ Array(index_paths).each do |index_path|
111
91
  delete_cell = false
112
92
  delete_cell = send(:on_cell_deleted, self.promotion_table_data.cell(index_path: index_path)) if self.respond_to?("on_cell_deleted:")
113
93
  unless delete_cell == false
@@ -115,45 +95,44 @@ module ProMotion
115
95
  deletable_index_paths << index_path
116
96
  end
117
97
  end
118
- table_view.deleteRowsAtIndexPaths(deletable_index_paths, withRowAnimation:animation) if deletable_index_paths.length > 0
98
+ table_view.deleteRowsAtIndexPaths(deletable_index_paths, withRowAnimation:map_row_animation_symbol(animation)) if deletable_index_paths.length > 0
119
99
  end
120
100
 
121
101
  def table_view_cell(params={})
102
+ params = index_path_to_section_index(params)
103
+ data_cell = self.promotion_table_data.cell(section: params[:section], index: params[:index])
104
+ return UITableViewCell.alloc.init unless data_cell
105
+ create_table_cell(data_cell)
106
+ end
107
+
108
+ def index_path_to_section_index(params)
122
109
  if params[:index_path]
123
110
  params[:section] = params[:index_path].section
124
111
  params[:index] = params[:index_path].row
125
112
  end
126
-
127
- data_cell = self.promotion_table_data.cell(section: params[:section], index: params[:index])
128
- return UITableViewCell.alloc.init unless data_cell # No data?
129
-
130
- table_cell = create_table_cell(data_cell)
131
-
132
- table_cell
113
+ params
133
114
  end
134
115
 
135
116
  def create_table_cell(data_cell)
136
- table_cell = table_view.dequeueReusableCellWithIdentifier(data_cell[:cell_identifier])
137
-
138
- unless table_cell
117
+ table_cell = table_view.dequeueReusableCellWithIdentifier(data_cell[:cell_identifier]) || begin
139
118
  table_cell = data_cell[:cell_class].alloc.initWithStyle(data_cell[:cell_style], reuseIdentifier:data_cell[:cell_identifier])
140
- table_cell.extend PM::TableViewCellModule unless table_cell.is_a?(PM::TableViewCellModule)
119
+ table_cell.extend(PM::TableViewCellModule) unless table_cell.is_a?(PM::TableViewCellModule)
141
120
  table_cell.autoresizingMask = UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin
142
121
  table_cell.clipsToBounds = true # fix for changed default in 7.1
122
+ table_cell
143
123
  end
144
-
145
124
  table_cell.setup(data_cell, self)
146
-
147
125
  table_cell
148
126
  end
149
127
 
150
128
  def update_table_data
151
129
  self.update_table_view_data(self.table_data)
130
+ self.promotion_table_data.search(search_string) if searching?
152
131
  end
153
132
 
154
133
  ########## Cocoa touch methods #################
155
134
  def numberOfSectionsInTableView(table_view)
156
- Array(self.promotion_table_data.data).length
135
+ self.promotion_table_data.sections.length
157
136
  end
158
137
 
159
138
  # Number of cells
@@ -162,8 +141,8 @@ module ProMotion
162
141
  end
163
142
 
164
143
  def tableView(table_view, titleForHeaderInSection:section)
165
- section = section_at_index(section) || return
166
- section[:title]
144
+ section = promotion_table_data.section(section)
145
+ section && section[:title]
167
146
  end
168
147
 
169
148
  # Set table_data_index if you want the right hand index column (jumplist)
@@ -179,8 +158,9 @@ module ProMotion
179
158
 
180
159
  def tableView(table_view, willDisplayCell: table_cell, forRowAtIndexPath: index_path)
181
160
  data_cell = self.promotion_table_data.cell(index_path: index_path)
182
- table_cell.backgroundColor = data_cell[:background_color] || UIColor.whiteColor
183
- table_cell.send(:restyle!) if table_cell.respond_to?(:restyle!)
161
+ set_attributes table_cell, data_cell[:style] if data_cell[:style]
162
+ table_cell.send(:will_display) if table_cell.respond_to?(:will_display)
163
+ table_cell.send(:restyle!) if table_cell.respond_to?(:restyle!) # Teacup compatibility
184
164
  end
185
165
 
186
166
  def tableView(table_view, heightForRowAtIndexPath:index_path)
@@ -190,26 +170,12 @@ module ProMotion
190
170
  def tableView(table_view, didSelectRowAtIndexPath:index_path)
191
171
  data_cell = self.promotion_table_data.cell(index_path: index_path)
192
172
  table_view.deselectRowAtIndexPath(index_path, animated: true) unless data_cell[:keep_selection] == true
193
-
194
- data_cell[:arguments] ||= {}
195
- data_cell[:arguments][:cell] = data_cell if data_cell[:arguments].is_a?(Hash) # TODO: Should we really do this?
196
-
197
173
  trigger_action(data_cell[:action], data_cell[:arguments]) if data_cell[:action]
198
174
  end
199
175
 
200
176
  def tableView(table_view, editingStyleForRowAtIndexPath: index_path)
201
177
  data_cell = self.promotion_table_data.cell(index_path: index_path)
202
-
203
- case data_cell[:editing_style]
204
- when nil, :none
205
- UITableViewCellEditingStyleNone
206
- when :delete
207
- UITableViewCellEditingStyleDelete
208
- when :insert
209
- UITableViewCellEditingStyleInsert
210
- else
211
- data_cell[:editing_style]
212
- end
178
+ map_cell_editing_style(data_cell[:editing_style])
213
179
  end
214
180
 
215
181
  def tableView(table_view, commitEditingStyle: editing_style, forRowAtIndexPath: index_path)
@@ -236,22 +202,16 @@ module ProMotion
236
202
 
237
203
  # Section view methods
238
204
  def tableView(table_view, viewForHeaderInSection: index)
239
- section = section_at_index(index)
240
-
241
- if section[:title_view]
242
- klass = section[:title_view]
243
- view = klass.new if klass.respond_to?(:new)
244
- view.title = section[:title] if view.respond_to?(:title=)
245
- view
246
- else
247
- nil
248
- end
205
+ section = promotion_table_data.section(index)
206
+ view = nil
207
+ view = section[:title_view].new if section[:title_view].respond_to?(:new)
208
+ view.title = section[:title] if view.respond_to?(:title=)
209
+ view
249
210
  end
250
211
 
251
212
  def tableView(table_view, heightForHeaderInSection: index)
252
- section = section_at_index(index)
253
-
254
- if section[:title_view] || (section[:title] && !section[:title].empty?)
213
+ section = promotion_table_data.section(index)
214
+ if section[:title_view] || section[:title].to_s.length > 0
255
215
  section[:title_view_height] || tableView.sectionHeaderHeight
256
216
  else
257
217
  0.0
@@ -260,10 +220,17 @@ module ProMotion
260
220
 
261
221
  protected
262
222
 
223
+ def map_cell_editing_style(symbol)
224
+ {
225
+ none: UITableViewCellEditingStyleNone,
226
+ delete: UITableViewCellEditingStyleDelete,
227
+ insert: UITableViewCellEditingStyleInsert
228
+ }[symbol] || symbol || UITableViewCellEditingStyleNone
229
+ end
230
+
263
231
  def map_row_animation_symbol(symbol)
264
232
  symbol ||= UITableViewRowAnimationAutomatic
265
233
  {
266
- automatic: UITableViewRowAnimationAutomatic,
267
234
  fade: UITableViewRowAnimationFade,
268
235
  right: UITableViewRowAnimationRight,
269
236
  left: UITableViewRowAnimationLeft,
@@ -272,7 +239,7 @@ module ProMotion
272
239
  none: UITableViewRowAnimationNone,
273
240
  middle: UITableViewRowAnimationMiddle,
274
241
  automatic: UITableViewRowAnimationAutomatic
275
- }[symbol] || symbol
242
+ }[symbol] || symbol || UITableViewRowAnimationAutomatic
276
243
  end
277
244
 
278
245
  module TableClassMethods
@@ -322,6 +289,19 @@ module ProMotion
322
289
  @indexable_params ||= nil
323
290
  end
324
291
 
292
+ # Longpressable
293
+ def longpressable(params = {})
294
+ @longpressable_params = params
295
+ @longpressable = true
296
+ end
297
+
298
+ def get_longpressable
299
+ @longpressable ||= false
300
+ end
301
+
302
+ def get_longpressable_params
303
+ @longpressable_params ||= nil
304
+ end
325
305
  end
326
306
 
327
307
  def self.included(base)