mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-22 10:40:00 +08:00
Implement a lot of new features.
This commit deserve to be cut into at least 8 sub commit. Sorry, I acknowledge this is bad... Here are the new features: * dom decorator: bold, dim, underlined, inverted. * component mechanism * components * menu * toogle
This commit is contained in:
parent
dd92b89611
commit
711b71688e
@ -1,4 +1,8 @@
|
||||
add_subdirectory(frame)
|
||||
add_subdirectory(gauge)
|
||||
add_subdirectory(menu)
|
||||
add_subdirectory(menu2)
|
||||
add_subdirectory(print_key_press)
|
||||
add_subdirectory(separator)
|
||||
add_subdirectory(vbox_hbox)
|
||||
add_subdirectory(toggle)
|
||||
|
@ -2,33 +2,47 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
using namespace ftxui::dom;
|
||||
auto document =
|
||||
hbox(
|
||||
frame(
|
||||
vbox(
|
||||
text(L"Line 1"),
|
||||
text(L"Line 2"),
|
||||
text(L"Line 3"),
|
||||
frame(
|
||||
vbox(
|
||||
text(L"Line 4"),
|
||||
text(L"Line 5"),
|
||||
text(L"Line 6")
|
||||
)
|
||||
),
|
||||
text(L"Line 7"),
|
||||
text(L"Line 8"),
|
||||
text(L"Line 9")
|
||||
)
|
||||
),
|
||||
flex()
|
||||
);
|
||||
auto document =
|
||||
hbox(
|
||||
frame(hcenter(text(L" main frame ")),
|
||||
vbox(
|
||||
text(L"Line 1"),
|
||||
text(L"Line 2"),
|
||||
text(L"Line 3"),
|
||||
frame(
|
||||
vbox(
|
||||
text(L"Line 4"),
|
||||
text(L"Line 5"),
|
||||
text(L"Line 6")
|
||||
)
|
||||
),
|
||||
hbox(
|
||||
frame(text(L"frame 2"),
|
||||
vbox(
|
||||
text(L"Line 4"),
|
||||
text(L"Line 5"),
|
||||
text(L"Line 6")
|
||||
)
|
||||
),
|
||||
frame(text(L"frame 3"),
|
||||
vbox(
|
||||
text(L"Line 7"),
|
||||
text(L"Line 8"),
|
||||
text(L"Line 9")
|
||||
)
|
||||
)
|
||||
),
|
||||
text(L"footer footer footer footer footer")
|
||||
)
|
||||
),
|
||||
flex()
|
||||
);
|
||||
auto screen = ftxui::Screen::TerminalOutput(document);
|
||||
Render(screen, document.get());
|
||||
std::cout << screen.ToString() << std::endl;
|
||||
|
@ -2,15 +2,21 @@
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
for(float percentage = 0; percentage <= 1.0; percentage+=0.001) {
|
||||
std::wstring data_downloaded =
|
||||
std::to_wstring(int(percentage * 44100)) + L"/44100";
|
||||
using namespace ftxui::dom;
|
||||
auto document =
|
||||
hbox(text(L"gauge = -"), flex(gauge(percentage)), text(L"-"));
|
||||
hbox(
|
||||
text(L"downloading:"),
|
||||
flex(gauge(percentage)),
|
||||
text(L" " + data_downloaded)
|
||||
);
|
||||
auto screen = ftxui::Screen(100, 1);
|
||||
Render(screen, document.get());
|
||||
std::cout << '\r' << screen.ToString() << std::flush;
|
||||
|
4
examples/menu/CMakeLists.txt
Normal file
4
examples/menu/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
add_executable(menu_main
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(menu_main PRIVATE ftxui)
|
21
examples/menu/main.cpp
Normal file
21
examples/menu/main.cpp
Normal file
@ -0,0 +1,21 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/screen_interactive.hpp"
|
||||
#include "ftxui/component/menu.hpp"
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
ftxui::ScreenInteractive screen(30,3);
|
||||
ftxui::component::Menu menu(screen.delegate());
|
||||
menu.entries = {
|
||||
L"entry 1",
|
||||
L"entry 2",
|
||||
L"entry 3"
|
||||
};
|
||||
menu.selected = 0;
|
||||
menu.on_enter = screen.ExitLoopClosure();
|
||||
|
||||
screen.Loop();
|
||||
}
|
4
examples/menu2/CMakeLists.txt
Normal file
4
examples/menu2/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
add_executable(menu2_main
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(menu2_main PRIVATE ftxui)
|
75
examples/menu2/main.cpp
Normal file
75
examples/menu2/main.cpp
Normal file
@ -0,0 +1,75 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/screen_interactive.hpp"
|
||||
#include "ftxui/component/menu.hpp"
|
||||
#include "ftxui/component/component_horizontal.hpp"
|
||||
#include "ftxui/component/component_vertical.hpp"
|
||||
#include "ftxui/util/string.hpp"
|
||||
|
||||
using namespace ftxui::component;
|
||||
using namespace ftxui::dom;
|
||||
|
||||
class MyComponent : ComponentHorizontal {
|
||||
public:
|
||||
MyComponent(ftxui::component::Delegate* delegate)
|
||||
: ComponentHorizontal(delegate),
|
||||
left_menu(delegate->NewChild()),
|
||||
right_menu(delegate->NewChild()) {
|
||||
left_menu.entries = {L"0%", L"10%", L"20%", L"30%", L"40%", L"50%",
|
||||
L"60%", L"70%", L"80%", L"90%"};
|
||||
right_menu.entries = {L"0%", L"1%", L"2%", L"3%", L"4%", L"5%",
|
||||
L"6%", L"7%", L"8%", L"9%", L"10%"};
|
||||
|
||||
left_menu.on_enter = [this]() { on_enter(); };
|
||||
right_menu.on_enter = [this]() { on_enter(); };
|
||||
Focus(&left_menu);
|
||||
}
|
||||
|
||||
std::function<void()> on_enter = [](){};
|
||||
private:
|
||||
Menu left_menu;
|
||||
Menu right_menu;
|
||||
|
||||
Element Render() override {
|
||||
int sum = left_menu.selected * 10 + right_menu.selected;
|
||||
return
|
||||
frame(
|
||||
vbox(
|
||||
// -------- Top panel --------------
|
||||
hbox(
|
||||
// -------- Left Menu --------------
|
||||
flex(
|
||||
vbox(
|
||||
hcenter(bold(text(L"Percentage by 10%"))),
|
||||
left_menu.Render()
|
||||
)
|
||||
),
|
||||
// -------- Right Menu --------------
|
||||
flex(
|
||||
vbox(
|
||||
hcenter(bold(text(L"Percentage by 1%"))),
|
||||
right_menu.Render()
|
||||
)
|
||||
),
|
||||
flex()
|
||||
),
|
||||
separator(),
|
||||
// -------- Bottom panel --------------
|
||||
flex(vbox(
|
||||
hbox(text(L" gauge : "), gauge(sum/100.0)),
|
||||
hbox(text(L" text : "), text(to_wstring(std::to_string(sum) + " %")))
|
||||
))
|
||||
)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
{
|
||||
ftxui::ScreenInteractive screen(60,17);
|
||||
MyComponent component(screen.delegate());
|
||||
component.on_enter = screen.ExitLoopClosure();
|
||||
screen.Loop();
|
||||
}
|
4
examples/print_key_press/CMakeLists.txt
Normal file
4
examples/print_key_press/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
add_executable(print_key_press
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(print_key_press PRIVATE ftxui)
|
44
examples/print_key_press/main.cpp
Normal file
44
examples/print_key_press/main.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/screen_interactive.hpp"
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/util/string.hpp"
|
||||
|
||||
class DrawKey : public ftxui::component::Component {
|
||||
public:
|
||||
DrawKey(ftxui::component::Delegate* delegate)
|
||||
: ftxui::component::Component(delegate) {}
|
||||
|
||||
ftxui::dom::Element Render() override {
|
||||
using namespace ftxui::dom;
|
||||
Children children;
|
||||
for (size_t i = std::max(0, (int)keys.size() - 10); i < keys.size(); ++i) {
|
||||
try {
|
||||
std::string line = std::to_string(i) + " -> " + std::to_string(keys[i]) +
|
||||
" (" + char(keys[i]) + ")";
|
||||
children.push_back(text(to_wstring(line)));
|
||||
} catch (...) {
|
||||
std::string line = std::to_string(i) + " -> " + std::to_string(keys[i]) +
|
||||
" (undefined)";
|
||||
children.push_back(text(to_wstring(line)));
|
||||
}
|
||||
}
|
||||
return vbox(std::move(children));
|
||||
}
|
||||
|
||||
bool Event(int key) override {
|
||||
keys.push_back(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<int> keys;
|
||||
};
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
ftxui::ScreenInteractive screen(80,10);
|
||||
DrawKey draw_key(screen.delegate());
|
||||
screen.Loop();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
@ -15,7 +15,7 @@ int main(int argc, const char *argv[])
|
||||
center(text(L"bottom-column"))
|
||||
))
|
||||
);
|
||||
auto screen = ftxui::Screen::WholeTerminal();
|
||||
auto screen = ftxui::Screen::TerminalFullscreen();
|
||||
Render(screen, document.get());
|
||||
|
||||
std::cout << screen.ToString();
|
||||
|
4
examples/toggle/CMakeLists.txt
Normal file
4
examples/toggle/CMakeLists.txt
Normal file
@ -0,0 +1,4 @@
|
||||
add_executable(toogle_main
|
||||
main.cpp
|
||||
)
|
||||
target_link_libraries(toogle_main PRIVATE ftxui)
|
69
examples/toggle/main.cpp
Normal file
69
examples/toggle/main.cpp
Normal file
@ -0,0 +1,69 @@
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
#include "ftxui/screen_interactive.hpp"
|
||||
#include "ftxui/component/toggle.hpp"
|
||||
#include "ftxui/component/component_horizontal.hpp"
|
||||
#include "ftxui/component/component_vertical.hpp"
|
||||
#include "ftxui/util/string.hpp"
|
||||
|
||||
using namespace ftxui::component;
|
||||
using namespace ftxui::dom;
|
||||
|
||||
class MyComponent : ComponentVertical {
|
||||
public:
|
||||
MyComponent(ftxui::component::Delegate* delegate)
|
||||
: ComponentVertical(delegate),
|
||||
toggle_1(delegate->NewChild()),
|
||||
toggle_2(delegate->NewChild()),
|
||||
toggle_3(delegate->NewChild()) {
|
||||
toggle_1.on = L"On";
|
||||
toggle_1.off = L"Off";
|
||||
|
||||
toggle_2.on = L"Enabled";
|
||||
toggle_2.off = L"Disabled";
|
||||
|
||||
toggle_3.on = L"10€";
|
||||
toggle_3.off = L"0€";
|
||||
|
||||
Focus(&toggle_1);
|
||||
}
|
||||
|
||||
std::function<void()> on_enter = []() {};
|
||||
|
||||
private:
|
||||
Toggle toggle_1;
|
||||
Toggle toggle_2;
|
||||
Toggle toggle_3;
|
||||
|
||||
Element Render() override {
|
||||
return
|
||||
vbox(
|
||||
text(L"Choose your options:"),
|
||||
text(L""),
|
||||
hbox(text(L" * Poweroff on startup : "), toggle_1.Render()),
|
||||
hbox(text(L" * Out of process : "), toggle_2.Render()),
|
||||
hbox(text(L" * Price of the information : "), toggle_3.Render())
|
||||
);
|
||||
}
|
||||
|
||||
bool Event(int key) override {
|
||||
if (ComponentVertical::Event(key))
|
||||
return true;
|
||||
|
||||
if (key == 10) {
|
||||
on_enter();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, const char* argv[]) {
|
||||
ftxui::ScreenInteractive screen(50,5);
|
||||
MyComponent component(screen.delegate());
|
||||
component.on_enter = screen.ExitLoopClosure();
|
||||
screen.Loop();
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, const char *argv[])
|
||||
@ -27,7 +27,7 @@ int main(int argc, const char *argv[])
|
||||
text(L"south-east")
|
||||
)
|
||||
);
|
||||
auto screen = ftxui::Screen::WholeTerminal();
|
||||
auto screen = ftxui::Screen::TerminalFullscreen();
|
||||
Render(screen, document.get());
|
||||
|
||||
std::cout << screen.ToString();
|
||||
|
@ -2,23 +2,32 @@ cmake_minimum_required(VERSION 3.0)
|
||||
project(ftxui)
|
||||
|
||||
add_library(ftxui
|
||||
src/ftxui/core/component.cpp
|
||||
src/ftxui/core/dom/frame.cpp
|
||||
src/ftxui/core/dom/centered.cpp
|
||||
src/ftxui/core/dom/flex.cpp
|
||||
src/ftxui/core/dom/frame.cpp
|
||||
src/ftxui/core/dom/gauge.cpp
|
||||
src/ftxui/core/dom/hbox.cpp
|
||||
src/ftxui/core/dom/node.cpp
|
||||
src/ftxui/core/dom/separator.cpp
|
||||
src/ftxui/core/dom/text.cpp
|
||||
src/ftxui/core/dom/vbox.cpp
|
||||
src/ftxui/core/screen.cpp
|
||||
src/ftxui/core/terminal.cpp
|
||||
src/ftxui/component/component.cpp
|
||||
src/ftxui/component/component_direction.cpp
|
||||
src/ftxui/component/component_horizontal.cpp
|
||||
src/ftxui/component/component_vertical.cpp
|
||||
src/ftxui/component/toggle.cpp
|
||||
src/ftxui/component/menu.cpp
|
||||
src/ftxui/dom/bold.cpp
|
||||
src/ftxui/dom/dim.cpp
|
||||
src/ftxui/dom/underlined.cpp
|
||||
src/ftxui/dom/inverted.cpp
|
||||
src/ftxui/dom/composite_decorator.cpp
|
||||
src/ftxui/dom/flex.cpp
|
||||
src/ftxui/dom/frame.cpp
|
||||
src/ftxui/dom/frame.cpp
|
||||
src/ftxui/dom/gauge.cpp
|
||||
src/ftxui/dom/hbox.cpp
|
||||
src/ftxui/dom/node.cpp
|
||||
src/ftxui/dom/separator.cpp
|
||||
src/ftxui/dom/text.cpp
|
||||
src/ftxui/dom/vbox.cpp
|
||||
src/ftxui/screen.cpp
|
||||
src/ftxui/screen_interactive.cpp
|
||||
src/ftxui/terminal.cpp
|
||||
src/ftxui/util/string.cpp
|
||||
)
|
||||
|
||||
|
||||
target_include_directories(ftxui
|
||||
PUBLIC include
|
||||
PRIVATE src
|
||||
@ -50,8 +59,9 @@ if (GTEST_FOUND AND THREADS_FOUND)
|
||||
endfunction(add_new_test)
|
||||
|
||||
add_new_test(dom_tests
|
||||
src/ftxui/core/dom/text_test.cpp
|
||||
src/ftxui/core/dom/hbox_test.cpp
|
||||
src/ftxui/core/dom/vbox_test.cpp
|
||||
src/ftxui/dom/gauge_test.cpp
|
||||
src/ftxui/dom/hbox_test.cpp
|
||||
src/ftxui/dom/text_test.cpp
|
||||
src/ftxui/dom/vbox_test.cpp
|
||||
)
|
||||
endif()
|
||||
|
@ -1 +1,31 @@
|
||||
State => Components => Document => Text.
|
||||
#
|
||||
* Level 0: terminal output.
|
||||
* Level 1: ftxui::Screen
|
||||
* Level 2: ftxui::dom::Node
|
||||
* Level 3: ftxui::component::Component
|
||||
|
||||
## Level 0: terminal output.
|
||||
The terminal you know, you can append text on it. It is represented by
|
||||
std::cout.
|
||||
|
||||
## Level 1: ftxui::Screen
|
||||
A rectangular grid of characters.
|
||||
Use Terminal::ToString() to append its content into the console.
|
||||
|
||||
## Level 2: ftxui::dom::Node
|
||||
A hierarchical set of element.
|
||||
They handle layout and Render themself on the screen.
|
||||
See ftxui/dom/elements.hpp
|
||||
|
||||
You can make implement your own.
|
||||
|
||||
## Level 3: ftxui::component::Component
|
||||
A hierarchical set of component. A component render itself by producing
|
||||
ftxui::dom::Node in Component::Render().
|
||||
|
||||
Some component can handle events:
|
||||
* keyboard
|
||||
* mouse
|
||||
* terminal event
|
||||
|
||||
You can make implement your own.
|
||||
|
34
ftxui/include/ftxui/component/Event.hpp
Normal file
34
ftxui/include/ftxui/component/Event.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FTXUI_COMPONENT_EVENT
|
||||
#define FTXUI_COMPONENT_EVENT
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
struct Event{
|
||||
// --- Character ---
|
||||
static Event Character(char);
|
||||
|
||||
// --- Arrow ---
|
||||
static Event Arrow_Left;
|
||||
static Event Arrow_Right;
|
||||
static Event Arrow_Up;
|
||||
static Event Arrow_Down;
|
||||
|
||||
// --- Other ---
|
||||
static Event Backspace;
|
||||
static Event Delete;
|
||||
static Event Escape;
|
||||
static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
|
||||
|
||||
// Internal representation.
|
||||
int values [3];
|
||||
Event(int values[3]) : values(values);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_EVENT */
|
44
ftxui/include/ftxui/component/component.hpp
Normal file
44
ftxui/include/ftxui/component/component.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
#ifndef FTXUI_COMPONENT_COMPONENT_HPP
|
||||
#define FTXUI_COMPONENT_COMPONENT_HPP
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/component/delegate.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
class Delegate;
|
||||
class Focus;
|
||||
|
||||
class Component {
|
||||
public:
|
||||
// Constructor/Destructor.
|
||||
Component(Delegate* delegate);
|
||||
virtual ~Component();
|
||||
|
||||
// Render the component.
|
||||
virtual dom::Element Render();
|
||||
|
||||
// Handle an event. By default, it calls this function on each children.
|
||||
virtual bool Event(int key);
|
||||
|
||||
// If this component contains children, this indicates which one is active. It
|
||||
// can be none of them.
|
||||
// We say an element has the focus if the chain of GetActiveChild() from the
|
||||
// root component contains this object.
|
||||
virtual Component* GetActiveChild() { return nullptr; }
|
||||
bool Active(); // True is this component is an active child.
|
||||
bool Focused(); // True if all the ancestors are active childs.
|
||||
|
||||
Component* Parent();
|
||||
Component* PreviousSibling();
|
||||
Component* NextSibling();
|
||||
|
||||
private:
|
||||
Delegate* delegate_;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HPP */
|
25
ftxui/include/ftxui/component/component_direction.hpp
Normal file
25
ftxui/include/ftxui/component/component_direction.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#ifndef FTXUI_COMPONENT_COMPONENT_DIRECTION_H_
|
||||
#define FTXUI_COMPONENT_COMPONENT_DIRECTION_H_
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
// A component where focus and events are automatically handled for you.
|
||||
class ComponentDirection : public Component {
|
||||
public:
|
||||
ComponentDirection(Delegate* delegate);
|
||||
bool Event(int key) override;
|
||||
Component* GetActiveChild() override;
|
||||
|
||||
protected:
|
||||
void Focus(Component* child);
|
||||
virtual bool HandleDirection(int key) = 0;
|
||||
Component* active_child_;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_DIRECTION_H_ */
|
20
ftxui/include/ftxui/component/component_horizontal.hpp
Normal file
20
ftxui/include/ftxui/component/component_horizontal.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef FTXUI_COMPONENT_COMPONENT_HORIZONTAL_H_
|
||||
#define FTXUI_COMPONENT_COMPONENT_HORIZONTAL_H_
|
||||
|
||||
#include "ftxui/component/component_direction.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
// A component where focus and events are automatically handled for you.
|
||||
// It assumes its children are put in the horizontal direction.
|
||||
class ComponentHorizontal : public ComponentDirection {
|
||||
public:
|
||||
ComponentHorizontal(Delegate* delegate);
|
||||
bool HandleDirection(int key) override;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_HORIZONTAL_H_ */
|
20
ftxui/include/ftxui/component/component_vertical.hpp
Normal file
20
ftxui/include/ftxui/component/component_vertical.hpp
Normal file
@ -0,0 +1,20 @@
|
||||
#ifndef FTXUI_COMPONENT_COMPONENT_VERTICAL_H_
|
||||
#define FTXUI_COMPONENT_COMPONENT_VERTICAL_H_
|
||||
|
||||
#include "ftxui/component/component_direction.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
// A component where focus and events are automatically handled for you.
|
||||
// It assumes its children are put in the vertical direction.
|
||||
class ComponentVertical : public ComponentDirection {
|
||||
public:
|
||||
ComponentVertical(Delegate* delegate);
|
||||
bool HandleDirection(int key) override;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_COMPONENT_VERTICAL_H_ */
|
34
ftxui/include/ftxui/component/delegate.hpp
Normal file
34
ftxui/include/ftxui/component/delegate.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FTXUI_COMPONENT_DELEGATE_HPP
|
||||
#define FTXUI_COMPONENT_DELEGATE_HPP
|
||||
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
class Component;
|
||||
|
||||
class Delegate {
|
||||
public:
|
||||
Delegate() {}
|
||||
virtual ~Delegate() {}
|
||||
|
||||
// A Delegate shadows a component.
|
||||
virtual void Register(Component* component) = 0;
|
||||
virtual Component* component() = 0;
|
||||
|
||||
// Create new children.
|
||||
virtual Delegate* NewChild() = 0;
|
||||
virtual std::vector<Delegate*> children() = 0;
|
||||
|
||||
// Navigate in the tree.
|
||||
virtual Delegate* PreviousSibling() = 0;
|
||||
virtual Delegate* NextSibling() = 0;
|
||||
virtual Delegate* Parent() = 0;
|
||||
virtual Delegate* Root() = 0;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_DELEGATE_HPP */
|
31
ftxui/include/ftxui/component/menu.hpp
Normal file
31
ftxui/include/ftxui/component/menu.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef FTXUI_COMPONENT_MENU
|
||||
#define FTXUI_COMPONENT_MENU
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
class Menu : public Component {
|
||||
public:
|
||||
// Constructor.
|
||||
Menu(Delegate*);
|
||||
|
||||
// State.
|
||||
std::vector<std::wstring> entries = {};
|
||||
int selected = 0;
|
||||
|
||||
// State update callback.
|
||||
std::function<void()> on_change = [](){};
|
||||
std::function<void()> on_enter = [](){};
|
||||
|
||||
// Component implementation.
|
||||
dom::Element Render() override;
|
||||
bool Event(int key) override;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_MENU */
|
31
ftxui/include/ftxui/component/toggle.hpp
Normal file
31
ftxui/include/ftxui/component/toggle.hpp
Normal file
@ -0,0 +1,31 @@
|
||||
#ifndef FTXUI_COMPONENT_TOGGLE_H_
|
||||
#define FTXUI_COMPONENT_TOGGLE_H_
|
||||
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include <functional>
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
class Toggle : public Component {
|
||||
public:
|
||||
// Constructor.
|
||||
Toggle(Delegate*);
|
||||
|
||||
// State.
|
||||
bool activated = true;
|
||||
std::wstring on = L"On";
|
||||
std::wstring off = L"Off";
|
||||
|
||||
// Callback.
|
||||
std::function<void()> on_change = [](){};
|
||||
|
||||
// Component implementation.
|
||||
dom::Element Render() override;
|
||||
bool Event(int key) override;
|
||||
};
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_COMPONENT_TOGGLE_H_ */
|
@ -1,23 +0,0 @@
|
||||
#ifndef FTXUI_STATE_HPP
|
||||
#define FTXUI_STATE_HPP
|
||||
|
||||
#include "ftxui/core/requirement.hpp"
|
||||
#include "ftxui/core/document.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class Component {
|
||||
public:
|
||||
virtual Document Render() = 0;
|
||||
|
||||
// Requirement -------------------------------------------------------------
|
||||
virtual void ComputeRequirement();
|
||||
Requirement requirement() { return requirement_; }
|
||||
|
||||
private:
|
||||
Requirement requirement_;
|
||||
};
|
||||
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_STATE_HPP */
|
@ -1,12 +0,0 @@
|
||||
#ifndef FTXUI_DOCUMENT_HPP
|
||||
#define FTXUI_DOCUMENT_HPP
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class Document {
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif /* end of include guard: FTXUI_DOCUMENT_HPP */
|
@ -1,33 +0,0 @@
|
||||
#ifndef FTXUI_CORE_SCREEN
|
||||
#define FTXUI_CORE_SCREEN
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
class Node;
|
||||
}
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
Screen(size_t dimx, size_t dimy);
|
||||
wchar_t& at(size_t x, size_t y);
|
||||
std::string ToString();
|
||||
|
||||
size_t dimx() { return dimx_;}
|
||||
size_t dimy() { return dimy_;}
|
||||
|
||||
static Screen WholeTerminal();
|
||||
static Screen TerminalOutput(std::unique_ptr<dom::Node>& element);
|
||||
|
||||
private:
|
||||
size_t dimx_;
|
||||
size_t dimy_;
|
||||
std::vector<std::wstring> lines_;
|
||||
};
|
||||
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_CORE_SCREEN */
|
@ -1,16 +1,14 @@
|
||||
#ifndef FTXUI_CORE_DOM_ELEMENTS_HPP
|
||||
#define FTXUI_CORE_DOM_ELEMENTS_HPP
|
||||
#ifndef FTXUI_DOM_ELEMENTS_HPP
|
||||
#define FTXUI_DOM_ELEMENTS_HPP
|
||||
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include <initializer_list>
|
||||
#include "ftxui/dom/node.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
using Element = std::unique_ptr<Node>;
|
||||
using Child = std::unique_ptr<Node>;
|
||||
using Children = std::vector<std::unique_ptr<Node>>;
|
||||
|
||||
using Children = std::vector<Child>;
|
||||
|
||||
// --- Layout ----
|
||||
Element vbox(Children);
|
||||
@ -22,7 +20,13 @@ Element text(std::wstring text);
|
||||
Element separator();
|
||||
Element gauge(float ratio);
|
||||
Element frame(Child);
|
||||
Element frame(std::wstring title, Child);
|
||||
Element frame(Child title, Child content);
|
||||
|
||||
// -- Decorator (Style) ---
|
||||
Element bold(Element);
|
||||
Element dim(Element);
|
||||
Element inverted(Element);
|
||||
Element underlined(Element);
|
||||
|
||||
// --- Decorator ---
|
||||
Element hcenter(Element);
|
||||
@ -31,23 +35,23 @@ Element center(Element);
|
||||
Element flex(Element);
|
||||
|
||||
template <class... Args>
|
||||
std::vector<Element> unpack(Args... args) {
|
||||
std::vector<Element> vec;
|
||||
Children unpack(Args... args) {
|
||||
Children vec;
|
||||
(vec.push_back(std::forward<Args>(args)), ...);
|
||||
return vec;
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
std::unique_ptr<Node> vbox(Args... children) {
|
||||
Element vbox(Args... children) {
|
||||
return vbox(unpack(std::forward<Args>(children)...));
|
||||
}
|
||||
|
||||
template <class... Args>
|
||||
std::unique_ptr<Node> hbox(Args... children) {
|
||||
Element hbox(Args... children) {
|
||||
return hbox(unpack(std::forward<Args>(children)...));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_CORE_DOM_ELEMENTS_HPP */
|
||||
#endif /* end of include guard: FTXUI_DOM_ELEMENTS_HPP */
|
@ -1,12 +1,12 @@
|
||||
#ifndef CORE_DOM_NODE_HPP
|
||||
#define CORE_DOM_NODE_HPP
|
||||
#ifndef DOM_NODE_HPP
|
||||
#define DOM_NODE_HPP
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "ftxui/core/requirement.hpp"
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/box.hpp"
|
||||
#include "ftxui/requirement.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/box.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
@ -41,4 +41,4 @@ void Render(Screen& screen, Node* node);
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: CORE_DOM_NODE_HPP */
|
||||
#endif /* end of include guard: DOM_NODE_HPP */
|
@ -1,5 +1,5 @@
|
||||
#ifndef FTXUI_LAYOUT_REQUIREMENT_HPP
|
||||
#define FTXUI_LAYOUT_REQUIREMENT_HPP
|
||||
#ifndef FTXUI_REQUIREMENT_HPP
|
||||
#define FTXUI_REQUIREMENT_HPP
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
@ -25,4 +25,4 @@ struct Requirement {
|
||||
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_LAYOUT_REQUIREMENT_HPP */
|
||||
#endif /* end of include guard: FTXUI_REQUIREMENT_HPP */
|
55
ftxui/include/ftxui/screen.hpp
Normal file
55
ftxui/include/ftxui/screen.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
#ifndef FTXUI_SCREEN
|
||||
#define FTXUI_SCREEN
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
class Node;
|
||||
}
|
||||
|
||||
struct Pixel {
|
||||
wchar_t character = U' ';
|
||||
bool bold = false;
|
||||
bool inverted = false;
|
||||
bool underlined = false;
|
||||
bool dim = false;
|
||||
};
|
||||
|
||||
class Screen {
|
||||
public:
|
||||
// Constructor.
|
||||
Screen(size_t dimx, size_t dimy);
|
||||
|
||||
// Constructor using the terminal.
|
||||
static Screen TerminalFullscreen();
|
||||
static Screen TerminalOutput(std::unique_ptr<dom::Node>& element);
|
||||
|
||||
// dom::Node write into the screen using Screen::at.
|
||||
wchar_t& at(size_t x, size_t y);
|
||||
Pixel& PixelAt(size_t x, size_t y);
|
||||
|
||||
// Convert the screen into a printable string in the terminal.
|
||||
std::string ToString();
|
||||
|
||||
// Get screen dimensions.
|
||||
size_t dimx() { return dimx_;}
|
||||
size_t dimy() { return dimy_;}
|
||||
|
||||
// Move the terminal cursor n-lines up with n = dimy().
|
||||
std::string ResetPosition();
|
||||
|
||||
// Fill with space.
|
||||
void Clear();
|
||||
|
||||
private:
|
||||
size_t dimx_;
|
||||
size_t dimy_;
|
||||
std::vector<std::vector<Pixel>> pixels_;
|
||||
};
|
||||
|
||||
}; // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_SCREEN */
|
34
ftxui/include/ftxui/screen_interactive.hpp
Normal file
34
ftxui/include/ftxui/screen_interactive.hpp
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef FTXUI_SCREEN_INTERACTIVE
|
||||
#define FTXUI_SCREEN_INTERACTIVE
|
||||
|
||||
#include "ftxui/screen.hpp"
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
namespace component {
|
||||
class Delegate;
|
||||
class Component;
|
||||
} // namespace component
|
||||
|
||||
class ScreenInteractive : public Screen {
|
||||
public:
|
||||
ScreenInteractive(size_t dimx, size_t dimy);
|
||||
~ScreenInteractive();
|
||||
component::Delegate* delegate();
|
||||
void Loop();
|
||||
std::function<void()> ExitLoopClosure();
|
||||
|
||||
private:
|
||||
class Delegate;
|
||||
std::unique_ptr<Delegate> delegate_;
|
||||
|
||||
void Clear();
|
||||
void Draw();
|
||||
bool quit_ = false;
|
||||
};
|
||||
|
||||
} // namespace ftxui
|
||||
|
||||
#endif /* end of include guard: FTXUI_SCREEN_INTERACTIVE */
|
59
ftxui/src/ftxui/component/component.cpp
Normal file
59
ftxui/src/ftxui/component/component.cpp
Normal file
@ -0,0 +1,59 @@
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/component/delegate.hpp"
|
||||
#include <assert.h>
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
Component::Component(Delegate* delegate) {
|
||||
delegate_ = delegate;
|
||||
delegate_->Register(this);
|
||||
}
|
||||
|
||||
Component::~Component() {}
|
||||
|
||||
dom::Element Component::Render() {
|
||||
using namespace ftxui::dom;
|
||||
return text(L"Not implemented component");
|
||||
}
|
||||
|
||||
bool Component::Event(int key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Component::Focused() {
|
||||
Delegate* current = delegate_->Root();
|
||||
while (current) {
|
||||
if (current == delegate_)
|
||||
return true;
|
||||
|
||||
Component* active_child = current->component()->GetActiveChild();
|
||||
current = active_child ? active_child->delegate_ : nullptr;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Component::Active() {
|
||||
Delegate* parent = delegate_->Parent();
|
||||
return parent && parent->component()->GetActiveChild() == this;
|
||||
}
|
||||
|
||||
Component* Component::PreviousSibling() {
|
||||
Delegate* sibling = delegate_->PreviousSibling();
|
||||
return sibling ? sibling->component() : nullptr;
|
||||
}
|
||||
|
||||
Component* Component::NextSibling() {
|
||||
Delegate* sibling = delegate_->NextSibling();
|
||||
return sibling ? sibling->component() : nullptr;
|
||||
}
|
||||
|
||||
Component* Component::Parent() {
|
||||
Delegate* parent_delegate = delegate_->Parent();
|
||||
if (!parent_delegate)
|
||||
return nullptr;
|
||||
return parent_delegate->component();
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
31
ftxui/src/ftxui/component/component_direction.cpp
Normal file
31
ftxui/src/ftxui/component/component_direction.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
#include "ftxui/component/component_direction.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
ComponentDirection::ComponentDirection(Delegate* delegate)
|
||||
: Component(delegate), active_child_(nullptr) {}
|
||||
|
||||
bool ComponentDirection::Event(int key) {
|
||||
if (!Focused())
|
||||
return false;
|
||||
|
||||
if (!active_child_)
|
||||
return false;
|
||||
|
||||
if (active_child_->Event(key))
|
||||
return true;
|
||||
|
||||
return HandleDirection(key);
|
||||
}
|
||||
|
||||
Component* ComponentDirection::GetActiveChild() {
|
||||
return active_child_;
|
||||
}
|
||||
|
||||
void ComponentDirection::Focus(Component* child) {
|
||||
active_child_ = child;
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
32
ftxui/src/ftxui/component/component_horizontal.cpp
Normal file
32
ftxui/src/ftxui/component/component_horizontal.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "ftxui/component/component_horizontal.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
ComponentHorizontal::ComponentHorizontal(Delegate* delegate)
|
||||
: ComponentDirection(delegate) {}
|
||||
|
||||
bool ComponentHorizontal::HandleDirection(int key) {
|
||||
// Left pressed ?
|
||||
if (key == 68 || key == 'h') {
|
||||
Component* previous_sibling = active_child_->PreviousSibling();
|
||||
if (previous_sibling) {
|
||||
active_child_ = previous_sibling;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Left pressed ?
|
||||
if (key == 67 || key == 'l') {
|
||||
Component* next_sibling = active_child_->NextSibling();
|
||||
if (next_sibling) {
|
||||
active_child_ = next_sibling;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
32
ftxui/src/ftxui/component/component_vertical.cpp
Normal file
32
ftxui/src/ftxui/component/component_vertical.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "ftxui/component/component_vertical.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
ComponentVertical::ComponentVertical(Delegate* delegate)
|
||||
: ComponentDirection(delegate) {}
|
||||
|
||||
bool ComponentVertical::HandleDirection(int key) {
|
||||
// Up pressed ?
|
||||
if (key == 65 || key == 'k') {
|
||||
Component* previous_sibling = active_child_->PreviousSibling();
|
||||
if (previous_sibling) {
|
||||
active_child_ = previous_sibling;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Down pressed ?
|
||||
if (key == 66 || key == 'j') {
|
||||
Component* next_sibling = active_child_->NextSibling();
|
||||
if (next_sibling) {
|
||||
active_child_ = next_sibling;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
53
ftxui/src/ftxui/component/menu.cpp
Normal file
53
ftxui/src/ftxui/component/menu.cpp
Normal file
@ -0,0 +1,53 @@
|
||||
#include "ftxui/component/menu.hpp"
|
||||
#include <algorithm>
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
Menu::Menu(Delegate* delegate) : Component(delegate) {}
|
||||
|
||||
dom::Element Menu::Render() {
|
||||
using namespace dom;
|
||||
std::vector<Element> elements;
|
||||
bool focused = Focused();
|
||||
for (size_t i = 0; i < entries.size(); ++i) {
|
||||
if (size_t(selected) == i) {
|
||||
if (focused)
|
||||
elements.push_back(inverted(text(L"> " + entries[i])));
|
||||
else
|
||||
elements.push_back(bold(text(L"> " + entries[i])));
|
||||
}
|
||||
else {
|
||||
elements.push_back(text(L" " + entries[i]));
|
||||
}
|
||||
}
|
||||
return vbox(std::move(elements));
|
||||
}
|
||||
|
||||
bool Menu::Event(int key) {
|
||||
if (!Focused())
|
||||
return false;
|
||||
|
||||
int new_selected = selected;
|
||||
if (key == 65 || key == 'k')
|
||||
new_selected--;
|
||||
if (key == 66 || key == 'j')
|
||||
new_selected++;
|
||||
new_selected = std::max(0, std::min(int(entries.size())-1, new_selected));
|
||||
|
||||
if (selected != new_selected) {
|
||||
selected = new_selected;
|
||||
on_change();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (key == 10) {
|
||||
on_enter();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
47
ftxui/src/ftxui/component/toggle.cpp
Normal file
47
ftxui/src/ftxui/component/toggle.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
#include "ftxui/component/toggle.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace component {
|
||||
|
||||
Toggle::Toggle(Delegate* delegate) : Component(delegate) {}
|
||||
|
||||
dom::Element Toggle::Render() {
|
||||
using namespace dom;
|
||||
auto highlight = Focused() ? inverted : bold;
|
||||
|
||||
Children children;
|
||||
children.push_back(text(L"["));
|
||||
if (activated) {
|
||||
children.push_back(highlight(text(on)));
|
||||
children.push_back(text(L"|"));
|
||||
children.push_back(dim(text(off)));
|
||||
} else {
|
||||
children.push_back(dim(text(on)));
|
||||
children.push_back(text(L"|"));
|
||||
children.push_back(highlight(text(off)));
|
||||
}
|
||||
children.push_back(text(L"]"));
|
||||
return hbox(std::move(children));
|
||||
}
|
||||
|
||||
bool Toggle::Event(int key) {
|
||||
|
||||
if (activated) {
|
||||
if (key == 67 || key == 'l') {
|
||||
activated = false;
|
||||
on_change();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (key == 68 || key == 'h') {
|
||||
activated = true;
|
||||
on_change();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace component
|
||||
} // namespace ftxui
|
@ -1,5 +0,0 @@
|
||||
#include "ftxui/core/component.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
void Component::ComputeRequirement() {}
|
||||
} // namespace ftxui.
|
@ -1,57 +0,0 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
static wchar_t charset[] = L"┌┐└┘─│";
|
||||
|
||||
class Frame : public Node {
|
||||
public:
|
||||
Frame(Child child) : Node(unpack(std::move(child))) {}
|
||||
~Frame() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
children[0]->ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
requirement_.min.x += 2;
|
||||
requirement_.min.y += 2;
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
box.left++;
|
||||
box.right--;
|
||||
box.top++;
|
||||
box.bottom--;
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
if (box_.left >= box_.right || box_.top >= box_.bottom)
|
||||
return;
|
||||
|
||||
screen.at(box_.left, box_.top) = charset[0];
|
||||
screen.at(box_.right, box_.top) = charset[1];
|
||||
screen.at(box_.left, box_.bottom) = charset[2];
|
||||
screen.at(box_.right, box_.bottom) = charset[3];
|
||||
for(float x = box_.left + 1; x<box_.right; ++x) {
|
||||
screen.at(x, box_.top) = charset[4];
|
||||
screen.at(x, box_.bottom) = charset[4];
|
||||
}
|
||||
for(float y = box_.top + 1; y<box_.bottom; ++y) {
|
||||
screen.at(box_.left, y) = charset[5];
|
||||
screen.at(box_.right,y) = charset[5];
|
||||
}
|
||||
children[0]->Render(screen);
|
||||
}
|
||||
private:
|
||||
float progress_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> frame(Child child) {
|
||||
return std::make_unique<Frame>(std::move(child));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,38 +0,0 @@
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/core/terminal.hpp"
|
||||
#include "ftxui/util/string.hpp"
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
Screen::Screen(size_t dimx, size_t dimy)
|
||||
: dimx_(dimx), dimy_(dimy), lines_(dimy, std::wstring(dimx, U' ')) {}
|
||||
|
||||
std::string Screen::ToString() {
|
||||
std::stringstream ss;
|
||||
for (size_t y = 0; y < dimy_; ++y) {
|
||||
ss << to_string(lines_[y]);
|
||||
if (y + 1 < dimy_)
|
||||
ss << '\n';
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
wchar_t& Screen::at(size_t x, size_t y) {
|
||||
return lines_[y][x];
|
||||
}
|
||||
|
||||
Screen Screen::WholeTerminal() {
|
||||
Terminal::Dimensions size = Terminal::Size();
|
||||
return Screen(size.dimx, size.dimy);
|
||||
}
|
||||
|
||||
Screen Screen::TerminalOutput(std::unique_ptr<dom::Node>& element) {
|
||||
element->ComputeRequirement();
|
||||
Terminal::Dimensions size = Terminal::Size();
|
||||
return Screen(size.dimx, element->requirement().min.y);
|
||||
}
|
||||
|
||||
}; // namespace ftxui
|
37
ftxui/src/ftxui/dom/bold.cpp
Normal file
37
ftxui/src/ftxui/dom/bold.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
class Bold : public Node {
|
||||
public:
|
||||
Bold(Children children) : Node(std::move(children)) {}
|
||||
~Bold() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
Node::Render(screen);
|
||||
for (int y = box_.top; y <= box_.bottom; ++y) {
|
||||
for (int x = box_.left; x <= box_.right; ++x) {
|
||||
screen.PixelAt(x,y).bold = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> bold(Child child) {
|
||||
return std::make_unique<Bold>(unpack(std::move(child)));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
37
ftxui/src/ftxui/dom/dim.cpp
Normal file
37
ftxui/src/ftxui/dom/dim.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
class Dim : public Node {
|
||||
public:
|
||||
Dim(Children children) : Node(std::move(children)) {}
|
||||
~Dim() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
Node::Render(screen);
|
||||
for (int y = box_.top; y <= box_.bottom; ++y) {
|
||||
for (int x = box_.left; x <= box_.right; ++x) {
|
||||
screen.PixelAt(x,y).dim = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> dim(Child child) {
|
||||
return std::make_unique<Dim>(unpack(std::move(child)));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
92
ftxui/src/ftxui/dom/frame.cpp
Normal file
92
ftxui/src/ftxui/dom/frame.cpp
Normal file
@ -0,0 +1,92 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
static wchar_t charset[] = L"┌┐└┘─│┬┴┤├";
|
||||
|
||||
class Frame : public Node {
|
||||
public:
|
||||
Frame(Children children) : Node(std::move(children)) {}
|
||||
~Frame() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
requirement_.min.x += 2;
|
||||
requirement_.min.y += 2;
|
||||
if (children.size() == 2) {
|
||||
requirement_.min.x =
|
||||
std::max(requirement_.min.x, children[1]->requirement().min.x + 2);
|
||||
}
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
if (children.size() == 2) {
|
||||
Box title_box;
|
||||
title_box.left = box.left + 1;
|
||||
title_box.right = box.right - 1;
|
||||
title_box.top = box.top;
|
||||
title_box.bottom = box.top;
|
||||
children[1]->SetBox(title_box);
|
||||
}
|
||||
box.left++;
|
||||
box.right--;
|
||||
box.top++;
|
||||
box.bottom--;
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
// Draw content.
|
||||
children[0]->Render(screen);
|
||||
|
||||
// Draw the frame.
|
||||
if (box_.left >= box_.right || box_.top >= box_.bottom)
|
||||
return;
|
||||
|
||||
screen.at(box_.left, box_.top) = charset[0];
|
||||
screen.at(box_.right, box_.top) = charset[1];
|
||||
screen.at(box_.left, box_.bottom) = charset[2];
|
||||
screen.at(box_.right, box_.bottom) = charset[3];
|
||||
for(float x = box_.left + 1; x<box_.right; ++x) {
|
||||
screen.at(x, box_.top) = charset[4];
|
||||
screen.at(x, box_.bottom) = charset[4];
|
||||
}
|
||||
for(float y = box_.top + 1; y<box_.bottom; ++y) {
|
||||
screen.at(box_.left, y) = charset[5];
|
||||
screen.at(box_.right,y) = charset[5];
|
||||
}
|
||||
|
||||
// Try to merge with separator.
|
||||
for(float x = box_.left + 1; x<box_.right; ++x) {
|
||||
if (screen.at(x, box_.top + 1) == charset[5])
|
||||
screen.at(x, box_.top) = charset[6];
|
||||
if (screen.at(x, box_.bottom - 1) == charset[5])
|
||||
screen.at(x, box_.bottom) = charset[7];
|
||||
}
|
||||
for(float y = box_.top + 1; y<box_.bottom; ++y) {
|
||||
if (screen.at(box_.left+1, y) == charset[4])
|
||||
screen.at(box_.left, y) = charset[9];
|
||||
if (screen.at(box_.right-1, y) == charset[4])
|
||||
screen.at(box_.right,y) = charset[8];
|
||||
}
|
||||
|
||||
// Draw title.
|
||||
if (children.size() == 2)
|
||||
children[1]->Render(screen);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> frame(Child child) {
|
||||
return std::make_unique<Frame>(unpack(std::move(child)));
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> frame(Child title, Child content) {
|
||||
return std::make_unique<Frame>(unpack(std::move(content), std::move(title)));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
34
ftxui/src/ftxui/dom/gauge_test.cpp
Normal file
34
ftxui/src/ftxui/dom/gauge_test.cpp
Normal file
@ -0,0 +1,34 @@
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
TEST(GaugeTest, zero) {
|
||||
auto root = gauge(0);
|
||||
Screen screen(11,1);
|
||||
Render(screen, root.get());
|
||||
|
||||
EXPECT_EQ(" ", screen.ToString());
|
||||
}
|
||||
|
||||
TEST(GaugeTest, half) {
|
||||
auto root = gauge(0.5);
|
||||
Screen screen(11,1);
|
||||
Render(screen, root.get());
|
||||
|
||||
EXPECT_EQ("█████▏▋ ", screen.ToString());
|
||||
//" ▏▎▍▌▊▉█";
|
||||
}
|
||||
|
||||
TEST(GaugeTest, one) {
|
||||
auto root = gauge(1.0);
|
||||
Screen screen(11,1);
|
||||
Render(screen, root.get());
|
||||
|
||||
EXPECT_EQ("███████████", screen.ToString());
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace ftxui
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace ftxui {
|
37
ftxui/src/ftxui/dom/inverted.cpp
Normal file
37
ftxui/src/ftxui/dom/inverted.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
class Inverted : public Node {
|
||||
public:
|
||||
Inverted(Children children) : Node(std::move(children)) {}
|
||||
~Inverted() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
Node::Render(screen);
|
||||
for (int y = box_.top; y <= box_.bottom; ++y) {
|
||||
for (int x = box_.left; x <= box_.right; ++x) {
|
||||
screen.PixelAt(x,y).inverted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> inverted(Child child) {
|
||||
return std::make_unique<Inverted>(unpack(std::move(child)));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,4 +1,4 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
@ -8,10 +8,15 @@ Node::Node(std::vector<std::unique_ptr<Node>> children)
|
||||
: children(std::move(children)) {}
|
||||
Node::~Node() {}
|
||||
|
||||
void Node::ComputeRequirement() {}
|
||||
void Node::ComputeRequirement() {
|
||||
for(auto& child : children)
|
||||
child->ComputeRequirement();
|
||||
}
|
||||
|
||||
void Node::SetBox(Box box) {
|
||||
box_ = box;
|
||||
}
|
||||
|
||||
void Node::Render(Screen& screen) {
|
||||
for(auto& child : children)
|
||||
child->Render(screen);
|
@ -1,4 +1,4 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
@ -1,4 +1,4 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace ftxui {
|
37
ftxui/src/ftxui/dom/underlined.cpp
Normal file
37
ftxui/src/ftxui/dom/underlined.cpp
Normal file
@ -0,0 +1,37 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
||||
|
||||
class Underlined : public Node {
|
||||
public:
|
||||
Underlined(Children children) : Node(std::move(children)) {}
|
||||
~Underlined() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
}
|
||||
|
||||
void SetBox(Box box) override {
|
||||
Node::SetBox(box);
|
||||
children[0]->SetBox(box);
|
||||
}
|
||||
|
||||
void Render(Screen& screen) override {
|
||||
Node::Render(screen);
|
||||
for (int y = box_.top; y <= box_.bottom; ++y) {
|
||||
for (int x = box_.left; x <= box_.right; ++x) {
|
||||
screen.PixelAt(x,y).underlined = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> underlined(Child child) {
|
||||
return std::make_unique<Underlined>(unpack(std::move(child)));
|
||||
}
|
||||
|
||||
}; // namespace dom
|
||||
}; // namespace ftxui
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/node.hpp"
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
namespace dom {
|
@ -1,5 +1,5 @@
|
||||
#include "ftxui/core/dom/elements.hpp"
|
||||
#include "ftxui/core/screen.hpp"
|
||||
#include "ftxui/dom/elements.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
namespace ftxui {
|
91
ftxui/src/ftxui/screen.cpp
Normal file
91
ftxui/src/ftxui/screen.cpp
Normal file
@ -0,0 +1,91 @@
|
||||
#include "ftxui/dom/node.hpp"
|
||||
#include "ftxui/screen.hpp"
|
||||
#include "ftxui/terminal.hpp"
|
||||
#include "ftxui/util/string.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
Screen::Screen(size_t dimx, size_t dimy)
|
||||
: dimx_(dimx), dimy_(dimy), pixels_(dimy, std::vector<Pixel>(dimx)) {}
|
||||
|
||||
std::string Screen::ToString() {
|
||||
std::wstringstream ss;
|
||||
|
||||
Pixel previous_pixel;
|
||||
|
||||
for (size_t y = 0; y < dimy_; ++y) {
|
||||
for (size_t x = 0; x < dimx_; ++x) {
|
||||
if (pixels_[y][x].bold != previous_pixel.bold) {
|
||||
if (pixels_[y][x].bold) {
|
||||
ss << L"\e[1m";
|
||||
} else {
|
||||
ss << L"\e[0m";
|
||||
}
|
||||
}
|
||||
if (pixels_[y][x].inverted != previous_pixel.inverted) {
|
||||
if (pixels_[y][x].inverted) {
|
||||
ss << L"\e[7m";
|
||||
} else {
|
||||
ss << L"\e[27m";
|
||||
}
|
||||
}
|
||||
if (pixels_[y][x].underlined != previous_pixel.underlined) {
|
||||
if (pixels_[y][x].underlined) {
|
||||
ss << L"\e[4m";
|
||||
} else {
|
||||
ss << L"\e[24m";
|
||||
}
|
||||
}
|
||||
if (pixels_[y][x].dim != previous_pixel.dim) {
|
||||
if (pixels_[y][x].dim) {
|
||||
ss << L"\e[2m";
|
||||
} else {
|
||||
ss << L"\e[22m";
|
||||
}
|
||||
}
|
||||
ss << pixels_[y][x].character;
|
||||
previous_pixel = pixels_[y][x];
|
||||
}
|
||||
if (y + 1 < dimy_)
|
||||
ss << '\n';
|
||||
}
|
||||
return to_string(ss.str());
|
||||
}
|
||||
|
||||
wchar_t& Screen::at(size_t x, size_t y) {
|
||||
return pixels_[y][x].character;
|
||||
}
|
||||
|
||||
Pixel& Screen::PixelAt(size_t x, size_t y) {
|
||||
return pixels_[y][x];
|
||||
}
|
||||
|
||||
// static
|
||||
Screen Screen::TerminalFullscreen() {
|
||||
Terminal::Dimensions size = Terminal::Size();
|
||||
return Screen(size.dimx, size.dimy);
|
||||
}
|
||||
|
||||
// static
|
||||
Screen Screen::TerminalOutput(std::unique_ptr<dom::Node>& element) {
|
||||
element->ComputeRequirement();
|
||||
Terminal::Dimensions size = Terminal::Size();
|
||||
return Screen(size.dimx, element->requirement().min.y);
|
||||
}
|
||||
|
||||
std::string Screen::ResetPosition() {
|
||||
std::stringstream ss;
|
||||
for(size_t y = 1; y<dimy_; ++y) {
|
||||
ss << "\e[2K\r\e[1A";
|
||||
}
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
void Screen::Clear() {
|
||||
pixels_ = std::vector<std::vector<Pixel>>(dimy_,
|
||||
std::vector<Pixel>(dimx_, Pixel()));
|
||||
}
|
||||
|
||||
}; // namespace ftxui
|
112
ftxui/src/ftxui/screen_interactive.cpp
Normal file
112
ftxui/src/ftxui/screen_interactive.cpp
Normal file
@ -0,0 +1,112 @@
|
||||
#include "ftxui/screen_interactive.hpp"
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/component/delegate.hpp"
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
class ScreenInteractive::Delegate : public component::Delegate {
|
||||
public:
|
||||
Delegate() : root_(this) {}
|
||||
|
||||
void Register(component::Component* c) override { component_ = c; }
|
||||
|
||||
std::vector<std::unique_ptr<Delegate>> child_;
|
||||
Delegate* NewChild() override {
|
||||
Delegate* child = new Delegate;
|
||||
child->root_ = root_;
|
||||
child->parent_ = this;
|
||||
|
||||
if (!child_.empty()) {
|
||||
child_.back()->next_sibling_ = child;
|
||||
child->previous_sibling_ = child_.back().get();
|
||||
}
|
||||
|
||||
child_.emplace_back(child);
|
||||
return child;
|
||||
}
|
||||
|
||||
void Event(int key) { component_->Event(key); }
|
||||
|
||||
|
||||
std::vector<component::Delegate*> children() override {
|
||||
std::vector<component::Delegate*> ret;
|
||||
for (auto& it : child_)
|
||||
ret.push_back(it.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
Delegate* root_;
|
||||
Delegate* parent_ = nullptr;
|
||||
Delegate* previous_sibling_ = nullptr;
|
||||
Delegate* next_sibling_ = nullptr;
|
||||
component::Component* component_;
|
||||
|
||||
Delegate* Root() override { return root_; }
|
||||
Delegate* Parent() override { return parent_; }
|
||||
Delegate* PreviousSibling() override { return previous_sibling_; }
|
||||
Delegate* NextSibling() override { return next_sibling_; }
|
||||
component::Component* component() override { return component_; }
|
||||
};
|
||||
|
||||
ScreenInteractive::ScreenInteractive(size_t dimx, size_t dimy)
|
||||
: Screen(dimx, dimy), delegate_(new Delegate) {}
|
||||
ScreenInteractive::~ScreenInteractive() {}
|
||||
|
||||
void ScreenInteractive::Loop() {
|
||||
std::cout << "\033[?9h"; /* Send Mouse Row & Column on Button Press */
|
||||
std::cout << "\033[?1000h"; /* Send Mouse X & Y on button press and release */
|
||||
std::cout << std::flush;
|
||||
|
||||
// Save the old terminal configuration.
|
||||
struct termios terminal_configuration_old;
|
||||
tcgetattr(STDIN_FILENO, &terminal_configuration_old);
|
||||
|
||||
// Set the new terminal configuration
|
||||
struct termios terminal_configuration_new;
|
||||
terminal_configuration_new = terminal_configuration_old;
|
||||
|
||||
// Non canonique terminal.
|
||||
terminal_configuration_new.c_lflag &= ~ICANON;
|
||||
// Do not print after a key press.
|
||||
terminal_configuration_new.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_new);
|
||||
|
||||
Draw();
|
||||
while (!quit_) {
|
||||
int key = getchar();
|
||||
delegate_->Event(key);
|
||||
|
||||
Clear();
|
||||
Draw();
|
||||
}
|
||||
std::cout << std::endl;
|
||||
//Clear();
|
||||
|
||||
// Restore the old terminal configuration.
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_old);
|
||||
}
|
||||
|
||||
void ScreenInteractive::Draw() {
|
||||
auto document = delegate_->component()->Render();
|
||||
Render(*this, document.get());
|
||||
std::cout << ToString() << std::flush;
|
||||
}
|
||||
|
||||
void ScreenInteractive::Clear() {
|
||||
std::cout << ResetPosition();
|
||||
Screen::Clear();
|
||||
}
|
||||
|
||||
component::Delegate* ScreenInteractive::delegate() {
|
||||
return delegate_.get();
|
||||
}
|
||||
|
||||
std::function<void()> ScreenInteractive::ExitLoopClosure() {
|
||||
return [this]() { quit_ = true; };
|
||||
}
|
||||
|
||||
} // namespace ftxui
|
@ -2,7 +2,7 @@
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "ftxui/core/terminal.hpp"
|
||||
#include "ftxui/terminal.hpp"
|
||||
|
||||
namespace ftxui {
|
||||
|
141
tutorials/dom_elements.md
Normal file
141
tutorials/dom_elements.md
Normal file
@ -0,0 +1,141 @@
|
||||
All the dom element are declared in one header:
|
||||
"""c++
|
||||
#include <ftxui/dom/elements.hpp>
|
||||
"""
|
||||
|
||||
It declares the following set of elements:
|
||||
|
||||
"""C++
|
||||
// --- Layout ----
|
||||
Element vbox(Children);
|
||||
Element hbox(Children);
|
||||
Element flex();
|
||||
|
||||
// --- Widget --
|
||||
Element text(std::wstring text);
|
||||
Element separator();
|
||||
Element gauge(float ratio);
|
||||
Element frame(Child);
|
||||
Element frame(Child title, Child content);
|
||||
|
||||
// -- Decorator (Style) ---
|
||||
Element bold(Element);
|
||||
Element dim(Element);
|
||||
Element inverted(Element);
|
||||
Element underlined(Element);
|
||||
|
||||
// --- Decorator ---
|
||||
Element hcenter(Element);
|
||||
Element vcenter(Element);
|
||||
Element center(Element);
|
||||
Element flex(Element);
|
||||
"""
|
||||
|
||||
# Layout elements.
|
||||
|
||||
vbox (Vertical-box) and hbox (Horizontal-box) are containers. They are used to
|
||||
compose all the elements together. They will display their children one by one in one direction.
|
||||
Each elements will occupy the space it required plus a fraction of the remaining
|
||||
space dispatched to all the flexible elements.
|
||||
|
||||
flex() is used to make an element flexible.
|
||||
|
||||
## Examples
|
||||
"""C++
|
||||
hbox(
|
||||
frame(text(L"left")),
|
||||
flex(frame(text(L"middle"))),
|
||||
frame(text(L"right"))
|
||||
);
|
||||
"""
|
||||
"""bash
|
||||
┌────┐┌─────────────────────────────────────────────────────────────────┐┌─────┐
|
||||
│left││middle ││right│
|
||||
└────┘└─────────────────────────────────────────────────────────────────┘└─────┘
|
||||
"""
|
||||
|
||||
"""C++
|
||||
hbox(
|
||||
frame(text(L"left")),
|
||||
flex(frame(text(L"middle"))),
|
||||
flex(frame(text(L"right")))
|
||||
);
|
||||
"""
|
||||
"""bash
|
||||
┌────┐┌───────────────────────────────────┐┌───────────────────────────────────┐
|
||||
│left││middle ││right │
|
||||
└────┘└───────────────────────────────────┘└───────────────────────────────────┘
|
||||
"""
|
||||
|
||||
# Widget elements.
|
||||
|
||||
## text
|
||||
|
||||
The more simple widget. It display a text.
|
||||
"""C++
|
||||
text(L"I am a piece of text");
|
||||
"""
|
||||
"""bash
|
||||
I am a piece of text.
|
||||
"""
|
||||
|
||||
## frame
|
||||
Add a border arround an element
|
||||
"""c+
|
||||
frame(text(L"The element"))
|
||||
"""
|
||||
|
||||
"""bash
|
||||
┌───────────┐
|
||||
│The element│
|
||||
└───────────┘
|
||||
"""
|
||||
|
||||
## separator
|
||||
|
||||
Display a vertical or horizontal line to visually split the content of a
|
||||
container in two.
|
||||
|
||||
"""c++
|
||||
frame(hbox(
|
||||
vbox(
|
||||
text(L"left top"),
|
||||
text(L"left bottom")
|
||||
),
|
||||
separator(),
|
||||
vbox(
|
||||
text(L"right top"),
|
||||
text(L"right bottom")
|
||||
)
|
||||
));
|
||||
"""
|
||||
|
||||
"""bash
|
||||
┌───────────┬────────────┐
|
||||
│left top │right top │
|
||||
│left bottom│right bottom│
|
||||
└───────────┴────────────┘
|
||||
"""
|
||||
|
||||
## gauge
|
||||
|
||||
|
||||
A gauge. It can be used to represent a progress bar.
|
||||
"""c+
|
||||
frame(gauge(0.5))
|
||||
"""
|
||||
|
||||
"""bash
|
||||
┌────────────────────────────────────────────────────────────────────────────┐
|
||||
│██████████████████████████████████████ │
|
||||
└────────────────────────────────────────────────────────────────────────────┘
|
||||
"""
|
||||
|
||||
# Decorator (style)
|
||||
A terminal console can usually display colored text and colored background.
|
||||
The text can also have different effects: bold, dim, underlined, inverted.
|
||||
|
||||
Element bold(Element);
|
||||
Element dim(Element);
|
||||
Element inverted(Element);
|
||||
Element underlined(Element);
|
Loading…
Reference in New Issue
Block a user