ProMotion 1.2.1 → 2.0.0.rc1
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.
- checksums.yaml +4 -4
- data/README.md +36 -10
- data/lib/ProMotion.rb +11 -2
- data/lib/ProMotion/cocoatouch/ns_string.rb +5 -0
- data/lib/ProMotion/cocoatouch/ns_url.rb +5 -0
- data/lib/ProMotion/cocoatouch/tab_bar_controller.rb +5 -7
- data/lib/ProMotion/cocoatouch/table_view_cell.rb +0 -16
- data/lib/ProMotion/cocoatouch/table_view_controller.rb +2 -3
- data/lib/ProMotion/cocoatouch/view_controller.rb +3 -6
- data/lib/ProMotion/delegate/delegate.rb +0 -3
- data/lib/ProMotion/delegate/delegate_module.rb +24 -20
- data/lib/ProMotion/{containers → ipad}/split_screen.rb +30 -32
- data/lib/ProMotion/{logger.rb → logger/logger.rb} +6 -5
- data/lib/ProMotion/screen/nav_bar_module.rb +126 -0
- data/lib/ProMotion/screen/screen.rb +0 -3
- data/lib/ProMotion/screen/screen_module.rb +54 -177
- data/lib/ProMotion/screen/screen_navigation.rb +29 -40
- data/lib/ProMotion/{view → styling}/styling.rb +17 -47
- data/lib/ProMotion/table/cell/table_view_cell_module.rb +76 -123
- data/lib/ProMotion/table/data/table_data.rb +1 -1
- data/lib/ProMotion/table/extensions/longpressable.rb +24 -0
- data/lib/ProMotion/table/extensions/refreshable.rb +1 -0
- data/lib/ProMotion/table/grouped_table_screen.rb +0 -5
- data/lib/ProMotion/table/table.rb +63 -83
- data/lib/ProMotion/table/table_screen.rb +0 -4
- data/lib/ProMotion/{containers → tabs}/tabs.rb +20 -21
- data/lib/ProMotion/version.rb +1 -1
- data/lib/ProMotion/web/web_screen.rb +0 -4
- data/lib/ProMotion/web/web_screen_module.rb +8 -5
- data/spec/functional/func_screen_spec.rb +14 -18
- data/spec/functional/func_split_screen_spec.rb +2 -2
- data/spec/functional/func_table_screen_spec.rb +54 -40
- data/spec/functional/func_web_screen_spec.rb +12 -17
- data/spec/helpers/test_helper.rb +27 -0
- data/spec/unit/delegate_spec.rb +4 -67
- data/spec/unit/image_title_screen.rb +9 -0
- data/spec/unit/image_view_title_screen.rb +9 -0
- data/spec/unit/load_view_spec.rb +27 -0
- data/spec/unit/main_spec.rb +0 -6
- data/spec/unit/screen_helpers_spec.rb +23 -17
- data/spec/unit/screen_spec.rb +21 -17
- data/spec/unit/searchable_table_spec.rb +55 -0
- data/spec/unit/split_screen_in_tab_bar_spec.rb +5 -5
- data/spec/unit/split_screen_spec.rb +4 -4
- data/spec/unit/tab_bar_spec.rb +79 -0
- data/spec/unit/tab_spec.rb +11 -5
- data/spec/unit/tables/table_module_spec.rb +22 -8
- data/spec/unit/tables/table_screen_spec.rb +1 -1
- data/spec/unit/tables/table_view_cell_spec.rb +16 -16
- data/spec/unit/view_helper_spec.rb +6 -81
- data/spec/unit/view_title_screen.rb +10 -0
- data/spec/unit/web_spec.rb +31 -37
- metadata +37 -111
- data/.gitignore +0 -33
- data/.travis.yml +0 -4
- data/CONTRIBUTING.md +0 -20
- data/Gemfile +0 -5
- data/LICENSE +0 -22
- data/ProMotion.gemspec +0 -30
- data/Rakefile +0 -66
- data/app/app_delegate.rb +0 -7
- data/app/screens/basic_screen.rb +0 -15
- data/lib/ProMotion/delegate/delegate_notifications.rb +0 -70
- data/lib/ProMotion/extensions/conversions.rb +0 -20
- data/lib/ProMotion/map/map_screen.rb +0 -10
- data/lib/ProMotion/map/map_screen_annotation.rb +0 -65
- data/lib/ProMotion/map/map_screen_module.rb +0 -212
- data/lib/ProMotion/push_notification/push_notification.rb +0 -58
- data/resources/WebScreen.html +0 -6
- data/resources/list.png +0 -0
- data/resources/test.png +0 -0
- data/spec/functional/func_image_title_screen.rb +0 -20
- data/spec/functional/func_image_view_title_screen.rb +0 -20
- data/spec/functional/func_map_screen_spec.rb +0 -162
- data/spec/functional/func_searchable_table_spec.rb +0 -56
- data/spec/functional/func_tab_bar_spec.rb +0 -78
- data/spec/functional/func_view_title_screen.rb +0 -21
- data/spec/helpers/basic_screen.rb +0 -3
- data/spec/helpers/custom_title_view.rb +0 -4
- data/spec/helpers/detail_screen.rb +0 -3
- data/spec/helpers/dummy_class.rb +0 -3
- data/spec/helpers/functional_screen.rb +0 -15
- data/spec/helpers/home_screen.rb +0 -19
- data/spec/helpers/image_title_screen.rb +0 -15
- data/spec/helpers/image_view_title_screen.rb +0 -15
- data/spec/helpers/map_screen.rb +0 -53
- data/spec/helpers/master_screen.rb +0 -3
- data/spec/helpers/present_screen.rb +0 -26
- data/spec/helpers/screen_module_view_controller.rb +0 -55
- data/spec/helpers/tab_screen.rb +0 -4
- data/spec/helpers/table_screen.rb +0 -117
- data/spec/helpers/table_screen_indexable.rb +0 -18
- data/spec/helpers/table_screen_refreshable.rb +0 -11
- data/spec/helpers/table_screen_searchable.rb +0 -72
- data/spec/helpers/test_delegate.rb +0 -34
- data/spec/helpers/test_delegate_colors.rb +0 -17
- data/spec/helpers/view_title_screen.rb +0 -15
- data/spec/helpers/web_screen.rb +0 -23
- 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
|
-
|
|
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
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
check_deprecated_styles
|
|
12
|
+
set_styles
|
|
13
|
+
set_title
|
|
16
14
|
set_subtitle
|
|
17
15
|
set_image
|
|
18
16
|
set_remote_image
|
|
19
|
-
|
|
20
|
-
set_details
|
|
21
|
-
set_styles
|
|
17
|
+
set_accessory_view
|
|
22
18
|
set_selection_style
|
|
23
|
-
|
|
24
|
-
self
|
|
25
19
|
end
|
|
26
20
|
|
|
27
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
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
|
-
|
|
35
|
+
def set_title
|
|
36
|
+
set_attributed_text(self.textLabel, data_cell[:title])
|
|
51
37
|
end
|
|
52
38
|
|
|
53
39
|
def set_subtitle
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
|
103
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
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
|
|
159
|
-
|
|
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
|
-
|
|
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]
|
|
169
|
-
|
|
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
|
|
@@ -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,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
|
-
|
|
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
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
183
|
-
table_cell.send(:
|
|
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 =
|
|
240
|
-
|
|
241
|
-
if section[:title_view]
|
|
242
|
-
|
|
243
|
-
|
|
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 =
|
|
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)
|