mirror of
https://github.com/vsariola/sointu.git
synced 2025-05-28 03:10:24 -04:00
fix(tracker/gioui): text.Shaper should not be a global variable
text.Shaper is not thread safe, which caused crash when adding multiple VSTI plugins to a DAW project. This change fixes that crash. Further refactorings need to consider where that text.Shaper should actually reside.
This commit is contained in:
parent
3c85f1155c
commit
a38a0f4235
@ -18,6 +18,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||||||
options
|
options
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- Crash when running more than one sointu VSTI plugins in parallel
|
||||||
- The scroll bars move in sync with the cursor.
|
- The scroll bars move in sync with the cursor.
|
||||||
- The stereo version of delay in the go virtual machine (executables / plugins
|
- The stereo version of delay in the go virtual machine (executables / plugins
|
||||||
not ending with -native) applied the left delay taps on the right channel, and
|
not ending with -native) applied the left delay taps on the right channel, and
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,6 +23,7 @@ type Alert struct {
|
|||||||
showTime time.Time
|
showTime time.Time
|
||||||
pos float64
|
pos float64
|
||||||
lastUpdate time.Time
|
lastUpdate time.Time
|
||||||
|
shaper *text.Shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlertType int
|
type AlertType int
|
||||||
@ -94,7 +96,7 @@ func (a *Alert) Layout(gtx C) D {
|
|||||||
}.Op())
|
}.Op())
|
||||||
return D{Size: gtx.Constraints.Min}
|
return D{Size: gtx.Constraints.Min}
|
||||||
}
|
}
|
||||||
labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16)}
|
labelStyle := LabelStyle{Text: a.showMessage, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16), Shaper: a.shaper}
|
||||||
return alertMargin.Layout(gtx, func(gtx C) D {
|
return alertMargin.Layout(gtx, func(gtx C) D {
|
||||||
return layout.S.Layout(gtx, func(gtx C) D {
|
return layout.S.Layout(gtx, func(gtx C) D {
|
||||||
defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
|
defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
|
||||||
|
@ -3,6 +3,7 @@ package gioui
|
|||||||
import (
|
import (
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget"
|
"gioui.org/widget"
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
@ -23,9 +24,10 @@ type DialogStyle struct {
|
|||||||
AltStyle material.ButtonStyle
|
AltStyle material.ButtonStyle
|
||||||
OkStyle material.ButtonStyle
|
OkStyle material.ButtonStyle
|
||||||
CancelStyle material.ButtonStyle
|
CancelStyle material.ButtonStyle
|
||||||
|
Shaper *text.Shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
func ConfirmDialog(th *material.Theme, dialog *Dialog, text string) DialogStyle {
|
func ConfirmDialog(th *material.Theme, dialog *Dialog, text string, shaper *text.Shaper) DialogStyle {
|
||||||
ret := DialogStyle{
|
ret := DialogStyle{
|
||||||
dialog: dialog,
|
dialog: dialog,
|
||||||
Text: text,
|
Text: text,
|
||||||
@ -33,6 +35,7 @@ func ConfirmDialog(th *material.Theme, dialog *Dialog, text string) DialogStyle
|
|||||||
AltStyle: HighEmphasisButton(th, &dialog.BtnAlt, "Alt"),
|
AltStyle: HighEmphasisButton(th, &dialog.BtnAlt, "Alt"),
|
||||||
OkStyle: HighEmphasisButton(th, &dialog.BtnOk, "Ok"),
|
OkStyle: HighEmphasisButton(th, &dialog.BtnOk, "Ok"),
|
||||||
CancelStyle: HighEmphasisButton(th, &dialog.BtnCancel, "Cancel"),
|
CancelStyle: HighEmphasisButton(th, &dialog.BtnCancel, "Cancel"),
|
||||||
|
Shaper: shaper,
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
@ -44,7 +47,7 @@ func (d *DialogStyle) Layout(gtx C) D {
|
|||||||
return Popup(&d.dialog.Visible).Layout(gtx, func(gtx C) D {
|
return Popup(&d.dialog.Visible).Layout(gtx, func(gtx C) D {
|
||||||
return d.Inset.Layout(gtx, func(gtx C) D {
|
return d.Inset.Layout(gtx, func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx,
|
||||||
layout.Rigid(Label(d.Text, highEmphasisTextColor)),
|
layout.Rigid(Label(d.Text, highEmphasisTextColor, d.Shaper)),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120))
|
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120))
|
||||||
if d.ShowAlt {
|
if d.ShowAlt {
|
||||||
|
@ -155,7 +155,7 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D {
|
|||||||
inset := layout.UniformInset(unit.Dp(6))
|
inset := layout.UniformInset(unit.Dp(6))
|
||||||
return inset.Layout(gtx, func(gtx C) D {
|
return inset.Layout(gtx, func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("OCT:", white)),
|
layout.Rigid(Label("OCT:", white, t.TextShaper)),
|
||||||
layout.Rigid(octave),
|
layout.Rigid(octave),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@ -193,7 +193,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D {
|
|||||||
loadInstrumentBtnStyle := IconButton(t.Theme, ie.loadInstrumentBtn, icons.FileFolderOpen, true, "Load instrument")
|
loadInstrumentBtnStyle := IconButton(t.Theme, ie.loadInstrumentBtn, icons.FileFolderOpen, true, "Load instrument")
|
||||||
deleteInstrumentBtnStyle := IconButton(t.Theme, ie.deleteInstrumentBtn, icons.ActionDelete, t.CanDeleteInstrument(), "Delete\ninstrument")
|
deleteInstrumentBtnStyle := IconButton(t.Theme, ie.deleteInstrumentBtn, icons.ActionDelete, t.CanDeleteInstrument(), "Delete\ninstrument")
|
||||||
|
|
||||||
m := PopupMenu(t.Theme, &ie.presetMenu)
|
m := t.PopupMenu(&ie.presetMenu)
|
||||||
|
|
||||||
for item, clicked := ie.presetMenu.Clicked(); clicked; item, clicked = ie.presetMenu.Clicked() {
|
for item, clicked := ie.presetMenu.Clicked(); clicked; item, clicked = ie.presetMenu.Clicked() {
|
||||||
t.SetInstrument(tracker.InstrumentPresets[item])
|
t.SetInstrument(tracker.InstrumentPresets[item])
|
||||||
@ -201,7 +201,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D {
|
|||||||
|
|
||||||
header := func(gtx C) D {
|
header := func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||||
layout.Rigid(Label("Voices: ", white)),
|
layout.Rigid(Label("Voices: ", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
maxRemain := t.MaxInstrumentVoices()
|
maxRemain := t.MaxInstrumentVoices()
|
||||||
t.InstrumentVoices.Value = t.Instrument().NumVoices
|
t.InstrumentVoices.Value = t.Instrument().NumVoices
|
||||||
@ -277,7 +277,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D {
|
|||||||
}
|
}
|
||||||
for ie.deleteInstrumentBtn.Clickable.Clicked() {
|
for ie.deleteInstrumentBtn.Clickable.Clicked() {
|
||||||
if t.CanDeleteInstrument() {
|
if t.CanDeleteInstrument() {
|
||||||
dialogStyle := ConfirmDialog(t.Theme, ie.confirmInstrDelete, "Are you sure you want to delete this instrument?")
|
dialogStyle := ConfirmDialog(t.Theme, ie.confirmInstrDelete, "Are you sure you want to delete this instrument?", t.TextShaper)
|
||||||
ie.confirmInstrDelete.Visible = true
|
ie.confirmInstrDelete.Visible = true
|
||||||
t.ModalDialog = dialogStyle.Layout
|
t.ModalDialog = dialogStyle.Layout
|
||||||
}
|
}
|
||||||
@ -303,7 +303,7 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D {
|
|||||||
element := func(gtx C, i int) D {
|
element := func(gtx C, i int) D {
|
||||||
gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36))
|
gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36))
|
||||||
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(30))
|
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(30))
|
||||||
grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center}
|
grabhandle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(10), Alignment: layout.Center, Shaper: t.TextShaper}
|
||||||
if i == t.InstrIndex() {
|
if i == t.InstrIndex() {
|
||||||
grabhandle.Text = ":::"
|
grabhandle.Text = ":::"
|
||||||
}
|
}
|
||||||
@ -346,7 +346,7 @@ func (ie *InstrumentEditor) layoutInstrumentNames(gtx C, t *Tracker) D {
|
|||||||
if text == "" {
|
if text == "" {
|
||||||
text = "Instr"
|
text = "Instr"
|
||||||
}
|
}
|
||||||
labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: color, FontSize: unit.Sp(12)}
|
labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: color, FontSize: unit.Sp(12), Shaper: t.TextShaper}
|
||||||
return layout.Center.Layout(gtx, labelStyle.Layout)
|
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.Inset{Left: unit.Dp(6), Right: unit.Dp(6)}.Layout(gtx, func(gtx C) D {
|
||||||
@ -470,14 +470,14 @@ func (ie *InstrumentEditor) layoutInstrumentEditor(gtx C, t *Tracker) D {
|
|||||||
editor.Font = labelDefaultFont
|
editor.Font = labelDefaultFont
|
||||||
unitName = editor.Layout
|
unitName = editor.Layout
|
||||||
} else {
|
} else {
|
||||||
unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12)}
|
unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper}
|
||||||
if unitNameLabel.Text == "" {
|
if unitNameLabel.Text == "" {
|
||||||
unitNameLabel.Text = "---"
|
unitNameLabel.Text = "---"
|
||||||
}
|
}
|
||||||
unitName = unitNameLabel.Layout
|
unitName = unitNameLabel.Layout
|
||||||
}
|
}
|
||||||
|
|
||||||
stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12)}
|
stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper}
|
||||||
rightMargin := layout.Inset{Right: unit.Dp(10)}
|
rightMargin := layout.Inset{Right: unit.Dp(10)}
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Flexed(1, unitName),
|
layout.Flexed(1, unitName),
|
||||||
|
@ -20,6 +20,7 @@ type LabelStyle struct {
|
|||||||
Alignment layout.Direction
|
Alignment layout.Direction
|
||||||
Font font.Font
|
Font font.Font
|
||||||
FontSize unit.Sp
|
FontSize unit.Sp
|
||||||
|
Shaper *text.Shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
|
func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
|
||||||
@ -31,7 +32,7 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
dims := widget.Label{
|
dims := widget.Label{
|
||||||
Alignment: text.Start,
|
Alignment: text.Start,
|
||||||
MaxLines: 1,
|
MaxLines: 1,
|
||||||
}.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{})
|
}.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{})
|
||||||
return layout.Dimensions{
|
return layout.Dimensions{
|
||||||
Size: dims.Size.Add(image.Pt(2, 2)),
|
Size: dims.Size.Add(image.Pt(2, 2)),
|
||||||
Baseline: dims.Baseline,
|
Baseline: dims.Baseline,
|
||||||
@ -42,11 +43,11 @@ func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions {
|
|||||||
return widget.Label{
|
return widget.Label{
|
||||||
Alignment: text.Start,
|
Alignment: text.Start,
|
||||||
MaxLines: 1,
|
MaxLines: 1,
|
||||||
}.Layout(gtx, textShaper, l.Font, l.FontSize, l.Text, op.CallOp{})
|
}.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{})
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func Label(str string, color color.NRGBA) layout.Widget {
|
func Label(str string, color color.NRGBA, shaper *text.Shaper) layout.Widget {
|
||||||
return LabelStyle{Text: str, Color: color, ShadeColor: black, Font: labelDefaultFont, FontSize: labelDefaultFontSize, Alignment: layout.W}.Layout
|
return LabelStyle{Text: str, Color: color, ShadeColor: black, Font: labelDefaultFont, FontSize: labelDefaultFontSize, Alignment: layout.W, Shaper: shaper}.Layout
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) {
|
|||||||
t.layoutBottom)
|
t.layoutBottom)
|
||||||
}
|
}
|
||||||
t.Alert.Layout(gtx)
|
t.Alert.Layout(gtx)
|
||||||
dstyle := ConfirmDialog(t.Theme, t.ConfirmSongDialog, "Do you want to save your changes to the song? Your changes will be lost if you don't save them.")
|
dstyle := ConfirmDialog(t.Theme, t.ConfirmSongDialog, "Do you want to save your changes to the song? Your changes will be lost if you don't save them.", t.TextShaper)
|
||||||
dstyle.ShowAlt = true
|
dstyle.ShowAlt = true
|
||||||
dstyle.OkStyle.Text = "Save"
|
dstyle.OkStyle.Text = "Save"
|
||||||
dstyle.AltStyle.Text = "Don't save"
|
dstyle.AltStyle.Text = "Don't save"
|
||||||
@ -56,7 +56,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) {
|
|||||||
for t.ConfirmSongDialog.BtnCancel.Clicked() {
|
for t.ConfirmSongDialog.BtnCancel.Clicked() {
|
||||||
t.ConfirmSongDialog.Visible = false
|
t.ConfirmSongDialog.Visible = false
|
||||||
}
|
}
|
||||||
dstyle = ConfirmDialog(t.Theme, t.WaveTypeDialog, "Export .wav in int16 or float32 sample format?")
|
dstyle = ConfirmDialog(t.Theme, t.WaveTypeDialog, "Export .wav in int16 or float32 sample format?", t.TextShaper)
|
||||||
dstyle.ShowAlt = true
|
dstyle.ShowAlt = true
|
||||||
dstyle.OkStyle.Text = "Int16"
|
dstyle.OkStyle.Text = "Int16"
|
||||||
dstyle.AltStyle.Text = "Float32"
|
dstyle.AltStyle.Text = "Float32"
|
||||||
|
@ -9,9 +9,9 @@ import (
|
|||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
"gioui.org/op/clip"
|
"gioui.org/op/clip"
|
||||||
"gioui.org/op/paint"
|
"gioui.org/op/paint"
|
||||||
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget"
|
"gioui.org/widget"
|
||||||
"gioui.org/widget/material"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Menu struct {
|
type Menu struct {
|
||||||
@ -33,6 +33,7 @@ type MenuStyle struct {
|
|||||||
FontSize unit.Sp
|
FontSize unit.Sp
|
||||||
IconSize unit.Dp
|
IconSize unit.Dp
|
||||||
HoverColor color.NRGBA
|
HoverColor color.NRGBA
|
||||||
|
Shaper *text.Shaper
|
||||||
}
|
}
|
||||||
|
|
||||||
type MenuItem struct {
|
type MenuItem struct {
|
||||||
@ -97,11 +98,11 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
|
|||||||
iconColor = mediumEmphasisTextColor
|
iconColor = mediumEmphasisTextColor
|
||||||
}
|
}
|
||||||
iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)}
|
iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)}
|
||||||
textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor}
|
textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor, Shaper: m.Shaper}
|
||||||
if item.Disabled {
|
if item.Disabled {
|
||||||
textLabel.Color = mediumEmphasisTextColor
|
textLabel.Color = mediumEmphasisTextColor
|
||||||
}
|
}
|
||||||
shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor}
|
shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor, Shaper: m.Shaper}
|
||||||
shortcutInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(12), Bottom: unit.Dp(2), Top: unit.Dp(2)}
|
shortcutInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(12), Bottom: unit.Dp(2), Top: unit.Dp(2)}
|
||||||
dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
dims := layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
@ -147,7 +148,7 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D {
|
|||||||
return popup.Layout(gtx, contents)
|
return popup.Layout(gtx, contents)
|
||||||
}
|
}
|
||||||
|
|
||||||
func PopupMenu(th *material.Theme, menu *Menu) MenuStyle {
|
func (t *Tracker) PopupMenu(menu *Menu) MenuStyle {
|
||||||
return MenuStyle{
|
return MenuStyle{
|
||||||
Menu: menu,
|
Menu: menu,
|
||||||
IconColor: white,
|
IconColor: white,
|
||||||
@ -156,5 +157,6 @@ func PopupMenu(th *material.Theme, menu *Menu) MenuStyle {
|
|||||||
FontSize: unit.Sp(16),
|
FontSize: unit.Sp(16),
|
||||||
IconSize: unit.Dp(16),
|
IconSize: unit.Dp(16),
|
||||||
HoverColor: menuHoverColor,
|
HoverColor: menuHoverColor,
|
||||||
|
Shaper: t.TextShaper,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
|
|||||||
} else {
|
} else {
|
||||||
title = "?"
|
title = "?"
|
||||||
}
|
}
|
||||||
LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx)
|
LabelStyle{Alignment: layout.N, Text: title, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: t.TextShaper}.Layout(gtx)
|
||||||
return D{Size: gtx.Constraints.Min}
|
return D{Size: gtx.Constraints.Min}
|
||||||
}
|
}
|
||||||
style := FilledDragList(t.Theme, oe.titleList, len(t.Song().Score.Tracks), elem, t.SwapTracks)
|
style := FilledDragList(t.Theme, oe.titleList, len(t.Song().Score.Tracks), elem, t.SwapTracks)
|
||||||
@ -211,7 +211,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
|
|||||||
paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}.Op())
|
paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, patternCellHeight)}.Op())
|
||||||
}
|
}
|
||||||
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
|
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
|
||||||
stack := op.Offset(image.Pt(patternRowMarkerWidth, 0)).Push(gtx.Ops)
|
stack := op.Offset(image.Pt(patternRowMarkerWidth, 0)).Push(gtx.Ops)
|
||||||
for i, track := range t.Song().Score.Tracks {
|
for i, track := range t.Song().Score.Tracks {
|
||||||
paint.FillShape(gtx.Ops, patternCellColor, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(patternCellWidth-1, patternCellHeight-1)}.Op())
|
paint.FillShape(gtx.Ops, patternCellColor, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(patternCellWidth-1, patternCellHeight-1)}.Op())
|
||||||
@ -220,7 +220,7 @@ func (oe *OrderEditor) doLayout(gtx C, t *Tracker) D {
|
|||||||
gtx := gtx
|
gtx := gtx
|
||||||
gtx.Constraints.Max.X = patternCellWidth
|
gtx.Constraints.Max.X = patternCellWidth
|
||||||
op.Offset(image.Pt(0, -2)).Add(gtx.Ops)
|
op.Offset(image.Pt(0, -2)).Add(gtx.Ops)
|
||||||
widget.Label{Alignment: text.Middle}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j]), op.CallOp{})
|
widget.Label{Alignment: text.Middle}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, patternIndexToString(track.Order[j]), op.CallOp{})
|
||||||
op.Offset(image.Pt(0, 2)).Add(gtx.Ops)
|
op.Offset(image.Pt(0, 2)).Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
point := tracker.ScorePoint{Track: i, ScoreRow: tracker.ScoreRow{Pattern: j}}
|
point := tracker.ScorePoint{Track: i, ScoreRow: tracker.ScoreRow{Pattern: j}}
|
||||||
|
@ -199,7 +199,7 @@ func (pe *ParamEditor) layoutUnitFooter(t *Tracker) layout.Widget {
|
|||||||
} else {
|
} else {
|
||||||
text = strings.Title(text)
|
text = strings.Title(text)
|
||||||
}
|
}
|
||||||
hintText := Label(text, white)
|
hintText := Label(text, white, t.TextShaper)
|
||||||
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
|
||||||
layout.Rigid(deleteUnitBtnStyle.Layout),
|
layout.Rigid(deleteUnitBtnStyle.Layout),
|
||||||
layout.Rigid(copyUnitBtnStyle.Layout),
|
layout.Rigid(copyUnitBtnStyle.Layout),
|
||||||
@ -226,7 +226,7 @@ func (pe *ParamEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D {
|
|||||||
if t.InstrumentEditor.unitTypeEditor.Focused() && !strings.HasPrefix(text, t.InstrumentEditor.unitTypeEditor.Text()) {
|
if t.InstrumentEditor.unitTypeEditor.Focused() && !strings.HasPrefix(text, t.InstrumentEditor.unitTypeEditor.Text()) {
|
||||||
return D{}
|
return D{}
|
||||||
}
|
}
|
||||||
labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12)}
|
labelStyle := LabelStyle{Text: text, ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.TextShaper}
|
||||||
bg := func(gtx C) D {
|
bg := func(gtx C) D {
|
||||||
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, 20))
|
gtx.Constraints = layout.Exact(image.Pt(gtx.Constraints.Max.X, 20))
|
||||||
var color color.NRGBA
|
var color color.NRGBA
|
||||||
|
@ -52,7 +52,7 @@ func (p ParameterStyle) Layout(gtx C) D {
|
|||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return p.ParameterWidget.labelBtn.Layout(gtx, func(gtx C) D {
|
return p.ParameterWidget.labelBtn.Layout(gtx, func(gtx C) D {
|
||||||
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(110))
|
gtx.Constraints.Min.X = gtx.Dp(unit.Dp(110))
|
||||||
return layout.E.Layout(gtx, Label(p.Parameter.Name, white))
|
return layout.E.Layout(gtx, Label(p.Parameter.Name, white, p.tracker.TextShaper))
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
@ -154,7 +154,7 @@ func (p ParameterStyle) Layout(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
if p.Parameter.Type != tracker.IDParameter {
|
if p.Parameter.Type != tracker.IDParameter {
|
||||||
return Label(p.Parameter.Hint, white)(gtx)
|
return Label(p.Parameter.Hint, white, p.tracker.TextShaper)(gtx)
|
||||||
}
|
}
|
||||||
return D{}
|
return D{}
|
||||||
}),
|
}),
|
||||||
|
@ -43,7 +43,7 @@ func (t *Tracker) layoutRowMarkers(gtx C) D {
|
|||||||
}
|
}
|
||||||
if j == 0 {
|
if j == 0 {
|
||||||
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
|
paint.ColorOp{Color: rowMarkerPatternTextColor}.Add(gtx.Ops)
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i)), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", i)), op.CallOp{})
|
||||||
}
|
}
|
||||||
if t.TrackEditor.Focused() && songRow == cursorSongRow {
|
if t.TrackEditor.Focused() && songRow == cursorSongRow {
|
||||||
paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops)
|
paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops)
|
||||||
@ -51,7 +51,7 @@ func (t *Tracker) layoutRowMarkers(gtx C) D {
|
|||||||
paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops)
|
paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
op.Offset(image.Pt(rowMarkerWidth/2, 0)).Add(gtx.Ops)
|
op.Offset(image.Pt(rowMarkerWidth/2, 0)).Add(gtx.Ops)
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{})
|
||||||
op.Offset(image.Pt(-rowMarkerWidth/2, trackRowHeight)).Add(gtx.Ops)
|
op.Offset(image.Pt(-rowMarkerWidth/2, trackRowHeight)).Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,7 @@ func (t *Tracker) layoutMenu(title string, clickable *widget.Clickable, menu *Me
|
|||||||
for clickable.Clicked() {
|
for clickable.Clicked() {
|
||||||
menu.Visible = true
|
menu.Visible = true
|
||||||
}
|
}
|
||||||
m := PopupMenu(t.Theme, menu)
|
m := t.PopupMenu(menu)
|
||||||
return func(gtx C) D {
|
return func(gtx C) D {
|
||||||
defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
|
defer op.Offset(image.Point{}).Push(gtx.Ops).Pop()
|
||||||
titleBtn := material.Button(t.Theme, clickable, title)
|
titleBtn := material.Button(t.Theme, clickable, title)
|
||||||
@ -145,7 +145,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
|||||||
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("LEN:", white)),
|
layout.Rigid(Label("LEN:", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
t.SongLength.Value = t.Song().Score.Length
|
t.SongLength.Value = t.Song().Score.Length
|
||||||
numStyle := NumericUpDown(t.Theme, t.SongLength, 1, math.MaxInt32, "Song length")
|
numStyle := NumericUpDown(t.Theme, t.SongLength, 1, math.MaxInt32, "Song length")
|
||||||
@ -159,7 +159,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("BPM:", white)),
|
layout.Rigid(Label("BPM:", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
t.BPM.Value = t.Song().BPM
|
t.BPM.Value = t.Song().BPM
|
||||||
numStyle := NumericUpDown(t.Theme, t.BPM, 1, 999, "Beats per minute")
|
numStyle := NumericUpDown(t.Theme, t.BPM, 1, 999, "Beats per minute")
|
||||||
@ -173,7 +173,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("RPP:", white)),
|
layout.Rigid(Label("RPP:", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
t.RowsPerPattern.Value = t.Song().Score.RowsPerPattern
|
t.RowsPerPattern.Value = t.Song().Score.RowsPerPattern
|
||||||
numStyle := NumericUpDown(t.Theme, t.RowsPerPattern, 1, 255, "Rows per pattern")
|
numStyle := NumericUpDown(t.Theme, t.RowsPerPattern, 1, 255, "Rows per pattern")
|
||||||
@ -187,7 +187,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("RPB:", white)),
|
layout.Rigid(Label("RPB:", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
t.RowsPerBeat.Value = t.Song().RowsPerBeat
|
t.RowsPerBeat.Value = t.Song().RowsPerBeat
|
||||||
numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32, "Rows per beat")
|
numStyle := NumericUpDown(t.Theme, t.RowsPerBeat, 1, 32, "Rows per beat")
|
||||||
@ -201,7 +201,7 @@ func (t *Tracker) layoutSongOptions(gtx C) D {
|
|||||||
}),
|
}),
|
||||||
layout.Rigid(func(gtx C) D {
|
layout.Rigid(func(gtx C) D {
|
||||||
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
return layout.Flex{Axis: layout.Horizontal}.Layout(gtx,
|
||||||
layout.Rigid(Label("STP:", white)),
|
layout.Rigid(Label("STP:", white, t.TextShaper)),
|
||||||
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
layout.Rigid(func(gtx layout.Context) layout.Dimensions {
|
||||||
numStyle := NumericUpDown(t.Theme, t.Step, 0, 8, "Cursor step")
|
numStyle := NumericUpDown(t.Theme, t.Step, 0, 8, "Cursor step")
|
||||||
numStyle.UnitsPerStep = unit.Dp(20)
|
numStyle.UnitsPerStep = unit.Dp(20)
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var fontCollection []text.FontFace = gofont.Collection()
|
var fontCollection []text.FontFace = gofont.Collection()
|
||||||
var textShaper = text.NewShaper(text.WithCollection(fontCollection))
|
|
||||||
|
|
||||||
var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
|
var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255}
|
||||||
var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255}
|
var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255}
|
||||||
|
@ -253,7 +253,7 @@ func (te *TrackEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions
|
|||||||
layout.Rigid(subtractOctaveBtnStyle.Layout),
|
layout.Rigid(subtractOctaveBtnStyle.Layout),
|
||||||
layout.Rigid(noteOffBtnStyle.Layout),
|
layout.Rigid(noteOffBtnStyle.Layout),
|
||||||
layout.Rigid(hexCheckBoxStyle.Layout),
|
layout.Rigid(hexCheckBoxStyle.Layout),
|
||||||
layout.Rigid(Label(" Voices:", white)),
|
layout.Rigid(Label(" Voices:", white, t.TextShaper)),
|
||||||
layout.Rigid(voiceUpDown),
|
layout.Rigid(voiceUpDown),
|
||||||
layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }),
|
layout.Flexed(1, func(gtx C) D { return layout.Dimensions{Size: gtx.Constraints.Min} }),
|
||||||
layout.Rigid(deleteTrackBtnStyle.Layout),
|
layout.Rigid(deleteTrackBtnStyle.Layout),
|
||||||
@ -388,7 +388,7 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gtx.Constraints.Max.X = trackColWidth
|
gtx.Constraints.Max.X = trackColWidth
|
||||||
LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor}.Layout(gtx)
|
LabelStyle{Alignment: layout.N, Text: instrName, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: t.TextShaper}.Layout(gtx)
|
||||||
op.Offset(image.Point{trackColWidth, 0}).Add(gtx.Ops)
|
op.Offset(image.Point{trackColWidth, 0}).Add(gtx.Ops)
|
||||||
curVoice += trk.NumVoices
|
curVoice += trk.NumVoices
|
||||||
}
|
}
|
||||||
@ -461,11 +461,11 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
|
|||||||
}
|
}
|
||||||
if s >= 0 && patRow == 0 {
|
if s >= 0 && patRow == 0 {
|
||||||
paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops)
|
paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops)
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{})
|
||||||
}
|
}
|
||||||
if s >= 0 && patRow == 1 && t.IsPatternUnique(trkIndex, s) {
|
if s >= 0 && patRow == 1 && t.IsPatternUnique(trkIndex, s) {
|
||||||
paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops)
|
paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops)
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, "*", op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, "*", op.CallOp{})
|
||||||
}
|
}
|
||||||
op.Offset(image.Point{patmarkWidth, 0}).Add(gtx.Ops)
|
op.Offset(image.Point{patmarkWidth, 0}).Add(gtx.Ops)
|
||||||
if te.Focused() && t.Cursor().Row == patRow && t.Cursor().Pattern == pat {
|
if te.Focused() && t.Cursor().Row == patRow && t.Cursor().Pattern == pat {
|
||||||
@ -487,9 +487,9 @@ func (te *TrackEditor) layoutTracks(gtx C, t *Tracker) D {
|
|||||||
default:
|
default:
|
||||||
text = fmt.Sprintf("%02x", c)
|
text = fmt.Sprintf("%02x", c)
|
||||||
}
|
}
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, strings.ToUpper(text), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, strings.ToUpper(text), op.CallOp{})
|
||||||
} else {
|
} else {
|
||||||
widget.Label{}.Layout(gtx, textShaper, trackerFont, trackerFontSize, noteStr(c), op.CallOp{})
|
widget.Label{}.Layout(gtx, t.TextShaper, trackerFont, trackerFontSize, noteStr(c), op.CallOp{})
|
||||||
}
|
}
|
||||||
op.Offset(image.Point{-patmarkWidth, trackRowHeight}).Add(gtx.Ops)
|
op.Offset(image.Point{-patmarkWidth, trackRowHeight}).Add(gtx.Ops)
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"gioui.org/io/system"
|
"gioui.org/io/system"
|
||||||
"gioui.org/layout"
|
"gioui.org/layout"
|
||||||
"gioui.org/op"
|
"gioui.org/op"
|
||||||
|
"gioui.org/text"
|
||||||
"gioui.org/unit"
|
"gioui.org/unit"
|
||||||
"gioui.org/widget"
|
"gioui.org/widget"
|
||||||
"gioui.org/widget/material"
|
"gioui.org/widget/material"
|
||||||
@ -55,6 +56,8 @@ type Tracker struct {
|
|||||||
TrackEditor *TrackEditor
|
TrackEditor *TrackEditor
|
||||||
Explorer *explorer.Explorer
|
Explorer *explorer.Explorer
|
||||||
|
|
||||||
|
TextShaper *text.Shaper
|
||||||
|
|
||||||
lastAvgVolume tracker.Volume
|
lastAvgVolume tracker.Volume
|
||||||
lastPeakVolume tracker.Volume
|
lastPeakVolume tracker.Volume
|
||||||
|
|
||||||
@ -153,6 +156,8 @@ func NewTracker(model *tracker.Model, synther sointu.Synther) *Tracker {
|
|||||||
marshalRecoveryChannel: make(chan (chan []byte)),
|
marshalRecoveryChannel: make(chan (chan []byte)),
|
||||||
unmarshalRecoveryChannel: make(chan []byte),
|
unmarshalRecoveryChannel: make(chan []byte),
|
||||||
}
|
}
|
||||||
|
t.TextShaper = text.NewShaper(text.WithCollection(fontCollection))
|
||||||
|
t.Alert.shaper = t.TextShaper
|
||||||
t.Theme.Palette.Fg = primaryColor
|
t.Theme.Palette.Fg = primaryColor
|
||||||
t.Theme.Palette.ContrastFg = black
|
t.Theme.Palette.ContrastFg = black
|
||||||
t.TrackEditor.Focus()
|
t.TrackEditor.Focus()
|
||||||
|
Loading…
Reference in New Issue
Block a user