diff --git a/app/src/main/java/org/y20k/trackbook/MapFragment.kt b/app/src/main/java/org/y20k/trackbook/MapFragment.kt index 3be2fca..1e15891 100644 --- a/app/src/main/java/org/y20k/trackbook/MapFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/MapFragment.kt @@ -181,11 +181,11 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe /* Overrides onMarkerTapped from MarkerListener */ - override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) { - super.onMarkerTapped(latitude, longitude, displayStartEndMarker) + override fun onMarkerTapped(latitude: Double, longitude: Double) { + super.onMarkerTapped(latitude, longitude) if (bound) { track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude) - layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker) + layout.overlayCurrentTrack(track, trackingState) trackerService.track = track } } @@ -320,7 +320,7 @@ class MapFragment : Fragment(), YesNoDialog.YesNoDialogListener, MapOverlayHelpe trackingState = trackerService.trackingState // update location and track layout.markCurrentPosition(currentBestLocation, trackingState) - layout.overlayCurrentTrack(track, trackingState, displayStartEndMarker = false) + layout.overlayCurrentTrack(track, trackingState) // center map, if it had not been dragged/zoomed before if (!layout.userInteraction) { layout.centerMap(currentBestLocation, true)} // show error snackbar if necessary diff --git a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt index e20592e..230ee28 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt @@ -162,11 +162,11 @@ class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDi /* Overrides onMarkerTapped from MarkerListener */ - override fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) { - super.onMarkerTapped(latitude, longitude, displayStartEndMarker) + override fun onMarkerTapped(latitude: Double, longitude: Double) { + super.onMarkerTapped(latitude, longitude) // update track display track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude) - layout.updateTrackOverlay(track, displayStartEndMarker) + layout.updateTrackOverlay(track) // save track GlobalScope.launch { FileHelper.saveTrackSuspended(track, true) diff --git a/app/src/main/java/org/y20k/trackbook/TrackerService.kt b/app/src/main/java/org/y20k/trackbook/TrackerService.kt index fdea803..4fb48df 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackerService.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackerService.kt @@ -476,7 +476,6 @@ class TrackerService: Service(), CoroutineScope, SensorEventListener { if (now.time - lastSave.time > Keys.SAVE_TEMP_TRACK_INTERVAL) { lastSave = now GlobalScope.launch { FileHelper.saveTempTrackSuspended(this@TrackerService, track) } - LogHelper.e(TAG, "TEMP SAVE: $lastSave") } } // update notification diff --git a/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt b/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt index 70ada89..b9907dd 100644 --- a/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt +++ b/app/src/main/java/org/y20k/trackbook/helpers/MapOverlayHelper.kt @@ -19,14 +19,20 @@ package org.y20k.trackbook.helpers import android.content.Context +import android.graphics.Paint import android.graphics.drawable.Drawable import android.location.Location import android.os.Vibrator import android.widget.Toast import androidx.core.content.ContextCompat +import org.osmdroid.api.IGeoPoint import org.osmdroid.util.GeoPoint import org.osmdroid.views.overlay.ItemizedIconOverlay import org.osmdroid.views.overlay.OverlayItem +import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint +import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay +import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlayOptions +import org.osmdroid.views.overlay.simplefastpoint.SimplePointTheme import org.y20k.trackbook.Keys import org.y20k.trackbook.R import org.y20k.trackbook.core.Track @@ -44,7 +50,7 @@ class MapOverlayHelper (private var markerListener: MarkerListener) { /* Interface used to communicate back to activity/fragment */ interface MarkerListener { - fun onMarkerTapped(latitude: Double, longitude: Double, displayStartEndMarker: Boolean) { + fun onMarkerTapped(latitude: Double, longitude: Double) { } } @@ -83,70 +89,86 @@ class MapOverlayHelper (private var markerListener: MarkerListener) { overlayItems.add(overlayItem) // create and return overlay for current position - return createOverlay(context, overlayItems, enableStarring = false, displayStartEndMarker = false) + return createOverlay(context, overlayItems, enableStarring = false) } /* Creates icon overlay for track */ - fun createTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay { - - val overlayItems: ArrayList = ArrayList() - val wayPoints: MutableList = track.wayPoints - val maxIndex: Int = wayPoints.size - 1 - - when (trackingState) { - // CASE: Recording is active - Keys.STATE_TRACKING_ACTIVE -> { - wayPoints.forEach { wayPoint: WayPoint -> - // get drawable - val newMarker: Drawable - if (wayPoint.starred) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!! - } else if (wayPoint.isStopOver) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!! - } else { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_red_24dp)!! - } - // create overlay item and add to list of overlay items - val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) - overlayItem.setMarker(newMarker) - overlayItems.add(overlayItem) - } - } - // CASE: Recording is paused/stopped - else -> { - wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint -> - // get drawable - val newMarker: Drawable - if (displayStartEndMarker && index == 0) { - if (wayPoint.starred) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!! - } else { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!! - } - } else if (displayStartEndMarker && index == maxIndex) { - if (wayPoint.starred) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!! - } else { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!! - } - } - else if (wayPoint.starred) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!! - } else if (wayPoint.isStopOver) { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!! - } else { - newMarker = ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_blue_24dp)!! - } - // create overlay item and add to list of overlay items - val overlayItem: OverlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) - overlayItem.setMarker(newMarker) - overlayItems.add(overlayItem) - } + fun createTrackOverlay(context: Context, track: Track, trackingState: Int): SimpleFastPointOverlay { + // get marker color + val color = if (trackingState == Keys.STATE_TRACKING_ACTIVE) context.getColor(R.color.trackbook_red) + else context.getColor(R.color.trackbook_blue) + // gather points for overlay + val points: MutableList = mutableListOf() + track.wayPoints.forEach { wayPoint -> + val label: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(wayPoint.time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(wayPoint.accuracy)} (${wayPoint.provider})" + // only add normal points + if (!wayPoint.starred && !wayPoint.isStopOver) { + points.add(LabelledGeoPoint(wayPoint.latitude, wayPoint.longitude, wayPoint.altitude, label)) } } + val pointTheme: SimplePointTheme = SimplePointTheme(points, false) + // set styling for overlay + val style: Paint = Paint() + style.style = Paint.Style.FILL + style.color = color + val scalingFactor: Float = UiHelper.getDensityScalingFactor(context) + val overlayOptions: SimpleFastPointOverlayOptions = SimpleFastPointOverlayOptions.getDefaultStyle() + .setAlgorithm(SimpleFastPointOverlayOptions.RenderingAlgorithm.MAXIMUM_OPTIMIZATION) + .setSymbol(SimpleFastPointOverlayOptions.Shape.CIRCLE) + .setPointStyle(style) + .setRadius(6F * scalingFactor) // radius is set in px - scaling factor makes that display density independent (= dp) + .setIsClickable(true) +// .setCellSize(15) // Sets the grid cell size used for indexing, in pixels. Larger cells result in faster rendering speed, but worse fidelity. Default is 10 pixels, for large datasets (>10k points), use 15. + // create and return overlay + val overlay: SimpleFastPointOverlay = SimpleFastPointOverlay(pointTheme, overlayOptions) + overlay.setOnClickListener(object : SimpleFastPointOverlay.OnClickListener { + override fun onClick(points: SimpleFastPointOverlay.PointAdapter?, point: Int?) { + if (points != null && point != null) { + val markerPoint: IGeoPoint = points.get(point) + markerListener.onMarkerTapped(markerPoint.latitude, markerPoint.longitude) + } + } + }) + return overlay + } + + + /* Creates overlay containing start, stop, stopover and starred markers for track */ + fun createSpecialMakersTrackOverlay(context: Context, track: Track, trackingState: Int, displayStartEndMarker: Boolean = false): ItemizedIconOverlay { + val overlayItems: ArrayList = ArrayList() + val trackingActive: Boolean = trackingState == Keys.STATE_TRACKING_ACTIVE + val maxIndex: Int = track.wayPoints.size - 1 + + track.wayPoints.forEachIndexed { index: Int, wayPoint: WayPoint -> + var overlayItem: OverlayItem? = null + if (!trackingActive && index == 0 && displayStartEndMarker && wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_starred_blue_48dp)!!) + } else if (!trackingActive && index == 0 && displayStartEndMarker && !wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_start_blue_48dp)!!) + } else if (!trackingActive && index == maxIndex && displayStartEndMarker && wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_starred_blue_48dp)!!) + } else if (!trackingActive && index == maxIndex && displayStartEndMarker && !wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_end_blue_48dp)!!) + } else if (!trackingActive && wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_blue_24dp)!!) + } else if (trackingActive && wayPoint.starred) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_star_red_24dp)!!) + } else if (wayPoint.isStopOver) { + overlayItem = createOverlayItem(context, wayPoint.latitude, wayPoint.longitude, wayPoint.accuracy, wayPoint.provider, wayPoint.time) + overlayItem.setMarker(ContextCompat.getDrawable(context, R.drawable.ic_marker_track_location_grey_24dp)!!) + } + // add overlay item, if it was created + if (overlayItem != null) overlayItems.add(overlayItem) + } // create and return overlay for current position - return createOverlay(context, overlayItems, enableStarring = true, displayStartEndMarker = displayStartEndMarker) + return createOverlay(context, overlayItems, enableStarring = true) } @@ -163,12 +185,12 @@ class MapOverlayHelper (private var markerListener: MarkerListener) { /* Creates an overlay */ - private fun createOverlay(context: Context, overlayItems: ArrayList, enableStarring: Boolean, displayStartEndMarker: Boolean): ItemizedIconOverlay { + private fun createOverlay(context: Context, overlayItems: ArrayList, enableStarring: Boolean): ItemizedIconOverlay { return ItemizedIconOverlay(context, overlayItems, object : ItemizedIconOverlay.OnItemGestureListener { override fun onItemSingleTapUp(index: Int, item: OverlayItem): Boolean { if (enableStarring) { - markerListener.onMarkerTapped(item.point.latitude, item.point.longitude, displayStartEndMarker) + markerListener.onMarkerTapped(item.point.latitude, item.point.longitude) return true } else { return false diff --git a/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt b/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt index a4313b6..5054545 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/MapFragmentLayoutHolder.kt @@ -41,6 +41,7 @@ import org.osmdroid.views.overlay.OverlayItem import org.osmdroid.views.overlay.TilesOverlay import org.osmdroid.views.overlay.compass.CompassOverlay import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider +import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay import org.y20k.trackbook.Keys import org.y20k.trackbook.R import org.y20k.trackbook.core.Track @@ -67,7 +68,8 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar val resumeButton: FloatingActionButton var userInteraction: Boolean = false private var currentPositionOverlay: ItemizedIconOverlay - private var currentTrackOverlay: ItemizedIconOverlay? + private var currentTrackOverlay: SimpleFastPointOverlay? + private var currentTrackSpecialMarkerOverlay: ItemizedIconOverlay? private var locationErrorBar: Snackbar private var controller: IMapController private var zoomLevel: Double @@ -112,8 +114,9 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar mapView.overlays.add(currentPositionOverlay) centerMap(startLocation) - // initialize track overlay + // initialize track overlays currentTrackOverlay = null + currentTrackSpecialMarkerOverlay = null // initialize recording button state updateRecordingButton(trackingState) @@ -162,13 +165,19 @@ data class MapFragmentLayoutHolder(private var context: Context, private var mar /* Overlay current track on map */ - fun overlayCurrentTrack(track: Track, trackingState: Int, displayStartEndMarker: Boolean) { + fun overlayCurrentTrack(track: Track, trackingState: Int) { if (currentTrackOverlay != null) { mapView.overlays.remove(currentTrackOverlay) } + if (currentTrackSpecialMarkerOverlay != null) { + mapView.overlays.remove(currentTrackSpecialMarkerOverlay) + } if (track.wayPoints.isNotEmpty()) { - currentTrackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, trackingState, displayStartEndMarker) + val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener) + currentTrackOverlay = mapOverlayHelper.createTrackOverlay(context, track, trackingState) + currentTrackSpecialMarkerOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, trackingState) mapView.overlays.add(currentTrackOverlay) + mapView.overlays.add(currentTrackSpecialMarkerOverlay) } } diff --git a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt index bce60a1..70b8511 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt @@ -45,6 +45,7 @@ import org.osmdroid.views.overlay.OverlayItem import org.osmdroid.views.overlay.TilesOverlay import org.osmdroid.views.overlay.compass.CompassOverlay import org.osmdroid.views.overlay.compass.InternalCompassOrientationProvider +import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay import org.y20k.trackbook.Keys import org.y20k.trackbook.R import org.y20k.trackbook.core.Track @@ -68,7 +69,8 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m val editButton: ImageButton val trackNameView: MaterialTextView private val mapView: MapView - private var trackOverlay: ItemizedIconOverlay? + private var trackSpecialMarkersOverlay: ItemizedIconOverlay? + private var trackOverlay: SimpleFastPointOverlay? private var controller: IMapController private var zoomLevel: Double private val statisticsSheetBehavior: BottomSheetBehavior @@ -146,9 +148,12 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m mapView.overlays.add(compassOverlay) // create map overlay - trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true) + val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener) + trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT) + trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true) if (track.wayPoints.isNotEmpty()) { mapView.overlays.add(trackOverlay) + mapView.overlays.add(trackSpecialMarkersOverlay) } // set up and show statistics sheet @@ -168,14 +173,20 @@ data class TrackFragmentLayoutHolder(private var context: Context, private var m /* Updates map overlay */ - fun updateTrackOverlay(newTrack: Track, displayStartEndMarker: Boolean) { + fun updateTrackOverlay(newTrack: Track) { track = newTrack if (trackOverlay != null) { mapView.overlays.remove(trackOverlay) } + if (trackSpecialMarkersOverlay != null) { + mapView.overlays.remove(trackSpecialMarkersOverlay) + } if (track.wayPoints.isNotEmpty()) { - trackOverlay = MapOverlayHelper(markerListener).createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker) + val mapOverlayHelper: MapOverlayHelper = MapOverlayHelper(markerListener) + trackOverlay = mapOverlayHelper.createTrackOverlay(context, track, Keys.STATE_TRACKING_NOT) + trackSpecialMarkersOverlay = mapOverlayHelper.createSpecialMakersTrackOverlay(context, track, Keys.STATE_TRACKING_NOT, displayStartEndMarker = true) mapView.overlays.add(trackOverlay) + mapView.overlays.add(trackSpecialMarkersOverlay) } }