feat: UiColor适配DarkMode & feat: 在主界面保存位置时进行检查 (#4352)

close #4336 
close #4365

<!-- Add GUI -->

示例作业中,
```
"xxx_color": "dark"
```

实际上是不合法的,正确的方式是使用[Colors类的命名](https://learn.microsoft.com/zh-cn/dotnet/api/system.windows.media.colors?view=netframework-4.8#properties)
_(:з」∠)_ ,之前会默认使用Colors.Black,现在默认使用UiLogColor.Message。

同时会检查TextBlock使用的Foreground颜色是否和背景颜色太相近。
This commit is contained in:
MistEO
2023-04-18 19:51:59 +08:00
committed by GitHub
9 changed files with 266 additions and 66 deletions

View File

@@ -21,41 +21,44 @@ namespace MaaWpfGui.Constants
/// <summary>
/// The recommended color for error logs.
/// </summary>
public const string Error = "DarkRed";
public const string Error = "ErrorLogBrush";
/// <summary>
/// The recommended color for warning logs.
/// </summary>
public const string Warning = "DarkGoldenrod";
public const string Warning = "WarningLogBrush";
/// <summary>
/// The recommended color for info logs.
/// </summary>
public const string Info = "DarkCyan";
public const string Info = "InfoLogBrush";
/// <summary>
/// The recommended color for trace logs.
/// </summary>
public const string Trace = "Gray";
public const string Trace = "TraceLogBrush";
/// <summary>
/// The recommended color for message logs.
/// </summary>
public const string Message = "Black";
public const string Message = "MessageLogBrush";
/// <summary>
/// The recommended color for rare operator logs.
/// </summary>
public const string RareOperator = "DarkOrange";
public const string RareOperator = "RareOperatorLogBrush";
/// <summary>
/// The recommended color for robot operator logs.
/// </summary>
public const string RobotOperator = "DarkGray";
public const string RobotOperator = "RobotOperatorLogBrush";
/// <summary>
/// The recommended color for file downloading or downloaded or download failed.
/// </summary>
public const string Download = "BlueViolet";
public const string Download = "DownloadLogBrush";
// 颜色在MaaWpfGui\Res\Themes中定义
// Brushs are defined in MaaWpfGui\Res\Themes
}
}

View File

@@ -0,0 +1,147 @@
// <copyright file="ThemeHelper.cs" company="MaaAssistantArknights">
// MaaWpfGui - A part of the MaaCoreArknights project
// Copyright (C) 2021 MistEO and Contributors
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY
// </copyright>
using System.Windows;
using System.Windows.Media;
using HandyControl.Themes;
using HandyControl.Tools;
using MaaWpfGui.Constants;
using Microsoft.Win32;
namespace MaaWpfGui.Helper
{
public static class ThemeHelper
{
#region Swith Theme
private static void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
ThemeManager.Current.ApplicationTheme = ThemeManager.GetSystemTheme(isSystemTheme: false);
ThemeManager.Current.AccentColor = ThemeManager.Current.GetAccentColorFromSystem();
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
}
public static void SwitchToLightMode()
{
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
ThemeManager.Current.UsingWindowsAppTheme = false;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
}
public static void SwitchToDarkMode()
{
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
ThemeManager.Current.UsingWindowsAppTheme = false;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
}
public static void SwitchToSyncWithOSMode()
{
ThemeManager.Current.UsingWindowsAppTheme = true;
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
}
#endregion
#region Check UiLogColor
// In official version, using ResourceHelper.GetSkin
private static readonly Color LightBackground = ((SolidColorBrush)ThemeResources.Current.GetThemeDictionary("Light")["RegionBrush"]).Color;
private static readonly Color DarkBackground = ((SolidColorBrush)ThemeResources.Current.GetThemeDictionary("Dark")["RegionBrush"]).Color;
public static bool SimilarToBackground(Color color)
{
return ColorDistance(color, LightBackground) == 0 || ColorDistance(color, DarkBackground) == 0;
}
/// <summary>
/// Gets the distance between colors c1 and c2.
/// </summary>
/// <param name="c1">The color c1.</param>
/// <param name="c2">The color c2.</param>
/// <returns>The distance from 0 to 35.</returns>
public static int ColorDistance(Color c1, Color c2)
{
// https://www.compuphase.com/cmetric.htm
long rmean = (c1.R + c2.R) / 2;
long r = c1.R - c2.R;
long g = c1.G - c2.G;
long b = c1.B - c2.B;
return (int)(((((512 + rmean) * r * r) >> 8) + (4 * g * g) + (((767 - rmean) * b * b) >> 8)) >> 14);
}
#endregion
#region Convert
public const string DefaultKey = UiLogColor.Message;
public static SolidColorBrush DefaultBrush => ResourceHelper.GetResource<SolidColorBrush>(DefaultKey);
public static Color DefaultColor => DefaultBrush.Color;
public static string DefaultHexString => $"#{DefaultColor.A:X2}{DefaultColor.R:X2}{DefaultColor.G:X2}{DefaultColor.B:X2}";
public static string Color2HexString(Color color, bool keepAlpha = false)
{
if (keepAlpha)
{
return $"#{color.A:X2}{color.R:X2}{color.G:X2}{color.B:X2}";
}
return $"#FF{color.R:X2}{color.G:X2}{color.B:X2}";
}
public static string Brush2HexString(SolidColorBrush brush, bool keepAlpha = false)
{
if (brush != null)
{
return Color2HexString(brush.Color, keepAlpha);
}
return DefaultHexString;
}
public static Color String2Color(string str)
{
if (!string.IsNullOrWhiteSpace(str))
{
try
{
object obj = ColorConverter.ConvertFromString(str);
if (obj is Color color)
{
return color;
}
}
catch
{
return DefaultColor;
}
}
return DefaultColor;
}
public static SolidColorBrush String2Brush(string str)
{
return new SolidColorBrush(String2Color(str));
}
#endregion
}
}

