summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt105
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt9
2 files changed, 114 insertions, 0 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt
new file mode 100644
index 000000000..52163f9d7
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/adapters/AbstractSingleSelectionList.kt
@@ -0,0 +1,105 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.adapters
5
6import org.yuzu.yuzu_emu.model.SelectableItem
7import org.yuzu.yuzu_emu.viewholder.AbstractViewHolder
8
9/**
10 * Generic list class meant to take care of single selection UI updates
11 * @param currentList The list to show initially
12 * @param defaultSelection The default selection to use if no list items are selected by
13 * [SelectableItem.selected] or if the currently selected item is removed from the list
14 */
15abstract class AbstractSingleSelectionList<
16 Model : SelectableItem,
17 Holder : AbstractViewHolder<Model>
18 >(
19 final override var currentList: List<Model>,
20 private val defaultSelection: DefaultSelection = DefaultSelection.Start
21) : AbstractListAdapter<Model, Holder>(currentList) {
22 var selectedItem = getDefaultSelection()
23
24 init {
25 findSelectedItem()
26 }
27
28 /**
29 * Changes the selection state of the [SelectableItem] that was selected and the previously selected
30 * item and notifies the underlying adapter of the change for those items. Invokes [callback] last.
31 * Does nothing if [position] is the same as the currently selected item.
32 * @param position Index of the item that was selected
33 * @param callback Lambda that's called at the end of the list changes and has the selected list
34 * position passed in as a parameter
35 */
36 fun selectItem(position: Int, callback: ((position: Int) -> Unit)? = null) {
37 if (position == selectedItem) {
38 return
39 }
40
41 val previouslySelectedItem = selectedItem
42 selectedItem = position
43 if (currentList.indices.contains(selectedItem)) {
44 currentList[selectedItem].onSelectionStateChanged(true)
45 }
46 if (currentList.indices.contains(previouslySelectedItem)) {
47 currentList[previouslySelectedItem].onSelectionStateChanged(false)
48 }
49 onItemChanged(previouslySelectedItem)
50 onItemChanged(selectedItem)
51 callback?.invoke(position)
52 }
53
54 /**
55 * Removes a given item from the list and notifies the underlying adapter of the change. If the
56 * currently selected item was the item that was removed, the item at the position provided
57 * by [defaultSelection] will be made the new selection. Invokes [callback] last.
58 * @param position Index of the item that was removed
59 * @param callback Lambda that's called at the end of the list changes and has the removed and
60 * selected list positions passed in as parameters
61 */
62 fun removeSelectableItem(
63 position: Int,
64 callback: ((removedPosition: Int, selectedPosition: Int) -> Unit)?
65 ) {
66 removeItem(position)
67 if (position == selectedItem) {
68 selectedItem = getDefaultSelection()
69 currentList[selectedItem].onSelectionStateChanged(true)
70 onItemChanged(selectedItem)
71 } else if (position < selectedItem) {
72 selectedItem--
73 }
74 callback?.invoke(position, selectedItem)
75 }
76
77 override fun addItem(item: Model, position: Int, callback: ((Int) -> Unit)?) {
78 super.addItem(item, position, callback)
79 if (position <= selectedItem && position != -1) {
80 selectedItem++
81 }
82 }
83
84 override fun replaceList(newList: List<Model>) {
85 super.replaceList(newList)
86 findSelectedItem()
87 }
88
89 private fun findSelectedItem() {
90 for (i in currentList.indices) {
91 if (currentList[i].selected) {
92 selectedItem = i
93 break
94 }
95 }
96 }
97
98 private fun getDefaultSelection(): Int =
99 when (defaultSelection) {
100 DefaultSelection.Start -> currentList.indices.first
101 DefaultSelection.End -> currentList.indices.last
102 }
103
104 enum class DefaultSelection { Start, End }
105}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt
new file mode 100644
index 000000000..11c22d323
--- /dev/null
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/model/SelectableItem.kt
@@ -0,0 +1,9 @@
1// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4package org.yuzu.yuzu_emu.model
5
6interface SelectableItem {
7 var selected: Boolean
8 fun onSelectionStateChanged(selected: Boolean)
9}