From 7df3312f840e5694789c6312c5f6bdaf389b7a10 Mon Sep 17 00:00:00 2001 From: dotmg Date: Sun, 13 Jul 2025 05:09:13 +0200 Subject: [PATCH] ScreenTranspose, first draft --- composeApp/build.gradle.kts | 2 + .../files/.fuse_hidden0000206a0000000a | Bin 0 -> 12288 bytes .../composeResources/files/config.json | 8 +++ .../composeResources/files/ffpm-179.txt | 10 +++ .../composeResources/files/ffpm-21.txt | 9 +++ .../composeResources/files/ffpm-297.txt | 13 ++++ .../composeResources/files/ffpm-33.txt | 9 +++ .../composeResources/files/ffpm-428.txt | 10 +++ .../composeResources/files/ffpm-449.txt | 12 ++++ .../composeResources/files/ffpm-489.txt | 10 +++ .../kotlin/mg/dot/feufaro/CommonTools.kt | 33 --------- .../kotlin/mg/dot/feufaro/ScreenSolfa.kt | 5 +- .../kotlin/mg/dot/feufaro/ScreenTranspose.kt | 64 ++++++++++++++++++ .../kotlin/mg/dot/feufaro/di/AppModule.kt | 1 + .../kotlin/mg/dot/feufaro/solfa/Solfa.kt | 28 +------- .../mg/dot/feufaro/solfa/TimeUnitObject.kt | 15 +++- .../kotlin/mg/dot/feufaro/solfa/Transpose.kt | 50 ++++++++++++++ .../feufaro/viewmodel/SharedScreenModel.kt | 16 ++++- gradle/libs.versions.toml | 1 + 19 files changed, 229 insertions(+), 67 deletions(-) create mode 100644 composeApp/src/commonMain/composeResources/files/.fuse_hidden0000206a0000000a create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-179.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-21.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-297.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-33.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-428.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-449.txt create mode 100644 composeApp/src/commonMain/composeResources/files/ffpm-489.txt delete mode 100644 composeApp/src/commonMain/kotlin/mg/dot/feufaro/CommonTools.kt create mode 100644 composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenTranspose.kt diff --git a/composeApp/build.gradle.kts b/composeApp/build.gradle.kts index 5658626..0504e64 100644 --- a/composeApp/build.gradle.kts +++ b/composeApp/build.gradle.kts @@ -55,6 +55,8 @@ kotlin { implementation(libs.koin.compose.viewmodel.navigation) implementation(libs.bundles.voyager) implementation(libs.cafe.voyager.koin) + implementation(libs.androidx.material.icons.extended) + } commonTest.dependencies { implementation(libs.kotlin.test) diff --git a/composeApp/src/commonMain/composeResources/files/.fuse_hidden0000206a0000000a b/composeApp/src/commonMain/composeResources/files/.fuse_hidden0000206a0000000a new file mode 100644 index 0000000000000000000000000000000000000000..2882ddd6cb222f29450213a991164f54a7466e7f GIT binary patch literal 12288 zcmeHNL2n#26rQ$RXel7zisWsO+M=CxcC$q3R6SHGOGCAxO4CY3ks>Fa>AD$@Bil`x zC5T?RafA!v#Dy#3!mS+n10aEb078JojXU4-?6wK2g6Iv!PF_6rdw%bG-+QxB6tBkU77l zJRjtD3SkZ3FnY_l{NmOYcXor8+EhcKs;Oo_KNk5A%o%VYR9sid9*Vxe@ zGH|FFxZ{g-;bbz`>&_AnGpAbY`RA@5YD!}Ak%7oSWFRsS8Hfx-1|kEIfy2gt-#U`K zi=>ZE5seIh84=; z#+|4H9|)$Eup*VB#2N;w5Y?ujgBP``cJF<7v65B^Ehx!%84Dl$+kdT}E5e<4C|m%>aroV?jI0;~3x->UJ=408C4Bo@fY9 zFe83~dm^k!E8|x|kpyW>RH+vgA{04bjKwyXhMx}KOGBHv%I)6!g!8!$yMibqkh`s{ zX`*{!06vvg08pDR5hB!MQ;fj|BalQ{!xupdRo=b#!P0H8Y4c6f5X`>(ti>O02j97= zgaJk1%ozr1*<~t%;Ug+4QoJI{ZDH&4)9Qs%u`(a2^}Ge9R5)f>ex45j!U-n=YD-=i zGHu!kDNJ28B^Zh_*L6U;ObAgb!|bFLXoc7T6x_5Q0BrVAwTe1s+9}G4O`L8`8f>xh z;9EWTiL?xR9k)dJK8>Yqd_T~>x=BEqj->vhHrI-}-0;hWZJP>Yp)`~j&^c;v#BH-p z!2khATA{n%U}%Z${i$eE8jstoXj~jEsJp3e;4CD9)e|*zZ!ceXXJ2EYaUVA2KFvWb zyBa<-|8vi_lBIq&W81PBg)6;GC6n{4EVb>s@mNYoTecnPnDiwE6dnhd44YDiW4YPlL<}&S^#wfH656gvinrZC@81U)zIE7k5&0uipk`4+RjA+;C!osV?W9bT=EcLP( z*LH~M+_h2yBm#LWy(>#!0+eR~DdMj{ZKaif$s}oD%V-zoaE7BuL8jg_mn?NN2fsiP z+#)8Dnkn0EP@Z-gEZzpm>u{odJex9ffXOs{vguII5}y~$v-*XzxPuSQ4DK|h(uGMLp1$#6E?*~nho z(OHl8cWidGGu-jnU~qNFaP@u9`#$Z?9g!^yd>qr|{fd53b = mapOf( - "C" to 1, - "C#" to 2, "Db" to 2, - "D" to 3, - "D#" to 4, "Eb" to 4, - "E" to 5, - "F" to 6, - "F#" to 7, "Gb" to 7, - "G" to 8, - "G#" to 9, "Ab" to 9, - "A" to 10, - "A#" to 11, "Bb" to 11, - "B" to 12 - ) - if (result.containsKey(tonality)) { - return result[tonality]!! - } - return -1 - } - fun numberToTonality(number: Int): String { - val result: Array = arrayOf("", "C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B") - return if (number in 1..12) { - result[number] - } else { - "" - } - } - } diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenSolfa.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenSolfa.kt index 7c65916..f9e64b4 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenSolfa.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenSolfa.kt @@ -111,6 +111,7 @@ object ScreenSolfa : Screen { ) Text(text = measureString) Text(text = "Stanza: $stanza") + ScreenTranspose.Content() } LazyVerticalGridTUO( gridTUOData, @@ -123,8 +124,8 @@ object ScreenSolfa : Screen { solfaScreenModel.loadNextInPlaylist() }, modifier = Modifier.height(40.dp)) { - val debugData: String by sharedScreenModel.data.collectAsState() - Text(debugData) + val nextLabel: String by sharedScreenModel.nextLabel.collectAsState() + Text(nextLabel) } FlowRow( modifier = Modifier.fillMaxWidth() diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenTranspose.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenTranspose.kt new file mode 100644 index 0000000..05fc2d9 --- /dev/null +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/ScreenTranspose.kt @@ -0,0 +1,64 @@ +package mg.dot.feufaro + +import SharedScreenModel +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.WindowInsets +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.safeDrawing +import androidx.compose.foundation.layout.windowInsetsPadding +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import java.io.ObjectStreamException +import androidx.compose.foundation.layout.FlowRow +import androidx.compose.foundation.layout.fillMaxHeight +import androidx.compose.material3.Text +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import cafe.adriel.voyager.koin.koinScreenModel +import mg.dot.feufaro.solfa.Transpose +import androidx.compose.ui.Alignment +import mg.dot.feufaro.solfa.TimeUnitObject + + +object ScreenTranspose : Screen { + @Composable + override fun Content() { + FlowRow( + modifier = Modifier.fillMaxWidth() + .windowInsetsPadding(WindowInsets.safeDrawing) + .padding(start = 8.dp, end = 8.dp, top = 8.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + verticalArrangement = Arrangement.spacedBy(4.dp) + ) { + val sharedScreenModel = koinScreenModel() + val originalKey by sharedScreenModel.songKey.collectAsState() + val transposeTo by sharedScreenModel.transposeTo.collectAsState() + val transposeAsIf by sharedScreenModel.transposeAsIf.collectAsState() + Box(modifier = Modifier.fillMaxHeight().align(Alignment.CenterVertically)) { + Text("Original Key: $originalKey") + } + Box(modifier = Modifier.fillMaxHeight().align(Alignment.CenterVertically)) { + Text("Transpose to key: $transposeTo") + } + Transpose.chooseKey { it -> + sharedScreenModel.setTransposeTo(it) + TimeUnitObject.changeTransposeTo(it) + } + Box(modifier = Modifier.fillMaxHeight().align(Alignment.CenterVertically)) { + Text("Transpose as if key was : $transposeAsIf") + } + Transpose.chooseKey { it -> + sharedScreenModel.setTransposeAsIf(it) + TimeUnitObject.changeTransposeAsIf(it) + } + } + } + @Throws(ObjectStreamException::class) // C'est une méthode de sérialisation Java, donc l'exception est nécessaire + private fun readResolve(): Any { + return this // Toujours retourner l'instance unique de ce singleton + } +} \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppModule.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppModule.kt index e7b4e81..648689b 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppModule.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/di/AppModule.kt @@ -6,6 +6,7 @@ import mg.dot.feufaro.FileRepository import mg.dot.feufaro.DisplayConfigManager // Importez DisplayConfigManager import mg.dot.feufaro.musicXML.MusicXML import mg.dot.feufaro.solfa.Solfa +import mg.dot.feufaro.solfa.TimeUnitObject import mg.dot.feufaro.viewmodel.SolfaScreenModel import org.koin.dsl.module import org.koin.core.module.dsl.singleOf diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt index 40f3300..5ce768f 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Solfa.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import mg.dot.feufaro.FileRepository -import mg.dot.feufaro.CommonTools class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository: FileRepository) { private val T: MutableList = mutableListOf() @@ -388,32 +387,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository val tonality = line.uppercaseFirstMeta() meta["C"] = tonality sharedScreenModel.setSongKey(tonality) - val keyOrigin = CommonTools.tonalityToNumber(tonality) - val transposeTo = getOpt("transposeto") - val transposeAsIf = getOpt("transposeasif") - val keyDest = if (transposeTo != "") { - CommonTools.tonalityToNumber(transposeTo) - } else { - keyOrigin - } - val keyAsIf = if (transposeAsIf != "") { - if (transposeAsIf.toIntOrNull() != null) { - keyOrigin + transposeAsIf.toInt() - } else { - CommonTools.tonalityToNumber(transposeAsIf) - } - } else { - keyOrigin - } - if (!meta.containsKey("transposeValue")) { - meta["transposeValue"] = (keyDest - keyAsIf).toString() - } - if (keyAsIf != keyOrigin) { - meta["C"] = CommonTools.numberToTonality(keyAsIf) - } - if (keyDest != keyOrigin) { - meta["C"] += " (" + CommonTools.numberToTonality(keyDest) + ")" - } + sharedScreenModel.setTransposeAsIf(tonality) } } 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 d35c127..78a766e 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/TimeUnitObject.kt @@ -42,6 +42,7 @@ import androidx.compose.ui.text.style.BaselineShift import androidx.compose.ui.text.withStyle val FEUFAROO_TRIOLET_COLOR = Color.DarkGray +val FEUFAROO_KEY_CHANGE_COLOR = Color.Blue class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { var mutableNoteVersion: Int by mutableStateOf(0) private var lyrics: MutableList = mutableListOf() @@ -71,6 +72,14 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { lastHairPinStart = -1 lastHairPinSymbol = null } + var transposeAsIf: String = "" + var transposeTo: String = "" + fun changeTransposeAsIf(asIf: String) { + transposeAsIf = asIf + } + fun changeTransposeTo(to: String) { + transposeTo = to + } } init { nbBlock++ @@ -164,7 +173,9 @@ class TimeUnitObject (val pTemplate: PTemplate, val prevTUO: TimeUnitObject?) { } else { transposeOldKey = prevTUO?.transposeOldKey ?: "Bb" "" } - + if (pTemplate.template == "z") { + return "$separatorBefore\n$separatorBefore\n$separatorBefore\n$separatorBefore" + } val retour = tuNotes.drop(1).joinToString (separator = "\n"){ separatorBefore + markersBefore + it.toString(transposeFrom, transposeTo).replace(Regex("[\\(\\)\\[\\]]"), "") } @@ -365,7 +376,7 @@ fun TimeUnitComposable( fontSize = 10.sp, baselineShift = BaselineShift.Superscript, //fontStyle = FontStyle.Italic, - color = Color.Blue + color = FEUFAROO_KEY_CHANGE_COLOR )) { append(text+" ") } diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Transpose.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Transpose.kt index 4c6b9b2..97ae384 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Transpose.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/solfa/Transpose.kt @@ -1,5 +1,23 @@ package mg.dot.feufaro.solfa +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.padding +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.runtime.mutableStateOf +import androidx.compose.material3.ExperimentalMaterial3Api // Nécessaire pour ExposedDropdownMenuBox +import androidx.compose.material3.Icon +import androidx.compose.material3.Text +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowDropDown +import androidx.compose.material3.DropdownMenu +import androidx.compose.runtime.getValue +import androidx.compose.runtime.setValue +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.IconButton +import androidx.compose.ui.unit.dp + class Transpose { companion object { val noteToNumber = listOf("d", "di", "r", "ri", "m", "f", "fi", "s", "si", "l", "ta", "t") @@ -38,5 +56,37 @@ class Transpose { .replace(",", "₁") .replace("'", "¹") + regexFound.groupValues[3] } + @OptIn(ExperimentalMaterial3Api::class) // Ajoutez cette annotation pour utiliser ExposedDropdownMenuBox + @Composable + fun chooseKey( + modifier: Modifier = Modifier, + label: String = "Choose a key", + menuItemData: List = keyToNumber, + onOptionSelected: (String) -> Unit + ) { + var expanded by remember { mutableStateOf(false) } + Box( + modifier = modifier + .padding(0.dp) + ) { + IconButton(onClick = {expanded = !expanded}) { + Icon(Icons.Default.ArrowDropDown, contentDescription = label) + } + DropdownMenu( + expanded = expanded, + onDismissRequest = { expanded = false} + ) { + menuItemData.forEach { option -> + DropdownMenuItem( + text = { Text(option)}, + onClick = { + onOptionSelected(option) + expanded = false + } + ) + } + } + } + } } } \ No newline at end of file diff --git a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt index 2b6daf2..ed19862 100644 --- a/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt +++ b/composeApp/src/commonMain/kotlin/mg/dot/feufaro/viewmodel/SharedScreenModel.kt @@ -6,8 +6,8 @@ import kotlinx.coroutines.flow.asStateFlow import mg.dot.feufaro.solfa.TimeUnitObject class SharedScreenModel() : ScreenModel { - private val _data = MutableStateFlow("Next ...") - val data: StateFlow = _data.asStateFlow() + private val _nextLabel = MutableStateFlow("Next ...") + val nextLabel: StateFlow = _nextLabel.asStateFlow() private val _measure = MutableStateFlow("") val measure: StateFlow = _measure.asStateFlow() private val _songTitle = MutableStateFlow("") @@ -16,6 +16,10 @@ class SharedScreenModel() : ScreenModel { val stanza: StateFlow = _stanza.asStateFlow() private val _songKey = MutableStateFlow("") val songKey: StateFlow = _songKey.asStateFlow() + private val _transposeTo = MutableStateFlow("") + val transposeTo: StateFlow = _transposeTo.asStateFlow() + private val _transposeAsIf = MutableStateFlow("") + val transposeAsIf: StateFlow = _transposeAsIf.asStateFlow() private val _songAuthor = MutableStateFlow("") val songAuthor: StateFlow = _songAuthor.asStateFlow() private val _songComposer = MutableStateFlow("") @@ -37,7 +41,7 @@ class SharedScreenModel() : ScreenModel { val hasMarker: StateFlow = _hasMarker.asStateFlow() fun appendData(otherData: String) { - _data.value += otherData + _nextLabel.value += otherData } fun reset() { tempTimeUnitObjectList.clear() @@ -67,6 +71,12 @@ class SharedScreenModel() : ScreenModel { fun setSongKey(theSongKey: String) { _songKey.value = theSongKey } + fun setTransposeTo(key: String) { + _transposeTo.value = key + } + fun setTransposeAsIf(key: String) { + _transposeAsIf.value = key + } fun setSongAuthor(theSongAuthor: String) { _songAuthor.value = theSongAuthor } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 9cbd080..03175eb 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -24,6 +24,7 @@ material3 = "1.3.2" voyager = "1.1.0-beta03" [libraries] +androidx-material-icons-extended = { module = "androidx.compose.material:material-icons-extended" } cafe-voyager-koin = { module = "cafe.adriel.voyager:voyager-koin" } koin-compose-viewmodel = { module = "io.insert-koin:koin-compose-viewmodel", version.ref = "koin" } koin-compose-viewmodel-navigation = { module = "io.insert-koin:koin-compose-viewmodel-navigation", version.ref = "koin" }