Skip to content

Commit

Permalink
Fix ScrollContentPresenter incorrectly handling BringIntoView when of…
Browse files Browse the repository at this point in the history
…fset is coerced (AvaloniaUI#14913)

* Added failing test for nested ScrollContentPresenters w/o rounding

* Fix SCP.BringDescendantIntoView with coerced offset
  • Loading branch information
MrJul authored Mar 11, 2024
1 parent 86bfc26 commit acc3c3c
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 1 deletion.
6 changes: 5 additions & 1 deletion src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -285,8 +285,12 @@ public bool BringDescendantIntoView(Visual target, Rect targetRect)
return false;
}

var oldOffset = Offset;
SetCurrentValue(OffsetProperty, offset);
return true;

// It's possible that the Offset coercion has changed the offset back to its previous value,
// this is common for floating point rounding errors.
return !Offset.NearlyEquals(oldOffset);
}

protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,56 @@ public void Nested_Presenters_Should_Scroll_Outer_When_Content_Exceeds_Viewport(
Assert.Equal(new Vector(0, 0), innerPresenter.Offset);
}

[Fact]
public void Nested_Presenters_Should_Scroll_Outer_When_Viewports_Are_Close()
{
ScrollContentPresenter innerPresenter;
Border border;

var outerPresenter = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Width = 100,
Height = 170.0568181818182,
UseLayoutRounding = false,
Content = innerPresenter = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Width = 100,
Height = 493.2613636363636,
UseLayoutRounding = false,
Content = new StackPanel
{
Children =
{
new Border
{
Height = 455.31818181818187,
UseLayoutRounding = false
},
(border = new Border {
Width = 100,
Height = 37.94318181818182,
UseLayoutRounding = false
})
}
}
}
};

innerPresenter.UpdateChild();
outerPresenter.UpdateChild();
outerPresenter.Measure(new Size(100, 170.0568181818182));
outerPresenter.Arrange(new Rect(0, 0, 100, 170.0568181818182));

border.BringIntoView();

Assert.Equal(new Vector(0, 323.20454545454544), outerPresenter.Offset);
Assert.Equal(new Vector(0, 0), innerPresenter.Offset);
}

private class TestControl : Control
{
public Size AvailableSize { get; private set; }
Expand Down

0 comments on commit acc3c3c

Please sign in to comment.