Refactor and enhance overlay feedback handling
- Promote `_containerPanel` to a protected property for better accessibility - Extract `CoerceDelta` method to centralize constraint logic - Implement `AnchorAndUpdatePositionInfo` across dialog controls for consistent positioning behavior - Adjust margin binding for `DialogResizer` to include parent border margin - Simplify pointer movement calculations and conditional checks
This commit is contained in:
@@ -55,7 +55,7 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" />
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}" />
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
@@ -242,7 +242,7 @@
|
||||
</Grid>
|
||||
</Border>
|
||||
</Border>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}"/>
|
||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}"/>
|
||||
</Panel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
@@ -204,4 +204,50 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
if (ContainerPanel is null) return;
|
||||
ActualHorizontalAnchor = HorizontalPosition.Center;
|
||||
ActualVerticalAnchor = VerticalPosition.Center;
|
||||
double left = Canvas.GetLeft(this);
|
||||
double top = Canvas.GetTop(this);
|
||||
double right = ContainerPanel.Bounds.Width - left - Bounds.Width;
|
||||
double bottom = ContainerPanel.Bounds.Height - top - Bounds.Height;
|
||||
if (ContainerPanel is OverlayDialogHost h)
|
||||
{
|
||||
var snapThickness = h.SnapThickness;
|
||||
if(top < snapThickness.Top)
|
||||
{
|
||||
Canvas.SetTop(this, 0);
|
||||
ActualVerticalAnchor = VerticalPosition.Top;
|
||||
VerticalOffsetRatio = 0;
|
||||
}
|
||||
if(bottom < snapThickness.Bottom)
|
||||
{
|
||||
Canvas.SetTop(this, ContainerPanel.Bounds.Height - Bounds.Height);
|
||||
ActualVerticalAnchor = VerticalPosition.Bottom;
|
||||
VerticalOffsetRatio = 1;
|
||||
}
|
||||
if(left < snapThickness.Left)
|
||||
{
|
||||
Canvas.SetLeft(this, 0);
|
||||
ActualHorizontalAnchor = HorizontalPosition.Left;
|
||||
HorizontalOffsetRatio = 0;
|
||||
}
|
||||
if(right < snapThickness.Right)
|
||||
{
|
||||
Canvas.SetLeft(this, ContainerPanel.Bounds.Width - this.Bounds.Width);
|
||||
ActualHorizontalAnchor = HorizontalPosition.Right;
|
||||
HorizontalOffsetRatio = 1;
|
||||
}
|
||||
}
|
||||
left = Canvas.GetLeft(this);
|
||||
top = Canvas.GetTop(this);
|
||||
right = ContainerPanel.Bounds.Width - left - Bounds.Width;
|
||||
bottom = ContainerPanel.Bounds.Height - top - Bounds.Height;
|
||||
|
||||
HorizontalOffsetRatio = (left + right) == 0 ? 0 : left / (left + right);
|
||||
VerticalOffsetRatio = (top + bottom) == 0 ? 0 : top / (top + bottom);
|
||||
}
|
||||
}
|
||||
@@ -25,4 +25,9 @@ public class CustomDrawerControl: DrawerControlBase
|
||||
OnElementClosing(this, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -135,4 +135,9 @@ public class DefaultDrawerControl : DrawerControlBase
|
||||
RaiseEvent(new ResultEventArgs(ClosedEvent, result));
|
||||
}
|
||||
}
|
||||
|
||||
protected internal override void AnchorAndUpdatePositionInfo()
|
||||
{
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -28,8 +28,8 @@ public partial class OverlayDialogHost
|
||||
}
|
||||
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;
|
||||
var newLeft = width * control.HorizontalOffsetRatio ?? 0;
|
||||
var newTop = height * control.VerticalOffsetRatio ?? 0;
|
||||
if(control.ActualHorizontalAnchor == HorizontalPosition.Left)
|
||||
{
|
||||
newLeft = 0;
|
||||
@@ -91,7 +91,7 @@ public partial class OverlayDialogHost
|
||||
{
|
||||
if (e.Source is DialogControlBase item)
|
||||
{
|
||||
AnchorAndUpdatePositionInfo(item);
|
||||
item.AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,48 +230,7 @@ public partial class OverlayDialogHost
|
||||
double top = GetTopPosition(control);
|
||||
SetLeft(control, left);
|
||||
SetTop(control, top);
|
||||
AnchorAndUpdatePositionInfo(control);
|
||||
}
|
||||
|
||||
private void AnchorAndUpdatePositionInfo(DialogControlBase control)
|
||||
{
|
||||
control.ActualHorizontalAnchor = HorizontalPosition.Center;
|
||||
control.ActualVerticalAnchor = VerticalPosition.Center;
|
||||
double left = GetLeft(control);
|
||||
double top = GetTop(control);
|
||||
double right = Bounds.Width - left - control.Bounds.Width;
|
||||
double bottom = Bounds.Height - top - control.Bounds.Height;
|
||||
if(top < SnapThickness.Top)
|
||||
{
|
||||
SetTop(control, 0);
|
||||
control.ActualVerticalAnchor = VerticalPosition.Top;
|
||||
control.VerticalOffsetRatio = 0;
|
||||
}
|
||||
if(bottom < SnapThickness.Bottom)
|
||||
{
|
||||
SetTop(control, Bounds.Height - control.Bounds.Height);
|
||||
control.ActualVerticalAnchor = VerticalPosition.Bottom;
|
||||
control.VerticalOffsetRatio = 1;
|
||||
}
|
||||
if(left < SnapThickness.Left)
|
||||
{
|
||||
SetLeft(control, 0);
|
||||
control.ActualHorizontalAnchor = HorizontalPosition.Left;
|
||||
control.HorizontalOffsetRatio = 0;
|
||||
}
|
||||
if(right < SnapThickness.Right)
|
||||
{
|
||||
SetLeft(control, Bounds.Width - control.Bounds.Width);
|
||||
control.ActualHorizontalAnchor = HorizontalPosition.Right;
|
||||
control.HorizontalOffsetRatio = 1;
|
||||
}
|
||||
left = GetLeft(control);
|
||||
top = GetTop(control);
|
||||
right = Bounds.Width - left - control.Bounds.Width;
|
||||
bottom = Bounds.Height - top - control.Bounds.Height;
|
||||
|
||||
control.HorizontalOffsetRatio = (left + right) == 0 ? 0 : left / (left + right);
|
||||
control.VerticalOffsetRatio = (top + bottom) == 0 ? 0 : top / (top + bottom);
|
||||
control.AnchorAndUpdatePositionInfo();
|
||||
}
|
||||
|
||||
private double GetLeftPosition(DialogControlBase control)
|
||||
|
||||
@@ -22,7 +22,7 @@ public abstract class OverlayFeedbackElement : ContentControl
|
||||
private bool _resizeDragging;
|
||||
private bool _moveDragging;
|
||||
|
||||
private Panel? _containerPanel;
|
||||
protected Panel? ContainerPanel;
|
||||
private Rect _resizeDragStartBounds;
|
||||
private Point _resizeDragStartPoint;
|
||||
|
||||
@@ -110,7 +110,7 @@ public abstract class OverlayFeedbackElement : ContentControl
|
||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
base.OnAttachedToVisualTree(e);
|
||||
_containerPanel = this.FindAncestorOfType<Panel>();
|
||||
ContainerPanel = this.FindAncestorOfType<Panel>();
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
@@ -130,73 +130,72 @@ public abstract class OverlayFeedbackElement : ContentControl
|
||||
base.OnPointerMoved(e);
|
||||
if (!_resizeDragging || _windowEdge is null) return;
|
||||
var point = e.GetPosition(this);
|
||||
var diff = point - _resizeDragStartPoint;
|
||||
Vector diff = point - _resizeDragStartPoint;
|
||||
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;
|
||||
var height = _windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? Bounds.Height : _resizeDragStartBounds.Height;
|
||||
var newBounds = CalculateNewBounds(left, top, width, height, diff, _containerPanel?.Bounds, _windowEdge.Value);
|
||||
var newBounds = CalculateNewBounds(left, top, width, height, diff, ContainerPanel?.Bounds, _windowEdge.Value);
|
||||
Canvas.SetLeft(this, newBounds.Left);
|
||||
Canvas.SetTop(this, newBounds.Top);
|
||||
SetCurrentValue(WidthProperty, newBounds.Width);
|
||||
SetCurrentValue(HeightProperty, newBounds.Height);
|
||||
}
|
||||
|
||||
private Rect CalculateNewBounds(double left, double top, double width, double height, Point diff, Rect? containerBounds,
|
||||
private Rect CalculateNewBounds(double left, double top, double width, double height, Vector diff, Rect? containerBounds,
|
||||
WindowEdge windowEdge)
|
||||
{
|
||||
if (containerBounds is not null)
|
||||
{
|
||||
var minX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
||||
? -left
|
||||
: double.NegativeInfinity;
|
||||
var minY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? -top
|
||||
: double.NegativeInfinity;
|
||||
var maxX = containerBounds.Value.Width - left - MinWidth;
|
||||
var maxY = containerBounds.Value.Height - top - MinHeight;
|
||||
diff = new Point(MathHelpers.SafeClamp(diff.X, minX, maxX), MathHelpers.SafeClamp(diff.Y, minY, maxY));
|
||||
}
|
||||
diff = CoerceDelta(left, top, width, height, diff, containerBounds, windowEdge);
|
||||
switch (windowEdge)
|
||||
{
|
||||
case WindowEdge.North:
|
||||
top += diff.Y;
|
||||
height -= diff.Y;
|
||||
top = Math.Max(0, top);
|
||||
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;
|
||||
top += diff.Y; width -= diff.X; height -= diff.Y;
|
||||
break;
|
||||
}
|
||||
return new Rect(left, top, width, height);
|
||||
}
|
||||
|
||||
private Vector CoerceDelta(double left, double top, double width, double height, Vector diff, Rect? containerBounds,
|
||||
WindowEdge windowEdge)
|
||||
{
|
||||
if (containerBounds is null) return diff;
|
||||
var minX = windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
||||
? -left
|
||||
: -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;
|
||||
var maxY = windowEdge is WindowEdge.North or WindowEdge.NorthEast or WindowEdge.NorthWest
|
||||
? 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();
|
||||
}
|
||||
Reference in New Issue
Block a user