165 lines
5.8 KiB
Go
165 lines
5.8 KiB
Go
package ui
|
|
|
|
import (
|
|
"image/color"
|
|
|
|
"fyne.io/fyne/v2"
|
|
"fyne.io/fyne/v2/theme"
|
|
)
|
|
|
|
// 主题模式。
|
|
const (
|
|
ThemeSystem = "system" // 跟随系统
|
|
ThemeContrast = "contrast" // 黑白高对比
|
|
ThemeLight = "light" // 浅色高对比
|
|
)
|
|
|
|
// themeLabel 返回主题模式的中文名。
|
|
func themeLabel(mode string) string {
|
|
switch mode {
|
|
case ThemeContrast:
|
|
return "黑白高对比"
|
|
case ThemeLight:
|
|
return "浅色高对比"
|
|
default:
|
|
return "跟随系统"
|
|
}
|
|
}
|
|
|
|
// themeOptions 返回设置页下拉里的可选项。
|
|
func themeOptions() []string {
|
|
return []string{
|
|
themeLabel(ThemeSystem),
|
|
themeLabel(ThemeContrast),
|
|
themeLabel(ThemeLight),
|
|
}
|
|
}
|
|
|
|
// themeFromLabel 由中文名反查主题模式。
|
|
func themeFromLabel(label string) string {
|
|
for _, mode := range []string{ThemeSystem, ThemeContrast, ThemeLight} {
|
|
if themeLabel(mode) == label {
|
|
return mode
|
|
}
|
|
}
|
|
return ThemeSystem
|
|
}
|
|
|
|
// applyThemeMode 按主题模式切换界面主题。
|
|
func applyThemeMode(mode string) {
|
|
app := fyne.CurrentApp()
|
|
if app == nil {
|
|
return
|
|
}
|
|
switch mode {
|
|
case ThemeContrast:
|
|
app.Settings().SetTheme(newMonoTheme(darkPalette()))
|
|
case ThemeLight:
|
|
app.Settings().SetTheme(newMonoTheme(lightPalette()))
|
|
default:
|
|
app.Settings().SetTheme(theme.DefaultTheme())
|
|
}
|
|
}
|
|
|
|
// monoTheme 是一套纯灰度主题:所有颜色都去掉彩度,只靠明暗区分层级,
|
|
// 文字与背景的对比拉到最高。
|
|
type monoTheme struct {
|
|
base fyne.Theme
|
|
colors map[fyne.ThemeColorName]color.Color
|
|
}
|
|
|
|
// newMonoTheme 用给定配色造一个主题,其余项沿用默认主题。
|
|
func newMonoTheme(palette map[fyne.ThemeColorName]color.Color) fyne.Theme {
|
|
return &monoTheme{base: theme.DefaultTheme(), colors: palette}
|
|
}
|
|
|
|
func (t *monoTheme) Color(name fyne.ThemeColorName, variant fyne.ThemeVariant) color.Color {
|
|
if c, ok := t.colors[name]; ok {
|
|
return c
|
|
}
|
|
return t.base.Color(name, variant)
|
|
}
|
|
|
|
func (t *monoTheme) Font(style fyne.TextStyle) fyne.Resource { return t.base.Font(style) }
|
|
|
|
func (t *monoTheme) Icon(name fyne.ThemeIconName) fyne.Resource { return t.base.Icon(name) }
|
|
|
|
func (t *monoTheme) Size(name fyne.ThemeSizeName) float32 { return t.base.Size(name) }
|
|
|
|
// rgb 生成不透明灰度色。
|
|
func rgb(v uint8) color.NRGBA {
|
|
return color.NRGBA{R: v, G: v, B: v, A: 0xFF}
|
|
}
|
|
|
|
// darkPalette 是黑白高对比(纯黑底)的配色。
|
|
func darkPalette() map[fyne.ThemeColorName]color.Color {
|
|
return map[fyne.ThemeColorName]color.Color{
|
|
theme.ColorNameBackground: rgb(0x00),
|
|
theme.ColorNameForeground: rgb(0xFF),
|
|
theme.ColorNameDisabled: rgb(0x8C),
|
|
theme.ColorNameDisabledButton: rgb(0x1A),
|
|
theme.ColorNameButton: rgb(0x2E),
|
|
theme.ColorNameHover: rgb(0x4A),
|
|
theme.ColorNamePressed: rgb(0x1E),
|
|
theme.ColorNameFocus: rgb(0xFF),
|
|
theme.ColorNamePrimary: rgb(0xFF),
|
|
theme.ColorNameForegroundOnPrimary: rgb(0x00),
|
|
theme.ColorNameSelection: rgb(0xFF),
|
|
theme.ColorNameInputBackground: rgb(0x0B),
|
|
theme.ColorNameInputBorder: rgb(0xE6),
|
|
theme.ColorNamePlaceHolder: rgb(0xA6),
|
|
theme.ColorNameSeparator: rgb(0x5A),
|
|
theme.ColorNameOverlayBackground: rgb(0x11),
|
|
theme.ColorNameMenuBackground: rgb(0x16),
|
|
theme.ColorNameHeaderBackground: rgb(0x1C),
|
|
theme.ColorNameInnerWindowBorder: rgb(0x3A),
|
|
theme.ColorNameInnerWindowBorderInactive: rgb(0x26),
|
|
theme.ColorNameScrollBar: rgb(0x9A),
|
|
theme.ColorNameScrollBarBackground: rgb(0x1A),
|
|
theme.ColorNameShadow: rgb(0x00),
|
|
theme.ColorNameError: rgb(0xFF),
|
|
theme.ColorNameForegroundOnError: rgb(0x00),
|
|
theme.ColorNameSuccess: rgb(0xFF),
|
|
theme.ColorNameForegroundOnSuccess: rgb(0x00),
|
|
theme.ColorNameWarning: rgb(0xFF),
|
|
theme.ColorNameForegroundOnWarning: rgb(0x00),
|
|
theme.ColorNameHyperlink: rgb(0xFF),
|
|
}
|
|
}
|
|
|
|
// lightPalette 是浅色高对比(纯白底)的配色。
|
|
func lightPalette() map[fyne.ThemeColorName]color.Color {
|
|
return map[fyne.ThemeColorName]color.Color{
|
|
theme.ColorNameBackground: rgb(0xFF),
|
|
theme.ColorNameForeground: rgb(0x00),
|
|
theme.ColorNameDisabled: rgb(0x70),
|
|
theme.ColorNameDisabledButton: rgb(0xF0),
|
|
theme.ColorNameButton: rgb(0xE0),
|
|
theme.ColorNameHover: rgb(0xC8),
|
|
theme.ColorNamePressed: rgb(0xD4),
|
|
theme.ColorNameFocus: rgb(0x00),
|
|
theme.ColorNamePrimary: rgb(0x00),
|
|
theme.ColorNameForegroundOnPrimary: rgb(0xFF),
|
|
theme.ColorNameSelection: rgb(0x00),
|
|
theme.ColorNameInputBackground: rgb(0xFF),
|
|
theme.ColorNameInputBorder: rgb(0x00),
|
|
theme.ColorNamePlaceHolder: rgb(0x70),
|
|
theme.ColorNameSeparator: rgb(0x9A),
|
|
theme.ColorNameOverlayBackground: rgb(0xF4),
|
|
theme.ColorNameMenuBackground: rgb(0xFA),
|
|
theme.ColorNameHeaderBackground: rgb(0xEF),
|
|
theme.ColorNameInnerWindowBorder: rgb(0xC0),
|
|
theme.ColorNameInnerWindowBorderInactive: rgb(0xD8),
|
|
theme.ColorNameScrollBar: rgb(0x55),
|
|
theme.ColorNameScrollBarBackground: rgb(0xED),
|
|
theme.ColorNameShadow: rgb(0x00),
|
|
theme.ColorNameError: rgb(0x00),
|
|
theme.ColorNameForegroundOnError: rgb(0xFF),
|
|
theme.ColorNameSuccess: rgb(0x00),
|
|
theme.ColorNameForegroundOnSuccess: rgb(0xFF),
|
|
theme.ColorNameWarning: rgb(0x00),
|
|
theme.ColorNameForegroundOnWarning: rgb(0xFF),
|
|
theme.ColorNameHyperlink: rgb(0x00),
|
|
}
|
|
}
|