Initial commit

This commit is contained in:
2025-03-21 18:47:49 +01:00
commit a8e1193e12
46 changed files with 2787 additions and 0 deletions

View File

@@ -0,0 +1,138 @@
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#ifndef FTXUI_DOM_CANVAS_HPP
#define FTXUI_DOM_CANVAS_HPP
#include <cstddef> // for size_t
#include <functional> // for function
#include <string> // for string
#include <unordered_map> // for unordered_map
#include "ftxui/screen/color.hpp" // for Color
#include "ftxui/screen/screen.hpp" // for Pixel
#ifdef DrawText
// Workaround for WinUsr.h (via Windows.h) defining macros that break things.
// https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-drawtext
#undef DrawText
#endif
namespace ftxui {
struct Canvas {
public:
Canvas() = default;
Canvas(int width, int height);
// Getters:
int width() const { return width_; }
int height() const { return height_; }
Pixel GetPixel(int x, int y) const;
using Stylizer = std::function<void(Pixel&)>;
// Draws using braille characters --------------------------------------------
void DrawPointOn(int x, int y);
void DrawPointOff(int x, int y);
void DrawPointToggle(int x, int y);
void DrawPoint(int x, int y, bool value);
void DrawPoint(int x, int y, bool value, const Stylizer& s);
void DrawPoint(int x, int y, bool value, const Color& color);
void DrawPointLine(int x1, int y1, int x2, int y2);
void DrawPointLine(int x1, int y1, int x2, int y2, const Stylizer& s);
void DrawPointLine(int x1, int y1, int x2, int y2, const Color& color);
void DrawPointCircle(int x, int y, int radius);
void DrawPointCircle(int x, int y, int radius, const Stylizer& s);
void DrawPointCircle(int x, int y, int radius, const Color& color);
void DrawPointCircleFilled(int x, int y, int radius);
void DrawPointCircleFilled(int x, int y, int radius, const Stylizer& s);
void DrawPointCircleFilled(int x, int y, int radius, const Color& color);
void DrawPointEllipse(int x, int y, int r1, int r2);
void DrawPointEllipse(int x, int y, int r1, int r2, const Color& color);
void DrawPointEllipse(int x, int y, int r1, int r2, const Stylizer& s);
void DrawPointEllipseFilled(int x, int y, int r1, int r2);
void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Color& color);
void DrawPointEllipseFilled(int x, int y, int r1, int r2, const Stylizer& s);
// Draw using box characters -------------------------------------------------
// Block are of size 1x2. y is considered to be a multiple of 2.
void DrawBlockOn(int x, int y);
void DrawBlockOff(int x, int y);
void DrawBlockToggle(int x, int y);
void DrawBlock(int x, int y, bool value);
void DrawBlock(int x, int y, bool value, const Stylizer& s);
void DrawBlock(int x, int y, bool value, const Color& color);
void DrawBlockLine(int x1, int y1, int x2, int y2);
void DrawBlockLine(int x1, int y1, int x2, int y2, const Stylizer& s);
void DrawBlockLine(int x1, int y1, int x2, int y2, const Color& color);
void DrawBlockCircle(int x1, int y1, int radius);
void DrawBlockCircle(int x1, int y1, int radius, const Stylizer& s);
void DrawBlockCircle(int x1, int y1, int radius, const Color& color);
void DrawBlockCircleFilled(int x1, int y1, int radius);
void DrawBlockCircleFilled(int x1, int y1, int radius, const Stylizer& s);
void DrawBlockCircleFilled(int x1, int y1, int radius, const Color& color);
void DrawBlockEllipse(int x1, int y1, int r1, int r2);
void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Stylizer& s);
void DrawBlockEllipse(int x1, int y1, int r1, int r2, const Color& color);
void DrawBlockEllipseFilled(int x1, int y1, int r1, int r2);
void DrawBlockEllipseFilled(int x1,
int y1,
int r1,
int r2,
const Stylizer& s);
void DrawBlockEllipseFilled(int x1,
int y1,
int r1,
int r2,
const Color& color);
// Draw using normal characters ----------------------------------------------
// Draw using character of size 2x4 at position (x,y)
// x is considered to be a multiple of 2.
// y is considered to be a multiple of 4.
void DrawText(int x, int y, const std::string& value);
void DrawText(int x, int y, const std::string& value, const Color& color);
void DrawText(int x, int y, const std::string& value, const Stylizer& style);
// Decorator:
// x is considered to be a multiple of 2.
// y is considered to be a multiple of 4.
void Style(int x, int y, const Stylizer& style);
private:
bool IsIn(int x, int y) const {
return x >= 0 && x < width_ && y >= 0 && y < height_;
}
enum CellType {
kBraille,
kBlock,
kText,
};
struct Cell {
CellType type = kText;
Pixel content;
};
struct XY {
int x;
int y;
bool operator==(const XY& other) const {
return x == other.x && y == other.y;
}
};
struct XYHash {
size_t operator()(const XY& xy) const {
constexpr size_t shift = 1024;
return size_t(xy.x) * shift + size_t(xy.y);
}
};
int width_ = 0;
int height_ = 0;
std::unordered_map<XY, Cell, XYHash> storage_;
};
} // namespace ftxui
#endif // FTXUI_DOM_CANVAS_HPP

