This commit is contained in:
5684185+vsariola@users.noreply.github.com
2025-07-07 13:58:02 +03:00
parent 5a11b290a2
commit 0d21afa2c1
7 changed files with 92 additions and 40 deletions

View File

@ -332,22 +332,22 @@ func (m *Redo) Do() {
// AddSemiTone
func (m *Model) AddSemitone() Action { return MakeEnabledAction((*AddSemitone)(m)) }
func (m *AddSemitone) Do() { Table{(*Notes)(m)}.Add(1) }
func (m *AddSemitone) Do() { Table{(*Notes)(m)}.Add(1, false) }
// SubtractSemitone
func (m *Model) SubtractSemitone() Action { return MakeEnabledAction((*SubtractSemitone)(m)) }
func (m *SubtractSemitone) Do() { Table{(*Notes)(m)}.Add(-1) }
func (m *SubtractSemitone) Do() { Table{(*Notes)(m)}.Add(-1, false) }
// AddOctave
func (m *Model) AddOctave() Action { return MakeEnabledAction((*AddOctave)(m)) }
func (m *AddOctave) Do() { Table{(*Notes)(m)}.Add(12) }
func (m *AddOctave) Do() { Table{(*Notes)(m)}.Add(1, true) }
// SubtractOctave
func (m *Model) SubtractOctave() Action { return MakeEnabledAction((*SubtractOctave)(m)) }
func (m *SubtractOctave) Do() { Table{(*Notes)(m)}.Add(-12) }
func (m *SubtractOctave) Do() { Table{(*Notes)(m)}.Add(-1, true) }
// EditNoteOff

View File

@ -93,3 +93,6 @@
- { key: "P", action: "Note28" }
- { key: "+", action: "Increase" }
- { key: "-", action: "Decrease" }
- { key: "+", shortcut: true, action: "IncreaseMore" } # increase a large step
- { key: "-", shortcut: true, action: "DecreaseMore" } # decrease a large step

View File

@ -62,7 +62,7 @@ func NewScrollTable(table tracker.Table, vertList, horizList tracker.List) *Scro
}
for k, a := range keyBindingMap {
switch a {
case "Copy", "Paste", "Cut", "Increase", "Decrease":
case "Copy", "Paste", "Cut", "Increase", "Decrease", "IncreaseMore", "DecreaseMore":
ret.eventFilters = append(ret.eventFilters, key.Filter{Focus: ret, Name: k.Name, Required: k.Modifiers})
}
}
@ -305,11 +305,11 @@ func (s *ScrollTable) command(gtx C, e key.Event, p image.Point) {
case "Paste":
gtx.Execute(clipboard.ReadCmd{Tag: s})
return
case "Increase":
s.Table.Add(1)
case "Increase", "IncreaseMore":
s.Table.Add(1, a == "IncreaseMore")
return
case "Decrease":
s.Table.Add(-1)
case "Decrease", "DecreaseMore":
s.Table.Add(-1, a == "DecreaseMore")
return
}
}

View File

