From 911716654164751c04238b5ebeabdc50abe39521 Mon Sep 17 00:00:00 2001 From: ArthurSonzogni Date: Sat, 26 Jan 2019 21:52:55 +0100 Subject: [PATCH] Add Graph. --- examples/component/gallery.cpp | 2 +- examples/dom/CMakeLists.txt | 1 + examples/dom/border.cpp | 2 +- examples/dom/dbox.cpp | 2 +- examples/dom/graph.cpp | 65 +++++++++++++++++ examples/dom/hflow.cpp | 2 +- examples/dom/html_like.cpp | 2 +- examples/dom/package_manager.cpp | 2 +- examples/dom/paragraph.cpp | 2 +- examples/dom/separator.cpp | 17 ++--- examples/dom/size.cpp | 2 +- examples/dom/spinner.cpp | 2 +- examples/dom/style_blink.cpp | 2 +- examples/dom/style_bold.cpp | 2 +- examples/dom/style_color.cpp | 2 +- examples/dom/style_dim.cpp | 2 +- examples/dom/style_gallery.cpp | 2 +- examples/dom/style_inverted.cpp | 2 +- examples/dom/style_underlined.cpp | 2 +- examples/dom/vbox_hbox.cpp | 2 +- ftxui/CMakeLists.txt | 1 + ftxui/include/ftxui/component/checkbox.hpp | 2 +- .../ftxui/component/screen_interactive.hpp | 4 +- ftxui/include/ftxui/dom/elements.hpp | 3 + ftxui/include/ftxui/dom/graph.hpp | 15 ++++ ftxui/include/ftxui/screen/screen.hpp | 30 ++++---- .../ftxui/component/screen_interactive.cpp | 10 +-- ftxui/src/ftxui/dom/graph.cpp | 45 ++++++++++++ ftxui/src/ftxui/dom/hflow.cpp | 2 +- ftxui/src/ftxui/dom/util.cpp | 7 ++ ftxui/src/ftxui/screen/screen.cpp | 70 ++++++++++--------- 31 files changed, 226 insertions(+), 80 deletions(-) create mode 100644 examples/dom/graph.cpp create mode 100644 ftxui/include/ftxui/dom/graph.hpp create mode 100644 ftxui/src/ftxui/dom/graph.cpp diff --git a/examples/component/gallery.cpp b/examples/component/gallery.cpp index 37f1264..9458442 100644 --- a/examples/component/gallery.cpp +++ b/examples/component/gallery.cpp @@ -73,7 +73,7 @@ class MyComponent : public Component { separator(), Render(L"radiobox", radiobox), separator(), - Render(L"input", input) | size(WIDTH, EQUAL, 20) + Render(L"input", input) | size(WIDTH, LESS_THAN, 30) ) | border; } }; diff --git a/examples/dom/CMakeLists.txt b/examples/dom/CMakeLists.txt index 1aa7aa5..422adfe 100644 --- a/examples/dom/CMakeLists.txt +++ b/examples/dom/CMakeLists.txt @@ -8,6 +8,7 @@ example(border) example(gauge) example(package_manager) example(separator) +example(graph) example(spinner) example(style_blink) example(style_bold) diff --git a/examples/dom/border.cpp b/examples/dom/border.cpp index 6a5a2f9..e994b0e 100644 --- a/examples/dom/border.cpp +++ b/examples/dom/border.cpp @@ -41,7 +41,7 @@ int main(int argc, const char *argv[]) ), filler() ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString() << std::endl; } diff --git a/examples/dom/dbox.cpp b/examples/dom/dbox.cpp index cb8b07e..df12fb4 100644 --- a/examples/dom/dbox.cpp +++ b/examples/dom/dbox.cpp @@ -16,7 +16,7 @@ int main(int argc, const char *argv[]) ) | border, text(L"overlay") | border | center ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/graph.cpp b/examples/dom/graph.cpp new file mode 100644 index 0000000..e600cf8 --- /dev/null +++ b/examples/dom/graph.cpp @@ -0,0 +1,65 @@ +#include "ftxui/dom/elements.hpp" +#include "ftxui/dom/graph.hpp" +#include "ftxui/screen/screen.hpp" +#include "ftxui/screen/string.hpp" +#include +#include +#include +#include + +class Graph : public ftxui::GraphFunction { + public: + std::vector operator()(int width, int height) { + std::vector output(width); + for (int i = 0; i < width; ++i) { + float v = 0; + v += 0.1 * sin((i + shift) * 0.1); + v += 0.2 * sin((i + shift+10) * 0.15); + v += 0.1 * sin((i + shift) * 0.03); + // v += 0.2*sin((i+shift)*0.3); + // v += 0.1*sin((i+shift)*0.9); + v *= height; + v += 0.5 * height; + output[i] = v; + } + return output; + } + int shift = 0; +}; + +int main(int argc, const char* argv[]) { + using namespace ftxui; + using namespace std::chrono_literals; + + Graph my_graph; + + std::string reset_position; + for (int i = 0;; ++i) { + auto document = + window(text(L"Your graphs"), + hbox( + vbox( + graph(my_graph), separator(), + graph(my_graph) | inverted + ) | flex, + separator(), + vbox( + graph(my_graph) | color(Color::BlueLight), separator(), + graph(my_graph) | color(Color::RedLight), separator(), + graph(my_graph) | color(Color::YellowLight) + ) | flex + ) + ) | size(HEIGHT, GREATER_THAN, 40); + + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + Render(screen, document.get()); + std::cout << reset_position << screen.ToString() << std::flush; + + reset_position = screen.ResetPosition(); + + std::this_thread::sleep_for(0.03s); + my_graph.shift++; + } + + return 0; +} diff --git a/examples/dom/hflow.cpp b/examples/dom/hflow.cpp index ae0e6b5..1619844 100644 --- a/examples/dom/hflow.cpp +++ b/examples/dom/hflow.cpp @@ -43,7 +43,7 @@ int main(int argc, const char *argv[]) | size(WIDTH, LESS_THAN, 50) ; - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString() << std::endl; diff --git a/examples/dom/html_like.cpp b/examples/dom/html_like.cpp index 2a4f667..4147b5b 100644 --- a/examples/dom/html_like.cpp +++ b/examples/dom/html_like.cpp @@ -39,7 +39,7 @@ int main(int argc, const char* argv[]) { paragraph(L" A spinner "), spinner(6, i / 10)) | border; - auto screen = Screen::TerminalFullscreen(); + auto screen = Screen::Create(Dimension::Full()); Render(screen, document.get()); std::cout << reset_position << screen.ToString() << std::flush; diff --git a/examples/dom/package_manager.cpp b/examples/dom/package_manager.cpp index 3f32822..328ac1f 100644 --- a/examples/dom/package_manager.cpp +++ b/examples/dom/package_manager.cpp @@ -115,7 +115,7 @@ int main(int argc, const char *argv[]) // Draw. auto document = render(); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << reset_position << screen.ToString() << std::flush; reset_position = screen.ResetPosition(); diff --git a/examples/dom/paragraph.cpp b/examples/dom/paragraph.cpp index 8c747c9..529f23e 100644 --- a/examples/dom/paragraph.cpp +++ b/examples/dom/paragraph.cpp @@ -24,7 +24,7 @@ int main(int argc, const char *argv[]) ) | flex ); - auto screen = Screen::TerminalFullscreen(); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); getchar(); diff --git a/examples/dom/separator.cpp b/examples/dom/separator.cpp index 01ca83b..3af4114 100644 --- a/examples/dom/separator.cpp +++ b/examples/dom/separator.cpp @@ -9,17 +9,18 @@ int main(int argc, const char *argv[]) hbox( text(L"left-column"), separator(), - flex(vbox( - center(text(L"right-column")) | flex, + vbox( + center(text(L"right-top")) | flex, separator(), - center(text(L"bottom-column")) - )) - ); - auto screen = Screen::TerminalFullscreen(); + center(text(L"bottom-bottom")) + ) | flex, + separator(), + text(L"right-column") + ) | border; + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); - std::cout << screen.ToString(); - getchar(); + std::cout << screen.ToString() << std::endl; return 0; } diff --git a/examples/dom/size.cpp b/examples/dom/size.cpp index 6d91091..3bce0c1 100644 --- a/examples/dom/size.cpp +++ b/examples/dom/size.cpp @@ -22,7 +22,7 @@ int main(int argc, const char *argv[]) ); } auto document = hbox(std::move(content)); - auto screen = Screen::FitDocument(document); + auto screen = Screen::Create(Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString() << std::endl; diff --git a/examples/dom/spinner.cpp b/examples/dom/spinner.cpp index 835a2c9..56307b4 100644 --- a/examples/dom/spinner.cpp +++ b/examples/dom/spinner.cpp @@ -26,7 +26,7 @@ int main(int argc, const char *argv[]) ); } auto document = hbox(vbox(std::move(entries)) | border, filler()); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << reset_position << screen.ToString() << std::flush; reset_position = screen.ResetPosition(); diff --git a/examples/dom/style_blink.cpp b/examples/dom/style_blink.cpp index a40f95d..3a7814c 100644 --- a/examples/dom/style_blink.cpp +++ b/examples/dom/style_blink.cpp @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) text(L"blink") | blink, text(L". Do you like it?") ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_bold.cpp b/examples/dom/style_bold.cpp index 24d0fb5..c612b72 100644 --- a/examples/dom/style_bold.cpp +++ b/examples/dom/style_bold.cpp @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) text(L"bold") | bold, text(L". Do you like it?") ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_color.cpp b/examples/dom/style_color.cpp index 2002b54..8b05578 100644 --- a/examples/dom/style_color.cpp +++ b/examples/dom/style_color.cpp @@ -48,7 +48,7 @@ int main(int argc, const char *argv[]) filler() ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_dim.cpp b/examples/dom/style_dim.cpp index 57a9bd4..7299f6b 100644 --- a/examples/dom/style_dim.cpp +++ b/examples/dom/style_dim.cpp @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) text(L"dim") | dim, text(L". Do you like it?") ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_gallery.cpp b/examples/dom/style_gallery.cpp index 9ecc0aa..82528d2 100644 --- a/examples/dom/style_gallery.cpp +++ b/examples/dom/style_gallery.cpp @@ -16,7 +16,7 @@ int main(int argc, const char *argv[]) text(L"color") | color(Color::Blue) , text(L" ") , text(L"bgcolor") | bgcolor(Color::Blue) ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_inverted.cpp b/examples/dom/style_inverted.cpp index 53e03f9..7f0f6fa 100644 --- a/examples/dom/style_inverted.cpp +++ b/examples/dom/style_inverted.cpp @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) text(L"inverted") | inverted, text(L". Do you like it?") ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/style_underlined.cpp b/examples/dom/style_underlined.cpp index c5f68f1..3b63bcf 100644 --- a/examples/dom/style_underlined.cpp +++ b/examples/dom/style_underlined.cpp @@ -11,7 +11,7 @@ int main(int argc, const char *argv[]) text(L"underlined") | underlined, text(L". Do you like it?") ); - auto screen = Screen::TerminalOutput(document); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/examples/dom/vbox_hbox.cpp b/examples/dom/vbox_hbox.cpp index a9cec20..fcf390b 100644 --- a/examples/dom/vbox_hbox.cpp +++ b/examples/dom/vbox_hbox.cpp @@ -28,7 +28,7 @@ int main(int argc, const char *argv[]) text(L"south-east") ) ); - auto screen = Screen::TerminalFullscreen(); + auto screen = Screen::Create(Dimension::Full()); Render(screen, document.get()); std::cout << screen.ToString(); diff --git a/ftxui/CMakeLists.txt b/ftxui/CMakeLists.txt index 7cf89e5..c5451b0 100644 --- a/ftxui/CMakeLists.txt +++ b/ftxui/CMakeLists.txt @@ -18,6 +18,7 @@ add_library(dom src/ftxui/dom/flex.cpp src/ftxui/dom/frame.cpp src/ftxui/dom/gauge.cpp + src/ftxui/dom/graph.cpp src/ftxui/dom/hbox.cpp src/ftxui/dom/hflow.cpp src/ftxui/dom/inverted.cpp diff --git a/ftxui/include/ftxui/component/checkbox.hpp b/ftxui/include/ftxui/component/checkbox.hpp index 6e880cf..ea69b08 100644 --- a/ftxui/include/ftxui/component/checkbox.hpp +++ b/ftxui/include/ftxui/component/checkbox.hpp @@ -17,7 +17,7 @@ class CheckBox : public Component { //std::wstring checked = L"[X] "; //std::wstring unchecked = L"[ ] "; - std::wstring checked = L"☑ "; + std::wstring checked = L"▣ "; std::wstring unchecked = L"☐ "; Decorator focused_style = inverted; diff --git a/ftxui/include/ftxui/component/screen_interactive.hpp b/ftxui/include/ftxui/component/screen_interactive.hpp index 5553a1b..71cef2c 100644 --- a/ftxui/include/ftxui/component/screen_interactive.hpp +++ b/ftxui/include/ftxui/component/screen_interactive.hpp @@ -10,7 +10,7 @@ class Component; class ScreenInteractive : public Screen { public: - static ScreenInteractive FixedSize(size_t dimx, size_t dimy); + static ScreenInteractive FixedSize(int dimx, int dimy); static ScreenInteractive Fullscreen(); static ScreenInteractive FitComponent(); static ScreenInteractive TerminalOutput(); @@ -30,7 +30,7 @@ class ScreenInteractive : public Screen { TerminalOutput, }; Dimension dimension_ = Dimension::Fixed; - ScreenInteractive(size_t dimx, size_t dimy, Dimension dimension); + ScreenInteractive(int dimx, int dimy, Dimension dimension); }; } // namespace ftxui diff --git a/ftxui/include/ftxui/dom/elements.hpp b/ftxui/include/ftxui/dom/elements.hpp index 8a2c35d..6a92117 100644 --- a/ftxui/include/ftxui/dom/elements.hpp +++ b/ftxui/include/ftxui/dom/elements.hpp @@ -3,6 +3,7 @@ #include +#include "ftxui/dom/graph.hpp" #include "ftxui/dom/node.hpp" #include "ftxui/screen/color.hpp" @@ -20,6 +21,7 @@ Element border(Element); Element window(Element title, Element content); Element spinner(int charset_index, size_t image_index); Elements paragraph(std::wstring text); // Use inside hflow(). Split by space. +Element graph(GraphFunction&); // See graph.hpp // -- Decorator --- Element bold(Element); @@ -68,6 +70,7 @@ Element nothing(Element element); // Pipe elements into decorator togethers. // Examples: text("ftxui") | bold | underlined; Element operator|(Element, Decorator); +Elements operator|(Elements, Decorator); Decorator operator|(Decorator, Decorator); // Make container able to take any number of children as input. diff --git a/ftxui/include/ftxui/dom/graph.hpp b/ftxui/include/ftxui/dom/graph.hpp new file mode 100644 index 0000000..4f7a471 --- /dev/null +++ b/ftxui/include/ftxui/dom/graph.hpp @@ -0,0 +1,15 @@ +#ifndef FTXUI_DOM_GRAPH_HPP +#define FTXUI_DOM_GRAPH_HPP + +#include "ftxui/dom/elements.hpp" + +namespace ftxui { + +class GraphFunction { + public: + virtual std::vector operator()(int width, int height) = 0; +}; + +} // namespace ftxui + +#endif /* end of include guard: FTXUI_DOM_GRAPH_HPP */ diff --git a/ftxui/include/ftxui/screen/screen.hpp b/ftxui/include/ftxui/screen/screen.hpp index 0495319..373e237 100644 --- a/ftxui/include/ftxui/screen/screen.hpp +++ b/ftxui/include/ftxui/screen/screen.hpp @@ -25,26 +25,32 @@ struct Pixel { Color foreground_color = Color::Default; }; +struct Dimension { + static Dimension Fixed(int); + static Dimension Fit(std::unique_ptr&); + static Dimension Full(); + + int dimx; + int dimy; +}; + class Screen { public: // Constructor. - Screen(size_t dimx, size_t dimy); - - // Constructor using the terminal. - static Screen TerminalFullscreen(); - static Screen TerminalOutput(std::unique_ptr& element); - static Screen FitDocument(std::unique_ptr& element); + Screen(int dimx, int dimy); + static Screen Create(Dimension dimension); + static Screen Create(Dimension width, Dimension height); // 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); + wchar_t& at(int x, int y); + Pixel& PixelAt(int x, int 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_;} + int dimx() { return dimx_;} + int dimy() { return dimy_;} // Move the terminal cursor n-lines up with n = dimy(). std::string ResetPosition(); @@ -56,8 +62,8 @@ class Screen { Box stencil; protected: - size_t dimx_; - size_t dimy_; + int dimx_; + int dimy_; std::vector> pixels_; }; diff --git a/ftxui/src/ftxui/component/screen_interactive.cpp b/ftxui/src/ftxui/component/screen_interactive.cpp index c10409d..459a06c 100644 --- a/ftxui/src/ftxui/component/screen_interactive.cpp +++ b/ftxui/src/ftxui/component/screen_interactive.cpp @@ -44,14 +44,14 @@ Event GetEvent() { }; // namespace -ScreenInteractive::ScreenInteractive(size_t dimx, - size_t dimy, +ScreenInteractive::ScreenInteractive(int dimx, + int dimy, Dimension dimension) : Screen(dimx, dimy), dimension_(dimension) {} ScreenInteractive::~ScreenInteractive() {} // static -ScreenInteractive ScreenInteractive::FixedSize(size_t dimx, size_t dimy) { +ScreenInteractive ScreenInteractive::FixedSize(int dimx, int dimy) { return ScreenInteractive(dimx, dimy, Dimension::Fixed); } @@ -106,8 +106,8 @@ void ScreenInteractive::Loop(Component* component) { void ScreenInteractive::Draw(Component* component) { auto document = component->Render(); - size_t dimx; - size_t dimy; + int dimx; + int dimy; switch (dimension_) { case Dimension::Fixed: dimx = dimx_; diff --git a/ftxui/src/ftxui/dom/graph.cpp b/ftxui/src/ftxui/dom/graph.cpp new file mode 100644 index 0000000..0e8b766 --- /dev/null +++ b/ftxui/src/ftxui/dom/graph.cpp @@ -0,0 +1,45 @@ +#include "ftxui/dom/elements.hpp" + +namespace ftxui { + +const wchar_t charset[] = L" ▗▐▖▄▟▌▙█"; + +class Graph : public Node { + public: + Graph(GraphFunction& graph_function) : graph_function_(graph_function) {} + ~Graph() override {} + + void ComputeRequirement() override { + requirement_.flex.x = 1; + requirement_.flex.y = 1; + requirement_.min.x = 1; + requirement_.min.y = 1; + } + + void Render(Screen& screen) override { + int width = (box_.x_max - box_.x_min + 1) * 2; + int height = (box_.y_max - box_.y_min + 1) * 2; + auto data = graph_function_(width, height); + int i = 0; + for (int x = box_.x_min; x <= box_.x_max; ++x) { + int height_1 = 2 * box_.y_max - data[i++]; + int height_2 = 2 * box_.y_max - data[i++]; + for (int y = box_.y_min; y <= box_.y_max; ++y) { + int yy = 2 * y; + int i_1 = yy < height_1 ? 0 : yy == height_1 ? 3 : 6; + int i_2 = yy < height_2 ? 0 : yy == height_2 ? 1 : 2; + wchar_t pix = charset[i_1 + i_2]; + screen.at(x, y) = pix; + } + } + } + + private: + GraphFunction& graph_function_; +}; + +std::unique_ptr graph(GraphFunction& graph_function) { + return std::make_unique(graph_function); +} + +}; // namespace ftxui diff --git a/ftxui/src/ftxui/dom/hflow.cpp b/ftxui/src/ftxui/dom/hflow.cpp index 05a5370..bf49251 100644 --- a/ftxui/src/ftxui/dom/hflow.cpp +++ b/ftxui/src/ftxui/dom/hflow.cpp @@ -12,7 +12,7 @@ class HFlow : public Node { requirement_.min.x = 0; requirement_.min.y = 0; requirement_.flex.x = 1; - requirement_.flex.y = 0; + requirement_.flex.y = 1; for(auto& child : children) child->ComputeRequirement(); } diff --git a/ftxui/src/ftxui/dom/util.cpp b/ftxui/src/ftxui/dom/util.cpp index cd0fed9..c125873 100644 --- a/ftxui/src/ftxui/dom/util.cpp +++ b/ftxui/src/ftxui/dom/util.cpp @@ -19,6 +19,13 @@ Decorator operator|(Decorator a, Decorator b) { return compose(a, b); } +Elements operator|(Elements es, Decorator d) { + Elements output; + for (auto& it : es) + output.push_back(std::move(it) | d); + return output; +} + Element operator|(Element e, Decorator d) { return d(std::move(e)); } diff --git a/ftxui/src/ftxui/screen/screen.cpp b/ftxui/src/ftxui/screen/screen.cpp index 0306a6b..86d7d7c 100644 --- a/ftxui/src/ftxui/screen/screen.cpp +++ b/ftxui/src/ftxui/screen/screen.cpp @@ -1,5 +1,5 @@ -#include "ftxui/dom/node.hpp" #include "ftxui/screen/screen.hpp" +#include "ftxui/dom/node.hpp" #include "ftxui/screen/string.hpp" #include "ftxui/screen/terminal.hpp" @@ -36,8 +36,34 @@ Pixel dev_null_pixel; } // namespace -Screen::Screen(size_t dimx, size_t dimy) - : stencil({0, int(dimx) - 1, 0, int(dimy) - 1}), +Dimension Dimension::Fixed(int v) { + return Dimension{v, v}; +} + +Dimension Dimension::Fit(std::unique_ptr& e) { + e->ComputeRequirement(); + Terminal::Dimensions size = Terminal::Size(); + return Dimension{std::min(e->requirement().min.x, size.dimx), + std::min(e->requirement().min.y, size.dimy)}; +} + +Dimension Dimension::Full() { + Terminal::Dimensions size = Terminal::Size(); + return Dimension{size.dimx, size.dimy}; +} + +// static +Screen Screen::Create(Dimension width, Dimension height) { + return Screen(width.dimx, height.dimy); +} + +// static +Screen Screen::Create(Dimension dimension) { + return Screen(dimension.dimx, dimension.dimy); +} + +Screen::Screen(int dimx, int dimy) + : stencil({0, dimx - 1, 0, dimy - 1}), dimx_(dimx), dimy_(dimy), pixels_(dimy, std::vector(dimx)) {} @@ -72,10 +98,10 @@ std::string Screen::ToString() { Pixel previous_pixel; - for (size_t y = 0; y < dimy_; ++y) { + for (int y = 0; y < dimy_; ++y) { if (y != 0) ss << '\n'; - for (size_t x = 0; x < dimx_; ++x) { + for (int x = 0; x < dimx_; ++x) { UpdatePixelStyle(ss, previous_pixel, pixels_[y][x]); ss << pixels_[y][x].character; } @@ -88,42 +114,18 @@ std::string Screen::ToString() { return to_string(ss.str()); } -wchar_t& Screen::at(size_t x, size_t y) { +wchar_t& Screen::at(int x, int y) { return PixelAt(x,y).character; } -Pixel& Screen::PixelAt(size_t x, size_t y) { +Pixel& Screen::PixelAt(int x, int y) { return In(stencil, x, y) ? pixels_[y][x] : dev_null_pixel; } -// static -Screen Screen::TerminalFullscreen() { - Terminal::Dimensions size = Terminal::Size(); - return Screen(size.dimx, size.dimy); -} - -// static -Screen Screen::TerminalOutput(std::unique_ptr& element) { - element->ComputeRequirement(); - Terminal::Dimensions size = Terminal::Size(); - return Screen(size.dimx, element->requirement().min.y); -} - -// static -Screen Screen::FitDocument(std::unique_ptr& element) { - element->ComputeRequirement(); - Terminal::Dimensions size = Terminal::Size(); - return - Screen( - std::min(size.dimx, element->requirement().min.x), - std::min(size.dimy, element->requirement().min.y) - ); -} - std::string Screen::ResetPosition() { std::stringstream ss; ss << MOVE_LEFT << CLEAR_LINE; - for (size_t y = 1; y < dimy_; ++y) { + for (int y = 1; y < dimy_; ++y) { ss << MOVE_UP << CLEAR_LINE; } return ss.str(); @@ -137,8 +139,8 @@ void Screen::Clear() { void Screen::ApplyShader() { // Merge box characters togethers. - for(size_t y = 1; y