mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-25 20:27:31 +08:00
Improve the documentation.
This commit is contained in:
parent
58287c147a
commit
9fdf235836
213
doc/mainpage.md
213
doc/mainpage.md
@ -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,30 +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.
|
|
||||||
|
|
||||||
|
|
||||||
**List of Component**
|
|
||||||
|
|
||||||
You only need one header: ftxui/dom/component.hpp
|
|
||||||
|
|
||||||
\include ftxui/component/component.hpp
|
|
||||||
|
|
||||||
# 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.
|
||||||
@ -226,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
|
||||||
@ -369,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
|
||||||
@ -377,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>
|
||||||
@ -385,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>
|
||||||
@ -393,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>
|
||||||
@ -401,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>
|
||||||
@ -409,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
|
|
||||||
~~~
|
|
||||||
|
@ -32,11 +32,11 @@ Component Renderer(std::function<Element()>);
|
|||||||
template <class T> // T = {int, float}
|
template <class T> // T = {int, float}
|
||||||
Component Slider(std::wstring label, T* value, T min, T max, T increment);
|
Component Slider(std::wstring label, T* value, T min, T max, T increment);
|
||||||
|
|
||||||
// namespace Component {
|
namespace Container {
|
||||||
// Component Vertical(Components children);
|
Component Vertical(Components children);
|
||||||
// Component Horizontal(Components children);
|
Component Horizontal(Components children);
|
||||||
// Component Tab(int* selector, Components children);
|
Component Tab(int* selector, Components children);
|
||||||
//} // namespace Component
|
} // namespace Container
|
||||||
|
|
||||||
}; // namespace ftxui
|
}; // namespace ftxui
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
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 ComponentBase {
|
class ContainerBase : public ComponentBase {
|
||||||
public:
|
public:
|
||||||
static Component Vertical();
|
static Component Vertical();
|
||||||
static Component Vertical(Components children);
|
static Component Vertical(Components children);
|
||||||
@ -20,7 +20,7 @@ class Container : public ComponentBase {
|
|||||||
static Component Tab(int* selector);
|
static Component Tab(int* selector);
|
||||||
static Component Tab(int* selector, Components children);
|
static Component Tab(int* selector, Components children);
|
||||||
|
|
||||||
~Container() override = default;
|
~ContainerBase() override = default;
|
||||||
|
|
||||||
// Component override.
|
// Component override.
|
||||||
bool OnEvent(Event event) override;
|
bool OnEvent(Event event) override;
|
||||||
@ -30,13 +30,13 @@ class Container : public ComponentBase {
|
|||||||
|
|
||||||
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();
|
||||||
|
@ -9,65 +9,120 @@
|
|||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Component ContainerVertical(Components children) {
|
namespace Container {
|
||||||
return Container::Vertical(std::move(children));
|
|
||||||
|
/// @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));
|
||||||
}
|
}
|
||||||
|
|
||||||
Component ContainerHorizontal(Components children) {
|
/// @brief A list of components, drawn one by one horizontally and navigated
|
||||||
return Container::Horizontal(std::move(children));
|
/// 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));
|
||||||
}
|
}
|
||||||
|
|
||||||
Component ContainerTab(int* selector, Components children) {
|
/// @brief A list of components, where only one is drawn and interacted with at
|
||||||
return Container::Tab(selector, std::move(children));
|
/// 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
|
||||||
Component Container::Vertical() {
|
Component ContainerBase::Vertical() {
|
||||||
return Vertical({});
|
return Vertical({});
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Component Container::Vertical(Components children) {
|
Component ContainerBase::Vertical(Components children) {
|
||||||
auto container = std::make_shared<Container>();
|
auto container = std::make_shared<Container>();
|
||||||
container->event_handler_ = &Container::VerticalEvent;
|
container->event_handler_ = &ContainerBase::VerticalEvent;
|
||||||
container->render_handler_ = &Container::VerticalRender;
|
container->render_handler_ = &ContainerBase::VerticalRender;
|
||||||
for (Component& child : children)
|
for (Component& child : children)
|
||||||
container->Add(std::move(child));
|
container->Add(std::move(child));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Component Container::Horizontal() {
|
Component ContainerBase::Horizontal() {
|
||||||
return Horizontal({});
|
return Horizontal({});
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Component Container::Horizontal(Components children) {
|
Component ContainerBase::Horizontal(Components children) {
|
||||||
auto container = std::make_shared<Container>();
|
auto container = std::make_shared<Container>();
|
||||||
container->event_handler_ = &Container::HorizontalEvent;
|
container->event_handler_ = &ContainerBase::HorizontalEvent;
|
||||||
container->render_handler_ = &Container::HorizontalRender;
|
container->render_handler_ = &ContainerBase::HorizontalRender;
|
||||||
for (Component& child : children)
|
for (Component& child : children)
|
||||||
container->Add(std::move(child));
|
container->Add(std::move(child));
|
||||||
return container;
|
return container;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Component Container::Tab(int* selector) {
|
Component ContainerBase::Tab(int* selector) {
|
||||||
return Tab(selector, {});
|
return Tab(selector, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
Component Container::Tab(int* selector, Components children) {
|
Component ContainerBase::Tab(int* selector, Components children) {
|
||||||
auto container = std::make_shared<Container>();
|
auto container = std::make_shared<Container>();
|
||||||
container->selector_ = selector;
|
container->selector_ = selector;
|
||||||
container->event_handler_ = &Container::TabEvent;
|
container->event_handler_ = &ContainerBase::TabEvent;
|
||||||
container->render_handler_ = &Container::TabRender;
|
container->render_handler_ = &ContainerBase::TabRender;
|
||||||
for (Component& child : children)
|
for (Component& child : children)
|
||||||
container->Add(std::move(child));
|
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);
|
||||||
|
|
||||||
@ -80,7 +135,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;
|
||||||
|
|
||||||
@ -88,7 +143,7 @@ Component Container::ActiveChild() {
|
|||||||
return children_[selected % children_.size()];
|
return children_[selected % children_.size()];
|
||||||
}
|
}
|
||||||
|
|
||||||
void Container::SetActiveChild(ComponentBase* 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].get() == child) {
|
if (children_[i].get() == child) {
|
||||||
(selector_ ? *selector_ : selected_) = i;
|
(selector_ ? *selector_ : selected_) = i;
|
||||||
@ -97,7 +152,7 @@ void Container::SetActiveChild(ComponentBase* child) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_--;
|
||||||
@ -112,7 +167,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_--;
|
||||||
@ -127,11 +182,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());
|
||||||
@ -140,7 +195,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());
|
||||||
@ -149,14 +204,14 @@ 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);
|
||||||
|
|
||||||
|
@ -27,10 +27,43 @@ class RendererBase : public ComponentBase {
|
|||||||
std::function<Element()> render_;
|
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) {
|
Component Renderer(std::function<Element()> render) {
|
||||||
return Make<RendererBase>(std::move(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(Component child, std::function<Element()> render) {
|
||||||
Component renderer = Renderer(std::move(render));
|
Component renderer = Renderer(std::move(render));
|
||||||
renderer->Add(std::move(child));
|
renderer->Add(std::move(child));
|
||||||
|
Loading…
Reference in New Issue
Block a user