Focus with bordered grid on editing

This commit is contained in:
Hasinjato 2026-06-01 15:15:32 +03:00
parent 14c27b541a
commit d59eeac52e

View file

@ -6,7 +6,9 @@ import androidx.compose.animation.core.tween
import androidx.compose.foundation.Canvas import androidx.compose.foundation.Canvas
import androidx.compose.foundation.LocalIndication import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.focusable
import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.gestures.detectTapGestures
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsHoveredAsState import androidx.compose.foundation.interaction.collectIsHoveredAsState
@ -16,11 +18,9 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Undo import androidx.compose.material.icons.automirrored.filled.Undo
import androidx.compose.material.icons.filled.ArrowBackIosNew
import androidx.compose.material.icons.filled.Build import androidx.compose.material.icons.filled.Build
import androidx.compose.material.icons.filled.Close import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.Description import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.KeyboardDoubleArrowLeft
import androidx.compose.material.icons.filled.Save import androidx.compose.material.icons.filled.Save
import androidx.compose.material3.* import androidx.compose.material3.*
import androidx.compose.runtime.* import androidx.compose.runtime.*
@ -28,6 +28,8 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.draw.drawWithContent import androidx.compose.ui.draw.drawWithContent
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.geometry.Offset import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size import androidx.compose.ui.geometry.Size
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
@ -36,6 +38,7 @@ import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.input.pointer.pointerInput import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.* import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontStyle
@ -265,7 +268,9 @@ fun TimeUnitComposable(
tuo: TimeUnitObject, tuo: TimeUnitObject,
stanzaNumber: Int, stanzaNumber: Int,
gridColumnCount: Int, gridColumnCount: Int,
gridActive: Boolean gridActive: Boolean,
isCurrentBlock: Boolean = false,
parentFocusRequester: FocusRequester? = null
) { ) {
val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff) val col = if (tuo.getNum() % 2 == 0) Color(0xff, 0xfa, 0xf7) else Color(0xfb, 0xf3, 0xff)
val currentDensity = LocalDensity.current val currentDensity = LocalDensity.current
@ -274,6 +279,8 @@ fun TimeUnitComposable(
targetValue = if (gridActive) Color.Cyan.copy(alpha = 0.5f) else col, targetValue = if (gridActive) Color.Cyan.copy(alpha = 0.5f) else col,
animationSpec = tween(durationMillis = 100) // Très court pour rester réactif animationSpec = tween(durationMillis = 100) // Très court pour rester réactif
) )
val focusRequesters = remember { List(4) { FocusRequester() } }
Column( Column(
modifier = Modifier modifier = Modifier
.background(animatedColor) .background(animatedColor)
@ -569,6 +576,9 @@ fun LazyVerticalGridTUO(
var selectedIndex by remember { mutableStateOf(-1) } var selectedIndex by remember { mutableStateOf(-1) }
val regexMeasure = Regex("(\\d)/\\d").find(viewModel.measure) val regexMeasure = Regex("(\\d)/\\d").find(viewModel.measure)
val focusRequester = remember { FocusRequester() }
var selectedGridIndex by remember { mutableStateOf(0) }
LaunchedEffect(tuoList) { LaunchedEffect(tuoList) {
showContextualMenu = false showContextualMenu = false
showEditDialog = false showEditDialog = false
@ -580,13 +590,21 @@ fun LazyVerticalGridTUO(
val editMode by sharedScreenModel.modeEditor.collectAsState() val editMode by sharedScreenModel.modeEditor.collectAsState()
val focusManager = LocalFocusManager.current
Column( Column(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.onSizeChanged { size -> .onSizeChanged { size ->
onGridWidthMeasured(size.width) onGridWidthMeasured(size.width)
} }
.focusRequester(focusRequester)
.focusable()
) { ) {
LaunchedEffect(editMode) {
if (editMode) {
focusRequester.requestFocus()
}
}
val density = LocalDensity.current val density = LocalDensity.current
val horizontalArrangementSpacing: Dp = 0.dp val horizontalArrangementSpacing: Dp = 0.dp
val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1" val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1"
@ -765,6 +783,7 @@ fun LazyVerticalGridTUO(
measureTUOs.forEachIndexed { indexInMeasure, oneTUO -> measureTUOs.forEachIndexed { indexInMeasure, oneTUO ->
val globalIndex = (measureIndex * gridColumnCount) + indexInMeasure val globalIndex = (measureIndex * gridColumnCount) + indexInMeasure
val isActive = (globalIndex == activeRowIndex) val isActive = (globalIndex == activeRowIndex)
val isSelectedByKeyboard = (globalIndex == selectedGridIndex)
val myTimestamp = sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L } val myTimestamp = sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L }
var menuOffset by remember { mutableStateOf(Offset.Zero) } var menuOffset by remember { mutableStateOf(Offset.Zero) }
@ -774,6 +793,11 @@ fun LazyVerticalGridTUO(
key(oneTUO.numBlock) { key(oneTUO.numBlock) {
Box(modifier = Modifier Box(modifier = Modifier
.width(gridWidthDp / gridColumnCount) .width(gridWidthDp / gridColumnCount)
.border(
width = if (isSelectedByKeyboard && editMode) 2.dp else 0.dp,
color = if (isSelectedByKeyboard && editMode) Color(0xFF9C27B0) else Color.Transparent,
shape = RoundedCornerShape(4.dp)
)
.background( .background(
if (isHovered) Color.Black.copy(alpha = 0.05f) else Color.Transparent, if (isHovered) Color.Black.copy(alpha = 0.05f) else Color.Transparent,
RoundedCornerShape(4.dp) RoundedCornerShape(4.dp)
@ -787,6 +811,7 @@ fun LazyVerticalGridTUO(
detectTapGestures( detectTapGestures(
onTap = { offset -> onTap = { offset ->
if(editMode) { if(editMode) {
selectedGridIndex = globalIndex
menuOffset = offset menuOffset = offset
selectedTUO = oneTUO selectedTUO = oneTUO
selectedIndex = globalIndex selectedIndex = globalIndex
@ -802,7 +827,9 @@ fun LazyVerticalGridTUO(
tuo = oneTUO, tuo = oneTUO,
stanzaNumber = currentStanza, stanzaNumber = currentStanza,
gridColumnCount = gridColumnCount, gridColumnCount = gridColumnCount,
gridActive = isActive gridActive = isActive,
isCurrentBlock = isSelectedByKeyboard && editMode,
parentFocusRequester = focusRequester
) )
if (showContextualMenu && selectedIndex == globalIndex) { if (showContextualMenu && selectedIndex == globalIndex) {
@ -877,7 +904,8 @@ fun LazyVerticalGridTUO(
oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() }, oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() } oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
).joinToString(" "), ).joinToString(" "),
silentDuration = blankPrefix silentDuration = blankPrefix,
sep = oneTUO.sep0
) )
TUODetailDialog( TUODetailDialog(
editState = editState, editState = editState,
@ -1422,4 +1450,21 @@ fun autoFixNote(rawNote: String, template: String): String {
// println("on a RES ${finalResult}") // println("on a RES ${finalResult}")
return finalResult return finalResult
}
private fun transformMusicalInput(input: String): String {
return input.lowercase()
.replace(";", "• ,")
.replace(".", "")
.replace("-", "")
.replace("(?<=[a-z])[']".toRegex(), "¹")
.replace("(?<=[a-z])[,]".toRegex(), "")
.replace("¹¹", "²")
.replace("¹'", "²")
.replace("²¹", "³")
.replace("²'", "³")
.replace("₁,", "")
.replace("₁₁", "")
.replace("₂,", "")
.replace("₂₁", "")
.replace("'", "¹")
} }