diff options
-rw-r--r-- | build.gradle | 2 | ||||
-rw-r--r-- | src/main/kotlin/pl/treksoft/kvision/data/DataContainer.kt | 55 | ||||
-rw-r--r-- | src/test/kotlin/test/pl/treksoft/kvision/data/DataContainerSpec.kt | 2 |
3 files changed, 43 insertions, 16 deletions
diff --git a/build.gradle b/build.gradle index 84b7c574..84bb5ce8 100644 --- a/build.gradle +++ b/build.gradle @@ -117,7 +117,7 @@ dependencies { compile "com.github.snabbdom:snabbdom-kotlin:0.1.1" compile "pl.treksoft:navigo-kotlin:0.0.3" compile "pl.treksoft:jquery-kotlin:0.0.4" - compile "pl.treksoft:kotlin-observable-js:0.0.3" + compile "pl.treksoft:kotlin-observable-js:0.0.4" } kotlinFrontend { 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( |