View File

@@ -0,0 +1,15 @@
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#ifndef FTXUI_DOM_DEPRECATED_HPP
#define FTXUI_DOM_DEPRECATED_HPP
#include "ftxui/dom/elements.hpp"
namespace ftxui {
Element text(std::wstring text);
Element vtext(std::wstring text);
Elements paragraph(std::wstring text);
} // namespace ftxui
#endif // FTXUI_DOM_DEPRECATED_HPP

View File

@@ -0,0 +1,17 @@
// 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.
#ifndef FTXUI_DOM_DIRECTION_HPP
#define FTXUI_DOM_DIRECTION_HPP
namespace ftxui {
enum class Direction {
Up = 0,
Down = 1,
Left = 2,
Right = 3,
};
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_DIRECTION_HPP */

View File

@@ -0,0 +1,196 @@
// 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.
#ifndef FTXUI_DOM_ELEMENTS_HPP
#define FTXUI_DOM_ELEMENTS_HPP
#include <functional>
#include <memory>
#include "ftxui/dom/canvas.hpp"
#include "ftxui/dom/direction.hpp"
#include "ftxui/dom/flexbox_config.hpp"
#include "ftxui/dom/linear_gradient.hpp"
#include "ftxui/dom/node.hpp"
#include "ftxui/screen/box.hpp"
#include "ftxui/screen/color.hpp"
#include "ftxui/screen/screen.hpp"
#include "ftxui/screen/terminal.hpp"
#include "ftxui/util/ref.hpp"
namespace ftxui {
class Node;
using Element = std::shared_ptr<Node>;
using Elements = std::vector<Element>;
using Decorator = std::function<Element(Element)>;
using GraphFunction = std::function<std::vector<int>(int, int)>;
enum BorderStyle {
LIGHT,
DASHED,
HEAVY,
DOUBLE,
ROUNDED,
EMPTY,
};
// Pipe elements into decorator togethers.
// For instance the next lines are equivalents:
// -> text("ftxui") | bold | underlined
// -> underlined(bold(text("FTXUI")))
Element operator|(Element, Decorator);
Element& operator|=(Element&, Decorator);
Elements operator|(Elements, Decorator);
Decorator operator|(Decorator, Decorator);
// --- Widget ---
Element text(std::string text);
Element vtext(std::string text);
Element separator();
Element separatorLight();
Element separatorDashed();
Element separatorHeavy();
Element separatorDouble();
Element separatorEmpty();
Element separatorStyled(BorderStyle);
Element separator(Pixel);
Element separatorCharacter(std::string);
Element separatorHSelector(float left,
float right,
Color unselected_color,
Color selected_color);
Element separatorVSelector(float up,
float down,
Color unselected_color,
Color selected_color);
Element gauge(float progress);
Element gaugeLeft(float progress);
Element gaugeRight(float progress);
Element gaugeUp(float progress);
Element gaugeDown(float progress);
Element gaugeDirection(float progress, Direction direction);
Element border(Element);
Element borderLight(Element);
Element borderDashed(Element);
Element borderHeavy(Element);
Element borderDouble(Element);
Element borderRounded(Element);
Element borderEmpty(Element);
Decorator borderStyled(BorderStyle);
Decorator borderStyled(BorderStyle, Color);
Decorator borderStyled(Color);
Decorator borderWith(const Pixel&);
Element window(Element title, Element content);
Element spinner(int charset_index, size_t image_index);
Element paragraph(const std::string& text);
Element paragraphAlignLeft(const std::string& text);
Element paragraphAlignRight(const std::string& text);
Element paragraphAlignCenter(const std::string& text);
Element paragraphAlignJustify(const std::string& text);
Element graph(GraphFunction);
Element emptyElement();
Element canvas(ConstRef<Canvas>);
Element canvas(int width, int height, std::function<void(Canvas&)>);
Element canvas(std::function<void(Canvas&)>);
// -- Decorator ---
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);
Decorator color(const LinearGradient&);
Decorator bgcolor(const LinearGradient&);
Element color(Color, Element);
Element bgcolor(Color, Element);
Element color(const LinearGradient&, Element);
Element bgcolor(const LinearGradient&, Element);
Decorator focusPosition(int x, int y);
Decorator focusPositionRelative(float x, float y);
Element automerge(Element child);
Decorator hyperlink(std::string link);
Element hyperlink(std::string link, Element child);
// --- Layout is
// Horizontal, Vertical or stacked set of elements.
Element hbox(Elements);
Element vbox(Elements);
Element dbox(Elements);
Element flexbox(Elements, FlexboxConfig config = FlexboxConfig());
Element gridbox(std::vector<Elements> lines);
Element hflow(Elements); // Helper: default flexbox with row direction.
Element vflow(Elements); // Helper: default flexbox with column direction.
// -- Flexibility ---
// Define how to share the remaining space when not all of it is used inside a
// container.
Element flex(Element); // Expand/Minimize if possible/needed.
Element flex_grow(Element); // Expand element if possible.
Element flex_shrink(Element); // Minimize element if needed.
Element xflex(Element); // Expand/Minimize if possible/needed on X axis.
Element xflex_grow(Element); // Expand element if possible on X axis.
Element xflex_shrink(Element); // Minimize element if needed on X axis.
Element yflex(Element); // Expand/Minimize if possible/needed on Y axis.
Element yflex_grow(Element); // Expand element if possible on Y axis.
Element yflex_shrink(Element); // Minimize element if needed on Y axis.
Element notflex(Element); // Reset the flex attribute.
Element filler(); // A blank expandable element.
// -- Size override;
enum WidthOrHeight { WIDTH, HEIGHT };
enum Constraint { LESS_THAN, EQUAL, GREATER_THAN };
Decorator size(WidthOrHeight, Constraint, int value);
// --- Frame ---
// A frame is a scrollable area. The internal area is potentially larger than
// the external one. The internal area is scrolled in order to make visible the
// focused element.
Element frame(Element);
Element xframe(Element);
Element yframe(Element);
Element focus(Element);
Element select(Element);
// --- Cursor ---
// Those are similar to `focus`, but also change the shape of the cursor.
Element focusCursorBlock(Element);
Element focusCursorBlockBlinking(Element);
Element focusCursorBar(Element);
Element focusCursorBarBlinking(Element);
Element focusCursorUnderline(Element);
Element focusCursorUnderlineBlinking(Element);
// --- Misc ---
Element vscroll_indicator(Element);
Decorator reflect(Box& box);
// Before drawing the |element| clear the pixel below. This is useful in
// combinaison with dbox.
Element clear_under(Element element);
// --- Util --------------------------------------------------------------------
Element hcenter(Element);
Element vcenter(Element);
Element center(Element);
Element align_right(Element);
Element nothing(Element element);
namespace Dimension {
Dimensions Fit(Element&);
} // namespace Dimension
} // namespace ftxui
// Make container able to take any number of children as input.
#include "ftxui/dom/take_any_args.hpp"
// Include old definitions using wstring.
#include "ftxui/dom/deprecated.hpp"
#endif // FTXUI_DOM_ELEMENTS_HPP

