mirror of
https://github.com/CachyOS/New-Cli-Installer.git
synced 2025-01-23 14:32:22 +08:00
249 lines
7.7 KiB
C++
249 lines
7.7 KiB
C++
|
#include "widgets.hpp"
|
||
|
#include "config.hpp"
|
||
|
#include "utils.hpp"
|
||
|
|
||
|
/* clang-format off */
|
||
|
#include <csignal> // for raise
|
||
|
#include <algorithm> // for transform
|
||
|
#include <string> // for basic_string
|
||
|
#include <ftxui/component/component.hpp> // for Renderer, Button
|
||
|
#include <ftxui/component/component_options.hpp> // for ButtonOption
|
||
|
#include <ftxui/component/screen_interactive.hpp> // for Component, ScreenI...
|
||
|
/* clang-format on */
|
||
|
|
||
|
using namespace ftxui;
|
||
|
|
||
|
namespace tui::detail {
|
||
|
|
||
|
Element centered_widget(Component& container, const std::string_view& title, const Element& widget) noexcept {
|
||
|
return vbox({
|
||
|
// -------- Title --------------
|
||
|
text(title.data()) | bold,
|
||
|
filler(),
|
||
|
// -------- Center Menu --------------
|
||
|
hbox({
|
||
|
filler(),
|
||
|
border(vbox({
|
||
|
widget,
|
||
|
separator(),
|
||
|
container->Render() | hcenter | size(HEIGHT, LESS_THAN, 3) | size(WIDTH, GREATER_THAN, 25),
|
||
|
})),
|
||
|
filler(),
|
||
|
}) | center,
|
||
|
filler(),
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Element centered_widget_nocontrols(const std::string_view& title, const Element& widget) noexcept {
|
||
|
return vbox({
|
||
|
// -------- Title --------------
|
||
|
text(title.data()) | bold,
|
||
|
filler(),
|
||
|
// -------- Center Menu --------------
|
||
|
hbox({
|
||
|
filler(),
|
||
|
border(vbox({widget})),
|
||
|
filler(),
|
||
|
}) | center,
|
||
|
filler(),
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Component controls_widget(const std::array<std::string_view, 2>&& titles, const std::array<std::function<void()>, 2>&& callbacks, ButtonOption* button_option) noexcept {
|
||
|
/* clang-format off */
|
||
|
auto button_ok = Button(titles[0].data(), callbacks[0], button_option);
|
||
|
auto button_quit = Button(titles[1].data(), callbacks[1], button_option);
|
||
|
/* clang-format on */
|
||
|
|
||
|
auto container = Container::Horizontal({
|
||
|
button_ok,
|
||
|
Renderer([] { return filler() | size(WIDTH, GREATER_THAN, 3); }),
|
||
|
button_quit,
|
||
|
});
|
||
|
|
||
|
return container;
|
||
|
}
|
||
|
|
||
|
Element centered_interative_multi(const std::string_view& title, Component& widgets) noexcept {
|
||
|
return vbox({
|
||
|
// -------- Title --------------
|
||
|
text(title.data()) | bold,
|
||
|
filler(),
|
||
|
// -------- Center Menu --------------
|
||
|
hbox({
|
||
|
filler(),
|
||
|
border(vbox({
|
||
|
widgets->Render(),
|
||
|
})),
|
||
|
filler(),
|
||
|
}) | center,
|
||
|
filler(),
|
||
|
});
|
||
|
}
|
||
|
|
||
|
Element multiline_text(const std::vector<std::string>& lines) noexcept {
|
||
|
Elements multiline;
|
||
|
|
||
|
std::transform(lines.cbegin(), lines.cend(), std::back_inserter(multiline),
|
||
|
[=](const std::string& line) -> Element { return text(line); });
|
||
|
return vbox(std::move(multiline)) | frame;
|
||
|
}
|
||
|
|
||
|
Components from_vector_checklist(const std::vector<std::string>& opts, bool* opts_state) noexcept {
|
||
|
Components components;
|
||
|
|
||
|
for (size_t i = 0; i < opts.size(); ++i) {
|
||
|
auto component = Checkbox(&opts[i], &opts_state[i]);
|
||
|
components.emplace_back(component);
|
||
|
}
|
||
|
return components;
|
||
|
}
|
||
|
|
||
|
std::string from_checklist_string(const std::vector<std::string>& opts, bool* opts_state) noexcept {
|
||
|
std::string res{};
|
||
|
|
||
|
for (size_t i = 0; i < opts.size(); ++i) {
|
||
|
if (opts_state[i]) {
|
||
|
res += opts[i] + " ";
|
||
|
}
|
||
|
}
|
||
|
/* clang-format off */
|
||
|
if (res.ends_with(" ")) { res.pop_back(); }
|
||
|
/* clang-format on */
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
std::vector<std::string> from_checklist_vector(const std::vector<std::string>& opts, bool* opts_state) noexcept {
|
||
|
std::vector<std::string> res{};
|
||
|
|
||
|
for (size_t i = 0; i < opts.size(); ++i) {
|
||
|
if (opts_state[i]) {
|
||
|
res.push_back(opts[i]);
|
||
|
}
|
||
|
}
|
||
|
return res;
|
||
|
}
|
||
|
|
||
|
void msgbox_widget(const std::string_view& content, Decorator boxsize) noexcept {
|
||
|
auto screen = ScreenInteractive::Fullscreen();
|
||
|
/* clang-format off */
|
||
|
auto button_option = ButtonOption();
|
||
|
button_option.border = false;
|
||
|
auto button_back = Button("OK", screen.ExitLoopClosure(), &button_option);
|
||
|
/* clang-format on */
|
||
|
|
||
|
auto container = Container::Horizontal({
|
||
|
button_back,
|
||
|
});
|
||
|
|
||
|
std::string tmp{content.data()};
|
||
|
auto renderer = Renderer(container, [&] {
|
||
|
return centered_widget(container, "New CLI Installer", multiline_text(utils::make_multiline(tmp)) | hcenter | boxsize);
|
||
|
});
|
||
|
|
||
|
screen.Loop(renderer);
|
||
|
}
|
||
|
|
||
|
void infobox_widget(const std::string_view& content, Decorator boxsize) noexcept {
|
||
|
auto screen = Screen::Create(
|
||
|
Dimension::Full(), // Width
|
||
|
Dimension::Full() // Height
|
||
|
);
|
||
|
|
||
|
std::string tmp{content.data()};
|
||
|
auto element = centered_widget_nocontrols("New CLI Installer", multiline_text(utils::make_multiline(tmp)) | vcenter | boxsize);
|
||
|
Render(screen, element);
|
||
|
screen.Print();
|
||
|
}
|
||
|
|
||
|
bool yesno_widget(const std::string_view& content, Decorator boxsize) noexcept {
|
||
|
auto screen = ScreenInteractive::Fullscreen();
|
||
|
|
||
|
bool success{};
|
||
|
auto ok_callback = [&] {
|
||
|
success = true;
|
||
|
std::raise(SIGINT);
|
||
|
};
|
||
|
ButtonOption button_option{.border = false};
|
||
|
auto controls_container = controls_widget({"OK", "Cancel"}, {ok_callback, screen.ExitLoopClosure()}, &button_option);
|
||
|
|
||
|
auto controls = Renderer(controls_container, [&] {
|
||
|
return controls_container->Render() | hcenter | size(HEIGHT, LESS_THAN, 3) | size(WIDTH, GREATER_THAN, 25);
|
||
|
});
|
||
|
|
||
|
auto container = Container::Horizontal({
|
||
|
controls,
|
||
|
});
|
||
|
|
||
|
auto renderer = Renderer(container, [&] {
|
||
|
return centered_widget(container, "New CLI Installer", text(content.data()) | hcenter | boxsize);
|
||
|
});
|
||
|
|
||
|
screen.Loop(renderer);
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
bool yesno_widget(ftxui::Component& container, Decorator boxsize) noexcept {
|
||
|
auto screen = ScreenInteractive::Fullscreen();
|
||
|
|
||
|
auto content = Renderer(container, [&] {
|
||
|
return container->Render() | hcenter | boxsize;
|
||
|
});
|
||
|
|
||
|
bool success{};
|
||
|
auto ok_callback = [&] {
|
||
|
success = true;
|
||
|
std::raise(SIGINT);
|
||
|
};
|
||
|
ButtonOption button_option{.border = false};
|
||
|
auto controls_container = controls_widget({"OK", "Cancel"}, {ok_callback, screen.ExitLoopClosure()}, &button_option);
|
||
|
|
||
|
auto controls = Renderer(controls_container, [&] {
|
||
|
return controls_container->Render() | hcenter | size(HEIGHT, LESS_THAN, 3) | size(WIDTH, GREATER_THAN, 25);
|
||
|
});
|
||
|
|
||
|
auto global = Container::Vertical({
|
||
|
content,
|
||
|
Renderer([] { return separator(); }),
|
||
|
controls,
|
||
|
});
|
||
|
|
||
|
auto renderer = Renderer(global, [&] {
|
||
|
return centered_interative_multi("New CLI Installer", global);
|
||
|
});
|
||
|
|
||
|
screen.Loop(renderer);
|
||
|
|
||
|
return success;
|
||
|
}
|
||
|
|
||
|
void menu_widget(const std::vector<std::string>& entries, const std::function<void()>&& ok_callback, std::int32_t* selected) noexcept {
|
||
|
auto screen = ScreenInteractive::Fullscreen();
|
||
|
auto menu = Menu(&entries, selected);
|
||
|
auto content = Renderer(menu, [&] {
|
||
|
return menu->Render() | center | size(HEIGHT, GREATER_THAN, 10) | size(WIDTH, GREATER_THAN, 40);
|
||
|
});
|
||
|
|
||
|
ButtonOption button_option{.border = false};
|
||
|
auto controls_container = controls_widget({"OK", "Cancel"}, {ok_callback, screen.ExitLoopClosure()}, &button_option);
|
||
|
|
||
|
auto controls = Renderer(controls_container, [&] {
|
||
|
return controls_container->Render() | hcenter | size(HEIGHT, LESS_THAN, 3) | size(WIDTH, GREATER_THAN, 25);
|
||
|
});
|
||
|
|
||
|
auto global = Container::Vertical({
|
||
|
content,
|
||
|
Renderer([] { return separator(); }),
|
||
|
controls,
|
||
|
});
|
||
|
|
||
|
auto renderer = Renderer(global, [&] {
|
||
|
return centered_interative_multi("New CLI Installer", global);
|
||
|
});
|
||
|
|
||
|
screen.Loop(renderer);
|
||
|
}
|
||
|
|
||
|
} // namespace tui::detail
|