@ -93,6 +93,12 @@ func (pe *UnitEditor) update(gtx C, t *Tracker) {
for pe.commentEditor.Update(gtx, t.UnitComment()) != EditorEventNone {
t.FocusPrev(gtx, false)
}
for pe.ClearUnitBtn.Clicked(gtx) {
t.ClearUnit().Do()
t.UnitSearch().SetValue("")
t.UnitSearching().SetValue(true)
pe.searchList.Focus()
}
for {
e, ok := gtx.Event(
key.Filter{Focus: pe.searchList, Name: key.NameEnter},
@ -123,20 +129,13 @@ func (pe *UnitEditor) update(gtx C, t *Tracker) {
break
}
if e, ok := e.(key.Event); ok && e.State == key.Press {
params := t.Model.Params()
doRange := func(f func(p tracker.Parameter)) {
for i := params.Table().Range().TopLeft.Y; i <= params.Table().Range().BottomRight.Y; i++ {
item := params.Item(tracker.Point{X: params.Table().Range().TopLeft.X, Y: i})
f(item)
}
}
switch e.Name {
case key.NameLeftArrow:
doRange(func(item tracker.Parameter) { item.Add(-1, e.Modifiers.Contain(key.ModShortcut)) })
t.Model.Params().Table().Add(-1, e.Modifiers.Contain(key.ModShortcut))
case key.NameRightArrow:
doRange(func(item tracker.Parameter) { item.Add(1, e.Modifiers.Contain(key.ModShortcut)) })
t.Model.Params().Table().Add(1, e.Modifiers.Contain(key.ModShortcut))
case key.NameDeleteBackward, key.NameDeleteForward:
doRange(func(item tracker.Parameter) { item.Reset() })
t.Model.Params().Table().Clear()
}
}
}
@ -145,6 +144,7 @@ func (pe *UnitEditor) update(gtx C, t *Tracker) {
key.Filter{Focus: pe.paramTable.RowTitleList, Name: key.NameEnter},
key.Filter{Focus: pe.paramTable.RowTitleList, Name: key.NameReturn},
key.Filter{Focus: pe.paramTable.RowTitleList, Name: key.NameLeftArrow},
key.Filter{Focus: pe.paramTable.RowTitleList, Name: key.NameDeleteBackward},
)
if !ok {
break
@ -154,6 +154,7 @@ func (pe *UnitEditor) update(gtx C, t *Tracker) {
case key.NameLeftArrow:
t.PatchPanel.unitList.dragList.Focus()
case key.NameDeleteBackward:
t.ClearUnit().Do()
t.UnitSearch().SetValue("")
t.UnitSearching().SetValue(true)
pe.searchList.Focus()
@ -369,29 +370,25 @@ func (pe *UnitEditor) layoutFooter(gtx C) D {
t := TrackerFromContext(gtx)
st := t.Units().SelectedType()
text := "Choose unit type"
if st != "" {
if !t.UnitSearching().Value() {
text = pe.caser.String(st)
}
hintText := Label(t.Theme, &t.Theme.UnitEditor.Hint, text)
deleteUnitBtn := ActionIconBtn(t.DeleteUnit(), t.Theme, pe.DeleteUnitBtn, icons.ActionDelete, "Delete unit (Ctrl+Backspace)")
copyUnitBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, pe.CopyUnitBtn, icons.ContentContentCopy, pe.copyHint)
disableUnitBtn := ToggleIconBtn(t.UnitDisabled(), t.Theme, pe.DisableUnitBtn, icons.AVVolumeUp, icons.AVVolumeOff, pe.disableUnitHint, pe.enableUnitHint)
w := layout.Spacer{Width: t.Theme.IconButton.Enabled.Size}.Layout
if st != "" {
clearUnitBtn := ActionIconBtn(t.ClearUnit(), t.Theme, pe.ClearUnitBtn, icons.ContentClear, "Clear unit")
w = clearUnitBtn.Layout
}
clearUnitBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, pe.ClearUnitBtn, icons.ContentClear, "Clear unit")
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(deleteUnitBtn.Layout),
layout.Rigid(copyUnitBtn.Layout),
layout.Rigid(disableUnitBtn.Layout),
layout.Rigid(w),
layout.Rigid(clearUnitBtn.Layout),
layout.Rigid(func(gtx C) D {
gtx.Constraints.Min.X = gtx.Dp(120)
gtx.Constraints.Min.X = gtx.Dp(130)
return hintText.Layout(gtx)
}),
layout.Flexed(1, func(gtx C) D {
return pe.commentEditor.Layout(gtx, t.UnitComment(), t.Theme, &t.Theme.InstrumentEditor.UnitComment, "---")
return pe.commentEditor.Layout(gtx, t.UnitComment(), t.Theme, &t.Theme.InstrumentEditor.UnitComment, "Comment")
}),
)
}

View File

@ -239,7 +239,7 @@ func (s *modelFuzzState) IterateTable(name string, table tracker.Table, yield fu
table.Fill(seed % 16)
})
yield(name+".Add", func(p string, t *testing.T) {
table.Add(seed % 16)
table.Add((seed>>1)%16, seed%2 == 0)
})
}

View File

