aprsdroid/src/GoogleMapAct.scala

221 wiersze
9.2 KiB
Scala

package org.aprsdroid.app
import java.util
import android.app.Activity
import android.os.Bundle
import android.util.Log
import android.view.View
import com.google.android.gms.maps.GoogleMap.{OnCameraMoveListener, OnInfoWindowClickListener, OnMarkerClickListener}
import com.google.android.gms.maps.model.{BitmapDescriptor, BitmapDescriptorFactory, LatLng, Marker, MarkerOptions}
import com.google.android.gms.maps.{CameraUpdateFactory, GoogleMap, MapView, OnMapReadyCallback}
import com.google.maps.android.ui.IconGenerator
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
// to make scala-style iterating over arraylist possible
import scala.collection.JavaConversions._
class GoogleMapAct extends Activity with MapLoaderBase
with OnMarkerClickListener
with OnInfoWindowClickListener with OnCameraMoveListener {
lazy val loading = findViewById(R.id.loading).asInstanceOf[View]
lazy val mapview = findViewById(R.id.mapview).asInstanceOf[MapView]
var map : GoogleMap = null
lazy val icons = mutable.HashMap[String, BitmapDescriptor]()
var visible_callsigns = true
var first_load = true
val CALLSIGN_ZOOM = 8
override def onCreate(savedInstanceState: Bundle) {
super.onCreate(savedInstanceState)
setContentView(R.layout.googlemapview)
mapview.onCreate(savedInstanceState)
mapview.getMapAsync(new OnMapReadyCallback {
override def onMapReady(googleMap: GoogleMap): Unit = {
Log.d(TAG, "Got map!")
map = googleMap
loadMapViewPosition()
setMapMode(MapModes.defaultMapMode(GoogleMapAct.this, prefs))
//not helpful, off at the top:
//map.setMyLocationEnabled(true)
map.setOnMarkerClickListener(GoogleMapAct.this)
map.setOnInfoWindowClickListener(GoogleMapAct.this)
map.setOnCameraMoveListener(GoogleMapAct.this)
map.getUiSettings().setCompassEnabled(true)
map.getUiSettings().setZoomControlsEnabled(true)
visible_callsigns = (map.getCameraPosition().zoom > CALLSIGN_ZOOM)
startLoading()
}
})
Log.d(TAG, "Creating bitmaps...")
Log.d(TAG, "Done creating bitmaps...")
}
override def onLowMemory(): Unit = {
super.onLowMemory()
mapview.onLowMemory()
}
override def onStart(): Unit = {
super.onStart()
mapview.onStart()
}
override def onResume(): Unit = {
super.onResume()
setKeepScreenOn()
setVolumeControls()
mapview.onResume()
if (targetcall != "")
startFollowStation(targetcall)
}
override def onSaveInstanceState(outState: Bundle): Unit = {
super.onSaveInstanceState(outState)
mapview.onSaveInstanceState(outState)
}
override def onPause(): Unit = {
super.onPause()
mapview.onPause()
if (map == null)
return
val position = map.getCameraPosition()
saveMapViewPosition(position.target.latitude.asInstanceOf[Float], position.target.longitude.asInstanceOf[Float], position.zoom)
}
override def onStop(): Unit = {
super.onStop()
mapview.onStop()
}
override def onDestroy(): Unit = {
super.onDestroy()
mapview.onDestroy()
}
override def loadMapViewPosition(lat : Float, lon : Float, zoom : Float) {
map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lon), zoom))
}
override def setMapMode(mm : MapMode) = {
mm match {
case gmm : GoogleMapMode =>
map.setMapType(gmm.mapType)
case _ =>
super.setMapMode(mm)
}
}
override def onStartLoading() {
loading.setVisibility(View.VISIBLE)
}
override def onStopLoading() {
loading.setVisibility(View.GONE)
if (targetcall != "") {
markers.get(targetcall) match {
case None =>
case Some(sta) =>
if (first_load) {
map.animateCamera(CameraUpdateFactory.newLatLngZoom(sta.icon.getPosition(), 14f))
sta.icon.showInfoWindow()
first_load = false
} else
map.animateCamera(CameraUpdateFactory.newLatLng(sta.icon.getPosition()))
}
}
}
override def changeZoom(delta : Int): Unit = {
}
class MarkerInfo(val icon : Marker, val label : Marker, var last_update : Int) {}
val markers = new mutable.HashMap[String, MarkerInfo]()
lazy val drawSize = (getResources().getDisplayMetrics().density * 24).toInt
lazy val iconGenerator = initIconGenerator()
def initIconGenerator(): IconGenerator = {
val ig = new IconGenerator(this)
ig.setBackground(null)
ig.setTextAppearance(R.style.MapCallSign)
ig.setContentPadding(0, 0, 0, 0)
ig
}
def symbol2marker(symbol : String): BitmapDescriptor = {
icons.get(symbol) match {
case Some(desc) => desc
case None =>
val desc = BitmapDescriptorFactory.fromBitmap(symbol2bitmap(symbol, drawSize))
icons(symbol) = desc
desc
}
}
def onStationUpdate(stations : util.ArrayList[Station]): Unit = {
for (sta <- stations) {
//Log.d(TAG, "onStaUpdate: " + sta.call)
if (map == null)
return
val latlon = new LatLng(sta.lat, sta.lon)
markers.get(sta.call) match {
case Some(mi) =>
mi.icon.setPosition(latlon)
mi.label.setPosition(latlon)
mi.last_update = 1234
case None =>
val icon = map.addMarker(new MarkerOptions()
.position(latlon)
.anchor(0.5f, 0.5f) // center at the middle of the icon
//.infoWindowAnchor(0.5f, 0.0f) // at the top of the icon
.flat(true)
//.rotation(sta.course) // TODO fuckers! - the rotation will also rotate the info window anchor
.icon(symbol2marker(sta.symbol))
.title(sta.callQrg())
.snippet(sta.comment))
val label = map.addMarker(new MarkerOptions()
.position(latlon)
.icon(BitmapDescriptorFactory.fromBitmap(iconGenerator.makeIcon(sta.call)))
.visible(visible_callsigns)
.anchor(0.0f, -0.2f) // center text below the icon
)
icon.setTag(sta.call)
label.setTag(sta.call)
markers(sta.call) = new MarkerInfo(icon, label, 0)
}
}
}
// OnMarkerClickListener
override def onMarkerClick(marker : Marker): Boolean = {
Log.d(TAG, "marker click: " + marker.getTitle() + " / " + marker.getTag())
startFollowStation(marker.getTag().toString())
false
}
// OnInfoWindowClickListener
override def onInfoWindowClick(marker: Marker): Unit = {
openDetails(marker.getTag().toString())
}
// OnCameraMoveListener
override def onCameraMove(): Unit = {
val pos = map.getCameraPosition()
Log.d(TAG, "zoom level: " + pos.zoom)
val need_visible = (pos.zoom > CALLSIGN_ZOOM)
if (need_visible != visible_callsigns) {
visible_callsigns = need_visible
for ((call, marker) <- markers)
marker.label.setVisible(visible_callsigns)
}
updateCoordinateInfo(pos.target.latitude.asInstanceOf[Float], pos.target.longitude.asInstanceOf[Float])
}
}