diff --git a/ui/browsing/browsingpane.go b/ui/browsing/browsingpane.go index c432a4e..cadee11 100644 --- a/ui/browsing/browsingpane.go +++ b/ui/browsing/browsingpane.go @@ -5,9 +5,9 @@ import ( "supersonic/ui/controller" "supersonic/ui/layouts" myTheme "supersonic/ui/theme" + "supersonic/ui/widgets" "fyne.io/fyne/v2" - "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/layout" "fyne.io/fyne/v2/theme" @@ -67,11 +67,8 @@ func NewBrowsingPane(app *backend.App) *BrowsingPane { b.forward = widget.NewButtonWithIcon("", theme.NavigateNextIcon(), b.GoForward) b.reload = widget.NewButtonWithIcon("", theme.ViewRefreshIcon(), b.Reload) b.app.PlaybackManager.OnSongChange(b.onSongChange) - b.pageContainer = container.NewMax( - canvas.NewRectangle(fyne.CurrentApp().Settings().Theme().Color( - myTheme.ColorNamePageBackground, fyne.CurrentApp().Settings().ThemeVariant(), - )), - layout.NewSpacer()) + bkgrnd := widgets.NewThemedRectangle(myTheme.ColorNamePageBackground) + b.pageContainer = container.NewMax(bkgrnd, layout.NewSpacer()) b.settingsBtn = widget.NewButtonWithIcon("", theme.SettingsIcon(), func() { p := widget.NewPopUpMenu(b.settingsMenu, fyne.CurrentApp().Driver().CanvasForObject(b.settingsBtn)) @@ -110,19 +107,19 @@ func (b *BrowsingPane) AddSettingsMenuItem(label string, action func()) { fyne.NewMenuItem(label, action)) } -func (b *BrowsingPane) AddNavigationButton(iconRes fyne.Resource, action func()) { - b.navBtnsContainer.Add(widget.NewButtonWithIcon("", iconRes, action)) +func (b *BrowsingPane) AddNavigationButton(iconName fyne.ThemeIconName, action func()) { + b.navBtnsContainer.Add(widgets.NewThemedIconButton(iconName, "", action)) } func (b *BrowsingPane) DisableNavigationButtons() { for _, obj := range b.navBtnsContainer.Objects { - obj.(*widget.Button).Disable() + obj.(*widgets.ThemedIconButton).Disable() } } func (b *BrowsingPane) EnableNavigationButtons() { for _, obj := range b.navBtnsContainer.Objects { - obj.(*widget.Button).Enable() + obj.(*widgets.ThemedIconButton).Enable() } } diff --git a/ui/mainwindow.go b/ui/mainwindow.go index 17bbf5c..be2ae54 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -3,10 +3,10 @@ package ui import ( "fmt" "supersonic/backend" - "supersonic/res" "supersonic/ui/browsing" "supersonic/ui/controller" "supersonic/ui/os" + "supersonic/ui/theme" "fyne.io/fyne/v2" "fyne.io/fyne/v2/container" @@ -178,22 +178,22 @@ func (m *MainWindow) ShowNewVersionDialog(appName, versionTag string) { } func (m *MainWindow) addNavigationButtons() { - m.BrowsingPane.AddNavigationButton(res.ResHeadphonesInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNameNowPlaying, func() { m.Router.NavigateTo(controller.NowPlayingRoute("")) }) - m.BrowsingPane.AddNavigationButton(res.ResHeartFilledInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNameFavorite, func() { m.Router.NavigateTo(controller.FavoritesRoute()) }) - m.BrowsingPane.AddNavigationButton(res.ResDiscInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNameAlbum, func() { m.Router.NavigateTo(controller.AlbumsRoute()) }) - m.BrowsingPane.AddNavigationButton(res.ResPeopleInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNameArtist, func() { m.Router.NavigateTo(controller.ArtistsRoute()) }) - m.BrowsingPane.AddNavigationButton(res.ResTheatermasksInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNameGenre, func() { m.Router.NavigateTo(controller.GenresRoute()) }) - m.BrowsingPane.AddNavigationButton(res.ResPlaylistInvertPng, func() { + m.BrowsingPane.AddNavigationButton(theme.IconNamePlaylist, func() { m.Router.NavigateTo(controller.PlaylistsRoute()) }) m.BrowsingPane.AddNavigationButton(res.ResMusicnotesInvertPng, func() { diff --git a/ui/theme/theme.go b/ui/theme/theme.go index b49941e..633d013 100644 --- a/ui/theme/theme.go +++ b/ui/theme/theme.go @@ -14,16 +14,6 @@ import ( const ColorNamePageBackground fyne.ThemeColorName = "PageBackground" -var ( - normalFont fyne.Resource - boldFont fyne.Resource -) - -type MyTheme struct { - NormalFont string - BoldFont string -} - const ( IconNameNowPlaying fyne.ThemeIconName = "NowPlaying" IconNameFavorite fyne.ThemeIconName = "Favorite" @@ -35,20 +25,40 @@ const ( IconNameShuffle fyne.ThemeIconName = "Shuffle" ) +type VariantMode int + +const ( + VariantModeAuto VariantMode = iota + VariantModeDark + VariantModeLight +) + +var ( + normalFont fyne.Resource + boldFont fyne.Resource +) + +type MyTheme struct { + NormalFont string + BoldFont string + VariantMode VariantMode +} + var _ fyne.Theme = (*MyTheme)(nil) -func (m *MyTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color { +func (m *MyTheme) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color { + variant := m.getVariant() switch name { case ColorNamePageBackground: if variant == theme.VariantDark { return color.RGBA{R: 15, G: 15, B: 15, A: 255} } - return color.RGBA{R: 255, G: 255, B: 255, A: 255} + return color.RGBA{R: 250, G: 250, B: 250, A: 255} case theme.ColorNameBackground: if variant == theme.VariantDark { return color.RGBA{R: 35, G: 35, B: 35, A: 255} } - return color.RGBA{R: 240, G: 240, B: 240, A: 255} + return color.RGBA{R: 225, G: 225, B: 225, A: 255} case theme.ColorNameScrollBar: if variant == theme.VariantDark { return theme.DarkTheme().Color(theme.ColorNameForeground, variant) @@ -76,23 +86,48 @@ func (m *MyTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) col } func (m *MyTheme) Icon(name fyne.ThemeIconName) fyne.Resource { + variant := m.getVariant() switch name { case IconNameAlbum: - return res.ResDiscInvertPng + if variant == theme.VariantDark { + return res.ResDiscInvertPng + } + return res.ResDiscPng case IconNameArtist: - return res.ResPeopleInvertPng + if variant == theme.VariantDark { + return res.ResPeopleInvertPng + } + return res.ResPeoplePng case IconNameFavorite: - return res.ResHeartFilledInvertPng + if variant == theme.VariantDark { + return res.ResHeartFilledInvertPng + } + return res.ResHeartFilledPng case IconNameNotFavorite: - return res.ResHeartOutlineInvertPng + if variant == theme.VariantDark { + return res.ResHeartOutlineInvertPng + } + return res.ResHeartOutlinePng case IconNameGenre: - return res.ResTheatermasksInvertPng + if variant == theme.VariantDark { + return res.ResTheatermasksInvertPng + } + return res.ResTheatermasksPng case IconNameNowPlaying: - return res.ResHeadphonesInvertPng + if variant == theme.VariantDark { + return res.ResHeadphonesInvertPng + } + return res.ResHeadphonesPng case IconNamePlaylist: - return res.ResPlaylistInvertPng + if variant == theme.VariantDark { + return res.ResPlaylistInvertPng + } + return res.ResPlaylistPng case IconNameShuffle: - return res.ResShuffleInvertSvg + if variant == theme.VariantDark { + return res.ResShuffleInvertSvg + } + return res.ResShuffleSvg default: return theme.DefaultTheme().Icon(name) } @@ -127,7 +162,6 @@ func (m *MyTheme) Font(style fyne.TextStyle) fyne.Resource { return normalFont } } - return theme.DefaultTheme().Font(style) } @@ -135,6 +169,15 @@ func (m *MyTheme) Size(name fyne.ThemeSizeName) float32 { return theme.DefaultTheme().Size(name) } +func (m *MyTheme) getVariant() fyne.ThemeVariant { + if m.VariantMode == VariantModeDark { + return theme.VariantDark + } else if m.VariantMode == VariantModeLight { + return theme.VariantLight + } + return fyne.CurrentApp().Settings().ThemeVariant() +} + func readTTFFile(filepath string) ([]byte, error) { if !strings.HasSuffix(filepath, ".ttf") { err := errors.New("only .ttf fonts are supported") diff --git a/ui/widgets/favoritebutton.go b/ui/widgets/favoritebutton.go index 942ffac..bac50e4 100644 --- a/ui/widgets/favoritebutton.go +++ b/ui/widgets/favoritebutton.go @@ -2,6 +2,7 @@ package widgets import ( "supersonic/res" + "supersonic/ui/theme" "fyne.io/fyne/v2" "fyne.io/fyne/v2/widget" @@ -31,10 +32,12 @@ func (f *FavoriteButton) Tapped(e *fyne.PointEvent) { } func (f *FavoriteButton) Refresh() { + var iconName fyne.ThemeIconName if f.IsFavorited { - f.Icon = res.ResHeartFilledInvertPng + iconName = theme.IconNameFavorite } else { - f.Icon = res.ResHeartOutlineInvertPng + iconName = theme.IconNameNotFavorite } + f.Icon = fyne.CurrentApp().Settings().Theme().Icon(iconName) f.Button.Refresh() } diff --git a/ui/widgets/listheader.go b/ui/widgets/listheader.go index e90d829..ccf21b3 100644 --- a/ui/widgets/listheader.go +++ b/ui/widgets/listheader.go @@ -5,7 +5,6 @@ import ( "supersonic/ui/layouts" "fyne.io/fyne/v2" - "fyne.io/fyne/v2/canvas" "fyne.io/fyne/v2/container" "fyne.io/fyne/v2/theme" "fyne.io/fyne/v2/widget" @@ -42,7 +41,7 @@ func NewListHeader(cols []ListColumn, layout *layouts.ColumnsLayout) *ListHeader for i, _ := range l.columnVisible { l.columnVisible[i] = true } - l.container = container.NewMax(canvas.NewRectangle(theme.BackgroundColor()), l.columnsContainer) + l.container = container.NewMax(NewThemedRectangle(theme.ColorNameBackground), l.columnsContainer) l.ExtendBaseWidget(l) l.buildColumns() return l diff --git a/ui/widgets/themed.go b/ui/widgets/themed.go new file mode 100644 index 0000000..b709607 --- /dev/null +++ b/ui/widgets/themed.go @@ -0,0 +1,63 @@ +package widgets + +import ( + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/widget" +) + +type ThemedIconButton struct { + widget.Button + + IconName fyne.ThemeIconName +} + +func NewThemedIconButton(iconName fyne.ThemeIconName, text string, action func()) *ThemedIconButton { + b := &ThemedIconButton{ + IconName: iconName, + Button: widget.Button{ + Text: text, + OnTapped: action, + }, + } + b.updateIcon() + b.ExtendBaseWidget(b) + return b +} + +func (b *ThemedIconButton) updateIcon() { + b.Icon = fyne.CurrentApp().Settings().Theme().Icon(b.IconName) +} + +func (b *ThemedIconButton) Refresh() { + b.updateIcon() + b.Button.Refresh() +} + +type ThemedRectangle struct { + widget.BaseWidget + + rect *canvas.Rectangle + + ColorName fyne.ThemeColorName +} + +func NewThemedRectangle(colorName fyne.ThemeColorName) *ThemedRectangle { + t := &ThemedRectangle{ + ColorName: colorName, + rect: canvas.NewRectangle(fyne.CurrentApp().Settings().Theme().Color(colorName, + fyne.CurrentApp().Settings().ThemeVariant())), + } + t.ExtendBaseWidget(t) + return t +} + +func (t *ThemedRectangle) Refresh() { + t.rect.FillColor = fyne.CurrentApp().Settings().Theme().Color(t.ColorName, + fyne.CurrentApp().Settings().ThemeVariant()) + t.BaseWidget.Refresh() +} + +func (t *ThemedRectangle) CreateRenderer() fyne.WidgetRenderer { + return widget.NewSimpleRenderer(t.rect) +}