Refactor ArrowDecoratedBox

This commit is contained in:
polarboy 2024-09-19 12:53:14 +08:00
parent e0fb335357
commit 9d219301f2
8 changed files with 148 additions and 133 deletions

View File

@ -23,4 +23,5 @@
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpKeepExistingMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpPlaceEmbeddedOnSameLineMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ECSharpUseContinuousIndentInsideBracesMigration/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002EMemberReordering_002EMigrations_002ECSharpFileLayoutPatternRemoveIsAttributeUpgrade/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary> <s:Boolean x:Key="/Default/Environment/SettingsMigration/IsMigratorApplied/=JetBrains_002EReSharper_002EPsi_002ECSharp_002ECodeStyle_002ESettingsUpgrade_002EMigrateBlankLinesAroundFieldToBlankLinesAroundProperty/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>

View File

@ -117,6 +117,9 @@ public class ArrowDecoratedBox : ContentControl,
internal static readonly StyledProperty<double> ArrowSizeProperty internal static readonly StyledProperty<double> ArrowSizeProperty
= AvaloniaProperty.Register<ArrowDecoratedBox, double>(nameof(ArrowSize)); = AvaloniaProperty.Register<ArrowDecoratedBox, double>(nameof(ArrowSize));
internal static readonly StyledProperty<Direction> ArrowDirectionProperty
= AvaloniaProperty.Register<ArrowDecoratedBox, Direction>(nameof(ArrowDirection));
/// <summary> /// <summary>
/// 箭头的大小 /// 箭头的大小
/// </summary> /// </summary>
@ -125,7 +128,13 @@ public class ArrowDecoratedBox : ContentControl,
get => GetValue(ArrowSizeProperty); get => GetValue(ArrowSizeProperty);
set => SetValue(ArrowSizeProperty, value); set => SetValue(ArrowSizeProperty, value);
} }
internal Direction ArrowDirection
{
get => GetValue(ArrowDirectionProperty);
set => SetValue(ArrowDirectionProperty, value);
}
#endregion #endregion
// 指针最顶点位置 // 指针最顶点位置
@ -133,13 +142,19 @@ public class ArrowDecoratedBox : ContentControl,
private (double, double) _arrowVertexPoint; private (double, double) _arrowVertexPoint;
internal (double, double) ArrowVertexPoint => GetArrowVertexPoint(); internal (double, double) ArrowVertexPoint => GetArrowVertexPoint();
private Geometry? _arrowGeometry; private Geometry? _arrowGeometry;
private Rect _contentRect;
private Rect _arrowRect; private Rect _arrowRect;
private bool _needGenerateArrowVertexPoint = true; private bool _needGenerateArrowVertexPoint = true;
private Border? _contentDecorator;
static ArrowDecoratedBox() static ArrowDecoratedBox()
{ {
AffectsMeasure<ArrowDecoratedBox>(ArrowPositionProperty, IsShowArrowProperty); AffectsMeasure<ArrowDecoratedBox>(IsShowArrowProperty);
}
public ArrowDecoratedBox()
{
IsShowArrow = true;
ArrowPosition = ArrowPosition.BottomEdgeAlignedLeft;
} }
public static Direction GetDirection(ArrowPosition arrowPosition) public static Direction GetDirection(ArrowPosition arrowPosition)
@ -179,17 +194,19 @@ public class ArrowDecoratedBox : ContentControl,
public Rect GetMaskBounds() public Rect GetMaskBounds()
{ {
return GetContentRect(DesiredSize).Deflate(0.5); if (_contentDecorator is not null)
{
return _contentDecorator.Bounds;
}
return Bounds;
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);
HandleTemplateApplied(e.NameScope); _contentDecorator = e.NameScope.Get<Border>(ArrowDecoratedBoxTheme.ContentDecoratorPart);
}
private void HandleTemplateApplied(INameScope scope)
{
if (IsShowArrow) if (IsShowArrow)
{ {
BuildGeometry(true); BuildGeometry(true);
@ -219,14 +236,22 @@ public class ArrowDecoratedBox : ContentControl,
{ {
// 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下 // 当开启的时候,但是还没有加入的渲染树,这个时候我们取不到 Token 需要在取值的时候重新生成一下
_needGenerateArrowVertexPoint = true; _needGenerateArrowVertexPoint = true;
} }
if (VisualRoot is not null) if (VisualRoot is not null)
{ {
BuildGeometry(true); BuildGeometry(true);
_arrowRect = GetArrowRect(DesiredSize); _arrowRect = GetArrowRect(DesiredSize);
InvalidateArrange();
} }
} }
if (e.Property == ArrowPositionProperty)
{
ArrowDirection = GetDirection(ArrowPosition);
}
} }
private void BuildGeometry(bool force = false) private void BuildGeometry(bool force = false)
@ -241,9 +266,10 @@ public class ArrowDecoratedBox : ContentControl,
{ {
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));
@ -263,97 +289,12 @@ public class ArrowDecoratedBox : ContentControl,
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(Background, null, _arrowGeometry); context.DrawGeometry(Background, null, _arrowGeometry);
} }
} }
protected override Size MeasureOverride(Size availableSize)
{
var size = base.MeasureOverride(availableSize);
var targetWidth = size.Width;
var targetHeight = size.Height;
targetHeight = Math.Max(MinHeight, targetHeight);
if (IsShowArrow)
{
BuildGeometry();
var realArrowSize = Math.Min(_arrowGeometry!.Bounds.Size.Height, _arrowGeometry!.Bounds.Size.Width);
var direction = GetDirection(ArrowPosition);
if (direction == Direction.Left || direction == Direction.Right)
{
targetWidth += realArrowSize;
}
else
{
targetHeight += realArrowSize;
}
}
var targetSize = new Size(targetWidth, targetHeight);
_arrowRect = GetArrowRect(targetSize);
return targetSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
var visualChildren = VisualChildren;
var visualCount = visualChildren.Count;
_contentRect = GetContentRect(finalSize);
for (var i = 0; i < visualCount; ++i)
{
var child = visualChildren[i];
if (child is Layoutable layoutable)
{
layoutable.Arrange(_contentRect);
}
}
return finalSize;
}
internal Rect GetContentRect(Size finalSize)
{
var offsetX = 0d;
var offsetY = 0d;
var targetWidth = finalSize.Width;
var targetHeight = finalSize.Height;
if (IsShowArrow)
{
var arrowSize = Math.Min(_arrowGeometry!.Bounds.Size.Height, _arrowGeometry!.Bounds.Size.Width) + 0.5;
var direction = GetDirection(ArrowPosition);
if (direction == Direction.Left || direction == Direction.Right)
{
targetWidth -= arrowSize;
}
else
{
targetHeight -= arrowSize;
}
if (direction == Direction.Right)
{
offsetX = 0.5;
}
else if (direction == Direction.Bottom)
{
offsetY = 0.5;
}
else if (direction == Direction.Top)
{
offsetY = arrowSize - 0.5;
}
else
{
offsetX = arrowSize - 0.5;
}
}
return new Rect(offsetX, offsetY, targetWidth, targetHeight);
}
private Rect GetArrowRect(Size finalSize) private Rect GetArrowRect(Size finalSize)
{ {
var offsetX = 0d; var offsetX = 0d;
@ -371,6 +312,7 @@ public class ArrowDecoratedBox : ContentControl,
position == ArrowPosition.LeftEdgeAlignedTop || position == ArrowPosition.LeftEdgeAlignedTop ||
position == ArrowPosition.LeftEdgeAlignedBottom) position == ArrowPosition.LeftEdgeAlignedBottom)
{ {
offsetX = 0.5d;
targetWidth = minValue; targetWidth = minValue;
targetHeight = maxValue; targetHeight = maxValue;
if (position == ArrowPosition.Left) if (position == ArrowPosition.Left)
@ -404,6 +346,7 @@ public class ArrowDecoratedBox : ContentControl,
position == ArrowPosition.TopEdgeAlignedLeft || position == ArrowPosition.TopEdgeAlignedLeft ||
position == ArrowPosition.TopEdgeAlignedRight) position == ArrowPosition.TopEdgeAlignedRight)
{ {
offsetY = 0.5d;
if (position == ArrowPosition.TopEdgeAlignedLeft) if (position == ArrowPosition.TopEdgeAlignedLeft)
{ {
offsetX = maxValue; offsetX = maxValue;
@ -424,7 +367,7 @@ public class ArrowDecoratedBox : ContentControl,
position == ArrowPosition.RightEdgeAlignedTop || position == ArrowPosition.RightEdgeAlignedTop ||
position == ArrowPosition.RightEdgeAlignedBottom) position == ArrowPosition.RightEdgeAlignedBottom)
{ {
offsetX = finalSize.Width - minValue; offsetX = finalSize.Width - minValue - 1.0d;
if (position == ArrowPosition.Right) if (position == ArrowPosition.Right)
{ {
offsetY = (finalSize.Height - maxValue) / 2; offsetY = (finalSize.Height - maxValue) / 2;
@ -457,7 +400,7 @@ public class ArrowDecoratedBox : ContentControl,
} }
else else
{ {
offsetY = finalSize.Height - minValue; offsetY = finalSize.Height - minValue - 1.0d;
targetWidth = maxValue; targetWidth = maxValue;
targetHeight = minValue; targetHeight = minValue;
if (position == ArrowPosition.BottomEdgeAlignedLeft) if (position == ArrowPosition.BottomEdgeAlignedLeft)

View File

@ -6,6 +6,7 @@ using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Media;
using Avalonia.Styling; using Avalonia.Styling;
namespace AtomUI.Controls; namespace AtomUI.Controls;
@ -13,8 +14,10 @@ namespace AtomUI.Controls;
[ControlThemeProvider] [ControlThemeProvider]
internal class ArrowDecoratedBoxTheme : BaseControlTheme internal class ArrowDecoratedBoxTheme : BaseControlTheme
{ {
public const string DecoratorPart = "PART_Decorator"; public const string ContentDecoratorPart = "PART_ContentDecorator";
public const string ContentLayoutPart = "PART_ContentLayout";
public const string ContentPresenterPart = "PART_ContentPresenter"; public const string ContentPresenterPart = "PART_ContentPresenter";
public const string ArrowContentPart = "PART_ArrowContent";
public ArrowDecoratedBoxTheme() : this(typeof(ArrowDecoratedBox)) public ArrowDecoratedBoxTheme() : this(typeof(ArrowDecoratedBox))
{ {
@ -28,32 +31,48 @@ internal class ArrowDecoratedBoxTheme : BaseControlTheme
{ {
return new FuncControlTemplate<ArrowDecoratedBox>((box, scope) => return new FuncControlTemplate<ArrowDecoratedBox>((box, scope) =>
{ {
var decorator = new Border var contentLayout = new DockPanel()
{ {
Name = DecoratorPart, Name = ContentLayoutPart,
Margin = new Thickness(0) LastChildFill = true
}; };
decorator.RegisterInNameScope(scope); var arrowContent = new Control()
{
decorator.Child = BuildContent(scope); Name = ArrowContentPart
};
CreateTemplateParentBinding(decorator, Border.BackgroundSizingProperty, CreateTemplateParentBinding(arrowContent, Border.IsVisibleProperty,
ArrowDecoratedBox.IsShowArrowProperty);
contentLayout.Children.Add(arrowContent);
arrowContent.RegisterInNameScope(scope);
var content = BuildContent(scope);
var contentDecorator = new Border
{
Name = ContentDecoratorPart,
Margin = new Thickness(0)
};
contentDecorator.RegisterInNameScope(scope);
; CreateTemplateParentBinding(contentDecorator, Border.BackgroundSizingProperty,
TemplatedControl.BackgroundSizingProperty); TemplatedControl.BackgroundSizingProperty);
CreateTemplateParentBinding(decorator, Border.BackgroundProperty, TemplatedControl.BackgroundProperty); CreateTemplateParentBinding(contentDecorator, Border.BackgroundProperty, TemplatedControl.BackgroundProperty);
CreateTemplateParentBinding(decorator, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty); CreateTemplateParentBinding(contentDecorator, Border.CornerRadiusProperty, TemplatedControl.CornerRadiusProperty);
CreateTemplateParentBinding(decorator, Decorator.PaddingProperty, TemplatedControl.PaddingProperty); CreateTemplateParentBinding(contentDecorator, Decorator.PaddingProperty, TemplatedControl.PaddingProperty);
return decorator; contentDecorator.Child = content;
contentLayout.Children.Add(contentDecorator);
return contentLayout;
}); });
} }
protected virtual Control BuildContent(INameScope scope) protected virtual Control BuildContent(INameScope scope)
{ {
var contentPresenter = new ContentPresenter var contentPresenter = new ContentPresenter
{ {
Name = ContentPresenterPart Name = ContentPresenterPart
}; };
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, ContentControl.ContentProperty); CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty, ContentControl.ContentProperty);
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty, CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentTemplateProperty,
ContentControl.ContentTemplateProperty); ContentControl.ContentTemplateProperty);
@ -69,6 +88,43 @@ internal class ArrowDecoratedBoxTheme : BaseControlTheme
commonStyle.Add(TemplatedControl.PaddingProperty, ArrowDecoratedBoxTokenResourceKey.Padding); commonStyle.Add(TemplatedControl.PaddingProperty, ArrowDecoratedBoxTokenResourceKey.Padding);
commonStyle.Add(ArrowDecoratedBox.ArrowSizeProperty, ArrowDecoratedBoxTokenResourceKey.ArrowSize); commonStyle.Add(ArrowDecoratedBox.ArrowSizeProperty, ArrowDecoratedBoxTokenResourceKey.ArrowSize);
commonStyle.Add(TemplatedControl.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius); commonStyle.Add(TemplatedControl.CornerRadiusProperty, GlobalTokenResourceKey.BorderRadius);
BuildArrowDirectionStyle(commonStyle);
Add(commonStyle); Add(commonStyle);
} }
private void BuildArrowDirectionStyle(Style commonStyle)
{
var topDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Top));
{
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Top);
arrowContentStyle.Add(Control.HeightProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
topDirectionStyle.Add(arrowContentStyle);
}
commonStyle.Add(topDirectionStyle);
var rightDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Right));
{
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Right);
arrowContentStyle.Add(Control.WidthProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
rightDirectionStyle.Add(arrowContentStyle);
}
commonStyle.Add(rightDirectionStyle);
var bottomDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Bottom));
{
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Bottom);
arrowContentStyle.Add(Control.HeightProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
bottomDirectionStyle.Add(arrowContentStyle);
}
commonStyle.Add(bottomDirectionStyle);
var leftDirectionStyle = new Style(selector => selector.Nesting().PropertyEquals(ArrowDecoratedBox.ArrowDirectionProperty, Direction.Left));
{
var arrowContentStyle = new Style(selector => selector.Nesting().Template().Name(ArrowContentPart));
arrowContentStyle.Add(DockPanel.DockProperty, Dock.Left);
arrowContentStyle.Add(Control.WidthProperty, ArrowDecoratedBoxTokenResourceKey.ArrowContentThickness);
leftDirectionStyle.Add(arrowContentStyle);
}
commonStyle.Add(leftDirectionStyle);
}
} }

