203 lines
5.2 KiB
Go
203 lines
5.2 KiB
Go
package theme
|
|
|
|
import (
|
|
"errors"
|
|
"image/color"
|
|
"io/ioutil"
|
|
"log"
|
|
"strings"
|
|
"supersonic/backend"
|
|
"supersonic/res"
|
|
"supersonic/sharedutil"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/theme"
|
|
)
|
|
|
|
const ColorNamePageBackground fyne.ThemeColorName = "PageBackground"
|
|
|
|
const (
|
|
IconNameNowPlaying fyne.ThemeIconName = "NowPlaying"
|
|
IconNameFavorite fyne.ThemeIconName = "Favorite"
|
|
IconNameNotFavorite fyne.ThemeIconName = "NotFavorite"
|
|
IconNameAlbum fyne.ThemeIconName = "Album"
|
|
IconNameArtist fyne.ThemeIconName = "Artist"
|
|
IconNameGenre fyne.ThemeIconName = "Genre"
|
|
IconNamePlaylist fyne.ThemeIconName = "Playlist"
|
|
IconNameShuffle fyne.ThemeIconName = "Shuffle"
|
|
)
|
|
|
|
type AppearanceMode string
|
|
|
|
const (
|
|
AppearanceLight AppearanceMode = "Light"
|
|
AppearanceDark AppearanceMode = "Dark"
|
|
AppearanceAuto AppearanceMode = "Auto"
|
|
)
|
|
|
|
var (
|
|
normalFont fyne.Resource
|
|
boldFont fyne.Resource
|
|
)
|
|
|
|
type MyTheme struct {
|
|
NormalFont string
|
|
BoldFont string
|
|
Config *backend.ThemeConfig
|
|
}
|
|
|
|
var _ fyne.Theme = (*MyTheme)(nil)
|
|
|
|
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: 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: 225, G: 223, B: 225, A: 255}
|
|
case theme.ColorNameScrollBar:
|
|
if variant == theme.VariantDark {
|
|
return theme.DarkTheme().Color(theme.ColorNameForeground, variant)
|
|
}
|
|
return theme.LightTheme().Color(theme.ColorNameForeground, variant)
|
|
case theme.ColorNameButton:
|
|
if variant == theme.VariantDark {
|
|
return color.RGBA{R: 20, G: 20, B: 20, A: 50}
|
|
}
|
|
return color.RGBA{R: 200, G: 200, B: 200, A: 240}
|
|
case theme.ColorNameInputBackground:
|
|
if variant == theme.VariantDark {
|
|
return color.RGBA{R: 20, G: 20, B: 20, A: 50}
|
|
}
|
|
case theme.ColorNameForeground:
|
|
if variant == theme.VariantLight {
|
|
return color.RGBA{R: 10, G: 10, B: 10, A: 255}
|
|
}
|
|
case theme.ColorNamePrimary:
|
|
if variant == theme.VariantLight {
|
|
return color.RGBA{R: 25, G: 25, B: 250, A: 255}
|
|
}
|
|
}
|
|
return theme.DefaultTheme().Color(name, variant)
|
|
}
|
|
|
|
func (m *MyTheme) Icon(name fyne.ThemeIconName) fyne.Resource {
|
|
variant := m.getVariant()
|
|
switch name {
|
|
case IconNameAlbum:
|
|
if variant == theme.VariantDark {
|
|
return res.ResDiscInvertPng
|
|
}
|
|
return res.ResDiscPng
|
|
case IconNameArtist:
|
|
if variant == theme.VariantDark {
|
|
return res.ResPeopleInvertPng
|
|
}
|
|
return res.ResPeoplePng
|
|
case IconNameFavorite:
|
|
if variant == theme.VariantDark {
|
|
return res.ResHeartFilledInvertPng
|
|
}
|
|
return res.ResHeartFilledPng
|
|
case IconNameNotFavorite:
|
|
if variant == theme.VariantDark {
|
|
return res.ResHeartOutlineInvertPng
|
|
}
|
|
return res.ResHeartOutlinePng
|
|
case IconNameGenre:
|
|
if variant == theme.VariantDark {
|
|
return res.ResTheatermasksInvertPng
|
|
}
|
|
return res.ResTheatermasksPng
|
|
case IconNameNowPlaying:
|
|
if variant == theme.VariantDark {
|
|
return res.ResHeadphonesInvertPng
|
|
}
|
|
return res.ResHeadphonesPng
|
|
case IconNamePlaylist:
|
|
if variant == theme.VariantDark {
|
|
return res.ResPlaylistInvertPng
|
|
}
|
|
return res.ResPlaylistPng
|
|
case IconNameShuffle:
|
|
if variant == theme.VariantDark {
|
|
return res.ResShuffleInvertSvg
|
|
}
|
|
return res.ResShuffleSvg
|
|
default:
|
|
return theme.DefaultTheme().Icon(name)
|
|
}
|
|
}
|
|
|
|
<<<<<<< HEAD
|
|
func (m *MyTheme) Font(style fyne.TextStyle) fyne.Resource {
|
|
switch style {
|
|
case fyne.TextStyle{}:
|
|
if m.NormalFont != "" && normalFont == nil {
|
|
if content, err := readTTFFile(m.NormalFont); err != nil {
|
|
m.NormalFont = ""
|
|
m.BoldFont = ""
|
|
} else {
|
|
normalFont = fyne.NewStaticResource("normalFont", content)
|
|
}
|
|
}
|
|
if normalFont != nil {
|
|
return normalFont
|
|
}
|
|
case fyne.TextStyle{Bold: true}:
|
|
if m.BoldFont != "" && boldFont == nil {
|
|
if content, err := ioutil.ReadFile(m.BoldFont); err != nil {
|
|
m.BoldFont = ""
|
|
} else {
|
|
normalFont = fyne.NewStaticResource("boldFont", content)
|
|
}
|
|
}
|
|
if boldFont != nil {
|
|
return boldFont
|
|
}
|
|
if normalFont != nil {
|
|
return normalFont
|
|
}
|
|
}
|
|
return theme.DefaultTheme().Font(style)
|
|
}
|
|
|
|
func (m *MyTheme) Size(name fyne.ThemeSizeName) float32 {
|
|
return theme.DefaultTheme().Size(name)
|
|
}
|
|
|
|
func (m *MyTheme) getVariant() fyne.ThemeVariant {
|
|
v := "Dark" // default if config has invalid or missing setting
|
|
if sharedutil.StringSliceContains(
|
|
[]string{string(AppearanceLight), string(AppearanceDark), string(AppearanceAuto)},
|
|
m.Config.Appearance) {
|
|
v = m.Config.Appearance
|
|
}
|
|
|
|
if AppearanceMode(v) == AppearanceDark {
|
|
return theme.VariantDark
|
|
} else if AppearanceMode(v) == AppearanceLight {
|
|
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")
|
|
log.Printf("error loading custom font %q: %s", filepath, err.Error())
|
|
return nil, err
|
|
}
|
|
content, err := ioutil.ReadFile(filepath)
|
|
if err != nil {
|
|
log.Printf("error loading custom font %q: %s", filepath, err.Error())
|
|
}
|
|
return content, err
|
|
}
|