Skip to content

Commit 0badfcf

Browse files
committed
feat(calendar): Enable phase loading
1 parent 1589851 commit 0badfcf

8 files changed

+70
-31
lines changed

src/Uno.UI/DirectUI/BudgetManager.uno.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ partial class BudgetManager
77
{
88
public int GetElapsedMilliSecondsSinceLastUITick()
99
{
10-
throw new NotImplementedException();
10+
// 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
11+
// (40 ms are allowed, cf CalendarViewGeneratorMonthViewHost.BUDGET_MANAGER_DEFAULT_LIMIT)
12+
13+
return 1;
1114
}
1215
}
1316
}

src/Uno.UI/DirectUI/DXamlCore.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ public void RegisterWork(ITreeBuilder treeBuilder)
4646
return;
4747
}
4848

49+
treeBuilder.IsRegisteredForCallbacks = false;
50+
4951
var workerHasWorkLeft = treeBuilder.BuildTree();
52+
5053
if (workerHasWorkLeft)
5154
{
5255
var workerReRegistered = treeBuilder.IsRegisteredForCallbacks;

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/CalendarViewDayItem.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ internal CalendarViewDayItemChangingEventArgs GetBuildTreeArgs()
5656
{
5757
CalendarViewDayItemChangingEventArgs spArgs;
5858

59-
spArgs = default;
59+
spArgs = new CalendarViewDayItemChangingEventArgs();
6060
m_tpBuildTreeArgs = spArgs;
6161
pspArgs = spArgs;
6262
}

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ internal virtual void PrepareItemContainer(
160160
return;
161161
}
162162

163-
internal void ClearContainerForItem(
163+
internal virtual void ClearContainerForItem(
164164
DependencyObject pContainer,
165165
object pItem)
166166
{

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorHost.h.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using Windows.Foundation;
34
using Windows.Globalization;
45
using Windows.UI.Xaml.Controls.Primitives;
56
using Windows.UI.Xaml.Data;
@@ -14,5 +15,17 @@ partial class CalendarViewGeneratorHost : IDirectManipulationStateChangeHandler
1415
internal DateTime GetMinDateOfCurrentScope() { return m_minDateOfCurrentScope; }
1516
internal DateTime GetMaxDateOfCurrentScope() { return m_maxDateOfCurrentScope; }
1617
internal string GetHeaderTextOfCurrentScope() { return m_pHeaderText; }
18+
19+
internal virtual void SetupContainerContentChangingAfterPrepare(
20+
DependencyObject pContainer,
21+
object pItem,
22+
int itemIndex,
23+
Size measureSize)
24+
{ }
25+
26+
internal virtual void RaiseContainerContentChangingOnRecycle(
27+
UIElement pContainer,
28+
object pItem)
29+
{ }
1730
}
1831
}

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorMonthViewHost.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ internal override void UpdateLabel(CalendarViewBaseItem pItem, bool isLabelVisib
137137
}
138138

139139
// reset CIC event if the container is being cleared.
140-
private void ClearContainerForItem(
140+
internal override void ClearContainerForItem(
141141
DependencyObject pContainer,
142142
object pItem)
143143
{

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/CalendarViewGeneratorMonthViewHost_ContainerPhase.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#nullable enable
2+
13
// Copyright (c) Microsoft Corporation. All rights reserved.
24
// Licensed under the MIT License. See LICENSE in the project root for license information.
35

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

21-
private void SetupContainerContentChangingAfterPrepare(
23+
internal override void SetupContainerContentChangingAfterPrepare(
2224
DependencyObject pContainer,
23-
DependencyObject pItem,
25+
object pItem,
2426
int itemIndex,
2527
Size measureSize)
2628
{
@@ -49,6 +51,12 @@ private void SetupContainerContentChangingAfterPrepare(
4951
spArgsConcrete = spArgs as CalendarViewDayItemChangingEventArgs;
5052
}
5153

54+
// Uno only null-ref fix:
55+
if (pVirtualizationInformation is null || spArgsConcrete is null)
56+
{
57+
return;
58+
}
59+
5260
// store the size we would measure with
5361
pVirtualizationInformation.MeasureSize = measureSize;
5462

@@ -202,9 +210,9 @@ bool ITreeBuilder.BuildTree()
202210
return pWorkLeft;
203211
}
204212

205-
private void RaiseContainerContentChangingOnRecycle(
213+
internal override void RaiseContainerContentChangingOnRecycle(
206214
UIElement pContainer,
207-
DependencyObject pItem)
215+
object pItem)
208216
{
209217
CalendarViewDayItemChangingEventArgs spArgs;
210218
CalendarViewDayItemChangingEventArgs spArgsConcrete;

src/Uno.UI/Microsoft/UI/Xaml/Controls/CalendarView/Primitives/CalendarPanel.ModernCollectionBasePanel.cs

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ internal IEnumerable<CacheEntry> CompleteGeneration(int endIndex)
181181
return unusedEntries;
182182
}
183183

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

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

226-
return (entry.Container, false);
226+
return (entry, CacheEntryKind.Kept);
227227
}
228228

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

235235
CacheEntry entry;
236-
bool isNew;
236+
CacheEntryKind kind;
237237
if (_generationRecyclableBefore.count > 0)
238238
{
239239
entry = _entries[_generationRecyclableBefore.at];
240-
isNew = false;
240+
kind = CacheEntryKind.Recycled;
241241

242242
_generationRecyclableBefore.at++;
243243
_generationRecyclableBefore.count--;
244244
}
245245
else if (_generationRecyclableAfter.count > 0)
246246
{
247247
entry = _entries[_generationRecyclableAfter.at + _generationRecyclableAfter.count - 1];
248-
isNew = false;
248+
kind = CacheEntryKind.Recycled;
249249

250250
_generationRecyclableAfter.count--;
251251

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

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

266266
_host.PrepareItemContainer(entry.Container, item);
267267

268-
return (entry.Container, isNew);
268+
return (entry, kind);
269269
}
270270
}
271271

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

312+
private enum CacheEntryKind
313+
{
314+
New,
315+
Kept,
316+
Recycled
317+
}
318+
312319
internal event VisibleIndicesUpdatedEventCallback VisibleIndicesUpdated;
313320

314321
private readonly ContainersCache _cache = new ContainersCache();
@@ -328,8 +335,8 @@ private void base_Initialize()
328335
#region Private and internal API required by UWP code
329336
internal int FirstVisibleIndexBase { get; private set; }
330337
internal int LastVisibleIndexBase { get; private set; }
331-
internal int FirstCacheIndexBase { get; private set; }
332-
internal int LastCacheIndexBase { get; private set; }
338+
internal int FirstCacheIndexBase => _cache.StartIndex;
339+
internal int LastCacheIndexBase => _cache.EndIndex;
333340

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

372379
private Size GetViewportSize()
373-
{
374-
return _lastLayoutedViewport.Size.AtLeast(_defaultHardCodedSize).FiniteOrDefault(_defaultHardCodedSize);
375-
}
380+
=> _lastLayoutedViewport.Size.AtLeast(_defaultHardCodedSize).FiniteOrDefault(_defaultHardCodedSize);
376381

377382
internal Size GetDesiredViewportSize()
378-
{
379-
return _layoutStrategy.GetDesiredViewportSize();
380-
}
383+
=> _layoutStrategy?.GetDesiredViewportSize() ?? default;
381384

382385
[NotImplemented]
383386
internal void GetTargetIndexFromNavigationAction(
@@ -396,9 +399,7 @@ internal void GetTargetIndexFromNavigationAction(
396399
}
397400

398401
internal IItemContainerMapping GetItemContainerMapping()
399-
{
400-
throw new NotImplementedException();
401-
}
402+
=> _cache;
402403

403404
private void SetLayoutStrategyBase(CalendarLayoutStrategy spLayoutStrategy)
404405
{
@@ -463,10 +464,10 @@ private Size base_MeasureOverride(Size availableSize)
463464
|| _layoutStrategy.ShouldContinueFillingUpSpace(ElementType.ItemContainer, index, layout, remainingWindowToFill))
464465
)
465466
{
466-
var (container, isNew) = _cache.GetOrCreate(index);
467-
if (isNew)
467+
var (entry, kind) = _cache.GetOrCreate(index);
468+
if (kind == CacheEntryKind.New)
468469
{
469-
Children.Add(container);
470+
Children.Add(entry.Container);
470471
}
471472

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

483-
container.Measure(itemSize);
484-
container.GetVirtualizationInformation().MeasureSize = itemSize;
484+
entry.Container.Measure(itemSize);
485+
entry.Container.GetVirtualizationInformation().MeasureSize = itemSize;
486+
switch (kind)
487+
{
488+
case CacheEntryKind.New:
489+
_host.SetupContainerContentChangingAfterPrepare(entry.Container, entry.Item, entry.Index, itemSize);
490+
break;
491+
492+
case CacheEntryKind.Recycled:
493+
// Note: ModernBasePanel seems to use only SetupContainerContentChangingAfterPrepare
494+
_host.RaiseContainerContentChangingOnRecycle(entry.Container, entry.Item);
495+
break;
496+
}
485497

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

0 commit comments

Comments
 (0)