Compare commits
2 commits
96eb4dbbf0
...
ca2e10b9b2
| Author | SHA1 | Date | |
|---|---|---|---|
| ca2e10b9b2 | |||
| f6366cfd3f |
1 changed files with 495 additions and 579 deletions
|
|
@ -28,11 +28,13 @@ import androidx.compose.ui.focus.focusRequester
|
||||||
import androidx.compose.ui.geometry.Offset
|
import androidx.compose.ui.geometry.Offset
|
||||||
import androidx.compose.ui.geometry.Size
|
import androidx.compose.ui.geometry.Size
|
||||||
import androidx.compose.ui.graphics.Color
|
import androidx.compose.ui.graphics.Color
|
||||||
|
import androidx.compose.ui.graphics.RectangleShape
|
||||||
import androidx.compose.ui.graphics.SolidColor
|
import androidx.compose.ui.graphics.SolidColor
|
||||||
import androidx.compose.ui.graphics.drawscope.Stroke
|
import androidx.compose.ui.graphics.drawscope.Stroke
|
||||||
import androidx.compose.ui.input.pointer.pointerInput
|
import androidx.compose.ui.input.pointer.pointerInput
|
||||||
import androidx.compose.ui.layout.onSizeChanged
|
import androidx.compose.ui.layout.onSizeChanged
|
||||||
import androidx.compose.ui.platform.LocalDensity
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.platform.LocalFocusManager
|
||||||
import androidx.compose.ui.text.*
|
import androidx.compose.ui.text.*
|
||||||
import androidx.compose.ui.text.font.FontFamily
|
import androidx.compose.ui.text.font.FontFamily
|
||||||
import androidx.compose.ui.text.font.FontStyle
|
import androidx.compose.ui.text.font.FontStyle
|
||||||
|
|
@ -271,8 +273,8 @@ fun TimeUnitComposable(
|
||||||
val currentDensity = LocalDensity.current
|
val currentDensity = LocalDensity.current
|
||||||
|
|
||||||
val animatedColor by animateColorAsState(
|
val animatedColor by animateColorAsState(
|
||||||
targetValue = if (gridActive) MaterialTheme.colorScheme.secondary.copy(alpha = 0.5f) else col,
|
targetValue = if (gridActive) MaterialTheme.colorScheme.secondary.copy(alpha = 1f) else col,
|
||||||
animationSpec = tween(durationMillis = 150) // Très court pour rester réactif
|
animationSpec = tween(durationMillis = 100) // Très court pour rester réactif
|
||||||
)
|
)
|
||||||
val focusRequesters = remember { List(4) { FocusRequester() } }
|
val focusRequesters = remember { List(4) { FocusRequester() } }
|
||||||
|
|
||||||
|
|
@ -475,13 +477,17 @@ fun TimeUnitComposable(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data class TUOWidthMeasure(val width: Dp, val isReady: Boolean)
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun bestTUOWidth(items: List<TimeUnitObject>): Dp {
|
fun bestTUOWidth(items: List<TimeUnitObject>): TUOWidthMeasure {
|
||||||
val textMeasurer = rememberTextMeasurer()
|
val textMeasurer = rememberTextMeasurer()
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
|
|
||||||
var maxWidth by remember { mutableStateOf(0.dp) }
|
var maxWidth by remember(items) { mutableStateOf(0.dp) }
|
||||||
|
var isReady by remember(items) { mutableStateOf(false) }
|
||||||
LaunchedEffect(items) {
|
LaunchedEffect(items) {
|
||||||
|
isReady = false
|
||||||
maxWidth = 0.dp
|
maxWidth = 0.dp
|
||||||
items.forEach {
|
items.forEach {
|
||||||
val textLayoutResult: TextLayoutResult = textMeasurer.measure(
|
val textLayoutResult: TextLayoutResult = textMeasurer.measure(
|
||||||
|
|
@ -495,8 +501,9 @@ fun bestTUOWidth(items: List<TimeUnitObject>): Dp {
|
||||||
maxWidth = textWidth
|
maxWidth = textWidth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
isReady = true
|
||||||
}
|
}
|
||||||
return maxWidth + 13.dp
|
return TUOWidthMeasure(maxWidth + 13.dp, isReady)
|
||||||
}
|
}
|
||||||
@Composable
|
@Composable
|
||||||
fun AutoResizingText(
|
fun AutoResizingText(
|
||||||
|
|
@ -564,10 +571,6 @@ fun LazyVerticalGridTUO(
|
||||||
val tuoList = viewModel.tuoList
|
val tuoList = viewModel.tuoList
|
||||||
key(tuoList) {
|
key(tuoList) {
|
||||||
|
|
||||||
var isCalculatingGrid by remember { mutableStateOf(true) }
|
|
||||||
var gridColumnCount by remember { mutableStateOf(0) }
|
|
||||||
var computedMeasures by remember { mutableStateOf<List<List<TimeUnitObject>>>(emptyList()) }
|
|
||||||
|
|
||||||
var menuPosition by remember { mutableStateOf(Offset.Zero) }
|
var menuPosition by remember { mutableStateOf(Offset.Zero) }
|
||||||
var showAddDialog by remember { mutableStateOf(false) }
|
var showAddDialog by remember { mutableStateOf(false) }
|
||||||
var showDetailDialog by remember { mutableStateOf(false) }
|
var showDetailDialog by remember { mutableStateOf(false) }
|
||||||
|
|
@ -592,40 +595,57 @@ fun LazyVerticalGridTUO(
|
||||||
val editMode by sharedScreenModel.modeEditor.collectAsState()
|
val editMode by sharedScreenModel.modeEditor.collectAsState()
|
||||||
val showFullChord by sharedScreenModel.harmonyView.collectAsState()
|
val showFullChord by sharedScreenModel.harmonyView.collectAsState()
|
||||||
var toggleWithDegreeAndChord by remember { mutableStateOf (false) }
|
var toggleWithDegreeAndChord by remember { mutableStateOf (false) }
|
||||||
|
|
||||||
|
val focusManager = LocalFocusManager.current
|
||||||
|
Column(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.onSizeChanged { size ->
|
||||||
|
onGridWidthMeasured(size.width)
|
||||||
|
}
|
||||||
|
.focusRequester(focusRequester)
|
||||||
|
.focusable()
|
||||||
|
) {
|
||||||
|
LaunchedEffect(editMode) {
|
||||||
|
if (editMode) {
|
||||||
|
focusRequester.requestFocus()
|
||||||
|
}
|
||||||
|
}
|
||||||
val density = LocalDensity.current
|
val density = LocalDensity.current
|
||||||
|
val horizontalArrangementSpacing: Dp = 0.dp
|
||||||
val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1"
|
val columnGroupString = regexMeasure?.groupValues?.get(1) ?: "1"
|
||||||
val columnGroup = columnGroupString.toInt().coerceAtLeast(1)
|
val columnGroup = columnGroupString.toInt().coerceAtLeast(1)
|
||||||
val itemMinBaseWidth = bestTUOWidth(tuoList)
|
val tuoWidthMeasure = bestTUOWidth(tuoList)
|
||||||
|
val itemMinBaseWidth = tuoWidthMeasure.width
|
||||||
val gridWidthDp = with(density) { gridWidthPx.toDp() }
|
val gridWidthDp = with(density) { gridWidthPx.toDp() }
|
||||||
|
|
||||||
|
// on affiche un loader pour éviter le "saut" visuel
|
||||||
|
val isLayoutReady = tuoWidthMeasure.isReady && gridWidthDp > 0.dp
|
||||||
|
|
||||||
val gridCount by sharedScreenModel.gridCount.collectAsState()
|
val gridCount by sharedScreenModel.gridCount.collectAsState()
|
||||||
val currentStanza = viewModel.stanza
|
|
||||||
|
|
||||||
// Calcul asynchrone nombre de colonnes
|
var gridColumnCount: Int = remember(gridWidthDp, itemMinBaseWidth, columnGroup) {
|
||||||
LaunchedEffect(gridWidthDp, itemMinBaseWidth, columnGroup, gridCount, tuoList) {
|
if (gridWidthDp == 0.dp) return@remember columnGroup
|
||||||
if (gridWidthDp == 0.dp || tuoList.isEmpty()) return@LaunchedEffect
|
var calculatedCols =
|
||||||
|
(gridWidthDp / (itemMinBaseWidth + horizontalArrangementSpacing)).toInt()
|
||||||
isCalculatingGrid = true
|
|
||||||
withContext(Dispatchers.Default) {
|
|
||||||
var calculatedCols = (gridWidthDp / (itemMinBaseWidth + 0.dp)).toInt()
|
|
||||||
if (calculatedCols == 0) calculatedCols = columnGroup
|
if (calculatedCols == 0) calculatedCols = columnGroup
|
||||||
if (calculatedCols % columnGroup != 0) {
|
if (calculatedCols % columnGroup != 0) {
|
||||||
calculatedCols = (calculatedCols / columnGroup) * columnGroup
|
calculatedCols = (calculatedCols / columnGroup) * columnGroup
|
||||||
if (calculatedCols == 0) calculatedCols = columnGroup
|
if (calculatedCols == 0) calculatedCols = columnGroup
|
||||||
}
|
}
|
||||||
val finalCols = calculatedCols.coerceAtLeast(columnGroup) + gridCount
|
val actualColumnCount: Int = calculatedCols.coerceAtLeast(columnGroup)
|
||||||
val chunkedMeasures = tuoList.drop(1).chunked(finalCols)
|
actualColumnCount
|
||||||
|
}
|
||||||
|
gridColumnCount += gridCount
|
||||||
|
val flowRowSize: Float = 0.98f / gridColumnCount
|
||||||
|
|
||||||
withContext(Dispatchers.Main) {
|
val currentStanza = viewModel.stanza
|
||||||
gridColumnCount = finalCols
|
|
||||||
computedMeasures = chunkedMeasures
|
|
||||||
isCalculatingGrid = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val tuoTimestamps by sharedScreenModel.tuoTimestamps.collectAsState()
|
val tuoTimestamps by sharedScreenModel.tuoTimestamps.collectAsState()
|
||||||
val activeRowIndex by sharedScreenModel.activeIndex.collectAsState()
|
val activeRowIndex by sharedScreenModel.activeIndex.collectAsState()
|
||||||
|
|
||||||
|
val measures = tuoList.drop(1).chunked(gridColumnCount)
|
||||||
|
// Avant column affichage:
|
||||||
val metadataList = remember(tuoList) {
|
val metadataList = remember(tuoList) {
|
||||||
tuoList.drop(1).mapIndexedNotNull { globalIndex, oneTUO ->
|
tuoList.drop(1).mapIndexedNotNull { globalIndex, oneTUO ->
|
||||||
val markerText = oneTUO.pTemplate.markerToString()
|
val markerText = oneTUO.pTemplate.markerToString()
|
||||||
|
|
@ -661,48 +681,26 @@ fun LazyVerticalGridTUO(
|
||||||
sharedScreenModel.updateAndFinalizeMidiData(metadataList)
|
sharedScreenModel.updateAndFinalizeMidiData(metadataList)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LaunchedEffect(computedMeasures, sharedScreenModel.stanza.value) {
|
LaunchedEffect(measures, sharedScreenModel.stanza.value) {
|
||||||
sharedScreenModel.updateSyllablesFromList(
|
sharedScreenModel.updateSyllablesFromList(
|
||||||
measures = computedMeasures,
|
measures = measures,
|
||||||
stanzaNumber = sharedScreenModel.stanza.value
|
stanzaNumber = sharedScreenModel.stanza.value
|
||||||
)
|
)
|
||||||
|
|
||||||
val totalSyllables = sharedScreenModel.synchronizedSyllables.value.size
|
val totalSyllables = sharedScreenModel.synchronizedSyllables.value.size
|
||||||
//println("Sync complète effectuée SUR stz: ${sharedScreenModel.stanza.value}! Total colonnes : $totalSyllables")
|
//println("Sync complète effectuée SUR stz: ${sharedScreenModel.stanza.value}! Total colonnes : $totalSyllables")
|
||||||
}
|
}
|
||||||
|
if (!isLayoutReady) {
|
||||||
Box(
|
Box(
|
||||||
modifier = modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.onSizeChanged { size->
|
.height(200.dp),
|
||||||
onGridWidthMeasured(size.width)
|
|
||||||
}
|
|
||||||
.focusRequester(focusRequester)
|
|
||||||
.focusable(),
|
|
||||||
contentAlignment = Alignment.Center
|
contentAlignment = Alignment.Center
|
||||||
) {
|
|
||||||
LaunchedEffect(editMode) {
|
|
||||||
if (editMode) focusRequester.requestFocus()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Chargement avant affichage
|
|
||||||
if (isCalculatingGrid || computedMeasures.isEmpty() || gridColumnCount == 0) {
|
|
||||||
Box(
|
|
||||||
contentAlignment = Alignment.Center,
|
|
||||||
modifier = Modifier
|
|
||||||
.padding(32.dp)
|
|
||||||
.size(100.dp)
|
|
||||||
) {
|
) {
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.size(64.dp),
|
||||||
color = MaterialTheme.colorScheme.primary,
|
strokeWidth = 3.dp
|
||||||
strokeWidth = 2.dp,
|
|
||||||
trackColor = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.1f)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
Column(
|
|
||||||
horizontalAlignment = Alignment.CenterHorizontally,
|
|
||||||
verticalArrangement = Arrangement.Center
|
|
||||||
) {
|
|
||||||
Text(
|
Text(
|
||||||
text = "𝄞 ♫",
|
text = "𝄞 ♫",
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
|
|
@ -711,71 +709,14 @@ fun LazyVerticalGridTUO(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier.fillMaxWidth()
|
modifier = Modifier.fillMaxWidth()
|
||||||
){
|
){
|
||||||
computedMeasures.forEachIndexed { measureIndex, measureTUOs ->
|
measures.forEachIndexed { measureIndex, measureTUOs ->
|
||||||
key(measureIndex) {
|
key(measureIndex) {
|
||||||
MeasureRowItem(
|
|
||||||
measureTUOs,
|
|
||||||
gridWidthDp,
|
|
||||||
gridColumnCount,
|
|
||||||
showFullChord,
|
|
||||||
sharedScreenModel,
|
|
||||||
toggleWithDegreeAndChord,
|
|
||||||
measureIndex,
|
|
||||||
activeRowIndex,
|
|
||||||
selectedGridIndex,
|
|
||||||
editMode,
|
|
||||||
selectedTUO,
|
|
||||||
selectedIndex,
|
|
||||||
showContextualMenu,
|
|
||||||
currentStanza,
|
|
||||||
focusRequester,
|
|
||||||
showEditDialog,
|
|
||||||
showAddDialog,
|
|
||||||
showDetailDialog
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Composable
|
|
||||||
private fun MeasureRowItem(
|
|
||||||
measureTUOs: List<TimeUnitObject>,
|
|
||||||
gridWidthDp: Dp,
|
|
||||||
gridColumnCount: Int,
|
|
||||||
showFullChord: Boolean,
|
|
||||||
sharedScreenModel: SharedScreenModel,
|
|
||||||
toggleWithDegreeAndChord: Boolean,
|
|
||||||
measureIndex: Int,
|
|
||||||
activeRowIndex: Int,
|
|
||||||
selectedGridIndex: Int,
|
|
||||||
editMode: Boolean,
|
|
||||||
selectedTUO: TimeUnitObject?,
|
|
||||||
selectedIndex: Int,
|
|
||||||
showContextualMenu: Boolean,
|
|
||||||
currentStanza: Int,
|
|
||||||
focusRequester: FocusRequester,
|
|
||||||
showEditDialog: Boolean,
|
|
||||||
showAddDialog: Boolean,
|
|
||||||
showDetailDialog: Boolean
|
|
||||||
) {
|
|
||||||
var toggleWithDegreeAndChord1 = toggleWithDegreeAndChord
|
|
||||||
var selectedGridIndex1 = selectedGridIndex
|
|
||||||
var selectedTUO1 = selectedTUO
|
|
||||||
var selectedIndex1 = selectedIndex
|
|
||||||
var showContextualMenu1 = showContextualMenu
|
|
||||||
var showEditDialog1 = showEditDialog
|
|
||||||
var showAddDialog1 = showAddDialog
|
|
||||||
var showDetailDialog1 = showDetailDialog
|
|
||||||
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) {
|
Column(modifier = Modifier.fillMaxWidth().padding(vertical = 4.dp)) {
|
||||||
|
|
||||||
Row(
|
Row(
|
||||||
modifier = Modifier.fillMaxWidth(),
|
modifier = Modifier.fillMaxWidth(),
|
||||||
horizontalArrangement = Arrangement.Start,
|
horizontalArrangement = Arrangement.Start,
|
||||||
|
|
@ -822,10 +763,8 @@ private fun MeasureRowItem(
|
||||||
Canvas(
|
Canvas(
|
||||||
modifier = Modifier.fillMaxSize()
|
modifier = Modifier.fillMaxSize()
|
||||||
) {
|
) {
|
||||||
val xStart =
|
val xStart = if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width/2
|
||||||
if (lastHairPinSymbol == '>') -size.width * (tuo.numBlock - hairPinStart) else size.width / 2
|
val xEnd = if (lastHairPinSymbol == '>') size.width/2 else -size.width * (tuo.numBlock - hairPinStart)
|
||||||
val xEnd =
|
|
||||||
if (lastHairPinSymbol == '>') size.width / 2 else -size.width * (tuo.numBlock - hairPinStart)
|
|
||||||
drawLine(
|
drawLine(
|
||||||
Color.DarkGray,
|
Color.DarkGray,
|
||||||
start = Offset(x=xStart, y=0f),
|
start = Offset(x=xStart, y=0f),
|
||||||
|
|
@ -854,13 +793,9 @@ private fun MeasureRowItem(
|
||||||
if (text.contains(Regex("^\\s*(ppp|pp|p|mp|mf|f|ff|fff)\\s*$"))) {
|
if (text.contains(Regex("^\\s*(ppp|pp|p|mp|mf|f|ff|fff)\\s*$"))) {
|
||||||
fontWeight = FontWeight.Bold
|
fontWeight = FontWeight.Bold
|
||||||
}
|
}
|
||||||
Text(
|
Text(text = text,
|
||||||
text = text,
|
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.wrapContentSize(
|
.wrapContentSize(unbounded = true, align = Alignment.CenterStart,),
|
||||||
unbounded = true,
|
|
||||||
align = Alignment.CenterStart
|
|
||||||
),
|
|
||||||
softWrap = false,
|
softWrap = false,
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
fontStyle = fontStyle,
|
fontStyle = fontStyle,
|
||||||
|
|
@ -890,10 +825,7 @@ private fun MeasureRowItem(
|
||||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null
|
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeDegree(chordMap) else null
|
||||||
}
|
}
|
||||||
val chordName = remember(chordMap) {
|
val chordName = remember(chordMap) {
|
||||||
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName(
|
if (chordMap.isNotEmpty()) HarmonicAnalyzer.analyzeChordName(chordMap, sharedScreenModel.songKey.value) else null
|
||||||
chordMap,
|
|
||||||
sharedScreenModel.songKey.value
|
|
||||||
) else null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Column(
|
Column(
|
||||||
|
|
@ -905,15 +837,12 @@ private fun MeasureRowItem(
|
||||||
var currentFontSize by remember { mutableStateOf(maxFontSize) }
|
var currentFontSize by remember { mutableStateOf(maxFontSize) }
|
||||||
|
|
||||||
TextButton(
|
TextButton(
|
||||||
onClick = { toggleWithDegreeAndChord1 = !toggleWithDegreeAndChord1 },
|
onClick = { toggleWithDegreeAndChord = !toggleWithDegreeAndChord },
|
||||||
contentPadding = PaddingValues(0.dp),
|
contentPadding = PaddingValues(0.dp),
|
||||||
modifier = Modifier.height(24.dp).fillMaxWidth()
|
modifier = Modifier.height(24.dp).fillMaxWidth()
|
||||||
) {
|
) {
|
||||||
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
BoxWithConstraints(modifier = Modifier.fillMaxWidth()) {
|
||||||
val textToDisplay =
|
val textToDisplay = if (toggleWithDegreeAndChord) (chordName ?: "") else (degreeName ?: "")
|
||||||
if (toggleWithDegreeAndChord1) (chordName
|
|
||||||
?: "") else (degreeName
|
|
||||||
?: "")
|
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = textToDisplay,
|
text = textToDisplay,
|
||||||
|
|
@ -926,11 +855,7 @@ private fun MeasureRowItem(
|
||||||
maxLines = 1,
|
maxLines = 1,
|
||||||
overflow = TextOverflow.Visible,
|
overflow = TextOverflow.Visible,
|
||||||
style = TextStyle(
|
style = TextStyle(
|
||||||
color = if (!toggleWithDegreeAndChord1) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy(
|
color = if (!toggleWithDegreeAndChord) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.secondary.copy(red = MaterialTheme.colorScheme.secondary.red * 0.4f, green = MaterialTheme.colorScheme.secondary.green * 0.4f, blue = MaterialTheme.colorScheme.secondary.blue * 0.4f ),
|
||||||
red = MaterialTheme.colorScheme.secondary.red * 0.4f,
|
|
||||||
green = MaterialTheme.colorScheme.secondary.green * 0.4f,
|
|
||||||
blue = MaterialTheme.colorScheme.secondary.blue * 0.4f
|
|
||||||
),
|
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
fontSize = currentFontSize
|
fontSize = currentFontSize
|
||||||
)
|
)
|
||||||
|
|
@ -945,17 +870,15 @@ private fun MeasureRowItem(
|
||||||
measureTUOs.forEachIndexed { indexInMeasure, oneTUO ->
|
measureTUOs.forEachIndexed { indexInMeasure, oneTUO ->
|
||||||
val globalIndex = (measureIndex * gridColumnCount) + indexInMeasure
|
val globalIndex = (measureIndex * gridColumnCount) + indexInMeasure
|
||||||
val isActive = (globalIndex == activeRowIndex)
|
val isActive = (globalIndex == activeRowIndex)
|
||||||
val isSelectedByKeyboard = (globalIndex == selectedGridIndex1)
|
val isSelectedByKeyboard = (globalIndex == selectedGridIndex)
|
||||||
|
|
||||||
val myTimestamp =
|
val myTimestamp = sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L }
|
||||||
sharedScreenModel.tuoTimestamps.value.getOrElse(globalIndex) { 0L }
|
|
||||||
var menuOffset by remember { mutableStateOf(Offset.Zero) }
|
var menuOffset by remember { mutableStateOf(Offset.Zero) }
|
||||||
val interactionSource = remember { MutableInteractionSource() }
|
val interactionSource = remember { MutableInteractionSource() }
|
||||||
val isHovered by interactionSource.collectIsHoveredAsState()
|
val isHovered by interactionSource.collectIsHoveredAsState()
|
||||||
|
|
||||||
key(oneTUO.numBlock) {
|
key(oneTUO.numBlock) {
|
||||||
Box(
|
Box(modifier = Modifier
|
||||||
modifier = Modifier
|
|
||||||
.width(gridWidthDp / gridColumnCount)
|
.width(gridWidthDp / gridColumnCount)
|
||||||
.border(
|
.border(
|
||||||
width = if (isSelectedByKeyboard && editMode) 2.dp else 0.dp,
|
width = if (isSelectedByKeyboard && editMode) 2.dp else 0.dp,
|
||||||
|
|
@ -975,11 +898,11 @@ private fun MeasureRowItem(
|
||||||
detectTapGestures(
|
detectTapGestures(
|
||||||
onTap = { offset ->
|
onTap = { offset ->
|
||||||
if(editMode) {
|
if(editMode) {
|
||||||
selectedGridIndex1 = globalIndex
|
selectedGridIndex = globalIndex
|
||||||
menuOffset = offset
|
menuOffset = offset
|
||||||
selectedTUO1 = oneTUO
|
selectedTUO = oneTUO
|
||||||
selectedIndex1 = globalIndex
|
selectedIndex = globalIndex
|
||||||
showContextualMenu1 = true
|
showContextualMenu = true
|
||||||
} else {
|
} else {
|
||||||
sharedScreenModel.seekToGrid(globalIndex)
|
sharedScreenModel.seekToGrid(globalIndex)
|
||||||
}
|
}
|
||||||
|
|
@ -998,47 +921,43 @@ private fun MeasureRowItem(
|
||||||
transpositionInterval = currentInterval
|
transpositionInterval = currentInterval
|
||||||
)
|
)
|
||||||
|
|
||||||
if (showContextualMenu1 && selectedIndex1 == globalIndex) {
|
if (showContextualMenu && selectedIndex == globalIndex) {
|
||||||
Popup(
|
Popup(
|
||||||
alignment = Alignment.TopStart,
|
alignment = Alignment.TopStart,
|
||||||
offset = IntOffset(
|
offset = IntOffset(
|
||||||
menuOffset.x.roundToInt(),
|
menuOffset.x.roundToInt(),
|
||||||
menuOffset.y.roundToInt()
|
menuOffset.y.roundToInt()
|
||||||
),
|
),
|
||||||
onDismissRequest = { showContextualMenu1 = false }
|
onDismissRequest = { showContextualMenu = false }
|
||||||
) {
|
) {
|
||||||
ContextualMenu(onMenuItemClick = { item ->
|
ContextualMenu(onMenuItemClick = { item ->
|
||||||
println("Clicked in TUO $globalIndex: $item")
|
println("Clicked in TUO $globalIndex: $item")
|
||||||
showContextualMenu1 = false
|
showContextualMenu = false
|
||||||
when(item) {
|
when(item) {
|
||||||
"Modifier" -> {
|
"Modifier" -> {
|
||||||
showEditDialog1 = true
|
showEditDialog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Ajouter" -> {
|
"Ajouter" -> {
|
||||||
showAddDialog1 = true
|
showAddDialog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
"Liste" -> {
|
"Liste" -> {
|
||||||
showDetailDialog1 = true
|
showDetailDialog = true
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
showDetailDialog1 = false
|
showDetailDialog = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val currentSelected = selectedTUO1
|
val currentSelected = selectedTUO
|
||||||
if ((showEditDialog1 || showAddDialog1 || showDetailDialog1) && currentSelected != null && selectedIndex1 == globalIndex) {
|
if ((showEditDialog || showAddDialog || showDetailDialog) && currentSelected != null && selectedIndex == globalIndex) {
|
||||||
val canAdd = showAddDialog1
|
val canAdd = showAddDialog
|
||||||
val canEdit = showEditDialog1 || canAdd
|
val canEdit = showEditDialog || canAdd
|
||||||
|
|
||||||
val template = oneTUO.pTemplate.template
|
val template = oneTUO.pTemplate.template
|
||||||
val expectedTemplate =
|
val expectedTemplate = template.count { it.isLetter() } == 2 && template.contains(".")
|
||||||
template.count { it.isLetter() } == 2 && template.contains(".")
|
|
||||||
|
|
||||||
val fileC = sharedScreenModel.fileContent.value ?: ""
|
val fileC = sharedScreenModel.fileContent.value ?: ""
|
||||||
val lines = fileC.split("\n").toMutableList()
|
val lines = fileC.split("\n").toMutableList()
|
||||||
|
|
@ -1049,11 +968,9 @@ private fun MeasureRowItem(
|
||||||
t0Idx != -1 -> {
|
t0Idx != -1 -> {
|
||||||
lines[t0Idx]
|
lines[t0Idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
u0Idx != -1 -> {
|
u0Idx != -1 -> {
|
||||||
lines[u0Idx]
|
lines[u0Idx]
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> ""
|
else -> ""
|
||||||
}
|
}
|
||||||
val afterU0T0 = fullLine.substringAfter("0:")
|
val afterU0T0 = fullLine.substringAfter("0:")
|
||||||
|
|
@ -1064,8 +981,7 @@ private fun MeasureRowItem(
|
||||||
val editState = TUOEditState(
|
val editState = TUOEditState(
|
||||||
tuoIndex = oneTUO.firstTuoIndex,
|
tuoIndex = oneTUO.firstTuoIndex,
|
||||||
notesByVoice = (0..3).associate { i ->
|
notesByVoice = (0..3).associate { i ->
|
||||||
val rawNote =
|
val rawNote = oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
||||||
oneTUO.tuNotes.getOrNull(i + 1)?.toString() ?: ""
|
|
||||||
val fixedNote = autoFixNote(rawNote, template)
|
val fixedNote = autoFixNote(rawNote, template)
|
||||||
i to fixedNote
|
i to fixedNote
|
||||||
},
|
},
|
||||||
|
|
@ -1074,8 +990,7 @@ private fun MeasureRowItem(
|
||||||
}.toMutableMap(),
|
}.toMutableMap(),
|
||||||
templateFragment = oneTUO.pTemplate.template,
|
templateFragment = oneTUO.pTemplate.template,
|
||||||
marker = listOfNotNull(
|
marker = listOfNotNull(
|
||||||
oneTUO.pTemplate.markerToString()
|
oneTUO.pTemplate.markerToString().takeIf { it.isNotBlank() },
|
||||||
.takeIf { it.isNotBlank() },
|
|
||||||
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
|
oneTUO.hasHairPin()?.toString()?.takeIf { it.isNotBlank() }
|
||||||
).joinToString(" "),
|
).joinToString(" "),
|
||||||
silentDuration = blankPrefix,
|
silentDuration = blankPrefix,
|
||||||
|
|
@ -1093,26 +1008,26 @@ private fun MeasureRowItem(
|
||||||
isEditable = canEdit,
|
isEditable = canEdit,
|
||||||
canAdd = canAdd,
|
canAdd = canAdd,
|
||||||
onDismiss = {
|
onDismiss = {
|
||||||
showAddDialog1 = false
|
showAddDialog = false
|
||||||
showDetailDialog1 = false
|
showDetailDialog = false
|
||||||
showEditDialog1 = false
|
showEditDialog = false
|
||||||
},
|
},
|
||||||
onSave = { newState ->
|
onSave = { newState ->
|
||||||
sharedScreenModel.openTUOEditor(newState)
|
sharedScreenModel.openTUOEditor(newState)
|
||||||
showAddDialog1 = false
|
showAddDialog = false
|
||||||
showEditDialog1 = false
|
showEditDialog = false
|
||||||
},
|
},
|
||||||
onIndexChanged = { newIndex ->
|
onIndexChanged = { newIndex ->
|
||||||
selectedIndex1 = newIndex
|
selectedIndex = newIndex
|
||||||
val globalList = sharedScreenModel.tuoList.value
|
val globalList = sharedScreenModel.tuoList.value
|
||||||
val nextTUO = globalList.getOrNull(newIndex)
|
val nextTUO = globalList.getOrNull(newIndex)
|
||||||
|
|
||||||
if (nextTUO != null) {
|
if (nextTUO != null) {
|
||||||
selectedTUO1 = nextTUO
|
selectedTUO = nextTUO
|
||||||
}else {
|
}else {
|
||||||
showAddDialog1 = false
|
showAddDialog = false
|
||||||
showDetailDialog1 = false
|
showDetailDialog = false
|
||||||
showEditDialog1 = false
|
showEditDialog = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -1164,12 +1079,7 @@ private fun MeasureRowItem(
|
||||||
val isTooLong = textWidthDp > containerWidthDp
|
val isTooLong = textWidthDp > containerWidthDp
|
||||||
|
|
||||||
val spacer = makeSpaceBetweenSyllables(textMeasurer, columnWidthDp)
|
val spacer = makeSpaceBetweenSyllables(textMeasurer, columnWidthDp)
|
||||||
val (dynamicSpaceSyl, alignmentText) = spacer(
|
val (dynamicSpaceSyl, alignmentText) = spacer(syl, cleanAllTemps, syls_i, index)
|
||||||
syl,
|
|
||||||
cleanAllTemps,
|
|
||||||
syls_i,
|
|
||||||
index
|
|
||||||
)
|
|
||||||
Text(
|
Text(
|
||||||
text = dynamicSpaceSyl,
|
text = dynamicSpaceSyl,
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -1199,6 +1109,12 @@ private fun MeasureRowItem(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun makeSpaceBetweenSyllables(
|
fun makeSpaceBetweenSyllables(
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue