202 lines
4.4 KiB
Go
202 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 (
|
|
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()
|
|
}
|
|
}
|
|
}
|
|
}
|