Browse Source

Implement disabling of ListBox scrollbars.

Fixes #1344.
pull/1348/head
Steven Kirk 8 years ago
parent
commit
8a80a724d7
  1. 4
      samples/VirtualizationTest/ViewModels/MainWindowViewModel.cs
  2. 12
      src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs
  3. 27
      src/Avalonia.Controls/Presenters/ItemsPresenter.cs
  4. 63
      src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs
  5. 10
      src/Avalonia.Controls/Primitives/ILogicalScrollable.cs
  6. 97
      src/Avalonia.Controls/ScrollViewer.cs
  7. 22
      src/Avalonia.Controls/TextBox.cs
  8. 2
      src/Avalonia.Controls/VirtualizingStackPanel.cs
  9. 7
      src/Avalonia.Themes.Default/ListBox.xaml
  10. 5
      src/Avalonia.Themes.Default/ScrollViewer.xaml
  11. 3
      src/Avalonia.Themes.Default/TextBox.xaml
  12. 2
      src/Avalonia.Themes.Default/TreeView.xaml
  13. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs
  14. 2
      tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs
  15. 11
      tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs
  16. 46
      tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs
  17. 30
      tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs
  18. 2
      tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs
  19. 2
      tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests_HitTesting.cs
  20. 2
      tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests_HitTesting.cs

4
samples/VirtualizationTest/ViewModels/MainWindowViewModel.cs

@ -18,8 +18,8 @@ namespace VirtualizationTest.ViewModels
private int _newItemIndex;
private IReactiveList<ItemViewModel> _items;
private string _prefix = "Item";
private ScrollBarVisibility _horizontalScrollBarVisibility;
private ScrollBarVisibility _verticalScrollBarVisibility;
private ScrollBarVisibility _horizontalScrollBarVisibility = ScrollBarVisibility.Auto;
private ScrollBarVisibility _verticalScrollBarVisibility = ScrollBarVisibility.Auto;
private Orientation _orientation = Orientation.Vertical;
private ItemVirtualizationMode _virtualizationMode = ItemVirtualizationMode.Simple;

12
src/Avalonia.Controls/Presenters/ItemVirtualizerSimple.cs

@ -5,6 +5,7 @@ using System;
using System.Collections;
using System.Collections.Specialized;
using System.Linq;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.Layout;
@ -97,6 +98,7 @@ namespace Avalonia.Controls.Presenters
/// <inheritdoc/>
public override Size MeasureOverride(Size availableSize)
{
var scrollable = (ILogicalScrollable)Owner;
var visualRoot = Owner.GetVisualRoot();
var maxAvailableSize = (visualRoot as WindowBase)?.PlatformImpl?.MaxClientSize
?? (visualRoot as TopLevel)?.ClientSize;
@ -115,7 +117,10 @@ namespace Avalonia.Controls.Presenters
}
}
availableSize = availableSize.WithWidth(double.PositiveInfinity);
if (scrollable.CanHorizontallyScroll)
{
availableSize = availableSize.WithWidth(double.PositiveInfinity);
}
}
else
{
@ -127,7 +132,10 @@ namespace Avalonia.Controls.Presenters
}
}
availableSize = availableSize.WithHeight(double.PositiveInfinity);
if (scrollable.CanVerticallyScroll)
{
availableSize = availableSize.WithHeight(double.PositiveInfinity);
}
}
Owner.Panel.Measure(availableSize);

27
src/Avalonia.Controls/Presenters/ItemsPresenter.cs

