From fb2dac9b3f4b21a1765e15da0840b8f0bec04230 Mon Sep 17 00:00:00 2001 From: Sarah Gerweck Date: Mon, 18 Apr 2016 20:18:45 -0700 Subject: [PATCH] Code to make an `Observable` from a `Future` --- .../scalafx/util/FutureObservable.scala | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 src/main/scala/org/gerweck/scalafx/util/FutureObservable.scala diff --git a/src/main/scala/org/gerweck/scalafx/util/FutureObservable.scala b/src/main/scala/org/gerweck/scalafx/util/FutureObservable.scala new file mode 100644 index 0000000..9fd7cbb --- /dev/null +++ b/src/main/scala/org/gerweck/scalafx/util/FutureObservable.scala @@ -0,0 +1,39 @@ +package org.gerweck.scalafx.util + +import scala.concurrent._ + +import org.log4s._ + +import scalafx.application.Platform.runLater +import scalafx.beans.property._ + +/** An [[scalafx.beans.value.ObservableValue]] that pulls its value from a future. + * + * @author Sarah Gerweck + */ +object FutureObservable { + private[this] val logger = getLogger + + /** Construct an observable that gives the value of the future on success. + * + * Until the future completes successfully, the value will be that of + * `defaultValue`. If there is an error, the value will persist as + * `defaultValue`. + * + * If you want to change state in case of an error, I recommend you use + * [[scala.concurrent.Future.recover]] to choose the values that will be + * used in that case. The `defaultValue` is provided because `Future` has + * no equivalent mechanism for this mandatory functionality, but recovery + * is already a built-in feature. + */ + def apply[A](defaultValue: A)(future: Future[A])(implicit ec: ExecutionContext): ReadOnlyObjectProperty[A] = { + val prop = ObjectProperty[A](defaultValue) + future onSuccess { case a => + runLater { + logger.trace("Updating property value after Future's success") + prop.value = a + } + } + prop + } +}