From 7ea9d08cb3a73f54a902ab28fba43dc4546112d7 Mon Sep 17 00:00:00 2001 From: hasina Date: Mon, 2 Feb 2026 15:36:11 +0300 Subject: [PATCH] Move all markers in the new Row separated like lyrics to resolve 'ffpm-657-1 4/4 Miadana kely' & ffpm-211 (markers) --- .../mg/dot/feufaro/solfa/TimeUnitObject.kt | 138 +++++++++++++++--- 1 file changed, 119 insertions(+), 19 deletions(-) diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt index 80c0436..3b94489 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt @@ -3,9 +3,6 @@ package mg.dot.feufaro.solfa import androidx.compose.foundation.background import androidx.compose.runtime.Composable import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyGridState -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.ui.Modifier import androidx.compose.material3.Text import androidx.compose.material3.LocalTextStyle @@ -46,7 +43,7 @@ import SharedScreenModel import androidx.compose.runtime.collectAsState import androidx.compose.ui.Alignment import androidx.compose.ui.text.TextMeasurer -import kotlinx.coroutines.delay +import androidx.compose.ui.text.style.TextAlign val FEUFAROO_TRIOLET_COLOR = Color.DarkGray val FEUFAROO_KEY_CHANGE_COLOR = Color.Blue @@ -270,7 +267,7 @@ fun TimeUnitComposable( val hairPinSymbol = tuo.hasHairPin() val yHeight = with(density) { lineHeightDp.toPx()} - if (tuo.isTriolet()) { + /*if (tuo.isTriolet()) { Canvas(modifier = Modifier.fillMaxSize()) { val arcWidth = with(density) { size.width * 0.75f} drawArc( @@ -324,8 +321,8 @@ fun TimeUnitComposable( } if (text.contains("p")) { fontWeight = FontWeight.Bold - } - AutoResizingText( + }*/ + /*AutoResizingText( text = text, minFontSize = 18.sp, maxFontSize = 18.sp, @@ -333,7 +330,7 @@ fun TimeUnitComposable( fontStyle = fontStyle, fontWeight = fontWeight, modifier = Modifier.fillMaxWidth() - .height(lineHeightDp)) + .height(lineHeightDp))*/ } @@ -587,6 +584,99 @@ fun LazyVerticalGridTUO( ){ measures.forEachIndexed { measureIndex, measureTUOs -> Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) { + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.Center, + verticalAlignment = Alignment.CenterVertically + ) { + measureTUOs.forEachIndexed { indexInMeasure, tuo -> + Column( + modifier = Modifier + .weight(1f) + ) { + if (TimeUnitObject._hasMarker) { + val lineHeight = 20.sp + val density = LocalDensity.current + val lineHeightDp : Dp = with(density) { + lineHeight.toDp() + } + var fontStyle = FontStyle.Normal + var fontWeight = FontWeight.Normal + val hairPinSymbol = tuo.hasHairPin() + val yHeight = with(density) { lineHeightDp.toPx()} + + if (tuo.isTriolet()) { + Canvas(modifier = Modifier.fillMaxSize()) { + val arcWidth = with(density) { size.width * 0.75f} + drawArc( + color = FEUFAROO_TRIOLET_COLOR, + startAngle = 200f, + sweepAngle = 140f, + useCenter = false, + topLeft = Offset(0f, yHeight / 2), + size = Size(arcWidth, yHeight), + style = Stroke(width = 2f) + + ) + } + } + if ((hairPinSymbol == '=') && (TimeUnitObject.lastHairPinSymbol != null)) { + println("LastHairpin: ${TimeUnitObject.lastHairPinSymbol} ${TimeUnitObject.lastHairPinStart}") + val hairPinStart = TimeUnitObject.lastHairPinStart + val lastHairPinSymbol = TimeUnitObject.lastHairPinSymbol + val hairPinStartLine: Int = (hairPinStart - 1) / gridColumnCount + val hairPinEndLine: Int = (tuo.numBlock - 1) / gridColumnCount + if (hairPinStartLine == hairPinEndLine) { + Canvas( + modifier = Modifier.fillMaxSize() + ) { + val xStart = if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width/2 + val xEnd = if (lastHairPinSymbol == '>') size.width/2 else -size.width * (tuo.numBlock - hairPinStart) + drawLine( + Color.DarkGray, + start = Offset(x=xStart, y=0f), + end = Offset(xEnd, yHeight/2) + ) + drawLine( + Color.DarkGray, + start = Offset(xStart, yHeight), + end = Offset(xEnd, yHeight/2) + ) + } + TimeUnitObject.endHairPin() + } + + } + if (hairPinSymbol != null && hairPinSymbol != '=') { + TimeUnitObject.startHairPin(hairPinSymbol, tuo.numBlock) + } + // @todo pTemplate.markerToString retourne les marqueurs comme une seule chaîne + // problème si template = $QD:,-$QD + tuo.pTemplate.resetCalledMarker() + val text = tuo.pTemplate.markerToString() + if (text.contains(Regex("^([mfp]+|[rR]it.*)$"))) { + fontStyle = FontStyle.Italic + } + if (text.contains(Regex("^\\s*(ppp|pp|p|mp|mf|f|ff|fff)\\s*$"))) { + fontWeight = FontWeight.Bold + } + Text(text = text, + modifier = Modifier + .wrapContentSize(unbounded = true, align = Alignment.CenterStart,), + softWrap = false, + maxLines = 1, + fontStyle = fontStyle, + fontWeight = fontWeight, + style = TextStyle( + color = Color.Black, + fontSize = 17.sp + ) + ) + } + } + } + } Row(modifier = Modifier.fillMaxWidth()) { measureTUOs.forEachIndexed { indexInMeasure, oneTUO -> val globalIndex = (measureIndex * gridColumnCount) + indexInMeasure @@ -644,13 +734,13 @@ fun LazyVerticalGridTUO( val isTooLong = textWidthDp > containerWidthDp val spacer = makeSpaceBetweenSyllables(textMeasurer, gridWidthDp / gridColumnCount) - val dynamicSpaceSyl = spacer(syl, allTemps, syls_i, index) + val (dynamicSpaceSyl, alignText) = spacer(syl, allTemps, syls_i, index) Text( text = dynamicSpaceSyl, modifier = Modifier .fillMaxWidth() - .padding(end = 4.dp) - .wrapContentSize(unbounded = true, align = Alignment.Center,), + .padding(end = 4.dp)/*.border(1.dp, Color.Yellow, RectangleShape)*/ + .wrapContentSize(unbounded = true, align = alignText), softWrap = false, maxLines = 1, overflow = TextOverflow.Visible, @@ -683,34 +773,43 @@ fun makeSpaceBetweenSyllables( textMeasurer: TextMeasurer, noteWidthDp: Dp, fontSize: TextUnit = 16.sp -): (String, List>, Int, Int) -> String { +): (String, List>, Int, Int) -> Pair { val density = LocalDensity.current val noteWidthPx = with(density) { noteWidthDp.toPx() } val style = TextStyle(fontSize = fontSize) val spaceWidthPx = textMeasurer.measure("\u00A0", style).size.width + return { currentSyl, allT, s_i, index -> - if (currentSyl.isEmpty()) "" + var textAlign = Alignment.Center + if (currentSyl.isEmpty()) "" to textAlign else { val currentWidth = textMeasurer.measure(currentSyl, style).size.width val next_syl = allT.getOrNull(s_i + 1)?.getOrNull(index) ?: "" val prev_syl = if (s_i > 0) allT.getOrNull(s_i - 1)?.getOrNull(index) ?: "" else "" val excessPx = currentWidth - noteWidthPx - val neededSpaces = if (excessPx > 0) (excessPx / spaceWidthPx).toInt() + 1 else 0 + val isExcess = (excessPx > 0) + val neededSpaces = if (isExcess) (excessPx / spaceWidthPx).toInt() + 1 else 0 val nextNextSyl = allT.getOrNull(s_i + 2)?.getOrNull(index) ?: "" + // println("801: prev: [$prev_syl]${prev_syl.length}:[${textMeasurer.measure(prev_syl, style).size.width}], current [$currentSyl]:[${textMeasurer.measure(currentSyl, style).size.width}], next [$next_syl]:[${textMeasurer.measure(next_syl, style).size.width}], isExcess=$excessPx & need $neededSpaces \t spwp $spaceWidthPx\n") - when { - excessPx > 0 && next_syl.length < prev_syl.length -> { - // Ici, currentSyl se décale à gauche. + val totalSpacesPossible = (noteWidthPx / spaceWidthPx).toInt() + val paddingNeeded = totalSpacesPossible - (currentSyl.length+4) + val resultText = when { + !isExcess && (paddingNeeded > 0) -> { + textAlign = Alignment.TopStart + currentSyl + "\u00A0".repeat(paddingNeeded) + } + isExcess && next_syl.length < prev_syl.length -> { "\u00A0".repeat(neededSpaces) + currentSyl } - excessPx > 0 && next_syl.length >= prev_syl.length -> { + isExcess && next_syl.length >= prev_syl.length -> { currentSyl + "\u00A0".repeat(neededSpaces) } - next_syl.isNotEmpty() -> { + isExcess && next_syl.isNotEmpty() -> { val nextWidth = textMeasurer.measure(next_syl, style).size.width val nextExcess = nextWidth - noteWidthPx @@ -725,6 +824,7 @@ fun makeSpaceBetweenSyllables( else -> currentSyl } + resultText to textAlign } } } \ No newline at end of file