Skip to content

Instantly share code, notes, and snippets.

@thomasnield
Last active May 13, 2019 19:45
Show Gist options
  • Select an option

  • Save thomasnield/bf262ce7f8ba6b9cd2edf6f7c4454d5b to your computer and use it in GitHub Desktop.

Select an option

Save thomasnield/bf262ce7f8ba6b9cd2edf6f7c4454d5b to your computer and use it in GitHub Desktop.
Mutli Date Range Selector JavaFX Control
import javafx.application.Application
import javafx.beans.property.SimpleStringProperty
import javafx.collections.FXCollections
import javafx.collections.ObservableList
import javafx.scene.control.TextField
import tornadofx.*
import java.time.LocalDate
import java.time.format.DateTimeFormatter
fun main() {
Application.launch(MyApp::class.java)
}
class MyApp: App(MyView::class)
class MyView: View() {
override val root = borderpane {
val dateRanges = FXCollections.observableArrayList<ClosedRange<LocalDate>>()
left = MultiDateRangeSelector(dateRanges)
center = tableview(dateRanges) {
readonlyColumn("START", ClosedRange<LocalDate>::start)
readonlyColumn("END", ClosedRange<LocalDate>::endInclusive)
}
}
}
class MultiDateRangeSelector(dateRanges: ObservableList<ClosedRange<LocalDate>>? = null): TextField() {
private val dateTimeFormat = DateTimeFormatter.ofPattern("M/d/yyyy")
private val _dateRanges = dateRanges ?: FXCollections.observableArrayList<ClosedRange<LocalDate>>()
val dateRanges = FXCollections.unmodifiableObservableList(_dateRanges)
private val toolTipTextProperty = SimpleStringProperty()
init {
textProperty().onChange {
update()
}
tooltip {
textProperty().bind(toolTipTextProperty)
}
}
private fun update() {
try {
text.split(",")
.asSequence()
.map { it.trim() }
.filter {
it.matches(Regex("[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}(-[0-9]{1,2}/[0-9]{1,2}/[0-9]{4})?"))
}
.map { dateRangeStr ->
dateRangeStr.split("-")
.asSequence()
.map { it.trim() }
.filter {
it.matches(Regex("[0-9]{1,2}/[0-9]{1,2}/[0-9]{4}"))
}.map { LocalDate.parse(it, dateTimeFormat) }
.toList()
}.filter { it.count() in 1..2 }
.map {
when {
it.count() == 1 -> it[0]..it[0]
it.count() == 2 -> it[0]..it[1]
else -> throw Exception("Must be 1 to 2 elements")
}
}
.toList().also {
_dateRanges.setAll(it)
toolTipTextProperty.set(
dateRanges?.asSequence()
?.map {
when {
it.start == it.endInclusive -> "${it.start.format(dateTimeFormat)}"
else -> "${it.start.format(dateTimeFormat)}-${it.endInclusive.format(dateTimeFormat)}"
}
}
?.joinToString("\r\n")
)
}
} catch (e: Exception) {
_dateRanges.clear()
toolTipTextProperty.set(null)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment