Last active
May 13, 2019 19:45
-
-
Save thomasnield/bf262ce7f8ba6b9cd2edf6f7c4454d5b to your computer and use it in GitHub Desktop.
Mutli Date Range Selector JavaFX Control
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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