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.
 
 
 

173 lines
5.1 KiB

package nova.monadic_sfx
import java.util.concurrent.TimeUnit
import scala.util.Random
import com.softwaremill.macwire._
import io.odin.Logger
import monix.bio.IO
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 org.gerweck.scalafx.util._
import scalafx.Includes._
import scalafx.application.JFXApp.PrimaryStage
import scalafx.beans.property.ObjectProperty
import scalafx.beans.property.StringProperty
import scalafx.collections.ObservableBuffer
import scalafx.geometry.Insets
import scalafx.geometry.Pos
import scalafx.scene.Parent
import scalafx.scene.Scene
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
class MainApp(
// spawnProtocol: ActorSystem[SpawnProtocol.Command],
schedulers: Schedulers,
startTime: Long
)(implicit logger: Logger[Task]) {
private lazy val _scene = new Scene {
root = new HBox {
padding = Insets(20)
}
}
private lazy val stage = new PrimaryStage {
title = "Simple ScalaFX App"
scene = _scene
width = 640
height = 480
}
val program = for {
(fxApp, fxAppFib) <- wire[MyFxApp].init(stage)
_ <-
wire[MainAppDelegate].init
.flatMap(mainSceneNode => Task(_scene.getChildren += mainSceneNode))
.executeOn(schedulers.fx)
currentTime <- IO.clock.realTime(TimeUnit.MILLISECONDS)
_ <- logger.info(
s"Application started in ${(currentTime - startTime) / 1000f} seconds"
)
_ <- fxAppFib.join
} yield ()
}
class MainAppDelegate(schedulers: Schedulers)(implicit logger: Logger[Task]) {
val buttonStyle = """| -fx-padding: 0.7em 0.57em;
| -fx-font-size: 14px;
| -jfx-button-type: RAISED;
| -fx-background-color: rgb(77,102,204);
| -fx-pref-width: 200;
| -fx-text-fill: WHITE; """.stripMargin
val init =
for {
//FXRouter does not allocate mutable state so it's ok to use pure here
router <- Task.pure(new FXRouter[Page])
routerStore <- router.store(Page.Home, logger)
todoStore <- TodoListStore(logger)
todoComponent <- TodoListView(todoStore)
resolver: PartialFunction[Page, Task[Parent]] = {
case Page.Home =>
Task(new Label {
text = "HomePage"
})
case Page.UserHome(id0) =>
Task(new Label {
text = s"User Home, Id = $id0"
})
case Page.Todo =>
Task(todoComponent)
}
routerNode <-
Task
.deferAction(implicit s =>
Task(new HBox {
//TODO find a better way to do this
var oldValue: Option[Parent] = None
children <-- router
.render(resolver)(routerStore)
// call cancel on the old component to cancel all subscriptions
.doOnNextF(newValue =>
Coeval { oldValue.foreach(_ => ()) } >> Coeval {
oldValue = Some(newValue)
}
)
.map(_.delegate)
})
)
mainSceneNode <- Task.deferAction(implicit s =>
Task(new BorderPane {
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
}
)
}
})
)
} yield mainSceneNode
}
class TestModel(_name: String, _age: Int) {
val name = StringProperty(_name).readOnly
val age = ObjectProperty(_age).readOnly
}
object Test {
val items = ObservableBuffer(
new TestModel("hmm", 1),
new TestModel("hmm2", 2)
)
val ttv = new TableView[TestModel](items) {
columns ++= Seq(
new TableColumn[TestModel, String] {
text = "Name"
cellValueFactory = { _.value.name }
},
new TableColumn[TestModel, Int] {
text = "Age"
cellValueFactory = { _.value.age }
}
)
}
}