- ODS importer (libzip + pugixml): each sheet → Part, rows → Pin/Signal.
- save / restore commands: tab-delimited snapshot of modules, parts,
signals, connections + pin_map. `restore` replaces the System.
- source / script-save: replay a file of commands; record canonical
commands since last `new` for replay later. Interactive screens
refused during source. `explore` marked non-scriptable.
- TUI screen_explore: 4 columns (modules, type, children, detail) with
filters on children and detail; detail is a Menu so arrows scroll
long pin lists.
- Connector types & transforms: each Part carries a `connector_type`
string. `set-type` validates the part's pin layout against the type
(cols set check). `connect` strict pair: rejects when lookup falls
back to identity unless types are both empty AND pin sets match.
- VPX 3U transforms: 3 registered pairs (vpx-3u-bkp-pN ↔ vpx-3u-payload-pN,
N=0/1/2) with row-pattern correspondence tables ported from the user's
Python reference.
- Code split for maintainability: src/tui/{shell,completion,commands,
screen_main,screen_search,screen_connect,screen_settype,screen_explore,
tui_helpers}.cpp.
- Bug fixes: Module::add(Part*) override sets part->prnt (was always
null, breaking save's W lines). Defensive guards in explore against
empty Menu lists. Renderer wrapped in try/catch so domain throws
surface as on-screen errors instead of SIGABRT.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
84 lines
2.9 KiB
C++
84 lines
2.9 KiB
C++
#include "tui/tui.hpp"
|
|
#include "tui/tui_helpers.hpp"
|
|
|
|
#include "system/modules.hpp"
|
|
#include "system/parts.hpp"
|
|
#include "system/signals.hpp"
|
|
#include "system/system.hpp"
|
|
|
|
#include <ftxui/component/component.hpp>
|
|
#include <ftxui/component/component_options.hpp>
|
|
#include <ftxui/dom/elements.hpp>
|
|
|
|
#include <algorithm>
|
|
#include <exception>
|
|
#include <utility>
|
|
|
|
using namespace ftxui;
|
|
|
|
Component Tui::BuildSearchScreen() {
|
|
InputOption query_opt;
|
|
query_opt.multiline = false;
|
|
query_opt.transform = [](InputState s) {
|
|
auto el = s.element;
|
|
if (s.is_placeholder) el |= dim;
|
|
return el;
|
|
};
|
|
|
|
auto query_input = Input(&search_query, "filter…", query_opt);
|
|
auto module_menu = Menu(&search_modules, &search_module_idx);
|
|
auto type_menu = Menu(&search_types, &search_type_idx);
|
|
|
|
auto components = Container::Vertical(
|
|
{query_input, module_menu, type_menu}, &search_focus_idx);
|
|
|
|
return Renderer(components,
|
|
[this, query_input, module_menu, type_menu] {
|
|
std::vector<std::pair<std::string, size_t>> hits;
|
|
if (!search_modules.empty() && sys) {
|
|
const std::string &mname = search_modules[search_module_idx];
|
|
try {
|
|
Module *mod = sys->modules()->get(mname);
|
|
std::string needle = ToLower(search_query);
|
|
if (search_type_idx == 0) { // parts
|
|
for (auto &pkv : *mod)
|
|
if (needle.empty()
|
|
|| ToLower(pkv.first).find(needle) != std::string::npos)
|
|
hits.emplace_back(pkv.first, pkv.second->size());
|
|
} else { // signals
|
|
for (auto &skv : *mod->signals)
|
|
if (needle.empty()
|
|
|| ToLower(skv.first).find(needle) != std::string::npos)
|
|
hits.emplace_back(skv.first, skv.second->size());
|
|
}
|
|
} catch (const std::exception &) {}
|
|
}
|
|
std::sort(hits.begin(), hits.end(),
|
|
[](const auto &a, const auto &b) { return NaturalLess(a.first, b.first); });
|
|
|
|
Elements result_lines;
|
|
for (const auto &h : hits)
|
|
result_lines.push_back(
|
|
text(" " + h.first + " (" + std::to_string(h.second) + " pins)"));
|
|
|
|
auto left = vbox({
|
|
text("module") | bold,
|
|
module_menu->Render() | yframe | flex,
|
|
separator(),
|
|
text("type") | bold,
|
|
type_menu->Render(),
|
|
}) | size(WIDTH, EQUAL, 28);
|
|
|
|
auto right = vbox({
|
|
hbox({text(" search: "), query_input->Render() | flex}) | border,
|
|
text(std::to_string(hits.size()) + " match(es)") | dim,
|
|
vbox(std::move(result_lines)) | yframe | flex,
|
|
}) | flex;
|
|
|
|
return vbox({
|
|
hbox({left, separator(), right}) | flex,
|
|
text(" Tab: cycle focus | Esc: leave search ") | dim,
|
|
}) | border;
|
|
});
|
|
}
|