View File

@@ -8,10 +8,10 @@
<!-- See https://github.com/ghost1372/HandyControls/blob/v3.4.5/src/Shared/HandyControl_Shared/Themes/Basic/Colors/Dark.xaml -->
<!-- Latest Doc https://ghost1372.github.io/handycontrol/basic_xaml/brushes/ -->
<!-- 文字颜色 -->
<SolidColorBrush x:Key="PrimaryTextBrush" Color="White" />
<SolidColorBrush x:Key="PrimaryTextBrush" Color="#E6E6E6" />
<!-- 文字颜色 -->
<SolidColorBrush x:Key="TextIconBrush" Color="White" />
<SolidColorBrush x:Key="TextIconBrush" Color="#E6E6E6" />
<!-- 背景颜色 -->
<SolidColorBrush x:Key="RegionBrush" Color="#1c1c1c" />
<!-- 背景颜色 没用到(建议和背景颜色一致)-->
@@ -26,4 +26,14 @@
<!-- 标题背景 没用到(建议和主题色一致)-->
<SolidColorBrush x:Key="TitleBrush" Color="#326cf3" />
<!-- UiLogColor -->
<SolidColorBrush x:Key="ErrorLogBrush" Color="#C80000" />
<SolidColorBrush x:Key="WarningLogBrush" Color="Goldenrod" />
<SolidColorBrush x:Key="InfoLogBrush" Color="#00C8C8" />
<SolidColorBrush x:Key="TraceLogBrush" Color="DarkGray" />
<SolidColorBrush x:Key="MessageLogBrush" Color="#E6E6E6" />
<SolidColorBrush x:Key="RareOperatorLogBrush" Color="Orange" />
<SolidColorBrush x:Key="RobotOperatorLogBrush" Color="Gray" />
<SolidColorBrush x:Key="DownloadLogBrush" Color="Violet" />
</ResourceDictionary>

View File

@@ -5,5 +5,15 @@
<SolidColorBrush x:Key="PallasBrush" Color="#6A6AAB" />
<SolidColorBrush x:Key="ErrorViewBackgroundBrush" Color="#E6E6E6" />
<SolidColorBrush x:Key="SecondaryRegionBrush" Color="#ffffff" />
<!-- UiLogColor -->
<SolidColorBrush x:Key="ErrorLogBrush" Color="DarkRed" />
<SolidColorBrush x:Key="WarningLogBrush" Color="DarkGoldenrod" />
<SolidColorBrush x:Key="InfoLogBrush" Color="DarkCyan" />
<SolidColorBrush x:Key="TraceLogBrush" Color="Gray" />
<SolidColorBrush x:Key="MessageLogBrush" Color="Black" />
<SolidColorBrush x:Key="RareOperatorLogBrush" Color="DarkOrange" />
<SolidColorBrush x:Key="RobotOperatorLogBrush" Color="DarkGray" />
<SolidColorBrush x:Key="DownloadLogBrush" Color="BlueViolet" />
</ResourceDictionary>

