com.github.mvysny.karibudsl.v8.DateRangePopup.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of karibu-dsl-v8 Show documentation
Show all versions of karibu-dsl-v8 Show documentation
Karibu-DSL, Kotlin extensions/DSL for Vaadin
The newest version!
package com.github.mvysny.karibudsl.v8
import com.vaadin.shared.ui.datefield.DateTimeResolution
import com.vaadin.ui.*
import java.io.Serializable
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
/**
* A potentially open date range. If both [from] and [to] are `null`, then the interval accepts any date.
* @property to the maximum accepted value, inclusive. If `null` then the date range has no upper limit.
* @property from the minimum accepted value, inclusive. If `null` then the date range has no lower limit.
*/
public data class DateInterval(var from: LocalDateTime?, var to: LocalDateTime?) : Serializable {
/**
* True if the interval includes all possible dates (both [from] and [to] are `null`).
*/
val isUniversalSet: Boolean
get() = from == null && to == null
public companion object {
public fun now(zoneId: ZoneId = browserTimeZone): DateInterval =
DateInterval(LocalDateTime.now(zoneId), LocalDateTime.now(zoneId))
}
}
/**
* Only shows a single button as its contents. When the button is clicked, it opens a dialog and allows the user to specify a range
* of dates. When the user sets the values, the dialog is
* hidden and the date range is set as the value of the popup.
*
* The current date range is also displayed as the caption of the button.
*/
public class DateRangePopup: CustomField() {
private val formatter get() = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT).withLocale(UI.getCurrent().locale!!)
private lateinit var fromField: InlineDateTimeField
private lateinit var toField: InlineDateTimeField
private lateinit var set: Button
private lateinit var clear: Button
/**
* The desired resolution of this filter popup, defaults to [DateTimeResolution.MINUTE].
*/
public var resolution: DateTimeResolution = DateTimeResolution.MINUTE
set(value) {
field = value
updateFields()
}
private var internalValue: DateInterval? = null
init {
styleName = "datefilterpopup"
// force initcontents so that fromField and toField are initialized and one can set resolution to them
content
}
override fun doSetValue(value: DateInterval?) {
internalValue = value?.copy()
updateValueToFields()
updateCaption()
}
private fun updateValueToFields() {
if (isPopupInitialized) {
fromField.value = internalValue?.from
toField.value = internalValue?.to
}
}
override fun getValue(): DateInterval? = internalValue?.copy()
private fun format(date: LocalDateTime?) = if (date == null) "" else formatter.format(date)
private fun updateCaption() {
val content = content as KPopupView
val value = value
if (value == null || value.isUniversalSet) {
content.minimizedValueAsHTML = karibuDslI18n("all")
} else {
content.minimizedValueAsHTML = "${format(value.from)} - ${format(value.to)}"
}
}
private fun truncateDate(date: LocalDateTime?, resolution: DateTimeResolution, start: Boolean): LocalDateTime? {
@Suppress("NAME_SHADOWING")
var date = date ?: return null
for (res in DateTimeResolution.values().slice(0..resolution.ordinal - 1)) {
if (res == DateTimeResolution.SECOND) {
date = date.withSecond(if (start) 0 else 59)
} else if (res == DateTimeResolution.MINUTE) {
date = date.withMinute(if (start) 0 else 59)
} else if (res == DateTimeResolution.HOUR) {
date = date.withHour(if (start) 0 else 23)
} else if (res == DateTimeResolution.DAY) {
date = date.withDayOfMonth(if (start) 1 else date.toLocalDate().lengthOfMonth())
} else if (res == DateTimeResolution.MONTH) {
date = date.withMonth(if (start) 1 else 12)
}
}
date = date.withNano(if (start) 0 else 999)
return date
}
override fun initContent(): Component = KPopupView().apply {
w = fillParent; minimizedValueAsHTML = karibuDslI18n("all"); isHideOnMouseOut = false
lazy {
verticalLayout {
styleName = "datefilterpopupcontent"; setSizeUndefined(); isSpacing = true; isMargin = true
horizontalLayout {
isSpacing = true
fromField = inlineDateTimeField {
locale = [email protected]
}
toField = inlineDateTimeField {
locale = [email protected]
}
}
horizontalLayout {
alignment = Alignment.BOTTOM_RIGHT
isSpacing = true
set = button(karibuDslI18n("set")) {
onLeftClick {
value = DateInterval(
truncateDate(fromField.value, resolution, true),
truncateDate(toField.value, resolution, false)
)
isPopupVisible = false
}
}
clear = button(karibuDslI18n("clear")) {
onLeftClick {
value = null
isPopupVisible = false
}
}
}
}
updateValueToFields()
updateFields()
}
}
override fun setReadOnly(readOnly: Boolean) {
super.setReadOnly(readOnly)
updateFields()
}
private val isPopupInitialized: Boolean get() = ::set.isInitialized
private fun updateFields() {
if (isPopupInitialized) {
set.isEnabled = !isReadOnly
clear.isEnabled = !isReadOnly
fromField.isEnabled = !isReadOnly
toField.isEnabled = !isReadOnly
fromField.resolution = resolution
toField.resolution = resolution
}
}
public var isPopupVisible: Boolean
get() = (content as KPopupView).isPopupVisible
set(value) {
(content as KPopupView).isPopupVisible = value
}
}
@VaadinDsl
public fun (@VaadinDsl HasComponents).dateRangePopup(value: DateInterval? = null, block: (@VaadinDsl DateRangePopup).()->Unit = {}): DateRangePopup {
val popup = DateRangePopup()
if (value != null) popup.value = value
return init(popup, block)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy