mirror of
https://github.com/Lime3DS/Lime3DS.git
synced 2026-06-02 04:55:28 -06:00
Added Multi Choice Impl. Need to Refactor OnClick for MultiChoice and debug Impl when adding combo button.
This commit is contained in:
parent
77081d002a
commit
bfcafccb8e
@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractMultiBooleanSetting : AbstractSetting {
|
||||
var booleans: List<Boolean>
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractMultiFloatSetting : AbstractSetting {
|
||||
var floats: List<Float>
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractMultiIntSetting : AbstractSetting {
|
||||
var ints: List<Int>
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractMultiShortSetting : AbstractSetting {
|
||||
var shorts: List<Short>
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model
|
||||
|
||||
interface AbstractMultiStringSetting : AbstractSetting {
|
||||
var strings: List<String>
|
||||
}
|
||||
@ -4,9 +4,9 @@
|
||||
|
||||
package org.citra.citra_emu.features.settings.model.view
|
||||
|
||||
import org.citra.citra_emu.features.settings.model.AbstractIntSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractMultiIntSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting
|
||||
|
||||
class MultiChoiceSetting(
|
||||
setting: AbstractSetting?,
|
||||
@ -15,26 +15,26 @@ class MultiChoiceSetting(
|
||||
val choicesId: Int,
|
||||
val valuesId: Int,
|
||||
val key: String? = null,
|
||||
val defaultValues: Int? = null,
|
||||
val defaultValues: List<Int>? = null,
|
||||
override var isEnabled: Boolean = true
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_MULTI_CHOICE
|
||||
|
||||
val selectedValue: Int
|
||||
val selectedValues: List<Int>
|
||||
get() {
|
||||
if (setting == null) {
|
||||
return defaultValues!!
|
||||
}
|
||||
|
||||
try {
|
||||
val setting = setting as AbstractIntSetting
|
||||
return setting.int
|
||||
val setting = setting as AbstractMultiIntSetting
|
||||
return setting.ints
|
||||
} catch (_: ClassCastException) {
|
||||
}
|
||||
|
||||
try {
|
||||
val setting = setting as AbstractShortSetting
|
||||
return setting.short.toInt()
|
||||
val setting = setting as AbstractMultiShortSetting
|
||||
return setting.shorts.map { it.toInt() }
|
||||
} catch (_: ClassCastException) {
|
||||
}
|
||||
|
||||
@ -48,15 +48,15 @@ class MultiChoiceSetting(
|
||||
* @param selection New value of the int.
|
||||
* @return the existing setting with the new value applied.
|
||||
*/
|
||||
fun setSelectedValue(selection: Int): AbstractIntSetting {
|
||||
val intSetting = setting as AbstractIntSetting
|
||||
intSetting.int = selection
|
||||
fun setSelectedValues(selection: List<Int>): AbstractMultiIntSetting {
|
||||
val intSetting = setting as AbstractMultiIntSetting
|
||||
intSetting.ints = selection
|
||||
return intSetting
|
||||
}
|
||||
|
||||
fun setSelectedValue(selection: Short): AbstractShortSetting {
|
||||
val shortSetting = setting as AbstractShortSetting
|
||||
shortSetting.short = selection
|
||||
fun setSelectedValues(selection: List<Short>): AbstractMultiShortSetting {
|
||||
val shortSetting = setting as AbstractMultiShortSetting
|
||||
shortSetting.shorts = selection
|
||||
return shortSetting
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,5 +48,6 @@ abstract class SettingsItem(
|
||||
const val TYPE_STRING_INPUT = 9
|
||||
const val TYPE_FLOAT_INPUT = 10
|
||||
const val TYPE_MULTI_CHOICE = 11
|
||||
const val TYPE_STRING_MULTI_CHOICE = 12
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,92 @@
|
||||
// Copyright 2023 Citra Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.model.view
|
||||
|
||||
import org.citra.citra_emu.features.settings.model.AbstractSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting
|
||||
|
||||
class StringMultiChoiceSetting(
|
||||
setting: AbstractSetting?,
|
||||
titleId: Int,
|
||||
descriptionId: Int,
|
||||
val choices: Array<String>,
|
||||
val values: Array<String>?,
|
||||
val key: String? = null,
|
||||
private val defaultValue: List<String>? = null,
|
||||
override var isEnabled: Boolean = true
|
||||
) : SettingsItem(setting, titleId, descriptionId) {
|
||||
override val type = TYPE_STRING_MULTI_CHOICE
|
||||
|
||||
fun getValueAt(index: Int): String? {
|
||||
if (values == null) return null
|
||||
return if (index >= 0 && index < values.size) {
|
||||
values[index]
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
val selectedValues: List<String>
|
||||
get() {
|
||||
if (setting == null) {
|
||||
return defaultValue!!
|
||||
}
|
||||
|
||||
try {
|
||||
val setting = setting as AbstractMultiStringSetting
|
||||
return setting.strings
|
||||
} catch (_: ClassCastException) {
|
||||
}
|
||||
|
||||
try {
|
||||
val setting = setting as AbstractMultiShortSetting
|
||||
return setting.shorts.map { it.toString() }
|
||||
} catch (_: ClassCastException) {
|
||||
}
|
||||
return defaultValue!!
|
||||
}
|
||||
val selectValueIndices: BooleanArray
|
||||
get() {
|
||||
val noneList = values?.let {
|
||||
ArrayList(BooleanArray(it.size) { false }.toList())
|
||||
} ?: ArrayList()
|
||||
|
||||
val chosenindices = mutableListOf<Boolean>()
|
||||
val selectedValues = selectedValues
|
||||
for (i in values!!.indices) {
|
||||
if (values[i] in selectedValues) {
|
||||
chosenindices.add(true)
|
||||
} else {
|
||||
chosenindices.add(false)
|
||||
}
|
||||
}
|
||||
if (chosenindices == null) {
|
||||
return noneList.toBooleanArray()
|
||||
} else {
|
||||
return chosenindices.toBooleanArray()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a value to the backing int. If that int was previously null,
|
||||
* initializes a new one and returns it, so it can be added to the Hashmap.
|
||||
*
|
||||
* @param selection New value of the int.
|
||||
* @return the existing setting with the new value applied.
|
||||
*/
|
||||
fun setSelectedValues(selection: List<String>): AbstractMultiStringSetting {
|
||||
val stringSetting = setting as AbstractMultiStringSetting
|
||||
stringSetting.strings = selection
|
||||
return stringSetting
|
||||
}
|
||||
|
||||
fun setSelectedValues(selection: List<Short>): AbstractMultiShortSetting {
|
||||
val shortSetting = setting as AbstractMultiShortSetting
|
||||
shortSetting.shorts = selection
|
||||
return shortSetting
|
||||
}
|
||||
}
|
||||
@ -45,16 +45,19 @@ import org.citra.citra_emu.features.settings.model.ScaledFloatSetting
|
||||
import org.citra.citra_emu.features.settings.model.AbstractShortSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.DateTimeSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.InputBindingSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||
import org.citra.citra_emu.features.settings.model.view.SingleChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SliderSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.StringInputSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.StringSingleChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SubmenuSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SwitchSetting
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.DateTimeViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.HeaderViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.InputBindingSettingViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.MultiChoiceViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.RunnableViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.SettingViewHolder
|
||||
import org.citra.citra_emu.features.settings.ui.viewholder.SingleChoiceViewHolder
|
||||
@ -72,7 +75,7 @@ import kotlin.math.roundToInt
|
||||
class SettingsAdapter(
|
||||
private val fragmentView: SettingsFragmentView,
|
||||
public val context: Context
|
||||
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener {
|
||||
) : RecyclerView.Adapter<SettingViewHolder?>(), DialogInterface.OnClickListener, DialogInterface.OnMultiChoiceClickListener {
|
||||
private var settings: ArrayList<SettingsItem>? = null
|
||||
private var clickedItem: SettingsItem? = null
|
||||
private var clickedPosition: Int
|
||||
@ -128,6 +131,10 @@ class SettingsAdapter(
|
||||
StringInputViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
SettingsItem.TYPE_MULTI_CHOICE, SettingsItem.TYPE_STRING_MULTI_CHOICE -> {
|
||||
MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this)
|
||||
}
|
||||
|
||||
else -> {
|
||||
// TODO: Create an error view since we can't return null now
|
||||
HeaderViewHolder(ListItemSettingsHeaderBinding.inflate(inflater), this)
|
||||
@ -632,4 +639,113 @@ class SettingsAdapter(
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
private fun getSelectionForMultiChoiceValues(item: MultiChoiceSetting): BooleanArray {
|
||||
val checked_values = mutableListOf<Boolean>()
|
||||
val values = item.selectedValues
|
||||
val valuesId = item.valuesId
|
||||
if (valuesId > 0) {
|
||||
val valuesArray = context.resources.getIntArray(valuesId)
|
||||
for (index in valuesArray.indices) {
|
||||
val current = valuesArray[index]
|
||||
if (current in values) {
|
||||
checked_values.add(true)
|
||||
} else {
|
||||
checked_values.add(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (checked_values == null) {
|
||||
return booleanArrayOf(false)
|
||||
} else {
|
||||
return checked_values.toBooleanArray()
|
||||
}
|
||||
}
|
||||
|
||||
private fun onMultiChoiceClick(item: MultiChoiceSetting) {
|
||||
clickedItem = item
|
||||
val values = getSelectionForMultiChoiceValues(item)
|
||||
dialog = MaterialAlertDialogBuilder(context)
|
||||
.setTitle(item.nameId)
|
||||
.setMultiChoiceItems(item.choicesId, values, this)
|
||||
.show()
|
||||
}
|
||||
|
||||
fun onMultiChoiceClick(item: MultiChoiceSetting, position: Int) {
|
||||
clickedPosition = position
|
||||
onMultiChoiceClick(item)
|
||||
}
|
||||
|
||||
private fun onStringMultiChoiceClick(item: StringMultiChoiceSetting) {
|
||||
clickedItem = item
|
||||
dialog = context?.let {
|
||||
MaterialAlertDialogBuilder(it)
|
||||
.setTitle(item.nameId)
|
||||
.setMultiChoiceItems(item.choices, item.selectValueIndices, this)
|
||||
.show()
|
||||
}
|
||||
}
|
||||
|
||||
fun onStringMultiChoiceClick(item: StringMultiChoiceSetting, position: Int) {
|
||||
clickedPosition = position
|
||||
onStringMultiChoiceClick(item)
|
||||
}
|
||||
|
||||
//TODO: REFACTOR TO BE MULTICHOICE
|
||||
override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) {
|
||||
when (clickedItem) {
|
||||
is SingleChoiceSetting -> {
|
||||
val scSetting = clickedItem as? SingleChoiceSetting
|
||||
scSetting?.let {
|
||||
val setting = when (it.setting) {
|
||||
is AbstractIntSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(it, which)
|
||||
if (it.selectedValue != value) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
val value = getValueForSingleChoiceSelection(it, which).toShort()
|
||||
if (it.selectedValue.toShort() != value) {
|
||||
fragmentView?.onSettingChanged()
|
||||
}
|
||||
it.setSelectedValue(value)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for SingleChoiceSetting!")
|
||||
}
|
||||
fragmentView?.putSetting(setting)
|
||||
fragmentView.loadSettingsList()
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
|
||||
is StringSingleChoiceSetting -> {
|
||||
val scSetting = clickedItem as? StringSingleChoiceSetting
|
||||
scSetting?.let {
|
||||
val setting = when (it.setting) {
|
||||
is AbstractStringSetting -> {
|
||||
val value = it.getValueAt(which)
|
||||
if (it.selectedValue != value) fragmentView?.onSettingChanged()
|
||||
it.setSelectedValue(value ?: "")
|
||||
}
|
||||
|
||||
is AbstractShortSetting -> {
|
||||
if (it.selectValueIndex != which) fragmentView?.onSettingChanged()
|
||||
it.setSelectedValue(it.getValueAt(which)?.toShort() ?: 1)
|
||||
}
|
||||
|
||||
else -> throw IllegalStateException("Unrecognized type used for StringSingleChoiceSetting!")
|
||||
}
|
||||
|
||||
fragmentView?.putSetting(setting)
|
||||
fragmentView.loadSettingsList()
|
||||
closeDialog()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,94 @@
|
||||
// Copyright Citra Emulator Project / Azahar Emulator Project
|
||||
// Licensed under GPLv2 or any later version
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
package org.citra.citra_emu.features.settings.ui.viewholder
|
||||
|
||||
import android.view.View
|
||||
import org.citra.citra_emu.databinding.ListItemSettingBinding
|
||||
import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.model.view.SettingsItem
|
||||
import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting
|
||||
import org.citra.citra_emu.features.settings.ui.SettingsAdapter
|
||||
|
||||
class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||
SettingViewHolder(binding.root, adapter) {
|
||||
private lateinit var setting: SettingsItem
|
||||
|
||||
override fun bind(item: SettingsItem) {
|
||||
setting = item
|
||||
binding.textSettingName.setText(item.nameId)
|
||||
if (item.descriptionId != 0) {
|
||||
binding.textSettingDescription.visibility = View.VISIBLE
|
||||
binding.textSettingDescription.setText(item.descriptionId)
|
||||
} else {
|
||||
binding.textSettingDescription.visibility = View.GONE
|
||||
}
|
||||
binding.textSettingValue.visibility = View.VISIBLE
|
||||
binding.textSettingValue.text = getTextSetting()
|
||||
|
||||
if (setting.isActive) {
|
||||
binding.textSettingName.alpha = 1f
|
||||
binding.textSettingDescription.alpha = 1f
|
||||
binding.textSettingValue.alpha = 1f
|
||||
} else {
|
||||
binding.textSettingName.alpha = 0.5f
|
||||
binding.textSettingDescription.alpha = 0.5f
|
||||
binding.textSettingValue.alpha = 0.5f
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTextSetting(): String {
|
||||
when (val item = setting) {
|
||||
is MultiChoiceSetting -> {
|
||||
val resMgr = binding.textSettingDescription.context.resources
|
||||
val values = resMgr.getIntArray(item.valuesId)
|
||||
values.forEachIndexed { i: Int, value: Int ->
|
||||
if (value in (setting as MultiChoiceSetting).selectedValues) {
|
||||
return resMgr.getStringArray(item.choicesId)[i]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
is StringMultiChoiceSetting -> {
|
||||
item.values?.forEachIndexed { i: Int, value: String ->
|
||||
if (value in item.selectedValues) {
|
||||
return item.choices[i]
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
else -> return ""
|
||||
}
|
||||
}
|
||||
|
||||
override fun onClick(clicked: View) {
|
||||
if (!setting.isEditable || !setting.isEnabled) {
|
||||
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||
return
|
||||
}
|
||||
|
||||
if (setting is MultiChoiceSetting) {
|
||||
adapter.onMultiChoiceClick(
|
||||
(setting as MultiChoiceSetting),
|
||||
bindingAdapterPosition
|
||||
)
|
||||
} else if (setting is StringMultiChoiceSetting) {
|
||||
adapter.onStringMultiChoiceClick(
|
||||
(setting as StringMultiChoiceSetting),
|
||||
bindingAdapterPosition
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLongClick(clicked: View): Boolean {
|
||||
if (setting.isActive) {
|
||||
return adapter.onLongClick(setting.setting!!, bindingAdapterPosition)
|
||||
} else {
|
||||
adapter.onClickDisabledSetting(!setting.isEditable)
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user