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.

128 lines
4.1 KiB

  1. package nova.monadic_sfx.ui.components.todo
  2. import monix.bio.Task
  3. import monix.execution.cancelables.CompositeCancelable
  4. import nova.monadic_sfx.implicits.FontIcon
  5. import nova.monadic_sfx.implicits.IconLiteral
  6. import nova.monadic_sfx.implicits.JFXButton
  7. import nova.monadic_sfx.implicits.JFXListView
  8. import nova.monadic_sfx.implicits.JFXTextField
  9. import nova.monadic_sfx.implicits.JavaFXMonixObservables._
  10. import nova.monadic_sfx.implicits.MenuItem
  11. import nova.monadic_sfx.util.reactive._
  12. import org.gerweck.scalafx.util._
  13. import scalafx.Includes._
  14. import scalafx.beans.property.ObjectProperty
  15. import scalafx.beans.property.StringProperty
  16. import scalafx.geometry.Insets
  17. import scalafx.scene.Node
  18. import scalafx.scene.control.ContextMenu
  19. import scalafx.scene.control.ListCell
  20. import scalafx.scene.control.SelectionMode
  21. import scalafx.scene.layout.HBox
  22. import scalafx.scene.text.Text
  23. import monix.{eval => me}
  24. object TodoListView {
  25. def apply(
  26. store: MonixProSubject[
  27. TodoListStore.Command,
  28. (TodoListStore.Command, TodoListStore.State)
  29. ]
  30. ): Task[Node] =
  31. Task.deferAction(implicit s =>
  32. Task {
  33. val cc = CompositeCancelable()
  34. val todos =
  35. store.map { case (_, state) => state.todos }
  36. // Todo(-1, "").some
  37. val _selectedItems = ObjectProperty(Seq.empty[Todo])
  38. new HBox {
  39. padding = Insets(5)
  40. val _content = StringProperty("")
  41. children = Seq(
  42. new JFXTextField {
  43. text ==> _content
  44. },
  45. new JFXListView[Todo] {
  46. def selectedItems = selectionModel().selectedItems.view
  47. cc += items <-- todos
  48. val emptyCell = ObjectProperty(new HBox)
  49. cellFactory = _ =>
  50. new ListCell[Todo] {
  51. val _text = StringProperty("")
  52. val _graphic = ObjectProperty(
  53. new HBox {
  54. children = Seq(
  55. new FontIcon {
  56. iconSize = 10
  57. iconLiteral = IconLiteral.Gmi10k
  58. },
  59. new Text {
  60. text <== _text
  61. }
  62. )
  63. }
  64. )
  65. item.asOption.map(
  66. _.fold("")(todo => s"${todo.id} - ${todo.content}")
  67. ) ==> _text
  68. graphic <== item.asOption.flatMap(
  69. _.fold(emptyCell)(_ => _graphic)
  70. )
  71. }
  72. selectionModel().selectionMode = SelectionMode.Multiple
  73. selectionModel().selectedItems.observableSeqValue ==> _selectedItems
  74. contextMenu = new ContextMenu {
  75. items ++= Seq(
  76. new MenuItem {
  77. text = "Add"
  78. // obsAction.useLazyEval(TodoListStore.Add("blah3")) --> store
  79. },
  80. new MenuItem {
  81. text = "Delete"
  82. obsAction.useIterableEval(_ =>
  83. selectedItems
  84. .map(todo => TodoListStore.Delete(todo.id))
  85. .toList
  86. ) --> store
  87. },
  88. new MenuItem {
  89. text = "Edit"
  90. }
  91. )
  92. }
  93. },
  94. new JFXButton {
  95. text = "Add"
  96. disable <== _selectedItems.map(_.length > 0)
  97. obsAction
  98. .useLazyEval(me.Task(TodoListStore.Add(_content()))) --> store
  99. },
  100. new JFXButton {
  101. text = "Edit"
  102. disable <== _selectedItems.map(_.length > 1)
  103. obsAction.useLazyEval(
  104. me.Task(
  105. TodoListStore.Edit(
  106. _selectedItems
  107. .map(_.headOption.map(_.id).getOrElse(-1))
  108. .value,
  109. _content()
  110. )
  111. )
  112. ) --> store
  113. }
  114. )
  115. }
  116. }
  117. )
  118. }