@ -23,6 +23,8 @@ namespace Avalonia.Controls.Presenters
defaultValue: ItemVirtualizationMode.None);
private ItemVirtualizer _virtualizer;
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
/// <summary>
/// Initializes static members of the <see cref="ItemsPresenter"/> class.
@ -46,6 +48,31 @@ namespace Avalonia.Controls.Presenters
set { SetValue(VirtualizationModeProperty, value); }
}
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
bool ILogicalScrollable.CanHorizontallyScroll
{
get { return _canHorizontallyScroll; }
set
{
_canHorizontallyScroll = value;
InvalidateMeasure();
}
}
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
bool ILogicalScrollable.CanVerticallyScroll
{
get { return _canVerticallyScroll; }
set
{
_canVerticallyScroll = value;
InvalidateMeasure();
}
}
/// <inheritdoc/>
bool ILogicalScrollable.IsLogicalScrollEnabled
{

63
src/Avalonia.Controls/Presenters/ScrollContentPresenter.cs

@ -17,6 +17,24 @@ namespace Avalonia.Controls.Presenters
/// </summary>
public class ScrollContentPresenter : ContentPresenter, IPresenter, IScrollable
{
/// <summary>
/// Defines the <see cref="CanHorizontallyScroll"/> property.
/// </summary>
public static readonly DirectProperty<ScrollContentPresenter, bool> CanHorizontallyScrollProperty =
AvaloniaProperty.RegisterDirect<ScrollContentPresenter, bool>(
nameof(CanHorizontallyScroll),
o => o.CanHorizontallyScroll,
(o, v) => o.CanHorizontallyScroll = v);
/// <summary>
/// Defines the <see cref="CanVerticallyScroll"/> property.
/// </summary>
public static readonly DirectProperty<ScrollContentPresenter, bool> CanVerticallyScrollProperty =
AvaloniaProperty.RegisterDirect<ScrollContentPresenter, bool>(
nameof(CanVerticallyScroll),
o => o.CanVerticallyScroll,
(o, v) => o.CanVerticallyScroll = v);
/// <summary>
/// Defines the <see cref="Extent"/> property.
/// </summary>
@ -41,12 +59,8 @@ namespace Avalonia.Controls.Presenters
o => o.Viewport,
(o, v) => o.Viewport = v);
/// <summary>
/// Defines the <see cref="CanScrollHorizontally"/> property.
/// </summary>
public static readonly StyledProperty<bool> CanScrollHorizontallyProperty =
ScrollViewer.CanScrollHorizontallyProperty.AddOwner<ScrollContentPresenter>();
private bool _canHorizontallyScroll;
private bool _canVerticallyScroll;
private Size _extent;
private Size _measuredExtent;
private Vector _offset;
@ -73,6 +87,24 @@ namespace Avalonia.Controls.Presenters
this.GetObservable(ChildProperty).Subscribe(UpdateScrollableSubscription);
}
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
public bool CanHorizontallyScroll
{
get { return _canHorizontallyScroll; }
set { SetAndRaise(CanHorizontallyScrollProperty, ref _canHorizontallyScroll, value); }
}
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
public bool CanVerticallyScroll
{
get { return _canVerticallyScroll; }
set { SetAndRaise(CanVerticallyScrollProperty, ref _canVerticallyScroll, value); }
}
/// <summary>
/// Gets the extent of the scrollable content.
/// </summary>
@ -100,11 +132,6 @@ namespace Avalonia.Controls.Presenters
private set { SetAndRaise(ViewportProperty, ref _viewport, value); }
}
/// <summary>
/// Gets a value indicating whether the content can be scrolled horizontally.
/// </summary>
public bool CanScrollHorizontally => GetValue(CanScrollHorizontallyProperty);
/// <summary>
/// Attempts to bring a portion of the target visual into view by scrolling the content.
/// </summary>
@ -182,10 +209,15 @@ namespace Avalonia.Controls.Presenters
{
measureSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
if (!CanScrollHorizontally)
if (!CanHorizontallyScroll)
{
measureSize = measureSize.WithWidth(availableSize.Width);
}
if (!CanVerticallyScroll)
{
measureSize = measureSize.WithHeight(availableSize.Height);
}
}
child.Measure(measureSize);
@ -289,7 +321,12 @@ namespace Avalonia.Controls.Presenters
if (scrollable.IsLogicalScrollEnabled == true)
{
_logicalScrollSubscription = new CompositeDisposable(
this.GetObservable(OffsetProperty).Skip(1).Subscribe(x => scrollable.Offset = x),
this.GetObservable(CanHorizontallyScrollProperty)
.Subscribe(x => scrollable.CanHorizontallyScroll = x),
this.GetObservable(CanVerticallyScrollProperty)
.Subscribe(x => scrollable.CanVerticallyScroll = x),
this.GetObservable(OffsetProperty)
.Skip(1).Subscribe(x => scrollable.Offset = x),
Disposable.Create(() => scrollable.InvalidateScroll = null));
UpdateFromScrollable(scrollable);
}

10
src/Avalonia.Controls/Primitives/ILogicalScrollable.cs

