Browse Source
Add `observableSize` operation to collections
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.master
Sarah Gerweck
8 years ago
3 changed files with 98 additions and 61 deletions
-
60src/main/scala/org/gerweck/scalafx/util/observable.scala
-
97src/main/scala/org/gerweck/scalafx/util/observableCollection.scala
-
2version.sbt
@ -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" |
Write
Preview
Loading…
Cancel
Save
Reference in new issue