@ -5,6 +5,7 @@ using System.Linq;
using Moq ;
using Avalonia.Controls.Presenters ;
using Avalonia.Controls.Primitives ;
using Avalonia.Controls.Primitives.PopupPositioning ;
using Avalonia.Controls.Templates ;
using Avalonia.Layout ;
using Avalonia.LogicalTree ;
@ -595,6 +596,113 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
[Fact]
public void Popup_Should_Follow_Placement_Target_On_Window_Move ( )
{
using ( CreateServices ( ) )
{
var popup = new Popup { Width = 4 0 0 , Height = 2 0 0 } ;
var window = PreparedWindow ( popup ) ;
popup . Open ( ) ;
if ( popup . Host is PopupRoot popupRoot )
{
// Moving the window must move the popup (screen coordinates have changed)
var raised = false ;
popupRoot . PositionChanged + = ( _ , args ) = >
{
Assert . Equal ( new PixelPoint ( 1 0 , 1 0 ) , args . Point ) ;
raised = true ;
} ;
window . Position = new PixelPoint ( 1 0 , 1 0 ) ;
Assert . True ( raised ) ;
}
}
}
[Fact]
public void Popup_Should_Follow_Placement_Target_On_Window_Resize ( )
{
using ( CreateServices ( ) )
{
var placementTarget = new Panel ( )
{
Width = 1 0 ,
Height = 1 0 ,
HorizontalAlignment = HorizontalAlignment . Center ,
VerticalAlignment = VerticalAlignment . Center
} ;
var popup = new Popup ( ) { PlacementTarget = placementTarget , Width = 1 0 , Height = 1 0 } ;
( ( ISetLogicalParent ) popup ) . SetParent ( popup . PlacementTarget ) ;
var window = PreparedWindow ( placementTarget ) ;
window . Show ( ) ;
popup . Open ( ) ;
// The target's initial placement is (395,295) which is a 10x10 panel centered in a 800x600 window
Assert . Equal ( placementTarget . Bounds , new Rect ( 3 9 5D , 2 9 5D , 1 0 , 1 0 ) ) ;
if ( popup . Host is PopupRoot popupRoot )
{
// Resizing the window to 700x500 must move the popup to (345,255) as this is the new
// location of the placement target
var raised = false ;
popupRoot . PositionChanged + = ( _ , args ) = >
{
Assert . Equal ( new PixelPoint ( 3 4 5 , 2 5 5 ) , args . Point ) ;
raised = true ;
} ;
window . PlatformImpl ? . Resize ( new Size ( 7 0 0D , 5 0 0D ) , PlatformResizeReason . Unspecified ) ;
Assert . True ( raised ) ;
}
}
}
[Fact]
public void Popup_Should_Follow_Popup_Root_Placement_Target ( )
{
// When the placement target of a popup is another popup (e.g. nested menu items), the child popup must
// follow the parent popup if it moves (due to root window movement or resize)
using ( CreateServices ( ) )
{
// The child popup is placed directly over the parent popup for position testing
var parentPopup = new Popup ( ) { Width = 1 0 , Height = 1 0 } ;
var childPopup = new Popup ( ) {
Width = 2 0 ,
Height = 2 0 ,
PlacementTarget = parentPopup ,
PlacementMode = PlacementMode . AnchorAndGravity ,
PlacementAnchor = PopupAnchor . TopLeft ,
PlacementGravity = PopupGravity . BottomRight
} ;
( ( ISetLogicalParent ) childPopup ) . SetParent ( childPopup . PlacementTarget ) ;
var window = PreparedWindow ( parentPopup ) ;
window . Show ( ) ;
parentPopup . Open ( ) ;
childPopup . Open ( ) ;
if ( childPopup . Host is PopupRoot popupRoot )
{
var raised = false ;
popupRoot . PositionChanged + = ( _ , args ) = >
{
// The parent's initial placement is (395,295) which is a 10x10 popup centered
// in a 800x600 window. When the window is moved, the child's final placement is (405, 305)
// which is the parent's placement moved 10 pixels left and down.
Assert . Equal ( new PixelPoint ( 4 0 5 , 3 0 5 ) , args . Point ) ;
raised = true ;
} ;
window . Position = new PixelPoint ( 1 0 , 1 0 ) ;
Assert . True ( raised ) ;
}
}
}
private IDisposable CreateServices ( )
{
return UnitTestApplication . Start ( TestServices . StyledWindow . With ( windowingPlatform :