From dd564815d4d3f62b3a1443141d956a7bd7e536a5 Mon Sep 17 00:00:00 2001 From: "5684185+vsariola@users.noreply.github.com" <5684185+vsariola@users.noreply.github.com> Date: Fri, 2 May 2025 22:49:52 +0300 Subject: [PATCH] drafting --- tracker/gioui/buttons.go | 4 +- tracker/gioui/dialog.go | 22 ++++----- tracker/gioui/instrument_editor.go | 45 +++++++++--------- tracker/gioui/label.go | 56 +++++++++++----------- tracker/gioui/menu.go | 13 +++--- tracker/gioui/note_editor.go | 10 +--- tracker/gioui/order_editor.go | 8 +--- tracker/gioui/oscilloscope.go | 4 +- tracker/gioui/popup_alert.go | 27 +++++------ tracker/gioui/songpanel.go | 75 +++++++++++++----------------- tracker/gioui/theme.go | 47 +++++++++++++++++++ tracker/gioui/theme.yml | 74 +++++++++++++++++++++++++++-- tracker/gioui/tracker.go | 8 ++-- tracker/gioui/unit_editor.go | 38 +++++++-------- 14 files changed, 259 insertions(+), 172 deletions(-) diff --git a/tracker/gioui/buttons.go b/tracker/gioui/buttons.go index 1d868fc..870ed82 100644 --- a/tracker/gioui/buttons.go +++ b/tracker/gioui/buttons.go @@ -259,6 +259,7 @@ type ButtonStyle struct { TextSize unit.Sp Background color.NRGBA CornerRadius unit.Dp + Height unit.Dp Inset layout.Inset } @@ -304,8 +305,9 @@ func IconButton(th *material.Theme, button *Clickable, icon *widget.Icon, descri } } -func (b Button) Layout(gtx layout.Context) layout.Dimensions { +func (b *Button) Layout(gtx layout.Context) layout.Dimensions { min := gtx.Constraints.Min + min.Y = gtx.Dp(b.Height) return b.Button.Layout(gtx, func(gtx layout.Context) layout.Dimensions { semantic.Button.Add(gtx.Ops) return layout.Background{}.Layout(gtx, diff --git a/tracker/gioui/dialog.go b/tracker/gioui/dialog.go index 2577a67..5a3326d 100644 --- a/tracker/gioui/dialog.go +++ b/tracker/gioui/dialog.go @@ -4,7 +4,6 @@ import ( "gioui.org/io/key" "gioui.org/layout" "gioui.org/op/paint" - "gioui.org/text" "gioui.org/unit" "gioui.org/widget" "gioui.org/widget/material" @@ -28,7 +27,7 @@ type DialogStyle struct { AltStyle material.ButtonStyle OkStyle material.ButtonStyle CancelStyle material.ButtonStyle - Shaper *text.Shaper + Theme *Theme } func NewDialog(ok, alt, cancel tracker.Action) *Dialog { @@ -37,22 +36,22 @@ func NewDialog(ok, alt, cancel tracker.Action) *Dialog { return ret } -func ConfirmDialog(gtx C, th *material.Theme, dialog *Dialog, title, text string) DialogStyle { +func ConfirmDialog(gtx C, th *Theme, dialog *Dialog, title, text string) DialogStyle { ret := DialogStyle{ dialog: dialog, Title: title, Text: text, Inset: layout.Inset{Top: unit.Dp(12), Bottom: unit.Dp(12), Left: unit.Dp(20), Right: unit.Dp(20)}, TextInset: layout.Inset{Top: unit.Dp(12), Bottom: unit.Dp(12)}, - AltStyle: material.Button(th, &dialog.BtnAlt, "Alt"), - OkStyle: material.Button(th, &dialog.BtnOk, "Ok"), - CancelStyle: material.Button(th, &dialog.BtnCancel, "Cancel"), - Shaper: th.Shaper, + AltStyle: material.Button(&th.Material, &dialog.BtnAlt, "Alt"), + OkStyle: material.Button(&th.Material, &dialog.BtnOk, "Ok"), + CancelStyle: material.Button(&th.Material, &dialog.BtnCancel, "Cancel"), + Theme: th, } for _, b := range [...]*material.ButtonStyle{&ret.AltStyle, &ret.OkStyle, &ret.CancelStyle} { b.Background = transparent b.Inset = layout.UniformInset(unit.Dp(6)) - b.Color = th.Palette.Fg + b.Color = th.Material.Palette.Fg } return ret } @@ -107,16 +106,13 @@ func (d *DialogStyle) Layout(gtx C) D { } d.dialog.handleKeys(gtx) paint.Fill(gtx.Ops, dialogBgColor) - text := func(gtx C) D { - return d.TextInset.Layout(gtx, LabelStyle{Text: d.Text, Color: highEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(14), Shaper: d.Shaper}.Layout) - } visible := true return layout.Center.Layout(gtx, func(gtx C) D { return Popup(&visible).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, - layout.Rigid(Label(d.Title, highEmphasisTextColor, d.Shaper)), - layout.Rigid(text), + layout.Rigid(Label(d.Theme, &d.Theme.Dialog.Title, d.Title).Layout), + layout.Rigid(Label(d.Theme, &d.Theme.Dialog.Text, d.Text).Layout), layout.Rigid(func(gtx C) D { return layout.E.Layout(gtx, func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(unit.Dp(120)) diff --git a/tracker/gioui/instrument_editor.go b/tracker/gioui/instrument_editor.go index 315bc30..9caa8c0 100644 --- a/tracker/gioui/instrument_editor.go +++ b/tracker/gioui/instrument_editor.go @@ -144,7 +144,7 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D { return ie.layoutInstrumentList(gtx, t) }), layout.Rigid(layout.Spacer{Width: 10}.Layout), - layout.Rigid(LabelStyle{Text: "Octave", Color: disabledTextColor, Alignment: layout.W, FontSize: t.Theme.Material.TextSize * 14.0 / 16.0, Shaper: t.Theme.Material.Shaper}.Layout), + layout.Rigid(Label(t.Theme, &t.Theme.InstrumentEditor.Octave, "Octave").Layout), layout.Rigid(layout.Spacer{Width: 4}.Layout), layout.Rigid(octave), layout.Rigid(func(gtx C) D { @@ -186,7 +186,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { soloBtnStyle := ToggleIcon(gtx, &t.Theme.Material, ie.soloBtn, icons.SocialGroup, icons.SocialPerson, ie.soloHint, ie.unsoloHint) muteBtnStyle := ToggleIcon(gtx, &t.Theme.Material, ie.muteBtn, icons.AVVolumeUp, icons.AVVolumeOff, ie.muteHint, ie.unmuteHint) - m := PopupMenu(&ie.presetMenu, t.Theme.Material.Shaper) + m := PopupMenu(t.Theme, &ie.presetMenu) for ie.copyInstrumentBtn.Clickable.Clicked(gtx) { if contents, ok := t.Instruments().List().CopyElements(); ok { @@ -214,7 +214,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { header := func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(layout.Spacer{Width: 6}.Layout), - layout.Rigid(LabelStyle{Text: "Voices", Color: disabledTextColor, Alignment: layout.W, FontSize: t.Theme.Material.TextSize * 14.0 / 16.0, Shaper: t.Theme.Material.Shaper}.Layout), + layout.Rigid(Label(t.Theme, &t.Theme.InstrumentEditor.Voices, "Voices").Layout), layout.Rigid(layout.Spacer{Width: 4}.Layout), layout.Rigid(func(gtx layout.Context) layout.Dimensions { numStyle := NumUpDown(t.Theme, t.InstrumentVoices, "Number of voices for this instrument") @@ -274,29 +274,30 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { element := func(gtx C, i int) D { gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36)) gtx.Constraints.Min.X = gtx.Dp(unit.Dp(30)) - grabhandle := LabelStyle{Text: strconv.Itoa(i + 1), ShadeColor: black, Color: mediumEmphasisTextColor, FontSize: unit.Sp(10), Alignment: layout.Center, Shaper: t.Theme.Material.Shaper} + grabhandle := Label(t.Theme, &t.Theme.InstrumentEditor.InstrumentNumber, strconv.Itoa(i+1)) label := func(gtx C) D { name, level, mute, ok := (*tracker.Instruments)(t.Model).Item(i) if !ok { - labelStyle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} + labelStyle := Label(t.Theme, &t.Theme.InstrumentEditor.InstrumentName, "") return layout.Center.Layout(gtx, labelStyle.Layout) } k := byte(255 - level*127) color := color.NRGBA{R: 255, G: k, B: 255, A: 255} + s := t.Theme.InstrumentEditor.InstrumentName + if mute { + s = t.Theme.InstrumentEditor.InstrumentNameMuted + } + s.Color = color if i == ie.instrumentDragList.TrackerList.Selected() { ie.nameEditor.SetText(name) for ie.nameEditor.Submitted(gtx) || ie.nameEditor.Cancelled(gtx) { ie.instrumentDragList.Focus() } style := MaterialEditor(&t.Theme.Material, ie.nameEditor, "Instr") - style.Color = color + style.Color = s.Color style.HintColor = instrumentNameHintColor - style.TextSize = unit.Sp(12) - style.Font = labelDefaultFont - if mute { - style.Color = disabledTextColor - style.Font.Style = font.Italic - } + style.TextSize = s.TextSize + style.Font = s.Font dims := layout.Center.Layout(gtx, func(gtx C) D { defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop() return style.Layout(gtx) @@ -307,12 +308,7 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { if name == "" { name = "Instr" } - labelStyle := LabelStyle{Text: name, ShadeColor: black, Color: color, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} - if mute { - labelStyle.Color = disabledTextColor - labelStyle.Font.Style = font.Italic - } - return layout.Center.Layout(gtx, labelStyle.Layout) + return layout.Center.Layout(gtx, Label(t.Theme, &s, name).Layout) } return layout.Inset{Left: unit.Dp(6), Right: unit.Dp(6), Top: unit.Dp(4)}.Layout(gtx, func(gtx C) D { return layout.Flex{Axis: layout.Vertical, Alignment: layout.Middle}.Layout(gtx, @@ -409,7 +405,8 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { f.Style = font.Italic } - stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} + stackLabel := Label(t.Theme, &t.Theme.InstrumentEditor.UnitList.Stack, stackText) + rightMargin := layout.Inset{Right: unit.Dp(10)} return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -444,15 +441,15 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { str.Set(ie.searchEditor.Text()) return ret } else { - unitNameLabel := LabelStyle{Text: u.Type, ShadeColor: black, Color: color, Font: f, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} - if unitNameLabel.Text == "" { - unitNameLabel.Text = "---" + text := u.Type + if text == "" { + text = "---" } - return unitNameLabel.Layout(gtx) + return Label(t.Theme, &t.Theme.InstrumentEditor.UnitList.Name, text).Layout(gtx) } }), layout.Flexed(1, func(gtx C) D { - unitNameLabel := LabelStyle{Text: u.Comment, ShadeColor: black, Color: mediumEmphasisTextColor, Font: f, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} + unitNameLabel := Label(t.Theme, &t.Theme.InstrumentEditor.UnitList.Comment, u.Comment) inset := layout.Inset{Left: unit.Dp(5)} return inset.Layout(gtx, unitNameLabel.Layout) }), diff --git a/tracker/gioui/label.go b/tracker/gioui/label.go index 1c2081a..fa97e22 100644 --- a/tracker/gioui/label.go +++ b/tracker/gioui/label.go @@ -5,7 +5,6 @@ import ( "image/color" "gioui.org/font" - "gioui.org/layout" "gioui.org/op" "gioui.org/op/paint" "gioui.org/text" @@ -14,37 +13,38 @@ import ( ) type LabelStyle struct { - Text string - Color color.NRGBA - ShadeColor color.NRGBA - Alignment layout.Direction - Font font.Font - FontSize unit.Sp - Shaper *text.Shaper + Color color.NRGBA + ShadowColor color.NRGBA + Alignment text.Alignment + Font font.Font + TextSize unit.Sp } -func (l LabelStyle) Layout(gtx layout.Context) layout.Dimensions { - return l.Alignment.Layout(gtx, func(gtx C) D { - gtx.Constraints.Min = image.Point{} - paint.ColorOp{Color: l.ShadeColor}.Add(gtx.Ops) +type LabelWidget struct { + Text string + Shaper *text.Shaper + LabelStyle +} + +func (l LabelWidget) Layout(gtx C) D { + textColorMacro := op.Record(gtx.Ops) + paint.ColorOp{Color: l.Color}.Add(gtx.Ops) + textColor := textColorMacro.Stop() + t := widget.Label{ + Alignment: l.Alignment, + MaxLines: 1, + } + if l.ShadowColor.A > 0 { + shadowColorMacro := op.Record(gtx.Ops) + paint.ColorOp{Color: l.ShadowColor}.Add(gtx.Ops) + shadowColor := shadowColorMacro.Stop() offs := op.Offset(image.Pt(2, 2)).Push(gtx.Ops) - widget.Label{ - Alignment: text.Start, - MaxLines: 1, - }.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{}) + t.Layout(gtx, l.Shaper, l.Font, l.TextSize, l.Text, shadowColor) offs.Pop() - paint.ColorOp{Color: l.Color}.Add(gtx.Ops) - dims := widget.Label{ - Alignment: text.Start, - MaxLines: 1, - }.Layout(gtx, l.Shaper, l.Font, l.FontSize, l.Text, op.CallOp{}) - return layout.Dimensions{ - Size: dims.Size, - Baseline: dims.Baseline, - } - }) + } + return t.Layout(gtx, l.Shaper, l.Font, l.TextSize, l.Text, textColor) } -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, Shaper: shaper}.Layout +func Label(th *Theme, style *LabelStyle, txt string) LabelWidget { + return LabelWidget{Text: txt, Shaper: th.Material.Shaper, LabelStyle: *style} } diff --git a/tracker/gioui/menu.go b/tracker/gioui/menu.go index b1090b0..5ada9c6 100644 --- a/tracker/gioui/menu.go +++ b/tracker/gioui/menu.go @@ -10,7 +10,6 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" - "gioui.org/text" "gioui.org/unit" "github.com/vsariola/sointu/tracker" ) @@ -33,7 +32,7 @@ type MenuStyle struct { FontSize unit.Sp IconSize unit.Dp HoverColor color.NRGBA - Shaper *text.Shaper + Theme *Theme } type MenuItem struct { @@ -105,11 +104,11 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { iconColor = mediumEmphasisTextColor } iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)} - textLabel := LabelStyle{Text: item.Text, FontSize: m.FontSize, Color: m.TextColor, Shaper: m.Shaper} + textLabel := Label(m.Theme, &m.Theme.Menu.Text, item.Text) if !item.Doer.Allowed() { textLabel.Color = mediumEmphasisTextColor } - shortcutLabel := LabelStyle{Text: item.ShortcutText, FontSize: m.FontSize, Color: m.ShortCutColor, Shaper: m.Shaper} + shortcutLabel := Label(m.Theme, &m.Theme.Menu.ShortCut, item.ShortcutText) 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, layout.Rigid(func(gtx C) D { @@ -153,7 +152,7 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { return popup.Layout(gtx, contents) } -func PopupMenu(menu *Menu, shaper *text.Shaper) MenuStyle { +func PopupMenu(th *Theme, menu *Menu) MenuStyle { return MenuStyle{ Menu: menu, IconColor: white, @@ -162,7 +161,7 @@ func PopupMenu(menu *Menu, shaper *text.Shaper) MenuStyle { FontSize: unit.Sp(16), IconSize: unit.Dp(16), HoverColor: menuHoverColor, - Shaper: shaper, + Theme: th, } } @@ -170,7 +169,7 @@ func (tr *Tracker) layoutMenu(gtx C, title string, clickable *Clickable, menu *M for clickable.Clicked(gtx) { menu.Visible = true } - m := PopupMenu(menu, tr.Theme.Material.Shaper) + m := PopupMenu(tr.Theme, menu) return func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() titleBtn := Btn(tr.Theme, &tr.Theme.MenuButton, clickable, title) diff --git a/tracker/gioui/note_editor.go b/tracker/gioui/note_editor.go index b7707ef..259e36a 100644 --- a/tracker/gioui/note_editor.go +++ b/tracker/gioui/note_editor.go @@ -176,7 +176,7 @@ func (te *NoteEditor) layoutButtons(gtx C, t *Tracker) D { layout.Rigid(effectBtnStyle.Layout), layout.Rigid(uniqueBtnStyle.Layout), layout.Rigid(layout.Spacer{Width: 10}.Layout), - layout.Rigid(LabelStyle{Text: "Voices", Color: disabledTextColor, Alignment: layout.W, FontSize: t.Theme.Material.TextSize * 14.0 / 16.0, Shaper: t.Theme.Material.Shaper}.Layout), + layout.Rigid(Label(t.Theme, &t.Theme.NoteEditor.Header, "Voices").Layout), layout.Rigid(layout.Spacer{Width: 4}.Layout), layout.Rigid(voiceUpDown), layout.Rigid(splitTrackBtnStyle.Layout), @@ -224,13 +224,7 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { colTitle := func(gtx C, i int) D { h := gtx.Dp(trackColTitleHeight) gtx.Constraints = layout.Exact(image.Pt(pxWidth, h)) - LabelStyle{ - Alignment: layout.N, - Text: t.Model.TrackTitle(i), - FontSize: unit.Sp(12), - Color: mediumEmphasisTextColor, - Shaper: t.Theme.Material.Shaper, - }.Layout(gtx) + Label(t.Theme, &t.Theme.NoteEditor.TrackTitle, t.Model.TrackTitle(i)).Layout(gtx) return D{Size: image.Pt(pxWidth, h)} } diff --git a/tracker/gioui/order_editor.go b/tracker/gioui/order_editor.go index 7848273..a27bb1e 100644 --- a/tracker/gioui/order_editor.go +++ b/tracker/gioui/order_editor.go @@ -68,13 +68,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { defer op.Offset(image.Pt(0, -2)).Push(gtx.Ops).Pop() defer op.Affine(f32.Affine2D{}.Rotate(f32.Pt(0, 0), -90*math.Pi/180).Offset(f32.Point{X: 0, Y: float32(h)})).Push(gtx.Ops).Pop() gtx.Constraints = layout.Exact(image.Pt(1e6, 1e6)) - LabelStyle{ - Alignment: layout.NW, - Text: t.Model.TrackTitle(i), - FontSize: unit.Sp(12), - Color: mediumEmphasisTextColor, - Shaper: t.Theme.Material.Shaper, - }.Layout(gtx) + Label(t.Theme, &t.Theme.OrderEditor.TrackTitle, t.Model.TrackTitle(i)).Layout(gtx) return D{Size: image.Pt(gtx.Dp(patternCellWidth), h)} } diff --git a/tracker/gioui/oscilloscope.go b/tracker/gioui/oscilloscope.go index 2dd8484..06ea35f 100644 --- a/tracker/gioui/oscilloscope.go +++ b/tracker/gioui/oscilloscope.go @@ -70,7 +70,7 @@ func (s *Oscilloscope) Layout(gtx C) D { layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(leftSpacer), - layout.Rigid(LabelStyle{Text: "Trigger", Color: disabledTextColor, Alignment: layout.W, FontSize: s.Theme.Material.TextSize * 14.0 / 16.0, Shaper: s.Theme.Material.Shaper}.Layout), + layout.Rigid(Label(s.Theme, &s.Theme.SongPanel.RowHeader, "Trigger").Layout), layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(onceBtnStyle.Layout), layout.Rigid(triggerChannelStyle.Layout), @@ -80,7 +80,7 @@ func (s *Oscilloscope) Layout(gtx C) D { layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(leftSpacer), - layout.Rigid(LabelStyle{Text: "Buffer", Color: disabledTextColor, Alignment: layout.W, FontSize: s.Theme.Material.TextSize * 14.0 / 16.0, Shaper: s.Theme.Material.Shaper}.Layout), + layout.Rigid(Label(s.Theme, &s.Theme.SongPanel.RowHeader, "Buffer").Layout), layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(wrapBtnStyle.Layout), layout.Rigid(lengthNumberStyle.Layout), diff --git a/tracker/gioui/popup_alert.go b/tracker/gioui/popup_alert.go index 0971f0b..f23ad47 100644 --- a/tracker/gioui/popup_alert.go +++ b/tracker/gioui/popup_alert.go @@ -20,14 +20,19 @@ type PopupAlert struct { shaper *text.Shaper } +type PopupAlertStyle struct { + Bg color.NRGBA + Text LabelStyle +} + var alertMargin = layout.UniformInset(unit.Dp(6)) var alertInset = layout.UniformInset(unit.Dp(6)) -func NewPopupAlert(alerts *tracker.Alerts, shaper *text.Shaper) *PopupAlert { - return &PopupAlert{alerts: alerts, shaper: shaper, prevUpdate: time.Now()} +func NewPopupAlert(alerts *tracker.Alerts) *PopupAlert { + return &PopupAlert{alerts: alerts, prevUpdate: time.Now()} } -func (a *PopupAlert) Layout(gtx C) D { +func (a *PopupAlert) Layout(gtx C, th *Theme) D { now := time.Now() if a.alerts.Update(now.Sub(a.prevUpdate)) { gtx.Execute(op.InvalidateCmd{At: now.Add(50 * time.Millisecond)}) @@ -36,26 +41,22 @@ func (a *PopupAlert) Layout(gtx C) D { var totalY float64 = float64(gtx.Dp(38)) for _, alert := range a.alerts.Iterate { - var color, textColor, shadeColor color.NRGBA + var alertStyle *PopupAlertStyle switch alert.Priority { case tracker.Warning: - color = warningColor - textColor = black + alertStyle = &th.Alert.Warning case tracker.Error: - color = errorColor - textColor = black + alertStyle = &th.Alert.Error default: - color = popupSurfaceColor - textColor = white - shadeColor = black + alertStyle = &th.Alert.Info } bgWidget := func(gtx C) D { - paint.FillShape(gtx.Ops, color, clip.Rect{ + paint.FillShape(gtx.Ops, alertStyle.Bg, clip.Rect{ Max: gtx.Constraints.Min, }.Op()) return D{Size: gtx.Constraints.Min} } - labelStyle := LabelStyle{Text: alert.Message, Color: textColor, ShadeColor: shadeColor, Font: labelDefaultFont, Alignment: layout.Center, FontSize: unit.Sp(16), Shaper: a.shaper} + labelStyle := Label(th, &alertStyle.Text, alert.Message) alertMargin.Layout(gtx, func(gtx C) D { return layout.S.Layout(gtx, func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() diff --git a/tracker/gioui/songpanel.go b/tracker/gioui/songpanel.go index a55e94e..c438f27 100644 --- a/tracker/gioui/songpanel.go +++ b/tracker/gioui/songpanel.go @@ -97,8 +97,6 @@ func (s *SongPanel) Layout(gtx C, t *Tracker) D { func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { paint.FillShape(gtx.Ops, songSurfaceColor, clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Op()) - scopeStyle := Scope(t.Scope, tr.SignalAnalyzer().Waveform(), tr.Theme) - var weightingTxt string switch tracker.WeightingType(tr.Model.DetectorWeighting().Value()) { case tracker.KWeighting: @@ -121,51 +119,51 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - return t.SongSettingsExpander.Layout(gtx, &tr.Theme.Material, "Song", + return t.SongSettingsExpander.Layout(gtx, tr.Theme, "Song", func(gtx C) D { - return LabelStyle{Text: strconv.Itoa(tr.BPM().Value()) + " BPM", Color: mediumEmphasisTextColor, Alignment: layout.W, FontSize: tr.Theme.Material.TextSize * 14.0 / 16.0, Shaper: tr.Theme.Material.Shaper}.Layout(gtx) + return Label(tr.Theme, &tr.Theme.SongPanel.RowHeader, strconv.Itoa(tr.BPM().Value())+" BPM").Layout(gtx) }, func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "BPM", NumUpDown(tr.Theme, t.BPM, "Song Length").Layout) + return layoutSongOptionRow(gtx, tr.Theme, "BPM", NumUpDown(tr.Theme, t.BPM, "Song Length").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Song length", NumUpDown(tr.Theme, t.SongLength, "Song Length").Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Song length", NumUpDown(tr.Theme, t.SongLength, "Song Length").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Rows per pat", NumUpDown(tr.Theme, t.RowsPerPattern, "Rows per pattern").Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Rows per pat", NumUpDown(tr.Theme, t.RowsPerPattern, "Rows per pattern").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Rows per beat", NumUpDown(tr.Theme, t.RowsPerBeat, "Rows per beat").Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Rows per beat", NumUpDown(tr.Theme, t.RowsPerBeat, "Rows per beat").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Cursor step", NumUpDown(tr.Theme, t.Step, "Cursor step").Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", NumUpDown(tr.Theme, t.Step, "Cursor step").Layout) }), ) }) }), layout.Rigid(func(gtx C) D { - return t.LoudnessExpander.Layout(gtx, &tr.Theme.Material, "Loudness", + return t.LoudnessExpander.Layout(gtx, tr.Theme, "Loudness", func(gtx C) D { - return LabelStyle{Text: fmt.Sprintf("%.1f dB", tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm]), Color: mediumEmphasisTextColor, Alignment: layout.W, FontSize: tr.Theme.Material.TextSize * 14.0 / 16.0, Shaper: tr.Theme.Material.Shaper}.Layout(gtx) + return Label(tr.Theme, &tr.Theme.SongPanel.RowHeader, fmt.Sprintf("%.1f dB", tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm])).Layout(gtx) }, func(gtx C) D { return layout.Flex{Axis: layout.Vertical, Alignment: layout.End}.Layout(gtx, layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Momentary", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMomentary]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Momentary", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMomentary]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Short term", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessIntegrated]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Integrated", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessIntegrated]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Max. momentary", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxMomentary]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Max. momentary", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxMomentary]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Max. short term", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxShortTerm]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Max. short term", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxShortTerm]).Layout) }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = 0 @@ -176,25 +174,25 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { ) }), layout.Rigid(func(gtx C) D { - return t.PeakExpander.Layout(gtx, &tr.Theme.Material, "Peaks", + return t.PeakExpander.Layout(gtx, tr.Theme, "Peaks", func(gtx C) D { maxPeak := max(tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][0], tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][1]) - return dbLabel(&tr.Theme.Material, maxPeak).Layout(gtx) + return dbLabel(tr.Theme, maxPeak).Layout(gtx) }, func(gtx C) D { return layout.Flex{Axis: layout.Vertical, Alignment: layout.End}.Layout(gtx, // no need to show momentary peak, it does not have too much meaning layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term L", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][0]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Short term L", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][0]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term R", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][1]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Short term R", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][1]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated L", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][0]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Integrated L", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][0]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated R", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][1]).Layout) + return layoutSongOptionRow(gtx, tr.Theme, "Integrated R", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][1]).Layout) }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = 0 @@ -205,36 +203,27 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { ) }), layout.Flexed(1, func(gtx C) D { - return t.ScopeExpander.Layout(gtx, &tr.Theme.Material, "Oscilloscope", func(gtx C) D { return D{} }, scopeStyle.Layout) - }), - layout.Rigid(func(gtx C) D { - labelStyle := LabelStyle{Text: version.VersionOrHash, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: tr.Theme.Material.Shaper} - return labelStyle.Layout(gtx) + return t.ScopeExpander.Layout(gtx, tr.Theme, "Oscilloscope", func(gtx C) D { return D{} }, Scope(t.Scope, tr.SignalAnalyzer().Waveform(), tr.Theme).Layout) }), + layout.Rigid(Label(tr.Theme, &tr.Theme.SongPanel.Version, version.VersionOrHash).Layout), ) } -func dbLabel(th *material.Theme, value tracker.Decibel) LabelStyle { - color := mediumEmphasisTextColor +func dbLabel(th *Theme, value tracker.Decibel) LabelWidget { + ret := Label(th, &th.SongPanel.RowValue, fmt.Sprintf("%.1f dB", value)) if value >= 0 { - color = errorColor - } - return LabelStyle{ - Text: fmt.Sprintf("%.1f dB", value), - Color: color, - Alignment: layout.W, - FontSize: th.TextSize * 14.0 / 16.0, - Shaper: th.Shaper, + ret.Color = th.SongPanel.ErrorColor } + return ret } -func layoutSongOptionRow(gtx C, th *material.Theme, label string, widget layout.Widget) D { +func layoutSongOptionRow(gtx C, th *Theme, label string, widget layout.Widget) D { leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout rightSpacer := layout.Spacer{Width: unit.Dp(6)}.Layout return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(leftSpacer), - layout.Rigid(LabelStyle{Text: label, Color: mediumEmphasisTextColor, Alignment: layout.W, FontSize: th.TextSize * 14.0 / 16.0, Shaper: th.Shaper}.Layout), + layout.Rigid(Label(th, &th.SongPanel.RowHeader, label).Layout), layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(widget), layout.Rigid(rightSpacer), @@ -255,7 +244,7 @@ func (e *Expander) Update(gtx C) { } } -func (e *Expander) Layout(gtx C, th *material.Theme, title string, smallWidget, largeWidget layout.Widget) D { +func (e *Expander) Layout(gtx C, th *Theme, title string, smallWidget, largeWidget layout.Widget) D { e.Update(gtx) return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { return e.layoutHeader(gtx, th, title, smallWidget) }), @@ -273,7 +262,7 @@ func (e *Expander) Layout(gtx C, th *material.Theme, title string, smallWidget, ) } -func (e *Expander) layoutHeader(gtx C, th *material.Theme, title string, smallWidget layout.Widget) D { +func (e *Expander) layoutHeader(gtx C, th *Theme, title string, smallWidget layout.Widget) D { return layout.Background{}.Layout(gtx, func(gtx C) D { defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y)).Push(gtx.Ops).Pop() @@ -285,7 +274,7 @@ func (e *Expander) layoutHeader(gtx C, th *material.Theme, title string, smallWi leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(leftSpacer), - layout.Rigid(LabelStyle{Text: title, Color: disabledTextColor, Alignment: layout.W, FontSize: th.TextSize * 14.0 / 16.0, Shaper: th.Shaper}.Layout), + layout.Rigid(Label(th, &th.SongPanel.Expander, title).Layout), layout.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(func(gtx C) D { if !e.Expanded { @@ -300,7 +289,7 @@ func (e *Expander) layoutHeader(gtx C, th *material.Theme, title string, smallWi icon = icons.NavigationExpandLess } gtx.Constraints.Min = image.Pt(gtx.Dp(unit.Dp(24)), gtx.Dp(unit.Dp(24))) - return widgetForIcon(icon).Layout(gtx, th.Palette.Fg) + return widgetForIcon(icon).Layout(gtx, th.SongPanel.Expander.Color) }), ) }, diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index 3ecdb9c..83f3ada 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -22,6 +22,53 @@ type Theme struct { MenuButton ButtonStyle Oscilloscope OscilloscopeStyle NumericUpDown NumericUpDownStyle + DialogTitle LabelStyle + DialogText LabelStyle + SongPanel struct { + RowHeader LabelStyle + RowValue LabelStyle + Expander LabelStyle + Version LabelStyle + ErrorColor color.NRGBA + } + Alert struct { + Warning PopupAlertStyle + Error PopupAlertStyle + Info PopupAlertStyle + } + NoteEditor struct { + TrackTitle LabelStyle + Header LabelStyle + } + Dialog struct { + Title LabelStyle + Text LabelStyle + } + OrderEditor struct { + TrackTitle LabelStyle + } + Menu struct { + Text LabelStyle + ShortCut LabelStyle + } + InstrumentEditor struct { + Octave LabelStyle + Voices LabelStyle + InstrumentNumber LabelStyle + InstrumentName LabelStyle + InstrumentNameMuted LabelStyle + UnitList struct { + Name LabelStyle + Comment LabelStyle + Stack LabelStyle + Disabled LabelStyle + } + } + UnitEditor struct { + Hint LabelStyle + Chooser LabelStyle + ParameterName LabelStyle + } } //go:embed theme.yml diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index d7ea684..310fde9 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -1,6 +1,17 @@ -primarycolor: &primarycolor { r: 243, g: 187, b: 252, a: 255 } -secondarycolor: &secondarycolor { r: 187, g: 245, b: 252, a: 255 } +# following definitions are not in theme.go, but defined here just for +# reusability, with &... *... references +primarycolor: &primarycolor { r: 206, g: 147, b: 216, a: 255 } # { r: 243, g: 187, b: 252, a: 255 } +secondarycolor: &secondarycolor { r: 128, g: 222, b: 234, a: 255 } # { r: 187, g: 245, b: 252, a: 255 } transparentcolor: &transparentcolor { r: 0, g: 0, b: 0, a: 0 } +mediumemphasis: &mediumemphasis { r: 153, g: 153, b: 153, a: 255 } +highemphasis: &highemphasis { r: 222, g: 222, b: 222, a: 255 } +disabled: &disabled { r: 255, g: 255, b: 255, a: 97 } +errorcolor: &errorcolor { r: 207, g: 102, b: 121, a: 255 } +warningcolor: &warningcolor { r: 251, g: 192, b: 45, a: 255 } +white: &white { r: 255, g: 255, b: 255, a: 255 } +black: &black { r: 0, g: 0, b: 0, a: 255 } + +# from here on starts the structs defined in the theme.go material: textsize: 16 fingersize: 38 @@ -13,25 +24,29 @@ filledbutton: background: *primarycolor color: *contrastfg textsize: &buttontextsize 14 - cornerradius: &buttoncornerradius 12 + cornerradius: &buttoncornerradius 18 + height: &buttonheight 36 inset: &buttoninset { top: 0, bottom: 0, left: 6, right: 6 } textbutton: background: *transparentcolor color: *primarycolor textsize: *buttontextsize cornerradius: *buttoncornerradius + height: *buttonheight inset: *buttoninset disabledbutton: background: { r: 53, g: 51, b: 55, a: 255 } color: { r: 120, g: 116, b: 121, a: 255 } textsize: *buttontextsize cornerradius: *buttoncornerradius + height: *buttonheight inset: *buttoninset menubutton: background: *transparentcolor color: { r: 255, g: 255, b: 255, a: 255 } textsize: *buttontextsize cornerradius: 0 + height: *buttonheight inset: *buttoninset oscilloscope: curvecolors: [*primarycolor, *secondarycolor] @@ -47,3 +62,56 @@ numericupdown: textsize: 14 width: 70 height: 20 +songpanel: + rowheader: + textsize: 14 + color: *mediumemphasis + rowvalue: + textsize: 14 + color: *mediumemphasis + expander: + textsize: 14 + color: *highemphasis + errorcolor: *errorcolor + version: + textsize: 12 + color: *mediumemphasis +alerts: + error: + bg: *errorcolor + text: { textsize: 16, color: *black } + warning: + bg: *warningcolor + text: { textsize: 16, color: *black } + info: + bg: { r: 50, g: 50, b: 51, a: 255 } + text: { textsize: 16, shadowcolor: *black } +dialog: + title: { textsize: 16, color: *highemphasis, shadowcolor: *black } + text: { textsize: 16, color: *highemphasis, shadowcolor: *black } +ordereditor: + tracktitle: + textsize: 12 + color: *mediumemphasis +noteeditor: + tracktitle: { textsize: 12, color: *mediumemphasis } + header: { textsize: 14, color: *disabled } +menu: + text: { textsize: 16, color: *highemphasis, shadowcolor: *black } + shortcut: { textsize: 16, color: *mediumemphasis, shadowcolor: *black } +instrumenteditor: + octave: { textsize: 14, color: *disabled } + voices: { textsize: 14, color: *disabled } + instrumentnumber: + { textsize: 10, color: *mediumemphasis, shadowcolor: *black, alignment: 1 } + instrumentname: + { textsize: 10, color: *white, shadowcolor: *black, alignment: 1 } + unitlist: + name: { textsize: 12, color: *mediumemphasis, shadowcolor: *black } + comment: { textsize: 12, color: *disabled } + stack: { textsize: 12, color: *mediumemphasis, shadowcolor: *black } + disabled: { textsize: 12, color: *disabled } +uniteditor: + hint: { textsize: 12, color: *highemphasis, shadowcolor: *black } + chooser: { textsize: 12, color: *white, shadowcolor: *black } + parametername: { textsize: 12, color: *white, shadowcolor: *black } diff --git a/tracker/gioui/tracker.go b/tracker/gioui/tracker.go index 8ed75d3..e0c574b 100644 --- a/tracker/gioui/tracker.go +++ b/tracker/gioui/tracker.go @@ -95,7 +95,7 @@ func NewTracker(model *tracker.Model) *Tracker { preferences: MakePreferences(), } t.Theme.Material.Shaper = text.NewShaper(text.WithCollection(fontCollection)) - t.PopupAlert = NewPopupAlert(model.Alerts(), t.Theme.Material.Shaper) + t.PopupAlert = NewPopupAlert(model.Alerts()) if t.preferences.YmlError != nil { model.Alerts().Add( fmt.Sprintf("Preferences YML Error: %s", t.preferences.YmlError), @@ -201,7 +201,7 @@ func (t *Tracker) Layout(gtx layout.Context, w *app.Window) { t.layoutTop, t.layoutBottom) } - t.PopupAlert.Layout(gtx) + t.PopupAlert.Layout(gtx, t.Theme) t.showDialog(gtx) // this is the top level input handler for the whole app // it handles all the global key events and clipboard events @@ -241,12 +241,12 @@ func (t *Tracker) showDialog(gtx C) { } switch t.Dialog() { case tracker.NewSongChanges, tracker.OpenSongChanges, tracker.QuitChanges: - dstyle := ConfirmDialog(gtx, &t.Theme.Material, t.SaveChangesDialog, "Save changes to song?", "Your changes will be lost if you don't save them.") + dstyle := ConfirmDialog(gtx, t.Theme, t.SaveChangesDialog, "Save changes to song?", "Your changes will be lost if you don't save them.") dstyle.OkStyle.Text = "Save" dstyle.AltStyle.Text = "Don't save" dstyle.Layout(gtx) case tracker.Export: - dstyle := ConfirmDialog(gtx, &t.Theme.Material, t.WaveTypeDialog, "", "Export .wav in int16 or float32 sample format?") + dstyle := ConfirmDialog(gtx, t.Theme, t.WaveTypeDialog, "", "Export .wav in int16 or float32 sample format?") dstyle.OkStyle.Text = "Int16" dstyle.AltStyle.Text = "Float32" dstyle.Layout(gtx) diff --git a/tracker/gioui/unit_editor.go b/tracker/gioui/unit_editor.go index 260213c..cd18eb9 100644 --- a/tracker/gioui/unit_editor.go +++ b/tracker/gioui/unit_editor.go @@ -112,7 +112,7 @@ func (pe *UnitEditor) layoutSliders(gtx C, t *Tracker) D { if index < 0 || index >= numItems { return D{} } - paramStyle := t.ParamStyle(&t.Theme.Material, pe.Parameters[index]) + paramStyle := t.ParamStyle(t.Theme, pe.Parameters[index]) paramStyle.Focus = pe.sliderList.TrackerList.Selected() == index dims := paramStyle.Layout(gtx) return D{Size: image.Pt(gtx.Constraints.Max.X, dims.Size.Y)} @@ -141,7 +141,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { } else { text = pe.caser.String(text) } - hintText := Label(text, white, t.Theme.Material.Shaper) + hintText := Label(t.Theme, &t.Theme.UnitEditor.Hint, text) return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(deleteUnitBtnStyle.Layout), layout.Rigid(copyUnitBtnStyle.Layout), @@ -156,7 +156,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(120) - return hintText(gtx) + return hintText.Layout(gtx) }), layout.Flexed(1, func(gtx C) D { s := t.UnitComment().String() @@ -185,7 +185,8 @@ func (pe *UnitEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D { names[i] = item } element := func(gtx C, i int) D { - w := LabelStyle{Text: names[i], ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} + w := Label(t.Theme, &t.Theme.UnitEditor.Chooser, names[i]) + if i == pe.searchList.TrackerList.Selected() { for pe.SelectTypeBtn.Clicked(gtx) { t.Units().SetSelectedType(names[i]) @@ -248,17 +249,17 @@ type ParameterWidget struct { type ParameterStyle struct { tracker *Tracker w *ParameterWidget - Theme *material.Theme + Theme *Theme SendTargetTheme *material.Theme Focus bool } -func (t *Tracker) ParamStyle(th *material.Theme, paramWidget *ParameterWidget) ParameterStyle { - sendTargetTheme := th.WithPalette(material.Palette{ - Bg: th.Bg, +func (t *Tracker) ParamStyle(th *Theme, paramWidget *ParameterWidget) ParameterStyle { + sendTargetTheme := th.Material.WithPalette(material.Palette{ + Bg: th.Material.Bg, Fg: paramIsSendTargetColor, - ContrastBg: th.ContrastBg, - ContrastFg: th.ContrastFg, + ContrastBg: th.Material.ContrastBg, + ContrastFg: th.Material.ContrastFg, }) return ParameterStyle{ tracker: t, // TODO: we need this to pull the instrument names for ID style parameters, find out another way @@ -273,7 +274,7 @@ func (p ParameterStyle) Layout(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = gtx.Dp(unit.Dp(110)) - return layout.E.Layout(gtx, Label(p.w.Parameter.Name(), white, p.tracker.Theme.Material.Shaper)) + return layout.E.Layout(gtx, Label(p.Theme, &p.Theme.UnitEditor.ParameterName, p.w.Parameter.Name()).Layout) }), layout.Rigid(func(gtx C) D { switch p.w.Parameter.Type() { @@ -298,7 +299,7 @@ func (p ParameterStyle) Layout(gtx C) D { if !p.w.floatWidget.Dragging() { p.w.floatWidget.Value = (float32(p.w.Parameter.Value()) - float32(ra.Min)) / float32(ra.Max-ra.Min) } - sliderStyle := material.Slider(p.Theme, &p.w.floatWidget) + sliderStyle := material.Slider(&p.Theme.Material, &p.w.floatWidget) if isSendTarget { sliderStyle.Color = paramIsSendTargetColor } @@ -316,8 +317,8 @@ func (p ParameterStyle) Layout(gtx C) D { gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(40)) ra := p.w.Parameter.Range() p.w.boolWidget.Value = p.w.Parameter.Value() > ra.Min - boolStyle := material.Switch(p.Theme, &p.w.boolWidget, "Toggle boolean parameter") - boolStyle.Color.Disabled = p.Theme.Fg + boolStyle := material.Switch(&p.Theme.Material, &p.w.boolWidget, "Toggle boolean parameter") + boolStyle.Color.Disabled = p.Theme.Material.Fg defer pointer.PassOp{}.Push(gtx.Ops).Pop() dims := layout.Center.Layout(gtx, boolStyle.Layout) if p.w.boolWidget.Value { @@ -372,17 +373,16 @@ func (p ParameterStyle) Layout(gtx C) D { }), layout.Rigid(func(gtx C) D { if p.w.Parameter.Type() != tracker.IDParameter { - color := white hint := p.w.Parameter.Hint() + label := Label(p.tracker.Theme, &p.tracker.Theme.UnitEditor.Hint, hint.Label) if !hint.Valid { - color = paramValueInvalidColor + label.Color = paramValueInvalidColor } - label := Label(hint.Label, color, p.tracker.Theme.Material.Shaper) if info == "" { - return label(gtx) + return label.Layout(gtx) } tooltip := component.PlatformTooltip(p.SendTargetTheme, info) - return p.w.tipArea.Layout(gtx, tooltip, label) + return p.w.tipArea.Layout(gtx, tooltip, label.Layout) } return D{} }),