giowrap/cmd/cal/main.go

201 lines
4.4 KiB
Go

// +build darwin linux
package main
import (
"fmt"
"image/color"
"log"
"time"
gio "git.wow.st/gmp/giowrap"
"gioui.org/ui"
"gioui.org/ui/app"
"gioui.org/ui/layout"
"gioui.org/ui/text"
"golang.org/x/image/font/gofont/goregular"
"golang.org/x/image/font/sfnt"
)
var (
face text.Face
)
func main() {
log.Print("Staring event loop")
go eventloop()
app.Main()
log.Print("App closed")
}
func NewButton(t string, lops ...gio.LabelOption) gio.Clickable {
lops = append([]gio.LabelOption{gio.Face(face), gio.Align(text.Middle)}, lops...)
lbl := gio.NewLabel(t, lops...)
bg := gio.NewBackground(
gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}),
gio.Radius(ui.Dp(4)))
return gio.AsClickable(bg(lbl))
}
type SLabel struct {
w gio.Clickable
bg *gio.Background
active *bool
}
func NewSLabel(t string, active *bool, lops ...gio.LabelOption) *SLabel {
ret := &SLabel{}
lops = append([]gio.LabelOption{gio.Face(face)}, lops...)
lbl := gio.NewLabel(t, lops...)
bg := &gio.Background{
Color: color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0},
Radius: ui.Dp(4),
Inset: layout.UniformInset(ui.Dp(4)),
}
if *active {
bg.Color = color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}
}
l := gio.AsClickable(gio.Enclose(bg, lbl))
ret.w = l
ret.bg = bg
ret.active = active
return ret
}
func (w *SLabel) Layout(ctx *gio.Context) {
if *w.active {
w.bg.Color = color.RGBA{A: 0xff, R: 0xe0, G: 0xe0, B: 0xe0}
} else {
w.bg.Color = color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}
}
w.w.Layout(ctx)
if w.w.Clicked(ctx) {
if *w.active {
*w.active = false
} else {
*w.active = true
}
}
}
func NewCal(sm *SelectableMonth) gio.Widget {
pad := gio.NewLabel("", gio.Face(face), gio.Align(text.End))
ds := make([]gio.Widget, 42)
for i := 0; i < len(ds); i++ {
if i < sm.Pad || i >= sm.DaysIn+sm.Pad {
ds[i] = pad
} else {
ds[i] = NewSLabel(fmt.Sprintf("%d", i+1-sm.Pad), &sm.S[i+1-sm.Pad], gio.Align(text.End))
}
}
return gio.NewGrid(7)(ds...)
}
func eventloop() {
w := app.NewWindow(
app.WithWidth(ui.Dp(600)),
app.WithHeight(ui.Dp(600)),
app.WithTitle("Calendar"))
ctx := gio.NewContext(w)
sm := NewMonth(time.Now())
regular, err := sfnt.Parse(goregular.TTF)
face = ctx.Faces.For(regular, ui.Sp(20))
if err != nil {
log.Fatal("Cannot parse font.")
}
bg := gio.NewBackground(
gio.Color(color.RGBA{A: 0xff, R: 0xf0, G: 0xf0, B: 0xe0}))
margin := gio.NewInset(gio.Size(ui.Dp(10)))
f1 := gio.NewFlex(gio.Vertical)
f2 := gio.NewFlex(gio.Horizontal)
sidegrid := gio.NewGrid(1)
yrs := make([]gio.Widget, 6)
curyr := sm.Year
topgrid := gio.NewGrid(3)
lbtn := NewButton(" < ")
mth := gio.NewLabel("", gio.Face(face), gio.Align(text.Middle))
rbtn := NewButton(" > ")
var cal gio.Widget
f3 := gio.NewFlex(gio.Vertical)
daygrid := gio.NewGrid(7)
sun := NewSLabel("Sun", &sm.Ws[time.Sunday], gio.Align(text.End))
mon := NewSLabel("Mon", &sm.Ws[time.Monday], gio.Align(text.End))
tue := NewSLabel("Tue", &sm.Ws[time.Tuesday], gio.Align(text.End))
wed := NewSLabel("Wed", &sm.Ws[time.Wednesday], gio.Align(text.End))
thu := NewSLabel("Thu", &sm.Ws[time.Thursday], gio.Align(text.End))
fri := NewSLabel("Fri", &sm.Ws[time.Friday], gio.Align(text.End))
sat := NewSLabel("Sat", &sm.Ws[time.Saturday], gio.Align(text.End))
resetCal := func() {
cal = NewCal(sm)
for i, _ := range yrs {
yrs[i] = NewButton(fmt.Sprintf("%d", curyr-i),
gio.Align(text.Start))
}
w.Invalidate()
}
resetCal()
for {
select {
case e := <-w.Events():
switch e := e.(type) {
case app.DestroyEvent:
return
case app.UpdateEvent:
ctx.Reset(&e)
mth.SetText(fmt.Sprintf("%s %d", sm.Month.String(), sm.Year))
ows := sm.Ws
bg(margin(f1(
topgrid(lbtn, mth, rbtn),
f2(
sidegrid(yrs...),
f3(
daygrid(sun, mon, tue, wed, thu, fri, sat),
cal,
),
),
))).Layout(ctx)
ctx.Update()
for i := time.Sunday; i < 7; i++ {
switch {
case sm.Ws[i] && !ows[i]:
sm.SelectWeekday(i)
resetCal()
case !sm.Ws[i] && ows[i]:
sm.DeselectWeekday(i)
resetCal()
}
}
if lbtn.Clicked(ctx) {
sm.Previous()
resetCal()
}
if rbtn.Clicked(ctx) {
sm.Next()
resetCal()
}
for i, y := range yrs {
if y.(gio.Clickable).Clicked(ctx) {
sm.Year = curyr - i
sm.Refresh()
resetCal()
}
}
sm.CheckSel()
}
}
}
}