完成 DotBadge 改造

This commit is contained in:
polarboy 2024-07-22 11:49:50 +08:00
parent fa9c19574a
commit e4ef5a9b59
7 changed files with 260 additions and 344 deletions

View File

@ -49,6 +49,10 @@ public partial class CountBadge : Control, IControlCustomStyle
public static readonly StyledProperty<bool> BadgeIsVisibleProperty =
AvaloniaProperty.Register<CountBadge, bool>(nameof(BadgeIsVisible));
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
AvaloniaProperty.Register<CountBadge, TimeSpan>(
nameof(MotionDuration));
public string? BadgeColor
{
get => GetValue(BadgeColorProperty);
@ -98,7 +102,12 @@ public partial class CountBadge : Control, IControlCustomStyle
set => SetValue(BadgeIsVisibleProperty, value);
}
private bool _initialized = false;
public TimeSpan MotionDuration
{
get => GetValue(MotionDurationProperty);
set => SetValue(MotionDurationProperty, value);
}
private IControlCustomStyle _customStyle;
private CountBadgeAdorner? _badgeAdorner;
private AdornerLayer? _adornerLayer;
@ -118,38 +127,37 @@ public partial class CountBadge : Control, IControlCustomStyle
AffectsRender<CountBadge>(BadgeColorProperty, OffsetProperty);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
public sealed override void ApplyTemplate()
{
base.OnAttachedToLogicalTree(e);
if (!_initialized) {
_customStyle.HandleAttachedToLogicalTree(e);
_initialized = true;
}
base.ApplyTemplate();
CreateBadgeAdorner();
}
void IControlCustomStyle.HandleAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
private void CreateBadgeAdorner()
{
_badgeAdorner = new CountBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (BadgeColor is not null) {
SetupBadgeColor(BadgeColor);
if (_badgeAdorner is null) {
_badgeAdorner = new CountBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (BadgeColor is not null) {
SetupBadgeColor(BadgeColor);
}
}
}
private void PrepareAdorner()
{
if (_adornerLayer is null &&
DecoratedTarget is not null &&
_badgeAdorner is not null) {
if (_adornerLayer is null && DecoratedTarget is not null) {
CreateBadgeAdorner();
var badgeAdorner = _badgeAdorner!;
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
// 这里需要抛出异常吗?
if (_adornerLayer == null) {
return;
}
AdornerLayer.SetAdornedElement(_badgeAdorner, this);
AdornerLayer.SetIsClipEnabled(_badgeAdorner, false);
_adornerLayer.Children.Add(_badgeAdorner);
AdornerLayer.SetAdornedElement(badgeAdorner, this);
AdornerLayer.SetIsClipEnabled(badgeAdorner, false);
_adornerLayer.Children.Add(badgeAdorner);
}
}
@ -167,14 +175,14 @@ public partial class CountBadge : Control, IControlCustomStyle
var adorner = _badgeAdorner!;
if (DecoratedTarget is not null) {
var countBadgeZoomBadgeIn = new CountBadgeZoomBadgeIn();
countBadgeZoomBadgeIn.ConfigureOpacity(_motionDurationSlow);
countBadgeZoomBadgeIn.ConfigureRenderTransform(_motionDurationSlow);
countBadgeZoomBadgeIn.ConfigureOpacity(MotionDuration);
countBadgeZoomBadgeIn.ConfigureRenderTransform(MotionDuration);
motion = countBadgeZoomBadgeIn;
adorner.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
} else {
var countBadgeNoWrapperZoomBadgeIn = new CountBadgeNoWrapperZoomBadgeIn();
countBadgeNoWrapperZoomBadgeIn.ConfigureOpacity(_motionDurationSlow);
countBadgeNoWrapperZoomBadgeIn.ConfigureRenderTransform(_motionDurationSlow);
countBadgeNoWrapperZoomBadgeIn.ConfigureOpacity(MotionDuration);
countBadgeNoWrapperZoomBadgeIn.ConfigureRenderTransform(MotionDuration);
motion = countBadgeNoWrapperZoomBadgeIn;
}
@ -209,14 +217,14 @@ public partial class CountBadge : Control, IControlCustomStyle
var adorner = _badgeAdorner!;
if (DecoratedTarget is not null) {
var countBadgeZoomBadgeOut = new CountBadgeZoomBadgeOut();
countBadgeZoomBadgeOut.ConfigureOpacity(_motionDurationSlow);
countBadgeZoomBadgeOut.ConfigureRenderTransform(_motionDurationSlow);
countBadgeZoomBadgeOut.ConfigureOpacity(MotionDuration);
countBadgeZoomBadgeOut.ConfigureRenderTransform(MotionDuration);
motion = countBadgeZoomBadgeOut;
adorner.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
} else {
var countBadgeNoWrapperZoomBadgeOut = new CountBadgeNoWrapperZoomBadgeOut();
countBadgeNoWrapperZoomBadgeOut.ConfigureOpacity(_motionDurationSlow);
countBadgeNoWrapperZoomBadgeOut.ConfigureRenderTransform(_motionDurationSlow);
countBadgeNoWrapperZoomBadgeOut.ConfigureOpacity(MotionDuration);
countBadgeNoWrapperZoomBadgeOut.ConfigureRenderTransform(MotionDuration);
motion = countBadgeNoWrapperZoomBadgeOut;
}
@ -251,20 +259,20 @@ public partial class CountBadge : Control, IControlCustomStyle
BindUtils.RelayBind(this, OverflowCountProperty, _badgeAdorner, CountBadgeAdorner.OverflowCountProperty);
BindUtils.RelayBind(this, CountProperty, _badgeAdorner, CountBadgeAdorner.CountProperty);
}
BindUtils.CreateTokenBinding(this, MotionDurationSlowTokenProperty, GlobalResourceKey.MotionDurationSlow);
BindUtils.CreateTokenBinding(this, MotionDurationProperty, GlobalResourceKey.MotionDurationSlow);
}
private void HandleDecoratedTargetChanged()
{
if (_badgeAdorner is not null) {
if (DecoratedTarget is null) {
((ISetLogicalParent)_badgeAdorner).SetParent(this);
VisualChildren.Add(_badgeAdorner);
LogicalChildren.Add(_badgeAdorner);
_badgeAdorner.IsAdornerMode = false;
} else if (DecoratedTarget is not null) {
_badgeAdorner.IsAdornerMode = true;
((ISetLogicalParent)DecoratedTarget).SetParent(this);
VisualChildren.Add(DecoratedTarget);
LogicalChildren.Add(DecoratedTarget);
}
}
}
@ -293,7 +301,7 @@ public partial class CountBadge : Control, IControlCustomStyle
HideAdornerWithMotion();
}
}
if (_initialized) {
if (VisualRoot is not null) {
if (e.Property == DecoratedTargetProperty) {
HandleDecoratedTargetChanged();
}

View File

@ -1,8 +1,6 @@
using System.Globalization;
using AtomUI.Data;
using AtomUI.Media;
using AtomUI.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
@ -14,7 +12,7 @@ using Avalonia.Styling;
namespace AtomUI.Controls;
internal partial class CountBadgeAdorner : Control, IControlCustomStyle
internal class CountBadgeAdorner : Control, IControlCustomStyle
{
public static readonly StyledProperty<IBrush?> BadgeColorProperty =
AvaloniaProperty.Register<CountBadgeAdorner, IBrush?>(
@ -38,22 +36,22 @@ internal partial class CountBadgeAdorner : Control, IControlCustomStyle
internal static readonly StyledProperty<FontFamily> FontFamilyProperty =
TextElement.FontFamilyProperty.AddOwner<CountBadgeAdorner>();
internal static readonly StyledProperty<FontWeight> TextFontWeightProperty =
TextElement.FontWeightProperty.AddOwner<CountBadgeAdorner>();
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
AvaloniaProperty.Register<CountBadgeAdorner, IBrush?>(
nameof(BadgeShadowColor));
internal static readonly StyledProperty<double> BadgeShadowSizeProperty =
AvaloniaProperty.Register<CountBadgeAdorner, double>(
nameof(BadgeShadowSize));
internal static readonly StyledProperty<double> PaddingInlineProperty =
AvaloniaProperty.Register<CountBadgeAdorner, double>(
nameof(PaddingInline));
public IBrush? BadgeColor
{
get => GetValue(BadgeColorProperty);
@ -83,51 +81,59 @@ internal partial class CountBadgeAdorner : Control, IControlCustomStyle
get => GetValue(CountProperty);
set => SetValue(CountProperty, value);
}
internal FontFamily FontFamily
{
get => GetValue(FontFamilyProperty);
set => SetValue(FontFamilyProperty, value);
}
internal FontWeight TextFontWeight
{
get => GetValue(TextFontWeightProperty);
set => SetValue(TextFontWeightProperty, value);
}
internal IBrush? BadgeShadowColor
{
get => GetValue(BadgeShadowColorProperty);
set => SetValue(BadgeShadowColorProperty, value);
}
internal double BadgeShadowSize
{
get => GetValue(BadgeShadowSizeProperty);
set => SetValue(BadgeShadowSizeProperty, value);
}
internal double PaddingInline
{
get => GetValue(PaddingInlineProperty);
set => SetValue(PaddingInlineProperty, value);
}
internal bool IsAdornerMode { get; set; }
internal static readonly DirectProperty<DotBadgeAdorner, bool> IsAdornerModeProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, bool>(
nameof(IsAdornerMode),
o => o.IsAdornerMode,
(o, v) => o.IsAdornerMode = v);
public static readonly DirectProperty<CountBadgeAdorner, Point> OffsetProperty =
AvaloniaProperty.RegisterDirect<CountBadgeAdorner, Point>(
nameof(Offset),
o => o.Offset,
(o, v) => o.Offset = v);
private bool _isAdornerMode = false;
private Point _offset;
internal bool IsAdornerMode
{
get => _isAdornerMode;
set => SetAndRaise(IsAdornerModeProperty, ref _isAdornerMode, value);
}
internal static readonly StyledProperty<Point> OffsetProperty =
AvaloniaProperty.Register<CountBadgeAdorner, Point>(
nameof(Offset));
public Point Offset
{
get => _offset;
set => SetAndRaise(OffsetProperty, ref _offset, value);
get => GetValue(OffsetProperty);
set => SetValue(OffsetProperty, value);
}
public static readonly DirectProperty<CountBadgeAdorner, int> OverflowCountProperty =
@ -166,7 +172,8 @@ internal partial class CountBadgeAdorner : Control, IControlCustomStyle
{
AffectsMeasure<CountBadgeAdorner>(OverflowCountProperty,
SizeProperty,
CountProperty);
CountProperty,
IsAdornerModeProperty);
AffectsRender<CountBadgeAdorner>(BadgeColorProperty, OffsetProperty);
}
@ -201,18 +208,17 @@ internal partial class CountBadgeAdorner : Control, IControlCustomStyle
commonStyle.Add(BadgeTextColorProperty, BadgeResourceKey.BadgeTextColor);
commonStyle.Add(PaddingInlineProperty, GlobalResourceKey.PaddingXS);
Styles.Add(commonStyle);
var defaultSizeStyle =
new Style(selector => selector.PropertyEquals(SizeProperty, CountBadgeSize.Default));
defaultSizeStyle.Add(TextFontSizeProperty, BadgeResourceKey.TextFontSize);
defaultSizeStyle.Add(IndicatorHeightProperty, BadgeResourceKey.IndicatorHeight);
Styles.Add(defaultSizeStyle);
var smallSizeStyle = new Style(selector => selector.PropertyEquals(SizeProperty, CountBadgeSize.Small));
smallSizeStyle.Add(TextFontSizeProperty, BadgeResourceKey.TextFontSizeSM);
smallSizeStyle.Add(IndicatorHeightProperty, BadgeResourceKey.IndicatorHeightSM);
Styles.Add(smallSizeStyle);
}
public override void ApplyTemplate()

View File

@ -1,17 +0,0 @@
using Avalonia;
namespace AtomUI.Controls;
public partial class CountBadge
{
#region Control token
private TimeSpan _motionDurationSlow;
private static readonly DirectProperty<CountBadge, TimeSpan> MotionDurationSlowTokenProperty =
AvaloniaProperty.RegisterDirect<CountBadge, TimeSpan>(
nameof(_motionDurationSlow),
o => o._motionDurationSlow,
(o, v) => o._motionDurationSlow = v);
#endregion
}

View File

@ -46,6 +46,10 @@ public partial class DotBadge : Control, IControlCustomStyle
public static readonly StyledProperty<bool> BadgeIsVisibleProperty =
AvaloniaProperty.Register<DotBadge, bool>(nameof(BadgeIsVisible));
internal static readonly StyledProperty<TimeSpan> MotionDurationProperty =
AvaloniaProperty.Register<CountBadge, TimeSpan>(
nameof(MotionDuration));
public string? DotColor
{
get => GetValue(DotColorProperty);
@ -83,6 +87,12 @@ public partial class DotBadge : Control, IControlCustomStyle
set => SetValue(BadgeIsVisibleProperty, value);
}
public TimeSpan MotionDuration
{
get => GetValue(MotionDurationProperty);
set => SetValue(MotionDurationProperty, value);
}
private bool _initialized = false;
private IControlCustomStyle _customStyle;
private DotBadgeAdorner? _dotBadgeAdorner;
@ -96,19 +106,9 @@ public partial class DotBadge : Control, IControlCustomStyle
static DotBadge()
{
AffectsMeasure<DotBadge>(DecoratedTargetProperty,
TextProperty);
AffectsMeasure<DotBadge>(DecoratedTargetProperty, TextProperty);
AffectsRender<DotBadge>(DotColorProperty, StatusProperty);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
if (!_initialized) {
_customStyle.SetupUI();
_initialized = true;
}
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
@ -116,19 +116,31 @@ public partial class DotBadge : Control, IControlCustomStyle
PrepareAdorner();
}
private void CreateDotBadgeAdorner()
{
if (_dotBadgeAdorner is null) {
_dotBadgeAdorner = new DotBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (DotColor is not null) {
SetupDotColor(DotColor);
}
}
}
private void PrepareAdorner()
{
if (_adornerLayer is null &&
DecoratedTarget is not null &&
_dotBadgeAdorner is not null) {
if (_adornerLayer is null && DecoratedTarget is not null) {
CreateDotBadgeAdorner();
var dotBadgeAdorner = _dotBadgeAdorner!;
_adornerLayer = AdornerLayer.GetAdornerLayer(this);
// 这里需要抛出异常吗?
if (_adornerLayer == null) {
return;
}
AdornerLayer.SetAdornedElement(_dotBadgeAdorner, this);
AdornerLayer.SetIsClipEnabled(_dotBadgeAdorner, false);
_adornerLayer.Children.Add(_dotBadgeAdorner);
AdornerLayer.SetAdornedElement(dotBadgeAdorner, this);
AdornerLayer.SetIsClipEnabled(dotBadgeAdorner, false);
_adornerLayer.Children.Add(dotBadgeAdorner);
}
}
@ -142,8 +154,8 @@ public partial class DotBadge : Control, IControlCustomStyle
_animating = true;
var director = Director.Instance;
var motion = new CountBadgeZoomBadgeIn();
motion.ConfigureOpacity(_motionDurationSlow);
motion.ConfigureRenderTransform(_motionDurationSlow);
motion.ConfigureOpacity(MotionDuration);
motion.ConfigureRenderTransform(MotionDuration);
_dotBadgeAdorner!.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
var motionActor = new MotionActor(_dotBadgeAdorner, motion);
motionActor.DispatchInSceneLayer = false;
@ -174,8 +186,8 @@ public partial class DotBadge : Control, IControlCustomStyle
_animating = true;
var director = Director.Instance;
var motion = new CountBadgeZoomBadgeOut();
motion.ConfigureOpacity(_motionDurationSlow);
motion.ConfigureRenderTransform(_motionDurationSlow);
motion.ConfigureOpacity(MotionDuration);
motion.ConfigureRenderTransform(MotionDuration);
_dotBadgeAdorner!.AnimationRenderTransformOrigin = motion.MotionRenderTransformOrigin;
var motionActor = new MotionActor(_dotBadgeAdorner, motion);
motionActor.DispatchInSceneLayer = false;
@ -195,16 +207,6 @@ public partial class DotBadge : Control, IControlCustomStyle
HideAdorner();
}
void IControlCustomStyle.SetupUI()
{
_dotBadgeAdorner = new DotBadgeAdorner();
_customStyle.SetupTokenBindings();
HandleDecoratedTargetChanged();
if (DotColor is not null) {
SetupDotColor(DotColor);
}
}
void IControlCustomStyle.SetupTokenBindings()
{
if (_dotBadgeAdorner is not null) {
@ -212,24 +214,30 @@ public partial class DotBadge : Control, IControlCustomStyle
BindUtils.RelayBind(this, TextProperty, _dotBadgeAdorner, DotBadgeAdorner.TextProperty);
BindUtils.RelayBind(this, OffsetProperty, _dotBadgeAdorner, DotBadgeAdorner.OffsetProperty);
}
BindUtils.CreateTokenBinding(this, MotionDurationSlowTokenProperty, GlobalResourceKey.MotionDurationSlow);
BindUtils.CreateTokenBinding(this, MotionDurationProperty, GlobalResourceKey.MotionDurationSlow);
}
private void HandleDecoratedTargetChanged()
{
if (_dotBadgeAdorner is not null) {
if (DecoratedTarget is null) {
VisualChildren.Add(_dotBadgeAdorner);
LogicalChildren.Add(_dotBadgeAdorner);
_dotBadgeAdorner.IsAdornerMode = false;
((ISetLogicalParent)_dotBadgeAdorner).SetParent(this);
VisualChildren.Add(_dotBadgeAdorner);
} else if (DecoratedTarget is not null) {
_dotBadgeAdorner.IsAdornerMode = true;
VisualChildren.Add(DecoratedTarget);
LogicalChildren.Add(DecoratedTarget);
((ISetLogicalParent)DecoratedTarget).SetParent(this);
}
}
}
public sealed override void ApplyTemplate()
{
base.ApplyTemplate();
CreateDotBadgeAdorner();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
@ -281,12 +289,12 @@ public partial class DotBadge : Control, IControlCustomStyle
foreach (var presetColor in PresetPrimaryColor.AllColorTypes()) {
if (presetColor.Type.ToString().ToLower() == colorStr) {
_dotBadgeAdorner!.DotColor = new SolidColorBrush(presetColor.Color());
_dotBadgeAdorner!.BadgeDotColor = new SolidColorBrush(presetColor.Color());
return;
}
}
if (Color.TryParse(colorStr, out Color color)) {
_dotBadgeAdorner!.DotColor = new SolidColorBrush(color);
_dotBadgeAdorner!.BadgeDotColor = new SolidColorBrush(color);
}
}
}

View File

@ -5,24 +5,12 @@ using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.Styling;
namespace AtomUI.Controls;
internal partial class DotBadgeAdorner : Control, IControlCustomStyle
{
public static readonly DirectProperty<DotBadgeAdorner, IBrush?> DotColorProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(DotColor),
o => o.DotColor,
(o, v) => o.DotColor = v);
private IBrush? _dotColor;
public IBrush? DotColor
{
get => _dotColor;
set => SetAndRaise(DotColorProperty, ref _dotColor, value);
}
public static readonly DirectProperty<DotBadgeAdorner, DotBadgeStatus?> StatusProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, DotBadgeStatus?>(
nameof(Status),
@ -54,7 +42,35 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
nameof(IsAdornerMode),
o => o.IsAdornerMode,
(o, v) => o.IsAdornerMode = v);
internal static readonly StyledProperty<IBrush?> BadgeDotColorProperty =
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
nameof(BadgeDotColor));
internal static readonly StyledProperty<double> DotSizeProperty =
AvaloniaProperty.Register<DotBadgeAdorner, double>(
nameof(DotSize));
internal static readonly StyledProperty<double> StatusSizeProperty =
AvaloniaProperty.Register<DotBadgeAdorner, double>(
nameof(StatusSize));
internal static readonly StyledProperty<IBrush?> BadgeShadowColorProperty =
AvaloniaProperty.Register<DotBadgeAdorner, IBrush?>(
nameof(BadgeShadowColor));
private static readonly StyledProperty<double> BadgeShadowSizeProperty =
AvaloniaProperty.Register<DotBadgeAdorner, double>(
nameof(BadgeShadowSize));
private static readonly StyledProperty<double> BadgeTextMarginInlineProperty =
AvaloniaProperty.Register<DotBadgeAdorner, double>(
nameof(BadgeTextMarginInline));
public static readonly StyledProperty<Point> OffsetProperty =
AvaloniaProperty.Register<DotBadgeAdorner, Point>(
nameof(Offset));
private bool _isAdornerMode = false;
public bool IsAdornerMode
{
@ -62,33 +78,46 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
set => SetAndRaise(IsAdornerModeProperty, ref _isAdornerMode, value);
}
public static readonly DirectProperty<DotBadgeAdorner, IBrush?> EffectiveDotColorProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(EffectiveDotColor),
o => o.EffectiveDotColor,
(o, v) => o.EffectiveDotColor = v);
private IBrush? _effectiveDotColor;
// 当前有效的颜色
public IBrush? EffectiveDotColor
{
get => _effectiveDotColor;
set => SetAndRaise(EffectiveDotColorProperty, ref _effectiveDotColor, value);
}
public static readonly DirectProperty<DotBadgeAdorner, Point> OffsetProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, Point>(
nameof(Offset),
o => o.Offset,
(o, v) => o.Offset = v);
private Point _offset;
public Point Offset
{
get => _offset;
set => SetAndRaise(OffsetProperty, ref _offset, value);
get => GetValue(OffsetProperty);
set => SetValue(OffsetProperty,value);
}
public double DotSize
{
get => GetValue(DotSizeProperty);
set => SetValue(DotSizeProperty, value);
}
public double StatusSize
{
get => GetValue(StatusSizeProperty);
set => SetValue(StatusSizeProperty, value);
}
internal IBrush? BadgeDotColor
{
get => GetValue(BadgeDotColorProperty);
set => SetValue(BadgeDotColorProperty, value);
}
internal IBrush? BadgeShadowColor
{
get => GetValue(BadgeShadowColorProperty);
set => SetValue(BadgeShadowColorProperty, value);
}
public double BadgeShadowSize
{
get => GetValue(BadgeShadowSizeProperty);
set => SetValue(BadgeShadowSizeProperty, value);
}
public double BadgeTextMarginInline
{
get => GetValue(BadgeTextMarginInlineProperty);
set => SetValue(BadgeTextMarginInlineProperty, value);
}
private bool _initialized = false;
@ -102,84 +131,79 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
static DotBadgeAdorner()
{
AffectsMeasure<DotBadge>(TextProperty, IsAdornerModeProperty);
AffectsRender<DotBadge>(EffectiveDotColorProperty, OffsetProperty);
AffectsRender<DotBadge>(BadgeDotColorProperty, OffsetProperty);
}
public DotBadgeAdorner()
{
_customStyle = this;
}
void IControlCustomStyle.SetupUI()
{
_textLabel = new Label
{
Content = Text,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
Padding = new Thickness(0),
};
LogicalChildren.Add(_textLabel);
VisualChildren.Add(_textLabel);
_customStyle.SetupTokenBindings();
SetupEffectiveDotColor();
BuildBoxShadow();
}
void IControlCustomStyle.SetupTokenBindings()
public sealed override void ApplyTemplate()
{
BindUtils.CreateTokenBinding(this, ColorTextPlaceholderTokenProperty, GlobalResourceKey.ColorTextPlaceholder);
BindUtils.CreateTokenBinding(this, ColorErrorTokenProperty, GlobalResourceKey.ColorError);
BindUtils.CreateTokenBinding(this, ColorWarningTokenProperty, GlobalResourceKey.ColorWarning);
BindUtils.CreateTokenBinding(this, ColorSuccessTokenProperty, GlobalResourceKey.ColorSuccess);
BindUtils.CreateTokenBinding(this, ColorInfoTokenProperty, GlobalResourceKey.ColorInfo);
BindUtils.CreateTokenBinding(this, MarginXSTokenProperty, GlobalResourceKey.MarginXS);
BindUtils.CreateTokenBinding(this, DotSizeTokenProperty, BadgeResourceKey.DotSize);
BindUtils.CreateTokenBinding(this, StatusSizeTokenProperty, BadgeResourceKey.StatusSize);
BindUtils.CreateTokenBinding(this, BadgeColorTokenProperty, BadgeResourceKey.BadgeColor);
BindUtils.CreateTokenBinding(this, BadgeShadowSizeTokenProperty, BadgeResourceKey.BadgeShadowSize);
BindUtils.CreateTokenBinding(this, BadgeShadowColorTokenProperty, BadgeResourceKey.BadgeShadowColor);
}
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
base.OnAttachedToLogicalTree(e);
base.ApplyTemplate();
if (!_initialized) {
_customStyle.SetupUI();
_textLabel = new Label
{
Content = Text,
HorizontalAlignment = HorizontalAlignment.Left,
VerticalAlignment = VerticalAlignment.Center,
HorizontalContentAlignment = HorizontalAlignment.Center,
VerticalContentAlignment = VerticalAlignment.Center,
Padding = new Thickness(0),
};
((ISetLogicalParent)_textLabel).SetParent(this);
VisualChildren.Add(_textLabel);
BuildBoxShadow();
_initialized = true;
}
}
private IBrush? GetStatusColor(DotBadgeStatus status)
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
{
if (status == DotBadgeStatus.Error) {
return _colorErrorToken;
} else if (status == DotBadgeStatus.Processing) {
return _colorInfoToken;
} else if (status == DotBadgeStatus.Success) {
return _colorSuccessToken;
} else if (status == DotBadgeStatus.Warning) {
return _colorWarningToken;
} else {
return _colorTextPlaceholderToken;
base.OnAttachedToLogicalTree(e);
_customStyle.BuildStyles();
}
void IControlCustomStyle.BuildStyles()
{
if (Styles.Count == 0) {
BuildBadgeColorStyle();
}
}
private void SetupEffectiveDotColor()
private void BuildBadgeColorStyle()
{
if (_dotColor is not null) {
EffectiveDotColor = _dotColor;
} else if (Status.HasValue) {
EffectiveDotColor = GetStatusColor(Status.Value);
}
var commonStyle = new Style(selector => selector.OfType<DotBadgeAdorner>());
commonStyle.Add(BadgeTextMarginInlineProperty, GlobalResourceKey.MarginXS);
commonStyle.Add(BadgeDotColorProperty, BadgeResourceKey.BadgeColor);
commonStyle.Add(DotSizeProperty, BadgeResourceKey.DotSize);
commonStyle.Add(StatusSizeProperty, BadgeResourceKey.StatusSize);
commonStyle.Add(BadgeShadowSizeProperty, BadgeResourceKey.BadgeShadowSize);
commonStyle.Add(BadgeShadowColorProperty, BadgeResourceKey.BadgeShadowColor);
if (EffectiveDotColor is null) {
EffectiveDotColor = _badgeColorToken;
}
var errorStatusStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.StatusProperty, DotBadgeStatus.Error));
errorStatusStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, GlobalResourceKey.ColorError);
commonStyle.Add(errorStatusStyle);
var successStatusStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.StatusProperty, DotBadgeStatus.Success));
successStatusStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, GlobalResourceKey.ColorSuccess);
commonStyle.Add(successStatusStyle);
var warningStatusStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.StatusProperty, DotBadgeStatus.Warning));
warningStatusStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, GlobalResourceKey.ColorWarning);
commonStyle.Add(warningStatusStyle);
var defaultStatusStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.StatusProperty, DotBadgeStatus.Default));
defaultStatusStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, GlobalResourceKey.ColorTextPlaceholder);
commonStyle.Add(defaultStatusStyle);
var processingStatusStyle = new Style(selector => selector.Nesting().PropertyEquals(DotBadgeAdorner.StatusProperty, DotBadgeStatus.Processing));
processingStatusStyle.Add(DotBadgeAdorner.BadgeDotColorProperty, GlobalResourceKey.ColorInfo);
commonStyle.Add(processingStatusStyle);
Styles.Add(commonStyle);
}
protected override Size MeasureOverride(Size availableSize)
@ -191,11 +215,11 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
targetHeight = availableSize.Height;
} else {
var textSize = base.MeasureOverride(availableSize);
targetWidth += _statusSizeToken;
targetWidth += StatusSize;
targetWidth += textSize.Width;
targetHeight += Math.Max(textSize.Height, _statusSizeToken);
targetHeight += Math.Max(textSize.Height, StatusSize);
if (textSize.Width > 0) {
targetWidth += _marginXSToken;
targetWidth += BadgeTextMarginInline;
}
}
return new Size(targetWidth, targetHeight);
@ -206,12 +230,12 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
if (!IsAdornerMode) {
double textOffsetX = 0;
if (IsAdornerMode) {
textOffsetX += _dotSizeToken;
textOffsetX += DotSize;
} else {
textOffsetX += _statusSizeToken;
textOffsetX += StatusSize;
}
textOffsetX += _marginXSToken;
textOffsetX += BadgeTextMarginInline;
var textRect = new Rect(new Point(textOffsetX, 0), _textLabel!.DesiredSize);
_textLabel.Arrange(textRect);
}
@ -226,26 +250,19 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
if (_textLabel is not null) {
_textLabel.IsVisible = !newValue;
}
} else if (e.Property == BadgeShadowSizeTokenProperty ||
e.Property == BadgeShadowColorTokenProperty) {
} else if (e.Property == BadgeShadowSizeProperty ||
e.Property == BadgeShadowColorProperty) {
BuildBoxShadow();
}
if (_initialized) {
if (e.Property == StatusProperty ||
e.Property == DotColorProperty) {
SetupEffectiveDotColor();
}
}
}
public override void Render(DrawingContext context)
{
var dotSize = 0d;
if (IsAdornerMode) {
dotSize = _dotSizeToken;
dotSize = DotSize;
} else {
dotSize = _statusSizeToken;
dotSize = StatusSize;
}
var offsetX = 0d;
@ -273,19 +290,20 @@ internal partial class DotBadgeAdorner : Control, IControlCustomStyle
var renderTransform = (-offset) * RenderTransform.Value * (offset);
context.PushTransform(renderTransform);
}
context.DrawRectangle(EffectiveDotColor, null, dotRect, dotSize, dotSize, _boxShadows);
context.DrawRectangle(BadgeDotColor, null, dotRect, dotSize, dotSize, _boxShadows);
}
private void BuildBoxShadow()
{
_boxShadows = new BoxShadows(new BoxShadow()
{
OffsetX = 0,
OffsetY = 0,
Blur = 0,
Spread = _badgeShadowSizeToken,
Color = ((SolidColorBrush)_badgeShadowColorToken!).Color
});
if (IsSet(BadgeShadowSizeProperty) && IsSet(BadgeShadowColorProperty)) {
_boxShadows = new BoxShadows(new BoxShadow()
{
OffsetX = 0,
OffsetY = 0,
Blur = 0,
Spread = BadgeShadowSize,
Color = ((SolidColorBrush)BadgeShadowColor!).Color
});
}
}
}

