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"