diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt deleted file mode 100644 index 0c916bab7..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiIntSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// 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.model - -interface AbstractMultiIntSetting : AbstractSetting { - var ints: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt deleted file mode 100644 index acbc7b7a2..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/AbstractMultiShortSetting.kt +++ /dev/null @@ -1,9 +0,0 @@ -// 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.model - -interface AbstractMultiShortSetting : AbstractSetting { - var shorts: MutableSet -} diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt index 12f8d77f6..dd12c54dc 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/StringListSetting.kt @@ -7,11 +7,24 @@ package org.citra.citra_emu.features.settings.model enum class StringListSetting( override val key: String, override val section: String, - override val defaultValue: List + override val defaultValue: List, + val canBeEmpty: Boolean = true ) : AbstractListSetting { - COMBO_KEY_LIST("combo_key_list", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); + COMBO_KEYS("combo_keys", Settings.SECTION_CONTROLS, listOf("A", "B", "X", "Y", "L", "R", "ZL", "ZR", "Start", "Select")); - override var list: List = defaultValue + private var backingList: List = defaultValue + private var lastValidList : List = defaultValue + + override var list: List + get() = backingList + set(value) { + if (!canBeEmpty && value.isEmpty()) { + backingList = lastValidList + } else { + backingList = value + lastValidList = value + } + } override val valueAsString: String get() = list.joinToString() diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt index f99b2719c..b6dd0a8a9 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/model/view/StringMultiChoiceSetting.kt @@ -3,12 +3,8 @@ // 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 import org.citra.citra_emu.features.settings.model.StringListSetting - class StringMultiChoiceSetting( setting: AbstractSetting?, titleId: Int, @@ -29,77 +25,29 @@ class StringMultiChoiceSetting( "" } } - val selectedValues: List get() { if (setting == null) { return defaultValue!! } - try { - val setting = setting as AbstractMultiStringSetting - return setting.strings.toList() - } catch (_: ClassCastException) { - } - - try { - val setting = setting as AbstractMultiShortSetting - return setting.shorts.map { it.toString() } - } catch (_: ClassCastException) { + val setting = setting as StringListSetting + return setting.list + }catch (_: ClassCastException) { } return defaultValue!! } - val selectValueIndices: BooleanArray - get() { - val noneList = values?.let { - ArrayList(BooleanArray(it.size) { false }.toList()) - } ?: ArrayList() - - val chosenindices = mutableListOf() - 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() - } - - } - /** - * Add values to multi choice through the backing mutable sets. + * Write a value to the backing list. If that list 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 added. + * @return the existing setting with the new value applied. */ - fun addSelectedValue(selection: String): AbstractMultiStringSetting { - val stringSetting = setting as AbstractMultiStringSetting - stringSetting.strings.add(selection) + fun setSelectedValue(selection: List): StringListSetting { + val stringSetting = setting as StringListSetting + stringSetting.list = selection return stringSetting } - - fun addSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.add(selection) - return shortSetting - } - - fun removeSelectedValue(selection: String): AbstractMultiStringSetting { - val stringSetting = setting as AbstractMultiStringSetting - stringSetting.strings.remove(selection) - return stringSetting - } - - fun removeSelectedValue(selection: Short): AbstractMultiShortSetting { - val shortSetting = setting as AbstractMultiShortSetting - shortSetting.shorts.remove(selection) - return shortSetting - } } \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt index 5673d4e9c..dc07fd209 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsAdapter.kt @@ -38,7 +38,6 @@ import org.citra.citra_emu.databinding.ListItemSettingsHeaderBinding import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractFloatSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiShortSetting import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting import org.citra.citra_emu.features.settings.model.AbstractSetting import org.citra.citra_emu.features.settings.model.AbstractStringSetting @@ -61,7 +60,6 @@ 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.StringMultiChoiceViewHolder // TODO: Remove and integrate within MultiChoiceViewHolder 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 @@ -143,7 +141,7 @@ class SettingsAdapter( } SettingsItem.TYPE_MULTI_CHOICE, SettingsItem.TYPE_STRING_MULTI_CHOICE -> { - StringMultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) + MultiChoiceViewHolder(ListItemSettingBinding.inflate(inflater), this) } else -> { @@ -285,6 +283,26 @@ class SettingsAdapter( onMultiChoiceClick(item) } + private fun onStringMultiChoiceClick(item: StringMultiChoiceSetting) { + clickedItem = item + val values: BooleanArray = getSelectionForStringMultiChoiceValue(item); + dialog = MaterialAlertDialogBuilder(context) + .setTitle(item.nameId) + .setMultiChoiceItems(item.choices, values, this) + .setOnDismissListener { + if (clickedPosition != -1) { + notifyItemChanged(clickedPosition) + clickedPosition = -1 + } + } + .show() + } + + fun onStringMultiChoiceClick(item: StringMultiChoiceSetting, position: Int) { + clickedPosition = position + onStringMultiChoiceClick(item) + } + private fun onStringSingleChoiceClick(item: StringSingleChoiceSetting) { clickedItem = item dialog = context?.let { @@ -585,15 +603,34 @@ class SettingsAdapter( //onclick for multichoice override fun onClick(dialog: DialogInterface?, which: Int, isChecked: Boolean) { - val mcsetting = clickedItem as? MultiChoiceSetting - mcsetting?.let { - val value = getValueForMultiChoiceSelection(it, which) - if (it.selectedValues.contains(value) != isChecked) { - val setting = it.setSelectedValue((if (isChecked) it.selectedValues + value else it.selectedValues - value).sorted()) - fragmentView?.putSetting(setting) - fragmentView?.onSettingChanged() + when (clickedItem) { + is MultiChoiceSetting -> { + val mcsetting = clickedItem as? MultiChoiceSetting + mcsetting?.let { + val value = getValueForMultiChoiceSelection(it, which) + if (it.selectedValues.contains(value) != isChecked) { + val setting = + it.setSelectedValue((if (isChecked) it.selectedValues + value else it.selectedValues - value).sorted()) + fragmentView?.putSetting(setting) + fragmentView?.onSettingChanged() + } + fragmentView.loadSettingsList() + } + } + + is StringMultiChoiceSetting -> { + val mcsetting = clickedItem as? StringMultiChoiceSetting + mcsetting?.let { + val value = it.getValueAt(which) + if (it.selectedValues.contains(value) != isChecked) { + val setting = + it.setSelectedValue((if (isChecked) it.selectedValues + value.toString() else it.selectedValues - value.toString()).sorted()) + fragmentView?.putSetting(setting) + fragmentView?.onSettingChanged() + } + fragmentView.loadSettingsList() + } } - fragmentView.loadSettingsList() } } @@ -728,6 +765,7 @@ class SettingsAdapter( } } + private fun getSelectionForSingleChoiceValue(item: SingleChoiceSetting): Int { val value = item.selectedValue val valuesId = item.valuesId @@ -760,8 +798,33 @@ class SettingsAdapter( } return BooleanArray(1){false}; } - + + //TODO: Properly Implement in line with string single choice + private fun getSelectionForStringMultiChoiceValue(item: StringMultiChoiceSetting): BooleanArray { + val values = item.selectedValues; + val available_values = item.values; + val res = BooleanArray(available_values?.size ?: 0){false} + var index = 0; + + if (available_values != null) { + for (choice_val in available_values) { + if (values.contains(choice_val)) { + res[index] = true; + index++; + } + } + } + return if (res.isNotEmpty()) { + res; + } else { + BooleanArray(1) { false }; + } + } + + + //TODO: I only added MultiChoice for fleshing out backend, debating whether to remove MultiChoiceSetting and related code for cleaning up + /* override fun onClick(dialog: DialogInterface?, which: Int, is_checked: Boolean) { when (clickedItem) { /* @@ -836,4 +899,6 @@ class SettingsAdapter( } } } + + */ } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt index 1747a2df6..290cdffd7 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/SettingsFragmentPresenter.kt @@ -22,7 +22,6 @@ import org.citra.citra_emu.display.StereoMode import org.citra.citra_emu.display.StereoWhichDisplay import org.citra.citra_emu.features.settings.model.AbstractBooleanSetting import org.citra.citra_emu.features.settings.model.AbstractIntSetting -import org.citra.citra_emu.features.settings.model.AbstractMultiStringSetting 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.AbstractStringSetting @@ -32,6 +31,7 @@ import org.citra.citra_emu.features.settings.model.IntSetting import org.citra.citra_emu.features.settings.model.IntListSetting import org.citra.citra_emu.features.settings.model.ScaledFloatSetting import org.citra.citra_emu.features.settings.model.Settings +import org.citra.citra_emu.features.settings.model.StringListSetting import org.citra.citra_emu.features.settings.model.StringSetting import org.citra.citra_emu.features.settings.model.view.DateTimeSetting import org.citra.citra_emu.features.settings.model.view.HeaderSetting @@ -781,25 +781,6 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) private fun addControlsSettings(sl: ArrayList) { settingsActivity.setToolbarTitle(settingsActivity.getString(R.string.preferences_controls)) - val comboSetting = object : AbstractMultiStringSetting { - override var strings: MutableSet - get() { - return Settings.comboSelection - } - set(values) { - for (item in values) { - Settings.comboSelection.add(item) - } - } - override val key = null - override val section = null - override val isRuntimeEditable = true - override val valueAsString get() = "" - override val defaultValue = "" - } - - val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() - sl.apply { add( RunnableSetting( @@ -861,13 +842,17 @@ class SettingsFragmentPresenter(private val fragmentView: SettingsFragmentView) BooleanSetting.USE_ARTIC_BASE_CONTROLLER.defaultValue ) ) + + val buttons = settingsActivity.resources.getStringArray(R.array.n3dsButtons).take(10).toTypedArray() add( StringMultiChoiceSetting( - comboSetting, + StringListSetting.COMBO_KEYS, R.string.combo_key_options, - 0, + R.string.combo_key_description, buttons, - buttons + buttons, + StringListSetting.COMBO_KEYS.key, + StringListSetting.COMBO_KEYS.defaultValue ) ) } diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt index 8493115a4..4e59ed984 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/MultiChoiceViewHolder.kt @@ -8,6 +8,7 @@ import android.view.View import org.citra.citra_emu.databinding.ListItemSettingBinding import org.citra.citra_emu.features.settings.model.view.SettingsItem import org.citra.citra_emu.features.settings.model.view.MultiChoiceSetting +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) : @@ -51,6 +52,16 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin return resList.joinToString(); } + is StringMultiChoiceSetting -> { + var resList:List = emptyList(); + item.values?.forEachIndexed { i: Int, value: String -> + if (value in item.selectedValues) { + resList = resList + item.choices[i] + } + } + return resList.joinToString() + } + else -> return "" } } @@ -67,6 +78,12 @@ class MultiChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Settin bindingAdapterPosition ) } + if (setting is StringMultiChoiceSetting) { + adapter.onStringMultiChoiceClick( + (setting as StringMultiChoiceSetting), + bindingAdapterPosition + ) + } } override fun onLongClick(clicked: View): Boolean { diff --git a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt b/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt deleted file mode 100644 index 35d4d6e79..000000000 --- a/src/android/app/src/main/java/org/citra/citra_emu/features/settings/ui/viewholder/StringMultiChoiceViewHolder.kt +++ /dev/null @@ -1,77 +0,0 @@ -// 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.SettingsItem -import org.citra.citra_emu.features.settings.model.view.StringMultiChoiceSetting -import org.citra.citra_emu.features.settings.ui.SettingsAdapter - -class StringMultiChoiceViewHolder(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 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 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 - } -} \ No newline at end of file diff --git a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt index 80fbf97af..29400e7cd 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt +++ b/src/android/app/src/main/java/org/citra/citra_emu/utils/ComboHelper.kt @@ -7,6 +7,7 @@ package org.citra.citra_emu.utils import org.citra.citra_emu.NativeLibrary import org.citra.citra_emu.features.settings.model.Settings import org.citra.citra_emu.overlay.InputOverlayDrawableButton +import org.citra.citra_emu.features.settings.model.StringListSetting object ComboHelper { @@ -27,16 +28,17 @@ object ComboHelper { } fun comboActivate(button: InputOverlayDrawableButton) { - var comboArray = Settings.comboSelection - for (selectedbutton in comboArray) { - var nativebutton = getButton(selectedbutton) - if (nativebutton == -1) + var comboArray = StringListSetting.COMBO_KEYS.list + for (selected_button in comboArray) { + var native_button = getButton(selected_button) + if (native_button == -1) { + //TODO: Need proper error handling here println("Bad Button") } else { - NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, nativebutton, button.status) + NativeLibrary.onGamePadEvent(NativeLibrary.TouchScreenDevice, native_button, button.status) } } }