diff --git a/tracker/gioui/buttons.go b/tracker/gioui/buttons.go index 024ab10..109fd60 100644 --- a/tracker/gioui/buttons.go +++ b/tracker/gioui/buttons.go @@ -77,7 +77,7 @@ func ActionIcon(gtx C, th *material.Theme, w *ActionClickable, icon []byte, tip func TipIcon(th *material.Theme, w *TipClickable, icon []byte, tip string) TipIconButtonStyle { iconButtonStyle := IconButton(th, &w.Clickable, widgetForIcon(icon), "") - iconButtonStyle.Color = primaryColor + iconButtonStyle.Color = th.Palette.ContrastBg iconButtonStyle.Background = transparent iconButtonStyle.Inset = layout.UniformInset(unit.Dp(6)) return TipIconButtonStyle{ @@ -100,7 +100,7 @@ func ToggleIcon(gtx C, th *material.Theme, w *BoolClickable, offIcon, onIcon []b ibStyle := IconButton(th, &w.Clickable, widgetForIcon(icon), "") ibStyle.Background = transparent ibStyle.Inset = layout.UniformInset(unit.Dp(6)) - ibStyle.Color = primaryColor + ibStyle.Color = th.Palette.ContrastBg if !w.Bool.Enabled() { ibStyle.Color = disabledTextColor } @@ -138,9 +138,9 @@ func ToggleButton(gtx C, th *material.Theme, b *BoolClickable, text string) Butt ret.Inset = layout.UniformInset(unit.Dp(6)) if b.Bool.Value() { ret.Color = th.Palette.ContrastFg - ret.Background = th.Palette.Fg + ret.Background = th.Palette.ContrastBg } else { - ret.Color = th.Palette.Fg + ret.Color = th.Palette.ContrastBg ret.Background = transparent } return ret diff --git a/tracker/gioui/instrument_editor.go b/tracker/gioui/instrument_editor.go index 1d30721..baa8070 100644 --- a/tracker/gioui/instrument_editor.go +++ b/tracker/gioui/instrument_editor.go @@ -125,17 +125,17 @@ func (ie *InstrumentEditor) childFocused(gtx C) bool { func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D { ie.wasFocused = ie.Focused() || ie.childFocused(gtx) - fullscreenBtnStyle := ToggleIcon(gtx, t.Theme, ie.enlargeBtn, icons.NavigationFullscreen, icons.NavigationFullscreenExit, ie.enlargeHint, ie.shrinkHint) - linkBtnStyle := ToggleIcon(gtx, t.Theme, ie.linkInstrTrackBtn, icons.NotificationSyncDisabled, icons.NotificationSync, ie.linkDisabledHint, ie.linkEnabledHint) + fullscreenBtnStyle := ToggleIcon(gtx, &t.Theme.Material, ie.enlargeBtn, icons.NavigationFullscreen, icons.NavigationFullscreenExit, ie.enlargeHint, ie.shrinkHint) + linkBtnStyle := ToggleIcon(gtx, &t.Theme.Material, ie.linkInstrTrackBtn, icons.NotificationSyncDisabled, icons.NotificationSync, ie.linkDisabledHint, ie.linkEnabledHint) octave := func(gtx C) D { in := layout.UniformInset(unit.Dp(1)) - numStyle := NumericUpDown(t.Theme, t.OctaveNumberInput, ie.octaveHint) + numStyle := NumericUpDown(&t.Theme.Material, t.OctaveNumberInput, ie.octaveHint) dims := in.Layout(gtx, numStyle.Layout) return dims } - newBtnStyle := ActionIcon(gtx, t.Theme, ie.newInstrumentBtn, icons.ContentAdd, ie.addInstrumentHint) + newBtnStyle := ActionIcon(gtx, &t.Theme.Material, ie.newInstrumentBtn, icons.ContentAdd, ie.addInstrumentHint) ret := layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout( @@ -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.TextSize * 14.0 / 16.0, Shaper: t.Theme.Shaper}.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(layout.Spacer{Width: 4}.Layout), layout.Rigid(octave), layout.Rigid(func(gtx C) D { @@ -176,17 +176,17 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D { func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { header := func(gtx C) D { - commentExpandBtnStyle := ToggleIcon(gtx, t.Theme, ie.commentExpandBtn, icons.NavigationExpandMore, icons.NavigationExpandLess, ie.expandCommentHint, ie.collapseCommentHint) - presetMenuBtnStyle := TipIcon(t.Theme, ie.presetMenuBtn, icons.NavigationMenu, "Load preset") - copyInstrumentBtnStyle := TipIcon(t.Theme, ie.copyInstrumentBtn, icons.ContentContentCopy, "Copy instrument") - saveInstrumentBtnStyle := TipIcon(t.Theme, ie.saveInstrumentBtn, icons.ContentSave, "Save instrument") - loadInstrumentBtnStyle := TipIcon(t.Theme, ie.loadInstrumentBtn, icons.FileFolderOpen, "Load instrument") - deleteInstrumentBtnStyle := ActionIcon(gtx, t.Theme, ie.deleteInstrumentBtn, icons.ActionDelete, ie.deleteInstrumentHint) - splitInstrumentBtnStyle := ActionIcon(gtx, t.Theme, ie.splitInstrumentBtn, icons.CommunicationCallSplit, ie.splitInstrumentHint) - soloBtnStyle := ToggleIcon(gtx, t.Theme, ie.soloBtn, icons.SocialGroup, icons.SocialPerson, ie.soloHint, ie.unsoloHint) - muteBtnStyle := ToggleIcon(gtx, t.Theme, ie.muteBtn, icons.AVVolumeUp, icons.AVVolumeOff, ie.muteHint, ie.unmuteHint) + commentExpandBtnStyle := ToggleIcon(gtx, &t.Theme.Material, ie.commentExpandBtn, icons.NavigationExpandMore, icons.NavigationExpandLess, ie.expandCommentHint, ie.collapseCommentHint) + presetMenuBtnStyle := TipIcon(&t.Theme.Material, ie.presetMenuBtn, icons.NavigationMenu, "Load preset") + copyInstrumentBtnStyle := TipIcon(&t.Theme.Material, ie.copyInstrumentBtn, icons.ContentContentCopy, "Copy instrument") + saveInstrumentBtnStyle := TipIcon(&t.Theme.Material, ie.saveInstrumentBtn, icons.ContentSave, "Save instrument") + loadInstrumentBtnStyle := TipIcon(&t.Theme.Material, ie.loadInstrumentBtn, icons.FileFolderOpen, "Load instrument") + deleteInstrumentBtnStyle := ActionIcon(gtx, &t.Theme.Material, ie.deleteInstrumentBtn, icons.ActionDelete, ie.deleteInstrumentHint) + splitInstrumentBtnStyle := ActionIcon(gtx, &t.Theme.Material, ie.splitInstrumentBtn, icons.CommunicationCallSplit, ie.splitInstrumentHint) + 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.Shaper) + m := PopupMenu(&ie.presetMenu, t.Theme.Material.Shaper) for ie.copyInstrumentBtn.Clickable.Clicked(gtx) { if contents, ok := t.Instruments().List().CopyElements(); ok { @@ -214,10 +214,10 @@ 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.TextSize * 14.0 / 16.0, Shaper: t.Theme.Shaper}.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(layout.Spacer{Width: 4}.Layout), layout.Rigid(func(gtx layout.Context) layout.Dimensions { - numStyle := NumericUpDown(t.Theme, t.InstrumentVoices, "Number of voices for this instrument") + numStyle := NumericUpDown(&t.Theme.Material, t.InstrumentVoices, "Number of voices for this instrument") dims := numStyle.Layout(gtx) return dims }), @@ -254,7 +254,7 @@ func (ie *InstrumentEditor) layoutInstrumentHeader(gtx C, t *Tracker) D { for ie.commentEditor.Submitted(gtx) || ie.commentEditor.Cancelled(gtx) { ie.instrumentDragList.Focus() } - style := MaterialEditor(t.Theme, ie.commentEditor, "Comment") + style := MaterialEditor(&t.Theme.Material, ie.commentEditor, "Comment") style.Color = highEmphasisTextColor ret := layout.UniformInset(unit.Dp(6)).Layout(gtx, style.Layout) ie.commentString.Set(ie.commentEditor.Text()) @@ -274,11 +274,11 @@ 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.Shaper} + grabhandle := LabelStyle{Text: strconv.Itoa(i + 1), ShadeColor: black, Color: mediumEmphasisTextColor, FontSize: unit.Sp(10), Alignment: layout.Center, Shaper: t.Theme.Material.Shaper} 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.Shaper} + labelStyle := LabelStyle{Text: "", ShadeColor: black, Color: white, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} return layout.Center.Layout(gtx, labelStyle.Layout) } k := byte(255 - level*127) @@ -288,7 +288,7 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { for ie.nameEditor.Submitted(gtx) || ie.nameEditor.Cancelled(gtx) { ie.instrumentDragList.Focus() } - style := MaterialEditor(t.Theme, ie.nameEditor, "Instr") + style := MaterialEditor(&t.Theme.Material, ie.nameEditor, "Instr") style.Color = color style.HintColor = instrumentNameHintColor style.TextSize = unit.Sp(12) @@ -307,7 +307,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.Shaper} + 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 @@ -326,7 +326,7 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { if ie.wasFocused { color = activeLightSurfaceColor } - instrumentList := FilledDragList(t.Theme, ie.instrumentDragList, element, nil) + instrumentList := FilledDragList(&t.Theme.Material, ie.instrumentDragList, element, nil) instrumentList.SelectedColor = color instrumentList.HoverColor = instrumentHoverColor instrumentList.ScrollBarWidth = unit.Dp(6) @@ -366,9 +366,9 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { // TODO: how to ie.unitDragList.Focus() - addUnitBtnStyle := ActionIcon(gtx, t.Theme, ie.addUnitBtn, icons.ContentAdd, "Add unit (Enter)") - addUnitBtnStyle.IconButtonStyle.Color = t.Theme.ContrastFg - addUnitBtnStyle.IconButtonStyle.Background = t.Theme.Fg + addUnitBtnStyle := ActionIcon(gtx, &t.Theme.Material, ie.addUnitBtn, icons.ContentAdd, "Add unit (Enter)") + addUnitBtnStyle.IconButtonStyle.Color = t.Theme.Material.ContrastFg + addUnitBtnStyle.IconButtonStyle.Background = t.Theme.Material.Fg addUnitBtnStyle.IconButtonStyle.Inset = layout.UniformInset(unit.Dp(4)) var units [256]tracker.UnitListItem @@ -409,7 +409,7 @@ 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.Shaper} + stackLabel := LabelStyle{Text: stackText, ShadeColor: black, Color: mediumEmphasisTextColor, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} rightMargin := layout.Inset{Right: unit.Dp(10)} return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -435,7 +435,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { ie.searchEditor.SetText(str.Value()) ie.unitDragList.Focus() } - style := MaterialEditor(t.Theme, ie.searchEditor, "---") + style := MaterialEditor(&t.Theme.Material, ie.searchEditor, "---") style.Color = color style.HintColor = instrumentNameHintColor style.TextSize = unit.Sp(12) @@ -444,7 +444,7 @@ 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.Shaper} + 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 = "---" } @@ -452,7 +452,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { } }), 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.Shaper} + unitNameLabel := LabelStyle{Text: u.Comment, ShadeColor: black, Color: mediumEmphasisTextColor, Font: f, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} inset := layout.Inset{Left: unit.Dp(5)} return inset.Layout(gtx, unitNameLabel.Layout) }), @@ -463,7 +463,7 @@ func (ie *InstrumentEditor) layoutUnitList(gtx C, t *Tracker) D { } defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() - unitList := FilledDragList(t.Theme, ie.unitDragList, element, nil) + unitList := FilledDragList(&t.Theme.Material, ie.unitDragList, element, nil) for { event, ok := gtx.Event( key.Filter{Focus: ie.unitDragList, Name: key.NameRightArrow}, diff --git a/tracker/gioui/menu.go b/tracker/gioui/menu.go index baac7df..e419eb5 100644 --- a/tracker/gioui/menu.go +++ b/tracker/gioui/menu.go @@ -170,10 +170,10 @@ func (tr *Tracker) layoutMenu(gtx C, title string, clickable *Clickable, menu *M for clickable.Clicked(gtx) { menu.Visible = true } - m := PopupMenu(menu, tr.Theme.Shaper) + m := PopupMenu(menu, tr.Theme.Material.Shaper) return func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() - titleBtn := Button(tr.Theme, clickable, title) + titleBtn := Button(&tr.Theme.Material, clickable, title) titleBtn.Color = white titleBtn.Background = transparent titleBtn.CornerRadius = unit.Dp(0) diff --git a/tracker/gioui/note_editor.go b/tracker/gioui/note_editor.go index 39173bd..b330db8 100644 --- a/tracker/gioui/note_editor.go +++ b/tracker/gioui/note_editor.go @@ -150,22 +150,22 @@ func (te *NoteEditor) Layout(gtx layout.Context, t *Tracker) layout.Dimensions { func (te *NoteEditor) layoutButtons(gtx C, t *Tracker) D { return Surface{Gray: 37, Focus: te.scrollTable.Focused() || te.scrollTable.ChildFocused()}.Layout(gtx, func(gtx C) D { - addSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.AddSemitoneBtn, "+1") - subtractSemitoneBtnStyle := ActionButton(gtx, t.Theme, te.SubtractSemitoneBtn, "-1") - addOctaveBtnStyle := ActionButton(gtx, t.Theme, te.AddOctaveBtn, "+12") - subtractOctaveBtnStyle := ActionButton(gtx, t.Theme, te.SubtractOctaveBtn, "-12") - noteOffBtnStyle := ActionButton(gtx, t.Theme, te.NoteOffBtn, "Note Off") - deleteTrackBtnStyle := ActionIcon(gtx, t.Theme, te.DeleteTrackBtn, icons.ActionDelete, te.deleteTrackHint) - splitTrackBtnStyle := ActionIcon(gtx, t.Theme, te.SplitTrackBtn, icons.CommunicationCallSplit, te.splitTrackHint) - newTrackBtnStyle := ActionIcon(gtx, t.Theme, te.NewTrackBtn, icons.ContentAdd, te.addTrackHint) + addSemitoneBtnStyle := ActionButton(gtx, &t.Theme.Material, te.AddSemitoneBtn, "+1") + subtractSemitoneBtnStyle := ActionButton(gtx, &t.Theme.Material, te.SubtractSemitoneBtn, "-1") + addOctaveBtnStyle := ActionButton(gtx, &t.Theme.Material, te.AddOctaveBtn, "+12") + subtractOctaveBtnStyle := ActionButton(gtx, &t.Theme.Material, te.SubtractOctaveBtn, "-12") + noteOffBtnStyle := ActionButton(gtx, &t.Theme.Material, te.NoteOffBtn, "Note Off") + deleteTrackBtnStyle := ActionIcon(gtx, &t.Theme.Material, te.DeleteTrackBtn, icons.ActionDelete, te.deleteTrackHint) + splitTrackBtnStyle := ActionIcon(gtx, &t.Theme.Material, te.SplitTrackBtn, icons.CommunicationCallSplit, te.splitTrackHint) + newTrackBtnStyle := ActionIcon(gtx, &t.Theme.Material, te.NewTrackBtn, icons.ContentAdd, te.addTrackHint) in := layout.UniformInset(unit.Dp(1)) voiceUpDown := func(gtx C) D { - numStyle := NumericUpDown(t.Theme, te.TrackVoices, "Track voices") + numStyle := NumericUpDown(&t.Theme.Material, te.TrackVoices, "Track voices") return in.Layout(gtx, numStyle.Layout) } - effectBtnStyle := ToggleButton(gtx, t.Theme, te.EffectBtn, "Hex") - uniqueBtnStyle := ToggleIcon(gtx, t.Theme, te.UniqueBtn, icons.ToggleStarBorder, icons.ToggleStar, te.uniqueOffTip, te.uniqueOnTip) - midiInBtnStyle := ToggleButton(gtx, t.Theme, te.TrackMidiInBtn, "MIDI") + effectBtnStyle := ToggleButton(gtx, &t.Theme.Material, te.EffectBtn, "Hex") + uniqueBtnStyle := ToggleIcon(gtx, &t.Theme.Material, te.UniqueBtn, icons.ToggleStarBorder, icons.ToggleStar, te.uniqueOffTip, te.uniqueOnTip) + midiInBtnStyle := ToggleButton(gtx, &t.Theme.Material, te.TrackMidiInBtn, "MIDI") return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(func(gtx C) D { return layout.Dimensions{Size: image.Pt(gtx.Dp(unit.Dp(12)), 0)} }), layout.Rigid(addSemitoneBtnStyle.Layout), @@ -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.TextSize * 14.0 / 16.0, Shaper: t.Theme.Shaper}.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(layout.Spacer{Width: 4}.Layout), layout.Rigid(voiceUpDown), layout.Rigid(splitTrackBtnStyle.Layout), @@ -229,7 +229,7 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { Text: t.Model.TrackTitle(i), FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, - Shaper: t.Theme.Shaper, + Shaper: t.Theme.Material.Shaper, }.Layout(gtx) return D{Size: image.Pt(pxWidth, h)} } @@ -258,11 +258,11 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { color = loopMarkerColor } paint.ColorOp{Color: color}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", pat)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", pat)), op.CallOp{}) } defer op.Offset(image.Pt(pxPatMarkWidth, 0)).Push(gtx.Ops).Pop() paint.ColorOp{Color: rowMarkerRowTextColor}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", row)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", row)), op.CallOp{}) return D{Size: image.Pt(w, pxHeight)} } @@ -310,11 +310,11 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { s := t.Model.Order().Value(tracker.Point{X: x, Y: pat}) if row == 0 { // draw the pattern marker paint.ColorOp{Color: trackerPatMarker}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{}) + widget.Label{}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, patternIndexToString(s), op.CallOp{}) } if row == 1 && t.Model.PatternUnique(x, s) { // draw a * if the pattern is unique paint.ColorOp{Color: mediumEmphasisTextColor}.Add(gtx.Ops) - widget.Label{}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, "*", op.CallOp{}) + widget.Label{}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, "*", op.CallOp{}) } if te.scrollTable.Table.Cursor() == point && te.scrollTable.Focused() { paint.ColorOp{Color: trackerActiveTextColor}.Add(gtx.Ops) @@ -325,10 +325,10 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { if t.Model.Notes().Effect(x) { val = hexStr[byte(t.Model.Notes().Value(tracker.Point{X: x, Y: y}))] } - widget.Label{Alignment: text.Middle}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, val, op.CallOp{}) + widget.Label{Alignment: text.Middle}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, val, op.CallOp{}) return D{Size: image.Pt(pxWidth, pxHeight)} } - table := FilledScrollTable(t.Theme, te.scrollTable, cell, colTitle, rowTitle, nil, rowTitleBg) + table := FilledScrollTable(&t.Theme.Material, te.scrollTable, cell, colTitle, rowTitle, nil, rowTitleBg) table.RowTitleWidth = trackPatMarkWidth + trackRowMarkWidth table.ColumnTitleHeight = trackColTitleHeight table.CellWidth = trackColWidth diff --git a/tracker/gioui/numericupdown.go b/tracker/gioui/numericupdown.go index bfa231d..7e1c4e5 100644 --- a/tracker/gioui/numericupdown.go +++ b/tracker/gioui/numericupdown.go @@ -2,13 +2,11 @@ package gioui import ( "image" - "image/color" "strconv" "github.com/vsariola/sointu/tracker" "golang.org/x/exp/shiny/materialdesign/icons" - "gioui.org/font" "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" @@ -20,8 +18,6 @@ import ( "gioui.org/io/pointer" "gioui.org/layout" "gioui.org/text" - "gioui.org/unit" - "gioui.org/widget/material" ) type NumberInput struct { @@ -34,48 +30,26 @@ type NumberInput struct { } type NumericUpDownStyle struct { - NumberInput *NumberInput - Color color.NRGBA - Font font.Font - TextSize unit.Sp - BorderColor color.NRGBA - IconColor color.NRGBA - BackgroundColor color.NRGBA - CornerRadius unit.Dp - Border unit.Dp - ButtonWidth unit.Dp - UnitsPerStep unit.Dp - Tooltip component.Tooltip - Width unit.Dp - Height unit.Dp - shaper text.Shaper + Theme *Theme + NumberInput *NumberInput + Tooltip component.Tooltip } func NewNumberInput(v tracker.Int) *NumberInput { return &NumberInput{Int: v} } -func NumericUpDown(th *material.Theme, number *NumberInput, tooltip string) NumericUpDownStyle { +func NumericUpDown(th *Theme, number *NumberInput, tooltip string) NumericUpDownStyle { return NumericUpDownStyle{ - NumberInput: number, - Color: white, - IconColor: th.Palette.Fg, - BackgroundColor: numberInputBgColor, - CornerRadius: unit.Dp(4), - ButtonWidth: unit.Dp(16), - Border: unit.Dp(1), - UnitsPerStep: unit.Dp(8), - TextSize: th.TextSize * 14 / 16, - Tooltip: Tooltip(th, tooltip), - Width: unit.Dp(70), - Height: unit.Dp(20), - shaper: *th.Shaper, + NumberInput: number, + Theme: th, + Tooltip: Tooltip(&th.Material, tooltip), } } func (s *NumericUpDownStyle) Update(gtx layout.Context) { // handle dragging - pxPerStep := float32(gtx.Dp(s.UnitsPerStep)) + pxPerStep := float32(gtx.Dp(s.Theme.NumericUpDown.DpPerStep)) for { ev, ok := gtx.Event(pointer.Filter{ Target: s.NumberInput, @@ -119,13 +93,13 @@ func (s NumericUpDownStyle) Layout(gtx C) D { func (s *NumericUpDownStyle) actualLayout(gtx C) D { s.Update(gtx) - gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(s.Width), gtx.Dp(s.Height))) - width := gtx.Dp(s.ButtonWidth) - height := gtx.Dp(s.Height) + gtx.Constraints = layout.Exact(image.Pt(gtx.Dp(s.Theme.NumericUpDown.Width), gtx.Dp(s.Theme.NumericUpDown.Height))) + width := gtx.Dp(s.Theme.NumericUpDown.ButtonWidth) + height := gtx.Dp(s.Theme.NumericUpDown.Height) return layout.Background{}.Layout(gtx, func(gtx C) D { - defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, gtx.Dp(s.CornerRadius)).Push(gtx.Ops).Pop() - paint.Fill(gtx.Ops, s.BackgroundColor) + defer clip.UniformRRect(image.Rectangle{Max: gtx.Constraints.Min}, gtx.Dp(s.Theme.NumericUpDown.CornerRadius)).Push(gtx.Ops).Pop() + paint.Fill(gtx.Ops, s.Theme.NumericUpDown.BgColor) event.Op(gtx.Ops, s.NumberInput) // register drag inputs, if not hitting the clicks return D{Size: gtx.Constraints.Min} }, @@ -139,12 +113,12 @@ func (s *NumericUpDownStyle) actualLayout(gtx C) D { s.NumberInput.clickDecrease.Add(gtx.Ops) return D{Size: gtx.Constraints.Min} }, - func(gtx C) D { return widgetForIcon(icons.ContentRemove).Layout(gtx, s.IconColor) }, + func(gtx C) D { return widgetForIcon(icons.ContentRemove).Layout(gtx, s.Theme.NumericUpDown.IconColor) }, ) }), layout.Flexed(1, func(gtx C) D { - paint.ColorOp{Color: s.Color}.Add(gtx.Ops) - return widget.Label{Alignment: text.Middle}.Layout(gtx, &s.shaper, s.Font, s.TextSize, strconv.Itoa(s.NumberInput.Int.Value()), op.CallOp{}) + paint.ColorOp{Color: s.Theme.NumericUpDown.TextColor}.Add(gtx.Ops) + return widget.Label{Alignment: text.Middle}.Layout(gtx, s.Theme.Material.Shaper, s.Font, s.Theme.NumericUpDown.TextSize, strconv.Itoa(s.NumberInput.Int.Value()), op.CallOp{}) }), layout.Rigid(func(gtx C) D { gtx.Constraints = layout.Exact(image.Pt(width, height)) diff --git a/tracker/gioui/order_editor.go b/tracker/gioui/order_editor.go index 679b145..7848273 100644 --- a/tracker/gioui/order_editor.go +++ b/tracker/gioui/order_editor.go @@ -73,7 +73,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { Text: t.Model.TrackTitle(i), FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, - Shaper: t.Theme.Shaper, + Shaper: t.Theme.Material.Shaper, }.Layout(gtx) return D{Size: image.Pt(gtx.Dp(patternCellWidth), h)} } @@ -93,7 +93,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { } paint.ColorOp{Color: color}.Add(gtx.Ops) defer op.Offset(image.Pt(0, -2)).Push(gtx.Ops).Pop() - widget.Label{}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) + widget.Label{}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, strings.ToUpper(fmt.Sprintf("%02x", j)), op.CallOp{}) return D{Size: image.Pt(w, gtx.Dp(patternCellHeight))} } @@ -115,11 +115,11 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { paint.FillShape(gtx.Ops, color, clip.Rect{Min: image.Pt(1, 1), Max: image.Pt(gtx.Constraints.Min.X-1, gtx.Constraints.Min.X-1)}.Op()) paint.ColorOp{Color: patternTextColor}.Add(gtx.Ops) defer op.Offset(image.Pt(0, -2)).Push(gtx.Ops).Pop() - widget.Label{Alignment: text.Middle}.Layout(gtx, t.Theme.Shaper, trackerFont, trackerFontSize, val, op.CallOp{}) + widget.Label{Alignment: text.Middle}.Layout(gtx, t.Theme.Material.Shaper, trackerFont, trackerFontSize, val, op.CallOp{}) return D{Size: image.Pt(gtx.Dp(patternCellWidth), gtx.Dp(patternCellHeight))} } - table := FilledScrollTable(t.Theme, oe.scrollTable, cell, colTitle, rowTitle, nil, rowTitleBg) + table := FilledScrollTable(&t.Theme.Material, oe.scrollTable, cell, colTitle, rowTitle, nil, rowTitleBg) table.ColumnTitleHeight = orderTitleHeight return table.Layout(gtx) diff --git a/tracker/gioui/oscilloscope.go b/tracker/gioui/oscilloscope.go index 3720329..bd4d92c 100644 --- a/tracker/gioui/oscilloscope.go +++ b/tracker/gioui/oscilloscope.go @@ -2,7 +2,6 @@ package gioui import ( "image" - "image/color" "math" "gioui.org/f32" @@ -12,7 +11,6 @@ import ( "gioui.org/op/clip" "gioui.org/op/paint" "gioui.org/unit" - "gioui.org/widget/material" "github.com/vsariola/sointu/tracker" ) @@ -33,9 +31,7 @@ type ( OscilloscopeStyle struct { Oscilloscope *Oscilloscope Wave tracker.RingBuffer[[2]float32] - Colors [2]color.NRGBA - ClippedColor color.NRGBA - Theme *material.Theme + Theme *Theme } ) @@ -48,15 +44,15 @@ func NewOscilloscope(model *tracker.Model) *Oscilloscope { } } -func LineOscilloscope(s *Oscilloscope, wave tracker.RingBuffer[[2]float32], th *material.Theme) *OscilloscopeStyle { - return &OscilloscopeStyle{Oscilloscope: s, Wave: wave, Colors: [2]color.NRGBA{primaryColor, secondaryColor}, Theme: th, ClippedColor: errorColor} +func LineOscilloscope(s *Oscilloscope, wave tracker.RingBuffer[[2]float32], th *Theme) *OscilloscopeStyle { + return &OscilloscopeStyle{Oscilloscope: s, Wave: wave, Theme: th} } func (s *OscilloscopeStyle) Layout(gtx C) D { - wrapBtnStyle := ToggleButton(gtx, s.Theme, s.Oscilloscope.wrapBtn, "Wrap") - onceBtnStyle := ToggleButton(gtx, s.Theme, s.Oscilloscope.onceBtn, "Once") - triggerChannelStyle := NumericUpDown(s.Theme, s.Oscilloscope.triggerChannelNumber, "Trigger channel") - lengthNumberStyle := NumericUpDown(s.Theme, s.Oscilloscope.lengthInBeatsNumber, "Buffer length in beats") + wrapBtnStyle := ToggleButton(gtx, &s.Theme.Material, s.Oscilloscope.wrapBtn, "Wrap") + onceBtnStyle := ToggleButton(gtx, &s.Theme.Material, s.Oscilloscope.onceBtn, "Once") + triggerChannelStyle := NumericUpDown(&s.Theme.Material, s.Oscilloscope.triggerChannelNumber, "Trigger channel") + lengthNumberStyle := NumericUpDown(&s.Theme.Material, s.Oscilloscope.lengthInBeatsNumber, "Buffer length in beats") leftSpacer := layout.Spacer{Width: unit.Dp(6), Height: unit.Dp(24)}.Layout rightSpacer := layout.Spacer{Width: unit.Dp(6)}.Layout @@ -66,7 +62,7 @@ func (s *OscilloscopeStyle) 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.TextSize * 14.0 / 16.0, Shaper: s.Theme.Shaper}.Layout), + 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.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(onceBtnStyle.Layout), layout.Rigid(triggerChannelStyle.Layout), @@ -76,7 +72,7 @@ func (s *OscilloscopeStyle) 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.TextSize * 14.0 / 16.0, Shaper: s.Theme.Shaper}.Layout), + 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.Flexed(1, func(gtx C) D { return D{Size: gtx.Constraints.Min} }), layout.Rigid(wrapBtnStyle.Layout), layout.Rigid(lengthNumberStyle.Layout), @@ -93,10 +89,10 @@ func (s *OscilloscopeStyle) layoutWave(gtx C) D { } defer clip.Rect(image.Rectangle{Max: gtx.Constraints.Max}).Push(gtx.Ops).Pop() event.Op(gtx.Ops, s.Oscilloscope) - paint.ColorOp{Color: oscilloscopeCursorColor}.Add(gtx.Ops) + paint.ColorOp{Color: s.Theme.Oscilloscope.CursorColor}.Add(gtx.Ops) cursorX := int(s.sampleToPx(gtx, float32(s.Wave.Cursor))) fillRect(gtx, clip.Rect{Min: image.Pt(cursorX, 0), Max: image.Pt(cursorX+1, gtx.Constraints.Max.Y)}) - paint.ColorOp{Color: oscilloscopeLimitColor}.Add(gtx.Ops) + paint.ColorOp{Color: s.Theme.Oscilloscope.LimitColor}.Add(gtx.Ops) minusOneY := int(s.ampToY(gtx, -1)) fillRect(gtx, clip.Rect{Min: image.Pt(0, minusOneY), Max: image.Pt(gtx.Constraints.Max.X, minusOneY+1)}) plusOneY := int(s.ampToY(gtx, 1)) @@ -106,7 +102,7 @@ func (s *OscilloscopeStyle) layoutWave(gtx C) D { rightX := int(s.sampleToPx(gtx, float32(len(s.Wave.Buffer)-1))) fillRect(gtx, clip.Rect{Min: image.Pt(rightX, 0), Max: image.Pt(rightX+1, gtx.Constraints.Max.Y)}) for chn := range 2 { - paint.ColorOp{Color: s.Colors[chn]}.Add(gtx.Ops) + paint.ColorOp{Color: s.Theme.Oscilloscope.CurveColors[chn]}.Add(gtx.Ops) for px := range gtx.Constraints.Max.X { // left and right is the sample range covered by the pixel left := int(s.pxToSample(gtx, float32(px)-0.5)) diff --git a/tracker/gioui/songpanel.go b/tracker/gioui/songpanel.go index 085c9d0..cfae65a 100644 --- a/tracker/gioui/songpanel.go +++ b/tracker/gioui/songpanel.go @@ -84,7 +84,7 @@ func (s *SongPanel) Layout(gtx C, t *Tracker) D { return D{Size: image.Pt(gtx.Constraints.Min.X, gtx.Constraints.Min.Y)} }, func(gtx C) D { - return s.PlayBar.Layout(gtx, t.Theme) + return s.PlayBar.Layout(gtx, &t.Theme.Material) }, ) }), @@ -111,63 +111,63 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { weightingTxt = "No weight (RMS)" } - weightingBtn := LowEmphasisButton(tr.Theme, t.WeightingTypeBtn, weightingTxt) + weightingBtn := LowEmphasisButton(&tr.Theme.Material, t.WeightingTypeBtn, weightingTxt) weightingBtn.Color = mediumEmphasisTextColor oversamplingTxt := "Sample peak" if tr.Model.Oversampling().Value() { oversamplingTxt = "True peak" } - oversamplingBtn := LowEmphasisButton(tr.Theme, t.OversamplingBtn, oversamplingTxt) + oversamplingBtn := LowEmphasisButton(&tr.Theme.Material, t.OversamplingBtn, oversamplingTxt) oversamplingBtn.Color = mediumEmphasisTextColor return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - return t.SongSettingsExpander.Layout(gtx, tr.Theme, "Song", + return t.SongSettingsExpander.Layout(gtx, &tr.Theme.Material, "Song", func(gtx C) D { - return LabelStyle{Text: strconv.Itoa(tr.BPM().Value()) + " BPM", Color: mediumEmphasisTextColor, Alignment: layout.W, FontSize: tr.Theme.TextSize * 14.0 / 16.0, Shaper: tr.Theme.Shaper}.Layout(gtx) + 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) }, func(gtx C) D { return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "BPM", NumericUpDown(tr.Theme, t.BPM, "Song Length").Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "BPM", NumericUpDown(&tr.Theme.Material, t.BPM, "Song Length").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Song length", NumericUpDown(tr.Theme, t.SongLength, "Song Length").Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Song length", NumericUpDown(&tr.Theme.Material, t.SongLength, "Song Length").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Rows per pat", NumericUpDown(tr.Theme, t.RowsPerPattern, "Rows per pattern").Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Rows per pat", NumericUpDown(&tr.Theme.Material, t.RowsPerPattern, "Rows per pattern").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Rows per beat", NumericUpDown(tr.Theme, t.RowsPerBeat, "Rows per beat").Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Rows per beat", NumericUpDown(&tr.Theme.Material, t.RowsPerBeat, "Rows per beat").Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Cursor step", NumericUpDown(tr.Theme, t.Step, "Cursor step").Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Cursor step", NumericUpDown(&tr.Theme.Material, t.Step, "Cursor step").Layout) }), ) }) }), layout.Rigid(func(gtx C) D { - return t.LoudnessExpander.Layout(gtx, tr.Theme, "Loudness", + return t.LoudnessExpander.Layout(gtx, &tr.Theme.Material, "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.TextSize * 14.0 / 16.0, Shaper: tr.Theme.Shaper}.Layout(gtx) + 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) }, 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, "Momentary", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMomentary]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Momentary", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMomentary]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Short term", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessShortTerm]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Integrated", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessIntegrated]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessIntegrated]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Max. momentary", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxMomentary]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Max. momentary", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxMomentary]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Max. short term", dbLabel(tr.Theme, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxShortTerm]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Max. short term", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Loudness[tracker.LoudnessMaxShortTerm]).Layout) }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = 0 @@ -178,25 +178,25 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { ) }), layout.Rigid(func(gtx C) D { - return t.PeakExpander.Layout(gtx, tr.Theme, "Peaks", + return t.PeakExpander.Layout(gtx, &tr.Theme.Material, "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, maxPeak).Layout(gtx) + return dbLabel(&tr.Theme.Material, 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, "Short term L", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][0]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term L", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][0]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Short term R", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][1]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Short term R", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakShortTerm][1]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Integrated L", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][0]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated L", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][0]).Layout) }), layout.Rigid(func(gtx C) D { - return layoutSongOptionRow(gtx, tr.Theme, "Integrated R", dbLabel(tr.Theme, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][1]).Layout) + return layoutSongOptionRow(gtx, &tr.Theme.Material, "Integrated R", dbLabel(&tr.Theme.Material, tr.Model.DetectorResult().Peaks[tracker.PeakIntegrated][1]).Layout) }), layout.Rigid(func(gtx C) D { gtx.Constraints.Min.X = 0 @@ -207,10 +207,10 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { ) }), layout.Flexed(1, func(gtx C) D { - return t.ScopeExpander.Layout(gtx, tr.Theme, "Oscilloscope", func(gtx C) D { return D{} }, scopeStyle.Layout) + 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.Shaper} + labelStyle := LabelStyle{Text: version.VersionOrHash, FontSize: unit.Sp(12), Color: mediumEmphasisTextColor, Shaper: tr.Theme.Material.Shaper} return labelStyle.Layout(gtx) }), ) @@ -357,7 +357,7 @@ func (t *MenuBar) Layout(gtx C, tr *Tracker) D { gtx.Constraints.Max.Y = gtx.Dp(unit.Dp(36)) gtx.Constraints.Min.Y = gtx.Dp(unit.Dp(36)) - panicBtnStyle := ToggleIcon(gtx, tr.Theme, t.PanicBtn, icons.AlertErrorOutline, icons.AlertError, t.panicHint, t.panicHint) + panicBtnStyle := ToggleIcon(gtx, &tr.Theme.Material, t.PanicBtn, icons.AlertErrorOutline, icons.AlertError, t.panicHint, t.panicHint) if t.PanicBtn.Bool.Value() { panicBtnStyle.IconButtonStyle.Color = errorColor } diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index 7110a43..a89c3f7 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -1,13 +1,63 @@ package gioui import ( + _ "embed" + "fmt" "image/color" "gioui.org/font/gofont" "gioui.org/text" "gioui.org/unit" + "gioui.org/widget" + "gioui.org/widget/material" + "golang.org/x/exp/shiny/materialdesign/icons" + "gopkg.in/yaml.v2" ) +type Theme struct { + Material material.Theme + Oscilloscope struct { + CurveColors [2]color.NRGBA `yaml:",flow"` + LimitColor color.NRGBA `yaml:",flow"` + CursorColor color.NRGBA `yaml:",flow"` + } + NumericUpDown struct { + TextColor color.NRGBA `yaml:",flow"` + IconColor color.NRGBA `yaml:",flow"` + BgColor color.NRGBA `yaml:",flow"` + CornerRadius unit.Dp + ButtonWidth unit.Dp + Width unit.Dp + Height unit.Dp + TextSize unit.Sp + DpPerStep unit.Dp + } +} + +//go:embed theme.yml +var defaultTheme []byte + +func NewTheme() *Theme { + var theme Theme + yaml.Unmarshal(defaultTheme, &theme) + str, _ := yaml.Marshal(theme) + fmt.Printf(string(str)) + ReadCustomConfigYml("theme.yml", &theme) + theme.Material.Shaper = &text.Shaper{} + theme.Material.Icon.CheckBoxChecked = mustIcon(widget.NewIcon(icons.ToggleCheckBox)) + theme.Material.Icon.CheckBoxUnchecked = mustIcon(widget.NewIcon(icons.ToggleCheckBoxOutlineBlank)) + theme.Material.Icon.RadioChecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonChecked)) + theme.Material.Icon.RadioUnchecked = mustIcon(widget.NewIcon(icons.ToggleRadioButtonUnchecked)) + return &theme +} + +func mustIcon(ic *widget.Icon, err error) *widget.Icon { + if err != nil { + panic(err) + } + return ic +} + var fontCollection []text.FontFace = gofont.Collection() var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255} @@ -77,6 +127,3 @@ var dialogBgColor = color.NRGBA{R: 0, G: 0, B: 0, A: 224} var paramIsSendTargetColor = color.NRGBA{R: 120, G: 120, B: 210, A: 255} var paramValueInvalidColor = color.NRGBA{R: 120, G: 120, B: 120, A: 190} - -var oscilloscopeLimitColor = color.NRGBA{R: 255, G: 255, B: 255, A: 8} -var oscilloscopeCursorColor = color.NRGBA{R: 252, G: 186, B: 3, A: 255} diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml new file mode 100644 index 0000000..20fa0ed --- /dev/null +++ b/tracker/gioui/theme.yml @@ -0,0 +1,23 @@ +material: + textsize: 16 + fingersize: 38 + palette: + bg: &bg { r: 18, g: 18, b: 18, a: 255 } + fg: &fg { r: 255, g: 255, b: 255, a: 255 } + contrastbg: &contrastbg { r: 206, g: 147, b: 216, a: 255 } + contrastfg: &contrastfg { r: 0, g: 0, b: 0, a: 255 } +oscilloscope: + curvecolors: + [{ r: 206, g: 147, b: 216, a: 255 }, { r: 128, g: 222, b: 234, a: 255 }] + limitcolor: { r: 255, g: 255, b: 255, a: 8 } + cursorcolor: { r: 252, g: 186, b: 3, a: 255 } +numericupdown: + bgcolor: { r: 255, g: 255, b: 255, A: 3 } + textcolor: *fg + iconcolor: *contrastbg + cornerradius: 4 + buttonwidth: 16 + unitsperstep: 8 + textsize: 14 + width: 70 + height: 20 diff --git a/tracker/gioui/tracker.go b/tracker/gioui/tracker.go index 3e95be6..8ed75d3 100644 --- a/tracker/gioui/tracker.go +++ b/tracker/gioui/tracker.go @@ -18,7 +18,6 @@ import ( "gioui.org/op/clip" "gioui.org/op/paint" "gioui.org/text" - "gioui.org/widget/material" "gioui.org/x/explorer" "github.com/vsariola/sointu/tracker" ) @@ -27,7 +26,7 @@ var canQuit = true // set to false in init() if plugin tag is enabled type ( Tracker struct { - Theme *material.Theme + Theme *Theme OctaveNumberInput *NumberInput InstrumentVoices *NumberInput TopHorizontalSplit *Split @@ -71,7 +70,7 @@ var ZoomFactors = []float32{.25, 1. / 3, .5, 2. / 3, .75, .8, 1, 1.1, 1.25, 1.5, func NewTracker(model *tracker.Model) *Tracker { t := &Tracker{ - Theme: material.NewTheme(), + Theme: NewTheme(), OctaveNumberInput: NewNumberInput(model.Octave().Int()), InstrumentVoices: NewNumberInput(model.InstrumentVoices().Int()), @@ -95,16 +94,14 @@ func NewTracker(model *tracker.Model) *Tracker { filePathString: model.FilePath().String(), preferences: MakePreferences(), } - t.Theme.Shaper = text.NewShaper(text.WithCollection(fontCollection)) - t.PopupAlert = NewPopupAlert(model.Alerts(), t.Theme.Shaper) + t.Theme.Material.Shaper = text.NewShaper(text.WithCollection(fontCollection)) + t.PopupAlert = NewPopupAlert(model.Alerts(), t.Theme.Material.Shaper) if t.preferences.YmlError != nil { model.Alerts().Add( fmt.Sprintf("Preferences YML Error: %s", t.preferences.YmlError), tracker.Warning, ) } - t.Theme.Palette.Fg = primaryColor - t.Theme.Palette.ContrastFg = black t.TrackEditor.scrollTable.Focus() return t } @@ -244,12 +241,12 @@ func (t *Tracker) showDialog(gtx C) { } switch t.Dialog() { case tracker.NewSongChanges, tracker.OpenSongChanges, tracker.QuitChanges: - dstyle := ConfirmDialog(gtx, t.Theme, t.SaveChangesDialog, "Save changes to song?", "Your changes will be lost if you don't save them.") + dstyle := ConfirmDialog(gtx, &t.Theme.Material, 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, t.WaveTypeDialog, "", "Export .wav in int16 or float32 sample format?") + dstyle := ConfirmDialog(gtx, &t.Theme.Material, 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 34a40a0..1176a96 100644 --- a/tracker/gioui/unit_editor.go +++ b/tracker/gioui/unit_editor.go @@ -112,13 +112,13 @@ func (pe *UnitEditor) layoutSliders(gtx C, t *Tracker) D { if index < 0 || index >= numItems { return D{} } - paramStyle := t.ParamStyle(t.Theme, pe.Parameters[index]) + paramStyle := t.ParamStyle(&t.Theme.Material, 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)} } - fdl := FilledDragList(t.Theme, pe.sliderList, element, nil) + fdl := FilledDragList(&t.Theme.Material, pe.sliderList, element, nil) dims := fdl.Layout(gtx) gtx.Constraints = layout.Exact(dims.Size) fdl.LayoutScrollBar(gtx) @@ -132,16 +132,16 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { t.Alerts().Add("Unit copied to clipboard", tracker.Info) } } - copyUnitBtnStyle := TipIcon(t.Theme, pe.CopyUnitBtn, icons.ContentContentCopy, pe.copyHint) - deleteUnitBtnStyle := ActionIcon(gtx, t.Theme, pe.DeleteUnitBtn, icons.ActionDelete, "Delete unit (Ctrl+Backspace)") - disableUnitBtnStyle := ToggleIcon(gtx, t.Theme, pe.DisableUnitBtn, icons.AVVolumeUp, icons.AVVolumeOff, pe.disableUnitHint, pe.enableUnitHint) + copyUnitBtnStyle := TipIcon(&t.Theme.Material, pe.CopyUnitBtn, icons.ContentContentCopy, pe.copyHint) + deleteUnitBtnStyle := ActionIcon(gtx, &t.Theme.Material, pe.DeleteUnitBtn, icons.ActionDelete, "Delete unit (Ctrl+Backspace)") + disableUnitBtnStyle := ToggleIcon(gtx, &t.Theme.Material, pe.DisableUnitBtn, icons.AVVolumeUp, icons.AVVolumeOff, pe.disableUnitHint, pe.enableUnitHint) text := t.Units().SelectedType() if text == "" { text = "Choose unit type" } else { text = pe.caser.String(text) } - hintText := Label(text, white, t.Theme.Shaper) + hintText := Label(text, white, t.Theme.Material.Shaper) return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx, layout.Rigid(deleteUnitBtnStyle.Layout), layout.Rigid(copyUnitBtnStyle.Layout), @@ -149,7 +149,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { layout.Rigid(func(gtx C) D { var dims D if t.Units().SelectedType() != "" { - clearUnitBtnStyle := ActionIcon(gtx, t.Theme, pe.ClearUnitBtn, icons.ContentClear, "Clear unit") + clearUnitBtnStyle := ActionIcon(gtx, &t.Theme.Material, pe.ClearUnitBtn, icons.ContentClear, "Clear unit") dims = clearUnitBtnStyle.Layout(gtx) } return D{Size: image.Pt(gtx.Dp(unit.Dp(48)), dims.Size.Y)} @@ -164,7 +164,7 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { for pe.commentEditor.Submitted(gtx) || pe.commentEditor.Cancelled(gtx) { t.InstrumentEditor.Focus() } - commentStyle := MaterialEditor(t.Theme, pe.commentEditor, "---") + commentStyle := MaterialEditor(&t.Theme.Material, pe.commentEditor, "---") commentStyle.Font = labelDefaultFont commentStyle.TextSize = labelDefaultFontSize commentStyle.Color = mediumEmphasisTextColor @@ -185,7 +185,7 @@ 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.Shaper} + w := LabelStyle{Text: names[i], ShadeColor: black, Color: white, Font: labelDefaultFont, FontSize: unit.Sp(12), Shaper: t.Theme.Material.Shaper} if i == pe.searchList.TrackerList.Selected() { for pe.SelectTypeBtn.Clicked(gtx) { t.Units().SetSelectedType(names[i]) @@ -194,7 +194,7 @@ func (pe *UnitEditor) layoutUnitTypeChooser(gtx C, t *Tracker) D { } return w.Layout(gtx) } - fdl := FilledDragList(t.Theme, pe.searchList, element, nil) + fdl := FilledDragList(&t.Theme.Material, pe.searchList, element, nil) dims := fdl.Layout(gtx) gtx.Constraints = layout.Exact(dims.Size) fdl.LayoutScrollBar(gtx) @@ -273,7 +273,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.Shaper)) + return layout.E.Layout(gtx, Label(p.w.Parameter.Name(), white, p.tracker.Theme.Material.Shaper)) }), layout.Rigid(func(gtx C) D { switch p.w.Parameter.Type() { @@ -319,7 +319,7 @@ func (p ParameterStyle) Layout(gtx C) D { 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.Color.Enabled = white + boolStyle.Color.Enabled = p.Theme.ContrastBg defer pointer.PassOp{}.Push(gtx.Ops).Pop() dims := layout.Center.Layout(gtx, boolStyle.Layout) if p.w.boolWidget.Value { @@ -379,7 +379,7 @@ func (p ParameterStyle) Layout(gtx C) D { if !hint.Valid { color = paramValueInvalidColor } - label := Label(hint.Label, color, p.tracker.Theme.Shaper) + label := Label(hint.Label, color, p.tracker.Theme.Material.Shaper) if info == "" { return label(gtx) }