This file was deleted.

@@ -0,0 +1,98 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.settings.ui.viewholder

import android.text.TextUtils
import android.view.View
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSetting
import org.dolphinemu.dolphinemu.features.settings.model.view.SingleChoiceSettingDynamicDescriptions
import org.dolphinemu.dolphinemu.features.settings.model.view.StringSingleChoiceSetting
import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter

class SingleChoiceViewHolder(
private val binding: ListItemSettingBinding,
adapter: SettingsAdapter
) : SettingViewHolder(binding.getRoot(), adapter) {
override var item: SettingsItem? = null

override fun bind(item: SettingsItem) {
this.item = item

binding.textSettingName.text = item.name

if (!TextUtils.isEmpty(item.description)) {
binding.textSettingDescription.text = item.description
} else if (item is SingleChoiceSetting) {
val selected = item.selectedValue
val resources = binding.textSettingDescription.context.resources
val choices = resources.getStringArray(item.choicesId)
val values = resources.getIntArray(item.valuesId)
for (i in values.indices) {
if (values[i] == selected) {
binding.textSettingDescription.text = choices[i]
}
}
} else if (item is StringSingleChoiceSetting) {
val choice = item.selectedChoice
binding.textSettingDescription.text = choice
} else if (item is SingleChoiceSettingDynamicDescriptions) {
val selected = item.selectedValue
val resMgr = binding.textSettingDescription.context.resources
val choices = resMgr.getStringArray(item.descriptionChoicesId)
val values = resMgr.getIntArray(item.descriptionValuesId)
for (i in values.indices) {
if (values[i] == selected) {
binding.textSettingDescription.text = choices[i]
}
}
}

var menuTag: MenuTag? = null
var selectedValue = 0
if (item is SingleChoiceSetting) {
menuTag = item.menuTag
selectedValue = item.selectedValue
} else if (item is StringSingleChoiceSetting) {
menuTag = item.menuTag
selectedValue = item.selectedValueIndex
}

if (menuTag != null && adapter.hasMenuTagActionForValue(menuTag, selectedValue)) {
binding.buttonMoreSettings.visibility = View.VISIBLE

binding.buttonMoreSettings.setOnClickListener {
adapter.onMenuTagAction(menuTag, selectedValue)
}
} else {
binding.buttonMoreSettings.visibility = View.GONE
}
setStyle(binding.textSettingName, item)
}

override fun onClick(clicked: View) {
if (!item?.isEditable!!) {
showNotRuntimeEditableError()
return
}

val position = bindingAdapterPosition
when (item) {
is SingleChoiceSetting -> {
adapter.onSingleChoiceClick(item as SingleChoiceSetting, position)
}
is StringSingleChoiceSetting -> {
adapter.onStringSingleChoiceClick(item as StringSingleChoiceSetting, position)
}
is SingleChoiceSettingDynamicDescriptions -> {
adapter.onSingleChoiceDynamicDescriptionsClick(
item as SingleChoiceSettingDynamicDescriptions,
position
)
}
}
setStyle(binding.textSettingName, item!!)
}
}

This file was deleted.

@@ -0,0 +1,51 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.settings.ui.viewholder

import android.content.Context
import android.text.TextUtils
import android.view.View
import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.databinding.ListItemSettingBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SliderSetting
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter

class SliderViewHolder(
private val binding: ListItemSettingBinding, adapter: SettingsAdapter?,
private val context: Context
) : SettingViewHolder(binding.getRoot(), adapter!!) {
private lateinit var setting: SliderSetting

override val item: SettingsItem
get() = setting

override fun bind(item: SettingsItem) {
setting = item as SliderSetting

binding.textSettingName.text = item.name

if (!TextUtils.isEmpty(item.description)) {
binding.textSettingDescription.text = item.description
} else {
binding.textSettingDescription.text = context.getString(
R.string.slider_setting_value,
setting.selectedValue,
setting.units
)
}

setStyle(binding.textSettingName, setting)
}

override fun onClick(clicked: View) {
if (!setting.isEditable) {
showNotRuntimeEditableError()
return
}

adapter.onSliderClick(setting, bindingAdapterPosition)

setStyle(binding.textSettingName, setting)
}
}

This file was deleted.

@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.settings.ui.viewholder

import android.view.View
import org.dolphinemu.dolphinemu.databinding.ListItemSubmenuBinding
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SubmenuSetting
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter

class SubmenuViewHolder(
private val mBinding: ListItemSubmenuBinding,
adapter: SettingsAdapter
) : SettingViewHolder(mBinding.root, adapter) {
private lateinit var setting: SubmenuSetting

override val item: SettingsItem
get() = setting

override fun bind(item: SettingsItem) {
setting = item as SubmenuSetting
mBinding.textSettingName.text = item.name
}

override fun onClick(clicked: View) {
adapter.onSubmenuClick(setting)
}
}

This file was deleted.

@@ -0,0 +1,82 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.settings.ui.viewholder

import android.view.View
import android.widget.CompoundButton
import org.dolphinemu.dolphinemu.databinding.ListItemSettingSwitchBinding
import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem
import org.dolphinemu.dolphinemu.features.settings.model.view.SwitchSetting
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
import java.io.File
import java.util.*

