Add theme management functionality to the application
Implemented a theme management system allowing users to select and persist themes (default, light, dark) in the settings menu.
This commit is contained in:
parent
712ec2f182
commit
82167f042f
@ -5,6 +5,7 @@ import (
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/localizer"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
)
|
||||
|
||||
@ -20,6 +21,7 @@ type MenuHandler struct {
|
||||
menuViewSetting menu.ViewSettingContract
|
||||
localizerView localizer.ViewContract
|
||||
localizerRepository localizer.RepositoryContract
|
||||
themeService theme.ThemeContract
|
||||
}
|
||||
|
||||
func NewMenuHandler(
|
||||
@ -29,6 +31,7 @@ func NewMenuHandler(
|
||||
menuViewSetting menu.ViewSettingContract,
|
||||
localizerView localizer.ViewContract,
|
||||
localizerRepository localizer.RepositoryContract,
|
||||
themeService theme.ThemeContract,
|
||||
) *MenuHandler {
|
||||
return &MenuHandler{
|
||||
app: app,
|
||||
@ -37,6 +40,7 @@ func NewMenuHandler(
|
||||
menuViewSetting: menuViewSetting,
|
||||
localizerView: localizerView,
|
||||
localizerRepository: localizerRepository,
|
||||
themeService: themeService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -154,6 +158,12 @@ func (h MenuHandler) settingsSelection() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = h.themeService.SetCurrentTheme(setting.ThemeInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h.convertorHandler.MainConvertor()
|
||||
return nil
|
||||
}
|
||||
|
@ -426,6 +426,10 @@ other = "Licenses from other products used in the program"
|
||||
hash = "sha1-ed3f0e507a5b4ed0649d7c768fe0d47413d839ba"
|
||||
other = "Language"
|
||||
|
||||
[menuSettingsTheme]
|
||||
hash = "sha1-553c45f1b84a92b08dc1f088c13f924cde95765e"
|
||||
other = "Theme"
|
||||
|
||||
[or]
|
||||
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
|
||||
other = "or"
|
||||
@ -522,6 +526,18 @@ other = "Settings"
|
||||
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
|
||||
other = "Checking FFmpeg for serviceability..."
|
||||
|
||||
[themesNameDark]
|
||||
hash = "sha1-bd16b234708a2515a9f2d0ca41fb11e7fe8a38a2"
|
||||
other = "Dark"
|
||||
|
||||
[themesNameDefault]
|
||||
hash = "sha1-469631cb165dcbbfea9e747056c25fbccb28c481"
|
||||
other = "Default"
|
||||
|
||||
[themesNameLight]
|
||||
hash = "sha1-8080010c5e7d7edf56e89a99d8a2422898417845"
|
||||
other = "Light"
|
||||
|
||||
[titleDownloadLink]
|
||||
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
|
||||
other = "You can download it from here"
|
||||
|
@ -426,6 +426,10 @@ other = "Бағдарламада пайдаланылатын басқа өні
|
||||
hash = "sha1-ed3f0e507a5b4ed0649d7c768fe0d47413d839ba"
|
||||
other = "Тіл"
|
||||
|
||||
[menuSettingsTheme]
|
||||
hash = "sha1-553c45f1b84a92b08dc1f088c13f924cde95765e"
|
||||
other = "Тақырып"
|
||||
|
||||
[or]
|
||||
hash = "sha1-30bb0333ca1583110e4ced513b5d2455b86f529b"
|
||||
other = "немесе"
|
||||
@ -522,6 +526,18 @@ other = "Параметрлер"
|
||||
hash = "sha1-f5b8ed88e9609963035d2235be0a79bbec619976"
|
||||
other = "FFmpeg функционалдығы тексерілуде..."
|
||||
|
||||
[themesNameDark]
|
||||
hash = "sha1-bd16b234708a2515a9f2d0ca41fb11e7fe8a38a2"
|
||||
other = "Қараңғы тақырып"
|
||||
|
||||
[themesNameDefault]
|
||||
hash = "sha1-469631cb165dcbbfea9e747056c25fbccb28c481"
|
||||
other = "Әдепкі бойынша"
|
||||
|
||||
[themesNameLight]
|
||||
hash = "sha1-8080010c5e7d7edf56e89a99d8a2422898417845"
|
||||
other = "Жеңіл тақырып"
|
||||
|
||||
[titleDownloadLink]
|
||||
hash = "sha1-92df86371f6c3a06ca1e4754f113142776a32d49"
|
||||
other = "Сіз оны осы жерден жүктей аласыз"
|
||||
|
@ -105,6 +105,7 @@ languageSelectionHead = "Выберите язык"
|
||||
licenseLink = "Сведения о лицензии"
|
||||
licenseLinkOther = "Лицензии от других продуктов, которые используются в программе"
|
||||
menuSettingsLanguage = "Язык"
|
||||
menuSettingsTheme = "Тема"
|
||||
or = "или"
|
||||
parameterCheckbox = "Включить параметр"
|
||||
pathToFfmpeg = "Путь к FFmpeg:"
|
||||
@ -129,6 +130,9 @@ selectFFPathTitle = "Укажите путь к FFmpeg и к FFprobe"
|
||||
selectFormat = "Расширение файла:"
|
||||
settings = "Настройки"
|
||||
testFF = "Проверка FFmpeg на работоспособность..."
|
||||
themesNameDark = "Тёмная"
|
||||
themesNameDefault = "По умолчанию"
|
||||
themesNameLight = "Светлая"
|
||||
titleDownloadLink = "Скачать можно от сюда"
|
||||
total = "Всего"
|
||||
unzipRun = "Распаковывается..."
|
||||
|
8
main.go
8
main.go
@ -12,6 +12,7 @@ import (
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/menu"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/migration"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme"
|
||||
"go.etcd.io/bbolt"
|
||||
"golang.org/x/text/language"
|
||||
"os"
|
||||
@ -109,10 +110,13 @@ func main() {
|
||||
convertorView := convertor.NewView(application)
|
||||
convertorHandler := handler.NewConvertorHandler(application, convertorView, errorView, convertorRepository, settingDirectoryForSaving)
|
||||
|
||||
themeRepository := theme.NewRepository(settingRepository)
|
||||
themeService := theme.NewTheme(application, themeRepository)
|
||||
|
||||
localizerRepository := localizer.NewRepository(settingRepository)
|
||||
menuView := menu.NewView(application)
|
||||
menuSettingView := menu.NewViewSetting(application)
|
||||
mainMenu := handler.NewMenuHandler(application, convertorHandler, menuView, menuSettingView, localizerView, localizerRepository)
|
||||
menuSettingView := menu.NewViewSetting(application, themeService)
|
||||
mainMenu := handler.NewMenuHandler(application, convertorHandler, menuView, menuSettingView, localizerView, localizerRepository, themeService)
|
||||
|
||||
mainHandler := handler.NewMainHandler(application, convertorHandler, mainMenu, localizerRepository)
|
||||
mainHandler.Start()
|
||||
|
@ -5,6 +5,7 @@ import (
|
||||
"fyne.io/fyne/v2/canvas"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/theme"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"image/color"
|
||||
)
|
||||
@ -17,16 +18,19 @@ type ViewSettingContract interface {
|
||||
}
|
||||
|
||||
type SettingForm struct {
|
||||
Language kernel.Lang
|
||||
Language kernel.Lang
|
||||
ThemeInfo theme.ThemeInfoContract
|
||||
}
|
||||
|
||||
type ViewSetting struct {
|
||||
app kernel.AppContract
|
||||
app kernel.AppContract
|
||||
themeService theme.ThemeContract
|
||||
}
|
||||
|
||||
func NewViewSetting(app kernel.AppContract) *ViewSetting {
|
||||
func NewViewSetting(app kernel.AppContract, themeService theme.ThemeContract) *ViewSetting {
|
||||
return &ViewSetting{
|
||||
app: app,
|
||||
app: app,
|
||||
themeService: themeService,
|
||||
}
|
||||
}
|
||||
|
||||
@ -36,7 +40,8 @@ func (v ViewSetting) Main(save func(*SettingForm) error, cancel func()) {
|
||||
errorMessage.TextStyle = fyne.TextStyle{Bold: true}
|
||||
|
||||
viewSettingForm := &SettingForm{
|
||||
Language: v.app.GetLocalizerService().GetCurrentLanguage().Lang,
|
||||
Language: v.app.GetLocalizerService().GetCurrentLanguage().Lang,
|
||||
ThemeInfo: v.themeService.GetCurrentThemeInfo(),
|
||||
}
|
||||
|
||||
languageItems := []string{}
|
||||
@ -45,12 +50,25 @@ func (v ViewSetting) Main(save func(*SettingForm) error, cancel func()) {
|
||||
languageItems = append(languageItems, language.Title)
|
||||
langByTitle[language.Title] = language
|
||||
}
|
||||
selectLanguages := widget.NewSelect(languageItems, func(s string) {
|
||||
selectLanguage := widget.NewSelect(languageItems, func(s string) {
|
||||
if lang, ok := langByTitle[s]; ok {
|
||||
viewSettingForm.Language = lang
|
||||
}
|
||||
})
|
||||
selectLanguages.Selected = v.app.GetLocalizerService().GetCurrentLanguage().Lang.Title
|
||||
selectLanguage.Selected = v.app.GetLocalizerService().GetCurrentLanguage().Lang.Title
|
||||
|
||||
themeItems := []string{}
|
||||
themeByTitle := map[string]theme.ThemeInfoContract{}
|
||||
for _, themeInfo := range v.themeService.List() {
|
||||
themeItems = append(themeItems, themeInfo.GetTitle())
|
||||
themeByTitle[themeInfo.GetTitle()] = themeInfo
|
||||
}
|
||||
selectTheme := widget.NewSelect(themeItems, func(s string) {
|
||||
if themeInfo, ok := themeByTitle[s]; ok {
|
||||
viewSettingForm.ThemeInfo = themeInfo
|
||||
}
|
||||
})
|
||||
selectTheme.Selected = v.themeService.GetCurrentThemeInfo().GetTitle()
|
||||
|
||||
form := &widget.Form{
|
||||
Items: []*widget.FormItem{
|
||||
@ -58,7 +76,13 @@ func (v ViewSetting) Main(save func(*SettingForm) error, cancel func()) {
|
||||
Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: "menuSettingsLanguage",
|
||||
}),
|
||||
Widget: selectLanguages,
|
||||
Widget: selectLanguage,
|
||||
},
|
||||
{
|
||||
Text: v.app.GetLocalizerService().GetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: "menuSettingsTheme",
|
||||
}),
|
||||
Widget: selectTheme,
|
||||
},
|
||||
{
|
||||
Widget: errorMessage,
|
||||
|
28
theme/repository.go
Normal file
28
theme/repository.go
Normal file
@ -0,0 +1,28 @@
|
||||
package theme
|
||||
|
||||
import "git.kor-elf.net/kor-elf/gui-for-ffmpeg/setting"
|
||||
|
||||
type RepositoryContract interface {
|
||||
GetCode() string
|
||||
Save(code string) (setting.Setting, error)
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
settingRepository setting.RepositoryContract
|
||||
}
|
||||
|
||||
func NewRepository(settingRepository setting.RepositoryContract) *Repository {
|
||||
return &Repository{settingRepository: settingRepository}
|
||||
}
|
||||
|
||||
func (r Repository) GetCode() string {
|
||||
name, err := r.settingRepository.GetValue("theme")
|
||||
if err != nil {
|
||||
return "default"
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (r Repository) Save(code string) (setting.Setting, error) {
|
||||
return r.settingRepository.CreateOrUpdate("theme", code)
|
||||
}
|
158
theme/theme.go
Normal file
158
theme/theme.go
Normal file
@ -0,0 +1,158 @@
|
||||
package theme
|
||||
|
||||
import (
|
||||
"fyne.io/fyne/v2"
|
||||
fyneTheme "fyne.io/fyne/v2/theme"
|
||||
"git.kor-elf.net/kor-elf/gui-for-ffmpeg/kernel"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"image/color"
|
||||
)
|
||||
|
||||
type ThemeContract interface {
|
||||
List() map[string]ThemeInfoContract
|
||||
GetCurrentThemeInfo() ThemeInfoContract
|
||||
SetCurrentTheme(themeInfo ThemeInfoContract) error
|
||||
}
|
||||
|
||||
type theme struct {
|
||||
app kernel.AppContract
|
||||
repository RepositoryContract
|
||||
list map[string]ThemeInfoContract
|
||||
}
|
||||
|
||||
func NewTheme(app kernel.AppContract, repository RepositoryContract) ThemeContract {
|
||||
theme := &theme{
|
||||
app: app,
|
||||
repository: repository,
|
||||
list: getThemes(app.GetLocalizerService()),
|
||||
}
|
||||
|
||||
theme.init()
|
||||
|
||||
return theme
|
||||
}
|
||||
|
||||
func (t theme) init() {
|
||||
themeInfo := t.GetCurrentThemeInfo()
|
||||
if themeInfo.GetName() == "default" {
|
||||
t.app.GetAppFyne().Settings().SetTheme(fyneTheme.DefaultTheme())
|
||||
return
|
||||
}
|
||||
t.app.GetAppFyne().Settings().SetTheme(&forcedVariant{theme: fyneTheme.DefaultTheme(), variant: themeInfo.GetVariant()})
|
||||
}
|
||||
|
||||
func (t theme) GetCurrentThemeInfo() ThemeInfoContract {
|
||||
themes := t.List()
|
||||
if themeInfo, ok := themes[t.repository.GetCode()]; ok {
|
||||
return themeInfo
|
||||
}
|
||||
|
||||
return themes["default"]
|
||||
}
|
||||
|
||||
func (t theme) List() map[string]ThemeInfoContract {
|
||||
return t.list
|
||||
}
|
||||
|
||||
func (t theme) SetCurrentTheme(themeInfo ThemeInfoContract) error {
|
||||
_, err := t.repository.Save(themeInfo.GetName())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if themeInfo.GetName() == "default" {
|
||||
t.app.GetAppFyne().Settings().SetTheme(fyneTheme.DefaultTheme())
|
||||
return nil
|
||||
}
|
||||
t.app.GetAppFyne().Settings().SetTheme(&forcedVariant{theme: fyneTheme.DefaultTheme(), variant: themeInfo.GetVariant()})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type ThemeInfoContract interface {
|
||||
GetName() string
|
||||
GetTitle() string
|
||||
GetVariant() fyne.ThemeVariant
|
||||
}
|
||||
|
||||
type themeInfo struct {
|
||||
name string
|
||||
title string
|
||||
variant fyne.ThemeVariant
|
||||
}
|
||||
|
||||
func (inf themeInfo) GetName() string {
|
||||
return inf.name
|
||||
}
|
||||
|
||||
func (inf themeInfo) GetTitle() string {
|
||||
return inf.title
|
||||
}
|
||||
|
||||
func (inf themeInfo) GetVariant() fyne.ThemeVariant {
|
||||
return inf.variant
|
||||
}
|
||||
|
||||
func getThemes(localizer kernel.LocalizerContract) map[string]ThemeInfoContract {
|
||||
themesNameDefault := &themeInfo{
|
||||
name: "default",
|
||||
title: localizer.GetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: "themesNameDefault",
|
||||
}),
|
||||
}
|
||||
|
||||
themesNameLight := &themeInfo{
|
||||
name: "light",
|
||||
title: localizer.GetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: "themesNameLight",
|
||||
}),
|
||||
variant: fyneTheme.VariantLight,
|
||||
}
|
||||
|
||||
themesNameDark := &themeInfo{
|
||||
name: "dark",
|
||||
title: localizer.GetMessage(&i18n.LocalizeConfig{
|
||||
MessageID: "themesNameDark",
|
||||
}),
|
||||
variant: fyneTheme.VariantDark,
|
||||
}
|
||||
|
||||
list := map[string]ThemeInfoContract{
|
||||
"default": themesNameDefault,
|
||||
"light": themesNameLight,
|
||||
"dark": themesNameDark,
|
||||
}
|
||||
|
||||
localizer.AddChangeCallback("themesNameDefault", func(text string) {
|
||||
themesNameDefault.title = text
|
||||
})
|
||||
localizer.AddChangeCallback("themesNameLight", func(text string) {
|
||||
themesNameLight.title = text
|
||||
})
|
||||
localizer.AddChangeCallback("themesNameDark", func(text string) {
|
||||
themesNameDark.title = text
|
||||
})
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
type forcedVariant struct {
|
||||
theme fyne.Theme
|
||||
variant fyne.ThemeVariant
|
||||
}
|
||||
|
||||
func (f *forcedVariant) Color(name fyne.ThemeColorName, _ fyne.ThemeVariant) color.Color {
|
||||
return f.theme.Color(name, f.variant)
|
||||
}
|
||||
|
||||
func (f *forcedVariant) Font(style fyne.TextStyle) fyne.Resource {
|
||||
return fyneTheme.DefaultTheme().Font(style)
|
||||
}
|
||||
|
||||
func (f *forcedVariant) Icon(name fyne.ThemeIconName) fyne.Resource {
|
||||
return fyneTheme.DefaultTheme().Icon(name)
|
||||
}
|
||||
|
||||
func (f *forcedVariant) Size(name fyne.ThemeSizeName) float32 {
|
||||
return fyneTheme.DefaultTheme().Size(name)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user