package main import ( "fmt" "image/color" "log" 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 black color.RGBA = color.RGBA{A: 0xff, R: 0x00, G: 0x00, B: 0x00} gray2 color.RGBA = color.RGBA{A: 0xff, R: 0xc0, G: 0xc0, B: 0xc0} gray1 color.RGBA = color.RGBA{A: 0xff, R: 0x70, G: 0x70, B: 0x70} ) 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: gray2, Radius: ui.Dp(4), Inset: layout.UniformInset(ui.Dp(4)), } if *active { bg.Color = gray1 } 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 = gray1 } else { w.bg.Color = gray2 } w.w.Layout(ctx) if w.w.Clicked(ctx) { if *w.active { *w.active = false } else { *w.active = true } } } func main() { log.Print("Staring event loop") go eventloop() app.Main() log.Print("App closed") } func diffInsets(x, y app.Insets) bool { return x.Top != y.Top || x.Bottom != y.Bottom || x.Left != y.Left || x.Right != y.Right } func eventloop() { w := app.NewWindow( app.WithWidth(ui.Dp(400)), app.WithHeight(ui.Dp(400)), app.WithTitle("Tickets")) ctx := gio.NewContext(w) regular, err := sfnt.Parse(goregular.TTF) face = ctx.Faces.For(regular, ui.Sp(16)) if err != nil { log.Fatal("Cannot parse font.") } sysbg := gio.NewBackground(gio.Color(black)) bg := gio.NewBackground(gio.Color(gray2)) margin := gio.NewInset(gio.Size(ui.Dp(10))) f1 := gio.NewFlex(gio.Axis(layout.Horizontal)) lbar := gio.NewLabel(" ", gio.Face(face)) f2 := gio.NewFlex(gio.Axis(layout.Vertical)) topbar := gio.NewLabel("Scroll X and Y. Click to select", gio.Face(face)) sh := gio.HScroll(gio.NewFlex(gio.Axis(layout.Horizontal))) sv := gio.VScroll(gio.NewFlex(gio.Axis(layout.Vertical))) numlabs := 50 labs := make([][]gio.Widget, numlabs) sels := make([][]bool, numlabs) for i := 0; i < 16; i++ { labs[i] = make([]gio.Widget, numlabs) sels[i] = make([]bool, numlabs) for j := 0; j < numlabs; j++ { labs[i][j] = NewSLabel(fmt.Sprintf("%03d", i*16+j), &sels[i][j]) } } sysinset := gio.NewInset(gio.Size(ui.Dp(0))) resetSysinset := func(x app.Insets) { sysinset = gio.NewInset(gio.Top(x.Top), gio.Bottom(x.Bottom), gio.Left(x.Left), gio.Right(x.Right)) } var oldInsets app.Insets for { select { case e := <-w.Events(): switch e := e.(type) { case app.DestroyEvent: return case app.UpdateEvent: ctx.Reset(e) if diffInsets(e.Insets, oldInsets) { oldInsets = e.Insets resetSysinset(e.Insets) } sysbg(sysinset(bg(margin( f1(lbar, f2(topbar, sh( sv(labs[0]...), sv(labs[1]...), sv(labs[2]...), sv(labs[3]...), sv(labs[4]...), sv(labs[5]...), sv(labs[6]...), sv(labs[7]...), sv(labs[8]...), sv(labs[9]...), sv(labs[10]...), sv(labs[11]...), sv(labs[12]...), sv(labs[13]...), sv(labs[14]...), sv(labs[15]...), ))))))).Layout(ctx) ctx.Update() } } } }