Forge
csharpdeeb25a2
1#nullable enable
2using System.Collections.ObjectModel;
3using CascadeIDE.Models;
4
5namespace CascadeIDE.Features.Workspace.Application;
6
7/// <summary>
8/// Фильтр SE: пересборка видимого дерева (Avalonia TreeView не умеет prune через IsVisible).
9/// </summary>
10public static class SolutionExplorerTreeFilter
11{
12 public static void RebuildDisplayRoots(
13 ObservableCollection<SolutionItem> sourceRoots,
14 ObservableCollection<SolutionItem> displayRoots,
15 string filterText,
16 WorkspaceFileIndex index)
17 {
18 displayRoots.Clear();
19 var term = filterText.Trim();
20 if (term.Length == 0)
21 {
22 foreach (var root in sourceRoots)
23 displayRoots.Add(root);
24 return;
25 }
26
27 var matches = index.MatchingFullPaths(term);
28 foreach (var root in sourceRoots)
29 {
30 var filtered = FilterNode(root, term, matches);
31 if (filtered is not null)
32 displayRoots.Add(filtered);
33 }
34 }
35
36 internal static SolutionItem? FilterNode(SolutionItem node, string term, HashSet<string> matchingPaths)
37 {
38 var selfMatches = NodeMatches(node, matchingPaths, term);
39 var filteredChildren = new List<SolutionItem>();
40 foreach (var child in node.Children)
41 {
42 var filteredChild = FilterNode(child, term, matchingPaths);
43 if (filteredChild is not null)
44 filteredChildren.Add(filteredChild);
45 }
46
47 if (!selfMatches && filteredChildren.Count == 0)
48 return null;
49
50 var result = CloneForFilter(node);
51 foreach (var child in filteredChildren)
52 result.Children.Add(child);
53 return result;
54 }
55
56 private static SolutionItem CloneForFilter(SolutionItem source)
57 {
58 SolutionItem clone = source.FullPath switch
59 {
60 null => SolutionItem.CreateFolder(source.Title),
61 { } path when source.IconKey.Equals("solution", StringComparison.OrdinalIgnoreCase)
62 => SolutionItem.CreateSolution(source.Title, path),
63 { } path when source.IconKey.Equals("project", StringComparison.OrdinalIgnoreCase)
64 => SolutionItem.CreateProject(source.Title, path),
65 { } path when Directory.Exists(path)
66 => SolutionItem.CreateFolderWorkspaceRoot(source.Title, path),
67 { } path => SolutionItem.CreateFile(source.Title, path),
68 };
69 clone.IsExpanded = true;
70 return clone;
71 }
72
73 private static bool NodeMatches(SolutionItem node, HashSet<string> matchingPaths, string term)
74 {
75 if (node.FullPath is { } path)
76 {
77 if (matchingPaths.Contains(path))
78 return true;
79
80 return node.Title.Contains(term, StringComparison.OrdinalIgnoreCase)
81 || path.Contains(term, StringComparison.OrdinalIgnoreCase);
82 }
83
84 return node.Title.Contains(term, StringComparison.OrdinalIgnoreCase);
85 }
86}
87
View only · write via MCP/CIDE