View File

@@ -13,6 +13,7 @@
using System.Windows;
using System.Windows.Media;
using MaaWpfGui.Helper;
namespace MaaWpfGui.Styles.Controls
{
@@ -23,12 +24,50 @@ namespace MaaWpfGui.Styles.Controls
DefaultStyleKeyProperty.OverrideMetadata(typeof(TextBlock), new FrameworkPropertyMetadata(typeof(TextBlock)));
}
public static readonly DependencyProperty CustomForegroundProperty = DependencyProperty.Register("CustomForeground", typeof(Brush), typeof(TextBlock), new PropertyMetadata(Brushes.Black));
public static readonly DependencyProperty CustomForegroundProperty = DependencyProperty.Register("CustomForeground", typeof(Brush), typeof(TextBlock), new PropertyMetadata(ThemeHelper.DefaultBrush));
public Brush CustomForeground
{
get { return (Brush)GetValue(CustomForegroundProperty); }
set { SetValue(CustomForegroundProperty, value); }
}
public static readonly DependencyProperty ForegroundKeyProperty = DependencyProperty.Register("ForegroundKey", typeof(string), typeof(TextBlock), new PropertyMetadata(ThemeHelper.DefaultKey, OnForegroundKeyChanged));
private static void OnForegroundKeyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var element = (TextBlock)d;
if (e.NewValue != null)
{
element.ForegroundKey = (string)e.NewValue;
}
}
public string ForegroundKey
{
get
{
return (string)GetValue(ForegroundKeyProperty);
}
set
{
SetValue(ForegroundKeyProperty, value);
if (Application.Current.Resources.Contains(value))
{
SetResourceReference(ForegroundProperty, value);
return;
}
var brush = ThemeHelper.String2Brush(value);
if (ThemeHelper.SimilarToBackground(brush.Color))
{
SetResourceReference(ForegroundProperty, ThemeHelper.DefaultKey);
return;
}
SetValue(ForegroundProperty, brush);
}
}
}
}

View File

@@ -27,12 +27,10 @@ using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Interop;
using HandyControl.Themes;
using MaaWpfGui.Constants;
using MaaWpfGui.Extensions;
using MaaWpfGui.Helper;
using MaaWpfGui.Main;
using MaaWpfGui.Services;
using MaaWpfGui.Services.HotKeys;
using MaaWpfGui.Services.Managers;
using MaaWpfGui.Services.Web;
@@ -2420,6 +2418,13 @@ namespace MaaWpfGui.ViewModels.UI
return;
}
var mainWindowRect = new Rect(mainWindow.Left + 25, mainWindow.Top + 25, mainWindow.Width - 50, mainWindow.Height - 50);
var virtualScreenRect = new Rect(SystemParameters.VirtualScreenLeft, SystemParameters.VirtualScreenTop, SystemParameters.VirtualScreenWidth, SystemParameters.VirtualScreenHeight);
if (!virtualScreenRect.IntersectsWith(mainWindowRect))
{
return;
}
// 请在配置文件中修改该部分配置暂不支持从GUI设置
// Please modify this part of configuration in the configuration file.
ConfigurationHelper.SetValue(ConfigurationKeys.LoadPositionAndSize, LoadGUIParameters.ToString());
@@ -2575,31 +2580,17 @@ namespace MaaWpfGui.ViewModels.UI
switch (darkModeType)
{
case DarkModeType.Light:
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
ThemeManager.Current.UsingWindowsAppTheme = false;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Light;
ThemeHelper.SwitchToLightMode();
break;
case DarkModeType.Dark:
SystemEvents.UserPreferenceChanged -= SystemEvents_UserPreferenceChanged;
ThemeManager.Current.UsingWindowsAppTheme = false;
ThemeManager.Current.ApplicationTheme = ApplicationTheme.Dark;
ThemeHelper.SwitchToDarkMode();
break;
case DarkModeType.SyncWithOS:
ThemeManager.Current.UsingWindowsAppTheme = true;
SystemEvents.UserPreferenceChanged += SystemEvents_UserPreferenceChanged;
ThemeHelper.SwitchToSyncWithOSMode();
break;
}
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
}
private void SystemEvents_UserPreferenceChanged(object sender, UserPreferenceChangedEventArgs e)
{
ThemeManager.Current.ApplicationTheme = ThemeManager.GetSystemTheme(isSystemTheme: false);
ThemeManager.Current.AccentColor = ThemeManager.Current.GetAccentColorFromSystem();
Application.Current.Resources["TitleBrush"] = ThemeManager.Current.AccentColor;
}
private enum InverseClearType

