wx: enrich the explore tree down to pins and signals
The model tree was modules → parts only. Drill it down:
- each Part now lists its Pins, each labelled with the signal it is wired to
and that signal's type, or "(NC[, imported|dropped])";
- each Module gains a "Signals (N)" branch — the per-module net view, each
signal labelled with its type and fan-out.
Pin/part/signal lists sort in natural order ("2" < "10") via a small helper.
Modules expand to show their parts + Signals node; pins and the signal list
stay collapsed (revealed on demand) so large parts don't flood the view.
wx-only change (no core, no tui); builds clean, window opens with no asserts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@
|
|||||||
#include "core/domain/modules.hpp"
|
#include "core/domain/modules.hpp"
|
||||||
#include "core/domain/parts.hpp"
|
#include "core/domain/parts.hpp"
|
||||||
#include "core/domain/persist.hpp"
|
#include "core/domain/persist.hpp"
|
||||||
|
#include "core/domain/pins.hpp"
|
||||||
#include "core/domain/signal_type.hpp"
|
#include "core/domain/signal_type.hpp"
|
||||||
#include "core/domain/signals.hpp"
|
#include "core/domain/signals.hpp"
|
||||||
#include "core/domain/system.hpp"
|
#include "core/domain/system.hpp"
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
#include <wx/treectrl.h>
|
#include <wx/treectrl.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -44,6 +46,34 @@ enum {
|
|||||||
|
|
||||||
// Core (UTF-8 std::string) -> wxString, and back for paths.
|
// Core (UTF-8 std::string) -> wxString, and back for paths.
|
||||||
inline wxString wx(const std::string &s) { return wxString::FromUTF8(s.c_str()); }
|
inline wxString wx(const std::string &s) { return wxString::FromUTF8(s.c_str()); }
|
||||||
|
|
||||||
|
// Natural order ("2" < "10", "A2" < "A10") so pin/part lists read intuitively.
|
||||||
|
bool natural_less(const std::string &a, const std::string &b) {
|
||||||
|
size_t i = 0, j = 0;
|
||||||
|
while (i < a.size() && j < b.size()) {
|
||||||
|
unsigned char ca = a[i], cb = b[j];
|
||||||
|
if (std::isdigit(ca) && std::isdigit(cb)) {
|
||||||
|
size_t i0 = i, j0 = j;
|
||||||
|
while (i < a.size() && std::isdigit((unsigned char)a[i])) ++i;
|
||||||
|
while (j < b.size() && std::isdigit((unsigned char)b[j])) ++j;
|
||||||
|
std::string na = a.substr(i0, i - i0), nb = b.substr(j0, j - j0);
|
||||||
|
na.erase(0, na.find_first_not_of('0')); // ignore leading zeros
|
||||||
|
nb.erase(0, nb.find_first_not_of('0'));
|
||||||
|
if (na.size() != nb.size()) return na.size() < nb.size();
|
||||||
|
if (na != nb) return na < nb;
|
||||||
|
} else {
|
||||||
|
if (ca != cb) return ca < cb;
|
||||||
|
++i; ++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a.size() < b.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
// " (Power)" / " (Gnd)" — only for the meaningful types; "" for Other.
|
||||||
|
wxString type_suffix(SignalType t) {
|
||||||
|
return t == SignalType::Other ? wxString()
|
||||||
|
: " (" + wxString(signal_type_name(t)) + ")";
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
EssimFrame::EssimFrame(WxFrontend &fe)
|
EssimFrame::EssimFrame(WxFrontend &fe)
|
||||||
@@ -143,17 +173,54 @@ void EssimFrame::RebuildModelView() {
|
|||||||
wxTreeItemId mid = tree_->AppendItem(
|
wxTreeItemId mid = tree_->AppendItem(
|
||||||
root, wx(mname) + wxString::Format(" — %d part(s), %d signal(s)",
|
root, wx(mname) + wxString::Format(" — %d part(s), %d signal(s)",
|
||||||
mp, ms));
|
mp, ms));
|
||||||
|
|
||||||
|
// Parts → pins (each pin shows the signal it is wired to, or NC).
|
||||||
std::vector<std::string> parts;
|
std::vector<std::string> parts;
|
||||||
for (auto &pkv : *m) parts.push_back(pkv.first);
|
for (auto &pkv : *m) parts.push_back(pkv.first);
|
||||||
std::sort(parts.begin(), parts.end());
|
std::sort(parts.begin(), parts.end(), natural_less);
|
||||||
for (const auto &pname : parts) {
|
for (const auto &pname : parts) {
|
||||||
Part *p = m->get(pname);
|
Part *p = m->get(pname);
|
||||||
wxString label = wx(pname)
|
wxString label = wx(pname)
|
||||||
+ wxString::Format(" (%d pin(s))", (int)p->size());
|
+ wxString::Format(" (%d pin(s))", (int)p->size());
|
||||||
if (!p->connector_type.empty())
|
if (!p->connector_type.empty())
|
||||||
label += " [" + wx(p->connector_type) + "]";
|
label += " [" + wx(p->connector_type) + "]";
|
||||||
tree_->AppendItem(mid, label);
|
wxTreeItemId pid = tree_->AppendItem(mid, label);
|
||||||
|
|
||||||
|
std::vector<std::string> pins;
|
||||||
|
for (auto &nkv : *p) pins.push_back(nkv.first);
|
||||||
|
std::sort(pins.begin(), pins.end(), natural_less);
|
||||||
|
for (const auto &pinname : pins) {
|
||||||
|
Pin *pin = p->get(pinname);
|
||||||
|
wxString pl = wx(pinname) + " -> ";
|
||||||
|
if (Signal *s = pin->signal()) {
|
||||||
|
pl += wx(s->name) + type_suffix(s->type);
|
||||||
|
} else {
|
||||||
|
pl += "(NC";
|
||||||
|
if (pin->nc_origin == NcOrigin::ImportedUnconnected)
|
||||||
|
pl += ", imported";
|
||||||
|
else if (pin->nc_origin == NcOrigin::DroppedSingleton)
|
||||||
|
pl += ", dropped";
|
||||||
|
pl += ")";
|
||||||
}
|
}
|
||||||
|
tree_->AppendItem(pid, pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Signals branch (the per-module net view: type + fan-out).
|
||||||
|
if (ms > 0) {
|
||||||
|
wxTreeItemId sid =
|
||||||
|
tree_->AppendItem(mid, wxString::Format("Signals (%d)", ms));
|
||||||
|
std::vector<std::string> sigs;
|
||||||
|
for (auto &skv : *m->signals) sigs.push_back(skv.first);
|
||||||
|
std::sort(sigs.begin(), sigs.end(), natural_less);
|
||||||
|
for (const auto &sname : sigs) {
|
||||||
|
Signal *s = m->signals->get(sname);
|
||||||
|
tree_->AppendItem(sid, wx(sname) + type_suffix(s->type)
|
||||||
|
+ wxString::Format(" — %d pin(s)", (int)s->size()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tree_->Expand(mid); // parts + Signals visible; pins/nets on demand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tree_->Expand(root);
|
tree_->Expand(root);
|
||||||
|
|||||||
Reference in New Issue
Block a user