class SwitchSettingViewHolder(
private val binding: ListItemSettingSwitchBinding,
adapter: SettingsAdapter
) : SettingViewHolder(binding.root, adapter) {
private lateinit var setting: SwitchSetting

override val item: SettingsItem
get() = setting

private var iplExists = false

override fun bind(item: SettingsItem) {
setting = item as SwitchSetting

binding.textSettingName.text = item.name
binding.textSettingDescription.text = item.description

binding.settingSwitch.isChecked = setting.isChecked
binding.settingSwitch.isEnabled = setting.isEditable

// Check for IPL to make sure user can skip.
if (setting.setting === BooleanSetting.MAIN_SKIP_IPL) {
val iplDirs = ArrayList(listOf("USA", "JAP", "EUR"))
for (dir in iplDirs) {
val iplFile = File(
DirectoryInitialization.getUserDirectory(),
File.separator + "GC" + File.separator + dir + File.separator + "IPL.bin"
)
if (iplFile.exists()) {
iplExists = true
break
}
}
binding.settingSwitch.isEnabled = iplExists || !setting.isChecked
}

binding.settingSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean ->
// If a user has skip IPL disabled previously and deleted their IPL file, we need to allow
// them to skip it or else their game will appear broken. However, once this is enabled, we
// need to disable the option again to prevent the same issue from occurring.
if (setting.setting === BooleanSetting.MAIN_SKIP_IPL && !iplExists && isChecked) {
binding.settingSwitch.isEnabled = false
}

adapter.onBooleanClick(setting, binding.settingSwitch.isChecked)

setStyle(binding.textSettingName, setting)
}
setStyle(binding.textSettingName, setting)
}

override fun onClick(clicked: View) {
if (!setting.isEditable) {
showNotRuntimeEditableError()
return
}

if (setting.setting === BooleanSetting.MAIN_SKIP_IPL && !iplExists) {
if (setting.isChecked) {
showIplNotAvailableError()
return
}
}

binding.settingSwitch.toggle()
}
}

This file was deleted.

@@ -0,0 +1,107 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.features.settings.utils

import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivityView
import org.dolphinemu.dolphinemu.utils.BiMap
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
import org.dolphinemu.dolphinemu.utils.IniFile
import org.dolphinemu.dolphinemu.utils.Log
import java.io.File

/**
* Contains static methods for interacting with .ini files in which settings are stored.
*/
object SettingsFile {
const val KEY_ISO_PATH_BASE = "ISOPath"
const val KEY_ISO_PATHS = "ISOPaths"
private val sectionsMap = BiMap<String?, String?>()

init {
sectionsMap.apply {
add("Hardware", "Video_Hardware")
add("Settings", "Video_Settings")
add("Enhancements", "Video_Enhancements")
add("Stereoscopy", "Video_Stereoscopy")
add("Hacks", "Video_Hacks")
add("GameSpecific", "Video")
}
}

/**
* Reads a given .ini file from disk and returns it.
* If unsuccessful, outputs an error telling why it failed.
*
* @param file The ini file to load the settings from
* @param ini The object to load into
* @param view The current view.
*/
private fun readFile(file: File, ini: IniFile, view: SettingsActivityView) {
if (!ini.load(file, true)) {
Log.error("[SettingsFile] Error reading from: " + file.absolutePath)
view.onSettingsFileNotFound()
}
}

fun readFile(fileName: String, ini: IniFile, view: SettingsActivityView) {
readFile(getSettingsFile(fileName), ini, view)
}

/**
* Reads a given .ini file from disk and returns it.
* If unsuccessful, outputs an error telling why it failed.
*
* @param gameId the id of the game to load settings for.
* @param ini The object to load into
* @param view The current view.
*/
fun readCustomGameSettings(
gameId: String,
ini: IniFile,
view: SettingsActivityView
) {
readFile(getCustomGameSettingsFile(gameId), ini, view)
}

/**
* Saves a given .ini file on disk.
* If unsuccessful, outputs an error telling why it failed.
*
* @param fileName The target filename without a path or extension.
* @param ini The IniFile we want to serialize.
* @param view The current view.
*/
fun saveFile(fileName: String, ini: IniFile, view: SettingsActivityView) {
if (!ini.save(getSettingsFile(fileName))) {
Log.error("[SettingsFile] Error saving to: $fileName.ini")
view.showToastMessage("Error saving $fileName.ini")
}
}

fun saveCustomGameSettings(gameId: String, ini: IniFile) {
ini.save(getCustomGameSettingsFile(gameId))
}

fun mapSectionNameFromIni(generalSectionName: String): String? {
return if (sectionsMap.getForward(generalSectionName) != null) {
sectionsMap.getForward(generalSectionName)
} else generalSectionName
}

fun mapSectionNameToIni(generalSectionName: String): String? {
return if (sectionsMap.getBackward(generalSectionName) != null) {
sectionsMap.getBackward(generalSectionName)
} else generalSectionName
}

@JvmStatic
fun getSettingsFile(fileName: String): File {
return File(DirectoryInitialization.getUserDirectory() + "/Config/" + fileName + ".ini")
}

private fun getCustomGameSettingsFile(gameId: String): File {
return File(
DirectoryInitialization.getUserDirectory() + "/GameSettings/" + gameId + ".ini"
)
}
}
@@ -0,0 +1,24 @@
// SPDX-License-Identifier: GPL-2.0-or-later

package org.dolphinemu.dolphinemu.utils

import android.content.Intent
import android.os.Build
import android.os.Bundle
import java.io.Serializable

object SerializableHelper {
inline fun <reified T : Serializable> Intent.serializable(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
getSerializableExtra(key, T::class.java)
else
getSerializableExtra(key) as T?
}

inline fun <reified T : Serializable> Bundle.serializable(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
getSerializable(key, T::class.java)
else
getSerializable(key) as T?
}
}