mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-28 16:29:34 +08:00
Compare commits
9 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
75cd2b0fca | ||
![]() |
0a5e9f2a2f | ||
![]() |
66cdf9b2a5 | ||
![]() |
84287eb217 | ||
![]() |
535974d291 | ||
![]() |
753502998c | ||
![]() |
31b5fac9c5 | ||
![]() |
76b2f17488 | ||
![]() |
c5ef0c7fb5 |
39
.github/workflows/release.yaml
vendored
Normal file
39
.github/workflows/release.yaml
vendored
Normal file
@@ -0,0 +1,39 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
create:
|
||||
tags:
|
||||
-v*
|
||||
|
||||
jobs:
|
||||
build:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
|
||||
- name: Build
|
||||
run: >
|
||||
mkdir build;
|
||||
cd build;
|
||||
cmake ..
|
||||
-DCMAKE_CXX_COMPILER=clang++
|
||||
-DFTXUI_BUILD_DOCS=OFF
|
||||
-DFTXUI_BUILD_EXAMPLES=OFF
|
||||
-DFTXUI_BUILD_TESTS=OFF
|
||||
-DFTXUI_BUILD_TESTS_FUZZER=OFF
|
||||
-DFTXUI_ENABLE_INSTALL=ON;
|
||||
cmake --build . --config Release;
|
||||
make package;
|
||||
|
||||
- name: Upload
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
files: build/ftxui-*
|
||||
draft: false
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
14
CHANGELOG.md
14
CHANGELOG.md
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## Current
|
||||
|
||||
## 0.10 (2021-09-30)
|
||||
|
||||
## Bug
|
||||
- Fix the automated merge of borders.
|
||||
|
||||
### Dom
|
||||
- `vscroll_indicator`. Show a scrollbar indicator on the right.
|
||||
|
||||
### Component
|
||||
- `Maybe`: Display an component conditionnally based on a boolean.
|
||||
- `Dropdown`: A dropdown select list.
|
||||
|
||||
## 0.9 (2021-09-26)
|
||||
|
||||
The initial release where changelog where written.
|
||||
|
@@ -4,7 +4,7 @@ include(cmake/ftxui_git_version.cmake)
|
||||
|
||||
project(ftxui
|
||||
LANGUAGES CXX
|
||||
VERSION 0.9.${git_version}
|
||||
VERSION 0.10.${git_version}
|
||||
)
|
||||
|
||||
option(FTXUI_BUILD_DOCS "Set to ON to build tests" ON)
|
||||
@@ -57,14 +57,15 @@ add_library(dom STATIC
|
||||
src/ftxui/dom/frame.cpp
|
||||
src/ftxui/dom/gauge.cpp
|
||||
src/ftxui/dom/graph.cpp
|
||||
src/ftxui/dom/hbox.cpp
|
||||
src/ftxui/dom/gridbox.cpp
|
||||
src/ftxui/dom/hbox.cpp
|
||||
src/ftxui/dom/hflow.cpp
|
||||
src/ftxui/dom/inverted.cpp
|
||||
src/ftxui/dom/node.cpp
|
||||
src/ftxui/dom/node_decorator.cpp
|
||||
src/ftxui/dom/paragraph.cpp
|
||||
src/ftxui/dom/reflect.cpp
|
||||
src/ftxui/dom/scroll_indicator.cpp
|
||||
src/ftxui/dom/separator.cpp
|
||||
src/ftxui/dom/size.cpp
|
||||
src/ftxui/dom/spinner.cpp
|
||||
@@ -87,8 +88,10 @@ add_library(component STATIC
|
||||
src/ftxui/component/checkbox.cpp
|
||||
src/ftxui/component/component.cpp
|
||||
src/ftxui/component/container.cpp
|
||||
src/ftxui/component/dropdown.cpp
|
||||
src/ftxui/component/event.cpp
|
||||
src/ftxui/component/input.cpp
|
||||
src/ftxui/component/maybe.cpp
|
||||
src/ftxui/component/menu.cpp
|
||||
src/ftxui/component/radiobox.cpp
|
||||
src/ftxui/component/radiobox.cpp
|
||||
@@ -120,10 +123,6 @@ if (FTXUI_BUILD_TESTS AND ${CMAKE_VERSION} VERSION_GREATER "3.11.4")
|
||||
include(cmake/ftxui_test.cmake)
|
||||
endif()
|
||||
|
||||
if(FTXUI_ENABLE_INSTALL)
|
||||
include(cmake/ftxui_install.cmake)
|
||||
endif()
|
||||
|
||||
if(FTXUI_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
@@ -134,3 +133,9 @@ endif()
|
||||
|
||||
include(cmake/iwyu.cmake)
|
||||
include(cmake/ftxui_export.cmake)
|
||||
|
||||
if(FTXUI_ENABLE_INSTALL)
|
||||
include(cmake/ftxui_install.cmake)
|
||||
include(cmake/ftxui_package.cmake)
|
||||
endif()
|
||||
|
||||
|
41
README.md
41
README.md
@@ -1,24 +1,29 @@
|
||||
# FTXUI
|
||||
<p align="center">
|
||||
<img src="./examples/component/homescreen.gif" alt="Demo image"></img>
|
||||
<br/>
|
||||
<a href="#"><img src="https://img.shields.io/badge/c++-%2300599C.svg?style=flat&logo=c%2B%2B&logoColor=white"></img></a>
|
||||
<a href="http://opensource.org/licenses/MIT"><img src="https://img.shields.io/github/license/arthursonzogni/FTXUI?color=black"></img></a>
|
||||
<a href="#"><img src="https://img.shields.io/github/stars/ArthurSonzogni/FTXUI"></img></a>
|
||||
<a href="#"><img src="https://img.shields.io/github/forks/ArthurSonzogni/FTXUI"></img></a>
|
||||
<a href="#"><img src="https://img.shields.io/github/repo-size/ArthurSonzogni/FTXUI"></img></a>
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/issues"><img src="https://img.shields.io/github/issues/ArthurSonzogni/FTXUI"></img></a>
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/graphs/contributors"><img src="https://img.shields.io/github/contributors/arthursonzogni/FTXUI?color=blue"></img></a>
|
||||
|
||||
[![issues][badge.issues]][issues]
|
||||
[![license][badge.license]][license]
|
||||
[![contributors][badge.contributors]][contributors]
|
||||
<br/>
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/wiki">Documentation</a> ·
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Report Bug</a> ·
|
||||
<a href="https://arthursonzogni.github.io/FTXUI/examples.html">Examples</a> .
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/issues">Request Feature</a> ·
|
||||
<a href="https://github.com/ArthurSonzogni/FTXUI/pulls">Send a Pull Request</a>
|
||||
|
||||
[badge.issues]: https://img.shields.io/github/issues-raw/arthursonzogni/FTXUI
|
||||
[badge.license]: https://img.shields.io/github/license/arthursonzogni/FTXUI?color=black
|
||||
[badge.contributors]: https://img.shields.io/github/contributors/arthursonzogni/FTXUI?color=blue
|
||||
</p>
|
||||
|
||||
[issues]: https://github.com/ArthurSonzogni/FTXUI/issues
|
||||
[license]: http://opensource.org/licenses/MIT
|
||||
[contributors]: https://github.com/ArthurSonzogni/FTXUI/graphs/contributors
|
||||
## FTXUI
|
||||
|
||||
**Functional Terminal (X) User interface**
|
||||
<i>Functional Terminal (X) User interface</i>
|
||||
|
||||
A simple C++ library for terminal based user interface.
|
||||
|
||||
## Demo:
|
||||

|
||||
|
||||
## Feature
|
||||
* Functional style. Inspired by
|
||||
[[1]](https://hackernoon.com/building-reactive-terminal-interfaces-in-c-d392ce34e649?gi=d9fb9ce35901)
|
||||
@@ -48,7 +53,7 @@ A simple C++ library for terminal based user interface.
|
||||
[link.windows-msvc]: https://github.com/ArthurSonzogni/FTXUI/actions/workflows/windows-msvc.yaml
|
||||
[link.mac-clang]: https://github.com/ArthurSonzogni/FTXUI/actions/workflows/mac-clang.yaml
|
||||
|
||||
## Example:
|
||||
## Example
|
||||
~~~cpp
|
||||
vbox({
|
||||
hbox({
|
||||
@@ -69,7 +74,7 @@ A simple C++ library for terminal based user interface.
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
~~~
|
||||
|
||||
# Documentation:
|
||||
# Documentation
|
||||
|
||||
- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
|
||||
- [Documentation](https://arthursonzogni.github.io/FTXUI/)
|
||||
@@ -94,11 +99,11 @@ Feel free to add your projects here:
|
||||
- [todoman](https://github.com/aaleino/todoman)
|
||||
- [TimeAccumulator](https://github.com/asari555/TimeAccumulator)
|
||||
|
||||
## Hosted on:
|
||||
## Hosted on
|
||||
* [github](https://github.com/ArthurSonzogni/ftxui)
|
||||
* [gitlab](https://gitlab.com/ArthurSonzogni/ftxui)
|
||||
|
||||
## External package:
|
||||
## External package
|
||||
|
||||
It is **highly** recommanded to use cmake FetchContent to depends on FTXUI. This
|
||||
way you can specify which commit you would like to depends on.
|
||||
|
16
cmake/ftxui_package.cmake
Normal file
16
cmake/ftxui_package.cmake
Normal file
@@ -0,0 +1,16 @@
|
||||
set(CPACK_GENERATOR "DEB;External;RPM;STGZ;TBZ2;TGZ;TXZ;TZ;TZST;ZIP")
|
||||
set(CPACK_DEBIAN_PACKAGE_DEPENDS " ")
|
||||
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE_URL "https://github.com/ArthurSonzogni/FTXUI/")
|
||||
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Arthur Sonzogni")
|
||||
set(CPACK_DEBIAN_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "A simple C++ Terminal UI library")
|
||||
set(CPACK_PACKAGE_HOMEPAGE_URL "https://github.com/ArthurSonzogni/FTXUI/")
|
||||
set(CPACK_PACKAGE_NAME "ftxui")
|
||||
set(CPACK_PACKAGE_VENDOR "Arthur Sonzogni")
|
||||
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
|
||||
set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR})
|
||||
set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH})
|
||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
|
||||
|
||||
include(CPack)
|
@@ -2,19 +2,21 @@ set(DIRECTORY_LIB component)
|
||||
|
||||
example(button)
|
||||
example(checkbox)
|
||||
example(nested_screen)
|
||||
example(checkbox_in_frame)
|
||||
example(composition)
|
||||
example(dropdown)
|
||||
example(gallery)
|
||||
example(homescreen)
|
||||
example(input)
|
||||
example(maybe)
|
||||
example(menu)
|
||||
example(menu_in_frame)
|
||||
example(menu2)
|
||||
example(menu_multiple)
|
||||
example(menu_entries)
|
||||
example(menu_in_frame)
|
||||
example(menu_multiple)
|
||||
example(menu_style)
|
||||
example(modal_dialog)
|
||||
example(nested_screen)
|
||||
example(print_key_press)
|
||||
example(radiobox)
|
||||
example(radiobox_in_frame)
|
||||
|
@@ -24,7 +24,8 @@ int main(int argc, const char* argv[]) {
|
||||
}
|
||||
|
||||
auto renderer = Renderer(container, [&] {
|
||||
return container->Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
|
||||
return container->Render() | vscroll_indicator | frame |
|
||||
size(HEIGHT, LESS_THAN, 10) | border;
|
||||
});
|
||||
|
||||
auto screen = ScreenInteractive::FitComponent();
|
||||
|
48
examples/component/dropdown.cpp
Normal file
48
examples/component/dropdown.cpp
Normal file
@@ -0,0 +1,48 @@
|
||||
#include <functional> // for function
|
||||
#include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
|
||||
#include <string> // for string, basic_string, allocator
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||
#include "ftxui/component/component.hpp" // for Menu
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption
|
||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
using namespace ftxui;
|
||||
|
||||
std::vector<std::string> entries = {
|
||||
"tribute", "clearance", "ally", "bend", "electronics",
|
||||
"module", "era", "cultural", "sniff", "nationalism",
|
||||
"negotiation", "deliver", "figure", "east",
|
||||
"tribute", "clearance", "ally", "bend", "electronics",
|
||||
"module", "era", "cultural", "sniff", "nationalism",
|
||||
"negotiation", "deliver", "figure", "east",
|
||||
"tribute", "clearance", "ally", "bend", "electronics",
|
||||
"module", "era", "cultural", "sniff", "nationalism",
|
||||
"negotiation", "deliver", "figure", "east",
|
||||
};
|
||||
|
||||
int selected_1 = 0;
|
||||
int selected_2 = 0;
|
||||
int selected_3 = 0;
|
||||
int selected_4 = 0;
|
||||
|
||||
auto layout = Container::Vertical({
|
||||
Container::Horizontal({
|
||||
Dropdown(&entries, &selected_1),
|
||||
Dropdown(&entries, &selected_2),
|
||||
}),
|
||||
Container::Horizontal({
|
||||
Dropdown(&entries, &selected_3),
|
||||
Dropdown(&entries, &selected_4),
|
||||
}),
|
||||
});
|
||||
|
||||
auto screen = ScreenInteractive::FitComponent();
|
||||
screen.Loop(layout);
|
||||
}
|
||||
|
||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
@@ -214,12 +214,13 @@ int main(int argc, const char* argv[]) {
|
||||
};
|
||||
|
||||
auto compiler_renderer = Renderer(compiler_component, [&] {
|
||||
auto compiler_win = window(text("Compiler"), compiler->Render() | frame);
|
||||
auto flags_win = window(text("Flags"), flags->Render() | frame);
|
||||
auto compiler_win = window(text("Compiler"),
|
||||
compiler->Render() | vscroll_indicator | frame);
|
||||
auto flags_win =
|
||||
window(text("Flags"), flags->Render() | vscroll_indicator | frame);
|
||||
auto executable_win = window(text("Executable:"), executable_->Render());
|
||||
auto input_win =
|
||||
window(text("Input"),
|
||||
hbox({
|
||||
window(text("Input"), hbox({
|
||||
vbox({
|
||||
hbox({
|
||||
text("Add: "),
|
||||
@@ -229,7 +230,8 @@ int main(int argc, const char* argv[]) {
|
||||
filler(),
|
||||
}),
|
||||
separator(),
|
||||
input->Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
|
||||
input->Render() | vscroll_indicator | frame |
|
||||
size(HEIGHT, EQUAL, 3) | flex,
|
||||
}));
|
||||
return vbox({
|
||||
hbox({
|
||||
@@ -240,7 +242,7 @@ int main(int argc, const char* argv[]) {
|
||||
input_win | size(WIDTH, EQUAL, 60),
|
||||
}),
|
||||
filler(),
|
||||
}) | size(HEIGHT, LESS_THAN, 6),
|
||||
}) | size(HEIGHT, LESS_THAN, 8),
|
||||
hflow(render_command()) | flex_grow,
|
||||
}) |
|
||||
flex_grow | border;
|
||||
|
47
examples/component/maybe.cpp
Normal file
47
examples/component/maybe.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include <functional> // for function
|
||||
#include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
|
||||
#include <string> // for string, basic_string, allocator
|
||||
#include <vector> // for vector
|
||||
|
||||
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||
#include "ftxui/component/component.hpp" // for Menu
|
||||
#include "ftxui/component/component_options.hpp" // for MenuOption
|
||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||
|
||||
using namespace ftxui;
|
||||
Component Border(Component child) {
|
||||
return Renderer(child, [child] { return child->Render() | border; });
|
||||
}
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
|
||||
std::vector<std::string> entries = {
|
||||
"entry 1",
|
||||
"entry 2",
|
||||
"entry 3",
|
||||
};
|
||||
int menu_1_selected = 0;
|
||||
int menu_2_selected = 0;
|
||||
auto menu_1 = Radiobox(&entries, &menu_1_selected);
|
||||
auto menu_2 = Radiobox(&entries, &menu_2_selected);
|
||||
|
||||
menu_1 = Border(menu_1);
|
||||
menu_2 = Border(menu_2);
|
||||
|
||||
bool menu_1_show = false;
|
||||
bool menu_2_show = false;
|
||||
|
||||
auto layout = Container::Vertical({
|
||||
Checkbox("Show menu_1", &menu_1_show),
|
||||
Maybe(menu_1, &menu_1_show),
|
||||
Checkbox("Show menu_2", &menu_2_show),
|
||||
Maybe(menu_2, &menu_2_show),
|
||||
});
|
||||
|
||||
auto screen = ScreenInteractive::TerminalOutput();
|
||||
screen.Loop(layout);
|
||||
}
|
||||
|
||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||
// Use of this source code is governed by the MIT license that can be found in
|
||||
// the LICENSE file.
|
@@ -18,7 +18,8 @@ int main(int argc, const char* argv[]) {
|
||||
entries.push_back("Entry " + std::to_string(i));
|
||||
auto radiobox = Menu(&entries, &selected);
|
||||
auto renderer = Renderer(radiobox, [&] {
|
||||
return radiobox->Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
|
||||
return radiobox->Render() | vscroll_indicator | frame |
|
||||
size(HEIGHT, LESS_THAN, 10) | border;
|
||||
});
|
||||
|
||||
auto screen = ScreenInteractive::FitComponent();
|
||||
|
@@ -18,7 +18,8 @@ int main(int argc, const char* argv[]) {
|
||||
entries.push_back("RadioBox " + std::to_string(i));
|
||||
auto radiobox = Radiobox(&entries, &selected);
|
||||
auto renderer = Renderer(radiobox, [&] {
|
||||
return radiobox->Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
|
||||
return radiobox->Render() | vscroll_indicator | frame |
|
||||
size(HEIGHT, LESS_THAN, 10) | border;
|
||||
});
|
||||
|
||||
auto screen = ScreenInteractive::FitComponent();
|
||||
|
@@ -39,6 +39,7 @@ Component Menu(ConstStringListRef entries,
|
||||
int* selected_,
|
||||
Ref<MenuOption> = {});
|
||||
Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> = {});
|
||||
Component Dropdown(ConstStringListRef entries, int* selected);
|
||||
Component Radiobox(ConstStringListRef entries,
|
||||
int* selected_,
|
||||
Ref<RadioboxOption> option = {});
|
||||
@@ -55,6 +56,7 @@ Component Renderer(Component child, std::function<Element()>);
|
||||
Component Renderer(std::function<Element()>);
|
||||
Component Renderer(std::function<Element(bool /* focused */)>);
|
||||
Component CatchEvent(Component child, std::function<bool(Event)>);
|
||||
Component Maybe(Component, bool* show);
|
||||
|
||||
namespace Container {
|
||||
Component Vertical(Components children);
|
||||
|
@@ -74,6 +74,7 @@ struct Event {
|
||||
bool operator!=(const Event& other) const { return !operator==(other); }
|
||||
|
||||
//--- State section ----------------------------------------------------------
|
||||
ScreenInteractive* screen_ = nullptr;
|
||||
private:
|
||||
friend ComponentBase;
|
||||
friend ScreenInteractive;
|
||||
@@ -95,8 +96,6 @@ struct Event {
|
||||
struct Cursor cursor_;
|
||||
};
|
||||
std::string input_;
|
||||
|
||||
ScreenInteractive* screen_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
@@ -104,6 +104,8 @@ Element yframe(Element);
|
||||
Element focus(Element);
|
||||
Element select(Element);
|
||||
|
||||
Element vscroll_indicator(Element);
|
||||
|
||||
// --- Util --------------------------------------------------------------------
|
||||
Element hcenter(Element);
|
||||
Element vcenter(Element);
|
||||
|
@@ -57,7 +57,7 @@ Component GeneratorComponent(const char*& data, size_t& size, int depth) {
|
||||
if (depth <= 0)
|
||||
return Button(GeneratorString(data, size), [] {});
|
||||
|
||||
switch (value % 16) {
|
||||
switch (value % 18) {
|
||||
case 1:
|
||||
return Checkbox(GeneratorString(data, size), &g_bool);
|
||||
case 2:
|
||||
@@ -102,6 +102,10 @@ Component GeneratorComponent(const char*& data, size_t& size, int depth) {
|
||||
&g_int);
|
||||
case 15:
|
||||
return Container::Tab(GeneratorComponents(data, size, depth - 1), &g_int);
|
||||
case 16:
|
||||
return Maybe(GeneratorComponent(data, size, depth - 1), &g_bool);
|
||||
case 17:
|
||||
return Dropdown(&g_list, &g_int);
|
||||
default:
|
||||
return Button(GeneratorString(data, size), [] {});
|
||||
}
|
||||
|
54
src/ftxui/component/dropdown.cpp
Normal file
54
src/ftxui/component/dropdown.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/component/component_base.hpp"
|
||||
#include "ftxui/component/event.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
Component Dropdown(ConstStringListRef entries, int* selected) {
|
||||
class Impl : public ComponentBase {
|
||||
public:
|
||||
Impl(ConstStringListRef entries, int* selected)
|
||||
: entries_(std::move(entries)), selected_(selected) {
|
||||
CheckboxOption option;
|
||||
option.style_checked = "↓│";
|
||||
option.style_unchecked = "→│";
|
||||
checkbox_ = Checkbox(&title_, &show_, option),
|
||||
radiobox_ = Radiobox(entries_, selected_);
|
||||
|
||||
Add(Container::Vertical({
|
||||
checkbox_,
|
||||
Maybe(radiobox_, &show_),
|
||||
}));
|
||||
}
|
||||
|
||||
Element Render() override {
|
||||
title_ = entries_[*selected_];
|
||||
if (show_) {
|
||||
return vbox({
|
||||
checkbox_->Render(),
|
||||
separator(),
|
||||
radiobox_->Render() | vscroll_indicator | frame |
|
||||
size(HEIGHT, LESS_THAN, 12),
|
||||
}) |
|
||||
border;
|
||||
}
|
||||
|
||||
return vbox({
|
||||
checkbox_->Render() | border,
|
||||
filler(),
|
||||
});
|
||||
}
|
||||
|
||||
private:
|
||||
ConstStringListRef entries_;
|
||||
bool show_ = false;
|
||||
int* selected_;
|
||||
std::string title_;
|
||||
Component checkbox_;
|
||||
Component radiobox_;
|
||||
};
|
||||
|
||||
return Make<Impl>(std::move(entries), selected);
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
31
src/ftxui/component/maybe.cpp
Normal file
31
src/ftxui/component/maybe.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/component/component_base.hpp"
|
||||
#include "ftxui/component/event.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
Component Maybe(Component child, bool* show) {
|
||||
class Impl : public ComponentBase {
|
||||
public:
|
||||
Impl(bool* show): show_(show) {}
|
||||
|
||||
private:
|
||||
Element Render() override {
|
||||
return *show_ ? ComponentBase::Render() : std::make_unique<Node>();
|
||||
}
|
||||
bool Focusable() const override {
|
||||
return *show_ && ComponentBase::Focusable();
|
||||
}
|
||||
bool OnEvent(Event event) override {
|
||||
return *show_ && ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
bool* show_;
|
||||
};
|
||||
|
||||
auto maybe = Make<Impl>(show);
|
||||
maybe->Add(std::move(child));
|
||||
return maybe;
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
26
src/ftxui/component/show.cpp
Normal file
26
src/ftxui/component/show.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include "ftxui/component/component_base.hpp"
|
||||
|
||||
Component Maybe(Component child, bool* show) {
|
||||
class Impl : public ComponentBase {
|
||||
public:
|
||||
Impl(Component child, bool* show) : ComponentBase(child), show_(show) {}
|
||||
|
||||
private:
|
||||
Element Render() override {
|
||||
if (*show_)
|
||||
return ComponentBase::Render();
|
||||
else
|
||||
return text("");
|
||||
}
|
||||
bool Focusable() const override {
|
||||
return *show_ && ComponentBase::Focusable();
|
||||
}
|
||||
bool OnEvent(Event event) override {
|
||||
if (*show_)
|
||||
return false return ComponentBase::OnEvent(event);
|
||||
}
|
||||
|
||||
bool* show_;
|
||||
};
|
||||
return Make<Impl>(std::move(child), show);
|
||||
}
|
58
src/ftxui/dom/scroll_indicator.cpp
Normal file
58
src/ftxui/dom/scroll_indicator.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||
#include "ftxui/screen/box.hpp"
|
||||
#include "ftxui/screen/screen.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
/// @brief Add a filter that will invert the foreground and the background
|
||||
/// colors.
|
||||
/// @ingroup dom
|
||||
Element vscroll_indicator(Element child) {
|
||||
class Impl : public NodeDecorator {
|
||||
using NodeDecorator::NodeDecorator;
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children_[0]->requirement();
|
||||
requirement_.min_x++;
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
if (box_.x_min > box_.x_max)
|
||||
box_.x_max--;
|
||||
children_[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) final {
|
||||
Node::Render(screen);
|
||||
|
||||
const Box& stencil = screen.stencil;
|
||||
|
||||
int size_inner = box_.y_max - box_.y_min;
|
||||
int size_outter = stencil.y_max - stencil.y_min;
|
||||
if (size_outter >= size_inner)
|
||||
return;
|
||||
|
||||
int start_y = 2 * stencil.y_min + 2 * float(stencil.y_min - box_.y_min) *
|
||||
(size_outter - 1) / size_inner;
|
||||
int size = 2 * float(size_outter) * (size_outter - 1) / size_inner + 2;
|
||||
size = std::max(size, 1);
|
||||
|
||||
const int x = stencil.x_max;
|
||||
for (int y = stencil.y_min; y <= stencil.y_max; ++y) {
|
||||
bool up = (2 * y + -1 >= start_y) && (2 * y - 1 <= start_y + size);
|
||||
bool down = (2 * y - 0 >= start_y) && (2 * y - 0 <= start_y + size);
|
||||
|
||||
const char* c = up ? (down ? "┃" : "╹") : (down ? "╻" : " ");
|
||||
screen.PixelAt(x, y).character = c;
|
||||
screen.PixelAt(x, y).inverted = true;
|
||||
}
|
||||
};
|
||||
};
|
||||
return std::make_shared<Impl>(std::move(child));
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
@@ -98,16 +98,21 @@ struct TileEncoding {
|
||||
unsigned int down : 2;
|
||||
unsigned int round : 1;
|
||||
|
||||
// clang-format off
|
||||
bool operator<(const TileEncoding& other) const {
|
||||
union Converter {
|
||||
TileEncoding input;
|
||||
uint16_t output = 0;
|
||||
};
|
||||
Converter a, b;
|
||||
a.input = *this;
|
||||
b.input = other;
|
||||
return a.output < b.output;
|
||||
if (left < other.left) return true;
|
||||
if (left > other.left) return false;
|
||||
if (top < other.top) return true;
|
||||
if (top > other.top) return false;
|
||||
if (right < other.right) return true;
|
||||
if (right > other.right) return false;
|
||||
if (down < other.down) return true;
|
||||
if (down > other.down) return false;
|
||||
if (round < other.round) return true;
|
||||
if (round > other.round) return false;
|
||||
return false;
|
||||
}
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
|
Reference in New Issue
Block a user