// This source file is adapted from the WinUI project.
// (https://github.com/microsoft/microsoft-ui-xaml)
//
// Licensed to The Avalonia Project under MIT License, courtesy of The .NET Foundation.
using System;
namespace Avalonia.Layout
{
///
/// Defines constants that specify whether to suppress automatic recycling of the retrieved
/// element or force creation of a new element.
///
///
/// When you call ,
/// you can specify whether to suppress automatic recycling of the retrieved element or force
/// creation of a new element. Elements retrieved with automatic recycling suppressed
/// (SuppressAutoRecycle) are ignored by the automatic recycling logic that clears realized
/// elements that were not retrieved as part of the current layout pass. You must explicitly
/// recycle these elements by passing them to the RecycleElement method to avoid memory leaks.
///
[Flags]
public enum ElementRealizationOptions
{
///
/// No option is specified.
///
None = 0x0,
///
/// Creation of a new element is forced.
///
ForceCreate = 0x1,
///
/// The element is ignored by the automatic recycling logic.
///
SuppressAutoRecycle = 0x2,
};
///
/// Represents the base class for layout context types that support virtualization.
///
public abstract class VirtualizingLayoutContext : LayoutContext
{
private NonVirtualizingLayoutContext _contextAdapter;
///
/// Gets the number of items in the data.
///
///
/// This property gets the value returned by ItemCountCore, which must be implemented in
/// a derived class.
///
public int ItemCount => ItemCountCore();
///
/// Gets or sets the origin point for the estimated content size.
///
///
/// LayoutOrigin is used by virtualizing layouts that rely on estimations when determining
/// the size and position of content. It allows the layout to fix-up the estimated origin
/// of the content as it changes due to on-going estimation or potentially identifying the
/// actual size to use. For example, it’s possible that as a user is scrolling back to the
/// top of the content that the layout's estimates for the content size that it reports as
/// part of its MeasureOverride become increasingly accurate. If the predicted position of
/// the content does not already match the previously predicted position (for example, if
/// the size of the elements ends up being smaller than previously thought), then the
/// layout can indicate a new origin. The viewport provided to the layout on subsequent
/// passes will take into account the adjusted origin.
///
public Point LayoutOrigin { get => LayoutOriginCore; set => LayoutOriginCore = value; }
///
/// Gets an area that represents the viewport and buffer that the layout should fill with
/// realized elements.
///
public Rect RealizationRect => RealizationRectCore();
///
/// Gets the recommended index from which to start the generation and layout of elements.
///
///
/// The recommended index might be the result of programmatically realizing an element and
/// requesting that it be brought into view. Or, it may be that a user drags the scrollbar
/// thumb so quickly that the new viewport and the viewport and buffer previously given to
/// the layout do not intersect, so a new index is suggested as the anchor from which to
/// generate and layout other elements.
///
public int RecommendedAnchorIndex => RecommendedAnchorIndexCore;
///
/// Implements the behavior of LayoutOrigin in a derived or custom VirtualizingLayoutContext.
///
protected abstract Point LayoutOriginCore { get; set; }
///
/// Implements the behavior for getting the return value of RecommendedAnchorIndex in a
/// derived or custom .
///
protected virtual int RecommendedAnchorIndexCore { get; }
///
/// Retrieves the data item in the source found at the specified index.
///
/// The index of the data item to retrieve.
public object GetItemAt(int index) => GetItemAtCore(index);
///
/// Retrieves a UIElement that represents the data item in the source found at the
/// specified index. By default, if an element already exists, it is returned; otherwise,
/// a new element is created.
///
/// The index of the data item to retrieve a UIElement for.
///
/// This method calls
/// with options set to None. GetElementAtCore must be implemented in a derived class.
///
public ILayoutable GetOrCreateElementAt(int index)
=> GetOrCreateElementAtCore(index, ElementRealizationOptions.None);
///
/// Retrieves a UIElement that represents the data item in the source found at the
/// specified index using the specified options.
///
/// The index of the data item to retrieve a UIElement for.
///
/// A value of that specifies whether to suppress
/// automatic recycling of the retrieved element or force creation of a new element.
///
///
/// This method calls ,
/// which must be implemented in a derived class. When you request an element for the
/// specified index, you can optionally specify whether to suppress automatic recycling of
/// the retrieved element or force creation of a new element.Elements retrieved with
/// automatic recycling suppressed(SuppressAutoRecycle) are ignored by the automatic
/// recycling logic that clears realized elements that were not retrieved as part of the
/// current layout pass.You must explicitly recycle these elements by passing them to the
/// RecycleElement method to avoid memory leaks. These options are intended for more
/// advanced layouts that choose to explicitly manage the realization and recycling of
/// elements as a performance optimization.
///
public ILayoutable GetOrCreateElementAt(int index, ElementRealizationOptions options)
=> GetOrCreateElementAtCore(index, options);
///
/// Clears the specified UIElement and allows it to be either re-used or released.
///
/// The element to clear.
///
/// This method calls , which must be implemented
/// in a derived class.
///
public void RecycleElement(ILayoutable element) => RecycleElementCore(element);
///
/// When implemented in a derived class, retrieves the number of items in the data.
///
protected abstract int ItemCountCore();
///
/// When implemented in a derived class, retrieves the data item in the source found at the
/// specified index.
///
/// The index of the data item to retrieve.
protected abstract object GetItemAtCore(int index);
///
/// When implemented in a derived class, retrieves an area that represents the viewport and
/// buffer that the layout should fill with realized elements.
///
protected abstract Rect RealizationRectCore();
///
/// When implemented in a derived class, retrieves a UIElement that represents the data item
/// in the source found at the specified index using the specified options.
///
/// The index of the data item to retrieve a UIElement for.
///
/// A value of that specifies whether to suppress
/// automatic recycling of the retrieved element or force creation of a new element.
///
protected abstract ILayoutable GetOrCreateElementAtCore(int index, ElementRealizationOptions options);
///
/// When implemented in a derived class, clears the specified UIElement and allows it to be
/// either re-used or released.
///
/// The element to clear.
protected abstract void RecycleElementCore(ILayoutable element);
internal NonVirtualizingLayoutContext GetNonVirtualizingContextAdapter() =>
_contextAdapter ?? (_contextAdapter = new VirtualLayoutContextAdapter(this));
}
}