diff --git a/CHANGELOG.md b/CHANGELOG.md index 6aa0880..35ae72e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ current (development) --------------------- ### DOM +- Feature: more styles: + - `strikethrough` + - `underlinedDouble` - Feature: Customize the cursor. Add the following decorators: - `focusCursorBlock` - `focusCursorBlockBlinking` diff --git a/CMakeLists.txt b/CMakeLists.txt index dab2557..adb4ec5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -79,9 +79,11 @@ add_library(dom src/ftxui/dom/separator.cpp src/ftxui/dom/size.cpp src/ftxui/dom/spinner.cpp + src/ftxui/dom/strikethrough.cpp src/ftxui/dom/table.cpp src/ftxui/dom/text.cpp src/ftxui/dom/underlined.cpp + src/ftxui/dom/underlined_double.cpp src/ftxui/dom/util.cpp src/ftxui/dom/vbox.cpp ) diff --git a/README.md b/README.md index c9aa65c..7f1b067 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,9 @@ An element can be decorated using the functions: - `dim` - `inverted` - `underlined` + - `underlinedDouble` - `blink` + - `strikethrough` - `color` - `bgcolor` diff --git a/doc/mainpage.md b/doc/mainpage.md index 2395748..9c03660 100644 --- a/doc/mainpage.md +++ b/doc/mainpage.md @@ -453,6 +453,8 @@ Element bold(Element); Element dim(Element); Element inverted(Element); Element underlined(Element); +Element underlinedDouble(Element); +Element strikethrough(Element); Element blink(Element); Decorator color(Color); Decorator bgcolor(Color); @@ -469,7 +471,7 @@ underlined(bold(text("This text is bold and underlined"))) Alternatively, use the pipe operator to chain it on your element: ```cpp -text("This text is bold")) | bold | underlined +text("This text is bold") | bold | underlined ``` ## Layout {#dom-layout} diff --git a/examples/dom/CMakeLists.txt b/examples/dom/CMakeLists.txt index ee2265c..df6e1b9 100644 --- a/examples/dom/CMakeLists.txt +++ b/examples/dom/CMakeLists.txt @@ -26,7 +26,9 @@ example(style_color) example(style_dim) example(style_gallery) example(style_inverted) +example(style_strikethrough) example(style_underlined) +example(style_underlined_double) example(table) example(vbox_hbox) example(vflow) diff --git a/examples/dom/style_gallery.cpp b/examples/dom/style_gallery.cpp index 9303e67..8826388 100644 --- a/examples/dom/style_gallery.cpp +++ b/examples/dom/style_gallery.cpp @@ -10,14 +10,16 @@ int main(int argc, const char* argv[]) { // clang-format off auto document = hbox({ - text("normal") , text(" ") , - text("bold") | bold , text(" ") , - text("dim") | dim , text(" ") , - text("inverted") | inverted , text(" ") , - text("underlined")| underlined , text(" ") , - text("blink") | blink , text(" ") , - text("color") | color(Color::Blue) , text(" ") , - text("bgcolor") | bgcolor(Color::Blue), + text("normal") , text(" ") , + text("bold") | bold , text(" ") , + text("dim") | dim , text(" ") , + text("inverted") | inverted , text(" ") , + text("underlined") | underlined , text(" ") , + text("underlinedDouble") | underlinedDouble , text(" ") , + text("blink") | blink , text(" ") , + text("strikethrough") | strikethrough , text(" ") , + text("color") | color(Color::Blue) , text(" ") , + text("bgcolor") | bgcolor(Color::Blue) , }); // clang-format on auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); diff --git a/examples/dom/style_strikethrough.cpp b/examples/dom/style_strikethrough.cpp new file mode 100644 index 0000000..c2c8355 --- /dev/null +++ b/examples/dom/style_strikethrough.cpp @@ -0,0 +1,25 @@ +#include // for text, operator|, strikethrough, Fit, hbox, Element +#include // for Full, Screen +#include // for allocator + +#include "ftxui/dom/node.hpp" // for Render +#include "ftxui/screen/color.hpp" // for ftxui + +int main(int argc, const char* argv[]) { + using namespace ftxui; + auto document = // + hbox({ + text("This text is "), + text("strikethrough") | strikethrough, + text(". Do you like it?"), + }); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + Render(screen, document); + screen.Print(); + + return 0; +} + +// Copyright 2020 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/examples/dom/style_underlined_double.cpp b/examples/dom/style_underlined_double.cpp new file mode 100644 index 0000000..ea2a998 --- /dev/null +++ b/examples/dom/style_underlined_double.cpp @@ -0,0 +1,25 @@ +#include // for text, operator|, underlinedDouble, Fit, hbox, Element +#include // for Full, Screen +#include // for allocator + +#include "ftxui/dom/node.hpp" // for Render +#include "ftxui/screen/color.hpp" // for ftxui + +int main(int argc, const char* argv[]) { + using namespace ftxui; + auto document = // + hbox({ + text("This text is "), + text("underlinedDouble") | underlinedDouble, + text(". Do you like it?"), + }); + auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document)); + Render(screen, document); + screen.Print(); + + return 0; +} + +// Copyright 2020 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/include/ftxui/dom/elements.hpp b/include/ftxui/dom/elements.hpp index ce14801..b3935c5 100644 --- a/include/ftxui/dom/elements.hpp +++ b/include/ftxui/dom/elements.hpp @@ -83,7 +83,9 @@ Element bold(Element); Element dim(Element); Element inverted(Element); Element underlined(Element); +Element underlinedDouble(Element); Element blink(Element); +Element strikethrough(Element); Decorator color(Color); Decorator bgcolor(Color); Element color(Color, Element); diff --git a/include/ftxui/screen/screen.hpp b/include/ftxui/screen/screen.hpp index 96242a3..d8a5329 100644 --- a/include/ftxui/screen/screen.hpp +++ b/include/ftxui/screen/screen.hpp @@ -30,6 +30,8 @@ struct Pixel { bool dim : 1; bool inverted : 1; bool underlined : 1; + bool underlined_double : 1; + bool strikethrough : 1; bool automerge : 1; Pixel() @@ -38,6 +40,8 @@ struct Pixel { dim(false), inverted(false), underlined(false), + underlined_double(false), + strikethrough(false), automerge(false) {} }; diff --git a/src/ftxui/dom/strikethrough.cpp b/src/ftxui/dom/strikethrough.cpp new file mode 100644 index 0000000..13c8559 --- /dev/null +++ b/src/ftxui/dom/strikethrough.cpp @@ -0,0 +1,36 @@ +#include // for make_shared +#include // for move + +#include "ftxui/dom/elements.hpp" // for Element, strikethrough +#include "ftxui/dom/node.hpp" // for Node +#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator +#include "ftxui/screen/box.hpp" // for Box +#include "ftxui/screen/screen.hpp" // for Pixel, Screen + +namespace ftxui { + +/// @brief Apply a strikethrough to text. +/// @ingroup dom +Element strikethrough(Element child) { + class Impl : public NodeDecorator { + public: + using NodeDecorator::NodeDecorator; + + void Render(Screen& screen) override { + for (int y = box_.y_min; y <= box_.y_max; ++y) { + for (int x = box_.x_min; x <= box_.x_max; ++x) { + screen.PixelAt(x, y).strikethrough = true; + } + } + Node::Render(screen); + } + }; + + return std::make_shared(std::move(child)); +} + +} // namespace ftxui + +// Copyright 2023 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/src/ftxui/dom/underlined_double.cpp b/src/ftxui/dom/underlined_double.cpp new file mode 100644 index 0000000..c1089f7 --- /dev/null +++ b/src/ftxui/dom/underlined_double.cpp @@ -0,0 +1,36 @@ +#include // for make_shared +#include // for move + +#include "ftxui/dom/elements.hpp" // for Element, underlinedDouble +#include "ftxui/dom/node.hpp" // for Node +#include "ftxui/dom/node_decorator.hpp" // for NodeDecorator +#include "ftxui/screen/box.hpp" // for Box +#include "ftxui/screen/screen.hpp" // for Pixel, Screen + +namespace ftxui { + +/// @brief Apply a underlinedDouble to text. +/// @ingroup dom +Element underlinedDouble(Element child) { + class Impl : public NodeDecorator { + public: + using NodeDecorator::NodeDecorator; + + void Render(Screen& screen) override { + for (int y = box_.y_min; y <= box_.y_max; ++y) { + for (int x = box_.x_min; x <= box_.x_max; ++x) { + screen.PixelAt(x, y).underlined_double = true; + } + } + Node::Render(screen); + } + }; + + return std::make_shared(std::move(child)); +} + +} // namespace ftxui + +// Copyright 2023 Arthur Sonzogni. All rights reserved. +// Use of this source code is governed by the MIT license that can be found in +// the LICENSE file. diff --git a/src/ftxui/screen/screen.cpp b/src/ftxui/screen/screen.cpp index 96cef9f..21a93ca 100644 --- a/src/ftxui/screen/screen.cpp +++ b/src/ftxui/screen/screen.cpp @@ -66,6 +66,16 @@ void UpdatePixelStyle(std::stringstream& ss, previous.dim = false; } + if ((!next.underlined && previous.underlined) || + (!next.underlined_double && previous.underlined_double)) { + // We might have wrongfully reset underlined or underlinedbold because they + // share the same resetter. Take it into account so that the side effect + // will cause it to be set again below. + ss << "\x1B[24m"; // UNDERLINED_RESET + previous.underlined = false; + previous.underlined_double = false; + } + if (next.bold && !previous.bold) { ss << "\x1B[1m"; // BOLD_SET } @@ -78,10 +88,6 @@ void UpdatePixelStyle(std::stringstream& ss, ss << "\x1B[4m"; // UNDERLINED_SET } - if (!next.underlined && previous.underlined) { - ss << "\x1B[24m"; // UNDERLINED_RESET - } - if (next.blink && !previous.blink) { ss << "\x1B[5m"; // BLINK_SET } @@ -98,6 +104,18 @@ void UpdatePixelStyle(std::stringstream& ss, ss << "\x1B[27m"; // INVERTED_RESET } + if (next.strikethrough && !previous.strikethrough) { + ss << "\x1B[9m"; // CROSSED_OUT + } + + if (!next.strikethrough && previous.strikethrough) { + ss << "\x1B[29m"; // CROSSED_OUT_RESET + } + + if (next.underlined_double && !previous.underlined_double) { + ss << "\x1B[21m"; // DOUBLE_UNDERLINED_SET + } + if (next.foreground_color != previous.foreground_color || next.background_color != previous.background_color) { ss << "\x1B[" + next.foreground_color.Print(false) + "m";