feat(tracker): only show either notes or hex for a track + checkbox to toggle

This commit is contained in:
vsariola 2021-01-12 18:52:15 +02:00
parent dcb0877c71
commit 5a69c14f61
4 changed files with 96 additions and 53 deletions

View File

@ -89,15 +89,19 @@ func (t *Tracker) KeyEvent(e key.Event) bool {
t.NoteTracking = false t.NoteTracking = false
return true return true
case key.NameLeftArrow: case key.NameLeftArrow:
if t.CursorColumn == 0 { if t.CursorColumn == 0 || !t.TrackShowHex[t.ActiveTrack] || e.Modifiers.Contain(key.ModCtrl) {
t.ActiveTrack = (t.ActiveTrack + len(t.song.Tracks) - 1) % len(t.song.Tracks) t.ActiveTrack = (t.ActiveTrack + len(t.song.Tracks) - 1) % len(t.song.Tracks)
t.CursorColumn = 2 if t.TrackShowHex[t.ActiveTrack] {
t.CursorColumn = 1
} else {
t.CursorColumn = 0
}
} else { } else {
t.CursorColumn-- t.CursorColumn--
} }
return true return true
case key.NameRightArrow: case key.NameRightArrow:
if t.CursorColumn == 2 { if t.CursorColumn == 1 || !t.TrackShowHex[t.ActiveTrack] || e.Modifiers.Contain(key.ModCtrl) {
t.ActiveTrack = (t.ActiveTrack + 1) % len(t.song.Tracks) t.ActiveTrack = (t.ActiveTrack + 1) % len(t.song.Tracks)
t.CursorColumn = 0 t.CursorColumn = 0
} else { } else {
@ -119,7 +123,7 @@ func (t *Tracker) KeyEvent(e key.Event) bool {
return true return true
} }
} else { } else {
if t.CursorColumn == 0 { if !t.TrackShowHex[t.ActiveTrack] {
if val, ok := noteMap[e.Name]; ok { if val, ok := noteMap[e.Name]; ok {
t.NotePressed(val) t.NotePressed(val)
return true return true
@ -163,9 +167,9 @@ func (t *Tracker) NotePressed(val int) {
// NumberPressed handles incoming presses while in either of the hex number columns // NumberPressed handles incoming presses while in either of the hex number columns
func (t *Tracker) NumberPressed(iv byte) { func (t *Tracker) NumberPressed(iv byte) {
val := t.getCurrent() val := t.getCurrent()
if t.CursorColumn == 1 { if t.CursorColumn == 0 {
val = ((iv & 0xF) << 4) | (val & 0xF) val = ((iv & 0xF) << 4) | (val & 0xF)
} else if t.CursorColumn == 2 { } else if t.CursorColumn == 1 {
val = (val & 0xF0) | (iv & 0xF) val = (val & 0xF0) | (iv & 0xF)
} }
t.SetCurrentNote(val) t.SetCurrentNote(val)

View File

@ -61,6 +61,15 @@ func enableButton(icStyle material.IconButtonStyle, enabled bool) material.IconB
return icStyle return icStyle
} }
func trackButton(t *material.Theme, w *widget.Clickable, text string, enabled bool) material.ButtonStyle {
ret := material.Button(t, w, text)
if !enabled {
ret.Background = disabledContainerColor
ret.Color = disabledTextColor
}
return ret
}
func (t *Tracker) Layout(gtx layout.Context) { func (t *Tracker) Layout(gtx layout.Context) {
paint.FillShape(gtx.Ops, backgroundColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op()) paint.FillShape(gtx.Ops, backgroundColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op())
layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx2 layout.Context) layout.Dimensions { layout.UniformInset(unit.Dp(2)).Layout(gtx, func(gtx2 layout.Context) layout.Dimensions {
@ -95,17 +104,34 @@ func (t *Tracker) layoutTracker(gtx layout.Context) layout.Dimensions {
for i, trk := range t.song.Tracks { for i, trk := range t.song.Tracks {
i2 := i // avoids i being updated in the closure i2 := i // avoids i being updated in the closure
trk2 := trk // avoids trk being updated in the closure trk2 := trk // avoids trk being updated in the closure
if len(t.TrackHexCheckBoxes) <= i {
t.TrackHexCheckBoxes = append(t.TrackHexCheckBoxes, new(widget.Bool))
}
if len(t.TrackShowHex) <= i {
t.TrackShowHex = append(t.TrackShowHex, false)
}
flexTracks[i] = layout.Rigid(func(gtx layout.Context) layout.Dimensions { flexTracks[i] = layout.Rigid(func(gtx layout.Context) layout.Dimensions {
return leftInset.Layout(gtx, t.layoutTrack( t.TrackHexCheckBoxes[i2].Value = t.TrackShowHex[i2]
trk2.Patterns, cbStyle := material.CheckBox(t.Theme, t.TrackHexCheckBoxes[i2], "hex")
trk2.Sequence, cbStyle.Color = white
t.ActiveTrack == i2, ret := layout.Stack{}.Layout(gtx,
t.CursorRow, layout.Stacked(func(gtx layout.Context) D {
t.DisplayPattern, return leftInset.Layout(gtx, t.layoutTrack(
t.CursorColumn, trk2.Patterns,
t.PlayRow, trk2.Sequence,
playPat, t.ActiveTrack == i2,
)) t.TrackShowHex[i2],
t.CursorRow,
t.DisplayPattern,
t.CursorColumn,
t.PlayRow,
playPat,
))
}),
layout.Stacked(cbStyle.Layout),
)
t.TrackShowHex[i2] = t.TrackHexCheckBoxes[i2].Value
return ret
}) })
} }
in2 := layout.UniformInset(unit.Dp(8)) in2 := layout.UniformInset(unit.Dp(8))

View File

@ -14,10 +14,10 @@ import (
) )
const trackRowHeight = 16 const trackRowHeight = 16
const trackWidth = 84 const trackWidth = 54
const patmarkWidth = 16 const patmarkWidth = 16
func (t *Tracker) layoutTrack(patterns [][]byte, sequence []byte, active bool, cursorRow, cursorPattern, cursorCol, playRow, playPattern int) layout.Widget { func (t *Tracker) layoutTrack(patterns [][]byte, sequence []byte, active bool, hex bool, cursorRow, cursorPattern, cursorCol, playRow, playPattern int) layout.Widget {
return func(gtx layout.Context) layout.Dimensions { return func(gtx layout.Context) layout.Dimensions {
gtx.Constraints.Min.X = trackWidth gtx.Constraints.Min.X = trackWidth
gtx.Constraints.Max.X = trackWidth gtx.Constraints.Max.X = trackWidth
@ -51,16 +51,27 @@ func (t *Tracker) layoutTrack(patterns [][]byte, sequence []byte, active bool, c
paint.ColorOp{Color: trackerInactiveTextColor}.Add(gtx.Ops) paint.ColorOp{Color: trackerInactiveTextColor}.Add(gtx.Ops)
} }
op.Offset(f32.Pt(patmarkWidth, 0)).Add(gtx.Ops) op.Offset(f32.Pt(patmarkWidth, 0)).Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, valueAsNote(c)) if hex {
if active && cursorCol == 0 && songRow == cursorSongRow { var text string
paint.FillShape(gtx.Ops, trackerCursorColor, clip.Rect{Max: image.Pt(30, trackRowHeight)}.Op()) switch c {
case 0:
text = "--"
case 1:
text = ".."
default:
text = fmt.Sprintf("%02x", c)
}
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(text))
if active && songRow == cursorSongRow {
paint.FillShape(gtx.Ops, trackerCursorColor, clip.Rect{Min: image.Pt(cursorCol*10, 0), Max: image.Pt(cursorCol*10+10, trackRowHeight)}.Op())
}
} else {
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, valueAsNote(c))
if active && cursorCol == 0 && songRow == cursorSongRow {
paint.FillShape(gtx.Ops, trackerCursorColor, clip.Rect{Max: image.Pt(30, trackRowHeight)}.Op())
}
} }
op.Offset(f32.Pt(trackWidth/2, 0)).Add(gtx.Ops) op.Offset(f32.Pt(-patmarkWidth, trackRowHeight)).Add(gtx.Ops)
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", c)))
if active && cursorCol > 0 && songRow == cursorSongRow {
paint.FillShape(gtx.Ops, trackerCursorColor, clip.Rect{Min: image.Pt((cursorCol-1)*10, 0), Max: image.Pt((cursorCol-1)*10+10, trackRowHeight)}.Op())
}
op.Offset(f32.Pt(-trackWidth/2-patmarkWidth, trackRowHeight)).Add(gtx.Ops)
} }
} }
return layout.Dimensions{Size: gtx.Constraints.Max} return layout.Dimensions{Size: gtx.Constraints.Max}

View File

@ -18,32 +18,34 @@ type Tracker struct {
song sointu.Song song sointu.Song
Playing bool Playing bool
// protects PlayPattern and PlayRow // protects PlayPattern and PlayRow
playRowPatMutex sync.RWMutex // protects song and playing playRowPatMutex sync.RWMutex // protects song and playing
PlayPattern int PlayPattern int
PlayRow int PlayRow int
CursorRow int CursorRow int
CursorColumn int CursorColumn int
DisplayPattern int DisplayPattern int
ActiveTrack int ActiveTrack int
CurrentInstrument int CurrentInstrument int
CurrentUnit int CurrentUnit int
CurrentOctave byte CurrentOctave byte
NoteTracking bool NoteTracking bool
Theme *material.Theme Theme *material.Theme
OctaveUpBtn *widget.Clickable OctaveUpBtn *widget.Clickable
OctaveDownBtn *widget.Clickable OctaveDownBtn *widget.Clickable
BPMUpBtn *widget.Clickable BPMUpBtn *widget.Clickable
BPMDownBtn *widget.Clickable BPMDownBtn *widget.Clickable
NewTrackBtn *widget.Clickable NewTrackBtn *widget.Clickable
NewInstrumentBtn *widget.Clickable NewInstrumentBtn *widget.Clickable
LoadSongFileBtn *widget.Clickable LoadSongFileBtn *widget.Clickable
SongLengthUpBtn *widget.Clickable SongLengthUpBtn *widget.Clickable
SongLengthDownBtn *widget.Clickable SongLengthDownBtn *widget.Clickable
SaveSongFileBtn *widget.Clickable SaveSongFileBtn *widget.Clickable
ParameterSliders []*widget.Float ParameterSliders []*widget.Float
UnitBtns []*widget.Clickable UnitBtns []*widget.Clickable
InstrumentBtns []*widget.Clickable InstrumentBtns []*widget.Clickable
InstrumentList *layout.List InstrumentList *layout.List
TrackHexCheckBoxes []*widget.Bool
TrackShowHex []bool
sequencer *Sequencer sequencer *Sequencer
ticked chan struct{} ticked chan struct{}