@ -19,6 +19,16 @@ namespace Avalonia.Controls.Primitives
/// </remarks>
public interface ILogicalScrollable : IScrollable
{
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
bool CanHorizontallyScroll { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the content can be scrolled horizontally.
/// </summary>
bool CanVerticallyScroll { get; set; }
/// <summary>
/// Gets a value indicating whether logical scrolling is enabled on the control.
/// </summary>

97
src/Avalonia.Controls/ScrollViewer.cs

@ -2,8 +2,6 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using System.Reactive.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
@ -15,16 +13,34 @@ namespace Avalonia.Controls
public class ScrollViewer : ContentControl, IScrollable
{
/// <summary>
/// Defines the <see cref="CanScrollHorizontally"/> property.
/// Defines the <see cref="CanHorizontallyScroll"/> property.
/// </summary>
public static readonly StyledProperty<bool> CanScrollHorizontallyProperty =
AvaloniaProperty.Register<ScrollViewer, bool>(nameof(CanScrollHorizontally), true);
/// <remarks>
/// There is no public C# accessor for this property as it is intended to be bound to by a
/// <see cref="ScrollContentPresenter"/> in the control's template.
/// </remarks>
public static readonly DirectProperty<ScrollViewer, bool> CanHorizontallyScrollProperty =
AvaloniaProperty.RegisterDirect<ScrollViewer, bool>(
nameof(CanHorizontallyScroll),
o => o.CanHorizontallyScroll);
/// <summary>
/// Defines the <see cref="CanVerticallyScroll"/> property.
/// </summary>
/// <remarks>
/// There is no public C# accessor for this property as it is intended to be bound to by a
/// <see cref="ScrollContentPresenter"/> in the control's template.
/// </remarks>
public static readonly DirectProperty<ScrollViewer, bool> CanVerticallyScrollProperty =
AvaloniaProperty.RegisterDirect<ScrollViewer, bool>(
nameof(CanVerticallyScroll),
o => o.CanVerticallyScroll);
/// <summary>
/// Defines the <see cref="Extent"/> property.
/// </summary>
public static readonly DirectProperty<ScrollViewer, Size> ExtentProperty =
AvaloniaProperty.RegisterDirect<ScrollViewer, Size>(nameof(Extent),
AvaloniaProperty.RegisterDirect<ScrollViewer, Size>(nameof(Extent),
o => o.Extent,
(o, v) => o.Extent = v);
@ -41,7 +57,7 @@ namespace Avalonia.Controls
/// Defines the <see cref="Viewport"/> property.
/// </summary>
public static readonly DirectProperty<ScrollViewer, Size> ViewportProperty =
AvaloniaProperty.RegisterDirect<ScrollViewer, Size>(nameof(Viewport),
AvaloniaProperty.RegisterDirect<ScrollViewer, Size>(nameof(Viewport),
o => o.Viewport,
(o, v) => o.Viewport = v);
@ -85,14 +101,10 @@ namespace Avalonia.Controls
/// <summary>
/// Defines the <see cref="HorizontalScrollBarVisibility"/> property.
/// </summary>
/// <remarks>
/// There is no public C# accessor for this property as it is intended to be bound to by a
/// <see cref="ScrollContentPresenter"/> in the control's template.
/// </remarks>
public static readonly AttachedProperty<ScrollBarVisibility> HorizontalScrollBarVisibilityProperty =
AvaloniaProperty.RegisterAttached<ScrollViewer, Control, ScrollBarVisibility>(
nameof(HorizontalScrollBarVisibility),
ScrollBarVisibility.Auto);
ScrollBarVisibility.Hidden);
/// <summary>
/// Defines the VerticalScrollBarMaximum property.
@ -136,7 +148,7 @@ namespace Avalonia.Controls
/// </summary>
public static readonly AttachedProperty<ScrollBarVisibility> VerticalScrollBarVisibilityProperty =
AvaloniaProperty.RegisterAttached<ScrollViewer, Control, ScrollBarVisibility>(
nameof(VerticalScrollBarVisibility),
nameof(VerticalScrollBarVisibility),
ScrollBarVisibility.Auto);
private Size _extent;
@ -150,6 +162,8 @@ namespace Avalonia.Controls
{
AffectsValidation(ExtentProperty, OffsetProperty);
AffectsValidation(ViewportProperty, OffsetProperty);
HorizontalScrollBarVisibilityProperty.Changed.AddClassHandler<ScrollViewer>(x => x.ScrollBarVisibilityChanged);
VerticalScrollBarVisibilityProperty.Changed.AddClassHandler<ScrollViewer>(x => x.ScrollBarVisibilityChanged);
}
/// <summary>
@ -218,15 +232,6 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Gets a value indicating whether the content can be scrolled horizontally.
/// </summary>
public bool CanScrollHorizontally
{
get { return GetValue(CanScrollHorizontallyProperty); }
set { SetValue(CanScrollHorizontallyProperty, value); }
}
/// <summary>
/// Gets or sets the horizontal scrollbar visibility.
/// </summary>
@ -245,6 +250,22 @@ namespace Avalonia.Controls
set { SetValue(VerticalScrollBarVisibilityProperty, value); }
}
/// <summary>
/// Gets a value indicating whether the viewer can scroll horizontally.
/// </summary>
protected bool CanHorizontallyScroll
{
get { return HorizontalScrollBarVisibility != ScrollBarVisibility.Disabled; }
}
/// <summary>
/// Gets a value indicating whether the viewer can scroll vertically.
/// </summary>
protected bool CanVerticallyScroll
{
get { return VerticalScrollBarVisibility != ScrollBarVisibility.Disabled; }
}
/// <summary>
/// Gets the maximum horizontal scrollbar value.
/// </summary>
@ -316,7 +337,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="control">The control to read the value from.</param>
/// <returns>The value of the property.</returns>
public ScrollBarVisibility GetHorizontalScrollBarVisibility(Control control)
public static ScrollBarVisibility GetHorizontalScrollBarVisibility(Control control)
{
return control.GetValue(HorizontalScrollBarVisibilityProperty);
}
@ -326,7 +347,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="control">The control to set the value on.</param>
/// <param name="value">The value of the property.</param>
public void SetHorizontalScrollBarVisibility(Control control, ScrollBarVisibility value)
public static void SetHorizontalScrollBarVisibility(Control control, ScrollBarVisibility value)
{
control.SetValue(HorizontalScrollBarVisibilityProperty, value);
}
@ -336,7 +357,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="control">The control to read the value from.</param>
/// <returns>The value of the property.</returns>
public ScrollBarVisibility GetVerticalScrollBarVisibility(Control control)
public static ScrollBarVisibility GetVerticalScrollBarVisibility(Control control)
{
return control.GetValue(VerticalScrollBarVisibilityProperty);
}
@ -346,7 +367,7 @@ namespace Avalonia.Controls
/// </summary>
/// <param name="control">The control to set the value on.</param>
/// <param name="value">The value of the property.</param>
public void SetVerticalScrollBarVisibility(Control control, ScrollBarVisibility value)
public static void SetVerticalScrollBarVisibility(Control control, ScrollBarVisibility value)
{
control.SetValue(VerticalScrollBarVisibilityProperty, value);
}
@ -385,6 +406,30 @@ namespace Avalonia.Controls
}
}
private void ScrollBarVisibilityChanged(AvaloniaPropertyChangedEventArgs e)
{
var wasEnabled = !ScrollBarVisibility.Disabled.Equals(e.OldValue);
var isEnabled = !ScrollBarVisibility.Disabled.Equals(e.NewValue);
if (wasEnabled != isEnabled)
{
if (e.Property == HorizontalScrollBarVisibilityProperty)
{
RaisePropertyChanged(
CanHorizontallyScrollProperty,
wasEnabled,
isEnabled);
}
else if (e.Property == VerticalScrollBarVisibilityProperty)
{
RaisePropertyChanged(
CanVerticallyScrollProperty,
wasEnabled,
isEnabled);
}
}
}
private void CalculatedPropertiesChanged()
{
// Pass old values of 0 here because we don't have the old values at this point,

22
src/Avalonia.Controls/TextBox.cs

@ -8,7 +8,6 @@ using System.Linq;
using System.Reactive.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.Interactivity;
@ -26,9 +25,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty<bool> AcceptsTabProperty =
AvaloniaProperty.Register<TextBox, bool>(nameof(AcceptsTab));
public static readonly DirectProperty<TextBox, bool> CanScrollHorizontallyProperty =
AvaloniaProperty.RegisterDirect<TextBox, bool>(nameof(CanScrollHorizontally), o => o.CanScrollHorizontally);
public static readonly DirectProperty<TextBox, int> CaretIndexProperty =
AvaloniaProperty.RegisterDirect<TextBox, int>(
nameof(CaretIndex),
@ -92,7 +88,6 @@ namespace Avalonia.Controls
private int _caretIndex;
private int _selectionStart;
private int _selectionEnd;
private bool _canScrollHorizontally;
private TextPresenter _presenter;
private UndoRedoHelper<UndoRedoState> _undoRedoHelper;
private bool _ignoreTextChanges;
@ -106,12 +101,11 @@ namespace Avalonia.Controls
public TextBox()
{
this.GetObservable(TextWrappingProperty)
.Select(x => x == TextWrapping.NoWrap)
.Subscribe(x => CanScrollHorizontally = x);
var horizontalScrollBarVisibility = this.GetObservable(AcceptsReturnProperty)
.Select(x => x ? ScrollBarVisibility.Auto : ScrollBarVisibility.Hidden);
var horizontalScrollBarVisibility = Observable.CombineLatest(
this.GetObservable(AcceptsReturnProperty),
this.GetObservable(TextWrappingProperty),
(acceptsReturn, wrapping) => acceptsReturn && wrapping == TextWrapping.NoWrap ?
ScrollBarVisibility.Auto : ScrollBarVisibility.Disabled);
Bind(
ScrollViewer.HorizontalScrollBarVisibilityProperty,
@ -132,12 +126,6 @@ namespace Avalonia.Controls
set { SetValue(AcceptsTabProperty, value); }
}
public bool CanScrollHorizontally
{
get { return _canScrollHorizontally; }
private set { SetAndRaise(CanScrollHorizontallyProperty, ref _canScrollHorizontally, value); }
}
public int CaretIndex
{
get

2
src/Avalonia.Controls/VirtualizingStackPanel.cs

@ -3,11 +3,9 @@
using System;
using System.Collections.Specialized;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.VisualTree;
namespace Avalonia.Controls
{

7
src/Avalonia.Themes.Default/ListBox.xaml

@ -3,11 +3,16 @@
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/>
<Setter Property="BorderThickness" Value="{DynamicResource ThemeBorderThickness}"/>
<Setter Property="Padding" Value="4"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Template">
<ControlTemplate>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer Name="PART_ScrollViewer" Background="{TemplateBinding Background}">
<ScrollViewer Name="PART_ScrollViewer"
Background="{TemplateBinding Background}"
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
<ItemsPresenter Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"

5
src/Avalonia.Themes.Default/ScrollViewer.xaml

@ -6,12 +6,13 @@
<Grid ColumnDefinitions="*,Auto" RowDefinitions="*,Auto">
<ScrollContentPresenter Name="PART_ContentPresenter"
Background="{TemplateBinding Background}"
CanHorizontallyScroll="{TemplateBinding CanHorizontallyScroll}"
CanVerticallyScroll="{TemplateBinding CanVerticallyScroll}"
Content="{TemplateBinding Content}"
Extent="{TemplateBinding Path=Extent, Mode=TwoWay}"
Margin="{TemplateBinding Padding}"
Offset="{TemplateBinding Path=Offset, Mode=TwoWay}"
Viewport="{TemplateBinding Path=Viewport, Mode=TwoWay}"
CanScrollHorizontally="{TemplateBinding CanScrollHorizontally}"/>
Viewport="{TemplateBinding Path=Viewport, Mode=TwoWay}"/>
<ScrollBar Name="horizontalScrollBar"
Orientation="Horizontal"
Maximum="{TemplateBinding HorizontalScrollBarMaximum}"

3
src/Avalonia.Themes.Default/TextBox.xaml

@ -36,8 +36,7 @@
<Path Data="M14,7 A7,7 0 0,0 0,7 M0,7 A7,7 0 1,0 14,7 M7,3l0,5 M7,9l0,2" Stroke="{DynamicResource ErrorBrush}" StrokeThickness="2"/>
</Canvas>
<ScrollViewer CanScrollHorizontally="{TemplateBinding CanScrollHorizontally}"
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
<ScrollViewer HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}">
<Panel>

2
src/Avalonia.Themes.Default/TreeView.xaml

@ -7,7 +7,7 @@
<ControlTemplate>
<Border BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ScrollViewer CanScrollHorizontally="True" Background="{TemplateBinding Background}">
<ScrollViewer Background="{TemplateBinding Background}">
<ItemsPresenter Name="PART_ItemsPresenter"
Items="{TemplateBinding Items}"
ItemsPanel="{TemplateBinding ItemsPanel}"

2
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization.cs

@ -281,6 +281,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
var scroller = new TestScroller
{
CanHorizontallyScroll = false,
CanVerticallyScroll = true,
Content = result = new TestItemsPresenter(useContainers)
{
Items = items,

2
tests/Avalonia.Controls.UnitTests/Presenters/ItemsPresenterTests_Virtualization_Simple.cs

@ -998,6 +998,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
var scroller = new TestScroller
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = result = new TestItemsPresenter(useContainers)
{
Items = items,

11
tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests.cs

@ -5,6 +5,7 @@ using System;
using System.Collections.Generic;
using System.Reactive.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Layout;
using Xunit;
@ -118,6 +119,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
TestControl content;
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = content = new TestControl(),
};
@ -134,6 +137,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
Border content;
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = content = new Border
{
Width = 150,
@ -155,8 +160,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
var child = new TestControl();
var target = new ScrollContentPresenter
{
CanVerticallyScroll = true,
Content = child,
[ScrollContentPresenter.CanScrollHorizontallyProperty] = false,
};
target.UpdateChild();
@ -171,6 +176,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
var child = new TestControl();
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = child,
};
@ -246,6 +253,8 @@ namespace Avalonia.Controls.UnitTests.Presenters
Border border;
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Width = 100,
Height = 100,
Content = new Decorator

46
tests/Avalonia.Controls.UnitTests/Presenters/ScrollContentPresenterTests_ILogicalScrollable.cs

@ -13,7 +13,7 @@ namespace Avalonia.Controls.UnitTests
public class ScrollContentPresenterTests_ILogicalScrollable
{
[Fact]
public void Measure_Should_Pass_Unchanged_Bounds_To_IScrollable()
public void Measure_Should_Pass_Unchanged_Bounds_To_ILogicalScrollable()
{
var scrollable = new TestScrollable();
var target = new ScrollContentPresenter
@ -28,7 +28,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Arrange_Should_Not_Offset_IScrollable_Bounds()
public void Arrange_Should_Not_Offset_ILogicalScrollable_Bounds()
{
var scrollable = new TestScrollable
{
@ -50,7 +50,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Arrange_Should_Offset_IScrollable_Bounds_When_Logical_Scroll_Disabled()
public void Arrange_Should_Offset_ILogicalScrollable_Bounds_When_Logical_Scroll_Disabled()
{
var scrollable = new TestScrollable
{
@ -59,6 +59,8 @@ namespace Avalonia.Controls.UnitTests
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = scrollable,
Offset = new Vector(25, 25),
};
@ -71,7 +73,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Arrange_Should_Not_Set_Viewport_And_Extent_With_IScrollable()
public void Arrange_Should_Not_Set_Viewport_And_Extent_With_ILogicalScrollable()
{
var target = new ScrollContentPresenter
{
@ -122,7 +124,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Extent_Offset_And_Viewport_Should_Be_Read_From_IScrollable()
public void Extent_Offset_And_Viewport_Should_Be_Read_From_ILogicalScrollable()
{
var scrollable = new TestScrollable
{
@ -152,7 +154,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Offset_Should_Be_Written_To_IScrollable()
public void Offset_Should_Be_Written_To_ILogicalScrollable()
{
var scrollable = new TestScrollable
{
@ -172,7 +174,7 @@ namespace Avalonia.Controls.UnitTests
}
[Fact]
public void Offset_Should_Not_Be_Written_To_IScrollable_After_Removal()
public void Offset_Should_Not_Be_Written_To_ILogicalScrollable_After_Removal()
{
var scrollable = new TestScrollable
{
@ -203,6 +205,8 @@ namespace Avalonia.Controls.UnitTests
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = scrollable,
};
@ -253,6 +257,8 @@ namespace Avalonia.Controls.UnitTests
var target = new ScrollContentPresenter
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = logicalScrollable,
};
@ -286,12 +292,38 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Rect(0, 0, 100, 100), logicalScrollable.Bounds);
}
[Fact]
public void Should_Set_ILogicalScrolable_CanHorizontallyScroll()
{
var logicalScrollable = new TestScrollable();
var target = new ScrollContentPresenter { Content = logicalScrollable };
target.UpdateChild();
Assert.False(logicalScrollable.CanHorizontallyScroll);
target.CanHorizontallyScroll = true;
Assert.True(logicalScrollable.CanHorizontallyScroll);
}
[Fact]
public void Should_Set_ILogicalScrolable_CanVerticallyScroll()
{
var logicalScrollable = new TestScrollable();
var target = new ScrollContentPresenter { Content = logicalScrollable };
target.UpdateChild();
Assert.False(logicalScrollable.CanVerticallyScroll);
target.CanVerticallyScroll = true;
Assert.True(logicalScrollable.CanVerticallyScroll);
}
private class TestScrollable : Control, ILogicalScrollable
{
private Size _extent;
private Vector _offset;
private Size _viewport;
public bool CanHorizontallyScroll { get; set; }
public bool CanVerticallyScroll { get; set; }
public bool IsLogicalScrollEnabled { get; set; } = true;
public Size AvailableSize { get; private set; }
public Action InvalidateScroll { get; set; }

30
tests/Avalonia.Controls.UnitTests/ScrollViewerTests.cs

@ -1,6 +1,8 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
@ -25,6 +27,32 @@ namespace Avalonia.Controls.UnitTests
Assert.IsType<TextBlock>(target.Presenter.Child);
}
[Fact]
public void CanHorizontallyScroll_Should_Track_HorizontalScrollBarVisibility()
{
var target = new ScrollViewer();
var values = new List<bool>();
target.GetObservable(ScrollViewer.CanHorizontallyScrollProperty).Subscribe(x => values.Add(x));
target.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
target.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
Assert.Equal(new[] { true, false, true }, values);
}
[Fact]
public void CanVerticallyScroll_Should_Track_VerticalScrollBarVisibility()
{
var target = new ScrollViewer();
var values = new List<bool>();
target.GetObservable(ScrollViewer.CanVerticallyScrollProperty).Subscribe(x => values.Add(x));
target.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
target.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
Assert.Equal(new[] { true, false, true }, values);
}
[Fact]
public void Offset_Should_Be_Coerced_To_Viewport()
{
@ -59,7 +87,7 @@ namespace Avalonia.Controls.UnitTests
[~~ScrollContentPresenter.ExtentProperty] = control[~~ScrollViewer.ExtentProperty],
[~~ScrollContentPresenter.OffsetProperty] = control[~~ScrollViewer.OffsetProperty],
[~~ScrollContentPresenter.ViewportProperty] = control[~~ScrollViewer.ViewportProperty],
[~ScrollContentPresenter.CanScrollHorizontallyProperty] = control[~ScrollViewer.CanScrollHorizontallyProperty],
[~ScrollContentPresenter.CanHorizontallyScrollProperty] = control[~ScrollViewer.CanHorizontallyScrollProperty],
},
new ScrollBar
{

2
tests/Avalonia.Layout.UnitTests/FullLayoutTests.cs

@ -85,7 +85,7 @@ namespace Avalonia.Layout.UnitTests
{
Width = 200,
Height = 200,
CanScrollHorizontally = true,
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
Content = textBlock = new TextBlock

2
tests/Avalonia.Visuals.UnitTests/Rendering/DeferredRendererTests_HitTesting.cs

@ -372,6 +372,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
Margin = new Thickness(0, 100, 0, 0),
Child = scroll = new ScrollContentPresenter()
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = new StackPanel()
{
Children =

2
tests/Avalonia.Visuals.UnitTests/Rendering/ImmediateRendererTests_HitTesting.cs

@ -357,6 +357,8 @@ namespace Avalonia.Visuals.UnitTests.Rendering
Margin = new Thickness(0, 100, 0, 0),
Child = scroll = new ScrollContentPresenter()
{
CanHorizontallyScroll = true,
CanVerticallyScroll = true,
Content = new StackPanel()
{
Children =

Loading…
Cancel
Save