diff options
Diffstat (limited to 'androidApp/src/main')
5 files changed, 241 insertions, 96 deletions
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<Pair<ScreenMarker, ComponentObject>>() @@ -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<Marker>) { + 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 { diff --git a/androidApp/src/main/res/layout/map_fragment.xml b/androidApp/src/main/res/layout/map_fragment.xml deleted file mode 100644 index 8d36fc1..0000000 --- a/androidApp/src/main/res/layout/map_fragment.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<androidx.constraintlayout.widget.ConstraintLayout - xmlns:android="http://schemas.android.com/apk/res/android" - android:layout_width="match_parent" - android:layout_height="match_parent" - xmlns:app="http://schemas.android.com/apk/res-auto"> - - <TextView - android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:text="MAP" - app:layout_constraintTop_toTopOf="parent" - app:layout_constraintStart_toStartOf="parent" - app:layout_constraintEnd_toEndOf="parent" - app:layout_constraintBottom_toBottomOf="parent"/> - -</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file diff --git a/androidApp/src/main/res/layout/unit_map_fragment.xml b/androidApp/src/main/res/layout/unit_map_fragment.xml new file mode 100644 index 0000000..914558a --- /dev/null +++ b/androidApp/src/main/res/layout/unit_map_fragment.xml @@ -0,0 +1,46 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:app="http://schemas.android.com/apk/res-auto"> + + <fragment + android:id="@+id/unitsMap" + android:layout_width="0dp" + android:layout_height="0dp" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + android:name="mx.trackermap.TrackerMap.android.map.MapFragment"/> + + <androidx.cardview.widget.CardView + android:id="@+id/mapUnitCard" + android:layout_width="0dp" + android:layout_height="wrap_content" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintBottom_toBottomOf="parent" + app:cardUseCompatPadding="true" + app:cardElevation="@dimen/card_elevation" + app:cardCornerRadius="@dimen/card_border_radius" + app:contentPadding="@dimen/card_padding" + android:visibility="gone"> + + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:orientation="vertical"> + + <TextView + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="SELECTED UNIT" + android:gravity="center"/> + + </LinearLayout> + + </androidx.cardview.widget.CardView> + +</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file |