View File

@ -12,6 +12,11 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
/// 箭头三角形大小 /// 箭头三角形大小
/// </summary> /// </summary>
public double ArrowSize { get; set; } public double ArrowSize { get; set; }
/// <summary>
/// 绘制箭头的厚度,跟位置有关
/// </summary>
public double ArrowContentThickness { get; set; }
/// <summary> /// <summary>
/// 默认的内边距 /// 默认的内边距
@ -26,7 +31,8 @@ public class ArrowDecoratedBoxToken : AbstractControlDesignToken
internal override void CalculateFromAlias() internal override void CalculateFromAlias()
{ {
base.CalculateFromAlias(); base.CalculateFromAlias();
ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3; ArrowSize = _globalToken.SeedToken.SizePopupArrow / 1.3;
Padding = new Thickness(_globalToken.PaddingXS); ArrowContentThickness = ArrowSize / 2;
Padding = new Thickness(_globalToken.PaddingXS);
} }
} }

View File

@ -6,6 +6,7 @@ using AtomUI.Utils;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Primitives.PopupPositioning; using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Data;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Metadata; using Avalonia.Metadata;
@ -149,9 +150,9 @@ public class Flyout : PopupFlyoutBase
} }
} }
var placement = Placement; var placement = popup.Placement;
var anchor = PlacementAnchor; var anchor = popup.PlacementAnchor;
var gravity = PlacementGravity; var gravity = popup.PlacementGravity;
if (flyoutPresenter is not null) if (flyoutPresenter is not null)
{ {
@ -178,11 +179,11 @@ public class Flyout : PopupFlyoutBase
protected internal override void NotifyPopupCreated(Popup popup) protected internal override void NotifyPopupCreated(Popup popup)
{ {
base.NotifyPopupCreated(popup); base.NotifyPopupCreated(popup);
BindUtils.RelayBind(this, PlacementProperty, popup, Avalonia.Controls.Primitives.Popup.PlacementProperty); BindUtils.RelayBind(this, PlacementProperty, popup, Popup.PlacementProperty);
BindUtils.RelayBind(this, PlacementAnchorProperty, popup, BindUtils.RelayBind(this, PlacementAnchorProperty, popup,
Avalonia.Controls.Primitives.Popup.PlacementAnchorProperty); Popup.PlacementAnchorProperty);
BindUtils.RelayBind(this, PlacementGravityProperty, popup, BindUtils.RelayBind(this, PlacementGravityProperty, popup,
Avalonia.Controls.Primitives.Popup.PlacementGravityProperty); Popup.PlacementGravityProperty);
BindUtils.RelayBind(this, MaskShadowsProperty, popup, Popup.MaskShadowsProperty); BindUtils.RelayBind(this, MaskShadowsProperty, popup, Popup.MaskShadowsProperty);
SetupArrowPosition(popup); SetupArrowPosition(popup);
} }

View File

@ -167,7 +167,7 @@ public class MenuFlyoutPresenter : MenuBase, IShadowMaskInfoProvider
{ {
if (_arrowDecoratedBox is not null) if (_arrowDecoratedBox is not null)
{ {
var contentRect = _arrowDecoratedBox.GetContentRect(Bounds.Size); var contentRect = _arrowDecoratedBox.GetMaskBounds();
var adjustedPos = _arrowDecoratedBox.TranslatePoint(contentRect.Position, this) ?? default; var adjustedPos = _arrowDecoratedBox.TranslatePoint(contentRect.Position, this) ?? default;
return new Rect(adjustedPos, contentRect.Size); return new Rect(adjustedPos, contentRect.Size);
} }

View File

@ -41,6 +41,7 @@ namespace AtomUI.Theme.Styling
public static class ArrowDecoratedBoxTokenResourceKey public static class ArrowDecoratedBoxTokenResourceKey
{ {
public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize", "AtomUI.Token"); public static readonly TokenResourceKey ArrowSize = new TokenResourceKey("ArrowDecoratedBox.ArrowSize", "AtomUI.Token");
public static readonly TokenResourceKey ArrowContentThickness = new TokenResourceKey("ArrowDecoratedBox.ArrowContentThickness", "AtomUI.Token");
public static readonly TokenResourceKey Padding = new TokenResourceKey("ArrowDecoratedBox.Padding", "AtomUI.Token"); public static readonly TokenResourceKey Padding = new TokenResourceKey("ArrowDecoratedBox.Padding", "AtomUI.Token");
} }

View File

@ -67,6 +67,7 @@ public class Popup : AvaloniaPopup
private bool _initialized; private bool _initialized;
private ManagedPopupPositionerInfo? _managedPopupPositioner; private ManagedPopupPositionerInfo? _managedPopupPositioner;
protected bool _animating; protected bool _animating;
private bool _isNeedFlip = true;
// 当鼠标移走了,但是打开动画还没完成,我们需要记录下来这个信号 // 当鼠标移走了,但是打开动画还没完成,我们需要记录下来这个信号
internal bool RequestCloseWhereAnimationCompleted { get; set; } internal bool RequestCloseWhereAnimationCompleted { get; set; }
@ -147,11 +148,14 @@ public class Popup : AvaloniaPopup
"Unable to create shadow layer, top level for PlacementTarget is null."); "Unable to create shadow layer, top level for PlacementTarget is null.");
} }
if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center) if (_isNeedFlip)
{ {
AdjustPopupHostPosition(placementTarget); if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center)
{
AdjustPopupHostPosition(placementTarget!);
}
} }
if (!_animating) if (!_animating)
{ {
CreateShadowLayer(); CreateShadowLayer();
@ -291,8 +295,6 @@ public class Popup : AvaloniaPopup
/// <summary> /// <summary>
/// 在这里处理翻转问题 /// 在这里处理翻转问题
/// </summary> /// </summary>
/// <param name="popupHost"></param>
/// <param name="placementTarget"></param>
internal void AdjustPopupHostPosition(Control placementTarget) internal void AdjustPopupHostPosition(Control placementTarget)
{ {
var offsetX = HorizontalOffset; var offsetX = HorizontalOffset;
@ -307,8 +309,7 @@ public class Popup : AvaloniaPopup
var direction = PopupUtils.GetDirection(Placement); var direction = PopupUtils.GetDirection(Placement);
var topLevel = TopLevel.GetTopLevel(placementTarget)!; var topLevel = TopLevel.GetTopLevel(placementTarget)!;
if (Placement != PlacementMode.Center && if (Placement != PlacementMode.Center && Placement != PlacementMode.Pointer)
Placement != PlacementMode.Pointer)
{ {
// 计算是否 flip // 计算是否 flip
var parameters = new PopupPositionerParameters(); var parameters = new PopupPositionerParameters();
@ -422,16 +423,22 @@ public class Popup : AvaloniaPopup
_animating = true; _animating = true;
var placementTarget = GetEffectivePlacementTarget();
Open(); Open();
if (Placement != PlacementMode.Pointer && Placement != PlacementMode.Center)
{
AdjustPopupHostPosition(placementTarget!);
_isNeedFlip = false;
}
var popupRoot = (Host as PopupRoot)!; var popupRoot = (Host as PopupRoot)!;
// 获取 popup 的具体位置,这个就是非常准确的位置,还有大小 // 获取 popup 的具体位置,这个就是非常准确的位置,还有大小
// TODO 暂时只支持 WindowBase popup // TODO 暂时只支持 WindowBase popup
popupRoot.Hide(); popupRoot.Hide();
var popupOffset = popupRoot.PlatformImpl!.Position; var popupOffset = popupRoot.PlatformImpl!.Position;
var offset = new Point(popupOffset.X, popupOffset.Y); var offset = new Point(popupOffset.X, popupOffset.Y);
var placementTarget = GetEffectivePlacementTarget(); var topLevel = TopLevel.GetTopLevel(placementTarget);
var topLevel = TopLevel.GetTopLevel(placementTarget); var scaling = topLevel?.RenderScaling ?? 1.0;
var scaling = topLevel?.RenderScaling ?? 1.0;
// 调度动画 // 调度动画
var director = Director.Instance; var director = Director.Instance;