mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-09-28 17:58:07 +08:00
Add example homepage.cpp
This commit is contained in:
@@ -34,4 +34,6 @@ Event Event::F10{ESC, '[', '2', '1', '~'};
|
||||
Event Event::F11{ESC, '[', '2', '1', '~'}; // Same as F10 ?
|
||||
Event Event::F12{ESC, '[', '2', '4', '~'};
|
||||
|
||||
Event Event::Custom{0, 0, 0, 0, 0};
|
||||
|
||||
} // namespace ftxui
|
||||
|
@@ -5,19 +5,21 @@ namespace ftxui {
|
||||
|
||||
// Component implementation.
|
||||
Element Input::Render() {
|
||||
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
||||
auto main_decorator = flex | size(HEIGHT, EQUAL, 1);
|
||||
bool is_focused = Focused();
|
||||
|
||||
// Placeholder.
|
||||
if (content.size() == 0) {
|
||||
if (is_focused)
|
||||
return text(placeholder) | dim | inverted | flex;
|
||||
return text(placeholder) | dim | inverted | main_decorator;
|
||||
else
|
||||
return text(placeholder) | dim | flex;
|
||||
return text(placeholder) | dim | main_decorator;
|
||||
}
|
||||
|
||||
// Not focused.
|
||||
if (!is_focused)
|
||||
return text(content) | flex;
|
||||
return text(content) | main_decorator;
|
||||
|
||||
std::wstring part_before_cursor = content.substr(0,cursor_position);
|
||||
std::wstring part_at_cursor = cursor_position < (int)content.size()
|
||||
@@ -34,9 +36,11 @@ Element Input::Render() {
|
||||
text(part_before_cursor),
|
||||
text(part_at_cursor) | underlined | focused,
|
||||
text(part_after_cursor)
|
||||
) | flex | inverted | frame;
|
||||
) | flex | inverted | frame | main_decorator;
|
||||
|
||||
}
|
||||
bool Input::OnEvent(Event event) {
|
||||
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
||||
std::wstring c;
|
||||
|
||||
// Backspace.
|
||||
@@ -50,9 +54,14 @@ bool Input::OnEvent(Event event) {
|
||||
|
||||
// Enter.
|
||||
if (event == Event::Return) {
|
||||
on_enter();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event == Event::Custom) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (event == Event::ArrowLeft && cursor_position > 0) {
|
||||
cursor_position--;
|
||||
return true;
|
||||
|
@@ -6,6 +6,7 @@
|
||||
#include <iostream>
|
||||
#include "ftxui/component/component.hpp"
|
||||
#include "ftxui/screen/terminal.hpp"
|
||||
#include <thread>
|
||||
|
||||
namespace ftxui {
|
||||
|
||||
@@ -70,6 +71,28 @@ ScreenInteractive ScreenInteractive::FitComponent() {
|
||||
return ScreenInteractive(0, 0, Dimension::FitComponent);
|
||||
}
|
||||
|
||||
void ScreenInteractive::PostEvent(Event event) {
|
||||
std::unique_lock<std::mutex> lock(events_queue_mutex);
|
||||
events_queue.push(event);
|
||||
events_queue_wait.notify_one();
|
||||
}
|
||||
|
||||
void ScreenInteractive::EventLoop(Component* component) {
|
||||
bool handled = 0;
|
||||
for (;;) {
|
||||
std::unique_lock<std::mutex> lock(events_queue_mutex);
|
||||
while (!events_queue.empty()) {
|
||||
component->OnEvent(events_queue.front());
|
||||
events_queue.pop();
|
||||
handled = true;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
return;
|
||||
events_queue_wait.wait(lock);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenInteractive::Loop(Component* component) {
|
||||
//std::cout << "\033[?9h"; [> Send Mouse Row & Column on Button Press <]
|
||||
//std::cout << "\033[?1000h"; [> Send Mouse X & Y on button press and release <]
|
||||
@@ -89,18 +112,25 @@ void ScreenInteractive::Loop(Component* component) {
|
||||
terminal_configuration_new.c_lflag &= ~ECHO;
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_new);
|
||||
|
||||
std::thread read_char([this]() {
|
||||
while (!quit_)
|
||||
PostEvent(GetEvent());
|
||||
});
|
||||
|
||||
std::string reset_position;
|
||||
while (!quit_) {
|
||||
reset_position = ResetPosition();
|
||||
Draw(component);
|
||||
std::cout << reset_position << ToString() << std::flush;
|
||||
Clear();
|
||||
component->OnEvent(GetEvent());
|
||||
EventLoop(component);
|
||||
}
|
||||
|
||||
// Restore the old terminal configuration.
|
||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_old);
|
||||
|
||||
read_char.join();
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
|
@@ -5,13 +5,21 @@ namespace ftxui {
|
||||
|
||||
using namespace ftxui;
|
||||
|
||||
static wchar_t charset[] = L"┌┐└┘─│┬┴┤├";
|
||||
static wchar_t simple_border_charset[] = L"┌┐└┘─│┬┴┤├";
|
||||
|
||||
class Border : public Node {
|
||||
public:
|
||||
Border(Elements children) : Node(std::move(children)) {}
|
||||
Border(Elements children)
|
||||
: Node(std::move(children)),
|
||||
charset(std::begin(simple_border_charset),
|
||||
std::end(simple_border_charset)) {}
|
||||
Border(Elements children, Pixel pixel)
|
||||
: Node(std::move(children)), charset_pixel(10, pixel) {}
|
||||
~Border() override {}
|
||||
|
||||
std::vector<Pixel> charset_pixel;
|
||||
std::vector<wchar_t> charset;
|
||||
|
||||
void ComputeRequirement() override {
|
||||
Node::ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
@@ -52,6 +60,13 @@ class Border : public Node {
|
||||
if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max)
|
||||
return;
|
||||
|
||||
if (!charset.empty())
|
||||
RenderPixel(screen);
|
||||
else
|
||||
RenderChar(screen);
|
||||
}
|
||||
|
||||
void RenderPixel(Screen& screen) {
|
||||
screen.at(box_.x_min, box_.y_min) = charset[0];
|
||||
screen.at(box_.x_max, box_.y_min) = charset[1];
|
||||
screen.at(box_.x_min, box_.y_max) = charset[2];
|
||||
@@ -69,6 +84,21 @@ class Border : public Node {
|
||||
if (children.size() == 2)
|
||||
children[1]->Render(screen);
|
||||
}
|
||||
|
||||
void RenderChar(Screen& screen) {
|
||||
screen.PixelAt(box_.x_min, box_.y_min) = charset_pixel[0];
|
||||
screen.PixelAt(box_.x_max, box_.y_min) = charset_pixel[1];
|
||||
screen.PixelAt(box_.x_min, box_.y_max) = charset_pixel[2];
|
||||
screen.PixelAt(box_.x_max, box_.y_max) = charset_pixel[3];
|
||||
for(float x = box_.x_min + 1; x<box_.x_max; ++x) {
|
||||
screen.PixelAt(x, box_.y_min) = charset_pixel[4];
|
||||
screen.PixelAt(x, box_.y_max) = charset_pixel[4];
|
||||
}
|
||||
for(float y = box_.y_min + 1; y<box_.y_max; ++y) {
|
||||
screen.PixelAt(box_.x_min, y) = charset_pixel[5];
|
||||
screen.PixelAt(box_.x_max,y) = charset_pixel[5];
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> border(Element child) {
|
||||
@@ -79,9 +109,9 @@ std::unique_ptr<Node> window(Element title, Element content) {
|
||||
return std::make_unique<Border>(unpack(std::move(content), std::move(title)));
|
||||
}
|
||||
|
||||
Decorator boxed() {
|
||||
return [](Element child) {
|
||||
return border(std::move(child));
|
||||
Decorator borderWith(Pixel pixel) {
|
||||
return [pixel](Element child) {
|
||||
return std::make_unique<Border>(unpack(std::move(child)), pixel);
|
||||
};
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ class Flex : public Node {
|
||||
Flex() {}
|
||||
Flex(Element child) : Node(unpack(std::move(child))) {}
|
||||
~Flex() override {}
|
||||
void ComputeRequirement() {
|
||||
void ComputeRequirement() override {
|
||||
requirement_.min.x = 0;
|
||||
requirement_.min.y = 0;
|
||||
if (!children.empty()) {
|
||||
@@ -26,6 +26,23 @@ class Flex : public Node {
|
||||
}
|
||||
};
|
||||
|
||||
class NotFlex : public Flex {
|
||||
public:
|
||||
NotFlex() {}
|
||||
NotFlex(Element child) : Flex(std::move(child)) {}
|
||||
~NotFlex() override {}
|
||||
void ComputeRequirement() override {
|
||||
requirement_.min.x = 0;
|
||||
requirement_.min.y = 0;
|
||||
if (!children.empty()) {
|
||||
children[0]->ComputeRequirement();
|
||||
requirement_ = children[0]->requirement();
|
||||
}
|
||||
requirement_.flex.x = 0;
|
||||
requirement_.flex.y = 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> filler() {
|
||||
return std::make_unique<Flex>();
|
||||
}
|
||||
@@ -34,4 +51,8 @@ std::unique_ptr<Node> flex(Element child) {
|
||||
return std::make_unique<Flex>(std::move(child));
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> notflex(Element child) {
|
||||
return std::make_unique<NotFlex>(std::move(child));
|
||||
}
|
||||
|
||||
}; // namespace ftxui
|
||||
|
@@ -6,7 +6,7 @@ const wchar_t charset[] = L" ▗▐▖▄▟▌▙█";
|
||||
|
||||
class Graph : public Node {
|
||||
public:
|
||||
Graph(GraphFunction& graph_function) : graph_function_(graph_function) {}
|
||||
Graph(GraphFunction graph_function) : graph_function_(graph_function) {}
|
||||
~Graph() override {}
|
||||
|
||||
void ComputeRequirement() override {
|
||||
@@ -35,10 +35,10 @@ class Graph : public Node {
|
||||
}
|
||||
|
||||
private:
|
||||
GraphFunction& graph_function_;
|
||||
GraphFunction graph_function_;
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> graph(GraphFunction& graph_function) {
|
||||
std::unique_ptr<Node> graph(GraphFunction graph_function) {
|
||||
return std::make_unique<Graph>(graph_function);
|
||||
}
|
||||
|
||||
|
@@ -23,16 +23,34 @@ class Separator : public Node {
|
||||
else
|
||||
c = U'│';
|
||||
|
||||
Pixel p;
|
||||
p.character = c;
|
||||
RenderWithPixel(screen, p);
|
||||
}
|
||||
|
||||
void RenderWithPixel(Screen& screen, Pixel pixel) {
|
||||
for (int y = box_.y_min; y <= box_.y_max; ++y) {
|
||||
for (int x = box_.x_min; x <= box_.x_max; ++x) {
|
||||
screen.at(x, y) = c;
|
||||
screen.PixelAt(x, y) = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class SeparatorWithPixel : public Separator {
|
||||
public:
|
||||
SeparatorWithPixel(Pixel p) : p(p) {}
|
||||
~SeparatorWithPixel() override {}
|
||||
void Render(Screen& screen) override { RenderWithPixel(screen, p); }
|
||||
Pixel p;
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> separator() {
|
||||
return std::make_unique<Separator>();
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> separator(Pixel pixel) {
|
||||
return std::make_unique<SeparatorWithPixel>(pixel);
|
||||
}
|
||||
|
||||
}; // namespace ftxui
|
||||
|
Reference in New Issue
Block a user