Skip to content
This repository has been archived by the owner on Oct 18, 2024. It is now read-only.

Commit

Permalink
fix(preferences): show confirmation buttons in dialog preferences
Browse files Browse the repository at this point in the history
  • Loading branch information
itsaky committed Nov 4, 2023
1 parent ea8deab commit 624e55a
Show file tree
Hide file tree
Showing 8 changed files with 191 additions and 68 deletions.
22 changes: 13 additions & 9 deletions app/src/main/java/com/itsaky/androidide/preferences/buildAndRun.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import com.itsaky.androidide.tasks.executeAsync
import com.itsaky.androidide.utils.Environment.GRADLE_USER_HOME
import com.itsaky.androidide.utils.flashError
import com.itsaky.androidide.utils.flashSuccess
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize
import java.io.File

Expand Down Expand Up @@ -112,15 +113,18 @@ private class GradleCommands(
)
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
when (position) {
0 -> isStacktraceEnabled = isSelected
1 -> isInfoEnabled = isSelected
2 -> isDebugEnabled = isSelected
3 -> isScanEnabled = isSelected
4 -> isWarningModeAllEnabled = isSelected
5 -> isBuildCacheEnabled = isSelected
6 -> isOfflineEnabled = isSelected
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)
}
}
}
Expand Down
49 changes: 25 additions & 24 deletions app/src/main/java/com/itsaky/androidide/preferences/editor.kt
Original file line number Diff line number Diff line change
Expand Up @@ -183,21 +183,21 @@ private class TabSize(
return choices
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
var size = (position + 1) * 2
if (size < 2 || size > 8) {
size = 4
}
tabSize = size
}

override fun getSelectedItem(context: Context): Int {
override fun getInitiallySelectionItemPosition(context: Context): Int {
var current = tabSize / 2 - 1
if (current < 0 || current >= choices.size) {
current = 1
}
return current
}

override fun onChoiceConfirmed(position: Int) {
var size = (position + 1) * 2
if (size < 2 || size > 8) {
size = 4
}
tabSize = size
}
}

@Parcelize
Expand All @@ -217,14 +217,12 @@ private class ColorSchemePreference(
return schemes.map { it.name }.toTypedArray()
}

override fun getSelectedItem(context: Context): Int {
override fun getInitiallySelectionItemPosition(context: Context): Int {
return schemes.indexOfFirst { it.key == colorScheme }
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
if (isSelected) {
colorScheme = schemes[position].key
}
override fun onChoiceConfirmed(position: Int) {
colorScheme = schemes[position].key
}
}

Expand All @@ -240,16 +238,6 @@ private class NonPrintablePaintingFlags(
return arrayOf("Leading", "Trailing", "Inner", "Empty lines", "Line breaks")
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
when (position) {
0 -> drawLeadingWs = isSelected
1 -> drawTrailingWs = isSelected
2 -> drawInnerWs = isSelected
3 -> drawEmptyLineWs = isSelected
4 -> drawLineBreak = isSelected
}
}

override fun getCheckedItems(): BooleanArray {
return booleanArrayOf(
drawLeadingWs,
Expand All @@ -259,6 +247,19 @@ private class NonPrintablePaintingFlags(
drawLineBreak
)
}

override fun onChoicesConfirmed(selectedPositions: List<Int>) {
for (position in selectedPositions) {
when (position) {
0 -> ::drawLeadingWs
1 -> ::drawTrailingWs
2 -> ::drawInnerWs
3 -> ::drawEmptyLineWs
4 -> ::drawLineBreak
else -> null
}?.set(true)
}
}
}

@Parcelize
Expand Down
24 changes: 9 additions & 15 deletions app/src/main/java/com/itsaky/androidide/preferences/general.kt
Original file line number Diff line number Diff line change
Expand Up @@ -110,23 +110,19 @@ class UiMode(
)
}

