Skip to content

Commit

Permalink
feat(calendar): Enable phase loading
Browse files Browse the repository at this point in the history
  • Loading branch information
dr1rrb committed Jun 1, 2021
1 parent 1589851 commit 0badfcf
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 31 deletions.
5 changes: 4 additions & 1 deletion src/Uno.UI/DirectUI/BudgetManager.uno.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ partial class BudgetManager
{
public int GetElapsedMilliSecondsSinceLastUITick()
{
throw new NotImplementedException();
// This method is use to re-dispatch a work item to the next dispatcher loop if we are about to freeze UI for too long
// (40 ms are allowed, cf CalendarViewGeneratorMonthViewHost.BUDGET_MANAGER_DEFAULT_LIMIT)

return 1;
}
}
}
3 changes: 3 additions & 0 deletions src/Uno.UI/DirectUI/DXamlCore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ public void RegisterWork(ITreeBuilder treeBuilder)
return;
}
treeBuilder.IsRegisteredForCallbacks = false;
var workerHasWorkLeft = treeBuilder.BuildTree();
if (workerHasWorkLeft)
{
var workerReRegistered = treeBuilder.IsRegisteredForCallbacks;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ internal CalendarViewDayItemChangingEventArgs GetBuildTreeArgs()
{
CalendarViewDayItemChangingEventArgs spArgs;

spArgs = default;
spArgs = new CalendarViewDayItemChangingEventArgs();
m_tpBuildTreeArgs = spArgs;
pspArgs = spArgs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ internal virtual void PrepareItemContainer(
return;
}

internal void ClearContainerForItem(
internal virtual void ClearContainerForItem(
DependencyObject pContainer,
object pItem)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.Globalization;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
Expand All @@ -14,5 +15,17 @@ partial class CalendarViewGeneratorHost : IDirectManipulationStateChangeHandler
internal DateTime GetMinDateOfCurrentScope() { return m_minDateOfCurrentScope; }
internal DateTime GetMaxDateOfCurrentScope() { return m_maxDateOfCurrentScope; }
internal string GetHeaderTextOfCurrentScope() { return m_pHeaderText; }

internal virtual void SetupContainerContentChangingAfterPrepare(
DependencyObject pContainer,
object pItem,
int itemIndex,
Size measureSize)
{ }

internal virtual void RaiseContainerContentChangingOnRecycle(
UIElement pContainer,
object pItem)
{ }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ internal override void UpdateLabel(CalendarViewBaseItem pItem, bool isLabelVisib
}

// reset CIC event if the container is being cleared.
private void ClearContainerForItem(
internal override void ClearContainerForItem(
DependencyObject pContainer,
object pItem)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#nullable enable

// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License. See LICENSE in the project root for license information.

Expand All @@ -18,9 +20,9 @@ partial class CalendarViewGeneratorMonthViewHost : ITreeBuilder
// the CalendarView version removes UIPlaceHolder and handles blackout state.
// Other logicals are still same as ListViewBase.

private void SetupContainerContentChangingAfterPrepare(
internal override void SetupContainerContentChangingAfterPrepare(
DependencyObject pContainer,
DependencyObject pItem,
object pItem,
int itemIndex,
Size measureSize)
{
Expand Down Expand Up @@ -49,6 +51,12 @@ private void SetupContainerContentChangingAfterPrepare(
spArgsConcrete = spArgs as CalendarViewDayItemChangingEventArgs;
}

// Uno only null-ref fix:
if (pVirtualizationInformation is null || spArgsConcrete is null)
{
return;
}

// store the size we would measure with
pVirtualizationInformation.MeasureSize = measureSize;

Expand Down Expand Up @@ -202,9 +210,9 @@ bool ITreeBuilder.BuildTree()
return pWorkLeft;
}

private void RaiseContainerContentChangingOnRecycle(
internal override void RaiseContainerContentChangingOnRecycle(
UIElement pContainer,
DependencyObject pItem)
object pItem)
{
CalendarViewDayItemChangingEventArgs spArgs;
CalendarViewDayItemChangingEventArgs spArgsConcrete;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)
return unusedEntries;
}

internal (UIElement container, bool isNew) GetOrCreate(int index)
internal (CacheEntry entry, CacheEntryKind kind) GetOrCreate(int index)
{
Debug.Assert(_host is { });
Debug.Assert(_generationStartIndex <= index);
Expand Down Expand Up @@ -223,7 +223,7 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)

Debug.Assert(entry.Index == index);

return (entry.Container, false);
return (entry, CacheEntryKind.Kept);
}

case GenerationState.Before:
Expand All @@ -233,19 +233,19 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)
var item = _host![index];

CacheEntry entry;
bool isNew;
CacheEntryKind kind;
if (_generationRecyclableBefore.count > 0)
{
entry = _entries[_generationRecyclableBefore.at];
isNew = false;
kind = CacheEntryKind.Recycled;

_generationRecyclableBefore.at++;
_generationRecyclableBefore.count--;
}
else if (_generationRecyclableAfter.count > 0)
{
entry = _entries[_generationRecyclableAfter.at + _generationRecyclableAfter.count - 1];
isNew = false;
kind = CacheEntryKind.Recycled;

_generationRecyclableAfter.count--;

Expand All @@ -255,7 +255,7 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)
{
var container = (UIElement)_host.GetContainerForItem(item, null);
entry = new CacheEntry(container);
isNew = true;
kind = CacheEntryKind.New;

_entries.Add(entry);
}
Expand All @@ -265,7 +265,7 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)

_host.PrepareItemContainer(entry.Container, item);

return (entry.Container, isNew);
return (entry, kind);
}
}

