From dccb3c029c5d05423443dafdca5adb6cf6529430 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Wed, 18 Sep 2024 02:37:17 +0800 Subject: [PATCH] Refactor and optimize overlay dialog handling and resizing logic - Remove unused `_moveDragging` variable in `OverlayFeedbackElement.cs` - Rename private static animations to follow PascalCase in `OverlayDialogHost.Shared.cs` - Simplify and streamline `ClickMaskToCloseDialog`, `OnPointerMoved`, `OnPointerPressed`, and `OnPointerReleased` methods in `OverlayDialogHost.Dialog.cs` - Remove redundant null checks and streamline method calls in various files - Optimize `_moveDragging` logic and pointer event handling in `DialogControlBase.cs` This commit enhances readability, maintains consistency in naming conventions, and optimizes the code for better performance and clarity. --- src/Ursa/Controls/Dialog/DialogControlBase.cs | 36 +++- .../OverlayShared/OverlayDialogHost.Dialog.cs | 180 +++++------------- .../OverlayShared/OverlayDialogHost.Drawer.cs | 6 +- .../OverlayShared/OverlayDialogHost.Shared.cs | 33 ++-- .../OverlayShared/OverlayFeedbackElement.cs | 2 +- 5 files changed, 102 insertions(+), 155 deletions(-) diff --git a/src/Ursa/Controls/Dialog/DialogControlBase.cs b/src/Ursa/Controls/Dialog/DialogControlBase.cs index 038d6c6..7ebcd23 100644 --- a/src/Ursa/Controls/Dialog/DialogControlBase.cs +++ b/src/Ursa/Controls/Dialog/DialogControlBase.cs @@ -31,6 +31,9 @@ public abstract class DialogControlBase : OverlayFeedbackElement private bool _isFullScreen; private Panel? _titleArea; + private bool _moveDragging; + private Point _moveDragStartPoint; + static DialogControlBase() { @@ -88,17 +91,44 @@ public abstract class DialogControlBase : OverlayFeedbackElement private void OnTitlePointerPressed(InputElement sender, PointerPressedEventArgs e) { - e.Source = this; + //e.Source = this; + if (ContainerPanel is OverlayDialogHost h) + { + if (h.IsTopLevel && this.IsFullScreen) + { + var top = TopLevel.GetTopLevel(this); + if (top is Window w) + { + w.BeginMoveDrag(e); + return; + } + } + } + if (!e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) return; + if (IsFullScreen) return; + _moveDragging = true; + _moveDragStartPoint = e.GetPosition(this); } private void OnTitlePointerMove(InputElement sender, PointerEventArgs e) { - e.Source = this; + //e.Source = this; + if (!_moveDragging) return; + if (ContainerPanel is null) return; + var p = e.GetPosition(this); + var left = Canvas.GetLeft(this) + p.X - _moveDragStartPoint.X; + var top = Canvas.GetTop(this) + p.Y - _moveDragStartPoint.Y; + left = MathHelpers.SafeClamp(left, 0, ContainerPanel.Bounds.Width - Bounds.Width); + top = MathHelpers.SafeClamp(top, 0, ContainerPanel.Bounds.Height - Bounds.Height); + Canvas.SetLeft(this, left); + Canvas.SetTop(this, top); } private void OnTitlePointerRelease(InputElement sender, PointerReleasedEventArgs e) { - e.Source = this; + // e.Source = this; + _moveDragging = false; + AnchorAndUpdatePositionInfo(); } private void OnCloseButtonClick(object? sender, RoutedEventArgs args) diff --git a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Dialog.cs b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Dialog.cs index b7f8a37..e2f2be3 100644 --- a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Dialog.cs +++ b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Dialog.cs @@ -1,5 +1,4 @@ using Avalonia; -using Avalonia.Controls; using Avalonia.Input; using Avalonia.VisualTree; using Irihi.Avalonia.Shared.Helpers; @@ -10,10 +9,8 @@ namespace Ursa.Controls; public partial class OverlayDialogHost { - private Point _lastPoint; - - public Thickness SnapThickness { get; set; } = new Thickness(0); - + public Thickness SnapThickness { get; set; } = new(0); + private static void ResetDialogPosition(DialogControlBase control, Size newSize) { control.MaxWidth = newSize.Width; @@ -26,138 +23,71 @@ public partial class OverlayDialogHost SetTop(control, 0); return; } + var width = newSize.Width - control.Bounds.Width; var height = newSize.Height - control.Bounds.Height; var newLeft = width * control.HorizontalOffsetRatio ?? 0; var newTop = height * control.VerticalOffsetRatio ?? 0; - if(control.ActualHorizontalAnchor == HorizontalPosition.Left) - { - newLeft = 0; - } - if (control.ActualHorizontalAnchor == HorizontalPosition.Right) - { - newLeft = newSize.Width - control.Bounds.Width; - } - if (control.ActualVerticalAnchor == VerticalPosition.Top) - { - newTop = 0; - } - if (control.ActualVerticalAnchor == VerticalPosition.Bottom) - { - newTop = newSize.Height - control.Bounds.Height; - } + if (control.ActualHorizontalAnchor == HorizontalPosition.Left) newLeft = 0; + if (control.ActualHorizontalAnchor == HorizontalPosition.Right) newLeft = newSize.Width - control.Bounds.Width; + if (control.ActualVerticalAnchor == VerticalPosition.Top) newTop = 0; + if (control.ActualVerticalAnchor == VerticalPosition.Bottom) newTop = newSize.Height - control.Bounds.Height; SetLeft(control, Math.Max(0.0, newLeft)); SetTop(control, Math.Max(0.0, newTop)); } - - protected override void OnPointerMoved(PointerEventArgs e) - { - if (e.Source is DialogControlBase item) - { - if (item.IsFullScreen) return; - if (e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) - { - var p = e.GetPosition(this); - var left = p.X - _lastPoint.X; - var top = p.Y - _lastPoint.Y; - left = MathHelpers.SafeClamp(left, 0, Bounds.Width - item.Bounds.Width); - top = MathHelpers.SafeClamp(top, 0, Bounds.Height - item.Bounds.Height); - SetLeft(item, left); - SetTop(item, top); - } - } - } - - protected override void OnPointerPressed(PointerPressedEventArgs e) - { - if (e.Source is DialogControlBase item) - { - if (IsTopLevel && item.IsFullScreen) - { - var top = TopLevel.GetTopLevel(item); - if (top is Window w) - { - w.BeginMoveDrag(e); - } - } - else - { - _lastPoint = e.GetPosition(item); - } - } - } - - protected override void OnPointerReleased(PointerReleasedEventArgs e) - { - if (e.Source is DialogControlBase item) - { - item.AnchorAndUpdatePositionInfo(); - } - } internal void AddDialog(DialogControlBase control) { PureRectangle? mask = null; - if (control.CanLightDismiss) - { - mask = CreateOverlayMask(false, control.CanLightDismiss); - } - if (mask is not null) - { - Children.Add(mask); - } - this.Children.Add(control); + if (control.CanLightDismiss) mask = CreateOverlayMask(false, control.CanLightDismiss); + if (mask is not null) Children.Add(mask); + Children.Add(control); _layers.Add(new DialogPair(mask, control, false)); if (control.IsFullScreen) { control.Width = Bounds.Width; control.Height = Bounds.Height; } + control.MaxWidth = Bounds.Width; control.MaxHeight = Bounds.Height; - control.Measure(this.Bounds.Size); + control.Measure(Bounds.Size); control.Arrange(new Rect(control.DesiredSize)); SetToPosition(control); control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing); control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged); ResetZIndices(); } - + private async void OnDialogControlClosing(object? sender, object? e) { - if (sender is DialogControlBase control) + if (sender is not DialogControlBase control) return; + var layer = _layers.FirstOrDefault(a => a.Element == control); + if (layer is null) return; + _layers.Remove(layer); + + control.RemoveHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing); + control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged); + layer.Mask?.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow); + + Children.Remove(control); + + if (layer.Mask is not null) { - var layer = _layers.FirstOrDefault(a => a.Element == control); - if (layer is null) return; - _layers.Remove(layer); - - control.RemoveHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing); - control.RemoveHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged); - control.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow); - - Children.Remove(control); - - if (layer.Mask is not null) + Children.Remove(layer.Mask); + if (layer.Modal) { - Children.Remove(layer.Mask); - - if (layer.Modal) - { - _modalCount--; - IsInModalStatus = _modalCount > 0; - if (!IsAnimationDisabled) - { - await _maskDisappearAnimation.RunAsync(layer.Mask); - } - } + _modalCount--; + IsInModalStatus = _modalCount > 0; + if (!IsAnimationDisabled) await MaskDisappearAnimation.RunAsync(layer.Mask); } - - ResetZIndices(); } + + ResetZIndices(); } /// - /// Add a dialog as a modal dialog to the host + /// Add a dialog as a modal dialog to the host /// /// internal void AddModalDialog(DialogControlBase control) @@ -166,24 +96,22 @@ public partial class OverlayDialogHost _layers.Add(new DialogPair(mask, control)); control.SetAsModal(true); ResetZIndices(); - this.Children.Add(mask); - this.Children.Add(control); + Children.Add(mask); + Children.Add(control); if (control.IsFullScreen) { control.Width = Bounds.Width; control.Height = Bounds.Height; } + control.MaxWidth = Bounds.Width; control.MaxHeight = Bounds.Height; - control.Measure(this.Bounds.Size); + control.Measure(Bounds.Size); control.Arrange(new Rect(control.DesiredSize)); SetToPosition(control); control.AddHandler(OverlayFeedbackElement.ClosedEvent, OnDialogControlClosing); control.AddHandler(DialogControlBase.LayerChangedEvent, OnDialogLayerChanged); - if (!IsAnimationDisabled) - { - _maskAppearAnimation.RunAsync(mask); - } + if (!IsAnimationDisabled) MaskAppearAnimation.RunAsync(mask); var element = control.GetVisualDescendants().OfType().FirstOrDefault(a => a.Focusable); element?.Focus(); @@ -200,9 +128,9 @@ public partial class OverlayDialogHost return; var layer = _layers.FirstOrDefault(a => a.Element == control); if (layer is null) return; - int index = _layers.IndexOf(layer); + var index = _layers.IndexOf(layer); _layers.Remove(layer); - int newIndex = index; + var newIndex = index; switch (e.ChangeType) { case DialogLayerChangeType.BringForward: @@ -222,12 +150,12 @@ public partial class OverlayDialogHost _layers.Insert(newIndex, layer); ResetZIndices(); } - + private void SetToPosition(DialogControlBase? control) { if (control is null) return; - double left = GetLeftPosition(control); - double top = GetTopPosition(control); + var left = GetLeftPosition(control); + var top = GetTopPosition(control); SetLeft(control, left); SetTop(control, top); control.AnchorAndUpdatePositionInfo(); @@ -235,9 +163,8 @@ public partial class OverlayDialogHost private double GetLeftPosition(DialogControlBase control) { - double left; - double offset = Math.Max(0, control.HorizontalOffset ?? 0); - left = this.Bounds.Width - control.Bounds.Width; + var offset = Math.Max(0, control.HorizontalOffset ?? 0); + var left = Bounds.Width - control.Bounds.Width; if (control.HorizontalAnchor == HorizontalPosition.Center) { left *= 0.5; @@ -249,20 +176,18 @@ public partial class OverlayDialogHost } else if (control.HorizontalAnchor == HorizontalPosition.Right) { - double leftOffset = Bounds.Width - control.Bounds.Width - offset; + var leftOffset = Bounds.Width - control.Bounds.Width - offset; leftOffset = Math.Max(0, leftOffset); - if(control.HorizontalOffset.HasValue) - { - left = MathHelpers.SafeClamp(left, 0, leftOffset); - } + if (control.HorizontalOffset.HasValue) left = MathHelpers.SafeClamp(left, 0, leftOffset); } + return left; - } + } private double GetTopPosition(DialogControlBase control) { - double offset = Math.Max(0, control.VerticalOffset ?? 0); - var top = this.Bounds.Height - control.Bounds.Height; + var offset = Math.Max(0, control.VerticalOffset ?? 0); + var top = Bounds.Height - control.Bounds.Height; if (control.VerticalAnchor == VerticalPosition.Center) { top *= 0.5; @@ -277,8 +202,7 @@ public partial class OverlayDialogHost var topOffset = Math.Max(0, Bounds.Height - control.Bounds.Height - offset); top = MathHelpers.SafeClamp(top, 0, topOffset); } + return top; } - - } \ No newline at end of file diff --git a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Drawer.cs b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Drawer.cs index e6bec9d..438d8a9 100644 --- a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Drawer.cs +++ b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Drawer.cs @@ -42,7 +42,7 @@ public partial class OverlayDialogHost } else { - await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask)); + await Task.WhenAll(animation.RunAsync(control), MaskAppearAnimation.RunAsync(mask)); } } } @@ -67,7 +67,7 @@ public partial class OverlayDialogHost } else { - await Task.WhenAll(animation.RunAsync(control), _maskAppearAnimation.RunAsync(mask)); + await Task.WhenAll(animation.RunAsync(control), MaskAppearAnimation.RunAsync(mask)); } var element = control.GetVisualDescendants().OfType().FirstOrDefault(a => a.Focusable); element?.Focus(); @@ -174,7 +174,7 @@ public partial class OverlayDialogHost if (!IsAnimationDisabled) { var disappearAnimation = CreateAnimation(control.Bounds.Size, control.Position, false); - await Task.WhenAll(disappearAnimation.RunAsync(control), _maskDisappearAnimation.RunAsync(layer.Mask)); + await Task.WhenAll(disappearAnimation.RunAsync(control), MaskDisappearAnimation.RunAsync(layer.Mask)); } Children.Remove(layer.Mask); } diff --git a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Shared.cs b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Shared.cs index 164366b..3dabc19 100644 --- a/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Shared.cs +++ b/src/Ursa/Controls/OverlayShared/OverlayDialogHost.Shared.cs @@ -14,8 +14,8 @@ namespace Ursa.Controls; public partial class OverlayDialogHost: Canvas { - private static readonly Animation _maskAppearAnimation; - private static readonly Animation _maskDisappearAnimation; + private static readonly Animation MaskAppearAnimation; + private static readonly Animation MaskDisappearAnimation; private readonly List _layers = new List(10); @@ -61,8 +61,8 @@ public partial class OverlayDialogHost: Canvas static OverlayDialogHost() { ClipToBoundsProperty.OverrideDefaultValue(true); - _maskAppearAnimation = CreateOpacityAnimation(true); - _maskDisappearAnimation = CreateOpacityAnimation(false); + MaskAppearAnimation = CreateOpacityAnimation(true); + MaskDisappearAnimation = CreateOpacityAnimation(false); } private static Animation CreateOpacityAnimation(bool appear) @@ -128,28 +128,21 @@ public partial class OverlayDialogHost: Canvas { return; } - if (sender is PureRectangle mask) + if (sender is not PureRectangle mask) return; + if(TopLevel.GetTopLevel(mask) is Window window) { - var window = this.GetVisualAncestors().OfType().FirstOrDefault(); - if(window is not null) - { - window.BeginMoveDrag(e); - } + window.BeginMoveDrag(e); } } private void ClickMaskToCloseDialog(object? sender, PointerReleasedEventArgs e) { - if (sender is PureRectangle border) - { - var layer = _layers.FirstOrDefault(a => a.Mask == border); - if (layer is not null) - { - layer.Element.Close(); - border.RemoveHandler(PointerReleasedEvent, ClickMaskToCloseDialog); - border.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow); - } - } + if (sender is not PureRectangle border) return; + var layer = _layers.FirstOrDefault(a => a.Mask == border); + if (layer is null) return; + border.RemoveHandler(PointerReleasedEvent, ClickMaskToCloseDialog); + border.RemoveHandler(PointerPressedEvent, DragMaskToMoveWindow); + layer.Element.Close(); } private IDisposable? _modalStatusSubscription; private int? _toplevelHash; diff --git a/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs b/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs index 8dc7ed0..06f9b8c 100644 --- a/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs +++ b/src/Ursa/Controls/OverlayShared/OverlayFeedbackElement.cs @@ -20,7 +20,6 @@ public abstract class OverlayFeedbackElement : ContentControl nameof(Closed), RoutingStrategies.Bubble); private bool _resizeDragging; - private bool _moveDragging; protected Panel? ContainerPanel; private Rect _resizeDragStartBounds; @@ -142,6 +141,7 @@ public abstract class OverlayFeedbackElement : ContentControl Canvas.SetTop(this, newBounds.Top); SetCurrentValue(WidthProperty, newBounds.Width); SetCurrentValue(HeightProperty, newBounds.Height); + AnchorAndUpdatePositionInfo(); } private Rect CalculateNewBounds(double left, double top, double width, double height, Vector diff, Rect? containerBounds,