Преглед на файлове

android: Allow SettingsItems to use String or StringRes

t895 преди 2 години
родител
ревизия
a251f77556
променени са 17 файла, в които са добавени 278 реда и са изтрити 214 реда
  1. 6 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt
  2. 5 2
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/HeaderSetting.kt
  3. 6 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/RunnableSetting.kt
  4. 133 100
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt
  5. 9 5
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt
  6. 9 6
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt
  7. 7 4
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt
  8. 6 4
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt
  9. 6 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt
  10. 30 34
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt
  11. 3 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt
  12. 1 1
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt
  13. 5 6
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/RunnableViewHolder.kt
  14. 37 24
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt
  15. 3 3
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt
  16. 8 8
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt
  17. 4 5
      src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt

+ 6 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/DateTimeSetting.kt

@@ -3,13 +3,16 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.AbstractLongSetting
 
 class DateTimeSetting(
     private val longSetting: AbstractLongSetting,
-    titleId: Int,
-    descriptionId: Int
-) : SettingsItem(longSetting, titleId, descriptionId) {
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = ""
+) : SettingsItem(longSetting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_DATETIME_SETTING
 
     fun getValue(needsGlobal: Boolean = false): Long = longSetting.getLong(needsGlobal)

+ 5 - 2
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/HeaderSetting.kt

@@ -3,8 +3,11 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
+
 class HeaderSetting(
-    titleId: Int
-) : SettingsItem(emptySetting, titleId, 0) {
+    @StringRes titleId: Int = 0,
+    titleString: String = ""
+) : SettingsItem(emptySetting, titleId, titleString, 0, "") {
     override val type = TYPE_HEADER
 }

+ 6 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/RunnableSetting.kt

@@ -4,13 +4,16 @@
 package org.yuzu.yuzu_emu.features.settings.model.view
 
 import androidx.annotation.DrawableRes
+import androidx.annotation.StringRes
 
 class RunnableSetting(
-    titleId: Int,
-    descriptionId: Int,
     val isRuntimeRunnable: Boolean,
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = "",
     @DrawableRes val iconId: Int = 0,
     val runnable: () -> Unit
-) : SettingsItem(emptySetting, titleId, descriptionId) {
+) : SettingsItem(emptySetting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_RUNNABLE
 }

+ 133 - 100
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt

@@ -3,8 +3,12 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.NativeLibrary
 import org.yuzu.yuzu_emu.R
+import org.yuzu.yuzu_emu.YuzuApplication
+import org.yuzu.yuzu_emu.features.input.NativeInput
+import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
 import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
 import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
@@ -23,13 +27,34 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
  */
 abstract class SettingsItem(
     val setting: AbstractSetting,
-    val nameId: Int,
-    val descriptionId: Int
+    @StringRes val titleId: Int,
+    val titleString: String,
+    @StringRes val descriptionId: Int,
+    val descriptionString: String
 ) {
     abstract val type: Int
 
+    val title: String by lazy {
+        if (titleId != 0) {
+            return@lazy YuzuApplication.appContext.getString(titleId)
+        }
+        return@lazy titleString
+    }
+
+    val description: String by lazy {
+        if (descriptionId != 0) {
+            return@lazy YuzuApplication.appContext.getString(descriptionId)
+        }
+        return@lazy descriptionString
+    }
+
     val isEditable: Boolean
         get() {
+            // Can't change docked mode toggle when using handheld mode
+            if (setting.key == BooleanSetting.USE_DOCKED_MODE.key) {
+                return NativeInput.getStyleIndex(0) != NpadStyleIndex.Handheld
+            }
+
             // Can't edit settings that aren't saveable in per-game config even if they are switchable
             if (NativeConfig.isPerGameConfigLoaded() && !setting.isSaveable) {
                 return false
@@ -59,6 +84,9 @@ abstract class SettingsItem(
         const val TYPE_STRING_SINGLE_CHOICE = 5
         const val TYPE_DATETIME_SETTING = 6
         const val TYPE_RUNNABLE = 7
+        const val TYPE_INPUT = 8
+        const val TYPE_INT_SINGLE_CHOICE = 9
+        const val TYPE_INPUT_PROFILE = 10
 
         const val FASTMEM_COMBINED = "fastmem_combined"
 
@@ -80,237 +108,242 @@ abstract class SettingsItem(
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_USE_SPEED_LIMIT,
-                    R.string.frame_limit_enable,
-                    R.string.frame_limit_enable_description
+                    titleId = R.string.frame_limit_enable,
+                    descriptionId = R.string.frame_limit_enable_description
                 )
             )
             put(
                 SliderSetting(
                     ShortSetting.RENDERER_SPEED_LIMIT,
-                    R.string.frame_limit_slider,
-                    R.string.frame_limit_slider_description,
-                    1,
-                    400,
-                    "%"
+                    titleId = R.string.frame_limit_slider,
+                    descriptionId = R.string.frame_limit_slider_description,
+                    min = 1,
+                    max = 400,
+                    units = "%"
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.CPU_BACKEND,
-                    R.string.cpu_backend,
-                    0,
-                    R.array.cpuBackendArm64Names,
-                    R.array.cpuBackendArm64Values
+                    titleId = R.string.cpu_backend,
+                    choicesId = R.array.cpuBackendArm64Names,
+                    valuesId = R.array.cpuBackendArm64Values
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.CPU_ACCURACY,
-                    R.string.cpu_accuracy,
-                    0,
-                    R.array.cpuAccuracyNames,
-                    R.array.cpuAccuracyValues
+                    titleId = R.string.cpu_accuracy,
+                    choicesId = R.array.cpuAccuracyNames,
+                    valuesId = R.array.cpuAccuracyValues
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.PICTURE_IN_PICTURE,
-                    R.string.picture_in_picture,
-                    R.string.picture_in_picture_description
+                    titleId = R.string.picture_in_picture,
+                    descriptionId = R.string.picture_in_picture_description
                 )
             )
+
+            val dockedModeSetting = object : AbstractBooleanSetting {
+                override val key = BooleanSetting.USE_DOCKED_MODE.key
+
+                override fun getBoolean(needsGlobal: Boolean): Boolean {
+                    if (NativeInput.getStyleIndex(0) == NpadStyleIndex.Handheld) {
+                        return false
+                    }
+                    return BooleanSetting.USE_DOCKED_MODE.getBoolean(needsGlobal)
+                }
+
+                override fun setBoolean(value: Boolean) =
+                    BooleanSetting.USE_DOCKED_MODE.setBoolean(value)
+
+                override val defaultValue = BooleanSetting.USE_DOCKED_MODE.defaultValue
+
+                override fun getValueAsString(needsGlobal: Boolean): String =
+                    BooleanSetting.USE_DOCKED_MODE.getValueAsString(needsGlobal)
+
+                override fun reset() = BooleanSetting.USE_DOCKED_MODE.reset()
+            }
             put(
                 SwitchSetting(
-                    BooleanSetting.USE_DOCKED_MODE,
-                    R.string.use_docked_mode,
-                    R.string.use_docked_mode_description
+                    dockedModeSetting,
+                    titleId = R.string.use_docked_mode,
+                    descriptionId = R.string.use_docked_mode_description
                 )
             )
+
             put(
                 SingleChoiceSetting(
                     IntSetting.REGION_INDEX,
-                    R.string.emulated_region,
-                    0,
-                    R.array.regionNames,
-                    R.array.regionValues
+                    titleId = R.string.emulated_region,
+                    choicesId = R.array.regionNames,
+                    valuesId = R.array.regionValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.LANGUAGE_INDEX,
-                    R.string.emulated_language,
-                    0,
-                    R.array.languageNames,
-                    R.array.languageValues
+                    titleId = R.string.emulated_language,
+                    choicesId = R.array.languageNames,
+                    valuesId = R.array.languageValues
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.USE_CUSTOM_RTC,
-                    R.string.use_custom_rtc,
-                    R.string.use_custom_rtc_description
+                    titleId = R.string.use_custom_rtc,
+                    descriptionId = R.string.use_custom_rtc_description
                 )
             )
-            put(DateTimeSetting(LongSetting.CUSTOM_RTC, R.string.set_custom_rtc, 0))
+            put(DateTimeSetting(LongSetting.CUSTOM_RTC, titleId = R.string.set_custom_rtc))
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_ACCURACY,
-                    R.string.renderer_accuracy,
-                    0,
-                    R.array.rendererAccuracyNames,
-                    R.array.rendererAccuracyValues
+                    titleId = R.string.renderer_accuracy,
+                    choicesId = R.array.rendererAccuracyNames,
+                    valuesId = R.array.rendererAccuracyValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_RESOLUTION,
-                    R.string.renderer_resolution,
-                    0,
-                    R.array.rendererResolutionNames,
-                    R.array.rendererResolutionValues
+                    titleId = R.string.renderer_resolution,
+                    choicesId = R.array.rendererResolutionNames,
+                    valuesId = R.array.rendererResolutionValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_VSYNC,
-                    R.string.renderer_vsync,
-                    0,
-                    R.array.rendererVSyncNames,
-                    R.array.rendererVSyncValues
+                    titleId = R.string.renderer_vsync,
+                    choicesId = R.array.rendererVSyncNames,
+                    valuesId = R.array.rendererVSyncValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_SCALING_FILTER,
-                    R.string.renderer_scaling_filter,
-                    0,
-                    R.array.rendererScalingFilterNames,
-                    R.array.rendererScalingFilterValues
+                    titleId = R.string.renderer_scaling_filter,
+                    choicesId = R.array.rendererScalingFilterNames,
+                    valuesId = R.array.rendererScalingFilterValues
                 )
             )
             put(
                 SliderSetting(
                     IntSetting.FSR_SHARPENING_SLIDER,
-                    R.string.fsr_sharpness,
-                    R.string.fsr_sharpness_description,
-                    0,
-                    100,
-                    "%"
+                    titleId = R.string.fsr_sharpness,
+                    descriptionId = R.string.fsr_sharpness_description,
+                    units = "%"
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_ANTI_ALIASING,
-                    R.string.renderer_anti_aliasing,
-                    0,
-                    R.array.rendererAntiAliasingNames,
-                    R.array.rendererAntiAliasingValues
+                    titleId = R.string.renderer_anti_aliasing,
+                    choicesId = R.array.rendererAntiAliasingNames,
+                    valuesId = R.array.rendererAntiAliasingValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_SCREEN_LAYOUT,
-                    R.string.renderer_screen_layout,
-                    0,
-                    R.array.rendererScreenLayoutNames,
-                    R.array.rendererScreenLayoutValues
+                    titleId = R.string.renderer_screen_layout,
+                    choicesId = R.array.rendererScreenLayoutNames,
+                    valuesId = R.array.rendererScreenLayoutValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_ASPECT_RATIO,
-                    R.string.renderer_aspect_ratio,
-                    0,
-                    R.array.rendererAspectRatioNames,
-                    R.array.rendererAspectRatioValues
+                    titleId = R.string.renderer_aspect_ratio,
+                    choicesId = R.array.rendererAspectRatioNames,
+                    valuesId = R.array.rendererAspectRatioValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.VERTICAL_ALIGNMENT,
-                    R.string.vertical_alignment,
-                    0,
-                    R.array.verticalAlignmentEntries,
-                    R.array.verticalAlignmentValues
+                    titleId = R.string.vertical_alignment,
+                    descriptionId = 0,
+                    choicesId = R.array.verticalAlignmentEntries,
+                    valuesId = R.array.verticalAlignmentValues
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_USE_DISK_SHADER_CACHE,
-                    R.string.use_disk_shader_cache,
-                    R.string.use_disk_shader_cache_description
+                    titleId = R.string.use_disk_shader_cache,
+                    descriptionId = R.string.use_disk_shader_cache_description
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_FORCE_MAX_CLOCK,
-                    R.string.renderer_force_max_clock,
-                    R.string.renderer_force_max_clock_description
+                    titleId = R.string.renderer_force_max_clock,
+                    descriptionId = R.string.renderer_force_max_clock_description
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_ASYNCHRONOUS_SHADERS,
-                    R.string.renderer_asynchronous_shaders,
-                    R.string.renderer_asynchronous_shaders_description
+                    titleId = R.string.renderer_asynchronous_shaders,
+                    descriptionId = R.string.renderer_asynchronous_shaders_description
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_REACTIVE_FLUSHING,
-                    R.string.renderer_reactive_flushing,
-                    R.string.renderer_reactive_flushing_description
+                    titleId = R.string.renderer_reactive_flushing,
+                    descriptionId = R.string.renderer_reactive_flushing_description
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.MAX_ANISOTROPY,
-                    R.string.anisotropic_filtering,
-                    R.string.anisotropic_filtering_description,
-                    R.array.anisoEntries,
-                    R.array.anisoValues
+                    titleId = R.string.anisotropic_filtering,
+                    descriptionId = R.string.anisotropic_filtering_description,
+                    choicesId = R.array.anisoEntries,
+                    valuesId = R.array.anisoValues
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.AUDIO_OUTPUT_ENGINE,
-                    R.string.audio_output_engine,
-                    0,
-                    R.array.outputEngineEntries,
-                    R.array.outputEngineValues
+                    titleId = R.string.audio_output_engine,
+                    choicesId = R.array.outputEngineEntries,
+                    valuesId = R.array.outputEngineValues
                 )
             )
             put(
                 SliderSetting(
                     ByteSetting.AUDIO_VOLUME,
-                    R.string.audio_volume,
-                    R.string.audio_volume_description,
-                    0,
-                    100,
-                    "%"
+                    titleId = R.string.audio_volume,
+                    descriptionId = R.string.audio_volume_description,
+                    units = "%"
                 )
             )
             put(
                 SingleChoiceSetting(
                     IntSetting.RENDERER_BACKEND,
-                    R.string.renderer_api,
-                    0,
-                    R.array.rendererApiNames,
-                    R.array.rendererApiValues
+                    titleId = R.string.renderer_api,
+                    choicesId = R.array.rendererApiNames,
+                    valuesId = R.array.rendererApiValues
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.RENDERER_DEBUG,
-                    R.string.renderer_debug,
-                    R.string.renderer_debug_description
+                    titleId = R.string.renderer_debug,
+                    descriptionId = R.string.renderer_debug_description
                 )
             )
             put(
                 SwitchSetting(
                     BooleanSetting.CPU_DEBUG_MODE,
-                    R.string.cpu_debug_mode,
-                    R.string.cpu_debug_mode_description
+                    titleId = R.string.cpu_debug_mode,
+                    descriptionId = R.string.cpu_debug_mode_description
                 )
             )
 
@@ -346,7 +379,7 @@ abstract class SettingsItem(
 
                 override fun reset() = setBoolean(defaultValue)
             }
-            put(SwitchSetting(fastmem, R.string.fastmem, 0))
+            put(SwitchSetting(fastmem, R.string.fastmem))
         }
     }
 }

