Skip to content

Commit 5531a75

Browse files
WIP Virtual tree view
1 parent e4f075e commit 5531a75

File tree

3 files changed

+171
-2
lines changed

3 files changed

+171
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
@inherits ComponentBase
2+
@typeparam T
3+
4+
5+
<ul style="flex-shrink:0">
6+
<Virtualize Items="viewList" ItemSize="50" Context="viewListItem">
7+
<li @key="@viewListItem" style="height:50px; flex-shrink:0; margin-left:@(viewListItem.level * 48)pt;">
8+
@if (ChildrenSelector?.Invoke(viewListItem.item)?.Count > 0)
9+
{
10+
<MudIconButton Icon="@Icons.Material.Filled.ChevronRight" OnClick="() => OnClick(viewListItem)" />
11+
}
12+
@if (ItemTemplate == null)
13+
{
14+
@viewListItem.item
15+
}
16+
else
17+
{
18+
@ItemTemplate(viewListItem.item)
19+
}
20+
</li>
21+
</Virtualize>
22+
</ul>
23+
24+
25+
@code {
26+
[Parameter]
27+
public RenderFragment<T>? ItemTemplate { get; set; }
28+
29+
[Parameter]
30+
public IReadOnlyCollection<T>? Items { get; set; }
31+
32+
[Parameter]
33+
public Func<T, IReadOnlyCollection<T>>? ChildrenSelector { get; set; }
34+
35+
36+
private List<(T item, bool isExpanded, int level)> viewList = new();
37+
38+
protected override void OnParametersSet()
39+
{
40+
base.OnParametersSet();
41+
SynchronizeViewList();
42+
}
43+
44+
private void SynchronizeViewList()
45+
{
46+
if (Items is { } items)
47+
{
48+
viewList.Clear();
49+
viewList.AddRange(items.Select(x => (x, false, 0)));
50+
}
51+
}
52+
53+
private void OnClick((T item, bool isExpanded, int level) item)
54+
{
55+
var current = Items;
56+
var viewListIndex = 0;
57+
IterateCurrent(Items ?? []);
58+
59+
bool IterateCurrent(IReadOnlyCollection<T> current)
60+
{
61+
foreach (var currentItem in current)
62+
{
63+
var currentViewItem = viewList[viewListIndex];
64+
if (!EqualityComparer<T>.Default.Equals(currentItem, currentViewItem.item))
65+
{
66+
SynchronizeViewList();
67+
return false;
68+
}
69+
else if (EqualityComparer<T>.Default.Equals(currentItem, item.item))
70+
{
71+
var newIsExpanded = !item.isExpanded;
72+
viewList[viewListIndex] = item with { isExpanded = newIsExpanded };
73+
var children = ChildrenSelector?.Invoke(currentItem) ?? [];
74+
if (newIsExpanded)
75+
{
76+
viewList.InsertRange(viewListIndex + 1, children.Select(x => (x, false, item.level + 1)));
77+
}
78+
else
79+
{
80+
viewList.RemoveRange(viewListIndex +1, children.Count);
81+
}
82+
return false;
83+
}
84+
else
85+
{
86+
viewListIndex++;
87+
if (currentViewItem.isExpanded)
88+
{
89+
var children = ChildrenSelector?.Invoke(currentItem) ?? [];
90+
var doContinue = IterateCurrent(children);
91+
if (!doContinue)
92+
{
93+
return doContinue;
94+
}
95+
}
96+
}
97+
}
98+
return true;
99+
}
100+
}
101+
}

ProtoBufViewer.Blazor/Pages/Index.razor

+69-2
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,75 @@
8181
</ButtonTemplate>
8282
</MudFileUpload>
8383
}
84-
85-
<MudTreeView T="ProtoType" Items="TypedMessages" Context="typedValue">
84+
<VirtualTreeView T="ProtoType" Items="TypedMessages" ChildrenSelector="x => x switch {
85+
TypedMessage message => message.Fields,
86+
TypedField { Value: TypedMessage message } => message.Fields,
87+
_ => []
88+
}">
89+
<ItemTemplate>
90+
@switch (context)
91+
{
92+
case TypedMessage message:
93+
@message.MessageType
94+
break;
95+
case TypedField field:
96+
<b>@field.Name:&nbsp;</b>
97+
@switch (field.Value)
98+
{
99+
case TypedFloat x:
100+
@x.Value
101+
break;
102+
case TypedInt32 x:
103+
@x.Value
104+
break;
105+
case TypedInt64 x:
106+
@x.Value
107+
break;
108+
case TypedUint32 x:
109+
@x.Value
110+
break;
111+
case TypedUint64 x:
112+
@x.Value
113+
break;
114+
case TypedSint32 x:
115+
@x.Value
116+
break;
117+
case TypedSint64 x:
118+
@x.Value
119+
break;
120+
case TypedFixed32 x:
121+
@x.Value
122+
break;
123+
case TypedFixed64 x:
124+
@x.Value
125+
break;
126+
case TypedSfixed32 x:
127+
@x.Value
128+
break;
129+
case TypedSfixed64 x:
130+
@x.Value
131+
break;
132+
case TypedBool x:
133+
@x.Value
134+
break;
135+
case TypedString x:
136+
@x.Value
137+
break;
138+
case TypedBytes x:
139+
@x.Value
140+
break;
141+
case TypedUnknown x:
142+
@x.Value
143+
break;
144+
case TypedEnum x:
145+
@x.EnumValue
146+
break;
147+
}
148+
break;
149+
}
150+
</ItemTemplate>
151+
</VirtualTreeView>
152+
<MudTreeView T="ProtoType" Context="typedValue">
86153
<ItemTemplate>
87154
@switch (typedValue)
88155
{

ProtoBufViewer.Blazor/_Imports.razor

+1
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@
99
@using MudBlazor
1010
@using ProtoBufViewer.Blazor
1111
@using ProtoBufViewer.Blazor.Shared
12+
@using ProtoBufViewer.Blazor.Components

0 commit comments

Comments
 (0)