#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 #include #include #include #include #include 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> 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; }); }