mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-30 02:47:45 +08:00
完成 Empty 控件改造
This commit is contained in:
parent
b73611f5c4
commit
f91f2e6b7f
@ -31,6 +31,23 @@ public static class BindUtils
|
||||
return target.Bind(targetProperty, descriptor);
|
||||
}
|
||||
|
||||
public static IDisposable RelayBind<TSource, TResult>(AvaloniaObject source, AvaloniaProperty<TSource> sourceProperty,
|
||||
AvaloniaObject target, AvaloniaProperty<TResult> targetProperty,
|
||||
Func<TSource, TResult> converter,
|
||||
BindingPriority priority = BindingPriority.Template)
|
||||
{
|
||||
var registry = AvaloniaPropertyRegistry.Instance;
|
||||
if (!registry.IsRegistered(source.GetType(), sourceProperty)) {
|
||||
throw new ArgumentException($"Relay source property is not registered for: {source.GetType().Name}.");
|
||||
}
|
||||
|
||||
if (!registry.IsRegistered(target.GetType(), targetProperty)) {
|
||||
throw new ArgumentException($"Relay target property is not registered for: {target.GetType().Name}.");
|
||||
}
|
||||
|
||||
return target.Bind(targetProperty, source.GetObservable(sourceProperty, converter), priority);
|
||||
}
|
||||
|
||||
public static IDisposable CreateTokenBinding(AvaloniaObject target,
|
||||
AvaloniaProperty targetProperty,
|
||||
string resourceKey)
|
||||
|
@ -96,7 +96,6 @@ public class Alert : TemplatedControl, IControlCustomStyle
|
||||
|
||||
private readonly IControlCustomStyle _customStyle;
|
||||
private readonly ControlTokenBinder _controlTokenBinder;
|
||||
private bool _initialized = false;
|
||||
|
||||
private bool _scalingAwareConfigApplied = false;
|
||||
|
||||
@ -120,15 +119,6 @@ public class Alert : TemplatedControl, IControlCustomStyle
|
||||
_customStyle.InitOnConstruct();
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
if (!_initialized) {
|
||||
_customStyle.SetupUi();
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
@ -169,7 +159,7 @@ public class Alert : TemplatedControl, IControlCustomStyle
|
||||
|
||||
void IControlCustomStyle.HandlePropertyChangedForStyle(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
if (_initialized) {
|
||||
if (VisualRoot is not null) {
|
||||
if (e.Property == IsClosableProperty) {
|
||||
SetupCloseButton();
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ internal class AlertTheme : ControlTheme
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildStyles()
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
BuildAlertTypeStyle();
|
||||
BuildMessageLabelStyle();
|
||||
@ -196,7 +196,7 @@ internal class AlertTheme : ControlTheme
|
||||
}
|
||||
}
|
||||
|
||||
public override void BuildControlTemplate()
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
var controlTemplate = new FuncControlTemplate<Alert>((alert, scope) =>
|
||||
{
|
||||
@ -253,9 +253,8 @@ internal class AlertTheme : ControlTheme
|
||||
|
||||
return borderContainer;
|
||||
});
|
||||
|
||||
var setter = new Setter(TemplatedControl.TemplateProperty, controlTemplate);
|
||||
Add(setter);
|
||||
|
||||
return controlTemplate;
|
||||
}
|
||||
|
||||
private Border CreateBorderContainer(Alert alert, INameScope scope)
|
||||
|
@ -12,7 +12,7 @@ public class CheckBoxTheme : ControlTheme
|
||||
{
|
||||
}
|
||||
|
||||
public override void BuildStyles()
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
Add(new Setter(CheckBox.CheckIndicatorSizeProperty, new DynamicResourceExtension(CheckBoxResourceKey.CheckIndicatorSize)));
|
||||
Add(new Setter(CheckBox.PaddingInlineProperty, new DynamicResourceExtension(GlobalResourceKey.PaddingXS)));
|
||||
|
@ -1,12 +1,10 @@
|
||||
using AtomUI.ColorSystem;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Documents;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
@ -17,7 +15,7 @@ public enum PresetEmptyImage
|
||||
Default,
|
||||
}
|
||||
|
||||
public partial class EmptyIndicator : Control,
|
||||
public partial class EmptyIndicator : TemplatedControl,
|
||||
IControlCustomStyle
|
||||
|
||||
{
|
||||
@ -96,42 +94,7 @@ public partial class EmptyIndicator : Control,
|
||||
_customStyle = this;
|
||||
_controlTokenBinder = new ControlTokenBinder(this, EmptyIndicatorToken.ID);
|
||||
}
|
||||
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
if (!_initialized) {
|
||||
_customStyle.SetupUi();
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (_initialized) {
|
||||
if (change.Property == SizeTypeProperty) {
|
||||
HandleSizeTypeChanged();
|
||||
} else if (change.Property == DescriptionMarginProperty) {
|
||||
_description!.Margin = new Thickness(0, _descriptionMargin, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void HandleSizeTypeChanged()
|
||||
{
|
||||
_customStyle.ApplySizeTypeStyleConfig();
|
||||
if (_svg is not null) {
|
||||
if (SizeType == SizeType.Large) {
|
||||
_svg.Height = _emptyImgHeightToken;
|
||||
} else if (SizeType == SizeType.Middle) {
|
||||
_svg.Height = _emptyImgHeightMDToken;
|
||||
} else {
|
||||
_svg.Height = _emptyImgHeightSMToken;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void CheckImageSource()
|
||||
{
|
||||
var imageSettedCount = 0;
|
||||
@ -163,18 +126,6 @@ public partial class EmptyIndicator : Control,
|
||||
_controlTokenBinder.AddControlBinding(ColorFillTertiaryTokenProperty, GlobalResourceKey.ColorFillTertiary);
|
||||
_controlTokenBinder.AddControlBinding(ColorFillQuaternaryTokenProperty, GlobalResourceKey.ColorFillQuaternary);
|
||||
_controlTokenBinder.AddControlBinding(ColorBgContainerTokenProperty, GlobalResourceKey.ColorBgContainer);
|
||||
_controlTokenBinder.AddControlBinding(_description!, TextElement.ForegroundProperty,
|
||||
GlobalResourceKey.ColorTextDescription);
|
||||
}
|
||||
|
||||
void IControlCustomStyle.ApplySizeTypeStyleConfig()
|
||||
{
|
||||
if (SizeType == SizeType.Small ||
|
||||
SizeType == SizeType.Middle) {
|
||||
_controlTokenBinder.AddControlBinding(DescriptionMarginProperty, GlobalResourceKey.MarginXS);
|
||||
} else {
|
||||
_controlTokenBinder.AddControlBinding(DescriptionMarginProperty, GlobalResourceKey.MarginSM);
|
||||
}
|
||||
}
|
||||
|
||||
void IControlCustomStyle.SetupUi()
|
||||
@ -182,31 +133,6 @@ public partial class EmptyIndicator : Control,
|
||||
HorizontalAlignment = HorizontalAlignment.Center;
|
||||
VerticalAlignment = VerticalAlignment.Center;
|
||||
CheckImageSource();
|
||||
_layout = new StackPanel()
|
||||
{
|
||||
Orientation = Orientation.Vertical
|
||||
};
|
||||
|
||||
LogicalChildren.Add(_layout);
|
||||
VisualChildren.Add(_layout);
|
||||
|
||||
_svg = new Avalonia.Svg.Svg(new Uri("https://github.com/avaloniaui"));
|
||||
_layout.Children.Add(_svg);
|
||||
_description = new TextBlock()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Text = Description ?? "No data"
|
||||
};
|
||||
BindUtils.RelayBind(this, IsShowDescriptionProperty, _description, TextBlock.IsVisibleProperty);
|
||||
|
||||
_layout.Children.Add(_description);
|
||||
_customStyle.ApplyFixedStyleConfig();
|
||||
_customStyle.ApplySizeTypeStyleConfig();
|
||||
|
||||
_description.Margin = new Thickness(0, _descriptionMargin, 0, 0);
|
||||
SetupImage();
|
||||
HandleSizeTypeChanged();
|
||||
}
|
||||
|
||||
private void SetupImage()
|
||||
@ -234,6 +160,19 @@ public partial class EmptyIndicator : Control,
|
||||
_svg.Path = ImagePath;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
_customStyle.ApplyFixedStyleConfig();
|
||||
_customStyle.HandleTemplateApplied(e.NameScope);
|
||||
}
|
||||
|
||||
void IControlCustomStyle.HandleTemplateApplied(INameScope scope)
|
||||
{
|
||||
_svg = scope.Find<Avalonia.Svg.Svg>(EmptyIndicatorTheme.SvgImagePart);
|
||||
SetupImage();
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
@ -5,12 +5,15 @@ namespace AtomUI.Controls;
|
||||
|
||||
public partial class EmptyIndicator
|
||||
{
|
||||
private double _descriptionMargin;
|
||||
private static readonly DirectProperty<EmptyIndicator, double> DescriptionMarginProperty =
|
||||
AvaloniaProperty.RegisterDirect<EmptyIndicator, double>(
|
||||
nameof(_descriptionMargin),
|
||||
o => o._descriptionMargin,
|
||||
(o, v) => o._descriptionMargin = v);
|
||||
internal static readonly StyledProperty<double> DescriptionMarginProperty =
|
||||
AvaloniaProperty.Register<EmptyIndicator, double>(
|
||||
nameof(DescriptionMargin));
|
||||
|
||||
internal double DescriptionMargin
|
||||
{
|
||||
get => GetValue(DescriptionMarginProperty);
|
||||
set => SetValue(DescriptionMarginProperty, value);
|
||||
}
|
||||
|
||||
#region Control token 值绑定属性
|
||||
|
||||
|
96
src/AtomUI.Controls/EmptyIndicator/EmptyIndicatorTheme.cs
Normal file
96
src/AtomUI.Controls/EmptyIndicator/EmptyIndicatorTheme.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using AtomUI.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
public class EmptyIndicatorTheme : ControlTheme
|
||||
{
|
||||
public const string SvgImagePart = "PART_SvgImage";
|
||||
|
||||
public EmptyIndicatorTheme()
|
||||
: base(typeof(EmptyIndicator))
|
||||
{}
|
||||
|
||||
protected override IControlTemplate? BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<EmptyIndicator>((indicator, scope) =>
|
||||
{
|
||||
var layout = new StackPanel()
|
||||
{
|
||||
Orientation = Orientation.Vertical
|
||||
};
|
||||
|
||||
var svg = new Avalonia.Svg.Svg(new Uri("https://github.com/avaloniaui"))
|
||||
{
|
||||
Name = SvgImagePart
|
||||
};
|
||||
layout.Children.Add(svg);
|
||||
svg.RegisterInNameScope(scope);
|
||||
|
||||
var description = new TextBlock()
|
||||
{
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
Text = indicator.Description ?? "No data"
|
||||
};
|
||||
|
||||
BindUtils.CreateTokenBinding(description, TextBlock.ForegroundProperty, GlobalResourceKey.ColorTextDescription);
|
||||
BindUtils.RelayBind(indicator, EmptyIndicator.DescriptionMarginProperty, description, TextBlock.MarginProperty,
|
||||
d => new Thickness(0, d, 0, 0));
|
||||
layout.Children.Add(description);
|
||||
|
||||
return layout;
|
||||
});
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
// 设置本身样式
|
||||
var sizeSmallAndMiddleStyle = new Style(selector => Selectors.Or(selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Middle),
|
||||
selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Small)));
|
||||
sizeSmallAndMiddleStyle.Setters.Add(new Setter(EmptyIndicator.DescriptionMarginProperty, new DynamicResourceExtension(GlobalResourceKey.MarginXS)));
|
||||
Add(sizeSmallAndMiddleStyle);
|
||||
|
||||
var sizeLargeStyle = new Style(selector => selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Large));
|
||||
sizeLargeStyle.Setters.Add(new Setter(EmptyIndicator.DescriptionMarginProperty, new DynamicResourceExtension(GlobalResourceKey.MarginSM)));
|
||||
Add(sizeLargeStyle);
|
||||
|
||||
BuildSvgStyle();
|
||||
}
|
||||
|
||||
private void BuildSvgStyle()
|
||||
{
|
||||
var svgSelector = default(Selector).Nesting().Template().OfType<Avalonia.Svg.Svg>();
|
||||
{
|
||||
var largeSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Large));
|
||||
var svgStyle = new Style(selector => svgSelector);
|
||||
svgStyle.Setters.Add(new Setter(Layoutable.HeightProperty, new DynamicResourceExtension(EmptyIndicatorResourceKey.EmptyImgHeight)));
|
||||
largeSizeStyle.Add(svgStyle);
|
||||
Add(largeSizeStyle);
|
||||
}
|
||||
|
||||
{
|
||||
var middleSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Middle));
|
||||
var svgStyle = new Style(selector => svgSelector);
|
||||
svgStyle.Setters.Add(new Setter(Layoutable.HeightProperty, new DynamicResourceExtension(EmptyIndicatorResourceKey.EmptyImgHeightMD)));
|
||||
middleSizeStyle.Add(svgStyle);
|
||||
Add(middleSizeStyle);
|
||||
}
|
||||
|
||||
{
|
||||
var smallSizeStyle = new Style(selector => selector.Nesting().PropertyEquals(EmptyIndicator.SizeTypeProperty, SizeType.Small));
|
||||
var svgStyle = new Style(selector => svgSelector);
|
||||
svgStyle.Setters.Add(new Setter(Layoutable.HeightProperty, new DynamicResourceExtension(EmptyIndicatorResourceKey.EmptyImgHeightSM)));
|
||||
smallSizeStyle.Add(svgStyle);
|
||||
Add(smallSizeStyle);
|
||||
}
|
||||
}
|
||||
}
|
@ -102,7 +102,6 @@ internal static class PopupInterceptorsRegister
|
||||
{
|
||||
public static void Register(Harmony harmony)
|
||||
{
|
||||
Console.WriteLine("Register");
|
||||
RegisterPopupFlyoutBaseCreatePopup(harmony);
|
||||
RegisterPopupUpdateHostPositionPrefix(harmony);
|
||||
RegisterPopupUpdateHostPositionPostfix(harmony);
|
||||
|
@ -1,18 +1,24 @@
|
||||
namespace AtomUI;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI;
|
||||
|
||||
using AvaloniaControlTheme = Avalonia.Styling.ControlTheme;
|
||||
|
||||
public class ControlTheme : AvaloniaControlTheme
|
||||
{
|
||||
public ControlTheme() { }
|
||||
public ControlTheme(Type targetType) : base(targetType) {}
|
||||
|
||||
public void Build()
|
||||
{
|
||||
BuildStyles();
|
||||
BuildControlTemplate();
|
||||
var template = BuildControlTemplate();
|
||||
if (template is not null) {
|
||||
Add(new Setter(TemplatedControl.TemplateProperty, template));
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void BuildControlTemplate() {}
|
||||
public virtual void BuildStyles() {}
|
||||
|
||||
protected virtual IControlTemplate? BuildControlTemplate() { return default; }
|
||||
protected virtual void BuildStyles() {}
|
||||
}
|
Loading…
Reference in New Issue
Block a user