-
Notifications
You must be signed in to change notification settings - Fork 743
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(itemsrepeater): Brings more C++ code and begin integration with Uno
- Loading branch information
Showing
24 changed files
with
1,278 additions
and
333 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
64 changes: 64 additions & 0 deletions
64
src/Uno.UI/UI/Xaml/Controls/Primitives/Repeater/BuildTreeScheduler.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See LICENSE in the project root for license information. | ||
|
||
#include "pch.h" | ||
#include "common.h" | ||
#include "QPCTimer.h" | ||
#include "BuildTreeScheduler.h" | ||
#include "RepeaterTestHooks.h" | ||
|
||
double BuildTreeScheduler.m_budgetInMs = 40.0; | ||
thread_local QPCTimer BuildTreeScheduler.m_timer{}; | ||
thread_local std.CalculatorList<WorkInfo> BuildTreeScheduler.m_pendingWork{}; | ||
thread_local event_token BuildTreeScheduler.m_renderingToken{}; | ||
|
||
void RegisterWork(int priority, const std.function<void()>& workFunc) | ||
{ | ||
global::System.Diagnostics.Debug.Assert(priority >= 0); | ||
global::System.Diagnostics.Debug.Assert(workFunc != null); | ||
|
||
QueueTick(); | ||
m_pendingWork.push_back(WorkInfo(priority, workFunc)); | ||
} | ||
|
||
bool ShouldYield() | ||
{ | ||
return m_timer.DurationInMilliSeconds() > m_budgetInMs; | ||
} | ||
|
||
void OnRendering(const IInspectable&, const IInspectable&) | ||
{ | ||
bool budgetReached = ShouldYield(); | ||
if (!budgetReached && m_pendingWork.size() > 0) | ||
{ | ||
// Sort in descending order of priority and work from the end of the list to avoid moving around during erase. | ||
std.sort(m_pendingWork.begin(), m_pendingWork.end(), [](const auto& lhs, const auto& rhs) { return lhs.Priority() > rhs.Priority(); }); | ||
int currentIndex = (int)(m_pendingWork.size()) - 1; | ||
|
||
do | ||
{ | ||
m_pendingWork[currentIndex].InvokeWorkFunc(); | ||
m_pendingWork.erase(m_pendingWork.begin() + currentIndex); | ||
} while (--currentIndex >= 0 && !ShouldYield()); | ||
} | ||
|
||
if (m_pendingWork.empty()) | ||
{ | ||
// No more pending work, unhook from rendering event since being hooked up will case wux to try to | ||
// call the event at 60 frames per second | ||
Windows.UI.Xaml.Media.CompositionTarget.CompositionTarget.Rendering(m_renderingToken); | ||
m_renderingToken.value = 0; | ||
RepeaterTestHooks.NotifyBuildTreeCompleted(); | ||
} | ||
|
||
// Reset the timer so it snaps the time just before rendering | ||
m_timer.Reset(); | ||
} | ||
|
||
void QueueTick() | ||
{ | ||
if (m_renderingToken.value == 0) | ||
{ | ||
m_renderingToken = Windows.UI.Xaml.Media.CompositionTarget.Rendering(OnRendering); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
src/Uno.UI/UI/Xaml/Controls/Primitives/Repeater/ChildrenInTabFocusOrderIterable.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. See LICENSE in the project root for license information. | ||
using System; | ||
using System.Collections; | ||
using System.Collections.Generic; | ||
using Windows.UI.Xaml; | ||
using Windows.UI.Xaml.Controls; | ||
|
||
namespace Microsoft.UI.Xaml.Controls | ||
{ | ||
internal class ChildrenInTabFocusOrderIterable : IEnumerable<DependencyObject> | ||
{ | ||
private readonly ItemsRepeater m_repeater; | ||
|
||
public ChildrenInTabFocusOrderIterable(ItemsRepeater repeater) | ||
{ | ||
m_repeater = repeater; | ||
} | ||
|
||
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); | ||
|
||
public IEnumerator<DependencyObject> GetEnumerator() => new ChildrenInTabFocusOrderIterator(m_repeater); | ||
|
||
private class ChildrenInTabFocusOrderIterator : IEnumerator<DependencyObject> | ||
{ | ||
private readonly List<KeyValuePair<int /* index */, UIElement>> m_realizedChildren; | ||
private int m_index = 0; | ||
|
||
public ChildrenInTabFocusOrderIterator(ItemsRepeater repeater) | ||
{ | ||
var children = repeater.Children; | ||
m_realizedChildren = new List<KeyValuePair<int, UIElement>>(children.Count); | ||
|
||
// Filter out unrealized children. | ||
for (var i = 0; i < children.Count; ++i) | ||
{ | ||
var element = children[i]; | ||
var virtInfo = ItemsRepeater.GetVirtualizationInfo(element); | ||
if (virtInfo.IsRealized) | ||
{ | ||
m_realizedChildren.Add(new KeyValuePair<int, UIElement>(virtInfo.Index, element)); | ||
} | ||
} | ||
|
||
// Sort children by index. | ||
m_realizedChildren.Sort((lhs, rhs) => lhs.Key - rhs.Key); | ||
} | ||
|
||
object IEnumerator.Current => Current; | ||
public DependencyObject Current | ||
{ | ||
get | ||
{ | ||
if (m_index < m_realizedChildren.Count) | ||
{ | ||
return m_realizedChildren[m_index].Value; | ||
} | ||
else | ||
{ | ||
throw new IndexOutOfRangeException(); | ||
} | ||
} | ||
} | ||
|
||
public bool MoveNext() | ||
{ | ||
if (m_index < m_realizedChildren.Count) | ||
{ | ||
++m_index; | ||
return m_index < m_realizedChildren.Count; | ||
} | ||
else | ||
{ | ||
throw new IndexOutOfRangeException(); | ||
} | ||
} | ||
|
||
public void Reset() { } | ||
public void Dispose() { } | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
using System; | ||
using System.Linq; | ||
using Windows.UI.Xaml.Controls; | ||
|
||
namespace Microsoft.UI.Xaml.Controls | ||
{ | ||
/// <summary> | ||
/// This interface allows use to replicate the "DeriveFromPanelHelper_base" of WinUI (cf. Remarks) | ||
/// </summary> | ||
/// <remarks> | ||
/// Doc about the DeriveFromPanelHelper_base in WinUI: | ||
/// This type exists for types that in metadata derive from FrameworkElement but internally want to derive from Panel | ||
/// to get "protected" Children. | ||
/// </remarks> | ||
internal interface IPanel | ||
{ | ||
public UIElementCollection Children { get; } | ||
} | ||
} |
Oops, something went wrong.