Used MutHistory to implement forward/backward

router buttons
This commit is contained in:
Rohan Sircar 2020-12-23 14:03:10 +05:30
parent d18c884168
commit 5b50f161d2
2 changed files with 91 additions and 29 deletions

View File

@ -4,6 +4,7 @@ import java.util.concurrent.TimeUnit
import scala.util.Random
import com.jfoenix.controls.JFXDialog
import com.softwaremill.macwire._
import io.odin.Logger
import monix.bio.IO
@ -11,14 +12,16 @@ import monix.bio.Task
import monix.eval.Coeval
import monix.{eval => me}
import nova.monadic_sfx.executors.Schedulers
import nova.monadic_sfx.util.controls.JFXButton
import nova.monadic_sfx.implicits._
import nova.monadic_sfx.ui.MyFxApp
import nova.monadic_sfx.ui.components.router.FXRouter
import nova.monadic_sfx.ui.components.router.Page
import nova.monadic_sfx.ui.components.todo.TodoListStore
import nova.monadic_sfx.ui.components.todo.TodoListView
import nova.monadic_sfx.util.MutHistory
import nova.monadic_sfx.util.controls.JFXButton
import org.gerweck.scalafx.util._
import org.kordamp.bootstrapfx.BootstrapFX
import scalafx.Includes._
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.ObjectProperty
@ -32,9 +35,9 @@ import scalafx.scene.control.Label
import scalafx.scene.control.TableColumn
import scalafx.scene.control.TableView
import scalafx.scene.layout.BorderPane
import scalafx.scene.layout.FlowPane
import scalafx.scene.layout.HBox
import scalafx.scene.layout.Priority
import scalafx.scene.layout.StackPane
class MainApp(
// spawnProtocol: ActorSystem[SpawnProtocol.Command],
@ -45,6 +48,12 @@ class MainApp(
private lazy val _scene = new Scene {
root = new HBox {
padding = Insets(20)
// style = """| -fx-background-color: rgb(38, 38, 38);
// | -fx-text-fill: white;""".stripMargin
stylesheets ++= Seq(
BootstrapFX.bootstrapFXStylesheet,
os.rel / "static" / "css" / "main.css"
)
}
}
@ -53,6 +62,7 @@ class MainApp(
scene = _scene
width = 640
height = 480
// resizable = false
}
val program = for {
@ -61,10 +71,12 @@ class MainApp(
wire[MainAppDelegate].init
.flatMap(mainSceneNode => Task(_scene.getChildren += mainSceneNode))
.executeOn(schedulers.fx)
_ <- Task(stage.resizable = false).executeOn(schedulers.fx)
currentTime <- IO.clock.realTime(TimeUnit.MILLISECONDS)
_ <- logger.info(
s"Application started in ${(currentTime - startTime) / 1000f} seconds"
)
// _ <- Task(CSSFX.start(stage))
_ <- fxAppFib.join
} yield ()
@ -81,30 +93,39 @@ class MainAppDelegate(schedulers: Schedulers)(implicit logger: Logger[Task]) {
val init =
for {
//FXRouter does not allocate mutable state so it's ok to use pure here
router <- Task.pure(new FXRouter[Page])
history <- Task(new MutHistory[Page](Page.Home))
router <- Task.pure(new FXRouter[Page](history))
routerStore <- router.store(Page.Home, logger)
todoStore <- TodoListStore(logger)
todoComponent <- TodoListView(todoStore)
resolver: PartialFunction[Page, Task[Parent]] = {
case Page.Home =>
Task(new Label {
styleClass ++= Seq("text-white")
text = "HomePage"
})
case Page.UserHome(id0) =>
Task(new Label {
styleClass ++= Seq("text-white")
text = s"User Home, Id = $id0"
})
case Page.Todo =>
Task(todoComponent)
Task.pure(todoComponent)
}
routerNode <-
Task
.deferAction(implicit s =>
Task(new HBox {
alignment = Pos.Center
//TODO find a better way to do this
var oldValue: Option[Parent] = None
children <-- router
.render(resolver)(routerStore)
// .scanEvalF[Coeval, (Option[Parent], Option[Parent])](
// Coeval.pure(None -> None)
// ) {
// case (oldValue, newValue) => Coeval(None -> None)
// }
// call cancel on the old component to cancel all subscriptions
.doOnNextF(newValue =>
Coeval { oldValue.foreach(_ => ()) } >> Coeval {
@ -116,14 +137,41 @@ class MainAppDelegate(schedulers: Schedulers)(implicit logger: Logger[Task]) {
)
mainSceneNode <- Task.deferAction(implicit s =>
Task(new BorderPane {
Task(new StackPane { root =>
hgrow = Priority.Always
vgrow = Priority.Always
children = new BorderPane {
hgrow = Priority.Always
vgrow = Priority.Always
center = routerNode
bottom = new FlowPane {
bottom = new HBox {
alignment = Pos.Center
hgap = 20
spacing = 20
children = Seq(
new JFXButton {
text = "Forward"
style = buttonStyle
onAction = () => {
history.forward()
routerStore.onNext(FXRouter.HistoryEvent(history.current))
}
},
new JFXButton {
text = "Backward"
style = buttonStyle
onAction = () => {
history.backward()
routerStore.onNext(FXRouter.HistoryEvent(history.current))
}
},
new JFXButton {
text = "Home"
style = buttonStyle
obsAction
.useLazyEval(
me.Task.pure(FXRouter.Replace(Page.Home))
) --> routerStore
},
new JFXButton {
text = "Todo"
style = buttonStyle
@ -137,11 +185,25 @@ class MainAppDelegate(schedulers: Schedulers)(implicit logger: Logger[Task]) {
style = buttonStyle
obsAction
.useLazyEval(
me.Task(FXRouter.Replace(Page.UserHome(Random.nextInt(20))))
me.Task(
FXRouter.Replace(Page.UserHome(Random.nextInt(20)))
)
) --> routerStore
},
new JFXButton {
text = "Dialog"
style = buttonStyle
val d = new JFXDialog()
d.setContent(new HBox {
children = Seq(new Label("hmm"))
padding = Insets(20)
})
d.styleClass ++= Seq("text-white")
onAction = () => d.show(root)
}
)
}
}
})
)
} yield mainSceneNode

View File

@ -5,10 +5,10 @@ import java.time.LocalDateTime
import io.circe.Encoder
import io.odin.Logger
import monix.bio.Task
import monix.reactive.OverflowStrategy
import monix.reactive.subjects.ConcurrentSubject
import monix.eval.Coeval
import monix.reactive.Observable
import monix.reactive.OverflowStrategy
import monix.reactive.subjects.ConcurrentSubject
object Store {
def createL[A, M](