// +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 ( sel int32 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.Axis(layout.Vertical)) f2 := gio.NewFlex(gio.Axis(layout.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.Axis(layout.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() } } } }