View File

@ -1,90 +0,0 @@
using Avalonia;
using Avalonia.Media;
namespace AtomUI.Controls;
internal partial class DotBadgeAdorner
{
#region Control token
private IBrush? _colorTextPlaceholderToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> ColorTextPlaceholderTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_colorTextPlaceholderToken),
o => o._colorTextPlaceholderToken,
(o, v) => o._colorTextPlaceholderToken = v);
private IBrush? _colorErrorToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> ColorErrorTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_colorErrorToken),
o => o._colorErrorToken,
(o, v) => o._colorErrorToken = v);
private IBrush? _colorWarningToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> ColorWarningTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_colorWarningToken),
o => o._colorWarningToken,
(o, v) => o._colorWarningToken = v);
private IBrush? _colorSuccessToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> ColorSuccessTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_colorSuccessToken),
o => o._colorSuccessToken,
(o, v) => o._colorSuccessToken = v);
private IBrush? _colorInfoToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> ColorInfoTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_colorInfoToken),
o => o._colorInfoToken,
(o, v) => o._colorInfoToken = v);
private double _dotSizeToken;
private static readonly DirectProperty<DotBadgeAdorner, double> DotSizeTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, double>(
nameof(_dotSizeToken),
o => o._dotSizeToken,
(o, v) => o._dotSizeToken = v);
private double _statusSizeToken;
private static readonly DirectProperty<DotBadgeAdorner, double> StatusSizeTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, double>(
nameof(_statusSizeToken),
o => o._statusSizeToken,
(o, v) => o._statusSizeToken = v);
private double _marginXSToken;
private static readonly DirectProperty<DotBadgeAdorner, double> MarginXSTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, double>(
nameof(_marginXSToken),
o => o._marginXSToken,
(o, v) => o._marginXSToken = v);
private IBrush? _badgeColorToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> BadgeColorTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_badgeColorToken),
o => o._badgeColorToken,
(o, v) => o._badgeColorToken = v);
private IBrush? _badgeShadowColorToken;
private static readonly DirectProperty<DotBadgeAdorner, IBrush?> BadgeShadowColorTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, IBrush?>(
nameof(_badgeShadowColorToken),
o => o._badgeShadowColorToken,
(o, v) => o._badgeShadowColorToken = v);
private double _badgeShadowSizeToken;
private static readonly DirectProperty<DotBadgeAdorner, double> BadgeShadowSizeTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadgeAdorner, double>(
nameof(_badgeShadowSizeToken),
o => o._badgeShadowSizeToken,
(o, v) => o._badgeShadowSizeToken = v);
#endregion
}

View File

@ -1,17 +0,0 @@
using Avalonia;
namespace AtomUI.Controls;
public partial class DotBadge
{
#region Control token
private TimeSpan _motionDurationSlow;
private static readonly DirectProperty<DotBadge, TimeSpan> MotionDurationSlowTokenProperty =
AvaloniaProperty.RegisterDirect<DotBadge, TimeSpan>(
nameof(_motionDurationSlow),
o => o._motionDurationSlow,
(o, v) => o._motionDurationSlow = v);
#endregion
}