Files
MujicaUI/datetime/week_picker.go
T

98 lines
3.1 KiB
Go

package datetime
import (
"fmt"
"log/slog"
"github.com/egoist/mygo/ui"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/core"
"git.zacharyzhang.com/ZacharyZhang-NY/MujicaUI/icons"
)
// WeekPickerOptions configure a WeekPicker.
type WeekPickerOptions struct {
WeekStart WeekStart
// Min and Max bound the chosen week's days.
Min, Max core.Date
// Today is marked; zero uses the system clock.
Today core.Date
Clearable bool
Disabled bool
Label string
}
// WeekPicker chooses a week; *value is its first day.
func WeekPicker(c *ui.Context, value *core.Date, opts WeekPickerOptions) core.ChoiceResult {
core.DatetimeCheckDate("WeekPicker value", *value)
core.DatetimeCheckBounds("WeekPicker", opts.Min, opts.Max)
first := CalendarFirstWeekday(c, opts.WeekStart)
weekOf := func(d core.Date) core.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 := core.Density(c)
today := core.DatetimeToday(c, opts.Today)
label := opts.Label
if label == "" {
label = core.Msg(c, "week_picker.label")
}
enabled := func(x core.Date) bool {
w := weekOf(x)
return w.AddDays(6).Within(opts.Min, core.Date{}) && w.Within(core.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() core.Date { return core.Date{} })
hover := ui.Local(col, "week-picker-hover", func() core.Date { return core.Date{} })
old := *value
text := ""
if !value.IsZero() {
text = WeekViewTitle(c, *value, value.AddDays(6))
}
col.Children(func() {
field := core.DatetimeField(c, ui.Row(c), false, false)
field.Children(func() {
t := core.DatetimeTrigger(c, text, core.Msg(c, "week_picker.placeholder"), "calendar").Label(label).Description(text)
if !t.IsDisabled() && (t.Clicked() || !*open && t.Shortcut(0, ui.KeyDown)) {
*open, *hover = !*open, core.Date{}
*cursor = *value
if cursor.IsZero() {
*cursor = today
}
}
if opts.Clearable && !value.IsZero() {
if b := core.IconAction(c, icons.Must("x"), core.Msg(c, "calendar.clear")); b.Clicked() && !b.IsDisabled() {
*value = core.Date{}
}
}
})
core.DatetimePopup(c, field, open, false, func() {
band := *hover
if band.IsZero() {
band = *cursor
}
picked, hovered := calendarMonth(c, cursor, calendarConfig{
chosen: func(x core.Date) bool { return !value.IsZero() && weekOf(x) == *value },
inRange: func(x core.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 core.NewChoiceResult(col, changed)
}