Compare commits
	
		
			No commits in common. "f134a1f21e862813ce08da69ad35fe640b3d82be" and "cf56e8c47eeaff437870eea1f93f27607ff5a11d" have entirely different histories.
		
	
	
		
			f134a1f21e
			...
			cf56e8c47e
		
	
		
							
								
								
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| 
						 | 
					@ -2,6 +2,4 @@ cmd/hello/hello
 | 
				
			||||||
cmd/cal/cal
 | 
					cmd/cal/cal
 | 
				
			||||||
cmd/scroll/scroll
 | 
					cmd/scroll/scroll
 | 
				
			||||||
cmd/grid/grid
 | 
					cmd/grid/grid
 | 
				
			||||||
cmd/form/form
 | 
					 | 
				
			||||||
*.apk
 | 
					*.apk
 | 
				
			||||||
memprofile*
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 | 
						sel  int32
 | 
				
			||||||
	face text.Face
 | 
						face text.Face
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										227
									
								
								cmd/form/main.go
									
									
									
									
									
								
							
							
						
						
									
										227
									
								
								cmd/form/main.go
									
									
									
									
									
								
							| 
						 | 
					@ -1,227 +0,0 @@
 | 
				
			||||||
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")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					@ -1,36 +0,0 @@
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	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,7 +204,6 @@ type List = WidgetCombinator
 | 
				
			||||||
type AxisOpt struct{ axis layout.Axis }
 | 
					type AxisOpt struct{ axis layout.Axis }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Axis(x layout.Axis) AxisOpt { return AxisOpt{x} }
 | 
					func Axis(x layout.Axis) AxisOpt { return AxisOpt{x} }
 | 
				
			||||||
 | 
					 | 
				
			||||||
var Horizontal = AxisOpt{ layout.Horizontal }
 | 
					var Horizontal = AxisOpt{ layout.Horizontal }
 | 
				
			||||||
var Vertical = AxisOpt{ layout.Vertical }
 | 
					var Vertical = AxisOpt{ layout.Vertical }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -511,29 +510,6 @@ func Rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) {
 | 
				
			||||||
	Mallocs("Rrect() end")
 | 
						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 {
 | 
					type Clickable interface {
 | 
				
			||||||
	Widget
 | 
						Widget
 | 
				
			||||||
	Clicked(*Context) bool
 | 
						Clicked(*Context) bool
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user