diff --git a/tracker/gioui/buttons.go b/tracker/gioui/buttons.go index cba4fc7..f5de38a 100644 --- a/tracker/gioui/buttons.go +++ b/tracker/gioui/buttons.go @@ -17,7 +17,6 @@ import ( "gioui.org/text" "gioui.org/unit" "gioui.org/widget" - "gioui.org/widget/material" "gioui.org/x/component" "github.com/vsariola/sointu/tracker" ) @@ -58,28 +57,28 @@ func NewBoolClickable(b tracker.Bool) *BoolClickable { } } -func Tooltip(th *material.Theme, tip string) component.Tooltip { - tooltip := component.PlatformTooltip(th, tip) - tooltip.Bg = black - tooltip.Text.Color = white +func Tooltip(th *Theme, tip string) component.Tooltip { + tooltip := component.PlatformTooltip(&th.Material, tip) + tooltip.Bg = th.Tooltip.Bg + tooltip.Text.Color = th.Tooltip.Color return tooltip } -func ActionIcon(gtx C, th *material.Theme, w *ActionClickable, icon []byte, tip string) TipIconButtonStyle { +func ActionIcon(gtx C, th *Theme, w *ActionClickable, icon []byte, tip string) TipIconButtonStyle { ret := TipIcon(th, &w.TipClickable, icon, tip) for w.Clickable.Clicked(gtx) { w.Action.Do() } if !w.Action.Allowed() { - ret.IconButtonStyle.Color = disabledTextColor + ret.IconButtonStyle.Color = th.Button.Disabled.Color } return ret } -func TipIcon(th *material.Theme, w *TipClickable, icon []byte, tip string) TipIconButtonStyle { +func TipIcon(th *Theme, w *TipClickable, icon []byte, tip string) TipIconButtonStyle { iconButtonStyle := IconButton(th, &w.Clickable, widgetForIcon(icon), "") - iconButtonStyle.Color = th.Palette.ContrastBg - iconButtonStyle.Background = transparent + iconButtonStyle.Color = th.Material.Palette.ContrastBg + iconButtonStyle.Background = color.NRGBA{} iconButtonStyle.Inset = layout.UniformInset(unit.Dp(6)) return TipIconButtonStyle{ TipArea: &w.TipArea, @@ -88,7 +87,7 @@ func TipIcon(th *material.Theme, w *TipClickable, icon []byte, tip string) TipIc } } -func ToggleIcon(gtx C, th *material.Theme, w *BoolClickable, offIcon, onIcon []byte, offTip, onTip string) TipIconButtonStyle { +func ToggleIcon(gtx C, th *Theme, w *BoolClickable, offIcon, onIcon []byte, offTip, onTip string) TipIconButtonStyle { icon := offIcon tip := offTip if w.Bool.Value() { @@ -99,11 +98,11 @@ func ToggleIcon(gtx C, th *material.Theme, w *BoolClickable, offIcon, onIcon []b w.Bool.Toggle() } ibStyle := IconButton(th, &w.Clickable, widgetForIcon(icon), "") - ibStyle.Background = transparent + ibStyle.Background = color.NRGBA{} ibStyle.Inset = layout.UniformInset(unit.Dp(6)) - ibStyle.Color = th.Palette.ContrastBg + ibStyle.Color = th.Material.Palette.ContrastBg if !w.Bool.Enabled() { - ibStyle.Color = disabledTextColor + ibStyle.Color = th.Button.Disabled.Color } return TipIconButtonStyle{ TipArea: &w.TipArea, @@ -121,7 +120,7 @@ func ActionButton(gtx C, th *Theme, style *ButtonStyle, w *ActionClickable, text w.Action.Do() } if !w.Action.Allowed() { - return Btn(th, &th.DisabledButton, &w.Clickable, text) + return Btn(th, &th.Button.Disabled, &w.Clickable, text) } return Btn(th, style, &w.Clickable, text) } @@ -131,12 +130,12 @@ func ToggleButton(gtx C, th *Theme, b *BoolClickable, text string) Button { b.Bool.Toggle() } if !b.Bool.Enabled() { - return Btn(th, &th.DisabledButton, &b.Clickable, text) + return Btn(th, &th.Button.Disabled, &b.Clickable, text) } if b.Bool.Value() { - return Btn(th, &th.FilledButton, &b.Clickable, text) + return Btn(th, &th.Button.Filled, &b.Clickable, text) } - return Btn(th, &th.TextButton, &b.Clickable, text) + return Btn(th, &th.Button.Text, &b.Clickable, text) } // Clickable represents a clickable area. @@ -293,10 +292,10 @@ func Btn(th *Theme, style *ButtonStyle, button *Clickable, txt string) Button { return b } -func IconButton(th *material.Theme, button *Clickable, icon *widget.Icon, description string) IconButtonStyle { +func IconButton(th *Theme, button *Clickable, icon *widget.Icon, description string) IconButtonStyle { return IconButtonStyle{ - Background: th.Palette.ContrastBg, - Color: th.Palette.ContrastFg, + Background: th.Material.Palette.ContrastBg, + Color: th.Material.Palette.ContrastFg, Icon: icon, Size: 24, Inset: layout.UniformInset(12), diff --git a/tracker/gioui/dialog.go b/tracker/gioui/dialog.go index 2aace09..d7451d7 100644 --- a/tracker/gioui/dialog.go +++ b/tracker/gioui/dialog.go @@ -1,6 +1,8 @@ package gioui import ( + "image/color" + "gioui.org/io/key" "gioui.org/layout" "gioui.org/op/paint" @@ -49,7 +51,7 @@ func ConfirmDialog(gtx C, th *Theme, dialog *Dialog, title, text string) DialogS Theme: th, } for _, b := range [...]*material.ButtonStyle{&ret.AltStyle, &ret.OkStyle, &ret.CancelStyle} { - b.Background = transparent + b.Background = color.NRGBA{} b.Inset = layout.UniformInset(unit.Dp(6)) b.Color = th.Material.Palette.Fg } @@ -108,7 +110,7 @@ func (d *DialogStyle) Layout(gtx C) D { paint.Fill(gtx.Ops, d.Theme.Dialog.Bg) visible := true return layout.Center.Layout(gtx, func(gtx C) D { - return Popup(&visible).Layout(gtx, func(gtx C) D { + return Popup(d.Theme, &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.Theme, &d.Theme.Dialog.Title, d.Title).Layout), diff --git a/tracker/gioui/draglist.go b/tracker/gioui/draglist.go index 74dff81..cbe22ef 100644 --- a/tracker/gioui/draglist.go +++ b/tracker/gioui/draglist.go @@ -15,7 +15,6 @@ import ( "gioui.org/op" "gioui.org/op/clip" "gioui.org/op/paint" - "gioui.org/unit" "github.com/vsariola/sointu/tracker" ) @@ -33,18 +32,12 @@ type DragList struct { } type FilledDragListStyle struct { - dragList *DragList - HoverColor color.NRGBA - Cursor struct { - Active color.NRGBA - Inactive color.NRGBA - } - Selection struct { - Active color.NRGBA - Inactive color.NRGBA - } - ScrollBarWidth unit.Dp - element, bg func(gtx C, i int) D + dragList *DragList + HoverColor color.NRGBA + Cursor CursorStyle + Selection CursorStyle + ScrollBar ScrollBarStyle + element, bg func(gtx C, i int) D } func NewDragList(model tracker.List, axis layout.Axis) *DragList { @@ -53,13 +46,13 @@ func NewDragList(model tracker.List, axis layout.Axis) *DragList { func FilledDragList(th *Theme, dragList *DragList, element, bg func(gtx C, i int) D) FilledDragListStyle { return FilledDragListStyle{ - dragList: dragList, - element: element, - bg: bg, - HoverColor: hoveredColor(th.Selection.Active), - Cursor: th.Cursor, - Selection: th.Selection, - ScrollBarWidth: unit.Dp(10), + dragList: dragList, + element: element, + bg: bg, + HoverColor: hoveredColor(th.Selection.Active), + Cursor: th.Cursor, + Selection: th.Selection, + ScrollBar: th.ScrollBar, } } @@ -72,7 +65,7 @@ func (d *DragList) Focused() bool { } func (s FilledDragListStyle) LayoutScrollBar(gtx C) D { - return s.dragList.ScrollBar.Layout(gtx, s.ScrollBarWidth, s.dragList.TrackerList.Count(), &s.dragList.List.Position) + return s.dragList.ScrollBar.Layout(gtx, &s.ScrollBar, s.dragList.TrackerList.Count(), &s.dragList.List.Position) } func (s FilledDragListStyle) Layout(gtx C) D { diff --git a/tracker/gioui/instrument_editor.go b/tracker/gioui/instrument_editor.go index 9a85b67..447a5ab 100644 --- a/tracker/gioui/instrument_editor.go +++ b/tracker/gioui/instrument_editor.go @@ -124,8 +124,8 @@ 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.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) + 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) octave := func(gtx C) D { in := layout.UniformInset(unit.Dp(1)) @@ -134,7 +134,7 @@ func (ie *InstrumentEditor) Layout(gtx C, t *Tracker) D { return dims } - newBtnStyle := ActionIcon(gtx, &t.Theme.Material, ie.newInstrumentBtn, icons.ContentAdd, ie.addInstrumentHint) + newBtnStyle := ActionIcon(gtx, t.Theme, 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( @@ -175,17 +175,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.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) + 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) - m := PopupMenu(t.Theme, &ie.presetMenu) + m := PopupMenu(t.Theme, &t.Theme.Menu.Text, &ie.presetMenu) for ie.copyInstrumentBtn.Clickable.Clicked(gtx) { if contents, ok := t.Instruments().List().CopyElements(); ok { @@ -314,7 +314,7 @@ func (ie *InstrumentEditor) layoutInstrumentList(gtx C, t *Tracker) D { } instrumentList := FilledDragList(t.Theme, ie.instrumentDragList, element, nil) - instrumentList.ScrollBarWidth = unit.Dp(6) + instrumentList.ScrollBar = t.Theme.InstrumentEditor.InstrumentList.ScrollBar defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() defer clip.Rect(image.Rect(0, 0, gtx.Constraints.Max.X, gtx.Constraints.Max.Y)).Push(gtx.Ops).Pop() @@ -351,7 +351,7 @@ 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.Material, ie.addUnitBtn, icons.ContentAdd, "Add unit (Enter)") + addUnitBtnStyle := ActionIcon(gtx, t.Theme, ie.addUnitBtn, icons.ContentAdd, "Add unit (Enter)") addUnitBtnStyle.IconButtonStyle.Color = t.Theme.Material.ContrastFg addUnitBtnStyle.IconButtonStyle.Background = t.Theme.Material.ContrastBg addUnitBtnStyle.IconButtonStyle.Inset = layout.UniformInset(unit.Dp(4)) diff --git a/tracker/gioui/menu.go b/tracker/gioui/menu.go index 5ada9c6..8f1aadb 100644 --- a/tracker/gioui/menu.go +++ b/tracker/gioui/menu.go @@ -26,13 +26,11 @@ type Menu struct { type MenuStyle struct { Menu *Menu Title string - IconColor color.NRGBA - TextColor color.NRGBA ShortCutColor color.NRGBA - FontSize unit.Sp - IconSize unit.Dp HoverColor color.NRGBA Theme *Theme + LabelStyle LabelStyle + Disabled color.NRGBA } type MenuItem struct { @@ -99,21 +97,21 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { macro = op.Record(gtx.Ops) } icon := widgetForIcon(item.IconBytes) - iconColor := m.IconColor - if !item.Doer.Allowed() { - iconColor = mediumEmphasisTextColor - } + iconColor := m.LabelStyle.Color iconInset := layout.Inset{Left: unit.Dp(12), Right: unit.Dp(6)} textLabel := Label(m.Theme, &m.Theme.Menu.Text, item.Text) + shortcutLabel := Label(m.Theme, &m.Theme.Menu.Text, item.ShortcutText) + shortcutLabel.Color = m.ShortCutColor if !item.Doer.Allowed() { - textLabel.Color = mediumEmphasisTextColor + iconColor = m.Disabled + textLabel.Color = m.Disabled + shortcutLabel.Color = m.Disabled } - 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 { return iconInset.Layout(gtx, func(gtx C) D { - p := gtx.Dp(unit.Dp(m.IconSize)) + p := gtx.Dp(unit.Dp(m.LabelStyle.TextSize)) gtx.Constraints.Min = image.Pt(p, p) return icon.Layout(gtx, iconColor) }) @@ -141,26 +139,24 @@ func (m *MenuStyle) Layout(gtx C, items ...MenuItem) D { }) }), layout.Expanded(func(gtx C) D { - return m.Menu.scrollBar.Layout(gtx, unit.Dp(10), len(items), &m.Menu.list.Position) + return m.Menu.scrollBar.Layout(gtx, &m.Theme.ScrollBar, len(items), &m.Menu.list.Position) }), ) } - popup := Popup(&m.Menu.Visible) + popup := Popup(m.Theme, &m.Menu.Visible) popup.NE = unit.Dp(0) popup.ShadowN = unit.Dp(0) popup.NW = unit.Dp(0) return popup.Layout(gtx, contents) } -func PopupMenu(th *Theme, menu *Menu) MenuStyle { +func PopupMenu(th *Theme, s *LabelStyle, menu *Menu) MenuStyle { return MenuStyle{ Menu: menu, - IconColor: white, - TextColor: white, - ShortCutColor: mediumEmphasisTextColor, - FontSize: unit.Sp(16), - IconSize: unit.Dp(16), - HoverColor: menuHoverColor, + ShortCutColor: th.Menu.ShortCut, + LabelStyle: *s, + HoverColor: th.Menu.Hover, + Disabled: th.Menu.Disabled, Theme: th, } } @@ -169,12 +165,10 @@ func (tr *Tracker) layoutMenu(gtx C, title string, clickable *Clickable, menu *M for clickable.Clicked(gtx) { menu.Visible = true } - m := PopupMenu(tr.Theme, menu) + m := PopupMenu(tr.Theme, &tr.Theme.Menu.Text, menu) return func(gtx C) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() - titleBtn := Btn(tr.Theme, &tr.Theme.MenuButton, clickable, title) - titleBtn.Color = white - titleBtn.Background = transparent + titleBtn := Btn(tr.Theme, &tr.Theme.Button.Menu, clickable, title) titleBtn.CornerRadius = unit.Dp(0) dims := titleBtn.Layout(gtx) op.Offset(image.Pt(0, dims.Size.Y)).Add(gtx.Ops) diff --git a/tracker/gioui/note_editor.go b/tracker/gioui/note_editor.go index d94e238..43bf09c 100644 --- a/tracker/gioui/note_editor.go +++ b/tracker/gioui/note_editor.go @@ -150,21 +150,21 @@ 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, &t.Theme.TextButton, te.AddSemitoneBtn, "+1") - subtractSemitoneBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.TextButton, te.SubtractSemitoneBtn, "-1") - addOctaveBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.TextButton, te.AddOctaveBtn, "+12") - subtractOctaveBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.TextButton, te.SubtractOctaveBtn, "-12") - noteOffBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.TextButton, 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) + addSemitoneBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.Button.Text, te.AddSemitoneBtn, "+1") + subtractSemitoneBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.Button.Text, te.SubtractSemitoneBtn, "-1") + addOctaveBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.Button.Text, te.AddOctaveBtn, "+12") + subtractOctaveBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.Button.Text, te.SubtractOctaveBtn, "-12") + noteOffBtnStyle := ActionButton(gtx, t.Theme, &t.Theme.Button.Text, 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) in := layout.UniformInset(unit.Dp(1)) voiceUpDown := func(gtx C) D { numStyle := NumUpDown(t.Theme, te.TrackVoices, "Track voices") return in.Layout(gtx, numStyle.Layout) } effectBtnStyle := ToggleButton(gtx, t.Theme, te.EffectBtn, "Hex") - uniqueBtnStyle := ToggleIcon(gtx, &t.Theme.Material, te.UniqueBtn, icons.ToggleStarBorder, icons.ToggleStar, te.uniqueOffTip, te.uniqueOnTip) + uniqueBtnStyle := ToggleIcon(gtx, t.Theme, te.UniqueBtn, icons.ToggleStarBorder, icons.ToggleStar, te.uniqueOffTip, te.uniqueOnTip) midiInBtnStyle := ToggleButton(gtx, t.Theme, 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)} }), @@ -230,12 +230,12 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { rowTitleBg := func(gtx C, j int) D { if mod(j, beatMarkerDensity*2) == 0 { - paint.FillShape(gtx.Ops, twoBeatHighlight, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) + paint.FillShape(gtx.Ops, t.Theme.NoteEditor.TwoBeat, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) } else if mod(j, beatMarkerDensity) == 0 { - paint.FillShape(gtx.Ops, oneBeatHighlight, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) + paint.FillShape(gtx.Ops, t.Theme.NoteEditor.OneBeat, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) } if t.Model.Playing().Value() && j == playSongRow { - paint.FillShape(gtx.Ops, trackerPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) + paint.FillShape(gtx.Ops, t.Theme.NoteEditor.Play, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, pxHeight)}.Op()) } return D{} } @@ -288,7 +288,7 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { c = t.Theme.Cursor.Active } if hasTrackMidiIn { - c = cursorForTrackMidiInColor + c = t.Theme.Cursor.ActiveAlt } te.paintColumnCell(gtx, x, t, c) } @@ -296,7 +296,7 @@ func (te *NoteEditor) layoutTracks(gtx C, t *Tracker) D { if hasTrackMidiIn { for _, trackIndex := range t.Model.TracksWithSameInstrumentAsCurrent() { if x == trackIndex && y == cursor.Y { - te.paintColumnCell(gtx, x, t, cursorNeighborForTrackMidiInColor) + te.paintColumnCell(gtx, x, t, t.Theme.Selection.ActiveAlt) } } } diff --git a/tracker/gioui/numericupdown.go b/tracker/gioui/numericupdown.go index 29231f2..374c238 100644 --- a/tracker/gioui/numericupdown.go +++ b/tracker/gioui/numericupdown.go @@ -60,7 +60,7 @@ func NumUpDown(th *Theme, number *NumberInput, tooltip string) NumericUpDown { return NumericUpDown{ NumberInput: number, Shaper: th.Material.Shaper, - Tooltip: Tooltip(&th.Material, tooltip), + Tooltip: Tooltip(th, tooltip), NumericUpDownStyle: th.NumericUpDown, } } diff --git a/tracker/gioui/order_editor.go b/tracker/gioui/order_editor.go index efac535..90b4bfd 100644 --- a/tracker/gioui/order_editor.go +++ b/tracker/gioui/order_editor.go @@ -74,7 +74,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { rowTitleBg := func(gtx C, j int) D { if t.Model.Playing().Value() && j == t.PlayPosition().OrderRow { - paint.FillShape(gtx.Ops, patternPlayColor, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, gtx.Dp(patternCellHeight))}.Op()) + paint.FillShape(gtx.Ops, t.Theme.OrderEditor.Play, clip.Rect{Max: image.Pt(gtx.Constraints.Max.X, gtx.Dp(patternCellHeight))}.Op()) } return D{} } @@ -98,7 +98,7 @@ func (oe *OrderEditor) Layout(gtx C, t *Tracker) D { cell := func(gtx C, x, y int) D { val := patternIndexToString(t.Model.Order().Value(tracker.Point{X: x, Y: y})) - color := patternCellColor + color := t.Theme.OrderEditor.CellBg point := tracker.Point{X: x, Y: y} if selection.Contains(point) { color = t.Theme.Selection.Inactive diff --git a/tracker/gioui/popup.go b/tracker/gioui/popup.go index c477317..70cb19e 100644 --- a/tracker/gioui/popup.go +++ b/tracker/gioui/popup.go @@ -24,11 +24,11 @@ type PopupStyle struct { SE, SW, NW, NE unit.Dp } -func Popup(visible *bool) PopupStyle { +func Popup(th *Theme, visible *bool) PopupStyle { return PopupStyle{ Visible: visible, - SurfaceColor: popupSurfaceColor, - ShadowColor: popupShadowColor, + SurfaceColor: th.Popup.Bg, + ShadowColor: th.Popup.Shadow, ShadowN: unit.Dp(2), ShadowE: unit.Dp(2), ShadowS: unit.Dp(2), diff --git a/tracker/gioui/scrollbar.go b/tracker/gioui/scrollbar.go index 03fc21a..506bdd1 100644 --- a/tracker/gioui/scrollbar.go +++ b/tracker/gioui/scrollbar.go @@ -2,6 +2,7 @@ package gioui import ( "image" + "image/color" "gioui.org/f32" "gioui.org/io/event" @@ -21,19 +22,27 @@ type ScrollBar struct { tag bool } -func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Position) D { +type ScrollBarStyle struct { + Color color.NRGBA + Width unit.Dp + Gradient color.NRGBA +} + +func (s *ScrollBar) Layout(gtx C, style *ScrollBarStyle, numItems int, pos *layout.Position) D { defer op.Offset(image.Point{}).Push(gtx.Ops).Pop() defer clip.Rect{Max: gtx.Constraints.Min}.Push(gtx.Ops).Pop() gradientSize := gtx.Dp(unit.Dp(4)) var totalPixelsEstimate, scrollBarRelLength float32 + transparent := style.Gradient + transparent.A = 0 switch s.Axis { case layout.Vertical: if pos.First > 0 || pos.Offset > 0 { - paint.LinearGradientOp{Color1: black, Color2: transparent, Stop2: f32.Pt(0, float32(gradientSize))}.Add(gtx.Ops) + paint.LinearGradientOp{Color1: style.Gradient, Color2: transparent, Stop2: f32.Pt(0, float32(gradientSize))}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) } if pos.BeforeEnd { - paint.LinearGradientOp{Color1: black, Color2: transparent, Stop1: f32.Pt(0, float32(gtx.Constraints.Min.Y)), Stop2: f32.Pt(0, float32(gtx.Constraints.Min.Y-gradientSize))}.Add(gtx.Ops) + paint.LinearGradientOp{Color1: style.Gradient, Color2: transparent, Stop1: f32.Pt(0, float32(gtx.Constraints.Min.Y)), Stop2: f32.Pt(0, float32(gtx.Constraints.Min.Y-gradientSize))}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) } totalPixelsEstimate = float32(gtx.Constraints.Min.Y+pos.Offset-pos.OffsetLast) * float32(numItems) / float32(pos.Count) @@ -41,11 +50,11 @@ func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Posit case layout.Horizontal: if pos.First > 0 || pos.Offset > 0 { - paint.LinearGradientOp{Color1: black, Color2: transparent, Stop2: f32.Pt(float32(gradientSize), 0)}.Add(gtx.Ops) + paint.LinearGradientOp{Color1: style.Gradient, Color2: transparent, Stop2: f32.Pt(float32(gradientSize), 0)}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) } if pos.BeforeEnd { - paint.LinearGradientOp{Color1: black, Color2: transparent, Stop1: f32.Pt(float32(gtx.Constraints.Min.X), 0), Stop2: f32.Pt(float32(gtx.Constraints.Min.X-gradientSize), 0)}.Add(gtx.Ops) + paint.LinearGradientOp{Color1: style.Gradient, Color2: transparent, Stop1: f32.Pt(float32(gtx.Constraints.Min.X), 0), Stop2: f32.Pt(float32(gtx.Constraints.Min.X-gradientSize), 0)}.Add(gtx.Ops) paint.PaintOp{}.Add(gtx.Ops) } totalPixelsEstimate = float32(gtx.Constraints.Min.X+pos.Offset-pos.OffsetLast) * float32(numItems) / float32(pos.Count) @@ -56,7 +65,7 @@ func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Posit } scrollBarRelStart := (float32(pos.First)*totalPixelsEstimate/float32(numItems) + float32(pos.Offset)) / totalPixelsEstimate - scrWidth := gtx.Dp(width) + scrWidth := gtx.Dp(style.Width) stack := op.Offset(image.Point{}).Push(gtx.Ops) var area clip.Stack @@ -65,7 +74,7 @@ func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Posit if scrollBarRelLength < 1 && (s.dragging || s.hovering) { y1 := int(scrollBarRelStart * float32(gtx.Constraints.Min.Y)) y2 := int((scrollBarRelStart + scrollBarRelLength) * float32(gtx.Constraints.Min.Y)) - paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(gtx.Constraints.Min.X-scrWidth, y1), Max: image.Pt(gtx.Constraints.Min.X, y2)}.Op()) + paint.FillShape(gtx.Ops, style.Color, clip.Rect{Min: image.Pt(gtx.Constraints.Min.X-scrWidth, y1), Max: image.Pt(gtx.Constraints.Min.X, y2)}.Op()) } rect := image.Rect(gtx.Constraints.Min.X-scrWidth, 0, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) area = clip.Rect(rect).Push(gtx.Ops) @@ -73,7 +82,7 @@ func (s *ScrollBar) Layout(gtx C, width unit.Dp, numItems int, pos *layout.Posit if scrollBarRelLength < 1 && (s.dragging || s.hovering) { x1 := int(scrollBarRelStart * float32(gtx.Constraints.Min.X)) x2 := int((scrollBarRelStart + scrollBarRelLength) * float32(gtx.Constraints.Min.X)) - paint.FillShape(gtx.Ops, scrollBarColor, clip.Rect{Min: image.Pt(x1, gtx.Constraints.Min.Y-scrWidth), Max: image.Pt(x2, gtx.Constraints.Min.Y)}.Op()) + paint.FillShape(gtx.Ops, style.Color, clip.Rect{Min: image.Pt(x1, gtx.Constraints.Min.Y-scrWidth), Max: image.Pt(x2, gtx.Constraints.Min.Y)}.Op()) } rect := image.Rect(0, gtx.Constraints.Min.Y-scrWidth, gtx.Constraints.Min.X, gtx.Constraints.Min.Y) area = clip.Rect(rect).Push(gtx.Ops) diff --git a/tracker/gioui/songpanel.go b/tracker/gioui/songpanel.go index 6da6dda..5b04922 100644 --- a/tracker/gioui/songpanel.go +++ b/tracker/gioui/songpanel.go @@ -11,7 +11,6 @@ import ( "gioui.org/op/clip" "gioui.org/op/paint" "gioui.org/unit" - "gioui.org/widget/material" "github.com/vsariola/sointu/tracker" "github.com/vsariola/sointu/version" "golang.org/x/exp/shiny/materialdesign/icons" @@ -76,7 +75,7 @@ func (s *SongPanel) Layout(gtx C, t *Tracker) D { return s.MenuBar.Layout(gtx, t) }), layout.Rigid(func(gtx C) D { - return s.PlayBar.Layout(gtx, &t.Theme.Material) + return s.PlayBar.Layout(gtx, t.Theme) }), layout.Rigid(func(gtx C) D { return s.layoutSongOptions(gtx, t) @@ -99,13 +98,13 @@ func (t *SongPanel) layoutSongOptions(gtx C, tr *Tracker) D { weightingTxt = "No weight (RMS)" } - weightingBtn := Btn(tr.Theme, &tr.Theme.TextButton, t.WeightingTypeBtn, weightingTxt) + weightingBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.WeightingTypeBtn, weightingTxt) oversamplingTxt := "Sample peak" if tr.Model.Oversampling().Value() { oversamplingTxt = "True peak" } - oversamplingBtn := Btn(tr.Theme, &tr.Theme.TextButton, t.OversamplingBtn, oversamplingTxt) + oversamplingBtn := Btn(tr.Theme, &tr.Theme.Button.Text, t.OversamplingBtn, oversamplingTxt) return layout.Flex{Axis: layout.Vertical}.Layout(gtx, layout.Rigid(func(gtx C) D { @@ -334,7 +333,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.Material, t.PanicBtn, icons.AlertErrorOutline, icons.AlertError, t.panicHint, t.panicHint) + panicBtnStyle := ToggleIcon(gtx, tr.Theme, t.PanicBtn, icons.AlertErrorOutline, icons.AlertError, t.panicHint, t.panicHint) if t.PanicBtn.Bool.Value() { panicBtnStyle.IconButtonStyle.Color = tr.Theme.SongPanel.ErrorColor } @@ -388,7 +387,7 @@ func NewPlayBar(model *tracker.Model) *PlayBar { return ret } -func (pb *PlayBar) Layout(gtx C, th *material.Theme) D { +func (pb *PlayBar) Layout(gtx C, th *Theme) D { rewindBtnStyle := ActionIcon(gtx, th, pb.RewindBtn, icons.AVFastRewind, pb.rewindHint) playBtnStyle := ToggleIcon(gtx, th, pb.PlayingBtn, icons.AVPlayArrow, icons.AVStop, pb.playHint, pb.stopHint) recordBtnStyle := ToggleIcon(gtx, th, pb.RecordBtn, icons.AVFiberManualRecord, icons.AVFiberSmartRecord, pb.recordHint, pb.stopRecordHint) diff --git a/tracker/gioui/theme.go b/tracker/gioui/theme.go index 2442844..26a709c 100644 --- a/tracker/gioui/theme.go +++ b/tracker/gioui/theme.go @@ -13,16 +13,19 @@ import ( ) type Theme struct { - Material material.Theme - FilledButton ButtonStyle - TextButton ButtonStyle - DisabledButton ButtonStyle - MenuButton ButtonStyle - Oscilloscope OscilloscopeStyle - NumericUpDown NumericUpDownStyle - DialogTitle LabelStyle - DialogText LabelStyle - SongPanel struct { + Define any // this is just needed for yaml.UnmarshalStrict, so we can have "defines" in the yaml + Material material.Theme + Button struct { + Filled ButtonStyle + Text ButtonStyle + Disabled ButtonStyle + Menu ButtonStyle + } + Oscilloscope OscilloscopeStyle + NumericUpDown NumericUpDownStyle + DialogTitle LabelStyle + DialogText LabelStyle + SongPanel struct { RowHeader LabelStyle RowValue LabelStyle Expander LabelStyle @@ -44,6 +47,9 @@ type Theme struct { Unique LabelStyle Loop color.NRGBA Header LabelStyle + Play color.NRGBA + OneBeat color.NRGBA + TwoBeat color.NRGBA } Dialog struct { Bg color.NRGBA @@ -55,10 +61,14 @@ type Theme struct { RowTitle LabelStyle Cell LabelStyle Loop color.NRGBA + CellBg color.NRGBA + Play color.NRGBA } Menu struct { Text LabelStyle - ShortCut LabelStyle + ShortCut color.NRGBA + Hover color.NRGBA + Disabled color.NRGBA } InstrumentEditor struct { Octave LabelStyle @@ -69,6 +79,7 @@ type Theme struct { Number LabelStyle Name LabelStyle NameMuted LabelStyle + ScrollBar ScrollBarStyle } UnitList struct { Name LabelStyle @@ -84,15 +95,26 @@ type Theme struct { Hint LabelStyle Chooser LabelStyle ParameterName LabelStyle + InvalidParam color.NRGBA + SendTarget color.NRGBA } - Cursor struct { - Active color.NRGBA - Inactive color.NRGBA + Cursor CursorStyle + Selection CursorStyle + Tooltip struct { + Color color.NRGBA + Bg color.NRGBA } - Selection struct { - Active color.NRGBA - Inactive color.NRGBA + Popup struct { + Bg color.NRGBA + Shadow color.NRGBA } + ScrollBar ScrollBarStyle +} + +type CursorStyle struct { + Active color.NRGBA + ActiveAlt color.NRGBA // alternative color for the cursor, used e.g. when the midi input is active + Inactive color.NRGBA } //go:embed theme.yml @@ -100,12 +122,10 @@ var defaultTheme []byte func NewTheme() *Theme { var theme Theme - err := yaml.Unmarshal(defaultTheme, &theme) + err := yaml.UnmarshalStrict(defaultTheme, &theme) if err != nil { panic(fmt.Errorf("failed to default theme: %w", err)) } - str, _ := yaml.Marshal(theme) - fmt.Printf(string(str)) ReadCustomConfigYml("theme.yml", &theme) theme.Material.Shaper = &text.Shaper{} theme.Material.Icon.CheckBoxChecked = must(widget.NewIcon(icons.ToggleCheckBox)) @@ -121,30 +141,3 @@ func must[T any](ic T, err error) T { } return ic } - -var white = color.NRGBA{R: 255, G: 255, B: 255, A: 255} -var black = color.NRGBA{R: 0, G: 0, B: 0, A: 255} -var transparent = color.NRGBA{A: 0} - -var mediumEmphasisTextColor = color.NRGBA{R: 153, G: 153, B: 153, A: 153} -var disabledTextColor = color.NRGBA{R: 255, G: 255, B: 255, A: 97} - -var trackerPlayColor = color.NRGBA{R: 55, G: 55, B: 61, A: 255} -var oneBeatHighlight = color.NRGBA{R: 31, G: 37, B: 38, A: 255} -var twoBeatHighlight = color.NRGBA{R: 31, G: 51, B: 53, A: 255} - -var patternPlayColor = color.NRGBA{R: 55, G: 55, B: 61, A: 255} -var patternCellColor = color.NRGBA{R: 255, G: 255, B: 255, A: 3} - -var popupSurfaceColor = color.NRGBA{R: 50, G: 50, B: 51, A: 255} -var popupShadowColor = color.NRGBA{R: 0, G: 0, B: 0, A: 192} - -var cursorForTrackMidiInColor = color.NRGBA{R: 255, G: 100, B: 140, A: 48} -var cursorNeighborForTrackMidiInColor = color.NRGBA{R: 255, G: 100, B: 140, A: 24} - -var menuHoverColor = color.NRGBA{R: 30, G: 31, B: 38, A: 255} - -var scrollBarColor = color.NRGBA{R: 255, G: 255, B: 255, A: 32} - -var paramIsSendTargetColor = color.NRGBA{R: 120, G: 120, B: 210, A: 255} -var paramValueInvalidColor = color.NRGBA{R: 120, G: 120, B: 120, A: 190} diff --git a/tracker/gioui/theme.yml b/tracker/gioui/theme.yml index 9e32ae3..185ae00 100644 --- a/tracker/gioui/theme.yml +++ b/tracker/gioui/theme.yml @@ -1,16 +1,20 @@ -# 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 } -loopcolor: &loopcolor { r: 252, g: 186, b: 3, a: 255 } +# Because we use yaml.UnmarshalStrict, we needed to have "Define any" field for +# all the defines; UnmarshalStrict thrwows an error if a field is not defined +define: + [ + &primarycolor { r: 206, g: 147, b: 216, a: 255 }, + &secondarycolor { r: 128, g: 222, b: 234, a: 255 }, + &transparentcolor { r: 0, g: 0, b: 0, a: 0 }, + &mediumemphasis { r: 153, g: 153, b: 153, a: 255 }, + &highemphasis { r: 222, g: 222, b: 222, a: 255 }, + &disabled { r: 255, g: 255, b: 255, a: 97 }, + &errorcolor { r: 207, g: 102, b: 121, a: 255 }, + &warningcolor { r: 251, g: 192, b: 45, a: 255 }, + &white { r: 255, g: 255, b: 255, a: 255 }, + &black { r: 0, g: 0, b: 0, a: 255 }, + &loopcolor { r: 252, g: 186, b: 3, a: 255 }, + &scrollbarcolor { r: 255, g: 255, b: 255, a: 32 }, + ] # from here on starts the structs defined in the theme.go material: @@ -21,40 +25,41 @@ material: fg: &fg { r: 255, g: 255, b: 255, a: 255 } contrastbg: *primarycolor contrastfg: &contrastfg { r: 0, g: 0, b: 0, a: 255 } -filledbutton: - background: *primarycolor - color: *contrastfg - textsize: &buttontextsize 14 - 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 +button: + filled: + background: *primarycolor + color: *contrastfg + textsize: &buttontextsize 14 + cornerradius: &buttoncornerradius 18 + height: &buttonheight 36 + inset: &buttoninset { top: 0, bottom: 0, left: 6, right: 6 } + text: + background: *transparentcolor + color: *primarycolor + textsize: *buttontextsize + cornerradius: *buttoncornerradius + height: *buttonheight + inset: *buttoninset + disabled: + 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 + menu: + background: *transparentcolor + color: { r: 255, g: 255, b: 255, a: 255 } + textsize: *buttontextsize + cornerradius: 0 + height: *buttonheight + inset: *buttoninset oscilloscope: curvecolors: [*primarycolor, *secondarycolor] 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 } + bgcolor: { r: 255, g: 255, b: 255, a: 3 } textcolor: *fg iconcolor: *primarycolor cornerradius: 4 @@ -64,7 +69,7 @@ numericupdown: width: 70 height: 20 songpanel: - bg: { r: 24, g: 24, b: 24, A: 255 } + bg: { r: 24, g: 24, b: 24, a: 255 } rowheader: textsize: 14 color: *mediumemphasis @@ -78,7 +83,7 @@ songpanel: version: textsize: 12 color: *mediumemphasis -alerts: +alert: error: bg: *errorcolor text: { textsize: 16, color: *black } @@ -98,8 +103,10 @@ ordereditor: { textsize: 16, color: *secondarycolor, font: { typeface: "Go Mono" } } cell: { textsize: 16, color: *primarycolor, font: { typeface: "Go Mono" } } loop: *loopcolor + cellbg: { r: 255, g: 255, b: 255, a: 3 } + play: { r: 55, g: 55, b: 61, a: 255 } noteeditor: - tracktitle: { textsize: 12, color: *mediumemphasis } + tracktitle: { textsize: 12, color: *mediumemphasis, alignment: 2 } orderrow: { textsize: 16, color: *secondarycolor, font: { typeface: "Go Mono" } } patternrow: @@ -111,9 +118,14 @@ noteeditor: { textsize: 16, color: *secondarycolor, font: { typeface: "Go Mono" } } loop: *loopcolor header: { textsize: 14, color: *disabled } + play: { r: 55, g: 55, b: 61, a: 255 } + onebeat: { r: 31, g: 37, b: 38, a: 255 } + twobeat: { r: 31, g: 51, b: 53, a: 255 } menu: text: { textsize: 16, color: *highemphasis, shadowcolor: *black } - shortcut: { textsize: 16, color: *mediumemphasis, shadowcolor: *black } + shortcut: *mediumemphasis + hover: { r: 100, g: 140, b: 255, a: 48 } + disabled: *disabled instrumenteditor: octave: { textsize: 14, color: *disabled } voices: { textsize: 14, color: *disabled } @@ -123,6 +135,7 @@ instrumenteditor: number: { textsize: 10, color: *mediumemphasis, shadowcolor: *black } name: { textsize: 12, color: *white, shadowcolor: *black } namemuted: { textsize: 12, color: *disabled } + scrollbar: { width: 6, color: *scrollbarcolor } unitlist: name: { textsize: 12, color: *white, shadowcolor: *black } namedisabled: @@ -139,9 +152,18 @@ uniteditor: hint: { textsize: 16, color: *highemphasis, shadowcolor: *black } chooser: { textsize: 12, color: *white, shadowcolor: *black } parametername: { textsize: 16, color: *white, shadowcolor: *black } + invalidparam: { r: 120, g: 120, b: 120, a: 190 } + sendtarget: { r: 120, g: 120, b: 210, a: 255 } cursor: active: { r: 100, g: 140, b: 255, a: 48 } + activealt: { r: 255, g: 100, b: 140, a: 48 } inactive: { r: 140, g: 140, b: 140, a: 48 } selection: active: { r: 100, g: 140, b: 255, a: 16 } + activealt: { r: 255, g: 100, b: 140, a: 24 } inactive: { r: 140, g: 140, b: 140, a: 16 } +scrollbar: { width: 10, color: *scrollbarcolor, gradient: *black } +tooltip: { color: *white, bg: *black } +popup: + bg: { r: 50, g: 50, b: 51, a: 255 } + shadow: { r: 0, g: 0, b: 0, a: 192 } diff --git a/tracker/gioui/unit_editor.go b/tracker/gioui/unit_editor.go index 627af23..ba20b1d 100644 --- a/tracker/gioui/unit_editor.go +++ b/tracker/gioui/unit_editor.go @@ -132,9 +132,9 @@ func (pe *UnitEditor) layoutFooter(gtx C, t *Tracker) D { t.Alerts().Add("Unit copied to clipboard", tracker.Info) } } - 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) + 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) text := t.Units().SelectedType() if text == "" { text = "Choose unit type" @@ -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.Material, pe.ClearUnitBtn, icons.ContentClear, "Clear unit") + clearUnitBtnStyle := ActionIcon(gtx, t.Theme, pe.ClearUnitBtn, icons.ContentClear, "Clear unit") dims = clearUnitBtnStyle.Layout(gtx) } return D{Size: image.Pt(gtx.Dp(unit.Dp(48)), dims.Size.Y)} @@ -253,7 +253,7 @@ type ParameterStyle struct { func (t *Tracker) ParamStyle(th *Theme, paramWidget *ParameterWidget) ParameterStyle { sendTargetTheme := th.Material.WithPalette(material.Palette{ Bg: th.Material.Bg, - Fg: paramIsSendTargetColor, + Fg: th.UnitEditor.SendTarget, ContrastBg: th.Material.ContrastBg, ContrastFg: th.Material.ContrastFg, }) @@ -297,7 +297,7 @@ func (p ParameterStyle) Layout(gtx C) D { } sliderStyle := material.Slider(&p.Theme.Material, &p.w.floatWidget) if isSendTarget { - sliderStyle.Color = paramIsSendTargetColor + sliderStyle.Color = p.Theme.UnitEditor.SendTarget } r := image.Rectangle{Max: gtx.Constraints.Min} defer clip.Rect(r).Push(gtx.Ops).Pop() @@ -372,7 +372,7 @@ func (p ParameterStyle) Layout(gtx C) D { hint := p.w.Parameter.Hint() label := Label(p.tracker.Theme, &p.tracker.Theme.UnitEditor.Hint, hint.Label) if !hint.Valid { - label.Color = paramValueInvalidColor + label.Color = p.tracker.Theme.UnitEditor.InvalidParam } if info == "" { return label.Layout(gtx)