From 455a8960e5b6efcdb9bb80a5e5f47a54c82bcf5a Mon Sep 17 00:00:00 2001 From: Greg Date: Tue, 8 Oct 2019 10:58:42 -0400 Subject: [PATCH] Update gio version. --- .gitignore | 1 + cmd/passgo-gui/main.go | 486 +++++++++++++++++++++++------------------ cmd/passgo-gui/ui.go | 137 ++++++------ go.mod | 2 +- go.sum | 11 + 5 files changed, 352 insertions(+), 285 deletions(-) diff --git a/.gitignore b/.gitignore index 2925ed9..300e00c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ cmd/passgo/passgo cmd/passgo-gui/passgo-gui nohup.out *.apk +cpuprofile diff --git a/cmd/passgo-gui/main.go b/cmd/passgo-gui/main.go index 6e8574a..5715edf 100644 --- a/cmd/passgo-gui/main.go +++ b/cmd/passgo-gui/main.go @@ -3,20 +3,23 @@ package main import ( + "fmt" "io/ioutil" "os" "path" + "runtime" + "runtime/pprof" "strconv" "strings" "sync" "time" - "gioui.org/ui" - "gioui.org/ui/app" - "gioui.org/ui/key" - "gioui.org/ui/layout" - "gioui.org/ui/measure" - "gioui.org/ui/text" + "gioui.org/app" + "gioui.org/io/key" + "gioui.org/layout" + "gioui.org/text" + "gioui.org/text/shape" + "gioui.org/unit" "golang.org/x/image/font/sfnt" @@ -33,6 +36,24 @@ type conf struct { } func main() { + go func() { + f, err := os.Create("cpuprofile") + if err != nil { + fmt.Printf("Can't create CPU profile\n") + os.Exit(-1) + } + fmt.Printf("Starting CPU profile\n") + if err := pprof.StartCPUProfile(f); err != nil { + fmt.Printf("Can't start CPU profile\n") + f.Close() + os.Exit(-1) + } + time.Sleep(time.Second * 10) + fmt.Printf("Stopping CPU profile\n") + pprof.StopCPUProfile() + f.Close() + fmt.Printf("CPU profile written\n") + }() var fd *os.File confFile := path.Join(confDir, "config.yml") if _, err := os.Stat(confFile); os.IsNotExist(err) { @@ -94,6 +115,7 @@ var ( func Updater() { update := func() { + fmt.Printf("update()\n") ltmp, err := store.List() if err != nil { log(Info, err) @@ -155,24 +177,21 @@ func saveConf(fds ...*os.File) { func eventLoop() { w := app.NewWindow( - app.WithWidth(ui.Dp(250)), - app.WithTitle("passgo")) - q := w.Queue() - var c ui.Config - ops := new(ui.Ops) - var dims layout.Dimensions - var cs layout.Constraints + app.Size(unit.Dp(250), unit.Dp(500)), + app.Title("passgo")) + gtx := &layout.Context{Queue: w.Queue()} + var margincs layout.Constraints - var faces measure.Faces + family := &shape.Family{Regular: regular} + var c1 layout.FlexChild // flex child for title bar - face := faces.For(regular, ui.Sp(16)) sysinset := &layout.Inset{} - margin := layout.UniformInset(ui.Dp(10)) + margin := layout.UniformInset(unit.Dp(10)) - title := &text.Label{Face: face, Text: "passgo"} + title := &text.Label{Size: unit.Sp(16), Text: "passgo"} dotsBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "\xe2\x8b\xae", Alignment: text.Middle, Color: black, @@ -185,12 +204,12 @@ func eventLoop() { lst := &layout.List{Axis: layout.Vertical} passBtns := make([]*Button, 0) pathnames := make([]string, 0) - copied := &Overlay{Face: face, Text: "copied to clipboard", + copied := &Overlay{Size: unit.Sp(16), Text: "copied to clipboard", Color: black, Background: darkgray, Alignment: text.Middle, } - cleared := &Overlay{Face: face, Text: "clipboard cleared", + cleared := &Overlay{Size: unit.Sp(16), Text: "clipboard cleared", Color: black, Background: darkgray, Alignment: text.Middle, @@ -210,7 +229,7 @@ func eventLoop() { z = "/" } passBtns = append(passBtns, &Button{ - Face: face, + Size: unit.Sp(16), Label: strings.Join([]string{s, n, z}, ""), Background: gray, }) @@ -231,7 +250,7 @@ func eventLoop() { for i, n := range ids { if i >= len(idBtns) { idBtns = append(idBtns, &Button{ - Face: face, + Size: unit.Sp(16), Label: n, Alignment: text.End, Color: black, @@ -245,70 +264,70 @@ func eventLoop() { } confBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "configure", Alignment: text.Middle, Color: black, Background: gray, } - storeDirLabel := &text.Label{Face: face, Text: "Store directory"} - storeDirEd := &text.Editor{Face: face, SingleLine: true} + storeDirLabel := &text.Label{Size: unit.Sp(16), Text: "Store directory"} + storeDirEd := &text.Editor{Size: unit.Sp(16), Family: family, SingleLine: true} storeDirEd.SetText(store.Dir) saveBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "save", Alignment: text.End, Color: black, Background: gray, } backBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "back", Alignment: text.End, Color: black, Background: gray, } - confirmLabel := &text.Label{Face: face, Text: "Password exists. Overwrite?"} + confirmLabel := &text.Label{Size: unit.Sp(16), Text: "Password exists. Overwrite?"} yesBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "yes", Alignment: text.End, Color: black, Background: gray, } - promptLabel := &text.Label{Face: face, Text: "passphrase"} - promptEd := &text.Editor{Face: face, SingleLine: true, Submit: true} + promptLabel := &text.Label{Size: unit.Sp(16), Text: "passphrase"} + promptEd := &text.Editor{Size: unit.Sp(16), Family: family, SingleLine: true, Submit: true} okBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "ok", Alignment: text.End, Color: black, Background: gray, } plusBtn := &Button{ - Face: face, + Size: unit.Sp(16), Label: "+", Alignment: text.Middle, Color: black, Background: gray, } - insertLabel := &text.Label{Face: face, Text: "Insert"} - passnameLabel := &text.Label{Face: face, Text: "password name:"} - passnameEd := &text.Editor{Face: face, SingleLine: true, Submit: true} - passvalLabel := &text.Label{Face: face, Text: "password value:"} - passvalEd := &text.Editor{Face: face, SingleLine: true, Submit: true} + insertLabel := &text.Label{Size: unit.Sp(16), Text: "Insert"} + passnameLabel := &text.Label{Size: unit.Sp(16), Text: "password name:"} + passnameEd := &text.Editor{Size: unit.Sp(16), Family: family, SingleLine: true, Submit: true} + passvalLabel := &text.Label{Size: unit.Sp(16), Text: "password value:"} + passvalEd := &text.Editor{Size: unit.Sp(16), Family: family, SingleLine: true, Submit: true} - noidLabel := &text.Label{Face: face, Text: "No GPG ids available. Please create a private key"} - idLabel := &text.Label{Face: face, Text: "Select ID"} + noidLabel := &text.Label{Size: unit.Sp(16), Text: "No GPG ids available. Please create a private key"} + idLabel := &text.Label{Size: unit.Sp(16), Text: "Select ID"} anim := &time.Ticker{} animating := false animOn := func() { log(Info, "animOn()") - anim = time.NewTicker(time.Second / 120) + anim = time.NewTicker(time.Second / 30) animating = true w.Invalidate() } @@ -333,63 +352,63 @@ func eventLoop() { start2 := float64(Config.ClearDelay) fade2a, end := start2+1.5, start2+2.0 - cs = flex.Flexible(1.0) - mux.Lock() - if lst.Dragging() { - key.HideInputOp{}.Add(ops) - } - var c2 layout.FlexChild - switch { - case store.Empty: - c2 = flex.End(confBtn.Layout(c, q, ops, cs)) - if confBtn.Clicked() { - log(Info, "Configure") - w.Invalidate() - page = confPage + c2 := flex.Flex(gtx, 1.0, func() { + mux.Lock() + if lst.Dragging() { + key.HideInputOp{}.Add(gtx.Ops) } - case store.Id == "": - c2 = flex.End(idLabel.Layout(ops, cs)) - w.Invalidate() - page = idPage - default: - for lst.Init(c, q, ops, cs, len(passBtns)); lst.More(); lst.Next() { - i := lst.Index() - btn := passBtns[i] - dims = btn.Layout(c, q, ops, lst.Constraints()) - lst.End(dims) - if btn.Clicked() { - log(Info, "Clicked ", btn.Label) - // don't block UI thread on decryption attempt - go func(name string) { - p, err := store.Decrypt(name, prompt) - //p, err := store.Decrypt(name) - if err == nil { - passgo.Clip(p) - overlayStart = time.Now() - overlay = copied - overlay.Color = black - overlay.Background = darkgray - w.Invalidate() - go func() { - time.Sleep(time.Millisecond * time.Duration(fade1a*1000)) - animOn() - }() - go func() { - time.Sleep(time.Millisecond * time.Duration(Config.ClearDelay*1000)) - log(Info, "clearing clipboard") - passgo.Clip("") - }() - } else { - log(Info, "Can't decrypt ", name) - log(Info, err) - } - }(pathnames[i]) + switch { + case store.Empty: + confBtn.Layout(gtx, family) + if confBtn.Clicked() { + log(Info, "Configure") + w.Invalidate() + page = confPage + } + case store.Id == "": + idLabel.Layout(gtx, family) + w.Invalidate() + page = idPage + default: + li := func(i int) { + btn := passBtns[i] + btn.Layout(gtx, family) + if btn.Clicked() { + log(Info, "Clicked ", btn.Label) + // don't block UI thread on decryption attempt + go func(name string) { + p, err := store.Decrypt(name, prompt) + //p, err := store.Decrypt(name) + if err == nil { + passgo.Clip(p) + overlayStart = time.Now() + overlay = copied + overlay.Color = black + overlay.Background = darkgray + w.Invalidate() + go func() { + time.Sleep(time.Millisecond * time.Duration(fade1a*1000)) + animOn() + }() + go func() { + time.Sleep(time.Millisecond * time.Duration(Config.ClearDelay*1000)) + log(Info, "clearing clipboard") + passgo.Clip("") + }() + } else { + log(Info, "Can't decrypt ", name) + log(Info, err) + } + }(pathnames[i]) + } + } + for i := 0; i < len(passBtns); i++ { + lst.Layout(gtx, len(passBtns), li) } } - c2 = flex.End(lst.Layout()) - } - mux.Unlock() - flex.Layout(c1, c2) + mux.Unlock() + }) + flex.Layout(gtx, c1, c2) x := time.Since(overlayStart).Seconds() if x >= fade1b && x < start2 && animating { animOff() @@ -426,11 +445,12 @@ func eventLoop() { overlay.Color = black overlay.Background = darkgray } - cs = margincs - al := layout.Align{Alignment: layout.SE} - cs = al.Begin(ops, cs) - cs.Width.Min = cs.Width.Max - dims = al.End(overlay.Layout(c, ops, cs)) + gtx.Constraints = margincs + al := layout.Align(layout.SE) + al.Layout(gtx, func() { + gtx.Constraints.Width.Min = gtx.Constraints.Width.Max + overlay.Layout(gtx, family) + }) } if x > start2 && x < fade2a { // animOff() @@ -444,44 +464,46 @@ func eventLoop() { if !animating { animOn() } - cs = flex.Rigid() - c2 := flex.End(idLabel.Layout(ops, cs)) - var c3 layout.FlexChild + c2 := flex.Rigid(gtx, func() { + idLabel.Layout(gtx, family) + }) //if len(idBtns) == 0 { updateIdBtns() //} - cs = flex.Rigid() - if len(idBtns) == 0 { // still zero after update - c3 = flex.End(noidLabel.Layout(ops, cs)) - } else { - for lst.Init(c, q, ops, cs, len(idBtns)); lst.More(); lst.Next() { - lst.End(idBtns[lst.Index()].Layout(c, q, ops, lst.Constraints())) - } - c3 = flex.End(lst.Layout()) - for _, btn := range idBtns { - if btn.Clicked() { - log(Info, "ID selected: ", btn.Label) - store.SetID(btn.Label) - w.Invalidate() - animOff() - page = listPage + c3 := flex.Rigid(gtx, func() { + if len(idBtns) == 0 { // still zero after update + noidLabel.Layout(gtx, family) + } else { + for i := 0; i < len(idBtns); i++ { + lst.Layout(gtx, len(idBtns), func(i int) { + idBtns[i].Layout(gtx, family) + }) + } + for _, btn := range idBtns { + if btn.Clicked() { + log(Info, "ID selected: ", btn.Label) + store.SetID(btn.Label) + w.Invalidate() + animOff() + page = listPage + } } } - } - flex.Layout(c1, c2, c3) + }) + flex.Layout(gtx, c1, c2, c3) } var insName, insValue string genBtn := &SelButton{SelColor: darkgray} - genBtn.Button = Button{Face: face, Label: "generate", Background: gray} + genBtn.Button = Button{Size: unit.Sp(16), Label: "generate", Background: gray} symBtn := &SelButton{SelColor: gray, Selected: true} numBtn := &SelButton{SelColor: gray, Selected: true} - symBtn.Button = Button{Face: face, Label: "@", Background: darkgray} - numBtn.Button = Button{Face: face, Label: "#", Background: darkgray} - lenEd := &text.Editor{Face: face, SingleLine: true, Alignment: text.End} + symBtn.Button = Button{Size: unit.Sp(16), Label: "@", Background: darkgray} + numBtn.Button = Button{Size: unit.Sp(16), Label: "#", Background: darkgray} + lenEd := &text.Editor{Size: unit.Sp(16), Family: family, SingleLine: true, Alignment: text.End} lenEd.SetText("15") - lBtn := &Button{Face: face, Label: "<", Background: gray} - rBtn := &Button{Face: face, Label: ">", Background: gray} + lBtn := &Button{Size: unit.Sp(16), Label: "<", Background: gray} + rBtn := &Button{Size: unit.Sp(16), Label: ">", Background: gray} updatePw := func() { if !genBtn.Selected { @@ -499,40 +521,49 @@ func eventLoop() { default: gen = rand.Letter } - l,_ := strconv.Atoi(lenEd.Text()) - pw,_ := rand.Slice(gen,l) + l, _ := strconv.Atoi(lenEd.Text()) + pw, _ := rand.Slice(gen, l) passvalEd.SetText(string(pw)) } insertPage = func() { - c2 := flex.End(insertLabel.Layout(ops, flex.Rigid())) + c2 := flex.Rigid(gtx, func() { insertLabel.Layout(gtx, family) }) + c3 := flex.Rigid(gtx, func() { passnameLabel.Layout(gtx, family) }) + c4 := flex.Rigid(gtx, func() { passnameEd.Layout(gtx) }) + c5 := flex.Rigid(gtx, func() { passvalLabel.Layout(gtx, family) }) + c6 := flex.Rigid(gtx, func() { passvalEd.Layout(gtx) }) - c3 := flex.End(passnameLabel.Layout(ops, flex.Rigid())) - c4 := flex.End(passnameEd.Layout(c, q, ops, flex.Rigid())) - c5 := flex.End(passvalLabel.Layout(ops, flex.Rigid())) - c6 := flex.End(passvalEd.Layout(c, q, ops, flex.Rigid())) - - al := &layout.Align{Alignment: layout.E} btnflx := &layout.Flex{Axis: layout.Horizontal} - btnflx.Init(ops, al.Begin(ops, flex.Rigid())) - bc1 := btnflx.End(lBtn.Layout(c, q, ops, btnflx.Rigid())) - cs := btnflx.Rigid() - cs.Width.Min = 60 - bc2 := btnflx.End(lenEd.Layout(c, q, ops, cs)) - bc3 := btnflx.End(rBtn.Layout(c, q, ops, btnflx.Rigid())) - bc4 := btnflx.End(symBtn.Layout(c, q, ops, btnflx.Rigid())) - bc5 := btnflx.End(numBtn.Layout(c, q, ops, btnflx.Rigid())) - bc6 := btnflx.End(genBtn.Layout(c, q, ops, btnflx.Rigid())) - c7 := flex.End(al.End(btnflx.Layout(bc1, bc2, bc3, bc4, bc5, bc6))) + al := layout.Align(layout.E) + c7 := flex.Rigid(gtx, func() { + bc1 := btnflx.Rigid(gtx, func() { lBtn.Layout(gtx, family) }) + bc2 := btnflx.Rigid(gtx, func() { + gtx.Constraints.Width.Min = 60 + lenEd.Layout(gtx) + }) - btnflx.Init(ops, al.Begin(ops, flex.Rigid())) - bc1 = btnflx.End(backBtn.Layout(c, q, ops, btnflx.Rigid())) - bc2 = btnflx.End(saveBtn.Layout(c, q, ops, btnflx.Rigid())) - c8 := flex.End(al.End(btnflx.Layout(bc1, bc2))) - flex.Layout(c1, c2, c3, c4, c5, c6, c7, c8) + bc3 := btnflx.Rigid(gtx, func() { rBtn.Layout(gtx, family) }) + bc4 := btnflx.Rigid(gtx, func() { symBtn.Layout(gtx, family) }) + bc5 := btnflx.Rigid(gtx, func() { numBtn.Layout(gtx, family) }) + bc6 := btnflx.Rigid(gtx, func() { genBtn.Layout(gtx, family) }) + + al.Layout(gtx, func() { + btnflx.Layout(gtx, bc1, bc2, bc3, bc4, bc5, bc6) + }) + }) + + c8 := flex.Rigid(gtx, func() { + bc1 := btnflx.Rigid(gtx, func() { backBtn.Layout(gtx, family) }) + bc2 := btnflx.Rigid(gtx, func() { saveBtn.Layout(gtx, family) }) + al.Layout(gtx, func() { + btnflx.Layout(gtx, bc1, bc2) + }) + }) + + flex.Layout(gtx, c1, c2, c3, c4, c5, c6, c7, c8) if lBtn.Clicked() { - l,_ := strconv.Atoi(lenEd.Text()) + l, _ := strconv.Atoi(lenEd.Text()) if l > 0 { l -= 1 } @@ -541,8 +572,8 @@ func eventLoop() { w.Invalidate() } if rBtn.Clicked() { - l,_ := strconv.Atoi(lenEd.Text()) - lenEd.SetText(strconv.Itoa(l+1)) + l, _ := strconv.Atoi(lenEd.Text()) + lenEd.SetText(strconv.Itoa(l + 1)) updatePw() w.Invalidate() } @@ -580,15 +611,20 @@ func eventLoop() { } confirmPage = func() { - cs = flex.Rigid() - c2 := flex.End(confirmLabel.Layout(ops, cs)) - al := &layout.Align{Alignment: layout.E} + c2 := flex.Rigid(gtx, func() { + confirmLabel.Layout(gtx, family) + }) + al := layout.Align(layout.E) btnflx := &layout.Flex{Axis: layout.Horizontal} - btnflx.Init(ops, al.Begin(ops, flex.Rigid())) - bc1 := btnflx.End(backBtn.Layout(c, q, ops, btnflx.Rigid())) - bc2 := btnflx.End(yesBtn.Layout(c, q, ops, btnflx.Rigid())) - c3 := flex.End(al.End(btnflx.Layout(bc1, bc2))) - flex.Layout(c1, c2, c3) + c3 := flex.Rigid(gtx, func() { + bc1 := btnflx.Rigid(gtx, func() { backBtn.Layout(gtx, family) }) + bc2 := btnflx.Rigid(gtx, func() { yesBtn.Layout(gtx, family) }) + + al.Layout(gtx, func() { + btnflx.Layout(gtx, bc1, bc2) + }) + }) + flex.Layout(gtx, c1, c2, c3) if backBtn.Clicked() { w.Invalidate() @@ -602,22 +638,24 @@ func eventLoop() { } confPage = func() { - cs = flex.Rigid() - c2 := flex.End(storeDirLabel.Layout(ops, cs)) - cs = flex.Rigid() - c3 := flex.End(storeDirEd.Layout(c, q, ops, cs)) - cs = flex.Rigid() - al := &layout.Align{Alignment: layout.E} - cs = al.Begin(ops, cs) - btnflx := &layout.Flex{Axis: layout.Horizontal} - btnflx.Init(ops, cs) - cs = btnflx.Rigid() - bc1 := btnflx.End(backBtn.Layout(c, q, ops, cs)) - cs = btnflx.Rigid() - bc2 := btnflx.End(saveBtn.Layout(c, q, ops, cs)) - dims = btnflx.Layout(bc1, bc2) - c4 := flex.End(al.End(dims)) - flex.Layout(c1, c2, c3, c4) + c2 := flex.Rigid(gtx, func() { storeDirLabel.Layout(gtx, family) }) + c3 := flex.Rigid(gtx, func() { storeDirEd.Layout(gtx) }) + + al := layout.Align(layout.E) + c4 := flex.Rigid(gtx, func() { + btnflx := &layout.Flex{Axis: layout.Horizontal} + bc1 := btnflx.Rigid(gtx, func() { + backBtn.Layout(gtx, family) + }) + bc2 := btnflx.Rigid(gtx, func() { + saveBtn.Layout(gtx, family) + }) + al.Layout(gtx, func() { + btnflx.Layout(gtx, bc1, bc2) + }) + }) + flex.Layout(gtx, c1, c2, c3, c4) + if backBtn.Clicked() { log(Info, "Back") storeDirEd.SetText(store.Dir) @@ -642,29 +680,30 @@ func eventLoop() { promptPage = func() { submit := false - for e, ok := promptEd.Next(c, q); ok; e, ok = promptEd.Next(c, q) { + for e, ok := promptEd.Event(gtx); ok; e, ok = promptEd.Event(gtx) { switch e.(type) { case text.SubmitEvent: log(Info, "Submit") submit = true } } - cs = flex.Rigid() - c2 := flex.End(promptLabel.Layout(ops, cs)) - cs = flex.Rigid() - c3 := flex.End(promptEd.Layout(c, q, ops, cs)) - cs = flex.Rigid() - al := &layout.Align{Alignment: layout.E} - cs = al.Begin(ops, cs) - btnflx := &layout.Flex{Axis: layout.Horizontal} - btnflx.Init(ops, cs) - cs = btnflx.Rigid() - bc1 := btnflx.End(backBtn.Layout(c, q, ops, cs)) - cs = btnflx.Rigid() - bc2 := btnflx.End(okBtn.Layout(c, q, ops, cs)) - dims = btnflx.Layout(bc1, bc2) - c4 := flex.End(al.End(dims)) - flex.Layout(c1, c2, c3, c4) + c2 := flex.Rigid(gtx, func() { promptLabel.Layout(gtx, family) }) + c3 := flex.Rigid(gtx, func() { promptEd.Layout(gtx) }) + c4 := flex.Rigid(gtx, func() { + al := layout.Align(layout.E) + btnflx := &layout.Flex{Axis: layout.Horizontal} + bc1 := btnflx.Rigid(gtx, func() { + backBtn.Layout(gtx, family) + }) + bc2 := btnflx.Rigid(gtx, func() { + okBtn.Layout(gtx, family) + }) + al.Layout(gtx, func() { + btnflx.Layout(gtx, bc1, bc2) + }) + }) + flex.Layout(gtx, c1, c2, c3, c4) + if submit || okBtn.Clicked() { log(Info, "Ok") go func() { // do not block UI thread @@ -685,6 +724,9 @@ func eventLoop() { page = listPage + ms := &runtime.MemStats{} + x := 0 + var mallocs uint64 for { select { case <-updated: @@ -694,36 +736,45 @@ func eventLoop() { case <-anim.C: w.Invalidate() case e := <-w.Events(): + x++ + if x == 100 { + runtime.ReadMemStats(ms) + mallocs = ms.Mallocs + } switch e := e.(type) { case app.DestroyEvent: return case app.UpdateEvent: - c = &e.Config - ops.Reset() - faces.Reset(c) - cs = layout.RigidConstraints(e.Size) + fmt.Printf("UpdateEvent\n") + gtx.Reset(&e.Config, e.Size) + sysinset.Top = e.Insets.Top sysinset.Bottom = e.Insets.Bottom sysinset.Left = e.Insets.Left sysinset.Right = e.Insets.Right - cs = sysinset.Begin(c, ops, cs) - cs = margin.Begin(c, ops, cs) - margincs = cs - flex.Init(ops, cs) - cs = flex.Rigid() - titleflex.Init(ops, cs) - cs = titleflex.Rigid() - ct2 := titleflex.End(plusBtn.Layout(c, q, ops, cs)) - cs = titleflex.Rigid() - ct3 := titleflex.End(dotsBtn.Layout(c, q, ops, cs)) - cs = titleflex.Flexible(1.0) - cs.Width.Min = cs.Width.Max - ct1 := titleflex.End(title.Layout(ops, cs)) - c1 = flex.End(titleflex.Layout(ct1, ct2, ct3)) - page() + sysinset.Layout(gtx, func() { + margin.Layout(gtx, func() { + margincs = gtx.Constraints + c1 = flex.Rigid(gtx, func() { + ct2 := titleflex.Rigid(gtx, func() { + plusBtn.Layout(gtx, family) + }) + ct3 := titleflex.Rigid(gtx, func() { + dotsBtn.Layout(gtx, family) + }) + ct1 := titleflex.Flex(gtx, 1.0, func() { + gtx.Constraints.Width.Min = gtx.Constraints.Width.Max + title.Layout(gtx, family) + }) + titleflex.Layout(gtx, ct1, ct2, ct3) + }) - sysinset.End(margin.End(dims)) + stime := time.Now() + page() + fmt.Printf("page in %s\n", time.Since(stime)) + }) + }) if dotsBtn.Clicked() { log(Info, "Configure") @@ -736,7 +787,12 @@ func eventLoop() { insName, insValue = "", "" page = insertPage } - w.Update(ops) + w.Update(gtx.Ops) + } + if x == 100 { + x = 0 + runtime.ReadMemStats(ms) + fmt.Printf("mallocs: %d\n", ms.Mallocs-mallocs) } } } diff --git a/cmd/passgo-gui/ui.go b/cmd/passgo-gui/ui.go index a50ca08..8a7fac4 100644 --- a/cmd/passgo-gui/ui.go +++ b/cmd/passgo-gui/ui.go @@ -4,14 +4,14 @@ import ( "image" "image/color" - "gioui.org/ui" - "gioui.org/ui/f32" - "gioui.org/ui/gesture" - "gioui.org/ui/input" - "gioui.org/ui/layout" - "gioui.org/ui/paint" - "gioui.org/ui/pointer" - "gioui.org/ui/text" + "gioui.org/f32" + "gioui.org/gesture" + "gioui.org/io/pointer" + "gioui.org/layout" + "gioui.org/op" + "gioui.org/op/paint" + "gioui.org/text" + "gioui.org/unit" ) var ( @@ -22,7 +22,7 @@ var ( ) type Overlay struct { - Face text.Face + Size unit.Value Text string Click gesture.Click Color color.RGBA @@ -30,30 +30,30 @@ type Overlay struct { Alignment text.Alignment } -func (b *Overlay) Layout(c ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimensions { - ins := layout.UniformInset(ui.Dp(1)) - cs = ins.Begin(c, ops, cs) - var dims layout.Dimensions - st := layout.Stack{} - st.Init(ops, cs) - { - cs = st.Rigid() - l := text.Label{ - Face: b.Face, - Text: b.Text, - Alignment: b.Alignment, - } - ins := layout.UniformInset(ui.Dp(4)) - l.Material.Record(ops) - paint.ColorOp{Color: b.Color}.Add(ops) - l.Material.Stop() - dims = ins.End(l.Layout(ops, ins.Begin(c, ops, cs))) - pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops) - } - c2 := st.End(dims) - c1 := st.End(layoutRRect(b.Background, c, ops, st.Expand())) - dims = st.Layout(c1, c2) - return ins.End(dims) +func (b *Overlay) Layout(gtx *layout.Context, family text.Family) { + ins := layout.UniformInset(unit.Dp(1)) + ins.Layout(gtx, func() { + st := layout.Stack{} + c2 := st.Rigid(gtx, func() { + l := text.Label{ + Size: b.Size, + Text: b.Text, + Alignment: b.Alignment, + } + ins := layout.UniformInset(unit.Dp(4)) + l.Material.Record(gtx.Ops) + paint.ColorOp{Color: b.Color}.Add(gtx.Ops) + l.Material.Stop() + ins.Layout(gtx, func() { + l.Layout(gtx, family) + }) + pointer.RectAreaOp{image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)}.Add(gtx.Ops) + }) + c1 := st.Expand(gtx, func() { + layoutRRect(b.Background, gtx) + }) + st.Layout(gtx, c1, c2) + }) } type SelButton struct { @@ -63,7 +63,7 @@ type SelButton struct { } type Button struct { - Face text.Face + Size unit.Value Label string Click gesture.Click Color color.RGBA @@ -72,22 +72,22 @@ type Button struct { clicked bool } -func layoutRRect(col color.RGBA, c ui.Config, ops *ui.Ops, cs layout.Constraints) layout.Dimensions { - r := float32(c.Px(ui.Dp(4))) - sz := image.Point{X: cs.Width.Min, Y: cs.Height.Min} +func layoutRRect(col color.RGBA, gtx *layout.Context) { + r := float32(gtx.Config.Px(unit.Dp(4))) + sz := image.Point{X: gtx.Constraints.Width.Min, Y: gtx.Constraints.Height.Min} w, h := float32(sz.X), float32(sz.Y) - rrect(ops, w, h, r, r, r, r) - paint.ColorOp{Color: col}.Add(ops) - paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(ops) - return layout.Dimensions{Size: sz} + rrect(gtx.Ops, w, h, r, r, r, r) + paint.ColorOp{Color: col}.Add(gtx.Ops) + paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: w, Y: h}}}.Add(gtx.Ops) + gtx.Dimensions = layout.Dimensions{Size: sz} } // https://pomax.github.io/bezierinfo/#circles_cubic. -func rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) { +func rrect(ops *op.Ops, width, height, se, sw, nw, ne float32) { w, h := float32(width), float32(height) const c = 0.55228475 // 4*(sqrt(2)-1)/3 - var b paint.PathBuilder - b.Init(ops) + var b paint.Path + b.Begin(ops) b.Move(f32.Point{X: w, Y: h - se}) b.Cube(f32.Point{X: 0, Y: se * c}, f32.Point{X: -se + se*c, Y: se}, f32.Point{X: -se, Y: se}) // SE b.Line(f32.Point{X: sw - w + se, Y: 0}) @@ -99,35 +99,35 @@ func rrect(ops *ui.Ops, width, height, se, sw, nw, ne float32) { b.End() } -func (b *Button) Layout(c ui.Config, q input.Queue, ops *ui.Ops, cs layout.Constraints) layout.Dimensions { +func (b *Button) Layout(gtx *layout.Context, family text.Family) { b.clicked = false - for ev, ok := b.Click.Next(q); ok; ev, ok = b.Click.Next(q) { + for _, ev := range b.Click.Events(gtx) { if ev.Type == gesture.TypeClick { b.clicked = true } } - ins := layout.UniformInset(ui.Dp(1)) - cs = ins.Begin(c, ops, cs) - var dims layout.Dimensions - st := layout.Stack{} - st.Init(ops, cs) - { - cs = st.Rigid() - l := text.Label{ - Face: b.Face, - Text: b.Label, - Alignment: b.Alignment, - } - ins := layout.UniformInset(ui.Dp(4)) - //paint.ColorOp{Color: b.Color}.Add(ops) - dims = ins.End(l.Layout(ops, ins.Begin(c, ops, cs))) - pointer.RectAreaOp{image.Rect(0, 0, dims.Size.X, dims.Size.Y)}.Add(ops) - b.Click.Add(ops) - } - c2 := st.End(dims) - c1 := st.End(layoutRRect(b.Background, c, ops, st.Expand())) - dims = st.Layout(c1, c2) - return ins.End(dims) + ins := layout.UniformInset(unit.Dp(1)) + ins.Layout(gtx, func() { + st := layout.Stack{} + c2 := st.Rigid(gtx, func() { + l := text.Label{ + Size: b.Size, + Text: b.Label, + Alignment: b.Alignment, + } + ins := layout.UniformInset(unit.Dp(4)) + //paint.ColorOp{Color: b.Color}.Add(ops) + ins.Layout(gtx, func() { + l.Layout(gtx, family) + }) + pointer.RectAreaOp{image.Rect(0, 0, gtx.Dimensions.Size.X, gtx.Dimensions.Size.Y)}.Add(gtx.Ops) + b.Click.Add(gtx.Ops) + }) + c1 := st.Expand(gtx, func() { + layoutRRect(b.Background, gtx) + }) + st.Layout(gtx, c1, c2) + }) } func (b *Button) Clicked() bool { @@ -143,4 +143,3 @@ func (b *SelButton) Clicked() bool { return false } } - diff --git a/go.mod b/go.mod index ff7fe86..4a27b7a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module git.wow.st/gmp/passgo go 1.12 require ( - gioui.org/ui v0.0.0-20190918172808-816f0e901fc6 + gioui.org v0.0.0-20191008122509-6bc55d66c2fe git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5 git.wow.st/gmp/rand v0.0.0-20191001220155-a81bebfaf8b0 github.com/fsnotify/fsnotify v1.4.7 diff --git a/go.sum b/go.sum index fe1b3f2..a0c1947 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,15 @@ +gioui.org v0.0.0-20191002081212-2a1c203863c3 h1:4ROVjhDrWa/J/O4KbtbCItYHhWnFWbmTyHPrfBeeG0w= +gioui.org v0.0.0-20191002081212-2a1c203863c3/go.mod h1:+CEjc9B//HrBfWsQOVxjCyih7HGIj3Pww1xFHVDZyyk= +gioui.org v0.0.0-20191002205528-32bda106e7ff h1:pLleCPnIUzrPrjM+kad+jVhU31lzoEfINETZkLcTMRQ= +gioui.org v0.0.0-20191002205528-32bda106e7ff/go.mod h1:+CEjc9B//HrBfWsQOVxjCyih7HGIj3Pww1xFHVDZyyk= +gioui.org v0.0.0-20191002212946-96d3d74cb33a h1:+VTwpWGLLyLXICY3wn4LQlSLXpwX06PenIutOxYqe+M= +gioui.org v0.0.0-20191002212946-96d3d74cb33a/go.mod h1:+CEjc9B//HrBfWsQOVxjCyih7HGIj3Pww1xFHVDZyyk= +gioui.org v0.0.0-20191008122509-6bc55d66c2fe h1:N29sMDb1EoJNXSTxGWWb1i+3GymQXbbwLiRc7bEW450= +gioui.org v0.0.0-20191008122509-6bc55d66c2fe/go.mod h1:+CEjc9B//HrBfWsQOVxjCyih7HGIj3Pww1xFHVDZyyk= gioui.org/ui v0.0.0-20190918172808-816f0e901fc6 h1:LvHEYxyOW7g+PhOiAm8Delc3AUv9EH219oDvaUMeKBw= gioui.org/ui v0.0.0-20190918172808-816f0e901fc6/go.mod h1:PssKPKlqVIeyaed+0w492Xc2NgX5M3n6oZKOAj5rxoE= +gioui.org/ui v0.0.0-20190926171558-ce74bc0cbaea h1:rv21Wx1Inf27NY453rrrP6tuEG65PyWPhnP2Jx+Qb8k= +gioui.org/ui v0.0.0-20190926171558-ce74bc0cbaea/go.mod h1:PssKPKlqVIeyaed+0w492Xc2NgX5M3n6oZKOAj5rxoE= git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5 h1:OKeTjZST+/TKvtdA258NXJH+/gIx/xwyZxKrAezNFvk= git.wow.st/gmp/clip v0.0.0-20191001134149-1458ba6a7cf5/go.mod h1:NLdpaBoMQNFqncwP8OVRNWUDw1Kt9XWm3snfT7cXu24= git.wow.st/gmp/rand v0.0.0-20191001220006-66bfa936ad6b h1:yu3SnygEUgkNJ3xBXLkWHws7tki5qveZ6Kk7ybWj1GQ= @@ -18,6 +28,7 @@ golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a h1:gHevYm0pO4QUbwy8Dmdr01R golang.org/x/image v0.0.0-20190910094157-69e4b8554b2a/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=