From 6fc927711307d194b54a13dfa22eb4602eda2676 Mon Sep 17 00:00:00 2001 From: "5684185+vsariola@users.noreply.github.com" <5684185+vsariola@users.noreply.github.com> Date: Sat, 7 Sep 2024 21:29:37 +0300 Subject: [PATCH] fix(tracker): unit search gains focus when adding a unit on last row --- CHANGELOG.md | 2 + tracker/bool.go | 8 ++- tracker/gioui/instrument_editor.go | 85 +++++++++++++----------------- tracker/list.go | 10 ++-- tracker/string.go | 15 +++++- 5 files changed, 68 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 67e651d..bc5ff37 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). resized ([#145][i145]) ### Fixed +- When adding a unit on the last row of the unit list, the editor for entering + the type of the unit by text did gain focus. - When inputting a note to the note editor, advance the cursor by step ([#144][i144]) - When loading an instrument, make sure the total number of voices does not go diff --git a/tracker/bool.go b/tracker/bool.go index b7cb7f6..70cf5f9 100644 --- a/tracker/bool.go +++ b/tracker/bool.go @@ -125,9 +125,15 @@ func (m *UnitSearching) Bool() Bool { return Bool{m} } func (m *UnitSearching) Value() bool { return m.d.UnitSearching } func (m *UnitSearching) setValue(val bool) { m.d.UnitSearching = val - if !val { + if m.d.InstrIndex < 0 || m.d.InstrIndex >= len(m.d.Song.Patch) { m.d.UnitSearchString = "" + return } + if m.d.UnitIndex < 0 || m.d.UnitIndex >= len(m.d.Song.Patch[m.d.InstrIndex].Units) { + m.d.UnitSearchString = "" + return + } + m.d.UnitSearchString = m.d.Song.Patch[m.d.InstrIndex].Units[m.d.UnitIndex].Type } func (m *UnitSearching) Enabled() bool { return true } diff --git a/tracker/gioui/instrument_editor.go b/tracker/gioui/instrument_editor.go index 2b51abd..0fffdf0 100644 --- a/tracker/gioui/instrument_editor.go +++ b/tracker/gioui/instrument_editor.go @@ -380,7 +380,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { element := func(gtx C, i int) D { gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(unit.Dp(120)), gtx.Dp(unit.Dp(20)))) - if i < 0 || i >= count { + if i < 0 || i > 255 { return layout.Dimensions{Size: gtx.Constraints.Min} } u := units[i] @@ -412,13 +412,9 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { editor.TextSize = unit.Sp(12) editor.Font = f defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop() - txt := u.Type str := tracker.String{StringData: (*tracker.UnitSearch)(t.Model)} - if t.UnitSearching().Value() { - txt = str.Value() - } - if ie.searchEditor.Text() != txt { - ie.searchEditor.SetText(txt) + if ie.searchEditor.Text() != str.Value() { + ie.searchEditor.SetText(str.Value()) } for { ev, ok := ie.searchEditor.Update(gtx) @@ -427,18 +423,17 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { } _, ok = ev.(widget.SubmitEvent) if ok { - txt := "" ie.unitDragList.Focus() if text := ie.searchEditor.Text(); text != "" { for _, n := range sointu.UnitNames { if strings.HasPrefix(n, ie.searchEditor.Text()) { - txt = n + t.Units().SetSelectedType(n) break } } } - t.Units().SetSelectedType(txt) t.UnitSearching().Bool().Set(false) + ie.searchEditor.SetText(str.Value()) continue } } @@ -452,7 +447,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { ie.instrumentDragList.Focus() } } - if ie.searchEditor.Text() != txt { + if ie.searchEditor.Text() != str.Value() { str.Set(ie.searchEditor.Text()) } return ret @@ -472,46 +467,42 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() unitList := FilledDragList(t.Theme, ie.unitDragList, element, nil) + for { + event, ok := gtx.Event( + key.Filter{Focus: ie.unitDragList, Name: key.NameRightArrow}, + key.Filter{Focus: ie.unitDragList, Name: key.NameEnter, Optional: key.ModCtrl}, + key.Filter{Focus: ie.unitDragList, Name: key.NameReturn, Optional: key.ModCtrl}, + key.Filter{Focus: ie.unitDragList, Name: key.NameDeleteBackward}, + key.Filter{Focus: ie.unitDragList, Name: key.NameEscape}, + ) + if !ok { + break + } + switch e := event.(type) { + case key.Event: + switch e.State { + case key.Press: + switch e.Name { + case key.NameEscape: + ie.instrumentDragList.Focus() + case key.NameRightArrow: + ie.unitEditor.sliderList.Focus() + case key.NameDeleteBackward: + t.Units().SetSelectedType("") + t.UnitSearching().Bool().Set(true) + gtx.Execute(key.FocusCmd{Tag: ie.searchEditor}) + case key.NameEnter, key.NameReturn: + t.Model.AddUnit(e.Modifiers.Contain(key.ModCtrl)).Do() + t.UnitSearching().Bool().Set(true) + gtx.Execute(key.FocusCmd{Tag: ie.searchEditor}) + } + } + } + } return Surface{Gray: 30, Focus: ie.wasFocused}.Layout(gtx, func(gtx C) D { return layout.Stack{Alignment: layout.SE}.Layout(gtx, layout.Expanded(func(gtx C) D { defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop() - for { - event, ok := gtx.Event( - key.Filter{Focus: ie.unitDragList, Name: key.NameRightArrow}, - key.Filter{Focus: ie.unitDragList, Name: key.NameEnter, Optional: key.ModCtrl}, - key.Filter{Focus: ie.unitDragList, Name: key.NameReturn, Optional: key.ModCtrl}, - key.Filter{Focus: ie.unitDragList, Name: key.NameDeleteBackward}, - key.Filter{Focus: ie.unitDragList, Name: key.NameEscape}, - ) - if !ok { - break - } - - switch e := event.(type) { - case key.Event: - switch e.State { - case key.Press: - switch e.Name { - case key.NameEscape: - ie.instrumentDragList.Focus() - case key.NameRightArrow: - ie.unitEditor.sliderList.Focus() - case key.NameDeleteBackward: - t.Units().SetSelectedType("") - gtx.Execute(key.FocusCmd{Tag: ie.searchEditor}) - l := len(ie.searchEditor.Text()) - ie.searchEditor.SetCaret(l, l) - case key.NameEnter, key.NameReturn: - t.Model.AddUnit(e.Modifiers.Contain(key.ModCtrl)).Do() - ie.searchEditor.SetText("") - gtx.Execute(key.FocusCmd{Tag: ie.searchEditor}) - l := len(ie.searchEditor.Text()) - ie.searchEditor.SetCaret(l, l) - } - } - } - } gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(unit.Dp(120)), gtx.Constraints.Max.Y)) dims := unitList.Layout(gtx) unitList.LayoutScrollBar(gtx) diff --git a/tracker/list.go b/tracker/list.go index e765946..ed112ce 100644 --- a/tracker/list.go +++ b/tracker/list.go @@ -299,11 +299,15 @@ func (m *Units) SelectedType() string { func (m *Units) SetSelectedType(t string) { if m.d.InstrIndex < 0 || - m.d.InstrIndex >= len(m.d.Song.Patch) || - m.d.UnitIndex < 0 || - m.d.UnitIndex >= len(m.d.Song.Patch[m.d.InstrIndex].Units) { + m.d.InstrIndex >= len(m.d.Song.Patch) { return } + if m.d.UnitIndex < 0 { + m.d.UnitIndex = 0 + } + for len(m.d.Song.Patch[m.d.InstrIndex].Units) <= m.d.UnitIndex { + m.d.Song.Patch[m.d.InstrIndex].Units = append(m.d.Song.Patch[m.d.InstrIndex].Units, sointu.Unit{}) + } unit, ok := defaultUnits[t] if !ok { // if the type is invalid, we just set it to empty unit unit = sointu.Unit{Parameters: make(map[string]int)} diff --git a/tracker/string.go b/tracker/string.go index aceda76..55ee5f9 100644 --- a/tracker/string.go +++ b/tracker/string.go @@ -41,7 +41,20 @@ func (v *FilePath) change(kind string) func() { return func() {} } // UnitSearchString func (v *UnitSearch) String() String { return String{v} } -func (v *UnitSearch) Value() string { return v.d.UnitSearchString } +func (v *UnitSearch) Value() string { + // return current unit type string if not searching + if !v.d.UnitSearching { + if v.d.InstrIndex < 0 || v.d.InstrIndex >= len(v.d.Song.Patch) { + return "" + } + if v.d.UnitIndex < 0 || v.d.UnitIndex >= len(v.d.Song.Patch[v.d.InstrIndex].Units) { + return "" + } + return v.d.Song.Patch[v.d.InstrIndex].Units[v.d.UnitIndex].Type + } else { + return v.d.UnitSearchString + } +} func (v *UnitSearch) setValue(value string) { v.d.UnitSearchString = value v.d.UnitSearching = true