refactor(tracker/gioui): rewrote Button(s) to bind to Model during layout

The old mechanism made it difficult to follow exactly what happens
when a button was clicked, because the Action/Bool that gets
executed / toggled was declared ages ago, in the constructor. In the
new mechanism, the Action / Bool is bound to the button at the last
minute, right before Layout. ActionButton, ToggleButton,
ActionIconButton and ToggleIconButton were done to avoid heap
escapes: if the corresponding functions woudl've returned
layout.Widget, a heap allocation would've been needed.
This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-06-21 23:49:07 +03:00
parent 0ea20ea5bf
commit db2ccf977d
11 changed files with 453 additions and 411 deletions

View File

@ -17,8 +17,8 @@ import (
type (
OscilloscopeState struct {
onceBtn *BoolClickable
wrapBtn *BoolClickable
onceBtn *Clickable
wrapBtn *Clickable
lengthInBeatsNumber *NumericUpDown
triggerChannelNumber *NumericUpDown
xScale int
@ -38,20 +38,20 @@ type (
func NewOscilloscope(model *tracker.Model) *OscilloscopeState {
return &OscilloscopeState{
onceBtn: NewBoolClickable(model.SignalAnalyzer().Once()),
wrapBtn: NewBoolClickable(model.SignalAnalyzer().Wrap()),
onceBtn: new(Clickable),
wrapBtn: new(Clickable),
lengthInBeatsNumber: NewNumericUpDown(),
triggerChannelNumber: NewNumericUpDown(),
}
}
func (s *OscilloscopeState) Layout(gtx C, vtrig, vlen tracker.Int, wave tracker.RingBuffer[[2]float32], th *Theme, st *OscilloscopeStyle) D {
wrapBtnStyle := ToggleButton(gtx, th, s.wrapBtn, "Wrap")
onceBtnStyle := ToggleButton(gtx, th, s.onceBtn, "Once")
func (s *OscilloscopeState) Layout(gtx C, vtrig, vlen tracker.Int, once, wrap tracker.Bool, wave tracker.RingBuffer[[2]float32], th *Theme, st *OscilloscopeStyle) D {
leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout
rightSpacer := layout.Spacer{Width: unit.Dp(6)}.Layout
onceBtn := ToggleBtn(once, th, s.onceBtn, "Once", "Trigger once on next event")
wrapBtn := ToggleBtn(wrap, th, s.wrapBtn, "Wrap", "Wrap buffer when full")
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
layout.Flexed(1, func(gtx C) D { return s.layoutWave(gtx, wave, th) }),
layout.Rigid(func(gtx C) D {
@ -59,7 +59,7 @@ func (s *OscilloscopeState) Layout(gtx C, vtrig, vlen tracker.Int, wave tracker.
layout.Rigid(leftSpacer),
layout.Rigid(Label(th, &th.SongPanel.RowHeader, "Trigger").Layout),
layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }),
layout.Rigid(onceBtnStyle.Layout),
layout.Rigid(onceBtn.Layout),
layout.Rigid(func(gtx C) D {
return s.triggerChannelNumber.Layout(gtx, vtrig, th, &th.NumericUpDown, "Trigger channel")
}),
@ -71,7 +71,7 @@ func (s *OscilloscopeState) Layout(gtx C, vtrig, vlen tracker.Int, wave tracker.
layout.Rigid(leftSpacer),
layout.Rigid(Label(th, &th.SongPanel.RowHeader, "Buffer").Layout),
layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }),
layout.Rigid(wrapBtnStyle.Layout),
layout.Rigid(wrapBtn.Layout),
layout.Rigid(func(gtx C) D {
return s.lengthInBeatsNumber.Layout(gtx, vlen, th, &th.NumericUpDown, "Buffer length in beats")
}),