~eliasnaur/gio

layout.Format, like fmt.Printf for layouts

Details
Message ID
<BXR2KXYJKQVO.1E27NGCB50H3P@toolbox>
DKIM signature
pass
Download raw message
Hi,

I just pushed a change that implements layout.Format, which is to layout what
fmt.Printf is to strings.

The examples are converted in the `layout-format` branch:

	https://git.sr.ht/~eliasnaur/gio/tree/layout-format

Details are in the layout.Format documentation:

	$ go doc gioui.org/layout.Format

As always, layout.Format generates no garbage as long as your format
string is constant.

TODO:
- Is layout.Format a good idea?
- Can formats be extended to themes, in particular constant labels? Is
  that a good idea?

Example:

	func (u *UI) layoutUsers(gtx *layout.Context) {
		const f = `
		stack(southeast,
			r(vflex(
				r(hexp(inset(16dp,vcap(200dp,_)))),
				r(hexp(inset(0dp16dp16dp16dp,_))),
				r(stack(e(hexp(_)),
				r(inset(16dp8dp8dp8dp,hexp(_))))),
				f(1,_))),
			r(inset(16dp,_))
		)`
		layout.Format(gtx, f,
			func() {
				theme.Editor("Hint").Layout(gtx, u.edit)
			},
			func() {
				e := theme.Editor("Hint")
				e.Font.Size = unit.Sp(14)
				e.Font.Style = text.Italic
				e.Layout(gtx, u.edit2)
			},
			func() {
				fill{rgb(0xf2f2f2)}.Layout(gtx)
			},
			func() {
				lbl := theme.Caption("GOPHERS")
				lbl.Color = rgb(0x888888)
				lbl.Layout(gtx)
			},
			func() {
				u.layoutContributors(gtx)
			},
			func() {
				for u.fab.Clicked(gtx) {
				}
				theme.IconButton(u.fabIcon).Layout(gtx, u.fab)
			})
	}

which is the equivalent to

	func (u *UI) layoutUsers(gtx *layout.Context) {
		st := layout.Stack{Alignment: layout.SE}
		c1 := st.Rigid(gtx, func() {
			f := layout.Flex{Axis: layout.Vertical}

			c1 := f.Rigid(gtx, func() {
				gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
				layout.UniformInset(unit.Dp(16)).Layout(gtx, func() {
					sz := gtx.Px(unit.Dp(200))
					cs := gtx.Constraints
					gtx.Constraints = layout.RigidConstraints(cs.Constrain(image.Point{X: sz, Y: sz}))
					theme.Editor("Hint").Layout(gtx, u.edit)
				})
			})

			c2 := f.Rigid(gtx, func() {
				gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
				in := layout.Inset{Bottom: unit.Dp(16), Left: unit.Dp(16), Right: unit.Dp(16)}
				in.Layout(gtx, func() {
					e := theme.Editor("Hint")
					e.Font.Size = unit.Sp(14)
					e.Font.Style = text.Italic
					e.Layout(gtx, u.edit2)
				})
			})

			c3 := f.Rigid(gtx, func() {
				s := layout.Stack{}
				c2 := s.Rigid(gtx, func() {
					in := layout.Inset{Top: unit.Dp(16), Right: unit.Dp(8), Bottom: unit.Dp(8), Left: unit.Dp(8)}
					in.Layout(gtx, func() {
						lbl := theme.Caption("GOPHERS")
						lbl.Color = rgb(0x888888)
						lbl.Layout(gtx)
					})
				})
				c1 := s.Expand(gtx, func() {
					gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
					fill{rgb(0xf2f2f2)}.Layout(gtx)
				})
				s.Layout(gtx, c1, c2)
			})

			c4 := f.Flex(gtx, 1, func() {
				gtx.Constraints.Width.Min = gtx.Constraints.Width.Max
				u.layoutContributors(gtx)
			})
			f.Layout(gtx, c1, c2, c3, c4)
		})
		c2 := st.Rigid(gtx, func() {
			in := layout.UniformInset(unit.Dp(16))
			in.Layout(gtx, func() {
				for u.fab.Clicked(gtx) {
				}
				theme.IconButton(u.fabIcon).Layout(gtx, u.fab)
			})
		})

		st.Layout(gtx, c1, c2)
	}

-- elias