mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-30 02:47:45 +08:00
完成 ArrowDecoratedBox 风格化改造
This commit is contained in:
parent
1f17287cdb
commit
a7726f4f58
@ -94,6 +94,8 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
public static readonly StyledProperty<Control?> ChildProperty =
|
public static readonly StyledProperty<Control?> ChildProperty =
|
||||||
Border.ChildProperty.AddOwner<ArrowDecoratedBox>();
|
Border.ChildProperty.AddOwner<ArrowDecoratedBox>();
|
||||||
|
|
||||||
|
internal static readonly StyledProperty<double> ArrowSizeProperty
|
||||||
|
= AvaloniaProperty.Register<ArrowDecoratedBox, double>(nameof(ArrowSize));
|
||||||
|
|
||||||
// 指针最顶点位置
|
// 指针最顶点位置
|
||||||
// 相对坐标
|
// 相对坐标
|
||||||
@ -117,6 +119,15 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
get => GetValue(ArrowPositionProperty);
|
get => GetValue(ArrowPositionProperty);
|
||||||
set => SetValue(ArrowPositionProperty, value);
|
set => SetValue(ArrowPositionProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 箭头的大小
|
||||||
|
/// </summary>
|
||||||
|
internal double ArrowSize
|
||||||
|
{
|
||||||
|
get => GetValue(ArrowSizeProperty);
|
||||||
|
set => SetValue(ArrowSizeProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the decorated control.
|
/// Gets or sets the decorated control.
|
||||||
@ -133,8 +144,6 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
private Geometry? _arrowGeometry;
|
private Geometry? _arrowGeometry;
|
||||||
private Rect _contentRect;
|
private Rect _contentRect;
|
||||||
private Rect _arrowRect;
|
private Rect _arrowRect;
|
||||||
private Border? _container;
|
|
||||||
private CompositeDisposable? _compositeDisposable;
|
|
||||||
private bool _needGenerateArrowVertexPoint = true;
|
private bool _needGenerateArrowVertexPoint = true;
|
||||||
|
|
||||||
static ArrowDecoratedBox()
|
static ArrowDecoratedBox()
|
||||||
@ -171,27 +180,6 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnAttachedToLogicalTree(e);
|
|
||||||
if (!_initialized) {
|
|
||||||
_customStyle.SetupUI();
|
|
||||||
SetupRelayProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnAttachedToVisualTree(e);
|
|
||||||
SetupRelayProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
|
||||||
{
|
|
||||||
base.OnDetachedFromVisualTree(e);
|
|
||||||
_compositeDisposable?.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnPropertyChanged(e);
|
base.OnPropertyChanged(e);
|
||||||
@ -208,54 +196,20 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
return GetContentRect(DesiredSize).Deflate(0.5);
|
return GetContentRect(DesiredSize).Deflate(0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
#region IControlCustomStyle 实现
|
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||||
|
{
|
||||||
// 组件的 Token 绑定属性
|
base.OnApplyTemplate(e);
|
||||||
private double _arrowSize;
|
_customStyle.HandleTemplateApplied(e.NameScope);
|
||||||
|
}
|
||||||
private static readonly DirectProperty<ArrowDecoratedBox, double> ArrowSizeTokenProperty
|
|
||||||
= AvaloniaProperty.RegisterDirect<ArrowDecoratedBox, double>(nameof(_arrowSize),
|
void IControlCustomStyle.HandleTemplateApplied(INameScope scope)
|
||||||
(o) => o._arrowSize,
|
|
||||||
(o, v) => o._arrowSize = v);
|
|
||||||
// 组件的 Token 绑定属性
|
|
||||||
|
|
||||||
void IControlCustomStyle.SetupUI()
|
|
||||||
{
|
{
|
||||||
_container = new Border();
|
|
||||||
_customStyle.SetupTokenBindings();
|
|
||||||
if (IsShowArrow) {
|
if (IsShowArrow) {
|
||||||
BuildGeometry(true);
|
BuildGeometry(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
LogicalChildren.Add(_container);
|
|
||||||
VisualChildren.Add(_container);
|
|
||||||
|
|
||||||
BindUtils.CreateTokenBinding(this, BackgroundProperty, GlobalResourceKey.ColorBgContainer);
|
|
||||||
_initialized = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void SetupRelayProperties()
|
|
||||||
{
|
|
||||||
_compositeDisposable = new CompositeDisposable();
|
|
||||||
// 生命周期一样,可以不用管理
|
|
||||||
if (_container is not null) {
|
|
||||||
if (Child?.Parent is not null) {
|
|
||||||
UIStructureUtils.ClearLogicalParentRecursive(Child, null);
|
|
||||||
UIStructureUtils.ClearVisualParentRecursive(Child, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
_compositeDisposable.Add(BindUtils.RelayBind(this, BackgroundSizingProperty, _container));
|
|
||||||
_compositeDisposable.Add(BindUtils.RelayBind(this, BackgroundProperty, _container));
|
|
||||||
_compositeDisposable.Add(BindUtils.RelayBind(this, CornerRadiusProperty, _container));
|
|
||||||
_compositeDisposable.Add(BindUtils.RelayBind(this, ChildProperty, _container));
|
|
||||||
_compositeDisposable.Add(BindUtils.RelayBind(this, PaddingProperty, _container));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IControlCustomStyle.SetupTokenBindings()
|
|
||||||
{
|
|
||||||
NotifySetupTokenBindings();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#region IControlCustomStyle 实现
|
||||||
|
|
||||||
private (double, double) GetArrowVertexPoint()
|
private (double, double) GetArrowVertexPoint()
|
||||||
{
|
{
|
||||||
@ -272,7 +226,7 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
{
|
{
|
||||||
if (e.Property == IsShowArrowProperty ||
|
if (e.Property == IsShowArrowProperty ||
|
||||||
e.Property == ArrowPositionProperty ||
|
e.Property == ArrowPositionProperty ||
|
||||||
e.Property == ArrowSizeTokenProperty ||
|
e.Property == ArrowSizeProperty ||
|
||||||
e.Property == VisualParentProperty) {
|
e.Property == VisualParentProperty) {
|
||||||
if (e.Property == IsShowArrowProperty && VisualRoot is null) {
|
if (e.Property == IsShowArrowProperty && VisualRoot is null) {
|
||||||
// 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下
|
// 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下
|
||||||
@ -289,40 +243,32 @@ public class ArrowDecoratedBox : TemplatedControl,
|
|||||||
private void BuildGeometry(bool force = false)
|
private void BuildGeometry(bool force = false)
|
||||||
{
|
{
|
||||||
if (_arrowGeometry is null || force) {
|
if (_arrowGeometry is null || force) {
|
||||||
_arrowGeometry = CommonShapeBuilder.BuildArrow(_arrowSize, 1.5);
|
_arrowGeometry = CommonShapeBuilder.BuildArrow(ArrowSize, 1.5);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void NotifySetupTokenBindings()
|
|
||||||
{
|
|
||||||
BindUtils.CreateTokenBinding(this, MinHeightProperty, GlobalResourceKey.ControlHeight);
|
|
||||||
BindUtils.CreateTokenBinding(this, PaddingProperty, GlobalResourceKey.PaddingXS);
|
|
||||||
BindUtils.CreateTokenBinding(this, ArrowSizeTokenProperty, ArrowDecoratedBoxResourceKey.ArrowSize);
|
|
||||||
BindUtils.CreateTokenBinding(this, CornerRadiusProperty, GlobalResourceKey.BorderRadius);
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed override void Render(DrawingContext context)
|
public sealed override void Render(DrawingContext context)
|
||||||
{
|
{
|
||||||
if (IsShowArrow) {
|
if (IsShowArrow) {
|
||||||
var direction = GetDirection(ArrowPosition);
|
var direction = GetDirection(ArrowPosition);
|
||||||
var matrix = Matrix.CreateTranslation(-_arrowSize / 2, -_arrowSize / 2);
|
var matrix = Matrix.CreateTranslation(-ArrowSize / 2, -ArrowSize / 2);
|
||||||
|
|
||||||
if (direction == Direction.Right) {
|
if (direction == Direction.Right) {
|
||||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(90));
|
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(90));
|
||||||
matrix *= Matrix.CreateTranslation(_arrowSize / 2, _arrowSize / 2);
|
matrix *= Matrix.CreateTranslation(ArrowSize / 2, ArrowSize / 2);
|
||||||
} else if (direction == Direction.Top) {
|
} else if (direction == Direction.Top) {
|
||||||
matrix *= Matrix.CreateTranslation(_arrowSize / 2, 0);
|
matrix *= Matrix.CreateTranslation(ArrowSize / 2, 0);
|
||||||
} else if (direction == Direction.Left) {
|
} else if (direction == Direction.Left) {
|
||||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(-90));
|
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(-90));
|
||||||
matrix *= Matrix.CreateTranslation(0, _arrowSize / 2);
|
matrix *= Matrix.CreateTranslation(0, ArrowSize / 2);
|
||||||
} else {
|
} else {
|
||||||
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(180));
|
matrix *= Matrix.CreateRotation(MathUtils.Deg2Rad(180));
|
||||||
matrix *= Matrix.CreateTranslation(_arrowSize / 2, _arrowSize / 2);
|
matrix *= Matrix.CreateTranslation(ArrowSize / 2, ArrowSize / 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
matrix *= Matrix.CreateTranslation(_arrowRect.X, _arrowRect.Y);
|
matrix *= Matrix.CreateTranslation(_arrowRect.X, _arrowRect.Y);
|
||||||
_arrowGeometry!.Transform = new MatrixTransform(matrix);
|
_arrowGeometry!.Transform = new MatrixTransform(matrix);
|
||||||
context.DrawGeometry(_container?.Background, null, _arrowGeometry);
|
context.DrawGeometry(Background, null, _arrowGeometry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using AtomUI.TokenSystem;
|
using AtomUI.TokenSystem;
|
||||||
|
using Avalonia;
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
@ -12,6 +13,11 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public double ArrowSize { get; set; }
|
public double ArrowSize { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 默认的内边距
|
||||||
|
/// </summary>
|
||||||
|
public Thickness Padding { get; set; }
|
||||||
|
|
||||||
public ArrowDecoratedBoxToken()
|
public ArrowDecoratedBoxToken()
|
||||||
: base(ID)
|
: base(ID)
|
||||||
{
|
{
|
||||||
@ -21,5 +27,6 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
|
|||||||
{
|
{
|
||||||
base.CalculateFromAlias();
|
base.CalculateFromAlias();
|
||||||
ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3;
|
ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3;
|
||||||
|
Padding = new Thickness(_globalToken.PaddingXS);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -158,7 +158,7 @@ public class Flyout : PopupFlyoutBase
|
|||||||
{
|
{
|
||||||
var presenter = new FlyoutPresenter
|
var presenter = new FlyoutPresenter
|
||||||
{
|
{
|
||||||
[!Border.ChildProperty] = this[!ContentProperty]
|
[!FlyoutPresenter.ChildProperty] = this[!ContentProperty]
|
||||||
};
|
};
|
||||||
BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, presenter, IsShowArrowProperty);
|
BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, presenter, IsShowArrowProperty);
|
||||||
SetupArrowPosition(AtomPopup, presenter);
|
SetupArrowPosition(AtomPopup, presenter);
|
||||||
|
@ -4,7 +4,9 @@ using Avalonia.LogicalTree;
|
|||||||
namespace AtomUI.Controls;
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
public class FlyoutPresenter : ArrowDecoratedBox
|
public class FlyoutPresenter : ArrowDecoratedBox
|
||||||
{
|
{
|
||||||
|
// 我们在这里并没有增加任何元素或者样式
|
||||||
|
protected override Type StyleKeyOverride => typeof(ArrowDecoratedBox);
|
||||||
protected override void OnKeyDown(KeyEventArgs e)
|
protected override void OnKeyDown(KeyEventArgs e)
|
||||||
{
|
{
|
||||||
if (e.Key == Key.Escape)
|
if (e.Key == Key.Escape)
|
||||||
|
20
src/AtomUI.Controls/Flyouts/FlyoutPresenterTheme.cs
Normal file
20
src/AtomUI.Controls/Flyouts/FlyoutPresenterTheme.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using AtomUI.Styling;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
|
||||||
|
namespace AtomUI.Controls;
|
||||||
|
|
||||||
|
[ControlThemeProvider]
|
||||||
|
public class FlyoutPresenterTheme : ControlTheme
|
||||||
|
{
|
||||||
|
public FlyoutPresenterTheme() : base(typeof(FlyoutPresenter)) {}
|
||||||
|
|
||||||
|
protected override IControlTemplate? BuildControlTemplate()
|
||||||
|
{
|
||||||
|
return new FuncControlTemplate<FlyoutPresenter>(((presenter, scope) =>
|
||||||
|
{
|
||||||
|
Console.WriteLine("xxxxxxxxxxxxxx");
|
||||||
|
return new Panel();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +0,0 @@
|
|||||||
using Avalonia.Controls;
|
|
||||||
|
|
||||||
namespace AtomUI.Controls;
|
|
||||||
|
|
||||||
public class InfoFlyout : PopupFlyoutBase
|
|
||||||
{
|
|
||||||
protected override Control CreatePresenter()
|
|
||||||
{
|
|
||||||
return default!;
|
|
||||||
}
|
|
||||||
}
|
|
@ -18,6 +18,7 @@ namespace AtomUI.Styling
|
|||||||
public static class ArrowDecoratedBoxResourceKey
|
public static class ArrowDecoratedBoxResourceKey
|
||||||
{
|
{
|
||||||
public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize");
|
public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize");
|
||||||
|
public static readonly TokenResourceKey Padding = new TokenResourceKey("ArrowDecoratedBox.Padding");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BadgeResourceKey
|
public static class BadgeResourceKey
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using AtomUI.TokenSystem;
|
using AtomUI.TokenSystem;
|
||||||
using Avalonia;
|
using Avalonia;
|
||||||
|
using Avalonia.Data;
|
||||||
using Avalonia.Markup.Xaml.MarkupExtensions;
|
using Avalonia.Markup.Xaml.MarkupExtensions;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user