Set location dialog prefab and proper ViewModel handling

This commit is contained in:
Alexey 2025-09-02 13:31:35 +03:00
commit 2937f17a69
3 changed files with 92 additions and 20 deletions

View file

@ -3,18 +3,22 @@ package com.mirenkov.ktheightmap
import android.app.Application
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Build
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.FloatingActionButton
@ -23,7 +27,10 @@ import androidx.compose.material3.MaterialTheme.colorScheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Slider
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.material3.TextField
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
@ -35,7 +42,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.rotate
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.toUpperCase
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
@ -79,8 +87,6 @@ class MainActivity : ComponentActivity() {
@Composable
fun Main(vm: TileViewModel = viewModel()) {
val sliderValue = rememberSaveable { mutableFloatStateOf(1F) }
val canvasOffsetX = rememberSaveable { mutableFloatStateOf(-652.0647F) }
val canvasOffsetY = rememberSaveable { mutableFloatStateOf(-1145.693F) }
val coroutineScope = rememberCoroutineScope()
val tileContainer = TileContainer(vm, coroutineScope)
KtHeightMapTheme {
@ -97,8 +103,6 @@ fun Main(vm: TileViewModel = viewModel()) {
backColor = colorScheme.background,
scale = sliderValue,
tileContainer = tileContainer,
offsetX = canvasOffsetX,
offsetY = canvasOffsetY,
modifier = Modifier.padding(innerPadding),
)
}
@ -122,7 +126,10 @@ fun Main(vm: TileViewModel = viewModel()) {
@Composable
fun ToolButton(viewModel: TileViewModel) {
val context = LocalContext.current
var expanded by remember{ mutableStateOf(false) }
var expanded by rememberSaveable{ mutableStateOf(false) }
var debug by rememberSaveable{ viewModel.debug }
var logRequested by remember{ viewModel.logRequested }
val dialogShown = rememberSaveable{ mutableStateOf(false) }
FloatingActionButton(
onClick = {
expanded = !expanded
@ -135,23 +142,79 @@ fun ToolButton(viewModel: TileViewModel) {
) {
DropdownMenuItem(
text = { Text("Toggle debug") },
onClick = { viewModel.debug = !viewModel.debug }
onClick = {
debug = !debug
expanded = false
}
)
DropdownMenuItem(
text = { Text("Log") },
onClick = { viewModel.logRequested = true }
onClick = {
logRequested = true
expanded = false
}
)
DropdownMenuItem(
text = { Text("Set location") },
onClick = {}
onClick = {
expanded = false
dialogShown.value = true
}
)
DropdownMenuItem(
text = { Text("Settings") },
onClick = {
expanded = false
val intent = Intent(context, SettingsActivity::class.java)
context.startActivity(intent)
}
)
SetLocationDialog(viewModel, dialogShown)
}
}
}
@Composable
fun SetLocationDialog(vm: TileViewModel, dialogShown: MutableState<Boolean>) {
var showLocationDialog by dialogShown
if (showLocationDialog) {
var latitudeText by remember { vm.latitudeText }
var longitudeText by remember { vm.longitudeText }
AlertDialog (
onDismissRequest = { showLocationDialog = false },
title = { Text("Input coordinates") },
text = {
Column {
TextField(
value = latitudeText,
onValueChange = { newValue ->
latitudeText = newValue
},
label = { Text("Latitude") },
placeholder = { Text("60.086763") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
TextField(
value = longitudeText,
onValueChange = { newValue ->
longitudeText = newValue
},
label = { Text("Longitude") },
placeholder = { Text("30.014658") },
keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number)
)
}
},
confirmButton = { TextButton(onClick = {
Log.i(TAG, "Lat: %.6f, Lon: %.6f".format(
latitudeText.text.toDoubleOrNull() ?: 0.0, longitudeText.text.toDoubleOrNull() ?: 0.0
))
}) {
Text("Confirm".uppercase())
} },
dismissButton = { TextButton(onClick = { showLocationDialog = false }) {
Text("Cancel".uppercase())
} }
)
}
}

View file

@ -34,15 +34,15 @@ fun MapCanvas(
backColor: Color,
gridColor: Color,
scale: MutableFloatState,
offsetX: MutableFloatState,
offsetY: MutableFloatState,
tileContainer: TileContainer,
modifier: Modifier = Modifier
) {
var offsetX by rememberSaveable { offsetX }
var offsetY by rememberSaveable { offsetY }
var offsetX by rememberSaveable { viewModel.mapOffsetX }
var offsetY by rememberSaveable { viewModel.mapOffsetY }
val scale by rememberSaveable { scale }
val textMeasurer = rememberTextMeasurer()
val debug by rememberSaveable { viewModel.debug }
var logRequested by rememberSaveable { viewModel.logRequested }
Canvas(
modifier = modifier.fillMaxSize()
.pointerInput(Unit) {
@ -57,9 +57,9 @@ fun MapCanvas(
size = size
)
if (viewModel.logRequested) {
if (logRequested) {
Log.i(TAG, "Offset: %.6f, %.6f".format(offsetX, offsetY))
viewModel.logRequested = false
logRequested = false
}
val oldLevel = tileContainer.getLevel()
@ -101,7 +101,7 @@ fun MapCanvas(
val crossRadius = 24F
val additionalSize = if (viewModel.debug) 96F else 0F
val additionalSize = if (debug) 96F else 0F
val latLonSize = Size(196F, 96F + additionalSize)
val latLonOffset = Offset(16F, 16F)
@ -124,7 +124,7 @@ fun MapCanvas(
)
}
if (viewModel.debug) {
if (debug) {
drawRect(
color = gridColor,
size = Size(TILE_SIZE, TILE_SIZE),
@ -175,7 +175,7 @@ fun MapCanvas(
val lon = SphereMercator.mercateX(centerTileX, level)
val lat = SphereMercator.mercateY(centerTileY, level)
append("%.6f\n%.6f".format(lon, lat))
if (viewModel.debug) {
if (debug) {
append("\n%.0f\n%.0f".format(offsetX, offsetY))
}
}

View file

@ -1,13 +1,22 @@
package com.mirenkov.ktheightmap
import android.app.Application
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.text.input.TextFieldValue
import androidx.lifecycle.ViewModel
class TileViewModel(application: Application): ViewModel() {
val repository: TileRepository
var debug = false
var logRequested = false
var debug = mutableStateOf(false)
var logRequested = mutableStateOf(false)
var latitudeText = mutableStateOf(TextFieldValue(""))
var longitudeText = mutableStateOf(TextFieldValue(""))
val mapOffsetX = mutableFloatStateOf(-646.65625F)
val mapOffsetY = mutableFloatStateOf(-1157.2814F)
init {
val tileDb = TileDB.getInstance(application)