@@ 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 {