Refactor LoadingIndicator

This commit is contained in:
CHINBOY
2025-03-09 09:34:06 +08:00
parent fb9dcba9ef
commit 6cf758a34e
6 changed files with 68 additions and 72 deletions
+6 -9
View File
@@ -228,18 +228,19 @@ public class Expander : AvaloniaExpander,
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, BorderThicknessProperty,
SharedTokenKey.BorderThickness,
BindingPriority.Template, new RenderScaleAwareThicknessConfigure(this)));
SetupEffectiveBorderThickness();
SetupExpanderBorderThickness();
SetupDefaultIcon();
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
SetupDefaultIcon();
base.OnApplyTemplate(e);
this.RunThemeTokenBindingActions();
_motionActor = e.NameScope.Find<MotionActorControl>(ExpanderTheme.ContentMotionActorPart);
_headerDecorator = e.NameScope.Find<Border>(ExpanderTheme.HeaderDecoratorPart);
_expandButton = e.NameScope.Find<IconButton>(ExpanderTheme.ExpandButtonPart);
SetupEffectiveBorderThickness();
SetupExpanderBorderThickness();
_tempAnimationDisabled = true;
HandleExpandedChanged();
_tempAnimationDisabled = false;
@@ -276,16 +277,12 @@ public class Expander : AvaloniaExpander,
SetupDefaultIcon();
}
}
if (this.IsAttachedToVisualTree())
{
if (change.Property == IsBorderlessProperty)
else if (change.Property == IsBorderlessProperty)
{
SetupEffectiveBorderThickness();
}
}
if (change.Property == ExpandIconProperty)
{
if (change.OldValue is Icon oldIcon)
+9 -11
View File
@@ -192,17 +192,6 @@ public class FlyoutHost : Control,
{
base.OnAttachedToLogicalTree(e);
_tokenBindingsDisposable = new CompositeDisposable();
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, MarginToAnchorProperty, SharedTokenKey.MarginXXS));
BindUtils.RelayBind(this, AnchorTargetProperty, _flyoutStateHelper, FlyoutStateHelper.AnchorTargetProperty);
BindUtils.RelayBind(this, FlyoutProperty, _flyoutStateHelper, FlyoutStateHelper.FlyoutProperty);
BindUtils.RelayBind(this, MouseEnterDelayProperty, _flyoutStateHelper,
FlyoutStateHelper.MouseEnterDelayProperty);
BindUtils.RelayBind(this, MouseLeaveDelayProperty, _flyoutStateHelper,
FlyoutStateHelper.MouseLeaveDelayProperty);
BindUtils.RelayBind(this, TriggerProperty, _flyoutStateHelper, FlyoutStateHelper.TriggerTypeProperty);
SetupFlyoutProperties();
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
@@ -214,7 +203,16 @@ public class FlyoutHost : Control,
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
BindUtils.RelayBind(this, AnchorTargetProperty, _flyoutStateHelper, FlyoutStateHelper.AnchorTargetProperty);
BindUtils.RelayBind(this, FlyoutProperty, _flyoutStateHelper, FlyoutStateHelper.FlyoutProperty);
BindUtils.RelayBind(this, MouseEnterDelayProperty, _flyoutStateHelper,
FlyoutStateHelper.MouseEnterDelayProperty);
BindUtils.RelayBind(this, MouseLeaveDelayProperty, _flyoutStateHelper,
FlyoutStateHelper.MouseLeaveDelayProperty);
BindUtils.RelayBind(this, TriggerProperty, _flyoutStateHelper, FlyoutStateHelper.TriggerTypeProperty);
SetupFlyoutProperties();
_flyoutStateHelper.NotifyAttachedToVisualTree();
this.AddTokenBindingDisposable(TokenResourceBinder.CreateTokenBinding(this, MarginToAnchorProperty, SharedTokenKey.MarginXXS));
}
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+8 -10
View File
@@ -113,12 +113,6 @@ public class TextBox : AvaloniaTextBox,
this.RegisterResources();
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
SetupEffectiveShowClearButton();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
@@ -130,13 +124,11 @@ public class TextBox : AvaloniaTextBox,
{
SetupEffectiveShowClearButton();
}
if (change.Property == StatusProperty)
else if (change.Property == StatusProperty)
{
UpdatePseudoClasses();
}
if (change.Property == InnerLeftContentProperty ||
else if (change.Property == InnerLeftContentProperty ||
change.Property == InnerRightContentProperty)
{
if (change.OldValue is Control oldControl)
@@ -179,4 +171,10 @@ public class TextBox : AvaloniaTextBox,
base.OnDetachedFromLogicalTree(e);
this.DisposeTokenBindings();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
SetupEffectiveShowClearButton();
}
}
@@ -70,4 +70,10 @@ public class ListBoxItem : AvaloniaListBoxItem
}
}
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
SetupTransitions();
}
}
+17 -37
View File
@@ -7,11 +7,11 @@ using Avalonia;
using Avalonia.Animation;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
using Avalonia.Media.Transformation;
using Avalonia.Styling;
using Avalonia.VisualTree;
namespace AtomUI.Controls;
@@ -122,7 +122,7 @@ public class LoadingIndicator : TemplatedControl,
get => _indicatorAngle;
set => SetAndRaise(IndicatorAngleProperty, ref _indicatorAngle, value);
}
Control IControlSharedTokenResourcesHost.HostControl => this;
string IControlSharedTokenResourcesHost.TokenId => LoadingIndicatorToken.ID;
@@ -130,8 +130,8 @@ public class LoadingIndicator : TemplatedControl,
private Animation? _animation;
private TextBlock? _loadingText;
private Canvas? _mainContainer;
private RenderInfo? _renderInfo;
private ContentPresenter? _customIndicatorIconPresenter;
private CancellationTokenSource? _cancellationTokenSource;
internal const double LARGE_INDICATOR_SIZE = 48;
@@ -154,7 +154,7 @@ public class LoadingIndicator : TemplatedControl,
{
this.RegisterResources();
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
@@ -173,60 +173,40 @@ public class LoadingIndicator : TemplatedControl,
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (this.IsAttachedToVisualTree())
if (e.Property == CustomIndicatorIconProperty)
{
if (e.Property == CustomIndicatorIconProperty)
if (e.OldValue is Icon oldIcon)
{
var oldCustomIcon = e.GetOldValue<Icon?>();
if (oldCustomIcon is not null)
{
_mainContainer?.Children.Remove(oldCustomIcon);
}
oldIcon.SetTemplatedParent(null);
}
SetupCustomIndicator();
if (e.NewValue is Icon newIcon)
{
newIcon.SetTemplatedParent(this);
}
}
if (e.Property == IndicatorAngleProperty)
{
if (CustomIndicatorIcon is not null)
{
HandleIndicatorAngleChanged();
}
HandleIndicatorAngleChanged();
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
HandleTemplateApplied(e.NameScope);
}
private void HandleTemplateApplied(INameScope scope)
{
_mainContainer = scope.Find<Canvas>(LoadingIndicatorTheme.MainContainerPart);
_loadingText = scope.Find<TextBlock>(LoadingIndicatorTheme.LoadingTextPart);
SetupCustomIndicator();
_loadingText = e.NameScope.Find<TextBlock>(LoadingIndicatorTheme.LoadingTextPart);
_customIndicatorIconPresenter =
e.NameScope.Find<ContentPresenter>(LoadingIndicatorTheme.CustomIndicatorIconPresenterPart);
}
// 只在使用自定义的 Icon 的时候有效
private void HandleIndicatorAngleChanged()
{
if (CustomIndicatorIcon is not null)
if (_customIndicatorIconPresenter is not null && _customIndicatorIconPresenter.IsVisible)
{
var builder = new TransformOperations.Builder(1);
builder.AppendRotate(MathUtils.Deg2Rad(IndicatorAngle));
CustomIndicatorIcon.RenderTransform = builder.Build();
}
}
private void SetupCustomIndicator()
{
if (CustomIndicatorIcon is not null)
{
CustomIndicatorIcon.SetTemplatedParent(this);
_mainContainer?.Children.Insert(0, CustomIndicatorIcon);
_customIndicatorIconPresenter.RenderTransform = builder.Build();
}
}
@@ -3,8 +3,11 @@ using AtomUI.Theme;
using AtomUI.Theme.Styling;
using Avalonia.Animation.Easings;
using Avalonia.Controls;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Layout;
using Avalonia.Styling;
@@ -15,6 +18,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
{
public const string MainContainerPart = "PART_MainContainer";
public const string LoadingTextPart = "PART_LoadingText";
public const string CustomIndicatorIconPresenterPart = "PART_CustomIndicatorIconPresenter";
public LoadingIndicatorTheme()
: base(typeof(LoadingIndicator))
@@ -25,6 +29,17 @@ internal class LoadingIndicatorTheme : BaseControlTheme
{
return new FuncControlTemplate<LoadingIndicator>((indicator, scope) =>
{
var customIndicatorIconPresenter = new ContentPresenter()
{
Name = CustomIndicatorIconPresenterPart,
};
CreateTemplateParentBinding(customIndicatorIconPresenter, ContentPresenter.ContentProperty,
LoadingIndicator.CustomIndicatorIconProperty);
CreateTemplateParentBinding(customIndicatorIconPresenter, ContentPresenter.IsVisibleProperty,
LoadingIndicator.CustomIndicatorIconProperty,
BindingMode.Default,
ObjectConverters.IsNotNull);
customIndicatorIconPresenter.RegisterInNameScope(scope);
var loadingText = new TextBlock()
{
Name = LoadingTextPart,
@@ -37,6 +52,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
{
Name = MainContainerPart
};
mainContainer.Children.Add(customIndicatorIconPresenter);
mainContainer.Children.Add(loadingText);
mainContainer.RegisterInNameScope(scope);
return mainContainer;
@@ -49,7 +65,8 @@ internal class LoadingIndicatorTheme : BaseControlTheme
commonStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Left);
commonStyle.Add(Layoutable.VerticalAlignmentProperty, VerticalAlignment.Top);
commonStyle.Add(TemplatedControl.FontSizeProperty, SharedTokenKey.FontSize);
commonStyle.Add(LoadingIndicator.MotionEasingCurveProperty, new SetterValueFactory<Easing>(() => new LinearEasing()));
commonStyle.Add(LoadingIndicator.MotionEasingCurveProperty,
new SetterValueFactory<Easing>(() => new LinearEasing()));
commonStyle.Add(LoadingIndicator.MotionDurationProperty, LoadingIndicatorTokenKey.IndicatorDuration);
commonStyle.Add(LoadingIndicator.DotBgBrushProperty, SharedTokenKey.ColorPrimary);
commonStyle.Add(LoadingIndicator.IndicatorTextMarginProperty, SharedTokenKey.MarginXXS);
@@ -63,7 +80,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
private void BuildCustomIconStyle()
{
var customIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
var customIconStyle = new Style(selector => selector.Nesting().Template().Name(CustomIndicatorIconPresenterPart).Descendant().OfType<Icon>());
customIconStyle.Add(Icon.IconModeProperty, IconMode.Normal);
customIconStyle.Add(Layoutable.VerticalAlignmentProperty, VerticalAlignment.Center);
customIconStyle.Add(Layoutable.HorizontalAlignmentProperty, HorizontalAlignment.Center);
@@ -71,7 +88,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
var largeSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Large));
var largeIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
var largeIconStyle = new Style(selector => selector.Nesting().Template().Name(CustomIndicatorIconPresenterPart).Descendant().OfType<Icon>());
largeIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.LARGE_INDICATOR_SIZE);
largeIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.LARGE_INDICATOR_SIZE);
largeSizeStyle.Add(largeIconStyle);
@@ -79,7 +96,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
var middleSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Middle));
var middleIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
var middleIconStyle = new Style(selector => selector.Nesting().Template().Name(CustomIndicatorIconPresenterPart).Descendant().OfType<Icon>());
middleIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.MIDDLE_INDICATOR_SIZE);
middleIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.MIDDLE_INDICATOR_SIZE);
middleSizeStyle.Add(middleIconStyle);
@@ -87,7 +104,7 @@ internal class LoadingIndicatorTheme : BaseControlTheme
var smallSizeStyle = new Style(selector =>
selector.Nesting().PropertyEquals(LoadingIndicator.SizeTypeProperty, SizeType.Small));
var smallIconStyle = new Style(selector => selector.Nesting().Template().OfType<Icon>());
var smallIconStyle = new Style(selector => selector.Nesting().Template().Name(CustomIndicatorIconPresenterPart).Descendant().OfType<Icon>());
smallIconStyle.Add(Layoutable.WidthProperty, LoadingIndicator.SMALL_INDICATOR_SIZE);
smallIconStyle.Add(Layoutable.HeightProperty, LoadingIndicator.SMALL_INDICATOR_SIZE);
smallSizeStyle.Add(smallIconStyle);