module ProMotion::MapScreenModule

Constants

PIN_COLORS

Public Class Methods

included(base) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 382
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
annotation_view(map_view, annotation) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 130
def annotation_view(map_view, annotation)
  return if annotation.is_a? MKUserLocation

  params = annotation.params

  identifier = params[:identifier]
  if view = map_view.dequeueReusableAnnotationViewWithIdentifier(identifier)
    view.annotation = annotation
  else
    # Set the pin properties
    if params[:image]
      view = MKAnnotationView.alloc.initWithAnnotation(annotation, reuseIdentifier:identifier)
    else
      view = MKPinAnnotationView.alloc.initWithAnnotation(annotation, reuseIdentifier:identifier)
    end
  end
  view.image = params[:image] if view.respond_to?("image=") && params[:image]
  view.animatesDrop = params[:animates_drop] if view.respond_to?("animatesDrop=")
  view.pinColor = (PIN_COLORS[params[:pin_color]] || params[:pin_color]) if view.respond_to?("pinColor=")
  view.canShowCallout = params[:show_callout] if view.respond_to?("canShowCallout=")

  if params[:left_accessory]
    view.leftCalloutAccessoryView = params[:left_accessory]
  end
  if params[:right_accessory]
    view.rightCalloutAccessoryView = params[:right_accessory]
  end

  if params[:action]
    button_type = params[:action_button_type] || UIButtonTypeDetailDisclosure

    action_button = UIButton.buttonWithType(button_type)
    action_button.addTarget(self, action: params[:action], forControlEvents:UIControlEventTouchUpInside)

    view.rightCalloutAccessoryView = action_button
  end
  view
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 40
def center
  self.view.centerCoordinate
end
center=(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 44
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 26
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_annotations() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 123
def clear_annotations
  @promotion_annotation_data.each do |a|
    self.view.removeAnnotation(a)
  end
  @promotion_annotation_data = []
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 206
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 64
def hide_user_location
  set_show_user_location false
end
look_up_address(args={}, &callback) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 281
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 290
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 35
def map
  self.view
end
Also aliased as: mapview
mapView(map_view, viewForAnnotation:annotation) click to toggle source

Cocoa touch methods #################

# File lib/ProMotion/map/map_screen_module.rb, line 303
def mapView(map_view, viewForAnnotation:annotation)
  annotation_view(map_view, annotation)
end
mapview()
Alias for: map
region(params) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 270
def region(params)
  return nil unless params.is_a? Hash

  params[:coordinate] = CLLocationCoordinate2D.new(params[:coordinate][:latitude], params[:coordinate][:longitude]) if params[:coordinate].is_a? Hash
  params[:span] = MKCoordinateSpanMake(params[:span][0], params[:span][1]) if params[:span].is_a? Array

  if params[:coordinate] && params[:span]
    MKCoordinateRegionMake( params[:coordinate], params[:span] )
  end
end
screen_setup() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 10
def screen_setup
  self.view = nil
  self.view = MKMapView.alloc.initWithFrame(self.view.bounds)
  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_region(region, animated=true) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 266
def set_region(region, animated=true)
  self.view.setRegion(region, animated:animated)
end
set_show_user_location(show) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 68
def set_show_user_location(show)
  self.view.showsUserLocation = show
end
set_start_position(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 169
def set_start_position(params={})
  params = {
    latitude: 37.331789,
    longitude: -122.029620,
    radius: 10
  }.merge(params)

  meters_per_mile = 1609.344

  initialLocation = CLLocationCoordinate2D.new(params[:latitude], params[:longitude])
  region = MKCoordinateRegionMakeWithDistance(initialLocation, params[:radius] * meters_per_mile, params[:radius] * meters_per_mile)
  set_region(region, animated:false)
end
set_tap_to_add(params={}) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 189
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 183
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 219
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 56
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 333
def type
  map.mapType
end
type=(type) click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 337
def type=(type)
  map.mapType = type
end
update_annotation_data() click to toggle source
# File lib/ProMotion/map/map_screen_module.rb, line 30
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
view_will_appear(animated) click to toggle source
Calls superclass method
# File lib/ProMotion/map/map_screen_module.rb, line 21
def view_will_appear(animated)
  super
  update_annotation_data
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 226
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(MKCoordinateRegionMake(user_location, [radius, radius]), animated)
end

Private Instance Methods

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