Forge
csharpdeeb25a2
1using System.Collections.ObjectModel;
2using System.ComponentModel;
3using System.Runtime.CompilerServices;
4
5namespace CascadeIDE.Models;
6
7public sealed class SolutionItem : INotifyPropertyChanged
8{
9 private bool _isExpanded;
10 private bool _isVisible = true;
11
12 public string Title { get; }
13 public string? FullPath { get; }
14 public bool IsFolder => Children.Count > 0 && FullPath is null;
15 public ObservableCollection<SolutionItem> Children { get; } = [];
16
17 public bool IsExpanded
18 {
19 get => _isExpanded;
20 set
21 {
22 if (_isExpanded == value)
23 return;
24 _isExpanded = value;
25 OnPropertyChanged();
26 }
27 }
28
29 public bool IsVisible
30 {
31 get => _isVisible;
32 set
33 {
34 if (_isVisible == value)
35 return;
36 _isVisible = value;
37 OnPropertyChanged();
38 }
39 }
40
41 /// <summary>Ключ иконки для UI: solution, project, folder, file, file_cs, file_json, file_md, file_xml, file_txt и т.д.</summary>
42 public string IconKey => GetIconKey();
43
44 public event PropertyChangedEventHandler? PropertyChanged;
45
46 private string GetIconKey()
47 {
48 if (FullPath is null)
49 return Children.Count > 0 ? "folder" : "file";
50 if (Directory.Exists(FullPath))
51 return "folder";
52 var p = FullPath.AsSpan();
53 if (p.EndsWith(".slnx", StringComparison.OrdinalIgnoreCase) || p.EndsWith(".sln", StringComparison.OrdinalIgnoreCase))
54 return "solution";
55 if (p.EndsWith(".csproj", StringComparison.OrdinalIgnoreCase))
56 return "file_csproj";
57 if (p.EndsWith(".fsproj", StringComparison.OrdinalIgnoreCase))
58 return "file_fsproj";
59 if (p.EndsWith(".vbproj", StringComparison.OrdinalIgnoreCase))
60 return "file_vbproj";
61 var ext = Path.GetExtension(FullPath);
62 if (string.IsNullOrEmpty(ext) || ext.Length <= 1) return "file";
63 return "file_" + ext[1..].ToLowerInvariant();
64 }
65
66 private SolutionItem(string title, string? fullPath)
67 {
68 Title = title;
69 FullPath = fullPath;
70 }
71
72 public static SolutionItem CreateSolution(string title, string slnPath)
73 => new(title, slnPath);
74
75 /// <summary>Корень обозревателя при открытии каталога как workspace (без .sln). <see cref="IconKey"/> — папка.</summary>
76 public static SolutionItem CreateFolderWorkspaceRoot(string title, string folderPath)
77 => new(title, folderPath);
78
79 public static SolutionItem CreateProject(string title, string projectPath)
80 => new(title, projectPath);
81
82 public static SolutionItem CreateFile(string title, string filePath)
83 => new(title, filePath);
84
85 public static SolutionItem CreateFolder(string title)
86 => new(title, null);
87
88 private void OnPropertyChanged([CallerMemberName] string? name = null) =>
89 PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
90}
91
View only · write via MCP/CIDE