diff --git a/tracker/alert.go b/tracker/alert.go index 5986967..871e828 100644 --- a/tracker/alert.go +++ b/tracker/alert.go @@ -18,7 +18,7 @@ type ( } AlertPriority int - AlertYieldFunc func(alert Alert) + AlertYieldFunc func(index int, alert Alert) bool Alerts Model ) @@ -35,9 +35,13 @@ func (m *Model) Alerts() *Alerts { return (*Alerts)(m) } // Alerts methods -func (m *Alerts) Iterate(yield AlertYieldFunc) { - for _, a := range m.alerts { - yield(a) +func (m *Alerts) Iterate() func(yield func(index int, alert Alert) bool) { + return func(yield func(index int, alert Alert) bool) { + for i, a := range m.alerts { + if !yield(i, a) { + break + } + } } } diff --git a/tracker/gioui/instrument_editor.go b/tracker/gioui/instrument_editor.go index 1b7d67d..5128ae7 100644 --- a/tracker/gioui/instrument_editor.go +++ b/tracker/gioui/instrument_editor.go @@ -338,13 +338,13 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { addUnitBtnStyle.IconButtonStyle.Background = t.Theme.Fg addUnitBtnStyle.IconButtonStyle.Inset = layout.UniformInset(unit.Dp(4)) - index := 0 var units [256]tracker.UnitListItem - (*tracker.Units)(t.Model).Iterate(func(item tracker.UnitListItem) (ok bool) { - units[index] = item - index++ - return index <= 256 - }) + for i, item := range (*tracker.Units)(t.Model).Iterate() { + if i >= 256 { + break + } + units[i] = item + } count := intMin(ie.unitDragList.TrackerList.Count(), 256) element := func(gtx C, i int) D { diff --git a/tracker/gioui/popup_alert.go b/tracker/gioui/popup_alert.go index 6ffcfb6..c44a5db 100644 --- a/tracker/gioui/popup_alert.go +++ b/tracker/gioui/popup_alert.go @@ -36,7 +36,7 @@ func (a *PopupAlert) Layout(gtx C) D { a.prevUpdate = now var totalY float64 = float64(gtx.Dp(38)) - a.alerts.Iterate(func(alert tracker.Alert) { + for _, alert := range a.alerts.Iterate() { var color, textColor, shadeColor color.NRGBA switch alert.Priority { case tracker.Warning: @@ -76,6 +76,6 @@ func (a *PopupAlert) Layout(gtx C) D { return dims }) }) - }) + } return D{} } diff --git a/tracker/gioui/unit_editor.go b/tracker/gioui/unit_editor.go index 0c2543b..7f33a2d 100644 --- a/tracker/gioui/unit_editor.go +++ b/tracker/gioui/unit_editor.go @@ -102,11 +102,10 @@ func (pe *UnitEditor) layoutSliders(gtx C, t *Tracker) D { } index := 0 - t.Model.Params().Iterate(func(param tracker.Parameter) { + for param := range t.Model.Params().Iterate() { pe.Parameters[index].Parameter = param index++ - }) - + } element := func(gtx C, index int) D { if index < 0 || index >= numItems { return D{} @@ -177,12 +176,12 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { func (pe *UnitEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D { var names [256]string - index := 0 - t.Model.SearchResults().Iterate(func(item string) (ok bool) { - names[index] = item - index++ - return index <= 256 - }) + for i, item := range t.Model.SearchResults().Iterate() { + if i >= 256 { + break + } + names[i] = item + } element := func(gtx C, i int) D { w := LabelStyle{Text: names[i], ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Shaper} if i == pe.searchList.TrackerList.Selected() { diff --git a/tracker/list.go b/tracker/list.go index 8ba5731..c86d4df 100644 --- a/tracker/list.go +++ b/tracker/list.go @@ -38,8 +38,8 @@ type ( StackNeed, StackBefore, StackAfter int } - UnitYieldFunc func(item UnitListItem) (ok bool) - UnitSearchYieldFunc func(item string) (ok bool) + UnitYieldFunc func(index int, item UnitListItem) (ok bool) + UnitSearchYieldFunc func(index int, item string) (ok bool) Instruments Model // Instruments is a list of instruments, implementing ListData & MutableListData interfaces Units Model // Units is a list of all the units in the selected instrument, implementing ListData & MutableListData interfaces @@ -323,24 +323,26 @@ func (m *Units) SetSelectedType(t string) { m.d.Song.Patch[m.d.InstrIndex].Units[m.d.UnitIndex].ID = oldUnit.ID // keep the ID of the replaced unit } -func (v *Units) Iterate(yield UnitYieldFunc) { - if v.d.InstrIndex < 0 || v.d.InstrIndex >= len(v.d.Song.Patch) { - return - } - stackBefore := 0 - for _, unit := range v.d.Song.Patch[v.d.InstrIndex].Units { - stackAfter := stackBefore + unit.StackChange() - if !yield(UnitListItem{ - Type: unit.Type, - Comment: unit.Comment, - Disabled: unit.Disabled, - StackNeed: unit.StackNeed(), - StackBefore: stackBefore, - StackAfter: stackAfter, - }) { - break +func (v *Units) Iterate() func(yield UnitYieldFunc) { + return func(yield UnitYieldFunc) { + if v.d.InstrIndex < 0 || v.d.InstrIndex >= len(v.d.Song.Patch) { + return + } + stackBefore := 0 + for i, unit := range v.d.Song.Patch[v.d.InstrIndex].Units { + stackAfter := stackBefore + unit.StackChange() + if !yield(i, UnitListItem{ + Type: unit.Type, + Comment: unit.Comment, + Disabled: unit.Disabled, + StackNeed: unit.StackNeed(), + StackBefore: stackBefore, + StackAfter: stackAfter, + }) { + break + } + stackBefore = stackAfter } - stackBefore = stackAfter } } @@ -743,13 +745,17 @@ func (v *SearchResults) List() List { return List{v} } -func (l *SearchResults) Iterate(yield UnitSearchYieldFunc) { - for _, name := range sointu.UnitNames { - if !strings.HasPrefix(name, l.d.UnitSearchString) { - continue - } - if !yield(name) { - break +func (l *SearchResults) Iterate() func(yield UnitSearchYieldFunc) { + return func(yield UnitSearchYieldFunc) { + index := 0 + for _, name := range sointu.UnitNames { + if !strings.HasPrefix(name, l.d.UnitSearchString) { + continue + } + if !yield(index, name) { + break + } + index++ } } } diff --git a/tracker/model_test.go b/tracker/model_test.go index b77b860..36ef169 100644 --- a/tracker/model_test.go +++ b/tracker/model_test.go @@ -292,14 +292,14 @@ func FuzzModel(f *testing.F) { index-- return index > 0 }, seed) - state.model.Alerts().Iterate(func(a tracker.Alert) { + for _, a := range model.Alerts().Iterate() { if a.Name == "IDCollision" { t.Errorf("Path: %s Model has ID collisions", totalPath) } if a.Name == "InvalidUnitParameters" { t.Errorf("Path: %s Model units with invalid parameters", totalPath) } - }) + } } closeChan <- struct{}{} }) diff --git a/tracker/params.go b/tracker/params.go index 3e09f99..afbf3df 100644 --- a/tracker/params.go +++ b/tracker/params.go @@ -41,7 +41,7 @@ type ( Params Model - ParamYieldFunc func(Parameter) + ParamYieldFunc func(param Parameter) bool ParameterType int ) @@ -77,59 +77,71 @@ func (pl *Params) change(n string, severity ChangeSeverity) func() { func (pl *Params) Count() int { count := 0 - pl.Iterate(func(p Parameter) { + for range pl.Iterate() { count++ - }) + } return count } func (pl *Params) SelectedItem() (ret Parameter) { index := pl.Selected() - pl.Iterate(func(param Parameter) { + for param := range pl.Iterate() { if index == 0 { ret = param } index-- - }) + } return } -func (pl *Params) Iterate(yield ParamYieldFunc) { - if pl.d.InstrIndex < 0 || pl.d.InstrIndex >= len(pl.d.Song.Patch) { - return - } - if pl.d.UnitIndex < 0 || pl.d.UnitIndex >= len(pl.d.Song.Patch[pl.d.InstrIndex].Units) { - return - } - unit := &pl.d.Song.Patch[pl.d.InstrIndex].Units[pl.d.UnitIndex] - unitType, ok := sointu.UnitTypes[unit.Type] - if !ok { - return - } - for i := range unitType { - if !unitType[i].CanSet { - continue +func (pl *Params) Iterate() func(yield ParamYieldFunc) { + return func(yield ParamYieldFunc) { + if pl.d.InstrIndex < 0 || pl.d.InstrIndex >= len(pl.d.Song.Patch) { + return } - if unit.Type == "oscillator" && unit.Parameters["type"] != sointu.Sample && i >= 11 { - break // don't show the sample related params unless necessary + if pl.d.UnitIndex < 0 || pl.d.UnitIndex >= len(pl.d.Song.Patch[pl.d.InstrIndex].Units) { + return } - yield(NamedParameter{ - parameter: parameter{m: (*Model)(pl), unit: unit}, - up: &unitType[i], - }) - } - if unit.Type == "oscillator" && unit.Parameters["type"] == sointu.Sample { - yield(GmDlsEntryParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) - } - switch { - case unit.Type == "delay": - if unit.Parameters["stereo"] == 1 && len(unit.VarArgs)%2 == 1 { - unit.VarArgs = append(unit.VarArgs, 1) + unit := &pl.d.Song.Patch[pl.d.InstrIndex].Units[pl.d.UnitIndex] + unitType, ok := sointu.UnitTypes[unit.Type] + if !ok { + return } - yield(ReverbParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) - yield(DelayLinesParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) - for i := range unit.VarArgs { - yield(DelayTimeParameter{parameter: parameter{m: (*Model)(pl), unit: unit}, index: i}) + for i := range unitType { + if !unitType[i].CanSet { + continue + } + if unit.Type == "oscillator" && unit.Parameters["type"] != sointu.Sample && i >= 11 { + break // don't show the sample related params unless necessary + } + if !yield(NamedParameter{ + parameter: parameter{m: (*Model)(pl), unit: unit}, + up: &unitType[i], + }) { + return + } + } + if unit.Type == "oscillator" && unit.Parameters["type"] == sointu.Sample { + if !yield(GmDlsEntryParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) { + return + } + } + switch { + case unit.Type == "delay": + if unit.Parameters["stereo"] == 1 && len(unit.VarArgs)%2 == 1 { + unit.VarArgs = append(unit.VarArgs, 1) + } + if !yield(ReverbParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) { + return + } + if !yield(DelayLinesParameter{parameter: parameter{m: (*Model)(pl), unit: unit}}) { + return + } + for i := range unit.VarArgs { + if !yield(DelayTimeParameter{parameter: parameter{m: (*Model)(pl), unit: unit}, index: i}) { + return + } + } } } }