aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt55
-rw-r--r--src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt2
2 files changed, 42 insertions, 15 deletions
diff --git a/src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt b/src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt
index d8b74c54..bb3eaa83 100644
--- a/src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt
+++ b/src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt
@@ -29,6 +29,14 @@ import pl.treksoft.kvision.core.Widget
import pl.treksoft.kvision.panel.VPanel
/**
+ * Sorter types.
+ */
+enum class SorterType {
+ ASC,
+ DESC
+}
+
+/**
* A container class with support for observable data model.
*
* @constructor Creates DataContainer bound to given data model.
@@ -37,15 +45,17 @@ import pl.treksoft.kvision.panel.VPanel
* @param model data model of type *ObservableList<M>*
* @param factory a function which creates component C from data model at given index
* @param filter a filtering function
- * @param mapping a mapping function
+ * @param sorter a sorting function
+ * @param sorterType a sorting type selection function
* @param container internal container (defaults to [VPanel])
* @param init an initializer extension function
*/
class DataContainer<M, C : Component>(
private val model: ObservableList<M>,
- private val factory: (Int, M) -> C,
- private val filter: ((Int, M) -> Boolean)? = null,
- private val mapping: ((List<Pair<Int, M>>) -> List<Pair<Int, M>>)? = null,
+ private val factory: (M, Int, ObservableList<M>) -> C,
+ private val filter: ((M) -> Boolean)? = null,
+ private val sorter: ((M) -> Comparable<*>?)? = null,
+ private val sorterType: () -> SorterType = { SorterType.ASC },
private val container: Container = VPanel(),
init: (DataContainer<M, C>.() -> Unit)? = null
) :
@@ -106,13 +116,29 @@ class DataContainer<M, C : Component>(
}
singleRender {
container.removeAll()
- val indexed = model.mapIndexed { index, m -> index to m }
- val mapped = mapping?.invoke(indexed) ?: indexed
- val children = if (filter != null) {
- mapped.filter { p -> filter.invoke(p.first, p.second) }
+ val indexed = model.mapIndexed { index, m -> m to index }
+ val sorted = if (sorter != null) {
+ when (sorterType()) {
+ SorterType.ASC ->
+ indexed.sortedBy {
+ @Suppress("UNCHECKED_CAST")
+ sorter.invoke(it.first) as Comparable<Any>?
+ }
+ SorterType.DESC ->
+ indexed.sortedByDescending {
+ @Suppress("UNCHECKED_CAST")
+ sorter.invoke(it.first) as Comparable<Any>?
+ }
+ }
+ } else {
+ indexed
+ }
+ val filtered = if (filter != null) {
+ sorted.filter { filter.invoke(it.first) }
} else {
- mapped
- }.map { p -> factory(p.first, p.second) }
+ sorted
+ }
+ val children = filtered.map { p -> factory(p.first, p.second, model) }
container.addAll(children)
}
onUpdateHandler?.invoke()
@@ -145,13 +171,14 @@ class DataContainer<M, C : Component>(
*/
fun <M, C : Component> Container.dataContainer(
model: ObservableList<M>,
- factory: (Int, M) -> C,
- filter: ((Int, M) -> Boolean)? = null,
- mapping: ((List<Pair<Int, M>>) -> List<Pair<Int, M>>)? = null,
+ factory: (M, Int, ObservableList<M>) -> C,
+ filter: ((M) -> Boolean)? = null,
+ sorter: ((M) -> Comparable<*>?)? = null,
+ sorterType: () -> SorterType = { SorterType.ASC },
container: Container = VPanel(),
init: (DataContainer<M, C>.() -> Unit)? = null
): DataContainer<M, C> {
- val dataContainer = DataContainer(model, factory, filter, mapping, container, init)
+ val dataContainer = DataContainer(model, factory, filter, sorter, sorterType, container, init)
this.add(dataContainer)
return dataContainer
}
diff --git a/src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt b/src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt
index 3f07626d..2cf3160d 100644
--- a/src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt
+++ b/src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt
@@ -42,7 +42,7 @@ class DataContainerSpec : DomSpec {
}
val model = observableListOf(Model("First"), Model("Second"))
- val container = DataContainer(model, { _, m -> Label(m.value) })
+ val container = DataContainer(model, { m, _, _ -> Label(m.value) })
root.add(container)
val element = document.getElementById("test")
assertEqualsHtml(