adam-gui/vendor/fyne.io/fyne/v2/app/settings.go

169 lines
3.9 KiB
Go
Raw Permalink Normal View History

2024-04-29 19:13:50 +02:00
package app
import (
"bytes"
"os"
"path/filepath"
"sync"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/theme"
)
var noAnimations bool // set to true at compile time if no_animations tag is passed
// SettingsSchema is used for loading and storing global settings
type SettingsSchema struct {
// these items are used for global settings load
ThemeName string `json:"theme"`
Scale float32 `json:"scale"`
PrimaryColor string `json:"primary_color"`
CloudName string `json:"cloud_name"`
CloudConfig string `json:"cloud_config"`
DisableAnimations bool `json:"no_animations"`
}
// StoragePath returns the location of the settings storage
func (sc *SettingsSchema) StoragePath() string {
return filepath.Join(rootConfigDir(), "settings.json")
}
// Declare conformity with Settings interface
var _ fyne.Settings = (*settings)(nil)
type settings struct {
propertyLock sync.RWMutex
theme fyne.Theme
themeSpecified bool
variant fyne.ThemeVariant
changeListeners sync.Map // map[chan fyne.Settings]bool
watcher interface{} // normally *fsnotify.Watcher or nil - avoid import in this file
schema SettingsSchema
}
func (s *settings) BuildType() fyne.BuildType {
return buildMode
}
func (s *settings) PrimaryColor() string {
s.propertyLock.RLock()
defer s.propertyLock.RUnlock()
return s.schema.PrimaryColor
}
// OverrideTheme allows the settings app to temporarily preview different theme details.
// Please make sure that you remember the original settings and call this again to revert the change.
func (s *settings) OverrideTheme(theme fyne.Theme, name string) {
s.propertyLock.Lock()
defer s.propertyLock.Unlock()
s.schema.PrimaryColor = name
s.theme = theme
}
func (s *settings) Theme() fyne.Theme {
s.propertyLock.RLock()
defer s.propertyLock.RUnlock()
return s.theme
}
func (s *settings) SetTheme(theme fyne.Theme) {
s.themeSpecified = true
s.applyTheme(theme, s.variant)
}
func (s *settings) ShowAnimations() bool {
return !s.schema.DisableAnimations && !noAnimations
}
func (s *settings) ThemeVariant() fyne.ThemeVariant {
return s.variant
}
func (s *settings) applyTheme(theme fyne.Theme, variant fyne.ThemeVariant) {
s.propertyLock.Lock()
defer s.propertyLock.Unlock()
s.variant = variant
s.theme = theme
s.apply()
}
func (s *settings) Scale() float32 {
s.propertyLock.RLock()
defer s.propertyLock.RUnlock()
if s.schema.Scale < 0.0 {
return 1.0 // catching any really old data still using the `-1` value for "auto" scale
}
return s.schema.Scale
}
func (s *settings) AddChangeListener(listener chan fyne.Settings) {
s.changeListeners.Store(listener, true) // the boolean is just a dummy value here.
}
func (s *settings) apply() {
s.changeListeners.Range(func(key, _ interface{}) bool {
listener := key.(chan fyne.Settings)
select {
case listener <- s:
default:
l := listener
go func() { l <- s }()
}
return true
})
}
func (s *settings) fileChanged() {
s.load()
s.apply()
}
func (s *settings) loadSystemTheme() fyne.Theme {
path := filepath.Join(rootConfigDir(), "theme.json")
data, err := fyne.LoadResourceFromPath(path)
if err != nil {
if !os.IsNotExist(err) {
fyne.LogError("Failed to load user theme file: "+path, err)
}
return theme.DefaultTheme()
}
if data != nil && data.Content() != nil {
th, err := theme.FromJSONReader(bytes.NewReader(data.Content()))
if err == nil {
return th
}
fyne.LogError("Failed to parse user theme file: "+path, err)
}
return theme.DefaultTheme()
}
func (s *settings) setupTheme() {
name := s.schema.ThemeName
if env := os.Getenv("FYNE_THEME"); env != "" {
name = env
}
variant := defaultVariant()
effectiveTheme := s.theme
if !s.themeSpecified {
effectiveTheme = s.loadSystemTheme()
}
switch name {
case "light":
variant = theme.VariantLight
case "dark":
variant = theme.VariantDark
}
s.applyTheme(effectiveTheme, variant)
}
func loadSettings() *settings {
s := &settings{}
s.load()
return s
}