mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-23 03:10:01 +08:00
Add example homepage.cpp
This commit is contained in:
parent
9117166541
commit
eacb634a9e
@ -16,3 +16,4 @@ example(radiobox_in_frame)
|
|||||||
example(tab_horizontal)
|
example(tab_horizontal)
|
||||||
example(tab_vertical)
|
example(tab_vertical)
|
||||||
example(toggle)
|
example(toggle)
|
||||||
|
example(homescreen)
|
||||||
|
244
examples/component/homescreen.cpp
Normal file
244
examples/component/homescreen.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#include <cmath>
|
||||||
|
#include <thread>
|
||||||
|
#include "ftxui/component/checkbox.hpp"
|
||||||
|
#include "ftxui/component/container.hpp"
|
||||||
|
#include "ftxui/component/input.hpp"
|
||||||
|
#include "ftxui/component/menu.hpp"
|
||||||
|
#include "ftxui/component/radiobox.hpp"
|
||||||
|
#include "ftxui/component/screen_interactive.hpp"
|
||||||
|
#include "ftxui/component/toggle.hpp"
|
||||||
|
#include "ftxui/screen/string.hpp"
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
int shift = 0;
|
||||||
|
class Graph {
|
||||||
|
public:
|
||||||
|
std::vector<int> operator()(int width, int height) {
|
||||||
|
std::vector<int> output(width);
|
||||||
|
for (int i = 0; i < width; ++i) {
|
||||||
|
float v = 0;
|
||||||
|
v += 0.1 * sin((i + shift) * 0.1);
|
||||||
|
v += 0.2 * sin((i + shift+10) * 0.15);
|
||||||
|
v += 0.1 * sin((i + shift) * 0.03);
|
||||||
|
v *= height;
|
||||||
|
v += 0.5 * height;
|
||||||
|
output[i] = v;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class HTopComponent : public Component {
|
||||||
|
Graph my_graph;
|
||||||
|
|
||||||
|
public:
|
||||||
|
HTopComponent() {}
|
||||||
|
~HTopComponent() override {}
|
||||||
|
|
||||||
|
Element Render() override {
|
||||||
|
return
|
||||||
|
vbox(
|
||||||
|
text(L"Frequency [Mhz]") | hcenter,
|
||||||
|
hbox(
|
||||||
|
vbox(
|
||||||
|
text(L"2400 "), filler(),
|
||||||
|
text(L"1200 "), filler(),
|
||||||
|
text(L"0% ")
|
||||||
|
),
|
||||||
|
graph(std::ref(my_graph))
|
||||||
|
) | flex,
|
||||||
|
separator(),
|
||||||
|
text(L"Utilization [%]") | hcenter,
|
||||||
|
hbox(
|
||||||
|
vbox(
|
||||||
|
text(L"100 "), filler(),
|
||||||
|
text(L"50 "), filler(),
|
||||||
|
text(L"0 ")
|
||||||
|
),
|
||||||
|
graph(std::ref(my_graph)) | color(Color::RedLight)
|
||||||
|
) | flex,
|
||||||
|
separator(),
|
||||||
|
text(L"Ram [Go]") | hcenter,
|
||||||
|
hbox(
|
||||||
|
vbox(
|
||||||
|
text(L"8192"), filler(),
|
||||||
|
text(L"4096 "), filler(),
|
||||||
|
text(L"0 ")
|
||||||
|
),
|
||||||
|
graph(std::ref(my_graph)) | color(Color::BlueLight)
|
||||||
|
) | flex
|
||||||
|
) | border;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CompilerComponent : public Component {
|
||||||
|
Container container = Container::Horizontal();
|
||||||
|
RadioBox compiler;
|
||||||
|
Container flag = Container::Vertical();
|
||||||
|
CheckBox flag_checkbox[4];
|
||||||
|
Container subcontainer = Container::Vertical();
|
||||||
|
Container input_container = Container::Horizontal();
|
||||||
|
Input input_add;
|
||||||
|
Menu input;
|
||||||
|
Input executable;
|
||||||
|
|
||||||
|
public:
|
||||||
|
~CompilerComponent() override {}
|
||||||
|
CompilerComponent() {
|
||||||
|
Add(&container);
|
||||||
|
|
||||||
|
// Compiler ----------------------------------------------------------------
|
||||||
|
compiler.entries = {
|
||||||
|
L"gcc",
|
||||||
|
L"clang",
|
||||||
|
L"emcc",
|
||||||
|
L"game_maker"
|
||||||
|
};
|
||||||
|
container.Add(&compiler);
|
||||||
|
|
||||||
|
// Flags ----------------------------------------------------------------
|
||||||
|
container.Add(&flag);
|
||||||
|
flag_checkbox[0].label = L"-Wall";
|
||||||
|
flag_checkbox[1].label = L"-Werror";
|
||||||
|
flag_checkbox[2].label = L"-lpthread";
|
||||||
|
flag_checkbox[3].label = L"-O3";
|
||||||
|
for(auto& c : flag_checkbox)
|
||||||
|
flag.Add(&c);
|
||||||
|
|
||||||
|
container.Add(&subcontainer);
|
||||||
|
// Executable ----------------------------------------------------------------
|
||||||
|
executable.placeholder = L"executable";
|
||||||
|
subcontainer.Add(&executable);
|
||||||
|
|
||||||
|
// Input ----------------------------------------------------------------
|
||||||
|
subcontainer.Add(&input_container);
|
||||||
|
|
||||||
|
input_add.placeholder = L"input files";
|
||||||
|
input_add.on_enter = [this] {
|
||||||
|
input.entries.push_back(input_add.content);
|
||||||
|
input_add.content = L"";
|
||||||
|
};
|
||||||
|
input_container.Add(&input_add);
|
||||||
|
input_container.Add(&input);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() override {
|
||||||
|
return
|
||||||
|
vbox(
|
||||||
|
hbox(
|
||||||
|
window(text(L"Compiler"), compiler.Render()),
|
||||||
|
window(text(L"Flags"), flag.Render()),
|
||||||
|
vbox(
|
||||||
|
window(text(L"Executable:"), executable.Render())
|
||||||
|
| size(WIDTH, EQUAL, 20),
|
||||||
|
window(text(L"Input"),
|
||||||
|
hbox(
|
||||||
|
vbox(
|
||||||
|
hbox(text(L"Add: "), input_add.Render())
|
||||||
|
| size(WIDTH, EQUAL, 20)
|
||||||
|
| size(HEIGHT, EQUAL, 1),
|
||||||
|
filler()
|
||||||
|
),
|
||||||
|
separator(),
|
||||||
|
input.Render() | frame | size(HEIGHT, EQUAL, 3) | flex
|
||||||
|
)
|
||||||
|
) | size(WIDTH, EQUAL, 60)
|
||||||
|
),
|
||||||
|
filler()
|
||||||
|
),
|
||||||
|
hflow(RenderCommandLine())
|
||||||
|
) | border;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elements RenderCommandLine() {
|
||||||
|
Elements line;
|
||||||
|
// Compiler
|
||||||
|
line.push_back(text(compiler.entries[compiler.selected]) | bold);
|
||||||
|
// flags
|
||||||
|
for(auto& it : flag_checkbox) {
|
||||||
|
if (it.state) {
|
||||||
|
line.push_back(text(L" "));
|
||||||
|
line.push_back(text(it.label) | dim);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Executable
|
||||||
|
if (!executable.content.empty()) {
|
||||||
|
line.push_back(text(L" -O ") | bold);
|
||||||
|
line.push_back(text(executable.content) | color(Color::BlueLight) | bold);
|
||||||
|
}
|
||||||
|
// Input
|
||||||
|
for(auto& it : input.entries) {
|
||||||
|
line.push_back(text(L" " + it) | color(Color::RedLight));
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class SpinnerComponent : public Component {
|
||||||
|
Element Render() override {
|
||||||
|
Elements entries;
|
||||||
|
for(int i = 0; i<22; ++i) {
|
||||||
|
if (i != 0)
|
||||||
|
entries.push_back(
|
||||||
|
spinner(i, shift/2)
|
||||||
|
| bold
|
||||||
|
| size(WIDTH, GREATER_THAN, 2)
|
||||||
|
| border
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return hflow(std::move(entries)) | border;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Tab : public Component {
|
||||||
|
public:
|
||||||
|
Container main_container = Container::Vertical();
|
||||||
|
|
||||||
|
Toggle tab_selection;
|
||||||
|
Container container = Container::Tab(&tab_selection.selected);
|
||||||
|
|
||||||
|
HTopComponent htop;
|
||||||
|
CompilerComponent compiler;
|
||||||
|
SpinnerComponent spinner_component;
|
||||||
|
|
||||||
|
Tab() {
|
||||||
|
Add(&main_container);
|
||||||
|
main_container.Add(&tab_selection);
|
||||||
|
tab_selection.entries = {
|
||||||
|
L"compiler",
|
||||||
|
L"htop",
|
||||||
|
L"spinner"
|
||||||
|
};
|
||||||
|
main_container.Add(&container);
|
||||||
|
container.Add(&compiler);
|
||||||
|
container.Add(&htop);
|
||||||
|
container.Add(&spinner_component);
|
||||||
|
}
|
||||||
|
|
||||||
|
Element Render() override {
|
||||||
|
return vbox(
|
||||||
|
text(L"FTXUI Demo") | bold | hcenter,
|
||||||
|
tab_selection.Render() | hcenter,
|
||||||
|
container.Render()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, const char* argv[]) {
|
||||||
|
auto screen = ScreenInteractive::Fullscreen();
|
||||||
|
|
||||||
|
std::thread update([&screen]() {
|
||||||
|
for (;;) {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
std::this_thread::sleep_for(0.05s);
|
||||||
|
shift++;
|
||||||
|
screen.PostEvent(Event::Custom);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Tab tab;
|
||||||
|
screen.Loop(&tab);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,13 +1,12 @@
|
|||||||
#include "ftxui/dom/elements.hpp"
|
|
||||||
#include "ftxui/dom/graph.hpp"
|
|
||||||
#include "ftxui/screen/screen.hpp"
|
|
||||||
#include "ftxui/screen/string.hpp"
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "ftxui/dom/elements.hpp"
|
||||||
|
#include "ftxui/screen/screen.hpp"
|
||||||
|
#include "ftxui/screen/string.hpp"
|
||||||
|
|
||||||
class Graph : public ftxui::GraphFunction {
|
class Graph {
|
||||||
public:
|
public:
|
||||||
std::vector<int> operator()(int width, int height) {
|
std::vector<int> operator()(int width, int height) {
|
||||||
std::vector<int> output(width);
|
std::vector<int> output(width);
|
||||||
@ -16,8 +15,6 @@ class Graph : public ftxui::GraphFunction {
|
|||||||
v += 0.1 * sin((i + shift) * 0.1);
|
v += 0.1 * sin((i + shift) * 0.1);
|
||||||
v += 0.2 * sin((i + shift+10) * 0.15);
|
v += 0.2 * sin((i + shift+10) * 0.15);
|
||||||
v += 0.1 * sin((i + shift) * 0.03);
|
v += 0.1 * sin((i + shift) * 0.03);
|
||||||
// v += 0.2*sin((i+shift)*0.3);
|
|
||||||
// v += 0.1*sin((i+shift)*0.9);
|
|
||||||
v *= height;
|
v *= height;
|
||||||
v += 0.5 * height;
|
v += 0.5 * height;
|
||||||
output[i] = v;
|
output[i] = v;
|
||||||
@ -27,6 +24,14 @@ class Graph : public ftxui::GraphFunction {
|
|||||||
int shift = 0;
|
int shift = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::vector<int> triangle(int width, int height) {
|
||||||
|
std::vector<int> output(width);
|
||||||
|
for (int i = 0; i < width; ++i) {
|
||||||
|
output[i] = i % (height - 4) + 2;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
@ -36,20 +41,20 @@ int main(int argc, const char* argv[]) {
|
|||||||
std::string reset_position;
|
std::string reset_position;
|
||||||
for (int i = 0;; ++i) {
|
for (int i = 0;; ++i) {
|
||||||
auto document =
|
auto document =
|
||||||
window(text(L"Your graphs"),
|
|
||||||
hbox(
|
hbox(
|
||||||
vbox(
|
vbox(
|
||||||
graph(my_graph), separator(),
|
graph(std::ref(my_graph)), separator(),
|
||||||
graph(my_graph) | inverted
|
graph(triangle) | inverted
|
||||||
) | flex,
|
) | flex,
|
||||||
separator(),
|
separator(),
|
||||||
vbox(
|
vbox(
|
||||||
graph(my_graph) | color(Color::BlueLight), separator(),
|
graph(std::ref(my_graph)) | color(Color::BlueLight), separator(),
|
||||||
graph(my_graph) | color(Color::RedLight), separator(),
|
graph(std::ref(my_graph)) | color(Color::RedLight), separator(),
|
||||||
graph(my_graph) | color(Color::YellowLight)
|
graph(std::ref(my_graph)) | color(Color::YellowLight)
|
||||||
) | flex
|
) | flex
|
||||||
)
|
)
|
||||||
) | size(HEIGHT, GREATER_THAN, 40);
|
| border
|
||||||
|
| size(HEIGHT, GREATER_THAN, 40);
|
||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document.get());
|
Render(screen, document.get());
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
cmake_minimum_required(VERSION 3.0)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
find_package(Threads)
|
||||||
|
|
||||||
add_library(screen
|
add_library(screen
|
||||||
src/ftxui/screen/box.cpp
|
src/ftxui/screen/box.cpp
|
||||||
@ -48,7 +49,7 @@ add_library(component
|
|||||||
|
|
||||||
target_link_libraries(dom PUBLIC screen)
|
target_link_libraries(dom PUBLIC screen)
|
||||||
target_link_libraries(component PUBLIC dom)
|
target_link_libraries(component PUBLIC dom)
|
||||||
|
target_link_libraries(component PUBLIC Threads::Threads)
|
||||||
|
|
||||||
foreach(lib screen dom component)
|
foreach(lib screen dom component)
|
||||||
target_include_directories(${lib}
|
target_include_directories(${lib}
|
||||||
@ -86,7 +87,6 @@ install(EXPORT ftxui-export
|
|||||||
# Note: For gtest, please follow:
|
# Note: For gtest, please follow:
|
||||||
# https://stackoverflow.com/questions/24295876/cmake-cannot-find-a-googletest-required-library
|
# https://stackoverflow.com/questions/24295876/cmake-cannot-find-a-googletest-required-library
|
||||||
find_package(GTest)
|
find_package(GTest)
|
||||||
find_package(Threads)
|
|
||||||
if (GTEST_FOUND AND THREADS_FOUND)
|
if (GTEST_FOUND AND THREADS_FOUND)
|
||||||
add_executable(dom_tests
|
add_executable(dom_tests
|
||||||
src/ftxui/dom/gauge_test.cpp
|
src/ftxui/dom/gauge_test.cpp
|
||||||
|
@ -24,10 +24,14 @@ struct Event{
|
|||||||
static Event Escape;
|
static Event Escape;
|
||||||
static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
|
static Event F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12;
|
||||||
|
|
||||||
|
// --- Custom ---
|
||||||
|
static Event Custom;
|
||||||
|
|
||||||
bool operator==(const Event& other) { return values == other.values; }
|
bool operator==(const Event& other) { return values == other.values; }
|
||||||
|
|
||||||
// Internal representation.
|
// Internal representation.
|
||||||
std::array<int, 5> values = {0, 0, 0, 0, 0};
|
std::array<int, 5> values = {0, 0, 0, 0, 0};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
#ifndef FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
#ifndef FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
||||||
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
#define FTXUI_COMPONENT_SCREEN_INTERACTIVE_HPP
|
||||||
|
|
||||||
#include "ftxui/screen/screen.hpp"
|
#include <condition_variable>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <mutex>
|
||||||
|
#include <queue>
|
||||||
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "ftxui/component/event.hpp"
|
||||||
|
#include "ftxui/screen/screen.hpp"
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
class Component;
|
class Component;
|
||||||
@ -19,9 +25,11 @@ class ScreenInteractive : public Screen {
|
|||||||
void Loop(Component*);
|
void Loop(Component*);
|
||||||
std::function<void()> ExitLoopClosure();
|
std::function<void()> ExitLoopClosure();
|
||||||
|
|
||||||
|
void PostEvent(Event event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Draw(Component* component);
|
void Draw(Component* component);
|
||||||
bool quit_ = false;
|
void EventLoop(Component* component);
|
||||||
|
|
||||||
enum class Dimension {
|
enum class Dimension {
|
||||||
FitComponent,
|
FitComponent,
|
||||||
@ -31,6 +39,11 @@ class ScreenInteractive : public Screen {
|
|||||||
};
|
};
|
||||||
Dimension dimension_ = Dimension::Fixed;
|
Dimension dimension_ = Dimension::Fixed;
|
||||||
ScreenInteractive(int dimx, int dimy, Dimension dimension);
|
ScreenInteractive(int dimx, int dimy, Dimension dimension);
|
||||||
|
|
||||||
|
std::condition_variable events_queue_wait;
|
||||||
|
std::mutex events_queue_mutex;
|
||||||
|
std::queue<Event> events_queue;
|
||||||
|
std::atomic<bool> quit_ = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
|
||||||
#include "ftxui/dom/graph.hpp"
|
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp"
|
||||||
#include "ftxui/screen/color.hpp"
|
#include "ftxui/screen/color.hpp"
|
||||||
|
|
||||||
@ -12,16 +11,19 @@ namespace ftxui {
|
|||||||
using Element = std::unique_ptr<Node>;
|
using Element = std::unique_ptr<Node>;
|
||||||
using Elements = std::vector<Element>;
|
using Elements = std::vector<Element>;
|
||||||
using Decorator = std::function<Element(Element)>;
|
using Decorator = std::function<Element(Element)>;
|
||||||
|
using GraphFunction = std::function<std::vector<int>(int,int)>;
|
||||||
|
|
||||||
// --- Widget ---
|
// --- Widget ---
|
||||||
Element text(std::wstring text);
|
Element text(std::wstring text);
|
||||||
Element separator();
|
Element separator();
|
||||||
|
Element separator(Pixel);
|
||||||
Element gauge(float ratio);
|
Element gauge(float ratio);
|
||||||
Element border(Element);
|
Element border(Element);
|
||||||
|
Decorator borderWith(Pixel);
|
||||||
Element window(Element title, Element content);
|
Element window(Element title, Element content);
|
||||||
Element spinner(int charset_index, size_t image_index);
|
Element spinner(int charset_index, size_t image_index);
|
||||||
Elements paragraph(std::wstring text); // Use inside hflow(). Split by space.
|
Elements paragraph(std::wstring text); // Use inside hflow(). Split by space.
|
||||||
Element graph(GraphFunction&); // See graph.hpp
|
Element graph(GraphFunction);
|
||||||
|
|
||||||
// -- Decorator ---
|
// -- Decorator ---
|
||||||
Element bold(Element);
|
Element bold(Element);
|
||||||
@ -46,6 +48,7 @@ Element hflow(Elements);
|
|||||||
// container.
|
// container.
|
||||||
Element filler();
|
Element filler();
|
||||||
Element flex(Element);
|
Element flex(Element);
|
||||||
|
Element notflex(Element);
|
||||||
|
|
||||||
// -- Size override;
|
// -- Size override;
|
||||||
enum Direction { WIDTH, HEIGHT };
|
enum Direction { WIDTH, HEIGHT };
|
||||||
|
@ -1,15 +0,0 @@
|
|||||||
#ifndef FTXUI_DOM_GRAPH_HPP
|
|
||||||
#define FTXUI_DOM_GRAPH_HPP
|
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp"
|
|
||||||
|
|
||||||
namespace ftxui {
|
|
||||||
|
|
||||||
class GraphFunction {
|
|
||||||
public:
|
|
||||||
virtual std::vector<int> operator()(int width, int height) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace ftxui
|
|
||||||
|
|
||||||
#endif /* end of include guard: FTXUI_DOM_GRAPH_HPP */
|
|
@ -34,4 +34,6 @@ Event Event::F10{ESC, '[', '2', '1', '~'};
|
|||||||
Event Event::F11{ESC, '[', '2', '1', '~'}; // Same as F10 ?
|
Event Event::F11{ESC, '[', '2', '1', '~'}; // Same as F10 ?
|
||||||
Event Event::F12{ESC, '[', '2', '4', '~'};
|
Event Event::F12{ESC, '[', '2', '4', '~'};
|
||||||
|
|
||||||
|
Event Event::Custom{0, 0, 0, 0, 0};
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
@ -5,19 +5,21 @@ namespace ftxui {
|
|||||||
|
|
||||||
// Component implementation.
|
// Component implementation.
|
||||||
Element Input::Render() {
|
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();
|
bool is_focused = Focused();
|
||||||
|
|
||||||
// Placeholder.
|
// Placeholder.
|
||||||
if (content.size() == 0) {
|
if (content.size() == 0) {
|
||||||
if (is_focused)
|
if (is_focused)
|
||||||
return text(placeholder) | dim | inverted | flex;
|
return text(placeholder) | dim | inverted | main_decorator;
|
||||||
else
|
else
|
||||||
return text(placeholder) | dim | flex;
|
return text(placeholder) | dim | main_decorator;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Not focused.
|
// Not focused.
|
||||||
if (!is_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_before_cursor = content.substr(0,cursor_position);
|
||||||
std::wstring part_at_cursor = cursor_position < (int)content.size()
|
std::wstring part_at_cursor = cursor_position < (int)content.size()
|
||||||
@ -34,9 +36,11 @@ Element Input::Render() {
|
|||||||
text(part_before_cursor),
|
text(part_before_cursor),
|
||||||
text(part_at_cursor) | underlined | focused,
|
text(part_at_cursor) | underlined | focused,
|
||||||
text(part_after_cursor)
|
text(part_after_cursor)
|
||||||
) | flex | inverted | frame;
|
) | flex | inverted | frame | main_decorator;
|
||||||
|
|
||||||
}
|
}
|
||||||
bool Input::OnEvent(Event event) {
|
bool Input::OnEvent(Event event) {
|
||||||
|
cursor_position = std::max(0, std::min<int>(content.size(), cursor_position));
|
||||||
std::wstring c;
|
std::wstring c;
|
||||||
|
|
||||||
// Backspace.
|
// Backspace.
|
||||||
@ -50,9 +54,14 @@ bool Input::OnEvent(Event event) {
|
|||||||
|
|
||||||
// Enter.
|
// Enter.
|
||||||
if (event == Event::Return) {
|
if (event == Event::Return) {
|
||||||
|
on_enter();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event == Event::Custom) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (event == Event::ArrowLeft && cursor_position > 0) {
|
if (event == Event::ArrowLeft && cursor_position > 0) {
|
||||||
cursor_position--;
|
cursor_position--;
|
||||||
return true;
|
return true;
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "ftxui/component/component.hpp"
|
#include "ftxui/component/component.hpp"
|
||||||
#include "ftxui/screen/terminal.hpp"
|
#include "ftxui/screen/terminal.hpp"
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
@ -70,6 +71,28 @@ ScreenInteractive ScreenInteractive::FitComponent() {
|
|||||||
return ScreenInteractive(0, 0, Dimension::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) {
|
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 <]
|
||||||
@ -89,18 +112,25 @@ void ScreenInteractive::Loop(Component* component) {
|
|||||||
terminal_configuration_new.c_lflag &= ~ECHO;
|
terminal_configuration_new.c_lflag &= ~ECHO;
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_new);
|
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_new);
|
||||||
|
|
||||||
|
std::thread read_char([this]() {
|
||||||
|
while (!quit_)
|
||||||
|
PostEvent(GetEvent());
|
||||||
|
});
|
||||||
|
|
||||||
std::string reset_position;
|
std::string reset_position;
|
||||||
while (!quit_) {
|
while (!quit_) {
|
||||||
reset_position = ResetPosition();
|
reset_position = ResetPosition();
|
||||||
Draw(component);
|
Draw(component);
|
||||||
std::cout << reset_position << ToString() << std::flush;
|
std::cout << reset_position << ToString() << std::flush;
|
||||||
Clear();
|
Clear();
|
||||||
component->OnEvent(GetEvent());
|
EventLoop(component);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restore the old terminal configuration.
|
// Restore the old terminal configuration.
|
||||||
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_old);
|
tcsetattr(STDIN_FILENO, TCSANOW, &terminal_configuration_old);
|
||||||
|
|
||||||
|
read_char.join();
|
||||||
|
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,13 +5,21 @@ namespace ftxui {
|
|||||||
|
|
||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
static wchar_t charset[] = L"┌┐└┘─│┬┴┤├";
|
static wchar_t simple_border_charset[] = L"┌┐└┘─│┬┴┤├";
|
||||||
|
|
||||||
class Border : public Node {
|
class Border : public Node {
|
||||||
public:
|
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 {}
|
~Border() override {}
|
||||||
|
|
||||||
|
std::vector<Pixel> charset_pixel;
|
||||||
|
std::vector<wchar_t> charset;
|
||||||
|
|
||||||
void ComputeRequirement() override {
|
void ComputeRequirement() override {
|
||||||
Node::ComputeRequirement();
|
Node::ComputeRequirement();
|
||||||
requirement_ = children[0]->requirement();
|
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)
|
if (box_.x_min >= box_.x_max || box_.y_min >= box_.y_max)
|
||||||
return;
|
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_min, box_.y_min) = charset[0];
|
||||||
screen.at(box_.x_max, box_.y_min) = charset[1];
|
screen.at(box_.x_max, box_.y_min) = charset[1];
|
||||||
screen.at(box_.x_min, box_.y_max) = charset[2];
|
screen.at(box_.x_min, box_.y_max) = charset[2];
|
||||||
@ -69,6 +84,21 @@ class Border : public Node {
|
|||||||
if (children.size() == 2)
|
if (children.size() == 2)
|
||||||
children[1]->Render(screen);
|
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) {
|
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)));
|
return std::make_unique<Border>(unpack(std::move(content), std::move(title)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Decorator boxed() {
|
Decorator borderWith(Pixel pixel) {
|
||||||
return [](Element child) {
|
return [pixel](Element child) {
|
||||||
return border(std::move(child));
|
return std::make_unique<Border>(unpack(std::move(child)), pixel);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ class Flex : public Node {
|
|||||||
Flex() {}
|
Flex() {}
|
||||||
Flex(Element child) : Node(unpack(std::move(child))) {}
|
Flex(Element child) : Node(unpack(std::move(child))) {}
|
||||||
~Flex() override {}
|
~Flex() override {}
|
||||||
void ComputeRequirement() {
|
void ComputeRequirement() override {
|
||||||
requirement_.min.x = 0;
|
requirement_.min.x = 0;
|
||||||
requirement_.min.y = 0;
|
requirement_.min.y = 0;
|
||||||
if (!children.empty()) {
|
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() {
|
std::unique_ptr<Node> filler() {
|
||||||
return std::make_unique<Flex>();
|
return std::make_unique<Flex>();
|
||||||
}
|
}
|
||||||
@ -34,4 +51,8 @@ std::unique_ptr<Node> flex(Element child) {
|
|||||||
return std::make_unique<Flex>(std::move(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
|
}; // namespace ftxui
|
||||||
|
@ -6,7 +6,7 @@ const wchar_t charset[] = L" ▗▐▖▄▟▌▙█";
|
|||||||
|
|
||||||
class Graph : public Node {
|
class Graph : public Node {
|
||||||
public:
|
public:
|
||||||
Graph(GraphFunction& graph_function) : graph_function_(graph_function) {}
|
Graph(GraphFunction graph_function) : graph_function_(graph_function) {}
|
||||||
~Graph() override {}
|
~Graph() override {}
|
||||||
|
|
||||||
void ComputeRequirement() override {
|
void ComputeRequirement() override {
|
||||||
@ -35,10 +35,10 @@ class Graph : public Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
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);
|
return std::make_unique<Graph>(graph_function);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,16 +23,34 @@ class Separator : public Node {
|
|||||||
else
|
else
|
||||||
c = U'│';
|
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 y = box_.y_min; y <= box_.y_max; ++y) {
|
||||||
for (int x = box_.x_min; x <= box_.x_max; ++x) {
|
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() {
|
std::unique_ptr<Node> separator() {
|
||||||
return std::make_unique<Separator>();
|
return std::make_unique<Separator>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Node> separator(Pixel pixel) {
|
||||||
|
return std::make_unique<SeparatorWithPixel>(pixel);
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace ftxui
|
}; // namespace ftxui
|
||||||
|
Loading…
Reference in New Issue
Block a user