Add observableSize
operation to collections
Also, bump the version to 0.9 since this change is definitely not binary compatible: class names and structures have changed. Most clients should be fine though if they just recompile: the changes are to things that will generally be used through the implicits system, so most shoudln't notice the changes.
This commit is contained in:
parent
ce0e5c001e
commit
99ed345be5
@ -273,63 +273,3 @@ final class RichProperty[A, B](val inner: Property[A, B]) extends AnyVal {
|
||||
final class RichObjectProperty[A](val inner: ObjectProperty[A]) extends AnyVal {
|
||||
def readOnly: ReadOnlyObjectProperty[A] = inner
|
||||
}
|
||||
|
||||
sealed trait ToObservableOps[-A, +B] {
|
||||
def recalculate(a: A): B
|
||||
def onChange(a: A)(b: => Unit): Unit
|
||||
}
|
||||
object ToObservableOps {
|
||||
implicit def obOps[A] = new ToObservableOps[ObservableBuffer[A], Seq[A]] {
|
||||
def recalculate(oba: ObservableBuffer[A]) = oba.toVector
|
||||
def onChange(oba: ObservableBuffer[A])(b: => Unit) = oba onChange b
|
||||
}
|
||||
implicit def oaOps[A] = new ToObservableOps[ObservableArray[A, _, _], Seq[A]] {
|
||||
def recalculate(oaa: ObservableArray[A, _, _]) = oaa.toVector
|
||||
def onChange(oaa: ObservableArray[A, _, _])(b: => Unit) = oaa onChange b
|
||||
}
|
||||
implicit def osOps[A] = new ToObservableOps[ObservableSet[A], collection.immutable.Set[A]] {
|
||||
def recalculate(os: ObservableSet[A]) = os.toSet
|
||||
def onChange(os: ObservableSet[A])(b: => Unit) = os onChange b
|
||||
}
|
||||
}
|
||||
|
||||
object RichToObservable {
|
||||
@inline final def toObservable[A, B](a: A)(implicit ops: ToObservableOps[A, B]): ReadOnlyObjectProperty[B] = {
|
||||
@inline def recalculate(): B = ops.recalculate(a)
|
||||
val originalValue = recalculate()
|
||||
val prop = ObjectProperty[B](originalValue)
|
||||
var prevValue = originalValue
|
||||
ops.onChange(a) {
|
||||
prop.synchronized {
|
||||
val newVal = recalculate()
|
||||
if (prevValue != newVal) {
|
||||
prop.value = newVal
|
||||
prevValue = newVal
|
||||
}
|
||||
}
|
||||
}
|
||||
prop
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait RichObservableSeqLike[A] extends Any {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]]
|
||||
}
|
||||
|
||||
final class RichObservableBuffer[A](val obs: ObservableBuffer[A]) extends AnyVal with RichObservableSeqLike[A] {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]] = {
|
||||
RichToObservable.toObservable(obs)
|
||||
}
|
||||
}
|
||||
|
||||
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] {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]] = {
|
||||
RichToObservable.toObservable(oaa)
|
||||
}
|
||||
}
|
||||
|
||||
final class RichObservableSet[A](val os: ObservableSet[A]) extends AnyVal {
|
||||
def observableSetValue: ReadOnlyObjectProperty[Set[A]] = {
|
||||
RichToObservable.toObservable(os)
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,97 @@
|
||||
package org.gerweck.scalafx.util
|
||||
|
||||
import language.implicitConversions
|
||||
|
||||
import scalafx.beans.property._
|
||||
import scalafx.collections._
|
||||
|
||||
sealed trait ToFlatObservable[-A, +B] extends Calculable[A, B]
|
||||
object ToFlatObservable extends CalculableObservable[ToFlatObservable[_, _]] {
|
||||
implicit def obOps[A] = new ToFlatObservable[ObservableBuffer[A], Seq[A]] {
|
||||
def recalculate(oba: ObservableBuffer[A]) = oba.toVector
|
||||
}
|
||||
implicit def oaOps[A] = new ToFlatObservable[ObservableArray[A, _, _], Seq[A]] {
|
||||
def recalculate(oaa: ObservableArray[A, _, _]) = oaa.toVector
|
||||
}
|
||||
implicit def osOps[A] = new ToFlatObservable[ObservableSet[A], collection.immutable.Set[A]] {
|
||||
def recalculate(os: ObservableSet[A]) = os.toSet
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait ObservableSized[-A] extends Calculable[A, Int]
|
||||
object ObservableSized extends CalculableObservable[ObservableSized[_]] {
|
||||
implicit def obSize[A] = new ObservableSized[ObservableBuffer[A]] {
|
||||
def recalculate(oba: ObservableBuffer[A]) = oba.size
|
||||
}
|
||||
implicit def oaSize[A] = new ObservableSized[ObservableArray[A, _, _]] {
|
||||
def recalculate(oaa: ObservableArray[A, _, _]) = oaa.size
|
||||
}
|
||||
implicit def osSize[A] = new ObservableSized[ObservableSet[A]] {
|
||||
def recalculate(os: ObservableSet[A]) = os.size
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait RichObservableSeqLike[A] extends Any {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]]
|
||||
def observableSize: ReadOnlyObjectProperty[Int]
|
||||
}
|
||||
|
||||
final class RichObservableBuffer[A](val obs: ObservableBuffer[A]) extends AnyVal with RichObservableSeqLike[A] {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]] = ToFlatObservable.toObservable(obs)
|
||||
def observableSize = ObservableSized.toObservable(obs)
|
||||
}
|
||||
|
||||
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] {
|
||||
def observableSeqValue: ReadOnlyObjectProperty[Seq[A]] = ToFlatObservable.toObservable(oaa)
|
||||
def observableSize = ObservableSized.toObservable(oaa)
|
||||
}
|
||||
|
||||
final class RichObservableSet[A](val os: ObservableSet[A]) extends AnyVal {
|
||||
def observableSetValue: ReadOnlyObjectProperty[Set[A]] = ToFlatObservable.toObservable(os)
|
||||
def observableSize = ObservableSized.toObservable(os)
|
||||
}
|
||||
|
||||
class CalculableObservable[O <: Calculable[_, _]] {
|
||||
final def toObservable[A, B](a: A)(implicit ops: O with Calculable[A, B], cl: ChangeListenable[A]): ReadOnlyObjectProperty[B] = {
|
||||
@inline def recalculate(): B = ops.recalculate(a)
|
||||
val originalValue = recalculate()
|
||||
val prop = ObjectProperty[B](originalValue)
|
||||
var prevValue = originalValue
|
||||
cl.onChange(a) {
|
||||
prop.synchronized {
|
||||
val newVal = recalculate()
|
||||
if (prevValue != newVal) {
|
||||
prop.value = newVal
|
||||
prevValue = newVal
|
||||
}
|
||||
}
|
||||
}
|
||||
prop
|
||||
}
|
||||
}
|
||||
|
||||
/* Type Classes */
|
||||
|
||||
trait Calculable[-A, +B] extends Any {
|
||||
def recalculate(a: A): B
|
||||
}
|
||||
|
||||
sealed trait ChangeListenable[-A] {
|
||||
def onChange(a: A)(b: => Unit): Unit
|
||||
}
|
||||
object ChangeListenable {
|
||||
implicit def obListenable[A]: ChangeListenable[ObservableBuffer[A]] = new ChangeListenable[ObservableBuffer[A]] {
|
||||
def onChange(oba: ObservableBuffer[A])(b: => Unit) = oba onChange b
|
||||
}
|
||||
implicit def oaListenable[A]: ChangeListenable[ObservableArray[A, _, _]] = new ChangeListenable[ObservableArray[A, _, _]] {
|
||||
def onChange(oaa: ObservableArray[A, _, _])(b: => Unit) = oaa onChange b
|
||||
}
|
||||
implicit def osListenable[A]: ChangeListenable[ObservableSet[A]] = new ChangeListenable[ObservableSet[A]] {
|
||||
def onChange(osa: ObservableSet[A])(b: => Unit) = osa onChange b
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait DeriveChanges[A] {
|
||||
protected val evChange: ChangeListenable[A]
|
||||
def onChange(a: A)(b: => Unit) = evChange.onChange(a)(b)
|
||||
}
|
@ -1 +1 @@
|
||||
version in ThisBuild := "0.8.4-SNAPSHOT"
|
||||
version in ThisBuild := "0.9.0-SNAPSHOT"
|
||||
|
Loading…
Reference in New Issue
Block a user