You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

80 lines
2.2 KiB

package org.gerweck.scalafx.util
import shapeless._
import shapeless.ops.hlist._
import shapeless.ops.function._
import scalafx.beans.property.ObjectProperty
import scalafx.beans.value.ObservableValue
/**
*
* @author Sarah Gerweck <sarah@atscale.com>
*/
class ObservableTupler
[HLObs <: HList, HLParams <: HList, TParams <: Product] private
(hlist: HLObs)
(implicit
unwrapper: Mapper.Aux[ObservableUnwrapper.type, HLObs, HLParams],
tupler: Tupler.Aux[HLParams, TParams],
lister: ToList[HLObs, Observable[_]]) {
def |@|[O, P, Appended <: HList, Unwrap <: HList, Tupled <: Product, ApList]
(f: ObservableValue[O, P])
(implicit
prepend: Prepend.Aux[HLObs, ObservableValue[O, P]::HNil, Appended],
uw: Mapper.Aux[ObservableUnwrapper.type, Appended, Unwrap],
tplr: Tupler.Aux[Unwrap, Tupled],
lst: ToList[Appended, Observable[_]]): ObservableTupler[Appended, Unwrap, Tupled] = {
val newHL: Appended = hlist :+ f
new ObservableTupler[Appended, Unwrap, Tupled](newHL)
}
def hlisted: ObservableValue[HLParams, HLParams] = {
def calculate() = unwrapper(hlist)
val original = calculate()
val prop = ObjectProperty[HLParams](original)
for {
component <- hlist.toList
} {
component onChange {
prop.value = calculate()
}
}
prop
}
def tupled: ObservableValue[TParams, TParams] = {
def calculate() = unwrapper(hlist).tupled
val original = calculate()
val prop = ObjectProperty[TParams](original)
for {
component <- hlist.toList
} {
component onChange {
prop.value = calculate()
}
}
prop
}
def apply[Func, Result]
(f: Func)
(implicit ftp: FnToProduct.Aux[Func, HLParams => Result])
: ObservableValue[Result, Result] = {
hlisted map ftp(f)
}
}
object ObservableUnwrapper extends Poly1 {
implicit def apply[T, U, A](implicit ev1: A => ObservableValue[T, U]): Case.Aux[A, T] = at[A]{ o => o.value }
}
object ObservableTupler {
def apply[A, A1, B, B1](a: ObservableValue[A, A1], b: ObservableValue[B, B1]) = {
new ObservableTupler(a::b::HNil)
}
}