View File

@@ -0,0 +1,114 @@
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#ifndef FTXUI_DOM_FLEXBOX_CONFIG_HPP
#define FTXUI_DOM_FLEXBOX_CONFIG_HPP
/*
This replicate the CSS flexbox model.
See guide for documentation:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/
*/
namespace ftxui {
struct FlexboxConfig {
/// This establishes the main-axis, thus defining the direction flex items are
/// placed in the flex container. Flexbox is (aside wrapping) single-direction
/// layout concept. Think of flex items as primarily laying out either in
/// horizontal rows or vertical columns.
enum class Direction {
Row, ///< Flex items are laid out in a row.
RowInversed, ///< Flex items are laid out in a row, but in reverse order.
Column, ///< Flex items are laid out in a column.
ColumnInversed ///< Flex items are laid out in a column, but in reverse
///< order.
};
Direction direction = Direction::Row;
/// By default, flex items will all try to fit onto one line. You can change
/// that and allow the items to wrap as needed with this property.
enum class Wrap {
NoWrap, ///< Flex items will all try to fit onto one line.
Wrap, ///< Flex items will wrap onto multiple lines.
WrapInversed, ///< Flex items will wrap onto multiple lines, but in reverse
///< order.
};
Wrap wrap = Wrap::Wrap;
/// This defines the alignment along the main axis. It helps distribute extra
/// free space leftover when either all the flex items on a line are
/// inflexible, or are flexible but have reached their maximum size. It also
/// exerts some control over the alignment of items when they overflow the
/// line.
enum class JustifyContent {
/// Items are aligned to the start of flexbox's direction.
FlexStart,
/// Items are aligned to the end of flexbox's direction.
FlexEnd,
/// Items are centered along the line.
Center,
/// Items are stretched to fill the line.
Stretch,
/// Items are evenly distributed in the line; first item is on the start
// line, last item on the end line
SpaceBetween,
/// Items are evenly distributed in the line with equal space around them.
/// Note that visually the spaces arent equal, since all the items have
/// equal space on both sides. The first item will have one unit of space
/// against the container edge, but two units of space between the next item
/// because that next item has its own spacing that applies.
SpaceAround,
/// Items are distributed so that the spacing between any two items (and the
/// space to the edges) is equal.
SpaceEvenly,
};
JustifyContent justify_content = JustifyContent::FlexStart;
/// This defines the default behavior for how flex items are laid out along
/// the cross axis on the current line. Think of it as the justify-content
/// version for the cross-axis (perpendicular to the main-axis).
enum class AlignItems {
FlexStart, ///< items are placed at the start of the cross axis.
FlexEnd, ///< items are placed at the end of the cross axis.
Center, ///< items are centered along the cross axis.
Stretch, ///< items are stretched to fill the cross axis.
};
AlignItems align_items = AlignItems::FlexStart;
// This aligns a flex containers lines within when there is extra space in
// the cross-axis, similar to how justify-content aligns individual items
// within the main-axis.
enum class AlignContent {
FlexStart, ///< items are placed at the start of the cross axis.
FlexEnd, ///< items are placed at the end of the cross axis.
Center, ///< items are centered along the cross axis.
Stretch, ///< items are stretched to fill the cross axis.
SpaceBetween, ///< items are evenly distributed in the cross axis.
SpaceAround, ///< tems evenly distributed with equal space around each
///< line.
SpaceEvenly, ///< items are evenly distributed in the cross axis with equal
///< space around them.
};
AlignContent align_content = AlignContent::FlexStart;
int gap_x = 0;
int gap_y = 0;
// Constructor pattern. For chained use like:
// ```
// FlexboxConfig()
// .Set(FlexboxConfig::Direction::Row)
// .Set(FlexboxConfig::Wrap::Wrap);
// ```
FlexboxConfig& Set(FlexboxConfig::Direction);
FlexboxConfig& Set(FlexboxConfig::Wrap);
FlexboxConfig& Set(FlexboxConfig::JustifyContent);
FlexboxConfig& Set(FlexboxConfig::AlignItems);
FlexboxConfig& Set(FlexboxConfig::AlignContent);
FlexboxConfig& SetGap(int gap_x, int gap_y);
};
} // namespace ftxui
#endif // FTXUI_DOM_FLEXBOX_CONFIG_HPP

