Optimize & sync with measure(multiple) column count on TUO

This commit is contained in:
Hasinjato 2026-09-16 14:43:52 +03:00
parent b6f370504e
commit 91e9af73cc

View file

@ -445,31 +445,87 @@ data class TUOWidthMeasure(val width: Dp, val isReady: Boolean)
data class HairpinRange(val startBlock: Int, val endBlock: Int, val symbol: Char)
@Composable
fun bestTUOWidth(items: List<TimeUnitObject>): TUOWidthMeasure {
fun bestTUOWidth(
items: List<TimeUnitObject>,
stanzaNumber: Int = 1,
transpositionInterval: Int = 0,
noteStyle: TextStyle = MaterialTheme.typography.bodyLarge,
reducedLyricStyle: TextStyle = MaterialTheme.typography.labelLarge
): TUOWidthMeasure {
val textMeasurer = rememberTextMeasurer()
val density = LocalDensity.current
var maxWidth by remember(items) { mutableStateOf(0.dp) }
var isReady by remember(items) { mutableStateOf(false) }
LaunchedEffect(items) {
var maxWidth by remember(items, noteStyle, transpositionInterval) {
mutableStateOf(0.dp)
}
var isReady by remember(items, noteStyle, transpositionInterval) {
mutableStateOf(false)
}
LaunchedEffect(items, noteStyle, transpositionInterval) {
isReady = false
maxWidth = 0.dp
items.forEach {
val textLayoutResult: TextLayoutResult = textMeasurer.measure(
text = it.noteAsMultiString(),
maxLines = 1
var max = 0.dp
// println("=== [DEBUG TUO] Début mesure de ${items.size} blocs TUO ===")
items.forEach { tuo ->
val rawNotes = tuo.noteAsMultiString()
val transposedNotes = Transpose.transposeText(text = rawNotes, interval = transpositionInterval)
val noteLines = transposedNotes.lines()
var maxNoteWidthPx = 0
noteLines.forEachIndexed { lineIdx, line ->
val annotatedNote = parseNoteToAnnotatedString(line)
val noteResult = textMeasurer.measure(
text = annotatedNote,
style = noteStyle,
maxLines = 1,
softWrap = false
)
val textWidth = with(density) {
textLayoutResult.size.width.toDp()
val widthPx = noteResult.size.width
if (widthPx > maxNoteWidthPx) {
maxNoteWidthPx = widthPx
}
// println("TUO #${tuo.getNum()} | Ligne $lineIdx | Brut: \"$line\" | Annoté: \"${annotatedNote.text}\" -> Largeur: ${widthPx}px")
}
if (textWidth > maxWidth) {
maxWidth = textWidth
val tuoMaxWidthDp = with(density) { maxNoteWidthPx.toDp() }
// println("--> TUO #${tuo.getNum()} | Largeur max du bloc: $tuoMaxWidthDp ou ${maxNoteWidthPx}px")
if (tuoMaxWidthDp > max) {
max = tuoMaxWidthDp
}
}
maxWidth = max
isReady = true
// println("=== [DEBUG TUO] Largeur retenue (maxWidth finale) : $maxWidth ===")
}
return TUOWidthMeasure(maxWidth + 13.dp, isReady)
return TUOWidthMeasure(maxWidth, isReady)
}
fun parseNoteToAnnotatedString(
rawNote: String,
superscriptStyle: SpanStyle = SpanStyle(
fontSize = 10.sp,
baselineShift = BaselineShift.Superscript
)
): AnnotatedString {
return buildAnnotatedString {
val parts = rawNote.split(">")
parts.forEachIndexed { index, text ->
if (index % 2 == 1) {
withStyle(superscriptStyle) {
append(text + " ")
}
} else {
append(text)
}
}
}
}
@Composable
fun AutoResizingText(
text: String,
@ -591,11 +647,20 @@ fun LazyVerticalGridTUO(
focusRequester.requestFocus()
}
}
val numerator = viewModel.measure.substringBefore("/").toIntOrNull() ?: 4
val multiple = when (numerator) {
2, 4, 8, 10 -> 4
3, 6, 9, 12 -> 3
else -> 4
}
val density = LocalDensity.current
val horizontalArrangementSpacing: Dp = 0.dp
val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1"
val columnGroup = columnGroupString.toInt().coerceAtLeast(1)
val tuoWidthMeasure = bestTUOWidth(tuoList)
val tuoWidthMeasure = bestTUOWidth(
items = tuoList,
noteStyle = MaterialTheme.typography.bodyLarge
)
val itemMinBaseWidth = tuoWidthMeasure.width
val gridWidthDp = with(density) { gridWidthPx.toDp() }
@ -604,18 +669,27 @@ fun LazyVerticalGridTUO(
val gridCount by sharedScreenModel.gridCount.collectAsState()
var gridColumnCount: Int = remember(gridWidthDp, itemMinBaseWidth, columnGroup) {
if (gridWidthDp == 0.dp) return@remember columnGroup
var calculatedCols =
(gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt()
if (calculatedCols == 0) calculatedCols = columnGroup
if (calculatedCols % columnGroup != 0) {
calculatedCols = (calculatedCols / columnGroup) * columnGroup
if (calculatedCols == 0) calculatedCols = columnGroup
var gridColumnCount: Int = remember(gridWidthDp, tuoWidthMeasure.isReady, tuoWidthMeasure.width, multiple) {
if (!tuoWidthMeasure.isReady || gridWidthDp <= 0.dp || tuoWidthMeasure.width <= 0.dp) {
return@remember multiple
}
val actualColumnCount: Int = calculatedCols.coerceAtLeast(columnGroup)
actualColumnCount
val rawCapacity = (gridWidthDp + 9.dp) / tuoWidthMeasure.width
val rawColsInt = rawCapacity.toInt()
val roundedToMultiple = (rawColsInt / multiple) * multiple
val finalCols = roundedToMultiple.coerceAtLeast(multiple)
// println("Largeur écran/grille : $gridWidthDp")
// println("Largeur bloc TUO max : ${tuoWidthMeasure.width}")
// println("Signature temps (multiple) : $multiple")
// println("Capacité brute d'accueil : $rawCapacity blocs ($rawColsInt entiers)")
// println("Arrondi au multiple inférieur : $roundedToMultiple colonnes")
// println("Nombre final retenu (min $multiple) : $finalCols colonnes")
// println("=========================")
finalCols
}
gridColumnCount += gridCount
val flowRowSize: Float = 0.98f / gridColumnCount