1 changed files with 240 additions and 0 deletions
@ -0,0 +1,240 @@ |
|||
using System; |
|||
using Avalonia.Controls.Platform; |
|||
using Avalonia.Controls.Presenters; |
|||
using Avalonia.Controls.Templates; |
|||
using Avalonia.Platform; |
|||
using Avalonia.Threading; |
|||
using Avalonia.UnitTests; |
|||
using Moq; |
|||
using Xunit; |
|||
|
|||
namespace Avalonia.Controls.UnitTests.Platform |
|||
{ |
|||
public class InputPaneTests : ScopedTestBase |
|||
{ |
|||
[Fact] |
|||
public void Resize_With_Input_Pane_ScrollViewer_Brings_Focused_Into_View() |
|||
{ |
|||
var clock = new MockGlobalClock(); |
|||
using (UnitTestApplication.Start(TestServices.RealFocus. |
|||
With(globalClock: clock))) |
|||
{ |
|||
var inputPane = new TestInputPane(new Rect(0, 200, 200, 200)); |
|||
var target = new Button |
|||
{ |
|||
Width = 200, |
|||
Height = 100 |
|||
}; |
|||
|
|||
var panel = new StackPanel() |
|||
{ |
|||
Width = 200, |
|||
Height = 1000, |
|||
Orientation = Layout.Orientation.Vertical, |
|||
Children = |
|||
{ |
|||
new Border() |
|||
{ |
|||
Width = 200, |
|||
Height = 900, |
|||
}, |
|||
target, |
|||
new Border() |
|||
{ |
|||
Width = 200, |
|||
Height = 100, |
|||
} |
|||
} |
|||
}; |
|||
|
|||
var scrollViewer = new ScrollViewer |
|||
{ |
|||
Template = new FuncControlTemplate<ScrollViewer>(CreateScrollViewerTemplate), |
|||
Content = panel, |
|||
Width = 200, |
|||
Height = 600, |
|||
ResizeWithInputPane = true |
|||
}; |
|||
|
|||
var impl = CreateMockTopLevelImpl(inputPane); |
|||
var topLevel = new TestTopLevel(impl.Object) |
|||
{ |
|||
Template = CreateTopLevelTemplate(), |
|||
Content = scrollViewer |
|||
}; |
|||
|
|||
topLevel.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
Assert.Equal(0, scrollViewer.Offset.Y); |
|||
|
|||
target.Focus(); |
|||
|
|||
inputPane.Open(); |
|||
|
|||
clock.Pulse(TimeSpan.FromSeconds(5)); |
|||
|
|||
var timers = Dispatcher.SnapshotTimersForUnitTests(); |
|||
|
|||
foreach (var timer in timers) |
|||
{ |
|||
DispatcherTimerUtils.ForceFire(timer); |
|||
} |
|||
|
|||
topLevel.LayoutManager.ExecuteLayoutPass(); |
|||
|
|||
Assert.Equal(600, scrollViewer.Offset.Y); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void InputPaneAwareView_Resizes_Content_When_Behavior_Resize() |
|||
{ |
|||
var clock = new MockGlobalClock(); |
|||
using (UnitTestApplication.Start(TestServices.RealFocus. |
|||
With(globalClock: clock))) |
|||
{ |
|||
var inputPane = new TestInputPane(new Rect(0, 200, 200, 200)); |
|||
|
|||
var border = new Border(); |
|||
|
|||
var paneView = new InputPaneAwareView() |
|||
{ |
|||
Child = border, |
|||
Height = 500, |
|||
Width = 200, |
|||
Behavior = InputPaneAwareBehavior.Resize |
|||
}; |
|||
|
|||
var impl = CreateMockTopLevelImpl(inputPane); |
|||
var topLevel = new TestTopLevel(impl.Object) |
|||
{ |
|||
Template = CreateTopLevelTemplate(), |
|||
Content = paneView |
|||
}; |
|||
|
|||
topLevel.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
Assert.Equal(500, border.Bounds.Height); |
|||
|
|||
inputPane.Open(); |
|||
|
|||
clock.Pulse(TimeSpan.FromSeconds(5)); |
|||
|
|||
topLevel.LayoutManager.ExecuteLayoutPass(); |
|||
|
|||
Assert.Equal(300, border.Bounds.Height); |
|||
} |
|||
} |
|||
|
|||
[Fact] |
|||
public void InputPaneAwareView_Resizes_Content_When_Behavior_Pan() |
|||
{ |
|||
var clock = new MockGlobalClock(); |
|||
using (UnitTestApplication.Start(TestServices.RealFocus. |
|||
With(globalClock: clock))) |
|||
{ |
|||
var inputPane = new TestInputPane(new Rect(0, 200, 200, 200)); |
|||
|
|||
var border = new Border(); |
|||
|
|||
var paneView = new InputPaneAwareView() |
|||
{ |
|||
Child = border, |
|||
Height = 500, |
|||
Width = 200, |
|||
Behavior = InputPaneAwareBehavior.Pan |
|||
}; |
|||
|
|||
var impl = CreateMockTopLevelImpl(inputPane); |
|||
var topLevel = new TestTopLevel(impl.Object) |
|||
{ |
|||
Template = CreateTopLevelTemplate(), |
|||
Content = paneView |
|||
}; |
|||
|
|||
topLevel.LayoutManager.ExecuteInitialLayoutPass(); |
|||
|
|||
Assert.Equal(0, border.Bounds.Top); |
|||
|
|||
inputPane.Open(); |
|||
|
|||
clock.Pulse(TimeSpan.FromSeconds(5)); |
|||
|
|||
topLevel.LayoutManager.ExecuteLayoutPass(); |
|||
|
|||
Assert.Equal(-200, border.Bounds.Top); |
|||
} |
|||
} |
|||
|
|||
internal static Control CreateScrollViewerTemplate(ScrollViewer control, INameScope scope) |
|||
{ |
|||
return new Grid |
|||
{ |
|||
Children = |
|||
{ |
|||
new Decorator() |
|||
{ |
|||
Name = "PART_KeyboardAwareDecorator", |
|||
Child = new ScrollContentPresenter |
|||
{ |
|||
Name = "PART_ContentPresenter", |
|||
}.RegisterInNameScope(scope) |
|||
}.RegisterInNameScope(scope), |
|||
}, |
|||
}; |
|||
} |
|||
|
|||
static Mock<ITopLevelImpl> CreateMockTopLevelImpl(TestInputPane inputPane) |
|||
{ |
|||
var topLevel = new Mock<ITopLevelImpl>(); |
|||
topLevel.Setup(x => x.RenderScaling).Returns(1); |
|||
topLevel.Setup(x => x.Compositor).Returns(RendererMocks.CreateDummyCompositor()); |
|||
topLevel.Setup(x => x.TryGetFeature(typeof(IInputPane))).Returns(inputPane); |
|||
return topLevel; |
|||
} |
|||
|
|||
private static FuncControlTemplate<TestTopLevel> CreateTopLevelTemplate() |
|||
{ |
|||
return new FuncControlTemplate<TestTopLevel>((x, scope) => |
|||
new ContentPresenter |
|||
{ |
|||
Name = "PART_ContentPresenter", |
|||
[!ContentPresenter.ContentProperty] = x[!ContentControl.ContentProperty], |
|||
}.RegisterInNameScope(scope)); |
|||
} |
|||
|
|||
private class TestInputPane(Rect openRect) : IInputPane |
|||
{ |
|||
public InputPaneState State { get; private set; } |
|||
|
|||
public Rect OccludedRect { get; private set; } |
|||
|
|||
public event EventHandler<InputPaneStateEventArgs>? StateChanged; |
|||
|
|||
public void Open() |
|||
{ |
|||
var oldRect = OccludedRect; |
|||
OccludedRect = openRect; |
|||
|
|||
State = InputPaneState.Open; |
|||
|
|||
StateChanged?.Invoke(this, new InputPaneStateEventArgs(State, oldRect, OccludedRect)); |
|||
} |
|||
|
|||
public void Close() |
|||
{ |
|||
var oldRect = OccludedRect; |
|||
OccludedRect = default; |
|||
|
|||
State = InputPaneState.Closed; |
|||
|
|||
StateChanged?.Invoke(this, new InputPaneStateEventArgs(State, oldRect, OccludedRect)); |
|||
} |
|||
} |
|||
|
|||
private class TestTopLevel(ITopLevelImpl impl) : TopLevel(impl) |
|||
{ |
|||
|
|||
} |
|||
} |
|||
} |
|||
Loading…
Reference in new issue