Can Add Marker on editing partition TUODetailDialog '+' botton & reconstruct Template
This commit is contained in:
parent
bf797762ea
commit
80ef86527b
7 changed files with 579 additions and 113 deletions
|
|
@ -319,10 +319,15 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val t0Idx = lines.indexOfFirst { it.startsWith("T0:") }
|
val t0Idx = lines.indexOfFirst { it.startsWith("T0:") }
|
||||||
val u0Idx = lines.indexOfFirst { it.startsWith("U0:") }
|
val u0Idx = lines.indexOfFirst { it.startsWith("U0:") }
|
||||||
|
|
||||||
val noteS = lines[lines.indexOfFirst { it.startsWith("N1") }]
|
val idxS = lines.indexOfFirst { it.startsWith("N1") }
|
||||||
val noteA = lines[lines.indexOfFirst { it.startsWith("N2") }]
|
val idxA = lines.indexOfFirst { it.startsWith("N2") }
|
||||||
val noteT = lines[lines.indexOfFirst { it.startsWith("N3") }]
|
val idxT = lines.indexOfFirst { it.startsWith("N3") }
|
||||||
val noteB = lines[lines.indexOfFirst { it.startsWith("N4") }]
|
val idxB = lines.indexOfFirst { it.startsWith("N4") }
|
||||||
|
|
||||||
|
val noteS = if (idxS != -1) lines[idxS] else ""
|
||||||
|
val noteA = if (idxA != -1) lines[idxA] else ""
|
||||||
|
val noteT = if (idxT != -1) lines[idxT] else ""
|
||||||
|
val noteB = if (idxB != -1) lines[idxB] else ""
|
||||||
|
|
||||||
val currentStanza = sharedScreenModel.stanza.value
|
val currentStanza = sharedScreenModel.stanza.value
|
||||||
|
|
||||||
|
|
@ -331,7 +336,6 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
|
|
||||||
val lyrics = lines[lyrIdx]
|
val lyrics = lines[lyrIdx]
|
||||||
println("Parole sur $currentStanza: $lyrics")
|
|
||||||
|
|
||||||
val content = smartYLyrics(lyrics).substringAfter(":")
|
val content = smartYLyrics(lyrics).substringAfter(":")
|
||||||
|
|
||||||
|
|
@ -370,33 +374,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
|
|
||||||
when {
|
when {
|
||||||
t0Idx != -1 -> {
|
t0Idx != -1 -> {
|
||||||
val line = lines[t0Idx]
|
|
||||||
val prefix = line.substringBefore('{') + "{"
|
|
||||||
val suffix = "}"
|
|
||||||
val body = line.substringAfter('{').substringBeforeLast('}')
|
|
||||||
|
|
||||||
val regex = Regex("([^:|/!]*[:|/!])|([^:|/!]+)")
|
|
||||||
val fragments = regex.findAll(body).map { it.value }.toMutableList()
|
|
||||||
// println("Nombre de blocs détectés : ${fragments.size}")
|
|
||||||
|
|
||||||
val markerRegex = Regex("""\$\{.*?\}|\$.""")
|
|
||||||
|
|
||||||
if (targetIdx in fragments.indices) {
|
|
||||||
val oldFrag = fragments[targetIdx]
|
|
||||||
|
|
||||||
val delimiter = if (oldFrag.isNotEmpty() && oldFrag.last() in ":|/!") {
|
|
||||||
oldFrag.last().toString()
|
|
||||||
} else ""
|
|
||||||
|
|
||||||
val cleanBody = fragments.joinToString("") { it.replace(markerRegex, "") }
|
|
||||||
lines[t0Idx] = prefix + cleanBody + suffix
|
|
||||||
|
|
||||||
println("AVANT: $line")
|
|
||||||
println("APRÈS: ${lines[t0Idx]}")
|
|
||||||
} else {
|
|
||||||
println("Index $targetIdx hors limites pour T0 (taille=${fragments.size})")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
u0Idx != -1 -> {
|
u0Idx != -1 -> {
|
||||||
|
|
@ -405,7 +383,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
// println("fullLine = '$fullLine'")
|
// println("fullLine = '$fullLine'")
|
||||||
|
|
||||||
val afterU0 = fullLine.substringAfter("U0:")
|
val afterU0 = fullLine.substringAfter("U0:")
|
||||||
val blankPrefixRegex = Regex("^(z[048CEKO]:)")
|
val blankPrefixRegex = Regex("^(.*?z[0-9A-Z]:)")
|
||||||
val match = blankPrefixRegex.find(afterU0)
|
val match = blankPrefixRegex.find(afterU0)
|
||||||
val blankPrefix = match?.value ?: ""
|
val blankPrefix = match?.value ?: ""
|
||||||
val body = if (match != null) {
|
val body = if (match != null) {
|
||||||
|
|
@ -420,7 +398,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val symboles = parser.parsed()
|
val symboles = parser.parsed()
|
||||||
|
|
||||||
val newLigneT = "U0:"+blankPrefix+symboles
|
val newLigneT = "U0:"+blankPrefix+symboles
|
||||||
println("Ligne de U0 ==> $newLigneT")
|
// println("Ligne de U0 ==> $newLigneT")
|
||||||
lines[u0Idx] = newLigneT
|
lines[u0Idx] = newLigneT
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -438,20 +416,39 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
val markerClean = editState.marker
|
||||||
|
val modulaRegex = Regex("""^\s*D(ô|o)?\s*dia\s*(C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B)\s*$""", RegexOption.IGNORE_CASE)
|
||||||
|
val match = modulaRegex.find(markerClean)
|
||||||
|
|
||||||
|
val newMarker = if (match != null) {
|
||||||
|
val lettre = match.groupValues[2]
|
||||||
|
"\${c:$lettre}"
|
||||||
|
} else {
|
||||||
|
markerClean.split(Regex("\\s+")).filter { it.isNotEmpty() }.joinToString(" ") { part ->
|
||||||
|
when (part) {
|
||||||
|
"𝄐" -> "\$Q"
|
||||||
|
else -> "\${$part}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* MODIF TEMPLATE */
|
||||||
|
val markerUpdated = updateMarkerSource(if(u0Idx != -1) lines[u0Idx] else lines[t0Idx], targetIdx, newMarker)
|
||||||
|
|
||||||
|
/* MODIF SOURCE Note&Lyrics */
|
||||||
|
val updatedSource = updateSourceLines(lines, templatArray, targetIdx, editState)
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
MODIF NOTES N1 N2 N3 N4
|
val templateUpd = reconstructIt(markerUpdated, measureString[0].digitToInt())
|
||||||
*/
|
|
||||||
// println("taille tA: ${templatArray.size} et le trgt $targetIdx")
|
println("Re-formater:: $templateUpd")
|
||||||
val updatedNotes = updateSourceLines(lines, templatArray, targetIdx, editState)
|
|
||||||
|
|
||||||
// RESTAURATION DES TEMPLATES
|
// RESTAURATION DES TEMPLATES
|
||||||
if (templateString != "") {
|
if (templateString != "") {
|
||||||
updatedNotes[templateIndices] = templateString
|
updatedSource[templateIndices] = templateUpd
|
||||||
}
|
}
|
||||||
|
|
||||||
val finalString = updatedNotes.joinToString("\n")
|
val finalString = updatedSource.joinToString("\n")
|
||||||
|
|
||||||
val tempDir = System.getProperty("java.io.tmpdir")
|
val tempDir = System.getProperty("java.io.tmpdir")
|
||||||
val fileName = filePath.substringAfterLast('/')
|
val fileName = filePath.substringAfterLast('/')
|
||||||
|
|
@ -481,27 +478,61 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val result = StringBuilder()
|
val result = StringBuilder()
|
||||||
val lastSlash = filePath.lastIndexOf('/')
|
val lastSlash = filePath.lastIndexOf('/')
|
||||||
val directory = if (lastSlash != -1) filePath.substring(0, lastSlash + 1) else ""
|
val directory = if (lastSlash != -1) filePath.substring(0, lastSlash + 1) else ""
|
||||||
val myLines = fileRepository.readFileLines(filePath)
|
// Si inclusion multiples
|
||||||
|
val myLines = try {
|
||||||
|
fileRepository.readFileLines(filePath)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return "// Erreur lecture: $filePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
val inclusionRegex = Regex("""I\d+:[^ \n\r]+""")
|
||||||
|
|
||||||
myLines.forEach { line ->
|
myLines.forEach { line ->
|
||||||
if (line.startsWith("I0:")) {
|
var lastIndex = 0
|
||||||
|
val matches = inclusionRegex.findAll(line).toList()
|
||||||
|
|
||||||
|
if (matches.isNotEmpty()) {
|
||||||
|
val lineBuilder = StringBuilder()
|
||||||
|
for (match in matches) {
|
||||||
|
lineBuilder.append(line.substring(lastIndex, match.range.first))
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val parts = line.substring(3).split(":")
|
val fullTag = match.value
|
||||||
val fileName = parts[0]
|
val parts = fullTag.split(":", limit = 3)
|
||||||
val ignorePattern = if (parts.size > 1) parts[1] else ""
|
|
||||||
|
|
||||||
|
if (parts.size >= 2) {
|
||||||
|
val fileName = parts[1]
|
||||||
val fullPath = directory + fileName
|
val fullPath = directory + fileName
|
||||||
val includedLines = fileRepository.readFileLines(fullPath)
|
val rawIncludedContent = fileRepository.readFileLines(fullPath)
|
||||||
|
|
||||||
val regexIgnore = if (ignorePattern.isNotEmpty()) Regex(ignorePattern) else null
|
if (parts.size > 2 && parts[2].startsWith("^")) {
|
||||||
|
val patternInside = parts[2]
|
||||||
|
.substringAfter("(", "")
|
||||||
|
.substringBefore(")", "")
|
||||||
|
|
||||||
includedLines.forEach { incLine ->
|
val prefixesToIgnore = if (patternInside.isNotEmpty()) {
|
||||||
if (regexIgnore == null || !regexIgnore.containsMatchIn(incLine)) {
|
patternInside.split("|")
|
||||||
result.append(incLine).append("\n")
|
} else {
|
||||||
|
listOf(parts[2].substring(1))
|
||||||
|
}
|
||||||
|
|
||||||
|
val filteredLines = rawIncludedContent.filter { incLine ->
|
||||||
|
prefixesToIgnore.none { prefix ->
|
||||||
|
incLine.trim().startsWith(prefix)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineBuilder.append(filteredLines.joinToString("\n"))
|
||||||
|
} else {
|
||||||
|
lineBuilder.append(rawIncludedContent.joinToString("\n"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
result.append("// Erreur inclusion: ${e.message}\n")
|
lineBuilder.append("// Erreur: ${e.message}")
|
||||||
}
|
}
|
||||||
|
lastIndex = match.range.last + 1
|
||||||
|
}
|
||||||
|
lineBuilder.append(line.substring(lastIndex))
|
||||||
|
result.append(lineBuilder.toString()).append("\n")
|
||||||
} else {
|
} else {
|
||||||
result.append(line).append("\n")
|
result.append(line).append("\n")
|
||||||
}
|
}
|
||||||
|
|
@ -544,8 +575,8 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val lyricsContent = if(lineYIdx != -1) smartYLyrics(lyricsBody) else smartELyrics(lyricsBody)
|
val lyricsContent = if(lineYIdx != -1) smartYLyrics(lyricsBody) else smartELyrics(lyricsBody)
|
||||||
|
|
||||||
// Découpage strict pour correspondre au template
|
// Découpage strict pour correspondre au template
|
||||||
println("Lyrics BODY $lyricsBody")
|
// println("Lyrics BODY $lyricsBody")
|
||||||
println("LyricsC $lyricsContent")
|
// println("LyricsC $lyricsContent")
|
||||||
|
|
||||||
val lyricsInLines = sharedScreenModel.synchronizedSyllables.value
|
val lyricsInLines = sharedScreenModel.synchronizedSyllables.value
|
||||||
lyricsInLines.mapIndexed { index, string ->
|
lyricsInLines.mapIndexed { index, string ->
|
||||||
|
|
@ -575,7 +606,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
// marker))
|
// marker))
|
||||||
}
|
}
|
||||||
|
|
||||||
println("\nAction finale : Remplacer l'index $targetIdx (valeur: ${allTokens.getOrNull(targetIdx)})")
|
// println("\nAction finale : Remplacer l'index $targetIdx (valeur: ${allTokens.getOrNull(targetIdx)})")
|
||||||
|
|
||||||
if (targetIdx < allTokens.size) {
|
if (targetIdx < allTokens.size) {
|
||||||
allTokens[targetIdx] = newSyllable
|
allTokens[targetIdx] = newSyllable
|
||||||
|
|
@ -682,7 +713,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
val isStructural = token.contains("#") || token == "/" || token == "(" || token == ")"
|
val isStructural = token.contains("#") || token == "/" || token == "(" || token == ")"
|
||||||
|
|
||||||
if (isStructural) {
|
if (isStructural) {
|
||||||
println(String.format("%-5d | %-10s | %-8s | %-12s | %-10s", i, token, "STRUCT", "-", "Keep"))
|
// println(String.format("%-5d | %-10s | %-8s | %-12s | %-10s", i, token, "STRUCT", "-", "Keep"))
|
||||||
resultTokens.add(token)
|
resultTokens.add(token)
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
|
|
@ -731,7 +762,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
resultTokens.add(processedToken)
|
resultTokens.add(processedToken)
|
||||||
|
|
||||||
if (processedToken.matches(Regex("[drmfsltDRFSTzw].*|[-―]"))) {
|
if (processedToken.matches(Regex("[drmfsltDRFSTzw].*|[-―]"))) {
|
||||||
println(String.format("NEW | %-10s | INSERT | %-12d | REPLACE", processedToken, currentLogicalIdx))
|
// println(String.format("NEW | %-10s | INSERT | %-12d | REPLACE", processedToken, currentLogicalIdx))
|
||||||
currentLogicalIdx++
|
currentLogicalIdx++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -772,6 +803,160 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateMarkerSource(
|
||||||
|
templateLine: String,
|
||||||
|
targetPointer: Int,
|
||||||
|
newMarkerValue: String
|
||||||
|
): String {
|
||||||
|
val isT0 = templateLine.startsWith("T0")
|
||||||
|
|
||||||
|
val prefix: String
|
||||||
|
val body: String
|
||||||
|
val suffix = if (isT0) "}" else ""
|
||||||
|
|
||||||
|
if (isT0) {
|
||||||
|
prefix = "T0:{"
|
||||||
|
body = templateLine.substringAfter("{").substringBeforeLast("}")
|
||||||
|
} else {
|
||||||
|
val match = Regex("^(.*?z\\d|.*?z.):").find(templateLine)
|
||||||
|
if (match != null) {
|
||||||
|
prefix = match.value
|
||||||
|
body = templateLine.substring(match.value.length)
|
||||||
|
} else {
|
||||||
|
prefix = templateLine.substringBefore(":") + ":"
|
||||||
|
body = templateLine.substringAfter(":")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// println("\n" + "=".repeat(100))
|
||||||
|
// println("DEBUG COMPACTAGE & MARKERS - préfixe $prefix")
|
||||||
|
// println("Cible Idx: $targetPointer | Nouveau Marqueur: \"$newMarkerValue\"")
|
||||||
|
// println("-".repeat(100))
|
||||||
|
// println(String.format("%-4s | %-25s | %-15s | %-25s", "Idx", "Bloc Étendu (Input)", "Action", "Bloc Compacté (Output)"))
|
||||||
|
// println("-".repeat(100))
|
||||||
|
|
||||||
|
val resultBody = StringBuilder()
|
||||||
|
var currentLogicalIdx = 0
|
||||||
|
var i = 0
|
||||||
|
var currentBlock = StringBuilder()
|
||||||
|
val separators = listOf(':', '|', '!', '/')
|
||||||
|
|
||||||
|
while (i <= body.length) {
|
||||||
|
if (i < body.length && body[i] == '$' && i + 1 < body.length && body[i + 1] == '{') {
|
||||||
|
val endPos = body.indexOf('}', i)
|
||||||
|
if (endPos != -1) {
|
||||||
|
currentBlock.append(body.substring(i, endPos + 1))
|
||||||
|
i = endPos + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == body.length || body[i] in separators) {
|
||||||
|
if (isT0 && currentBlock.toString().trim().isEmpty()) {
|
||||||
|
if (i < body.length) resultBody.append(body[i])
|
||||||
|
currentBlock.clear()
|
||||||
|
i++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (i == body.length && currentBlock.toString().trim().isEmpty()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var rawBlockText = currentBlock.toString()
|
||||||
|
var actionTaken = "Keep"
|
||||||
|
|
||||||
|
if (rawBlockText.trim().isEmpty()) {
|
||||||
|
rawBlockText = if(isT0) "" else "z"
|
||||||
|
actionTaken = if(isT0) "EMPTY->\"\"" else "EMPTY->z"
|
||||||
|
}
|
||||||
|
|
||||||
|
var blockToProcess = if (currentLogicalIdx == targetPointer) {
|
||||||
|
actionTaken = if (newMarkerValue.isEmpty()) "DELETE" else "UPDATE"
|
||||||
|
val note = rawBlockText.replace(Regex("""\$\{.*?\}|\$."""), "").trim()
|
||||||
|
|
||||||
|
newMarkerValue + note
|
||||||
|
} else {
|
||||||
|
rawBlockText
|
||||||
|
}
|
||||||
|
|
||||||
|
val compactedBlock = StringBuilder()
|
||||||
|
if (blockToProcess.isNotEmpty()) {
|
||||||
|
var k = 0
|
||||||
|
while (k < blockToProcess.length) {
|
||||||
|
val char = blockToProcess[k]
|
||||||
|
|
||||||
|
if (char == 'D' || char == 'z' || char == '-') {
|
||||||
|
var count = 1
|
||||||
|
val noteStart = char
|
||||||
|
|
||||||
|
val markerFound = StringBuilder()
|
||||||
|
var mIdx = k + 1
|
||||||
|
while (mIdx < blockToProcess.length) {
|
||||||
|
val nextChar = blockToProcess[mIdx]
|
||||||
|
if (nextChar == '$') {
|
||||||
|
if (mIdx + 1 < blockToProcess.length && blockToProcess[mIdx + 1] == '{') {
|
||||||
|
val end = blockToProcess.indexOf('}', mIdx)
|
||||||
|
if (end != -1) {
|
||||||
|
markerFound.append(blockToProcess.substring(mIdx, end + 1))
|
||||||
|
mIdx = end + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
} else if (mIdx + 1 < blockToProcess.length) {
|
||||||
|
markerFound.append(blockToProcess.substring(mIdx, mIdx + 2))
|
||||||
|
mIdx += 2
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
var scanIdx = mIdx
|
||||||
|
while (scanIdx < blockToProcess.length && blockToProcess[scanIdx] == '-' && count < 4) {
|
||||||
|
if (scanIdx + 1 < blockToProcess.length && blockToProcess[scanIdx + 1] == '$') break
|
||||||
|
count++
|
||||||
|
scanIdx++
|
||||||
|
}
|
||||||
|
|
||||||
|
val compactCode = when (count) {
|
||||||
|
1 -> noteStart
|
||||||
|
2 -> if (noteStart == 'D') '8' else '2'
|
||||||
|
3 -> if (noteStart == 'D') 'C' else '3'
|
||||||
|
4 -> if (noteStart == 'D') 'G' else '4'
|
||||||
|
else -> noteStart
|
||||||
|
}
|
||||||
|
|
||||||
|
compactedBlock.append(compactCode).append(markerFound)
|
||||||
|
k = scanIdx
|
||||||
|
} else {
|
||||||
|
compactedBlock.append(char)
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
compactedBlock.append("")
|
||||||
|
}
|
||||||
|
|
||||||
|
// println(String.format("%-4d | %-25s | %-15s | %-25s",
|
||||||
|
// currentLogicalIdx, rawBlockText, actionTaken, compactedBlock.toString()))
|
||||||
|
|
||||||
|
resultBody.append(compactedBlock)
|
||||||
|
if (i < body.length) resultBody.append(body[i])
|
||||||
|
|
||||||
|
currentBlock.clear()
|
||||||
|
currentLogicalIdx++
|
||||||
|
} else {
|
||||||
|
currentBlock.append(body[i])
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
val finalResult = "$prefix$resultBody$suffix"
|
||||||
|
// println("-".repeat(100))
|
||||||
|
// println("RÉSULTAT FINAL COMPACTÉ : $finalResult")
|
||||||
|
// println("=".repeat(100))
|
||||||
|
|
||||||
|
return finalResult
|
||||||
|
}
|
||||||
|
|
||||||
private fun parseNoteAndOctave(s: String): Pair<String, Int> {
|
private fun parseNoteAndOctave(s: String): Pair<String, Int> {
|
||||||
val base = s.replace(Regex("[^drmfsltDRFSTzw]"), "")
|
val base = s.replace(Regex("[^drmfsltDRFSTzw]"), "")
|
||||||
|
|
@ -876,7 +1061,7 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
// "Array = ${templateArray.joinToString("|")}")
|
// "Array = ${templateArray.joinToString("|")}")
|
||||||
// println("APRèS T: ${templateArray.joinToString("|")}")
|
// println("APRèS T: ${templateArray.joinToString("|")}")
|
||||||
} else {
|
} else {
|
||||||
val body = templateLine.replaceFirst(Regex("^U0:z.:"), "")
|
val body = templateLine.replaceFirst(Regex("^U0:(?:z[0-9A-Z]:)?"), "")
|
||||||
|
|
||||||
//println("Mon contenu est: $body.")
|
//println("Mon contenu est: $body.")
|
||||||
val result = mutableListOf<String>()
|
val result = mutableListOf<String>()
|
||||||
|
|
@ -886,31 +1071,27 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
while (i < body.length) {
|
while (i < body.length) {
|
||||||
val char = body[i]
|
val char = body[i]
|
||||||
|
|
||||||
// 1. GESTION DES MARQUEURS ${...} -> ON IGNORE TOUT LE BLOC
|
|
||||||
if (char == '$' && i + 1 < body.length && body[i + 1] == '{') {
|
if (char == '$' && i + 1 < body.length && body[i + 1] == '{') {
|
||||||
val closingBrace = body.indexOf('}', i)
|
val closingBrace = body.indexOf('}', i)
|
||||||
if (closingBrace != -1) {
|
if (closingBrace != -1) {
|
||||||
i = closingBrace + 1 // On saute jusqu'après le '}'
|
i = closingBrace + 1
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (char == '$') {
|
if (char == '$') {
|
||||||
i += 2 // On saute le '$' et la lettre qui suit
|
i += 2
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. SÉPARATEURS -> ON COUPE LE BLOC
|
|
||||||
if (char in listOf(':', '|', '!', '/')) {
|
if (char in listOf(':', '|', '!', '/')) {
|
||||||
if (currentBlock.isNotEmpty()) {
|
if (currentBlock.isNotEmpty()) {
|
||||||
result.add(currentBlock.toString())
|
result.add(currentBlock.toString())
|
||||||
currentBlock.clear()
|
currentBlock.clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 4. IGNORER LES ESPACES
|
|
||||||
else if (char == ' ') {
|
else if (char == ' ') {
|
||||||
// ne rien faire
|
|
||||||
}
|
}
|
||||||
// 5. TOUT LE RESTE (D, z, -, ., ,, (, ) )
|
|
||||||
else {
|
else {
|
||||||
currentBlock.append(char)
|
currentBlock.append(char)
|
||||||
}
|
}
|
||||||
|
|
@ -918,7 +1099,6 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ajouter le dernier morceau s'il n'y a pas de séparateur à la fin
|
|
||||||
if (currentBlock.isNotEmpty()) result.add(currentBlock.toString())
|
if (currentBlock.isNotEmpty()) result.add(currentBlock.toString())
|
||||||
|
|
||||||
templateArray = result
|
templateArray = result
|
||||||
|
|
@ -929,6 +1109,297 @@ class Solfa(val sharedScreenModel: SharedScreenModel, private val fileRepository
|
||||||
return templateArray
|
return templateArray
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reconstructIt(finalResult: String, measure: Int): String {
|
||||||
|
if(finalResult.startsWith("T0:")) {
|
||||||
|
/* T0 */
|
||||||
|
return finalResult
|
||||||
|
} else {
|
||||||
|
/* U0 */
|
||||||
|
val prefixMatch = Regex("^(.*?z[048CEKO]:|.*?z.:)").find(finalResult)
|
||||||
|
val prefix = prefixMatch?.value ?: "U0:z0:"
|
||||||
|
val body = finalResult.substring(prefixMatch?.value?.length ?: (finalResult.indexOf(":") + 1))
|
||||||
|
|
||||||
|
val buff = mutableListOf<String>()
|
||||||
|
var currentBlockBuilder = StringBuilder()
|
||||||
|
var idx = 0
|
||||||
|
while (idx < body.length) {
|
||||||
|
if (body[idx] == '$' && idx + 1 < body.length && body[idx + 1] == '{') {
|
||||||
|
val endPos = body.indexOf('}', idx)
|
||||||
|
if (endPos != -1) {
|
||||||
|
currentBlockBuilder.append(body.substring(idx, endPos + 1))
|
||||||
|
idx = endPos + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val char = body[idx]
|
||||||
|
if (char == ':' || char == '|' || char == '!') {
|
||||||
|
if (currentBlockBuilder.isNotEmpty()) {
|
||||||
|
buff.add(currentBlockBuilder.toString())
|
||||||
|
currentBlockBuilder.setLength(0)
|
||||||
|
}
|
||||||
|
} else if (char == '/') {
|
||||||
|
currentBlockBuilder.append(char)
|
||||||
|
buff.add(currentBlockBuilder.toString())
|
||||||
|
currentBlockBuilder.setLength(0)
|
||||||
|
} else {
|
||||||
|
currentBlockBuilder.append(char)
|
||||||
|
}
|
||||||
|
idx++
|
||||||
|
}
|
||||||
|
if (currentBlockBuilder.isNotEmpty()) {
|
||||||
|
buff.add(currentBlockBuilder.toString())
|
||||||
|
}
|
||||||
|
|
||||||
|
val buff2 = mutableListOf<String>()
|
||||||
|
val consumedGlobally = mutableSetOf<Pair<Int, Int>>()
|
||||||
|
val consumedBlocks = mutableSetOf<Int>()
|
||||||
|
|
||||||
|
fun getDurationAt(targetStr: String, targetCharIdx: Int, blockIdx: Int): Int {
|
||||||
|
val cleanStr = targetStr.replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
val charAtIdx = targetStr[targetCharIdx]
|
||||||
|
|
||||||
|
if (blockIdx > 0) {
|
||||||
|
val prevBlock = buff[blockIdx - 1].replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
val isFirstActiveChar = targetCharIdx == 0 || targetStr.substring(0, targetCharIdx).all {
|
||||||
|
"., !:|(){}$".contains(it) || consumedGlobally.contains(blockIdx to targetStr.indexOf(it))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prevBlock.endsWith("-.") || prevBlock == ".") {
|
||||||
|
if (isFirstActiveChar) {
|
||||||
|
if (charAtIdx == 'z' || charAtIdx == 'D') {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cleanStr.contains(".") && !cleanStr.contains(",")) {
|
||||||
|
if (prevBlock.endsWith("./") || prevBlock.endsWith(".")) return 2
|
||||||
|
if (prevBlock.endsWith(",/") || prevBlock.endsWith(",")) return 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (charAtIdx == 'D' || charAtIdx == 'z') {
|
||||||
|
val textAfter = targetStr.substring(targetCharIdx + 1)
|
||||||
|
val cleanAfter = textAfter.replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
if (cleanAfter.startsWith(".") && !cleanAfter.substring(1).any { it == 'D' || it == 'z' || it == '-' }) {
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!cleanStr.contains(".") && !cleanStr.contains(",")) return 4
|
||||||
|
|
||||||
|
val pByPoint = cleanStr.split(".")
|
||||||
|
val prefixBefore = targetStr.substring(0, targetCharIdx).replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
val cleanIdx = prefixBefore.length
|
||||||
|
|
||||||
|
var curPos = 0
|
||||||
|
var zoneIdx = 0
|
||||||
|
for (i in pByPoint.indices) {
|
||||||
|
if (cleanIdx >= curPos && cleanIdx < curPos + pByPoint[i].length + 1) {
|
||||||
|
zoneIdx = i
|
||||||
|
break
|
||||||
|
}
|
||||||
|
curPos += pByPoint[i].length + 1
|
||||||
|
}
|
||||||
|
|
||||||
|
return if (cleanStr.contains(",")) {
|
||||||
|
if (pByPoint[zoneIdx].contains(",")) 1 else 2
|
||||||
|
} else {
|
||||||
|
2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun encodeDuration(duration: Int): String {
|
||||||
|
return when (duration) {
|
||||||
|
1 -> "1"; 2 -> "2"; 3 -> "3"; 4 -> "4"
|
||||||
|
6 -> "6"; 8 -> "8"; 10 -> "A"; 11 -> "B";
|
||||||
|
12 -> "C"; 14 -> "E"; 16 -> "G"; 20 -> "K";
|
||||||
|
24 -> "O"; 28 -> "S"; 32 -> "W"
|
||||||
|
else -> duration.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var k = 0
|
||||||
|
while (k < buff.size) {
|
||||||
|
if (consumedBlocks.contains(k)) {
|
||||||
|
// println("Pour $k = ${buff[k]} -> Saut du bloc entier (déjà absorbé dans un silence cumulé)")
|
||||||
|
k++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val currentStr = buff[k]
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val prefixBuffer = StringBuilder()
|
||||||
|
|
||||||
|
// println("Pour $k = $currentStr")
|
||||||
|
|
||||||
|
if (k > 0) {
|
||||||
|
val prevBlock = buff[k - 1].replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
val cleanCurrent = currentStr.replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
|
||||||
|
if (prevBlock.endsWith("-./") || prevBlock.endsWith("-.)/")) {
|
||||||
|
if (cleanCurrent.contains(".") && cleanCurrent.startsWith("D") && cleanCurrent.count { it == 'D' } >= 2) {
|
||||||
|
val silenceDuration = 2
|
||||||
|
sb.append("z$silenceDuration ")
|
||||||
|
// println(" -> [RÈGLE SPÉCIALE] Silence résiduel injecté ! Insertion de 'z$silenceDuration '")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var charIdx = 0
|
||||||
|
while (charIdx < currentStr.length) {
|
||||||
|
if (consumedGlobally.contains(k to charIdx)) {
|
||||||
|
// println(" -> Saut du caractère '${currentStr[charIdx]}' (déjà absorbé)")
|
||||||
|
charIdx++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val char = currentStr[charIdx]
|
||||||
|
when {
|
||||||
|
char == '$' && charIdx + 1 < currentStr.length && currentStr[charIdx + 1] == '{' -> {
|
||||||
|
val endIdx = currentStr.indexOf('}', charIdx)
|
||||||
|
if (endIdx != -1) {
|
||||||
|
prefixBuffer.append(currentStr.substring(charIdx, endIdx + 1))
|
||||||
|
charIdx = endIdx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
char == '$' && charIdx + 1 < currentStr.length -> {
|
||||||
|
prefixBuffer.append(char).append(currentStr[charIdx + 1])
|
||||||
|
charIdx++
|
||||||
|
}
|
||||||
|
|
||||||
|
char == '(' -> prefixBuffer.append(char)
|
||||||
|
char == ')' || char == '/' -> sb.append(char)
|
||||||
|
|
||||||
|
char == 'D' || char == 'z' -> {
|
||||||
|
var totalDuration = getDurationAt(currentStr, charIdx, k)
|
||||||
|
// println(" -> Note '$char' détectée. Zone initiale, Durée: $totalDuration")
|
||||||
|
|
||||||
|
var lookK = k
|
||||||
|
var lookC = charIdx + 1
|
||||||
|
var searching = true
|
||||||
|
|
||||||
|
while (searching) {
|
||||||
|
if (lookC >= buff[lookK].length) {
|
||||||
|
lookK++; lookC = 0
|
||||||
|
if (lookK >= buff.size) break
|
||||||
|
}
|
||||||
|
|
||||||
|
val next = buff[lookK][lookC]
|
||||||
|
|
||||||
|
when {
|
||||||
|
next == '$' -> {
|
||||||
|
if (lookC + 1 < buff[lookK].length && buff[lookK][lookC + 1] == '{') {
|
||||||
|
val end = buff[lookK].indexOf('}', lookC)
|
||||||
|
lookC = if (end != -1) end + 1 else lookC + 2
|
||||||
|
} else {
|
||||||
|
lookC += 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next == '-' -> {
|
||||||
|
val resDur = getDurationAt(buff[lookK], lookC, lookK)
|
||||||
|
totalDuration += resDur
|
||||||
|
consumedGlobally.add(lookK to lookC)
|
||||||
|
// println(" + Absorption tiret à [$lookK,$lookC]. Durée zone: $resDur. Total: $totalDuration")
|
||||||
|
lookC++
|
||||||
|
}
|
||||||
|
|
||||||
|
next == 'z' && lookK == k && char == 'D' -> {
|
||||||
|
var hasFutureResonance = false
|
||||||
|
if (k + 1 < buff.size) {
|
||||||
|
if (buff[k + 1].replace(Regex("\\$\\{.*?\\}|\\$."), "")
|
||||||
|
.startsWith("-")
|
||||||
|
) hasFutureResonance = true
|
||||||
|
}
|
||||||
|
if (!hasFutureResonance && currentStr.contains(".") && currentStr.contains(",")) {
|
||||||
|
val resDur = getDurationAt(currentStr, lookC, k)
|
||||||
|
totalDuration += resDur
|
||||||
|
consumedGlobally.add(lookK to lookC)
|
||||||
|
lookC++
|
||||||
|
} else {
|
||||||
|
searching = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
"., !:|(){}".contains(next) || next == '$' -> lookC++
|
||||||
|
else -> searching = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val isPureSilenceBlock =
|
||||||
|
char == 'z' && (lookK > k || (lookK == k && lookC >= buff[k].length))
|
||||||
|
|
||||||
|
if (isPureSilenceBlock) {
|
||||||
|
var nextBlockIdx = k + 1
|
||||||
|
var lookingForSilence = true
|
||||||
|
|
||||||
|
while (lookingForSilence && nextBlockIdx < buff.size) {
|
||||||
|
val nextBlockRaw = buff[nextBlockIdx]
|
||||||
|
val nextBlockClean = nextBlockRaw.replace(Regex("\\$\\{.*?\\}|\\$."), "").trim()
|
||||||
|
|
||||||
|
if (nextBlockClean.isNotEmpty() && nextBlockClean.all {
|
||||||
|
it == 'z' || "., !:|()/{}".contains(
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}) {
|
||||||
|
val zIdxInNext = nextBlockRaw.indexOf('z')
|
||||||
|
if (zIdxInNext != -1) {
|
||||||
|
val nextSilenceDur = getDurationAt(nextBlockRaw, zIdxInNext, nextBlockIdx)
|
||||||
|
totalDuration += nextSilenceDur
|
||||||
|
// println(" [CUMUL SILENCE] -> Bloc $nextBlockIdx ('$nextBlockClean') absorbé. Durée ajoutée: $nextSilenceDur. Total temporaire: $totalDuration")
|
||||||
|
consumedBlocks.add(nextBlockIdx)
|
||||||
|
nextBlockIdx++
|
||||||
|
} else {
|
||||||
|
lookingForSilence = false
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
lookingForSilence = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val code = if (char == 'z') {
|
||||||
|
"z${encodeDuration(totalDuration)}"
|
||||||
|
} else {
|
||||||
|
encodeDuration(totalDuration)
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(prefixBuffer.toString())
|
||||||
|
prefixBuffer.setLength(0)
|
||||||
|
sb.append(code)
|
||||||
|
// println(" -> Code généré: $code")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
charIdx++
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixBuffer.isNotEmpty()) sb.insert(0, prefixBuffer.toString())
|
||||||
|
var resultBlock = sb.toString()
|
||||||
|
|
||||||
|
if (resultBlock.contains("31")) {
|
||||||
|
resultBlock = resultBlock.replace("31", "y")
|
||||||
|
// println(" -> Motif 'y' détecté")
|
||||||
|
}
|
||||||
|
|
||||||
|
// println("Pour ça ON a $resultBlock \n")
|
||||||
|
if (resultBlock.isNotEmpty() || buff[k].contains("/")) buff2.add(resultBlock)
|
||||||
|
k++
|
||||||
|
}
|
||||||
|
|
||||||
|
val cleanedBlocks = buff2.map { it.replace(" ", "") }
|
||||||
|
val finalLines = (prefix + cleanedBlocks.joinToString(""))
|
||||||
|
.replace("2z11", "y")
|
||||||
|
.replace("/", "/ ")
|
||||||
|
.replace(Regex("\\s+"), " ")
|
||||||
|
.trim()
|
||||||
|
|
||||||
|
// println(finalLines)
|
||||||
|
return finalLines
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun expandNotes(text: String): String {
|
private fun expandNotes(text: String): String {
|
||||||
val regex = Regex("([drmfsltDRFSTzw])([,']*)(\\d+)")
|
val regex = Regex("([drmfsltDRFSTzw])([,']*)(\\d+)")
|
||||||
return regex.replace(text) { matchResult ->
|
return regex.replace(text) { matchResult ->
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,7 @@ class SolfaVisualTransformation : VisualTransformation {
|
||||||
|
|
||||||
when {
|
when {
|
||||||
line.startsWith("M0:") -> parseMetadataLine(line)
|
line.startsWith("M0:") -> parseMetadataLine(line)
|
||||||
line.startsWith("U0:") && hasU0 -> parseControlLine(line)
|
line.startsWith("U0:") || line.startsWith("T0:") -> parseControlLine(line)
|
||||||
line.startsWith("T0:") && !hasU0 && hasT0 -> parseControlLine(line)
|
|
||||||
line.startsWith("N") && line.getOrNull(2) == ':' -> parseNoteLine(line)
|
line.startsWith("N") && line.getOrNull(2) == ':' -> parseNoteLine(line)
|
||||||
(line.startsWith("Y") || line.startsWith("E")) && (line.getOrNull(2) == ':' || line.getOrNull(3) == ':') -> parseLyricLine(line)
|
(line.startsWith("Y") || line.startsWith("E")) && (line.getOrNull(2) == ':' || line.getOrNull(3) == ':') -> parseLyricLine(line)
|
||||||
else -> append(line)
|
else -> append(line)
|
||||||
|
|
@ -129,16 +128,21 @@ private fun AnnotatedString.Builder.appendWithMarkers(text: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun AnnotatedString.Builder.parseControlLine(line: String) {
|
private fun AnnotatedString.Builder.parseControlLine(line: String) {
|
||||||
val regex = Regex("^(U0:)(z[0-9A-Z]:)?(.*)$")
|
val regex = Regex("^([UT]0:)(z[0-9A-Z]:)?(.*)$")
|
||||||
val match = regex.find(line)
|
val match = regex.find(line)
|
||||||
match?.let {
|
if (match != null) {
|
||||||
pushStyle(SpanStyle(color = ColorPrefixA))
|
pushStyle(SpanStyle(color = ColorPrefixA, fontWeight = FontWeight.Bold))
|
||||||
append(it.groupValues[1])
|
append(match.groupValues[1])
|
||||||
pop()
|
pop()
|
||||||
|
|
||||||
|
if (match.groupValues[2].isNotEmpty()) {
|
||||||
pushStyle(SpanStyle(color = ColorPrefixB))
|
pushStyle(SpanStyle(color = ColorPrefixB))
|
||||||
append(it.groupValues[2])
|
append(match.groupValues[2])
|
||||||
pop()
|
pop()
|
||||||
parseGenericContent(it.groupValues[3])
|
}
|
||||||
|
parseGenericContent(match.groupValues[3])
|
||||||
|
} else {
|
||||||
|
append(line)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -19,10 +19,12 @@ import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.graphics.Brush
|
import androidx.compose.ui.graphics.Brush
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
|
import androidx.compose.ui.text.TextRange
|
||||||
import androidx.compose.ui.text.TextStyle
|
import androidx.compose.ui.text.TextStyle
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontWeight
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
import androidx.compose.ui.text.input.KeyboardType
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.text.input.TextFieldValue
|
||||||
import androidx.compose.ui.unit.*
|
import androidx.compose.ui.unit.*
|
||||||
import androidx.compose.ui.window.Popup
|
import androidx.compose.ui.window.Popup
|
||||||
import androidx.compose.ui.window.PopupProperties
|
import androidx.compose.ui.window.PopupProperties
|
||||||
|
|
@ -57,7 +59,6 @@ fun TUODetailDialog(
|
||||||
var templateFragment by remember { mutableStateOf(editState.templateFragment) }
|
var templateFragment by remember { mutableStateOf(editState.templateFragment) }
|
||||||
|
|
||||||
var marker by remember { mutableStateOf(editState.marker) }
|
var marker by remember { mutableStateOf(editState.marker) }
|
||||||
var hairPin by remember { mutableStateOf(editState.hairPin) }
|
|
||||||
|
|
||||||
val lyricsLines = remember {
|
val lyricsLines = remember {
|
||||||
mutableStateListOf<String>().apply {
|
mutableStateListOf<String>().apply {
|
||||||
|
|
@ -66,6 +67,7 @@ fun TUODetailDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var canAddMark = mutableStateOf(false)
|
||||||
Popup(
|
Popup(
|
||||||
offset = menuPosition,
|
offset = menuPosition,
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
|
|
@ -96,7 +98,6 @@ fun TUODetailDialog(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.verticalScroll(rememberScrollState())
|
.verticalScroll(rememberScrollState())
|
||||||
) {
|
) {
|
||||||
|
|
||||||
// --- SECTION TEMPLATE ---
|
// --- SECTION TEMPLATE ---
|
||||||
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -114,7 +115,7 @@ fun TUODetailDialog(
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
if(!editState.marker.isNullOrEmpty()) {
|
if(!editState.marker.isNullOrEmpty() || canAddMark.value) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.weight(1f)
|
modifier = Modifier.weight(1f)
|
||||||
) {
|
) {
|
||||||
|
|
@ -130,20 +131,16 @@ fun TUODetailDialog(
|
||||||
onValueChng = { marker = it }
|
onValueChng = { marker = it }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
if(!editState.hairPin.isNullOrEmpty()) {
|
IconButton(
|
||||||
Column(
|
modifier = Modifier.size(30.dp),
|
||||||
modifier = Modifier.weight(1f)
|
onClick = {
|
||||||
) {
|
canAddMark.value = true
|
||||||
MyTextEditField(
|
}) {
|
||||||
value = hairPin,
|
Icon(
|
||||||
customFontSize = 14.sp,
|
imageVector = Icons.Default.Add,
|
||||||
color = Color.Yellow,
|
tint = Color.Green,
|
||||||
customPadding = 8.dp,
|
contentDescription = null
|
||||||
customBrush = SolidColor(Color.White),
|
|
||||||
isEditable = isEditable,
|
|
||||||
isAddable = canAdd,
|
|
||||||
onValueChng = { hairPin = it }
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -263,7 +260,8 @@ fun TUODetailDialog(
|
||||||
originalNotes = originalNotes.toMap(),
|
originalNotes = originalNotes.toMap(),
|
||||||
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
||||||
lyricsByStanza = mutableMapOf(currentStanza to lyricsLines.joinToString(" ")),
|
lyricsByStanza = mutableMapOf(currentStanza to lyricsLines.joinToString(" ")),
|
||||||
templateFragment = templateFragment
|
templateFragment = templateFragment,
|
||||||
|
marker = marker
|
||||||
)
|
)
|
||||||
onSave(state)
|
onSave(state)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,5 @@ data class TUOEditState(
|
||||||
val lyricsByStanza: MutableMap<Int, String> = mutableMapOf(),
|
val lyricsByStanza: MutableMap<Int, String> = mutableMapOf(),
|
||||||
val originalLyricsByStanza: MutableMap<Int, String> = mutableMapOf(),
|
val originalLyricsByStanza: MutableMap<Int, String> = mutableMapOf(),
|
||||||
val templateFragment: String = "",
|
val templateFragment: String = "",
|
||||||
val marker: String = "",
|
val marker: String = ""
|
||||||
val hairPin: String = ""
|
|
||||||
)
|
)
|
||||||
|
|
@ -843,9 +843,6 @@ fun LazyVerticalGridTUO(
|
||||||
|
|
||||||
val editState = TUOEditState(
|
val editState = TUOEditState(
|
||||||
tuoIndex = oneTUO.firstTuoIndex,
|
tuoIndex = oneTUO.firstTuoIndex,
|
||||||
/*notesByVoice = (0..3).associate { i ->
|
|
||||||
i to (oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: "")
|
|
||||||
},*/
|
|
||||||
notesByVoice = (0..3).associate { i ->
|
notesByVoice = (0..3).associate { i ->
|
||||||
val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
||||||
val fixedNote = autoFixNote(rawNote, template)
|
val fixedNote = autoFixNote(rawNote, template)
|
||||||
|
|
@ -855,14 +852,11 @@ fun LazyVerticalGridTUO(
|
||||||
s to oneTUO.getSingleSyllable(s).firstOrNull().orEmpty()
|
s to oneTUO.getSingleSyllable(s).firstOrNull().orEmpty()
|
||||||
}.toMutableMap(),
|
}.toMutableMap(),
|
||||||
templateFragment = oneTUO.pTemplate.template,
|
templateFragment = oneTUO.pTemplate.template,
|
||||||
marker = oneTUO.pTemplate.markerToString(),
|
marker = listOfNotNull(
|
||||||
hairPin = oneTUO.hasHairPin()?.toString() ?: ""
|
oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
|
||||||
|
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
|
||||||
|
).joinToString(" ")
|
||||||
)
|
)
|
||||||
// oneTUO.tuNotes.mapIndexed { index, note ->
|
|
||||||
//
|
|
||||||
// println("i$index => ${note.toString()}")
|
|
||||||
// }
|
|
||||||
|
|
||||||
TUODetailDialog(
|
TUODetailDialog(
|
||||||
editState = editState,
|
editState = editState,
|
||||||
tuo = currentSelected,
|
tuo = currentSelected,
|
||||||
|
|
|
||||||
|
|
@ -523,7 +523,7 @@ class SharedScreenModel(private val fileRepository: FileRepository) : ScreenMode
|
||||||
|
|
||||||
fun openTUOEditor(editState: TUOEditState) {
|
fun openTUOEditor(editState: TUOEditState) {
|
||||||
_tuoEditState.value = editState
|
_tuoEditState.value = editState
|
||||||
println("nMrk = [${editState.marker}] template [${editState.templateFragment}] hp [${editState.hairPin}]")
|
println("nMrk = [${editState.marker}] template [${editState.templateFragment}]")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun closeTUOEditor() {
|
fun closeTUOEditor() {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue