Update ui & Dynamic factor slider - Settings

This commit is contained in:
Hasinjato 2026-10-07 15:32:32 +03:00
parent b5fdd7c30b
commit 83a26110e6
2 changed files with 623 additions and 571 deletions

View file

@ -5,14 +5,14 @@ import mg.dot.feufaro.provideSettings
import java.util.prefs.Preferences
enum class Dynamic(val velocity: Int, val label: String, val defaultFactor: Float) {
PPP(16, "ppp", 0.55f),
PP (33, "pp", 0.66f),
P (49, "p", 0.77f),
MP (64, "mp", 0.88f),
PPP(16, "ppp", 0.80f),
PP (32, "pp", 0.85f),
P (48, "p", 0.90f),
MP (64, "mp", 0.95f),
MF (80, "mf", 1.00f),
F (96, "f", 1.15f),
FF (112, "ff", 1.35f),
FFF(127, "fff", 1.60f);
F (96, "f", 1.05f),
FF (112, "ff", 1.10f),
FFF(127, "fff", 1.15f);
private val prefs: Settings = provideSettings()
var savedFactor: Float = prefs.getFloat("dynamic_${name.lowercase()}", defaultFactor)
set(value) {

View file

@ -95,7 +95,7 @@ fun Settings(
?: MidiInstrument(program = globalInstrumentProgram, name = "Instrument $globalInstrumentProgram")
val menuScrollState = rememberScrollState()
var expandedDropdown by remember { mutableStateOf(false) }
var expandedDropdown by remember { mutableStateOf(true) }
LaunchedEffect(expandedDropdown, globalInstrumentProgram) {
if (expandedDropdown) {
@ -128,10 +128,25 @@ fun Settings(
)
},
text = {
val settingsScrollState = rememberScrollState()
Box(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight()
) {
MyVerticalScrollbar(
scrollState = settingsScrollState,
modifier = Modifier
.align(Alignment.CenterEnd)
.fillMaxHeight()
.width(8.dp)
) {
Column(
modifier = Modifier
.fillMaxWidth()
.verticalScroll(rememberScrollState()),
.padding(end = 11.dp)
.verticalScroll(settingsScrollState),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
@ -147,7 +162,7 @@ fun Settings(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
if(isAndroid) {
if (isAndroid) {
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
@ -233,7 +248,12 @@ fun Settings(
},
modifier = Modifier.size(32.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
) {
Text("-", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
Text(
"-",
fontWeight = FontWeight.Bold,
style = MaterialTheme.typography.titleLarge,
color = Color.White
)
}
Spacer(modifier = Modifier.width(16.dp))
@ -255,9 +275,15 @@ fun Settings(
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize + 0.5f)
}
},
modifier = Modifier.size(32.dp).background(MaterialTheme.colorScheme.primary, CircleShape)
modifier = Modifier.size(32.dp)
.background(MaterialTheme.colorScheme.primary, CircleShape)
) {
Text("+", fontWeight = FontWeight.Bold, style = MaterialTheme.typography.titleLarge, color = Color.White)
Text(
"+",
fontWeight = FontWeight.Bold,
style = MaterialTheme.typography.titleLarge,
color = Color.White
)
}
}
}
@ -278,9 +304,21 @@ fun Settings(
)
val colorPickers = listOf(
Triple("Couleur Primaire", "primaryBlueHex", currentDisplayConfig.primaryBlueHex),
Triple("Couleur Secondaire", "accentGreenHex", currentDisplayConfig.accentGreenHex),
Triple("Couleur Tertiaire", "accentYellowHex", currentDisplayConfig.accentYellowHex),
Triple(
"Couleur Primaire",
"primaryBlueHex",
currentDisplayConfig.primaryBlueHex
),
Triple(
"Couleur Secondaire",
"accentGreenHex",
currentDisplayConfig.accentGreenHex
),
Triple(
"Couleur Tertiaire",
"accentYellowHex",
currentDisplayConfig.accentYellowHex
),
Triple("Autre couleur", "accentPinkHex", currentDisplayConfig.accentPinkHex)
)
@ -311,7 +349,10 @@ fun Settings(
FlowRow(
modifier = Modifier
.fillMaxWidth()
.background(MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f), RoundedCornerShape(8.dp))
.background(
MaterialTheme.colorScheme.surfaceVariant.copy(alpha = 0.3f),
RoundedCornerShape(8.dp)
)
.padding(12.dp),
horizontalArrangement = Arrangement.spacedBy(10.dp),
verticalArrangement = Arrangement.spacedBy(10.dp)
@ -328,7 +369,10 @@ fun Settings(
shape = CircleShape
)
.clickable {
displayConfigManager.updateCustomColor(configKey, colorHex)
displayConfigManager.updateCustomColor(
configKey,
colorHex
)
}
)
}
@ -359,7 +403,8 @@ fun Settings(
openExclusive("Audio")
}
) {
Column(modifier = Modifier.padding(top = 8.dp),
Column(
modifier = Modifier.padding(top = 8.dp),
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
Text(
@ -422,9 +467,10 @@ fun Settings(
key(refreshTrigger) {
val dynamicEntries = Dynamic.entries
val minF = 0.22f
val maxF = 2.33f
val step = 0.05f
val minF = 0.20f
val maxF = 1.59f
val gapStep = 0.01f
val mfIndex = dynamicEntries.indexOfFirst { it == Dynamic.MF }.let { if (it == -1) 4 else it }
Box(
modifier = Modifier
@ -445,21 +491,20 @@ fun Settings(
modifier = Modifier.padding(vertical = 0.dp)
) {
// (-)
if(index == 0) {
if (index == 0) {
FilledIconButton(
onClick = {
if (isDynamicEnabled) {
val delta = - step
var insideBounds = true
dynamicEntries.forEach { item ->
val projectedValue = item.savedFactor + delta
if (projectedValue < minF || projectedValue > maxF) {
insideBounds = false
val deltaGap = gapStep
val projected = dynamicEntries.mapIndexed { i, item ->
item.savedFactor + ((i - mfIndex) * deltaGap)
}
}
if (insideBounds) {
dynamicEntries.forEach { item ->
item.savedFactor = (item.savedFactor + delta).coerceIn(minF, maxF)
val insideBounds = projected.all { it in minF..maxF }
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
if (insideBounds && maintainsOrder) {
dynamicEntries.forEachIndexed { i, item ->
item.savedFactor = projected[i].coerceIn(minF, maxF)
}
refreshTrigger++
}
@ -477,6 +522,7 @@ fun Settings(
} else {
Spacer(modifier = Modifier.width(32.dp))
}
Text(
text = dynamicItem.label.lowercase(),
style = MaterialTheme.typography.displaySmall.copy(
@ -494,22 +540,23 @@ fun Settings(
if (isDynamicEnabled) {
val oldValue = dynamicItem.savedFactor
val delta = newValue - oldValue
var insideBounds = true
dynamicEntries.forEach { item ->
val projectedValue = item.savedFactor + delta
if (projectedValue < minF || projectedValue > maxF) {
insideBounds = false
}
if (delta != 0f) {
val deltaGap = delta
val projected = dynamicEntries.mapIndexed { i, item ->
item.savedFactor + ((i - mfIndex) * deltaGap)
}
val insideBounds = projected.all { it in minF..maxF }
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
if (insideBounds) {
dynamicEntries.forEach { item ->
item.savedFactor = (item.savedFactor + delta).coerceIn(minF, maxF)
if (insideBounds && maintainsOrder) {
dynamicEntries.forEachIndexed { i, item ->
item.savedFactor = projected[i].coerceIn(minF, maxF)
}
refreshTrigger++
}
}
}
},
valueRange = minF..maxF,
enabled = isDynamicEnabled,
@ -527,7 +574,9 @@ fun Settings(
thumb = {
SliderDefaults.Thumb(
interactionSource = remember { MutableInteractionSource() },
colors = SliderDefaults.colors(thumbColor = if(isDynamicEnabled) Color(0xFFFF4081) else Color.LightGray),
colors = SliderDefaults.colors(
thumbColor = if (isDynamicEnabled) Color(0xFFFF4081) else Color.LightGray
),
modifier = Modifier.size(12.dp),
)
},
@ -542,7 +591,10 @@ fun Settings(
)
Text(
text = String.format("%.2f", if (isDynamicEnabled) dynamicItem.savedFactor else 1.00f),
text = String.format(
"%.2f",
if (isDynamicEnabled) dynamicItem.savedFactor else 1.00f
),
fontSize = 11.sp,
fontWeight = FontWeight.Bold,
color = if (isDynamicEnabled) Color(0xFFDEFF9A) else Color.DarkGray,
@ -551,22 +603,20 @@ fun Settings(
)
// (+)
if(index == 0) {
if (index == 0) {
FilledIconButton(
onClick = {
if (isDynamicEnabled) {
val delta = step
var insideBounds = true
dynamicEntries.forEach { item ->
val projectedValue = item.savedFactor + delta
if (projectedValue < minF || projectedValue > maxF) {
insideBounds = false
val deltaGap = -gapStep
val projected = dynamicEntries.mapIndexed { i, item ->
item.savedFactor + ((i - mfIndex) * deltaGap)
}
}
if (insideBounds) {
dynamicEntries.forEach { item ->
item.savedFactor =
(item.savedFactor + delta).coerceIn(minF, maxF)
val insideBounds = projected.all { it in minF..maxF }
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
if (insideBounds && maintainsOrder) {
dynamicEntries.forEachIndexed { i, item ->
item.savedFactor = projected[i].coerceIn(minF, maxF)
}
refreshTrigger++
}
@ -727,7 +777,7 @@ fun Settings(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(10.dp)
) {
if(!isAndroid) {
if (!isAndroid) {
val stat = if (isSmartPointBLoop) "Désactiver" else "Activer"
Text(
text = stat,
@ -756,6 +806,8 @@ fun Settings(
}
}
}
}
}
},
confirmButton = {
TextButton(onClick = onDismissRequest) {