View File

@@ -1,4 +1,4 @@
<UserControl
<UserControl
x:Class="MaaWpfGui.Views.UI.CopilotView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -131,7 +131,7 @@
Width="350"
Margin="5"
FontWeight="{Binding Weight}"
Foreground="{Binding Color}"
ForegroundKey="{Binding Color}"
Text="{Binding Content}"
TextWrapping="Wrap" />
</StackPanel>

View File

@@ -1,4 +1,4 @@
<UserControl
<UserControl
x:Class="MaaWpfGui.Views.UI.SettingsView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -44,12 +44,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[0]}" />
<userControl:GameClientUserControl
Margin="20"
@@ -58,12 +58,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[1]}" />
<userControl:InfrastSettingsUserControl
Margin="20"
@@ -72,12 +72,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[2]}" />
<userControl:RoguelikeSettingsUserControl
Margin="20"
@@ -86,12 +86,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[3]}" />
<userControl:AutoRecruitSettingsUserControl
Margin="20"
@@ -100,12 +100,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[4]}" />
<userControl:MallSettingsUserControl
Margin="20"
@@ -114,12 +114,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[5]}" />
<userControl:OtherCombatSettingsUserControl
Margin="20"
@@ -128,12 +128,12 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[6]}" />
<userControl:ConnectSettingsUserControl
Margin="20"
@@ -142,70 +142,70 @@
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[7]}" />
<userControl:StartSettingsUserControl Margin="20" HorizontalAlignment="Center" />
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[8]}" />
<userControl:TimerSettingsUserControl Margin="20" HorizontalAlignment="Center" />
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[9]}" />
<userControl:GUISettingsUserControl Margin="20" HorizontalAlignment="Center" />
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[10]}" />
<userControl:HotKeySettingsUserControl Margin="20" HorizontalAlignment="Center" />
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[11]}" />
<userControl:VersionUpdateSettingsUserControl Margin="20" HorizontalAlignment="Center" />
<Rectangle
Height="1"
HorizontalAlignment="Stretch"
Fill="LightGray" />
Fill="{DynamicResource BorderBrush}" />
<controls:TextBlock
Margin="5"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding ListTitle[12]}" />
<userControl:AboutUserControl Margin="20" HorizontalAlignment="Center" />
<!--<Rectangle HorizontalAlignment="Stretch" Fill="LightGray" Height="1" />-->
<!--<Rectangle HorizontalAlignment="Stretch" Fill="{DynamicResource BorderBrush}" Height="1" />-->
</StackPanel>
</ScrollViewer>
</Grid>

View File

@@ -1,4 +1,4 @@
<UserControl
<UserControl
x:Class="MaaWpfGui.Views.UI.TaskQueueView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
@@ -186,7 +186,7 @@
</Grid>
<!--<GridSplitter Grid.Column="2" Width="5" HorizontalAlignment="Stretch" />-->
<!--<Rectangle Grid.Column="2" VerticalAlignment="Stretch" Fill="LightGray" Width="4" />-->
<!--<Rectangle Grid.Column="2" VerticalAlignment="Stretch" Fill="{DynamicResource BorderBrush}" Width="4" />-->
<ScrollViewer
Grid.Column="2"
Margin="10"
@@ -205,7 +205,7 @@
Width="95"
Margin="0,5"
VerticalAlignment="Top"
Foreground="Gray"
Foreground="{DynamicResource TraceLogBrush}"
Text="{Binding Time}"
TextWrapping="Wrap" />
<controls:TextBlock
@@ -213,7 +213,7 @@
Margin="0,5"
VerticalAlignment="Top"
FontWeight="{Binding Weight}"
Foreground="{Binding Color}"
ForegroundKey="{Binding Color}"
Text="{Binding Content}"
TextWrapping="Wrap" />
</StackPanel>