kopia lustrzana https://github.com/meshtastic/Meshtastic-Android
Working on cache downloader
rodzic
4d81689f21
commit
9b1dfb0d02
|
@ -140,9 +140,11 @@ dependencies {
|
||||||
kapt "androidx.room:room-compiler:$room_version"
|
kapt "androidx.room:room-compiler:$room_version"
|
||||||
kapt "com.google.dagger:hilt-compiler:$hilt_version"
|
kapt "com.google.dagger:hilt-compiler:$hilt_version"
|
||||||
|
|
||||||
//OSMAND
|
//OSMDROID, mgrs,
|
||||||
implementation 'org.osmdroid:osmdroid-android:6.1.14'
|
implementation 'org.osmdroid:osmdroid-android:6.1.14'
|
||||||
|
implementation 'com.github.MKergall:osmbonuspack:6.9.0'
|
||||||
implementation 'mil.nga:mgrs:2.0.0'
|
implementation 'mil.nga:mgrs:2.0.0'
|
||||||
|
implementation 'org.osmdroid:osmdroid-geopackage:6.1.14'
|
||||||
|
|
||||||
// optional - Kotlin Extensions and Coroutines support for Room
|
// optional - Kotlin Extensions and Coroutines support for Room
|
||||||
implementation "androidx.room:room-ktx:$room_version"
|
implementation "androidx.room:room-ktx:$room_version"
|
||||||
|
|
|
@ -37,6 +37,9 @@ import kotlinx.coroutines.flow.flatMapLatest
|
||||||
import kotlinx.coroutines.flow.mapLatest
|
import kotlinx.coroutines.flow.mapLatest
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
import org.osmdroid.bonuspack.kml.KmlDocument
|
||||||
|
import org.osmdroid.views.MapView
|
||||||
|
import org.osmdroid.views.overlay.FolderOverlay
|
||||||
import java.io.BufferedWriter
|
import java.io.BufferedWriter
|
||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.FileWriter
|
import java.io.FileWriter
|
||||||
|
@ -480,6 +483,31 @@ class UIViewModel @Inject constructor(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun parseUrl(url: String, map: MapView) {
|
||||||
|
viewModelScope.launch(Dispatchers.IO) {
|
||||||
|
parseIt(url, map)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Future Use
|
||||||
|
// model.parseUrl(
|
||||||
|
// "https://www.google.com/maps/d/kml?forcekml=1&mid=1FmqWhZG3PG3dY92x9yf2RlREcK7kMZs&lid=-ivSjBCePsM",
|
||||||
|
// map
|
||||||
|
// )
|
||||||
|
private fun parseIt(url: String, map: MapView) {
|
||||||
|
val kmlDoc = KmlDocument()
|
||||||
|
try {
|
||||||
|
kmlDoc.parseKMLUrl(url)
|
||||||
|
val kmlOverlay = kmlDoc.mKmlRoot.buildOverlay(map, null, null, kmlDoc) as FolderOverlay
|
||||||
|
kmlDoc.mKmlRoot.mItems
|
||||||
|
kmlDoc.mKmlRoot.mName
|
||||||
|
map.overlayManager.overlays().add(kmlOverlay)
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
debug("Failed to download .kml $ex")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun addQuickChatAction(name: String, value: String, mode: QuickChatAction.Mode) {
|
fun addQuickChatAction(name: String, value: String, mode: QuickChatAction.Mode) {
|
||||||
viewModelScope.launch(Dispatchers.Main) {
|
viewModelScope.launch(Dispatchers.Main) {
|
||||||
val action = QuickChatAction(0, name, value, mode, _quickChatActions.value.size)
|
val action = QuickChatAction(0, name, value, mode, _quickChatActions.value.size)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.geeksville.mesh.ui
|
package com.geeksville.mesh.ui
|
||||||
|
|
||||||
|
import android.app.AlertDialog
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.graphics.Canvas
|
import android.graphics.Canvas
|
||||||
|
@ -7,33 +8,41 @@ import android.graphics.Color
|
||||||
import android.graphics.Paint
|
import android.graphics.Paint
|
||||||
import android.graphics.Rect
|
import android.graphics.Rect
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.text.Editable
|
||||||
|
import android.text.TextWatcher
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.*
|
||||||
|
import android.widget.SeekBar.OnSeekBarChangeListener
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.fragment.app.activityViewModels
|
import androidx.fragment.app.activityViewModels
|
||||||
import com.geeksville.mesh.android.Logging
|
|
||||||
import com.geeksville.mesh.BuildConfig
|
import com.geeksville.mesh.BuildConfig
|
||||||
import com.geeksville.mesh.NodeInfo
|
import com.geeksville.mesh.NodeInfo
|
||||||
import com.geeksville.mesh.R
|
import com.geeksville.mesh.R
|
||||||
|
import com.geeksville.mesh.android.Logging
|
||||||
import com.geeksville.mesh.databinding.MapViewBinding
|
import com.geeksville.mesh.databinding.MapViewBinding
|
||||||
import com.geeksville.mesh.model.CustomTileSource
|
import com.geeksville.mesh.model.CustomTileSource
|
||||||
import com.geeksville.mesh.model.UIViewModel
|
import com.geeksville.mesh.model.UIViewModel
|
||||||
import com.geeksville.mesh.util.formatAgo
|
import com.geeksville.mesh.util.formatAgo
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
|
import com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
import org.osmdroid.api.IMapController
|
import org.osmdroid.api.IMapController
|
||||||
import org.osmdroid.config.Configuration
|
import org.osmdroid.config.Configuration
|
||||||
|
import org.osmdroid.tileprovider.cachemanager.CacheManager
|
||||||
import org.osmdroid.tileprovider.tilesource.ITileSource
|
import org.osmdroid.tileprovider.tilesource.ITileSource
|
||||||
import org.osmdroid.util.BoundingBox
|
import org.osmdroid.util.BoundingBox
|
||||||
import org.osmdroid.util.GeoPoint
|
import org.osmdroid.util.GeoPoint
|
||||||
import org.osmdroid.views.CustomZoomButtonsController
|
import org.osmdroid.views.CustomZoomButtonsController
|
||||||
import org.osmdroid.views.MapView
|
import org.osmdroid.views.MapView
|
||||||
import org.osmdroid.views.overlay.CopyrightOverlay
|
import org.osmdroid.views.overlay.*
|
||||||
import org.osmdroid.views.overlay.Marker
|
import kotlin.math.pow
|
||||||
|
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class MapFragment : ScreenFragment("Map"), Logging {
|
class MapFragment : ScreenFragment("Map"), Logging, View.OnClickListener, OnSeekBarChangeListener,
|
||||||
|
TextWatcher {
|
||||||
|
|
||||||
private lateinit var binding: MapViewBinding
|
private lateinit var binding: MapViewBinding
|
||||||
private lateinit var map: MapView
|
private lateinit var map: MapView
|
||||||
|
@ -41,20 +50,38 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
private lateinit var mPrefs: SharedPreferences
|
private lateinit var mPrefs: SharedPreferences
|
||||||
private val model: UIViewModel by activityViewModels()
|
private val model: UIViewModel by activityViewModels()
|
||||||
|
|
||||||
|
private lateinit var cacheManager: CacheManager
|
||||||
|
private lateinit var btnCache: FloatingActionButton
|
||||||
|
|
||||||
|
private lateinit var cacheNorth: EditText
|
||||||
|
private lateinit var cacheSouth: EditText
|
||||||
|
private lateinit var cacheEast: EditText
|
||||||
|
private lateinit var cacheWest: EditText
|
||||||
|
|
||||||
|
private lateinit var cacheEstimate: TextView
|
||||||
|
|
||||||
|
private lateinit var zoomMin: SeekBar
|
||||||
|
private lateinit var zoomMax: SeekBar
|
||||||
|
|
||||||
|
private var downloadPrompt: AlertDialog? = null
|
||||||
|
private var alertDialog: AlertDialog? = null
|
||||||
|
private lateinit var executeJob: Button
|
||||||
|
|
||||||
|
|
||||||
private val defaultMinZoom = 1.5
|
private val defaultMinZoom = 1.5
|
||||||
private val nodeZoomLevel = 8.5
|
private val nodeZoomLevel = 8.5
|
||||||
private val defaultZoomSpeed = 3000L
|
private val defaultZoomSpeed = 3000L
|
||||||
private val prefsName = "org.andnav.osm.prefs"
|
private val prefsName = "org.geeksville.osm.prefs"
|
||||||
private val mapStyleId = "map_style_id"
|
private val mapStyleId = "map_style_id"
|
||||||
private var nodePositions = listOf<MarkerWithLabel>()
|
private var nodePositions = listOf<MarkerWithLabel>()
|
||||||
private val nodeLayer = 1
|
private val nodeLayer = 1
|
||||||
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?,
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
savedInstanceState: Bundle?
|
|
||||||
): View {
|
): View {
|
||||||
binding = MapViewBinding.inflate(inflater)
|
binding = MapViewBinding.inflate(inflater)
|
||||||
|
btnCache = binding.root.findViewById(R.id.downloadButton)
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,6 +116,191 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
}
|
}
|
||||||
zoomToNodes(mapController)
|
zoomToNodes(mapController)
|
||||||
}
|
}
|
||||||
|
btnCache.setOnClickListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onClick(v: View) {
|
||||||
|
when (v.id) {
|
||||||
|
R.id.executeJob -> updateEstimate(true)
|
||||||
|
R.id.downloadButton -> showCacheManagerDialog()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showCacheManagerDialog() {
|
||||||
|
val alertDialogBuilder = AlertDialog.Builder(
|
||||||
|
activity
|
||||||
|
)
|
||||||
|
// set title
|
||||||
|
alertDialogBuilder.setTitle("Cache Manager")
|
||||||
|
//.setMessage(R.string.cache_manager_description);
|
||||||
|
|
||||||
|
// set dialog message
|
||||||
|
alertDialogBuilder.setItems(
|
||||||
|
arrayOf<CharSequence>(
|
||||||
|
"Cache current size",
|
||||||
|
"Cache Download",
|
||||||
|
resources.getString(R.string.cancel)
|
||||||
|
)
|
||||||
|
) { dialog, which ->
|
||||||
|
when (which) {
|
||||||
|
0 -> showCurrentCacheInfo()
|
||||||
|
1 -> {
|
||||||
|
downloadJobAlert()
|
||||||
|
dialog.dismiss()
|
||||||
|
}
|
||||||
|
else -> dialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// create alert dialog
|
||||||
|
alertDialog = alertDialogBuilder.create()
|
||||||
|
|
||||||
|
// show it
|
||||||
|
alertDialog!!.show()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun showCurrentCacheInfo() {
|
||||||
|
Toast.makeText(activity, "Calculating...", Toast.LENGTH_SHORT).show()
|
||||||
|
Thread {
|
||||||
|
val alertDialogBuilder = AlertDialog.Builder(
|
||||||
|
activity
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
// set title
|
||||||
|
alertDialogBuilder.setTitle("Cache Manager")
|
||||||
|
.setMessage(
|
||||||
|
"""
|
||||||
|
Cache Capacity (mb): ${cacheManager.cacheCapacity() * 2.0.pow(-20.0)}
|
||||||
|
Cache Usage (mb): ${cacheManager.currentCacheUsage() * 2.0.pow(-20.0)}
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
|
||||||
|
// set dialog message
|
||||||
|
alertDialogBuilder.setItems(
|
||||||
|
arrayOf<CharSequence>(
|
||||||
|
resources.getString(R.string.cancel)
|
||||||
|
)
|
||||||
|
) { dialog, _ -> dialog.dismiss() }
|
||||||
|
activity!!.runOnUiThread { // show it
|
||||||
|
// create alert dialog
|
||||||
|
val alertDialog = alertDialogBuilder.create()
|
||||||
|
alertDialog.show()
|
||||||
|
}
|
||||||
|
}.start()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun downloadJobAlert() {
|
||||||
|
//prompt for input params
|
||||||
|
val builder = AlertDialog.Builder(activity)
|
||||||
|
val view = View.inflate(activity, R.layout.cache_mgr_input, null)
|
||||||
|
val boundingBox: BoundingBox = map.boundingBox
|
||||||
|
zoomMax = view.findViewById(R.id.slider_zoom_max)
|
||||||
|
zoomMax.max = map.maxZoomLevel.toInt()
|
||||||
|
zoomMax.setOnSeekBarChangeListener(this)
|
||||||
|
zoomMin = view.findViewById(R.id.slider_zoom_min)
|
||||||
|
zoomMin.max = map.maxZoomLevel.toInt()
|
||||||
|
zoomMin.progress = map.minZoomLevel.toInt()
|
||||||
|
zoomMin.setOnSeekBarChangeListener(this)
|
||||||
|
cacheEast = view.findViewById(R.id.cache_east)
|
||||||
|
cacheEast.setText(boundingBox.lonEast.toString() + "")
|
||||||
|
cacheNorth = view.findViewById(R.id.cache_north)
|
||||||
|
cacheNorth.setText(boundingBox.latNorth.toString() + "")
|
||||||
|
cacheSouth = view.findViewById(R.id.cache_south)
|
||||||
|
cacheSouth.setText(boundingBox.latSouth.toString() + "")
|
||||||
|
cacheWest = view.findViewById(R.id.cache_west)
|
||||||
|
cacheWest.setText(boundingBox.lonWest.toString() + "")
|
||||||
|
cacheEstimate = view.findViewById(R.id.cache_estimate)
|
||||||
|
|
||||||
|
//change listeners for both validation and to trigger the download estimation
|
||||||
|
cacheEast.addTextChangedListener(this)
|
||||||
|
cacheNorth.addTextChangedListener(this)
|
||||||
|
cacheSouth.addTextChangedListener(this)
|
||||||
|
cacheWest.addTextChangedListener(this)
|
||||||
|
executeJob = view.findViewById(R.id.executeJob)
|
||||||
|
executeJob.setOnClickListener {
|
||||||
|
builder.setOnCancelListener {
|
||||||
|
cacheEast.text = null
|
||||||
|
cacheSouth.text = null
|
||||||
|
cacheEstimate.text = ""
|
||||||
|
cacheNorth.text = null
|
||||||
|
cacheWest.text = null
|
||||||
|
zoomMin.progress = 0
|
||||||
|
zoomMax.progress = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
builder.setView(view)
|
||||||
|
builder.setCancelable(true)
|
||||||
|
downloadPrompt = builder.create()
|
||||||
|
downloadPrompt!!.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* if true, start the job
|
||||||
|
* if false, just update the dialog box
|
||||||
|
*/
|
||||||
|
private fun updateEstimate(startJob: Boolean) {
|
||||||
|
try {
|
||||||
|
if (cacheWest.text != null && cacheNorth.text != null && cacheSouth.text != null && zoomMax.progress != 0 && zoomMin.progress != 0) {
|
||||||
|
val n: Double = cacheNorth.text.toString().toDouble()
|
||||||
|
val s: Double = cacheSouth.text.toString().toDouble()
|
||||||
|
val e: Double = cacheEast.text.toString().toDouble()
|
||||||
|
val w: Double = cacheWest.text.toString().toDouble()
|
||||||
|
val zoommin: Int = zoomMin.progress
|
||||||
|
val zoommax: Int = zoomMax.progress
|
||||||
|
//nesw
|
||||||
|
val bb = BoundingBox(n, e, s, w)
|
||||||
|
val tilecount: Int = cacheManager.possibleTilesInArea(bb, zoommin, zoommax)
|
||||||
|
cacheEstimate.text = ("$tilecount tiles")
|
||||||
|
if (startJob) {
|
||||||
|
if (downloadPrompt != null) {
|
||||||
|
downloadPrompt!!.dismiss()
|
||||||
|
downloadPrompt = null
|
||||||
|
}
|
||||||
|
|
||||||
|
//this triggers the download
|
||||||
|
cacheManager.downloadAreaAsync(activity,
|
||||||
|
bb,
|
||||||
|
zoommin,
|
||||||
|
zoommax,
|
||||||
|
object : CacheManager.CacheManagerCallback {
|
||||||
|
override fun onTaskComplete() {
|
||||||
|
Toast.makeText(activity, "Download complete!", Toast.LENGTH_LONG)
|
||||||
|
.show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTaskFailed(errors: Int) {
|
||||||
|
Toast.makeText(
|
||||||
|
activity,
|
||||||
|
"Download complete with $errors errors",
|
||||||
|
Toast.LENGTH_LONG
|
||||||
|
).show()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun updateProgress(
|
||||||
|
progress: Int, currentZoomLevel: Int, zoomMin: Int, zoomMax: Int
|
||||||
|
) {
|
||||||
|
//NOOP since we are using the build in UI
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun downloadStarted() {
|
||||||
|
//NOOP since we are using the build in UI
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setPossibleTilesInArea(total: Int) {
|
||||||
|
//NOOP since we are using the build in UI
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ex: Exception) {
|
||||||
|
ex.printStackTrace()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun chooseMapStyle() {
|
private fun chooseMapStyle() {
|
||||||
|
@ -138,8 +350,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
|
marker.setAnchor(Marker.ANCHOR_CENTER, Marker.ANCHOR_BOTTOM)
|
||||||
marker.position = GeoPoint(p.latitude, p.longitude)
|
marker.position = GeoPoint(p.latitude, p.longitude)
|
||||||
marker.icon = ContextCompat.getDrawable(
|
marker.icon = ContextCompat.getDrawable(
|
||||||
requireActivity(),
|
requireActivity(), R.drawable.ic_baseline_location_on_24
|
||||||
R.drawable.ic_baseline_location_on_24
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
marker
|
marker
|
||||||
|
@ -159,8 +370,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
* Adds copyright to map depending on what source is showing
|
* Adds copyright to map depending on what source is showing
|
||||||
*/
|
*/
|
||||||
private fun addCopyright() {
|
private fun addCopyright() {
|
||||||
val copyrightNotice: String =
|
val copyrightNotice: String = map.tileProvider.tileSource.copyrightNotice
|
||||||
map.tileProvider.tileSource.copyrightNotice
|
|
||||||
val copyrightOverlay = CopyrightOverlay(context)
|
val copyrightOverlay = CopyrightOverlay(context)
|
||||||
copyrightOverlay.setCopyrightNotice(copyrightNotice)
|
copyrightOverlay.setCopyrightNotice(copyrightNotice)
|
||||||
map.overlays.add(copyrightOverlay)
|
map.overlays.add(copyrightOverlay)
|
||||||
|
@ -168,6 +378,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
|
|
||||||
private fun setupMapProperties() {
|
private fun setupMapProperties() {
|
||||||
if (this::map.isInitialized) {
|
if (this::map.isInitialized) {
|
||||||
|
cacheManager = CacheManager(map)
|
||||||
map.setDestroyMode(false) // keeps map instance alive when in the background.
|
map.setDestroyMode(false) // keeps map instance alive when in the background.
|
||||||
map.isVerticalMapRepetitionEnabled = false // disables map repetition
|
map.isVerticalMapRepetitionEnabled = false // disables map repetition
|
||||||
map.setScrollableAreaLimitLatitude(
|
map.setScrollableAreaLimitLatitude(
|
||||||
|
@ -194,8 +405,7 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
nodesWithPosition.forEach {
|
nodesWithPosition.forEach {
|
||||||
points.add(
|
points.add(
|
||||||
GeoPoint(
|
GeoPoint(
|
||||||
it.position!!.latitude,
|
it.position!!.latitude, it.position!!.longitude
|
||||||
it.position!!.longitude
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -219,6 +429,12 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
map.onPause()
|
map.onPause()
|
||||||
|
if (alertDialog != null && alertDialog!!.isShowing) {
|
||||||
|
alertDialog!!.dismiss()
|
||||||
|
}
|
||||||
|
if (downloadPrompt != null && downloadPrompt!!.isShowing) {
|
||||||
|
downloadPrompt!!.dismiss()
|
||||||
|
}
|
||||||
super.onPause()
|
super.onPause()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +486,26 @@ class MapFragment : ScreenFragment("Map"), Logging {
|
||||||
c.drawText(mLabel, (p.x - 0f), (p.y - 110f), textPaint)
|
c.drawText(mLabel, (p.x - 0f), (p.y - 110f), textPaint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun onProgressChanged(p0: SeekBar?, p1: Int, p2: Boolean) {
|
||||||
|
updateEstimate(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStartTrackingTouch(p0: SeekBar?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onStopTrackingTouch(p0: SeekBar?) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
|
||||||
|
updateEstimate(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun afterTextChanged(p0: Editable?) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:id="@+id/scrollView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center_horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Northern most Latitude"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/cache_north"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:digits="1234567890.-"
|
||||||
|
android:inputType="number|numberDecimal|numberSigned" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Southern most Latitude"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/cache_south"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:digits="1234567890.-"
|
||||||
|
android:inputType="number|numberDecimal|numberSigned" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Eastern most Longitude"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/cache_east"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:digits="1234567890.-"
|
||||||
|
android:inputType="number|numberDecimal|numberSigned" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Western most Longitude"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/cache_west"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:digits="1234567890.-"
|
||||||
|
android:inputType="number|numberDecimal|numberSigned" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Zoom Level Min"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/slider_zoom_min"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Zoom Level Max"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<SeekBar
|
||||||
|
android:id="@+id/slider_zoom_max"
|
||||||
|
android:layout_width="fill_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Tile download estimate:"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/cache_estimate"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
|
||||||
|
/>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/cache_archival_section"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:visibility="gone">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Archive File name:"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge" />
|
||||||
|
|
||||||
|
<EditText
|
||||||
|
android:id="@+id/cache_output"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="archive.sqlite"
|
||||||
|
android:lines="1"
|
||||||
|
android:text="archive.sqlite"
|
||||||
|
|
||||||
|
/>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/executeJob"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Start Download" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
|
@ -25,15 +25,15 @@
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/fab_style_toggle"
|
android:id="@+id/downloadButton"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_margin="8dp"
|
android:layout_margin="8dp"
|
||||||
android:backgroundTint="@color/design_default_color_secondary"
|
android:backgroundTint="@color/design_default_color_secondary"
|
||||||
android:contentDescription="@string/style_selection"
|
android:contentDescription="@string/style_selection"
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
|
android:visibility="visible"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
tools:background="@color/design_default_color_secondary" />
|
tools:background="@color/design_default_color_secondary" />
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
Ładowanie…
Reference in New Issue