// 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)); } }