View File

@@ -0,0 +1,51 @@
// 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.
#ifndef FTXUI_DOM_LINEAR_GRADIENT_HPP
#define FTXUI_DOM_LINEAR_GRADIENT_HPP
#include <optional>
#include <vector>
#include "ftxui/screen/color.hpp" // for Colors
namespace ftxui {
/// @brief A class representing the settings for linear-gradient color effect.
///
/// Example:
/// ```cpp
/// LinearGradient()
/// .Angle(45)
/// .Stop(Color::Red, 0.0)
/// .Stop(Color::Green, 0.5)
/// .Stop(Color::Blue, 1.0);
/// ```
///
/// There are also shorthand constructors:
/// ```cpp
/// LinearGradient(Color::Red, Color::Blue);
/// LinearGradient(45, Color::Red, Color::Blue);
/// ```
struct LinearGradient {
float angle = 0.f;
struct Stop {
Color color = Color::Default;
std::optional<float> position;
};
std::vector<Stop> stops;
// Simple constructor
LinearGradient();
LinearGradient(Color begin, Color end);
LinearGradient(float angle, Color begin, Color end);
// Modifier using the builder pattern.
LinearGradient& Angle(float angle);
LinearGradient& Stop(Color color, float position);
LinearGradient& Stop(Color color);
};
} // namespace ftxui
#endif // FTXUI_DOM_LINEAR_GRADIENT_HPP

