2019-08-15 09:16:00 -04:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"git.wow.st/gmp/giowrap"
|
|
|
|
|
2019-08-15 18:32:01 -04:00
|
|
|
"image/color"
|
2019-08-15 09:16:00 -04:00
|
|
|
"log"
|
2019-08-18 17:00:19 -04:00
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
"runtime/pprof"
|
|
|
|
"sync"
|
2019-08-15 09:16:00 -04:00
|
|
|
"time"
|
|
|
|
|
|
|
|
"gioui.org/ui"
|
|
|
|
"gioui.org/ui/app"
|
2019-08-18 17:00:19 -04:00
|
|
|
gdraw "gioui.org/ui/draw"
|
|
|
|
"gioui.org/ui/f32"
|
|
|
|
"gioui.org/ui/gesture"
|
2019-08-15 09:16:00 -04:00
|
|
|
"gioui.org/ui/layout"
|
2019-08-18 17:00:19 -04:00
|
|
|
"gioui.org/ui/measure"
|
|
|
|
"gioui.org/ui/pointer"
|
2019-08-15 09:16:00 -04:00
|
|
|
"gioui.org/ui/text"
|
|
|
|
|
|
|
|
"golang.org/x/image/font/sfnt"
|
|
|
|
"golang.org/x/image/font/gofont/goregular"
|
|
|
|
)
|
|
|
|
|
2019-08-18 17:00:19 -04:00
|
|
|
var (
|
|
|
|
FPS int = 100
|
|
|
|
frames int64
|
|
|
|
frametime int64 // nanoseconds
|
|
|
|
maxframetime int64
|
|
|
|
mux sync.Mutex
|
|
|
|
Profile bool = false
|
|
|
|
)
|
|
|
|
|
2019-08-16 16:38:49 -04:00
|
|
|
func NewButton(face text.Face, t string, c color.RGBA) giowrap.Clickable {
|
2019-08-20 12:39:28 -04:00
|
|
|
lbl := giowrap.NewLabel(t, giowrap.Face(face), giowrap.Align(text.Center))
|
|
|
|
bg := giowrap.NewBackground(giowrap.Color(c), giowrap.Radius(ui.Dp(4)))
|
2019-08-16 16:38:49 -04:00
|
|
|
return giowrap.AsClickable(bg(lbl))
|
|
|
|
}
|
|
|
|
|
2019-08-15 09:16:00 -04:00
|
|
|
func main() {
|
|
|
|
go func() {
|
2019-08-18 17:00:19 -04:00
|
|
|
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()
|
2019-08-15 09:16:00 -04:00
|
|
|
}
|
2019-08-18 17:00:19 -04:00
|
|
|
}()
|
|
|
|
switch os.Args[1] {
|
|
|
|
case "", "main1":
|
|
|
|
log.Print("main1()")
|
|
|
|
go main1()
|
|
|
|
case "main2":
|
|
|
|
log.Print("main2()")
|
|
|
|
go main2()
|
|
|
|
default:
|
|
|
|
log.Fatal(`Usage:
|
|
|
|
hello [main1|main2]
|
|
|
|
`)
|
|
|
|
}
|
|
|
|
app.Main()
|
|
|
|
}
|
2019-08-15 09:16:00 -04:00
|
|
|
|
2019-08-18 17:00:19 -04:00
|
|
|
func main1() {
|
|
|
|
w := app.NewWindow(nil)
|
|
|
|
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))
|
2019-08-20 12:39:28 -04:00
|
|
|
e1 := giowrap.NewEditor("text 1",giowrap.Face(ctx.Faces.For(regular, ui.Sp(24))))
|
2019-08-18 17:00:19 -04:00
|
|
|
e1.Focus()
|
2019-08-15 09:16:00 -04:00
|
|
|
|
2019-08-20 12:39:28 -04:00
|
|
|
e2 := giowrap.NewEditor("text 2",giowrap.Face(ctx.Faces.For(regular, ui.Sp(24))))
|
2019-08-15 09:16:00 -04:00
|
|
|
|
2019-08-20 12:39:28 -04:00
|
|
|
f1 := giowrap.NewFlex(giowrap.Axis(layout.Vertical))
|
|
|
|
OuterInset := giowrap.NewInset(giowrap.Size(ui.Dp(10)))
|
|
|
|
InnerInset := giowrap.NewInset(giowrap.Size(ui.Dp(10)))
|
2019-08-16 16:38:49 -04:00
|
|
|
|
2019-08-20 12:39:28 -04:00
|
|
|
f2 := giowrap.NewFlex(giowrap.Axis(layout.Horizontal))
|
2019-08-15 09:16:00 -04:00
|
|
|
|
2019-08-18 17:00:19 -04:00
|
|
|
btn1 := NewButton(ctx.Faces.For(regular, ui.Sp(24)),
|
|
|
|
"push1", color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6})
|
|
|
|
btn2 := NewButton(ctx.Faces.For(regular, ui.Sp(24)),
|
|
|
|
"push2", color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6})
|
|
|
|
|
|
|
|
profiled := false
|
|
|
|
startTime := time.Now()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
w.Invalidate()
|
|
|
|
case e := <-w.Events():
|
|
|
|
stime := time.Now()
|
|
|
|
switch e := e.(type) {
|
|
|
|
case app.DestroyEvent:
|
|
|
|
return
|
|
|
|
case app.DrawEvent:
|
|
|
|
ctx.Reset(e)
|
|
|
|
OuterInset(
|
|
|
|
f1(
|
|
|
|
e1,
|
|
|
|
giowrap.Flexible(5),
|
|
|
|
InnerInset(e2),
|
|
|
|
giowrap.Flexible(10),
|
|
|
|
f2(
|
|
|
|
InnerInset(btn1),
|
|
|
|
giowrap.Flexible(0.5),
|
|
|
|
InnerInset(btn2),
|
|
|
|
),
|
|
|
|
)).Layout(ctx)
|
|
|
|
ctx.Draw()
|
|
|
|
if btn1.Clicked(ctx) {
|
|
|
|
log.Print("Clicked: " + e1.Text() )
|
|
|
|
}
|
|
|
|
if btn2.Clicked(ctx) {
|
|
|
|
log.Print("Clicked: " + e2.Text() )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dur := time.Since(stime).Nanoseconds()
|
|
|
|
mux.Lock()
|
|
|
|
frames = frames + 1
|
|
|
|
frametime = frametime + dur
|
|
|
|
if dur > maxframetime { maxframetime = dur }
|
|
|
|
mux.Unlock()
|
|
|
|
}
|
|
|
|
if profiled { continue }
|
|
|
|
if time.Since(startTime) < time.Second * 10 { continue }
|
|
|
|
if Profile {
|
|
|
|
profiled = true
|
|
|
|
f, err := os.Create("memprofile.pprof")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("could not create memory profile: ", err)
|
|
|
|
}
|
|
|
|
if err := pprof.WriteHeapProfile(f); err != nil {
|
|
|
|
log.Fatal("could not write memory profile: ", err)
|
|
|
|
}
|
|
|
|
log.Print("Memory profile written")
|
|
|
|
f.Close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main2() {
|
|
|
|
w := app.NewWindow(nil)
|
|
|
|
q := w.Queue()
|
|
|
|
ops := new(ui.Ops)
|
|
|
|
var faces measure.Faces
|
|
|
|
regular, err := sfnt.Parse(goregular.TTF)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("Cannot parse font.")
|
|
|
|
}
|
|
|
|
t := time.NewTicker(time.Second/time.Duration(FPS))
|
|
|
|
e1 := &text.Editor{
|
|
|
|
Face: faces.For(regular, ui.Sp(24)),
|
|
|
|
SingleLine: true,
|
|
|
|
}
|
|
|
|
e1.Focus()
|
|
|
|
e1.SetText("text 1")
|
|
|
|
|
|
|
|
e2 := &text.Editor{
|
|
|
|
Face: faces.For(regular, ui.Sp(24)),
|
|
|
|
SingleLine: true,
|
|
|
|
}
|
|
|
|
e2.Focus()
|
|
|
|
e2.SetText("text 2")
|
|
|
|
|
|
|
|
f1 := layout.Flex{ Axis: layout.Vertical }
|
|
|
|
OuterInset := layout.UniformInset(ui.Dp(10))
|
|
|
|
InnerInset := layout.UniformInset(ui.Dp(10))
|
|
|
|
|
|
|
|
f2 := layout.Flex{ Axis: layout.Horizontal }
|
|
|
|
|
|
|
|
btn1 := text.Label{
|
|
|
|
Face: faces.For(regular, ui.Sp(24)),
|
|
|
|
Text: "push1",
|
|
|
|
}
|
|
|
|
b1ins := layout.UniformInset(ui.Dp(4))
|
|
|
|
btn2 := text.Label{
|
|
|
|
Face: faces.For(regular, ui.Sp(24)),
|
|
|
|
Text: "push2",
|
|
|
|
}
|
|
|
|
b2ins := layout.UniformInset(ui.Dp(4))
|
|
|
|
var bg1, bg2 ui.MacroOp
|
|
|
|
click1 := new(gesture.Click)
|
|
|
|
click2 := new(gesture.Click)
|
|
|
|
|
|
|
|
profiled := false
|
|
|
|
startTime := time.Now()
|
|
|
|
|
|
|
|
for {
|
|
|
|
select {
|
|
|
|
case <-t.C:
|
|
|
|
w.Invalidate()
|
|
|
|
case e := <-w.Events():
|
|
|
|
stime := time.Now()
|
|
|
|
switch e := e.(type) {
|
|
|
|
case app.DestroyEvent:
|
|
|
|
return
|
|
|
|
case app.DrawEvent:
|
|
|
|
c := &e.Config
|
|
|
|
ops.Reset()
|
|
|
|
faces.Reset(c)
|
|
|
|
cs := layout.RigidConstraints(e.Size)
|
|
|
|
cs = OuterInset.Begin(c, ops, cs)
|
|
|
|
f1.Init(ops, cs)
|
|
|
|
cs = f1.Rigid()
|
|
|
|
dims := e1.Layout(c, q, ops, cs)
|
|
|
|
f1c1 := f1.End(dims)
|
|
|
|
cs = f1.Flexible(5)
|
|
|
|
cs = InnerInset.Begin(c, ops, cs)
|
|
|
|
dims = e2.Layout(c, q, ops, cs)
|
|
|
|
dims = InnerInset.End(dims)
|
|
|
|
f1c2 := f1.End(dims)
|
|
|
|
cs = f1.Flexible(10)
|
|
|
|
f2.Init(ops, cs)
|
|
|
|
cs = f2.Rigid()
|
|
|
|
cs = InnerInset.Begin(c, ops, cs)
|
|
|
|
bg1.Record(ops)
|
|
|
|
cs = b1ins.Begin(c, ops, cs)
|
|
|
|
dims = btn1.Layout(ops, cs)
|
|
|
|
dims = b1ins.End(dims)
|
|
|
|
pointer.RectAreaOp{Size: dims.Size}.Add(ops)
|
|
|
|
click1.Add(ops)
|
|
|
|
bg1.Stop()
|
|
|
|
wi, h := float32(dims.Size.X), float32(dims.Size.Y)
|
|
|
|
r := float32(c.Px(ui.Dp(4)))
|
|
|
|
giowrap.Rrect(ops, wi, h, r, r, r, r)
|
|
|
|
gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops)
|
|
|
|
gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops)
|
|
|
|
bg1.Add(ops)
|
|
|
|
dims = InnerInset.End(dims)
|
|
|
|
f2c1 := f2.End(dims)
|
|
|
|
cs = f2.Flexible(0.5)
|
|
|
|
cs = InnerInset.Begin(c, ops, cs)
|
|
|
|
bg2.Record(ops)
|
|
|
|
cs = b2ins.Begin(c, ops, cs)
|
|
|
|
dims = btn2.Layout(ops, cs)
|
|
|
|
dims = b2ins.End(dims)
|
|
|
|
pointer.RectAreaOp{Size: dims.Size}.Add(ops)
|
|
|
|
click2.Add(ops)
|
|
|
|
bg2.Stop()
|
|
|
|
wi, h = float32(dims.Size.X), float32(dims.Size.Y)
|
|
|
|
giowrap.Rrect(ops, wi, h, r, r, r, r)
|
|
|
|
gdraw.ColorOp{Color: color.RGBA{A: 0xff, R: 0x3c, G: 0x98, B: 0xc6}}.Add(ops)
|
|
|
|
gdraw.DrawOp{Rect: f32.Rectangle{Max: f32.Point{X: wi, Y: h}}}.Add(ops)
|
|
|
|
bg2.Add(ops)
|
|
|
|
dims = InnerInset.End(dims)
|
|
|
|
f2c2 := f2.End(dims)
|
|
|
|
dims = f2.Layout(f2c1, f2c2)
|
|
|
|
f1c3 := f1.End(dims)
|
|
|
|
dims = f1.Layout(f1c1, f1c2, f1c3)
|
|
|
|
dims = OuterInset.End(dims)
|
|
|
|
w.Draw(ops)
|
|
|
|
for _,ev := range click1.Events(q) {
|
|
|
|
if ev.Type == gesture.TypeClick {
|
2019-08-16 16:38:49 -04:00
|
|
|
log.Print("Clicked: " + e1.Text() )
|
|
|
|
}
|
2019-08-18 17:00:19 -04:00
|
|
|
}
|
|
|
|
for _, ev := range click2.Events(q) {
|
|
|
|
if ev.Type == gesture.TypeClick {
|
2019-08-15 09:16:00 -04:00
|
|
|
log.Print("Clicked: " + e2.Text() )
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-08-18 17:00:19 -04:00
|
|
|
dur := time.Since(stime).Nanoseconds()
|
|
|
|
mux.Lock()
|
|
|
|
frames = frames + 1
|
|
|
|
frametime = frametime + dur
|
|
|
|
if dur > maxframetime { maxframetime = dur }
|
|
|
|
mux.Unlock()
|
2019-08-15 09:16:00 -04:00
|
|
|
}
|
2019-08-18 17:00:19 -04:00
|
|
|
if profiled { continue }
|
|
|
|
if time.Since(startTime) < time.Second * 10 { continue }
|
|
|
|
if Profile {
|
|
|
|
profiled = true
|
|
|
|
f, err := os.Create("memprofile.pprof")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal("could not create memory profile: ", err)
|
|
|
|
}
|
|
|
|
if err := pprof.WriteHeapProfile(f); err != nil {
|
|
|
|
log.Fatal("could not write memory profile: ", err)
|
|
|
|
}
|
|
|
|
log.Print("Memory profile written")
|
|
|
|
f.Close()
|
|
|
|
}
|
|
|
|
}
|
2019-08-15 09:16:00 -04:00
|
|
|
}
|
|
|
|
|