Skip to content

Commit

Permalink
Support combine KeyItemMaps
Browse files Browse the repository at this point in the history
  • Loading branch information
GuhDoy committed Feb 28, 2024
1 parent d64fe5f commit 442d172
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 16 deletions.
66 changes: 54 additions & 12 deletions library/src/main/java/me/gm/selection/KeyIndexItemMap.kt
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ import androidx.compose.runtime.remember
* @see [androidx.compose.foundation.lazy.layout.LazyLayoutKeyIndexMap]
*/
sealed interface KeyIndexItemMap<K, V> {
val items: List<V>

fun getItem(e: K): V?

fun getFullItemMappings(): Iterable<Pair<K, V>>
}

interface KeyItemMap<V> : KeyIndexItemMap<Any, V> {
val key: (index: Int) -> Any
}

interface IndexItemMap<V> : KeyIndexItemMap<Int, V>

/**
* Automatically deselect removed keys when items change.
*/
Expand Down Expand Up @@ -60,7 +67,7 @@ fun <V> rememberKeyItemMap(
}

return remember(items, key) {
KeyItemMap(items) { index -> key(items[index]) }
KeyItemMapImpl(items) { index -> key(items[index]) }
}
}

Expand All @@ -76,17 +83,17 @@ fun <V> rememberKeyItemMap(
}

return remember(items, key) {
KeyItemMap(items) { index -> key(index, items[index]) }
KeyItemMapImpl(items) { index -> key(index, items[index]) }
}
}

/**
* @see [androidx.compose.foundation.lazy.layout.NearestRangeKeyIndexMap]
*/
open class KeyItemMap<V>(
val items: List<V>,
val key: ((index: Int) -> Any),
) : KeyIndexItemMap<Any, V> {
open class KeyItemMapImpl<V>(
override val items: List<V>,
override val key: (index: Int) -> Any,
) : KeyItemMap<V> {
private val map: MutableScatterMap<Any, V> = MutableScatterMap()

override fun getItem(e: Any): V? = map.getOrElse(e) {
Expand Down Expand Up @@ -117,20 +124,55 @@ fun <V> rememberIndexItemMap(
}

return remember(items) {
IndexItemMap(items)
IndexItemMapImpl(items)
}
}

open class IndexItemMap<V>(
val items: List<V>
) : KeyIndexItemMap<Int, V> {
open class IndexItemMapImpl<V>(
override val items: List<V>
) : IndexItemMap<V> {

override fun getItem(e: Int): V? = items[e]

override fun getFullItemMappings(): Iterable<Pair<Int, V>> =
items.mapIndexed { index, item -> index to item }
}

operator fun KeyIndexItemMap<*, *>.plus(other: KeyIndexItemMap<*, *>): KeyIndexItemMap<*, *> {
TODO()
/**
* This can only be used as a parameter for modifiers.
*/
private class CombinedKeyItemMap<V>(
val maps: MutableList<KeyItemMap<V>>,
override val items: List<V> = emptyList(),
override val key: (Int) -> Any = { throw UnsupportedOperationException() }
) : KeyItemMap<V> {

override fun getItem(e: Any): V? {
for (map in maps) {
val item = map.getItem(e)
if (item != null) {
return item
}
}
return null
}

override fun getFullItemMappings(): Iterable<Pair<Int, V>> =
throw UnsupportedOperationException()
}

operator fun <V> KeyItemMap<V>.plus(other: KeyItemMap<V>): KeyItemMap<V> {
return if (this is CombinedKeyItemMap) {
this.maps.add(other)
this
} else {
CombinedKeyItemMap(mutableListOf(this, other))
}
}

/*
* Combining [IndexItemMap] requires knowing the position of each interval, which is similar to
* [androidx.compose.foundation.lazy.layout.MutableIntervalList].
* This introduces some implicit restrictions on usage, which we do not favor, and therefore,
* we do not provide a built-in implementation.
*/
1 change: 0 additions & 1 deletion library/src/main/java/me/gm/selection/SelectionState.kt
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ fun <V> rememberKeySelectionState(
* [noOpSaver] or [viewModelSaver] to keep the implementation simple. Alternatively, you can use
* [autoSaver] or a custom [Saver] to ensure data is not lost
* @param initialSelection the initial value for [SelectionSupport.selection]
* @see [androidx.compose.foundation.lazy.layout.MutableIntervalList]
*/
@Composable
fun <V> rememberIndexSelectionState(
Expand Down
1 change: 1 addition & 0 deletions sample/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

<application
android:allowBackup="true"
android:enableOnBackInvokedCallback="true"
android:fullBackupContent="true"
android:label="ComposeSelectionTracker Sample"
android:theme="@android:style/Theme.Material.Light.NoActionBar">
Expand Down
31 changes: 28 additions & 3 deletions sample/src/main/java/me/gm/selection/sample/SampleScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import me.gm.selection.grid.selectableItems
import me.gm.selection.grid.tapInActionModeToToggleGesture
import me.gm.selection.list.dragAfterLongPressToSelectGesture
import me.gm.selection.list.selectableItems
import me.gm.selection.plus
import me.gm.selection.rememberKeyItemMap
import me.gm.selection.rememberKeySelectionState

Expand All @@ -78,12 +79,12 @@ import me.gm.selection.rememberKeySelectionState
@Composable
fun SampleScreen() {
val itemsA = remember {
List(10) { index ->
List(8) { index ->
index
}
}
val itemsB = remember {
List(10) { index ->
List(8) { index ->
index
}
}
Expand Down Expand Up @@ -123,6 +124,11 @@ fun SampleScreen() {
key = { item -> "A" to item },
state = selectionState
)
val mapB = rememberKeyItemMap(
items = itemsB,
key = { item -> "B" to item },
state = selectionState
)
Column(
modifier = Modifier
.fillMaxSize()
Expand All @@ -135,7 +141,9 @@ fun SampleScreen() {
modifier = Modifier
.fillMaxSize()
.weight(1f)
.dragAfterLongPressToSelectGesture(listState, selectionState, mapA),
.dragAfterLongPressToSelectGesture(
listState, selectionState, mapA + mapB
),
state = listState
) {
selectableItems(
Expand All @@ -155,6 +163,23 @@ fun SampleScreen() {
text = "ItemA $item",
)
}
selectableItems(
state = selectionState,
map = mapB
) { helper, item ->
val context = LocalContext.current
SampleListItem(
modifier = Modifier
.animateItemPlacement()
.clickable {
Toast
.makeText(context, "ItemB $item", Toast.LENGTH_SHORT)
.show()
},
helper = helper,
text = "ItemB $item",
)
}
}
}

Expand Down

0 comments on commit 442d172

Please sign in to comment.