Files
sointu/tracker/gioui/instrument_properties.go
5684185+vsariola@users.noreply.github.com 2336a135c6 feat(tracker): add a preset explorer with search and filters
Closes #91
2025-10-19 12:04:41 +03:00

106 lines
3.9 KiB
Go

package gioui
import (
"image"
"image/color"
"gioui.org/layout"
"gioui.org/op/clip"
"gioui.org/op/paint"
"gioui.org/text"
"gioui.org/unit"
"golang.org/x/exp/shiny/materialdesign/icons"
)
type (
InstrumentProperties struct {
nameEditor *Editor
commentEditor *Editor
list *layout.List
soloBtn *Clickable
muteBtn *Clickable
soloHint string
unsoloHint string
muteHint string
unmuteHint string
voices *NumericUpDownState
splitInstrumentBtn *Clickable
splitInstrumentHint string
}
)
func NewInstrumentProperties() *InstrumentProperties {
ret := &InstrumentProperties{
list: &layout.List{Axis: layout.Vertical},
nameEditor: NewEditor(true, true, text.Start),
commentEditor: NewEditor(false, false, text.Start),
soloBtn: new(Clickable),
muteBtn: new(Clickable),
voices: NewNumericUpDownState(),
splitInstrumentBtn: new(Clickable),
}
ret.soloHint = makeHint("Solo", " (%s)", "SoloToggle")
ret.unsoloHint = makeHint("Unsolo", " (%s)", "SoloToggle")
ret.muteHint = makeHint("Mute", " (%s)", "MuteToggle")
ret.unmuteHint = makeHint("Unmute", " (%s)", "MuteToggle")
ret.splitInstrumentHint = makeHint("Split instrument", " (%s)", "SplitInstrument")
return ret
}
func (ip *InstrumentProperties) Tags(level int, yield TagYieldFunc) bool {
return yield(level, &ip.commentEditor.widgetEditor)
}
// layout
func (ip *InstrumentProperties) layout(gtx C) D {
// get tracker from values
tr := TrackerFromContext(gtx)
voiceLine := func(gtx C) D {
splitInstrumentBtn := ActionIconBtn(tr.SplitInstrument(), tr.Theme, ip.splitInstrumentBtn, icons.CommunicationCallSplit, ip.splitInstrumentHint)
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(func(gtx C) D {
instrumentVoices := NumUpDown(tr.Model.InstrumentVoices(), tr.Theme, ip.voices, "Number of voices for this instrument")
return instrumentVoices.Layout(gtx)
}),
layout.Rigid(splitInstrumentBtn.Layout),
)
}
return ip.list.Layout(gtx, 9, func(gtx C, index int) D {
switch index {
case 0:
return layoutInstrumentPropertyLine(gtx, "Name", func(gtx C) D {
return ip.nameEditor.Layout(gtx, tr.InstrumentName(), tr.Theme, &tr.Theme.InstrumentEditor.InstrumentComment, "Instr")
})
case 2:
return layoutInstrumentPropertyLine(gtx, "Voices", voiceLine)
case 4:
muteBtn := ToggleIconBtn(tr.Mute(), tr.Theme, ip.muteBtn, icons.ToggleCheckBoxOutlineBlank, icons.ToggleCheckBox, ip.muteHint, ip.unmuteHint)
return layoutInstrumentPropertyLine(gtx, "Mute", muteBtn.Layout)
case 6:
soloBtn := ToggleIconBtn(tr.Solo(), tr.Theme, ip.soloBtn, icons.ToggleCheckBoxOutlineBlank, icons.ToggleCheckBox, ip.soloHint, ip.unsoloHint)
return layoutInstrumentPropertyLine(gtx, "Solo", soloBtn.Layout)
case 8:
return layout.UniformInset(unit.Dp(6)).Layout(gtx, func(gtx C) D {
return ip.commentEditor.Layout(gtx, tr.InstrumentComment(), tr.Theme, &tr.Theme.InstrumentEditor.InstrumentComment, "Comment")
})
default: // odd valued list items are dividers
px := max(gtx.Dp(unit.Dp(1)), 1)
paint.FillShape(gtx.Ops, color.NRGBA{255, 255, 255, 3}, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, px)).Op())
return D{Size: image.Pt(gtx.Constraints.Max.X, px)}
}
})
}
func layoutInstrumentPropertyLine(gtx C, text string, content layout.Widget) D {
tr := TrackerFromContext(gtx)
gtx.Constraints.Max.X = min(gtx.Dp(unit.Dp(200)), gtx.Constraints.Max.X)
label := Label(tr.Theme, &tr.Theme.InstrumentEditor.Properties.Label, text)
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
layout.Rigid(layout.Spacer{Width: 6, Height: 36}.Layout),
layout.Rigid(label.Layout),
layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }),
layout.Rigid(content),
)
}