mirror of
				https://github.com/ArthurSonzogni/FTXUI.git
				synced 2025-11-04 13:38:14 +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:
		@@ -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);
 | 
			
		||||
		Reference in New Issue
	
	Block a user