mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-28 14:20:47 +08:00
Add SkeletonWidth
This commit is contained in:
+1
@@ -45,6 +45,7 @@ namespace AtomUI.Theme
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.ScrollBarToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.SegmentedToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.SeparatorToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.SkeletonToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.SliderToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.TabControlToken));
|
||||
tokenTypes.Add(typeof(AtomUI.Controls.TagToken));
|
||||
|
||||
+12
@@ -659,6 +659,18 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey VerticalMarginInline = new TokenResourceKey("Separator.VerticalMarginInline");
|
||||
}
|
||||
|
||||
public static class SkeletonTokenKey
|
||||
{
|
||||
public static readonly TokenResourceKey BlockRadius = new TokenResourceKey("Skeleton.BlockRadius");
|
||||
public static readonly TokenResourceKey GradientFromColor = new TokenResourceKey("Skeleton.GradientFromColor");
|
||||
public static readonly TokenResourceKey GradientToColor = new TokenResourceKey("Skeleton.GradientToColor");
|
||||
public static readonly TokenResourceKey LoadingBackground = new TokenResourceKey("Skeleton.LoadingBackground");
|
||||
public static readonly TokenResourceKey LoadingMotionDuration = new TokenResourceKey("Skeleton.LoadingMotionDuration");
|
||||
public static readonly TokenResourceKey ParagraphLineHeight = new TokenResourceKey("Skeleton.ParagraphLineHeight");
|
||||
public static readonly TokenResourceKey ParagraphMarginTop = new TokenResourceKey("Skeleton.ParagraphMarginTop");
|
||||
public static readonly TokenResourceKey TitleHeight = new TokenResourceKey("Skeleton.TitleHeight");
|
||||
}
|
||||
|
||||
public static class SliderTokenKey
|
||||
{
|
||||
public static readonly TokenResourceKey MarginPartWithMark = new TokenResourceKey("Slider.MarginPartWithMark");
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls.Primitives;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public abstract class AbstractSkeleton : TemplatedControl,
|
||||
ISizeTypeAware
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<bool> IsActiveProperty =
|
||||
AvaloniaProperty.Register<StyledElement, bool>(nameof(IsActive));
|
||||
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner<AbstractSkeleton>();
|
||||
|
||||
public bool IsActive
|
||||
{
|
||||
get => GetValue(IsActiveProperty);
|
||||
set => SetValue(IsActiveProperty, value);
|
||||
}
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
get => GetValue(SizeTypeProperty);
|
||||
set => SetValue(SizeTypeProperty, value);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class Skeleton : ContentControl
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SkeletonAvatar : AbstractSkeleton
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SkeletonButton : AbstractSkeleton
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SkeletonInput : AbstractSkeleton
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class SkeletonLine : AbstractSkeleton
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SkeletonParagraph : AbstractSkeleton
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class SkeletonTitle
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlDesignToken]
|
||||
internal class SkeletonToken : AbstractControlDesignToken
|
||||
|
||||
{
|
||||
public const string ID = "Skeleton";
|
||||
|
||||
/// <summary>
|
||||
/// 渐变色起点颜色
|
||||
/// Start color of gradient
|
||||
/// </summary>
|
||||
public Color GradientFromColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 渐变色终点颜色
|
||||
/// End color of gradient
|
||||
/// </summary>
|
||||
public Color GradientToColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 标题骨架屏高度
|
||||
/// Height of title skeleton
|
||||
/// </summary>
|
||||
public double TitleHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 骨架屏圆角
|
||||
/// Border radius of skeleton
|
||||
/// </summary>
|
||||
public CornerRadius BlockRadius { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 段落骨架屏上间距
|
||||
/// Margin top of paragraph skeleton
|
||||
/// </summary>
|
||||
public Thickness ParagraphMarginTop { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 段落骨架屏单行高度
|
||||
/// Line height of paragraph skeleton
|
||||
/// </summary>
|
||||
public double ParagraphLineHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认加载的时长
|
||||
/// </summary>
|
||||
public TimeSpan LoadingMotionDuration { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 默认加载的动画背景笔刷
|
||||
/// </summary>
|
||||
public IBrush? LoadingBackground { get; set; }
|
||||
|
||||
public SkeletonToken()
|
||||
: base(ID)
|
||||
{
|
||||
}
|
||||
|
||||
protected internal override void CalculateFromAlias()
|
||||
{
|
||||
base.CalculateFromAlias();
|
||||
GradientFromColor = SharedToken.ColorFillContent;
|
||||
GradientToColor = SharedToken.ColorFill;
|
||||
TitleHeight = SharedToken.ControlHeight / 2;
|
||||
BlockRadius = SharedToken.BorderRadiusSM;
|
||||
ParagraphMarginTop = new Thickness(0, SharedToken.UniformlyMarginLG + SharedToken.UniformlyMarginXXS, 0, 0);
|
||||
ParagraphLineHeight = SharedToken.ControlHeight / 2;
|
||||
LoadingMotionDuration = TimeSpan.FromSeconds(1.4);
|
||||
LoadingBackground = new LinearGradientBrush()
|
||||
{
|
||||
StartPoint = new RelativePoint(0, 0.5, RelativeUnit.Relative),
|
||||
EndPoint = new RelativePoint(1, 0.5, RelativeUnit.Relative),
|
||||
GradientStops =
|
||||
{
|
||||
new GradientStop { Offset = 0.25, Color = GradientFromColor },
|
||||
new GradientStop { Offset = 0.37, Color = GradientToColor },
|
||||
new GradientStop { Offset = 0.63, Color = GradientFromColor }
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using AtomUI.Utils;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public enum SkeletonUnitType
|
||||
{
|
||||
Percentage = 0,
|
||||
Pixel = 1,
|
||||
}
|
||||
|
||||
public struct SkeletonWidth : IEquatable<SkeletonWidth>
|
||||
{
|
||||
private readonly SkeletonUnitType _type;
|
||||
private readonly double _value;
|
||||
|
||||
public SkeletonWidth(double value)
|
||||
: this(value, SkeletonUnitType.Pixel)
|
||||
{
|
||||
}
|
||||
|
||||
public SkeletonWidth(double value, SkeletonUnitType type)
|
||||
{
|
||||
if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
|
||||
{
|
||||
throw new ArgumentException("Invalid value", nameof(value));
|
||||
}
|
||||
|
||||
if (type < SkeletonUnitType.Percentage || type > SkeletonUnitType.Pixel)
|
||||
{
|
||||
throw new ArgumentException("Invalid value", nameof(type));
|
||||
}
|
||||
|
||||
_type = type;
|
||||
_value = value;
|
||||
}
|
||||
|
||||
public SkeletonUnitType SkeletonUnitType => _type;
|
||||
|
||||
public bool IsAbsolute => _type == SkeletonUnitType.Pixel;
|
||||
|
||||
public bool IsPercentage => _type == SkeletonUnitType.Percentage;
|
||||
|
||||
public bool IsPixel => _type == SkeletonUnitType.Pixel;
|
||||
|
||||
public double Value => _value;
|
||||
|
||||
public static bool operator ==(SkeletonWidth a, SkeletonWidth b)
|
||||
{
|
||||
return (MathUtils.AreClose(a._value, b._value) && a._type == b._type);
|
||||
}
|
||||
|
||||
public static bool operator !=(SkeletonWidth gl1, SkeletonWidth gl2)
|
||||
{
|
||||
return !(gl1 == gl2);
|
||||
}
|
||||
|
||||
public override bool Equals(object? o)
|
||||
{
|
||||
if (o == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!(o is SkeletonWidth))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this == (SkeletonWidth)o;
|
||||
}
|
||||
|
||||
public bool Equals(SkeletonWidth gridLength)
|
||||
{
|
||||
return this == gridLength;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return _value.GetHashCode() ^ _type.GetHashCode();
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
var vstr = _value.ToString(CultureInfo.InvariantCulture);
|
||||
if (IsPercentage)
|
||||
{
|
||||
return $"{vstr}%";
|
||||
}
|
||||
return $"{vstr}px";
|
||||
}
|
||||
|
||||
public static SkeletonWidth Parse(string s)
|
||||
{
|
||||
s = s.ToUpperInvariant();
|
||||
var match = Regex.Match(s.Trim(), @"^([+-]?\d*\.?\d+)\s*([a-zA-Z%]+)?$", RegexOptions.IgnoreCase);
|
||||
if (!match.Success)
|
||||
{
|
||||
throw new FormatException($"Invalid width format: '{s}'");
|
||||
}
|
||||
|
||||
SkeletonUnitType unit = SkeletonUnitType.Pixel;
|
||||
if (match.Groups[2].Value == "%")
|
||||
{
|
||||
unit = SkeletonUnitType.Percentage;
|
||||
}
|
||||
|
||||
var value = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
return new SkeletonWidth(value, unit);
|
||||
}
|
||||
|
||||
public static IEnumerable<SkeletonWidth> ParseWidths(string s)
|
||||
{
|
||||
var result = new List<SkeletonWidth>();
|
||||
using (var tokenizer = new SpanStringTokenizer(s, CultureInfo.InvariantCulture))
|
||||
{
|
||||
while (tokenizer.TryReadString(out var item))
|
||||
{
|
||||
result.Add(Parse(item));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:atom="https://atomui.net"
|
||||
x:ClassModifier="internal">
|
||||
</ResourceDictionary>
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace AtomUI.Controls.Themes;
|
||||
|
||||
internal static class SkeletonThemeConstants
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:ClassModifier="internal">
|
||||
<ResourceDictionary.MergedDictionaries>
|
||||
<ResourceInclude Source="SkeletonTheme.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
Reference in New Issue
Block a user