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.
 
 
 

84 lines
2.3 KiB

package nova.monadic_sfx.ui
import scala.concurrent.duration._
import cats.effect.Resource
import io.odin.Logger
import monix.bio.Task
import monix.execution.CancelablePromise
import nova.monadic_sfx.concurrent.Schedulers
import nova.monadic_sfx.ui.DefaultScene
import scalafx.application.JFXApp3
import scalafx.application.JFXApp3.PrimaryStage
import monix.bio.UIO
import monix.eval.Coeval
import scalafx.scene.Scene
import scalafx.scene.Parent
import scalafx.Includes._
import monix.bio.IO
import scalafx.scene.Node
final class FX private (
schedulers: Schedulers,
delegate: JFXApp3,
val await: Task[Unit],
val awaitStop: Task[Unit]
)(implicit logger: Logger[Task]) {
logger.debug("whoopie")
def runOnFx[E, A](io: IO[E, A]) = io.executeOn(schedulers.fx.value)
def addToScene(node: UIO[Node]) =
runOnFx {
for {
p <- node
_ <- UIO(delegate.stage.scene().getChildren += p)
} yield ()
}
}
object FX {
def resource(
schedulers: Schedulers,
stage: Coeval[PrimaryStage],
initialScene: Coeval[Scene] = DefaultScene(),
transitionDelay: FiniteDuration = 500.millis
)(implicit
logger: Logger[Task]
): Resource[Task, FX] =
Resource
.make(for {
_ <- logger.info("Starting FX App")
makePromise = UIO(CancelablePromise[Unit]())
startSignal <- makePromise
stopSignal <- makePromise
delegate <- Task(new JFXApp3 {
def start(): Unit = {
stage = new PrimaryStage {
scene = initialScene.value()
}
startSignal.success(())
}
override def stopApp(): Unit = {
stopSignal.success(())
}
})
fib <-
Task(delegate.main(Array.empty)).start.executeOn(schedulers.io.value)
fxApp <- Task(
new FX(
schedulers,
delegate,
fib.join,
Task.fromCancelablePromise(stopSignal)
)
)
_ <- Task.fromCancelablePromise(startSignal)
_ <- Task.sleep(transitionDelay)
_ <- Task(delegate.stage = stage.value())
.executeOn(schedulers.fx.value)
.delayExecution(transitionDelay)
} yield fxApp -> fib) { case _ -> fib => fib.cancel }
.map { case a -> _ => a }
}