Expand Down Expand Up @@ -309,6 +309,13 @@ private class CacheEntryComparer : IComparer<CacheEntry>
public int Compare(CacheEntry x, CacheEntry y) => x.Index.CompareTo(y.Index);
}

private enum CacheEntryKind
{
New,
Kept,
Recycled
}

internal event VisibleIndicesUpdatedEventCallback VisibleIndicesUpdated;

private readonly ContainersCache _cache = new ContainersCache();
Expand All @@ -328,8 +335,8 @@ private void base_Initialize()
#region Private and internal API required by UWP code
internal int FirstVisibleIndexBase { get; private set; }
internal int LastVisibleIndexBase { get; private set; }
internal int FirstCacheIndexBase { get; private set; }
internal int LastCacheIndexBase { get; private set; }
internal int FirstCacheIndexBase => _cache.StartIndex;
internal int LastCacheIndexBase => _cache.EndIndex;

[NotImplemented]
internal PanelScrollingDirection PanningDirectionBase { get; } = PanelScrollingDirection.None;
Expand Down Expand Up @@ -370,14 +377,10 @@ internal void ScrollItemIntoView(int index, ScrollIntoViewAlignment alignment, d
}

private Size GetViewportSize()
{
return _lastLayoutedViewport.Size.AtLeast(_defaultHardCodedSize).FiniteOrDefault(_defaultHardCodedSize);
}
=> _lastLayoutedViewport.Size.AtLeast(_defaultHardCodedSize).FiniteOrDefault(_defaultHardCodedSize);

internal Size GetDesiredViewportSize()
{
return _layoutStrategy.GetDesiredViewportSize();
}
=> _layoutStrategy?.GetDesiredViewportSize() ?? default;

[NotImplemented]
internal void GetTargetIndexFromNavigationAction(
Expand All @@ -396,9 +399,7 @@ internal void GetTargetIndexFromNavigationAction(
}

internal IItemContainerMapping GetItemContainerMapping()
{
throw new NotImplementedException();
}
=> _cache;

private void SetLayoutStrategyBase(CalendarLayoutStrategy spLayoutStrategy)
{
Expand Down Expand Up @@ -463,10 +464,10 @@ private Size base_MeasureOverride(Size availableSize)
|| _layoutStrategy.ShouldContinueFillingUpSpace(ElementType.ItemContainer, index, layout, remainingWindowToFill))
)
{
var (container, isNew) = _cache.GetOrCreate(index);
if (isNew)
var (entry, kind) = _cache.GetOrCreate(index);
if (kind == CacheEntryKind.New)
{
Children.Add(container);
Children.Add(entry.Container);
}

var itemSize = _layoutStrategy.GetElementMeasureSize(ElementType.ItemContainer, index, renderWindow); // Note: It's actually the same for all items
Expand All @@ -480,8 +481,19 @@ private Size base_MeasureOverride(Size availableSize)
return default;
}

container.Measure(itemSize);
container.GetVirtualizationInformation().MeasureSize = itemSize;
entry.Container.Measure(itemSize);
entry.Container.GetVirtualizationInformation().MeasureSize = itemSize;
switch (kind)
{
case CacheEntryKind.New:
_host.SetupContainerContentChangingAfterPrepare(entry.Container, entry.Item, entry.Index, itemSize);
break;

case CacheEntryKind.Recycled:
// Note: ModernBasePanel seems to use only SetupContainerContentChangingAfterPrepare
_host.RaiseContainerContentChangingOnRecycle(entry.Container, entry.Item);
break;
}

var isVisible = viewport.Contains(itemBounds.Location);
if (firstVisibleIndex == -1 && isVisible)
Expand Down

0 comments on commit 0badfcf

Please sign in to comment.