Desktop: app-wide zoom (Ctrl+=/-, Ctrl+0 resets) via scaled Density

This commit is contained in:
avi 2026-09-14 08:03:33 -05:00
commit 4944fcd162

View file

@ -4,31 +4,71 @@ import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.material3.Surface
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.isCtrlPressed
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.key.type
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Density
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.application
import androidx.compose.ui.window.rememberWindowState
/** Scales every dp/sp in the app uniformly (fonts, paddings, controls). */
private data class ScaledDensity(val base: Density, val zoom: Float) : Density {
override val density: Float get() = base.density * zoom
override val fontScale: Float get() = base.fontScale * zoom
}
fun main() = application {
val state = remember { DesktopState() }
val screen by state.screen.collectAsState()
// Ctrl+= / Ctrl+- zoom the whole app; Ctrl+0 resets (after a zoom).
var zoom by remember { mutableStateOf(1f) }
Window(
onCloseRequest = ::exitApplication,
title = "SHONAR Desktop",
state = rememberWindowState(width = 1100.dp, height = 800.dp),
) {
val baseDensity = LocalDensity.current
ShonarTheme {
Surface(Modifier.fillMaxSize()) {
Box(Modifier.fillMaxSize().padding(20.dp)) {
when (screen) {
DesktopState.Screen.ENGINE -> EngineScreen(state)
DesktopState.Screen.LIBRARY -> LibraryScreen(state)
DesktopState.Screen.DETAIL -> DetailScreen(state)
DesktopState.Screen.SETTINGS -> SettingsScreen(state)
Surface(
Modifier.fillMaxSize().onPreviewKeyEvent { e ->
if (e.type != KeyEventType.KeyDown || !e.isCtrlPressed) return@onPreviewKeyEvent false
when (e.key) {
Key.Equals, Key.Plus, Key.NumPadAdd -> {
zoom = (zoom * 1.1f).coerceAtMost(3f); true
}
Key.Minus, Key.NumPadSubtract -> {
zoom = (zoom / 1.1f).coerceAtLeast(0.4f); true
}
Key.Zero, Key.NumPad0 -> {
if (zoom != 1f) { zoom = 1f; true } else false
}
else -> false
}
},
) {
CompositionLocalProvider(
LocalDensity provides ScaledDensity(baseDensity, zoom),
) {
Box(Modifier.fillMaxSize().padding(20.dp)) {
when (screen) {
DesktopState.Screen.ENGINE -> EngineScreen(state)
DesktopState.Screen.LIBRARY -> LibraryScreen(state)
DesktopState.Screen.DETAIL -> DetailScreen(state)
DesktopState.Screen.SETTINGS -> SettingsScreen(state)
}
}
}
}