|
|
@ -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,31 +137,72 @@ 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 |
|
|
|
center = routerNode |
|
|
|
bottom = new FlowPane { |
|
|
|
alignment = Pos.Center |
|
|
|
hgap = 20 |
|
|
|
children = Seq( |
|
|
|
new JFXButton { |
|
|
|
text = "Todo" |
|
|
|
style = buttonStyle |
|
|
|
obsAction |
|
|
|
.useLazyEval( |
|
|
|
me.Task.pure(FXRouter.Replace(Page.Todo)) |
|
|
|
) --> routerStore |
|
|
|
}, |
|
|
|
new JFXButton { |
|
|
|
text = "UserHome" |
|
|
|
style = buttonStyle |
|
|
|
obsAction |
|
|
|
.useLazyEval( |
|
|
|
me.Task(FXRouter.Replace(Page.UserHome(Random.nextInt(20)))) |
|
|
|
) --> routerStore |
|
|
|
} |
|
|
|
) |
|
|
|
children = new BorderPane { |
|
|
|
hgrow = Priority.Always |
|
|
|
vgrow = Priority.Always |
|
|
|
center = routerNode |
|
|
|
bottom = new HBox { |
|
|
|
alignment = Pos.Center |
|
|
|
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 |
|
|
|
obsAction |
|
|
|
.useLazyEval( |
|
|
|
me.Task.pure(FXRouter.Replace(Page.Todo)) |
|
|
|
) --> routerStore |
|
|
|
}, |
|
|
|
new JFXButton { |
|
|
|
text = "UserHome" |
|
|
|
style = buttonStyle |
|
|
|
obsAction |
|
|
|
.useLazyEval( |
|
|
|
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) |
|
|
|
} |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
}) |
|
|
|
) |
|
|
|