Android: Support settings with float values

We did support float settings before but we never showed anything past the decimal place before.
This commit is contained in:
Charles Lombardo 2023-08-11 17:11:15 -04:00
parent 80b329b77f
commit 53fc3446d5
9 changed files with 132 additions and 62 deletions

View File

@ -6,7 +6,8 @@ import android.content.Context
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings import org.dolphinemu.dolphinemu.features.settings.model.Settings
import kotlin.math.roundToInt import java.math.BigDecimal
import java.math.MathContext
open class FloatSliderSetting : SliderSetting { open class FloatSliderSetting : SliderSetting {
var floatSetting: AbstractFloatSetting var floatSetting: AbstractFloatSetting
@ -19,11 +20,12 @@ open class FloatSliderSetting : SliderSetting {
setting: AbstractFloatSetting, setting: AbstractFloatSetting,
titleId: Int, titleId: Int,
descriptionId: Int, descriptionId: Int,
min: Int, min: Float,
max: Int, max: Float,
units: String?, units: String?,
stepSize: Int stepSize: Float,
) : super(context, titleId, descriptionId, min, max, units, stepSize) { showDecimal: Boolean
) : super(context, titleId, descriptionId, min, max, units, stepSize, showDecimal) {
floatSetting = setting floatSetting = setting
} }
@ -31,17 +33,21 @@ open class FloatSliderSetting : SliderSetting {
setting: AbstractFloatSetting, setting: AbstractFloatSetting,
name: CharSequence, name: CharSequence,
description: CharSequence?, description: CharSequence?,
min: Int, min: Float,
max: Int, max: Float,
units: String? units: String?,
) : super(name, description, min, max, units) { showDecimal: Boolean
) : super(name, description, min, max, units, showDecimal) {
floatSetting = setting floatSetting = setting
} }
override val selectedValue: Int override val selectedValue: Float
get() = floatSetting.float.roundToInt() get() = floatSetting.float
open fun setSelectedValue(settings: Settings?, selection: Float) { open fun setSelectedValue(settings: Settings?, selection: Float) {
floatSetting.setFloat(settings!!, selection) floatSetting.setFloat(
settings!!,
BigDecimal((selection).toDouble()).round(MathContext(3)).toFloat()
)
} }
} }

View File