+ 9 - 5
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SingleChoiceSetting.kt

@@ -3,16 +3,20 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.ArrayRes
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
 
 class SingleChoiceSetting(
     setting: AbstractSetting,
-    titleId: Int,
-    descriptionId: Int,
-    val choicesId: Int,
-    val valuesId: Int
-) : SettingsItem(setting, titleId, descriptionId) {
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = "",
+    @ArrayRes val choicesId: Int,
+    @ArrayRes val valuesId: Int
+) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_SINGLE_CHOICE
 
     fun getSelectedValue(needsGlobal: Boolean = false) =

+ 9 - 6
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SliderSetting.kt

@@ -3,6 +3,7 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.AbstractByteSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractFloatSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
@@ -12,12 +13,14 @@ import kotlin.math.roundToInt
 
 class SliderSetting(
     setting: AbstractSetting,
-    titleId: Int,
-    descriptionId: Int,
-    val min: Int,
-    val max: Int,
-    val units: String
-) : SettingsItem(setting, titleId, descriptionId) {
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = "",
+    val min: Int = 0,
+    val max: Int = 100,
+    val units: String = ""
+) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_SLIDER
 
     fun getSelectedValue(needsGlobal: Boolean = false) =

+ 7 - 4
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/StringSingleChoiceSetting.kt

