-
-
Notifications
You must be signed in to change notification settings - Fork 42
Expand file tree
/
Copy pathProgram.cs
More file actions
116 lines (104 loc) · 4.68 KB
/
Copy pathProgram.cs
File metadata and controls
116 lines (104 loc) · 4.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// ============================================================================
// Example: Walking a hierarchical schematic
// ============================================================================
//
// A multi-sheet design has a top sheet whose sheet symbols point at child .SchDoc
// files, which may themselves contain sheet symbols. This example walks that tree
// and prints it, listing each sheet's components and the ports (sheet entries) that
// connect it to its parent.
//
// WHERE THE DATA LIVES
// ────────────────────
// Sheet symbols are on SchDocument.SheetSymbols (cast the ISchDocument the reader
// returns). Each SchSheetSymbol has FileName (the child .SchDoc it references),
// SheetName (its label) and Entries (the SchSheetEntry ports, each with a Name).
//
// SCOPE NOTE: there is no project-file (.PrjScr) reader, so the child file name is
// resolved relative to the parent sheet's folder. A real project may keep sheets in
// other directories; adapt the resolution if yours does.
//
// RUNNING
// ───────
// dotnet run --project examples/WalkHierarchy (best bundled sheet)
// dotnet run --project examples/WalkHierarchy -- Top.SchDoc (your own top sheet)
//
// ============================================================================
using OriginalCircuit.Altium;
using OriginalCircuit.Altium.Models.Sch;
string? start;
if (args.Length > 0)
{
if (!File.Exists(args[0])) { Console.Error.WriteLine($"File not found: {args[0]}"); return; }
start = args[0];
}
else
{
var testData = FindRepoTestDataDir();
start = testData is null ? null : await FindBestTopSheet(testData);
}
if (start is null)
{
Console.WriteLine("No .SchDoc supplied and no bundled TestData sheet was found.");
Console.WriteLine("Usage: dotnet run --project examples/WalkHierarchy -- <top-sheet.SchDoc>");
return;
}
Console.WriteLine($"Walking hierarchy from: {Path.GetFileName(start)}\n");
var visited = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
await Walk(start, 0);
// Recursively prints a sheet and the child sheets its symbols reference.
async Task Walk(string path, int depth)
{
var indent = new string(' ', depth * 2);
var label = Path.GetFileName(path);
if (!File.Exists(path)) { Console.WriteLine($"{indent}• {label} (referenced file not found)"); return; }
if (!visited.Add(Path.GetFullPath(path))) { Console.WriteLine($"{indent}• {label} (already visited)"); return; }
OriginalCircuit.Eda.Models.Sch.ISchDocument idoc;
try { idoc = await AltiumLibrary.OpenSchDocAsync(path); }
catch (Exception ex) { Console.WriteLine($"{indent}• {label} (read error: {ex.Message})"); return; }
await using (idoc)
{
var doc = (SchDocument)idoc;
Console.WriteLine($"{indent}• {label} — {doc.Components.Count} components, {doc.SheetSymbols.Count} sub-sheet(s)");
var folder = Path.GetDirectoryName(Path.GetFullPath(path))!;
foreach (var sheet in doc.SheetSymbols)
{
var ports = sheet.Entries.Count == 0
? ""
: $" ports: {string.Join(", ", sheet.Entries.Select(e => e.Name))}";
var title = string.IsNullOrWhiteSpace(sheet.SheetName) ? (sheet.FileName ?? "(unnamed)") : sheet.SheetName!;
Console.WriteLine($"{indent} ↳ {title} -> {sheet.FileName ?? "(no file)"}{ports}");
if (!string.IsNullOrWhiteSpace(sheet.FileName))
await Walk(Path.Combine(folder, sheet.FileName!), depth + 1);
}
}
}
// Opens each bundled sheet and starts from whichever has the most sheet symbols.
async Task<string?> FindBestTopSheet(string testData)
{
string? best = null;
var bestCount = -1;
foreach (var file in TopLevel(testData, ".SchDoc"))
{
try
{
await using var idoc = await AltiumLibrary.OpenSchDocAsync(file);
var count = ((SchDocument)idoc).SheetSymbols.Count;
if (count > bestCount) { bestCount = count; best = file; }
}
catch { /* skip unreadable sheets */ }
}
return best;
}
static IEnumerable<string> TopLevel(string dir, string ext) =>
Directory.EnumerateFiles(dir, "*", SearchOption.TopDirectoryOnly)
.Where(f => Path.GetExtension(f).Equals(ext, StringComparison.OrdinalIgnoreCase));
static string? FindRepoTestDataDir()
{
foreach (var start in new[] { AppContext.BaseDirectory, Directory.GetCurrentDirectory() })
for (var dir = new DirectoryInfo(start); dir is not null; dir = dir.Parent)
{
var candidate = Path.Combine(dir.FullName, "TestData");
if (Directory.Exists(candidate)) return candidate;
}
return null;
}