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.

163 lines
5.6 KiB

3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. package nova.monadic_sfx.ui.components.todo
  2. import monix.bio.Task
  3. import monix.eval.Coeval
  4. import monix.execution.cancelables.CompositeCancelable
  5. import monix.{eval => me}
  6. import nova.monadic_sfx.implicits._
  7. import nova.monadic_sfx.util.controls.FontIcon
  8. import nova.monadic_sfx.util.controls.IconLiteral
  9. import nova.monadic_sfx.util.controls.JFXButton
  10. import nova.monadic_sfx.util.controls.JFXListView
  11. import nova.monadic_sfx.util.controls.JFXTextField
  12. import nova.monadic_sfx.util.controls.MenuItem
  13. import nova.monadic_sfx.util.reactive.store._
  14. import org.gerweck.scalafx.util._
  15. import scalafx.Includes._
  16. import scalafx.beans.property.ObjectProperty
  17. import scalafx.beans.property.StringProperty
  18. import scalafx.collections.ObservableBuffer
  19. import scalafx.geometry.Insets
  20. import scalafx.geometry.Pos
  21. import scalafx.scene.Parent
  22. import scalafx.scene.control.ContextMenu
  23. import scalafx.scene.control.Label
  24. import scalafx.scene.control.ListCell
  25. import scalafx.scene.control.SelectionMode
  26. import scalafx.scene.layout.BorderPane
  27. import scalafx.scene.layout.HBox
  28. import scalafx.scene.layout.Priority
  29. import scalafx.scene.paint.Color
  30. object TodoListView {
  31. def apply(
  32. store: Store[TodoListStore.Action, TodoListStore.State]
  33. ): Task[Parent] =
  34. Task.deferAction(implicit s =>
  35. Task {
  36. implicit val cc = CompositeCancelable()
  37. val todos = store
  38. .map { case (_, state) => state.todos }
  39. .distinctUntilChanged
  40. .map(ObservableBuffer.from)
  41. .doOnNextF(item => Coeval(println(s"Received item: $item")))
  42. val _selectedItems = ObjectProperty(Seq.empty[Todo])
  43. new BorderPane {
  44. padding = Insets(5)
  45. hgrow = Priority.Always
  46. val _content = StringProperty("")
  47. center = new HBox {
  48. padding = Insets(5)
  49. children ++= Seq(new JFXListView[Todo] {
  50. id = "todoList"
  51. hgrow = Priority.Always
  52. def selectedItems = selectionModel().selectedItems.view
  53. styleClass ++= Seq("text-white", "clear-list-view")
  54. selectionModel().selectionMode = SelectionMode.Multiple
  55. selectionModel().selectedItems.observableSeqValue ==> _selectedItems
  56. items <-- todos.map(_.delegate)
  57. val emptyCell = ObjectProperty(new HBox)
  58. cellFactory = _ =>
  59. new ListCell[Todo] {
  60. val _text = StringProperty("")
  61. val _graphic = ObjectProperty(
  62. new HBox {
  63. styleClass ++= Seq("text-white", "strong", "todo-cell")
  64. children = Seq(
  65. new FontIcon {
  66. iconSize = 20
  67. iconLiteral = IconLiteral.Gmi10k
  68. fill = Color.White
  69. },
  70. new Label {
  71. style = "-fx-text-fill: white "
  72. styleClass ++= Seq("text-white", "strong")
  73. text <== _text
  74. }
  75. )
  76. }
  77. )
  78. item.asOption.map(
  79. _.fold("")(todo => s"${todo.id} - ${todo.content}")
  80. ) ==> _text
  81. graphic <== item.asOption.flatMap(
  82. _.fold(emptyCell)(_ => _graphic)
  83. )
  84. }
  85. contextMenu = new ContextMenu {
  86. items ++= Seq(
  87. new MenuItem {
  88. text = "Delete"
  89. obsAction.useIterableEval(_ =>
  90. selectedItems
  91. .map(todo => TodoListStore.Delete(todo.id))
  92. .toList
  93. ) --> store
  94. // obsAction.split(
  95. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
  96. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
  97. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store
  98. // )
  99. },
  100. new MenuItem {
  101. text = "Edit"
  102. }
  103. )
  104. }
  105. })
  106. }
  107. bottom = new HBox {
  108. spacing = 5
  109. padding = Insets(5)
  110. children = Seq(
  111. new JFXTextField {
  112. id = "todoInputField"
  113. style = "-fx-background-color: rgb(38,38,38);"
  114. styleClass += "text-white"
  115. text ==> _content
  116. vgrow = Priority.Always
  117. },
  118. new JFXButton {
  119. id = "todoAddButton"
  120. text = "Add"
  121. alignment = Pos.Center
  122. // disable <== _selectedItems.map(_.length > 0)
  123. styleClass = Seq("btn", "btn-primary")
  124. obsAction
  125. .useLazyEval(
  126. me.Task(TodoListStore.Add(_content()))
  127. ) --> store
  128. },
  129. new JFXButton {
  130. id = "todoEditButton"
  131. text = "Edit"
  132. alignment = Pos.Center
  133. disable <== _selectedItems.map(_.length > 1)
  134. styleClass = Seq("btn", "btn-info")
  135. obsAction.useLazyEval(
  136. me.Task(
  137. TodoListStore.Edit(
  138. _selectedItems
  139. .map(_.headOption.map(_.id).getOrElse(-1))
  140. .value,
  141. _content()
  142. )
  143. )
  144. ) --> store
  145. }
  146. )
  147. }
  148. }
  149. }
  150. )
  151. }