// 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;
using System.Collections.Specialized;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Utils;
using Avalonia.Input;
using Avalonia.VisualTree;
namespace Avalonia.Controls.Presenters
{
///
/// Base class for classes which handle virtualization for an .
///
internal abstract class ItemVirtualizer : IVirtualizingController, IDisposable
{
private bool disposedValue;
///
/// Initializes a new instance of the class.
///
///
public ItemVirtualizer(ItemsPresenter owner)
{
Owner = owner;
Items = owner.Items;
ItemCount = owner.Items.Count();
}
///
/// Gets the which owns the virtualizer.
///
public ItemsPresenter Owner { get; }
///
/// Gets the which will host the items.
///
public IVirtualizingPanel VirtualizingPanel => Owner.Panel as IVirtualizingPanel;
///
/// Gets the items to display.
///
public IEnumerable Items { get; private set; }
///
/// Gets the number of items in .
///
public int ItemCount { get; private set; }
///
/// Gets or sets the index of the first item displayed in the panel.
///
public int FirstIndex { get; protected set; }
///
/// Gets or sets the index of the first item beyond those displayed in the panel.
///
public int NextIndex { get; protected set; }
///
/// Gets a value indicating whether the items should be scroll horizontally or vertically.
///
public bool Vertical => VirtualizingPanel.ScrollDirection == Orientation.Vertical;
///
/// Gets a value indicating whether logical scrolling is enabled.
///
public abstract bool IsLogicalScrollEnabled { get; }
///
/// Gets the value of the scroll extent.
///
public abstract double ExtentValue { get; }
///
/// Gets or sets the value of the current scroll offset.
///
public abstract double OffsetValue { get; set; }
///
/// Gets the value of the scrollable viewport.
///
public abstract double ViewportValue { get; }
///
/// Gets the as a .
///
public Size Extent => Vertical ? new Size(0, ExtentValue) : new Size(ExtentValue, 0);
///
/// Gets the as a .
///
public Size Viewport => Vertical ? new Size(0, ViewportValue) : new Size(ViewportValue, 0);
///
/// Gets or sets the as a .
///
public Vector Offset
{
get
{
return Vertical ? new Vector(0, OffsetValue) : new Vector(OffsetValue, 0);
}
set
{
OffsetValue = Vertical ? value.Y : value.X;
}
}
///
/// Creates an based on an item presenter's
/// .
///
/// The items presenter.
/// An .
public static ItemVirtualizer Create(ItemsPresenter owner)
{
var virtualizingPanel = owner.Panel as IVirtualizingPanel;
var scrollable = (ILogicalScrollable)owner;
ItemVirtualizer result = null;
if (virtualizingPanel != null && scrollable.InvalidateScroll != null)
{
switch (owner.VirtualizationMode)
{
case ItemVirtualizationMode.Simple:
result = new ItemVirtualizerSimple(owner);
break;
}
}
if (result == null)
{
result = new ItemVirtualizerNone(owner);
}
if (virtualizingPanel != null)
{
virtualizingPanel.Controller = result;
}
return result;
}
///
public virtual void UpdateControls()
{
}
///
/// Gets the next control in the specified direction.
///
/// The movement direction.
/// The control from which movement begins.
/// The control.
public virtual IControl GetControlInDirection(NavigationDirection direction, IControl from)
{
return null;
}
///
/// Called when the items for the presenter change, either because
/// has been set, the items collection has been
/// modified, or the panel has been created.
///
/// The items.
/// A description of the change.
public virtual void ItemsChanged(IEnumerable items, NotifyCollectionChangedEventArgs e)
{
Items = items;
ItemCount = items.Count();
}
///
/// Scrolls the specified item into view.
///
/// The item.
public virtual void ScrollIntoView(object item)
{
}
///
public virtual void Dispose()
{
if (VirtualizingPanel != null)
{
VirtualizingPanel.Controller = null;
VirtualizingPanel.Children.Clear();
}
Owner.ItemContainerGenerator.Clear();
}
///
/// Invalidates the current scroll.
///
protected void InvalidateScroll() => ((ILogicalScrollable)Owner).InvalidateScroll();
}
}