From 7484570e4013753f66a2da84f64a2af0aa93a9b7 Mon Sep 17 00:00:00 2001 From: Rohan Sircar Date: Sun, 13 Dec 2020 21:08:40 +0530 Subject: [PATCH] Updated project further Updated scala version to 2.13.4 Compiles to Java 11 now Updated sbt to 1.4.3 Updated scalafx version to 14 Removed unneeded dependencies Removed Akka code Added lint and fatal warnings scalac options Added parantheses to side effecting methods Added >> and << methods to observables --- .gitignore | 7 + .sbtopts | 1 - build.sbt | 16 +-- project/BasicSettings.scala | 6 +- project/Dependencies.scala | 7 +- project/ProjectSettings.scala | 2 +- project/build.properties | 2 +- project/plugins.sbt | 1 + .../org/gerweck/scalafx/akka/AkkaFX.scala | 136 +++++++++--------- .../scalafx/akka/AkkaFXCollections.scala | 116 +++++++-------- .../gerweck/scalafx/util/SingletonStage.scala | 2 +- .../scalafx/util/control/ControlPanel.scala | 5 +- .../scalafx/util/control/DialogButtons.scala | 4 +- .../org/gerweck/scalafx/util/observable.scala | 24 ++-- .../scalafx/util/observableCollection.scala | 8 +- .../scalafx/util/prefs/ObservablePref.scala | 124 ++++++++-------- version.sbt | 2 +- 17 files changed, 234 insertions(+), 229 deletions(-) create mode 100644 project/plugins.sbt diff --git a/.gitignore b/.gitignore index fea4af5..3c00d53 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,10 @@ bin /log /*.script typescript + +.metals +.sbt +.vscode +.bsp +.bloop +metals.sbt \ No newline at end of file diff --git a/.sbtopts b/.sbtopts index 3a0f3be..cc73fe6 100644 --- a/.sbtopts +++ b/.sbtopts @@ -1,4 +1,3 @@ -J-Xmx4G -J-XX:MaxMetaspaceSize=4g --J-XX:+UnlockCommercialFeatures -J-XX:+FlightRecorder diff --git a/build.sbt b/build.sbt index f01745f..755c123 100644 --- a/build.sbt +++ b/build.sbt @@ -27,21 +27,21 @@ lazy val root = (project in file (".")) jclBridge % "runtime,optional", log4jBridge % "runtime,optional", logback % "runtime,optional", - gerweckUtil, - scalaJava8, + // gerweckUtil, + // scalaJava8, scalaFx, cats, shapeless ), libraryDependencies ++= javaFXModules.map( m => - "org.openjfx" % s"javafx-$m" % "12.0.2" classifier osName + "org.openjfx" % s"javafx-$m" % "11.0.2" classifier osName ), /* Akka dependencies */ - libraryDependencies ++= Seq ( - akkaActor % "optional", - akkaStream % "optional", - gerweckUtilAkka % "optional" - ) + // libraryDependencies ++= Seq ( + // akkaActor % "optional", + // akkaStream % "optional", + // gerweckUtilAkka % "optional" + // ) ) diff --git a/project/BasicSettings.scala b/project/BasicSettings.scala index 3c9fb1d..26fdbbd 100644 --- a/project/BasicSettings.scala +++ b/project/BasicSettings.scala @@ -73,6 +73,8 @@ trait BasicSettings extends ProjectSettings { st: SettingTemplate => var options = Seq.empty[String] val sv = sver.value + options :+= "-Xlint" + options :+= "-Xfatal-warnings" options :+= "-unchecked" options :+= "-feature" if (deprecation) { @@ -160,8 +162,8 @@ trait BasicSettings extends ProjectSettings { st: SettingTemplate => if (sv.requireJava8) { options ++= Seq[String]( - "-target", "1.8", - "-source", "1.8" + "-target", "11", + "-source", "11" ) } else { options ++= Seq[String]( diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 3b7fa81..b24ffd0 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -34,10 +34,10 @@ object Dependencies { val logback = "ch.qos.logback" % "logback-classic" % logbackVersion val spire = "org.spire-math" %% "spire" % spireVersion val commonsIo = "commons-io" % "commons-io" % commonsIoVersion - val groovy = "org.codehaus.groovy" % "groovy-all" % groovyVersion + // val groovy = "org.codehaus.groovy" % "groovy-all" % groovyVersion val gerweckUtil = "org.gerweck.scala" %% "gerweck-utils" % gerweckUtilVersion val gerweckUtilAkka = "org.gerweck.scala" %% "gerweck-utils-akka" % gerweckUtilVersion - val scalaJava8 = "org.scala-lang.modules" %% "scala-java8-compat" % scalaJava8Version + // val scalaJava8 = "org.scala-lang.modules" %% "scala-java8-compat" % scalaJava8Version val cats = "org.typelevel" %% "cats-core" % catsVersion val shapeless = "com.chuusai" %% "shapeless" % shapelessVersion val scallop = "org.rogach" %% "scallop" % scallopVersion @@ -81,8 +81,7 @@ object Dependencies { /* ********************************************************************** */ /* ScalaFX */ /* ********************************************************************** */ - // final val scalaFxVersion = "8.0.144-R12" - final val scalaFxVersion = "12.0.2-R18" + final val scalaFxVersion = "14-R19" val scalaFx = "org.scalafx" %% "scalafx" % scalaFxVersion diff --git a/project/ProjectSettings.scala b/project/ProjectSettings.scala index 16e2c99..bc1b9ca 100644 --- a/project/ProjectSettings.scala +++ b/project/ProjectSettings.scala @@ -11,7 +11,7 @@ trait ProjectSettings override final val githubOrganization = "sarahgerweck" override final val githubProject = "scalafx-utils" - override final val buildScalaVersion = "2.13.1" + override final val buildScalaVersion = "2.13.4" override final val extraScalaVersions = Seq("2.11.12", "2.12.5") override final val defaultOptimize = true override final val defaultOptimizeGlobal = false diff --git a/project/build.properties b/project/build.properties index a919a9b..947bdd3 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.3.8 +sbt.version=1.4.3 diff --git a/project/plugins.sbt b/project/plugins.sbt new file mode 100644 index 0000000..7e66915 --- /dev/null +++ b/project/plugins.sbt @@ -0,0 +1 @@ +addSbtPlugin("com.thoughtworks.sbt-api-mappings" % "sbt-api-mappings" % "2.0.2") \ No newline at end of file diff --git a/src/main/scala/org/gerweck/scalafx/akka/AkkaFX.scala b/src/main/scala/org/gerweck/scalafx/akka/AkkaFX.scala index f494fd6..1fef27b 100644 --- a/src/main/scala/org/gerweck/scalafx/akka/AkkaFX.scala +++ b/src/main/scala/org/gerweck/scalafx/akka/AkkaFX.scala @@ -1,74 +1,74 @@ -package org.gerweck.scalafx.akka +// package org.gerweck.scalafx.akka -import scala.concurrent._ +// import scala.concurrent._ -import akka.Done -import akka.stream.OverflowStrategy -import akka.stream.scaladsl._ +// import akka.Done +// import akka.stream.OverflowStrategy +// import akka.stream.scaladsl._ -import scalafx.application.Platform.runLater -import scalafx.beans.property.Property -import scalafx.beans.value.ObservableValue +// import scalafx.application.Platform.runLater +// import scalafx.beans.property.Property +// import scalafx.beans.value.ObservableValue -/** A master object that exposes all the Akka-ScalaFX bridges. - * - * @author Sarah Gerweck - */ -object AkkaFX extends AkkaStreamFX with AkkaFXCollections +// /** A master object that exposes all the Akka-ScalaFX bridges. +// * +// * @author Sarah Gerweck +// */ +// object AkkaFX extends AkkaStreamFX with AkkaFXCollections -trait AkkaStreamFX extends Any { - /** A [[akka.stream.scaladsl.Sink]] that sends all values to a - * [[scalafx.beans.property.Property]]. - * - * Each event that's written into the `Sink` will trigger an update of the - * `Property` with the streamed value. - */ - def observableSink[A](prop: Property[A, _]): Sink[A, Future[Done]] = { - Sink.foreach[A] { a => - runLater { - prop.value = a - } - } - } +// trait AkkaStreamFX extends Any { +// /** A [[akka.stream.scaladsl.Sink]] that sends all values to a +// * [[scalafx.beans.property.Property]]. +// * +// * Each event that's written into the `Sink` will trigger an update of the +// * `Property` with the streamed value. +// */ +// def observableSink[A](prop: Property[A, _]): Sink[A, Future[Done]] = { +// Sink.foreach[A] { a => +// runLater { +// prop.value = a +// } +// } +// } - /** A [[akka.stream.scaladsl.Source]] that generates an event for each - * change of an [[scalafx.beans.value.ObservableValue]]. - * - * This source adds an `onChange` handler to the given `ObservableValue`. - * Each time it observes a change, the new value is pushed from the - * `Source`. The change handler is registered as soon as the source is - * materialized into a graph. It should be safe to use a single source - * in several graphs, as each will register its own change listener upon - * materialization. - * - * @param prop The value to observe. - * - * @param queueSize The maximum number of values to queue while waiting for - * the downstream flow to consume more data. - * - * @param overflow What to do when the queue is full because the downstream - * flow cannot keep up. The default behavior is to block, slowing the UI's - * main thread until some events are consumed, freeing space in the queue. - */ - def observableSource[A](prop: ObservableValue[_, A], - queueSize: Int = 10, - overflow: OverflowStrategy = OverflowStrategy.backpressure - )(implicit ec: ExecutionContext) = { - val src = Source - .queue[A](queueSize, overflow) - .mapMaterializedValue { m => - val sub = { - prop.onChange { (dta, oldV, newV) => - m.offer(newV) - } - } - m.watchCompletion foreach { c => - runLater { - sub.cancel() - } - } - m - } - src - } -} +// /** A [[akka.stream.scaladsl.Source]] that generates an event for each +// * change of an [[scalafx.beans.value.ObservableValue]]. +// * +// * This source adds an `onChange` handler to the given `ObservableValue`. +// * Each time it observes a change, the new value is pushed from the +// * `Source`. The change handler is registered as soon as the source is +// * materialized into a graph. It should be safe to use a single source +// * in several graphs, as each will register its own change listener upon +// * materialization. +// * +// * @param prop The value to observe. +// * +// * @param queueSize The maximum number of values to queue while waiting for +// * the downstream flow to consume more data. +// * +// * @param overflow What to do when the queue is full because the downstream +// * flow cannot keep up. The default behavior is to block, slowing the UI's +// * main thread until some events are consumed, freeing space in the queue. +// */ +// def observableSource[A](prop: ObservableValue[_, A], +// queueSize: Int = 10, +// overflow: OverflowStrategy = OverflowStrategy.backpressure +// )(implicit ec: ExecutionContext) = { +// val src = Source +// .queue[A](queueSize, overflow) +// .mapMaterializedValue { m => +// val sub = { +// prop.onChange { (dta, oldV, newV) => +// m.offer(newV) +// } +// } +// m.watchCompletion() foreach { c => +// runLater { +// sub.cancel() +// } +// } +// m +// } +// src +// } +// } diff --git a/src/main/scala/org/gerweck/scalafx/akka/AkkaFXCollections.scala b/src/main/scala/org/gerweck/scalafx/akka/AkkaFXCollections.scala index a864e48..65e0984 100644 --- a/src/main/scala/org/gerweck/scalafx/akka/AkkaFXCollections.scala +++ b/src/main/scala/org/gerweck/scalafx/akka/AkkaFXCollections.scala @@ -1,72 +1,72 @@ -package org.gerweck.scalafx.akka +// package org.gerweck.scalafx.akka -import language.implicitConversions +// import language.implicitConversions -import scala.collection.mutable.{ Clearable, Growable } -import scala.concurrent._ -import scala.concurrent.duration._ -import scala.util._ +// import scala.collection.mutable.{ Clearable, Growable } +// import scala.concurrent._ +// import scala.concurrent.duration._ +// import scala.util._ -import akka.{ Done, NotUsed } -import akka.stream.Materializer -import akka.stream.scaladsl._ +// import akka.{ Done, NotUsed } +// import akka.stream.Materializer +// import akka.stream.scaladsl._ -import scalafx.application.Platform.runLater -import scalafx.beans.Observable -import scalafx.beans.property._ +// import scalafx.application.Platform.runLater +// import scalafx.beans.Observable +// import scalafx.beans.property._ -import org.gerweck.scalafx.util.FutureObservable +// import org.gerweck.scalafx.util.FutureObservable -trait AkkaFXCollections extends Any { - implicit def sourceToRichSource[A, B](source: Source[A, B]) = new AkkaFXCollections.RichSource(source) -} +// trait AkkaFXCollections extends Any { +// implicit def sourceToRichSource[A, B](source: Source[A, B]) = new AkkaFXCollections.RichSource(source) +// } -object AkkaFXCollections { - def collectionWriterSink[A] - (buffer: Observable with Growable[A] with Clearable, - clearFirst: Boolean, - groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds) - : Sink[A, Future[Done]] = { - sealed trait PopulateAction - case class InsertRows(data: Seq[A]) extends PopulateAction - case object ClearData extends PopulateAction +// object AkkaFXCollections { +// def collectionWriterSink[A] +// (buffer: Observable with Growable[A] with Clearable, +// clearFirst: Boolean, +// groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds) +// : Sink[A, Future[Done]] = { +// sealed trait PopulateAction +// case class InsertRows(data: Seq[A]) extends PopulateAction +// case object ClearData extends PopulateAction - val grouping = { - Flow[A] - .groupedWithin(groupingSize, groupingTimeout) - .map(InsertRows) - .named("GroupInsertActions") - } +// val grouping = { +// Flow[A] +// .groupedWithin(groupingSize, groupingTimeout) +// .map(InsertRows) +// .named("GroupInsertActions") +// } - val clearData = { - if (clearFirst) - Source.single(ClearData) - else - Source.empty - }.named("OptionalClearAction") +// val clearData = { +// if (clearFirst) +// Source.single(ClearData) +// else +// Source.empty +// }.named("OptionalClearAction") - val combinedSource: Flow[A, PopulateAction, NotUsed] = grouping.prepend(clearData) - combinedSource .toMat { - Sink .foreach[PopulateAction] { - case ClearData => runLater { buffer.clear() } - case InsertRows(data) => runLater { buffer ++= data } - } .named("BufferWriter") - }(Keep.right) - } +// val combinedSource: Flow[A, PopulateAction, NotUsed] = grouping.prepend(clearData) +// combinedSource .toMat { +// Sink .foreach[PopulateAction] { +// case ClearData => runLater { buffer.clear() } +// case InsertRows(data) => runLater { buffer ++= data } +// } .named("BufferWriter") +// }(Keep.right) +// } - class RichSource[A, B](val inner: Source[A, B]) extends AnyVal { - def populateCollection[C >: A] - (buffer: Observable with Growable[C] with Clearable, - clearFirst: Boolean, - groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds) - (implicit mat: Materializer, ec: ExecutionContext) - : ReadOnlyObjectProperty[Option[Try[Done]]] = { +// class RichSource[A, B](val inner: Source[A, B]) extends AnyVal { +// def populateCollection[C >: A] +// (buffer: Observable with Growable[C] with Clearable, +// clearFirst: Boolean, +// groupingSize: Int = 50, groupingTimeout: FiniteDuration = 100.milliseconds) +// (implicit mat: Materializer, ec: ExecutionContext) +// : ReadOnlyObjectProperty[Option[Try[Done]]] = { - val sink = collectionWriterSink(buffer, clearFirst, groupingSize, groupingTimeout) +// val sink = collectionWriterSink(buffer, clearFirst, groupingSize, groupingTimeout) - val graph = inner.toMat(sink)(Keep.right) +// val graph = inner.toMat(sink)(Keep.right) - FutureObservable.ofTryOption(graph.run()) - } - } -} +// FutureObservable.ofTryOption(graph.run()) +// } +// } +// } diff --git a/src/main/scala/org/gerweck/scalafx/util/SingletonStage.scala b/src/main/scala/org/gerweck/scalafx/util/SingletonStage.scala index e4e9ab2..c5cc93c 100644 --- a/src/main/scala/org/gerweck/scalafx/util/SingletonStage.scala +++ b/src/main/scala/org/gerweck/scalafx/util/SingletonStage.scala @@ -46,7 +46,7 @@ abstract class SingletonStage { /** Create the stage, or give it focus if it already exists. * * This needs to be executed within the UI thread. If you're not already within some kind - * of event handler, you need to use [[scalafx.application.Platform.runLater]]. + * of event handler, you need to use [[scalafx.application.Platform$.runLater[R](op:=>R):Unit*]]. */ def showStage(): Unit = { State.currentStage match { diff --git a/src/main/scala/org/gerweck/scalafx/util/control/ControlPanel.scala b/src/main/scala/org/gerweck/scalafx/util/control/ControlPanel.scala index 29893e2..139ef98 100644 --- a/src/main/scala/org/gerweck/scalafx/util/control/ControlPanel.scala +++ b/src/main/scala/org/gerweck/scalafx/util/control/ControlPanel.scala @@ -28,7 +28,7 @@ object HorizontalControlPanel { alignment = Pos.CenterRight } case SeparatorEntry => - Separators.vertical + Separators.vertical() } } } @@ -56,9 +56,6 @@ object ControlPanel { def apply(controls: ControlPanelEntry*): Pane = VerticalControlPanel(controls: _*) private[this] lazy val defaultFont = new Font(Font.default) - private[this] lazy val boldFont = { - Font(defaultFont.family, FontWeight.Bold, defaultFont.size) - } private[this] lazy val labelsFont = defaultFont diff --git a/src/main/scala/org/gerweck/scalafx/util/control/DialogButtons.scala b/src/main/scala/org/gerweck/scalafx/util/control/DialogButtons.scala index 696e717..bb2106a 100644 --- a/src/main/scala/org/gerweck/scalafx/util/control/DialogButtons.scala +++ b/src/main/scala/org/gerweck/scalafx/util/control/DialogButtons.scala @@ -5,7 +5,6 @@ import org.log4s._ import scalafx.Includes._ import scalafx.event.ActionEvent -import scalafx.event.ActionEvent import scalafx.geometry.Insets import scalafx.scene.Node import scalafx.scene.control._ @@ -13,7 +12,6 @@ import scalafx.scene.layout._ import scalafx.stage.Stage import javafx.scene.{ Node => JNode } import javafx.scene.layout.{ Region => JRegion } -import scalafx.delegate.SFXDelegate /** A standard button bar with the major dialog buttons. * @@ -72,7 +70,7 @@ class DialogButtons(stage: Stage, showOk: Boolean = true, showApply: Boolean = t } } - protected[control] def mainLayout = new VBox(Separators.horizontal, bar) { + protected[control] def mainLayout = new VBox(Separators.horizontal(), bar) { hgrow = Priority.Always } diff --git a/src/main/scala/org/gerweck/scalafx/util/observable.scala b/src/main/scala/org/gerweck/scalafx/util/observable.scala index a09dfac..6d87c12 100644 --- a/src/main/scala/org/gerweck/scalafx/util/observable.scala +++ b/src/main/scala/org/gerweck/scalafx/util/observable.scala @@ -42,7 +42,7 @@ private object ObservableImplicits { val prop = ObjectProperty[B](originalValue) var prevValue = originalValue - def changeHandler = prop.synchronized { + def changeHandler() = prop.synchronized { val newVal = recalculate() if (prevValue != newVal) { prop.value = newVal @@ -50,7 +50,7 @@ private object ObservableImplicits { } } - a onChange changeHandler + a onChange changeHandler() prop } @@ -68,7 +68,7 @@ private object ObservableImplicits { var prevValue = originalValue - def changeHandler = prop.synchronized { + def changeHandler() = prop.synchronized { val newVal = recalculate() if (prevValue != newVal) { prop.value = newVal @@ -76,8 +76,8 @@ private object ObservableImplicits { } } - fa onChange changeHandler - f onChange changeHandler + fa onChange changeHandler() + f onChange changeHandler() prop } @@ -110,7 +110,7 @@ private object ObservableImplicits { prevValue = newVal } } - var innerSub = oa() onChange innerHandle + var innerSub = oa() onChange innerHandle() var prevOuter = oa() def outerHandle() = prop.synchronized { @@ -118,13 +118,13 @@ private object ObservableImplicits { /* We need reference equality here: we're subscribing to a specific object. */ if (prevOuter ne newOuter) { innerSub.cancel() - innerSub = newOuter onChange innerHandle + innerSub = newOuter onChange innerHandle() prevOuter = newOuter innerHandle() } } - ooa onChange outerHandle + ooa onChange outerHandle() prop } @@ -159,7 +159,7 @@ private object ObservableImplicits { prevValue = newVal } } - var innerSub = oa() onChange innerHandle + var innerSub = oa() onChange innerHandle() var prevOuter = oa() def outerHandle() = prop.synchronized { @@ -167,13 +167,13 @@ private object ObservableImplicits { /* We need reference equality here: we're subscribing to a specific object. */ if (prevOuter ne newOuter) { innerSub.cancel() - innerSub = newOuter onChange innerHandle + innerSub = newOuter onChange innerHandle() prevOuter = newOuter innerHandle() } } - ooa onChange outerHandle + ooa onChange outerHandle() prop } @@ -218,6 +218,8 @@ final class RichObservable[A, C](val self: ObservableValue[A, C]) extends AnyVal def tuple[B](f: Observable[B]): Observable[(A,B)] = oapp.tuple2(self, f) final def *>[B](fb: ObjObs[B]): Observable[B] = oapp.map2(self,fb)((_,b) => b) final def <*[B](fb: ObjObs[B]): Observable[A] = oapp.map2(self,fb)((a,_) => a) + final def >>[B](fb: => ObjObs[B]): Observable[B] = oapp.map2(self, fb)((_, b) => b) + final def <<[B](fb: => ObjObs[B]): Observable[A] = oapp.map2(self, fb)((a, _) => a) final def |@|[B, B1](fb: ObservableValue[B, B1]) = ObservableTupler(self, fb) diff --git a/src/main/scala/org/gerweck/scalafx/util/observableCollection.scala b/src/main/scala/org/gerweck/scalafx/util/observableCollection.scala index 20d31a2..d9fe01e 100644 --- a/src/main/scala/org/gerweck/scalafx/util/observableCollection.scala +++ b/src/main/scala/org/gerweck/scalafx/util/observableCollection.scala @@ -1,6 +1,6 @@ package org.gerweck.scalafx.util -import scala.compat.java8.FunctionConverters._ +// import scala.compat.java8.FunctionConverters._ import java.util.function.{ Predicate => JPredicate } @@ -58,9 +58,9 @@ final class RichObservableBuffer[A](val obs: ObservableBuffer[A]) extends AnyVal fb.predicate <== predicate fb } - def observeFiltered[B >: A](predicate: Observable[B => Boolean]): FilteredBuffer[A] = { - observeFiltered(predicate.map[JPredicate[A]](asJavaPredicate)) - } + // def observeFiltered[B >: A](predicate: Observable[B => Boolean]): FilteredBuffer[A] = { + // observeFiltered(predicate.map[JPredicate[A]](asJavaPredicate)) + // } } final class RichObservableArray[A, B <: ObservableArray[A, B, C], C <: javafx.collections.ObservableArray[C]](val oaa: ObservableArray[A, B, C]) extends AnyVal with RichObservableSeqLike[A] { diff --git a/src/main/scala/org/gerweck/scalafx/util/prefs/ObservablePref.scala b/src/main/scala/org/gerweck/scalafx/util/prefs/ObservablePref.scala index bf2869b..13f882e 100644 --- a/src/main/scala/org/gerweck/scalafx/util/prefs/ObservablePref.scala +++ b/src/main/scala/org/gerweck/scalafx/util/prefs/ObservablePref.scala @@ -1,62 +1,62 @@ -package org.gerweck.scalafx.util -package prefs - -import java.util.prefs._ - -import scalafx.application.Platform.runLater -import scalafx.beans.property.ObjectProperty - -import org.gerweck.scala.util.prefs._ - -/* TODO: take an implicit that will deteremine whether this is an `ObjectProperty` or what */ -class ObservablePref[A] protected (path: String)(implicit handler: Pref.AccessHandler[A], prefs: Preferences) - extends Pref[A](path) { thisPref => - - lazy val observe: ObjectProperty[A] = { - val initialValue: A = this() - val property = ObjectProperty[A](initialValue) - - /* We build two bridges, one that listens for changes in the preferences system and pushes - * them into the observable property, and another that listens for updates to the property and - * pushes them to the preference system. Each bridge is gated so that it only activates if the - * value has actually changed, which prevents the infinite looping that would otherwise occur - * in a bidirectional bridge. */ - - /* Preferences => Property bridge */ - - /* In Scala 2.12, the callback could just be bare inside `addPreferenceChangeListener`. - * However, it must be created explicitly since we cross-compile against Scala 2.11. */ - val changeListener = new PreferenceChangeListener { - def preferenceChange(pce: PreferenceChangeEvent): Unit = { - if (pce.getKey == path) { - runLater { - val currentValue = thisPref() - if (property.value != currentValue) { - property.value = currentValue - } - } - } - } - } - prefs.addPreferenceChangeListener(changeListener) - - /* Property => Preferences bridge */ - property.onChange { (_, _, newV) => - if (newV != this()) { - this() = newV - } - } - - /* Return the bridged property */ - property - } -} - -object ObservablePref { - def apply[A](path: String)(implicit handler: PrefHandler[A], prefs: Preferences) = { - new ObservablePref(path)(new Pref.AccessHandler.Optional, prefs) - } - def apply[A](path: String, default: A)(implicit handler: PrefHandler[A], prefs: Preferences) = { - new ObservablePref(path)(new Pref.AccessHandler.Defaulted(default), prefs) - } -} +// package org.gerweck.scalafx.util +// package prefs + +// import java.util.prefs._ + +// import scalafx.application.Platform.runLater +// import scalafx.beans.property.ObjectProperty + +// import org.gerweck.scala.util.prefs._ + +// /* TODO: take an implicit that will deteremine whether this is an `ObjectProperty` or what */ +// class ObservablePref[A] protected (path: String)(implicit handler: Pref.AccessHandler[A], prefs: Preferences) +// extends Pref[A](path) { thisPref => + +// lazy val observe: ObjectProperty[A] = { +// val initialValue: A = this() +// val property = ObjectProperty[A](initialValue) + +// /* We build two bridges, one that listens for changes in the preferences system and pushes +// * them into the observable property, and another that listens for updates to the property and +// * pushes them to the preference system. Each bridge is gated so that it only activates if the +// * value has actually changed, which prevents the infinite looping that would otherwise occur +// * in a bidirectional bridge. */ + +// /* Preferences => Property bridge */ + +// /* In Scala 2.12, the callback could just be bare inside `addPreferenceChangeListener`. +// * However, it must be created explicitly since we cross-compile against Scala 2.11. */ +// val changeListener = new PreferenceChangeListener { +// def preferenceChange(pce: PreferenceChangeEvent): Unit = { +// if (pce.getKey == path) { +// runLater { +// val currentValue = thisPref() +// if (property.value != currentValue) { +// property.value = currentValue +// } +// } +// } +// } +// } +// prefs.addPreferenceChangeListener(changeListener) + +// /* Property => Preferences bridge */ +// property.onChange { (_, _, newV) => +// if (newV != this()) { +// this() = newV +// } +// } + +// /* Return the bridged property */ +// property +// } +// } + +// object ObservablePref { +// def apply[A](path: String)(implicit handler: PrefHandler[A], prefs: Preferences) = { +// new ObservablePref(path)(new Pref.AccessHandler.Optional, prefs) +// } +// def apply[A](path: String, default: A)(implicit handler: PrefHandler[A], prefs: Preferences) = { +// new ObservablePref(path)(new Pref.AccessHandler.Defaulted(default), prefs) +// } +// } diff --git a/version.sbt b/version.sbt index 1b621de..b277194 100644 --- a/version.sbt +++ b/version.sbt @@ -1 +1 @@ -version in ThisBuild := "0.14.4-SNAPSHOT" +version in ThisBuild := "0.15.0"