diff --git a/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt b/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt index b8ac8ea960..d88c886616 100644 --- a/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt +++ b/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt @@ -1,21 +1,38 @@ package com.r3corda.client.fxutils -import com.r3corda.contracts.asset.Cash -import com.r3corda.core.contracts.StateAndRef import javafx.beans.binding.Bindings import javafx.beans.property.ReadOnlyObjectWrapper -import javafx.beans.property.SimpleObjectProperty import javafx.beans.value.ObservableValue import javafx.collections.ObservableList import javafx.collections.transformation.FilteredList -import kotlinx.support.jdk8.collections.stream import org.fxmisc.easybind.EasyBind import java.util.function.Predicate -import java.util.stream.Collector +/** + * Here follows utility extension functions that help reduce the visual load when developing RX code. Each function should + * have a short accompanying example code. + */ + +/** + * val person: ObservableValue = (..) + * val personName: ObservableValue = person.map { it.name } + */ fun ObservableValue.map(function: (A) -> B): ObservableValue = EasyBind.map(this, function) + +/** + * val dogs: ObservableList = (..) + * val dogOwners: ObservableList = dogs.map { it.owner } + */ fun ObservableList.map(function: (A) -> B): ObservableList = EasyBind.map(this, function) +/** + * val aliceHeight: ObservableValue = (..) + * val bobHeight: ObservableValue = (..) + * fun sumHeight(a: Long, b: Long): Long { .. } + * + * val aliceBobSumHeight = ::sumHeight.lift(aliceHeight, bobHeight) + * val aliceHeightPlus2 = ::sumHeight.lift(aliceHeight, 2L.lift()) + */ fun A.lift(): ObservableValue = ReadOnlyObjectWrapper(this) fun ((A) -> R).lift( arg0: ObservableValue @@ -36,11 +53,24 @@ fun ((A, B, C, D) -> R).lift( arg3: ObservableValue ): ObservableValue = EasyBind.combine(arg0, arg1, arg2, arg3, this) +/** + * data class Person(val height: ObservableValue) + * val person: ObservableValue = (..) + * val personHeight: ObservableValue = person.bind { it.height } + */ fun ObservableValue.bind(function: (A) -> ObservableValue): ObservableValue = // We cast here to enforce variance, flatMap should be covariant @Suppress("UNCHECKED_CAST") EasyBind.monadic(this).flatMap(function as (A) -> ObservableValue) +/** + * enum class FilterCriterion { HEIGHT, NAME } + * val filterCriterion: ObservableValue = (..) + * val people: ObservableList = (..) + * fun filterFunction(filterCriterion: FilterCriterion): (Person) -> Boolean { .. } + * + * val filteredPeople: ObservableList = people.filter(filterCriterion.map(filterFunction)) + */ fun ObservableList.filter(predicate: ObservableValue Boolean>): ObservableList { // We cast here to enforce variance, FilteredList should be covariant @Suppress("UNCHECKED_CAST") @@ -51,6 +81,11 @@ fun ObservableList.filter(predicate: ObservableValue Boole } } +/** + * val people: ObservableList = (..) + * val concatenatedNames = people.fold("", { names, person -> names + person.name }) + * val concatenatedNames2 = people.map(Person::name).fold("", String::plus) + */ fun ObservableList.fold(initial: B, folderFunction: (B, A) -> B): ObservableValue { return Bindings.createObjectBinding({ var current = initial @@ -61,20 +96,9 @@ fun ObservableList.fold(initial: B, folderFunction: (B, A) -> B): }, arrayOf(this)) } -fun ObservableList>.flatten(): ObservableList { - return FlattenedList(this) -} - -fun sum(a: Int, b: Int): Int = a + b - -fun main(args: Array) { - val a = SimpleObjectProperty(0) - val b = SimpleObjectProperty(0) - - ::sum.lift(a, b).addListener { observableValue, i0, i1 -> - println(i1) - } - - a.set(2) - b.set(4) -} +/** + * data class Person(val height: ObservableValue) + * val people: ObservableList = (..) + * val heights: ObservableList = people.map(Person::height).flatten() + */ +fun ObservableList>.flatten(): ObservableList = FlattenedList(this)