selector docs and several refactorings

This commit is contained in:
InsanusMokrassar 2020-12-14 19:36:07 +06:00
parent 12e37184e1
commit 80bc226ee1

View File

@ -3,6 +3,9 @@ package dev.inmo.micro_utils.selector
import kotlinx.coroutines.flow.* import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
/**
* Unified interface which can be used in any system which require some selection functionality
*/
interface Selector<T> { interface Selector<T> {
val selectedItems: List<T> val selectedItems: List<T>
val itemSelected: SharedFlow<T> val itemSelected: SharedFlow<T>
@ -16,9 +19,18 @@ inline operator fun <T> Selector<T>.contains(element: T) = selectedItems.contain
@Suppress("NOTHING_TO_INLINE") @Suppress("NOTHING_TO_INLINE")
inline fun <T> Selector<T>.nothingSelected(): Boolean = selectedItems.isEmpty() inline fun <T> Selector<T>.nothingSelected(): Boolean = selectedItems.isEmpty()
/**
* Realization of [Selector] with one or without selected element. This realization will always have empty
* [selectedItems] when nothing selected and one element in [selectedItems] when something selected. Contains
* [selectedItem] value for simple access to currently selected item.
*
* On calling of [toggleSelection] previous selection will be erased and [itemUnselected] will emit this element.
*
* @param safeChanges Set to false to disable using of [mutex] for synchronizing changes on [toggleSelection]
*/
class SingleSelector<T>( class SingleSelector<T>(
selectedItem: T? = null, selectedItem: T? = null,
useMutex: Boolean = true safeChanges: Boolean = true
) : Selector<T> { ) : Selector<T> {
var selectedItem: T? = selectedItem var selectedItem: T? = selectedItem
private set private set
@ -30,7 +42,7 @@ class SingleSelector<T>(
private val _itemUnselected = MutableSharedFlow<T>() private val _itemUnselected = MutableSharedFlow<T>()
override val itemUnselected: SharedFlow<T> = _itemUnselected.asSharedFlow() override val itemUnselected: SharedFlow<T> = _itemUnselected.asSharedFlow()
private val mutex = if (useMutex) { private val mutex = if (safeChanges) {
Mutex() Mutex()
} else { } else {
null null
@ -54,9 +66,15 @@ class SingleSelector<T>(
} }
} }
/**
* Realization of [Selector] with multiple selected elements. On calling of [toggleSelection] this realization will select passed element OR deselect it if it is already in
* [selectedItems]
*
* @param safeChanges Set to false to disable using of [mutex] for synchronizing changes on [toggleSelection]
*/
class MultipleSelector<T>( class MultipleSelector<T>(
selectedItems: List<T>, selectedItems: List<T> = emptyList(),
useMutex: Boolean = true safeChanges: Boolean = true
) : Selector<T> { ) : Selector<T> {
private val _selectedItems: MutableList<T> = selectedItems.toMutableList() private val _selectedItems: MutableList<T> = selectedItems.toMutableList()
override val selectedItems: List<T> = _selectedItems override val selectedItems: List<T> = _selectedItems
@ -66,7 +84,7 @@ class MultipleSelector<T>(
private val _itemUnselected = MutableSharedFlow<T>() private val _itemUnselected = MutableSharedFlow<T>()
override val itemUnselected: SharedFlow<T> = _itemUnselected.asSharedFlow() override val itemUnselected: SharedFlow<T> = _itemUnselected.asSharedFlow()
private val mutex = if (useMutex) { private val mutex = if (safeChanges) {
Mutex() Mutex()
} else { } else {
null null
@ -83,3 +101,13 @@ class MultipleSelector<T>(
mutex ?.unlock() mutex ?.unlock()
} }
} }
@Suppress("FunctionName", "NOTHING_TO_INLINE")
inline fun <T> Selector(
multiple: Boolean,
safeChanges: Boolean = true
): Selector<T> = if (multiple) {
MultipleSelector(safeChanges = safeChanges)
} else {
SingleSelector(safeChanges = safeChanges)
}