增加程序皮肤首选项

This commit is contained in:
ww-rm
2025-10-03 19:38:48 +08:00
parent 8b622050fa
commit 887e3f76d2
9 changed files with 154 additions and 2 deletions

View File

@@ -349,6 +349,28 @@ namespace SpineViewer
}
}
private AppLanguage _language = AppLanguage.ZH;
public AppSkin Skin
{
get => _skin;
set
{
var uri = $"Resources/Skins/{value.ToString().ToLower()}.xaml";
try
{
Resources.MergedDictionaries.Add(new() { Source = new(uri, UriKind.Relative) });
Resources.MergedDictionaries.Add(new() { Source = new("Resources/Theme.xaml", UriKind.Relative) });
_skin = value;
}
catch (Exception ex)
{
_logger.Error("Failed to switch skin to {0}, {1}", value, ex.Message);
_logger.Trace(ex.ToString());
}
}
}
private AppSkin _skin = AppSkin.Light;
}
public enum AppLanguage
@@ -357,4 +379,11 @@ namespace SpineViewer
EN,
JA
}
public enum AppSkin
{
Light,
Dark,
Violet,
}
}

View File

@@ -86,6 +86,9 @@ namespace SpineViewer.Models
[ObservableProperty]
private AppLanguage _appLanguage;
[ObservableProperty]
private AppSkin _appSkin;
[ObservableProperty]
private bool _renderSelectedOnly;

View File

