From 7d290b38b187bac89cb5f5874363196a0d63339d Mon Sep 17 00:00:00 2001 From: Andras Slemmer <andras.slemmer@r3cev.com> Date: Thu, 15 Sep 2016 18:01:23 +0100 Subject: [PATCH] client: Add utility javafx observable extension methods --- .../client/fxutils/ObservableUtilities.kt | 80 +++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt diff --git a/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt b/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt new file mode 100644 index 0000000000..b8ac8ea960 --- /dev/null +++ b/client/src/main/kotlin/com/r3corda/client/fxutils/ObservableUtilities.kt @@ -0,0 +1,80 @@ +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 + +fun <A, B> ObservableValue<out A>.map(function: (A) -> B): ObservableValue<B> = EasyBind.map(this, function) +fun <A, B> ObservableList<out A>.map(function: (A) -> B): ObservableList<B> = EasyBind.map(this, function) + +fun <A> A.lift(): ObservableValue<A> = ReadOnlyObjectWrapper(this) +fun <A, R> ((A) -> R).lift( + arg0: ObservableValue<A> +): ObservableValue<R> = EasyBind.map(arg0, this) +fun <A, B, R> ((A, B) -> R).lift( + arg0: ObservableValue<A>, + arg1: ObservableValue<B> +): ObservableValue<R> = EasyBind.combine(arg0, arg1, this) +fun <A, B, C, R> ((A, B, C) -> R).lift( + arg0: ObservableValue<A>, + arg1: ObservableValue<B>, + arg2: ObservableValue<C> +): ObservableValue<R> = EasyBind.combine(arg0, arg1, arg2, this) +fun <A, B, C, D, R> ((A, B, C, D) -> R).lift( + arg0: ObservableValue<A>, + arg1: ObservableValue<B>, + arg2: ObservableValue<C>, + arg3: ObservableValue<D> +): ObservableValue<R> = EasyBind.combine(arg0, arg1, arg2, arg3, this) + +fun <A, B> ObservableValue<out A>.bind(function: (A) -> ObservableValue<out B>): ObservableValue<out B> = + // We cast here to enforce variance, flatMap should be covariant + @Suppress("UNCHECKED_CAST") + EasyBind.monadic(this).flatMap(function as (A) -> ObservableValue<B>) + +fun <A> ObservableList<out A>.filter(predicate: ObservableValue<out (A) -> Boolean>): ObservableList<out A> { + // We cast here to enforce variance, FilteredList should be covariant + @Suppress("UNCHECKED_CAST") + return FilteredList<A>(this as ObservableList<A>).apply { + predicateProperty().bind(predicate.map { predicateFunction -> + Predicate<A> { predicateFunction(it) } + }) + } +} + +fun <A, B> ObservableList<out A>.fold(initial: B, folderFunction: (B, A) -> B): ObservableValue<B> { + return Bindings.createObjectBinding({ + var current = initial + forEach { + current = folderFunction(current, it) + } + current + }, arrayOf(this)) +} + +fun <A> ObservableList<out ObservableValue<out A>>.flatten(): ObservableList<out A> { + return FlattenedList(this) +} + +fun sum(a: Int, b: Int): Int = a + b + +fun main(args: Array<String>) { + val a = SimpleObjectProperty(0) + val b = SimpleObjectProperty(0) + + ::sum.lift(a, b).addListener { observableValue, i0, i1 -> + println(i1) + } + + a.set(2) + b.set(4) +}