From b207754636f7afd546fbe3747d0dc0fe55de5e30 Mon Sep 17 00:00:00 2001 From: Christian Basler Date: Mon, 12 Jan 2026 06:10:58 +0100 Subject: [PATCH] Reduce cyclomatic complexity --- .../kotlin/ch/dissem/yaep/ui/common/grid.kt | 163 +++++++++++------- 1 file changed, 102 insertions(+), 61 deletions(-) diff --git a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/grid.kt b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/grid.kt index 5439b19..01e1b0b 100644 --- a/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/grid.kt +++ b/commonUI/src/commonMain/kotlin/ch/dissem/yaep/ui/common/grid.kt @@ -2,6 +2,7 @@ package ch.dissem.yaep.ui.common import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.RowScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.wrapContentHeight @@ -61,74 +62,114 @@ private fun PuzzleRow( .fillMaxWidth() .wrapContentHeight() ) { - val allOptions = row.options for (cell in row) { - var selection by remember(cell) { mutableStateOf(cell.selection) } - val options = remember(cell) { - allOptions.map { Toggleable(it, cell.options.contains(it)) } - } - LaunchedEffect(cell) { - cell.optionsChangedListeners.add { enabled -> - options.forEach { it.enabled = enabled.contains(it.item) } - } - cell.selectionChangedListeners.add { - selection = it - onUpdate() - } - } - val focusable = remember(cell, selectionManager) { - selectionManager.add { e -> - if (selection != null) { - when (e.key) { - Key.Spacebar, Key.Enter, Key.Delete, Key.Backspace -> { - onSelectItem(row, cell, options, null, onSnapshot, onUndo) - true - } - - else -> false - } - } else { - val i = getNumber(e) - if (i != null && i in 1..options.size) { - val selectedItem = options[i - 1].item - if (e.isShiftPressed) { - if (cell.options.contains(selectedItem)) { - onOptionRemoved(row, cell, selectedItem, onSnapshot) - } else { - cell.options.add(selectedItem) - } - } else { - onSelectItem(row, cell, options, selectedItem, onSnapshot, onUndo) - } - true - } else { - false - } - } - } - } - Selector( - modifier = Modifier - .focus(focusable) - .padding(spacing) - .weight(1f), + PuzzleCell( + cell, + row, + onUpdate, + onSnapshot, + onUndo, spacing, - options = options, - onOptionRemoved = { selectedItem -> - onOptionRemoved(row, cell, selectedItem, onSnapshot) - }, - onOptionAdded = { - cell.options.add(it) - }, - selectedItem = selection, - onSelectItem = { selectedItem -> - onSelectItem(row, cell, options, selectedItem, onSnapshot, onUndo) - } + selectionManager ) } } } +@Composable +private fun RowScope.PuzzleCell( + cell: GameCell>, + row: GameRow>, + onUpdate: () -> Unit, + onSnapshot: () -> Unit, + onUndo: () -> Boolean, + spacing: Dp, + selectionManager: GridSelectionManager +) { + var selection by remember(cell) { mutableStateOf(cell.selection) } + val options = remember(cell) { + row.options.map { Toggleable(it, cell.options.contains(it)) } + } + LaunchedEffect(cell) { + cell.optionsChangedListeners.add { enabled -> + options.forEach { it.enabled = enabled.contains(it.item) } + } + cell.selectionChangedListeners.add { + selection = it + onUpdate() + } + } + val focusable = remember(cell, selectionManager) { + selectionManager.add { e -> + if (selection != null) { + handleClearSelection(e.key, row, cell, options, onSnapshot, onUndo) + } else { + handleSelection(e, options, cell, row, onSnapshot, onUndo) + } + } + } + Selector( + modifier = Modifier + .focus(focusable) + .padding(spacing) + .weight(1f), + spacing, + options = options, + onOptionRemoved = { selectedItem -> + onOptionRemoved(row, cell, selectedItem, onSnapshot) + }, + onOptionAdded = { + cell.options.add(it) + }, + selectedItem = selection, + onSelectItem = { selectedItem -> + onSelectItem(row, cell, options, selectedItem, onSnapshot, onUndo) + } + ) +} + +private fun handleSelection( + e: KeyEvent, + options: List>>>, + cell: GameCell>, + row: GameRow>, + onSnapshot: () -> Unit, + onUndo: () -> Boolean +): Boolean { + val i = getNumber(e) + return if (i != null && i in 1..options.size) { + val selectedItem = options[i - 1].item + if (e.isShiftPressed) { + if (cell.options.contains(selectedItem)) { + onOptionRemoved(row, cell, selectedItem, onSnapshot) + } else { + cell.options.add(selectedItem) + } + } else { + onSelectItem(row, cell, options, selectedItem, onSnapshot, onUndo) + } + true + } else { + false + } +} + +private fun handleClearSelection( + key: Key, + row: GameRow>, + cell: GameCell>, + options: List>>>, + onSnapshot: () -> Unit, + onUndo: () -> Boolean +): Boolean = when (key) { + Key.Spacebar, Key.Enter, Key.Delete, Key.Backspace -> { + onSelectItem(row, cell, options, null, onSnapshot, onUndo) + true + } + + else -> false +} + private fun onOptionRemoved( row: GameRow>, cell: GameCell>,