@@ -12,7 +12,102 @@ namespace SpineViewer.Resources
/// </summary>
public static class AppResource
{
public static T Get<T>(string key) => (T)App.Current.FindResource(key);
private static T Get<T>(string key) => (T)App.Current.FindResource(key);
#region Colors
public static Color Color_LightPrimary => Get<Color>("LightPrimaryColor");
public static Color Color_Primary => Get<Color>("PrimaryColor");
public static Color Color_DarkPrimary => Get<Color>("DarkPrimaryColor");
public static Color Color_LightDanger => Get<Color>("LightDangerColor");
public static Color Color_Danger => Get<Color>("DangerColor");
public static Color Color_DarkDanger => Get<Color>("DarkDangerColor");
public static Color Color_LightWarning => Get<Color>("LightWarningColor");
public static Color Color_Warning => Get<Color>("WarningColor");
public static Color Color_DarkWarning => Get<Color>("DarkWarningColor");
public static Color Color_LightInfo => Get<Color>("LightInfoColor");
public static Color Color_Info => Get<Color>("InfoColor");
public static Color Color_DarkInfo => Get<Color>("DarkInfoColor");
public static Color Color_LightSuccess => Get<Color>("LightSuccessColor");
public static Color Color_Success => Get<Color>("SuccessColor");
public static Color Color_DarkSuccess => Get<Color>("DarkSuccessColor");
public static Color Color_PrimaryText => Get<Color>("PrimaryTextColor");
public static Color Color_SecondaryText => Get<Color>("SecondaryTextColor");
public static Color Color_ThirdlyText => Get<Color>("ThirdlyTextColor");
public static Color Color_ReverseText => Get<Color>("ReverseTextColor");
public static Color Color_TextIcon => Get<Color>("TextIconColor");
public static Color Color_Border => Get<Color>("BorderColor");
public static Color Color_SecondaryBorder => Get<Color>("SecondaryBorderColor");
public static Color Color_Background => Get<Color>("BackgroundColor");
public static Color Color_Region => Get<Color>("RegionColor");
public static Color Color_SecondaryRegion => Get<Color>("SecondaryRegionColor");
public static Color Color_ThirdlyRegion => Get<Color>("ThirdlyRegionColor");
public static Color Color_Title => Get<Color>("TitleColor");
public static Color Color_SecondaryTitle => Get<Color>("SecondaryTitleColor");
public static Color Color_Default => Get<Color>("DefaultColor");
public static Color Color_DarkDefault => Get<Color>("DarkDefaultColor");
public static Color Color_Accent => Get<Color>("AccentColor");
public static Color Color_DarkAccent => Get<Color>("DarkAccentColor");
public static Color Color_DarkMask => Get<Color>("DarkMaskColor");
public static Color Color_DarkOpacity => Get<Color>("DarkOpacityColor");
#endregion
#region Brushes
public static SolidColorBrush Brush_LightPrimary => Get<SolidColorBrush>("LightPrimaryBrush");
public static LinearGradientBrush Brush_Primary => Get<LinearGradientBrush>("PrimaryBrush");
public static SolidColorBrush Brush_DarkPrimary => Get<SolidColorBrush>("DarkPrimaryBrush");
public static SolidColorBrush Brush_PrimaryText => Get<SolidColorBrush>("PrimaryTextBrush");
public static SolidColorBrush Brush_SecondaryText => Get<SolidColorBrush>("SecondaryTextBrush");
public static SolidColorBrush Brush_ThirdlyText => Get<SolidColorBrush>("ThirdlyTextBrush");
public static SolidColorBrush Brush_ReverseText => Get<SolidColorBrush>("ReverseTextBrush");
public static SolidColorBrush Brush_TextIcon => Get<SolidColorBrush>("TextIconBrush");
public static SolidColorBrush Brush_Border => Get<SolidColorBrush>("BorderBrush");
public static SolidColorBrush Brush_SecondaryBorder => Get<SolidColorBrush>("SecondaryBorderBrush");
public static SolidColorBrush Brush_Background => Get<SolidColorBrush>("BackgroundBrush");
public static SolidColorBrush Brush_Region => Get<SolidColorBrush>("RegionBrush");
public static SolidColorBrush Brush_SecondaryRegion => Get<SolidColorBrush>("SecondaryRegionBrush");
public static SolidColorBrush Brush_ThirdlyRegion => Get<SolidColorBrush>("ThirdlyRegionBrush");
public static LinearGradientBrush Brush_Title => Get<LinearGradientBrush>("TitleBrush");
public static SolidColorBrush Brush_Default => Get<SolidColorBrush>("DefaultBrush");
public static SolidColorBrush Brush_DarkDefault => Get<SolidColorBrush>("DarkDefaultBrush");
public static SolidColorBrush Brush_LightDanger => Get<SolidColorBrush>("LightDangerBrush");
public static LinearGradientBrush Brush_Danger => Get<LinearGradientBrush>("DangerBrush");
public static SolidColorBrush Brush_DarkDanger => Get<SolidColorBrush>("DarkDangerBrush");
public static SolidColorBrush Brush_LightWarning => Get<SolidColorBrush>("LightWarningBrush");
public static LinearGradientBrush Brush_Warning => Get<LinearGradientBrush>("WarningBrush");
public static SolidColorBrush Brush_DarkWarning => Get<SolidColorBrush>("DarkWarningBrush");
public static SolidColorBrush Brush_LightInfo => Get<SolidColorBrush>("LightInfoBrush");
public static LinearGradientBrush Brush_Info => Get<LinearGradientBrush>("InfoBrush");
public static SolidColorBrush Brush_DarkInfo => Get<SolidColorBrush>("DarkInfoBrush");
public static SolidColorBrush Brush_LightSuccess => Get<SolidColorBrush>("LightSuccessBrush");
public static LinearGradientBrush Brush_Success => Get<LinearGradientBrush>("SuccessBrush");
public static SolidColorBrush Brush_DarkSuccess => Get<SolidColorBrush>("DarkSuccessBrush");
public static SolidColorBrush Brush_Accent => Get<SolidColorBrush>("AccentBrush");
public static SolidColorBrush Brush_DarkAccent => Get<SolidColorBrush>("DarkAccentBrush");
public static SolidColorBrush Brush_DarkMask => Get<SolidColorBrush>("DarkMaskBrush");
public static SolidColorBrush Brush_DarkOpacity => Get<SolidColorBrush>("DarkOpacityBrush");
#endregion
#region Strings

View File

@@ -244,6 +244,7 @@
<s:String x:Key="Str_AppPreference">Application Options</s:String>
<s:String x:Key="Str_Language">Language</s:String>
<s:String x:Key="Str_AppSkin">Skin</s:String>
<s:String x:Key="Str_CloseToTray">Minimize to tray when closing</s:String>
<s:String x:Key="Str_AutoRun">Auto Start</s:String>
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">Auto-load Workspace File on Startup</s:String>

View File

@@ -244,6 +244,7 @@
<s:String x:Key="Str_AppPreference">アプリケーションプション</s:String>
<s:String x:Key="Str_Language">言語</s:String>
<s:String x:Key="Str_AppSkin">スキン</s:String>
<s:String x:Key="Str_CloseToTray">閉じるときにトレイに最小化する</s:String>
<s:String x:Key="Str_AutoRun">自動起動</s:String>
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">起動時にワークスペースファイルを自動読み込み</s:String>

View File

@@ -244,6 +244,7 @@
<s:String x:Key="Str_AppPreference">应用程序选项</s:String>
<s:String x:Key="Str_Language">语言</s:String>
<s:String x:Key="Str_AppSkin">皮肤</s:String>
<s:String x:Key="Str_CloseToTray">关闭时最小化至托盘图标</s:String>
<s:String x:Key="Str_AutoRun">开机自启</s:String>
<s:String x:Key="Str_AutoRunWorkspaceConfigPath">自启动加载工作区文件</s:String>

View File

@@ -109,6 +109,7 @@ namespace SpineViewer.ViewModels.MainWindow
DebugClippings = DebugClippings,
AppLanguage = AppLanguage,
AppSkin = AppSkin,
RenderSelectedOnly = RenderSelectedOnly,
HitTestLevel = HitTestLevel,
LogHitSlots = LogHitSlots,
@@ -140,6 +141,7 @@ namespace SpineViewer.ViewModels.MainWindow
DebugClippings = value.DebugClippings;
AppLanguage = value.AppLanguage;
AppSkin = value.AppSkin;
RenderSelectedOnly = value.RenderSelectedOnly;
HitTestLevel = value.HitTestLevel;
LogHitSlots = value.LogHitSlots;
@@ -253,6 +255,8 @@ namespace SpineViewer.ViewModels.MainWindow
public static ImmutableArray<AppLanguage> AppLanguageOptions { get; } = Enum.GetValues<AppLanguage>().ToImmutableArray();
public static ImmutableArray<AppSkin> AppSkinOptions { get; } = Enum.GetValues<AppSkin>().ToImmutableArray();
public static ImmutableArray<HitTestLevel> HitTestLevelOptions { get; } = Enum.GetValues<HitTestLevel>().ToImmutableArray();
public AppLanguage AppLanguage
@@ -261,6 +265,12 @@ namespace SpineViewer.ViewModels.MainWindow
set => SetProperty(((App)App.Current).Language, value, v => ((App)App.Current).Language = v);
}
public AppSkin AppSkin
{
get => ((App)App.Current).Skin;
set => SetProperty(((App)App.Current).Skin, value, v => ((App)App.Current).Skin = v);
}
public bool RenderSelectedOnly
{
get => _vmMain.SFMLRendererViewModel.RenderSelectedOnly;

View File

@@ -11,6 +11,7 @@
mc:Ignorable="d"
x:Name="_mainWindow"
Title="{Binding Title}"
Background="{DynamicResource RegionBrush}"
Width="1500"
Height="800"
WindowStartupLocation="CenterScreen"

View File

@@ -209,6 +209,17 @@
ItemsSource="{x:Static vm:PreferenceViewModel.AppLanguageOptions}"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Content="{DynamicResource Str_Skin}"/>
<ComboBox Grid.Column="1"
SelectedItem="{Binding AppSkin}"
ItemsSource="{x:Static vm:PreferenceViewModel.AppSkinOptions}"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="LabelCol"/>