View File

@@ -0,0 +1,66 @@
// 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.
#ifndef FTXUI_DOM_NODE_HPP
#define FTXUI_DOM_NODE_HPP
#include <memory> // for shared_ptr
#include <vector> // for vector
#include "ftxui/dom/requirement.hpp" // for Requirement
#include "ftxui/screen/box.hpp" // for Box
#include "ftxui/screen/screen.hpp"
namespace ftxui {
class Node;
class Screen;
using Element = std::shared_ptr<Node>;
using Elements = std::vector<Element>;
class Node {
public:
Node();
Node(Elements children);
Node(const Node&) = delete;
Node(const Node&&) = delete;
Node& operator=(const Node&) = delete;
Node& operator=(const Node&&) = delete;
virtual ~Node();
// Step 1: Compute layout requirement. Tell parent what dimensions this
// element wants to be.
// Propagated from Children to Parents.
virtual void ComputeRequirement();
Requirement requirement() { return requirement_; }
// Step 2: Assign this element its final dimensions.
// Propagated from Parents to Children.
virtual void SetBox(Box box);
// Step 3: Draw this element.
virtual void Render(Screen& screen);
// Layout may not resolve within a single iteration for some elements. This
// allows them to request additionnal iterations. This signal must be
// forwarded to children at least once.
struct Status {
int iteration = 0;
bool need_iteration = false;
};
virtual void Check(Status* status);
protected:
Elements children_;
Requirement requirement_;
Box box_;
};
void Render(Screen& screen, const Element& element);
void Render(Screen& screen, Node* node);
} // namespace ftxui
#endif // FTXUI_DOM_NODE_HPP

View File

@@ -0,0 +1,34 @@
// 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.
#ifndef FTXUI_DOM_REQUIREMENT_HPP
#define FTXUI_DOM_REQUIREMENT_HPP
#include "ftxui/screen/box.hpp"
namespace ftxui {
struct Requirement {
// The required size to fully draw the element.
int min_x = 0;
int min_y = 0;
// How much flexibility is given to the component.
int flex_grow_x = 0;
int flex_grow_y = 0;
int flex_shrink_x = 0;
int flex_shrink_y = 0;
// Focus management to support the frame/focus/select element.
enum Selection {
NORMAL = 0,
SELECTED = 1,
FOCUSED = 2,
};
Selection selection = NORMAL;
Box selected_box;
};
} // namespace ftxui
#endif // FTXUI_DOM_REQUIREMENT_HPP

View File

