Reduce cyclomatic complexity

This commit is contained in:
2026-01-12 06:10:58 +01:00
parent a8a07d9c8a
commit b207754636

View File

@@ -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<ItemClass<*>>,
row: GameRow<ItemClass<*>>,
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<Toggleable<Item<ItemClass<*>>>>,
cell: GameCell<ItemClass<*>>,
row: GameRow<ItemClass<*>>,
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<ItemClass<*>>,
cell: GameCell<ItemClass<*>>,
options: List<Toggleable<Item<ItemClass<*>>>>,
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<ItemClass<*>>,
cell: GameCell<ItemClass<*>>,