mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 12:37:06 +08:00
Merge pull request #90 from ArthurSonzogni/functionnal_component
Functional component
This commit is contained in:
commit
900ed256ae
@ -15,7 +15,7 @@ endif()
|
|||||||
|
|
||||||
project(ftxui
|
project(ftxui
|
||||||
LANGUAGES CXX
|
LANGUAGES CXX
|
||||||
VERSION 0.4.${git_version}
|
VERSION 0.5.${git_version}
|
||||||
)
|
)
|
||||||
|
|
||||||
option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON)
|
option(FTXUI_BUILD_EXAMPLES "Set to ON to build examples" ON)
|
||||||
@ -80,6 +80,7 @@ add_library(component
|
|||||||
include/ftxui/component/captured_mouse.hpp
|
include/ftxui/component/captured_mouse.hpp
|
||||||
include/ftxui/component/checkbox.hpp
|
include/ftxui/component/checkbox.hpp
|
||||||
include/ftxui/component/component.hpp
|
include/ftxui/component/component.hpp
|
||||||
|
include/ftxui/component/component_base.hpp
|
||||||
include/ftxui/component/container.hpp
|
include/ftxui/component/container.hpp
|
||||||
include/ftxui/component/event.hpp
|
include/ftxui/component/event.hpp
|
||||||
include/ftxui/component/input.hpp
|
include/ftxui/component/input.hpp
|
||||||
@ -88,7 +89,6 @@ add_library(component
|
|||||||
include/ftxui/component/radiobox.hpp
|
include/ftxui/component/radiobox.hpp
|
||||||
include/ftxui/component/receiver.hpp
|
include/ftxui/component/receiver.hpp
|
||||||
include/ftxui/component/screen_interactive.hpp
|
include/ftxui/component/screen_interactive.hpp
|
||||||
include/ftxui/component/slider.hpp
|
|
||||||
include/ftxui/component/toggle.hpp
|
include/ftxui/component/toggle.hpp
|
||||||
src/ftxui/component/button.cpp
|
src/ftxui/component/button.cpp
|
||||||
src/ftxui/component/checkbox.cpp
|
src/ftxui/component/checkbox.cpp
|
||||||
@ -99,6 +99,7 @@ add_library(component
|
|||||||
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
|
||||||
|
src/ftxui/component/renderer.cpp
|
||||||
src/ftxui/component/screen_interactive.cpp
|
src/ftxui/component/screen_interactive.cpp
|
||||||
src/ftxui/component/slider.cpp
|
src/ftxui/component/slider.cpp
|
||||||
src/ftxui/component/terminal_input_parser.cpp
|
src/ftxui/component/terminal_input_parser.cpp
|
||||||
|
@ -44,7 +44,7 @@ PROJECT_NUMBER = @CMAKE_PROJECT_VERSION@
|
|||||||
# for a project that appears at the top of each page and should give viewer a
|
# for a project that appears at the top of each page and should give viewer a
|
||||||
# quick idea about the purpose of the project. Keep the description short.
|
# quick idea about the purpose of the project. Keep the description short.
|
||||||
|
|
||||||
PROJECT_BRIEF = "C++ functionnal terminal UI."
|
PROJECT_BRIEF = "C++ functional terminal UI."
|
||||||
|
|
||||||
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
|
||||||
# in the documentation. The maximum height of the logo should not exceed 55
|
# in the documentation. The maximum height of the logo should not exceed 55
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
@example ./examples/component/input.cpp
|
@example ./examples/component/input.cpp
|
||||||
@example ./examples/component/homescreen.cpp
|
@example ./examples/component/homescreen.cpp
|
||||||
@example ./examples/component/radiobox.cpp
|
@example ./examples/component/radiobox.cpp
|
||||||
|
@example ./examples/component/slider_rgb.cpp
|
||||||
@example ./examples/component/menu.cpp
|
@example ./examples/component/menu.cpp
|
||||||
@example ./examples/component/menu_style.cpp
|
@example ./examples/component/menu_style.cpp
|
||||||
@example ./examples/component/radiobox_in_frame.cpp
|
@example ./examples/component/radiobox_in_frame.cpp
|
||||||
|
208
doc/mainpage.md
208
doc/mainpage.md
@ -31,7 +31,7 @@ int main(void) {
|
|||||||
Dimension::Fit(document) // Height
|
Dimension::Fit(document) // Height
|
||||||
);
|
);
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString() << std::endl;
|
screen.Print();
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
@ -44,28 +44,71 @@ int main(void) {
|
|||||||
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
|
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
|
||||||
```
|
```
|
||||||
|
|
||||||
**cmake**
|
# Build
|
||||||
```c
|
|
||||||
|
## Using CMake
|
||||||
|
|
||||||
|
CMakeLists.txt
|
||||||
|
~~~cmake
|
||||||
cmake_minimum_required (VERSION 3.11)
|
cmake_minimum_required (VERSION 3.11)
|
||||||
|
|
||||||
|
# --- Fetch FTXUI --------------------------------------------------------------
|
||||||
include(FetchContent)
|
include(FetchContent)
|
||||||
|
|
||||||
|
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
|
||||||
FetchContent_Declare(ftxui
|
FetchContent_Declare(ftxui
|
||||||
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
|
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
|
||||||
|
# Specify a GIT_TAG here.
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_GetProperties(ftxui)
|
FetchContent_GetProperties(ftxui)
|
||||||
if(NOT ftxui_POPULATED)
|
if(NOT ftxui_POPULATED)
|
||||||
FetchContent_Populate(ftxui)
|
FetchContent_Populate(ftxui)
|
||||||
add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
|
add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(main src/main.cpp)
|
# ------------------------------------------------------------------------------
|
||||||
target_link_libraries(main
|
|
||||||
|
project(ftxui-starter
|
||||||
|
LANGUAGES CXX
|
||||||
|
VERSION 1.0.0
|
||||||
|
)
|
||||||
|
|
||||||
|
add_executable(ftxui-starter src/main.cpp)
|
||||||
|
target_include_directories(ftxui-starter PRIVATE src)
|
||||||
|
|
||||||
|
target_link_libraries(ftxui-starter
|
||||||
PRIVATE ftxui::screen
|
PRIVATE ftxui::screen
|
||||||
PRIVATE ftxui::dom
|
PRIVATE ftxui::dom
|
||||||
PRIVATE ftxui::component # Not needed for this example.
|
PRIVATE ftxui::component # Not needed for this example.
|
||||||
)
|
)
|
||||||
set_target_properties(main PROPERTIES CXX_STANDARD 17)
|
|
||||||
```
|
# C++17 is used. We requires fold expressions at least.
|
||||||
|
set_target_properties(ftxui-starter PROPERTIES CXX_STANDARD 17)
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Build
|
||||||
|
~~~
|
||||||
|
mkdir build && cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
./main
|
||||||
|
~~~
|
||||||
|
|
||||||
|
## Using NXXM
|
||||||
|
|
||||||
|
**.nxxm/deps**
|
||||||
|
~~~json
|
||||||
|
{
|
||||||
|
"ArthurSonzogni/FTXUI": {}
|
||||||
|
}
|
||||||
|
~~~
|
||||||
|
|
||||||
|
Build:
|
||||||
|
~~~
|
||||||
|
nxxm . -t clang-cxx17
|
||||||
|
~~~
|
||||||
|
|
||||||
# List of modules.
|
# List of modules.
|
||||||
|
|
||||||
@ -82,7 +125,7 @@ input. It defines a set of ftxui::Component. The use can navigates using the
|
|||||||
arrow keys and interact with widgets like checkbox/inputbox/... You can make you
|
arrow keys and interact with widgets like checkbox/inputbox/... You can make you
|
||||||
own components.
|
own components.
|
||||||
|
|
||||||
## screen
|
# screen
|
||||||
|
|
||||||
It defines a ftxui::Screen. This is a grid of ftxui::Pixel. A Pixel represent a
|
It defines a ftxui::Screen. This is a grid of ftxui::Pixel. A Pixel represent a
|
||||||
unicode character and its associated style (bold, colors, etc...).
|
unicode character and its associated style (bold, colors, etc...).
|
||||||
@ -106,7 +149,7 @@ The screen can be printed as a string using ftxui::Screen::ToString().
|
|||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
## dom
|
# dom
|
||||||
|
|
||||||
This module defines a hierachical set of Element. An element manages layout and can be responsive to the terminal dimensions.
|
This module defines a hierachical set of Element. An element manages layout and can be responsive to the terminal dimensions.
|
||||||
|
|
||||||
@ -130,23 +173,6 @@ You only need one header: ftxui/dom/elements.hpp
|
|||||||
|
|
||||||
\include ftxui/dom/elements.hpp
|
\include ftxui/dom/elements.hpp
|
||||||
|
|
||||||
## component
|
|
||||||
|
|
||||||
Finally, the ftxui/component directory defines the logic to get interactivity.
|
|
||||||
|
|
||||||
Please take a look at ./examples/component
|
|
||||||
|
|
||||||
This provides:
|
|
||||||
1. A main loop.
|
|
||||||
2. Get events and respond to them.
|
|
||||||
3. A predefined implementation of "keyboard navigation".
|
|
||||||
4. A set of predefined widget: CheckBox, RadioBox, Input, Menu, Toggle.
|
|
||||||
|
|
||||||
# ftxui/dom
|
|
||||||
|
|
||||||
Every elements of the dom are declared from:
|
|
||||||
\ref ftxui/dom/elements.hpp
|
|
||||||
|
|
||||||
## text
|
## text
|
||||||
|
|
||||||
The most simple widget. It displays a text.
|
The most simple widget. It displays a text.
|
||||||
@ -219,6 +245,7 @@ border(gauge(0.5))
|
|||||||
~~~
|
~~~
|
||||||
|
|
||||||
## graph
|
## graph
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223726" src="https://asciinema.org/a/223726.js" async></script>
|
<script id="asciicast-223726" src="https://asciinema.org/a/223726.js" async></script>
|
||||||
@endhtmlonly
|
@endhtmlonly
|
||||||
@ -362,7 +389,25 @@ An horizontal flow layout is implemented by:
|
|||||||
└────┘└───────────────────────────────────┘└───────────────────────────────────┘
|
└────┘└───────────────────────────────────┘└───────────────────────────────────┘
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
# ftxui/component
|
|
||||||
|
# component
|
||||||
|
|
||||||
|
The `ftxui/component` directory defines the logic to get produce
|
||||||
|
interactive component responding to user's events (keyboard, mouse, etc...)
|
||||||
|
|
||||||
|
A ftxui::ScreenInteractive defines a main loop to render a component.
|
||||||
|
|
||||||
|
A ftxui::Component is a shared pointer to a ftxui::ComponentBase. The later
|
||||||
|
defines
|
||||||
|
- ftxui::ComponentBase::Render(): How to render the interface.
|
||||||
|
- ftxui::ComponentBase::OnEvent(): How to react to events.
|
||||||
|
- ftxui::ComponentBase::Add(): Give a parent/child relation ship in between
|
||||||
|
two component. This defines a tree a components, which help properly define
|
||||||
|
how keyboard navigation works.
|
||||||
|
|
||||||
|
Predefined components are available in `ftxui/dom/component.hpp`:
|
||||||
|
|
||||||
|
\include ftxui/component/component.hpp
|
||||||
|
|
||||||
Element are stateless object. On the other side, components are used when an
|
Element are stateless object. On the other side, components are used when an
|
||||||
internal state is needed. Components are used to interact with the user with
|
internal state is needed. Components are used to interact with the user with
|
||||||
@ -370,7 +415,7 @@ its keyboard. They handle keyboard navigation, including component focus.
|
|||||||
|
|
||||||
## Input
|
## Input
|
||||||
|
|
||||||
The component: \ref ftxui::Input
|
Produced by: ftxui::Input() from "ftxui/component/component.hpp"
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223719" src="https://asciinema.org/a/223719.js" async></script>
|
<script id="asciicast-223719" src="https://asciinema.org/a/223719.js" async></script>
|
||||||
@ -378,7 +423,7 @@ The component: \ref ftxui::Input
|
|||||||
|
|
||||||
## Menu
|
## Menu
|
||||||
|
|
||||||
The component: \ref ftxui::Menu
|
Produced by: ftxui::Menu() from "ftxui/component/component.hpp"
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223720" src="https://asciinema.org/a/223720.js" async></script>
|
<script id="asciicast-223720" src="https://asciinema.org/a/223720.js" async></script>
|
||||||
@ -386,7 +431,7 @@ The component: \ref ftxui::Menu
|
|||||||
|
|
||||||
## Toggle.
|
## Toggle.
|
||||||
|
|
||||||
The component: \ref ftxui::Toggle
|
Produced by: ftxui::Toggle() from "ftxui/component/component.hpp"
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223722" src="https://asciinema.org/a/223722.js" async></script>
|
<script id="asciicast-223722" src="https://asciinema.org/a/223722.js" async></script>
|
||||||
@ -394,7 +439,7 @@ The component: \ref ftxui::Toggle
|
|||||||
|
|
||||||
## CheckBox
|
## CheckBox
|
||||||
|
|
||||||
The component: \ref ftxui::CheckBox
|
Produced by: ftxui::Checkbox() from "ftxui/component/component.hpp"
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223724" src="https://asciinema.org/a/223724.js" async></script>
|
<script id="asciicast-223724" src="https://asciinema.org/a/223724.js" async></script>
|
||||||
@ -402,99 +447,32 @@ The component: \ref ftxui::CheckBox
|
|||||||
|
|
||||||
## RadioBox
|
## RadioBox
|
||||||
|
|
||||||
The component: \ref ftxui::RadioBox
|
Produced by: ftxui::Radiobox() from "ftxui/component/component.hpp"
|
||||||
|
|
||||||
@htmlonly
|
@htmlonly
|
||||||
<script id="asciicast-223725" src="https://asciinema.org/a/223725.js" async></script>
|
<script id="asciicast-223725" src="https://asciinema.org/a/223725.js" async></script>
|
||||||
@endhtmlonly
|
@endhtmlonly
|
||||||
|
|
||||||
# Build
|
## Renderer
|
||||||
|
|
||||||
Assuming this example example.cpp file.
|
Produced by: ftxui::Renderer() from \ref "ftxui/component/component.hpp". This
|
||||||
|
component decorate another one by using a different function to render an
|
||||||
|
interface.
|
||||||
|
|
||||||
**main.cpp**
|
## Container::Horizontal
|
||||||
~~~cpp
|
|
||||||
#include "ftxui/screen/screen.c
|
|
||||||
#include "ftxui/dom/elements.c
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
int main(int argc, const char *argv[]) {
|
Produced by: ftxui::Container::Horizontal() from
|
||||||
using namespace ftxui;
|
"ftxui/component/component.hpp". It displays a list of components horizontally
|
||||||
auto document =
|
and handle keyboard/mouse navigation.
|
||||||
hbox({
|
|
||||||
text(L"left") | bold | border,
|
|
||||||
text(L"middle") | flex | border,
|
|
||||||
text(L"right") | border,
|
|
||||||
});
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
|
||||||
Render(screen, document);
|
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
## Container::Vertial
|
||||||
|
|
||||||
return 0;
|
Produced by: ftxui::Container::Vertical() from
|
||||||
}
|
"ftxui/component/component.hpp". It displays a list of components vertically
|
||||||
~~~
|
and handles keyboard/mouse navigation.
|
||||||
|
|
||||||
## Using CMake
|
## Container::Tab
|
||||||
|
|
||||||
CMakeLists.txt
|
Produced by: ftxui::Container::Tab() from
|
||||||
~~~cmake
|
"ftxui/component/component.hpp". It take a list of component and display only
|
||||||
cmake_minimum_required (VERSION 3.11)
|
one of them. This is useful for implementing a tab bar.
|
||||||
|
|
||||||
# --- Fetch FTXUI --------------------------------------------------------------
|
|
||||||
include(FetchContent)
|
|
||||||
|
|
||||||
set(FETCHCONTENT_UPDATES_DISCONNECTED TRUE)
|
|
||||||
FetchContent_Declare(ftxui
|
|
||||||
GIT_REPOSITORY https://github.com/ArthurSonzogni/ftxui
|
|
||||||
# Specify a GIT TAG here.
|
|
||||||
)
|
|
||||||
|
|
||||||
FetchContent_GetProperties(ftxui)
|
|
||||||
if(NOT ftxui_POPULATED)
|
|
||||||
FetchContent_Populate(ftxui)
|
|
||||||
add_subdirectory(${ftxui_SOURCE_DIR} ${ftxui_BINARY_DIR} EXCLUDE_FROM_ALL)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
project(ftxui-starter
|
|
||||||
LANGUAGES CXX
|
|
||||||
VERSION 1.0.0
|
|
||||||
)
|
|
||||||
|
|
||||||
add_executable(ftxui-starter src/main.cpp)
|
|
||||||
target_include_directories(ftxui-starter PRIVATE src)
|
|
||||||
|
|
||||||
target_link_libraries(ftxui-starter
|
|
||||||
PRIVATE ftxui::screen
|
|
||||||
PRIVATE ftxui::dom
|
|
||||||
PRIVATE ftxui::component # Not needed for this example.
|
|
||||||
)
|
|
||||||
|
|
||||||
# C++17 is used. We requires fold expressions at least.
|
|
||||||
set_target_properties(ftxui-starter PROPERTIES CXX_STANDARD 17)
|
|
||||||
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Build
|
|
||||||
~~~
|
|
||||||
mkdir build && cd build
|
|
||||||
cmake ..
|
|
||||||
make
|
|
||||||
./main
|
|
||||||
~~~
|
|
||||||
|
|
||||||
## Using NXXM
|
|
||||||
|
|
||||||
**.nxxm/deps**
|
|
||||||
~~~json
|
|
||||||
{
|
|
||||||
"ArthurSonzogni/FTXUI": {}
|
|
||||||
}
|
|
||||||
~~~
|
|
||||||
|
|
||||||
Build:
|
|
||||||
~~~
|
|
||||||
nxxm . -t clang-cxx17
|
|
||||||
~~~
|
|
||||||
|
@ -17,6 +17,7 @@ example(modal_dialog)
|
|||||||
example(radiobox)
|
example(radiobox)
|
||||||
example(radiobox_in_frame)
|
example(radiobox_in_frame)
|
||||||
example(slider)
|
example(slider)
|
||||||
|
example(slider_rgb)
|
||||||
example(tab_horizontal)
|
example(tab_horizontal)
|
||||||
example(tab_vertical)
|
example(tab_vertical)
|
||||||
example(toggle)
|
example(toggle)
|
||||||
|
@ -1,51 +1,37 @@
|
|||||||
#include <functional> // for function
|
#include <memory> // for __shared_ptr_access, shared_ptr
|
||||||
#include <memory> // for unique_ptr, make_u...
|
#include <string> // for operator+, to_wstring
|
||||||
#include <string> // for wstring
|
|
||||||
#include <utility> // for move
|
|
||||||
#include <vector> // for vector
|
|
||||||
|
|
||||||
#include "ftxui/component/button.hpp" // for Button
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/component.hpp" // for Button, Horizontal, Renderer
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "ftxui/dom/elements.hpp" // for separator, Element, gauge, text, operator|, vbox, border
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
|
||||||
private:
|
|
||||||
std::vector<std::unique_ptr<Button>> buttons_;
|
|
||||||
Container container_ = Container::Horizontal();
|
|
||||||
|
|
||||||
public:
|
|
||||||
MyComponent() {
|
|
||||||
Add(&container_);
|
|
||||||
|
|
||||||
auto button_add = std::make_unique<Button>();
|
|
||||||
auto button_remove = std::make_unique<Button>();
|
|
||||||
container_.Add(button_add.get());
|
|
||||||
container_.Add(button_remove.get());
|
|
||||||
button_add->label = L"Add one button";
|
|
||||||
button_remove->label = L"Remove last button";
|
|
||||||
|
|
||||||
button_add->on_click = [&] {
|
|
||||||
auto extra_button = std::make_unique<Button>();
|
|
||||||
extra_button->label = L"extra button";
|
|
||||||
container_.Add(extra_button.get());
|
|
||||||
buttons_.push_back(std::move(extra_button));
|
|
||||||
};
|
|
||||||
|
|
||||||
button_remove->on_click = [&] { buttons_.resize(buttons_.size() - 1); };
|
|
||||||
|
|
||||||
buttons_.push_back(std::move(button_add));
|
|
||||||
buttons_.push_back(std::move(button_remove));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
int value = 50;
|
||||||
MyComponent component;
|
|
||||||
screen.Loop(&component);
|
// The tree of components. This defines how to navigate using the keyboard.
|
||||||
|
auto buttons = Container::Horizontal({
|
||||||
|
Button("Decrease", [&] { value--; }),
|
||||||
|
Button("Increase", [&] { value++; }),
|
||||||
|
});
|
||||||
|
|
||||||
|
// Modify the way to render them on screen:
|
||||||
|
auto component = Renderer(buttons, [&] {
|
||||||
|
return vbox({
|
||||||
|
text(L"value = " + std::to_wstring(value)),
|
||||||
|
separator(),
|
||||||
|
gauge(value * 0.01f),
|
||||||
|
separator(),
|
||||||
|
buttons->Render(),
|
||||||
|
}) |
|
||||||
|
border;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
|
screen.Loop(component);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,34 +1,23 @@
|
|||||||
#include "ftxui/component/checkbox.hpp"
|
#include "ftxui/component/checkbox.hpp"
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component.hpp" // for Checkbox, Vertical
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
|
||||||
private:
|
|
||||||
CheckBox box_1_;
|
|
||||||
CheckBox box_2_;
|
|
||||||
CheckBox box_3_;
|
|
||||||
Container container_ = Container::Vertical();
|
|
||||||
|
|
||||||
public:
|
|
||||||
MyComponent() {
|
|
||||||
Add(&container_);
|
|
||||||
container_.Add(&box_1_);
|
|
||||||
container_.Add(&box_2_);
|
|
||||||
container_.Add(&box_3_);
|
|
||||||
box_1_.label = L"Build examples";
|
|
||||||
box_2_.label = L"Build tests";
|
|
||||||
box_3_.label = L"Use WebAssembly";
|
|
||||||
box_3_.state = true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
bool build_examples_state = false;
|
||||||
|
bool build_tests_state = false;
|
||||||
|
bool use_webassembly_state = true;
|
||||||
|
|
||||||
|
auto component = Container::Vertical({
|
||||||
|
Checkbox("Build examples", &build_examples_state),
|
||||||
|
Checkbox("Build tests", &build_tests_state),
|
||||||
|
Checkbox("Use WebAssembly", &use_webassembly_state),
|
||||||
|
});
|
||||||
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
screen.Loop(component);
|
||||||
screen.Loop(&component);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,50 +1,36 @@
|
|||||||
#include <memory> // for allocator_traits<>...
|
#include <memory> // for __shared_ptr_access, allocator_traits<>::value_type, shared_ptr
|
||||||
#include <string> // for operator+, wstring
|
#include <string> // for operator+
|
||||||
#include <utility> // for move
|
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/checkbox.hpp" // for CheckBox
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Vertical
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/dom/elements.hpp" // for Element, operator|
|
#include "ftxui/dom/elements.hpp" // for Element, operator|, size, border, frame, HEIGHT, LESS_THAN
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
#include "ftxui/screen/string.hpp" // for to_wstring
|
#include "ftxui/screen/string.hpp" // for to_wstring
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
struct CheckboxState {
|
||||||
public:
|
bool checked;
|
||||||
MyComponent() {
|
|
||||||
Add(&container);
|
|
||||||
checkbox.resize(30);
|
|
||||||
for (int i = 0; i < checkbox.size(); ++i) {
|
|
||||||
checkbox[i].label = (L"CheckBox " + to_wstring(i));
|
|
||||||
container.Add(&checkbox[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
Element Render() override {
|
|
||||||
Elements content;
|
|
||||||
for (auto& it : checkbox) {
|
|
||||||
content.push_back(it.Render());
|
|
||||||
}
|
|
||||||
return vbox(std::move(content))
|
|
||||||
| frame
|
|
||||||
| size(HEIGHT, LESS_THAN, 10)
|
|
||||||
| border;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::vector<CheckBox> checkbox;
|
|
||||||
Container container = Container::Vertical();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
int size = 30;
|
||||||
|
std::vector<CheckboxState> states(size);
|
||||||
|
auto container = Container::Vertical({});
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
states[i].checked = false;
|
||||||
|
container->Add(Checkbox(L"Checkbox" + to_wstring(i), &states[i].checked));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto component = Renderer(container, [&] {
|
||||||
|
return container->Render() | frame | ftxui::size(HEIGHT, LESS_THAN, 10) |
|
||||||
|
border;
|
||||||
|
});
|
||||||
|
|
||||||
auto screen = ScreenInteractive::FitComponent();
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
MyComponent component;
|
screen.Loop(component);
|
||||||
screen.Loop(&component);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,130 +1,126 @@
|
|||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <memory> // for allocator, unique_ptr
|
#include <memory> // for shared_ptr, allocator, __shared_ptr_access
|
||||||
#include <string> // for wstring
|
#include <string> // for wstring, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/button.hpp" // for Button
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/checkbox.hpp" // for CheckBox
|
#include "ftxui/component/component.hpp" // for Slider, Checkbox, Vertical, Renderer, Button, Input, Menu, Radiobox, Toggle
|
||||||
#include "ftxui/component/component.hpp" // for Component, Compone...
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
#include "ftxui/component/input.hpp" // for Input
|
#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, xflex, text, WIDTH, hbox, vbox, EQUAL, border, GREATER_THAN
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
|
||||||
#include "ftxui/component/radiobox.hpp" // for RadioBox
|
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
|
||||||
#include "ftxui/component/slider.hpp" // for Slider
|
|
||||||
#include "ftxui/component/toggle.hpp" // for Toggle
|
|
||||||
#include "ftxui/dom/elements.hpp" // for separator, operator|
|
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
// Display a component nicely with a title on the left.
|
||||||
Container container = Container::Vertical();
|
Component Wrap(std::wstring name, Component component) {
|
||||||
Menu menu;
|
return Renderer(component, [name, component] {
|
||||||
Toggle toggle;
|
return hbox({
|
||||||
Container checkbox_container = Container::Vertical();
|
text(name) | size(WIDTH, EQUAL, 8),
|
||||||
CheckBox checkbox1;
|
separator(),
|
||||||
CheckBox checkbox2;
|
component->Render() | xflex,
|
||||||
RadioBox radiobox;
|
}) |
|
||||||
Input input;
|
xflex;
|
||||||
Button button;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
int slider_value_1_ = 12;
|
int main(int argc, const char* argv[]) {
|
||||||
int slider_value_2_ = 56;
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
int slider_value_3_ = 128;
|
|
||||||
ComponentPtr slider_1_ = Slider(L"R:", &slider_value_1_, 0, 256, 1);
|
|
||||||
ComponentPtr slider_2_ = Slider(L"G:", &slider_value_2_, 0, 256, 1);
|
|
||||||
ComponentPtr slider_3_ = Slider(L"B:", &slider_value_3_, 0, 256, 1);
|
|
||||||
|
|
||||||
public:
|
// -- Menu
|
||||||
MyComponent() {
|
// ----------------------------------------------------------------------
|
||||||
Add(&container);
|
const std::vector<std::wstring> menu_entries = {
|
||||||
menu.entries = {
|
|
||||||
L"Menu 1",
|
L"Menu 1",
|
||||||
L"Menu 2",
|
L"Menu 2",
|
||||||
L"Menu 3",
|
L"Menu 3",
|
||||||
L"Menu 4",
|
L"Menu 4",
|
||||||
};
|
};
|
||||||
container.Add(&menu);
|
int menu_selected = 0;
|
||||||
|
auto menu = Menu(&menu_entries, &menu_selected);
|
||||||
|
menu = Wrap(L"Menu", menu);
|
||||||
|
|
||||||
toggle.entries = {
|
// -- Toggle------------------------------------------------------------------
|
||||||
|
int toggle_selected = 0;
|
||||||
|
std::vector<std::wstring> toggle_entries = {
|
||||||
L"Toggle_1",
|
L"Toggle_1",
|
||||||
L"Toggle_2",
|
L"Toggle_2",
|
||||||
};
|
};
|
||||||
container.Add(&toggle);
|
auto toggle = Toggle(&toggle_entries, &toggle_selected);
|
||||||
|
toggle = Wrap(L"Toggle", toggle);
|
||||||
|
|
||||||
container.Add(&checkbox_container);
|
// -- Checkbox ---------------------------------------------------------------
|
||||||
checkbox1.label = L"checkbox1";
|
bool checkbox_1_selected = false;
|
||||||
checkbox_container.Add(&checkbox1);
|
bool checkbox_2_selected = false;
|
||||||
checkbox2.label = L"checkbox2";
|
|
||||||
checkbox_container.Add(&checkbox2);
|
|
||||||
|
|
||||||
radiobox.entries = {
|
auto checkboxes = Container::Vertical({
|
||||||
|
Checkbox("checkbox1", &checkbox_1_selected),
|
||||||
|
Checkbox("checkbox2", &checkbox_2_selected),
|
||||||
|
});
|
||||||
|
checkboxes = Wrap(L"Checkbox", checkboxes);
|
||||||
|
|
||||||
|
// -- Radiobox ---------------------------------------------------------------
|
||||||
|
int radiobox_selected = 0;
|
||||||
|
std::vector<std::wstring> radiobox_entries = {
|
||||||
L"Radiobox 1",
|
L"Radiobox 1",
|
||||||
L"Radiobox 2",
|
L"Radiobox 2",
|
||||||
L"Radiobox 3",
|
L"Radiobox 3",
|
||||||
L"Radiobox 4",
|
L"Radiobox 4",
|
||||||
};
|
};
|
||||||
container.Add(&radiobox);
|
auto radiobox = Radiobox(&radiobox_entries, &radiobox_selected);
|
||||||
|
radiobox = Wrap(L"Radiobox", radiobox);
|
||||||
|
|
||||||
input.placeholder = L"Input placeholder";
|
// -- Input ------------------------------------------------------------------
|
||||||
container.Add(&input);
|
std::wstring input_label;
|
||||||
|
auto input = Input(&input_label, L"placeholder");
|
||||||
|
input = Wrap(L"Input", input);
|
||||||
|
|
||||||
container.Add(slider_1_.get());
|
// -- Button -----------------------------------------------------------------
|
||||||
container.Add(slider_2_.get());
|
std::wstring button_label = L"Quit";
|
||||||
container.Add(slider_3_.get());
|
std::function<void()> on_button_clicked_;
|
||||||
|
auto button = Button(&button_label, screen.ExitLoopClosure());
|
||||||
|
button = Wrap(L"Button", button);
|
||||||
|
|
||||||
button.label = L"Quit";
|
// -- Slider -----------------------------------------------------------------
|
||||||
button.on_click = [&] { on_quit(); };
|
int slider_value_1 = 12;
|
||||||
container.Add(&button);
|
int slider_value_2 = 56;
|
||||||
}
|
int slider_value_3 = 128;
|
||||||
|
auto sliders = Container::Vertical({
|
||||||
|
Slider(L"R:", &slider_value_1, 0, 256, 1),
|
||||||
|
Slider(L"G:", &slider_value_2, 0, 256, 1),
|
||||||
|
Slider(L"B:", &slider_value_3, 0, 256, 1),
|
||||||
|
});
|
||||||
|
sliders = Wrap(L"Slider", sliders);
|
||||||
|
|
||||||
Element Render(std::wstring name, Element element) {
|
// -- Layout -----------------------------------------------------------------
|
||||||
return hbox({
|
auto layout = Container::Vertical({
|
||||||
text(name) | size(WIDTH, EQUAL, 8),
|
menu,
|
||||||
separator(),
|
toggle,
|
||||||
element | xflex,
|
checkboxes,
|
||||||
}) |
|
radiobox,
|
||||||
xflex;
|
input,
|
||||||
}
|
sliders,
|
||||||
|
button,
|
||||||
|
});
|
||||||
|
|
||||||
Element Render(std::wstring name, Component& component) {
|
auto component = Renderer(layout, [&] {
|
||||||
return Render(name, component.Render());
|
return vbox({
|
||||||
}
|
menu->Render(),
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
return //
|
|
||||||
vbox({
|
|
||||||
Render(L"menu", menu),
|
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"toggle", toggle),
|
toggle->Render(),
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"checkbox", checkbox_container),
|
checkboxes->Render(),
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"radiobox", radiobox),
|
radiobox->Render(),
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"input", input) | size(WIDTH, LESS_THAN, 50),
|
input->Render(),
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"slider", //
|
sliders->Render(),
|
||||||
vbox({
|
|
||||||
slider_1_->Render(),
|
|
||||||
slider_2_->Render(),
|
|
||||||
slider_3_->Render(),
|
|
||||||
})),
|
|
||||||
separator(),
|
separator(),
|
||||||
Render(L"button", button),
|
button->Render(),
|
||||||
}) |
|
}) |
|
||||||
xflex | size(WIDTH, GREATER_THAN, 40) | border;
|
xflex | size(WIDTH, GREATER_THAN, 40) | border;
|
||||||
}
|
});
|
||||||
|
|
||||||
std::function<void()> on_quit = [] {};
|
screen.Loop(component);
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::FitComponent();
|
|
||||||
MyComponent component;
|
|
||||||
component.on_quit = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&component);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,52 +1,50 @@
|
|||||||
#include <chrono> // for operator""s, chron...
|
#include <array> // for array
|
||||||
|
#include <chrono> // for operator""s, chrono_literals
|
||||||
#include <cmath> // for sin
|
#include <cmath> // for sin
|
||||||
#include <functional> // for ref, reference_wra...
|
#include <functional> // for ref, reference_wrapper, function
|
||||||
#include <string> // for allocator, wstring
|
#include <memory> // for allocator, shared_ptr, __shared_ptr_access
|
||||||
|
#include <string> // for wstring, basic_string, operator+, to_wstring
|
||||||
#include <thread> // for sleep_for, thread
|
#include <thread> // for sleep_for, thread
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/checkbox.hpp" // for CheckBox
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/component.hpp" // for Checkbox, Renderer, Horizontal, Vertical, Input, Menu, Radiobox, Tab, Toggle
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::Custom
|
#include "ftxui/component/event.hpp" // for Event, Event::Custom
|
||||||
#include "ftxui/component/input.hpp" // for Input
|
#include "ftxui/component/input.hpp" // for InputBase
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
#include "ftxui/component/radiobox.hpp" // for RadioBox
|
#include "ftxui/dom/elements.hpp" // for text, operator|, color, bgcolor, Element, filler, size, vbox, flex, hbox, graph, separator, EQUAL, WIDTH, hcenter, bold, border, window, HEIGHT, Elements, hflow, flex_grow, frame, gauge, LESS_THAN, spinner, dim, GREATER_THAN
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/screen/color.hpp" // for Color, Color::BlueLight, Color::RedLight, Color::Black, Color::Blue, Color::Cyan, Color::CyanLight, Color::GrayDark, Color::GrayLight, Color::Green, Color::GreenLight, Color::Magenta, Color::MagentaLight, Color::Red, Color::White, Color::Yellow, Color::YellowLight, Color::Default
|
||||||
#include "ftxui/component/toggle.hpp" // for Toggle
|
|
||||||
#include "ftxui/dom/elements.hpp" // for text, operator|
|
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
#include "ftxui/screen/color.hpp" // for Color, Color::Blue...
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
int shift = 0;
|
int main(int argc, const char* argv[]) {
|
||||||
class Graph {
|
auto screen = ScreenInteractive::Fullscreen();
|
||||||
|
|
||||||
|
int shift = 0;
|
||||||
|
|
||||||
|
class Graph {
|
||||||
public:
|
public:
|
||||||
|
Graph(int* shift) : shift_(shift) {}
|
||||||
std::vector<int> operator()(int width, int height) {
|
std::vector<int> operator()(int width, int height) {
|
||||||
std::vector<int> output(width);
|
std::vector<int> output(width);
|
||||||
for (int i = 0; i < width; ++i) {
|
for (int i = 0; i < width; ++i) {
|
||||||
float v = 0;
|
float v = 0;
|
||||||
v += 0.1f * sin((i + shift) * 0.1f);
|
v += 0.1f * sin((i + *shift_) * 0.1f);
|
||||||
v += 0.2f * sin((i + shift + 10) * 0.15f);
|
v += 0.2f * sin((i + *shift_ + 10) * 0.15f);
|
||||||
v += 0.1f * sin((i + shift) * 0.03f);
|
v += 0.1f * sin((i + *shift_) * 0.03f);
|
||||||
v *= height;
|
v *= height;
|
||||||
v += 0.5f * height;
|
v += 0.5f * height;
|
||||||
output[i] = (int)v;
|
output[i] = (int)v;
|
||||||
}
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
};
|
int* shift_;
|
||||||
|
};
|
||||||
|
|
||||||
class HTopComponent : public Component {
|
Graph my_graph(&shift);
|
||||||
Graph my_graph;
|
auto htop = Renderer([&] {
|
||||||
|
|
||||||
public:
|
|
||||||
HTopComponent() {}
|
|
||||||
~HTopComponent() override {}
|
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
auto frequency = vbox({
|
auto frequency = vbox({
|
||||||
text(L"Frequency [Mhz]") | hcenter,
|
text(L"Frequency [Mhz]") | hcenter,
|
||||||
hbox({
|
hbox({
|
||||||
@ -99,27 +97,9 @@ class HTopComponent : public Component {
|
|||||||
ram | flex,
|
ram | flex,
|
||||||
}) |
|
}) |
|
||||||
flex | border;
|
flex | border;
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
class CompilerComponent : public Component {
|
const std::vector<std::wstring> compiler_entries = {
|
||||||
Container container = Container::Horizontal();
|
|
||||||
RadioBox compiler;
|
|
||||||
Container flag = Container::Vertical();
|
|
||||||
CheckBox flag_checkbox[4];
|
|
||||||
Container subcontainer = Container::Vertical();
|
|
||||||
Container input_container = Container::Horizontal();
|
|
||||||
Input input_add;
|
|
||||||
Menu input;
|
|
||||||
Input executable;
|
|
||||||
|
|
||||||
public:
|
|
||||||
~CompilerComponent() override {}
|
|
||||||
CompilerComponent() {
|
|
||||||
Add(&container);
|
|
||||||
|
|
||||||
// Compiler ----------------------------------------------------------------
|
|
||||||
compiler.entries = {
|
|
||||||
L"gcc",
|
L"gcc",
|
||||||
L"clang",
|
L"clang",
|
||||||
L"emcc",
|
L"emcc",
|
||||||
@ -160,52 +140,97 @@ class CompilerComponent : public Component {
|
|||||||
L"Rexx Interpreters",
|
L"Rexx Interpreters",
|
||||||
L"CLI compilers",
|
L"CLI compilers",
|
||||||
};
|
};
|
||||||
container.Add(&compiler);
|
|
||||||
|
|
||||||
// Flags ----------------------------------------------------------------
|
int compiler_selected = 0;
|
||||||
container.Add(&flag);
|
Component compiler = Radiobox(&compiler_entries, &compiler_selected);
|
||||||
flag_checkbox[0].label = L"-Wall";
|
|
||||||
flag_checkbox[1].label = L"-Werror";
|
|
||||||
flag_checkbox[2].label = L"-lpthread";
|
|
||||||
flag_checkbox[3].label = L"-O3";
|
|
||||||
for (auto& c : flag_checkbox)
|
|
||||||
flag.Add(&c);
|
|
||||||
|
|
||||||
container.Add(&subcontainer);
|
std::array<std::wstring, 4> options_label = {
|
||||||
// Executable
|
L"-Wall",
|
||||||
// ----------------------------------------------------------------
|
L"-Werror",
|
||||||
executable.placeholder = L"executable";
|
L"-lpthread",
|
||||||
subcontainer.Add(&executable);
|
L"-O3",
|
||||||
|
|
||||||
// Input ----------------------------------------------------------------
|
|
||||||
subcontainer.Add(&input_container);
|
|
||||||
|
|
||||||
input_add.placeholder = L"input files";
|
|
||||||
input_add.on_enter = [this] {
|
|
||||||
input.entries.push_back(input_add.content);
|
|
||||||
input_add.content = L"";
|
|
||||||
};
|
};
|
||||||
input_container.Add(&input_add);
|
std::array<bool, 4> options_state = {
|
||||||
input_container.Add(&input);
|
false,
|
||||||
}
|
false,
|
||||||
|
false,
|
||||||
|
false,
|
||||||
|
};
|
||||||
|
std::wstring input_add_content;
|
||||||
|
Component input_add = Input(&input_add_content, "input files");
|
||||||
|
|
||||||
Element Render() override {
|
std::vector<std::wstring> input_entries;
|
||||||
auto compiler_win = window(text(L"Compiler"), compiler.Render() | frame);
|
int input_selected = 0;
|
||||||
auto flags_win = window(text(L"Flags"), flag.Render());
|
Component input = Menu(&input_entries, &input_selected);
|
||||||
auto executable_win = window(text(L"Executable:"), executable.Render());
|
|
||||||
|
std::wstring executable_content_ = L"";
|
||||||
|
Component executable_ = Input(&executable_content_, "executable");
|
||||||
|
|
||||||
|
Component flags = Container::Vertical({
|
||||||
|
Checkbox(&options_label[0], &options_state[0]),
|
||||||
|
Checkbox(&options_label[1], &options_state[1]),
|
||||||
|
Checkbox(&options_label[2], &options_state[2]),
|
||||||
|
Checkbox(&options_label[3], &options_state[3]),
|
||||||
|
});
|
||||||
|
|
||||||
|
auto compiler_component = Container::Horizontal({
|
||||||
|
compiler,
|
||||||
|
flags,
|
||||||
|
Container::Vertical({
|
||||||
|
executable_,
|
||||||
|
Container::Horizontal({
|
||||||
|
input_add,
|
||||||
|
input,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
InputBase::From(input_add)->on_enter = [&] {
|
||||||
|
input_entries.push_back(input_add_content);
|
||||||
|
input_add_content = L"";
|
||||||
|
};
|
||||||
|
|
||||||
|
auto render_command = [&] {
|
||||||
|
Elements line;
|
||||||
|
// Compiler
|
||||||
|
line.push_back(text(compiler_entries[compiler_selected]) | bold);
|
||||||
|
// flags
|
||||||
|
for (int i = 0; i < 4; ++i) {
|
||||||
|
if (options_state[i]) {
|
||||||
|
line.push_back(text(L" "));
|
||||||
|
line.push_back(text(options_label[i]) | dim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Executable
|
||||||
|
if (!executable_content_.empty()) {
|
||||||
|
line.push_back(text(L" -O ") | bold);
|
||||||
|
line.push_back(text(executable_content_) | color(Color::BlueLight) |
|
||||||
|
bold);
|
||||||
|
}
|
||||||
|
// Input
|
||||||
|
for (auto& it : input_entries) {
|
||||||
|
line.push_back(text(L" " + it) | color(Color::RedLight));
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto compiler_renderer = Renderer(compiler_component, [&] {
|
||||||
|
auto compiler_win = window(text(L"Compiler"), compiler->Render() | frame);
|
||||||
|
auto flags_win = window(text(L"Flags"), flags->Render());
|
||||||
|
auto executable_win = window(text(L"Executable:"), executable_->Render());
|
||||||
auto input_win =
|
auto input_win =
|
||||||
window(text(L"Input"),
|
window(text(L"Input"),
|
||||||
hbox({
|
hbox({
|
||||||
vbox({
|
vbox({
|
||||||
hbox({
|
hbox({
|
||||||
text(L"Add: "),
|
text(L"Add: "),
|
||||||
input_add.Render(),
|
input_add->Render(),
|
||||||
}) | size(WIDTH, EQUAL, 20) |
|
}) | size(WIDTH, EQUAL, 20) |
|
||||||
size(HEIGHT, EQUAL, 1),
|
size(HEIGHT, EQUAL, 1),
|
||||||
filler(),
|
filler(),
|
||||||
}),
|
}),
|
||||||
separator(),
|
separator(),
|
||||||
input.Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
|
input->Render() | frame | size(HEIGHT, EQUAL, 3) | flex,
|
||||||
}));
|
}));
|
||||||
return vbox({
|
return vbox({
|
||||||
hbox({
|
hbox({
|
||||||
@ -217,49 +242,21 @@ class CompilerComponent : public Component {
|
|||||||
}),
|
}),
|
||||||
filler(),
|
filler(),
|
||||||
}),
|
}),
|
||||||
hflow(RenderCommandLine()) | flex_grow,
|
hflow(render_command()) | flex_grow,
|
||||||
}) |
|
}) |
|
||||||
flex_grow | border;
|
flex_grow | border;
|
||||||
}
|
});
|
||||||
|
|
||||||
Elements RenderCommandLine() {
|
auto spinner_tab_renderer = Renderer([&] {
|
||||||
Elements line;
|
|
||||||
// Compiler
|
|
||||||
line.push_back(text(compiler.entries[compiler.selected]) | bold);
|
|
||||||
// flags
|
|
||||||
for (auto& it : flag_checkbox) {
|
|
||||||
if (it.state) {
|
|
||||||
line.push_back(text(L" "));
|
|
||||||
line.push_back(text(it.label) | dim);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Executable
|
|
||||||
if (!executable.content.empty()) {
|
|
||||||
line.push_back(text(L" -O ") | bold);
|
|
||||||
line.push_back(text(executable.content) | color(Color::BlueLight) | bold);
|
|
||||||
}
|
|
||||||
// Input
|
|
||||||
for (auto& it : input.entries) {
|
|
||||||
line.push_back(text(L" " + it) | color(Color::RedLight));
|
|
||||||
}
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SpinnerComponent : public Component {
|
|
||||||
Element Render() override {
|
|
||||||
Elements entries;
|
Elements entries;
|
||||||
for (int i = 0; i < 22; ++i) {
|
for (int i = 0; i < 22; ++i) {
|
||||||
if (i != 0)
|
|
||||||
entries.push_back(spinner(i, shift / 2) | bold |
|
entries.push_back(spinner(i, shift / 2) | bold |
|
||||||
size(WIDTH, GREATER_THAN, 2) | border);
|
size(WIDTH, GREATER_THAN, 2) | border);
|
||||||
}
|
}
|
||||||
return hflow(std::move(entries)) | border;
|
return hflow(std::move(entries)) | border;
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
class ColorComponent : public Component {
|
auto color_tab_renderer = Renderer([] {
|
||||||
Element Render() override {
|
|
||||||
return hbox({
|
return hbox({
|
||||||
vbox({
|
vbox({
|
||||||
color(Color::Default, text(L"Default")),
|
color(Color::Default, text(L"Default")),
|
||||||
@ -301,82 +298,67 @@ class ColorComponent : public Component {
|
|||||||
}),
|
}),
|
||||||
}) |
|
}) |
|
||||||
hcenter | border;
|
hcenter | border;
|
||||||
}
|
});
|
||||||
};
|
|
||||||
|
|
||||||
class GaugeComponent : public Component {
|
auto render_gauge = [&shift](int delta) {
|
||||||
Element RenderGauge(int delta) {
|
|
||||||
float progress = (shift + delta) % 1000 / 1000.f;
|
float progress = (shift + delta) % 1000 / 1000.f;
|
||||||
return hbox({
|
return hbox({
|
||||||
text(std::to_wstring(int(progress * 100)) + L"% ") |
|
text(std::to_wstring(int(progress * 100)) + L"% ") |
|
||||||
size(WIDTH, EQUAL, 5),
|
size(WIDTH, EQUAL, 5),
|
||||||
gauge(progress),
|
gauge(progress),
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
Element Render() override {
|
|
||||||
|
auto gauge_component = Renderer([render_gauge] {
|
||||||
return vbox({
|
return vbox({
|
||||||
RenderGauge(0) | color(Color::Black),
|
render_gauge(0) | color(Color::Black),
|
||||||
RenderGauge(100) | color(Color::GrayDark),
|
render_gauge(100) | color(Color::GrayDark),
|
||||||
RenderGauge(50) | color(Color::GrayLight),
|
render_gauge(50) | color(Color::GrayLight),
|
||||||
RenderGauge(6894) | color(Color::White),
|
render_gauge(6894) | color(Color::White),
|
||||||
separator(),
|
separator(),
|
||||||
RenderGauge(6841) | color(Color::Blue),
|
render_gauge(6841) | color(Color::Blue),
|
||||||
RenderGauge(9813) | color(Color::BlueLight),
|
render_gauge(9813) | color(Color::BlueLight),
|
||||||
RenderGauge(98765) | color(Color::Cyan),
|
render_gauge(98765) | color(Color::Cyan),
|
||||||
RenderGauge(98) | color(Color::CyanLight),
|
render_gauge(98) | color(Color::CyanLight),
|
||||||
RenderGauge(9846) | color(Color::Green),
|
render_gauge(9846) | color(Color::Green),
|
||||||
RenderGauge(1122) | color(Color::GreenLight),
|
render_gauge(1122) | color(Color::GreenLight),
|
||||||
RenderGauge(84) | color(Color::Magenta),
|
render_gauge(84) | color(Color::Magenta),
|
||||||
RenderGauge(645) | color(Color::MagentaLight),
|
render_gauge(645) | color(Color::MagentaLight),
|
||||||
RenderGauge(568) | color(Color::Red),
|
render_gauge(568) | color(Color::Red),
|
||||||
RenderGauge(2222) | color(Color::RedLight),
|
render_gauge(2222) | color(Color::RedLight),
|
||||||
RenderGauge(220) | color(Color::Yellow),
|
render_gauge(220) | color(Color::Yellow),
|
||||||
RenderGauge(348) | color(Color::YellowLight),
|
render_gauge(348) | color(Color::YellowLight),
|
||||||
}) |
|
}) |
|
||||||
border;
|
border;
|
||||||
};
|
});
|
||||||
};
|
|
||||||
|
|
||||||
class Tab : public Component {
|
int tab_index = 0;
|
||||||
public:
|
std::vector<std::wstring> tab_entries = {
|
||||||
Container main_container = Container::Vertical();
|
|
||||||
|
|
||||||
Toggle tab_selection;
|
|
||||||
Container container = Container::Tab(&tab_selection.selected);
|
|
||||||
|
|
||||||
HTopComponent htop_component;
|
|
||||||
ColorComponent color_component;
|
|
||||||
SpinnerComponent spinner_component;
|
|
||||||
GaugeComponent gauge_component;
|
|
||||||
CompilerComponent compiler_component;
|
|
||||||
|
|
||||||
Tab() {
|
|
||||||
Add(&main_container);
|
|
||||||
main_container.Add(&tab_selection);
|
|
||||||
tab_selection.entries = {
|
|
||||||
L"htop", L"color", L"spinner", L"gauge", L"compiler",
|
L"htop", L"color", L"spinner", L"gauge", L"compiler",
|
||||||
};
|
};
|
||||||
main_container.Add(&container);
|
auto tab_selection = Toggle(&tab_entries, &tab_index);
|
||||||
container.Add(&htop_component);
|
auto tab_content = Container::Tab(&tab_index, {
|
||||||
container.Add(&color_component);
|
htop,
|
||||||
container.Add(&spinner_component);
|
color_tab_renderer,
|
||||||
container.Add(&gauge_component);
|
spinner_tab_renderer,
|
||||||
container.Add(&compiler_component);
|
gauge_component,
|
||||||
}
|
compiler_renderer,
|
||||||
|
});
|
||||||
|
|
||||||
Element Render() override {
|
auto main_container = Container::Vertical({
|
||||||
|
tab_selection,
|
||||||
|
tab_content,
|
||||||
|
});
|
||||||
|
|
||||||
|
auto main_renderer = Renderer(main_container, [&] {
|
||||||
return vbox({
|
return vbox({
|
||||||
text(L"FTXUI Demo") | bold | hcenter,
|
text(L"FTXUI Demo") | bold | hcenter,
|
||||||
tab_selection.Render() | hcenter,
|
tab_selection->Render() | hcenter,
|
||||||
container.Render() | flex,
|
tab_content->Render() | flex,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
std::thread update([&screen, &shift]() {
|
||||||
auto screen = ScreenInteractive::Fullscreen();
|
|
||||||
|
|
||||||
std::thread update([&screen]() {
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
std::this_thread::sleep_for(0.05s);
|
std::this_thread::sleep_for(0.05s);
|
||||||
@ -385,8 +367,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Tab tab;
|
screen.Loop(main_renderer);
|
||||||
screen.Loop(&tab);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,44 +1,38 @@
|
|||||||
#include "ftxui/component/input.hpp"
|
#include <memory> // for allocator, __shared_ptr_access
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include <string> // for operator+, char_traits, wstring
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
|
||||||
|
|
||||||
using namespace ftxui;
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component.hpp" // for Input, Renderer, Vertical
|
||||||
class MyComponent : public Component {
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
public:
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
MyComponent() {
|
#include "ftxui/dom/elements.hpp" // for text, hbox, Element, separator, operator|, vbox, border
|
||||||
Add(&container);
|
|
||||||
container.Add(&input_1);
|
|
||||||
container.Add(&input_2);
|
|
||||||
container.Add(&input_3);
|
|
||||||
|
|
||||||
input_1.placeholder = L"input1";
|
|
||||||
input_2.placeholder = L"input2";
|
|
||||||
input_3.placeholder = L"input3";
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Container container = Container::Vertical();
|
|
||||||
Input input_1;
|
|
||||||
Input input_2;
|
|
||||||
Input input_3;
|
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
return border(vbox({
|
|
||||||
hbox({text(L" input_1 : "), input_1.Render()}),
|
|
||||||
hbox({text(L" input_2 : "), input_2.Render()}),
|
|
||||||
hbox({text(L" input_3 : "), input_3.Render()}),
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
std::wstring first_name_;
|
||||||
|
std::wstring last_name_;
|
||||||
|
|
||||||
|
Component input_first_name_ = Input(&first_name_, "first name");
|
||||||
|
Component input_last_name_ = Input(&last_name_, "last name");
|
||||||
|
|
||||||
|
auto component = Container::Vertical({
|
||||||
|
input_first_name_,
|
||||||
|
input_last_name_,
|
||||||
|
});
|
||||||
|
|
||||||
|
auto renderer = Renderer(component, [&] {
|
||||||
|
return vbox({
|
||||||
|
text(L"Hello " + first_name_ + L" " + last_name_),
|
||||||
|
separator(),
|
||||||
|
hbox({text(L" First name : "), input_first_name_->Render()}),
|
||||||
|
hbox({text(L" Last name : "), input_last_name_->Render()}),
|
||||||
|
}) |
|
||||||
|
border;
|
||||||
|
});
|
||||||
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
screen.Loop(renderer);
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,24 +1,30 @@
|
|||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <iostream> // for basic_ostream::ope...
|
#include <iostream> // for basic_ostream::operator<<, operator<<, endl, basic_ostream, basic_ostream<>::__ostream_type, cout, ostream
|
||||||
#include <string> // for wstring, allocator
|
#include <string> // for wstring, allocator, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component.hpp" // for Menu
|
||||||
|
#include "ftxui/component/menu.hpp" // for MenuBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
|
||||||
Menu menu;
|
std::vector<std::wstring> entries = {
|
||||||
menu.entries = {L"entry 1", L"entry 2", L"entry 3"};
|
L"entry 1",
|
||||||
menu.selected = 0;
|
L"entry 2",
|
||||||
menu.on_enter = screen.ExitLoopClosure();
|
L"entry 3",
|
||||||
|
};
|
||||||
|
int selected = 0;
|
||||||
|
|
||||||
screen.Loop(&menu);
|
auto menu = Menu(&entries, &selected);
|
||||||
|
MenuBase::From(menu)->on_enter = screen.ExitLoopClosure();
|
||||||
|
|
||||||
std::cout << "Selected element = " << menu.selected << std::endl;
|
screen.Loop(menu);
|
||||||
|
|
||||||
|
std::cout << "Selected element = " << selected << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,62 +1,56 @@
|
|||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <string> // for wstring, allocator
|
#include <memory> // for allocator, __shared_ptr_access
|
||||||
|
#include <string> // for wstring, operator+, to_string, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/menu.hpp" // for MenuBase
|
||||||
#include "ftxui/dom/elements.hpp" // for text, separator, bold
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "ftxui/dom/elements.hpp" // for text, separator, bold, hcenter, vbox, hbox, gauge, Element, operator|, border
|
||||||
#include "ftxui/screen/string.hpp" // for to_wstring
|
#include "ftxui/screen/string.hpp" // for to_wstring
|
||||||
|
|
||||||
using namespace ftxui;
|
int main(int argc, const char* argv[]) {
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
std::vector<std::wstring> left_menu_entries = {
|
||||||
public:
|
|
||||||
MyComponent() {
|
|
||||||
Add(&container);
|
|
||||||
container.Add(&left_menu);
|
|
||||||
container.Add(&right_menu);
|
|
||||||
|
|
||||||
left_menu.entries = {
|
|
||||||
L"0%", L"10%", L"20%", L"30%", L"40%",
|
L"0%", L"10%", L"20%", L"30%", L"40%",
|
||||||
L"50%", L"60%", L"70%", L"80%", L"90%",
|
L"50%", L"60%", L"70%", L"80%", L"90%",
|
||||||
};
|
};
|
||||||
right_menu.entries = {
|
std::vector<std::wstring> right_menu_entries = {
|
||||||
L"0%", L"1%", L"2%", L"3%", L"4%", L"5%",
|
L"0%", L"1%", L"2%", L"3%", L"4%", L"5%",
|
||||||
L"6%", L"7%", L"8%", L"9%", L"10%",
|
L"6%", L"7%", L"8%", L"9%", L"10%",
|
||||||
};
|
};
|
||||||
|
int left_menu_selected = 0;
|
||||||
|
int right_menu_selected = 0;
|
||||||
|
Component left_menu_ = Menu(&left_menu_entries, &left_menu_selected);
|
||||||
|
Component right_menu_ = Menu(&right_menu_entries, &right_menu_selected);
|
||||||
|
|
||||||
left_menu.on_enter = [this]() { on_enter(); };
|
Component container = Container::Horizontal({
|
||||||
right_menu.on_enter = [this]() { on_enter(); };
|
left_menu_,
|
||||||
}
|
right_menu_,
|
||||||
|
});
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
auto renderer = Renderer(container, [&] {
|
||||||
|
int sum = left_menu_selected * 10 + right_menu_selected;
|
||||||
private:
|
return vbox({
|
||||||
Container container = Container::Horizontal();
|
|
||||||
Menu left_menu;
|
|
||||||
Menu right_menu;
|
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
int sum = left_menu.selected * 10 + right_menu.selected;
|
|
||||||
return border(vbox({
|
|
||||||
// -------- Top panel --------------
|
// -------- Top panel --------------
|
||||||
hbox({
|
hbox({
|
||||||
// -------- Left Menu --------------
|
// -------- Left Menu --------------
|
||||||
vbox({
|
vbox({
|
||||||
hcenter(bold(text(L"Percentage by 10%"))),
|
hcenter(bold(text(L"Percentage by 10%"))),
|
||||||
separator(),
|
separator(),
|
||||||
left_menu.Render(),
|
left_menu_->Render(),
|
||||||
}) | flex,
|
}),
|
||||||
|
separator(),
|
||||||
// -------- Right Menu --------------
|
// -------- Right Menu --------------
|
||||||
vbox({
|
vbox({
|
||||||
hcenter(bold(text(L"Percentage by 1%"))),
|
hcenter(bold(text(L"Percentage by 1%"))),
|
||||||
separator(),
|
separator(),
|
||||||
right_menu.Render(),
|
right_menu_->Render(),
|
||||||
}) | flex,
|
}),
|
||||||
filler(),
|
separator(),
|
||||||
}),
|
}),
|
||||||
separator(),
|
separator(),
|
||||||
// -------- Bottom panel --------------
|
// -------- Bottom panel --------------
|
||||||
@ -69,16 +63,15 @@ class MyComponent : public Component {
|
|||||||
text(L" text : "),
|
text(L" text : "),
|
||||||
text(to_wstring(std::to_string(sum) + " %")),
|
text(to_wstring(std::to_string(sum) + " %")),
|
||||||
}),
|
}),
|
||||||
}) | flex,
|
}),
|
||||||
}));
|
}) |
|
||||||
}
|
border;
|
||||||
};
|
});
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
MenuBase::From(left_menu_)->on_enter = screen.ExitLoopClosure();
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
MenuBase::From(right_menu_)->on_enter = screen.ExitLoopClosure();
|
||||||
screen.Loop(&component);
|
screen.Loop(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,92 +1,83 @@
|
|||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <initializer_list> // for initializer_list
|
#include <initializer_list> // for initializer_list
|
||||||
#include <string> // for wstring, allocator
|
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
||||||
|
#include <string> // for wstring, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component.hpp" // for Menu, Horizontal, Renderer
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/menu.hpp" // for MenuBase
|
||||||
#include "ftxui/dom/elements.hpp" // for operator|, Element
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive, Component
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "ftxui/dom/elements.hpp" // for operator|, Element, separator, bgcolor, color, flex, Decorator, bold, hbox, border, dim
|
||||||
#include "ftxui/screen/color.hpp" // for Color, Color::Blue
|
#include "ftxui/screen/color.hpp" // for Color, Color::Blue, Color::BlueLight, Color::Red, Color::Yellow
|
||||||
|
|
||||||
using namespace ftxui;
|
|
||||||
|
|
||||||
class MyComponent : public Component {
|
|
||||||
public:
|
|
||||||
MyComponent() {
|
|
||||||
Add(&container);
|
|
||||||
|
|
||||||
for (Menu* menu : {
|
|
||||||
&menu_1,
|
|
||||||
&menu_2,
|
|
||||||
&menu_3,
|
|
||||||
&menu_4,
|
|
||||||
&menu_5,
|
|
||||||
&menu_6,
|
|
||||||
}) {
|
|
||||||
container.Add(menu);
|
|
||||||
menu->entries = {
|
|
||||||
L"Monkey", L"Dog", L"Cat", L"Bird", L"Elephant",
|
|
||||||
};
|
|
||||||
menu->on_enter = [this]() { on_enter(); };
|
|
||||||
}
|
|
||||||
|
|
||||||
menu_2.focused_style = bold | color(Color::Blue);
|
|
||||||
menu_2.selected_style = color(Color::Blue);
|
|
||||||
menu_2.selected_focused_style = bold | color(Color::Blue);
|
|
||||||
|
|
||||||
menu_3.selected_style = color(Color::Blue);
|
|
||||||
menu_3.focused_style = bgcolor(Color::Blue);
|
|
||||||
menu_3.selected_focused_style = bgcolor(Color::Blue);
|
|
||||||
|
|
||||||
menu_4.selected_style = bgcolor(Color::Blue);
|
|
||||||
menu_4.focused_style = bgcolor(Color::BlueLight);
|
|
||||||
menu_4.selected_focused_style = bgcolor(Color::BlueLight);
|
|
||||||
|
|
||||||
menu_5.normal_style = bgcolor(Color::Blue);
|
|
||||||
menu_5.selected_style = bgcolor(Color::Yellow);
|
|
||||||
menu_5.focused_style = bgcolor(Color::Red);
|
|
||||||
menu_5.selected_focused_style = bgcolor(Color::Red);
|
|
||||||
|
|
||||||
menu_6.normal_style = dim | color(Color::Blue);
|
|
||||||
menu_6.selected_style = color(Color::Blue);
|
|
||||||
menu_6.focused_style = bold | color(Color::Blue);
|
|
||||||
menu_6.selected_focused_style = bold | color(Color::Blue);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
|
||||||
|
|
||||||
private:
|
|
||||||
Container container = Container::Horizontal();
|
|
||||||
Menu menu_1;
|
|
||||||
Menu menu_2;
|
|
||||||
Menu menu_3;
|
|
||||||
Menu menu_4;
|
|
||||||
Menu menu_5;
|
|
||||||
Menu menu_6;
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
Element Render() override {
|
|
||||||
return
|
|
||||||
hbox({
|
|
||||||
menu_1.Render() | flex, separator(),
|
|
||||||
menu_2.Render() | flex, separator(),
|
|
||||||
menu_3.Render() | flex, separator(),
|
|
||||||
menu_4.Render() | flex, separator(),
|
|
||||||
menu_5.Render() | flex, separator(),
|
|
||||||
menu_6.Render() | flex,
|
|
||||||
}) | border;
|
|
||||||
}
|
|
||||||
// clang-format on
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
using namespace ftxui;
|
||||||
|
std::vector<std::wstring> entries = {
|
||||||
|
L"Monkey", L"Dog", L"Cat", L"Bird", L"Elephant",
|
||||||
|
};
|
||||||
|
int menu_1_selected_ = 0;
|
||||||
|
int menu_2_selected_ = 0;
|
||||||
|
int menu_3_selected_ = 0;
|
||||||
|
int menu_4_selected_ = 0;
|
||||||
|
int menu_5_selected_ = 0;
|
||||||
|
int menu_6_selected_ = 0;
|
||||||
|
auto menu_1_ = Menu(&entries, &menu_1_selected_);
|
||||||
|
auto menu_2_ = Menu(&entries, &menu_2_selected_);
|
||||||
|
auto menu_3_ = Menu(&entries, &menu_3_selected_);
|
||||||
|
auto menu_4_ = Menu(&entries, &menu_4_selected_);
|
||||||
|
auto menu_5_ = Menu(&entries, &menu_5_selected_);
|
||||||
|
auto menu_6_ = Menu(&entries, &menu_6_selected_);
|
||||||
|
auto container = Container::Horizontal({
|
||||||
|
menu_1_,
|
||||||
|
menu_2_,
|
||||||
|
menu_3_,
|
||||||
|
menu_4_,
|
||||||
|
menu_5_,
|
||||||
|
menu_6_,
|
||||||
|
});
|
||||||
|
|
||||||
|
// clang-format off
|
||||||
|
auto renderer = Renderer(container, [&] {
|
||||||
|
return
|
||||||
|
hbox({
|
||||||
|
menu_1_->Render() | flex, separator(),
|
||||||
|
menu_2_->Render() | flex, separator(),
|
||||||
|
menu_3_->Render() | flex, separator(),
|
||||||
|
menu_4_->Render() | flex, separator(),
|
||||||
|
menu_5_->Render() | flex, separator(),
|
||||||
|
menu_6_->Render() | flex,
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
// clang-format on
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
for (Component menu : {menu_1_, menu_2_, menu_3_, menu_4_, menu_5_, menu_6_})
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
MenuBase::From(menu)->on_enter = screen.ExitLoopClosure();
|
||||||
screen.Loop(&component);
|
|
||||||
|
MenuBase::From(menu_2_)->focused_style = bold | color(Color::Blue);
|
||||||
|
MenuBase::From(menu_2_)->selected_style = color(Color::Blue);
|
||||||
|
MenuBase::From(menu_2_)->selected_focused_style = bold | color(Color::Blue);
|
||||||
|
|
||||||
|
MenuBase::From(menu_3_)->selected_style = color(Color::Blue);
|
||||||
|
MenuBase::From(menu_3_)->focused_style = bgcolor(Color::Blue);
|
||||||
|
MenuBase::From(menu_3_)->selected_focused_style = bgcolor(Color::Blue);
|
||||||
|
|
||||||
|
MenuBase::From(menu_4_)->selected_style = bgcolor(Color::Blue);
|
||||||
|
MenuBase::From(menu_4_)->focused_style = bgcolor(Color::BlueLight);
|
||||||
|
MenuBase::From(menu_4_)->selected_focused_style = bgcolor(Color::BlueLight);
|
||||||
|
|
||||||
|
MenuBase::From(menu_5_)->normal_style = bgcolor(Color::Blue);
|
||||||
|
MenuBase::From(menu_5_)->selected_style = bgcolor(Color::Yellow);
|
||||||
|
MenuBase::From(menu_5_)->focused_style = bgcolor(Color::Red);
|
||||||
|
MenuBase::From(menu_5_)->selected_focused_style = bgcolor(Color::Red);
|
||||||
|
|
||||||
|
MenuBase::From(menu_6_)->normal_style = dim | color(Color::Blue);
|
||||||
|
MenuBase::From(menu_6_)->selected_style = color(Color::Blue);
|
||||||
|
MenuBase::From(menu_6_)->focused_style = bold | color(Color::Blue);
|
||||||
|
MenuBase::From(menu_6_)->selected_focused_style = bold | color(Color::Blue);
|
||||||
|
|
||||||
|
screen.Loop(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,132 +1,89 @@
|
|||||||
#include <functional> // for function
|
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
|
||||||
#include <memory> // for allocator_traits<>...
|
#include <string> // for wstring, operator+, basic_string, char_traits
|
||||||
#include <string> // for operator+, wstring
|
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/button.hpp" // for Button
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/component.hpp" // for Button, Renderer, Horizontal, Tab
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/dom/elements.hpp" // for Element, operator|
|
#include "ftxui/dom/elements.hpp" // for Element, operator|, filler, text, hbox, separator, center, vbox, bold, border, clear_under, dbox, size, GREATER_THAN, HEIGHT
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
|
|
||||||
using namespace ftxui;
|
int main(int argc, const char* argv[]) {
|
||||||
|
using namespace ftxui;
|
||||||
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
|
||||||
// The main screen, at depth 0. It display the main content.
|
// There are two layers. One at depth = 0 and the modal window at depth = 1;
|
||||||
class Content : public Component {
|
int depth = 0;
|
||||||
public:
|
|
||||||
std::function<void()> on_rate_ftxui = [] {};
|
|
||||||
std::function<void()> on_quit = [] {};
|
|
||||||
std::wstring rating_ = L"3/5 stars";
|
|
||||||
Content() {
|
|
||||||
Add(&container_);
|
|
||||||
container_.Add(&button_rate_ftxui);
|
|
||||||
container_.Add(&button_quit_);
|
|
||||||
button_rate_ftxui.on_click = [&] { on_rate_ftxui(); };
|
|
||||||
button_quit_.on_click = [&] { on_quit(); };
|
|
||||||
}
|
|
||||||
|
|
||||||
Element Render() final {
|
// The current rating of FTXUI.
|
||||||
auto button_elements = hbox({
|
std::wstring rating = L"3/5 stars";
|
||||||
button_rate_ftxui.Render(),
|
|
||||||
filler(),
|
// At depth=0, two buttons. One for rating FTXUI and one for quitting.
|
||||||
button_quit_.Render(),
|
auto button_rate_ftxui = Button("Rate FTXUI", [&] { depth = 1; });
|
||||||
|
auto button_quit = Button("Quit", screen.ExitLoopClosure());
|
||||||
|
|
||||||
|
auto depth_0_container = Container::Horizontal({
|
||||||
|
button_rate_ftxui,
|
||||||
|
button_quit,
|
||||||
});
|
});
|
||||||
|
auto depth_0_renderer = Renderer(depth_0_container, [&] {
|
||||||
auto document = //
|
return vbox({
|
||||||
vbox({
|
|
||||||
text(L"Modal dialog example"),
|
text(L"Modal dialog example"),
|
||||||
separator(),
|
separator(),
|
||||||
text(L"☆☆☆ FTXUI:" + rating_ + L" ☆☆☆") | bold,
|
text(L"☆☆☆ FTXUI:" + rating + L" ☆☆☆") | bold,
|
||||||
filler(),
|
filler(),
|
||||||
button_elements,
|
hbox({
|
||||||
|
button_rate_ftxui->Render(),
|
||||||
|
filler(),
|
||||||
|
button_quit->Render(),
|
||||||
|
}),
|
||||||
}) |
|
}) |
|
||||||
border;
|
border | size(HEIGHT, GREATER_THAN, 18) | center;
|
||||||
|
});
|
||||||
|
|
||||||
return document | size(HEIGHT, GREATER_THAN, 18) | center;
|
// At depth=1, The "modal" window.
|
||||||
}
|
std::vector<std::wstring> rating_labels = {
|
||||||
|
L"1/5 stars", L"2/5 stars", L"3/5 stars", L"4/5 stars", L"5/5 stars",
|
||||||
|
};
|
||||||
|
auto on_rating = [&](std::wstring new_rating) {
|
||||||
|
rating = new_rating;
|
||||||
|
depth = 0;
|
||||||
|
};
|
||||||
|
auto depth_1_container = Container::Horizontal({
|
||||||
|
Button(&rating_labels[0], [&] { on_rating(rating_labels[0]); }),
|
||||||
|
Button(&rating_labels[1], [&] { on_rating(rating_labels[1]); }),
|
||||||
|
Button(&rating_labels[2], [&] { on_rating(rating_labels[2]); }),
|
||||||
|
Button(&rating_labels[3], [&] { on_rating(rating_labels[3]); }),
|
||||||
|
Button(&rating_labels[4], [&] { on_rating(rating_labels[4]); }),
|
||||||
|
});
|
||||||
|
|
||||||
private:
|
auto depth_1_renderer = Renderer(depth_1_container, [&] {
|
||||||
Container container_ = Container::Horizontal();
|
|
||||||
Button button_rate_ftxui = Button(L"Rate FTXUI");
|
|
||||||
Button button_quit_ = Button(L"Quit");
|
|
||||||
};
|
|
||||||
|
|
||||||
// The "modal" screen, at depth 1. It display the modal dialog.
|
|
||||||
class Modal : public Component {
|
|
||||||
public:
|
|
||||||
std::function<void(std::wstring)> on_click;
|
|
||||||
|
|
||||||
Modal() {
|
|
||||||
Add(&container_);
|
|
||||||
buttons_.resize(5);
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
|
||||||
std::wstring stars = std::to_wstring(i + 1) + L"/5 stars";
|
|
||||||
buttons_[i] = Button(stars);
|
|
||||||
buttons_[i].on_click = [&, stars] { on_click(stars); };
|
|
||||||
container_.Add(&buttons_[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Element Render() final {
|
|
||||||
return vbox({
|
return vbox({
|
||||||
text(L"Do you like FTXUI?"),
|
text(L"Do you like FTXUI?"),
|
||||||
separator(),
|
separator(),
|
||||||
hbox({
|
hbox(depth_1_container->Render()),
|
||||||
buttons_[0].Render(),
|
|
||||||
buttons_[1].Render(),
|
|
||||||
buttons_[2].Render(),
|
|
||||||
buttons_[3].Render(),
|
|
||||||
buttons_[4].Render(),
|
|
||||||
}),
|
|
||||||
}) |
|
}) |
|
||||||
border;
|
border;
|
||||||
}
|
});
|
||||||
|
|
||||||
private:
|
auto main_container = Container::Tab(&depth, {
|
||||||
Container container_ = Container::Horizontal();
|
depth_0_renderer,
|
||||||
std::vector<Button> buttons_;
|
depth_1_renderer,
|
||||||
};
|
});
|
||||||
|
|
||||||
class MyComponent : public Component {
|
auto main_renderer = Renderer(main_container, [&] {
|
||||||
public:
|
Element document = depth_0_renderer->Render();
|
||||||
std::function<void()> on_quit = [] {};
|
|
||||||
|
|
||||||
MyComponent() {
|
if (depth == 1) {
|
||||||
Add(&container_);
|
|
||||||
container_.Add(&content_);
|
|
||||||
container_.Add(&modal_);
|
|
||||||
|
|
||||||
content_.on_quit = [&] { on_quit(); };
|
|
||||||
content_.on_rate_ftxui = [&] { modal_.TakeFocus(); };
|
|
||||||
modal_.on_click = [&](std::wstring rating) {
|
|
||||||
content_.rating_ = rating;
|
|
||||||
content_.TakeFocus();
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Element Render() final {
|
|
||||||
Element document = content_.Render();
|
|
||||||
if (modal_.Focused()) {
|
|
||||||
document = dbox({
|
document = dbox({
|
||||||
document,
|
document,
|
||||||
modal_.Render() | clear_under | center,
|
depth_1_renderer->Render() | clear_under | center,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return document;
|
return document;
|
||||||
}
|
});
|
||||||
|
|
||||||
private:
|
screen.Loop(main_renderer);
|
||||||
Container container_ = Container::Tab(nullptr);
|
|
||||||
Content content_;
|
|
||||||
Modal modal_;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
|
||||||
MyComponent my_component;
|
|
||||||
my_component.on_quit = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&my_component);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,18 +1,23 @@
|
|||||||
#include "ftxui/component/radiobox.hpp"
|
#include <string> // for wstring, allocator, basic_string
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component.hpp" // for Radiobox
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
std::vector<std::wstring> radiobox_list = {
|
||||||
RadioBox radiobox;
|
|
||||||
radiobox.entries = {
|
|
||||||
L"Use gcc",
|
L"Use gcc",
|
||||||
L"Use clang",
|
L"Use clang",
|
||||||
L"Use emscripten",
|
L"Use emscripten",
|
||||||
L"Use tcc",
|
L"Use tcc",
|
||||||
};
|
};
|
||||||
screen.Loop(&radiobox);
|
int selected = 0;
|
||||||
|
|
||||||
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
screen.Loop(Radiobox(&radiobox_list, &selected));
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,35 +1,29 @@
|
|||||||
|
#include <memory> // for __shared_ptr_access, shared_ptr
|
||||||
#include <string> // for wstring, operator+
|
#include <string> // for wstring, operator+
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/radiobox.hpp" // for RadioBox
|
#include "ftxui/component/component.hpp" // for Radiobox, Renderer
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/dom/elements.hpp" // for Element, operator|
|
#include "ftxui/dom/elements.hpp" // for Element, operator|, size, border, frame, HEIGHT, LESS_THAN
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
#include "ftxui/screen/string.hpp" // for to_wstring
|
#include "ftxui/screen/string.hpp" // for to_wstring
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
|
||||||
RadioBox radiobox;
|
|
||||||
|
|
||||||
public:
|
|
||||||
MyComponent() {
|
|
||||||
for (int i = 0; i < 30; ++i) {
|
|
||||||
radiobox.entries.push_back(L"RadioBox " + to_wstring(i));
|
|
||||||
}
|
|
||||||
Add(&radiobox);
|
|
||||||
}
|
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
return radiobox.Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
|
std::vector<std::wstring> entries;
|
||||||
|
int selected = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 30; ++i)
|
||||||
|
entries.push_back(L"RadioBox " + to_wstring(i));
|
||||||
|
auto radiobox = Radiobox(&entries, &selected);
|
||||||
|
auto renderer = Renderer(radiobox, [&] {
|
||||||
|
return radiobox->Render() | frame | size(HEIGHT, LESS_THAN, 10) | border;
|
||||||
|
});
|
||||||
|
|
||||||
auto screen = ScreenInteractive::FitComponent();
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
MyComponent component;
|
screen.Loop(renderer);
|
||||||
screen.Loop(&component);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1,82 +1,14 @@
|
|||||||
#include <functional> // for function
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include <memory> // for allocator, unique_ptr
|
#include "ftxui/component/component.hpp" // for Slider
|
||||||
#include <string> // for operator+, to_wstring
|
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component, Compone...
|
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::Escape
|
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/component/slider.hpp" // for Slider
|
|
||||||
#include "ftxui/dom/elements.hpp" // for separator, operator|
|
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
#include "ftxui/screen/color.hpp" // for Color
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
Element ColorTile(int red, int green, int blue) {
|
|
||||||
return text(L"") | size(WIDTH, GREATER_THAN, 14) |
|
|
||||||
size(HEIGHT, GREATER_THAN, 7) | bgcolor(Color::RGB(red, green, blue));
|
|
||||||
}
|
|
||||||
|
|
||||||
Element ColorString(int red, int green, int blue) {
|
|
||||||
return text(L"RGB = (" + //
|
|
||||||
std::to_wstring(red) + L"," + //
|
|
||||||
std::to_wstring(green) + L"," + //
|
|
||||||
std::to_wstring(blue) + L")" //
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyComponent : public Component {
|
|
||||||
public:
|
|
||||||
MyComponent(int* red, int* green, int* blue, std::function<void(void)> quit)
|
|
||||||
: red_(red), green_(green), blue_(blue), quit_(quit) {
|
|
||||||
Add(&container_);
|
|
||||||
container_.Add(slider_red_.get());
|
|
||||||
container_.Add(slider_green_.get());
|
|
||||||
container_.Add(slider_blue_.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
Element Render() {
|
|
||||||
return hbox({
|
|
||||||
ColorTile(*red_, *green_, *blue_),
|
|
||||||
separator(),
|
|
||||||
vbox({
|
|
||||||
slider_red_->Render(),
|
|
||||||
separator(),
|
|
||||||
slider_green_->Render(),
|
|
||||||
separator(),
|
|
||||||
slider_blue_->Render(),
|
|
||||||
separator(),
|
|
||||||
ColorString(*red_, *green_, *blue_),
|
|
||||||
}) | xflex,
|
|
||||||
}) |
|
|
||||||
border | size(WIDTH, LESS_THAN, 80);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool OnEvent(Event event) {
|
|
||||||
if (event == Event::Return || event == Event::Escape)
|
|
||||||
quit_();
|
|
||||||
return Component::OnEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
int* red_;
|
|
||||||
int* green_;
|
|
||||||
int* blue_;
|
|
||||||
Container container_ = Container::Vertical();
|
|
||||||
ComponentPtr slider_red_ = Slider(L"Red :", red_, 0, 255, 1);
|
|
||||||
ComponentPtr slider_green_ = Slider(L"Green:", green_, 0, 255, 1);
|
|
||||||
ComponentPtr slider_blue_ = Slider(L"Blue :", blue_, 0, 255, 1);
|
|
||||||
std::function<void(void)> quit_;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
int red = 128;
|
int value = 50;
|
||||||
int green = 25;
|
auto slider = Slider(L"Value:", &value, 0, 100, 1);
|
||||||
int blue = 100;
|
screen.Loop(slider);
|
||||||
auto component = MyComponent(&red, &green, &blue, screen.ExitLoopClosure());
|
|
||||||
screen.Loop(&component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
62
examples/component/slider_rgb.cpp
Normal file
62
examples/component/slider_rgb.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
|
||||||
|
#include <string> // for operator+, to_wstring, char_traits
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component.hpp" // for Slider, Renderer, Vertical
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
|
#include "ftxui/dom/elements.hpp" // for separator, Element, operator|, size, text, vbox, xflex, bgcolor, hbox, GREATER_THAN, WIDTH, border, HEIGHT, LESS_THAN
|
||||||
|
#include "ftxui/screen/color.hpp" // for Color
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
Element ColorTile(int red, int green, int blue) {
|
||||||
|
return text(L"") | size(WIDTH, GREATER_THAN, 14) |
|
||||||
|
size(HEIGHT, GREATER_THAN, 7) | bgcolor(Color::RGB(red, green, blue));
|
||||||
|
}
|
||||||
|
|
||||||
|
Element ColorString(int red, int green, int blue) {
|
||||||
|
return text(L"RGB = (" + //
|
||||||
|
std::to_wstring(red) + L"," + //
|
||||||
|
std::to_wstring(green) + L"," + //
|
||||||
|
std::to_wstring(blue) + L")" //
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
int red = 128;
|
||||||
|
int green = 25;
|
||||||
|
int blue = 100;
|
||||||
|
auto slider_red = Slider(L"Red :", &red, 0, 255, 1);
|
||||||
|
auto slider_green = Slider(L"Green:", &green, 0, 255, 1);
|
||||||
|
auto slider_blue = Slider(L"Blue :", &blue, 0, 255, 1);
|
||||||
|
|
||||||
|
auto container = Container::Vertical({
|
||||||
|
slider_red,
|
||||||
|
slider_green,
|
||||||
|
slider_blue,
|
||||||
|
});
|
||||||
|
|
||||||
|
auto renderer = Renderer(container, [&] {
|
||||||
|
return hbox({
|
||||||
|
ColorTile(red, green, blue),
|
||||||
|
separator(),
|
||||||
|
vbox({
|
||||||
|
slider_red->Render(),
|
||||||
|
separator(),
|
||||||
|
slider_green->Render(),
|
||||||
|
separator(),
|
||||||
|
slider_blue->Render(),
|
||||||
|
separator(),
|
||||||
|
ColorString(red, green, blue),
|
||||||
|
}) | xflex,
|
||||||
|
}) |
|
||||||
|
border | size(WIDTH, LESS_THAN, 80);
|
||||||
|
});
|
||||||
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
screen.Loop(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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.
|
@ -1,71 +1,68 @@
|
|||||||
#include <functional> // for function
|
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
|
||||||
#include <string> // for wstring, allocator
|
#include <string> // for wstring, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component.hpp" // for Radiobox, Renderer, Tab, Toggle, Vertical
|
||||||
#include "ftxui/component/radiobox.hpp" // for RadioBox
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/component/toggle.hpp" // for Toggle
|
#include "ftxui/dom/elements.hpp" // for Element, separator, operator|, vbox, border
|
||||||
#include "ftxui/dom/elements.hpp" // for Element, operator|
|
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
int main(int argc, const char* argv[]) {
|
||||||
public:
|
std::vector<std::wstring> tab_values{
|
||||||
MyComponent() {
|
|
||||||
Add(&container_);
|
|
||||||
container_.Add(&toggle_);
|
|
||||||
|
|
||||||
toggle_.entries = {
|
|
||||||
L"tab_1",
|
L"tab_1",
|
||||||
L"tab_2",
|
L"tab_2",
|
||||||
L"tab_3",
|
L"tab_3",
|
||||||
};
|
};
|
||||||
|
int tab_selected = 0;
|
||||||
|
auto tab_toggle = Toggle(&tab_values, &tab_selected);
|
||||||
|
|
||||||
container_.Add(&tab_container_);
|
std::vector<std::wstring> tab_1_entries{
|
||||||
|
L"Forest",
|
||||||
|
L"Water",
|
||||||
|
L"I don't know",
|
||||||
|
};
|
||||||
|
int tab_1_selected = 0;
|
||||||
|
|
||||||
radiobox_1_.entries = {L"Forest", L"Water", L"I don't know"};
|
std::vector<std::wstring> tab_2_entries{
|
||||||
tab_container_.Add(&radiobox_1_);
|
|
||||||
|
|
||||||
radiobox_2_.entries = {
|
|
||||||
L"Hello",
|
L"Hello",
|
||||||
L"Hi",
|
L"Hi",
|
||||||
L"Hay",
|
L"Hay",
|
||||||
};
|
};
|
||||||
tab_container_.Add(&radiobox_2_);
|
int tab_2_selected = 0;
|
||||||
|
|
||||||
radiobox_3_.entries = {
|
std::vector<std::wstring> tab_3_entries{
|
||||||
L"Table",
|
L"Table",
|
||||||
L"Nothing",
|
L"Nothing",
|
||||||
L"Is",
|
L"Is",
|
||||||
L"Empty",
|
L"Empty",
|
||||||
};
|
};
|
||||||
tab_container_.Add(&radiobox_3_);
|
int tab_3_selected = 0;
|
||||||
}
|
auto tab_container = Container::Tab(
|
||||||
|
&tab_selected, {
|
||||||
|
Radiobox(&tab_1_entries, &tab_1_selected),
|
||||||
|
Radiobox(&tab_2_entries, &tab_2_selected),
|
||||||
|
Radiobox(&tab_3_entries, &tab_3_selected),
|
||||||
|
});
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
auto container = Container::Vertical({
|
||||||
|
tab_toggle,
|
||||||
|
tab_container,
|
||||||
|
});
|
||||||
|
|
||||||
Element Render() {
|
auto renderer = Renderer(container, [&] {
|
||||||
return vbox(toggle_.Render(), separator(), tab_container_.Render()) |
|
return vbox({
|
||||||
|
tab_toggle->Render(),
|
||||||
|
separator(),
|
||||||
|
tab_container->Render(),
|
||||||
|
}) |
|
||||||
border;
|
border;
|
||||||
}
|
});
|
||||||
|
|
||||||
private:
|
|
||||||
Toggle toggle_;
|
|
||||||
Container container_ = Container::Vertical();
|
|
||||||
Container tab_container_ = Container::Tab(&(toggle_.selected));
|
|
||||||
RadioBox radiobox_1_;
|
|
||||||
RadioBox radiobox_2_;
|
|
||||||
RadioBox radiobox_3_;
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
screen.Loop(renderer);
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,64 +1,68 @@
|
|||||||
#include <functional> // for function
|
#include <memory> // for allocator, __shared_ptr_access, shared_ptr
|
||||||
#include <string> // for wstring, allocator
|
#include <string> // for wstring, basic_string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include "ftxui/component/component.hpp" // for Radiobox, Horizontal, Menu, Renderer, Tab
|
||||||
#include "ftxui/component/menu.hpp" // for Menu
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "ftxui/dom/elements.hpp" // for Element, separator, hbox, operator|, border
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
int main(int argc, const char* argv[]) {
|
||||||
public:
|
std::vector<std::wstring> tab_values{
|
||||||
MyComponent() {
|
L"tab_1",
|
||||||
Add(&container_);
|
L"tab_2",
|
||||||
container_.Add(&menu_);
|
L"tab_3",
|
||||||
|
|
||||||
menu_.entries = {
|
|
||||||
L"menu_1",
|
|
||||||
L"menu_2",
|
|
||||||
L"menu_3",
|
|
||||||
};
|
};
|
||||||
|
int tab_selected = 0;
|
||||||
|
auto tab_menu = Menu(&tab_values, &tab_selected);
|
||||||
|
|
||||||
container_.Add(&tab_container_);
|
std::vector<std::wstring> tab_1_entries{
|
||||||
|
L"Forest",
|
||||||
|
L"Water",
|
||||||
|
L"I don't know",
|
||||||
|
};
|
||||||
|
int tab_1_selected = 0;
|
||||||
|
|
||||||
menu_1_.entries = {L"Forest", L"Water", L"I don't know"};
|
std::vector<std::wstring> tab_2_entries{
|
||||||
tab_container_.Add(&menu_1_);
|
|
||||||
|
|
||||||
menu_2_.entries = {
|
|
||||||
L"Hello",
|
L"Hello",
|
||||||
L"Hi",
|
L"Hi",
|
||||||
L"Hay",
|
L"Hay",
|
||||||
};
|
};
|
||||||
tab_container_.Add(&menu_2_);
|
int tab_2_selected = 0;
|
||||||
|
|
||||||
menu_3_.entries = {
|
std::vector<std::wstring> tab_3_entries{
|
||||||
L"Table",
|
L"Table",
|
||||||
L"Nothing",
|
L"Nothing",
|
||||||
L"Is",
|
L"Is",
|
||||||
L"Empty",
|
L"Empty",
|
||||||
};
|
};
|
||||||
tab_container_.Add(&menu_3_);
|
int tab_3_selected = 0;
|
||||||
}
|
auto tab_container = Container::Tab(
|
||||||
|
&tab_selected, {
|
||||||
|
Radiobox(&tab_1_entries, &tab_1_selected),
|
||||||
|
Radiobox(&tab_2_entries, &tab_2_selected),
|
||||||
|
Radiobox(&tab_3_entries, &tab_3_selected),
|
||||||
|
});
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
auto container = Container::Horizontal({
|
||||||
|
tab_menu,
|
||||||
|
tab_container,
|
||||||
|
});
|
||||||
|
|
||||||
private:
|
auto renderer = Renderer(container, [&] {
|
||||||
Menu menu_;
|
return hbox({
|
||||||
Container container_ = Container::Horizontal();
|
tab_menu->Render(),
|
||||||
Container tab_container_ = Container::Tab(&(menu_.selected));
|
separator(),
|
||||||
Menu menu_1_;
|
tab_container->Render(),
|
||||||
Menu menu_2_;
|
}) |
|
||||||
Menu menu_3_;
|
border;
|
||||||
};
|
});
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
screen.Loop(renderer);
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,59 +1,63 @@
|
|||||||
#include "ftxui/component/toggle.hpp"
|
#include <memory> // for allocator, __shared_ptr_access
|
||||||
#include "ftxui/component/container.hpp" // for Container
|
#include <string> // for wstring, basic_string
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::Return
|
#include <vector> // for vector
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component.hpp" // for Toggle, Renderer, Vertical
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
|
#include "ftxui/dom/elements.hpp" // for text, hbox, vbox, Element
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
class MyComponent : public Component {
|
int main(int argc, const char* argv[]) {
|
||||||
public:
|
std::vector<std::wstring> toggle_1_entries = {
|
||||||
MyComponent() {
|
L"On",
|
||||||
Add(&container_);
|
L"Off",
|
||||||
container_.Add(&toggle_1_);
|
};
|
||||||
container_.Add(&toggle_2_);
|
std::vector<std::wstring> toggle_2_entries = {
|
||||||
container_.Add(&toggle_3_);
|
L"Enabled",
|
||||||
container_.Add(&toggle_4_);
|
L"Disabled",
|
||||||
|
};
|
||||||
|
std::vector<std::wstring> toggle_3_entries = {
|
||||||
|
L"10€",
|
||||||
|
L"0€",
|
||||||
|
};
|
||||||
|
std::vector<std::wstring> toggle_4_entries = {
|
||||||
|
L"Nothing",
|
||||||
|
L"One element",
|
||||||
|
L"Several elements",
|
||||||
|
};
|
||||||
|
|
||||||
toggle_1_.entries = {L"On", L"Off"};
|
int toggle_1_selected = 0;
|
||||||
toggle_2_.entries = {L"Enabled", L"Disabled"};
|
int toggle_2_selected = 0;
|
||||||
toggle_3_.entries = {L"10€", L"0€"};
|
int toggle_3_selected = 0;
|
||||||
toggle_4_.entries = {L"Nothing", L"One element", L"Several elements"};
|
int toggle_4_selected = 0;
|
||||||
}
|
Component toggle_1 = Toggle(&toggle_1_entries, &toggle_1_selected);
|
||||||
|
Component toggle_2 = Toggle(&toggle_2_entries, &toggle_2_selected);
|
||||||
|
Component toggle_3 = Toggle(&toggle_3_entries, &toggle_3_selected);
|
||||||
|
Component toggle_4 = Toggle(&toggle_4_entries, &toggle_4_selected);
|
||||||
|
|
||||||
std::function<void()> on_enter = []() {};
|
auto container = Container::Vertical({
|
||||||
|
toggle_1,
|
||||||
|
toggle_2,
|
||||||
|
toggle_3,
|
||||||
|
toggle_4,
|
||||||
|
});
|
||||||
|
|
||||||
private:
|
auto renderer = Renderer(container, [&] {
|
||||||
Container container_ = Container::Vertical();
|
|
||||||
Toggle toggle_1_;
|
|
||||||
Toggle toggle_2_;
|
|
||||||
Toggle toggle_3_;
|
|
||||||
Toggle toggle_4_;
|
|
||||||
|
|
||||||
Element Render() override {
|
|
||||||
return vbox({
|
return vbox({
|
||||||
text(L"Choose your options:"),
|
text(L"Choose your options:"),
|
||||||
text(L""),
|
text(L""),
|
||||||
hbox(text(L" * Poweroff on startup : "), toggle_1_.Render()),
|
hbox(text(L" * Poweroff on startup : "), toggle_1->Render()),
|
||||||
hbox(text(L" * Out of process : "), toggle_2_.Render()),
|
hbox(text(L" * Out of process : "), toggle_2->Render()),
|
||||||
hbox(text(L" * Price of the information : "), toggle_3_.Render()),
|
hbox(text(L" * Price of the information : "), toggle_3->Render()),
|
||||||
hbox(text(L" * Number of elements : "), toggle_4_.Render()),
|
hbox(text(L" * Number of elements : "), toggle_4->Render()),
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
bool OnEvent(Event event) override {
|
|
||||||
if (event == Event::Return) {
|
|
||||||
on_enter();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return Component::OnEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
MyComponent component;
|
screen.Loop(renderer);
|
||||||
component.on_enter = screen.ExitLoopClosure();
|
|
||||||
screen.Loop(&component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h> // for size_t
|
||||||
#include <ftxui/dom/elements.hpp>
|
#include <ftxui/dom/elements.hpp> // for operator|, size, Element, text, hcenter, Decorator, WIDTH, hflow, window, EQUAL, GREATER_THAN, HEIGHT, bold, border, dim, LESS_THAN
|
||||||
#include <ftxui/screen/screen.hpp>
|
#include <ftxui/screen/screen.hpp> // for Dimension, Screen
|
||||||
#include <ftxui/screen/string.hpp>
|
#include <ftxui/screen/string.hpp> // for to_wstring
|
||||||
#include <string>
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for allocator, operator+, char_traits, wstring
|
||||||
|
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Render
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for ftxui
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
#include <chrono>
|
#include <chrono> // for operator""s, chrono_literals
|
||||||
#include <ftxui/dom/elements.hpp>
|
#include <ftxui/dom/elements.hpp> // for paragraph, text, operator|, Element, border, color, hflow, spinner, vbox, bold, dim, underlined
|
||||||
#include <ftxui/screen/screen.hpp>
|
#include <ftxui/screen/screen.hpp> // for Screen, Dimension
|
||||||
#include <iostream>
|
#include <iostream> // for cout, ostream
|
||||||
#include <string>
|
#include <memory> // for shared_ptr
|
||||||
#include <thread>
|
#include <string> // for allocator, operator<<, string
|
||||||
|
#include <thread> // for sleep_for
|
||||||
|
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Render
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for ftxui
|
||||||
#include "ftxui/screen/color.hpp"
|
#include "ftxui/screen/color.hpp" // for Color, Color::Red
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
@ -33,15 +33,18 @@
|
|||||||
"./component/menu.js",
|
"./component/menu.js",
|
||||||
"./component/menu2.js",
|
"./component/menu2.js",
|
||||||
"./component/menu_style.js",
|
"./component/menu_style.js",
|
||||||
|
"./component/modal_dialog.js",
|
||||||
"./component/radiobox.js",
|
"./component/radiobox.js",
|
||||||
"./component/radiobox_in_frame.js",
|
"./component/radiobox_in_frame.js",
|
||||||
|
"./component/slider.js",
|
||||||
"./component/tab_horizontal.js",
|
"./component/tab_horizontal.js",
|
||||||
"./component/tab_vertical.js",
|
"./component/tab_vertical.js",
|
||||||
"./component/toggle.js",
|
"./component/toggle.js",
|
||||||
"./component/modal_dialog.js",
|
|
||||||
|
|
||||||
"./dom/border.js",
|
"./dom/border.js",
|
||||||
"./dom/color_gallery.js",
|
"./dom/color_gallery.js",
|
||||||
|
"./dom/color_info_palette256.js",
|
||||||
|
"./dom/color_truecolor_HSV.js",
|
||||||
|
"./dom/color_truecolor_RGB.js",
|
||||||
"./dom/dbox.js",
|
"./dom/dbox.js",
|
||||||
"./dom/gauge.js",
|
"./dom/gauge.js",
|
||||||
"./dom/graph.js",
|
"./dom/graph.js",
|
||||||
@ -55,16 +58,12 @@
|
|||||||
"./dom/style_blink.js",
|
"./dom/style_blink.js",
|
||||||
"./dom/style_bold.js",
|
"./dom/style_bold.js",
|
||||||
"./dom/style_color.js",
|
"./dom/style_color.js",
|
||||||
"./dom/color_truecolor_RGB.js",
|
|
||||||
"./dom/color_truecolor_HSV.js",
|
|
||||||
"./dom/color_info_palette256.js",
|
|
||||||
"./dom/style_dim.js",
|
"./dom/style_dim.js",
|
||||||
"./dom/style_gallery.js",
|
"./dom/style_gallery.js",
|
||||||
"./dom/style_inverted.js",
|
"./dom/style_inverted.js",
|
||||||
"./dom/style_underlined.js",
|
"./dom/style_underlined.js",
|
||||||
"./dom/vbox_hbox.js",
|
"./dom/vbox_hbox.js",
|
||||||
"./dom/window.js",
|
"./dom/window.js",
|
||||||
|
|
||||||
"./util/print_key_press.js",
|
"./util/print_key_press.js",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -4,16 +4,17 @@
|
|||||||
|
|
||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
#include <algorithm> // for max
|
#include <algorithm> // for max
|
||||||
#include <ftxui/component/component.hpp> // for Component
|
#include <ftxui/component/component.hpp> // for Make
|
||||||
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
#include <ftxui/component/screen_interactive.hpp> // for ScreenInteractive
|
||||||
#include <string> // for allocator, operator+
|
#include <string> // for allocator, operator+, wstring, char_traits, to_wstring, string
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/event.hpp" // for Event
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Middle, Mouse::None, Mouse::Pressed, Mouse::Released, Mouse::Right, Mouse::WheelDown, Mouse::WheelUp
|
||||||
#include "ftxui/dom/elements.hpp" // for text, vbox, window
|
#include "ftxui/dom/elements.hpp" // for text, vbox, window, Elements, Element
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
@ -71,7 +72,7 @@ std::wstring Stringify(Event event) {
|
|||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DrawKey : public Component {
|
class DrawKey : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
~DrawKey() override = default;
|
~DrawKey() override = default;
|
||||||
|
|
||||||
@ -94,6 +95,5 @@ class DrawKey : public Component {
|
|||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::TerminalOutput();
|
||||||
DrawKey draw_key;
|
screen.Loop(Make<DrawKey>());
|
||||||
screen.Loop(&draw_key);
|
|
||||||
}
|
}
|
||||||
|
@ -1,36 +1,36 @@
|
|||||||
#ifndef FTXUI_COMPONENT_BUTTON_HPP
|
#ifndef FTXUI_COMPONENT_BUTTON_HPP
|
||||||
#define FTXUI_COMPONENT_BUTTON_HPP
|
#define FTXUI_COMPONENT_BUTTON_HPP
|
||||||
|
|
||||||
#include <functional>
|
#include <functional> // for function
|
||||||
#include <string>
|
#include <string> // for wstring
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/string.hpp" // for ConstStringRef
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
/// @brief A button. An action is associated to the click event.
|
/// @brief A button. An action is associated to the click event.
|
||||||
/// @ingroup dom
|
/// @ingroup dom
|
||||||
class Button : public Component {
|
class ButtonBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
|
// Access this interface from a Component
|
||||||
|
static ButtonBase* From(Component);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
Button() = default;
|
ButtonBase(ConstStringRef label, std::function<void()> on_click);
|
||||||
Button(std::wstring label) : label(label) {}
|
~ButtonBase() override = default;
|
||||||
~Button() override = default;
|
|
||||||
|
|
||||||
/// The Button label.
|
|
||||||
std::wstring label = L"button";
|
|
||||||
|
|
||||||
/// Called when the user press the "enter" button.
|
|
||||||
std::function<void()> on_click = [] {};
|
|
||||||
|
|
||||||
// Component implementation.
|
// Component implementation.
|
||||||
Element Render() override;
|
Element Render() override;
|
||||||
bool OnEvent(Event) override;
|
bool OnEvent(Event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
ConstStringRef label_;
|
||||||
|
std::function<void()> on_click_;
|
||||||
Box box_;
|
Box box_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
#ifndef FTXUI_COMPONENT_CHECKBOX_HPP
|
#ifndef FTXUI_COMPONENT_CHECKBOX_HPP
|
||||||
#define FTXUI_COMPONENT_CHECKBOX_HPP
|
#define FTXUI_COMPONENT_CHECKBOX_HPP
|
||||||
|
|
||||||
#include <string>
|
#include <functional> // for function
|
||||||
|
#include <string> // for allocator, wstring
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
|
#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/string.hpp" // for ConstStringRef
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
@ -12,14 +16,14 @@ struct Event;
|
|||||||
/// @brief A Checkbox. It can be checked or unchecked.Display an element on a
|
/// @brief A Checkbox. It can be checked or unchecked.Display an element on a
|
||||||
/// ftxui::Screen.
|
/// ftxui::Screen.
|
||||||
/// @ingroup dom
|
/// @ingroup dom
|
||||||
class CheckBox : public Component {
|
class CheckboxBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
// Constructor.
|
// Access this interface from a Component
|
||||||
CheckBox() = default;
|
static CheckboxBase* From(Component component);
|
||||||
~CheckBox() override = default;
|
|
||||||
|
|
||||||
bool state = false; // The current state. true=checked, false:unchecked.
|
// Constructor.
|
||||||
std::wstring label = L"label"; // The CheckBox label.
|
CheckboxBase(ConstStringRef label, bool* state);
|
||||||
|
~CheckboxBase() override = default;
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
std::wstring checked = L"[X] "; /// Prefix for a "checked" state.
|
std::wstring checked = L"[X] "; /// Prefix for a "checked" state.
|
||||||
@ -32,7 +36,7 @@ class CheckBox : public Component {
|
|||||||
Decorator focused_style = inverted; /// Decorator used when focused.
|
Decorator focused_style = inverted; /// Decorator used when focused.
|
||||||
Decorator unfocused_style = nothing; /// Decorator used when unfocused.
|
Decorator unfocused_style = nothing; /// Decorator used when unfocused.
|
||||||
|
|
||||||
/// Called when the user change the state of the CheckBox.
|
/// Called when the user change the state of the CheckboxBase.
|
||||||
std::function<void()> on_change = []() {};
|
std::function<void()> on_change = []() {};
|
||||||
|
|
||||||
// Component implementation.
|
// Component implementation.
|
||||||
@ -42,6 +46,8 @@ class CheckBox : public Component {
|
|||||||
private:
|
private:
|
||||||
bool OnMouseEvent(Event event);
|
bool OnMouseEvent(Event event);
|
||||||
|
|
||||||
|
ConstStringRef label_;
|
||||||
|
bool* const state_;
|
||||||
int cursor_position = 0;
|
int cursor_position = 0;
|
||||||
Box box_;
|
Box box_;
|
||||||
};
|
};
|
||||||
|
@ -1,77 +1,48 @@
|
|||||||
#ifndef FTXUI_COMPONENT_COMPONENT_HPP
|
#ifndef FTXUI_COMPONENT_HPP
|
||||||
#define FTXUI_COMPONENT_COMPONENT_HPP
|
#define FTXUI_COMPONENT_HPP
|
||||||
|
|
||||||
#include <memory> // for unique_ptr
|
#include <functional> // for function
|
||||||
|
#include <memory> // for shared_ptr, make_shared
|
||||||
|
#include <string> // for wstring
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
|
#include "ftxui/component/component_base.hpp"
|
||||||
#include "ftxui/dom/elements.hpp" // for Element
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
#include "ftxui/screen/string.hpp" // for ConstStringRef, StringRef
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
class Delegate;
|
class ComponentBase;
|
||||||
class Focus;
|
|
||||||
struct Event;
|
|
||||||
|
|
||||||
/// @brief It implement rendering itself as ftxui::Element. It implement
|
using Component = std::shared_ptr<ComponentBase>;
|
||||||
/// keyboard navigation by responding to ftxui::Event.
|
using Components = std::vector<Component>;
|
||||||
/// @ingroup component
|
|
||||||
class Component {
|
|
||||||
public:
|
|
||||||
// Constructor/Destructor.
|
|
||||||
Component() = default;
|
|
||||||
virtual ~Component();
|
|
||||||
|
|
||||||
// Component hierarchy.
|
template <class T, class... Args>
|
||||||
Component* Parent();
|
std::shared_ptr<T> Make(Args&&... args) {
|
||||||
void Add(Component* children);
|
return std::make_shared<T>(args...);
|
||||||
|
}
|
||||||
|
|
||||||
// Renders the component.
|
Component Button(ConstStringRef label, std::function<void()> on_click);
|
||||||
virtual Element Render();
|
Component Checkbox(ConstStringRef label, bool* checked);
|
||||||
|
Component Input(StringRef content, ConstStringRef placeholder);
|
||||||
|
Component Menu(const std::vector<std::wstring>* entries, int* selected_);
|
||||||
|
Component Radiobox(const std::vector<std::wstring>* entries, int* selected_);
|
||||||
|
Component Toggle(const std::vector<std::wstring>* entries, int* selected);
|
||||||
|
Component Renderer(Component child, std::function<Element()>);
|
||||||
|
Component Renderer(std::function<Element()>);
|
||||||
|
template <class T> // T = {int, float}
|
||||||
|
Component Slider(StringRef label, T* value, T min, T max, T increment);
|
||||||
|
|
||||||
// Handles an event.
|
namespace Container {
|
||||||
// By default, reduce on children with a lazy OR.
|
Component Vertical(Components children);
|
||||||
//
|
Component Horizontal(Components children);
|
||||||
// Returns whether the event was handled or not.
|
Component Tab(int* selector, Components children);
|
||||||
virtual bool OnEvent(Event);
|
} // namespace Container
|
||||||
|
|
||||||
// Focus management ----------------------------------------------------------
|
|
||||||
//
|
|
||||||
// If this component contains children, this indicates which one is active,
|
|
||||||
// nullptr if none is active.
|
|
||||||
//
|
|
||||||
// We say an element has the focus if the chain of ActiveChild() from the
|
|
||||||
// root component contains this object.
|
|
||||||
virtual Component* ActiveChild();
|
|
||||||
|
|
||||||
// Whether this is the active child of its parent.
|
|
||||||
bool Active();
|
|
||||||
// Whether all the ancestors are active.
|
|
||||||
bool Focused();
|
|
||||||
|
|
||||||
// Make the |child| to be the "active" one.
|
|
||||||
virtual void SetActiveChild(Component* child);
|
|
||||||
|
|
||||||
// Configure all the ancestors to give focus to this component.
|
|
||||||
void TakeFocus();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
CapturedMouse CaptureMouse(const Event& event);
|
|
||||||
|
|
||||||
std::vector<Component*> children_;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Component* parent_ = nullptr;
|
|
||||||
void Detach();
|
|
||||||
void Attach(Component* parent);
|
|
||||||
};
|
|
||||||
|
|
||||||
using ComponentPtr = std::unique_ptr<Component>;
|
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|
||||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */
|
#endif /* end of include guard: FTXUI_COMPONENT_HPP */
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
|
81
include/ftxui/component/component_base.hpp
Normal file
81
include/ftxui/component/component_base.hpp
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
#ifndef FTXUI_COMPONENT_BASE_HPP
|
||||||
|
#define FTXUI_COMPONENT_BASE_HPP
|
||||||
|
|
||||||
|
#include <memory> // for unique_ptr
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CaptureMouse
|
||||||
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
|
||||||
|
namespace ftxui {
|
||||||
|
|
||||||
|
class Delegate;
|
||||||
|
class Focus;
|
||||||
|
struct Event;
|
||||||
|
|
||||||
|
class ComponentBase;
|
||||||
|
using Component = std::shared_ptr<ComponentBase>;
|
||||||
|
using Components = std::vector<Component>;
|
||||||
|
|
||||||
|
/// @brief It implement rendering itself as ftxui::Element. It implement
|
||||||
|
/// keyboard navigation by responding to ftxui::Event.
|
||||||
|
/// @ingroup component
|
||||||
|
class ComponentBase {
|
||||||
|
public:
|
||||||
|
// Constructor/Destructor.
|
||||||
|
ComponentBase() = default;
|
||||||
|
virtual ~ComponentBase();
|
||||||
|
|
||||||
|
// ComponentBase hierarchy.
|
||||||
|
ComponentBase* Parent();
|
||||||
|
void Add(Component children);
|
||||||
|
|
||||||
|
// Renders the component.
|
||||||
|
virtual Element Render();
|
||||||
|
|
||||||
|
// Handles an event.
|
||||||
|
// By default, reduce on children with a lazy OR.
|
||||||
|
//
|
||||||
|
// Returns whether the event was handled or not.
|
||||||
|
virtual bool OnEvent(Event);
|
||||||
|
|
||||||
|
// Focus management ----------------------------------------------------------
|
||||||
|
//
|
||||||
|
// If this component contains children, this indicates which one is active,
|
||||||
|
// nullptr if none is active.
|
||||||
|
//
|
||||||
|
// We say an element has the focus if the chain of ActiveChild() from the
|
||||||
|
// root component contains this object.
|
||||||
|
virtual Component ActiveChild();
|
||||||
|
|
||||||
|
// Whether this is the active child of its parent.
|
||||||
|
bool Active();
|
||||||
|
// Whether all the ancestors are active.
|
||||||
|
bool Focused();
|
||||||
|
|
||||||
|
// Make the |child| to be the "active" one.
|
||||||
|
virtual void SetActiveChild(ComponentBase* child);
|
||||||
|
void SetActiveChild(Component child);
|
||||||
|
|
||||||
|
// Configure all the ancestors to give focus to this component.
|
||||||
|
void TakeFocus();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
CapturedMouse CaptureMouse(const Event& event);
|
||||||
|
|
||||||
|
std::vector<Component> children_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ComponentBase* parent_ = nullptr;
|
||||||
|
void Detach();
|
||||||
|
};
|
||||||
|
|
||||||
|
using Component = std::shared_ptr<ComponentBase>;
|
||||||
|
|
||||||
|
} // namespace ftxui
|
||||||
|
|
||||||
|
#endif /* end of include guard: FTXUI_COMPONENT_BASE_HPP */
|
||||||
|
|
||||||
|
// 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.
|
@ -1,36 +1,42 @@
|
|||||||
#ifndef FTXUI_COMPONENT_CONTAINER_HPP
|
#ifndef FTXUI_COMPONENT_CONTAINER_HPP
|
||||||
#define FTXUI_COMPONENT_CONTAINER_HPP
|
#define FTXUI_COMPONENT_CONTAINER_HPP
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component, Components
|
||||||
#include "ftxui/component/event.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
/// @brief A component where focus and events are automatically handled for you.
|
/// @brief A component where focus and events are automatically handled for you.
|
||||||
class Container : public Component {
|
class ContainerBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
static Container Vertical();
|
static Component Vertical();
|
||||||
static Container Horizontal();
|
static Component Vertical(Components children);
|
||||||
static Container Tab(int* selector);
|
|
||||||
|
|
||||||
~Container() override = default;
|
static Component Horizontal();
|
||||||
|
static Component Horizontal(Components children);
|
||||||
|
|
||||||
|
static Component Tab(int* selector);
|
||||||
|
static Component Tab(int* selector, Components children);
|
||||||
|
|
||||||
|
~ContainerBase() override = default;
|
||||||
|
|
||||||
// Component override.
|
// Component override.
|
||||||
bool OnEvent(Event event) override;
|
bool OnEvent(Event event) override;
|
||||||
Element Render() override;
|
Element Render() override;
|
||||||
Component* ActiveChild() override;
|
Component ActiveChild() override;
|
||||||
virtual void SetActiveChild(Component*) override;
|
virtual void SetActiveChild(ComponentBase*) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Handlers
|
// Handlers
|
||||||
using EventHandler = bool (Container::*)(Event);
|
using EventHandler = bool (ContainerBase::*)(Event);
|
||||||
bool VerticalEvent(Event event);
|
bool VerticalEvent(Event event);
|
||||||
bool HorizontalEvent(Event event);
|
bool HorizontalEvent(Event event);
|
||||||
bool TabEvent(Event) { return false; }
|
bool TabEvent(Event) { return false; }
|
||||||
EventHandler event_handler_;
|
EventHandler event_handler_;
|
||||||
|
|
||||||
using RenderHandler = Element (Container::*)();
|
using RenderHandler = Element (ContainerBase::*)();
|
||||||
Element VerticalRender();
|
Element VerticalRender();
|
||||||
Element HorizontalRender();
|
Element HorizontalRender();
|
||||||
Element TabRender();
|
Element TabRender();
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
class ScreenInteractive;
|
class ScreenInteractive;
|
||||||
class Component;
|
class ComponentBase;
|
||||||
|
|
||||||
/// @brief Represent an event. It can be key press event, a terminal resize, or
|
/// @brief Represent an event. It can be key press event, a terminal resize, or
|
||||||
/// more ...
|
/// more ...
|
||||||
@ -76,7 +76,7 @@ struct Event {
|
|||||||
|
|
||||||
//--- State section ----------------------------------------------------------
|
//--- State section ----------------------------------------------------------
|
||||||
private:
|
private:
|
||||||
friend Component;
|
friend ComponentBase;
|
||||||
friend ScreenInteractive;
|
friend ScreenInteractive;
|
||||||
enum class Type {
|
enum class Type {
|
||||||
Unknown,
|
Unknown,
|
||||||
|
@ -1,27 +1,30 @@
|
|||||||
#ifndef FTXUI_COMPONENT_INPUT_H_
|
#ifndef FTXUI_COMPONENT_INPUT_H_
|
||||||
#define FTXUI_COMPONENT_INPUT_H_
|
#define FTXUI_COMPONENT_INPUT_H_
|
||||||
|
|
||||||
#include <functional>
|
#include <functional> // for function
|
||||||
#include <string>
|
#include <string> // for wstring
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/string.hpp" // for ConstStringRef, StringRef
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
/// @brief An input box. The user can type text into it.
|
/// @brief An input box. The user can type text into it.
|
||||||
/// @ingroup component.
|
/// @ingroup component.
|
||||||
class Input : public Component {
|
class InputBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
|
// Access this interface from a Component
|
||||||
|
static InputBase* From(Component component);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
Input() = default;
|
InputBase(StringRef content, ConstStringRef placeholder);
|
||||||
~Input() override = default;
|
~InputBase() override = default;
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
std::wstring content;
|
|
||||||
std::wstring placeholder;
|
|
||||||
int cursor_position = 0;
|
int cursor_position = 0;
|
||||||
|
|
||||||
// State update callback.
|
// State update callback.
|
||||||
@ -33,6 +36,9 @@ class Input : public Component {
|
|||||||
bool OnEvent(Event) override;
|
bool OnEvent(Event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
StringRef content_;
|
||||||
|
ConstStringRef placeholder_;
|
||||||
|
|
||||||
bool OnMouseEvent(Event);
|
bool OnMouseEvent(Event);
|
||||||
Box input_box_;
|
Box input_box_;
|
||||||
Box cursor_box_;
|
Box cursor_box_;
|
||||||
|
@ -1,28 +1,30 @@
|
|||||||
#ifndef FTXUI_COMPONENT_MENU
|
#ifndef FTXUI_COMPONENT_MENU
|
||||||
#define FTXUI_COMPONENT_MENU
|
#define FTXUI_COMPONENT_MENU
|
||||||
|
|
||||||
#include <functional>
|
#include <functional> // for function
|
||||||
#include <string>
|
#include <string> // for wstring
|
||||||
#include <vector>
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, inverted, nothing
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
/// @brief A list of items. The user can navigate through them.
|
/// @brief A list of items. The user can navigate through them.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
class Menu : public Component {
|
class MenuBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
|
// Access this interface from a Component
|
||||||
|
static MenuBase* From(Component component);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
Menu() = default;
|
MenuBase(const std::vector<std::wstring>* entries, int* selected_);
|
||||||
~Menu() override = default;
|
~MenuBase() override = default;
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
std::vector<std::wstring> entries = {};
|
|
||||||
int selected = 0;
|
|
||||||
int focused = 0;
|
int focused = 0;
|
||||||
|
|
||||||
Decorator normal_style = nothing;
|
Decorator normal_style = nothing;
|
||||||
@ -38,7 +40,10 @@ class Menu : public Component {
|
|||||||
Element Render() override;
|
Element Render() override;
|
||||||
bool OnEvent(Event) override;
|
bool OnEvent(Event) override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
const std::vector<std::wstring>* const entries_;
|
||||||
|
int* selected_ = 0;
|
||||||
|
|
||||||
bool OnMouseEvent(Event);
|
bool OnMouseEvent(Event);
|
||||||
|
|
||||||
std::vector<Box> boxes_;
|
std::vector<Box> boxes_;
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
#ifndef FTXUI_COMPONENT_RADIOBOX_HPP
|
#ifndef FTXUI_COMPONENT_RADIOBOX_HPP
|
||||||
#define FTXUI_COMPONENT_RADIOBOX_HPP
|
#define FTXUI_COMPONENT_RADIOBOX_HPP
|
||||||
|
|
||||||
#include <string>
|
#include <functional> // for function
|
||||||
#include <vector>
|
#include <string> // for wstring, allocator
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, Decorator, inverted, nothing
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
@ -14,15 +16,16 @@ struct Event;
|
|||||||
/// @brief A list of selectable element. One and only one can be selected at
|
/// @brief A list of selectable element. One and only one can be selected at
|
||||||
/// the same time.
|
/// the same time.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
class RadioBox : public Component {
|
class RadioboxBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
// Constructor.
|
// Access this interface from a Component
|
||||||
RadioBox() = default;
|
static RadioboxBase* From(Component component);
|
||||||
~RadioBox() override = default;
|
|
||||||
|
// Constructor.
|
||||||
|
RadioboxBase(const std::vector<std::wstring>* entries, int* selected);
|
||||||
|
~RadioboxBase() override = default;
|
||||||
|
|
||||||
int selected = 0;
|
|
||||||
int focused = 0;
|
int focused = 0;
|
||||||
std::vector<std::wstring> entries;
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
std::wstring checked = L"(*) ";
|
std::wstring checked = L"(*) ";
|
||||||
@ -43,6 +46,9 @@ class RadioBox : public Component {
|
|||||||
bool OnEvent(Event) override;
|
bool OnEvent(Event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
const std::vector<std::wstring>* const entries_;
|
||||||
|
int* const selected_;
|
||||||
|
|
||||||
bool OnMouseEvent(Event event);
|
bool OnMouseEvent(Event event);
|
||||||
int cursor_position = 0;
|
int cursor_position = 0;
|
||||||
std::vector<Box> boxes_;
|
std::vector<Box> boxes_;
|
||||||
|
@ -1,13 +1,15 @@
|
|||||||
#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
|
#ifndef FTXUI_COMPONENT_RECEIVER_HPP_
|
||||||
#define FTXUI_COMPONENT_RECEIVER_HPP_
|
#define FTXUI_COMPONENT_RECEIVER_HPP_
|
||||||
|
|
||||||
#include <atomic> // for atomic
|
#include <algorithm> // for copy, max
|
||||||
|
#include <atomic> // for atomic, __atomic_base
|
||||||
#include <condition_variable> // for condition_variable
|
#include <condition_variable> // for condition_variable
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <memory> // for unique_ptr, make_unique
|
#include <memory> // for unique_ptr, make_unique
|
||||||
#include <mutex> // for mutex, unique_lock
|
#include <mutex> // for mutex, unique_lock
|
||||||
#include <queue> // for queue
|
#include <queue> // for queue
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
||||||
|
|
||||||
#include <atomic> // for atomic
|
#include <atomic> // for atomic
|
||||||
#include <ftxui/component/receiver.hpp>
|
#include <ftxui/component/receiver.hpp> // for Receiver, Sender
|
||||||
#include <memory> // for unique_ptr
|
#include <functional> // for function
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
#include <string> // for string
|
#include <string> // for string
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
@ -11,7 +12,9 @@
|
|||||||
#include "ftxui/screen/screen.hpp" // for Screen
|
#include "ftxui/screen/screen.hpp" // for Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
class Component;
|
class ComponentBase;
|
||||||
|
|
||||||
|
using Component = std::shared_ptr<ComponentBase>;
|
||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
class ScreenInteractive : public Screen {
|
class ScreenInteractive : public Screen {
|
||||||
@ -22,15 +25,15 @@ class ScreenInteractive : public Screen {
|
|||||||
static ScreenInteractive TerminalOutput();
|
static ScreenInteractive TerminalOutput();
|
||||||
|
|
||||||
~ScreenInteractive();
|
~ScreenInteractive();
|
||||||
void Loop(Component*);
|
void Loop(Component);
|
||||||
std::function<void()> ExitLoopClosure();
|
std::function<void()> ExitLoopClosure();
|
||||||
|
|
||||||
void PostEvent(Event event);
|
void PostEvent(Event event);
|
||||||
CapturedMouse CaptureMouse();
|
CapturedMouse CaptureMouse();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Draw(Component* component);
|
void Draw(Component component);
|
||||||
void EventLoop(Component* component);
|
void EventLoop(Component component);
|
||||||
|
|
||||||
enum class Dimension {
|
enum class Dimension {
|
||||||
FitComponent,
|
FitComponent,
|
||||||
|
@ -1,23 +0,0 @@
|
|||||||
#ifndef FTXUI_COMPONENT_SLIDER_HPP
|
|
||||||
#define FTXUI_COMPONENT_SLIDER_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include "ftxui/component/component.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
|
||||||
// ComponentPtr Slider(std::string label,
|
|
||||||
// float* value,
|
|
||||||
// float min = 0.f,
|
|
||||||
// float max = 100.f,
|
|
||||||
// float increment = (max - min) * 0.05f);
|
|
||||||
|
|
||||||
template <class T> // T = {int, float}
|
|
||||||
ComponentPtr Slider(std::wstring label, T* value, T min, T max, T increment);
|
|
||||||
|
|
||||||
} // namespace ftxui
|
|
||||||
|
|
||||||
#endif /* end of include guard: FTXUI_COMPONENT_SLIDER_HPP */
|
|
||||||
|
|
||||||
// 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.
|
|
@ -1,26 +1,30 @@
|
|||||||
#ifndef FTXUI_COMPONENT_TOGGLE_H_
|
#ifndef FTXUI_COMPONENT_TOGGLE_H_
|
||||||
#define FTXUI_COMPONENT_TOGGLE_H_
|
#define FTXUI_COMPONENT_TOGGLE_H_
|
||||||
|
|
||||||
#include <string>
|
#include <functional> // for function
|
||||||
#include <vector>
|
#include <string> // for wstring
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, Decorator, operator|, bold, dim, inverted
|
||||||
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
struct Event;
|
struct Event;
|
||||||
|
|
||||||
/// @brief An horizontal list of elements. The user can navigate through them.
|
/// @brief An horizontal list of elements. The user can navigate through them.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
class Toggle : public Component {
|
class ToggleBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
|
// Access this interface from a Component
|
||||||
|
static ToggleBase* From(Component component);
|
||||||
|
|
||||||
// Constructor.
|
// Constructor.
|
||||||
~Toggle() override = default;
|
ToggleBase(const std::vector<std::wstring>* entries, int* selected);
|
||||||
|
~ToggleBase() override = default;
|
||||||
|
|
||||||
// State.
|
// State.
|
||||||
std::vector<std::wstring> entries = {L"On", L"Off"};
|
|
||||||
int selected = 0;
|
|
||||||
int focused = 0;
|
int focused = 0;
|
||||||
|
|
||||||
Decorator normal_style = dim;
|
Decorator normal_style = dim;
|
||||||
@ -36,7 +40,10 @@ class Toggle : public Component {
|
|||||||
Element Render() override;
|
Element Render() override;
|
||||||
bool OnEvent(Event) override;
|
bool OnEvent(Event) override;
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
const std::vector<std::wstring>* const entries_;
|
||||||
|
int* selected_ = 0;
|
||||||
|
|
||||||
bool OnMouseEvent(Event event);
|
bool OnMouseEvent(Event event);
|
||||||
std::vector<Box> boxes_;
|
std::vector<Box> boxes_;
|
||||||
};
|
};
|
||||||
|
@ -16,6 +16,41 @@ int wchar_width(wchar_t);
|
|||||||
int wchar_width_cjk(wchar_t);
|
int wchar_width_cjk(wchar_t);
|
||||||
int wstring_width(const std::wstring&);
|
int wstring_width(const std::wstring&);
|
||||||
int wstring_width_cjk(const std::wstring&);
|
int wstring_width_cjk(const std::wstring&);
|
||||||
|
|
||||||
|
/// @brief For convenience, this class convert multiple mutable string
|
||||||
|
/// references toward a shared representation.
|
||||||
|
class StringRef {
|
||||||
|
public:
|
||||||
|
StringRef(std::wstring& ref);
|
||||||
|
StringRef(std::wstring* ref);
|
||||||
|
StringRef(const wchar_t* ref);
|
||||||
|
StringRef(const char* ref);
|
||||||
|
|
||||||
|
std::wstring& operator*();
|
||||||
|
std::wstring* operator->();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::wstring* const borrowed_ = nullptr;
|
||||||
|
std::wstring owned_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief For convenience, this class convert multiple immutable string
|
||||||
|
/// references toward shared representation.
|
||||||
|
class ConstStringRef {
|
||||||
|
public:
|
||||||
|
ConstStringRef(const std::wstring& ref);
|
||||||
|
ConstStringRef(const std::wstring* ref);
|
||||||
|
ConstStringRef(const wchar_t* ref);
|
||||||
|
ConstStringRef(const char* ref);
|
||||||
|
|
||||||
|
const std::wstring& operator*();
|
||||||
|
const std::wstring* operator->();
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::wstring* const borrowed_ = nullptr;
|
||||||
|
const std::wstring owned_;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|
||||||
#endif /* end of include guard: FTXUI_SCREEN_STRING_HPP */
|
#endif /* end of include guard: FTXUI_SCREEN_STRING_HPP */
|
||||||
|
9
iwyu.imp
9
iwyu.imp
@ -1,8 +1,11 @@
|
|||||||
[
|
[
|
||||||
{ symbol: [ "VMIN", private, "<termios.h>", public ] },
|
|
||||||
{ symbol: [ "VTIME", private, "<termios.h>", public ] },
|
|
||||||
{ symbol: [ "ECHO", private, "<termios.h>", public ] },
|
{ symbol: [ "ECHO", private, "<termios.h>", public ] },
|
||||||
{ symbol: [ "ICANON", private, "<termios.h>", public ] },
|
{ symbol: [ "ICANON", private, "<termios.h>", public ] },
|
||||||
{ symbol: [ "termios", private, "<termios.h>", public ] },
|
|
||||||
{ symbol: [ "TCSANOW", private, "<termios.h>", public ] },
|
{ symbol: [ "TCSANOW", private, "<termios.h>", public ] },
|
||||||
|
{ symbol: [ "VMIN", private, "<termios.h>", public ] },
|
||||||
|
{ symbol: [ "VTIME", private, "<termios.h>", public ] },
|
||||||
|
{ symbol: [ "__shared_ptr_access", private, "<memory>", public ] },
|
||||||
|
{ symbol: [ "termios", private, "<termios.h>", public ] },
|
||||||
|
{ symbol: ["__alloc_traits<>:value_type", private, "<vector>", public ] },
|
||||||
|
{ include: ["<ext/alloc_traits.h>", private, "<vector>", public] },
|
||||||
]
|
]
|
||||||
|
@ -9,12 +9,46 @@
|
|||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element Button::Render() {
|
/// @brief Draw a button. Execute a function when clicked.
|
||||||
auto style = Focused() ? inverted : nothing;
|
/// @param label The label of the button.
|
||||||
return text(label) | border | style | reflect(box_);
|
/// @param on_click The action to execute when clicked.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see ButtonBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::FitComponent();
|
||||||
|
/// std::wstring label = L"Click to quit";
|
||||||
|
/// Component button = Button(&label, screen.ExitLoopClosure());
|
||||||
|
/// screen.Loop(button)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// ┌─────────────┐
|
||||||
|
/// │Click to quit│
|
||||||
|
/// └─────────────┘
|
||||||
|
/// ```
|
||||||
|
Component Button(ConstStringRef label, std::function<void()> on_click) {
|
||||||
|
return Make<ButtonBase>(label, on_click);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Button::OnEvent(Event event) {
|
// static
|
||||||
|
ButtonBase* ButtonBase::From(Component component) {
|
||||||
|
return static_cast<ButtonBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ButtonBase::ButtonBase(ConstStringRef label, std::function<void()> on_click)
|
||||||
|
: label_(label), on_click_(on_click) {}
|
||||||
|
|
||||||
|
Element ButtonBase::Render() {
|
||||||
|
auto style = Focused() ? inverted : nothing;
|
||||||
|
return text(*label_) | border | style | reflect(box_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ButtonBase::OnEvent(Event event) {
|
||||||
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
|
if (event.is_mouse() && box_.Contain(event.mouse().x, event.mouse().y)) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
@ -23,7 +57,7 @@ bool Button::OnEvent(Event event) {
|
|||||||
|
|
||||||
if (event.mouse().button == Mouse::Left &&
|
if (event.mouse().button == Mouse::Left &&
|
||||||
event.mouse().motion == Mouse::Pressed) {
|
event.mouse().motion == Mouse::Pressed) {
|
||||||
on_click();
|
on_click_();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,7 +65,7 @@ bool Button::OnEvent(Event event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event == Event::Return) {
|
if (event == Event::Return) {
|
||||||
on_click();
|
on_click_();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -9,28 +9,61 @@
|
|||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element CheckBox::Render() {
|
/// @brief Draw checkable element.
|
||||||
|
/// @param label The label of the checkbox.
|
||||||
|
/// @param checked Whether the checkbox is checked or not.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see CheckboxBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::FitComponent();
|
||||||
|
/// std::wstring label = L"Make a sandwidth";
|
||||||
|
/// bool checked = false;
|
||||||
|
/// Component checkbox = Checkbox(&label, &checked);
|
||||||
|
/// screen.Loop(checkbox)
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// ☐ Make a sandwitch
|
||||||
|
/// ```
|
||||||
|
Component Checkbox(ConstStringRef label, bool* checked) {
|
||||||
|
return Make<CheckboxBase>(label, checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
CheckboxBase* CheckboxBase::From(Component component) {
|
||||||
|
return static_cast<CheckboxBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
CheckboxBase::CheckboxBase(ConstStringRef label, bool* state)
|
||||||
|
: label_(label), state_(state) {}
|
||||||
|
|
||||||
|
Element CheckboxBase::Render() {
|
||||||
bool is_focused = Focused();
|
bool is_focused = Focused();
|
||||||
auto style = is_focused ? focused_style : unfocused_style;
|
auto style = is_focused ? focused_style : unfocused_style;
|
||||||
auto focus_management = is_focused ? focus : state ? select : nothing;
|
auto focus_management = is_focused ? focus : *state_ ? select : nothing;
|
||||||
return hbox(text(state ? checked : unchecked),
|
return hbox(text(*state_ ? checked : unchecked),
|
||||||
text(label) | style | focus_management) |
|
text(*label_) | style | focus_management) |
|
||||||
reflect(box_);
|
reflect(box_);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckBox::OnEvent(Event event) {
|
bool CheckboxBase::OnEvent(Event event) {
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
return OnMouseEvent(event);
|
return OnMouseEvent(event);
|
||||||
|
|
||||||
if (event == Event::Character(' ') || event == Event::Return) {
|
if (event == Event::Character(' ') || event == Event::Return) {
|
||||||
state = !state;
|
*state_ = !*state_;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckBox::OnMouseEvent(Event event) {
|
bool CheckboxBase::OnMouseEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
if (!box_.Contain(event.mouse().x, event.mouse().y))
|
if (!box_.Contain(event.mouse().x, event.mouse().y))
|
||||||
@ -40,7 +73,7 @@ bool CheckBox::OnMouseEvent(Event event) {
|
|||||||
|
|
||||||
if (event.mouse().button == Mouse::Left &&
|
if (event.mouse().button == Mouse::Left &&
|
||||||
event.mouse().motion == Mouse::Pressed) {
|
event.mouse().motion == Mouse::Pressed) {
|
||||||
state = !state;
|
*state_ = !*state_;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
|
#include <algorithm> // for find_if, max
|
||||||
|
#include <iterator> // for begin, end
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp"
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase, Component
|
||||||
#include <algorithm>
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
|
#include "ftxui/component/screen_interactive.hpp" // for Component, ScreenInteractive
|
||||||
#include "ftxui/component/captured_mouse.hpp"
|
#include "ftxui/dom/elements.hpp" // for text, Element
|
||||||
#include "ftxui/component/event.hpp"
|
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
@ -13,33 +16,35 @@ class CaptureMouseImpl : public CapturedMouseInterface {
|
|||||||
public:
|
public:
|
||||||
~CaptureMouseImpl() override {}
|
~CaptureMouseImpl() override {}
|
||||||
};
|
};
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
Component::~Component() {
|
ComponentBase::~ComponentBase() {
|
||||||
Detach();
|
Detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Return the parent Component, or nul if any.
|
/// @brief Return the parent ComponentBase, or nul if any.
|
||||||
/// @see Attach
|
/// @see Attach
|
||||||
/// @see Detach
|
/// @see Detach
|
||||||
/// @see Parent
|
/// @see Parent
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
Component* Component::Parent() {
|
ComponentBase* ComponentBase::Parent() {
|
||||||
return parent_;
|
return parent_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Add a children.
|
/// @brief Add a children.
|
||||||
/// @@param child The child to be attached.
|
/// @@param child The child to be attached.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
void Component::Add(Component* child) {
|
void ComponentBase::Add(Component child) {
|
||||||
child->Attach(this);
|
child->Detach();
|
||||||
|
child->parent_ = this;
|
||||||
|
children_.push_back(std::move(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Draw the component.
|
/// @brief Draw the component.
|
||||||
/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
|
/// Build a ftxui::Element to be drawn on the ftxi::Screen representing this
|
||||||
/// ftxui::Component.
|
/// ftxui::ComponentBase.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
Element Component::Render() {
|
Element ComponentBase::Render() {
|
||||||
if (children_.size() == 1)
|
if (children_.size() == 1)
|
||||||
return children_.front()->Render();
|
return children_.front()->Render();
|
||||||
|
|
||||||
@ -52,8 +57,8 @@ Element Component::Render() {
|
|||||||
/// The default implementation called OnEvent on every child until one return
|
/// The default implementation called OnEvent on every child until one return
|
||||||
/// true. If none returns true, return false.
|
/// true. If none returns true, return false.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
bool Component::OnEvent(Event event) {
|
bool ComponentBase::OnEvent(Event event) {
|
||||||
for (Component* child : children_) {
|
for (Component& child : children_) {
|
||||||
if (child->OnEvent(event))
|
if (child->OnEvent(event))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -63,27 +68,27 @@ bool Component::OnEvent(Event event) {
|
|||||||
/// @brief Return the currently Active child.
|
/// @brief Return the currently Active child.
|
||||||
/// @return the currently Active child.
|
/// @return the currently Active child.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
Component* Component::ActiveChild() {
|
Component ComponentBase::ActiveChild() {
|
||||||
return children_.empty() ? nullptr : children_.front();
|
return children_.empty() ? nullptr : children_.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Returns if the element if the currently active child of its parent.
|
/// @brief Returns if the element if the currently active child of its parent.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
bool Component::Active() {
|
bool ComponentBase::Active() {
|
||||||
return !parent_ || parent_->ActiveChild() == this;
|
return !parent_ || parent_->ActiveChild().get() == this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Returns if the elements if focused by the user.
|
/// @brief Returns if the elements if focused by the user.
|
||||||
/// True when the Component is focused by the user. An element is Focused when
|
/// True when the ComponentBase is focused by the user. An element is Focused
|
||||||
/// it is with all its ancestors the ActiveChild() of their parents.
|
/// when it is with all its ancestors the ActiveChild() of their parents.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
bool Component::Focused() {
|
bool ComponentBase::Focused() {
|
||||||
Component* current = this;
|
ComponentBase* current = this;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
Component* parent = current->parent_;
|
ComponentBase* parent = current->parent_;
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return true;
|
return true;
|
||||||
if (parent->ActiveChild() != current)
|
if (parent->ActiveChild().get() != current)
|
||||||
return false;
|
return false;
|
||||||
current = parent;
|
current = parent;
|
||||||
}
|
}
|
||||||
@ -92,13 +97,20 @@ bool Component::Focused() {
|
|||||||
/// @brief Make the |child| to be the "active" one.
|
/// @brief Make the |child| to be the "active" one.
|
||||||
/// @argument child the child to become active.
|
/// @argument child the child to become active.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
void Component::SetActiveChild(Component*) {}
|
void ComponentBase::SetActiveChild(ComponentBase*) {}
|
||||||
|
|
||||||
|
/// @brief Make the |child| to be the "active" one.
|
||||||
|
/// @argument child the child to become active.
|
||||||
|
/// @ingroup component
|
||||||
|
void ComponentBase::SetActiveChild(Component child) {
|
||||||
|
SetActiveChild(child.get());
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Configure all the ancestors to give focus to this component.
|
/// @brief Configure all the ancestors to give focus to this component.
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
void Component::TakeFocus() {
|
void ComponentBase::TakeFocus() {
|
||||||
Component* child = this;
|
ComponentBase* child = this;
|
||||||
Component* parent = parent_;
|
ComponentBase* parent = parent_;
|
||||||
while (parent) {
|
while (parent) {
|
||||||
parent->SetActiveChild(child);
|
parent->SetActiveChild(child);
|
||||||
child = parent;
|
child = parent;
|
||||||
@ -110,7 +122,7 @@ void Component::TakeFocus() {
|
|||||||
/// them. It represents a component taking priority over others.
|
/// them. It represents a component taking priority over others.
|
||||||
/// @argument event
|
/// @argument event
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
CapturedMouse Component::CaptureMouse(const Event& event) {
|
CapturedMouse ComponentBase::CaptureMouse(const Event& event) {
|
||||||
if (!event.screen_)
|
if (!event.screen_)
|
||||||
return std::make_unique<CaptureMouseImpl>();
|
return std::make_unique<CaptureMouseImpl>();
|
||||||
return event.screen_->CaptureMouse();
|
return event.screen_->CaptureMouse();
|
||||||
@ -121,25 +133,17 @@ CapturedMouse Component::CaptureMouse(const Event& event) {
|
|||||||
/// @see Detach
|
/// @see Detach
|
||||||
/// @see Parent
|
/// @see Parent
|
||||||
/// @ingroup component
|
/// @ingroup component
|
||||||
void Component::Detach() {
|
void ComponentBase::Detach() {
|
||||||
if (!parent_)
|
if (!parent_)
|
||||||
return;
|
return;
|
||||||
auto it = std::find(std::begin(parent_->children_),
|
auto it = std::find_if(std::begin(parent_->children_), //
|
||||||
std::end(parent_->children_), this);
|
std::end(parent_->children_), //
|
||||||
|
[this](const Component& that) { //
|
||||||
|
return this == that.get();
|
||||||
|
});
|
||||||
parent_->children_.erase(it);
|
parent_->children_.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Attach this element to its parent.
|
|
||||||
/// @see Attach
|
|
||||||
/// @see Detach
|
|
||||||
/// @see Parent
|
|
||||||
/// @ingroup component
|
|
||||||
void Component::Attach(Component* parent) {
|
|
||||||
Detach();
|
|
||||||
parent_ = parent;
|
|
||||||
parent_->children_.push_back(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,37 +1,127 @@
|
|||||||
#include "ftxui/component/container.hpp"
|
#include <stddef.h> // for size_t
|
||||||
|
#include <algorithm> // for max, min
|
||||||
|
#include <memory> // for __shared_ptr_access, shared_ptr, make_shared, allocator, __shared_ptr_access<>::element_type, allocator_traits<>::value_type
|
||||||
|
#include <utility> // for move
|
||||||
|
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||||
|
|
||||||
#include <stddef.h>
|
#include "ftxui/component/container.hpp"
|
||||||
#include <algorithm>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
namespace Container {
|
||||||
|
|
||||||
|
/// @brief A list of components, drawn one by one vertically and navigated
|
||||||
|
/// vertically using up/down arrow key or 'j'/'k' keys.
|
||||||
|
/// @param children the list of components.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see ContainerBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto container = Container::Vertical({
|
||||||
|
/// children_1,
|
||||||
|
/// children_2,
|
||||||
|
/// children_3,
|
||||||
|
/// children_4,
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
Component Vertical(Components children) {
|
||||||
|
return ContainerBase::Vertical(std::move(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief A list of components, drawn one by one horizontally and navigated
|
||||||
|
/// horizontally using left/right arrow key or 'h'/'l' keys.
|
||||||
|
/// @param children the list of components.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see ContainerBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto container = Container::Horizontal({
|
||||||
|
/// children_1,
|
||||||
|
/// children_2,
|
||||||
|
/// children_3,
|
||||||
|
/// children_4,
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
Component Horizontal(Components children) {
|
||||||
|
return ContainerBase::Horizontal(std::move(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief A list of components, where only one is drawn and interacted with at
|
||||||
|
/// a time. The |selector| gives the index of the selected component. This is
|
||||||
|
/// useful to implement tabs.
|
||||||
|
/// @param selector The index of the drawn children.
|
||||||
|
/// @param children the list of components.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see ContainerBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// int tab_drawn = 0;
|
||||||
|
/// auto container = Container::Tab(&tab_drawn, {
|
||||||
|
/// children_1,
|
||||||
|
/// children_2,
|
||||||
|
/// children_3,
|
||||||
|
/// children_4,
|
||||||
|
/// });
|
||||||
|
/// ```
|
||||||
|
Component Tab(int* selector, Components children) {
|
||||||
|
return ContainerBase::Tab(selector, std::move(children));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Container
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Container Container::Horizontal() {
|
Component ContainerBase::Vertical() {
|
||||||
Container container;
|
return Vertical({});
|
||||||
container.event_handler_ = &Container::HorizontalEvent;
|
}
|
||||||
container.render_handler_ = &Container::HorizontalRender;
|
|
||||||
|
// static
|
||||||
|
Component ContainerBase::Vertical(Components children) {
|
||||||
|
auto container = std::make_shared<ContainerBase>();
|
||||||
|
container->event_handler_ = &ContainerBase::VerticalEvent;
|
||||||
|
container->render_handler_ = &ContainerBase::VerticalRender;
|
||||||
|
for (Component& child : children)
|
||||||
|
container->Add(std::move(child));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Container Container::Vertical() {
|
Component ContainerBase::Horizontal() {
|
||||||
Container container;
|
return Horizontal({});
|
||||||
container.event_handler_ = &Container::VerticalEvent;
|
}
|
||||||
container.render_handler_ = &Container::VerticalRender;
|
|
||||||
|
// static
|
||||||
|
Component ContainerBase::Horizontal(Components children) {
|
||||||
|
auto container = std::make_shared<ContainerBase>();
|
||||||
|
container->event_handler_ = &ContainerBase::HorizontalEvent;
|
||||||
|
container->render_handler_ = &ContainerBase::HorizontalRender;
|
||||||
|
for (Component& child : children)
|
||||||
|
container->Add(std::move(child));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Container Container::Tab(int* selector) {
|
Component ContainerBase::Tab(int* selector) {
|
||||||
Container container;
|
return Tab(selector, {});
|
||||||
container.event_handler_ = &Container::TabEvent;
|
}
|
||||||
container.render_handler_ = &Container::TabRender;
|
|
||||||
container.selector_ = selector;
|
// static
|
||||||
|
Component ContainerBase::Tab(int* selector, Components children) {
|
||||||
|
auto container = std::make_shared<ContainerBase>();
|
||||||
|
container->selector_ = selector;
|
||||||
|
container->event_handler_ = &ContainerBase::TabEvent;
|
||||||
|
container->render_handler_ = &ContainerBase::TabRender;
|
||||||
|
for (Component& child : children)
|
||||||
|
container->Add(std::move(child));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Container::OnEvent(Event event) {
|
bool ContainerBase::OnEvent(Event event) {
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
return OnMouseEvent(event);
|
return OnMouseEvent(event);
|
||||||
|
|
||||||
@ -44,7 +134,7 @@ bool Container::OnEvent(Event event) {
|
|||||||
return (this->*event_handler_)(event);
|
return (this->*event_handler_)(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
Component* Container::ActiveChild() {
|
Component ContainerBase::ActiveChild() {
|
||||||
if (children_.size() == 0)
|
if (children_.size() == 0)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
@ -52,16 +142,16 @@ Component* Container::ActiveChild() {
|
|||||||
return children_[selected % children_.size()];
|
return children_[selected % children_.size()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::SetActiveChild(Component* child) {
|
void ContainerBase::SetActiveChild(ComponentBase* child) {
|
||||||
for (size_t i = 0; i < children_.size(); ++i) {
|
for (size_t i = 0; i < children_.size(); ++i) {
|
||||||
if (children_[i] == child) {
|
if (children_[i].get() == child) {
|
||||||
(selector_ ? *selector_ : selected_) = i;
|
(selector_ ? *selector_ : selected_) = i;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Container::VerticalEvent(Event event) {
|
bool ContainerBase::VerticalEvent(Event event) {
|
||||||
int old_selected = selected_;
|
int old_selected = selected_;
|
||||||
if (event == Event::ArrowUp || event == Event::Character('k'))
|
if (event == Event::ArrowUp || event == Event::Character('k'))
|
||||||
selected_--;
|
selected_--;
|
||||||
@ -76,7 +166,7 @@ bool Container::VerticalEvent(Event event) {
|
|||||||
return old_selected != selected_;
|
return old_selected != selected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Container::HorizontalEvent(Event event) {
|
bool ContainerBase::HorizontalEvent(Event event) {
|
||||||
int old_selected = selected_;
|
int old_selected = selected_;
|
||||||
if (event == Event::ArrowLeft || event == Event::Character('h'))
|
if (event == Event::ArrowLeft || event == Event::Character('h'))
|
||||||
selected_--;
|
selected_--;
|
||||||
@ -91,11 +181,11 @@ bool Container::HorizontalEvent(Event event) {
|
|||||||
return old_selected != selected_;
|
return old_selected != selected_;
|
||||||
}
|
}
|
||||||
|
|
||||||
Element Container::Render() {
|
Element ContainerBase::Render() {
|
||||||
return (this->*render_handler_)();
|
return (this->*render_handler_)();
|
||||||
}
|
}
|
||||||
|
|
||||||
Element Container::VerticalRender() {
|
Element ContainerBase::VerticalRender() {
|
||||||
Elements elements;
|
Elements elements;
|
||||||
for (auto& it : children_)
|
for (auto& it : children_)
|
||||||
elements.push_back(it->Render());
|
elements.push_back(it->Render());
|
||||||
@ -104,7 +194,7 @@ Element Container::VerticalRender() {
|
|||||||
return vbox(std::move(elements));
|
return vbox(std::move(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
Element Container::HorizontalRender() {
|
Element ContainerBase::HorizontalRender() {
|
||||||
Elements elements;
|
Elements elements;
|
||||||
for (auto& it : children_)
|
for (auto& it : children_)
|
||||||
elements.push_back(it->Render());
|
elements.push_back(it->Render());
|
||||||
@ -113,18 +203,18 @@ Element Container::HorizontalRender() {
|
|||||||
return hbox(std::move(elements));
|
return hbox(std::move(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
Element Container::TabRender() {
|
Element ContainerBase::TabRender() {
|
||||||
Component* active_child = ActiveChild();
|
Component active_child = ActiveChild();
|
||||||
if (active_child)
|
if (active_child)
|
||||||
return active_child->Render();
|
return active_child->Render();
|
||||||
return text(L"Empty container");
|
return text(L"Empty container");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Container::OnMouseEvent(Event event) {
|
bool ContainerBase::OnMouseEvent(Event event) {
|
||||||
if (selector_)
|
if (selector_)
|
||||||
return ActiveChild()->OnEvent(event);
|
return ActiveChild()->OnEvent(event);
|
||||||
|
|
||||||
for (Component* child : children_) {
|
for (Component& child : children_) {
|
||||||
if (child->OnEvent(event))
|
if (child->OnEvent(event))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -1,287 +1,293 @@
|
|||||||
#include <gtest/gtest-message.h> // for Message
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
||||||
#include <memory> // for allocator
|
#include <memory> // for __shared_ptr_access, shared_ptr, allocator
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/container.hpp"
|
#include "ftxui/component/container.hpp"
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "gtest/gtest_pred_impl.h" // for AssertionResult, EXPECT_EQ, EXPECT_FALSE, EXPECT_TRUE, Test, TEST
|
||||||
#include "gtest/gtest_pred_impl.h" // for AssertionResult, EXPECT_EQ, EXPEC...
|
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
TEST(ContainerTest, HorizontalEvent) {
|
TEST(ContainerTest, HorizontalEvent) {
|
||||||
auto container = Container::Horizontal();
|
auto container = ContainerBase::Horizontal();
|
||||||
Component c0, c1, c2;
|
auto c0 = Container::Horizontal({});
|
||||||
container.Add(&c0);
|
auto c1 = Container::Horizontal({});
|
||||||
container.Add(&c1);
|
auto c2 = Container::Horizontal({});
|
||||||
container.Add(&c2);
|
container->Add(c0);
|
||||||
|
container->Add(c1);
|
||||||
|
container->Add(c2);
|
||||||
|
|
||||||
// With arrow key.
|
// With arrow key.
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowRight);
|
container->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::ArrowRight);
|
container->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::ArrowRight);
|
container->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::ArrowLeft);
|
container->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::ArrowLeft);
|
container->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowLeft);
|
container->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With arrow key in the wrong dimension.
|
// With arrow key in the wrong dimension.
|
||||||
container.OnEvent(Event::ArrowUp);
|
container->OnEvent(Event::ArrowUp);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowDown);
|
container->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With vim like characters.
|
// With vim like characters.
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('l'));
|
container->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Character('l'));
|
container->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Character('l'));
|
container->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Character('h'));
|
container->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Character('h'));
|
container->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('h'));
|
container->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With vim like characters in the wrong direction.
|
// With vim like characters in the wrong direction.
|
||||||
container.OnEvent(Event::Character('j'));
|
container->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('k'));
|
container->OnEvent(Event::Character('k'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With tab characters.
|
// With tab characters.
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ContainerTest, VerticalEvent) {
|
TEST(ContainerTest, VerticalEvent) {
|
||||||
auto container = Container::Vertical();
|
auto container = ContainerBase::Vertical();
|
||||||
Component c0, c1, c2;
|
auto c0 = Container::Horizontal({});
|
||||||
container.Add(&c0);
|
auto c1 = Container::Horizontal({});
|
||||||
container.Add(&c1);
|
auto c2 = Container::Horizontal({});
|
||||||
container.Add(&c2);
|
container->Add(c0);
|
||||||
|
container->Add(c1);
|
||||||
|
container->Add(c2);
|
||||||
|
|
||||||
// With arrow key.
|
// With arrow key.
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowDown);
|
container->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::ArrowDown);
|
container->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::ArrowDown);
|
container->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::ArrowUp);
|
container->OnEvent(Event::ArrowUp);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::ArrowUp);
|
container->OnEvent(Event::ArrowUp);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowUp);
|
container->OnEvent(Event::ArrowUp);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With arrow key in the wrong dimension.
|
// With arrow key in the wrong dimension.
|
||||||
container.OnEvent(Event::ArrowLeft);
|
container->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::ArrowRight);
|
container->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With vim like characters.
|
// With vim like characters.
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('j'));
|
container->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Character('j'));
|
container->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Character('j'));
|
container->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Character('k'));
|
container->OnEvent(Event::Character('k'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Character('k'));
|
container->OnEvent(Event::Character('k'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('k'));
|
container->OnEvent(Event::Character('k'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With vim like characters in the wrong direction.
|
// With vim like characters in the wrong direction.
|
||||||
container.OnEvent(Event::Character('h'));
|
container->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Character('l'));
|
container->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
|
|
||||||
// With tab characters.
|
// With tab characters.
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::Tab);
|
container->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
container.OnEvent(Event::TabReverse);
|
container->OnEvent(Event::TabReverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ContainerTest, SetActiveChild) {
|
TEST(ContainerTest, SetActiveChild) {
|
||||||
auto container = Container::Horizontal();
|
auto container = ContainerBase::Horizontal();
|
||||||
Component c0, c1, c2;
|
auto c0 = Container::Horizontal({});
|
||||||
container.Add(&c0);
|
auto c1 = Container::Horizontal({});
|
||||||
container.Add(&c1);
|
auto c2 = Container::Horizontal({});
|
||||||
container.Add(&c2);
|
container->Add(c0);
|
||||||
|
container->Add(c1);
|
||||||
|
container->Add(c2);
|
||||||
|
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
EXPECT_TRUE(c0.Focused());
|
EXPECT_TRUE(c0->Focused());
|
||||||
EXPECT_TRUE(c0.Active());
|
EXPECT_TRUE(c0->Active());
|
||||||
EXPECT_FALSE(c1.Focused());
|
EXPECT_FALSE(c1->Focused());
|
||||||
EXPECT_FALSE(c1.Active());
|
EXPECT_FALSE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
|
|
||||||
container.SetActiveChild(&c0);
|
container->SetActiveChild(c0);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
EXPECT_TRUE(c0.Focused());
|
EXPECT_TRUE(c0->Focused());
|
||||||
EXPECT_TRUE(c0.Active());
|
EXPECT_TRUE(c0->Active());
|
||||||
EXPECT_FALSE(c1.Focused());
|
EXPECT_FALSE(c1->Focused());
|
||||||
EXPECT_FALSE(c1.Active());
|
EXPECT_FALSE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
|
|
||||||
container.SetActiveChild(&c1);
|
container->SetActiveChild(c1);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c1);
|
EXPECT_EQ(container->ActiveChild(), c1);
|
||||||
EXPECT_FALSE(c0.Focused());
|
EXPECT_FALSE(c0->Focused());
|
||||||
EXPECT_FALSE(c0.Active());
|
EXPECT_FALSE(c0->Active());
|
||||||
EXPECT_TRUE(c1.Focused());
|
EXPECT_TRUE(c1->Focused());
|
||||||
EXPECT_TRUE(c1.Active());
|
EXPECT_TRUE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
|
|
||||||
container.SetActiveChild(&c2);
|
container->SetActiveChild(c2);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c2);
|
EXPECT_EQ(container->ActiveChild(), c2);
|
||||||
EXPECT_FALSE(c0.Focused());
|
EXPECT_FALSE(c0->Focused());
|
||||||
EXPECT_FALSE(c0.Active());
|
EXPECT_FALSE(c0->Active());
|
||||||
EXPECT_FALSE(c1.Focused());
|
EXPECT_FALSE(c1->Focused());
|
||||||
EXPECT_FALSE(c1.Active());
|
EXPECT_FALSE(c1->Active());
|
||||||
EXPECT_TRUE(c2.Focused());
|
EXPECT_TRUE(c2->Focused());
|
||||||
EXPECT_TRUE(c2.Active());
|
EXPECT_TRUE(c2->Active());
|
||||||
|
|
||||||
container.SetActiveChild(&c0);
|
container->SetActiveChild(c0);
|
||||||
EXPECT_EQ(container.ActiveChild(), &c0);
|
EXPECT_EQ(container->ActiveChild(), c0);
|
||||||
EXPECT_TRUE(c0.Focused());
|
EXPECT_TRUE(c0->Focused());
|
||||||
EXPECT_TRUE(c0.Active());
|
EXPECT_TRUE(c0->Active());
|
||||||
EXPECT_FALSE(c1.Focused());
|
EXPECT_FALSE(c1->Focused());
|
||||||
EXPECT_FALSE(c1.Active());
|
EXPECT_FALSE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ContainerTest, TakeFocus) {
|
TEST(ContainerTest, TakeFocus) {
|
||||||
auto c = Container::Horizontal();
|
auto c = ContainerBase::Horizontal();
|
||||||
auto c1 = Container::Vertical();
|
auto c1 = ContainerBase::Vertical();
|
||||||
auto c2 = Container::Vertical();
|
auto c2 = ContainerBase::Vertical();
|
||||||
auto c3 = Container::Vertical();
|
auto c3 = ContainerBase::Vertical();
|
||||||
auto c11 = Container::Horizontal();
|
auto c11 = ContainerBase::Horizontal();
|
||||||
auto c12 = Container::Horizontal();
|
auto c12 = ContainerBase::Horizontal();
|
||||||
auto c13 = Container::Horizontal();
|
auto c13 = ContainerBase::Horizontal();
|
||||||
auto c21 = Container::Horizontal();
|
auto c21 = ContainerBase::Horizontal();
|
||||||
auto c22 = Container::Horizontal();
|
auto c22 = ContainerBase::Horizontal();
|
||||||
auto c23 = Container::Horizontal();
|
auto c23 = ContainerBase::Horizontal();
|
||||||
|
|
||||||
c.Add(&c1);
|
c->Add(c1);
|
||||||
c.Add(&c2);
|
c->Add(c2);
|
||||||
c.Add(&c3);
|
c->Add(c3);
|
||||||
c1.Add(&c11);
|
c1->Add(c11);
|
||||||
c1.Add(&c12);
|
c1->Add(c12);
|
||||||
c1.Add(&c13);
|
c1->Add(c13);
|
||||||
c2.Add(&c21);
|
c2->Add(c21);
|
||||||
c2.Add(&c22);
|
c2->Add(c22);
|
||||||
c2.Add(&c23);
|
c2->Add(c23);
|
||||||
|
|
||||||
EXPECT_TRUE(c.Focused());
|
EXPECT_TRUE(c->Focused());
|
||||||
EXPECT_TRUE(c1.Focused());
|
EXPECT_TRUE(c1->Focused());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_TRUE(c11.Focused());
|
EXPECT_TRUE(c11->Focused());
|
||||||
EXPECT_FALSE(c12.Focused());
|
EXPECT_FALSE(c12->Focused());
|
||||||
EXPECT_FALSE(c13.Focused());
|
EXPECT_FALSE(c13->Focused());
|
||||||
EXPECT_FALSE(c21.Focused());
|
EXPECT_FALSE(c21->Focused());
|
||||||
EXPECT_FALSE(c22.Focused());
|
EXPECT_FALSE(c22->Focused());
|
||||||
EXPECT_FALSE(c23.Focused());
|
EXPECT_FALSE(c23->Focused());
|
||||||
EXPECT_TRUE(c.Active());
|
EXPECT_TRUE(c->Active());
|
||||||
EXPECT_TRUE(c1.Active());
|
EXPECT_TRUE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
EXPECT_TRUE(c11.Active());
|
EXPECT_TRUE(c11->Active());
|
||||||
EXPECT_FALSE(c12.Active());
|
EXPECT_FALSE(c12->Active());
|
||||||
EXPECT_FALSE(c13.Active());
|
EXPECT_FALSE(c13->Active());
|
||||||
EXPECT_TRUE(c21.Active());
|
EXPECT_TRUE(c21->Active());
|
||||||
EXPECT_FALSE(c22.Active());
|
EXPECT_FALSE(c22->Active());
|
||||||
EXPECT_FALSE(c23.Active());
|
EXPECT_FALSE(c23->Active());
|
||||||
|
|
||||||
c22.TakeFocus();
|
c22->TakeFocus();
|
||||||
EXPECT_TRUE(c.Focused());
|
EXPECT_TRUE(c->Focused());
|
||||||
EXPECT_FALSE(c1.Focused());
|
EXPECT_FALSE(c1->Focused());
|
||||||
EXPECT_TRUE(c2.Focused());
|
EXPECT_TRUE(c2->Focused());
|
||||||
EXPECT_FALSE(c11.Focused());
|
EXPECT_FALSE(c11->Focused());
|
||||||
EXPECT_FALSE(c12.Focused());
|
EXPECT_FALSE(c12->Focused());
|
||||||
EXPECT_FALSE(c13.Focused());
|
EXPECT_FALSE(c13->Focused());
|
||||||
EXPECT_FALSE(c21.Focused());
|
EXPECT_FALSE(c21->Focused());
|
||||||
EXPECT_TRUE(c22.Focused());
|
EXPECT_TRUE(c22->Focused());
|
||||||
EXPECT_FALSE(c23.Focused());
|
EXPECT_FALSE(c23->Focused());
|
||||||
EXPECT_TRUE(c.Active());
|
EXPECT_TRUE(c->Active());
|
||||||
EXPECT_FALSE(c1.Active());
|
EXPECT_FALSE(c1->Active());
|
||||||
EXPECT_TRUE(c2.Active());
|
EXPECT_TRUE(c2->Active());
|
||||||
EXPECT_TRUE(c11.Active());
|
EXPECT_TRUE(c11->Active());
|
||||||
EXPECT_FALSE(c12.Active());
|
EXPECT_FALSE(c12->Active());
|
||||||
EXPECT_FALSE(c13.Active());
|
EXPECT_FALSE(c13->Active());
|
||||||
EXPECT_FALSE(c21.Active());
|
EXPECT_FALSE(c21->Active());
|
||||||
EXPECT_TRUE(c22.Active());
|
EXPECT_TRUE(c22->Active());
|
||||||
EXPECT_FALSE(c23.Active());
|
EXPECT_FALSE(c23->Active());
|
||||||
|
|
||||||
c1.TakeFocus();
|
c1->TakeFocus();
|
||||||
EXPECT_TRUE(c.Focused());
|
EXPECT_TRUE(c->Focused());
|
||||||
EXPECT_TRUE(c1.Focused());
|
EXPECT_TRUE(c1->Focused());
|
||||||
EXPECT_FALSE(c2.Focused());
|
EXPECT_FALSE(c2->Focused());
|
||||||
EXPECT_TRUE(c11.Focused());
|
EXPECT_TRUE(c11->Focused());
|
||||||
EXPECT_FALSE(c12.Focused());
|
EXPECT_FALSE(c12->Focused());
|
||||||
EXPECT_FALSE(c13.Focused());
|
EXPECT_FALSE(c13->Focused());
|
||||||
EXPECT_FALSE(c21.Focused());
|
EXPECT_FALSE(c21->Focused());
|
||||||
EXPECT_FALSE(c22.Focused());
|
EXPECT_FALSE(c22->Focused());
|
||||||
EXPECT_FALSE(c23.Focused());
|
EXPECT_FALSE(c23->Focused());
|
||||||
EXPECT_TRUE(c.Active());
|
EXPECT_TRUE(c->Active());
|
||||||
EXPECT_TRUE(c1.Active());
|
EXPECT_TRUE(c1->Active());
|
||||||
EXPECT_FALSE(c2.Active());
|
EXPECT_FALSE(c2->Active());
|
||||||
EXPECT_TRUE(c11.Active());
|
EXPECT_TRUE(c11->Active());
|
||||||
EXPECT_FALSE(c12.Active());
|
EXPECT_FALSE(c12->Active());
|
||||||
EXPECT_FALSE(c13.Active());
|
EXPECT_FALSE(c13->Active());
|
||||||
EXPECT_FALSE(c21.Active());
|
EXPECT_FALSE(c21->Active());
|
||||||
EXPECT_TRUE(c22.Active());
|
EXPECT_TRUE(c22->Active());
|
||||||
EXPECT_FALSE(c23.Active());
|
EXPECT_FALSE(c23->Active());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include "ftxui/component/event.hpp"
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/component/mouse.hpp"
|
#include "ftxui/component/event.hpp"
|
||||||
#include "ftxui/screen/string.hpp"
|
#include "ftxui/component/mouse.hpp" // for Mouse
|
||||||
|
#include "ftxui/screen/string.hpp" // for to_wstring
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,39 +1,74 @@
|
|||||||
|
#include <algorithm> // for max, min
|
||||||
|
#include <memory> // for shared_ptr
|
||||||
|
#include <string> // for wstring, allocator, basic_string
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Custom, Event::Delete, Event::End, Event::Home, Event::Return
|
||||||
#include "ftxui/component/input.hpp"
|
#include "ftxui/component/input.hpp"
|
||||||
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
|
||||||
#include <algorithm>
|
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp"
|
|
||||||
#include "ftxui/component/mouse.hpp"
|
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
/// @brief An input box for editing text.
|
||||||
|
/// @param content The editable content.
|
||||||
|
/// @param placeholder The text displayed when content is still empty.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see InputBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::FitComponent();
|
||||||
|
/// std::wstring content= L"";
|
||||||
|
/// std::wstring placeholder = L"placeholder";
|
||||||
|
/// Component input = Input(&content, &placeholder);
|
||||||
|
/// screen.Loop(input);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// placeholder
|
||||||
|
/// ```
|
||||||
|
Component Input(StringRef content, ConstStringRef placeholder) {
|
||||||
|
return Make<InputBase>(content, placeholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
InputBase* InputBase::From(Component component) {
|
||||||
|
return static_cast<InputBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
InputBase::InputBase(StringRef content, ConstStringRef placeholder)
|
||||||
|
: content_(content), placeholder_(placeholder) {}
|
||||||
|
|
||||||
// Component implementation.
|
// Component implementation.
|
||||||
Element Input::Render() {
|
Element InputBase::Render() {
|
||||||
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
cursor_position =
|
||||||
|
std::max(0, std::min<int>(content_->size(), cursor_position));
|
||||||
auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
|
auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
|
||||||
bool is_focused = Focused();
|
bool is_focused = Focused();
|
||||||
|
|
||||||
// Placeholder.
|
// placeholder.
|
||||||
if (content.size() == 0) {
|
if (content_->size() == 0) {
|
||||||
if (is_focused)
|
if (is_focused)
|
||||||
return text(placeholder) | focus | dim | inverted | main_decorator |
|
return text(*placeholder_) | focus | dim | inverted | main_decorator |
|
||||||
reflect(input_box_);
|
reflect(input_box_);
|
||||||
else
|
else
|
||||||
return text(placeholder) | dim | main_decorator | reflect(input_box_);
|
return text(*placeholder_) | dim | main_decorator | reflect(input_box_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not focused.
|
// Not focused.
|
||||||
if (!is_focused)
|
if (!is_focused)
|
||||||
return text(content) | main_decorator | reflect(input_box_);
|
return text(*content_) | main_decorator | reflect(input_box_);
|
||||||
|
|
||||||
std::wstring part_before_cursor = content.substr(0, cursor_position);
|
std::wstring part_before_cursor = content_->substr(0, cursor_position);
|
||||||
std::wstring part_at_cursor = cursor_position < (int)content.size()
|
std::wstring part_at_cursor = cursor_position < (int)content_->size()
|
||||||
? content.substr(cursor_position, 1)
|
? content_->substr(cursor_position, 1)
|
||||||
: L" ";
|
: L" ";
|
||||||
std::wstring part_after_cursor = cursor_position < (int)content.size() - 1
|
std::wstring part_after_cursor = cursor_position < (int)content_->size() - 1
|
||||||
? content.substr(cursor_position + 1)
|
? content_->substr(cursor_position + 1)
|
||||||
: L"";
|
: L"";
|
||||||
auto focused = is_focused ? focus : select;
|
auto focused = is_focused ? focus : select;
|
||||||
|
|
||||||
@ -47,8 +82,9 @@ Element Input::Render() {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::OnEvent(Event event) {
|
bool InputBase::OnEvent(Event event) {
|
||||||
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
cursor_position =
|
||||||
|
std::max(0, std::min<int>(content_->size(), cursor_position));
|
||||||
|
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
return OnMouseEvent(event);
|
return OnMouseEvent(event);
|
||||||
@ -59,7 +95,7 @@ bool Input::OnEvent(Event event) {
|
|||||||
if (event == Event::Backspace) {
|
if (event == Event::Backspace) {
|
||||||
if (cursor_position == 0)
|
if (cursor_position == 0)
|
||||||
return false;
|
return false;
|
||||||
content.erase(cursor_position - 1, 1);
|
content_->erase(cursor_position - 1, 1);
|
||||||
cursor_position--;
|
cursor_position--;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
@ -67,9 +103,9 @@ bool Input::OnEvent(Event event) {
|
|||||||
|
|
||||||
// Delete
|
// Delete
|
||||||
if (event == Event::Delete) {
|
if (event == Event::Delete) {
|
||||||
if (cursor_position == int(content.size()))
|
if (cursor_position == int(content_->size()))
|
||||||
return false;
|
return false;
|
||||||
content.erase(cursor_position, 1);
|
content_->erase(cursor_position, 1);
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -89,7 +125,7 @@ bool Input::OnEvent(Event event) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == Event::ArrowRight && cursor_position < (int)content.size()) {
|
if (event == Event::ArrowRight && cursor_position < (int)content_->size()) {
|
||||||
cursor_position++;
|
cursor_position++;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -100,13 +136,13 @@ bool Input::OnEvent(Event event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event == Event::End) {
|
if (event == Event::End) {
|
||||||
cursor_position = (int)content.size();
|
cursor_position = (int)content_->size();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Content
|
// Content
|
||||||
if (event.is_character()) {
|
if (event.is_character()) {
|
||||||
content.insert(cursor_position, 1, event.character());
|
content_->insert(cursor_position, 1, event.character());
|
||||||
cursor_position++;
|
cursor_position++;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
@ -114,7 +150,7 @@ bool Input::OnEvent(Event event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Input::OnMouseEvent(Event event) {
|
bool InputBase::OnMouseEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
if (!input_box_.Contain(event.mouse().x, event.mouse().y))
|
if (!input_box_.Contain(event.mouse().x, event.mouse().y))
|
||||||
@ -127,7 +163,7 @@ bool Input::OnMouseEvent(Event event) {
|
|||||||
int new_cursor_position =
|
int new_cursor_position =
|
||||||
cursor_position + event.mouse().x - cursor_box_.x_min;
|
cursor_position + event.mouse().x - cursor_box_.x_min;
|
||||||
new_cursor_position =
|
new_cursor_position =
|
||||||
std::max(0, std::min<int>(content.size(), new_cursor_position));
|
std::max(0, std::min<int>(content_->size(), new_cursor_position));
|
||||||
if (cursor_position != new_cursor_position) {
|
if (cursor_position != new_cursor_position) {
|
||||||
cursor_position = new_cursor_position;
|
cursor_position = new_cursor_position;
|
||||||
on_change();
|
on_change();
|
||||||
|
@ -1,159 +1,182 @@
|
|||||||
#include "ftxui/component/input.hpp"
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include "ftxui/component/event.hpp"
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
||||||
|
#include <memory> // for __shared_ptr_access
|
||||||
|
#include <string> // for wstring, allocator
|
||||||
|
|
||||||
#include "gtest/gtest.h"
|
#include "ftxui/component/captured_mouse.hpp" // for ftxui
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Backspace, Event::Delete, Event::End, Event::Home
|
||||||
|
#include "ftxui/component/input.hpp"
|
||||||
|
#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
TEST(InputTest, Init) {
|
TEST(InputTest, Init) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
EXPECT_EQ(input.content, L"");
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0);
|
||||||
EXPECT_EQ(input.placeholder, L"");
|
|
||||||
EXPECT_EQ(input.cursor_position, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Type) {
|
TEST(InputTest, Type) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
EXPECT_EQ(input.content, L"a");
|
EXPECT_EQ(content, L"a");
|
||||||
EXPECT_EQ(input.cursor_position, 1u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
EXPECT_EQ(input.content, L"ab");
|
EXPECT_EQ(content, L"ab");
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Arrow) {
|
TEST(InputTest, Arrow) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
|
|
||||||
EXPECT_EQ(input.cursor_position, 3u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(input.cursor_position, 1u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(input.cursor_position, 0u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(input.cursor_position, 0u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowRight);
|
input->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(input.cursor_position, 1u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowRight);
|
input->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowRight);
|
input->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(input.cursor_position, 3u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowRight);
|
input->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(input.cursor_position, 3u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Insert) {
|
TEST(InputTest, Insert) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
EXPECT_EQ(input.content, L"abc");
|
EXPECT_EQ(content, L"abc");
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::Character('-'));
|
input->OnEvent(Event::Character('-'));
|
||||||
EXPECT_EQ(input.content, L"a-bc");
|
EXPECT_EQ(content, L"a-bc");
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::Character('-'));
|
input->OnEvent(Event::Character('-'));
|
||||||
EXPECT_EQ(input.content, L"a--bc");
|
EXPECT_EQ(content, L"a--bc");
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::Character('-'));
|
input->OnEvent(Event::Character('-'));
|
||||||
EXPECT_EQ(input.content, L"-a--bc");
|
EXPECT_EQ(content, L"-a--bc");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Home) {
|
TEST(InputTest, Home) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
EXPECT_EQ(input.content, L"abc");
|
EXPECT_EQ(content, L"abc");
|
||||||
|
|
||||||
EXPECT_EQ(input.cursor_position, 3u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
|
||||||
input.OnEvent(Event::Home);
|
input->OnEvent(Event::Home);
|
||||||
EXPECT_EQ(input.cursor_position, 0u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('-'));
|
input->OnEvent(Event::Character('-'));
|
||||||
EXPECT_EQ(input.content, L"-abc");
|
EXPECT_EQ(content, L"-abc");
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, End) {
|
TEST(InputTest, End) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
|
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
|
|
||||||
EXPECT_EQ(input.cursor_position, 1u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
|
||||||
input.OnEvent(Event::End);
|
input->OnEvent(Event::End);
|
||||||
EXPECT_EQ(input.cursor_position, 3u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 3u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Delete) {
|
TEST(InputTest, Delete) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
|
|
||||||
EXPECT_EQ(input.content, L"abc");
|
EXPECT_EQ(content, L"abc");
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
|
|
||||||
input.OnEvent(Event::Delete);
|
input->OnEvent(Event::Delete);
|
||||||
EXPECT_EQ(input.content, L"ab");
|
EXPECT_EQ(content, L"ab");
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
|
|
||||||
input.OnEvent(Event::Delete);
|
input->OnEvent(Event::Delete);
|
||||||
EXPECT_EQ(input.content, L"ab");
|
EXPECT_EQ(content, L"ab");
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InputTest, Backspace) {
|
TEST(InputTest, Backspace) {
|
||||||
Input input;
|
std::wstring content;
|
||||||
|
std::wstring placeholder;
|
||||||
|
Component input = Input(&content, &placeholder);
|
||||||
|
|
||||||
input.OnEvent(Event::Character('a'));
|
input->OnEvent(Event::Character('a'));
|
||||||
input.OnEvent(Event::Character('b'));
|
input->OnEvent(Event::Character('b'));
|
||||||
input.OnEvent(Event::Character('c'));
|
input->OnEvent(Event::Character('c'));
|
||||||
input.OnEvent(Event::ArrowLeft);
|
input->OnEvent(Event::ArrowLeft);
|
||||||
|
|
||||||
EXPECT_EQ(input.content, L"abc");
|
EXPECT_EQ(content, L"abc");
|
||||||
EXPECT_EQ(input.cursor_position, 2u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 2u);
|
||||||
|
|
||||||
input.OnEvent(Event::Backspace);
|
input->OnEvent(Event::Backspace);
|
||||||
EXPECT_EQ(input.content, L"ac");
|
EXPECT_EQ(content, L"ac");
|
||||||
EXPECT_EQ(input.cursor_position, 1u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 1u);
|
||||||
|
|
||||||
input.OnEvent(Event::Backspace);
|
input->OnEvent(Event::Backspace);
|
||||||
EXPECT_EQ(input.content, L"c");
|
EXPECT_EQ(content, L"c");
|
||||||
EXPECT_EQ(input.cursor_position, 0u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
|
||||||
|
|
||||||
input.OnEvent(Event::Backspace);
|
input->OnEvent(Event::Backspace);
|
||||||
EXPECT_EQ(input.content, L"c");
|
EXPECT_EQ(content, L"c");
|
||||||
EXPECT_EQ(input.cursor_position, 0u);
|
EXPECT_EQ(InputBase::From(input)->cursor_position, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
|
// the LICENSE file.
|
||||||
|
@ -1,23 +1,62 @@
|
|||||||
|
#include <stddef.h> // for size_t
|
||||||
|
#include <algorithm> // for max, min
|
||||||
|
#include <memory> // for shared_ptr, allocator_traits<>::value_type
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Return, Event::Tab, Event::TabReverse
|
||||||
#include "ftxui/component/menu.hpp"
|
#include "ftxui/component/menu.hpp"
|
||||||
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Released
|
||||||
#include <stddef.h>
|
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||||
#include <algorithm>
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp"
|
|
||||||
#include "ftxui/component/mouse.hpp"
|
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element Menu::Render() {
|
/// @brief A list of text. The focused element is selected.
|
||||||
|
/// @param entries The list of entries in the menu.
|
||||||
|
/// @param selected The index of the currently selected element.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see MenuBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
/// std::vector<std::wstring> entries = {
|
||||||
|
/// L"entry 1",
|
||||||
|
/// L"entry 2",
|
||||||
|
/// L"entry 3",
|
||||||
|
/// };
|
||||||
|
/// int selected = 0;
|
||||||
|
/// auto menu = Menu(&entries, &selected);
|
||||||
|
/// screen.Loop(menu);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// > entry 1
|
||||||
|
/// entry 2
|
||||||
|
/// entry 3
|
||||||
|
/// ```
|
||||||
|
Component Menu(const std::vector<std::wstring>* entries, int* selected) {
|
||||||
|
return Make<MenuBase>(entries, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
MenuBase* MenuBase::From(Component component) {
|
||||||
|
return static_cast<MenuBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
MenuBase::MenuBase(const std::vector<std::wstring>* entries, int* selected)
|
||||||
|
: entries_(entries), selected_(selected) {}
|
||||||
|
|
||||||
|
Element MenuBase::Render() {
|
||||||
Elements elements;
|
Elements elements;
|
||||||
bool is_menu_focused = Focused();
|
bool is_menu_focused = Focused();
|
||||||
boxes_.resize(entries.size());
|
boxes_.resize(entries_->size());
|
||||||
for (size_t i = 0; i < entries.size(); ++i) {
|
for (size_t i = 0; i < entries_->size(); ++i) {
|
||||||
bool is_focused = (focused == int(i)) && is_menu_focused;
|
bool is_focused = (focused == int(i)) && is_menu_focused;
|
||||||
bool is_selected = (selected == int(i));
|
bool is_selected = (*selected_ == int(i));
|
||||||
|
|
||||||
auto style = is_selected
|
auto style = is_selected
|
||||||
? (is_focused ? selected_focused_style : selected_style)
|
? (is_focused ? selected_focused_style : selected_style)
|
||||||
@ -26,13 +65,13 @@ Element Menu::Render() {
|
|||||||
: is_menu_focused ? focus
|
: is_menu_focused ? focus
|
||||||
: select;
|
: select;
|
||||||
auto icon = is_selected ? L"> " : L" ";
|
auto icon = is_selected ? L"> " : L" ";
|
||||||
elements.push_back(text(icon + entries[i]) | style | focus_management |
|
elements.push_back(text(icon + entries_->at(i)) | style | focus_management |
|
||||||
reflect(boxes_[i]));
|
reflect(boxes_[i]));
|
||||||
}
|
}
|
||||||
return vbox(std::move(elements));
|
return vbox(std::move(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::OnEvent(Event event) {
|
bool MenuBase::OnEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
@ -41,20 +80,20 @@ bool Menu::OnEvent(Event event) {
|
|||||||
if (!Focused())
|
if (!Focused())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int old_selected = selected;
|
int old_selected = *selected_;
|
||||||
if (event == Event::ArrowUp || event == Event::Character('k'))
|
if (event == Event::ArrowUp || event == Event::Character('k'))
|
||||||
selected--;
|
(*selected_)--;
|
||||||
if (event == Event::ArrowDown || event == Event::Character('j'))
|
if (event == Event::ArrowDown || event == Event::Character('j'))
|
||||||
selected++;
|
(*selected_)++;
|
||||||
if (event == Event::Tab && entries.size())
|
if (event == Event::Tab && entries_->size())
|
||||||
selected = (selected + 1) % entries.size();
|
*selected_ = (*selected_ + 1) % entries_->size();
|
||||||
if (event == Event::TabReverse && entries.size())
|
if (event == Event::TabReverse && entries_->size())
|
||||||
selected = (selected + entries.size() - 1) % entries.size();
|
*selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
|
||||||
|
|
||||||
selected = std::max(0, std::min(int(entries.size()) - 1, selected));
|
*selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
|
||||||
|
|
||||||
if (selected != old_selected) {
|
if (*selected_ != old_selected) {
|
||||||
focused = selected;
|
focused = *selected_;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -67,7 +106,7 @@ bool Menu::OnEvent(Event event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Menu::OnMouseEvent(Event event) {
|
bool MenuBase::OnMouseEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < boxes_.size(); ++i) {
|
for (int i = 0; i < boxes_.size(); ++i) {
|
||||||
@ -78,8 +117,8 @@ bool Menu::OnMouseEvent(Event event) {
|
|||||||
focused = i;
|
focused = i;
|
||||||
if (event.mouse().button == Mouse::Left &&
|
if (event.mouse().button == Mouse::Left &&
|
||||||
event.mouse().motion == Mouse::Released) {
|
event.mouse().motion == Mouse::Released) {
|
||||||
if (selected != i) {
|
if (*selected_ != i) {
|
||||||
selected = i;
|
*selected_ = i;
|
||||||
on_change();
|
on_change();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,36 +1,76 @@
|
|||||||
|
#include <stddef.h> // for size_t
|
||||||
|
#include <algorithm> // for max, min
|
||||||
|
#include <functional> // for function
|
||||||
|
#include <memory> // for shared_ptr, allocator_traits<>::value_type
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Return, Event::Tab, Event::TabReverse
|
||||||
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
|
||||||
#include "ftxui/component/radiobox.hpp"
|
#include "ftxui/component/radiobox.hpp"
|
||||||
|
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||||
#include <stddef.h>
|
|
||||||
#include <algorithm>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <utility>
|
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp"
|
|
||||||
#include "ftxui/component/mouse.hpp"
|
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element RadioBox::Render() {
|
/// @brief A list of element, where only one can be selected.
|
||||||
|
/// @param entries The list of entries in the list.
|
||||||
|
/// @param selected The index of the currently selected element.
|
||||||
|
/// @ingroup component
|
||||||
|
/// @see RadioboxBase
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
/// std::vector<std::wstring> entries = {
|
||||||
|
/// L"entry 1",
|
||||||
|
/// L"entry 2",
|
||||||
|
/// L"entry 3",
|
||||||
|
/// };
|
||||||
|
/// int selected = 0;
|
||||||
|
/// auto menu = Radiobox(&entries, &selected);
|
||||||
|
/// screen.Loop(menu);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// ◉ entry 1
|
||||||
|
/// ○ entry 2
|
||||||
|
/// ○ entry 3
|
||||||
|
/// ```
|
||||||
|
Component Radiobox(const std::vector<std::wstring>* entries, int* selected) {
|
||||||
|
return Make<RadioboxBase>(entries, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
RadioboxBase* RadioboxBase::From(Component component) {
|
||||||
|
return static_cast<RadioboxBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
RadioboxBase::RadioboxBase(const std::vector<std::wstring>* entries,
|
||||||
|
int* selected_)
|
||||||
|
: entries_(entries), selected_(selected_) {}
|
||||||
|
|
||||||
|
Element RadioboxBase::Render() {
|
||||||
std::vector<Element> elements;
|
std::vector<Element> elements;
|
||||||
bool is_focused = Focused();
|
bool is_focused = Focused();
|
||||||
boxes_.resize(entries.size());
|
boxes_.resize(entries_->size());
|
||||||
for (size_t i = 0; i < entries.size(); ++i) {
|
for (size_t i = 0; i < entries_->size(); ++i) {
|
||||||
auto style =
|
auto style =
|
||||||
(focused == int(i) && is_focused) ? focused_style : unfocused_style;
|
(focused == int(i) && is_focused) ? focused_style : unfocused_style;
|
||||||
auto focus_management = (focused != int(i)) ? nothing
|
auto focus_management = (focused != int(i)) ? nothing
|
||||||
: is_focused ? focus
|
: is_focused ? focus
|
||||||
: select;
|
: select;
|
||||||
|
|
||||||
const std::wstring& symbol = selected == int(i) ? checked : unchecked;
|
const std::wstring& symbol = *selected_ == int(i) ? checked : unchecked;
|
||||||
elements.push_back(hbox(text(symbol), text(entries[i]) | style) |
|
elements.push_back(hbox(text(symbol), text(entries_->at(i)) | style) |
|
||||||
focus_management | reflect(boxes_[i]));
|
focus_management | reflect(boxes_[i]));
|
||||||
}
|
}
|
||||||
return vbox(std::move(elements));
|
return vbox(std::move(elements));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RadioBox::OnEvent(Event event) {
|
bool RadioboxBase::OnEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
@ -44,12 +84,12 @@ bool RadioBox::OnEvent(Event event) {
|
|||||||
new_focused--;
|
new_focused--;
|
||||||
if (event == Event::ArrowDown || event == Event::Character('j'))
|
if (event == Event::ArrowDown || event == Event::Character('j'))
|
||||||
new_focused++;
|
new_focused++;
|
||||||
if (event == Event::Tab && entries.size())
|
if (event == Event::Tab && entries_->size())
|
||||||
new_focused = (new_focused + 1) % entries.size();
|
new_focused = (new_focused + 1) % entries_->size();
|
||||||
if (event == Event::TabReverse && entries.size())
|
if (event == Event::TabReverse && entries_->size())
|
||||||
new_focused = (new_focused + entries.size() - 1) % entries.size();
|
new_focused = (new_focused + entries_->size() - 1) % entries_->size();
|
||||||
|
|
||||||
new_focused = std::max(0, std::min(int(entries.size()) - 1, new_focused));
|
new_focused = std::max(0, std::min(int(entries_->size()) - 1, new_focused));
|
||||||
|
|
||||||
if (focused != new_focused) {
|
if (focused != new_focused) {
|
||||||
focused = new_focused;
|
focused = new_focused;
|
||||||
@ -57,14 +97,14 @@ bool RadioBox::OnEvent(Event event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (event == Event::Character(' ') || event == Event::Return) {
|
if (event == Event::Character(' ') || event == Event::Return) {
|
||||||
selected = focused;
|
*selected_ = focused;
|
||||||
on_change();
|
on_change();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RadioBox::OnMouseEvent(Event event) {
|
bool RadioboxBase::OnMouseEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < boxes_.size(); ++i) {
|
for (int i = 0; i < boxes_.size(); ++i) {
|
||||||
@ -78,8 +118,8 @@ bool RadioBox::OnMouseEvent(Event event) {
|
|||||||
event.mouse().motion == Mouse::Pressed) {
|
event.mouse().motion == Mouse::Pressed) {
|
||||||
cursor_position = i;
|
cursor_position = i;
|
||||||
TakeFocus();
|
TakeFocus();
|
||||||
if (selected != i) {
|
if (*selected_ != i) {
|
||||||
selected = i;
|
*selected_ = i;
|
||||||
on_change();
|
on_change();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#include <gtest/gtest-message.h> // for Message
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
||||||
|
#include <memory> // for __shared_ptr_access, shared_ptr
|
||||||
|
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::ArrowDown, Event::ArrowUp, Event::Tab, Event::TabReverse
|
#include "ftxui/component/event.hpp" // for Event, Event::Return, Event::ArrowDown, Event::ArrowUp, Event::Tab, Event::TabReverse
|
||||||
#include "ftxui/component/mouse.hpp" // for ftxui
|
#include "ftxui/component/mouse.hpp" // for ftxui
|
||||||
#include "ftxui/component/radiobox.hpp"
|
#include "ftxui/component/radiobox.hpp"
|
||||||
#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST
|
#include "gtest/gtest_pred_impl.h" // for EXPECT_EQ, Test, TEST
|
||||||
@ -9,76 +10,105 @@
|
|||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
TEST(RadioboxTest, Navigation) {
|
TEST(RadioboxTest, Navigation) {
|
||||||
RadioBox radiobox;
|
int selected = 0;
|
||||||
radiobox.entries = {L"1", L"2", L"3"};
|
std::vector<std::wstring> entries = {L"1", L"2", L"3"};
|
||||||
|
auto radiobox = Radiobox(&entries, &selected);
|
||||||
|
|
||||||
// With arrow key.
|
// With arrow key.
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
EXPECT_EQ(selected, 1);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
EXPECT_EQ(selected, 2);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 1);
|
||||||
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
|
||||||
// With vim like characters.
|
// With vim like characters.
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
radiobox.OnEvent(Event::Character('j'));
|
radiobox->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::Character('j'));
|
EXPECT_EQ(selected, 1);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::Character('j'));
|
||||||
radiobox.OnEvent(Event::Character('j'));
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
radiobox.OnEvent(Event::Character('k'));
|
radiobox->OnEvent(Event::Character('j'));
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::Character('k'));
|
EXPECT_EQ(selected, 2);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
radiobox->OnEvent(Event::Character('k'));
|
||||||
radiobox.OnEvent(Event::Character('k'));
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 1);
|
||||||
|
radiobox->OnEvent(Event::Character('k'));
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
radiobox->OnEvent(Event::Character('k'));
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
|
||||||
// With more entries
|
// With more entries
|
||||||
radiobox.entries = {L"1", L"2", L"3"};
|
entries = {L"1", L"2", L"3"};
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
EXPECT_EQ(selected, 1);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
radiobox.OnEvent(Event::ArrowDown);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
radiobox->OnEvent(Event::ArrowDown);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
EXPECT_EQ(selected, 2);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
radiobox.OnEvent(Event::ArrowUp);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 1);
|
||||||
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
radiobox->OnEvent(Event::ArrowUp);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
|
||||||
// With tab.
|
// With tab.
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
radiobox.OnEvent(Event::Tab);
|
radiobox->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::Tab);
|
EXPECT_EQ(selected, 1);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::Tab);
|
||||||
radiobox.OnEvent(Event::Tab);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
EXPECT_EQ(selected, 2);
|
||||||
radiobox.OnEvent(Event::Tab);
|
radiobox->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::Tab);
|
EXPECT_EQ(selected, 0);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::Tab);
|
||||||
radiobox.OnEvent(Event::TabReverse);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
radiobox.OnEvent(Event::TabReverse);
|
radiobox->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(radiobox.focused, 0);
|
radiobox->OnEvent(Event::Return);
|
||||||
radiobox.OnEvent(Event::TabReverse);
|
EXPECT_EQ(selected, 2);
|
||||||
EXPECT_EQ(radiobox.focused, 2);
|
radiobox->OnEvent(Event::TabReverse);
|
||||||
radiobox.OnEvent(Event::TabReverse);
|
radiobox->OnEvent(Event::Return);
|
||||||
EXPECT_EQ(radiobox.focused, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
radiobox.OnEvent(Event::TabReverse);
|
radiobox->OnEvent(Event::TabReverse);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 0);
|
||||||
|
radiobox->OnEvent(Event::TabReverse);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 2);
|
||||||
|
radiobox->OnEvent(Event::TabReverse);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
|
EXPECT_EQ(selected, 1);
|
||||||
|
radiobox->OnEvent(Event::TabReverse);
|
||||||
|
radiobox->OnEvent(Event::Return);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
78
src/ftxui/component/renderer.cpp
Normal file
78
src/ftxui/component/renderer.cpp
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#include <functional> // for function
|
||||||
|
#include <memory> // for __shared_ptr_access
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/component/component.hpp" // for Component, Make, Renderer
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
|
#include "ftxui/dom/elements.hpp" // for Element
|
||||||
|
|
||||||
|
namespace ftxui {
|
||||||
|
|
||||||
|
/// @brief A component rendering Element from a function.
|
||||||
|
/// @ingroup component.
|
||||||
|
class RendererBase : public ComponentBase {
|
||||||
|
public:
|
||||||
|
// Access this interface from a Component
|
||||||
|
static RendererBase* From(Component component) {
|
||||||
|
return static_cast<RendererBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor.
|
||||||
|
RendererBase(std::function<Element()> render) : render_(std::move(render)) {}
|
||||||
|
~RendererBase() override = default;
|
||||||
|
|
||||||
|
// Component implementation.
|
||||||
|
Element Render() override { return render_(); }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::function<Element()> render_;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// @brief Return a component, using |render| to render its interface.
|
||||||
|
/// @param render The function drawing the interface.
|
||||||
|
/// @ingroup component
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
/// auto renderer = Renderer([] {
|
||||||
|
/// return text(L"My interface");
|
||||||
|
/// });
|
||||||
|
/// screen.Loop(renderer);
|
||||||
|
/// ```
|
||||||
|
Component Renderer(std::function<Element()> render) {
|
||||||
|
return Make<RendererBase>(std::move(render));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Return a new Component, similar to |child|, but using |render| as the
|
||||||
|
/// Component::Render() event.
|
||||||
|
/// @param child The component to forward events to.
|
||||||
|
/// @param render The function drawing the interface.
|
||||||
|
/// @ingroup component
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
/// std::wstring label = "Click to quit";
|
||||||
|
/// auto button = Button(&label, screen.ExitLoopClosure());
|
||||||
|
/// auto renderer = Renderer(button, [&] {
|
||||||
|
/// return hbox({
|
||||||
|
/// text("A button:"),
|
||||||
|
/// button->Render(),
|
||||||
|
/// });
|
||||||
|
/// });
|
||||||
|
/// screen.Loop(renderer);
|
||||||
|
/// ```
|
||||||
|
Component Renderer(Component child, std::function<Element()> render) {
|
||||||
|
Component renderer = Renderer(std::move(render));
|
||||||
|
renderer->Add(std::move(child));
|
||||||
|
return renderer;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ftxui
|
||||||
|
|
||||||
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
|
// the LICENSE file.
|
@ -1,24 +1,23 @@
|
|||||||
#include "ftxui/component/screen_interactive.hpp"
|
|
||||||
|
|
||||||
#include <stdio.h> // for fileno, stdin
|
#include <stdio.h> // for fileno, stdin
|
||||||
#include <algorithm> // for copy, max, min
|
#include <algorithm> // for copy, max, min
|
||||||
#include <csignal> // for signal, SIGINT
|
#include <csignal> // for signal, SIGINT, SIGWINCH
|
||||||
#include <cstdlib> // for exit, NULL
|
#include <cstdlib> // for exit, NULL
|
||||||
#include <iostream> // for cout, ostream
|
#include <iostream> // for cout, ostream, basic_ostream, operator<<, endl, flush
|
||||||
#include <stack> // for stack
|
#include <stack> // for stack
|
||||||
#include <thread> // for thread
|
#include <thread> // for thread
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse, CapturedMouseInterface
|
||||||
#include "ftxui/component/component.hpp" // for Component
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/event.hpp" // for Event
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse
|
#include "ftxui/component/mouse.hpp" // for Mouse
|
||||||
#include "ftxui/component/receiver.hpp" // for ReceiverImpl
|
#include "ftxui/component/receiver.hpp" // for ReceiverImpl, SenderImpl, MakeReceiver
|
||||||
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputPa...
|
#include "ftxui/component/screen_interactive.hpp"
|
||||||
|
#include "ftxui/component/terminal_input_parser.hpp" // for TerminalInputParser
|
||||||
#include "ftxui/dom/node.hpp" // for Node, Render
|
#include "ftxui/dom/node.hpp" // for Node, Render
|
||||||
#include "ftxui/dom/requirement.hpp" // for Requirement
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
#include "ftxui/screen/terminal.hpp" // for Terminal::Dimen...
|
#include "ftxui/screen/terminal.hpp" // for Terminal::Dimensions, Terminal
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
#define DEFINE_CONSOLEV2_PROPERTIES
|
#define DEFINE_CONSOLEV2_PROPERTIES
|
||||||
@ -31,8 +30,8 @@
|
|||||||
#error Must be compiled in UNICODE mode
|
#error Must be compiled in UNICODE mode
|
||||||
#endif
|
#endif
|
||||||
#else
|
#else
|
||||||
#include <sys/select.h> // for select, FD_ISSET
|
#include <sys/select.h> // for select, FD_ISSET, FD_SET, FD_ZERO, fd_set
|
||||||
#include <termios.h> // for tcsetattr, tcge...
|
#include <termios.h> // for tcsetattr, tcgetattr, cc_t
|
||||||
#include <unistd.h> // for STDIN_FILENO, read
|
#include <unistd.h> // for STDIN_FILENO, read
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -110,7 +109,7 @@ void EventListener(std::atomic<bool>* quit, Sender<Event> out) {
|
|||||||
|
|
||||||
char c;
|
char c;
|
||||||
while (!*quit) {
|
while (!*quit) {
|
||||||
while(read(STDIN_FILENO, &c, 1), c)
|
while (read(STDIN_FILENO, &c, 1), c)
|
||||||
parser.Add(c);
|
parser.Add(c);
|
||||||
|
|
||||||
emscripten_sleep(1);
|
emscripten_sleep(1);
|
||||||
@ -278,7 +277,7 @@ CapturedMouse ScreenInteractive::CaptureMouse() {
|
|||||||
[this] { mouse_captured = false; });
|
[this] { mouse_captured = false; });
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenInteractive::Loop(Component* component) {
|
void ScreenInteractive::Loop(Component component) {
|
||||||
// Install a SIGINT handler and restore the old handler on exit.
|
// Install a SIGINT handler and restore the old handler on exit.
|
||||||
auto old_sigint_handler = std::signal(SIGINT, OnExit);
|
auto old_sigint_handler = std::signal(SIGINT, OnExit);
|
||||||
on_exit_functions.push(
|
on_exit_functions.push(
|
||||||
@ -417,7 +416,7 @@ void ScreenInteractive::Loop(Component* component) {
|
|||||||
OnExit(0);
|
OnExit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScreenInteractive::Draw(Component* component) {
|
void ScreenInteractive::Draw(Component component) {
|
||||||
auto document = component->Render();
|
auto document = component->Render();
|
||||||
int dimx = 0;
|
int dimx = 0;
|
||||||
int dimy = 0;
|
int dimy = 0;
|
||||||
|
@ -1,21 +1,23 @@
|
|||||||
#include "ftxui/component/slider.hpp"
|
#include <string> // for allocator
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include <memory>
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
#include <utility>
|
#include "ftxui/component/component.hpp" // for Make, Slider
|
||||||
|
#include "ftxui/component/component_base.hpp" // for ComponentBase
|
||||||
#include "ftxui/component/captured_mouse.hpp"
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight
|
||||||
#include "ftxui/component/mouse.hpp"
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed, Mouse::Released
|
||||||
#include "ftxui/component/screen_interactive.hpp"
|
#include "ftxui/component/screen_interactive.hpp" // for Component
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, text, color, operator|, xflex, gauge, dim, hbox, reflect, underlined, vcenter
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/color.hpp"
|
#include "ftxui/screen/color.hpp" // for Color, Color::GrayDark, Color::GrayLight
|
||||||
|
#include "ftxui/screen/string.hpp" // for StringRef
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
class SliderImpl : public Component {
|
class SliderBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
SliderImpl(std::wstring label, T* value, T min, T max, T increment)
|
SliderBase(StringRef label, T* value, T min, T max, T increment)
|
||||||
: label_(label),
|
: label_(label),
|
||||||
value_(value),
|
value_(value),
|
||||||
min_(min),
|
min_(min),
|
||||||
@ -27,7 +29,7 @@ class SliderImpl : public Component {
|
|||||||
Focused() ? color(Color::GrayLight) : color(Color::GrayDark);
|
Focused() ? color(Color::GrayLight) : color(Color::GrayDark);
|
||||||
float percent = float(*value_ - min_) / float(max_ - min_);
|
float percent = float(*value_ - min_) / float(max_ - min_);
|
||||||
return hbox({
|
return hbox({
|
||||||
text(label_) | dim | vcenter,
|
text(*label_) | dim | vcenter,
|
||||||
hbox({
|
hbox({
|
||||||
text(L"["),
|
text(L"["),
|
||||||
gauge(percent) | underlined | xflex | reflect(gauge_box_),
|
gauge(percent) | underlined | xflex | reflect(gauge_box_),
|
||||||
@ -53,7 +55,7 @@ class SliderImpl : public Component {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Component::OnEvent(event);
|
return ComponentBase::OnEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OnMouseEvent(Event event) {
|
bool OnMouseEvent(Event event) {
|
||||||
@ -62,8 +64,7 @@ class SliderImpl : public Component {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (box_.Contain(event.mouse().x, event.mouse().y) &&
|
if (box_.Contain(event.mouse().x, event.mouse().y) && CaptureMouse(event)) {
|
||||||
CaptureMouse(event)) {
|
|
||||||
TakeFocus();
|
TakeFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +85,7 @@ class SliderImpl : public Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::wstring label_;
|
StringRef label_;
|
||||||
T* value_;
|
T* value_;
|
||||||
T min_;
|
T min_;
|
||||||
T max_;
|
T max_;
|
||||||
@ -94,19 +95,40 @@ class SliderImpl : public Component {
|
|||||||
CapturedMouse captured_mouse_;
|
CapturedMouse captured_mouse_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// @brief An horizontal slider.
|
||||||
|
/// @param label The name of the slider.
|
||||||
|
/// @param value The current value of the slider.
|
||||||
|
/// @param min The minimum value.
|
||||||
|
/// @param max The maximum value.
|
||||||
|
/// @param increment The increment when used by the cursor.
|
||||||
|
/// @ingroup component
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
///
|
||||||
|
/// ```cpp
|
||||||
|
/// auto screen = ScreenInteractive::TerminalOutput();
|
||||||
|
/// int value = 50;
|
||||||
|
/// auto slider = Slider(L"Value:", &value, 0, 100, 1);
|
||||||
|
/// screen.Loop(slider);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// ### Output
|
||||||
|
///
|
||||||
|
/// ```bash
|
||||||
|
/// Value:[██████████████████████████ ]
|
||||||
|
/// ```
|
||||||
template <class T>
|
template <class T>
|
||||||
ComponentPtr Slider(std::wstring label, T* value, T min, T max, T increment) {
|
Component Slider(StringRef label, T* value, T min, T max, T increment) {
|
||||||
return std::make_unique<SliderImpl<T>>(std::move(label), value, min, max,
|
return Make<SliderBase<T>>(std::move(label), value, min, max, increment);
|
||||||
increment);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template ComponentPtr Slider(std::wstring label,
|
template Component Slider(StringRef label,
|
||||||
int* value,
|
int* value,
|
||||||
int min,
|
int min,
|
||||||
int max,
|
int max,
|
||||||
int increment);
|
int increment);
|
||||||
|
|
||||||
template ComponentPtr Slider(std::wstring label,
|
template Component Slider(StringRef label,
|
||||||
float* value,
|
float* value,
|
||||||
float min,
|
float min,
|
||||||
float max,
|
float max,
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
#include "ftxui/component/terminal_input_parser.hpp"
|
#include "ftxui/component/terminal_input_parser.hpp"
|
||||||
|
|
||||||
#include <utility>
|
#include <algorithm> // for max
|
||||||
#include "ftxui/component/event.hpp"
|
#include <memory> // for unique_ptr
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/component/event.hpp" // for Event
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -5,11 +5,12 @@
|
|||||||
#include <string> // for string
|
#include <string> // for string
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/component/event.hpp" // IWYU pragma: keep
|
#include "ftxui/component/event.hpp" // for Event (ptr only)
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse
|
#include "ftxui/component/mouse.hpp" // for Mouse
|
||||||
#include "ftxui/component/receiver.hpp" // for SenderImpl
|
#include "ftxui/component/receiver.hpp" // for Sender
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
struct Event;
|
||||||
|
|
||||||
// Parse a sequence of |char| accross |time|. Produces |Event|.
|
// Parse a sequence of |char| accross |time|. Produces |Event|.
|
||||||
class TerminalInputParser {
|
class TerminalInputParser {
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
#include <gtest/gtest-message.h> // for Message
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include <gtest/gtest-test-part.h> // for TestPartResult
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
||||||
|
#include <algorithm> // for max
|
||||||
|
#include <memory> // for unique_ptr, allocator
|
||||||
|
|
||||||
|
#include "ftxui/component/event.hpp" // for Event, Event::Escape
|
||||||
#include "ftxui/component/receiver.hpp" // for MakeReceiver, ReceiverImpl
|
#include "ftxui/component/receiver.hpp" // for MakeReceiver, ReceiverImpl
|
||||||
#include "ftxui/component/terminal_input_parser.hpp"
|
#include "ftxui/component/terminal_input_parser.hpp"
|
||||||
#include "gtest/gtest_pred_impl.h" // for AssertionResult, Test, Suite...
|
#include "gtest/gtest_pred_impl.h" // for AssertionResult, Test, EXPECT_EQ, EXPECT_TRUE, EXPECT_FALSE, TEST
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
|
@ -1,26 +1,38 @@
|
|||||||
#include <stddef.h> // for size_t
|
#include <stddef.h> // for size_t
|
||||||
#include <algorithm> // for max, min
|
#include <algorithm> // for max, min
|
||||||
#include <memory> // for shared_ptr, alloca...
|
#include <memory> // for shared_ptr, allocator_traits<>::value_type
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
#include "ftxui/component/captured_mouse.hpp" // for CapturedMouse
|
||||||
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
|
||||||
#include "ftxui/component/screen_interactive.hpp" // for ScreenInteractive
|
#include "ftxui/component/mouse.hpp" // for Mouse, Mouse::Left, Mouse::Pressed
|
||||||
#include "ftxui/component/toggle.hpp"
|
#include "ftxui/component/toggle.hpp"
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element Toggle::Render() {
|
Component Toggle(const std::vector<std::wstring>* entries, int* selected) {
|
||||||
|
return Make<ToggleBase>(entries, selected);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
ToggleBase* ToggleBase::From(Component component) {
|
||||||
|
return static_cast<ToggleBase*>(component.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
ToggleBase::ToggleBase(const std::vector<std::wstring>* entries, int* selected)
|
||||||
|
: entries_(entries), selected_(selected) {}
|
||||||
|
|
||||||
|
Element ToggleBase::Render() {
|
||||||
Elements children;
|
Elements children;
|
||||||
bool is_toggle_focused = Focused();
|
bool is_toggle_focused = Focused();
|
||||||
boxes_.resize(entries.size());
|
boxes_.resize(entries_->size());
|
||||||
for (size_t i = 0; i < entries.size(); ++i) {
|
for (size_t i = 0; i < entries_->size(); ++i) {
|
||||||
// Separator.
|
// Separator.
|
||||||
if (i != 0)
|
if (i != 0)
|
||||||
children.push_back(separator());
|
children.push_back(separator());
|
||||||
|
|
||||||
bool is_focused = (focused == int(i)) && is_toggle_focused;
|
bool is_focused = (focused == int(i)) && is_toggle_focused;
|
||||||
bool is_selected = (selected == int(i));
|
bool is_selected = (*selected_ == int(i));
|
||||||
|
|
||||||
auto style = is_selected
|
auto style = is_selected
|
||||||
? (is_focused ? selected_focused_style : selected_style)
|
? (is_focused ? selected_focused_style : selected_style)
|
||||||
@ -28,30 +40,30 @@ Element Toggle::Render() {
|
|||||||
auto focus_management = !is_selected ? nothing
|
auto focus_management = !is_selected ? nothing
|
||||||
: is_toggle_focused ? focus
|
: is_toggle_focused ? focus
|
||||||
: select;
|
: select;
|
||||||
children.push_back(text(entries[i]) | style | focus_management |
|
children.push_back(text(entries_->at(i)) | style | focus_management |
|
||||||
reflect(boxes_[i]));
|
reflect(boxes_[i]));
|
||||||
}
|
}
|
||||||
return hbox(std::move(children));
|
return hbox(std::move(children));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toggle::OnEvent(Event event) {
|
bool ToggleBase::OnEvent(Event event) {
|
||||||
if (event.is_mouse())
|
if (event.is_mouse())
|
||||||
return OnMouseEvent(event);
|
return OnMouseEvent(event);
|
||||||
|
|
||||||
int old_selected = selected;
|
int old_selected = *selected_;
|
||||||
if (event == Event::ArrowLeft || event == Event::Character('h'))
|
if (event == Event::ArrowLeft || event == Event::Character('h'))
|
||||||
selected--;
|
(*selected_)--;
|
||||||
if (event == Event::ArrowRight || event == Event::Character('l'))
|
if (event == Event::ArrowRight || event == Event::Character('l'))
|
||||||
selected++;
|
(*selected_)++;
|
||||||
if (event == Event::Tab && entries.size())
|
if (event == Event::Tab && entries_->size())
|
||||||
selected = (selected + 1) % entries.size();
|
*selected_ = (*selected_ + 1) % entries_->size();
|
||||||
if (event == Event::TabReverse && entries.size())
|
if (event == Event::TabReverse && entries_->size())
|
||||||
selected = (selected + entries.size() - 1) % entries.size();
|
*selected_ = (*selected_ + entries_->size() - 1) % entries_->size();
|
||||||
|
|
||||||
selected = std::max(0, std::min(int(entries.size()) - 1, selected));
|
*selected_ = std::max(0, std::min(int(entries_->size()) - 1, *selected_));
|
||||||
|
|
||||||
if (old_selected != selected) {
|
if (old_selected != *selected_) {
|
||||||
focused = selected;
|
focused = *selected_;
|
||||||
on_change();
|
on_change();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -64,7 +76,7 @@ bool Toggle::OnEvent(Event event) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Toggle::OnMouseEvent(Event event) {
|
bool ToggleBase::OnMouseEvent(Event event) {
|
||||||
if (!CaptureMouse(event))
|
if (!CaptureMouse(event))
|
||||||
return false;
|
return false;
|
||||||
for (int i = 0; i < boxes_.size(); ++i) {
|
for (int i = 0; i < boxes_.size(); ++i) {
|
||||||
@ -76,8 +88,8 @@ bool Toggle::OnMouseEvent(Event event) {
|
|||||||
if (event.mouse().button == Mouse::Left &&
|
if (event.mouse().button == Mouse::Left &&
|
||||||
event.mouse().motion == Mouse::Pressed) {
|
event.mouse().motion == Mouse::Pressed) {
|
||||||
TakeFocus();
|
TakeFocus();
|
||||||
if (selected != i) {
|
if (*selected_ != i) {
|
||||||
selected = i;
|
*selected_ = i;
|
||||||
on_change();
|
on_change();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <gtest/gtest-message.h> // for Message
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
#include <gtest/gtest-test-part.h> // for TestPartResult, SuiteApiResolver, TestFactoryImpl
|
||||||
|
#include <memory> // for __shared_ptr_access, shared_ptr
|
||||||
|
|
||||||
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
|
#include "ftxui/component/event.hpp" // for Event, Event::ArrowLeft, Event::ArrowRight, Event::Return, Event::Tab, Event::TabReverse
|
||||||
#include "ftxui/component/mouse.hpp" // for ftxui
|
#include "ftxui/component/mouse.hpp" // for ftxui
|
||||||
@ -9,131 +10,136 @@
|
|||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
TEST(ToggleTest, leftRightArrow) {
|
TEST(ToggleTest, leftRightArrow) {
|
||||||
Toggle toggle;
|
std::vector<std::wstring> entries = {L"On", L"Off"};
|
||||||
|
int selected = 0;
|
||||||
|
auto toggle = Toggle(&entries, &selected);
|
||||||
|
|
||||||
// With arrow key.
|
// With arrow key.
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::ArrowRight);
|
toggle->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::ArrowRight);
|
toggle->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::ArrowLeft);
|
toggle->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::ArrowLeft);
|
toggle->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
|
|
||||||
// With vim like characters.
|
// With vim like characters.
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::Character('l'));
|
toggle->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::Character('l'));
|
toggle->OnEvent(Event::Character('l'));
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::Character('h'));
|
toggle->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::Character('h'));
|
toggle->OnEvent(Event::Character('h'));
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
|
|
||||||
// With more entries
|
// With more entries
|
||||||
toggle.entries = {L"1", L"2", L"3"};
|
entries = {L"1", L"2", L"3"};
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::ArrowRight);
|
toggle->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::ArrowRight);
|
toggle->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(toggle.selected, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
toggle.OnEvent(Event::ArrowRight);
|
toggle->OnEvent(Event::ArrowRight);
|
||||||
EXPECT_EQ(toggle.selected, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
toggle.OnEvent(Event::ArrowLeft);
|
toggle->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::ArrowLeft);
|
toggle->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::ArrowLeft);
|
toggle->OnEvent(Event::ArrowLeft);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ToggleTest, Tab) {
|
TEST(ToggleTest, Tab) {
|
||||||
Toggle toggle;
|
std::vector<std::wstring> entries = {L"1", L"2", L"3"};
|
||||||
toggle.entries = {L"1", L"2", L"3"};
|
int selected = 0;
|
||||||
|
auto toggle = Toggle(&entries, &selected);
|
||||||
|
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::Tab);
|
toggle->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::Tab);
|
toggle->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(toggle.selected, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
toggle.OnEvent(Event::Tab);
|
toggle->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::Tab);
|
toggle->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::Tab);
|
toggle->OnEvent(Event::Tab);
|
||||||
EXPECT_EQ(toggle.selected, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
toggle.OnEvent(Event::TabReverse);
|
toggle->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::TabReverse);
|
toggle->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(toggle.selected, 0);
|
EXPECT_EQ(selected, 0);
|
||||||
toggle.OnEvent(Event::TabReverse);
|
toggle->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(toggle.selected, 2);
|
EXPECT_EQ(selected, 2);
|
||||||
toggle.OnEvent(Event::TabReverse);
|
toggle->OnEvent(Event::TabReverse);
|
||||||
EXPECT_EQ(toggle.selected, 1);
|
EXPECT_EQ(selected, 1);
|
||||||
toggle.OnEvent(Event::TabReverse);
|
toggle->OnEvent(Event::TabReverse);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ToggleTest, OnChange) {
|
TEST(ToggleTest, OnChange) {
|
||||||
Toggle toggle;
|
std::vector<std::wstring> entries = {L"1", L"2", L"3"};
|
||||||
toggle.entries = {L"1", L"2", L"3"};
|
int selected = 0;
|
||||||
|
auto toggle = Toggle(&entries, &selected);
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
toggle.on_change = [&] { counter++; };
|
ToggleBase::From(toggle)->on_change = [&] { counter++; };
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
|
||||||
EXPECT_EQ(counter, 0);
|
EXPECT_EQ(counter, 0);
|
||||||
|
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [0] -> [1]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [0] -> [1]
|
||||||
EXPECT_EQ(counter, 1);
|
EXPECT_EQ(counter, 1);
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [1] -> [2]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [1] -> [2]
|
||||||
EXPECT_EQ(counter, 2);
|
EXPECT_EQ(counter, 2);
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowRight)); // Reached far right.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowRight)); // Reached far right.
|
||||||
EXPECT_EQ(counter, 2);
|
EXPECT_EQ(counter, 2);
|
||||||
|
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [2] -> [1]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [2] -> [1]
|
||||||
EXPECT_EQ(counter, 3);
|
EXPECT_EQ(counter, 3);
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [1] -> [0]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [1] -> [0]
|
||||||
EXPECT_EQ(counter, 4);
|
EXPECT_EQ(counter, 4);
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
|
||||||
EXPECT_EQ(counter, 4);
|
EXPECT_EQ(counter, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(ToggleTest, OnEnter) {
|
TEST(ToggleTest, OnEnter) {
|
||||||
Toggle toggle;
|
std::vector<std::wstring> entries = {L"1", L"2", L"3"};
|
||||||
toggle.entries = {L"1", L"2", L"3"};
|
int selected = 0;
|
||||||
|
auto toggle = Toggle(&entries, &selected);
|
||||||
|
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
toggle.on_enter = [&] { counter++; };
|
ToggleBase::From(toggle)->on_enter = [&] { counter++; };
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 1);
|
EXPECT_EQ(counter, 1);
|
||||||
|
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [0] -> [1]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [0] -> [1]
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 2);
|
EXPECT_EQ(counter, 2);
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowRight)); // [1] -> [2]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowRight)); // [1] -> [2]
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 3);
|
EXPECT_EQ(counter, 3);
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowRight)); // Reached far right.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowRight)); // Reached far right.
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 4);
|
EXPECT_EQ(counter, 4);
|
||||||
|
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [2] -> [1]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [2] -> [1]
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 5);
|
EXPECT_EQ(counter, 5);
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::ArrowLeft)); // [1] -> [0]
|
EXPECT_TRUE(toggle->OnEvent(Event::ArrowLeft)); // [1] -> [0]
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 6);
|
EXPECT_EQ(counter, 6);
|
||||||
|
|
||||||
EXPECT_FALSE(toggle.OnEvent(Event::ArrowLeft)); // Reached far left.
|
EXPECT_FALSE(toggle->OnEvent(Event::ArrowLeft)); // Reached far left.
|
||||||
EXPECT_TRUE(toggle.OnEvent(Event::Return));
|
EXPECT_TRUE(toggle->OnEvent(Event::Return));
|
||||||
EXPECT_EQ(counter, 7);
|
EXPECT_EQ(counter, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, blink
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, bold
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <iterator> // for begin, end
|
#include <iterator> // for begin, end
|
||||||
#include <memory> // for make_shared, __shared_ptr_access
|
#include <memory> // for make_shared, __shared_ptr_access
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, Elements, border, borderWith, window
|
#include "ftxui/dom/elements.hpp" // for unpack, Element, Decorator, Elements, border, borderWith, window
|
||||||
#include "ftxui/dom/node.hpp" // for Node
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, clear_under
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Decorator, Elements, bgcolor, color
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/color.hpp"
|
#include "ftxui/screen/color.hpp" // for Color
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include <utility> // for move
|
||||||
|
|
||||||
|
#include "ftxui/dom/elements.hpp" // for Element, filler, operator|, hbox, flex_grow, vbox, xflex_grow, yflex_grow, align_right, center, hcenter, vcenter
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, dim
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared, __shared_ptr_access
|
||||||
#include <vector>
|
#include <utility> // for move
|
||||||
|
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, filler, flex, flex_grow, flex_shrink, notflex, xflex, xflex_grow, xflex_shrink, yflex, yflex_grow, yflex_shrink
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/requirement.hpp"
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <algorithm> // for max, min
|
#include <algorithm> // for max, min
|
||||||
#include <memory> // for make_shared, shared_ptr, __shared_ptr_access
|
#include <memory> // for make_shared, shared_ptr, __shared_ptr_access
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for Element, unpack, focus, frame, select, xframe, yframe
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, focus, frame, select, xframe, yframe
|
||||||
#include "ftxui/dom/node.hpp" // for Node
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, gauge
|
||||||
#include "ftxui/dom/requirement.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/screen.hpp" // for Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
#include <utility>
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, inverted
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include <memory> // for __shared_ptr_access
|
#include <memory> // for __shared_ptr_access
|
||||||
#include <vector> // for vector
|
#include <vector> // for __alloc_traits<>::value_type, vector
|
||||||
|
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node_decorator.hpp"
|
||||||
#include "ftxui/dom/requirement.hpp" // for Requirement
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared, __shared_ptr_access
|
||||||
#include <utility>
|
#include <utility> // for move
|
||||||
#include <vector>
|
#include <vector> // for __alloc_traits<>::value_type, vector
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Decorator, reflect
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/dom/requirement.hpp"
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, separator
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/requirement.hpp" // for Requirement
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <algorithm> // for min, max
|
#include <algorithm> // for min, max
|
||||||
#include <memory> // for make_shared, __shared_ptr_access
|
#include <memory> // for make_shared, __shared_ptr_access
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
#include <vector> // for vector
|
#include <vector> // for __alloc_traits<>::value_type, vector
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size
|
#include "ftxui/dom/elements.hpp" // for Constraint, Direction, EQUAL, GREATER_THAN, LESS_THAN, WIDTH, unpack, Decorator, Element, size
|
||||||
#include "ftxui/dom/node.hpp" // for Node
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
|
@ -1,9 +1,10 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h> // for size_t
|
||||||
#include <memory>
|
#include <memory> // for allocator, allocator_traits<>::value_type
|
||||||
#include <string>
|
#include <string> // for basic_string, wstring
|
||||||
#include <vector>
|
#include <utility> // for move
|
||||||
|
#include <vector> // for vector, __alloc_traits<>::value_type
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, gauge, text, vbox, spinner
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
#include <gtest/gtest-message.h> // for Message
|
#include <gtest/gtest-message.h> // for Message
|
||||||
#include <gtest/gtest-test-part.h> // for TestPartResult
|
#include <gtest/gtest-test-part.h> // for SuiteApiResolver, TestFactoryImpl, TestPartResult
|
||||||
#include <memory> // for allocator
|
#include <memory> // for allocator
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, border
|
#include "ftxui/dom/elements.hpp" // for text, Element, operator|, border
|
||||||
|
#include "ftxui/dom/node.hpp" // for Render
|
||||||
#include "ftxui/screen/box.hpp" // for ftxui
|
#include "ftxui/screen/box.hpp" // for ftxui
|
||||||
#include "ftxui/screen/screen.hpp" // for Screen
|
#include "ftxui/screen/screen.hpp" // for Screen
|
||||||
#include "gtest/gtest_pred_impl.h" // for Test, SuiteApiResolver, EXPECT_EQ
|
#include "gtest/gtest_pred_impl.h" // for Test, EXPECT_EQ, TEST
|
||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
#include <memory>
|
#include <memory> // for make_shared
|
||||||
#include <utility>
|
#include <utility> // for move
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
#include "ftxui/dom/elements.hpp" // for Element, unpack, Elements, underlined
|
||||||
#include "ftxui/dom/node_decorator.hpp"
|
#include "ftxui/dom/node.hpp" // for Node
|
||||||
#include "ftxui/screen/box.hpp"
|
#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include "ftxui/screen/box.hpp" // for Box
|
||||||
|
#include "ftxui/screen/screen.hpp" // for Pixel, Screen
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include <functional> // for function
|
#include <functional> // for function
|
||||||
#include <utility> // for move
|
#include <utility> // for move
|
||||||
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for Decorator, Element, Elements, operator|, nothing
|
#include "ftxui/dom/elements.hpp" // for Decorator, Element, Elements, operator|, nothing
|
||||||
|
|
||||||
|
@ -25,6 +25,30 @@ std::wstring to_wstring(const std::string& s) {
|
|||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
StringRef::StringRef(std::wstring& ref) : borrowed_(&ref) {}
|
||||||
|
StringRef::StringRef(std::wstring* ref) : borrowed_(ref) {}
|
||||||
|
StringRef::StringRef(const wchar_t* ref) : owned_(ref) {}
|
||||||
|
StringRef::StringRef(const char* ref) : owned_(to_wstring(std::string(ref))) {}
|
||||||
|
std::wstring& StringRef::operator*() {
|
||||||
|
return borrowed_ ? *borrowed_ : owned_;
|
||||||
|
}
|
||||||
|
std::wstring* StringRef::operator->() {
|
||||||
|
return borrowed_ ? borrowed_ : &owned_;
|
||||||
|
}
|
||||||
|
|
||||||
|
ConstStringRef::ConstStringRef(const std::wstring& ref) : borrowed_(&ref) {}
|
||||||
|
ConstStringRef::ConstStringRef(const std::wstring* ref) : borrowed_(ref) {}
|
||||||
|
ConstStringRef::ConstStringRef(const wchar_t* ref) : owned_(ref) {}
|
||||||
|
ConstStringRef::ConstStringRef(const char* ref)
|
||||||
|
: owned_(to_wstring(std::string(ref))) {}
|
||||||
|
|
||||||
|
const std::wstring& ConstStringRef::operator*() {
|
||||||
|
return borrowed_ ? *borrowed_ : owned_;
|
||||||
|
}
|
||||||
|
const std::wstring* ConstStringRef::operator->() {
|
||||||
|
return borrowed_ ? borrowed_ : &owned_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -6,6 +6,8 @@ mkdir -p iwyu
|
|||||||
cd iwyu
|
cd iwyu
|
||||||
rm * -rf
|
rm * -rf
|
||||||
echo $CMAKE_CXX_INCLUDE_WHAT_YOU_USE
|
echo $CMAKE_CXX_INCLUDE_WHAT_YOU_USE
|
||||||
cmake .. -DFTXUI_BUILD_TESTS=ON -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="iwyu;-Xiwyu;--cxx17ns;-Xiwyu;--mapping_file=${mapping_dir}/iwyu.imp;-Xiwyu;--verbose=3"
|
cmake .. -DFTXUI_BUILD_TESTS=ON -DCMAKE_CXX_INCLUDE_WHAT_YOU_USE="include-what-you-use;-Xiwyu;--cxx17ns;-Xiwyu;--mapping_file=${mapping_dir}/iwyu.imp;-Xiwyu;--verbose=3"
|
||||||
make -j 2>out
|
make -j 2>out
|
||||||
fix_include --comments < out
|
fix_includes.py --comments < out
|
||||||
|
|
||||||
|
../tools/format.sh
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2021 Arthur Sonzogni. All rights reserved.
|
||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
|
Loading…
Reference in New Issue
Block a user