Add musical markers popup in the editor
This commit is contained in:
parent
f32147f24d
commit
9550ab0e3c
2 changed files with 510 additions and 23 deletions
|
|
@ -0,0 +1,415 @@
|
||||||
|
package mg.dot.feufaro.solfa
|
||||||
|
|
||||||
|
import androidx.compose.animation.*
|
||||||
|
import androidx.compose.animation.core.tween
|
||||||
|
import androidx.compose.foundation.*
|
||||||
|
import androidx.compose.foundation.layout.*
|
||||||
|
import androidx.compose.foundation.lazy.LazyColumn
|
||||||
|
import androidx.compose.foundation.lazy.itemsIndexed
|
||||||
|
import androidx.compose.foundation.text.KeyboardOptions
|
||||||
|
import androidx.compose.material.*
|
||||||
|
import androidx.compose.material.icons.Icons
|
||||||
|
import androidx.compose.material.icons.filled.AddCircleOutline
|
||||||
|
import androidx.compose.material.icons.filled.KeyboardArrowDown
|
||||||
|
import androidx.compose.material.icons.filled.KeyboardArrowUp
|
||||||
|
import androidx.compose.material.icons.filled.RemoveCircleOutline
|
||||||
|
import androidx.compose.material3.DropdownMenu
|
||||||
|
import androidx.compose.material3.DropdownMenuItem
|
||||||
|
import androidx.compose.material3.ExperimentalMaterial3Api
|
||||||
|
import androidx.compose.material3.HorizontalDivider
|
||||||
|
import androidx.compose.material3.Icon
|
||||||
|
import androidx.compose.material3.IconButton
|
||||||
|
import androidx.compose.material3.MaterialTheme
|
||||||
|
import androidx.compose.material3.OutlinedButton
|
||||||
|
import androidx.compose.material3.PlainTooltip
|
||||||
|
import androidx.compose.material3.Surface
|
||||||
|
import androidx.compose.material3.Text
|
||||||
|
import androidx.compose.material3.TextField
|
||||||
|
import androidx.compose.material3.TooltipBox
|
||||||
|
import androidx.compose.material3.TooltipDefaults
|
||||||
|
import androidx.compose.material3.rememberTooltipState
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Alignment
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.text.font.FontWeight
|
||||||
|
import androidx.compose.ui.text.input.KeyboardType
|
||||||
|
import androidx.compose.ui.unit.IntOffset
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import androidx.compose.ui.window.Popup
|
||||||
|
import androidx.compose.ui.window.PopupProperties
|
||||||
|
|
||||||
|
data class Marker(
|
||||||
|
val abbr: String,
|
||||||
|
val description: String,
|
||||||
|
val canEditValue: Boolean = false,
|
||||||
|
val defaultValue: String = "",
|
||||||
|
val options: List<String> = emptyList()
|
||||||
|
)
|
||||||
|
|
||||||
|
data class MarkerGroup(
|
||||||
|
val title: String,
|
||||||
|
val markers: List<Marker>
|
||||||
|
)
|
||||||
|
|
||||||
|
private val markerGroups = listOf(
|
||||||
|
MarkerGroup(
|
||||||
|
title = "Nuances",
|
||||||
|
markers = listOf(
|
||||||
|
Marker("ppp", "Très très doux"),
|
||||||
|
Marker("pp", "Pianissimo"),
|
||||||
|
Marker("p", "Piano"),
|
||||||
|
Marker("mp", "Mezzo piano"),
|
||||||
|
Marker("mf", "Mezzo forte"),
|
||||||
|
Marker("f", "Forte"),
|
||||||
|
Marker("ff", "Fortissimo"),
|
||||||
|
Marker("fff", "Très très fort"),
|
||||||
|
|
||||||
|
Marker("cres.", "Augmenter progressivement le volume"),
|
||||||
|
Marker("<", "Crescendo"),
|
||||||
|
Marker("decresc.", "Diminuer progressivement le volume"),
|
||||||
|
Marker("dim.", "Diminuendo"),
|
||||||
|
Marker(">", "Decrescendo"),
|
||||||
|
|
||||||
|
Marker("sf", "Accent soudain"),
|
||||||
|
Marker("sfz", "Sforzato"),
|
||||||
|
Marker("fz", "Forzando"),
|
||||||
|
Marker("rfz", "Rinforzando"),
|
||||||
|
Marker("fp", "Forte puis immédiatement piano"),
|
||||||
|
Marker("pf", "Piano puis forte"),
|
||||||
|
Marker("sub.p", "Subito piano"),
|
||||||
|
Marker("sub.f", "Subito forte")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
MarkerGroup(
|
||||||
|
title = "Tempo",
|
||||||
|
markers = listOf(
|
||||||
|
Marker("𝄐", "Point d'orgue"),
|
||||||
|
Marker("Largh.", "Très très lent"),
|
||||||
|
Marker("Grave", "Très lent et solennel"),
|
||||||
|
Marker("Largo", "Large et lent"),
|
||||||
|
Marker("Lento", "Lent"),
|
||||||
|
Marker("Adagio", "Assez lent"),
|
||||||
|
Marker("And.", "Andante"),
|
||||||
|
Marker("Mod.", "Moderato"),
|
||||||
|
Marker("Alleg.", "Allegretto"),
|
||||||
|
Marker("All.", "Allegro"),
|
||||||
|
Marker("Viv.", "Vivace"),
|
||||||
|
Marker("Presto", "Très rapide"),
|
||||||
|
Marker("Prestiss.", "Extrêmement rapide"),
|
||||||
|
|
||||||
|
Marker("accel.", "Accélérer progressivement"),
|
||||||
|
Marker("rit.", "Ralentir progressivement"),
|
||||||
|
Marker("rall.", "Ralentir"),
|
||||||
|
Marker("riten.", "Retenir le tempo"),
|
||||||
|
Marker("string.", "Presser le tempo"),
|
||||||
|
Marker("♩=", "Changement tempo", canEditValue = true, defaultValue = "60"),
|
||||||
|
Marker("allarg.", "Élargir le tempo"),
|
||||||
|
Marker("a tempo", "Retour au tempo initial"),
|
||||||
|
Marker("Tempo I", "Retour au premier tempo"),
|
||||||
|
Marker("rubato", "Tempo libre"),
|
||||||
|
Marker("meno mosso", "Moins rapide"),
|
||||||
|
Marker("più mosso", "Plus rapide")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
MarkerGroup(
|
||||||
|
title = "Reprises",
|
||||||
|
markers = listOf(
|
||||||
|
Marker("D.C.", "Da Capo"),
|
||||||
|
Marker("D.C. Fin", "Retour au début jusqu'à Fine"),
|
||||||
|
Marker("D.C. al Coda", "Retour au début puis aller à la Coda"),
|
||||||
|
Marker("D.S.", "Retour au Segno"),
|
||||||
|
Marker("End", "Fin"),
|
||||||
|
Marker("D.S. Fin", "Retour au Segno jusqu'à Fine"),
|
||||||
|
Marker("Farany", "Fin"),
|
||||||
|
Marker("$", "Segno"),
|
||||||
|
Marker("Fine", "Fin"),
|
||||||
|
Marker("𝄌", "Coda"),
|
||||||
|
Marker("To Coda", "Aller à la Coda"),
|
||||||
|
Marker("||:", "Début de reprise"),
|
||||||
|
Marker(":||", "Fin de reprise"),
|
||||||
|
Marker("Bis", "Rejouer")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
MarkerGroup(
|
||||||
|
title = "Tonalité",
|
||||||
|
markers = listOf(
|
||||||
|
Marker("Dô dia", "Modulation", canEditValue = true, defaultValue = "C", options = Transpose.keyToNumber)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun MarkerPopup(
|
||||||
|
menuPosition: IntOffset,
|
||||||
|
onDismiss: () -> Unit,
|
||||||
|
onMarkerSelected: (String) -> Unit
|
||||||
|
) {
|
||||||
|
var expandedGroupIndex by remember {
|
||||||
|
mutableStateOf<Int?>(null)
|
||||||
|
}
|
||||||
|
Popup(
|
||||||
|
offset = menuPosition,
|
||||||
|
onDismissRequest = onDismiss,
|
||||||
|
properties = PopupProperties(
|
||||||
|
focusable = true,
|
||||||
|
dismissOnBackPress = true,
|
||||||
|
dismissOnClickOutside = true
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
|
||||||
|
Surface (
|
||||||
|
modifier = Modifier
|
||||||
|
.widthIn(max=250.dp)
|
||||||
|
.heightIn(max=450.dp),
|
||||||
|
shape = MaterialTheme.shapes.small,
|
||||||
|
color = MaterialTheme.colorScheme.onSecondary.copy(0.75f),
|
||||||
|
) {
|
||||||
|
LazyColumn {
|
||||||
|
itemsIndexed(markerGroups) { index, group ->
|
||||||
|
ExpandableGroup(
|
||||||
|
group = group,
|
||||||
|
expanded = expandedGroupIndex == index,
|
||||||
|
onExpand = {
|
||||||
|
expandedGroupIndex = if(expandedGroupIndex == index) null else index
|
||||||
|
},
|
||||||
|
onMarkerSelected = {
|
||||||
|
onMarkerSelected(it)
|
||||||
|
onDismiss()
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(
|
||||||
|
ExperimentalFoundationApi::class,
|
||||||
|
ExperimentalMaterial3Api::class,
|
||||||
|
ExperimentalLayoutApi::class
|
||||||
|
)
|
||||||
|
@Composable
|
||||||
|
private fun ExpandableGroup(
|
||||||
|
group: MarkerGroup,
|
||||||
|
expanded: Boolean,
|
||||||
|
onExpand: () -> Unit,
|
||||||
|
onMarkerSelected: (String) -> Unit
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.clickable { onExpand() }
|
||||||
|
.padding(horizontal = 12.dp, vertical = 10.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = group.title,
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
style = MaterialTheme.typography.headlineSmall.copy(
|
||||||
|
color = MaterialTheme.colorScheme.background
|
||||||
|
)
|
||||||
|
)
|
||||||
|
Icon(
|
||||||
|
imageVector = if (expanded)
|
||||||
|
Icons.Default.RemoveCircleOutline
|
||||||
|
else
|
||||||
|
Icons.Default.AddCircleOutline,
|
||||||
|
contentDescription = null,
|
||||||
|
tint = MaterialTheme.colorScheme.primary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
AnimatedVisibility(
|
||||||
|
visible = expanded,
|
||||||
|
enter = expandVertically(
|
||||||
|
animationSpec = tween(250)
|
||||||
|
) + fadeIn(
|
||||||
|
animationSpec = tween(250)
|
||||||
|
),
|
||||||
|
exit = shrinkVertically(
|
||||||
|
animationSpec = tween(200)
|
||||||
|
) + fadeOut(
|
||||||
|
animationSpec = tween(200)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
Column {
|
||||||
|
FlowRow(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.heightIn(max = 220.dp)
|
||||||
|
.verticalScroll(rememberScrollState())
|
||||||
|
.padding(horizontal = 2.dp),
|
||||||
|
horizontalArrangement = Arrangement.spacedBy(4.dp),
|
||||||
|
verticalArrangement = Arrangement.spacedBy(4.dp)
|
||||||
|
) {
|
||||||
|
group.markers.forEach { marker ->
|
||||||
|
if (marker.canEditValue) {
|
||||||
|
var value by remember { mutableStateOf(marker.defaultValue) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.weight(1f)
|
||||||
|
.background(Color.Gray)
|
||||||
|
.padding(10.dp),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
if (marker.options.isNotEmpty()) {
|
||||||
|
Text(
|
||||||
|
marker.abbr,
|
||||||
|
style = MaterialTheme.typography.titleMedium
|
||||||
|
)
|
||||||
|
var optionsExpanded by remember { mutableStateOf(false) }
|
||||||
|
Box(modifier = Modifier.fillMaxWidth(0.6f)) {
|
||||||
|
OutlinedButton(
|
||||||
|
onClick = { optionsExpanded = true },
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.padding(2.dp)
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
value,
|
||||||
|
style = MaterialTheme.typography.titleLarge.copy(
|
||||||
|
fontWeight = FontWeight.Bold
|
||||||
|
),
|
||||||
|
color = MaterialTheme.colorScheme.secondary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
DropdownMenu(
|
||||||
|
expanded = optionsExpanded,
|
||||||
|
onDismissRequest = { optionsExpanded = false }
|
||||||
|
) {
|
||||||
|
marker.options.forEach { option ->
|
||||||
|
DropdownMenuItem(
|
||||||
|
onClick = {
|
||||||
|
value = option
|
||||||
|
optionsExpanded = false
|
||||||
|
},
|
||||||
|
text = {
|
||||||
|
Text(option)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Row(
|
||||||
|
modifier = Modifier.weight(1f),
|
||||||
|
verticalAlignment = Alignment.CenterVertically
|
||||||
|
) {
|
||||||
|
TextField(
|
||||||
|
value = value,
|
||||||
|
onValueChange = { input ->
|
||||||
|
value = input.filter { it.isDigit() }
|
||||||
|
},
|
||||||
|
modifier = Modifier.fillMaxWidth(0.70f),
|
||||||
|
singleLine = true,
|
||||||
|
keyboardOptions = KeyboardOptions(
|
||||||
|
keyboardType = KeyboardType.Number
|
||||||
|
),
|
||||||
|
leadingIcon = {
|
||||||
|
Text(
|
||||||
|
text = marker.abbr,
|
||||||
|
fontSize = MaterialTheme.typography.titleMedium.fontSize,
|
||||||
|
color = MaterialTheme.colorScheme.onSecondary
|
||||||
|
)
|
||||||
|
},
|
||||||
|
trailingIcon = {
|
||||||
|
Text(
|
||||||
|
text = "bpm",
|
||||||
|
fontSize = MaterialTheme.typography.titleSmall.fontSize,
|
||||||
|
color = MaterialTheme.colorScheme.onSecondary
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
Column(
|
||||||
|
horizontalAlignment = Alignment.CenterHorizontally
|
||||||
|
) {
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
val current = value.toIntOrNull() ?: 0
|
||||||
|
value = (current + 1).toString()
|
||||||
|
},
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.KeyboardArrowUp,
|
||||||
|
contentDescription = "Augmenter le tempo",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
val current = value.toIntOrNull() ?: 0
|
||||||
|
value = (current - 1).coerceAtLeast(0).toString()
|
||||||
|
},
|
||||||
|
modifier = Modifier.size(24.dp)
|
||||||
|
) {
|
||||||
|
Icon(
|
||||||
|
imageVector = Icons.Default.KeyboardArrowDown,
|
||||||
|
contentDescription = "Diminuer le tempo",
|
||||||
|
tint = Color.White
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
IconButton(
|
||||||
|
onClick = {
|
||||||
|
val result = marker.abbr + value
|
||||||
|
onMarkerSelected(result)
|
||||||
|
},
|
||||||
|
modifier = Modifier.size(40.dp)
|
||||||
|
) {
|
||||||
|
Text(text = "✓", color = Color.White)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
TooltipBox(
|
||||||
|
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||||
|
tooltip = {
|
||||||
|
PlainTooltip(
|
||||||
|
containerColor = Color.DarkGray,
|
||||||
|
contentColor = Color.White
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = marker.description,
|
||||||
|
fontSize = MaterialTheme.typography.bodySmall.fontSize,
|
||||||
|
modifier = Modifier.padding(8.dp)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
state = rememberTooltipState()
|
||||||
|
) {
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.weight(1f, fill = true)
|
||||||
|
.padding(4.dp)
|
||||||
|
.background(Color.Gray)
|
||||||
|
.clickable { onMarkerSelected(marker.abbr) }
|
||||||
|
.padding(horizontal = 7.dp, vertical = 2.dp),
|
||||||
|
contentAlignment = Alignment.Center
|
||||||
|
) {
|
||||||
|
Text(
|
||||||
|
text = marker.abbr,
|
||||||
|
fontSize = MaterialTheme.typography.titleSmall.fontSize,
|
||||||
|
color = MaterialTheme.colorScheme.surface
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Spacer(Modifier.height(8.dp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HorizontalDivider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,9 +16,13 @@ import androidx.compose.material3.*
|
||||||
import androidx.compose.runtime.*
|
import androidx.compose.runtime.*
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.geometry.Offset
|
||||||
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.layout.onGloballyPositioned
|
||||||
|
import androidx.compose.ui.layout.positionInParent
|
||||||
|
import androidx.compose.ui.layout.positionInWindow
|
||||||
import androidx.compose.ui.text.TextRange
|
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
|
||||||
|
|
@ -29,6 +33,7 @@ import androidx.compose.ui.text.style.TextAlign
|
||||||
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
|
||||||
|
import mg.dot.feufaro.solfa.MarkerPopup
|
||||||
import mg.dot.feufaro.solfa.Solfa
|
import mg.dot.feufaro.solfa.Solfa
|
||||||
import mg.dot.feufaro.solfa.TUOEditState
|
import mg.dot.feufaro.solfa.TUOEditState
|
||||||
import mg.dot.feufaro.solfa.TimeUnitObject
|
import mg.dot.feufaro.solfa.TimeUnitObject
|
||||||
|
|
@ -102,7 +107,11 @@ fun TUODetailDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var canAddMark = mutableStateOf(false)
|
var showMarkerPopup by remember { mutableStateOf(false) }
|
||||||
|
var markerButtonPos by remember {
|
||||||
|
mutableStateOf(IntOffset.Zero)
|
||||||
|
}
|
||||||
|
|
||||||
Popup(
|
Popup(
|
||||||
offset = menuPosition,
|
offset = menuPosition,
|
||||||
onDismissRequest = onDismiss,
|
onDismissRequest = onDismiss,
|
||||||
|
|
@ -271,7 +280,18 @@ fun TUODetailDialog(
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.size(20.dp),
|
modifier = Modifier.size(20.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
newSep = ""
|
val state = TUOEditState(
|
||||||
|
tuoIndex = globalIndex,
|
||||||
|
notesByVoice = notes.toMap(),
|
||||||
|
originalNotes = originalNotes.toMap(),
|
||||||
|
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
||||||
|
lyricsByStanza = mutableMapOf(),
|
||||||
|
templateFragment = templateFragment,
|
||||||
|
marker = if(marker.isEmpty()) "_" else marker,
|
||||||
|
originalSep = initialSep,
|
||||||
|
sep = ""
|
||||||
|
)
|
||||||
|
onSave(state)
|
||||||
}) {
|
}) {
|
||||||
Text(
|
Text(
|
||||||
text = "/",
|
text = "/",
|
||||||
|
|
@ -285,7 +305,19 @@ fun TUODetailDialog(
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.size(20.dp),
|
modifier = Modifier.size(20.dp),
|
||||||
onClick = {
|
onClick = {
|
||||||
newSep = "/"
|
|
||||||
|
val state = TUOEditState(
|
||||||
|
tuoIndex = globalIndex,
|
||||||
|
notesByVoice = notes.toMap(),
|
||||||
|
originalNotes = originalNotes.toMap(),
|
||||||
|
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
||||||
|
lyricsByStanza = mutableMapOf(),
|
||||||
|
templateFragment = templateFragment,
|
||||||
|
marker = if(marker.isEmpty()) "_" else marker,
|
||||||
|
originalSep = initialSep,
|
||||||
|
sep = "/"
|
||||||
|
)
|
||||||
|
onSave(state)
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Add,
|
imageVector = Icons.Default.Add,
|
||||||
|
|
@ -312,23 +344,13 @@ fun TUODetailDialog(
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
if(!editState.marker.isNullOrEmpty() || canAddMark.value) {
|
if(!templateFragment.isNullOrBlank() && templateFragment !="-") {
|
||||||
Column(
|
val hasMarker = marker.isNotEmpty()
|
||||||
modifier = Modifier.weight(1f)
|
val tooltipText = if (hasMarker) {
|
||||||
) {
|
"Enlever la marqueur"
|
||||||
MyTextEditField(
|
|
||||||
value = marker,
|
|
||||||
customFontSize = 14.sp,
|
|
||||||
color = MaterialTheme.colorScheme.tertiary.copy(alpha = 1.5f),
|
|
||||||
customPadding = 8.dp,
|
|
||||||
customBrush = SolidColor(Color.White),
|
|
||||||
isEditable = isEditable,
|
|
||||||
isAddable = canAdd,
|
|
||||||
funTransform = ::transformMarkerInput,
|
|
||||||
onValueChng = { marker = it }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
"Ajouter une marqueur"
|
||||||
|
}
|
||||||
TooltipBox(
|
TooltipBox(
|
||||||
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
|
||||||
tooltip = {
|
tooltip = {
|
||||||
|
|
@ -336,18 +358,41 @@ fun TUODetailDialog(
|
||||||
containerColor = Color.DarkGray,
|
containerColor = Color.DarkGray,
|
||||||
contentColor = Color.White
|
contentColor = Color.White
|
||||||
) {
|
) {
|
||||||
Text(text = "Ajouter une marqueur", fontSize = 12.sp)
|
Text(text = tooltipText, fontSize = MaterialTheme.typography.titleSmall.fontSize)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
state = rememberTooltipState()
|
state = rememberTooltipState()
|
||||||
) {
|
) {
|
||||||
IconButton(
|
IconButton(
|
||||||
modifier = Modifier.size(30.dp),
|
modifier = Modifier.size(30.dp)
|
||||||
|
.onGloballyPositioned { coordinates ->
|
||||||
|
markerButtonPos = coordinates.positionInParent()
|
||||||
|
.let {
|
||||||
|
IntOffset(
|
||||||
|
it.x.toInt(),
|
||||||
|
it.y.toInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
},
|
||||||
onClick = {
|
onClick = {
|
||||||
canAddMark.value = true
|
if(hasMarker) {
|
||||||
|
val state = TUOEditState(
|
||||||
|
tuoIndex = globalIndex,
|
||||||
|
notesByVoice = notes.toMap(),
|
||||||
|
originalNotes = originalNotes.toMap(),
|
||||||
|
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
||||||
|
lyricsByStanza = mutableMapOf(),
|
||||||
|
templateFragment = templateFragment,
|
||||||
|
marker = "_",
|
||||||
|
originalSep = initialSep,
|
||||||
|
sep = newSep
|
||||||
|
)
|
||||||
|
onSave(state)
|
||||||
|
}
|
||||||
|
showMarkerPopup = true
|
||||||
}) {
|
}) {
|
||||||
Icon(
|
Icon(
|
||||||
imageVector = Icons.Default.Add,
|
imageVector = if(hasMarker) Icons.Default.Remove else Icons.Default.Add,
|
||||||
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
|
||||||
contentDescription = null
|
contentDescription = null
|
||||||
)
|
)
|
||||||
|
|
@ -541,6 +586,33 @@ fun TUODetailDialog(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (showMarkerPopup) {
|
||||||
|
MarkerPopup(
|
||||||
|
menuPosition = IntOffset(
|
||||||
|
x = markerButtonPos.x + 180,
|
||||||
|
y = markerButtonPos.y + 100
|
||||||
|
),
|
||||||
|
onDismiss = {
|
||||||
|
showMarkerPopup = false
|
||||||
|
},
|
||||||
|
onMarkerSelected = { marker ->
|
||||||
|
showMarkerPopup = false
|
||||||
|
|
||||||
|
val state = TUOEditState(
|
||||||
|
tuoIndex = globalIndex,
|
||||||
|
notesByVoice = notes.toMap(),
|
||||||
|
originalNotes = originalNotes.toMap(),
|
||||||
|
originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
|
||||||
|
lyricsByStanza = mutableMapOf(),
|
||||||
|
templateFragment = templateFragment,
|
||||||
|
marker = marker,
|
||||||
|
originalSep = initialSep,
|
||||||
|
sep = newSep
|
||||||
|
)
|
||||||
|
onSave(state)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun unpackLyrics(lyrics: String): String {
|
private fun unpackLyrics(lyrics: String): String {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue