Files
MujicaUI/week_picker.go
T

97 lines
2.9 KiB
Go

package mujica
import (
"fmt"
"log/slog"
"github.com/egoist/mygo/ui"
"mujicaui/icons"
)
// WeekPickerOptions configure a WeekPicker.
type WeekPickerOptions struct {
WeekStart WeekStart
// Min and Max bound the chosen week's days.
Min, Max Date
// Today is marked; zero uses the system clock.
Today Date
Clearable bool
Disabled bool
Label string
}
// WeekPicker chooses a week; *value is its first day.
func WeekPicker(c *ui.Context, value *Date, opts WeekPickerOptions) ChoiceResult {
datetimeCheckDate("WeekPicker value", *value)
datetimeCheckBounds("WeekPicker", opts.Min, opts.Max)
first := calendarFirstWeekday(c, opts.WeekStart)
weekOf := func(d Date) Date { return d.AddDays(-((int(d.Weekday()) - int(first) + 7) % 7)) }
if !value.IsZero() && weekOf(*value) != *value {
panic(fmt.Sprintf("mujica: WeekPicker value %v does not start a week", *value))
}
d := Density(c)
today := datetimeToday(c, opts.Today)
label := opts.Label
if label == "" {
label = msg(c, "week_picker.label")
}
enabled := func(x Date) bool {
w := weekOf(x)
return w.AddDays(6).within(opts.Min, Date{}) && w.within(Date{}, opts.Max)
}
col := ui.Column(c).Width(d.ControlHeight() * 8).Gap(d.Unit()).AlignItems(ui.Stretch).Disabled(opts.Disabled)
open := ui.Local(col, "week-picker-open", func() bool { return false })
cursor := ui.Local(col, "week-picker-cursor", func() Date { return Date{} })
hover := ui.Local(col, "week-picker-hover", func() Date { return Date{} })
old := *value
text := ""
if !value.IsZero() {
text = weekViewTitle(c, *value, value.AddDays(6))
}
col.Children(func() {
field := datetimeField(c, ui.Row(c), false, false)
field.Children(func() {
t := datetimeTrigger(c, text, msg(c, "week_picker.placeholder"), "calendar").Label(label).Description(text)
if !t.IsDisabled() && (t.Clicked() || !*open && t.Shortcut(0, ui.KeyDown)) {
*open, *hover = !*open, Date{}
*cursor = *value
if cursor.IsZero() {
*cursor = today
}
}
if opts.Clearable && !value.IsZero() {
if b := iconAction(c, icons.Must("x"), msg(c, "calendar.clear")); b.Clicked() && !b.IsDisabled() {
*value = Date{}
}
}
})
datetimePopup(c, field, open, false, func() {
band := *hover
if band.IsZero() {
band = *cursor
}
picked, hovered := calendarMonth(c, cursor, calendarConfig{
chosen: func(x Date) bool { return !value.IsZero() && weekOf(x) == *value },
inRange: func(x Date) bool { return weekOf(x) == weekOf(band) },
enabled: enabled,
today: today,
weekStart: opts.WeekStart,
autoFocus: true,
})
if hovered != *hover {
*hover = hovered
c.Invalidate()
}
if !picked.IsZero() {
*value, *open = weekOf(picked), false
}
})
})
changed := *value != old
if changed {
slog.Debug("mujica: week_picker change", "from", old, "to", *value)
}
return ChoiceResult{Element: col, changed: changed}
}