@ -16,7 +16,7 @@ class IntSliderSetting(
max: Int, max: Int,
units: String?, units: String?,
stepSize: Int stepSize: Int
) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize) { ) : SliderSetting(context, titleId, descriptionId, min, max, units, stepSize, false) {
override val setting: AbstractSetting override val setting: AbstractSetting
get() = intSetting get() = intSetting

View File

@ -4,24 +4,38 @@ package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context import android.content.Context
import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting import org.dolphinemu.dolphinemu.features.settings.model.AbstractFloatSetting
import org.dolphinemu.dolphinemu.features.settings.model.AbstractSetting
import org.dolphinemu.dolphinemu.features.settings.model.Settings import org.dolphinemu.dolphinemu.features.settings.model.Settings
import kotlin.math.roundToInt import java.math.BigDecimal
import java.math.MathContext
class PercentSliderSetting( class PercentSliderSetting(
context: Context, context: Context,
override val setting: AbstractFloatSetting, override val setting: AbstractFloatSetting,
titleId: Int, titleId: Int,
descriptionId: Int, descriptionId: Int,
min: Int, min: Float,
max: Int, max: Float,
units: String?, units: String?,
stepSize: Int stepSize: Float,
) : FloatSliderSetting(context, setting, titleId, descriptionId, min, max, units, stepSize) { showDecimal: Boolean
override val selectedValue: Int ) : FloatSliderSetting(
get() = (floatSetting.float * 100).roundToInt() context,
setting,
titleId,
descriptionId,
min,
max,
units,
stepSize,
showDecimal
) {
override val selectedValue: Float
get() = (floatSetting.float * 100)
override fun setSelectedValue(settings: Settings?, selection: Float) { override fun setSelectedValue(settings: Settings?, selection: Float) {
floatSetting.setFloat(settings!!, selection / 100) floatSetting.setFloat(
settings!!,
BigDecimal((selection / 100).toDouble()).round(MathContext(3)).toFloat()
)
} }
} }

View File

@ -4,44 +4,50 @@ package org.dolphinemu.dolphinemu.features.settings.model.view
import android.content.Context import android.content.Context
abstract class SliderSetting : SettingsItem { sealed class SliderSetting : SettingsItem {
override val type: Int = TYPE_SLIDER override val type: Int = TYPE_SLIDER
var min: Int var min: Any
private set private set
var max: Int var max: Any
private set private set
var units: String? var units: String?
private set private set
var stepSize = 0 var stepSize: Any = 0
private set
var showDecimal: Boolean = false
private set private set
constructor( constructor(
context: Context, context: Context,
nameId: Int, nameId: Int,
descriptionId: Int, descriptionId: Int,
min: Int, min: Any,
max: Int, max: Any,
units: String?, units: String?,
stepSize: Int stepSize: Any,
showDecimal: Boolean
) : super(context, nameId, descriptionId) { ) : super(context, nameId, descriptionId) {
this.min = min this.min = min
this.max = max this.max = max
this.units = units this.units = units
this.stepSize = stepSize this.stepSize = stepSize
this.showDecimal = showDecimal
} }
constructor( constructor(
name: CharSequence, name: CharSequence,
description: CharSequence?, description: CharSequence?,
min: Int, min: Any,
max: Int, max: Any,
units: String? units: String?,
showDecimal: Boolean
) : super(name, description) { ) : super(name, description) {
this.min = min this.min = min
this.max = max this.max = max
this.units = units this.units = units
this.showDecimal = showDecimal
} }
abstract val selectedValue: Int abstract val selectedValue: Any
} }

View File

@ -19,6 +19,7 @@ enum class MenuTag {
DEBUG("debug"), DEBUG("debug"),
GRAPHICS("graphics"), GRAPHICS("graphics"),
ENHANCEMENTS("enhancements"), ENHANCEMENTS("enhancements"),
COLOR_CORRECTION("color_correction"),
STEREOSCOPY("stereoscopy"), STEREOSCOPY("stereoscopy"),
HACKS("hacks"), HACKS("hacks"),
STATISTICS("statistics"), STATISTICS("statistics"),

View File

@ -51,7 +51,7 @@ class SettingsAdapter(
private var settingsList: ArrayList<SettingsItem>? = null private var settingsList: ArrayList<SettingsItem>? = null
private var clickedItem: SettingsItem? = null private var clickedItem: SettingsItem? = null
private var clickedPosition: Int = -1 private var clickedPosition: Int = -1
private var seekbarProgress = 0 private var seekbarProgress: Float = 0f
private var dialog: AlertDialog? = null private var dialog: AlertDialog? = null
private var textSliderValue: TextView? = null private var textSliderValue: TextView? = null
@ -229,21 +229,37 @@ class SettingsAdapter(
fun onSliderClick(item: SliderSetting, position: Int) { fun onSliderClick(item: SliderSetting, position: Int) {
clickedItem = item clickedItem = item
clickedPosition = position clickedPosition = position
seekbarProgress = item.selectedValue seekbarProgress = when (item) {
is FloatSliderSetting -> item.selectedValue
is IntSliderSetting -> item.selectedValue.toFloat()
}
val inflater = LayoutInflater.from(fragmentView.fragmentActivity) val inflater = LayoutInflater.from(fragmentView.fragmentActivity)
val binding = DialogSliderBinding.inflate(inflater) val binding = DialogSliderBinding.inflate(inflater)
textSliderValue = binding.textValue textSliderValue = binding.textValue
textSliderValue!!.text = seekbarProgress.toString() textSliderValue!!.text = if (item.showDecimal) {
String.format("%.2f", seekbarProgress)
} else {
seekbarProgress.toInt().toString()
}
binding.textUnits.text = item.units binding.textUnits.text = item.units
val slider = binding.slider val slider = binding.slider
slider.valueFrom = item.min.toFloat() when (item) {
slider.valueTo = item.max.toFloat() is FloatSliderSetting -> {
slider.value = seekbarProgress.toFloat() slider.valueFrom = item.min as Float
slider.stepSize = item.stepSize.toFloat() slider.valueTo = item.max as Float
slider.stepSize = item.stepSize as Float
}
is IntSliderSetting -> {
slider.valueFrom = (item.min as Int).toFloat()
slider.valueTo = (item.max as Int).toFloat()
slider.stepSize = (item.stepSize as Int).toFloat()
}
}
slider.value = seekbarProgress
slider.addOnChangeListener(this) slider.addOnChangeListener(this)
dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity) dialog = MaterialAlertDialogBuilder(fragmentView.fragmentActivity)
@ -480,8 +496,10 @@ class SettingsAdapter(
} }
is IntSliderSetting -> { is IntSliderSetting -> {
val sliderSetting = clickedItem as IntSliderSetting val sliderSetting = clickedItem as IntSliderSetting
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged() if (sliderSetting.selectedValue != seekbarProgress.toInt()) {
sliderSetting.setSelectedValue(settings, seekbarProgress) fragmentView.onSettingChanged()
}
sliderSetting.setSelectedValue(settings, seekbarProgress.toInt())
closeDialog() closeDialog()
} }
is FloatSliderSetting -> { is FloatSliderSetting -> {
@ -489,13 +507,13 @@ class SettingsAdapter(
if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged() if (sliderSetting.selectedValue != seekbarProgress) fragmentView.onSettingChanged()
sliderSetting.setSelectedValue(settings, seekbarProgress.toFloat()) sliderSetting.setSelectedValue(settings, seekbarProgress)
closeDialog() closeDialog()
} }
} }
clickedItem = null clickedItem = null
seekbarProgress = -1 seekbarProgress = -1f
} }
fun closeDialog() { fun closeDialog() {
@ -510,8 +528,12 @@ class SettingsAdapter(
} }
override fun onValueChange(slider: Slider, progress: Float, fromUser: Boolean) { override fun onValueChange(slider: Slider, progress: Float, fromUser: Boolean) {
seekbarProgress = progress.toInt() seekbarProgress = progress
textSliderValue!!.text = seekbarProgress.toString() textSliderValue!!.text = if ((clickedItem as SliderSetting).showDecimal) {
String.format("%.2f", seekbarProgress)
} else {
seekbarProgress.toInt().toString()
}
} }
private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int { private fun getValueForSingleChoiceSelection(item: SingleChoiceSetting, which: Int): Int {

View File

@ -34,6 +34,7 @@ import org.dolphinemu.dolphinemu.model.GpuDriverMetadata
import org.dolphinemu.dolphinemu.ui.main.MainPresenter import org.dolphinemu.dolphinemu.ui.main.MainPresenter
import org.dolphinemu.dolphinemu.utils.* import org.dolphinemu.dolphinemu.utils.*
import java.util.* import java.util.*
import kotlin.collections.ArrayList
import kotlin.math.ceil import kotlin.math.ceil
import kotlin.math.floor import kotlin.math.floor
@ -119,6 +120,7 @@ class SettingsFragmentPresenter(
MenuTag.GCPAD_TYPE -> addGcPadSettings(sl) MenuTag.GCPAD_TYPE -> addGcPadSettings(sl)
MenuTag.WIIMOTE -> addWiimoteSettings(sl) MenuTag.WIIMOTE -> addWiimoteSettings(sl)
MenuTag.ENHANCEMENTS -> addEnhanceSettings(sl) MenuTag.ENHANCEMENTS -> addEnhanceSettings(sl)
MenuTag.COLOR_CORRECTION -> addColorCorrectionSettings(sl)
MenuTag.STEREOSCOPY -> addStereoSettings(sl) MenuTag.STEREOSCOPY -> addStereoSettings(sl)
MenuTag.HACKS -> addHackSettings(sl) MenuTag.HACKS -> addHackSettings(sl)
MenuTag.STATISTICS -> addStatisticsSettings(sl) MenuTag.STATISTICS -> addStatisticsSettings(sl)
@ -249,10 +251,11 @@ class SettingsFragmentPresenter(
FloatSetting.MAIN_EMULATION_SPEED, FloatSetting.MAIN_EMULATION_SPEED,
R.string.speed_limit, R.string.speed_limit,
0, 0,
0, 0f,
200, 200f,
"%", "%",
1 1f,
false
) )
) )
sl.add( sl.add(
@ -1000,10 +1003,11 @@ class SettingsFragmentPresenter(
FloatSetting.MAIN_OVERCLOCK, FloatSetting.MAIN_OVERCLOCK,
R.string.overclock_title, R.string.overclock_title,
R.string.overclock_title_description, R.string.overclock_title_description,
0, 0f,
400, 400f,
"%", "%",
1 1f,
false
) )
) )
@ -2349,9 +2353,10 @@ class SettingsFragmentPresenter(
InputMappingDoubleSetting(setting), InputMappingDoubleSetting(setting),
setting.getUiName(), setting.getUiName(),
"", "",
ceil(setting.getDoubleMin()).toInt(), ceil(setting.getDoubleMin()).toFloat(),
floor(setting.getDoubleMax()).toInt(), floor(setting.getDoubleMax()).toFloat(),
setting.getUiSuffix() setting.getUiSuffix(),
false
) )
) )

