mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 12:37:06 +08:00
Update tutorial.md
This commit is contained in:
parent
da5b4b5014
commit
5840966049
@ -22,18 +22,16 @@ class MyComponent : public Component {
|
|||||||
MyComponent() {
|
MyComponent() {
|
||||||
Add(&container);
|
Add(&container);
|
||||||
menu.entries = {
|
menu.entries = {
|
||||||
L"Browse the web",
|
L"Menu 1",
|
||||||
L"Meditate",
|
L"Menu 2",
|
||||||
L"Sleep",
|
L"Menu 3",
|
||||||
L"Eat",
|
L"Menu 4",
|
||||||
};
|
};
|
||||||
container.Add(&menu);
|
container.Add(&menu);
|
||||||
|
|
||||||
toggle.entries = {
|
toggle.entries = {
|
||||||
L"Browse the web",
|
L"Toggle_1",
|
||||||
L"Meditate",
|
L"Toggle_2",
|
||||||
L"Sleep",
|
|
||||||
L"Eat",
|
|
||||||
};
|
};
|
||||||
container.Add(&toggle);
|
container.Add(&toggle);
|
||||||
|
|
||||||
@ -44,10 +42,10 @@ class MyComponent : public Component {
|
|||||||
checkbox_container.Add(&checkbox2);
|
checkbox_container.Add(&checkbox2);
|
||||||
|
|
||||||
radiobox.entries = {
|
radiobox.entries = {
|
||||||
L"Browse the web",
|
L"Radiobox 1",
|
||||||
L"Meditate",
|
L"Radiobox 2",
|
||||||
L"Sleep",
|
L"Radiobox 3",
|
||||||
L"Eat",
|
L"Radiobox 4",
|
||||||
};
|
};
|
||||||
container.Add(&radiobox);
|
container.Add(&radiobox);
|
||||||
|
|
||||||
@ -56,7 +54,7 @@ class MyComponent : public Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Element Render(std::wstring name, Component& component) {
|
Element Render(std::wstring name, Component& component) {
|
||||||
return hbox(text(name) | size(10,1), separator(), component.Render());
|
return hbox(text(name) | size(8,1), separator(), component.Render());
|
||||||
}
|
}
|
||||||
|
|
||||||
Element Render() override {
|
Element Render() override {
|
||||||
@ -76,7 +74,7 @@ class MyComponent : public Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
auto screen = ScreenInteractive::FitComponent();
|
||||||
MyComponent component;
|
MyComponent component;
|
||||||
screen.Loop(&component);
|
screen.Loop(&component);
|
||||||
|
|
||||||
|
@ -20,6 +20,9 @@ class CheckBox : public Component {
|
|||||||
std::wstring checked = L"☑ ";
|
std::wstring checked = L"☑ ";
|
||||||
std::wstring unchecked = L"☐ ";
|
std::wstring unchecked = L"☐ ";
|
||||||
|
|
||||||
|
Decorator focused_style = inverted;
|
||||||
|
Decorator unfocused_style = nothing;
|
||||||
|
|
||||||
// State update callback.
|
// State update callback.
|
||||||
std::function<void()> on_change = [](){};
|
std::function<void()> on_change = [](){};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ class ScreenInteractive : public Screen {
|
|||||||
public:
|
public:
|
||||||
static ScreenInteractive FixedSize(size_t dimx, size_t dimy);
|
static ScreenInteractive FixedSize(size_t dimx, size_t dimy);
|
||||||
static ScreenInteractive Fullscreen();
|
static ScreenInteractive Fullscreen();
|
||||||
|
static ScreenInteractive FitComponent();
|
||||||
static ScreenInteractive TerminalOutput();
|
static ScreenInteractive TerminalOutput();
|
||||||
|
|
||||||
~ScreenInteractive();
|
~ScreenInteractive();
|
||||||
@ -23,9 +24,10 @@ class ScreenInteractive : public Screen {
|
|||||||
bool quit_ = false;
|
bool quit_ = false;
|
||||||
|
|
||||||
enum class Dimension {
|
enum class Dimension {
|
||||||
|
FitComponent,
|
||||||
Fixed,
|
Fixed,
|
||||||
TerminalOutput,
|
|
||||||
Fullscreen,
|
Fullscreen,
|
||||||
|
TerminalOutput,
|
||||||
};
|
};
|
||||||
Dimension dimension_ = Dimension::Fixed;
|
Dimension dimension_ = Dimension::Fixed;
|
||||||
ScreenInteractive(size_t dimx, size_t dimy, Dimension dimension);
|
ScreenInteractive(size_t dimx, size_t dimy, Dimension dimension);
|
||||||
|
@ -50,6 +50,8 @@ class Screen {
|
|||||||
// Fill with space.
|
// Fill with space.
|
||||||
void Clear();
|
void Clear();
|
||||||
|
|
||||||
|
void ApplyShader();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
size_t dimx_;
|
size_t dimx_;
|
||||||
size_t dimy_;
|
size_t dimy_;
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
Element CheckBox::Render() {
|
Element CheckBox::Render() {
|
||||||
auto style = Focused() ? bold : nothing;
|
auto style = Focused() ? focused_style : unfocused_style;
|
||||||
return text((state ? checked : unchecked) + label) | style;
|
return hbox(text(state ? checked : unchecked), text(label) | style);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CheckBox::OnEvent(Event event) {
|
bool CheckBox::OnEvent(Event event) {
|
||||||
|
@ -65,6 +65,11 @@ ScreenInteractive ScreenInteractive::TerminalOutput() {
|
|||||||
return ScreenInteractive(0, 0, Dimension::TerminalOutput);
|
return ScreenInteractive(0, 0, Dimension::TerminalOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// static
|
||||||
|
ScreenInteractive ScreenInteractive::FitComponent() {
|
||||||
|
return ScreenInteractive(0, 0, Dimension::FitComponent);
|
||||||
|
}
|
||||||
|
|
||||||
void ScreenInteractive::Loop(Component* component) {
|
void ScreenInteractive::Loop(Component* component) {
|
||||||
//std::cout << "\033[?9h"; [> Send Mouse Row & Column on Button Press <]
|
//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 << "\033[?1000h"; [> Send Mouse X & Y on button press and release <]
|
||||||
@ -114,10 +119,14 @@ void ScreenInteractive::Draw(Component* component) {
|
|||||||
dimy = document->requirement().min.y;
|
dimy = document->requirement().min.y;
|
||||||
break;
|
break;
|
||||||
case Dimension::Fullscreen:
|
case Dimension::Fullscreen:
|
||||||
document->ComputeRequirement();
|
|
||||||
dimx = Terminal::Size().dimx;
|
dimx = Terminal::Size().dimx;
|
||||||
dimy = Terminal::Size().dimy;
|
dimy = Terminal::Size().dimy;
|
||||||
break;
|
break;
|
||||||
|
case Dimension::FitComponent:
|
||||||
|
document->ComputeRequirement();
|
||||||
|
dimx = document->requirement().min.x;
|
||||||
|
dimy = document->requirement().min.y;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dimx != dimx_ || dimy != dimy_) {
|
if (dimx != dimx_ || dimy != dimy_) {
|
||||||
|
@ -61,20 +61,6 @@ class Frame : public Node {
|
|||||||
screen.at(box_.right,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.
|
// Draw title.
|
||||||
if (children.size() == 2)
|
if (children.size() == 2)
|
||||||
children[1]->Render(screen);
|
children[1]->Render(screen);
|
||||||
|
@ -38,6 +38,9 @@ void Render(Screen& screen, Node* node) {
|
|||||||
|
|
||||||
// Step 3: Draw the element.
|
// Step 3: Draw the element.
|
||||||
node->Render(screen);
|
node->Render(screen);
|
||||||
|
|
||||||
|
// Step 4: Apply shaders
|
||||||
|
screen.ApplyShader();
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace ftxui
|
}; // namespace ftxui
|
||||||
|
@ -22,6 +22,10 @@ static const wchar_t* BLINK_RESET = L"\e[25m";
|
|||||||
static const wchar_t* INVERTED_SET = L"\e[7m";
|
static const wchar_t* INVERTED_SET = L"\e[7m";
|
||||||
static const wchar_t* INVERTED_RESET = L"\e[27m";
|
static const wchar_t* INVERTED_RESET = L"\e[27m";
|
||||||
|
|
||||||
|
static const char* MOVE_LEFT = "\r";
|
||||||
|
static const char* MOVE_UP = "\e[1A";
|
||||||
|
static const char* CLEAR_LINE = "\e[2K";
|
||||||
|
|
||||||
Screen::Screen(size_t dimx, size_t dimy)
|
Screen::Screen(size_t dimx, size_t dimy)
|
||||||
: dimx_(dimx), dimy_(dimy), pixels_(dimy, std::vector<Pixel>(dimx)) {}
|
: dimx_(dimx), dimy_(dimy), pixels_(dimy, std::vector<Pixel>(dimx)) {}
|
||||||
|
|
||||||
@ -94,9 +98,9 @@ Screen Screen::TerminalOutput(std::unique_ptr<Node>& element) {
|
|||||||
|
|
||||||
std::string Screen::ResetPosition() {
|
std::string Screen::ResetPosition() {
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << '\r';
|
ss << MOVE_LEFT << CLEAR_LINE;
|
||||||
for (size_t y = 1; y < dimy_; ++y) {
|
for (size_t y = 1; y < dimy_; ++y) {
|
||||||
ss << "\e[2K\r\e[1A";
|
ss << MOVE_UP << CLEAR_LINE;
|
||||||
}
|
}
|
||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
@ -106,4 +110,37 @@ void Screen::Clear() {
|
|||||||
std::vector<Pixel>(dimx_, Pixel()));
|
std::vector<Pixel>(dimx_, Pixel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::ApplyShader() {
|
||||||
|
|
||||||
|
// Merge box characters togethers.
|
||||||
|
for(size_t y = 1; y<dimy_; ++y) {
|
||||||
|
for(size_t x = 1; x<dimx_; ++x) {
|
||||||
|
wchar_t& left = at(x - 1, y);
|
||||||
|
wchar_t& top = at(x, y - 1);
|
||||||
|
wchar_t& cur = at(x, y);
|
||||||
|
|
||||||
|
// Left vs current
|
||||||
|
if (cur== U'│' && left == U'─')
|
||||||
|
cur= U'┤';
|
||||||
|
if (cur== U'─' && left == U'│')
|
||||||
|
left = U'├';
|
||||||
|
if (cur== U'├' && left == U'─')
|
||||||
|
cur= U'┼';
|
||||||
|
if (cur== U'─' && left == U'┤')
|
||||||
|
left = U'┼';
|
||||||
|
|
||||||
|
// Top vs current
|
||||||
|
if (cur== U'─' && top == U'│')
|
||||||
|
cur= U'┴';
|
||||||
|
if (cur== U'│' && top == U'─')
|
||||||
|
top = U'┬';
|
||||||
|
if (cur== U'┬' && top == U'│')
|
||||||
|
cur= U'┼';
|
||||||
|
if (cur== U'│' && top == U'┴')
|
||||||
|
top = U'┼';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}; // namespace ftxui
|
}; // namespace ftxui
|
||||||
|
47
tutorial.md
47
tutorial.md
@ -1,17 +1,23 @@
|
|||||||
Table of content.
|
- [Introduction](#introduction)
|
||||||
- [DOM](#dom)
|
- [DOM](#dom)
|
||||||
* [Style](#style)
|
* [Style](#style)
|
||||||
* [Layout](#layout)
|
* [Layout](#layout)
|
||||||
|
+ [Examples](#examples)
|
||||||
* [Widget.](#widget)
|
* [Widget.](#widget)
|
||||||
+ [text](#text)
|
+ [text](#text)
|
||||||
+ [frame](#frame)
|
+ [frame](#frame)
|
||||||
+ [separator](#separator)
|
+ [separator](#separator)
|
||||||
+ [gauge](#gauge)
|
+ [gauge](#gauge)
|
||||||
|
* [Decorator](#decorator)
|
||||||
- [Components.](#components)
|
- [Components.](#components)
|
||||||
* [Input](#input)
|
* [Input](#input)
|
||||||
* [Menu](#menu)
|
* [Menu](#menu)
|
||||||
* [Toggle.](#toggle)
|
* [Toggle.](#toggle)
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
I highly recommand to not take too long on the tutorial, instead you should try
|
||||||
|
to understand the /example/*.
|
||||||
|
|
||||||
## DOM
|
## DOM
|
||||||
All the dom element are declared in one header:
|
All the dom element are declared in one header:
|
||||||
~~~cpp
|
~~~cpp
|
||||||
@ -22,18 +28,22 @@ It declares the following set of elements:
|
|||||||
|
|
||||||
~~~cpp
|
~~~cpp
|
||||||
// --- Layout ----
|
// --- Layout ----
|
||||||
Element vbox(Children);
|
Element vbox(Elements);
|
||||||
Element hbox(Children);
|
Element hbox(Elements);
|
||||||
Element dbox(Children);
|
Element dbox(Elements);
|
||||||
|
|
||||||
|
// -- Flexibility --
|
||||||
Element filler();
|
Element filler();
|
||||||
Element flex(Element);
|
Element flex(Element);
|
||||||
|
Decorator size(size_t width, size_t height);
|
||||||
|
|
||||||
// --- Widget --
|
// --- Widget --
|
||||||
Element text(std::wstring text);
|
Element text(std::wstring text);
|
||||||
Element separator();
|
Element separator();
|
||||||
Element gauge(float ratio);
|
Element gauge(float ratio);
|
||||||
Element frame(Element);
|
Element frame(Element);
|
||||||
Element window(Child title, Child content);
|
Element window(Element title, Element content);
|
||||||
|
Element spinner(int charset_index, size_t image_index);
|
||||||
|
|
||||||
// -- Decorator ---
|
// -- Decorator ---
|
||||||
Element bold(Element);
|
Element bold(Element);
|
||||||
@ -41,15 +51,17 @@ Element dim(Element);
|
|||||||
Element inverted(Element);
|
Element inverted(Element);
|
||||||
Element underlined(Element);
|
Element underlined(Element);
|
||||||
Element blink(Element);
|
Element blink(Element);
|
||||||
Element color(Color, Element);
|
|
||||||
Element bgcolor(Color, Element);
|
|
||||||
Decorator color(Color);
|
Decorator color(Color);
|
||||||
Decorator bgcolor(Color);
|
Decorator bgcolor(Color);
|
||||||
|
Element color(Color, Element);
|
||||||
|
Element bgcolor(Color, Element);
|
||||||
|
|
||||||
// --- Util ---
|
// --- Util ---
|
||||||
Element hcenter(Element);
|
Element hcenter(Element);
|
||||||
Element vcenter(Element);
|
Element vcenter(Element);
|
||||||
Element center(Element);
|
Element center(Element);
|
||||||
|
Element align_right(Element);
|
||||||
|
|
||||||
// --- Util ---
|
// --- Util ---
|
||||||
Element nothing(Element element);
|
Element nothing(Element element);
|
||||||
@ -74,21 +86,21 @@ Element bgcolor(Color, Element);
|
|||||||
|
|
||||||
* vbox (Vertical-box)
|
* vbox (Vertical-box)
|
||||||
* hbox (Horizontal-box)
|
* hbox (Horizontal-box)
|
||||||
* fbox (Depth-box)
|
* dbox (Depth-box)
|
||||||
are containers. They are used to compose all the elements together. Each
|
are containers. They are used to compose all the elements together. Each
|
||||||
children are put side by side. If the container is flexible, the extra space
|
children are put side by side. If the container is flexible, the extra space
|
||||||
available will be shared among the remaining flexible children.
|
available will be shared among the remaining flexible children.
|
||||||
|
|
||||||
flex(element) can be used to make a non-flexible element flexible.
|
flex(element) can be used to make a non-flexible element flexible. filler() is a
|
||||||
filler() is a flexible empty element. You can use it to children on one side of
|
flexible empty element. You can use it align children on one side of the
|
||||||
the container.
|
container.
|
||||||
|
|
||||||
#### Examples
|
#### Examples
|
||||||
~~~cpp
|
~~~cpp
|
||||||
hbox(
|
hbox(
|
||||||
frame(text(L"left")),
|
text(L"left") | frame ,
|
||||||
flex(frame(text(L"middle"))),
|
text(L"middle") | frame | flex,
|
||||||
frame(text(L"right"))
|
text(L"right") | frame
|
||||||
);
|
);
|
||||||
~~~
|
~~~
|
||||||
~~~bash
|
~~~bash
|
||||||
@ -99,9 +111,9 @@ the container.
|
|||||||
|
|
||||||
~~~cpp
|
~~~cpp
|
||||||
hbox(
|
hbox(
|
||||||
frame(text(L"left")),
|
text(L"left") | frame ,
|
||||||
flex(frame(text(L"middle"))),
|
text(L"middle") | frame | flex,
|
||||||
flex(frame(text(L"right")))
|
text(L"right") | frame | flex
|
||||||
);
|
);
|
||||||
~~~
|
~~~
|
||||||
~~~bash
|
~~~bash
|
||||||
@ -190,6 +202,7 @@ text(L"This text is bold")) | bold | underlined
|
|||||||
|
|
||||||
## Components.
|
## Components.
|
||||||
|
|
||||||
|
dom element are stateless.
|
||||||
### Input
|
### Input
|
||||||
TODO(arthursonzogni): Add Video
|
TODO(arthursonzogni): Add Video
|
||||||
### Menu
|
### Menu
|
||||||
|
Loading…
Reference in New Issue
Block a user