@@ -3,15 +3,18 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.AbstractStringSetting
 
 class StringSingleChoiceSetting(
     private val stringSetting: AbstractStringSetting,
-    titleId: Int,
-    descriptionId: Int,
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = "",
     val choices: Array<String>,
     val values: Array<String>
-) : SettingsItem(stringSetting, titleId, descriptionId) {
+) : SettingsItem(stringSetting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_STRING_SINGLE_CHOICE
 
     fun getValueAt(index: Int): String =
@@ -20,7 +23,7 @@ class StringSingleChoiceSetting(
     fun getSelectedValue(needsGlobal: Boolean = false) = stringSetting.getString(needsGlobal)
     fun setSelectedValue(value: String) = stringSetting.setString(value)
 
-    val selectValueIndex: Int
+    val selectedValueIndex: Int
         get() {
             for (i in values.indices) {
                 if (values[i] == getSelectedValue()) {

+ 6 - 4
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SubmenuSetting.kt

@@ -8,10 +8,12 @@ import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.Settings
 
 class SubmenuSetting(
-    @StringRes titleId: Int,
-    @StringRes descriptionId: Int,
-    @DrawableRes val iconId: Int,
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = "",
+    @DrawableRes val iconId: Int = 0,
     val menuKey: Settings.MenuTag
-) : SettingsItem(emptySetting, titleId, descriptionId) {
+) : SettingsItem(emptySetting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_SUBMENU
 }

+ 6 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SwitchSetting.kt

@@ -3,15 +3,18 @@
 
 package org.yuzu.yuzu_emu.features.settings.model.view
 
+import androidx.annotation.StringRes
 import org.yuzu.yuzu_emu.features.settings.model.AbstractBooleanSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractIntSetting
 import org.yuzu.yuzu_emu.features.settings.model.AbstractSetting
 
 class SwitchSetting(
     setting: AbstractSetting,
-    titleId: Int,
-    descriptionId: Int
-) : SettingsItem(setting, titleId, descriptionId) {
+    @StringRes titleId: Int = 0,
+    titleString: String = "",
+    @StringRes descriptionId: Int = 0,
+    descriptionString: String = ""
+) : SettingsItem(setting, titleId, titleString, descriptionId, descriptionString) {
     override val type = TYPE_SWITCH
 
     fun getIsChecked(needsGlobal: Boolean = false): Boolean {

+ 30 - 34
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt

@@ -84,42 +84,41 @@ class SettingsFragmentPresenter(
         sl.apply {
             add(
                 SubmenuSetting(
-                    R.string.preferences_system,
-                    R.string.preferences_system_description,
-                    R.drawable.ic_system_settings,
-                    Settings.MenuTag.SECTION_SYSTEM
+                    titleId = R.string.preferences_system,
+                    descriptionId = R.string.preferences_system_description,
+                    iconId = R.drawable.ic_system_settings,
+                    menuKey = MenuTag.SECTION_SYSTEM
                 )
             )
             add(
                 SubmenuSetting(
-                    R.string.preferences_graphics,
-                    R.string.preferences_graphics_description,
-                    R.drawable.ic_graphics,
-                    Settings.MenuTag.SECTION_RENDERER
+                    titleId = R.string.preferences_graphics,
+                    descriptionId = R.string.preferences_graphics_description,
+                    iconId = R.drawable.ic_graphics,
+                    menuKey = MenuTag.SECTION_RENDERER
                 )
             )
             add(
                 SubmenuSetting(
-                    R.string.preferences_audio,
-                    R.string.preferences_audio_description,
-                    R.drawable.ic_audio,
-                    Settings.MenuTag.SECTION_AUDIO
+                    titleId = R.string.preferences_audio,
+                    descriptionId = R.string.preferences_audio_description,
+                    iconId = R.drawable.ic_audio,
+                    menuKey = MenuTag.SECTION_AUDIO
                 )
             )
             add(
                 SubmenuSetting(
-                    R.string.preferences_debug,
-                    R.string.preferences_debug_description,
-                    R.drawable.ic_code,
-                    Settings.MenuTag.SECTION_DEBUG
+                    titleId = R.string.preferences_debug,
+                    descriptionId = R.string.preferences_debug_description,
+                    iconId = R.drawable.ic_code,
+                    menuKey = MenuTag.SECTION_DEBUG
                 )
             )
             add(
                 RunnableSetting(
-                    R.string.reset_to_default,
-                    R.string.reset_to_default_description,
-                    false,
-                    R.drawable.ic_restore
+                    titleId = R.string.reset_to_default,
+                    descriptionId = R.string.reset_to_default_description,
+                    iconId = R.drawable.ic_restore
                 ) { settingsViewModel.setShouldShowResetSettingsDialog(true) }
             )
         }
@@ -186,20 +185,18 @@ class SettingsFragmentPresenter(
                 add(
                     SingleChoiceSetting(
                         theme,
-                        R.string.change_app_theme,
-                        0,
-                        R.array.themeEntriesA12,
-                        R.array.themeValuesA12
+                        titleId = R.string.change_app_theme,
+                        choicesId = R.array.themeEntriesA12,
+                        valuesId = R.array.themeValuesA12
                     )
                 )
             } else {
                 add(
                     SingleChoiceSetting(
                         theme,
-                        R.string.change_app_theme,
-                        0,
-                        R.array.themeEntries,
-                        R.array.themeValues
+                        titleId = R.string.change_app_theme,
+                        choicesId = R.array.themeEntries,
+                        valuesId = R.array.themeValues
                     )
                 )
             }
@@ -228,10 +225,9 @@ class SettingsFragmentPresenter(
             add(
                 SingleChoiceSetting(
                     themeMode,
-                    R.string.change_theme_mode,
-                    0,
-                    R.array.themeModeEntries,
-                    R.array.themeModeValues
+                    titleId = R.string.change_theme_mode,
+                    choicesId = R.array.themeModeEntries,
+                    valuesId = R.array.themeModeValues
                 )
             )
 
@@ -262,8 +258,8 @@ class SettingsFragmentPresenter(
             add(
                 SwitchSetting(
                     blackBackgrounds,
-                    R.string.use_black_backgrounds,
-                    R.string.use_black_backgrounds_description
+                    titleId = R.string.use_black_backgrounds,
+                    descriptionId = R.string.use_black_backgrounds_description
                 )
             )
         }

+ 3 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/DateTimeViewHolder.kt

@@ -21,9 +21,9 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
 
     override fun bind(item: SettingsItem) {
         setting = item as DateTimeSetting
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
-            binding.textSettingDescription.setText(item.descriptionId)
+        binding.textSettingName.text = item.title
+        if (setting.description.isNotEmpty()) {
+            binding.textSettingDescription.text = item.description
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
             binding.textSettingDescription.visibility = View.GONE

+ 1 - 1
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/HeaderViewHolder.kt

@@ -16,7 +16,7 @@ class HeaderViewHolder(val binding: ListItemSettingsHeaderBinding, adapter: Sett
     }
 
     override fun bind(item: SettingsItem) {
-        binding.textHeaderName.setText(item.nameId)
+        binding.textHeaderName.text = item.title
     }
 
     override fun onClick(clicked: View) {

+ 5 - 6
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/RunnableViewHolder.kt

@@ -5,7 +5,6 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
 
 import android.view.View
 import androidx.core.content.res.ResourcesCompat
-import org.yuzu.yuzu_emu.NativeLibrary
 import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
 import org.yuzu.yuzu_emu.features.settings.model.view.RunnableSetting
 import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
@@ -17,12 +16,12 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
 
     override fun bind(item: SettingsItem) {
         setting = item as RunnableSetting
-        if (item.iconId != 0) {
+        if (setting.iconId != 0) {
             binding.icon.visibility = View.VISIBLE
             binding.icon.setImageDrawable(
                 ResourcesCompat.getDrawable(
                     binding.icon.resources,
-                    item.iconId,
+                    setting.iconId,
                     binding.icon.context.theme
                 )
             )
@@ -30,8 +29,8 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
             binding.icon.visibility = View.GONE
         }
 
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
+        binding.textSettingName.text = setting.title
+        if (setting.description.isNotEmpty()) {
             binding.textSettingDescription.setText(item.descriptionId)
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
@@ -44,7 +43,7 @@ class RunnableViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
     }
 
     override fun onClick(clicked: View) {
-        if (!setting.isRuntimeRunnable && !NativeLibrary.isRunning()) {
+        if (setting.isRunnable) {
             setting.runnable.invoke()
         }
     }

+ 37 - 24
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SingleChoiceViewHolder.kt

@@ -5,6 +5,7 @@ package org.yuzu.yuzu_emu.features.settings.ui.viewholder
 
 import android.view.View
 import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
+import org.yuzu.yuzu_emu.features.settings.model.view.IntSingleChoiceSetting
 import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
 import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
 import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
@@ -17,30 +18,33 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
 
     override fun bind(item: SettingsItem) {
         setting = item
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
-            binding.textSettingDescription.setText(item.descriptionId)
+        binding.textSettingName.text = setting.title
+        if (item.description.isNotEmpty()) {
+            binding.textSettingDescription.text = item.description
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
             binding.textSettingDescription.visibility = View.GONE
         }
 
         binding.textSettingValue.visibility = View.VISIBLE
-        if (item is SingleChoiceSetting) {
-            val resMgr = binding.textSettingValue.context.resources
-            val values = resMgr.getIntArray(item.valuesId)
-            for (i in values.indices) {
-                if (values[i] == item.getSelectedValue()) {
-                    binding.textSettingValue.text = resMgr.getStringArray(item.choicesId)[i]
-                    break
+        when (item) {
+            is SingleChoiceSetting -> {
+                val resMgr = binding.textSettingValue.context.resources
+                val values = resMgr.getIntArray(item.valuesId)
+                for (i in values.indices) {
+                    if (values[i] == item.getSelectedValue()) {
+                        binding.textSettingValue.text = resMgr.getStringArray(item.choicesId)[i]
+                        break
+                    }
                 }
             }
-        } else if (item is StringSingleChoiceSetting) {
-            for (i in item.values.indices) {
-                if (item.values[i] == item.getSelectedValue()) {
-                    binding.textSettingValue.text = item.choices[i]
-                    break
-                }
+
+            is StringSingleChoiceSetting -> {
+                binding.textSettingValue.text = item.getSelectedValue()
+            }
+
+            is IntSingleChoiceSetting -> {
+                binding.textSettingValue.text = item.getChoiceAt(item.getSelectedValue())
             }
         }
 
@@ -63,16 +67,25 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
             return
         }
 
-        if (setting is SingleChoiceSetting) {
-            adapter.onSingleChoiceClick(
-                (setting as SingleChoiceSetting),
-                bindingAdapterPosition
-            )
-        } else if (setting is StringSingleChoiceSetting) {
-            adapter.onStringSingleChoiceClick(
-                (setting as StringSingleChoiceSetting),
+        when (setting) {
+            is SingleChoiceSetting -> adapter.onSingleChoiceClick(
+                setting as SingleChoiceSetting,
                 bindingAdapterPosition
             )
+
+            is StringSingleChoiceSetting -> {
+                adapter.onStringSingleChoiceClick(
+                    setting as StringSingleChoiceSetting,
+                    bindingAdapterPosition
+                )
+            }
+
+            is IntSingleChoiceSetting -> {
+                adapter.onIntSingleChoiceClick(
+                    setting as IntSingleChoiceSetting,
+                    bindingAdapterPosition
+                )
+            }
         }
     }
 

+ 3 - 3
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SliderViewHolder.kt

@@ -17,9 +17,9 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
 
     override fun bind(item: SettingsItem) {
         setting = item as SliderSetting
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
-            binding.textSettingDescription.setText(item.descriptionId)
+        binding.textSettingName.text = setting.title
+        if (item.description.isNotEmpty()) {
+            binding.textSettingDescription.text = setting.description
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
             binding.textSettingDescription.visibility = View.GONE

+ 8 - 8
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SubmenuViewHolder.kt

@@ -12,16 +12,16 @@ import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
 
 class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
     SettingViewHolder(binding.root, adapter) {
-    private lateinit var item: SubmenuSetting
+    private lateinit var setting: SubmenuSetting
 
     override fun bind(item: SettingsItem) {
-        this.item = item as SubmenuSetting
-        if (item.iconId != 0) {
+        setting = item as SubmenuSetting
+        if (setting.iconId != 0) {
             binding.icon.visibility = View.VISIBLE
             binding.icon.setImageDrawable(
                 ResourcesCompat.getDrawable(
                     binding.icon.resources,
-                    item.iconId,
+                    setting.iconId,
                     binding.icon.context.theme
                 )
             )
@@ -29,9 +29,9 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
             binding.icon.visibility = View.GONE
         }
 
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
-            binding.textSettingDescription.setText(item.descriptionId)
+        binding.textSettingName.text = setting.title
+        if (setting.description.isNotEmpty()) {
+            binding.textSettingDescription.text = setting.description
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
             binding.textSettingDescription.visibility = View.GONE
@@ -41,7 +41,7 @@ class SubmenuViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAd
     }
 
     override fun onClick(clicked: View) {
-        adapter.onSubmenuClick(item)
+        adapter.onSubmenuClick(setting)
     }
 
     override fun onLongClick(clicked: View): Boolean {

+ 4 - 5
src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/viewholder/SwitchSettingViewHolder.kt

@@ -18,19 +18,18 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
 
     override fun bind(item: SettingsItem) {
         setting = item as SwitchSetting
-        binding.textSettingName.setText(item.nameId)
-        if (item.descriptionId != 0) {
-            binding.textSettingDescription.setText(item.descriptionId)
+        binding.textSettingName.text = setting.title
+        if (setting.description.isNotEmpty()) {
+            binding.textSettingDescription.text = setting.description
             binding.textSettingDescription.visibility = View.VISIBLE
         } else {
-            binding.textSettingDescription.text = ""
             binding.textSettingDescription.visibility = View.GONE
         }
 
         binding.switchWidget.setOnCheckedChangeListener(null)
         binding.switchWidget.isChecked = setting.getIsChecked(setting.needsRuntimeGlobal)
         binding.switchWidget.setOnCheckedChangeListener { _: CompoundButton, _: Boolean ->
-            adapter.onBooleanClick(item, binding.switchWidget.isChecked, bindingAdapterPosition)
+            adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)
         }
 
         binding.buttonClear.visibility = if (setting.setting.global ||