module ProMotion::MapScreenModule

Constants

PIN_COLORS

Public Class Methods

included(base) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 439
def self.included(base)
  base.extend(MapClassMethods)
end

Public Instance Methods

add_annotation(annotation) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 113
def add_annotation(annotation)
  @promotion_annotation_data << MapScreenAnnotation.new(annotation)
  self.view.addAnnotation @promotion_annotation_data.last
end
add_annotations(annotations) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 118
def add_annotations(annotations)
  @promotion_annotation_data = Array(annotations).map{|a| MapScreenAnnotation.new(a)}
  self.view.addAnnotations @promotion_annotation_data
end
annotations() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 89
def annotations
  @promotion_annotation_data
end
center() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 39
def center
  self.view.centerCoordinate
end
center=(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 43
def center=(params={})
  PM.logger.error "Missing #:latitude property in call to #center=." unless params[:latitude]
  PM.logger.error "Missing #:longitude property in call to #center=." unless params[:longitude]
  params[:animated] ||= true

  # Set the new region
  self.view.setCenterCoordinate(
    CLLocationCoordinate2D.new(params[:latitude], params[:longitude]),
    animated:params[:animated]
  )
end
check_annotation_data() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 25
def check_annotation_data
  PM.logger.error "Missing #annotation_data method in MapScreen #{self.class.to_s}." unless self.respond_to?(:annotation_data)
end
clear_annotation(annotation) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 123
def clear_annotation(annotation)
  self.view.removeAnnotation(annotation)
  @promotion_annotation_data.delete(annotation)
end
clear_annotations() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 128
def clear_annotations
  self.view.removeAnnotations(@promotion_annotation_data)
  @promotion_annotation_data = []
end
create_region(initialLocation,radius=10) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 267
def create_region(initialLocation,radius=10)
  return nil unless initialLocation.is_a? CLLocationCoordinate2D
  radius = radius * 1.820 # Meters equivalent to 1 Nautical Mile
  southWest = self.point_from_location_bearing_and_distance(initialLocation,225, radius)
  northEast = self.point_from_location_bearing_and_distance(initialLocation,45, radius)
  {:southWest => southWest, :northEast => northEast}
end
Also aliased as: region
deg_to_rad(angle) click to toggle source

REGION SETTINGS #######

# File lib/ProMotion/map/map_screen_module.rb, line 236
def deg_to_rad(angle)
  angle*Math::PI/180
end
deselect_annotations(animated=false) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 105
def deselect_annotations(animated=false)
  unless selected_annotations.nil?
    selected_annotations.each do |annotation|
      self.view.deselectAnnotation(annotation, animated:animated)
    end
  end
end
gesture_drop_pin(gesture_recognizer) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 168
def gesture_drop_pin(gesture_recognizer)
  if gesture_recognizer.state == UIGestureRecognizerStateBegan
    NSNotificationCenter.defaultCenter.postNotificationName("ProMotionMapWillAddPin", object:nil)
    touch_point = gesture_recognizer.locationInView(self.view)
    touch_map_coordinate = self.view.convertPoint(touch_point, toCoordinateFromView:self.view)

    add_annotation({
      coordinate: touch_map_coordinate
    }.merge(@tap_to_add_annotation_params))
    NSNotificationCenter.defaultCenter.postNotificationName("ProMotionMapAddedPin", object:@promotion_annotation_data.last)
  end
end
hide_user_location() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 63
def hide_user_location
  set_show_user_location false
end
look_up_address(args={}, &callback) click to toggle source

END MAP STYLE SETTINGS ######

# File lib/ProMotion/map/map_screen_module.rb, line 286
def look_up_address(args={}, &callback)
  args[:address] = args if args.is_a? String # Assume if a string is passed that they want an address

  geocoder = CLGeocoder.new
  return geocoder.geocodeAddressDictionary(args[:address], completionHandler: callback) if args[:address].is_a?(Hash)
  return geocoder.geocodeAddressString(args[:address].to_s, completionHandler: callback) unless args[:region]
  return geocoder.geocodeAddressString(args[:address].to_s, inRegion:args[:region].to_s, completionHandler: callback) if args[:region]
end
look_up_location(location, &callback) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 295
def look_up_location(location, &callback)
  location = CLLocation.alloc.initWithLatitude(location.latitude, longitude:location.longitude) if location.is_a?(CLLocationCoordinate2D)

  if location.kind_of?(CLLocation)
    geocoder = CLGeocoder.new
    geocoder.reverseGeocodeLocation(location, completionHandler: callback)
  else
    PM.logger.info("You're trying to reverse geocode something that isn't a CLLocation")
    callback.call nil, nil
  end
end
map() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 34
def map
  self.view
end
Also aliased as: mapview
mapView(mapView, annotationCanShowCallout: annotation) click to toggle source

Mapbox GL methods #################

# File lib/ProMotion/map/map_screen_module.rb, line 308
def mapView(mapView, annotationCanShowCallout: annotation)
  return nil if annotation.is_a? MGLUserLocation
  annotation.params[:show_callout]
end
mapview()
Alias for: map
on_appear() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 21
def on_appear
  update_annotation_data
end
point_from_location_bearing_and_distance(initialLocation, bearing, distance) click to toggle source

Input coordinates and bearing in decimal degrees, distance in kilometers

# File lib/ProMotion/map/map_screen_module.rb, line 245
def point_from_location_bearing_and_distance(initialLocation, bearing, distance)
  distance = distance / 6371.01 # Convert to angular radians dividing by the Earth radius
  bearing = deg_to_rad(bearing)
  input_latitude = deg_to_rad(initialLocation.latitude)
  input_longitude = deg_to_rad(initialLocation.longitude)

  output_latitude = Math.asin( 
                      Math.sin(input_latitude) * Math.cos(distance) + 
                      Math.cos(input_latitude) * Math.sin(distance) * 
                      Math.cos(bearing)
                    )

  dlon = input_longitude + Math.atan2(
                            Math.sin(bearing) * Math.sin(distance) * 
                            Math.cos(input_longitude), Math.cos(distance) - 
                            Math.sin(input_longitude) * Math.sin(output_latitude)
                          )

  output_longitude = (dlon + 3*Math::PI) % (2*Math::PI) - Math::PI  
  CLLocationCoordinate2DMake(rad_to_deg(output_latitude), rad_to_deg(output_longitude))
end
rad_to_deg(angle) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 240
def rad_to_deg(angle)
  angle*180/Math::PI
end
region(initialLocation,radius=10)
Alias for: create_region
screen_setup() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 10
def screen_setup
  self.view = nil
  self.view = MGLMapView.alloc.initWithFrame(self.view.bounds, styleURL: self.class.get_map_style)
  self.view.delegate = self

  check_annotation_data
  @promotion_annotation_data = []
  set_up_start_position
  set_up_tap_to_add
end
select_annotation(annotation, animated=true) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 93
def select_annotation(annotation, animated=true)
  self.view.selectAnnotation(annotation, animated:animated)
end
select_annotation_at(annotation_index, animated=true) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 97
def select_annotation_at(annotation_index, animated=true)
  select_annotation(annotations[annotation_index], animated:animated)
end
selected_annotations() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 101
def selected_annotations
  self.view.selectedAnnotations
end
set_map_style() click to toggle source

END REGION SETTINGS ###### MAP STYLE SETTINGS ######

# File lib/ProMotion/map/map_screen_module.rb, line 278
def set_map_style
  if self.class.respond_to?(:get_map_style)
      self.view.styleURL = self.class.get_map_style
  end
end
set_region(region, animated=true) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 228
def set_region(region, animated=true)
  self.view.setVisibleCoordinateBounds(
    [region[:southWest], region[:northEast]],
    animated: animated
  )
end
set_show_user_location(show,mode=MGLUserTrackingModeFollow) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 67
def set_show_user_location(show,mode=MGLUserTrackingModeFollow)
  self.view.showsUserLocation = show
  self.view.userTrackingMode = mode
end
set_start_position(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 133
def set_start_position(params={})
  params = {
    latitude: 37.331789,
    longitude: -122.029620,
    radius: 10
  }.merge(params)

  initialLocation = CLLocationCoordinate2D.new(params[:latitude], params[:longitude])
  region = create_region(initialLocation,params[:radius])
  set_region(region, animated:false)
end
set_tap_to_add(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 151
def set_tap_to_add(params={})
  params = {
    length: 2.0,
    target: self,
    action: "gesture_drop_pin:",
    annotation: {
      title: "Dropped Pin",
      animates_drop: true
    }
  }.merge(params)
  @tap_to_add_annotation_params = params[:annotation]

  lpgr = UILongPressGestureRecognizer.alloc.initWithTarget(params[:target], action:params[:action])
  lpgr.minimumPressDuration = params[:length]
  self.view.addGestureRecognizer(lpgr)
end
set_up_start_position() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 145
def set_up_start_position
  if self.class.respond_to?(:get_start_position) && self.class.get_start_position
    self.set_start_position self.class.get_start_position_params
  end
end
set_up_tap_to_add() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 181
def set_up_tap_to_add
  if self.class.respond_to?(:get_tap_to_add) && self.class.get_tap_to_add
    self.set_tap_to_add self.class.get_tap_to_add_params
  end
end
show_user_location() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 55
def show_user_location
  if location_manager.respondsToSelector('requestWhenInUseAuthorization')
    location_manager.requestWhenInUseAuthorization
  end

  set_show_user_location true
end
showing_user_location?() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 72
def showing_user_location?
  self.view.showsUserLocation
end
type() click to toggle source

Cocoa touch Ruby counterparts #################

# File lib/ProMotion/map/map_screen_module.rb, line 382
def type
  map.mapType
end
type=(type) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 386
def type=(type)
  map.mapType = type
end
update_annotation_data() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 29
def update_annotation_data
  clear_annotations
  add_annotations annotation_data
end
user_annotation() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 80
def user_annotation
  self.view.userLocation.location.nil? ? nil : self.view.userLocation.location
end
user_location() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 76
def user_location
  user_annotation.nil? ? nil : user_annotation.coordinate
end
zoom_to_fit_annotations(args={}) click to toggle source

TODO: Why is this so complex?

# File lib/ProMotion/map/map_screen_module.rb, line 188
def zoom_to_fit_annotations(args={})
  # Preserve backwards compatibility
  args = {animated: args} if args == true || args == false
  args = {animated: true, include_user: false}.merge(args)

  ann = args[:include_user] ? (annotations + [user_annotation]).compact : annotations

  #Don't attempt the rezoom of there are no pins
  return if ann.count == 0

  #Set some crazy boundaries
  topLeft = CLLocationCoordinate2D.new(-90, 180)
  bottomRight = CLLocationCoordinate2D.new(90, -180)

  #Find the bounds of the pins
  ann.each do |a|
    topLeft.longitude = [topLeft.longitude, a.coordinate.longitude].min
    topLeft.latitude = [topLeft.latitude, a.coordinate.latitude].max
    bottomRight.longitude = [bottomRight.longitude, a.coordinate.longitude].max
    bottomRight.latitude = [bottomRight.latitude, a.coordinate.latitude].min
  end

  #Find the bounds of all the pins and set the map_view
  coord = CLLocationCoordinate2D.new(
    topLeft.latitude - (topLeft.latitude - bottomRight.latitude) * 0.5,
    topLeft.longitude + (bottomRight.longitude - topLeft.longitude) * 0.5
  )

  # Add some padding to the edges
  span = MKCoordinateSpanMake(
    ((topLeft.latitude - bottomRight.latitude) * 1.075).abs,
    ((bottomRight.longitude - topLeft.longitude) * 1.075).abs
  )

  region = MKCoordinateRegionMake(coord, span)
  fits = self.view.regionThatFits(region)

  set_region(fits, animated: args[:animated])
end
zoom_to_user(radius = 0.05, animated=true) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 84
def zoom_to_user(radius = 0.05, animated=true)
  show_user_location unless showing_user_location?
  set_region(create_region(user_location,radius), animated)
end

Private Instance Methods

location_manager() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 445
def location_manager
  @location_manager ||= CLLocationManager.alloc.init
  @location_manager.delegate ||= self
  @location_manager
end