checkpoint
This commit is contained in:
parent
172ca703a9
commit
62675e1b97
7 changed files with 169 additions and 35 deletions
|
@ -47,6 +47,7 @@ class Database(trackbook: Trackbook)
|
|||
|
||||
fun insert_trkpt(device_id: String, trkpt: Trkpt)
|
||||
{
|
||||
Log.i("VOUSSOIR", "Database.insert_trkpt")
|
||||
val values = ContentValues().apply {
|
||||
put("device_id", device_id)
|
||||
put("lat", trkpt.latitude)
|
||||
|
@ -63,6 +64,24 @@ class Database(trackbook: Trackbook)
|
|||
connection.insert("trkpt", null, values)
|
||||
}
|
||||
|
||||
fun insert_homepoint(name: String, latitude: Double, longitude: Double, radius: Double)
|
||||
{
|
||||
Log.i("VOUSSOIR", "Database.insert_homepoint")
|
||||
val values = ContentValues().apply {
|
||||
put("lat", latitude)
|
||||
put("lon", longitude)
|
||||
put("radius", radius)
|
||||
put("name", name)
|
||||
}
|
||||
if (! connection.inTransaction())
|
||||
{
|
||||
connection.beginTransaction()
|
||||
}
|
||||
connection.insert("homepoints", null, values)
|
||||
commit()
|
||||
trackbook.load_homepoints()
|
||||
}
|
||||
|
||||
private fun initialize_tables()
|
||||
{
|
||||
this.connection.beginTransaction()
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
package org.y20k.trackbook
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Dialog
|
||||
import android.content.*
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Resources
|
||||
|
@ -29,6 +30,9 @@ import android.view.LayoutInflater
|
|||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.view.WindowManager
|
||||
import android.widget.Button
|
||||
import android.widget.EditText
|
||||
import android.widget.TextView
|
||||
import androidx.activity.result.contract.ActivityResultContracts.RequestPermission
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.core.view.isVisible
|
||||
|
@ -37,10 +41,12 @@ import com.google.android.material.floatingactionbutton.ExtendedFloatingActionBu
|
|||
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
import com.google.android.material.snackbar.Snackbar
|
||||
import org.osmdroid.api.IMapController
|
||||
import org.osmdroid.events.MapEventsReceiver
|
||||
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.MapEventsOverlay
|
||||
import org.osmdroid.views.overlay.Overlay
|
||||
import org.osmdroid.views.overlay.OverlayItem
|
||||
import org.osmdroid.views.overlay.Polygon
|
||||
|
@ -70,7 +76,7 @@ class MapFragment : Fragment()
|
|||
|
||||
private lateinit var trackbook: Trackbook
|
||||
lateinit var rootView: View
|
||||
var userInteraction: Boolean = false
|
||||
var continuous_auto_center: Boolean = true
|
||||
lateinit var currentLocationButton: FloatingActionButton
|
||||
lateinit var zoom_in_button: FloatingActionButton
|
||||
lateinit var zoom_out_button: FloatingActionButton
|
||||
|
@ -124,6 +130,12 @@ class MapFragment : Fragment()
|
|||
mainButton = rootView.findViewById(R.id.main_button)
|
||||
locationErrorBar = Snackbar.make(mapView, String(), Snackbar.LENGTH_INDEFINITE)
|
||||
|
||||
mapView.setOnLongClickListener{
|
||||
Log.i("VOUSSOIR", "mapview longpress")
|
||||
true
|
||||
}
|
||||
mapView.isLongClickable = true
|
||||
|
||||
// basic map setup
|
||||
controller = mapView.controller
|
||||
mapView.isTilesScaledToDpi = true
|
||||
|
@ -133,16 +145,13 @@ class MapFragment : Fragment()
|
|||
zoomLevel = PreferencesHelper.loadZoomLevel()
|
||||
controller.setZoom(zoomLevel)
|
||||
|
||||
// set dark map tiles, if necessary
|
||||
if (AppThemeHelper.isDarkModeOn(requireActivity()))
|
||||
{
|
||||
mapView.overlayManager.tilesOverlay.setColorFilter(TilesOverlay.INVERT_COLORS)
|
||||
}
|
||||
|
||||
// store Density Scaling Factor
|
||||
val densityScalingFactor: Float = UiHelper.getDensityScalingFactor(requireContext())
|
||||
|
||||
// add compass to map
|
||||
val compassOverlay = CompassOverlay(requireContext(), InternalCompassOrientationProvider(requireContext()), mapView)
|
||||
compassOverlay.enableCompass()
|
||||
// compassOverlay.setCompassCenter(36f, 36f + (statusBarHeight / densityScalingFactor)) // TODO uncomment when transparent status bar is re-implemented
|
||||
|
@ -167,8 +176,47 @@ class MapFragment : Fragment()
|
|||
// initialize main button state
|
||||
update_main_button()
|
||||
|
||||
// listen for user interaction
|
||||
addInteractionListener()
|
||||
mapView.setOnTouchListener { v, event ->
|
||||
continuous_auto_center = false
|
||||
false
|
||||
}
|
||||
|
||||
val receiver: MapEventsReceiver = object: MapEventsReceiver
|
||||
{
|
||||
override fun singleTapConfirmedHelper(p: GeoPoint?): Boolean
|
||||
{
|
||||
return true
|
||||
}
|
||||
|
||||
override fun longPressHelper(point: GeoPoint): Boolean
|
||||
{
|
||||
Log.i("VOUSSOIR", "MapFragment MapEventsReceiver.longPressHelper")
|
||||
val dialog = Dialog(activity as Context)
|
||||
dialog.setContentView(R.layout.dialog_homepoint)
|
||||
dialog.setTitle("Homepoint")
|
||||
|
||||
(dialog.findViewById(R.id.homepoint_dialog_title) as TextView).text = "Add a homepoint"
|
||||
|
||||
val name_input: EditText = dialog.findViewById(R.id.homepoint_name_input)
|
||||
val radius_input: EditText = dialog.findViewById(R.id.homepoint_radius_input)
|
||||
val cancel_button: Button = dialog.findViewById(R.id.homepoint_delete_cancel_button)
|
||||
val save_button: Button = dialog.findViewById(R.id.homepoint_save_button)
|
||||
cancel_button.text = "Cancel"
|
||||
cancel_button.setOnClickListener {
|
||||
dialog.cancel()
|
||||
}
|
||||
save_button.setOnClickListener {
|
||||
app.database.insert_homepoint(name=name_input.text.toString(), latitude=point.latitude, longitude=point.longitude, radius=radius_input.text.toString().toDouble())
|
||||
app.load_homepoints()
|
||||
create_homepoint_overlays(requireContext(), mapView, app.homepoints)
|
||||
dialog.dismiss()
|
||||
}
|
||||
|
||||
dialog.show()
|
||||
return true
|
||||
}
|
||||
}
|
||||
mapView.overlays.add(MapEventsOverlay(receiver))
|
||||
|
||||
// set up buttons
|
||||
mainButton.setOnClickListener {
|
||||
|
@ -338,28 +386,19 @@ class MapFragment : Fragment()
|
|||
}
|
||||
}
|
||||
|
||||
private fun addInteractionListener()
|
||||
{
|
||||
mapView.setOnTouchListener { v, event ->
|
||||
userInteraction = true
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun centerMap(location: Location, animated: Boolean = false) {
|
||||
val position = GeoPoint(location.latitude, location.longitude)
|
||||
when (animated) {
|
||||
true -> controller.animateTo(position)
|
||||
false -> controller.setCenter(position)
|
||||
}
|
||||
userInteraction = false
|
||||
continuous_auto_center = true
|
||||
}
|
||||
|
||||
fun saveBestLocationState(currentBestLocation: Location) {
|
||||
PreferencesHelper.saveCurrentBestLocation(currentBestLocation)
|
||||
PreferencesHelper.saveZoomLevel(mapView.zoomLevelDouble)
|
||||
// reset user interaction state
|
||||
userInteraction = false
|
||||
continuous_auto_center = true
|
||||
}
|
||||
|
||||
fun clear_current_position_overlays()
|
||||
|
@ -377,7 +416,7 @@ class MapFragment : Fragment()
|
|||
/* Mark current position on map */
|
||||
fun create_current_position_overlays(location: Location, trackingState: Int = Keys.STATE_TRACKING_STOPPED)
|
||||
{
|
||||
Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition")
|
||||
// Log.i("VOUSSOIR", "MapFragmentLayoutHolder.markCurrentPosition")
|
||||
|
||||
clear_current_position_overlays()
|
||||
|
||||
|
@ -555,7 +594,7 @@ class MapFragment : Fragment()
|
|||
create_current_position_overlays(currentBestLocation, trackingState)
|
||||
create_current_track_overlay(track, trackingState)
|
||||
// center map, if it had not been dragged/zoomed before
|
||||
if (!userInteraction)
|
||||
if (continuous_auto_center)
|
||||
{
|
||||
centerMap(currentBestLocation, true)
|
||||
}
|
||||
|
|
|
@ -161,7 +161,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
|||
PreferencesHelper.save_database_folder(path)
|
||||
preferenceDatabaseFolder.summary = (getString(R.string.pref_database_folder_summary) + "\n" + path).trim()
|
||||
}
|
||||
preferenceDatabaseFolder.title = "Database Directory"
|
||||
preferenceDatabaseFolder.title = getString(R.string.pref_database_folder)
|
||||
preferenceDatabaseFolder.setIcon(R.drawable.ic_save_to_storage_24dp)
|
||||
preferenceDatabaseFolder.key = Keys.PREF_DATABASE_DIRECTORY
|
||||
preferenceDatabaseFolder.summary = (getString(R.string.pref_database_folder_summary) + "\n" + PreferencesHelper.load_database_folder()).trim()
|
||||
|
@ -175,7 +175,7 @@ class SettingsFragment : PreferenceFragmentCompat(), YesNoDialog.YesNoDialogList
|
|||
return@setOnPreferenceClickListener true
|
||||
}
|
||||
preferenceDatabaseFolder.setOnPreferenceChangeListener { preference, newValue ->
|
||||
preferenceDatabaseFolder.summary = "Directory to contain your database file." + "\n" + newValue
|
||||
preferenceDatabaseFolder.summary = getString(R.string.pref_database_folder_summary) + "\n" + newValue
|
||||
return@setOnPreferenceChangeListener true
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.osmdroid.api.IGeoPoint
|
|||
import org.osmdroid.util.GeoPoint
|
||||
import org.osmdroid.views.MapView
|
||||
import org.osmdroid.views.overlay.ItemizedIconOverlay
|
||||
import org.osmdroid.views.overlay.MapEventsOverlay
|
||||
import org.osmdroid.views.overlay.OverlayItem
|
||||
import org.osmdroid.views.overlay.simplefastpoint.LabelledGeoPoint
|
||||
import org.osmdroid.views.overlay.simplefastpoint.SimpleFastPointOverlay
|
||||
|
@ -125,11 +126,10 @@ fun createSpecialMakersTrackOverlay(context: Context, map_view: MapView, track:
|
|||
|
||||
fun createOverlayItem(context: Context, latitude: Double, longitude: Double, accuracy: Float, provider: String, time: Long): OverlayItem
|
||||
{
|
||||
val title: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"
|
||||
//val description: String = "${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
|
||||
val description: String = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
|
||||
val position: GeoPoint = GeoPoint(latitude, longitude)
|
||||
val item: OverlayItem = OverlayItem(title, description, position)
|
||||
val title = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)}"
|
||||
val description = "${context.getString(R.string.marker_description_time)}: ${SimpleDateFormat.getTimeInstance(SimpleDateFormat.MEDIUM, Locale.getDefault()).format(time)} | ${context.getString(R.string.marker_description_accuracy)}: ${DecimalFormat("#0.00").format(accuracy)} (${provider})"
|
||||
val position = GeoPoint(latitude, longitude)
|
||||
val item = OverlayItem(title, description, position)
|
||||
item.markerHotspot = OverlayItem.HotspotPlace.CENTER
|
||||
return item
|
||||
}
|
||||
|
|
76
app/src/main/res/layout/dialog_homepoint.xml
Normal file
76
app/src/main/res/layout/dialog_homepoint.xml
Normal file
|
@ -0,0 +1,76 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/homepoint_dialog_title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Homepoint"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/homepoint_name_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Name"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_dialog_title" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/homepoint_name_input"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="textPersonName"
|
||||
android:minHeight="48dp"
|
||||
android:text=""
|
||||
app:layout_constraintStart_toStartOf="@+id/homepoint_name_label"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_name_label" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/homepoint_radius_label"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Radius"
|
||||
app:layout_constraintStart_toStartOf="@+id/homepoint_name_input"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_name_input" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/homepoint_radius_input"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:inputType="number"
|
||||
android:minHeight="48dp"
|
||||
app:layout_constraintStart_toStartOf="@+id/homepoint_radius_label"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_radius_label" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/homepoint_save_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Save"
|
||||
app:cornerRadius="8dp"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_radius_input" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/homepoint_delete_cancel_button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:text="Delete"
|
||||
app:cornerRadius="8dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/homepoint_radius_input" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -7,20 +7,19 @@
|
|||
android:layout_height="match_parent"
|
||||
tools:context=".MapFragment">
|
||||
|
||||
<!-- MAP -->
|
||||
<org.osmdroid.views.MapView
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/descr_map_current_track"
|
||||
android:visibility="visible" />
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_dodgeInsetEdges="bottom">
|
||||
|
||||
<org.osmdroid.views.MapView
|
||||
android:id="@+id/map"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:contentDescription="@string/descr_map_current_track"
|
||||
android:visibility="visible" />
|
||||
|
||||
<!-- BUTTON SAVE -->
|
||||
|
||||
<!-- BUTTON CLEAR -->
|
||||
|
|
|
@ -86,9 +86,10 @@
|
|||
<string name="pref_altitude_smoothing_value_title" translatable="false">Altitude Smoothing</string>
|
||||
<string name="pref_auto_export_interval_summary">Automatically export GPX file after this many hours.</string>
|
||||
<string name="pref_device_id_summary">A unique ID to distinguish tracks recorded across multiple devices:</string>
|
||||
<string name="pref_database_folder_summary">Directory to contain your database file:</string>
|
||||
<string name="pref_database_folder_summary">Directory to contain your database file. You could use Syncthing to sync with your PC!</string>
|
||||
<string name="pref_auto_export_interval_title">Auto Export Interval</string>
|
||||
<string name="pref_device_id">Device ID</string>
|
||||
<string name="pref_database_folder">Database directory</string>
|
||||
<string name="pref_advanced_title">Advanced</string>
|
||||
<string name="pref_delete_non_starred_summary">Delete all recordings in \"Tracks\" that are not starred.</string>
|
||||
<string name="pref_delete_non_starred_title">Delete Non-Starred Recordings</string>
|
||||
|
|
Loading…
Reference in a new issue