diff --git a/project/Build.scala b/project/Build.scala index 4fe8139..c0c9468 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -333,7 +333,8 @@ object UtilsBuild extends Build { logback % "runtime,optional", gerweckUtil, scalaFx, - scalaz + scalaz, + shapeless ), unmanagedJars in Compile += Attributed.blank(file(System.getenv("JAVA_HOME") + "/jre/lib/ext/jfxrt.jar")) diff --git a/src/main/scala/org/gerweck/scalafx/util/ObservableTupler.scala b/src/main/scala/org/gerweck/scalafx/util/ObservableTupler.scala new file mode 100644 index 0000000..5de155f --- /dev/null +++ b/src/main/scala/org/gerweck/scalafx/util/ObservableTupler.scala @@ -0,0 +1,44 @@ +/* + * Copyright AtScale, Inc. 2015. All Rights Reserved. + * + * No part of this project or any of its contents may be reproduced, copied, + * modified or adapted, without the prior written consent of AtScale, Inc.. + */ + +package org.gerweck.scalafx.util + +import scalaz._ +import Scalaz._ + +import shapeless._ +import shapeless.syntax._ +import shapeless.ops.hlist._ + +import scalafx.beans.value.ObservableValue + +/** + * + * @author Sarah Gerweck + */ +class ObservableTupler[HLObs <: HList, HLParams <: HList, TParams <: Product] private[util] + (hlist: HLObs) + (implicit ops: HListOps[HLObs], + unwrapper: Mapper.Aux[unwrapObservable.type, HLObs, HLParams], + tupler: Generic.Aux[HLParams, TParams]) { + def |@|[O, P, Appended <: HList, Unwrapped, Tupled] + (f: ObservableValue[O, P]) + (implicit prepend: Prepend.Aux[HLObs, ObservableValue[O, P]::HNil, Appended], + uw: Mapper.Aux[unwrapObservable.type, Appended, Unwrapped], + tplr: Generic.Aux[Unwrapped, Tupled], + ops: HListOps[Appended]) = { + val newHL: Appended = hlist :+ f + new ObservableTupler[Appended, Unwrapped, Tupled](newHL) + } +} + + +object ObservableTupler { + object unwrapObservable extends Poly1 { + implicit def apply[T, U, A <% ObservableValue[T, U]]: Case.Aux[A, T] = at[A]{ o => o.value } + } +} diff --git a/src/main/scala/org/gerweck/scalafx/util/package.scala b/src/main/scala/org/gerweck/scalafx/util/package.scala index 874280a..e7057e1 100644 --- a/src/main/scala/org/gerweck/scalafx/util/package.scala +++ b/src/main/scala/org/gerweck/scalafx/util/package.scala @@ -67,6 +67,33 @@ package object util { } } + implicit class RichObservable[A](val self: Observable[A]) { + private type F[X] = Observable[X] + @inline private def F = observableApplicative + + def map[A1 >: A, B](f: A1 => B) = F.map(self)(f) + def <*>[B](f: Observable[A => B]): Observable[B] = F.ap(self)(f) + def tuple[B](f: Observable[B]): Observable[(A,B)] = F.tuple2(self, f) + final def *>[B](fb: F[B]): F[B] = F.apply2(self,fb)((_,b) => b) + final def <*[B](fb: F[B]): F[A] = F.apply2(self,fb)((a,_) => a) + + import shapeless._ + import shapeless.syntax._ + import shapeless.ops.hlist._ + import HList._ + implicitly[HListOps[Int::Int::HNil]] + final def |@|[B](fb: F[B]) = new ObservableTupler(self::fb::HNil) + + /** Alias for `|@|` */ + final def ⊛[B](fb: F[B]) = |@|(fb) + } + + object unwrapObservable extends Poly1 { + implicit def apply[T, A <% Observable[T]]: Case.Aux[A, T] = at[A]{ o => o.value } + } + + trait TupleBuilder[] + implicit class RichProperty[A](val inner: SimpleProperty[A]) extends AnyVal { def biMap[B <: AnyRef](push: A => B, pull: B => A): ObjectProperty[B] = { val original = push(inner.value)