Compare commits

..

2 commits

View file

@ -28,11 +28,13 @@ 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
import androidx.compose.ui.graphics.RectangleShape
import androidx.compose.ui.graphics.SolidColor import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.drawscope.Stroke 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
@ -271,8 +273,8 @@ fun TimeUnitComposable(
val currentDensity = LocalDensity.current val currentDensity = LocalDensity.current
val animatedColor by animateColorAsState( val animatedColor by animateColorAsState(
targetValue = if (gridActive) MaterialTheme.colorScheme.secondary.copy(alpha = 0.5f) else col, targetValue = if (gridActive) MaterialTheme.colorScheme.secondary.copy(alpha = 1f) else col,
animationSpec = tween(durationMillis = 150) // Très court pour rester réactif animationSpec = tween(durationMillis = 100) // Très court pour rester réactif
) )
val focusRequesters = remember { List(4) { FocusRequester() } } val focusRequesters = remember { List(4) { FocusRequester() } }
@ -475,13 +477,17 @@ fun TimeUnitComposable(
} }
} }
data class TUOWidthMeasure(val width: Dp, val isReady: Boolean)
@Composable @Composable
fun bestTUOWidth(items: List<TimeUnitObject>): Dp { fun bestTUOWidth(items: List<TimeUnitObject>): TUOWidthMeasure {
val textMeasurer = rememberTextMeasurer() val textMeasurer = rememberTextMeasurer()
val density = LocalDensity.current val density = LocalDensity.current
var maxWidth by remember { mutableStateOf(0.dp) } var maxWidth by remember(items) { mutableStateOf(0.dp) }
var isReady by remember(items) { mutableStateOf(false) }
LaunchedEffect(items) { LaunchedEffect(items) {
isReady = false
maxWidth = 0.dp maxWidth = 0.dp
items.forEach { items.forEach {
val textLayoutResult: TextLayoutResult = textMeasurer.measure( val textLayoutResult: TextLayoutResult = textMeasurer.measure(
@ -495,8 +501,9 @@ fun bestTUOWidth(items: List<TimeUnitObject>): Dp {
maxWidth = textWidth maxWidth = textWidth
} }
} }
isReady = true
} }
return maxWidth + 13.dp return TUOWidthMeasure(maxWidth + 13.dp, isReady)
} }
@Composable @Composable
fun AutoResizingText( fun AutoResizingText(
@ -564,10 +571,6 @@ fun LazyVerticalGridTUO(
val tuoList = viewModel.tuoList val tuoList = viewModel.tuoList
key(tuoList) { key(tuoList) {
var isCalculatingGrid by remember { mutableStateOf(true) }
var gridColumnCount by remember { mutableStateOf(0) }
var computedMeasures by remember { mutableStateOf<List<List<TimeUnitObject>>>(emptyList()) }
var menuPosition by remember { mutableStateOf(Offset.Zero) } var menuPosition by remember { mutableStateOf(Offset.Zero) }
var showAddDialog by remember { mutableStateOf(false) } var showAddDialog by remember { mutableStateOf(false) }
var showDetailDialog by remember { mutableStateOf(false) } var showDetailDialog by remember { mutableStateOf(false) }
@ -592,40 +595,57 @@ fun LazyVerticalGridTUO(
val editMode by sharedScreenModel.modeEditor.collectAsState() val editMode by sharedScreenModel.modeEditor.collectAsState()
val showFullChord by sharedScreenModel.harmonyView.collectAsState() val showFullChord by sharedScreenModel.harmonyView.collectAsState()
var toggleWithDegreeAndChord by remember { mutableStateOf (false) } var toggleWithDegreeAndChord by remember { mutableStateOf (false) }
val focusManager = LocalFocusManager.current
Column(
modifier = Modifier
.fillMaxWidth()
.onSizeChanged { size ->
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 columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1" val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1"
val columnGroup = columnGroupString.toInt().coerceAtLeast(1) val columnGroup = columnGroupString.toInt().coerceAtLeast(1)
val itemMinBaseWidth = bestTUOWidth(tuoList) val tuoWidthMeasure = bestTUOWidth(tuoList)
val itemMinBaseWidth = tuoWidthMeasure.width
val gridWidthDp = with(density) { gridWidthPx.toDp() } val gridWidthDp = with(density) { gridWidthPx.toDp() }
// on affiche un loader pour éviter le "saut" visuel
val isLayoutReady = tuoWidthMeasure.isReady && gridWidthDp > 0.dp
val gridCount by sharedScreenModel.gridCount.collectAsState() val gridCount by sharedScreenModel.gridCount.collectAsState()
val currentStanza = viewModel.stanza
// Calcul asynchrone nombre de colonnes var gridColumnCount: Int = remember(gridWidthDp, itemMinBaseWidth, columnGroup) {
LaunchedEffect(gridWidthDp, itemMinBaseWidth, columnGroup, gridCount, tuoList) { if (gridWidthDp == 0.dp) return@remember columnGroup
if (gridWidthDp == 0.dp || tuoList.isEmpty()) return@LaunchedEffect var calculatedCols =
(gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt()
isCalculatingGrid = true
withContext(Dispatchers.Default) {
var calculatedCols = (gridWidthDp / (itemMinBaseWidth + 0.dp)).toInt()
if (calculatedCols == 0) calculatedCols = columnGroup if (calculatedCols == 0) calculatedCols = columnGroup
if (calculatedCols % columnGroup != 0) { if (calculatedCols % columnGroup != 0) {
calculatedCols = (calculatedCols / columnGroup) * columnGroup calculatedCols = (calculatedCols / columnGroup) * columnGroup
if (calculatedCols == 0) calculatedCols = columnGroup if (calculatedCols == 0) calculatedCols = columnGroup
} }
val finalCols = calculatedCols.coerceAtLeast(columnGroup) + gridCount val actualColumnCount: Int = calculatedCols.coerceAtLeast(columnGroup)
val chunkedMeasures = tuoList.drop(1).chunked(finalCols) actualColumnCount
}
gridColumnCount += gridCount
val flowRowSize: Float = 0.98f / gridColumnCount
withContext(Dispatchers.Main) { val currentStanza = viewModel.stanza
gridColumnCount = finalCols
computedMeasures = chunkedMeasures
isCalculatingGrid = false
}
}
}
val tuoTimestamps by sharedScreenModel.tuoTimestamps.collectAsState() val tuoTimestamps by sharedScreenModel.tuoTimestamps.collectAsState()
val activeRowIndex by sharedScreenModel.activeIndex.collectAsState() val activeRowIndex by sharedScreenModel.activeIndex.collectAsState()
val measures = tuoList.drop(1).chunked(gridColumnCount)
// Avant column affichage:
val metadataList = remember(tuoList) { val metadataList = remember(tuoList) {
tuoList.drop(1).mapIndexedNotNull { globalIndex, oneTUO -> tuoList.drop(1).mapIndexedNotNull { globalIndex, oneTUO ->
val markerText = oneTUO.pTemplate.markerToString() val markerText = oneTUO.pTemplate.markerToString()
@ -661,48 +681,26 @@ fun LazyVerticalGridTUO(
sharedScreenModel.updateAndFinalizeMidiData(metadataList) sharedScreenModel.updateAndFinalizeMidiData(metadataList)
} }
} }
LaunchedEffect(computedMeasures, sharedScreenModel.stanza.value) { LaunchedEffect(measures, sharedScreenModel.stanza.value) {
sharedScreenModel.updateSyllablesFromList( sharedScreenModel.updateSyllablesFromList(
measures = computedMeasures, measures = measures,
stanzaNumber = sharedScreenModel.stanza.value stanzaNumber = sharedScreenModel.stanza.value
) )
val totalSyllables = sharedScreenModel.synchronizedSyllables.value.size val totalSyllables = sharedScreenModel.synchronizedSyllables.value.size
//println("Sync complète effectuée SUR stz: ${sharedScreenModel.stanza.value}! Total colonnes : $totalSyllables") //println("Sync complète effectuée SUR stz: ${sharedScreenModel.stanza.value}! Total colonnes : $totalSyllables")
} }
if (!isLayoutReady) {
Box( Box(
modifier = modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.onSizeChanged { size-> .height(200.dp),
onGridWidthMeasured(size.width)
}
.focusRequester(focusRequester)
.focusable(),
contentAlignment = Alignment.Center contentAlignment = Alignment.Center
) {
LaunchedEffect(editMode) {
if (editMode) focusRequester.requestFocus()
}
// Chargement avant affichage
if (isCalculatingGrid || computedMeasures.isEmpty() || gridColumnCount == 0) {
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.padding(32.dp)
.size(100.dp)
) { ) {
CircularProgressIndicator( CircularProgressIndicator(
modifier = Modifier.fillMaxSize(), modifier = Modifier.size(64.dp),
color = MaterialTheme.colorScheme.primary, strokeWidth = 3.dp
strokeWidth = 2.dp,
trackColor = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f)
) )
Column(
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
Text( Text(
text = "𝄞 ♫", text = "𝄞 ♫",
style = TextStyle( style = TextStyle(
@ -711,71 +709,14 @@ fun LazyVerticalGridTUO(
) )
) )
} }
}
} else { } else {
Column( Column(
modifier = Modifier.fillMaxWidth() modifier = Modifier.fillMaxWidth()
) { ){
computedMeasures.forEachIndexed { measureIndex, measureTUOs -> measures.forEachIndexed { measureIndex, measureTUOs ->
key(measureIndex) { key(measureIndex) {
MeasureRowItem(
measureTUOs,
gridWidthDp,
gridColumnCount,
showFullChord,
sharedScreenModel,
toggleWithDegreeAndChord,
measureIndex,
activeRowIndex,
selectedGridIndex,
editMode,
selectedTUO,
selectedIndex,
showContextualMenu,
currentStanza,
focusRequester,
showEditDialog,
showAddDialog,
showDetailDialog
)
}
}
}
}
}
}
}
@Composable
private fun MeasureRowItem(
measureTUOs: List<TimeUnitObject>,
gridWidthDp: Dp,
gridColumnCount: Int,
showFullChord: Boolean,
sharedScreenModel: SharedScreenModel,
toggleWithDegreeAndChord: Boolean,
measureIndex: Int,
activeRowIndex: Int,
selectedGridIndex: Int,
editMode: Boolean,
selectedTUO: TimeUnitObject?,
selectedIndex: Int,
showContextualMenu: Boolean,
currentStanza: Int,
focusRequester: FocusRequester,
showEditDialog: Boolean,
showAddDialog: Boolean,
showDetailDialog: Boolean
) {
var toggleWithDegreeAndChord1 = toggleWithDegreeAndChord
var selectedGridIndex1 = selectedGridIndex
var selectedTUO1 = selectedTUO
var selectedIndex1 = selectedIndex
var showContextualMenu1 = showContextualMenu
var showEditDialog1 = showEditDialog
var showAddDialog1 = showAddDialog
var showDetailDialog1 = showDetailDialog
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) { Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
@ -789,17 +730,17 @@ private fun MeasureRowItem(
if (TimeUnitObject._hasMarker) { if (TimeUnitObject._hasMarker) {
val lineHeight = 20.sp val lineHeight = 20.sp
val density = LocalDensity.current val density = LocalDensity.current
val lineHeightDp: Dp = with(density) { val lineHeightDp : Dp = with(density) {
lineHeight.toDp() lineHeight.toDp()
} }
var fontStyle = FontStyle.Normal var fontStyle = FontStyle.Normal
var fontWeight = FontWeight.Normal var fontWeight = FontWeight.Normal
val hairPinSymbol = tuo.hasHairPin() val hairPinSymbol = tuo.hasHairPin()
val yHeight = with(density) { lineHeightDp.toPx() } val yHeight = with(density) { lineHeightDp.toPx()}
if (tuo.isTriolet()) { if (tuo.isTriolet()) {
Canvas(modifier = Modifier.fillMaxSize()) { Canvas(modifier = Modifier.fillMaxSize()) {
val arcWidth = with(density) { size.width * 0.75f } val arcWidth = with(density) { size.width * 0.75f}
drawArc( drawArc(
color = FEUFAROO_TRIOLET_COLOR, color = FEUFAROO_TRIOLET_COLOR,
startAngle = 200f, startAngle = 200f,
@ -813,32 +754,30 @@ private fun MeasureRowItem(
} }
} }
if ((hairPinSymbol == '=') && (TimeUnitObject.lastHairPinSymbol != null)) { if ((hairPinSymbol == '=') && (TimeUnitObject.lastHairPinSymbol != null)) {
// println("LastHairpin: ${TimeUnitObject.lastHairPinSymbol} ${TimeUnitObject.lastHairPinStart}") // println("LastHairpin: ${TimeUnitObject.lastHairPinSymbol} ${TimeUnitObject.lastHairPinStart}")
val hairPinStart = TimeUnitObject.lastHairPinStart val hairPinStart = TimeUnitObject.lastHairPinStart
val lastHairPinSymbol = TimeUnitObject.lastHairPinSymbol val lastHairPinSymbol = TimeUnitObject.lastHairPinSymbol
val hairPinStartLine: Int = (hairPinStart - 1) / gridColumnCount val hairPinStartLine: Int = (hairPinStart - 1) / gridColumnCount
val hairPinEndLine: Int = (tuo.numBlock - 1) / gridColumnCount val hairPinEndLine: Int = (tuo.numBlock - 1) / gridColumnCount
// if (hairPinStartLine == hairPinEndLine) { // if (hairPinStartLine == hairPinEndLine) {
Canvas( Canvas(
modifier = Modifier.fillMaxSize() modifier = Modifier.fillMaxSize()
) { ) {
val xStart = val xStart = if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width/2
if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width / 2 val xEnd = if (lastHairPinSymbol == '>') size.width/2 else -size.width * (tuo.numBlock - hairPinStart)
val xEnd =
if (lastHairPinSymbol == '>') size.width / 2 else -size.width * (tuo.numBlock - hairPinStart)
drawLine( drawLine(
Color.DarkGray, Color.DarkGray,
start = Offset(x = xStart, y = 0f), start = Offset(x=xStart, y=0f),
end = Offset(xEnd, yHeight / 2) end = Offset(xEnd, yHeight/2)
) )
drawLine( drawLine(
Color.DarkGray, Color.DarkGray,
start = Offset(xStart, yHeight), start = Offset(xStart, yHeight),
end = Offset(xEnd, yHeight / 2) end = Offset(xEnd, yHeight/2)
) )
} }
TimeUnitObject.endHairPin() TimeUnitObject.endHairPin()
// } // }
} }
if (hairPinSymbol != null && hairPinSymbol != '=') { if (hairPinSymbol != null && hairPinSymbol != '=') {
@ -854,13 +793,9 @@ private fun MeasureRowItem(
if (text.contains(Regex("^\\s*(ppp|pp|p|mp|mf|f|ff|fff)\\s*$"))) { if (text.contains(Regex("^\\s*(ppp|pp|p|mp|mf|f|ff|fff)\\s*$"))) {
fontWeight = FontWeight.Bold fontWeight = FontWeight.Bold
} }
Text( Text(text = text,
text = text,
modifier = Modifier modifier = Modifier
.wrapContentSize( .wrapContentSize(unbounded = true, align = Alignment.CenterStart,),
unbounded = true,
align = Alignment.CenterStart
),
softWrap = false, softWrap = false,
maxLines = 1, maxLines = 1,
fontStyle = fontStyle, fontStyle = fontStyle,
@ -874,7 +809,7 @@ private fun MeasureRowItem(
} }
} }
} }
if (showFullChord) { if(showFullChord) {
Row( Row(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start, horizontalArrangement = Arrangement.Start,
@ -890,10 +825,7 @@ private fun MeasureRowItem(
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null
} }
val chordName = remember(chordMap) { val chordName = remember(chordMap) {
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName( if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName(chordMap, sharedScreenModel.songKey.value) else null
chordMap,
sharedScreenModel.songKey.value
) else null
} }
Column( Column(
@ -905,15 +837,12 @@ private fun MeasureRowItem(
var currentFontSize by remember { mutableStateOf(maxFontSize) } var currentFontSize by remember { mutableStateOf(maxFontSize) }
TextButton( TextButton(
onClick = { toggleWithDegreeAndChord1 = !toggleWithDegreeAndChord1 }, onClick = { toggleWithDegreeAndChord = !toggleWithDegreeAndChord },
contentPadding = PaddingValues(0.dp), contentPadding = PaddingValues(0.dp),
modifier = Modifier.height(24.dp).fillMaxWidth() modifier = Modifier.height(24.dp).fillMaxWidth()
) { ) {
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) { BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
val textToDisplay = val textToDisplay = if (toggleWithDegreeAndChord) (chordName ?: "") else (degreeName ?: "")
if (toggleWithDegreeAndChord1) (chordName
?: "") else (degreeName
?: "")
Text( Text(
text = textToDisplay, text = textToDisplay,
@ -926,11 +855,7 @@ private fun MeasureRowItem(
maxLines = 1, maxLines = 1,
overflow = TextOverflow.Visible, overflow = TextOverflow.Visible,
style = TextStyle( style = TextStyle(
color = if (!toggleWithDegreeAndChord1) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy( color = if (!toggleWithDegreeAndChord) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy(red = MaterialTheme.colorScheme.secondary.red * 0.4f, green = MaterialTheme.colorScheme.secondary.green * 0.4f, blue = MaterialTheme.colorScheme.secondary.blue * 0.4f ),
red = MaterialTheme.colorScheme.secondary.red * 0.4f,
green = MaterialTheme.colorScheme.secondary.green * 0.4f,
blue = MaterialTheme.colorScheme.secondary.blue * 0.4f
),
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = currentFontSize fontSize = currentFontSize
) )
@ -945,17 +870,15 @@ private fun MeasureRowItem(
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 == selectedGridIndex1) val isSelectedByKeyboard = (globalIndex == selectedGridIndex)
val myTimestamp = val myTimestamp = sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L }
sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L }
var menuOffset by remember { mutableStateOf(Offset.Zero) } var menuOffset by remember { mutableStateOf(Offset.Zero) }
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
val isHovered by interactionSource.collectIsHoveredAsState() val isHovered by interactionSource.collectIsHoveredAsState()
key(oneTUO.numBlock) { key(oneTUO.numBlock) {
Box( Box(modifier = Modifier
modifier = Modifier
.width(gridWidthDp / gridColumnCount) .width(gridWidthDp / gridColumnCount)
.border( .border(
width = if (isSelectedByKeyboard && editMode) 2.dp else 0.dp, width = if (isSelectedByKeyboard && editMode) 2.dp else 0.dp,
@ -974,12 +897,12 @@ private fun MeasureRowItem(
.pointerInput(globalIndex) { .pointerInput(globalIndex) {
detectTapGestures( detectTapGestures(
onTap = { offset -> onTap = { offset ->
if (editMode) { if(editMode) {
selectedGridIndex1 = globalIndex selectedGridIndex = globalIndex
menuOffset = offset menuOffset = offset
selectedTUO1 = oneTUO selectedTUO = oneTUO
selectedIndex1 = globalIndex selectedIndex = globalIndex
showContextualMenu1 = true showContextualMenu = true
} else { } else {
sharedScreenModel.seekToGrid(globalIndex) sharedScreenModel.seekToGrid(globalIndex)
} }
@ -998,47 +921,43 @@ private fun MeasureRowItem(
transpositionInterval = currentInterval transpositionInterval = currentInterval
) )
if (showContextualMenu1 && selectedIndex1 == globalIndex) { if (showContextualMenu && selectedIndex == globalIndex) {
Popup( Popup(
alignment = Alignment.TopStart, alignment = Alignment.TopStart,
offset = IntOffset( offset = IntOffset(
menuOffset.x.roundToInt(), menuOffset.x.roundToInt(),
menuOffset.y.roundToInt() menuOffset.y.roundToInt()
), ),
onDismissRequest = { showContextualMenu1 = false } onDismissRequest = { showContextualMenu = false }
) { ) {
ContextualMenu(onMenuItemClick = { item -> ContextualMenu(onMenuItemClick = { item ->
println("Clicked in TUO $globalIndex: $item") println("Clicked in TUO $globalIndex: $item")
showContextualMenu1 = false showContextualMenu = false
when (item) { when(item) {
"Modifier" -> { "Modifier" -> {
showEditDialog1 = true showEditDialog = true
} }
"Ajouter" -> { "Ajouter" -> {
showAddDialog1 = true showAddDialog = true
} }
"Liste" -> { "Liste" -> {
showDetailDialog1 = true showDetailDialog = true
} }
else -> { else -> {
showDetailDialog1 = false showDetailDialog = false
} }
} }
}) })
} }
} }
val currentSelected = selectedTUO1 val currentSelected = selectedTUO
if ((showEditDialog1 || showAddDialog1 || showDetailDialog1) && currentSelected != null && selectedIndex1 == globalIndex) { if ((showEditDialog || showAddDialog || showDetailDialog) && currentSelected != null && selectedIndex == globalIndex) {
val canAdd = showAddDialog1 val canAdd = showAddDialog
val canEdit = showEditDialog1 || canAdd val canEdit = showEditDialog || canAdd
val template = oneTUO.pTemplate.template val template = oneTUO.pTemplate.template
val expectedTemplate = val expectedTemplate = template.count { it.isLetter() } == 2 && template.contains(".")
template.count { it.isLetter() } == 2 && template.contains(".")
val fileC = sharedScreenModel.fileContent.value ?: "" val fileC = sharedScreenModel.fileContent.value ?: ""
val lines = fileC.split("\n").toMutableList() val lines = fileC.split("\n").toMutableList()
@ -1049,23 +968,20 @@ private fun MeasureRowItem(
t0Idx != -1 -> { t0Idx != -1 -> {
lines[t0Idx] lines[t0Idx]
} }
u0Idx != -1 -> { u0Idx != -1 -> {
lines[u0Idx] lines[u0Idx]
} }
else -> "" else -> ""
} }
val afterU0T0 = fullLine.substringAfter("0:") val afterU0T0 = fullLine.substringAfter("0:")
val blankPrefixRegex = Regex("""z([0-9A-Z])[:]""") val blankPrefixRegex =Regex("""z([0-9A-Z])[:]""")
val match = blankPrefixRegex.find(afterU0T0) val match = blankPrefixRegex.find(afterU0T0)
val blankPrefix = match?.groups?.get(1)?.value ?: "" val blankPrefix = match?.groups?.get(1)?.value ?: ""
val editState = TUOEditState( val editState = TUOEditState(
tuoIndex = oneTUO.firstTuoIndex, tuoIndex = oneTUO.firstTuoIndex,
notesByVoice = (0..3).associate { i -> notesByVoice = (0..3).associate { i ->
val rawNote = val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
val fixedNote = autoFixNote(rawNote, template) val fixedNote = autoFixNote(rawNote, template)
i to fixedNote i to fixedNote
}, },
@ -1074,8 +990,7 @@ private fun MeasureRowItem(
}.toMutableMap(), }.toMutableMap(),
templateFragment = oneTUO.pTemplate.template, templateFragment = oneTUO.pTemplate.template,
marker = listOfNotNull( marker = listOfNotNull(
oneTUO.pTemplate.markerToString() oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
.takeIf { it.isNotBlank() },
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() } oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
).joinToString(" "), ).joinToString(" "),
silentDuration = blankPrefix, silentDuration = blankPrefix,
@ -1093,26 +1008,26 @@ private fun MeasureRowItem(
isEditable = canEdit, isEditable = canEdit,
canAdd = canAdd, canAdd = canAdd,
onDismiss = { onDismiss = {
showAddDialog1 = false showAddDialog = false
showDetailDialog1 = false showDetailDialog = false
showEditDialog1 = false showEditDialog = false
}, },
onSave = { newState -> onSave = { newState ->
sharedScreenModel.openTUOEditor(newState) sharedScreenModel.openTUOEditor(newState)
showAddDialog1 = false showAddDialog = false
showEditDialog1 = false showEditDialog = false
}, },
onIndexChanged = { newIndex -> onIndexChanged = { newIndex ->
selectedIndex1 = newIndex selectedIndex = newIndex
val globalList = sharedScreenModel.tuoList.value val globalList = sharedScreenModel.tuoList.value
val nextTUO = globalList.getOrNull(newIndex) val nextTUO = globalList.getOrNull(newIndex)
if (nextTUO != null) { if (nextTUO != null) {
selectedTUO1 = nextTUO selectedTUO = nextTUO
} else { }else {
showAddDialog1 = false showAddDialog = false
showDetailDialog1 = false showDetailDialog = false
showEditDialog1 = false showEditDialog = false
} }
} }
) )
@ -1164,12 +1079,7 @@ private fun MeasureRowItem(
val isTooLong = textWidthDp > containerWidthDp val isTooLong = textWidthDp > containerWidthDp
val spacer = makeSpaceBetweenSyllables(textMeasurer, columnWidthDp) val spacer = makeSpaceBetweenSyllables(textMeasurer, columnWidthDp)
val (dynamicSpaceSyl, alignmentText) = spacer( val (dynamicSpaceSyl, alignmentText) = spacer(syl, cleanAllTemps, syls_i, index)
syl,
cleanAllTemps,
syls_i,
index
)
Text( Text(
text = dynamicSpaceSyl, text = dynamicSpaceSyl,
modifier = Modifier modifier = Modifier
@ -1198,6 +1108,12 @@ private fun MeasureRowItem(
} }
} }
} }
}
}
}
}
}
}
} }
@Composable @Composable