ProMotion-map 0.1.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 730e656d5fad2888c9705a25a3344e086c3db6ff
4
+ data.tar.gz: d6d4d53d49f436970603a88d2c78110699900119
5
+ SHA512:
6
+ metadata.gz: 6fed3989bcade0436a2ee3d5f72f695de72ba733bf846917ab9c4a76cab8b12805eab9c8754cacd353e4b2596f6f86f988b4446f0a0ec1221b72c3399be820a3
7
+ data.tar.gz: e583ef3a2a88df469cbc54c8df5a507508698fd6c15151f9023590120c0b890a6d8e29755eda88a57ce8fb2cd4932ca0d82a527af728f7615ad5a6453797b8a5
data/README.md ADDED
@@ -0,0 +1,224 @@
1
+ # ProMotion-map
2
+
3
+ ProMotion-map is push notification support, extracted from the
4
+ popular RubyMotion gem [ProMotion](https://github.com/clearsightstudio/ProMotion).
5
+
6
+ ## Installation
7
+
8
+ ```ruby
9
+ gem 'ProMotion-map'
10
+ ```
11
+
12
+ ## Usage
13
+
14
+ Easily create a map screen, complete with annotations.
15
+
16
+ *Has all the methods of PM::Screen*
17
+
18
+ ```ruby
19
+ class MyMapScreen < PM::MapScreen
20
+ title "My Map"
21
+ start_position latitude: 35.090648651123, longitude: -82.965972900391, radius: 4
22
+
23
+ def on_appear
24
+ update_annotation_data
25
+ end
26
+
27
+ def annotation_data
28
+ [{
29
+ longitude: -82.965972900391,
30
+ latitude: 35.090648651123,
31
+ title: "Rainbow Falls",
32
+ subtitle: "Nantahala National Forest"
33
+ },{
34
+ longitude: -82.966093558105,
35
+ latitude: 35.092520895652,
36
+ title: "Turtleback Falls",
37
+ subtitle: "Nantahala National Forest"
38
+ },{
39
+ longitude: -82.95916,
40
+ latitude: 35.07496,
41
+ title: "Windy Falls"
42
+ },{
43
+ longitude: -82.943031505056,
44
+ latitude: 35.102516828489,
45
+ title: "Upper Bearwallow Falls",
46
+ subtitle: "Gorges State Park"
47
+ },{
48
+ longitude: -82.956244328014,
49
+ latitude: 35.085548421623,
50
+ title: "Stairway Falls",
51
+ subtitle: "Gorges State Park",
52
+ your_param: "CustomWhatever"
53
+ }, {
54
+ longitude: -82.965972900391,
55
+ latitude: 35.090648651123,
56
+ title: "Rainbow Falls",
57
+ subtitle: "Nantahala National Forest",
58
+ image: UIImage.imageNamed("custom-pin")
59
+ }]
60
+ end
61
+
62
+
63
+ end
64
+ ```
65
+
66
+ Here's a neat way to zoom into a specific marker in an animated fashion and then select the marker:
67
+
68
+ ```ruby
69
+ def zoom_to_marker(marker)
70
+ set_region region(coordinate: marker.coordinate, span: [0.05, 0.05])
71
+ select_annotation marker
72
+ end
73
+ ```
74
+
75
+ ---
76
+
77
+ ### Methods
78
+
79
+ #### annotation_data
80
+
81
+ Method that is called to get the map's annotation data and build the map. If you do not want any annotations, simply return an empty array.
82
+
83
+ ```ruby
84
+ def annotation_data
85
+ [{
86
+ longitude: -82.965972900391,
87
+ latitude: 35.090648651123,
88
+ title: "Rainbow Falls",
89
+ subtitle: "Nantahala National Forest"
90
+ },{
91
+ longitude: -82.965972900391,
92
+ latitude: 35.090648651123,
93
+ title: "Rainbow Falls",
94
+ subtitle: "Nantahala National Forest",
95
+ image: "custom-pin" # Use your own custom image. It will be converted to a UIImage automatically.
96
+ },{
97
+ longitude: -82.966093558105,
98
+ latitude: 35.092520895652,
99
+ title: "Turtleback Falls",
100
+ subtitle: "Nantahala National Forest"
101
+ },{
102
+ longitude: -82.95916,
103
+ latitude: 35.07496,
104
+ title: "Windy Falls"
105
+ },{
106
+ longitude: -82.943031505056,
107
+ latitude: 35.102516828489,
108
+ title: "Upper Bearwallow Falls",
109
+ subtitle: "Gorges State Park"
110
+ },{
111
+ longitude: -82.956244328014,
112
+ latitude: 35.085548421623,
113
+ title: "Stairway Falls",
114
+ subtitle: "Gorges State Park",
115
+ your_param: "CustomWahtever"
116
+ }]
117
+ end
118
+ ```
119
+
120
+ You may pass whatever properties you want in the annotation hash, but `:longitude`, `:latitude`, and `:title` are required.
121
+
122
+ Use `:image` to specify a custom image. Pass in a string to conserve memory and it will be converted using `UIImage.imageNamed(your_string)`. If you pass in a `UIImage`, we'll use that, but keep in mind that there will be another unnecessary copy of the UIImage in memory.
123
+
124
+ You can access annotation data you've arbitrarily stored in the hash by calling `annotation_instance.annotation_params[:your_param]`.
125
+
126
+ #### update_annotation_data
127
+
128
+ Forces a reload of all the annotations
129
+
130
+ #### center
131
+
132
+ Returns a `CLLocation2D` instance with the center coordinates of the map.
133
+
134
+ #### center=({latitude: Float, longitude: Float, animated: Boolean})
135
+
136
+ Sets the center of the map. `animated` property defaults to `true`.
137
+
138
+ #### annotations
139
+
140
+ Returns an array of all the annotations.
141
+
142
+ #### select_annotation(annotation, animated=true)
143
+
144
+ Selects a single annotation.
145
+
146
+ #### select_annotation_at(annotation_index, animated=true)
147
+
148
+ Selects a single annotation using the annotation at the index of your `annotation_data` array.
149
+
150
+ #### selected_annotations
151
+
152
+ Returns an array of annotations that are selected. If no annotations are selected, returns `nil`.
153
+
154
+ #### deselect_annotations(animated=false)
155
+
156
+ Deselects all selected annotations.
157
+
158
+ #### add_annotation(annotation)
159
+
160
+ Adds a new annotation to the map. Refer to `annotation_data` (above) for hash properties.
161
+
162
+ #### add_annotations(annotations)
163
+
164
+ Adds more than one annotation at a time to the map.
165
+
166
+ #### clear_annotations
167
+
168
+ Removes all annotations from the `MapScreen`.
169
+
170
+ #### zoom_to_fit_annotations(animated=true)
171
+
172
+ Changes the zoom and center point of the `MapScreen` to fit all the annotations.
173
+
174
+ #### set_region(region, animated=true)
175
+
176
+ Sets the region of the `MapScreen`. `region` should be an instance of `MKCoordinateRegion`.
177
+
178
+ #### region(params)
179
+
180
+ Helper method to create an `MKCoordinateRegion`. Expects a hash in the form of:
181
+
182
+ ```ruby
183
+ my_region = region({
184
+ coordinate:{
185
+ latitude: 35.0906,
186
+ longitude: -82.965
187
+ },
188
+ # span is the latitude and longitude delta
189
+ span: [0.5, 0.5]
190
+ })
191
+ ```
192
+
193
+ ---
194
+
195
+ ### Class Methods
196
+
197
+ #### start_position(latitude: Float, longitude: Float, radius: Float)
198
+
199
+ Class method to set the initial starting position of the `MapScreen`.
200
+
201
+ ```ruby
202
+ class MyMapScreen < PM::MapScreen
203
+ start_position latitude: 36.10, longitude: -80.26, radius: 4
204
+ end
205
+ ```
206
+
207
+ `radius` is the zoom level of the map in miles (default: 10).
208
+
209
+ ---
210
+
211
+ ### Accessors
212
+
213
+ #### mapview
214
+
215
+ Reference to the created UIMapView.
216
+
217
+ ## Contributing
218
+
219
+ 1. Fork it
220
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
221
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
222
+ 4. Make some specs pass
223
+ 5. Push to the branch (`git push origin my-new-feature`)
224
+ 6. Create new Pull Request
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ unless defined?(Motion::Project::Config)
4
+ raise "ProMotion-map must be required within a RubyMotion project."
5
+ end
6
+
7
+ Motion::Project::App.setup do |app|
8
+ lib_dir_path = File.dirname(File.expand_path(__FILE__))
9
+ app.files << File.join(lib_dir_path, "ProMotion/map/map_screen_annotation.rb")
10
+ app.files << File.join(lib_dir_path, "ProMotion/map/map_screen_module.rb")
11
+ app.files << File.join(lib_dir_path, "ProMotion/map/map_screen.rb")
12
+
13
+ app.frameworks += %w(CoreLocation MapKit)
14
+ end
@@ -0,0 +1,6 @@
1
+ module ProMotion
2
+ class MapScreen < ViewController
3
+ include ProMotion::ScreenModule
4
+ include ProMotion::MapScreenModule
5
+ end
6
+ end
@@ -0,0 +1,65 @@
1
+ module ProMotion
2
+ class MapScreenAnnotation
3
+
4
+ # Creates the new annotation object
5
+ def initialize(params = {})
6
+ @params = params
7
+ set_defaults
8
+
9
+ unless @params[:latitude] && @params[:longitude]
10
+ PM.logger.error("You are required to specify :latitude and :longitude for annotations.")
11
+ return nil
12
+ end
13
+ @coordinate = CLLocationCoordinate2D.new(@params[:latitude], @params[:longitude])
14
+ end
15
+
16
+ def set_defaults
17
+ @params = {
18
+ title: "Title",
19
+ pin_color: MKPinAnnotationColorRed,
20
+ identifier: "Annotation-#{@params[:pin_color] || @params[:image]}",
21
+ show_callout: true,
22
+ animates_drop: false
23
+ }.merge(@params)
24
+ end
25
+
26
+ def title
27
+ @params[:title]
28
+ end
29
+
30
+ def subtitle
31
+ @params[:subtitle] ||= nil
32
+ end
33
+
34
+ def coordinate
35
+ @coordinate
36
+ end
37
+
38
+ def cllocation
39
+ CLLocation.alloc.initWithLatitude(@params[:latitude], longitude:@params[:longitude])
40
+ end
41
+
42
+ def setCoordinate(new_coordinate);
43
+ if new_coordinate.is_a? Hash
44
+ @coordinate = CLLocationCoordinate2D.new(new_coordinate[:latitude], new_coordinate[:longitude])
45
+ else
46
+ @coordinate = new_coordinate
47
+ end
48
+ end
49
+
50
+ # Allows for retrieving your own custom values on the annotation
51
+ def annotation_params
52
+ @params
53
+ end
54
+
55
+ def method_missing(meth, *args)
56
+ if @params[meth.to_sym]
57
+ @params[meth.to_sym]
58
+ else
59
+ PM.logger.warn "The annotation parameter \"#{meth}\" does not exist on this pin."
60
+ nil
61
+ end
62
+ end
63
+
64
+ end
65
+ end
@@ -0,0 +1,248 @@
1
+ module ProMotion
2
+ module MapScreenModule
3
+ attr_accessor :mapview
4
+
5
+ def screen_setup
6
+ check_mapkit_included
7
+ self.mapview ||= add MKMapView.new, {
8
+ frame: CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height),
9
+ resize: [ :width, :height ],
10
+ delegate: self
11
+ }
12
+
13
+ check_annotation_data
14
+ @promotion_annotation_data = []
15
+ set_up_start_position
16
+ end
17
+
18
+ def view_will_appear(animated)
19
+ super
20
+ update_annotation_data
21
+ end
22
+
23
+ def check_mapkit_included
24
+ PM.logger.error "You must add MapKit and CoreLocation to your project's frameworks in the Rakefile." unless defined?(CLLocationCoordinate2D)
25
+ end
26
+
27
+ def check_annotation_data
28
+ PM.logger.error "Missing #annotation_data method in MapScreen #{self.class.to_s}." unless self.respond_to?(:annotation_data)
29
+ end
30
+
31
+ def update_annotation_data
32
+ clear_annotations
33
+ add_annotations annotation_data
34
+ end
35
+
36
+ def map
37
+ self.mapview
38
+ end
39
+
40
+ def center
41
+ self.mapview.centerCoordinate
42
+ end
43
+
44
+ def center=(params={})
45
+ PM.logger.error "Missing #:latitude property in call to #center=." unless params[:latitude]
46
+ PM.logger.error "Missing #:longitude property in call to #center=." unless params[:longitude]
47
+ params[:animated] = true
48
+
49
+ # Set the new region
50
+ self.mapview.setCenterCoordinate(
51
+ CLLocationCoordinate2D.new(params[:latitude], params[:longitude]),
52
+ animated:params[:animated]
53
+ )
54
+ end
55
+
56
+ def show_user_location
57
+ set_show_user_location true
58
+ end
59
+
60
+ def hide_user_location
61
+ set_show_user_location false
62
+ end
63
+
64
+ def set_show_user_location(show)
65
+ self.mapview.showsUserLocation = show
66
+ end
67
+
68
+ def showing_user_location?
69
+ self.mapview.showsUserLocation
70
+ end
71
+
72
+ def user_location
73
+ self.mapview.userLocation.location.nil? ? nil : self.mapview.userLocation.location.coordinate
74
+ end
75
+
76
+ def zoom_to_user(radius = 0.05, animated=true)
77
+ show_user_location unless showing_user_location?
78
+ set_region(MKCoordinateRegionMake(user_location, [radius, radius]), animated)
79
+ end
80
+
81
+ def annotations
82
+ @promotion_annotation_data
83
+ end
84
+
85
+ def select_annotation(annotation, animated=true)
86
+ self.mapview.selectAnnotation(annotation, animated:animated)
87
+ end
88
+
89
+ def select_annotation_at(annotation_index, animated=true)
90
+ select_annotation(annotations[annotation_index], animated:animated)
91
+ end
92
+
93
+ def selected_annotations
94
+ self.mapview.selectedAnnotations
95
+ end
96
+
97
+ def deselect_annotations(animated=false)
98
+ unless selected_annotations.nil?
99
+ selected_annotations.each do |annotation|
100
+ self.mapview.deselectAnnotation(annotation, animated:animated)
101
+ end
102
+ end
103
+ end
104
+
105
+ def add_annotation(annotation)
106
+ @promotion_annotation_data << MapScreenAnnotation.new(annotation)
107
+ self.mapview.addAnnotation @promotion_annotation_data.last
108
+ end
109
+
110
+ def add_annotations(annotations)
111
+ @promotion_annotation_data = Array(annotations).map{|a| MapScreenAnnotation.new(a)}
112
+ self.mapview.addAnnotations @promotion_annotation_data
113
+ end
114
+
115
+ def clear_annotations
116
+ @promotion_annotation_data.each do |a|
117
+ self.mapview.removeAnnotation(a)
118
+ end
119
+ @promotion_annotation_data = []
120
+ end
121
+
122
+ def mapView(mapView, viewForAnnotation:annotation)
123
+ return if annotation.is_a? MKUserLocation
124
+
125
+ identifier = annotation.annotation_params[:identifier]
126
+ if view = mapView.dequeueReusableAnnotationViewWithIdentifier(identifier)
127
+ view.annotation = annotation
128
+ else
129
+ #Set the pin properties
130
+ if annotation.annotation_params[:image]
131
+ view = MKAnnotationView.alloc.initWithAnnotation(annotation, reuseIdentifier:identifier)
132
+ view.image = annotation.annotation_params[:image]
133
+ else
134
+ view = MKPinAnnotationView.alloc.initWithAnnotation(annotation, reuseIdentifier:identifier)
135
+ view.animatesDrop = annotation.annotation_params[:animates_drop]
136
+ view.pinColor = annotation.annotation_params[:pin_color]
137
+ end
138
+ view.canShowCallout = annotation.annotation_params[:show_callout]
139
+ end
140
+ view
141
+ end
142
+
143
+ def set_start_position(params={})
144
+ params[:latitude] ||= 37.331789
145
+ params[:longitude] ||= -122.029620
146
+ params[:radius] ||= 10
147
+
148
+ meters_per_mile = 1609.344
149
+
150
+ initialLocation = CLLocationCoordinate2D.new(params[:latitude], params[:longitude])
151
+ region = MKCoordinateRegionMakeWithDistance(initialLocation, params[:radius] * meters_per_mile, params[:radius] * meters_per_mile)
152
+ set_region(region, animated:false)
153
+ end
154
+
155
+ def set_up_start_position
156
+ if self.class.respond_to?(:get_start_position) && self.class.get_start_position
157
+ self.set_start_position self.class.get_start_position_params
158
+ end
159
+ end
160
+
161
+ # TODO: Why is this so complex?
162
+ def zoom_to_fit_annotations(animated=true)
163
+ #Don't attempt the rezoom of there are no pins
164
+ return if annotations.count == 0
165
+
166
+ #Set some crazy boundaries
167
+ topLeft = CLLocationCoordinate2D.new(-90, 180)
168
+ bottomRight = CLLocationCoordinate2D.new(90, -180)
169
+
170
+ #Find the bounds of the pins
171
+ annotations.each do |a|
172
+ topLeft.longitude = [topLeft.longitude, a.coordinate.longitude].min
173
+ topLeft.latitude = [topLeft.latitude, a.coordinate.latitude].max
174
+ bottomRight.longitude = [bottomRight.longitude, a.coordinate.longitude].max
175
+ bottomRight.latitude = [bottomRight.latitude, a.coordinate.latitude].min
176
+ end
177
+
178
+ #Find the bounds of all the pins and set the mapView
179
+ coord = CLLocationCoordinate2D.new(
180
+ topLeft.latitude - (topLeft.latitude - bottomRight.latitude) * 0.5,
181
+ topLeft.longitude + (bottomRight.longitude - topLeft.longitude) * 0.5
182
+ )
183
+
184
+ # Add some padding to the edges
185
+ span = MKCoordinateSpanMake(
186
+ ((topLeft.latitude - bottomRight.latitude) * 1.075).abs,
187
+ ((bottomRight.longitude - topLeft.longitude) * 1.075).abs
188
+ )
189
+
190
+ region = MKCoordinateRegionMake(coord, span)
191
+ fits = self.mapview.regionThatFits(region);
192
+
193
+ set_region(fits, animated:animated)
194
+ end
195
+
196
+ def set_region(region, animated=true)
197
+ self.mapview.setRegion(region, animated:animated)
198
+ end
199
+
200
+ def region(params)
201
+ return nil unless params.is_a? Hash
202
+
203
+ params[:coordinate] = CLLocationCoordinate2D.new(params[:coordinate][:latitude], params[:coordinate][:longitude]) if params[:coordinate].is_a? Hash
204
+ params[:span] = MKCoordinateSpanMake(params[:span][0], params[:span][1]) if params[:span].is_a? Array
205
+
206
+ if params[:coordinate] && params[:span]
207
+ MKCoordinateRegionMake( params[:coordinate], params[:span] )
208
+ end
209
+ end
210
+
211
+ def look_up_address(args={}, &callback)
212
+ args[:address] = args if args.is_a? String # Assume if a string is passed that they want an address
213
+
214
+ geocoder = CLGeocoder.new
215
+ return geocoder.geocodeAddressDictionary(args[:address], completionHandler: callback) if args[:address].is_a?(Hash)
216
+ return geocoder.geocodeAddressString(args[:address].to_s, completionHandler: callback) unless args[:region]
217
+ return geocoder.geocodeAddressString(args[:address].to_s, inRegion:args[:region].to_s, completionHandler: callback) if args[:region]
218
+ end
219
+
220
+ ########## Cocoa touch methods #################
221
+ def mapView(mapView, didUpdateUserLocation:userLocation)
222
+ if self.respond_to?(:on_user_location)
223
+ on_user_location(userLocation)
224
+ else
225
+ PM.logger.info "You're tracking the user's location but have not implemented the #on_user_location(location) method in MapScreen #{self.class.to_s}."
226
+ end
227
+ end
228
+
229
+ module MapClassMethods
230
+ def start_position(params={})
231
+ @start_position_params = params
232
+ @start_position = true
233
+ end
234
+
235
+ def get_start_position_params
236
+ @start_position_params ||= nil
237
+ end
238
+
239
+ def get_start_position
240
+ @start_position ||= false
241
+ end
242
+ end
243
+ def self.included(base)
244
+ base.extend(MapClassMethods)
245
+ end
246
+
247
+ end
248
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ProMotion-map
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Mark Rickert
8
+ - Jamon Holmgren
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-05-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: ProMotion
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: 2.0.0
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: 2.0.0
28
+ - !ruby/object:Gem::Dependency
29
+ name: motion-stump
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '0.3'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '0.3'
42
+ - !ruby/object:Gem::Dependency
43
+ name: motion-redgreen
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '0.1'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '0.1'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rake
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ description: Adds PM::MapScreen support to ProMotion.
71
+ email:
72
+ - mark@mohawkapps.com
73
+ - jamon@clearsightstudio.com
74
+ executables: []
75
+ extensions: []
76
+ extra_rdoc_files: []
77
+ files:
78
+ - README.md
79
+ - lib/ProMotion-map.rb
80
+ - lib/ProMotion/map/map_screen.rb
81
+ - lib/ProMotion/map/map_screen_annotation.rb
82
+ - lib/ProMotion/map/map_screen_module.rb
83
+ homepage: https://github.com/clearsightstudio/ProMotion-map
84
+ licenses:
85
+ - MIT
86
+ metadata: {}
87
+ post_install_message:
88
+ rdoc_options: []
89
+ require_paths:
90
+ - lib
91
+ required_ruby_version: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: '0'
101
+ requirements: []
102
+ rubyforge_project:
103
+ rubygems_version: 2.2.2
104
+ signing_key:
105
+ specification_version: 4
106
+ summary: Adds PM::MapScreen support to ProMotion. Extracted from ProMotion.
107
+ test_files: []