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.

174 lines
6.3 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
  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. import nova.monadic_sfx.util.controls.ActionObservableDsl
  31. import nova.monadic_sfx.ui.FXComponent
  32. object TodoListView {
  33. def apply(
  34. store: MyStore[TodoListStore.Action, TodoListStore.State]
  35. ) =
  36. FXComponent(implicit cc =>
  37. Task.deferAction(implicit s =>
  38. Task {
  39. import ActionObservableDsl._
  40. // implicit val cc = CompositeCancelable()
  41. val todos = store.source
  42. .map { case (_, state) => state.todos }
  43. .distinctUntilChanged
  44. .map(ObservableBuffer.from)
  45. .doOnNextF(item => Coeval(println(s"Received item: $item")))
  46. val _selectedItems = ObjectProperty(Seq.empty[Todo])
  47. new BorderPane {
  48. padding = Insets(5)
  49. hgrow = Priority.Always
  50. val _content = StringProperty("")
  51. center = new HBox {
  52. padding = Insets(5)
  53. children ++= Seq(new JFXListView[Todo] {
  54. id = "todoList"
  55. hgrow = Priority.Always
  56. def selectedItems = selectionModel().selectedItems.view
  57. styleClass ++= Seq("text-white", "clear-list-view")
  58. selectionModel().selectionMode = SelectionMode.Multiple
  59. selectionModel().selectedItems.observableSeqValue ==> _selectedItems
  60. items <-- todos.map(_.delegate)
  61. val emptyCell = ObjectProperty(new HBox)
  62. cellFactory = _ =>
  63. new ListCell[Todo] {
  64. val _text = StringProperty("")
  65. val _graphic = ObjectProperty(
  66. new HBox {
  67. styleClass ++= Seq("text-white", "strong", "todo-cell")
  68. children = Seq(
  69. new FontIcon {
  70. iconSize = 20
  71. iconLiteral = IconLiteral.Gmi10k
  72. fill = Color.White
  73. },
  74. new Label {
  75. style = "-fx-text-fill: white "
  76. styleClass ++= Seq("text-white", "strong")
  77. text <== _text
  78. }
  79. )
  80. }
  81. )
  82. item.asOption.map(
  83. _.fold("")(todo => s"${todo.id} - ${todo.content}")
  84. ) ==> _text
  85. graphic <== item.asOption.flatMap(
  86. _.fold(emptyCell)(_ => _graphic)
  87. )
  88. }
  89. contextMenu = new ContextMenu {
  90. items ++= Seq(
  91. new MenuItem {
  92. text = "Delete"
  93. // obsAction.(_ =>
  94. // selectedItems
  95. // .map(todo => TodoListStore.Delete(todo.id))
  96. // .toList
  97. // ) --> store.sink
  98. obsAction.flatMapIterable(_ =>
  99. selectedItems
  100. .map(todo => TodoListStore.Delete(todo.id))
  101. .toList
  102. ) --> store.sink
  103. // obsAction.split(
  104. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
  105. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
  106. // _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store
  107. // )
  108. },
  109. new MenuItem {
  110. text = "Edit"
  111. }
  112. )
  113. }
  114. })
  115. }
  116. bottom = new HBox {
  117. spacing = 5
  118. padding = Insets(5)
  119. children = Seq(
  120. new JFXTextField {
  121. id = "todoInputField"
  122. style = "-fx-background-color: rgb(38,38,38);"
  123. styleClass += "text-white"
  124. text ==> _content
  125. vgrow = Priority.Always
  126. },
  127. new JFXButton {
  128. id = "todoAddButton"
  129. text = "Add"
  130. alignment = Pos.Center
  131. // disable <== _selectedItems.map(_.length > 0)
  132. styleClass = Seq("btn", "btn-primary")
  133. obsAction
  134. .mapEval(_ =>
  135. me.Task(TodoListStore.Add(_content()))
  136. ) --> store.sink
  137. },
  138. new JFXButton {
  139. id = "todoEditButton"
  140. text = "Edit"
  141. alignment = Pos.Center
  142. disable <== _selectedItems.map(_.length > 1)
  143. styleClass = Seq("btn", "btn-info")
  144. obsAction.mapEval(_ =>
  145. me.Task(
  146. TodoListStore.Edit(
  147. _selectedItems
  148. .map(_.headOption.map(_.id).getOrElse(-1))
  149. .value,
  150. _content()
  151. )
  152. )
  153. ) --> store.sink
  154. }
  155. )
  156. }
  157. }
  158. }
  159. )
  160. )
  161. }