@ -8,6 +8,7 @@ import (
"github.com/vsariola/sointu"
"github.com/vsariola/sointu/vm"
"gopkg.in/yaml.v3"
)
type (
@ -196,23 +197,68 @@ func (pt *Params) set(p Point, value int) {
q := pt.Item(p)
q.SetValue(value)
}
func (pt *Params) add(rect Rect, delta int) (ok bool) {
func (pt *Params) add(rect Rect, delta int, largeStep bool) (ok bool) {
for y := rect.TopLeft.Y; y <= rect.BottomRight.Y; y++ {
for x := rect.TopLeft.X; x <= rect.BottomRight.X; x++ {
p := Point{x, y}
q := pt.Item(p)
if !q.SetValue(q.Value() + delta) {
if !q.Add(delta, largeStep) {
return false
}
}
}
return true
}
func (pt *Params) marshal(rect Rect) (data []byte, ok bool) {
panic("NOT IMPLEMENTED")
type paramsTable struct {
Params [][]int `yaml:",flow"`
}
func (pt *Params) unmarshalAtCursor(data []byte) (ok bool) {
panic("NOT IMPLEMENTED")
func (pt *Params) marshal(rect Rect) (data []byte, ok bool) {
width := rect.BottomRight.X - rect.TopLeft.X + 1
height := rect.BottomRight.Y - rect.TopLeft.Y + 1
var table = paramsTable{Params: make([][]int, 0, width)}
for x := 0; x < width; x++ {
table.Params = append(table.Params, make([]int, 0, rect.BottomRight.Y-rect.TopLeft.Y+1))
for y := 0; y < height; y++ {
p := pt.Item(Point{x + rect.TopLeft.X, y + rect.TopLeft.Y})
table.Params[x] = append(table.Params[x], p.Value())
}
}
ret, err := yaml.Marshal(table)
if err != nil {
return nil, false
}
return ret, true
}
func (pt *Params) unmarshal(data []byte) (paramsTable, bool) {
var table paramsTable
yaml.Unmarshal(data, &table)
if len(table.Params) == 0 {
return paramsTable{}, false
}
for i := 0; i < len(table.Params); i++ {
if len(table.Params[i]) > 0 {
return table, true
}
}
return paramsTable{}, false
}
func (pt *Params) unmarshalAtCursor(data []byte) (ret bool) {
table, ok := pt.unmarshal(data)
if !ok {
return false
}
for i := 0; i < len(table.Params); i++ {
for j, q := range table.Params[i] {
x := i + pt.Cursor().X
y := j + pt.Cursor().Y
p := pt.Item(Point{x, y})
ret = p.SetValue(q) || ret
}
}
return ret
}
func (pt *Params) unmarshalRange(rect Rect, data []byte) (ok bool) {
panic("NOT IMPLEMENTED")

View File

@ -24,7 +24,7 @@ type (
clear(p Point)
set(p Point, value int)
add(rect Rect, delta int) (ok bool)
add(rect Rect, delta int, largestep bool) (ok bool)
marshal(rect Rect) (data []byte, ok bool)
unmarshalAtCursor(data []byte) (ok bool)
unmarshalRange(rect Rect, data []byte) (ok bool)
@ -135,9 +135,9 @@ func (v Table) Fill(value int) {
}
}
func (v Table) Add(delta int) {
func (v Table) Add(delta int, largeStep bool) {
defer v.change("Add", MinorChange)()
if !v.add(v.Range(), delta) {
if !v.add(v.Range(), delta, largeStep) {
v.cancel()
}
}
@ -227,7 +227,10 @@ func (m *Order) set(p Point, value int) {
m.d.Song.Score.Tracks[p.X].Order.Set(p.Y, value)
}
func (v *Order) add(rect Rect, delta int) (ok bool) {
func (v *Order) add(rect Rect, delta int, largeStep bool) (ok bool) {
if largeStep {
delta *= 8
}
for x := rect.TopLeft.X; x <= rect.BottomRight.X; x++ {
for y := rect.TopLeft.Y; y <= rect.BottomRight.Y; y++ {
if !v.add1(Point{x, y}, delta) {
@ -440,7 +443,10 @@ func (v *Notes) set(p Point, value int) {
v.SetValue(p, byte(value))
}
func (v *Notes) add(rect Rect, delta int) (ok bool) {
func (v *Notes) add(rect Rect, delta int, largeStep bool) (ok bool) {
if largeStep {
delta *= 12
}
for x := rect.BottomRight.X; x >= rect.TopLeft.X; x-- {
for y := rect.BottomRight.Y; y >= rect.TopLeft.Y; y-- {
if x < 0 || x >= len(v.d.Song.Score.Tracks) || y < 0 || y >= v.d.Song.Score.LengthInRows() {