Update ui & Dynamic factor slider - Settings
This commit is contained in:
parent
b5fdd7c30b
commit
83a26110e6
2 changed files with 623 additions and 571 deletions
|
|
@ -5,14 +5,14 @@ import mg.dot.feufaro.provideSettings
|
||||||
import java.util.prefs.Preferences
|
import java.util.prefs.Preferences
|
||||||
|
|
||||||
enum class Dynamic(val velocity: Int, val label: String, val defaultFactor: Float) {
|
enum class Dynamic(val velocity: Int, val label: String, val defaultFactor: Float) {
|
||||||
PPP(16, "ppp", 0.55f),
|
PPP(16, "ppp", 0.80f),
|
||||||
PP (33, "pp", 0.66f),
|
PP (32, "pp", 0.85f),
|
||||||
P (49, "p", 0.77f),
|
P (48, "p", 0.90f),
|
||||||
MP (64, "mp", 0.88f),
|
MP (64, "mp", 0.95f),
|
||||||
MF (80, "mf", 1.00f),
|
MF (80, "mf", 1.00f),
|
||||||
F (96, "f", 1.15f),
|
F (96, "f", 1.05f),
|
||||||
FF (112, "ff", 1.35f),
|
FF (112, "ff", 1.10f),
|
||||||
FFF(127, "fff", 1.60f);
|
FFF(127, "fff", 1.15f);
|
||||||
private val prefs: Settings = provideSettings()
|
private val prefs: Settings = provideSettings()
|
||||||
var savedFactor: Float = prefs.getFloat("dynamic_${name.lowercase()}", defaultFactor)
|
var savedFactor: Float = prefs.getFloat("dynamic_${name.lowercase()}", defaultFactor)
|
||||||
set(value) {
|
set(value) {
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ fun Settings(
|
||||||
?: MidiInstrument(program = globalInstrumentProgram, name = "Instrument $globalInstrumentProgram")
|
?: MidiInstrument(program = globalInstrumentProgram, name = "Instrument $globalInstrumentProgram")
|
||||||
|
|
||||||
val menuScrollState = rememberScrollState()
|
val menuScrollState = rememberScrollState()
|
||||||
var expandedDropdown by remember { mutableStateOf(false) }
|
var expandedDropdown by remember { mutableStateOf(true) }
|
||||||
|
|
||||||
LaunchedEffect(expandedDropdown, globalInstrumentProgram) {
|
LaunchedEffect(expandedDropdown, globalInstrumentProgram) {
|
||||||
if (expandedDropdown) {
|
if (expandedDropdown) {
|
||||||
|
|
@ -128,10 +128,25 @@ fun Settings(
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
text = {
|
text = {
|
||||||
|
val settingsScrollState = rememberScrollState()
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxWidth()
|
||||||
|
.fillMaxHeight()
|
||||||
|
) {
|
||||||
|
MyVerticalScrollbar(
|
||||||
|
scrollState = settingsScrollState,
|
||||||
|
modifier = Modifier
|
||||||
|
.align(Alignment.CenterEnd)
|
||||||
|
.fillMaxHeight()
|
||||||
|
.width(8.dp)
|
||||||
|
) {
|
||||||
Column(
|
Column(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.verticalScroll(rememberScrollState()),
|
.padding(end = 11.dp)
|
||||||
|
.verticalScroll(settingsScrollState),
|
||||||
verticalArrangement = Arrangement.spacedBy(8.dp)
|
verticalArrangement = Arrangement.spacedBy(8.dp)
|
||||||
) {
|
) {
|
||||||
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
HorizontalDivider(color = MaterialTheme.colorScheme.outlineVariant)
|
||||||
|
|
@ -233,7 +248,12 @@ fun Settings(
|
||||||
},
|
},
|
||||||
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
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Spacer(modifier = Modifier.width(16.dp))
|
Spacer(modifier = Modifier.width(16.dp))
|
||||||
|
|
@ -255,9 +275,15 @@ fun Settings(
|
||||||
displayConfigManager.updateFontSize(currentDisplayConfig.fontSize + 0.5f)
|
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(
|
val colorPickers = listOf(
|
||||||
Triple("Couleur Primaire", "primaryBlueHex", currentDisplayConfig.primaryBlueHex),
|
Triple(
|
||||||
Triple("Couleur Secondaire", "accentGreenHex", currentDisplayConfig.accentGreenHex),
|
"Couleur Primaire",
|
||||||
Triple("Couleur Tertiaire", "accentYellowHex", currentDisplayConfig.accentYellowHex),
|
"primaryBlueHex",
|
||||||
|
currentDisplayConfig.primaryBlueHex
|
||||||
|
),
|
||||||
|
Triple(
|
||||||
|
"Couleur Secondaire",
|
||||||
|
"accentGreenHex",
|
||||||
|
currentDisplayConfig.accentGreenHex
|
||||||
|
),
|
||||||
|
Triple(
|
||||||
|
"Couleur Tertiaire",
|
||||||
|
"accentYellowHex",
|
||||||
|
currentDisplayConfig.accentYellowHex
|
||||||
|
),
|
||||||
Triple("Autre couleur", "accentPinkHex", currentDisplayConfig.accentPinkHex)
|
Triple("Autre couleur", "accentPinkHex", currentDisplayConfig.accentPinkHex)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -311,7 +349,10 @@ fun Settings(
|
||||||
FlowRow(
|
FlowRow(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.fillMaxWidth()
|
.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),
|
.padding(12.dp),
|
||||||
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
horizontalArrangement = Arrangement.spacedBy(10.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(10.dp)
|
verticalArrangement = Arrangement.spacedBy(10.dp)
|
||||||
|
|
@ -328,7 +369,10 @@ fun Settings(
|
||||||
shape = CircleShape
|
shape = CircleShape
|
||||||
)
|
)
|
||||||
.clickable {
|
.clickable {
|
||||||
displayConfigManager.updateCustomColor(configKey, colorHex)
|
displayConfigManager.updateCustomColor(
|
||||||
|
configKey,
|
||||||
|
colorHex
|
||||||
|
)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
@ -359,7 +403,8 @@ fun Settings(
|
||||||
openExclusive("Audio")
|
openExclusive("Audio")
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
Column(modifier = Modifier.padding(top = 8.dp),
|
Column(
|
||||||
|
modifier = Modifier.padding(top = 8.dp),
|
||||||
verticalArrangement = Arrangement.spacedBy(2.dp)
|
verticalArrangement = Arrangement.spacedBy(2.dp)
|
||||||
) {
|
) {
|
||||||
Text(
|
Text(
|
||||||
|
|
@ -422,9 +467,10 @@ fun Settings(
|
||||||
|
|
||||||
key(refreshTrigger) {
|
key(refreshTrigger) {
|
||||||
val dynamicEntries = Dynamic.entries
|
val dynamicEntries = Dynamic.entries
|
||||||
val minF = 0.22f
|
val minF = 0.20f
|
||||||
val maxF = 2.33f
|
val maxF = 1.59f
|
||||||
val step = 0.05f
|
val gapStep = 0.01f
|
||||||
|
val mfIndex = dynamicEntries.indexOfFirst { it == Dynamic.MF }.let { if (it == -1) 4 else it }
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
|
|
@ -449,17 +495,16 @@ fun Settings(
|
||||||
FilledIconButton(
|
FilledIconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled) {
|
||||||
val delta = - step
|
val deltaGap = gapStep
|
||||||
var insideBounds = true
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
dynamicEntries.forEach { item ->
|
item.savedFactor + ((i - mfIndex) * deltaGap)
|
||||||
val projectedValue = item.savedFactor + delta
|
|
||||||
if (projectedValue < minF || projectedValue > maxF) {
|
|
||||||
insideBounds = false
|
|
||||||
}
|
}
|
||||||
}
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
if (insideBounds) {
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
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++
|
refreshTrigger++
|
||||||
}
|
}
|
||||||
|
|
@ -477,6 +522,7 @@ fun Settings(
|
||||||
} else {
|
} else {
|
||||||
Spacer(modifier = Modifier.width(32.dp))
|
Spacer(modifier = Modifier.width(32.dp))
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(
|
Text(
|
||||||
text = dynamicItem.label.lowercase(),
|
text = dynamicItem.label.lowercase(),
|
||||||
style = MaterialTheme.typography.displaySmall.copy(
|
style = MaterialTheme.typography.displaySmall.copy(
|
||||||
|
|
@ -494,22 +540,23 @@ fun Settings(
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled) {
|
||||||
val oldValue = dynamicItem.savedFactor
|
val oldValue = dynamicItem.savedFactor
|
||||||
val delta = newValue - oldValue
|
val delta = newValue - oldValue
|
||||||
var insideBounds = true
|
|
||||||
|
|
||||||
dynamicEntries.forEach { item ->
|
if (delta != 0f) {
|
||||||
val projectedValue = item.savedFactor + delta
|
val deltaGap = delta
|
||||||
if (projectedValue < minF || projectedValue > maxF) {
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
insideBounds = false
|
item.savedFactor + ((i - mfIndex) * deltaGap)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
|
|
||||||
if (insideBounds) {
|
if (insideBounds && maintainsOrder) {
|
||||||
dynamicEntries.forEach { item ->
|
dynamicEntries.forEachIndexed { i, item ->
|
||||||
item.savedFactor = (item.savedFactor + delta).coerceIn(minF, maxF)
|
item.savedFactor = projected[i].coerceIn(minF, maxF)
|
||||||
}
|
}
|
||||||
refreshTrigger++
|
refreshTrigger++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
valueRange = minF..maxF,
|
valueRange = minF..maxF,
|
||||||
enabled = isDynamicEnabled,
|
enabled = isDynamicEnabled,
|
||||||
|
|
@ -527,7 +574,9 @@ fun Settings(
|
||||||
thumb = {
|
thumb = {
|
||||||
SliderDefaults.Thumb(
|
SliderDefaults.Thumb(
|
||||||
interactionSource = remember { MutableInteractionSource() },
|
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),
|
modifier = Modifier.size(12.dp),
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
@ -542,7 +591,10 @@ fun Settings(
|
||||||
)
|
)
|
||||||
|
|
||||||
Text(
|
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,
|
fontSize = 11.sp,
|
||||||
fontWeight = FontWeight.Bold,
|
fontWeight = FontWeight.Bold,
|
||||||
color = if (isDynamicEnabled) Color(0xFFDEFF9A) else Color.DarkGray,
|
color = if (isDynamicEnabled) Color(0xFFDEFF9A) else Color.DarkGray,
|
||||||
|
|
@ -555,18 +607,16 @@ fun Settings(
|
||||||
FilledIconButton(
|
FilledIconButton(
|
||||||
onClick = {
|
onClick = {
|
||||||
if (isDynamicEnabled) {
|
if (isDynamicEnabled) {
|
||||||
val delta = step
|
val deltaGap = -gapStep
|
||||||
var insideBounds = true
|
val projected = dynamicEntries.mapIndexed { i, item ->
|
||||||
dynamicEntries.forEach { item ->
|
item.savedFactor + ((i - mfIndex) * deltaGap)
|
||||||
val projectedValue = item.savedFactor + delta
|
|
||||||
if (projectedValue < minF || projectedValue > maxF) {
|
|
||||||
insideBounds = false
|
|
||||||
}
|
}
|
||||||
}
|
val insideBounds = projected.all { it in minF..maxF }
|
||||||
if (insideBounds) {
|
val maintainsOrder = projected.zipWithNext().all { (a, b) -> a < b }
|
||||||
dynamicEntries.forEach { item ->
|
|
||||||
item.savedFactor =
|
if (insideBounds && maintainsOrder) {
|
||||||
(item.savedFactor + delta).coerceIn(minF, maxF)
|
dynamicEntries.forEachIndexed { i, item ->
|
||||||
|
item.savedFactor = projected[i].coerceIn(minF, maxF)
|
||||||
}
|
}
|
||||||
refreshTrigger++
|
refreshTrigger++
|
||||||
}
|
}
|
||||||
|
|
@ -756,6 +806,8 @@ fun Settings(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
confirmButton = {
|
confirmButton = {
|
||||||
TextButton(onClick = onDismissRequest) {
|
TextButton(onClick = onDismissRequest) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue