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

package nova.monadic_sfx.ui.components.todo
import monix.bio.Task
import monix.eval.Coeval
import monix.execution.cancelables.CompositeCancelable
import monix.{eval => me}
import nova.monadic_sfx.implicits._
import nova.monadic_sfx.util.controls.FontIcon
import nova.monadic_sfx.util.controls.IconLiteral
import nova.monadic_sfx.util.controls.JFXButton
import nova.monadic_sfx.util.controls.JFXListView
import nova.monadic_sfx.util.controls.JFXTextField
import nova.monadic_sfx.util.controls.MenuItem
import nova.monadic_sfx.util.reactive.store._
import org.gerweck.scalafx.util._
import scalafx.Includes._
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.control.ContextMenu
import scalafx.scene.control.Label
import scalafx.scene.control.ListCell
import scalafx.scene.control.SelectionMode
import scalafx.scene.layout.BorderPane
import scalafx.scene.layout.HBox
import scalafx.scene.layout.Priority
import scalafx.scene.paint.Color
object TodoListView {
def apply(
store: Store[TodoListStore.Action, TodoListStore.State]
): Task[Parent] =
Task.deferAction(implicit s =>
Task {
implicit val cc = CompositeCancelable()
val todos = store
.map { case (_, state) => state.todos }
.distinctUntilChanged
.map(ObservableBuffer.from)
.doOnNextF(item => Coeval(println(s"Received item: $item")))
val _selectedItems = ObjectProperty(Seq.empty[Todo])
new BorderPane {
padding = Insets(5)
hgrow = Priority.Always
val _content = StringProperty("")
center = new HBox {
padding = Insets(5)
children ++= Seq(new JFXListView[Todo] {
id = "todoList"
hgrow = Priority.Always
def selectedItems = selectionModel().selectedItems.view
styleClass ++= Seq("text-white", "clear-list-view")
selectionModel().selectionMode = SelectionMode.Multiple
selectionModel().selectedItems.observableSeqValue ==> _selectedItems
items <-- todos.map(_.delegate)
val emptyCell = ObjectProperty(new HBox)
cellFactory = _ =>
new ListCell[Todo] {
val _text = StringProperty("")
val _graphic = ObjectProperty(
new HBox {
styleClass ++= Seq("text-white", "strong", "todo-cell")
children = Seq(
new FontIcon {
iconSize = 20
iconLiteral = IconLiteral.Gmi10k
fill = Color.White
},
new Label {
style = "-fx-text-fill: white "
styleClass ++= Seq("text-white", "strong")
text <== _text
}
)
}
)
item.asOption.map(
_.fold("")(todo => s"${todo.id} - ${todo.content}")
) ==> _text
graphic <== item.asOption.flatMap(
_.fold(emptyCell)(_ => _graphic)
)
}
contextMenu = new ContextMenu {
items ++= Seq(
new MenuItem {
text = "Delete"
obsAction.useIterableEval(_ =>
selectedItems
.map(todo => TodoListStore.Delete(todo.id))
.toList
) --> store
// obsAction.split(
// _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
// _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store,
// _.useLazyEval(me.Task(TodoListStore.Delete(0))) --> store
// )
},
new MenuItem {
text = "Edit"
}
)
}
})
}
bottom = new HBox {
spacing = 5
padding = Insets(5)
children = Seq(
new JFXTextField {
id = "todoInputField"
style = "-fx-background-color: rgb(38,38,38);"
styleClass += "text-white"
text ==> _content
vgrow = Priority.Always
},
new JFXButton {
id = "todoAddButton"
text = "Add"
alignment = Pos.Center
// disable <== _selectedItems.map(_.length > 0)
styleClass = Seq("btn", "btn-primary")
obsAction
.useLazyEval(
me.Task(TodoListStore.Add(_content()))
) --> store
},
new JFXButton {
id = "todoEditButton"
text = "Edit"
alignment = Pos.Center
disable <== _selectedItems.map(_.length > 1)
styleClass = Seq("btn", "btn-info")
obsAction.useLazyEval(
me.Task(
TodoListStore.Edit(
_selectedItems
.map(_.headOption.map(_.id).getOrElse(-1))
.value,
_content()
)
)
) --> store
}
)
}
}
}
)
}