package main import ( "fmt" "image/color" "log" "runtime" "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 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.Horizontal) lbar := gio.NewLabel(" ", gio.Face(face)) f2 := gio.NewFlex(gio.Vertical) topbar := gio.NewLabel("Scroll X and Y. Click to select", gio.Face(face)) f3 := gio.NewFlex(gio.Horizontal) f4 := gio.NewFlex(gio.Vertical) sh := gio.HScroll(gio.NewFlex(gio.Horizontal)) sv := gio.VScroll(gio.NewFlex(gio.Vertical)) numrows := 16 numcols := 50 labs := make([][]gio.Widget, numrows) sels := make([][]bool, numrows) for i := 0; i < numrows; i++ { labs[i] = make([]gio.Widget, numcols) sels[i] = make([]bool, numcols) for j := 0; j < numcols; j++ { labs[i][j] = NewSLabel(fmt.Sprintf("%03d", i+j*numrows), &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)) } page := sysbg(sysinset(bg(margin( f1(lbar, f2(topbar, sh(sv(f3( f4(labs[0]...), f4(labs[1]...), f4(labs[2]...), f4(labs[3]...), f4(labs[4]...), f4(labs[5]...), f4(labs[6]...), f4(labs[7]...), f4(labs[8]...), f4(labs[9]...), f4(labs[10]...), f4(labs[11]...), f4(labs[12]...), f4(labs[13]...), f4(labs[14]...), f4(labs[15]...), ))))))))) var oldInsets app.Insets stime := time.Now() sm := runtime.MemStats{} for { select { case e := <-w.Events(): switch e := e.(type) { case app.DestroyEvent: return case app.UpdateEvent: profileNow := time.Since(stime) > time.Second*2 if profileNow { stime = time.Now() //gio.RecordMallocs() runtime.ReadMemStats(&sm) } gio.Mallocs("start") ctx.Reset(&e) if diffInsets(e.Insets, oldInsets) { oldInsets = e.Insets resetSysinset(e.Insets) } page.Layout(ctx) ctx.Update() gio.Mallocs("end") if profileNow { for _, m := range gio.AllMallocs { fmt.Printf("Mallocs: %d (%s)\n", m.Value, m.Text) } gio.AllMallocs = nil oldMallocs := sm.Mallocs runtime.ReadMemStats(&sm) fmt.Printf("Mallocs = %d\n", sm.Mallocs-oldMallocs) } } } } }