View File

@ -7,6 +7,7 @@ import android.text.TextUtils
import android.view.View import android.view.View
import org.dolphinemu.dolphinemu.R import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.IntSliderSetting
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
@ -14,7 +15,7 @@ import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
class SliderViewHolder( class SliderViewHolder(
private val binding: ListItemSettingBinding, adapter: SettingsAdapter?, private val binding: ListItemSettingBinding, adapter: SettingsAdapter?,
private val context: Context private val context: Context
) : SettingViewHolder(binding.getRoot(), adapter!!) { ) : SettingViewHolder(binding.root, adapter!!) {
private lateinit var setting: SliderSetting private lateinit var setting: SliderSetting
override val item: SettingsItem override val item: SettingsItem
@ -28,11 +29,25 @@ class SliderViewHolder(
if (!TextUtils.isEmpty(item.description)) { if (!TextUtils.isEmpty(item.description)) {
binding.textSettingDescription.text = item.description binding.textSettingDescription.text = item.description
} else { } else {
binding.textSettingDescription.text = context.getString( val selectedValue: Float = if (item is IntSliderSetting) {
R.string.slider_setting_value, (setting.selectedValue as Int).toFloat()
setting.selectedValue, } else {
setting.units setting.selectedValue as Float
) }
if (setting.showDecimal) {
binding.textSettingDescription.text = String.format(
context.getString(R.string.slider_setting_float_value),
selectedValue,
setting.units
)
} else {
binding.textSettingDescription.text = String.format(
context.getString(R.string.slider_setting_value),
selectedValue,
setting.units
)
}
} }
setStyle(binding.textSettingName, setting) setStyle(binding.textSettingName, setting)

View File

@ -632,7 +632,8 @@ It can efficiently compress both junk data and encrypted Wii data.
<!-- Misc --> <!-- Misc -->
<string name="enabled">Enabled</string> <string name="enabled">Enabled</string>
<string name="default_values">Default Values</string> <string name="default_values">Default Values</string>
<string name="slider_setting_value">%1$d%2$s</string> <string name="slider_setting_value">%.0f%2$s</string>
<string name="slider_setting_float_value">%.2f%2$s</string>
<string name="disc_number">Disc %1$d</string> <string name="disc_number">Disc %1$d</string>
<string name="replug_gc_adapter">GameCube Adapter couldn\'t be opened. Please re-plug the device.</string> <string name="replug_gc_adapter">GameCube Adapter couldn\'t be opened. Please re-plug the device.</string>
<string name="disabled_gc_overlay_notice">The selected GameCube controller is set to \"None\"</string> <string name="disabled_gc_overlay_notice">The selected GameCube controller is set to \"None\"</string>