From 76579da69444a4df31344e9e5897df933b213255 Mon Sep 17 00:00:00 2001 From: Elias Naur Date: Sat, 23 May 2020 22:58:38 +0200 Subject: [PATCH] cmd/scatter: bump gio version Signed-off-by: Elias Naur --- cmd/scatter/ui.go | 407 +++++++++++++++++++++++----------------------- go.mod | 2 +- go.sum | 4 +- 3 files changed, 205 insertions(+), 208 deletions(-) diff --git a/cmd/scatter/ui.go b/cmd/scatter/ui.go index ce8f414..a93d548 100644 --- a/cmd/scatter/ui.go +++ b/cmd/scatter/ui.go @@ -68,8 +68,8 @@ type pageStack struct { type Page interface { Start(stop <-chan struct{}) - Event(gtx *layout.Context) interface{} - Layout(gtx *layout.Context) + Event(gtx layout.Context) interface{} + Layout(gtx layout.Context) layout.Dimensions } type signInPage struct { @@ -77,7 +77,7 @@ type signInPage struct { account *Account list *layout.List fields []*formField - submit *widget.Button + submit *widget.Clickable } type Topbar struct { @@ -98,7 +98,7 @@ type threadsPage struct { env *Env account *Account - fab *widget.Button + fab *widget.Clickable fabIcon *widget.Icon updates <-chan struct{} @@ -118,9 +118,9 @@ type threadPage struct { messages []*Message result chan []*Message msgEdit *widget.Editor - send *widget.Button - invite *widget.Button - accept *widget.Button + send *widget.Clickable + invite *widget.Clickable + accept *widget.Clickable topbar *Topbar updates <-chan struct{} } @@ -171,6 +171,11 @@ var iconLib struct { send *widget.Icon } +type ( + C = layout.Context + D = layout.Dimensions +) + func uiMain() { gofont.Register() theme = material.NewTheme() @@ -199,7 +204,7 @@ func mustIcon(data []byte) *widget.Icon { func (a *App) run() error { var updates <-chan struct{} - gtx := layout.NewContext(a.w.Queue()) + var ops op.Ops for { select { case <-updates: @@ -246,7 +251,7 @@ func (a *App) run() error { } } case system.FrameEvent: - gtx.Reset(e.Config, e.Size) + gtx := layout.NewContext(&ops, e.Queue, e.Config, e.Size) a.env.insets = layout.Inset{ Top: e.Insets.Top, Left: e.Insets.Left, @@ -275,13 +280,14 @@ func (t *Transition) Start(stop <-chan struct{}) { t.page.Start(stop) } -func (t *Transition) Event(gtx *layout.Context) interface{} { +func (t *Transition) Event(gtx layout.Context) interface{} { return t.page.Event(gtx) } -func (t *Transition) Layout(gtx *layout.Context) { +func (t *Transition) Layout(gtx layout.Context) layout.Dimensions { var stack op.StackOp stack.Push(gtx.Ops) + defer stack.Pop() prev, page := t.prev, t.page if prev != nil { if t.reverse { @@ -293,7 +299,7 @@ func (t *Transition) Layout(gtx *layout.Context) { } prev.Layout(gtx) cs := gtx.Constraints - size := f32.Point{X: float32(cs.Width.Max), Y: float32(cs.Height.Max)} + size := layout.FPt(cs.Max) max := float32(math.Sqrt(float64(size.X*size.X + size.Y*size.Y))) progress := float32(now.Sub(t.time).Seconds()) * 3 progress = progress * progress // Accelerate @@ -318,8 +324,7 @@ func (t *Transition) Layout(gtx *layout.Context) { off.Invert().Add(gtx.Ops) fill{rgb(0xffffff)}.Layout(gtx) } - page.Layout(gtx) - stack.Pop() + return page.Layout(gtx) } func (s *pageStack) Len() int { @@ -403,31 +408,31 @@ func argb(c uint32) color.RGBA { return color.RGBA{A: uint8(c >> 24), R: uint8(c >> 16), G: uint8(c >> 8), B: uint8(c)} } -func (a *App) Layout(gtx *layout.Context) { +func (a *App) Layout(gtx layout.Context) { a.update(gtx) a.stack.Current().Layout(gtx) } -func (a *App) layoutTimings(gtx *layout.Context) { +func (a *App) layoutTimings(gtx layout.Context) layout.Dimensions { for _, e := range gtx.Events(a) { if e, ok := e.(profile.Event); ok { a.profile = e } } - profile.Op{Key: a}.Add(gtx.Ops) + profile.Op{Tag: a}.Add(gtx.Ops) var mstats runtime.MemStats runtime.ReadMemStats(&mstats) mallocs := mstats.Mallocs - a.lastMallocs a.lastMallocs = mstats.Mallocs - layout.NE.Layout(gtx, func() { + return layout.NE.Layout(gtx, func(gtx C) D { in := a.env.insets in.Top = unit.Max(gtx, unit.Dp(16), in.Top) - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { txt := fmt.Sprintf("m: %d %s", mallocs, a.profile.Timings) lbl := material.Caption(theme, txt) lbl.Font.Variant = "Mono" - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }) } @@ -452,7 +457,7 @@ func newContactsPage(env *Env) *contactsPage { func (p *contactsPage) Start(stop <-chan struct{}) {} -func (p *contactsPage) Event(gtx *layout.Context) interface{} { +func (p *contactsPage) Event(gtx layout.Context) interface{} { for _, e := range p.searchEdit.Events(gtx) { switch e := e.(type) { case widget.ChangeEvent: @@ -503,33 +508,33 @@ func (p *contactsPage) queryContacts(q string) { }() } -func (p *contactsPage) Layout(gtx *layout.Context) { +func (p *contactsPage) Layout(gtx layout.Context) layout.Dimensions { for e := p.Event(gtx); e != nil; e = p.Event(gtx) { } l := p.list if l.Dragging() { key.HideInputOp{}.Add(gtx.Ops) } - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { - p.topbar.Layout(gtx, p.env.insets, func() { - e := material.Editor(theme, "Email address") + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return p.topbar.Layout(gtx, p.env.insets, func(gtx C) D { + e := material.Editor(theme, p.searchEdit, "Email address") e.TextSize = unit.Sp(20) e.Color = rgb(0xffffff) e.HintColor = rgb(0xbbbbbb) - e.Layout(gtx, p.searchEdit) + return e.Layout(gtx) }) }), - layout.Flexed(1, func() { - gtx.Constraints.Height.Min = gtx.Constraints.Height.Max - l.Layout(gtx, len(p.contacts), func(i int) { - p.contact(gtx, i) + layout.Flexed(1, func(gtx C) D { + gtx.Constraints.Min.Y = gtx.Constraints.Max.Y + return l.Layout(gtx, len(p.contacts), func(gtx C, i int) D { + return p.contact(gtx, i) }) }), ) } -func (p *contactsPage) contact(gtx *layout.Context, index int) { +func (p *contactsPage) contact(gtx layout.Context, index int) layout.Dimensions { in := layout.Inset{ Top: unit.Dp(16), Bottom: unit.Dp(16), @@ -538,29 +543,28 @@ func (p *contactsPage) contact(gtx *layout.Context, index int) { } contact := p.contacts[index] click := &p.clicks[index] - in.Layout(gtx, func() { - layout.Flex{Alignment: layout.Middle}.Layout(gtx, - layout.Rigid(func() { + dims := in.Layout(gtx, func(gtx C) D { + return layout.Flex{Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(func(gtx C) D { in := layout.Inset{Right: unit.Dp(8)} - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { cc := clipCircle{} - cc.Layout(gtx, func() { + return cc.Layout(gtx, func(gtx C) D { sz := image.Point{X: gtx.Px(unit.Dp(48)), Y: gtx.Px(unit.Dp(48))} - gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(sz)) - fill{theme.Color.Primary}.Layout(gtx) + gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(sz)) + return fill{theme.Color.Primary}.Layout(gtx) }) }) }), - layout.Flexed(1, func() { - material.H6(theme, contact.Address).Layout(gtx) - }), + layout.Flexed(1, material.H6(theme, contact.Address).Layout), ) }) - pointer.Rect(image.Rectangle{Max: gtx.Dimensions.Size}).Add(gtx.Ops) + pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops) click.Add(gtx.Ops) + return dims } -func (t *Topbar) Event(gtx *layout.Context) interface{} { +func (t *Topbar) Event(gtx layout.Context) interface{} { for _, e := range t.backClick.Events(gtx) { if e.Type == gesture.TypeClick { return BackEvent{} @@ -569,30 +573,30 @@ func (t *Topbar) Event(gtx *layout.Context) interface{} { return nil } -func (t *Topbar) Layout(gtx *layout.Context, insets layout.Inset, w layout.Widget) { +func (t *Topbar) Layout(gtx layout.Context, insets layout.Inset, w layout.Widget) layout.Dimensions { insets = layout.Inset{ Top: unit.Add(gtx, insets.Top, unit.Dp(16)), Bottom: unit.Dp(16), Left: unit.Max(gtx, insets.Left, unit.Dp(16)), Right: unit.Max(gtx, insets.Right, unit.Dp(16)), } - layout.Stack{Alignment: layout.SW}.Layout(gtx, - layout.Expanded(func() { - fill{theme.Color.Primary}.Layout(gtx) - }), - layout.Stacked(func() { - insets.Layout(gtx, func() { - layout.Flex{Alignment: layout.Middle}.Layout(gtx, - layout.Rigid(func() { - if t.Back { - ico := (&icon{src: icons.NavigationArrowBack, size: unit.Dp(24)}).image(gtx, rgb(0xffffff)) - ico.Add(gtx.Ops) - paint.PaintOp{Rect: f32.Rectangle{Max: toPointF(ico.Size())}}.Add(gtx.Ops) - gtx.Dimensions.Size = ico.Size() - gtx.Dimensions.Size.X += gtx.Px(unit.Dp(4)) - pointer.Rect(image.Rectangle{Max: gtx.Dimensions.Size}).Add(gtx.Ops) - t.backClick.Add(gtx.Ops) + return layout.Stack{Alignment: layout.SW}.Layout(gtx, + layout.Expanded(fill{theme.Color.Primary}.Layout), + layout.Stacked(func(gtx C) D { + return insets.Layout(gtx, func(gtx C) D { + return layout.Flex{Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(func(gtx C) D { + if !t.Back { + return layout.Dimensions{} } + ico := (&icon{src: icons.NavigationArrowBack, size: unit.Dp(24)}).image(gtx, rgb(0xffffff)) + ico.Add(gtx.Ops) + paint.PaintOp{Rect: f32.Rectangle{Max: toPointF(ico.Size())}}.Add(gtx.Ops) + dims := layout.Dimensions{Size: ico.Size()} + dims.Size.X += gtx.Px(unit.Dp(4)) + pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops) + t.backClick.Add(gtx.Ops) + return dims }), layout.Flexed(1, w), ) @@ -619,7 +623,7 @@ func newSignInPage(env *Env) *signInPage { {Header: "IMAP host", Hint: "host:port", Value: &acc.IMAPHost}, {Header: "SMTP host", Hint: "host:port", Value: &acc.SMTPHost}, }, - submit: &widget.Button{}, + submit: &widget.Clickable{}, } for _, f := range p.fields { f.env = p.env @@ -634,7 +638,7 @@ func newSignInPage(env *Env) *signInPage { func (p *signInPage) Start(stop <-chan struct{}) { } -func (p *signInPage) Event(gtx *layout.Context) interface{} { +func (p *signInPage) Event(gtx layout.Context) interface{} { if p.submit.Clicked(gtx) { for _, f := range p.fields { *f.Value = f.edit.Text() @@ -644,29 +648,27 @@ func (p *signInPage) Event(gtx *layout.Context) interface{} { return nil } -func (p *signInPage) Layout(gtx *layout.Context) { - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { +func (p *signInPage) Layout(gtx layout.Context) layout.Dimensions { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { var t Topbar - t.Layout(gtx, p.env.insets, func() { + return t.Layout(gtx, p.env.insets, func(gtx C) D { lbl := material.H6(theme, "Sign in") lbl.Color = rgb(0xffffff) - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }), - layout.Flexed(1, func() { - p.layoutSigninForm(gtx) - }), + layout.Flexed(1, p.layoutSigninForm), ) } -func (p *signInPage) layoutSigninForm(gtx *layout.Context) { +func (p *signInPage) layoutSigninForm(gtx layout.Context) layout.Dimensions { l := p.list inset := layout.Inset{ Left: unit.Max(gtx, unit.Dp(32), p.env.insets.Left), Right: unit.Max(gtx, unit.Dp(32), p.env.insets.Right), } - l.Layout(gtx, len(p.fields)+1, func(i int) { + return l.Layout(gtx, len(p.fields)+1, func(gtx C, i int) D { in := inset switch { case i < len(p.fields): @@ -674,32 +676,27 @@ func (p *signInPage) layoutSigninForm(gtx *layout.Context) { if i == 0 { in.Top = unit.Dp(32) } - in.Layout(gtx, func() { - p.fields[i].Layout(gtx) - }) + return in.Layout(gtx, p.fields[i].Layout) default: in.Bottom = unit.Max(gtx, unit.Dp(32), p.env.insets.Bottom) - layout.E.Layout(gtx, func() { - in.Layout(gtx, func() { - material.Button(theme, "Sign in").Layout(gtx, p.submit) - }) + return layout.E.Layout(gtx, func(gtx C) D { + return in.Layout(gtx, material.Button(theme, p.submit, "Sign in").Layout) }) } }) } -func (f *formField) Layout(gtx *layout.Context) { - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max +func (f *formField) Layout(gtx layout.Context) layout.Dimensions { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X header := material.Caption(theme, f.Header) header.Font.Weight = text.Bold - header.Layout(gtx) - gtx.Dimensions.Size.Y += gtx.Px(unit.Dp(4)) - }), - layout.Rigid(func() { - material.Editor(theme, f.Hint).Layout(gtx, f.edit) + dims := header.Layout(gtx) + dims.Size.Y += gtx.Px(unit.Dp(4)) + return dims }), + layout.Rigid(material.Editor(theme, f.edit, f.Hint).Layout), ) } @@ -709,14 +706,14 @@ type Background struct { Inset layout.Inset } -func (b *Background) Layout(gtx *layout.Context, w layout.Widget) { +func (b *Background) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { var macro op.MacroOp macro.Record(gtx.Ops) - b.Inset.Layout(gtx, w) + dims := b.Inset.Layout(gtx, w) macro.Stop() var stack op.StackOp stack.Push(gtx.Ops) - size := gtx.Dimensions.Size + size := dims.Size width, height := float32(size.X), float32(size.Y) if r := float32(gtx.Px(b.Radius)); r > 0 { if r > width/2 { @@ -735,6 +732,7 @@ func (b *Background) Layout(gtx *layout.Context, w layout.Widget) { paint.PaintOp{Rect: f32.Rectangle{Max: f32.Point{X: width, Y: height}}}.Add(gtx.Ops) macro.Add() stack.Pop() + return dims } func newThreadsPage(env *Env) *threadsPage { @@ -743,7 +741,7 @@ func newThreadsPage(env *Env) *threadsPage { list: &layout.List{ Axis: layout.Vertical, }, - fab: new(widget.Button), + fab: new(widget.Clickable), } } @@ -757,7 +755,7 @@ func (p *threadsPage) Start(stop <-chan struct{}) { }() } -func (p *threadsPage) Event(gtx *layout.Context) interface{} { +func (p *threadsPage) Event(gtx layout.Context) interface{} { select { case <-p.updates: p.fetchThreads() @@ -795,43 +793,41 @@ func (p *threadsPage) fetchThreads() { }() } -func (p *threadsPage) Layout(gtx *layout.Context) { - layout.Stack{Alignment: layout.SE}.Layout(gtx, - layout.Stacked(func() { - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { +func (p *threadsPage) Layout(gtx layout.Context) layout.Dimensions { + return layout.Stack{Alignment: layout.SE}.Layout(gtx, + layout.Stacked(func(gtx C) D { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { var t Topbar - t.Layout(gtx, p.env.insets, func() { + return t.Layout(gtx, p.env.insets, func(gtx C) D { lbl := material.H6(theme, p.account.User) lbl.Color = rgb(0xffffff) - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }), - layout.Flexed(1, func() { - p.layoutThreads(gtx) - }), + layout.Flexed(1, p.layoutThreads), ) }), - layout.Stacked(func() { - layout.SE.Layout(gtx, func() { - layout.Inset{ + layout.Stacked(func(gtx C) D { + return layout.SE.Layout(gtx, func(gtx C) D { + return layout.Inset{ Right: unit.Max(gtx, unit.Dp(16), p.env.insets.Right), Bottom: unit.Max(gtx, unit.Dp(16), p.env.insets.Bottom), - }.Layout(gtx, func() { - material.IconButton(theme, iconLib.create).Layout(gtx, p.fab) - }) + }.Layout(gtx, + material.IconButton(theme, p.fab, iconLib.create).Layout, + ) }) }), ) } -func (p *threadsPage) layoutThreads(gtx *layout.Context) { +func (p *threadsPage) layoutThreads(gtx layout.Context) layout.Dimensions { l := p.list if l.Dragging() { key.HideInputOp{}.Add(gtx.Ops) } - l.Layout(gtx, len(p.threads), func(i int) { + return l.Layout(gtx, len(p.threads), func(gtx C, i int) D { in := layout.Inset{} switch i { case 0: @@ -839,8 +835,8 @@ func (p *threadsPage) layoutThreads(gtx *layout.Context) { case len(p.threads) - 1: in.Bottom = unit.Max(gtx, unit.Dp(4), p.env.insets.Bottom) } - in.Layout(gtx, func() { - p.thread(gtx, i) + return in.Layout(gtx, func(gtx C) D { + return p.thread(gtx, i) }) }) } @@ -854,7 +850,7 @@ var contactColors = []color.RGBA{ {A: 0xff, R: 0x00, G: 0x89, B: 0x7b}, } -func (p *threadsPage) thread(gtx *layout.Context, index int) { +func (p *threadsPage) thread(gtx layout.Context, index int) layout.Dimensions { t := p.threads[index] bgtexcol := rgb(0xbbbbbb) fontWeight := text.Normal @@ -867,25 +863,25 @@ func (p *threadsPage) thread(gtx *layout.Context, index int) { Left: unit.Max(gtx, unit.Dp(16), p.env.insets.Left), Right: unit.Max(gtx, unit.Dp(16), p.env.insets.Right), } - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { in := layout.Inset{Top: unit.Dp(8), Bottom: unit.Dp(8)} - in.Layout(gtx, func() { - centerRowOpts().Layout(gtx, - layout.Rigid(func() { + dims := in.Layout(gtx, func(gtx C) D { + return centerRowOpts().Layout(gtx, + layout.Rigid(func(gtx C) D { in := layout.Inset{Right: unit.Dp(12)} cc := clipCircle{} - in.Layout(gtx, func() { - cc.Layout(gtx, func() { - layout.Stack{Alignment: layout.Center}.Layout(gtx, + return in.Layout(gtx, func(gtx C) D { + return cc.Layout(gtx, func(gtx C) D { + return layout.Stack{Alignment: layout.Center}.Layout(gtx, // Background color - layout.Stacked(func() { + layout.Stacked(func(gtx C) D { sz := image.Point{X: gtx.Px(unit.Dp(48)), Y: gtx.Px(unit.Dp(48))} - gtx.Constraints = layout.RigidConstraints(gtx.Constraints.Constrain(sz)) + gtx.Constraints = layout.Exact(gtx.Constraints.Constrain(sz)) color := contactColors[index%len(contactColors)] - fill{color}.Layout(gtx) + return fill{color}.Layout(gtx) }), // Contact initial. - layout.Stacked(func() { + layout.Stacked(func(gtx C) D { initial := "" for _, c := range t.ID { initial = string(unicode.ToUpper(c)) @@ -893,50 +889,51 @@ func (p *threadsPage) thread(gtx *layout.Context, index int) { } lbl := material.H5(theme, initial) lbl.Color = rgb(0xffffff) - lbl.Layout(gtx) + return lbl.Layout(gtx) }), ) }) }) }), - layout.Rigid(func() { - column().Layout(gtx, - layout.Rigid(func() { - baseline().Layout(gtx, - layout.Rigid(func() { + layout.Rigid(func(gtx C) D { + return column().Layout(gtx, + layout.Rigid(func(gtx C) D { + return baseline().Layout(gtx, + layout.Rigid(func(gtx C) D { lbl := material.H6(theme, t.ID) lbl.Font.Weight = fontWeight - lbl.Layout(gtx) + return lbl.Layout(gtx) }), - layout.Flexed(1, func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max + layout.Flexed(1, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X in := layout.Inset{Left: unit.Dp(2)} - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { lbl := material.Caption(theme, formatTime(t.Updated)) lbl.Color = bgtexcol lbl.Alignment = text.End lbl.Font.Weight = fontWeight - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }), ) }), - layout.Rigid(func() { + layout.Rigid(func(gtx C) D { in := layout.Inset{Top: unit.Dp(6)} - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { lbl := material.Body2(theme, t.Snippet) lbl.Color = bgtexcol lbl.Font.Weight = fontWeight lbl.MaxLines = 1 - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }), ) }), ) }) - pointer.Rect(image.Rectangle{Max: gtx.Dimensions.Size}).Add(gtx.Ops) + pointer.Rect(image.Rectangle{Max: dims.Size}).Add(gtx.Ops) click.Add(gtx.Ops) + return dims }) } @@ -954,9 +951,9 @@ func newThreadPage(env *Env, threadID string) *threadPage { msgEdit: &widget.Editor{ Submit: true, }, - send: new(widget.Button), - invite: new(widget.Button), - accept: new(widget.Button), + send: new(widget.Clickable), + invite: new(widget.Clickable), + accept: new(widget.Clickable), topbar: &Topbar{ Back: true, }, @@ -973,7 +970,7 @@ func (p *threadPage) Start(stop <-chan struct{}) { }() } -func (p *threadPage) Event(gtx *layout.Context) interface{} { +func (p *threadPage) Event(gtx layout.Context) interface{} { select { case <-p.updates: p.fetchMessages() @@ -1009,7 +1006,7 @@ func (p *threadPage) sendMessage() { } } -func (p *threadPage) Layout(gtx *layout.Context) { +func (p *threadPage) Layout(gtx layout.Context) layout.Dimensions { l := p.list if l.Dragging() { key.HideInputOp{}.Add(gtx.Ops) @@ -1018,83 +1015,82 @@ func (p *threadPage) Layout(gtx *layout.Context) { case p.messages = <-p.result: default: } - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { - p.topbar.Layout(gtx, p.env.insets, func() { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { + return p.topbar.Layout(gtx, p.env.insets, func(gtx C) D { lbl := material.H6(theme, p.thread.ID) lbl.Color = rgb(0xffffff) - lbl.Layout(gtx) + return lbl.Layout(gtx) }) }), - layout.Flexed(1, func() { - gtx.Constraints.Height.Min = gtx.Constraints.Height.Max - l.Layout(gtx, len(p.messages), func(i int) { - p.message(gtx, i) + layout.Flexed(1, func(gtx C) D { + gtx.Constraints.Min.Y = gtx.Constraints.Max.Y + return l.Layout(gtx, len(p.messages), func(gtx C, i int) D { + return p.message(gtx, i) }) }), - layout.Rigid(func() { - in := layout.Inset{ + layout.Rigid(func(gtx C) D { + return layout.Inset{ Top: unit.Dp(16), Left: unit.Max(gtx, unit.Dp(16), p.env.insets.Left), Right: unit.Max(gtx, unit.Dp(16), p.env.insets.Right), Bottom: unit.Max(gtx, unit.Dp(16), p.env.insets.Bottom), - } - in.Layout(gtx, func() { + }.Layout(gtx, func(gtx C) D { switch { case p.thread.PendingInvitation: - material.Button(theme, "Accept invitation").Layout(gtx, p.accept) + return material.Button(theme, p.accept, "Accept invitation").Layout(gtx) case p.env.client.ContainsSession(p.thread.ID): - p.layoutMessageBox(gtx) + return p.layoutMessageBox(gtx) default: - material.Button(theme, "Send invitation").Layout(gtx, p.invite) + return material.Button(theme, p.invite, "Send invitation").Layout(gtx) } }) }), ) } -func (p *threadPage) layoutMessageBox(gtx *layout.Context) { - if mh := gtx.Px(unit.Dp(100)); gtx.Constraints.Height.Max > mh { - gtx.Constraints.Height.Max = mh +func (p *threadPage) layoutMessageBox(gtx layout.Context) layout.Dimensions { + if mh := gtx.Px(unit.Dp(100)); gtx.Constraints.Max.Y > mh { + gtx.Constraints.Max.Y = mh } var sendHeight int - layout.Flex{Alignment: layout.End}.Layout(gtx, - layout.Flexed(1, func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max - if gtx.Constraints.Height.Min < sendHeight { - gtx.Constraints.Height.Min = sendHeight + return layout.Flex{Alignment: layout.End}.Layout(gtx, + layout.Flexed(1, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + if gtx.Constraints.Min.Y < sendHeight { + gtx.Constraints.Min.Y = sendHeight } bg := Background{ Color: rgb(0xeeeeee), Inset: layout.Inset{Left: unit.Dp(8), Right: unit.Dp(8)}, Radius: unit.Dp(10), } - bg.Layout(gtx, func() { - layout.W.Layout(gtx, func() { - gtx.Constraints.Width.Min = gtx.Constraints.Width.Max - ed := material.Editor(theme, "Send a message") + return bg.Layout(gtx, func(gtx C) D { + return layout.W.Layout(gtx, func(gtx C) D { + gtx.Constraints.Min.X = gtx.Constraints.Max.X + ed := material.Editor(theme, p.msgEdit, "Send a message") ed.TextSize = unit.Sp(14) - ed.Layout(gtx, p.msgEdit) + return ed.Layout(gtx) }) }) }), - layout.Rigid(func() { - in := layout.Inset{Left: unit.Dp(8)} - in.Layout(gtx, func() { - btn := material.IconButton(theme, iconLib.send) + layout.Rigid(func(gtx C) D { + return layout.Inset{Left: unit.Dp(8)}.Layout(gtx, func(gtx C) D { + btn := material.IconButton(theme, p.send, iconLib.send) btn.Size = unit.Dp(48) - btn.Padding = unit.Dp(12) - btn.Layout(gtx, p.send) - sendHeight = gtx.Dimensions.Size.Y + btn.Inset = layout.UniformInset(unit.Dp(12)) + dims := btn.Layout(gtx) + sendHeight = dims.Size.Y + return dims }) }), ) } -func (p *threadPage) message(gtx *layout.Context, index int) { +func (p *threadPage) message(gtx layout.Context, index int) layout.Dimensions { msg := p.messages[index] in := layout.Inset{Top: unit.Dp(16), Left: unit.Dp(16), Right: unit.Dp(40)} align := layout.W @@ -1110,53 +1106,54 @@ func (p *threadPage) message(gtx *layout.Context, index int) { } in.Left = unit.Max(gtx, in.Left, p.env.insets.Left) in.Right = unit.Max(gtx, in.Right, p.env.insets.Right) - in.Layout(gtx, func() { - align.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { + return align.Layout(gtx, func(gtx C) D { bg := Background{ Color: bgcol, Inset: layout.Inset{Top: unit.Dp(8), Bottom: unit.Dp(8), Left: unit.Dp(12), Right: unit.Dp(12)}, Radius: unit.Dp(10), } - bg.Layout(gtx, func() { + return bg.Layout(gtx, func(gtx C) D { var msgWidth int - layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(func() { + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(func(gtx C) D { lbl := material.Body2(theme, msg.Message) lbl.Color = msgCol - lbl.Layout(gtx) - gtx.Dimensions.Size.Y += gtx.Px(unit.Dp(4)) - msgWidth = gtx.Dimensions.Size.X + dims := lbl.Layout(gtx) + dims.Size.Y += gtx.Px(unit.Dp(4)) + msgWidth = dims.Size.X + return dims }), - layout.Rigid(func() { - gtx.Constraints.Width.Min = msgWidth + layout.Rigid(func(gtx C) D { + gtx.Constraints.Min.X = msgWidth f := layout.Flex{Axis: layout.Horizontal, Spacing: layout.SpaceBetween, Alignment: layout.Middle} var children []layout.FlexChild - child := layout.Rigid(func() { + child := layout.Rigid(func(gtx C) D { time := formatTime(msg.Time) lbl := material.Caption(theme, time) lbl.Color = timecol - lbl.Layout(gtx) + return lbl.Layout(gtx) }) children = append(children, child) if msg.Own { - child := layout.Rigid(func() { + child := layout.Rigid(func(gtx C) D { in := layout.Inset{Left: unit.Dp(12)} - in.Layout(gtx, func() { + return in.Layout(gtx, func(gtx C) D { checkmark := p.checkmark.image(gtx, timecol) sz := checkmark.Size() if msg.Sent { checkmark.Add(gtx.Ops) paint.PaintOp{Rect: f32.Rectangle{Max: toPointF(sz)}}.Add(gtx.Ops) } - gtx.Dimensions = layout.Dimensions{Size: sz} + return layout.Dimensions{Size: sz} }) }) children = append(children, child) } - f.Layout(gtx, children...) + return f.Layout(gtx, children...) }), ) }) @@ -1193,7 +1190,7 @@ func formatTime(t time.Time) string { return t.Format(format) } -func (a *App) update(gtx *layout.Context) { +func (a *App) update(gtx layout.Context) { page := a.stack.Current() if e := page.Event(gtx); e != nil { switch e := e.(type) { @@ -1216,15 +1213,15 @@ type fill struct { color color.RGBA } -func (f fill) Layout(gtx *layout.Context) { +func (f fill) Layout(gtx layout.Context) layout.Dimensions { cs := gtx.Constraints - d := image.Point{X: cs.Width.Min, Y: cs.Height.Min} + d := cs.Min dr := f32.Rectangle{ Max: f32.Point{X: float32(d.X), Y: float32(d.Y)}, } paint.ColorOp{Color: f.color}.Add(gtx.Ops) paint.PaintOp{Rect: dr}.Add(gtx.Ops) - gtx.Dimensions = layout.Dimensions{Size: d, Baseline: d.Y} + return layout.Dimensions{Size: d, Baseline: d.Y} } func column() layout.Flex { @@ -1242,11 +1239,10 @@ func baseline() layout.Flex { type clipCircle struct { } -func (cc *clipCircle) Layout(gtx *layout.Context, w layout.Widget) { +func (cc *clipCircle) Layout(gtx layout.Context, w layout.Widget) layout.Dimensions { var macro op.MacroOp macro.Record(gtx.Ops) - w() - dims := gtx.Dimensions + dims := w(gtx) macro.Stop() max := dims.Size.X if dy := dims.Size.Y; dy > max { @@ -1262,6 +1258,7 @@ func (cc *clipCircle) Layout(gtx *layout.Context, w layout.Widget) { }.Op(gtx.Ops).Add(gtx.Ops) macro.Add() stack.Pop() + return dims } func toPointF(p image.Point) f32.Point { diff --git a/go.mod b/go.mod index 10ff550..85bae56 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module scatter.im go 1.13 require ( - gioui.org v0.0.0-20200503110655-d474b5b16a81 + gioui.org v0.0.0-20200523202849-2451750782b8 github.com/eliasnaur/libsignal-protocol-go v0.0.0-20190626062856-3295f72b181e github.com/emersion/go-imap v1.0.0-rc.1 github.com/emersion/go-imap-idle v0.0.0-20190519112320-2704abd7050e diff --git a/go.sum b/go.sum index f88f577..d2f1a47 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -gioui.org v0.0.0-20200503110655-d474b5b16a81 h1:7v3dtTlRk2A7j/iZnuVU8vyTpox1Ddtintk+C/cOW1w= -gioui.org v0.0.0-20200503110655-d474b5b16a81/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= +gioui.org v0.0.0-20200523202849-2451750782b8 h1:TB+F3jDAVjNemdtgc8yfvsPy1xWkyn7JLOsm5r+YUuQ= +gioui.org v0.0.0-20200523202849-2451750782b8/go.mod h1:AHI9rFr6AEEHCb8EPVtb/p5M+NMJRKH58IOp8O3Je04= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/RadicalApp/complete v0.0.0-20170329192659-17e6c0ee499b h1:cAULFohNVfNzco0flF4okSPg3s7/tCj+hMIldtYZo4c= github.com/RadicalApp/complete v0.0.0-20170329192659-17e6c0ee499b/go.mod h1:zZ3+l0EkpT2ZPnoamPBG50PBUtQrXwwyJ6elQZMmqgk= -- 2.45.2