package nova.monadic_sfx import com.softwaremill.macwire._ import io.odin.Logger import monix.bio.Task import monix.catnap.ConcurrentChannel import nova.monadic_sfx.executors.Schedulers import nova.monadic_sfx.implicits.JFXButton import nova.monadic_sfx.implicits.JavaFXMonixObservables._ import nova.monadic_sfx.ui.MyFxApp import nova.monadic_sfx.ui.components.todo.Todo import nova.monadic_sfx.ui.components.todo.TodoListComponent import nova.monadic_sfx.ui.components.todo.TodoListView import nova.monadic_sfx.util.IOUtils._ 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.scene.Scene import scalafx.scene.control.TableColumn import scalafx.scene.control.TableView import scalafx.scene.layout.HBox import scalafx.scene.paint.Color import scalafx.scene.shape.Rectangle class MainApp( // spawnProtocol: ActorSystem[SpawnProtocol.Command], schedulers: Schedulers, startTime: Long )(implicit logger: Logger[Task]) { lazy val addTodoButton = new JFXButton { text = "Add" } lazy val addTodoObs = addTodoButton.observableAction() lazy val todoListView = TodoListView.defaultListView lazy val _scene = new Scene { root = new HBox { padding = Insets(20) content = new Rectangle { width = 400 height = 200 fill = Color.DeepSkyBlue } children ++= Seq( new JFXButton { text = "DummyButton" }, new JFXButton { text = "DummyButton2" }, addTodoButton, Test.ttv // todoListView ) } } private lazy val stage = new PrimaryStage { title = "Simple ScalaFX App" scene = _scene width = 800 height = 400 } // implicit val l = logger // implicit val sp = spawnProtocol val program = for { (fxApp, fxAppFib) <- wire[MyFxApp].init(stage) // _ <- Task(fxApp.stage = stage) // .executeOn(schedulers.fx) // .delayExecution(2000.millis) todoComponent <- createTodoComponent _ <- toIO( addTodoObs .mapEval(_ => toTask(todoComponent.send(TodoListComponent.Add(Todo(1, "blah")))) ) .completedL .executeOn(schedulers.fx) .startAndForget ) _ <- logger.info( s"Application started in ${(System.currentTimeMillis() - startTime) / 1000f} seconds" ) _ <- fxAppFib.join } yield () def createTodoComponent: Task[TodoListComponent] = { for { channel <- ConcurrentChannel .of[Task, TodoListComponent.Complete, TodoListComponent.Command] scheduler = schedulers.fx (lv, delObs, editObs) <- TodoListView.defaultListView2.executeOn(scheduler) todoLV = new TodoListView(lv) todoComponent <- wire[TodoListComponent.Props].create // TODO make this a "message pass" instead of mutating directly _ <- Task(_scene.getChildren += lv).executeOn(scheduler) _ <- toIO( delObs .doOnNext(_ => toTask(logger.debug("Pressed delete"))) .doOnNext(todo => toTask( for { _ <- logger.debug(s"Got todo $todo") _ <- todoComponent.send(TodoListComponent.Delete(todo.id)) // _ <- Task.sequence( // lst.map(todo => // todoComponent.send(TodoListComponent.Delete(todo.id)) // ) // ) } yield () ) ) .completedL ).startAndForget _ <- toIO( editObs .doOnNext(_ => toTask(logger.debug("Pressed edit"))) .completedL ).startAndForget } yield todoComponent } } 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 } } ) } }