fix(preferences): add selection handler logic for choice prefs (fixes #1444)

This commit is contained in:
Akash Yadav
2023-11-10 14:29:25 +05:30
parent 510f77986b
commit e5448a4a19
7 changed files with 66 additions and 60 deletions
@@ -89,42 +89,28 @@ private class GradleCommands(
override val icon: Int? = drawable.ic_bash_commands,
) : MultiChoicePreference() {
override fun getCheckedItems(): BooleanArray {
return booleanArrayOf(
isStacktraceEnabled,
isInfoEnabled,
isDebugEnabled,
isScanEnabled,
isWarningModeAllEnabled,
isBuildCacheEnabled,
isOfflineEnabled
)
@IgnoredOnParcel
private val choices = linkedMapOf(
"--stacktrace" to ::isStacktraceEnabled,
"--info" to ::isInfoEnabled,
"--debug" to ::isDebugEnabled,
"--scan" to ::isScanEnabled,
"--warning-mode all" to ::isWarningModeAllEnabled,
"--build-cache" to ::isBuildCacheEnabled,
"--offline" to ::isOfflineEnabled,
)
override fun getCheckedItems(choices: Array<String>): BooleanArray {
return BooleanArray(choices.size) { this.choices[choices[it]]?.get() == true }
}
override fun getChoices(context: Context): Array<String> {
return arrayOf(
"--stacktrace",
"--info",
"--debug",
"--scan",
"--warning-mode all",
"--build-cache",
"--offline"
)
return choices.keys.toTypedArray()
}
override fun onChoicesConfirmed(selectedPositions: List<Int>) {
for (position in selectedPositions) {
when (position) {
0 -> ::isStacktraceEnabled
1 -> ::isInfoEnabled
2 -> ::isDebugEnabled
3 -> ::isScanEnabled
4 -> ::isWarningModeAllEnabled
5 -> ::isBuildCacheEnabled
6 -> ::isOfflineEnabled
else -> null
}?.set(true)
override fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>) {
selections.forEach { (key, value) ->
choices[key]?.set(value)
}
}
}
@@ -174,6 +174,7 @@ private class TabSize(
override val icon: Int? = drawable.ic_font_ligatures,
) : SingleChoicePreference() {
@IgnoredOnParcel
override val dialogCancellable = true
@IgnoredOnParcel
@@ -208,6 +209,7 @@ private class ColorSchemePreference(
override val icon: Int? = R.drawable.ic_color_scheme
) : SingleChoicePreference() {
@IgnoredOnParcel
override val dialogCancellable = true
@IgnoredOnParcel
@@ -238,7 +240,7 @@ private class NonPrintablePaintingFlags(
return arrayOf("Leading", "Trailing", "Inner", "Empty lines", "Line breaks")
}
override fun getCheckedItems(): BooleanArray {
override fun getCheckedItems(choices: Array<String>): BooleanArray? {
return booleanArrayOf(
drawLeadingWs,
drawTrailingWs,
@@ -248,7 +250,7 @@ private class NonPrintablePaintingFlags(
)
}
override fun onChoicesConfirmed(selectedPositions: List<Int>) {
override fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>) {
for (position in selectedPositions) {
when (position) {
0 -> ::drawLeadingWs
@@ -49,6 +49,7 @@ import com.itsaky.androidide.preferences.internal.splitAttributes
import com.itsaky.androidide.preferences.internal.splitAttributesIndentSize
import com.itsaky.androidide.preferences.internal.trimFinalNewLine
import com.itsaky.androidide.preferences.internal.trimTrailingWhitespace
import kotlinx.parcelize.IgnoredOnParcel
import org.eclipse.lemminx.dom.builder.EmptyElements
import kotlinx.parcelize.Parcelize
@@ -225,6 +226,8 @@ private class EmptyElementsBehavior(
override val title: Int = string.idepref_emptyElements_title,
override val summary: Int? = string.idepref_emptyElements_summary
) : SingleChoicePreference() {
@IgnoredOnParcel
override val dialogCancellable = true
override fun getInitiallySelectionItemPosition(context: Context): Int {
@@ -27,21 +27,25 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
*/
abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoices {
protected open var selectedPositions: MutableList<Int>? = null
private var checkedPositions = intArrayOf()
final override fun onConfigureDialog(preference: Preference, dialog: MaterialAlertDialogBuilder) {
val choices = getChoices(preference.context)
selectedPositions = MutableList(size = choices.size) { -1 }
val checkedItems = getCheckedItems(choices)
onConfigureDialogChoices(preference, dialog, choices)
checkedPositions = checkedItems?.map { if(it) 1 else 0 }?.toIntArray() ?: intArrayOf()
onConfigureDialogChoices(preference, dialog, choices, checkedItems)
dialog.setPositiveButton(android.R.string.ok) { dialogInterface, _ ->
dialogInterface.dismiss()
val positions = selectedPositions?.also { positions ->
positions.removeIf { idx -> idx == -1 }
val selections = HashMap<String, Boolean>(choices.size)
for (i in 0..checkedPositions.lastIndex) {
selections[choices[i]] = checkedPositions[i] == 1
}
onChoicesConfirmed(positions ?: emptyList())
onChoicesConfirmed(checkedPositions, selections)
}
dialog.setNegativeButton(android.R.string.cancel) { dialogInterface, _ ->
@@ -51,11 +55,11 @@ abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoic
}
override fun onSelectionChanged(position: Int, isSelected: Boolean) {
if (isSelected) {
selectedPositions!!.add(position)
} else {
selectedPositions!!.removeAt(position)
if (position < 0 || position >= checkedPositions.size) {
return
}
checkedPositions[position] = if (isSelected) 1 else 0
}
/**
@@ -64,10 +68,11 @@ abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoic
protected abstract fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
choices: Array<String>,
checkedItems: BooleanArray?
)
override fun onChoicesConfirmed(selectedPositions: List<Int>) {}
override fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>) {}
override fun onChoicesCancelled() {}
}
@@ -31,22 +31,16 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
*/
abstract class MultiChoicePreference : ChoiceBasedDialogPreference(), PreferenceChoices {
/**
* Get the index of all the checked and unchecked items.
*
* @see MaterialAlertDialogBuilder.setMultiChoiceItems
*/
abstract fun getCheckedItems(): BooleanArray
override fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
choices: Array<String>,
checkedItems: BooleanArray?
) {
dialog.setMultiChoiceItems(
getChoices(preference.context),
getCheckedItems()
choices,
checkedItems!!
) { _, which, checked ->
onSelectionChanged(which, checked)
}
@@ -18,6 +18,7 @@
package com.itsaky.androidide.preferences
import android.content.Context
import com.google.android.material.dialog.MaterialAlertDialogBuilder
/**
* A preference with choices.
@@ -29,6 +30,13 @@ interface PreferenceChoices {
/** Get the choices to show in the preference. */
fun getChoices(context: Context): Array<String>
/**
* Get all checked and unchecked items.
*
* @see MaterialAlertDialogBuilder.setMultiChoiceItems
*/
fun getCheckedItems(choices: Array<String>): BooleanArray?
/**
* Called when an item is selected from the single choice list.
*
@@ -42,7 +50,7 @@ interface PreferenceChoices {
*
* @param selectedPositions The positions of the selected items.
*/
fun onChoicesConfirmed(selectedPositions: List<Int>)
fun onChoicesConfirmed(selectedPositions: IntArray, selections: Map<String, Boolean>)
/**
* Called when the user cancels the selections.
@@ -44,14 +44,19 @@ abstract class SingleChoicePreference : ChoiceBasedDialogPreference(), Preferenc
*/
abstract fun getInitiallySelectionItemPosition(context: Context): Int
final override fun getCheckedItems(choices: Array<String>): BooleanArray? {
return null
}
override fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
choices: Array<String>,
checkedItems: BooleanArray?
) {
dialog.setSingleChoiceItems(
getChoices(preference.context),
choices,
getInitiallySelectionItemPosition(preference.context))
{ _, position ->
@@ -64,8 +69,11 @@ abstract class SingleChoicePreference : ChoiceBasedDialogPreference(), Preferenc
}
}
final override fun onChoicesConfirmed(selectedPositions: List<Int>) {
selectedPositions.firstOrNull()?.let { onChoiceConfirmed(it) }
final override fun onChoicesConfirmed(
selectedPositions: IntArray,
selections: Map<String, Boolean>
) {
onChoiceConfirmed(currentSelection)
}
protected open fun onChoiceConfirmed(position: Int) {}