9 Commits
v0.9 ... v0.10

Author SHA1 Message Date
ArthurSonzogni
75cd2b0fca Fix workflow 2021-09-30 21:29:41 +02:00
ArthurSonzogni
0a5e9f2a2f Add workflow creating releases. 2021-09-30 21:25:47 +02:00
ArthurSonzogni
66cdf9b2a5 Fix: box drawing comparison.
There was a bug. Converting the bitfield to int using the union wasn't
working correctly.
2021-09-30 20:55:47 +02:00
ArthurSonzogni
84287eb217 Use vscroll_indicator in examples. 2021-09-30 20:55:47 +02:00
Arthur Sonzogni
535974d291 Update README.md 2021-09-30 20:55:47 +02:00
ArthurSonzogni
753502998c Add a C++ badge. 2021-09-30 20:55:47 +02:00
ArthurSonzogni
31b5fac9c5 Add fuzzer to Maybe & Dropdown. 2021-09-30 20:55:47 +02:00
ArthurSonzogni
76b2f17488 fix: vscroll_indicator. Reserve one cell. 2021-09-30 20:55:47 +02:00
Arthur Sonzogni
c5ef0c7fb5 feat: Dropdown select menu. (#214)
Dom
 - `vscroll_indicator`. Show a scrollback indicator on the right.

Component
 - `Maybe`: Display an component conditionnally based on a boolean.
 - `Dropdown`: A dropdown select list.

This address:
https://github.com/ArthurSonzogni/FTXUI/issues/204
2021-09-30 20:55:47 +02:00
21 changed files with 420 additions and 58 deletions

39
.github/workflows/release.yaml vendored Normal file
View 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 }}

View File

@@ -1,5 +1,19 @@
# Changelog # 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) ## 0.9 (2021-09-26)
The initial release where changelog where written. The initial release where changelog where written.

View File

@@ -4,7 +4,7 @@ include(cmake/ftxui_git_version.cmake)
project(ftxui project(ftxui
LANGUAGES CXX LANGUAGES CXX
VERSION 0.9.${git_version} VERSION 0.10.${git_version}
) )
option(FTXUI_BUILD_DOCS "Set to ON to build tests" ON) 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/frame.cpp
src/ftxui/dom/gauge.cpp src/ftxui/dom/gauge.cpp
src/ftxui/dom/graph.cpp src/ftxui/dom/graph.cpp
src/ftxui/dom/hbox.cpp
src/ftxui/dom/gridbox.cpp src/ftxui/dom/gridbox.cpp
src/ftxui/dom/hbox.cpp
src/ftxui/dom/hflow.cpp src/ftxui/dom/hflow.cpp
src/ftxui/dom/inverted.cpp src/ftxui/dom/inverted.cpp
src/ftxui/dom/node.cpp src/ftxui/dom/node.cpp
src/ftxui/dom/node_decorator.cpp src/ftxui/dom/node_decorator.cpp
src/ftxui/dom/paragraph.cpp src/ftxui/dom/paragraph.cpp
src/ftxui/dom/reflect.cpp src/ftxui/dom/reflect.cpp
src/ftxui/dom/scroll_indicator.cpp
src/ftxui/dom/separator.cpp src/ftxui/dom/separator.cpp
src/ftxui/dom/size.cpp src/ftxui/dom/size.cpp
src/ftxui/dom/spinner.cpp src/ftxui/dom/spinner.cpp
@@ -87,8 +88,10 @@ add_library(component STATIC
src/ftxui/component/checkbox.cpp src/ftxui/component/checkbox.cpp
src/ftxui/component/component.cpp src/ftxui/component/component.cpp
src/ftxui/component/container.cpp src/ftxui/component/container.cpp
src/ftxui/component/dropdown.cpp
src/ftxui/component/event.cpp src/ftxui/component/event.cpp
src/ftxui/component/input.cpp src/ftxui/component/input.cpp
src/ftxui/component/maybe.cpp
src/ftxui/component/menu.cpp src/ftxui/component/menu.cpp
src/ftxui/component/radiobox.cpp src/ftxui/component/radiobox.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) include(cmake/ftxui_test.cmake)
endif() endif()
if(FTXUI_ENABLE_INSTALL)
include(cmake/ftxui_install.cmake)
endif()
if(FTXUI_BUILD_EXAMPLES) if(FTXUI_BUILD_EXAMPLES)
add_subdirectory(examples) add_subdirectory(examples)
endif() endif()
@@ -134,3 +133,9 @@ endif()
include(cmake/iwyu.cmake) include(cmake/iwyu.cmake)
include(cmake/ftxui_export.cmake) include(cmake/ftxui_export.cmake)
if(FTXUI_ENABLE_INSTALL)
include(cmake/ftxui_install.cmake)
include(cmake/ftxui_package.cmake)
endif()

