Refactor WaveSpiritAdorner Color Retrieve

This commit is contained in:
chinboy
2025-02-09 18:40:31 +08:00
parent f30ffaf12c
commit 811fc91e41
10 changed files with 162 additions and 31 deletions
+1
View File
@@ -17,6 +17,7 @@
<ItemGroup>
<InternalsVisibleTo Include="AtomUI"/>
<InternalsVisibleTo Include="AtomUI.Controls"/>
<InternalsVisibleTo Include="AtomUI.Theme"/>
</ItemGroup>
<ItemGroup>
+7
View File
@@ -59,4 +59,11 @@ public enum ColorNameFormat
{
HexRgb,
HexArgb
}
internal static class AtomUILogArea
{
public const string Theme = "Theme";
public const string Control = "Control";
public const string System = "System";
}
+23
View File
@@ -1,6 +1,8 @@
using AtomUI.Controls.Utils;
using AtomUI.Theme;
using Avalonia;
using Avalonia.Controls;
using Avalonia.LogicalTree;
namespace AtomUI.Controls;
@@ -28,6 +30,27 @@ public class LineEdit : TextBox
#endregion
#region 内部属性定义
private ControlTokenResourceRegister _controlTokenResourceRegister;
private bool _initialized;
#endregion
public LineEdit()
{
_controlTokenResourceRegister = new ControlTokenResourceRegister(this, LineEditToken.ID);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
if (!_initialized)
{
_controlTokenResourceRegister.RegisterResources();
_initialized = true;
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
+72 -9
View File
@@ -1,3 +1,4 @@
using AtomUI.Theme.Styling;
using AtomUI.Theme.Utils;
using Avalonia;
using Avalonia.Animation;
@@ -115,7 +116,59 @@ internal class WaveSpiritAdorner : Control, IDisposable
{
_targetControl = targetControl;
_targetControl.PropertyChanged += HandleTargetControlChanged;
var sharedToken = TokenFinderUtils.FindSharedToken(_targetControl!);
var sharedToken = TokenFinderUtils.FindSharedToken(_targetControl!);
var themeVariant = TokenFinderUtils.FindThemeVariant(_targetControl);
CornerRadius? borderRadius = null;
// 获取相关值
{
if (_targetControl.TryGetResource(SharedTokenKey.BorderRadius, themeVariant, out var value))
{
if (value is CornerRadius cornerRadius)
{
borderRadius = cornerRadius;
}
}
}
borderRadius ??= sharedToken.BorderRadius;
TimeSpan? motionDurationSlow = null;
{
if (_targetControl.TryGetResource(SharedTokenKey.MotionDurationSlow, themeVariant, out var value))
{
if (value is TimeSpan timeSpan)
{
motionDurationSlow = timeSpan;
}
}
}
motionDurationSlow ??= sharedToken.MotionDurationSlow;
double? waveStartOpacity = null;
{
if (_targetControl.TryGetResource(SharedTokenKey.WaveStartOpacity, themeVariant, out var value))
{
if (value is double dvalue)
{
waveStartOpacity = dvalue;
}
}
}
waveStartOpacity ??= sharedToken.WaveStartOpacity;
double? waveAnimationRange = null;
{
if (_targetControl.TryGetResource(SharedTokenKey.WaveAnimationRange, themeVariant, out var value))
{
if (value is double dvalue)
{
waveAnimationRange = dvalue;
}
}
}
waveAnimationRange ??= sharedToken.WaveAnimationRange;
if (waveType == WaveType.CircleWave)
{
_wavePainter = new CircleWavePainter();
@@ -127,24 +180,34 @@ internal class WaveSpiritAdorner : Control, IDisposable
else
{
var roundWavePainter = new RoundRectWavePainter();
roundWavePainter.CornerRadius = sharedToken.BorderRadius;
roundWavePainter.CornerRadius = borderRadius.Value;
_wavePainter = roundWavePainter;
}
var motionDurationSlow = sharedToken.MotionDurationSlow;
_wavePainter.SizeEasingCurve = new CubicEaseOut();
_wavePainter.OpacityEasingCurve = new CubicEaseOut();
_wavePainter.OriginOpacity = Math.Clamp(sharedToken.WaveStartOpacity, 0.0, 1.0);
_wavePainter.SizeMotionDuration = motionDurationSlow;
_wavePainter.OpacityMotionDuration = motionDurationSlow.Add(TimeSpan.FromMilliseconds(50));
_wavePainter.WaveRange = Math.Min(sharedToken.WaveAnimationRange, 8);
_wavePainter.OriginOpacity = Math.Clamp(waveStartOpacity.Value, 0.0, 1.0);
_wavePainter.SizeMotionDuration = motionDurationSlow.Value;
_wavePainter.OpacityMotionDuration = motionDurationSlow.Value.Add(TimeSpan.FromMilliseconds(50));
_wavePainter.WaveRange = Math.Min(waveAnimationRange.Value, 8);
if (waveColor is not null)
{
_wavePainter.WaveColor = waveColor.Value;
}
else
{
_wavePainter.WaveColor = sharedToken.ColorPrimary;
Color? colorPrimary = null;
{
if (_targetControl.TryGetResource(SharedTokenKey.ColorPrimary, themeVariant, out var value))
{
if (value is Color color)
{
colorPrimary = color;
}
}
}
colorPrimary ??= sharedToken.ColorPrimary;
_wavePainter.WaveColor = colorPrimary.Value;
}
LayoutUpdated += HandleLayoutUpdated;
@@ -1,9 +1,12 @@
using Avalonia.Metadata;
namespace AtomUI.Theme;
public class ControlTokenInfoSetter
{
public bool EnableAlgorithm { get; set; } = false;
[Content]
public List<TokenSetter> Setters { get; set; } = new ();
public string? Catalog { get; set; }
@@ -11,7 +11,7 @@ public class ControlTokenResourceRegister
private Control _target;
private string _tokenId;
private string? _resourceCatalog;
private IResourceDictionary? _resourceDictionary;
private ResourceDictionary? _resourceDictionary;
public ControlTokenResourceRegister(Control target, string tokenId, string? resourceCatalog = null)
{
@@ -34,8 +34,9 @@ public class ControlTokenResourceRegister
{
_resourceDictionary.Add(entry.Key, entry.Value);
}
_target.Resources.MergedDictionaries.Add(_resourceDictionary);
var themeVariant = TokenFinderUtils.FindThemeVariant(_target);
_target.Resources.ThemeDictionaries.Add(themeVariant, _resourceDictionary);
}
private IControlDesignToken? FindControlToken()
+2
View File
@@ -1,4 +1,5 @@
using AtomUI.Theme.TokenSystem;
using Avalonia.Styling;
namespace AtomUI.Theme;
@@ -9,4 +10,5 @@ public interface IThemeConfigProvider
IControlDesignToken? GetControlToken(string tokenId, string? catalog = null);
List<string> Algorithms { get; }
bool IsDarkMode { get; }
ThemeVariant ThemeVariant { get; }
}
@@ -83,7 +83,7 @@ public abstract class AbstractControlDesignToken : AbstractDesignToken, IControl
}
}
_sharedResourceDeltaDictionary.Add(name, localSharedTokenValue);
_sharedResourceDeltaDictionary.Add(new TokenResourceKey(name), localSharedTokenValue);
}
}
@@ -1,5 +1,7 @@
using System.Reflection;
using System.Diagnostics;
using System.Reflection;
using Avalonia.Controls;
using Avalonia.Logging;
using Avalonia.Media;
namespace AtomUI.Theme.TokenSystem;
@@ -33,28 +35,33 @@ public abstract class AbstractDesignToken : IDesignToken
try
{
var type = GetType();
var tokenProperties =
type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy);
foreach (var property in tokenProperties)
var tokenPropertyMap =
type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
.ToDictionary(p => p.Name);
foreach (var tokenInfo in tokenConfigInfo)
{
var tokenName = property.Name;
if (tokenConfigInfo.ContainsKey(tokenName))
var tokenName = tokenInfo.Key;
if (!tokenPropertyMap.ContainsKey(tokenInfo.Key))
{
var propertyType = property.PropertyType;
if (_valueConverters.ContainsKey(propertyType))
var logger = Logger.TryGet(LogEventLevel.Warning, AtomUILogArea.Theme);
logger?.Log(this, $"Token property: '{tokenInfo.Key}' found in token {type.Name}.'");
continue;
}
var property = tokenPropertyMap[tokenName];
var propertyType = property.PropertyType;
if (_valueConverters.ContainsKey(propertyType))
{
property.SetValue(this, _valueConverters[propertyType].Convert(tokenConfigInfo[tokenName]));
}
else
{
try
{
property.SetValue(this, _valueConverters[propertyType].Convert(tokenConfigInfo[tokenName]));
property.SetValue(tokenName, tokenConfigInfo[tokenName]);
}
else
catch (Exception ex)
{
try
{
property.SetValue(tokenName, tokenConfigInfo[tokenName]);
}
catch (Exception ex)
{
throw new InvalidOperationException($"Unable to set token property: {tokenName}, maybe value type mismatch.", ex);
}
throw new InvalidOperationException($"Unable to set token property: {tokenName}, maybe value type mismatch.", ex);
}
}
}
@@ -60,4 +60,28 @@ internal static class TokenFinderUtils
return token;
}
public static ThemeVariant FindThemeVariant(Control control)
{
ThemeVariant? themeVariant = null;
var current = control;
while (current != null)
{
if (current is IThemeConfigProvider configProvider)
{
themeVariant = configProvider.ThemeVariant;
break;
}
current = (current as IStyleHost).StylingParent as Control;
}
if (themeVariant is null)
{
var theme = ThemeManager.Current.ActivatedTheme;
Debug.Assert(theme != null);
themeVariant = theme.ThemeVariant;
}
return themeVariant;
}
}