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>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Border>
|
</Border>
|
||||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" />
|
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}" />
|
||||||
</Panel>
|
</Panel>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
@@ -242,7 +242,7 @@
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Border>
|
</Border>
|
||||||
</Border>
|
</Border>
|
||||||
<u:DialogResizer IsVisible="{TemplateBinding CanResize}"/>
|
<u:DialogResizer IsVisible="{TemplateBinding CanResize}" Margin="{Binding #PART_Border.Margin}"/>
|
||||||
</Panel>
|
</Panel>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
|||||||
@@ -204,4 +204,50 @@ public abstract class DialogControlBase : OverlayFeedbackElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#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);
|
OnElementClosing(this, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected internal override void AnchorAndUpdatePositionInfo()
|
||||||
|
{
|
||||||
|
// throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -135,4 +135,9 @@ public class DefaultDrawerControl : DrawerControlBase
|
|||||||
RaiseEvent(new ResultEventArgs(ClosedEvent, result));
|
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 width = newSize.Width - control.Bounds.Width;
|
||||||
var height = newSize.Height - control.Bounds.Height;
|
var height = newSize.Height - control.Bounds.Height;
|
||||||
var newLeft = width * control.HorizontalOffsetRatio??0;
|
var newLeft = width * control.HorizontalOffsetRatio ?? 0;
|
||||||
var newTop = height * control.VerticalOffsetRatio??0;
|
var newTop = height * control.VerticalOffsetRatio ?? 0;
|
||||||
if(control.ActualHorizontalAnchor == HorizontalPosition.Left)
|
if(control.ActualHorizontalAnchor == HorizontalPosition.Left)
|
||||||
{
|
{
|
||||||
newLeft = 0;
|
newLeft = 0;
|
||||||
@@ -91,7 +91,7 @@ public partial class OverlayDialogHost
|
|||||||
{
|
{
|
||||||
if (e.Source is DialogControlBase item)
|
if (e.Source is DialogControlBase item)
|
||||||
{
|
{
|
||||||
AnchorAndUpdatePositionInfo(item);
|
item.AnchorAndUpdatePositionInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,48 +230,7 @@ public partial class OverlayDialogHost
|
|||||||
double top = GetTopPosition(control);
|
double top = GetTopPosition(control);
|
||||||
SetLeft(control, left);
|
SetLeft(control, left);
|
||||||
SetTop(control, top);
|
SetTop(control, top);
|
||||||
AnchorAndUpdatePositionInfo(control);
|
control.AnchorAndUpdatePositionInfo();
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private double GetLeftPosition(DialogControlBase control)
|
private double GetLeftPosition(DialogControlBase control)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ public abstract class OverlayFeedbackElement : ContentControl
|
|||||||
private bool _resizeDragging;
|
private bool _resizeDragging;
|
||||||
private bool _moveDragging;
|
private bool _moveDragging;
|
||||||
|
|
||||||
private Panel? _containerPanel;
|
protected Panel? ContainerPanel;
|
||||||
private Rect _resizeDragStartBounds;
|
private Rect _resizeDragStartBounds;
|
||||||
private Point _resizeDragStartPoint;
|
private Point _resizeDragStartPoint;
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ public abstract class OverlayFeedbackElement : ContentControl
|
|||||||
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
|
||||||
{
|
{
|
||||||
base.OnAttachedToVisualTree(e);
|
base.OnAttachedToVisualTree(e);
|
||||||
_containerPanel = this.FindAncestorOfType<Panel>();
|
ContainerPanel = this.FindAncestorOfType<Panel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||||
@@ -130,73 +130,72 @@ public abstract class OverlayFeedbackElement : ContentControl
|
|||||||
base.OnPointerMoved(e);
|
base.OnPointerMoved(e);
|
||||||
if (!_resizeDragging || _windowEdge is null) return;
|
if (!_resizeDragging || _windowEdge is null) return;
|
||||||
var point = e.GetPosition(this);
|
var point = e.GetPosition(this);
|
||||||
var diff = point - _resizeDragStartPoint;
|
Vector diff = point - _resizeDragStartPoint;
|
||||||
var left = Canvas.GetLeft(this);
|
var left = Canvas.GetLeft(this);
|
||||||
var top = Canvas.GetTop(this);
|
var top = Canvas.GetTop(this);
|
||||||
var width = _windowEdge is WindowEdge.West or WindowEdge.NorthWest or WindowEdge.SouthWest
|
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
|
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);
|
var newBounds = CalculateNewBounds(left, top, width, height, diff, ContainerPanel?.Bounds, _windowEdge.Value);
|
||||||
Canvas.SetLeft(this, newBounds.Left);
|
Canvas.SetLeft(this, newBounds.Left);
|
||||||
Canvas.SetTop(this, newBounds.Top);
|
Canvas.SetTop(this, newBounds.Top);
|
||||||
SetCurrentValue(WidthProperty, newBounds.Width);
|
SetCurrentValue(WidthProperty, newBounds.Width);
|
||||||
SetCurrentValue(HeightProperty, newBounds.Height);
|
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)
|
WindowEdge windowEdge)
|
||||||
{
|
{
|
||||||
if (containerBounds is not null)
|
diff = CoerceDelta(left, top, width, height, diff, containerBounds, windowEdge);
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
switch (windowEdge)
|
switch (windowEdge)
|
||||||
{
|
{
|
||||||
case WindowEdge.North:
|
case WindowEdge.North:
|
||||||
top += diff.Y;
|
top += diff.Y; height -= diff.Y;
|
||||||
height -= diff.Y;
|
|
||||||
top = Math.Max(0, top);
|
|
||||||
break;
|
break;
|
||||||
case WindowEdge.NorthEast:
|
case WindowEdge.NorthEast:
|
||||||
top += diff.Y;
|
top += diff.Y; width += diff.X; height -= diff.Y;
|
||||||
width += diff.X;
|
|
||||||
height -= diff.Y;
|
|
||||||
break;
|
break;
|
||||||
case WindowEdge.East:
|
case WindowEdge.East:
|
||||||
width += diff.X;
|
width += diff.X;
|
||||||
break;
|
break;
|
||||||
case WindowEdge.SouthEast:
|
case WindowEdge.SouthEast:
|
||||||
width += diff.X;
|
width += diff.X; height += diff.Y;
|
||||||
height += diff.Y;
|
|
||||||
break;
|
break;
|
||||||
case WindowEdge.South:
|
case WindowEdge.South:
|
||||||
height += diff.Y;
|
height += diff.Y;
|
||||||
break;
|
break;
|
||||||
case WindowEdge.SouthWest:
|
case WindowEdge.SouthWest:
|
||||||
left += diff.X;
|
left += diff.X; width -= diff.X; height += diff.Y;
|
||||||
width -= diff.X;
|
|
||||||
height += diff.Y;
|
|
||||||
break;
|
break;
|
||||||
case WindowEdge.West:
|
case WindowEdge.West:
|
||||||
left += diff.X;
|
left += diff.X; width -= diff.X;
|
||||||
width -= diff.X;
|
|
||||||
break;
|
break;
|
||||||
case WindowEdge.NorthWest:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
return new Rect(left, top, width, height);
|
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