diff --git a/tracker/gioui/instr_props.go b/tracker/gioui/instr_props.go new file mode 100644 index 0000000..5d6b7b1 --- /dev/null +++ b/tracker/gioui/instr_props.go @@ -0,0 +1,101 @@ +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 { + 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}, + commentEditor: NewEditor(false, false, text.Start), + soloBtn: new(Clickable), + muteBtn: new(Clickable), + voices: NewNumericUpDownState(), + splitInstrumentBtn: new(Clickable), + } + ret.soloHint = makeHint("Solo", " (%s)", "SoloInstrument") + ret.unsoloHint = makeHint("Unsolo", " (%s)", "SoloInstrument") + ret.muteHint = makeHint("Mute", " (%s)", "MuteInstrument") + ret.unmuteHint = makeHint("Unmute", " (%s)", "MuteInstrument") + ret.splitInstrumentHint = makeHint("Split instrument", " (%s)", "SplitInstrument") + return ret +} + +// update +func (ip *InstrumentProperties) update(gtx C, tr *Tracker) { + /*for ip.commentEditor.Update(gtx, tr.InstrumentComment()) != EditorEventNone { + tr.PatchPanel.instrList.instrumentDragList.Focus() + }*/ +} + +// 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, 7, func(gtx C, index int) D { + switch index { + case 0: + return layoutInstrumentPropertyLine(gtx, "Voices", voiceLine) + case 2: + muteBtn := ToggleIconBtn(tr.Mute(), tr.Theme, ip.muteBtn, icons.ToggleCheckBoxOutlineBlank, icons.ToggleCheckBox, ip.muteHint, ip.unmuteHint) + return layoutInstrumentPropertyLine(gtx, "Mute", muteBtn.Layout) + case 4: + soloBtn := ToggleIconBtn(tr.Solo(), tr.Theme, ip.soloBtn, icons.ToggleCheckBoxOutlineBlank, icons.ToggleCheckBox, ip.soloHint, ip.unsoloHint) + return layoutInstrumentPropertyLine(gtx, "Solo", soloBtn.Layout) + case 6: + 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}.Layout), + layout.Rigid(label.Layout), + layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }), + layout.Rigid(content), + ) +} diff --git a/tracker/gioui/patch_panel.go b/tracker/gioui/patch_panel.go index ec7db4d..23d9882 100644 --- a/tracker/gioui/patch_panel.go +++ b/tracker/gioui/patch_panel.go @@ -24,11 +24,26 @@ type ( tools InstrumentTools unitList UnitList unitEditor UnitEditor + instrProps InstrumentProperties } InstrumentList struct { instrumentDragList *DragList nameEditor *Editor + } + + InstrumentTools struct { + EditorTab *Clickable + PresetsTab *Clickable + CommentTab *Clickable + + presetMenuBtn *Clickable + presetMenu MenuState + presetMenuItems []ActionMenuItem + saveInstrumentBtn *Clickable + loadInstrumentBtn *Clickable + copyInstrumentBtn *Clickable + deleteInstrumentBtn *Clickable octave *NumericUpDownState enlargeBtn *Clickable @@ -40,32 +55,9 @@ type ( linkEnabledHint string enlargeHint, shrinkHint string addInstrumentHint string - } - InstrumentTools struct { - EditorTab *Clickable - PresetsTab *Clickable - CommentTab *Clickable - - Voices *NumericUpDownState - splitInstrumentBtn *Clickable - commentExpandBtn *Clickable - commentEditor *Editor - soloBtn *Clickable - muteBtn *Clickable - presetMenuBtn *Clickable - presetMenu MenuState - presetMenuItems []ActionMenuItem - saveInstrumentBtn *Clickable - loadInstrumentBtn *Clickable - copyInstrumentBtn *Clickable - deleteInstrumentBtn *Clickable - - muteHint, unmuteHint string - soloHint, unsoloHint string expandCommentHint string collapseCommentHint string - splitInstrumentHint string deleteInstrumentHint string } ) @@ -78,19 +70,30 @@ func NewPatchPanel(model *tracker.Model) *PatchPanel { tools: MakeInstrumentTools(model), unitList: MakeUnitList(model), unitEditor: *NewUnitEditor(model), + instrProps: *NewInstrumentProperties(), } } func (pp *PatchPanel) Layout(gtx C) D { - return layout.Flex{Axis: layout.Vertical}.Layout(gtx, - layout.Rigid(pp.instrList.Layout), - layout.Rigid(pp.tools.Layout), - layout.Flexed(1, func(gtx C) D { + tr := TrackerFromContext(gtx) + bottom := func(gtx C) D { + switch { + case tr.InstrComment().Value(): + return pp.instrProps.layout(gtx) + case tr.InstrPresets().Value(): + return pp.instrProps.layout(gtx) + default: // editor return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Rigid(pp.unitList.Layout), layout.Flexed(1, pp.unitEditor.Layout), ) - })) + } + } + return layout.Flex{Axis: layout.Vertical}.Layout(gtx, + layout.Rigid(pp.instrList.Layout), + layout.Rigid(pp.tools.Layout), + layout.Flexed(1, bottom), + ) } func (pp *PatchPanel) Tags(level int, yield TagYieldFunc) bool { @@ -114,26 +117,24 @@ func MakeInstrumentTools(m *tracker.Model) InstrumentTools { EditorTab: new(Clickable), PresetsTab: new(Clickable), CommentTab: new(Clickable), - Voices: NewNumericUpDownState(), deleteInstrumentBtn: new(Clickable), - splitInstrumentBtn: new(Clickable), copyInstrumentBtn: new(Clickable), saveInstrumentBtn: new(Clickable), loadInstrumentBtn: new(Clickable), - commentExpandBtn: new(Clickable), presetMenuBtn: new(Clickable), - soloBtn: new(Clickable), - muteBtn: new(Clickable), presetMenuItems: []ActionMenuItem{}, - commentEditor: NewEditor(false, false, text.Start), expandCommentHint: makeHint("Expand comment", " (%s)", "CommentExpandedToggle"), - collapseCommentHint: makeHint("Collapse comment", " (%s)", "CommentExpandedToggle"), deleteInstrumentHint: makeHint("Delete\ninstrument", "\n(%s)", "DeleteInstrument"), - muteHint: makeHint("Mute", " (%s)", "MuteToggle"), - unmuteHint: makeHint("Unmute", " (%s)", "MuteToggle"), - soloHint: makeHint("Solo", " (%s)", "SoloToggle"), - unsoloHint: makeHint("Unsolo", " (%s)", "SoloToggle"), - splitInstrumentHint: makeHint("Split instrument", " (%s)", "SplitInstrument"), + octave: NewNumericUpDownState(), + enlargeBtn: new(Clickable), + linkInstrTrackBtn: new(Clickable), + newInstrumentBtn: new(Clickable), + octaveHint: makeHint("Octave down", " (%s)", "OctaveNumberInputSubtract") + makeHint(" or up", " (%s)", "OctaveNumberInputAdd"), + linkDisabledHint: makeHint("Instrument-Track\nlinking disabled", "\n(%s)", "LinkInstrTrackToggle"), + linkEnabledHint: makeHint("Instrument-Track\nlinking enabled", "\n(%s)", "LinkInstrTrackToggle"), + enlargeHint: makeHint("Enlarge", " (%s)", "InstrEnlargedToggle"), + shrinkHint: makeHint("Shrink", " (%s)", "InstrEnlargedToggle"), + addInstrumentHint: makeHint("Add\ninstrument", "\n(%s)", "AddInstrument"), } for index, name := range m.IterateInstrumentPresets { ret.presetMenuItems = append(ret.presetMenuItems, MenuItem(m.LoadPreset(index), name, "", icons.ImageAudiotrack)) @@ -144,20 +145,18 @@ func MakeInstrumentTools(m *tracker.Model) InstrumentTools { func (it *InstrumentTools) Layout(gtx C) D { t := TrackerFromContext(gtx) it.update(gtx, t) - voicesLabel := Label(t.Theme, &t.Theme.InstrumentEditor.Voices, "Voices") - editorBtn := TabBtn(t.Model.InstrEditor(), t.Theme, it.EditorTab, "Editor", "") presetsBtn := TabBtn(t.Model.InstrPresets(), t.Theme, it.PresetsTab, "Presets", "") - commentBtn := TabBtn(t.Model.InstrComment(), t.Theme, it.CommentTab, "Comment", "") + commentBtn := TabBtn(t.Model.InstrComment(), t.Theme, it.CommentTab, "Properties", "") + octave := NumUpDown(t.Model.Octave(), t.Theme, t.OctaveNumberInput, "Octave") + linkInstrTrackBtn := ToggleIconBtn(t.Model.LinkInstrTrack(), t.Theme, it.linkInstrTrackBtn, icons.NotificationSyncDisabled, icons.NotificationSync, it.linkDisabledHint, it.linkEnabledHint) + instrEnlargedBtn := ToggleIconBtn(t.Model.InstrEnlarged(), t.Theme, it.enlargeBtn, icons.NavigationFullscreen, icons.NavigationFullscreenExit, it.enlargeHint, it.shrinkHint) + addInstrumentBtn := ActionIconBtn(t.Model.AddInstrument(), t.Theme, it.newInstrumentBtn, icons.ContentAdd, it.addInstrumentHint) - splitInstrumentBtn := ActionIconBtn(t.SplitInstrument(), t.Theme, it.splitInstrumentBtn, icons.CommunicationCallSplit, it.splitInstrumentHint) - soloBtn := ToggleIconBtn(t.Solo(), t.Theme, it.soloBtn, icons.SocialGroup, icons.SocialPerson, it.soloHint, it.unsoloHint) - muteBtn := ToggleIconBtn(t.Mute(), t.Theme, it.muteBtn, icons.AVVolumeUp, icons.AVVolumeOff, it.muteHint, it.unmuteHint) // saveInstrumentBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, it.saveInstrumentBtn, icons.ContentSave, "Save instrument") // loadInstrumentBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, it.loadInstrumentBtn, icons.FileFolderOpen, "Load instrument") copyInstrumentBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, it.copyInstrumentBtn, icons.ContentContentCopy, "Copy instrument") deleteInstrumentBtn := ActionIconBtn(t.DeleteInstrument(), t.Theme, it.deleteInstrumentBtn, icons.ActionDelete, it.deleteInstrumentHint) - instrumentVoices := NumUpDown(t.Model.InstrumentVoices(), t.Theme, it.Voices, "Number of voices for this instrument") btns := func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(layout.Spacer{Width: 6}.Layout), @@ -165,12 +164,7 @@ func (it *InstrumentTools) Layout(gtx C) D { layout.Rigid(presetsBtn.Layout), layout.Rigid(commentBtn.Layout), layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }), - layout.Rigid(voicesLabel.Layout), layout.Rigid(layout.Spacer{Width: 4}.Layout), - layout.Rigid(instrumentVoices.Layout), - layout.Rigid(splitInstrumentBtn.Layout), - layout.Rigid(soloBtn.Layout), - layout.Rigid(muteBtn.Layout), /*layout.Rigid(func(gtx C) D { presetBtn := IconBtn(t.Theme, &t.Theme.IconButton.Enabled, it.presetMenuBtn, icons.NavigationMenu, "Load preset") dims := presetBtn.Layout(gtx) @@ -182,8 +176,13 @@ func (it *InstrumentTools) Layout(gtx C) D { }),*/ // layout.Rigid(saveInstrumentBtn.Layout), // layout.Rigid(loadInstrumentBtn.Layout), + layout.Rigid(Label(t.Theme, &t.Theme.InstrumentEditor.Octave, "Octave").Layout), + layout.Rigid(octave.Layout), + layout.Rigid(linkInstrTrackBtn.Layout), + layout.Rigid(instrEnlargedBtn.Layout), layout.Rigid(copyInstrumentBtn.Layout), layout.Rigid(deleteInstrumentBtn.Layout), + layout.Rigid(addInstrumentBtn.Layout), ) } /*comment := func(gtx C) D { @@ -220,9 +219,6 @@ func (it *InstrumentTools) update(gtx C, tr *Tracker) { for it.presetMenuBtn.Clicked(gtx) { it.presetMenu.visible = true } - for it.commentEditor.Update(gtx, tr.InstrumentComment()) != EditorEventNone { - tr.PatchPanel.instrList.instrumentDragList.Focus() - } } func (it *InstrumentTools) Tags(level int, yield TagYieldFunc) bool { @@ -235,41 +231,12 @@ func MakeInstrList(model *tracker.Model) InstrumentList { return InstrumentList{ instrumentDragList: NewDragList(model.Instruments().List(), layout.Horizontal), nameEditor: NewEditor(true, true, text.Middle), - octave: NewNumericUpDownState(), - enlargeBtn: new(Clickable), - linkInstrTrackBtn: new(Clickable), - newInstrumentBtn: new(Clickable), - octaveHint: makeHint("Octave down", " (%s)", "OctaveNumberInputSubtract") + makeHint(" or up", " (%s)", "OctaveNumberInputAdd"), - linkDisabledHint: makeHint("Instrument-Track\nlinking disabled", "\n(%s)", "LinkInstrTrackToggle"), - linkEnabledHint: makeHint("Instrument-Track\nlinking enabled", "\n(%s)", "LinkInstrTrackToggle"), - enlargeHint: makeHint("Enlarge", " (%s)", "InstrEnlargedToggle"), - shrinkHint: makeHint("Shrink", " (%s)", "InstrEnlargedToggle"), - addInstrumentHint: makeHint("Add\ninstrument", "\n(%s)", "AddInstrument"), } } func (il *InstrumentList) Layout(gtx C) D { t := TrackerFromContext(gtx) il.update(gtx, t) - octave := NumUpDown(t.Model.Octave(), t.Theme, t.OctaveNumberInput, "Octave") - linkInstrTrackBtn := ToggleIconBtn(t.Model.LinkInstrTrack(), t.Theme, il.linkInstrTrackBtn, icons.NotificationSyncDisabled, icons.NotificationSync, il.linkDisabledHint, il.linkEnabledHint) - instrEnlargedBtn := ToggleIconBtn(t.Model.InstrEnlarged(), t.Theme, il.enlargeBtn, icons.NavigationFullscreen, icons.NavigationFullscreenExit, il.enlargeHint, il.shrinkHint) - addInstrumentBtn := ActionIconBtn(t.Model.AddInstrument(), t.Theme, il.newInstrumentBtn, icons.ContentAdd, il.addInstrumentHint) - return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout( - gtx, - layout.Flexed(1, il.actualLayout), - layout.Rigid(layout.Spacer{Width: 10}.Layout), - layout.Rigid(Label(t.Theme, &t.Theme.InstrumentEditor.Octave, "Octave").Layout), - layout.Rigid(layout.Spacer{Width: 4}.Layout), - layout.Rigid(octave.Layout), - layout.Rigid(linkInstrTrackBtn.Layout), - layout.Rigid(instrEnlargedBtn.Layout), - layout.Rigid(addInstrumentBtn.Layout), - ) -} - -func (il *InstrumentList) actualLayout(gtx C) D { - t := TrackerFromContext(gtx) gtx.Constraints.Max.Y = gtx.Dp(36) gtx.Constraints.Min.Y = gtx.Dp(36) element := func(gtx C, i int) D { diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index 3c06194..7437d08 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -70,8 +70,10 @@ type Theme struct { Preset MenuStyle } InstrumentEditor struct { - Octave LabelStyle - Voices LabelStyle + Octave LabelStyle + Properties struct { + Label LabelStyle + } InstrumentComment EditorStyle UnitComment EditorStyle InstrumentList struct { diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index ce53f97..5c74e7e 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -164,7 +164,8 @@ menu: height: 300 instrumenteditor: octave: { textsize: 14, color: *disabled } - voices: { textsize: 14, color: *disabled } + properties: + label: { textsize: 14, color: *highemphasis } instrumentcomment: { textsize: 14, color: *highemphasis, hintcolor: *disabled } unitcomment: { textsize: 14, color: *highemphasis, hintcolor: *disabled }