View File

@@ -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] <br/>
[![license][badge.license]][license] <a href="https://github.com/ArthurSonzogni/FTXUI/wiki">Documentation</a> ·
[![contributors][badge.contributors]][contributors] <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 </p>
[badge.license]: https://img.shields.io/github/license/arthursonzogni/FTXUI?color=black
[badge.contributors]: https://img.shields.io/github/contributors/arthursonzogni/FTXUI?color=blue
[issues]: https://github.com/ArthurSonzogni/FTXUI/issues ## FTXUI
[license]: http://opensource.org/licenses/MIT
[contributors]: https://github.com/ArthurSonzogni/FTXUI/graphs/contributors
**Functional Terminal (X) User interface** <i>Functional Terminal (X) User interface</i>
A simple C++ library for terminal based user interface. A simple C++ library for terminal based user interface.
## Demo:
![Demo image](./examples/component/homescreen.gif)
## Feature ## Feature
* Functional style. Inspired by * Functional style. Inspired by
[[1]](https://hackernoon.com/building-reactive-terminal-interfaces-in-c-d392ce34e649?gi=d9fb9ce35901) [[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.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 [link.mac-clang]: https://github.com/ArthurSonzogni/FTXUI/actions/workflows/mac-clang.yaml
## Example: ## Example
~~~cpp ~~~cpp
vbox({ vbox({
hbox({ 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) - [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
- [Documentation](https://arthursonzogni.github.io/FTXUI/) - [Documentation](https://arthursonzogni.github.io/FTXUI/)
@@ -94,11 +99,11 @@ Feel free to add your projects here:
- [todoman](https://github.com/aaleino/todoman) - [todoman](https://github.com/aaleino/todoman)
- [TimeAccumulator](https://github.com/asari555/TimeAccumulator) - [TimeAccumulator](https://github.com/asari555/TimeAccumulator)
## Hosted on: ## Hosted on
* [github](https://github.com/ArthurSonzogni/ftxui) * [github](https://github.com/ArthurSonzogni/ftxui)
* [gitlab](https://gitlab.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 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. way you can specify which commit you would like to depends on.

16
cmake/ftxui_package.cmake Normal file
View 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)

View File

@@ -2,19 +2,21 @@ set(DIRECTORY_LIB component)
example(button) example(button)
example(checkbox) example(checkbox)
example(nested_screen)
example(checkbox_in_frame) example(checkbox_in_frame)
example(composition) example(composition)
example(dropdown)
example(gallery) example(gallery)
example(homescreen) example(homescreen)
example(input) example(input)
example(maybe)
example(menu) example(menu)
example(menu_in_frame)
example(menu2) example(menu2)
example(menu_multiple)
example(menu_entries) example(menu_entries)
example(menu_in_frame)
example(menu_multiple)
example(menu_style) example(menu_style)
example(modal_dialog) example(modal_dialog)
example(nested_screen)
example(print_key_press) example(print_key_press)
example(radiobox) example(radiobox)
example(radiobox_in_frame) example(radiobox_in_frame)

View File

@@ -24,7 +24,8 @@ int main(int argc, const char* argv[]) {
} }
auto renderer = Renderer(container, [&] { 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(); auto screen = ScreenInteractive::FitComponent();

View 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.

View File

@@ -214,12 +214,13 @@ int main(int argc, const char* argv[]) {
}; };
auto compiler_renderer = Renderer(compiler_component, [&] { auto compiler_renderer = Renderer(compiler_component, [&] {
auto compiler_win = window(text("Compiler"), compiler->Render() | frame); auto compiler_win = window(text("Compiler"),
auto flags_win = window(text("Flags"), flags->Render() | frame); 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 executable_win = window(text("Executable:"), executable_->Render());
auto input_win = auto input_win =
window(text("Input"), window(text("Input"), hbox({
hbox({
vbox({ vbox({
hbox({ hbox({
text("Add: "), text("Add: "),
@@ -229,7 +230,8 @@ int main(int argc, const char* argv[]) {
filler(), filler(),
}), }),
separator(), separator(),
input->Render() | frame | size(HEIGHT, EQUAL, 3) | flex, input->Render() | vscroll_indicator | frame |
size(HEIGHT, EQUAL, 3) | flex,
})); }));
return vbox({ return vbox({
hbox({ hbox({
@@ -240,7 +242,7 @@ int main(int argc, const char* argv[]) {
input_win | size(WIDTH, EQUAL, 60), input_win | size(WIDTH, EQUAL, 60),
}), }),
filler(), filler(),
}) | size(HEIGHT, LESS_THAN, 6), }) | size(HEIGHT, LESS_THAN, 8),
hflow(render_command()) | flex_grow, hflow(render_command()) | flex_grow,
}) | }) |
flex_grow | border; flex_grow | border;

View 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.

View File

@@ -18,7 +18,8 @@ int main(int argc, const char* argv[]) {
entries.push_back("Entry " + std::to_string(i)); entries.push_back("Entry " + std::to_string(i));
auto radiobox = Menu(&entries, &selected); auto radiobox = Menu(&entries, &selected);
auto renderer = Renderer(radiobox, [&] { 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(); auto screen = ScreenInteractive::FitComponent();

View File

@@ -18,7 +18,8 @@ int main(int argc, const char* argv[]) {
entries.push_back("RadioBox " + std::to_string(i)); entries.push_back("RadioBox " + std::to_string(i));
auto radiobox = Radiobox(&entries, &selected); auto radiobox = Radiobox(&entries, &selected);
auto renderer = Renderer(radiobox, [&] { 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(); auto screen = ScreenInteractive::FitComponent();

View File

@@ -39,6 +39,7 @@ Component Menu(ConstStringListRef entries,
int* selected_, int* selected_,
Ref<MenuOption> = {}); Ref<MenuOption> = {});
Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> = {}); Component MenuEntry(ConstStringRef label, Ref<MenuEntryOption> = {});
Component Dropdown(ConstStringListRef entries, int* selected);
Component Radiobox(ConstStringListRef entries, Component Radiobox(ConstStringListRef entries,
int* selected_, int* selected_,
Ref<RadioboxOption> option = {}); Ref<RadioboxOption> option = {});
@@ -55,6 +56,7 @@ Component Renderer(Component child, std::function<Element()>);
Component Renderer(std::function<Element()>); Component Renderer(std::function<Element()>);
Component Renderer(std::function<Element(bool /* focused */)>); Component Renderer(std::function<Element(bool /* focused */)>);
Component CatchEvent(Component child, std::function<bool(Event)>); Component CatchEvent(Component child, std::function<bool(Event)>);
Component Maybe(Component, bool* show);
namespace Container { namespace Container {
Component Vertical(Components children); Component Vertical(Components children);

View File

@@ -74,6 +74,7 @@ struct Event {
bool operator!=(const Event& other) const { return !operator==(other); } bool operator!=(const Event& other) const { return !operator==(other); }
//--- State section ---------------------------------------------------------- //--- State section ----------------------------------------------------------
ScreenInteractive* screen_ = nullptr;
private: private:
friend ComponentBase; friend ComponentBase;
friend ScreenInteractive; friend ScreenInteractive;
@@ -95,8 +96,6 @@ struct Event {
struct Cursor cursor_; struct Cursor cursor_;
}; };
std::string input_; std::string input_;
ScreenInteractive* screen_ = nullptr;
}; };
} // namespace ftxui } // namespace ftxui

View File

@@ -104,6 +104,8 @@ Element yframe(Element);
Element focus(Element); Element focus(Element);
Element select(Element); Element select(Element);
Element vscroll_indicator(Element);
// --- Util -------------------------------------------------------------------- // --- Util --------------------------------------------------------------------
Element hcenter(Element); Element hcenter(Element);
Element vcenter(Element); Element vcenter(Element);

View File

@@ -57,7 +57,7 @@ Component GeneratorComponent(const char*& data, size_t& size, int depth) {
if (depth <= 0) if (depth <= 0)
return Button(GeneratorString(data, size), [] {}); return Button(GeneratorString(data, size), [] {});
switch (value % 16) { switch (value % 18) {
case 1: case 1:
return Checkbox(GeneratorString(data, size), &g_bool); return Checkbox(GeneratorString(data, size), &g_bool);
case 2: case 2:
@@ -102,6 +102,10 @@ Component GeneratorComponent(const char*& data, size_t& size, int depth) {
&g_int); &g_int);
case 15: case 15:
return Container::Tab(GeneratorComponents(data, size, depth - 1), &g_int); 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: default:
return Button(GeneratorString(data, size), [] {}); return Button(GeneratorString(data, size), [] {});
} }

View 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

View 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

View 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);
}

View 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

View File

@@ -98,16 +98,21 @@ struct TileEncoding {
unsigned int down : 2; unsigned int down : 2;
unsigned int round : 1; unsigned int round : 1;
// clang-format off
bool operator<(const TileEncoding& other) const { bool operator<(const TileEncoding& other) const {
union Converter { if (left < other.left) return true;
TileEncoding input; if (left > other.left) return false;
uint16_t output = 0; if (top < other.top) return true;
}; if (top > other.top) return false;
Converter a, b; if (right < other.right) return true;
a.input = *this; if (right > other.right) return false;
b.input = other; if (down < other.down) return true;
return a.output < b.output; 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 // clang-format off