New ObservablePref
mechanism
This inherits from the `Pref` system in `scala-utils`, extending it so that preferences can be ScalaFX bound variables. This is the easiest way to store things like the preferred window size and other per-user local configuration.
This commit is contained in:
parent
bc76e50d2b
commit
bce5a0d39e
@ -68,3 +68,12 @@ change.
|
||||
* This is tested against Java 8u144, though it may work with older versions.
|
||||
* Improvements to `SingletonStage`
|
||||
* Update Scala to 2.12.4
|
||||
|
||||
### 0.13
|
||||
|
||||
* New `ObservablePref`
|
||||
* This builds on the `Pref` in `scala-utils`, making it a bindable property.
|
||||
* `Pref` and `ObservablePref` are the way I recommend to store things like
|
||||
window sizes, column selections and other UI preferences.
|
||||
* Use a database like [H2](http://www.h2database.com/) if you have
|
||||
complicated application state that needs to persist.
|
||||
|
@ -23,7 +23,7 @@ object Dependencies {
|
||||
final val scalaJava8Version = "0.8.0"
|
||||
final val scalaParserVersion = "1.0.4"
|
||||
final val scalaXmlVersion = "1.0.5"
|
||||
final val gerweckUtilVersion = "2.5.1"
|
||||
final val gerweckUtilVersion = "2.7.0-SNAPSHOT"
|
||||
final val scalazVersion = "7.2.16"
|
||||
final val shapelessVersion = "2.3.2"
|
||||
final val scallopVersion = "1.0.1"
|
||||
|
@ -0,0 +1,54 @@
|
||||
package org.gerweck.scalafx.util
|
||||
package prefs
|
||||
|
||||
import java.util.prefs.Preferences
|
||||
|
||||
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) {
|
||||
|
||||
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 */
|
||||
prefs.addPreferenceChangeListener { pce =>
|
||||
if (pce.getKey == path) {
|
||||
runLater {
|
||||
val currentValue = this()
|
||||
if (property.value != currentValue) {
|
||||
property.value = currentValue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Property => Preferences bridge */
|
||||
property.onChange { (_, _, newV) =>
|
||||
if (newV != this()) {
|
||||
this() = newV
|
||||
}
|
||||
()
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user