@@ -0,0 +1,95 @@
// Copyright 2021 Arthur Sonzogni. All rights reserved.
// Use of this source code is governed by the MIT license that can be found in
// the LICENSE file.
#ifndef FTXUI_DOM_TABLE
#define FTXUI_DOM_TABLE
#include <memory>
#include <string> // for string
#include <vector> // for vector
#include "ftxui/dom/elements.hpp" // for Element, BorderStyle, LIGHT, Decorator
namespace ftxui {
// Usage:
//
// Initialization:
// ---------------
//
// auto table = Table({
// {"X", "Y"},
// {"-1", "1"},
// {"+0", "0"},
// {"+1", "1"},
// });
//
// table.SelectAll().Border(LIGHT);
//
// table.SelectRow(1).Border(DOUBLE);
// table.SelectRow(1).SeparatorInternal(Light);
//
// std::move(table).Element();
class Table;
class TableSelection;
class Table {
public:
Table();
Table(std::vector<std::vector<std::string>>);
Table(std::vector<std::vector<Element>>);
TableSelection SelectAll();
TableSelection SelectCell(int column, int row);
TableSelection SelectRow(int row_index);
TableSelection SelectRows(int row_min, int row_max);
TableSelection SelectColumn(int column_index);
TableSelection SelectColumns(int column_min, int column_max);
TableSelection SelectRectangle(int column_min,
int column_max,
int row_min,
int row_max);
Element Render();
private:
void Initialize(std::vector<std::vector<Element>>);
friend TableSelection;
std::vector<std::vector<Element>> elements_;
int input_dim_x_ = 0;
int input_dim_y_ = 0;
int dim_x_ = 0;
int dim_y_ = 0;
};
class TableSelection {
public:
void Decorate(Decorator);
void DecorateAlternateRow(Decorator, int modulo = 2, int shift = 0);
void DecorateAlternateColumn(Decorator, int modulo = 2, int shift = 0);
void DecorateCells(Decorator);
void DecorateCellsAlternateColumn(Decorator, int modulo = 2, int shift = 0);
void DecorateCellsAlternateRow(Decorator, int modulo = 2, int shift = 0);
void Border(BorderStyle border = LIGHT);
void BorderLeft(BorderStyle border = LIGHT);
void BorderRight(BorderStyle border = LIGHT);
void BorderTop(BorderStyle border = LIGHT);
void BorderBottom(BorderStyle border = LIGHT);
void Separator(BorderStyle border = LIGHT);
void SeparatorVertical(BorderStyle border = LIGHT);
void SeparatorHorizontal(BorderStyle border = LIGHT);
private:
friend Table;
Table* table_;
int x_min_;
int x_max_;
int y_min_;
int y_max_;
};
} // namespace ftxui
#endif /* end of include guard: FTXUI_DOM_TABLE */

View File

@@ -0,0 +1,47 @@
// 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.
#ifndef FTXUI_DOM_TAKE_ANY_ARGS_HPP
#define FTXUI_DOM_TAKE_ANY_ARGS_HPP
// IWYU pragma: private, include "ftxui/dom/elements.hpp"
#include <type_traits>
namespace ftxui {
template <class T>
void Merge(Elements& /*container*/, T /*element*/) {}
template <>
inline void Merge(Elements& container, Element element) {
container.push_back(std::move(element));
}
template <>
inline void Merge(Elements& container, Elements elements) {
for (auto& element : elements)
container.push_back(std::move(element));
}
// Turn a set of arguments into a vector.
template <class... Args>
Elements unpack(Args... args) {
std::vector<Element> vec;
(Merge(vec, std::move(args)), ...);
return vec;
}
// Make |container| able to take any number of argments.
#define TAKE_ANY_ARGS(container) \
template <class... Args> \
Element container(Args... children) { \
return container(unpack(std::forward<Args>(children)...)); \
}
TAKE_ANY_ARGS(vbox)
TAKE_ANY_ARGS(hbox)
TAKE_ANY_ARGS(dbox)
TAKE_ANY_ARGS(hflow)
} // namespace ftxui
#endif // FTXUI_DOM_TAKE_ANY_ARGS_HPP