Dropdown menu and almost proper debugging
This commit is contained in:
parent
6c69440b4d
commit
8bdbe3dc69
7 changed files with 117 additions and 52 deletions
|
|
@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.safeDrawingPadding
|
|||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material3.DropdownMenu
|
||||
import androidx.compose.material3.DropdownMenuItem
|
||||
import androidx.compose.material3.FloatingActionButton
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme.colorScheme
|
||||
|
|
@ -22,9 +24,13 @@ import androidx.compose.material3.Scaffold
|
|||
import androidx.compose.material3.Slider
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableFloatStateOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.runtime.rememberCoroutineScope
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.runtime.setValue
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.draw.rotate
|
||||
|
|
@ -73,6 +79,8 @@ 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 {
|
||||
|
|
@ -81,13 +89,16 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
modifier = Modifier.fillMaxSize()
|
||||
.safeDrawingPadding()
|
||||
.align(Alignment.Center),
|
||||
floatingActionButton = { ToolButton() }
|
||||
floatingActionButton = { ToolButton(vm) }
|
||||
) { innerPadding ->
|
||||
MapCanvas(
|
||||
viewModel = vm,
|
||||
gridColor = colorScheme.primary,
|
||||
backColor = colorScheme.background,
|
||||
scale = sliderValue,
|
||||
tileContainer = tileContainer,
|
||||
offsetX = canvasOffsetX,
|
||||
offsetY = canvasOffsetY,
|
||||
modifier = Modifier.padding(innerPadding),
|
||||
)
|
||||
}
|
||||
|
|
@ -100,7 +111,7 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
Slider(
|
||||
value = sliderValue.floatValue,
|
||||
onValueChange = { sliderValue.floatValue = it },
|
||||
valueRange = 2F..14F,
|
||||
valueRange = 1F..14F,
|
||||
modifier = Modifier.align(Alignment.CenterStart)
|
||||
)
|
||||
}
|
||||
|
|
@ -109,33 +120,38 @@ fun Main(vm: TileViewModel = viewModel()) {
|
|||
}
|
||||
|
||||
@Composable
|
||||
fun ToolButton() {
|
||||
fun ToolButton(viewModel: TileViewModel) {
|
||||
val context = LocalContext.current
|
||||
var expanded by remember{ mutableStateOf(false) }
|
||||
FloatingActionButton(
|
||||
onClick = {
|
||||
val intent = Intent(context, SettingsActivity::class.java)
|
||||
context.startActivity(intent)
|
||||
expanded = !expanded
|
||||
}
|
||||
) { Icon(Icons.Filled.Build, contentDescription = "Tools") }
|
||||
}
|
||||
|
||||
@Preview(showBackground = true)
|
||||
@Composable
|
||||
fun MainPreview() {
|
||||
KtHeightMapTheme {
|
||||
Scaffold(
|
||||
modifier = Modifier.safeDrawingPadding(),
|
||||
floatingActionButton = { ToolButton() }
|
||||
) { innerPadding ->
|
||||
Box(
|
||||
modifier = Modifier.padding(innerPadding)
|
||||
.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Text(
|
||||
text = "Gryadki"
|
||||
)
|
||||
}
|
||||
) {
|
||||
Icon(Icons.Filled.Build, contentDescription = "Tools")
|
||||
DropdownMenu(
|
||||
expanded = expanded,
|
||||
onDismissRequest = { expanded = false }
|
||||
) {
|
||||
DropdownMenuItem(
|
||||
text = { Text("Toggle debug") },
|
||||
onClick = { viewModel.debug = !viewModel.debug }
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Log") },
|
||||
onClick = { viewModel.logRequested = true }
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Set location") },
|
||||
onClick = {}
|
||||
)
|
||||
DropdownMenuItem(
|
||||
text = { Text("Settings") },
|
||||
onClick = {
|
||||
val intent = Intent(context, SettingsActivity::class.java)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,8 @@
|
|||
package com.mirenkov.ktheightmap
|
||||
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.Canvas
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.gestures.detectDragGestures
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.runtime.Composable
|
||||
|
|
@ -28,14 +30,18 @@ import kotlin.math.absoluteValue
|
|||
|
||||
@Composable
|
||||
fun MapCanvas(
|
||||
viewModel: TileViewModel,
|
||||
backColor: Color,
|
||||
gridColor: Color,
|
||||
scale: MutableFloatState,
|
||||
offsetX: MutableFloatState,
|
||||
offsetY: MutableFloatState,
|
||||
tileContainer: TileContainer,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
var offsetX by rememberSaveable { mutableFloatStateOf(-TILE_SIZE) }
|
||||
var offsetY by rememberSaveable { mutableFloatStateOf(-TILE_SIZE) }
|
||||
var offsetX by rememberSaveable { offsetX }
|
||||
var offsetY by rememberSaveable { offsetY }
|
||||
val scale by rememberSaveable { scale }
|
||||
val textMeasurer = rememberTextMeasurer()
|
||||
Canvas(
|
||||
modifier = modifier.fillMaxSize()
|
||||
|
|
@ -50,8 +56,14 @@ fun MapCanvas(
|
|||
color = backColor,
|
||||
size = size
|
||||
)
|
||||
|
||||
if (viewModel.logRequested) {
|
||||
Log.i(TAG, "Offset: %.6f, %.6f".format(offsetX, offsetY))
|
||||
viewModel.logRequested = false
|
||||
}
|
||||
|
||||
val oldLevel = tileContainer.getLevel()
|
||||
val level = scale.floatValue.toInt()
|
||||
val level = scale.toInt()
|
||||
val levelDiff = level - oldLevel
|
||||
|
||||
if (levelDiff < 0) {
|
||||
|
|
@ -72,6 +84,9 @@ fun MapCanvas(
|
|||
val tileOffsetX = (offsetX / TILE_SIZE).toInt()
|
||||
val tileOffsetY = (offsetY / TILE_SIZE).toInt()
|
||||
|
||||
val centerTileX = (1 + (offsetX + size.width / 2) / TILE_SIZE).toDouble()
|
||||
val centerTileY = (1 + (offsetY + size.height / 2) / TILE_SIZE).toDouble()
|
||||
|
||||
val strippedOffsetX = offsetX % TILE_SIZE
|
||||
val strippedOffsetY = offsetY % TILE_SIZE
|
||||
|
||||
|
|
@ -86,6 +101,10 @@ fun MapCanvas(
|
|||
|
||||
val crossRadius = 24F
|
||||
|
||||
val additionalSize = if (viewModel.debug) 96F else 0F
|
||||
val latLonSize = Size(196F, 96F + additionalSize)
|
||||
val latLonOffset = Offset(16F, 16F)
|
||||
|
||||
for (cellX in 0 .. gridWidth + 2) {
|
||||
val tileX = tileOffsetX + cellX
|
||||
val localOffsetX = TILE_SIZE * (cellX - 1)
|
||||
|
|
@ -105,27 +124,29 @@ fun MapCanvas(
|
|||
)
|
||||
}
|
||||
|
||||
drawRect(
|
||||
color = gridColor,
|
||||
size = Size(TILE_SIZE, TILE_SIZE),
|
||||
topLeft = totalOffset,
|
||||
style = Stroke(width = 4F)
|
||||
)
|
||||
if (viewModel.debug) {
|
||||
drawRect(
|
||||
color = gridColor,
|
||||
size = Size(TILE_SIZE, TILE_SIZE),
|
||||
topLeft = totalOffset,
|
||||
style = Stroke(width = 4F)
|
||||
)
|
||||
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
val mercX = tile.mercateX()
|
||||
val mercY = tile.mercateY()
|
||||
append("%.6f, %.6f,\n%d, %d".format(mercX, mercY, tileX, tileY))
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
val mercX = tile.mercateX()
|
||||
val mercY = tile.mercateY()
|
||||
append("%.6f, %.6f,\n%d, %d".format(mercX, mercY, tileX, tileY))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
topLeft = totalOffset,
|
||||
size = Size(TILE_SIZE, TILE_SIZE)
|
||||
)
|
||||
},
|
||||
topLeft = totalOffset,
|
||||
size = Size(TILE_SIZE, TILE_SIZE)
|
||||
)
|
||||
}
|
||||
|
||||
val path = Path()
|
||||
path.moveTo(size.width / 2 - crossRadius, size.height / 2)
|
||||
|
|
@ -139,6 +160,30 @@ fun MapCanvas(
|
|||
Color.White,
|
||||
style = Stroke(width = 6F)
|
||||
)
|
||||
|
||||
drawRect(
|
||||
color = backColor,
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
|
||||
drawText(
|
||||
textMeasurer = textMeasurer,
|
||||
text = buildAnnotatedString {
|
||||
withStyle(ParagraphStyle(textAlign = TextAlign.Center)) {
|
||||
withStyle(SpanStyle(color = gridColor)) {
|
||||
val lon = SphereMercator.mercateX(centerTileX, level)
|
||||
val lat = SphereMercator.mercateY(centerTileY, level)
|
||||
append("%.6f\n%.6f".format(lon, lat))
|
||||
if (viewModel.debug) {
|
||||
append("\n%.0f\n%.0f".format(offsetX, offsetY))
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
size = latLonSize,
|
||||
topLeft = latLonOffset
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,5 +48,9 @@ class SphereMercator {
|
|||
fun lat2sy(latitude: Double, level: Int): Double {
|
||||
return lat2y(latitude) / scaledMetersPerPixel(level)
|
||||
}
|
||||
|
||||
fun mercateX(x: Double, level: Int): Double = sx2lon((x * TILE_SIZE), level) - 180.0
|
||||
|
||||
fun mercateY(y: Double, level: Int): Double = -sy2lat((y - ((1 shl (level - 1)).toDouble() / 2.0)) * TILE_SIZE, level - 1)
|
||||
}
|
||||
}
|
||||
|
|
@ -47,7 +47,7 @@ class Tile {
|
|||
return bitmap
|
||||
}
|
||||
|
||||
fun mercateX(): Double = SphereMercator.sx2lon((x * TILE_SIZE).toDouble(), level) - 180.0
|
||||
fun mercateX(): Double = SphereMercator.mercateX(x.toDouble(), level)
|
||||
|
||||
fun mercateY(): Double = -SphereMercator.sy2lat((y.toDouble() - ((1 shl (level - 1)).toDouble() / 2.0)) * TILE_SIZE, level - 1)
|
||||
fun mercateY(): Double = SphereMercator.mercateY(y.toDouble(), level)
|
||||
}
|
||||
|
|
@ -12,14 +12,12 @@ class TileRepository(private val tileDao: TileDao) {
|
|||
fun pushTile(tile: Tile) {
|
||||
coroutineScope.launch(Dispatchers.IO) { tileDao.pushTile(tile) }
|
||||
}
|
||||
|
||||
fun getTile(x: Int, y: Int, level: Int): Tile? {
|
||||
val tileFuture = coroutineScope.future(Dispatchers.IO) {
|
||||
tileDao.getTile(x, y, level)
|
||||
}
|
||||
return tileFuture.join()
|
||||
}
|
||||
|
||||
fun clearTiles() {
|
||||
coroutineScope.launch(Dispatchers.IO) { tileDao.clearTiles() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ import androidx.lifecycle.ViewModel
|
|||
|
||||
class TileViewModel(application: Application): ViewModel() {
|
||||
val repository: TileRepository
|
||||
var debug = false
|
||||
var logRequested = false
|
||||
|
||||
init {
|
||||
val tileDb = TileDB.getInstance(application)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue