diff --git a/app/src/main/java/org/y20k/trackbook/Track.kt b/app/src/main/java/org/y20k/trackbook/Track.kt index df848b1..c78e31d 100644 --- a/app/src/main/java/org/y20k/trackbook/Track.kt +++ b/app/src/main/java/org/y20k/trackbook/Track.kt @@ -30,8 +30,8 @@ import java.util.* data class Track ( val database: Database, val device_id: String, - val start_time: Date, - val stop_time: Date, + var start_time: Date, + var end_time: Date, var name: String = "", val trkpts: ArrayDeque = ArrayDeque(), var view_latitude: Double = Keys.DEFAULT_LATITUDE, @@ -135,7 +135,6 @@ data class Track ( continue } stats.distance += previous.toLocation().distanceTo(trkpt.toLocation()) - Log.i("VOUSSOIR", previous.toLocation().distanceTo(trkpt.toLocation()).toString()) val ascentdiff = trkpt.altitude - previous.altitude if (ascentdiff > 0) { @@ -169,8 +168,9 @@ data class Track ( { val cursor: Cursor = database.connection.rawQuery( "SELECT lat, lon, time, ele, accuracy, sat FROM trkpt WHERE device_id = ? AND time > ? AND time < ? ORDER BY time ASC", - arrayOf(device_id, start_time.time.toString(), stop_time.time.toString()) + arrayOf(device_id, start_time.time.toString(), end_time.time.toString()) ) + Log.i("VOUSSOIR", "Querying points between ${start_time} -- ${end_time}") val COLUMN_LAT = cursor.getColumnIndex("lat") val COLUMN_LON = cursor.getColumnIndex("lon") val COLUMN_ELE = cursor.getColumnIndex("ele") diff --git a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt index 6b6edad..08e9b4b 100644 --- a/app/src/main/java/org/y20k/trackbook/TrackFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TrackFragment.kt @@ -49,9 +49,8 @@ class TrackFragment : Fragment(), YesNoDialog.YesNoDialogListener name=this.requireArguments().getString(Keys.ARG_TRACK_TITLE, ""), device_id= this.requireArguments().getString(Keys.ARG_TRACK_DEVICE_ID, ""), start_time= iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_START_TIME)!!), - stop_time=iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!), + end_time=iso8601_format.parse(this.requireArguments().getString(Keys.ARG_TRACK_STOP_TIME)!!), ) - track.load_trkpts() layout = TrackFragmentLayoutHolder(activity as Context, inflater, container, track) // set up share button diff --git a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt index 6ab492e..999a645 100644 --- a/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt +++ b/app/src/main/java/org/y20k/trackbook/TracklistFragment.kt @@ -91,7 +91,7 @@ class TracklistFragment : Fragment(), TracklistAdapter.TracklistAdapterListener, Keys.ARG_TRACK_TITLE to track.name, Keys.ARG_TRACK_DEVICE_ID to track.device_id, Keys.ARG_TRACK_START_TIME to iso8601_format.format(track.start_time), - Keys.ARG_TRACK_STOP_TIME to iso8601_format.format(track.stop_time), + Keys.ARG_TRACK_STOP_TIME to iso8601_format.format(track.end_time), ) findNavController().navigate(R.id.fragment_track, bundle) } diff --git a/app/src/main/java/org/y20k/trackbook/tracklist/TracklistAdapter.kt b/app/src/main/java/org/y20k/trackbook/tracklist/TracklistAdapter.kt index 35b2151..4834e85 100644 --- a/app/src/main/java/org/y20k/trackbook/tracklist/TracklistAdapter.kt +++ b/app/src/main/java/org/y20k/trackbook/tracklist/TracklistAdapter.kt @@ -69,7 +69,7 @@ class TracklistAdapter(val fragment: Fragment, val database: Database) : Recycle Log.i("VOUSSOIR", "TracklistAdapter prep track ${trackdate}") if (start_time != null && stop_time != null) { - val track = Track(database=database, device_id=device_id, start_time=start_time, stop_time=stop_time) + val track = Track(database=database, device_id=device_id, start_time=start_time, end_time=stop_time) track.name = "$trackdate $device_id" tracks.add(track) } 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 958c141..1167919 100644 --- a/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt +++ b/app/src/main/java/org/y20k/trackbook/ui/TrackFragmentLayoutHolder.kt @@ -18,10 +18,15 @@ package org.y20k.trackbook.ui import android.app.Activity import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.DatePicker import android.widget.ImageButton +import android.widget.TimePicker import android.widget.Toast import androidx.constraintlayout.widget.Group import androidx.core.widget.NestedScrollView @@ -34,19 +39,17 @@ import org.osmdroid.events.ZoomEvent import org.osmdroid.tileprovider.tilesource.TileSourceFactory import org.osmdroid.util.GeoPoint import org.osmdroid.views.MapView +import org.osmdroid.views.overlay.ItemizedIconOverlay +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.Track import org.y20k.trackbook.TrackStatistics import org.y20k.trackbook.helpers.* +import java.util.* -/* - * TrackFragmentLayoutHolder class - */ -//data class TrackFragmentLayoutHolder(private var context: Context, private var markerListener: MapOverlayHelper.MarkerListener, private var inflater: LayoutInflater, private var statusBarHeight: Int, private var container: ViewGroup?, var track: Track): MapListener { TODO REMOVE data class TrackFragmentLayoutHolder( private var context: Context, private var inflater: LayoutInflater, @@ -54,11 +57,16 @@ data class TrackFragmentLayoutHolder( var track: Track ): MapListener { - /* Main class variables */ val rootView: View val save_track_button: ImageButton val deleteButton: ImageButton val trackNameView: MaterialTextView + val track_query_start_date: DatePicker + val track_query_start_time: TimePicker + val track_query_end_date: DatePicker + val track_query_end_time: TimePicker + var track_query_start_time_previous: Int + var track_query_end_time_previous: Int private val mapView: MapView private var controller: IMapController private val statisticsSheetBehavior: BottomSheetBehavior @@ -78,17 +86,93 @@ data class TrackFragmentLayoutHolder( private val negativeElevationView: MaterialTextView private val elevationDataViews: Group private val useImperialUnits: Boolean + private val handler: Handler = Handler(Looper.getMainLooper()) + private var special_points_overlay: ItemizedIconOverlay? = null + private var track_overlay: SimpleFastPointOverlay? = null + val RERENDER_DELAY: Long = 1000 init { - // find views rootView = inflater.inflate(R.layout.fragment_track, container, false) mapView = rootView.findViewById(R.id.map) save_track_button = rootView.findViewById(R.id.save_button) deleteButton = rootView.findViewById(R.id.delete_button) trackNameView = rootView.findViewById(R.id.statistics_track_name_headline) - // basic map setup + track.load_trkpts() + val actual_start_time: Date = if (track.trkpts.isEmpty()) track.start_time else Date(track.trkpts.first().time) + val actual_end_time: Date = if (track.trkpts.isEmpty()) track.end_time else Date(track.trkpts.last().time) + + track_query_start_date = rootView.findViewById(R.id.track_query_start_date) + val start_cal = GregorianCalendar() + start_cal.time = actual_start_time + track_query_start_date.init(start_cal.get(Calendar.YEAR), start_cal.get(Calendar.MONTH), start_cal.get(Calendar.DAY_OF_MONTH), object: DatePicker.OnDateChangedListener { + override fun onDateChanged(p0: DatePicker?, p1: Int, p2: Int, p3: Int) + { + handler.removeCallbacks(requery_and_render) + handler.postDelayed(requery_and_render, RERENDER_DELAY) + } + }) + + track_query_start_time = rootView.findViewById(R.id.track_query_start_time) + track_query_start_time.setIs24HourView(true) + track_query_start_time.hour = actual_start_time.hours + track_query_start_time.minute = actual_start_time.minutes + track_query_start_time_previous = (actual_start_time.hours * 60) + actual_start_time.minutes + track_query_start_time.setOnTimeChangedListener(object : TimePicker.OnTimeChangedListener{ + override fun onTimeChanged(p0: TimePicker?, p1: Int, p2: Int) + { + handler.removeCallbacks(requery_and_render) + val newminute = (p1 * 60) + p2 + Log.i("VOUSSOIR", "End time changed $newminute") + if (newminute < track_query_start_time_previous && (track_query_start_time_previous - newminute > 60)) + { + increment_datepicker(track_query_start_date) + } + else if (newminute > track_query_start_time_previous && (newminute - track_query_start_time_previous > 60)) + { + decrement_datepicker(track_query_start_date) + } + track_query_start_time_previous = newminute + handler.postDelayed(requery_and_render, RERENDER_DELAY) + } + }) + + track_query_end_date = rootView.findViewById(R.id.track_query_end_date) + val end_cal = GregorianCalendar() + end_cal.time = actual_end_time + track_query_end_date.init(end_cal.get(Calendar.YEAR), end_cal.get(Calendar.MONTH), end_cal.get(Calendar.DAY_OF_MONTH), object: DatePicker.OnDateChangedListener { + override fun onDateChanged(p0: DatePicker?, p1: Int, p2: Int, p3: Int) + { + handler.removeCallbacks(requery_and_render) + handler.postDelayed(requery_and_render, RERENDER_DELAY) + } + }) + + track_query_end_time = rootView.findViewById(R.id.track_query_end_time) + track_query_end_time.setIs24HourView(true) + track_query_end_time.hour = actual_end_time.hours + track_query_end_time.minute = actual_end_time.minutes + track_query_end_time_previous = (actual_end_time.hours * 60) + actual_end_time.minutes + track_query_end_time.setOnTimeChangedListener(object : TimePicker.OnTimeChangedListener{ + override fun onTimeChanged(p0: TimePicker?, p1: Int, p2: Int) + { + handler.removeCallbacks(requery_and_render) + val newminute = (p1 * 60) + p2 + Log.i("VOUSSOIR", "End time changed $newminute") + if (newminute < track_query_end_time_previous && (track_query_end_time_previous - newminute > 60)) + { + increment_datepicker(track_query_end_date) + } + else if (newminute > track_query_end_time_previous && (newminute - track_query_end_time_previous > 60)) + { + decrement_datepicker(track_query_end_date) + } + track_query_end_time_previous = newminute + handler.postDelayed(requery_and_render, RERENDER_DELAY) + } + }) + controller = mapView.controller mapView.addMapListener(this) mapView.isTilesScaledToDpi = true @@ -99,7 +183,6 @@ data class TrackFragmentLayoutHolder( controller.setCenter(GeoPoint(track.view_latitude, track.view_longitude)) controller.setZoom(Keys.DEFAULT_ZOOM_LEVEL) - // get views for statistics sheet statisticsSheet = rootView.findViewById(R.id.statistics_sheet) statisticsView = rootView.findViewById(R.id.statistics_view) distanceView = rootView.findViewById(R.id.statistics_data_distance) @@ -116,36 +199,59 @@ data class TrackFragmentLayoutHolder( negativeElevationView = rootView.findViewById(R.id.statistics_data_negative_elevation) elevationDataViews = rootView.findViewById(R.id.elevation_data) - // get measurement unit system useImperialUnits = PreferencesHelper.loadUseImperialUnits() - // set dark map tiles, if necessary if (AppThemeHelper.isDarkModeOn(context as Activity)) { mapView.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS) } - // add compass to map - val compassOverlay = CompassOverlay(context, InternalCompassOrientationProvider(context), mapView) - compassOverlay.enableCompass() - compassOverlay.setCompassCenter(36f, 36f) -// compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / UiHelper.getDensityScalingFactor(context))) TODO REMOVE - mapView.overlays.add(compassOverlay) - - if (track.trkpts.isNotEmpty()) { - createSpecialMakersTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED, displayStartEndMarker = true) - createTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED) - } - - // set up and show statistics sheet statisticsSheetBehavior = BottomSheetBehavior.from(statisticsSheet) statisticsSheetBehavior.state = BottomSheetBehavior.STATE_COLLAPSED + + render_track() + } + + fun render_track() + { + if (special_points_overlay != null) + { + mapView.overlays.remove(special_points_overlay) + mapView.overlays.remove(track_overlay) + } + if (track.trkpts.isNotEmpty()) + { + special_points_overlay = createSpecialMakersTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED, displayStartEndMarker = true) + track_overlay = createTrackOverlay(context, mapView, track.trkpts, Keys.STATE_TRACKING_STOPPED) + } setupStatisticsViews() } - /* Sets up the statistics sheet */ + fun get_datetime(datepicker: DatePicker, timepicker: TimePicker, seconds: Int): Date + { + val cal = GregorianCalendar.getInstance() + cal.set(datepicker.year, datepicker.month, datepicker.dayOfMonth, timepicker.hour, timepicker.minute, seconds) + Log.i("VOUSSOIR", cal.time.toString()) + return cal.time + } + + fun decrement_datepicker(picker: DatePicker) + { + val cal = GregorianCalendar.getInstance() + cal.set(picker.year, picker.month, picker.dayOfMonth) + cal.add(Calendar.DATE, -1) + picker.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) + } + + fun increment_datepicker(picker: DatePicker) + { + val cal = GregorianCalendar.getInstance() + cal.set(picker.year, picker.month, picker.dayOfMonth) + cal.add(Calendar.DATE, 1) + picker.updateDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DAY_OF_MONTH)) + } + private fun setupStatisticsViews() { - // populate views val stats: TrackStatistics = track.statistics() trackNameView.text = track.name distanceView.text = LengthUnitHelper.convertDistanceToString(stats.distance, useImperialUnits) @@ -153,7 +259,7 @@ data class TrackFragmentLayoutHolder( durationView.text = DateTimeHelper.convertToReadableTime(context, stats.duration) velocityView.text = LengthUnitHelper.convertToVelocityString(stats.velocity, useImperialUnits) recordingStartView.text = DateTimeHelper.convertToReadableDateAndTime(track.start_time) - recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(track.stop_time) + recordingStopView.text = DateTimeHelper.convertToReadableDateAndTime(track.end_time) maxAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.max_altitude, useImperialUnits) minAltitudeView.text = LengthUnitHelper.convertDistanceToString(stats.min_altitude, useImperialUnits) positiveElevationView.text = LengthUnitHelper.convertDistanceToString(stats.total_ascent, useImperialUnits) @@ -192,5 +298,17 @@ data class TrackFragmentLayoutHolder( return (event != null) } + private val requery_and_render: Runnable = object : Runnable { + override fun run() + { + Log.i("VOUSSOIR", "requery_and_render") + track.start_time = get_datetime(track_query_start_date, track_query_start_time, seconds=0) + track.end_time = get_datetime(track_query_end_date, track_query_end_time, seconds=59) + track.load_trkpts() + Log.i("VOUSSOIR", "Reloaded ${track.trkpts.size} trkpts.") + render_track() + mapView.invalidate() + } + } } diff --git a/app/src/main/res/layout/fragment_track.xml b/app/src/main/res/layout/fragment_track.xml index aacc397..3afaffc 100755 --- a/app/src/main/res/layout/fragment_track.xml +++ b/app/src/main/res/layout/fragment_track.xml @@ -7,18 +7,81 @@ android:layout_height="match_parent" tools:context=".MainActivity"> - - + > - + + + + + + + + + + + + + + + +