mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
195 lines
6.1 KiB
Go
195 lines
6.1 KiB
Go
package tracker
|
|
|
|
import (
|
|
"fmt"
|
|
"image"
|
|
"image/color"
|
|
|
|
"gioui.org/layout"
|
|
"gioui.org/op"
|
|
"gioui.org/op/clip"
|
|
"gioui.org/op/paint"
|
|
"gioui.org/unit"
|
|
"gioui.org/widget"
|
|
"gioui.org/widget/material"
|
|
"golang.org/x/exp/shiny/materialdesign/icons"
|
|
)
|
|
|
|
type C = layout.Context
|
|
type D = layout.Dimensions
|
|
|
|
func (t *Tracker) updateInstrumentScroll() {
|
|
if t.CurrentInstrument > 7 {
|
|
t.InstrumentList.Position.First = t.CurrentInstrument - 7
|
|
} else {
|
|
t.InstrumentList.Position.First = 0
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) layoutInstruments() layout.Widget {
|
|
btnStyle := material.IconButton(t.Theme, t.NewInstrumentBtn, widgetForIcon(icons.ContentAdd))
|
|
btnStyle.Background = transparent
|
|
btnStyle.Inset = layout.UniformInset(unit.Dp(6))
|
|
if t.song.Patch.TotalVoices() < 32 {
|
|
btnStyle.Color = primaryColor
|
|
} else {
|
|
btnStyle.Color = disabledTextColor
|
|
}
|
|
return func(gtx C) D {
|
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
|
layout.Rigid(func(gtx C) D {
|
|
return layout.Flex{}.Layout(
|
|
gtx,
|
|
layout.Flexed(1, t.layoutInstrumentNames()),
|
|
layout.Rigid(func(gtx C) D {
|
|
return layout.E.Layout(gtx, btnStyle.Layout)
|
|
}),
|
|
)
|
|
}),
|
|
layout.Rigid(t.layoutInstrumentHeader()),
|
|
layout.Flexed(1, t.layoutInstrumentEditor()))
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) layoutInstrumentHeader() layout.Widget {
|
|
headerBg := func(gtx C) D {
|
|
paint.FillShape(gtx.Ops, instrumentSurfaceColor, clip.Rect{
|
|
Max: gtx.Constraints.Min,
|
|
}.Op())
|
|
return layout.Dimensions{Size: gtx.Constraints.Min}
|
|
}
|
|
header := func(gtx C) D {
|
|
deleteInstrumentBtnStyle := material.IconButton(t.Theme, t.DeleteInstrumentBtn, widgetForIcon(icons.ActionDelete))
|
|
deleteInstrumentBtnStyle.Background = transparent
|
|
deleteInstrumentBtnStyle.Inset = layout.UniformInset(unit.Dp(6))
|
|
if len(t.song.Patch.Instruments) > 1 {
|
|
deleteInstrumentBtnStyle.Color = primaryColor
|
|
} else {
|
|
deleteInstrumentBtnStyle.Color = disabledTextColor
|
|
}
|
|
return layout.Flex{Axis: layout.Horizontal}.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 {
|
|
maxRemain = 0
|
|
}
|
|
t.InstrumentVoices.Value = t.song.Patch.Instruments[t.CurrentInstrument].NumVoices
|
|
numStyle := NumericUpDown(t.Theme, t.InstrumentVoices, 0, maxRemain)
|
|
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(20))
|
|
gtx.Constraints.Min.X = gtx.Px(unit.Dp(70))
|
|
dims := numStyle.Layout(gtx)
|
|
t.SetInstrumentVoices(t.InstrumentVoices.Value)
|
|
return dims
|
|
}),
|
|
layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }),
|
|
layout.Rigid(deleteInstrumentBtnStyle.Layout))
|
|
}
|
|
for t.DeleteInstrumentBtn.Clicked() {
|
|
t.DeleteInstrument()
|
|
}
|
|
return func(gtx C) D {
|
|
return layout.Stack{Alignment: layout.Center}.Layout(gtx,
|
|
layout.Expanded(headerBg),
|
|
layout.Stacked(header))
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) layoutInstrumentNames() layout.Widget {
|
|
return func(gtx C) D {
|
|
gtx.Constraints.Max.Y = gtx.Px(unit.Dp(36))
|
|
gtx.Constraints.Min.Y = gtx.Px(unit.Dp(36))
|
|
|
|
count := len(t.song.Patch.Instruments)
|
|
if len(t.InstrumentBtns) < count {
|
|
tail := make([]*widget.Clickable, count-len(t.InstrumentBtns))
|
|
for t := range tail {
|
|
tail[t] = new(widget.Clickable)
|
|
}
|
|
t.InstrumentBtns = append(t.InstrumentBtns, tail...)
|
|
}
|
|
|
|
defer op.Save(gtx.Ops).Load()
|
|
|
|
t.InstrumentList.Layout(gtx, count, func(gtx C, index int) D {
|
|
for t.InstrumentBtns[index].Clicked() {
|
|
t.CurrentInstrument = index
|
|
}
|
|
btnStyle := material.Button(t.Theme, t.InstrumentBtns[index], fmt.Sprintf("%v", index))
|
|
btnStyle.CornerRadius = unit.Dp(0)
|
|
btnStyle.Color = t.Theme.Fg
|
|
if t.CurrentInstrument == index {
|
|
btnStyle.Background = instrumentSurfaceColor
|
|
} else {
|
|
btnStyle.Background = transparent
|
|
}
|
|
return btnStyle.Layout(gtx)
|
|
})
|
|
|
|
return layout.Dimensions{Size: gtx.Constraints.Max}
|
|
}
|
|
}
|
|
func (t *Tracker) layoutInstrumentEditor() layout.Widget {
|
|
for t.AddUnitBtn.Clicked() {
|
|
t.AddUnit()
|
|
}
|
|
addUnitBtnStyle := material.IconButton(t.Theme, t.AddUnitBtn, widgetForIcon(icons.ContentAdd))
|
|
addUnitBtnStyle.Inset = layout.UniformInset(unit.Dp(4))
|
|
margin := layout.UniformInset(unit.Dp(2))
|
|
|
|
return func(gtx C) D {
|
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
|
layout.Rigid(func(gtx C) D {
|
|
return layout.Stack{Alignment: layout.SE}.Layout(gtx,
|
|
layout.Expanded(t.layoutUnitList()),
|
|
layout.Stacked(func(gtx C) D {
|
|
return margin.Layout(gtx, addUnitBtnStyle.Layout)
|
|
}))
|
|
}),
|
|
layout.Rigid(t.layoutUnitEditor()))
|
|
}
|
|
}
|
|
|
|
func (t *Tracker) layoutUnitList() layout.Widget {
|
|
return func(gtx C) D {
|
|
paint.FillShape(gtx.Ops, unitListSurfaceColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, gtx.Constraints.Max.Y)}.Op())
|
|
defer op.Save(gtx.Ops).Load()
|
|
|
|
gtx.Constraints.Min.Y = gtx.Constraints.Max.Y
|
|
units := t.song.Patch.Instruments[t.CurrentInstrument].Units
|
|
count := len(units)
|
|
for len(t.UnitBtns) < count {
|
|
t.UnitBtns = append(t.UnitBtns, new(widget.Clickable))
|
|
}
|
|
|
|
listElem := func(gtx C, i int) D {
|
|
for t.UnitBtns[i].Clicked() {
|
|
t.CurrentUnit = i
|
|
op.InvalidateOp{}.Add(gtx.Ops)
|
|
}
|
|
u := t.song.Patch.Instruments[t.CurrentInstrument].Units[i]
|
|
labelStyle := LabelStyle{Text: u.Type, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12)}
|
|
if labelStyle.Text == "" {
|
|
labelStyle.Text = "---"
|
|
labelStyle.Alignment = layout.Center
|
|
}
|
|
bg := func(gtx C) D {
|
|
gtx.Constraints = layout.Exact(image.Pt(120, 20))
|
|
var color color.NRGBA
|
|
if t.CurrentUnit == i {
|
|
color = unitListSelectedColor
|
|
} else if t.UnitBtns[i].Hovered() {
|
|
color = unitListHighlightColor
|
|
}
|
|
paint.FillShape(gtx.Ops, color, clip.Rect{Max: image.Pt(gtx.Constraints.Min.X, gtx.Constraints.Min.Y)}.Op())
|
|
return D{Size: gtx.Constraints.Min}
|
|
}
|
|
return layout.Stack{Alignment: layout.W}.Layout(gtx,
|
|
layout.Stacked(bg),
|
|
layout.Expanded(labelStyle.Layout),
|
|
layout.Expanded(t.UnitBtns[i].Layout))
|
|
}
|
|
return t.UnitList.Layout(gtx, len(t.song.Patch.Instruments[t.CurrentInstrument].Units), listElem)
|
|
}
|
|
}
|