diff --git a/tracker/instruments.go b/tracker/instruments.go index b4f0fa5..8e7b3c0 100644 --- a/tracker/instruments.go +++ b/tracker/instruments.go @@ -1,14 +1,16 @@ package tracker import ( - "fmt" "image" + "gioui.org/io/pointer" "gioui.org/layout" "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" + "gioui.org/text" "gioui.org/unit" + "gioui.org/widget" "gioui.org/widget/material" "golang.org/x/exp/shiny/materialdesign/icons" ) @@ -63,8 +65,9 @@ func (t *Tracker) layoutInstrumentHeader(gtx C) D { } else { deleteInstrumentBtnStyle.Color = disabledTextColor } - return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, - layout.Rigid(Label("Voices:", white)), + + return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(Label("Voices: ", white)), layout.Rigid(func(gtx layout.Context) layout.Dimensions { maxRemain := 32 - t.song.Patch.TotalVoices() + t.song.Patch.Instruments[t.CurrentInstrument].NumVoices if maxRemain < 0 { @@ -90,16 +93,45 @@ func (t *Tracker) layoutInstrumentHeader(gtx C) D { } func (t *Tracker) layoutInstrumentNames(gtx C) D { - element := func(gtx C, i int) D { gtx.Constraints.Min.Y = gtx.Px(unit.Dp(36)) - text := t.song.Patch.Instruments[i].Name - if text == "" { - text = fmt.Sprintf("%v", i) + gtx.Constraints.Min.X = gtx.Px(unit.Dp(30)) + grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center} + if i == t.CurrentInstrument { + grabhandle.Text = ":::" } - labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12)} - return layout.Inset{Left: unit.Dp(10), Right: unit.Dp(10)}.Layout(gtx, func(gtx C) D { + label := func(gtx C) D { + if i == t.CurrentInstrument { + for _, ev := range t.InstrumentNameEditor.Events() { + _, ok := ev.(widget.SubmitEvent) + if ok { + t.InstrumentNameEditor = &widget.Editor{SingleLine: true, Submit: true, Alignment: text.Middle} // TODO: is there any other way to defocus the editor + break + } + } + if n := t.song.Patch.Instruments[t.CurrentInstrument].Name; n != t.InstrumentNameEditor.Text() { + t.InstrumentNameEditor.SetText(n) + } + editor := material.Editor(t.Theme, t.InstrumentNameEditor, "Instr") + editor.Color = instrumentNameColor + editor.HintColor = instrumentNameHintColor + editor.TextSize = unit.Dp(12) + dims := layout.Center.Layout(gtx, editor.Layout) + t.SetInstrumentName(t.InstrumentNameEditor.Text()) + return dims + } + text := t.song.Patch.Instruments[i].Name + if text == "" { + text = "Instr" + } + labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, FontSize: unit.Sp(12)} return layout.Center.Layout(gtx, labelStyle.Layout) + } + return layout.Inset{Left: unit.Dp(6), Right: unit.Dp(6)}.Layout(gtx, func(gtx C) D { + return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx, + layout.Rigid(grabhandle.Layout), + layout.Rigid(label), + ) }) } @@ -109,6 +141,8 @@ func (t *Tracker) layoutInstrumentNames(gtx C) D { instrumentList.SurfaceColor = transparent t.InstrumentDragList.SelectedItem = t.CurrentInstrument + defer op.Save(gtx.Ops).Load() + pointer.PassOp{Pass: true}.Add(gtx.Ops) dims := instrumentList.Layout(gtx) if t.CurrentInstrument != t.InstrumentDragList.SelectedItem { t.CurrentInstrument = t.InstrumentDragList.SelectedItem diff --git a/tracker/keyevent.go b/tracker/keyevent.go index ffa3d83..35fa0c6 100644 --- a/tracker/keyevent.go +++ b/tracker/keyevent.go @@ -45,6 +45,9 @@ var noteMap = map[string]int{ // KeyEvent handles incoming key events and returns true if repaint is needed. func (t *Tracker) KeyEvent(e key.Event) bool { if e.State == key.Press { + if t.InstrumentNameEditor.Focused() { + return false + } switch e.Name { case "Z": if e.Modifiers.Contain(key.ModCtrl) { diff --git a/tracker/theme.go b/tracker/theme.go index d35a467..1a77fda 100644 --- a/tracker/theme.go +++ b/tracker/theme.go @@ -87,6 +87,8 @@ var inactiveBtnColor = color.NRGBA{R: 61, G: 55, B: 55, A: 255} var instrumentSurfaceColor = color.NRGBA{R: 45, G: 45, B: 45, A: 255} var instrumentHoverColor = color.NRGBA{R: 30, G: 31, B: 38, A: 255} +var instrumentNameColor = color.NRGBA{R: 255, G: 255, B: 255, A: 255} +var instrumentNameHintColor = color.NRGBA{R: 200, G: 200, B: 200, A: 255} var songSurfaceColor = color.NRGBA{R: 37, G: 37, B: 38, A: 255} diff --git a/tracker/tracker.go b/tracker/tracker.go index ad6d5da..99f2c90 100644 --- a/tracker/tracker.go +++ b/tracker/tracker.go @@ -2,10 +2,12 @@ package tracker import ( "fmt" + "strings" "sync" "gioui.org/font/gofont" "gioui.org/layout" + "gioui.org/text" "gioui.org/widget" "gioui.org/widget/material" "github.com/vsariola/sointu" @@ -34,6 +36,7 @@ type Tracker struct { RowsPerPattern *NumberInput RowsPerBeat *NumberInput InstrumentVoices *NumberInput + InstrumentNameEditor *widget.Editor NewTrackBtn *widget.Clickable NewInstrumentBtn *widget.Clickable DeleteInstrumentBtn *widget.Clickable @@ -164,6 +167,14 @@ func (t *Tracker) SetInstrumentVoices(value int) bool { return false } +func (t *Tracker) SetInstrumentName(name string) { + name = strings.TrimSpace(name) + if name != t.song.Patch.Instruments[t.CurrentInstrument].Name { + t.SaveUndo() + t.song.Patch.Instruments[t.CurrentInstrument].Name = name + } +} + func (t *Tracker) SetBPM(value int) bool { if value < 1 { value = 1 @@ -442,6 +453,7 @@ func New(audioContext sointu.AudioContext, synthService sointu.SynthService) *Tr RowsPerPattern: new(NumberInput), RowsPerBeat: new(NumberInput), InstrumentVoices: new(NumberInput), + InstrumentNameEditor: &widget.Editor{SingleLine: true, Submit: true, Alignment: text.Middle}, NewTrackBtn: new(widget.Clickable), NewInstrumentBtn: new(widget.Clickable), DeleteInstrumentBtn: new(widget.Clickable),