From 93a19e73e64f302d9e84e96a50185f4f2feb8971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9B=E5=B0=98=E7=A9=BA=E5=BF=A7?= Date: Thu, 31 Oct 2024 09:01:59 +0800 Subject: [PATCH 1/2] Fixed: Closing a dialog returns TView to the user instead of occupying its parent. --- .../OverlayShared/OverlayFeedbackElement.cs | 54 +++++++++++++------ 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs b/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs index 131b490..e437156 100644 --- a/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs +++ b/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs @@ -20,11 +20,11 @@ public abstract class OverlayFeedbackElement : ContentControl nameof(Closed), RoutingStrategies.Bubble); private bool _resizeDragging; - + protected Panel? ContainerPanel; private Rect _resizeDragStartBounds; private Point _resizeDragStartPoint; - + private WindowEdge? _windowEdge; static OverlayFeedbackElement() @@ -35,6 +35,12 @@ public abstract class OverlayFeedbackElement : ContentControl ClosedEvent.AddClassHandler((o, e) => o.OnClosed(e)); } + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + Content = null; + } + public bool IsClosed { get => GetValue(IsClosedProperty); @@ -96,7 +102,7 @@ public abstract class OverlayFeedbackElement : ContentControl _resizeDragStartBounds = Bounds; _windowEdge = windowEdge; } - + internal void BeginMoveDrag(PointerPressedEventArgs e) { if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return; @@ -133,9 +139,11 @@ public abstract class OverlayFeedbackElement : ContentControl var left = Canvas.GetLeft(this); var top = Canvas.GetTop(this); var width = _windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest - ? Bounds.Width : _resizeDragStartBounds.Width; + ? Bounds.Width + : _resizeDragStartBounds.Width; var height = _windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest - ? Bounds.Height : _resizeDragStartBounds.Height; + ? Bounds.Height + : _resizeDragStartBounds.Height; var newBounds = CalculateNewBounds(left, top, width, height, diff, ContainerPanel?.Bounds, _windowEdge.Value); Canvas.SetLeft(this, newBounds.Left); Canvas.SetTop(this, newBounds.Top); @@ -144,37 +152,49 @@ public abstract class OverlayFeedbackElement : ContentControl AnchorAndUpdatePositionInfo(); } - private Rect CalculateNewBounds(double left, double top, double width, double height, Vector diff, Rect? containerBounds, + private Rect CalculateNewBounds(double left, double top, double width, double height, Vector diff, + Rect? containerBounds, WindowEdge windowEdge) { diff = CoerceDelta(left, top, width, height, diff, containerBounds, windowEdge); switch (windowEdge) { case WindowEdge.North: - top += diff.Y; height -= diff.Y; + top += diff.Y; + height -= diff.Y; break; case WindowEdge.NorthEast: - top += diff.Y; width += diff.X; height -= diff.Y; + top += diff.Y; + width += diff.X; + height -= diff.Y; break; case WindowEdge.East: width += diff.X; break; case WindowEdge.SouthEast: - width += diff.X; height += diff.Y; + width += diff.X; + height += diff.Y; break; case WindowEdge.South: height += diff.Y; break; case WindowEdge.SouthWest: - left += diff.X; width -= diff.X; height += diff.Y; + left += diff.X; + width -= diff.X; + height += diff.Y; break; case WindowEdge.West: - left += diff.X; width -= diff.X; + left += diff.X; + width -= diff.X; break; case WindowEdge.NorthWest: - left += diff.X; top += diff.Y; width -= diff.X; height -= diff.Y; + left += diff.X; + top += diff.Y; + width -= diff.X; + height -= diff.Y; break; } + return new Rect(left, top, width, height); } @@ -184,18 +204,18 @@ public abstract class OverlayFeedbackElement : ContentControl if (containerBounds is null) return diff; var minX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest ? -left - : -width; + : -width; var minY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest ? -top : -height; var maxX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest - ? width-MinWidth - : containerBounds.Value.Width - left - width; + ? width - MinWidth + : containerBounds.Value.Width - left - width; var maxY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest - ? height-MinWidth + ? height - MinWidth : containerBounds.Value.Height - top - height; return new Vector(MathHelpers.SafeClamp(diff.X, minX, maxX), MathHelpers.SafeClamp(diff.Y, minY, maxY)); } - + protected internal abstract void AnchorAndUpdatePositionInfo(); } \ No newline at end of file From a9ce9fab0ea7c0de048ff6d382e968cac9d7537e Mon Sep 17 00:00:00 2001 From: rabbitism Date: Thu, 31 Oct 2024 12:01:52 +0800 Subject: [PATCH 2/2] feat: add headless test. --- .../Test.cs | 27 ++++++++++++++++ .../TestWindow.axaml | 11 +++++++ .../TestWindow.axaml.cs | 32 +++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/Test.cs create mode 100644 tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/TestWindow.axaml create mode 100644 tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/TestWindow.axaml.cs diff --git a/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/Test.cs b/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/Test.cs new file mode 100644 index 0000000..548e400 --- /dev/null +++ b/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/Test.cs @@ -0,0 +1,27 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Headless; +using Avalonia.Headless.XUnit; +using Avalonia.Input; +using Avalonia.Threading; + +namespace HeadlessTest.Ursa.Controls.OverlayShared.Case_Close_Dialog_Clear_Content_Parent; + +public class Test +{ + [AvaloniaFact] + public void Dialog_Parent_Is_Cleared_After_Close() + { + var ursaWindow = new TestWindow(); + ursaWindow.Show(); + var button = ursaWindow.FindControl + diff --git a/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/TestWindow.axaml.cs b/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/TestWindow.axaml.cs new file mode 100644 index 0000000..ee54018 --- /dev/null +++ b/tests/HeadlessTest.Ursa/Controls/OverlayShared/Case_Close_Dialog_Clear_Content_Parent/TestWindow.axaml.cs @@ -0,0 +1,32 @@ +using Avalonia.Controls; +using Avalonia.Interactivity; +using Irihi.Avalonia.Shared.Contracts; +using Ursa.Controls; + +namespace HeadlessTest.Ursa.Controls.OverlayShared.Case_Close_Dialog_Clear_Content_Parent; + +public partial class TestWindow : UrsaWindow +{ + public TestWindow() + { + InitializeComponent(); + } + + internal TextBox TextBox = new TextBox(); + internal DialogViewModel DialogViewModel = new DialogViewModel(); + + private void Button_OnClick(object? sender, RoutedEventArgs e) + { + OverlayDialog.Show(TextBox, DialogViewModel); + } +} + +class DialogViewModel : IDialogContext +{ + public void Close() + { + RequestClose?.Invoke(this, null); + } + + public event EventHandler? RequestClose; +} \ No newline at end of file