228 lines
5.6 KiB
Go
228 lines
5.6 KiB
Go
package main
|
|
|
|
import (
|
|
"git.wow.st/gmp/giowrap"
|
|
|
|
"fmt"
|
|
//"image"
|
|
"image/color"
|
|
"log"
|
|
"os"
|
|
"runtime"
|
|
"runtime/pprof"
|
|
"sync"
|
|
"time"
|
|
|
|
"gioui.org/ui"
|
|
"gioui.org/ui/app"
|
|
"gioui.org/ui/text"
|
|
|
|
"golang.org/x/image/font/gofont/goregular"
|
|
"golang.org/x/image/font/sfnt"
|
|
)
|
|
|
|
var (
|
|
FPS int = 100
|
|
frames int64
|
|
frametime int64 // nanoseconds
|
|
maxframetime int64
|
|
mux sync.Mutex
|
|
Profile bool = true
|
|
RecordMallocs bool = false
|
|
)
|
|
|
|
func NewButton(face text.Face, t string, c color.RGBA) giowrap.Clickable {
|
|
lbl := giowrap.NewLabel(t, giowrap.Face(face), giowrap.Align(text.Middle))
|
|
bg := giowrap.NewBackground(giowrap.Color(c), giowrap.Radius(ui.Dp(4)))
|
|
ins := giowrap.NewInset(giowrap.Size(ui.Dp(4)))
|
|
return giowrap.AsClickable(ins(bg(lbl)))
|
|
}
|
|
|
|
func main() {
|
|
go func() {
|
|
ms := &runtime.MemStats{}
|
|
var a1 uint64
|
|
for {
|
|
time.Sleep(time.Second * 3)
|
|
mux.Lock()
|
|
if frames == 0 {
|
|
mux.Unlock()
|
|
continue
|
|
}
|
|
runtime.ReadMemStats(ms)
|
|
a1 = ms.Alloc
|
|
runtime.GC()
|
|
runtime.ReadMemStats(ms)
|
|
log.Printf("Alloc: %d - %d = %d (%d per frame)", a1, ms.Alloc, a1-ms.Alloc, (a1-ms.Alloc)/(3*uint64(FPS)))
|
|
log.Printf("Frametime: %d max Frametime: %d us\n", frametime/(frames*1000), maxframetime/1000)
|
|
frames = 0
|
|
frametime = 0
|
|
maxframetime = 0
|
|
mux.Unlock()
|
|
}
|
|
}()
|
|
go main1()
|
|
app.Main()
|
|
}
|
|
|
|
func main1() {
|
|
w := app.NewWindow()
|
|
regular, err := sfnt.Parse(goregular.TTF)
|
|
if err != nil {
|
|
log.Fatal("Cannot parse font.")
|
|
}
|
|
ctx := giowrap.NewContext(w)
|
|
t := time.NewTicker(time.Second / time.Duration(FPS))
|
|
|
|
graybg := giowrap.NewBackground(
|
|
giowrap.Color(color.RGBA{A: 0xff, R: 0xd0, G: 0xd0, B: 0xd0}),
|
|
giowrap.Radius(ui.Dp(4)))
|
|
whitebg := giowrap.NewBackground(
|
|
giowrap.Color(color.RGBA{A: 0xff, R: 0xff, G: 0xff, B: 0xff}),
|
|
giowrap.Radius(ui.Dp(4)))
|
|
margin := giowrap.NewInset(giowrap.Size(ui.Dp(10)))
|
|
buffer := giowrap.NewInset(giowrap.Bottom(ui.Dp(10)))
|
|
f1 := giowrap.NewFlex(giowrap.Vertical)
|
|
row := giowrap.NewFlex(giowrap.Horizontal)
|
|
|
|
more := NewButton(ctx.Faces.For(regular, ui.Sp(24)),
|
|
"more", color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6})
|
|
submit := NewButton(ctx.Faces.For(regular, ui.Sp(24)),
|
|
"submit", color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6})
|
|
back := NewButton(ctx.Faces.For(regular, ui.Sp(24)),
|
|
"back", color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6})
|
|
|
|
numfields := 5
|
|
eds := make([]*giowrap.Editor,0)
|
|
btns := make([]giowrap.Clickable,0)
|
|
entryrows := make([]giowrap.Widget,0)
|
|
submitrows := make([]giowrap.Widget,0)
|
|
|
|
var entryPage giowrap.Widget
|
|
var submitPage giowrap.Widget
|
|
|
|
newRow := func(i int) {
|
|
eds = append(eds, giowrap.NewEditor(fmt.Sprintf("text %d",i), giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))))
|
|
btns = append(btns, NewButton(ctx.Faces.For(regular, ui.Sp(18)), "X",
|
|
color.RGBA{A: 0xff, R: 0x80, G: 0x80, B: 0x80}))
|
|
}
|
|
|
|
for i := 0; i < numfields; i++ {
|
|
newRow(i)
|
|
}
|
|
updatePages := func() {
|
|
entryrows = entryrows[0:0]
|
|
entryrows = append(entryrows, buffer(row(more, submit)))
|
|
for i := 0; i < len(btns); i++ {
|
|
entryrows = append(entryrows, row(btns[i], giowrap.FillWidth(whitebg(eds[i]))))
|
|
}
|
|
entryPage = graybg(margin(giowrap.VScroll(f1)(entryrows...)))
|
|
|
|
submitrows = submitrows[0:0]
|
|
submitrows = append(submitrows, buffer(row(back)))
|
|
for i := 0; i < len(btns); i++ {
|
|
submitrows = append(submitrows, giowrap.NewLabel(eds[i].Text(), giowrap.Face(ctx.Faces.For(regular, ui.Sp(24)))))
|
|
}
|
|
submitPage = graybg(margin(giowrap.VScroll(f1)(submitrows...)))
|
|
}
|
|
updatePages()
|
|
|
|
page := &entryPage
|
|
|
|
profiled := false
|
|
startTime := time.Now()
|
|
|
|
for {
|
|
select {
|
|
case <-t.C:
|
|
w.Invalidate()
|
|
case e := <-w.Events():
|
|
mux.Lock()
|
|
stime := time.Now()
|
|
switch e := e.(type) {
|
|
case app.DestroyEvent:
|
|
return
|
|
case app.UpdateEvent:
|
|
profileNow := false
|
|
var ms runtime.MemStats
|
|
if Profile && time.Since(startTime) > time.Second*2 {
|
|
startTime = time.Now()
|
|
profileNow = true
|
|
}
|
|
if profileNow {
|
|
if !profiled {
|
|
prof(0)
|
|
}
|
|
runtime.ReadMemStats(&ms)
|
|
if RecordMallocs {
|
|
giowrap.RecordMallocs()
|
|
}
|
|
}
|
|
ctx.Reset(&e)
|
|
giowrap.Mallocs("pre-layout")
|
|
(*page).Layout(ctx)
|
|
giowrap.Mallocs("post-layout")
|
|
ctx.Update()
|
|
for i, w := range btns {
|
|
if w.Clicked(ctx) {
|
|
log.Printf("%d clicked\n",i)
|
|
btns = append(btns[:i], btns[i+1:]...)
|
|
eds = append(eds[:i], eds[i+1:]...)
|
|
entryrows = append(entryrows[:i], entryrows[i+1:]...)
|
|
numfields--
|
|
updatePages()
|
|
}
|
|
}
|
|
if more.Clicked(ctx) {
|
|
log.Print("More")
|
|
newRow(len(btns))
|
|
updatePages()
|
|
}
|
|
if submit.Clicked(ctx) {
|
|
log.Print("Submit")
|
|
updatePages()
|
|
page = &submitPage
|
|
}
|
|
if back.Clicked(ctx) {
|
|
page = &entryPage
|
|
}
|
|
if profileNow {
|
|
for _, i := range giowrap.AllMallocs {
|
|
fmt.Printf("mallocs: %d (%s)\n", i.Value, i.Text)
|
|
}
|
|
giowrap.AllMallocs = nil
|
|
mallocs := ms.Mallocs
|
|
runtime.ReadMemStats(&ms)
|
|
mallocs = ms.Mallocs - mallocs
|
|
log.Printf("Mallocs = %d\n", mallocs)
|
|
if !profiled {
|
|
prof(1)
|
|
profiled = true
|
|
}
|
|
}
|
|
}
|
|
dur := time.Since(stime).Nanoseconds()
|
|
frames = frames + 1
|
|
frametime = frametime + dur
|
|
if dur > maxframetime {
|
|
maxframetime = dur
|
|
}
|
|
mux.Unlock()
|
|
}
|
|
}
|
|
}
|
|
|
|
func prof(x int) {
|
|
names := []string{"memprofile-1.pprof", "memprofile-2.pprof"}
|
|
f1, err := os.Create(names[x])
|
|
if err != nil {
|
|
log.Fatal("could not create memory profile: ", err)
|
|
}
|
|
if err := pprof.WriteHeapProfile(f1); err != nil {
|
|
log.Fatal("could not write memory profile: ", err)
|
|
}
|
|
f1.Close()
|
|
log.Print("Memory profile written")
|
|
}
|
|
|