override fun getSelectedItem(context: Context): Int {
override fun getInitiallySelectionItemPosition(context: Context): Int {
return when (uiMode) {
AppCompatDelegate.MODE_NIGHT_NO -> 0
AppCompatDelegate.MODE_NIGHT_YES -> 1
else -> 2
}
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
if (isSelected) {
val mode =
when (position) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
uiMode = mode
override fun onChoiceConfirmed(position: Int) {
uiMode = when (position) {
0 -> AppCompatDelegate.MODE_NIGHT_NO
1 -> AppCompatDelegate.MODE_NIGHT_YES
else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM
}
}
}
Expand All @@ -146,14 +142,12 @@ class ThemeSelector(
return themes.map { context.getString(it.title) }.toTypedArray()
}

override fun getSelectedItem(context: Context): Int {
override fun getInitiallySelectionItemPosition(context: Context): Int {
return themes.indexOf(ThemeManager.getCurrentTheme())
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
if (isSelected) {
selectedTheme = themes[position].name
}
override fun onChoiceConfirmed(position: Int) {
selectedTheme = themes[position].name
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,15 +227,15 @@ private class EmptyElementsBehavior(
) : SingleChoicePreference() {
override val dialogCancellable = true

override fun getSelectedItem(context: Context): Int {
override fun getInitiallySelectionItemPosition(context: Context): Int {
return EmptyElements.valueOf(emptyElementsBehavior).ordinal
}

override fun getChoices(context: Context): Array<String> {
return EmptyElements.values().map { it.toString() }.toTypedArray()
}

override fun onItemSelected(position: Int, isSelected: Boolean) {
override fun onChoiceConfirmed(position: Int) {
emptyElementsBehavior = EmptyElements.values()[position].toString()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* This file is part of AndroidIDE.
*
* AndroidIDE is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* AndroidIDE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with AndroidIDE. If not, see <https://www.gnu.org/licenses/>.
*/

package com.itsaky.androidide.preferences

import androidx.preference.Preference
import com.google.android.material.dialog.MaterialAlertDialogBuilder

/**
* Base class for dialog preferences which allows users to choose from multiple items.
*
* @author Akash Yadav
*/
abstract class ChoiceBasedDialogPreference : DialogPreference(), PreferenceChoices {

protected open var selectedPositions: MutableList<Int>? = null

final override fun onConfigureDialog(preference: Preference, dialog: MaterialAlertDialogBuilder) {
val choices = getChoices(preference.context)
selectedPositions = MutableList(size = choices.size) { -1 }

onConfigureDialogChoices(preference, dialog, choices)

dialog.setPositiveButton(android.R.string.ok) { dialogInterface, _ ->
dialogInterface.dismiss()

val positions = selectedPositions?.also { positions ->
positions.removeIf { idx -> idx == -1 }
}
onChoicesConfirmed(positions ?: emptyList())
}

dialog.setNegativeButton(android.R.string.cancel) { dialogInterface, _ ->
dialogInterface.dismiss()
onChoicesCancelled()
}
}

override fun onSelectionChanged(position: Int, isSelected: Boolean) {
if (isSelected) {
selectedPositions!!.add(position)
} else {
selectedPositions!!.removeAt(position)
}
}

/**
* Configure the dialog choices.
*/
protected abstract fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
)

override fun onChoicesConfirmed(selectedPositions: List<Int>) {}

override fun onChoicesCancelled() {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,32 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
/**
* A preference with multiple choices to select from.
*
* The [onSelectionChanged] is called whenever the
* [DialogInterface.OnMultiChoiceClickListener][android.content.DialogInterface.OnMultiChoiceClickListener]
* is called.
*
* @author Akash Yadav
*/
abstract class MultiChoicePreference : DialogPreference(), PreferenceChoices {
abstract class MultiChoicePreference : ChoiceBasedDialogPreference(), PreferenceChoices {

/**
* Get the index of all the items that should be selected by default.
* Get the index of all the checked and unchecked items.
*
* @see MaterialAlertDialogBuilder.setMultiChoiceItems
*/
abstract fun getCheckedItems(): BooleanArray

override fun onConfigureDialog(preference: Preference, dialog: MaterialAlertDialogBuilder) {
super.onConfigureDialog(preference, dialog)
dialog.setMultiChoiceItems(getChoices(preference.context), getCheckedItems()) { _, which, checked ->
onItemSelected(which, checked)
override fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
) {

dialog.setMultiChoiceItems(
getChoices(preference.context),
getCheckedItems()
) { _, which, checked ->
onSelectionChanged(which, checked)
}
dialog.setPositiveButton(android.R.string.ok, null)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,24 @@ interface PreferenceChoices {

/** Get the choices to show in the preference. */
fun getChoices(context: Context): Array<String>

/**
* Called when an item is selected from the single choice list.
*
* @param position The position of the selected item.
* @param isSelected Whether the item is selected.
*/
fun onSelectionChanged(position: Int, isSelected: Boolean)

/**
* Called when the user confirms the selections.
*
* @param selectedPositions The positions of the selected items.
*/
fun onChoicesConfirmed(selectedPositions: List<Int>)

/**
* Called when the user cancels the selections.
*/
fun onItemSelected(position: Int, isSelected: Boolean = true)
fun onChoicesCancelled()
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,22 +24,49 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
/**
* A preference which allows selecting a single value from a list of values.
*
* The [onSelectionChanged] method is called exactly two times when the user changes the selection, first call for the previously
* selected item and second call for the newly selected item.
*
* The [onChoicesConfirmed] is always called with a singleton list.
*
* @author Akash Yadav
*/
abstract class SingleChoicePreference : DialogPreference(), PreferenceChoices {
abstract class SingleChoicePreference : ChoiceBasedDialogPreference(), PreferenceChoices {

/**
* The currently selected item in the dialog.
*/
protected open var currentSelection: Int = -1

/**
* Get the index of the selected item.
* @see MaterialAlertDialogBuilder.setSingleChoiceItems
*/
abstract fun getSelectedItem(context: Context): Int

override fun onConfigureDialog(preference: Preference, dialog: MaterialAlertDialogBuilder) {
super.onConfigureDialog(preference, dialog)
dialog.setSingleChoiceItems(getChoices(preference.context),
getSelectedItem(preference.context)) { dialogInterface, position ->
dialogInterface.dismiss()
onItemSelected(position)
abstract fun getInitiallySelectionItemPosition(context: Context): Int

override fun onConfigureDialogChoices(
preference: Preference,
dialog: MaterialAlertDialogBuilder,
choices: Array<String>
) {

dialog.setSingleChoiceItems(
getChoices(preference.context),
getInitiallySelectionItemPosition(preference.context))
{ _, position ->

if (currentSelection != -1) {
onSelectionChanged(currentSelection, false)
}

currentSelection = position
onSelectionChanged(position, true)
}
}

final override fun onChoicesConfirmed(selectedPositions: List<Int>) {
selectedPositions.firstOrNull()?.let { onChoiceConfirmed(it) }
}

protected open fun onChoiceConfirmed(position: Int) {}
}

0 comments on commit 624e55a

Please sign in to comment.