Compare commits
2 Commits
cf56e8c47e
...
f134a1f21e
Author | SHA1 | Date | |
---|---|---|---|
f134a1f21e | |||
dfc3f618c0 |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -2,4 +2,6 @@ cmd/hello/hello
|
|||
cmd/cal/cal
|
||||
cmd/scroll/scroll
|
||||
cmd/grid/grid
|
||||
cmd/form/form
|
||||
*.apk
|
||||
memprofile*
|
||||
|
|
|
@ -20,7 +20,6 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
sel int32
|
||||
face text.Face
|
||||
)
|
||||
|
||||
|
|
227
cmd/form/main.go
Normal file
227
cmd/form/main.go
Normal file
|
@ -0,0 +1,227 @@
|
|||
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 = ctx.Reset(&e)
|
||||
giowrap.Mallocs("pre-layout")
|
||||
ctx = (*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")
|
||||
}
|
||||
|
36
examples/ctx.go
Normal file
36
examples/ctx.go
Normal file
|
@ -0,0 +1,36 @@
|
|||
{
|
||||
ctx.Reset(&e) // ctx keeps a pointer to e.Config, so we can do...
|
||||
ctx.RigidConstraints()
|
||||
{
|
||||
f1 := layout.Flex{Axis: layout.Vertical} // maybe pass ctx in here?
|
||||
ins := layout.UniformInset(ui.Dp(10))
|
||||
ins.Begin(ctx) // containers like Insets and Flex keep a pointer to ctx
|
||||
f1.Init(ctx)
|
||||
f1.Rigid()
|
||||
editor1.Layout(ctx)
|
||||
f1.End()
|
||||
{
|
||||
f1.Flexible(0.33)
|
||||
ins := layout.UniformInset(ui.Dp(10))
|
||||
ins.Begin(ctx)
|
||||
editor2.Layout(ctx)
|
||||
ins.End()
|
||||
}
|
||||
f1.End()
|
||||
{
|
||||
f1.Flexible(0.67)
|
||||
f2 := layout.Flex{Axis: layout.Horizontal}
|
||||
f2.Init(ctx)
|
||||
f2.Rigid()
|
||||
button1.Layout(ctx)
|
||||
c1 := f2.End()
|
||||
f2.Flexible(0.5)
|
||||
button2.Layout(ctx)
|
||||
c2 := f2.End()
|
||||
f2.Layout(c1, c2)
|
||||
}
|
||||
c3 := f1.End()
|
||||
f1.Layout(c1, c2, c3)
|
||||
ins.End()
|
||||
}
|
||||
}
|
24
main.go
24
main.go
|
@ -204,6 +204,7 @@ type List = WidgetCombinator
|
|||
type AxisOpt struct{ axis layout.Axis }
|
||||
|
||||
func Axis(x layout.Axis) AxisOpt { return AxisOpt{x} }
|
||||
|
||||
var Horizontal = AxisOpt{layout.Horizontal}
|
||||
var Vertical = AxisOpt{layout.Vertical}
|
||||
|
||||
|
@ -510,6 +511,29 @@ func Rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) {
|
|||
Mallocs("Rrect() end")
|
||||
}
|
||||
|
||||
type fillWidget struct {
|
||||
axis layout.Axis
|
||||
}
|
||||
|
||||
func FillWidth(ws ...Widget) Widget {
|
||||
return Enclose(fillWidget{layout.Horizontal}, ws...)
|
||||
}
|
||||
func FillHeight(ws ...Widget) Widget {
|
||||
return Enclose(fillWidget{layout.Vertical}, ws...)
|
||||
}
|
||||
|
||||
func (fw fillWidget) Begin(ctx *Context) {
|
||||
switch fw.axis {
|
||||
case layout.Horizontal:
|
||||
ctx.cs.Width.Min = ctx.cs.Width.Max
|
||||
case layout.Vertical:
|
||||
ctx.cs.Height.Min = ctx.cs.Height.Max
|
||||
}
|
||||
}
|
||||
|
||||
func (fw fillWidget) End(*Context) {
|
||||
}
|
||||
|
||||
type Clickable interface {
|
||||
Widget
|
||||
Clicked(*Context) bool
|
||||
|
|
Loading…
Reference in New Issue
Block a user