From f6171f524e64966355fa64644a46939a35beb412 Mon Sep 17 00:00:00 2001 From: Isidro Henoch Date: Mon, 3 Jan 2022 15:15:50 -0600 Subject: Splits the MapFragment funcionality - Now there's MapFragment, which is the map and is responsible for displaying markers and focusing on a particular point. This functionality will be extended. - UnitMapFragment is the entity in charge of the subscriptions and converts UnitInformation entities to something MapFragment can handle. --- .../TrackerMap/android/map/MapFragment.kt | 168 +++++++++++---------- .../TrackerMap/android/map/UnitMapFragment.kt | 103 +++++++++++++ .../TrackerMap/android/units/UnitsActivity.kt | 3 +- 3 files changed, 195 insertions(+), 79 deletions(-) create mode 100644 androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt (limited to 'androidApp/src/main/java') diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt index 8dbd26c..bd17013 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/MapFragment.kt @@ -1,22 +1,41 @@ package mx.trackermap.TrackerMap.android.map +import android.graphics.Bitmap import android.graphics.BitmapFactory import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import com.mousebird.maply.* +import com.mousebird.maply.ComponentObject +import com.mousebird.maply.GlobeMapFragment +import com.mousebird.maply.MarkerInfo +import com.mousebird.maply.Point2d +import com.mousebird.maply.QuadImageLoader +import com.mousebird.maply.RemoteTileInfoNew +import com.mousebird.maply.RenderController +import com.mousebird.maply.RenderControllerInterface +import com.mousebird.maply.SamplingParams +import com.mousebird.maply.ScreenMarker +import com.mousebird.maply.SphericalMercatorCoordSystem +import java.io.File import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.R -import mx.trackermap.TrackerMap.android.units.UnitsViewModel -import org.koin.androidx.viewmodel.ext.android.viewModel -import java.io.File @DelicateCoroutinesApi -class MapFragment: GlobeMapFragment() { +class MapFragment : GlobeMapFragment() { + + enum class MarkerType { + ANIMAL, BICYCLE, BOAT, BUS, CAR, CRANE, DEFAULT, HELICOPTER, MOTORCYCLE, OFFROAD, PERSON, + PICKUP, PLANE, SCOOTER, SHIP, TRACTOR, TRAIN, TRAM, TROLLEYBUS, TRUCK, VAN + } - private val unitsViewModel: UnitsViewModel by viewModel() + data class Marker( + val id: Int, + val latitude: Double, + val longitude: Double, + val type: MarkerType = MarkerType.DEFAULT + ) private val markers = mutableListOf>() @@ -38,7 +57,11 @@ class MapFragment: GlobeMapFragment() { val cacheDir = File(activity!!.cacheDir, cacheDirName) cacheDir.mkdir() - val tileInfo = RemoteTileInfoNew("https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}&s=Ga", 0, 21) + val tileInfo = RemoteTileInfoNew( + "https://mt0.google.com/vt/lyrs=m&hl=en&x={x}&y={y}&z={z}&s=Ga", + 0, + 21 + ) tileInfo.cacheDir = cacheDir val params = SamplingParams() @@ -58,80 +81,69 @@ class MapFragment: GlobeMapFragment() { mapControl.setPositionGeo(longitude, latitude, zoom) } - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - setupObservers() + fun clear() { + mapControl.removeObjects( + markers.map { it.second }, + RenderControllerInterface.ThreadMode.ThreadAny + ) } - @DelicateCoroutinesApi - private fun setupObservers() { - Log.d("MapFragment", "setupObservers()") - unitsViewModel.units.observe(viewLifecycleOwner) { units -> - /* Remove all markers */ - markers.forEach { - mapControl.removeObject(it.second, ThreadMode.ThreadAny) - } - markers.clear() - - /* Reinsert markers from units */ - units.forEach { unit -> - unit.position?.let { position -> - if (position.longitude != null && position.longitude != null) { - val icon = - BitmapFactory.decodeResource( - activity!!.resources, - when (unit.device.category?.lowercase()) { - "animal" -> R.drawable.map_animal - "bicycle" -> R.drawable.map_bicycle - "boat" -> R.drawable.map_boat - "bus" -> R.drawable.map_bus - "car" -> R.drawable.map_car - "crane" -> R.drawable.map_crane - "default" -> R.drawable.map_default - "helicopter" -> R.drawable.map_helicopter - "motorcycle" -> R.drawable.map_motorcycle - "offroad" -> R.drawable.map_offroad - "person" -> R.drawable.map_person - "pickup" -> R.drawable.map_pickup - "plane" -> R.drawable.map_plane - "scooter" -> R.drawable.map_scooter - "ship" -> R.drawable.map_ship - "tractor" -> R.drawable.map_tractor - "train" -> R.drawable.map_train - "tram" -> R.drawable.map_tram - "trolleybus" -> R.drawable.map_trolleybus - "truck" -> R.drawable.map_truck - "van" -> R.drawable.map_van - else -> R.drawable.map_default - } - ) - - val marker = ScreenMarker() - val markerSize = Point2d(144.0, 144.0) - - marker.loc = Point2d.FromDegrees(position.longitude!!, position.latitude!!) - marker.image = icon - marker.size = markerSize - marker.userObject = unit - - /* Add marker to map */ - val markerInfo = MarkerInfo() - val componentObject = mapControl.addScreenMarker(marker, markerInfo, ThreadMode.ThreadAny) - markers.add(marker to componentObject) - } - } - } + fun display(markers: Array) { + Log.d("MapFragment", "Displaying markers") + + clear() + + val screenMarkers = markers.map { marker -> + val screenMarker = ScreenMarker() + val markerSize = Point2d(144.0, 144.0) + + screenMarker.loc = Point2d.FromDegrees(marker.longitude, marker.latitude) + screenMarker.image = getIcon(marker.type) + screenMarker.size = markerSize + screenMarker.userObject = marker.id + + screenMarker } - unitsViewModel.selectedUnit.observe(viewLifecycleOwner) { - it?.let { unit -> - unit.position?.let { position -> - val latitude = position.latitude!! * Math.PI / 180 - val longitude = position.longitude!! * Math.PI / 180 - val zoom = 0.000008 - mapControl.setPositionGeo(longitude, latitude, zoom) - } + mapControl.addScreenMarkers( + screenMarkers, + MarkerInfo(), + RenderControllerInterface.ThreadMode.ThreadAny + ) + } + + fun focusOn(latitude: Double, longitude: Double) { + val lat = latitude * Math.PI / 180 + val lon = longitude * Math.PI / 180 + val zoom = 0.000008 + mapControl.setPositionGeo(lon, lat, zoom) + } + + private fun getIcon(markerType: MarkerType): Bitmap { + return BitmapFactory.decodeResource( + activity!!.resources, + when (markerType) { + MarkerType.ANIMAL -> R.drawable.map_animal + MarkerType.BICYCLE -> R.drawable.map_bicycle + MarkerType.BOAT -> R.drawable.map_boat + MarkerType.BUS -> R.drawable.map_bus + MarkerType.CAR -> R.drawable.map_car + MarkerType.CRANE -> R.drawable.map_crane + MarkerType.DEFAULT -> R.drawable.map_default + MarkerType.HELICOPTER -> R.drawable.map_helicopter + MarkerType.MOTORCYCLE -> R.drawable.map_motorcycle + MarkerType.OFFROAD -> R.drawable.map_offroad + MarkerType.PERSON -> R.drawable.map_person + MarkerType.PICKUP -> R.drawable.map_pickup + MarkerType.PLANE -> R.drawable.map_plane + MarkerType.SCOOTER -> R.drawable.map_scooter + MarkerType.SHIP -> R.drawable.map_ship + MarkerType.TRACTOR -> R.drawable.map_tractor + MarkerType.TRAIN -> R.drawable.map_train + MarkerType.TRAM -> R.drawable.map_tram + MarkerType.TROLLEYBUS -> R.drawable.map_trolleybus + MarkerType.TRUCK -> R.drawable.map_truck + MarkerType.VAN -> R.drawable.map_van } - } + ) } } \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt new file mode 100644 index 0000000..7212a23 --- /dev/null +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/map/UnitMapFragment.kt @@ -0,0 +1,103 @@ +package mx.trackermap.TrackerMap.android.map + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import kotlinx.coroutines.DelicateCoroutinesApi +import mx.trackermap.TrackerMap.android.R +import mx.trackermap.TrackerMap.android.databinding.UnitMapFragmentBinding +import mx.trackermap.TrackerMap.android.units.UnitsViewModel +import mx.trackermap.TrackerMap.client.models.UnitInformation +import org.koin.androidx.viewmodel.ext.android.viewModel + +@DelicateCoroutinesApi +class UnitMapFragment : Fragment() { + + private val unitsViewModel: UnitsViewModel by viewModel() + + private var _binding: UnitMapFragmentBinding? = null + private val binding get() = _binding!! + private lateinit var unitsMapFragment: MapFragment + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = UnitMapFragmentBinding.inflate(inflater) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + initializeMap() + setupObservers() + } + + private fun initializeMap() { + unitsMapFragment = childFragmentManager.findFragmentById(R.id.unitsMap) as MapFragment + } + + private fun setupObservers() { + Log.d("MapFragment", "setupObservers()") + + unitsViewModel.units.observe(viewLifecycleOwner) { units -> + Log.d("UnitMapFragment", "Available units: $units") + + unitsMapFragment.display(units.mapNotNull(this::unitToMarker).toTypedArray()) + } + + unitsViewModel.selectedUnit.observe(viewLifecycleOwner) { selectedUnit -> + Log.d("UnitMapFragment", "Selected Unit: $selectedUnit") + + binding.mapUnitCard.visibility = if (selectedUnit == null) View.GONE else View.VISIBLE + selectedUnit?.position?.let { position -> + if (position.latitude == null || position.longitude == null) { + return@let + } + + unitsMapFragment.focusOn(position.latitude!!, position.longitude!!) + } + } + } + + private fun unitToMarker(unit: UnitInformation): MapFragment.Marker? { + if (unit.position == null || unit.position!!.latitude == null || unit.position!!.longitude == null) { + return null + } + + return MapFragment.Marker( + unit.position!!.id!!, + unit.position!!.latitude!!, + unit.position!!.longitude!!, + when (unit.device.category?.lowercase()) { + "animal" -> MapFragment.MarkerType.ANIMAL + "bicycle" -> MapFragment.MarkerType.BICYCLE + "boat" -> MapFragment.MarkerType.BOAT + "bus" -> MapFragment.MarkerType.BUS + "car" -> MapFragment.MarkerType.CAR + "crane" -> MapFragment.MarkerType.CRANE + "helicopter" -> MapFragment.MarkerType.HELICOPTER + "motorcycle" -> MapFragment.MarkerType.MOTORCYCLE + "offroad" -> MapFragment.MarkerType.OFFROAD + "person" -> MapFragment.MarkerType.PERSON + "pickup" -> MapFragment.MarkerType.PICKUP + "plane" -> MapFragment.MarkerType.PLANE + "scooter" -> MapFragment.MarkerType.SCOOTER + "ship" -> MapFragment.MarkerType.SHIP + "tractor" -> MapFragment.MarkerType.TRACTOR + "train" -> MapFragment.MarkerType.TRAIN + "tram" -> MapFragment.MarkerType.TRAM + "trolleybus" -> MapFragment.MarkerType.TROLLEYBUS + "truck" -> MapFragment.MarkerType.TRUCK + "van" -> MapFragment.MarkerType.VAN + else -> MapFragment.MarkerType.DEFAULT + } + ) + } + +} \ No newline at end of file diff --git a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt index 8a6f699..796c29f 100644 --- a/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt +++ b/androidApp/src/main/java/mx/trackermap/TrackerMap/android/units/UnitsActivity.kt @@ -10,6 +10,7 @@ import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitsActivityBinding import mx.trackermap.TrackerMap.android.devices.DevicesFragment import mx.trackermap.TrackerMap.android.map.MapFragment +import mx.trackermap.TrackerMap.android.map.UnitMapFragment import org.koin.androidx.viewmodel.ext.android.viewModel @DelicateCoroutinesApi @@ -69,7 +70,7 @@ class UnitsActivity : AppCompatActivity() { val newFragment = when (displayMode) { UnitsViewModel.UnitsDisplayMode.LIST -> DevicesFragment() - UnitsViewModel.UnitsDisplayMode.MAP -> MapFragment() + UnitsViewModel.UnitsDisplayMode.MAP -> UnitMapFragment() else -> DevicesFragment() } supportFragmentManager.commit { -- cgit v1.2.3