mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2025-10-23 21:40:54 +08:00
Add Merge()
specializations to support more Element
containers (#1117)
`Merge()` was previously only supporting `Elements` as a `Element` container. This PR adds specialization for: - all the containers that matches the concept `std::ranges::range` - `std::queue` - `std::stack` Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com> Bug:https://github.com/ArthurSonzogni/FTXUI/issues/1108 Fixed:https://github.com/ArthurSonzogni/FTXUI/issues/1108
This commit is contained in:
@@ -35,6 +35,8 @@ Next
|
|||||||
### Dom
|
### Dom
|
||||||
- Fix integer overflow in `ComputeShrinkHard`. Thanks @its-pablo in #1137 for
|
- Fix integer overflow in `ComputeShrinkHard`. Thanks @its-pablo in #1137 for
|
||||||
reporting and fixing the issue.
|
reporting and fixing the issue.
|
||||||
|
- Add specialization for `vbox/hbox/dbox` to allow a container of Element as
|
||||||
|
as input. Thanks @nbusser in #1117.
|
||||||
|
|
||||||
6.1.9 (2025-05-07)
|
6.1.9 (2025-05-07)
|
||||||
------------
|
------------
|
||||||
|
@@ -5,25 +5,18 @@
|
|||||||
#define FTXUI_DOM_TAKE_ANY_ARGS_HPP
|
#define FTXUI_DOM_TAKE_ANY_ARGS_HPP
|
||||||
|
|
||||||
// IWYU pragma: private, include "ftxui/dom/elements.hpp"
|
// IWYU pragma: private, include "ftxui/dom/elements.hpp"
|
||||||
|
#include <deque>
|
||||||
#include <ftxui/dom/node.hpp>
|
#include <ftxui/dom/node.hpp>
|
||||||
|
#include <queue>
|
||||||
|
#include <stack>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace ftxui {
|
namespace ftxui {
|
||||||
|
|
||||||
template <class T>
|
|
||||||
void Merge(Elements& /*container*/, T /*element*/) {}
|
|
||||||
|
|
||||||
template <>
|
|
||||||
inline void Merge(Elements& container, Element element) {
|
inline void Merge(Elements& container, Element element) {
|
||||||
container.push_back(std::move(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.
|
// Turn a set of arguments into a vector.
|
||||||
template <class... Args>
|
template <class... Args>
|
||||||
Elements unpack(Args... args) {
|
Elements unpack(Args... args) {
|
||||||
@@ -32,11 +25,46 @@ Elements unpack(Args... args) {
|
|||||||
return vec;
|
return vec;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make |container| able to take any number of argments.
|
// Make |container| able to take any number of arguments.
|
||||||
#define TAKE_ANY_ARGS(container) \
|
#define TAKE_ANY_ARGS(container) \
|
||||||
template <class... Args> \
|
template <class... Args> \
|
||||||
Element container(Args... children) { \
|
inline Element container(Args... children) { \
|
||||||
return container(unpack(std::forward<Args>(children)...)); \
|
return container(unpack(std::forward<Args>(children)...)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
template <class Container> \
|
||||||
|
inline Element container(Container&& children) { \
|
||||||
|
Elements elements; \
|
||||||
|
for (auto& child : children) { \
|
||||||
|
elements.push_back(std::move(child)); \
|
||||||
|
} \
|
||||||
|
return container(std::move(elements)); \
|
||||||
|
} \
|
||||||
|
template <> \
|
||||||
|
inline Element container(std::stack<Element>&& children) { \
|
||||||
|
Elements elements; \
|
||||||
|
while (!children.empty()) { \
|
||||||
|
elements.push_back(std::move(children.top())); \
|
||||||
|
children.pop(); \
|
||||||
|
} \
|
||||||
|
return container(std::move(elements)); \
|
||||||
|
} \
|
||||||
|
template <> \
|
||||||
|
inline Element container(std::queue<Element>&& children) { \
|
||||||
|
Elements elements; \
|
||||||
|
while (!children.empty()) { \
|
||||||
|
elements.push_back(std::move(children.front())); \
|
||||||
|
children.pop(); \
|
||||||
|
} \
|
||||||
|
return container(std::move(elements)); \
|
||||||
|
} \
|
||||||
|
template <> \
|
||||||
|
inline Element container(std::deque<Element>&& children) { \
|
||||||
|
Elements elements; \
|
||||||
|
for (auto& child : children) { \
|
||||||
|
elements.push_back(std::move(child)); \
|
||||||
|
} \
|
||||||
|
return container(std::move(elements)); \
|
||||||
}
|
}
|
||||||
|
|
||||||
TAKE_ANY_ARGS(vbox)
|
TAKE_ANY_ARGS(vbox)
|
||||||
|
@@ -173,7 +173,7 @@ class InputBase : public ComponentBase, public InputOption {
|
|||||||
elements.push_back(element);
|
elements.push_back(element);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto element = vbox(std::move(elements), cursor_line) | frame;
|
auto element = vbox(std::move(elements)) | frame;
|
||||||
return transform_func({
|
return transform_func({
|
||||||
std::move(element), hovered_, is_focused,
|
std::move(element), hovered_, is_focused,
|
||||||
false // placeholder
|
false // placeholder
|
||||||
|
@@ -145,8 +145,8 @@ class MenuBase : public ComponentBase, public MenuOption {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const Element bar = IsHorizontal()
|
const Element bar = IsHorizontal()
|
||||||
? hbox(std::move(elements), selected_focus_)
|
? hbox(std::move(elements))
|
||||||
: vbox(std::move(elements), selected_focus_);
|
: vbox(std::move(elements));
|
||||||
|
|
||||||
if (!underline.enabled) {
|
if (!underline.enabled) {
|
||||||
return bar | reflect(box_);
|
return bar | reflect(box_);
|
||||||
|
@@ -46,7 +46,7 @@ class RadioboxBase : public ComponentBase, public RadioboxOption {
|
|||||||
}
|
}
|
||||||
elements.push_back(element | reflect(boxes_[i]));
|
elements.push_back(element | reflect(boxes_[i]));
|
||||||
}
|
}
|
||||||
return vbox(std::move(elements), hovered_) | reflect(box_);
|
return vbox(std::move(elements)) | reflect(box_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
// NOLINTNEXTLINE(readability-function-cognitive-complexity)
|
||||||
|
@@ -2,8 +2,12 @@
|
|||||||
// Use of this source code is governed by the MIT license that can be found in
|
// Use of this source code is governed by the MIT license that can be found in
|
||||||
// the LICENSE file.
|
// the LICENSE file.
|
||||||
#include <gtest/gtest.h> // for Test, TestInfo (ptr only), EXPECT_EQ, Message, TEST, TestPartResult
|
#include <gtest/gtest.h> // for Test, TestInfo (ptr only), EXPECT_EQ, Message, TEST, TestPartResult
|
||||||
|
#include <array> // for array
|
||||||
#include <cstddef> // for size_t
|
#include <cstddef> // for size_t
|
||||||
|
#include <queue>
|
||||||
|
#include <stack> // for stack
|
||||||
#include <string> // for allocator, basic_string, string
|
#include <string> // for allocator, basic_string, string
|
||||||
|
#include <unordered_set> // for unordered_set
|
||||||
#include <vector> // for vector
|
#include <vector> // for vector
|
||||||
|
|
||||||
#include "ftxui/dom/elements.hpp" // for text, operator|, Element, flex_grow, flex_shrink, hbox
|
#include "ftxui/dom/elements.hpp" // for text, operator|, Element, flex_grow, flex_shrink, hbox
|
||||||
@@ -358,5 +362,39 @@ TEST(HBoxTest, FlexGrow_NoFlex_FlewShrink) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(HBoxTest, FromElementsContainer) {
|
||||||
|
Elements elements_vector{text("0"), text("1")};
|
||||||
|
|
||||||
|
std::array<Element, 2> elements_array{text("0"), text("1")};
|
||||||
|
|
||||||
|
std::deque<Element> elements_deque{text("0"), text("1")};
|
||||||
|
|
||||||
|
std::stack<Element> elements_stack;
|
||||||
|
elements_stack.push(text("1"));
|
||||||
|
elements_stack.push(text("0"));
|
||||||
|
|
||||||
|
std::queue<Element> elements_queue;
|
||||||
|
elements_queue.emplace(text("0"));
|
||||||
|
elements_queue.emplace(text("1"));
|
||||||
|
|
||||||
|
const std::vector<Element> collection_hboxes{
|
||||||
|
hbox(std::move(elements_vector)), hbox(std::move(elements_array)),
|
||||||
|
hbox(std::move(elements_stack)), hbox(std::move(elements_deque)),
|
||||||
|
hbox(std::move(elements_queue)),
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const Element& collection_hbox : collection_hboxes) {
|
||||||
|
Screen screen(2, 1);
|
||||||
|
Render(screen, collection_hbox);
|
||||||
|
EXPECT_EQ("01", screen.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exception: unordered set, which has no guaranteed order.
|
||||||
|
std::unordered_set<Element> elements_set{text("0"), text("0")};
|
||||||
|
Screen screen(2, 1);
|
||||||
|
Render(screen, hbox(elements_set));
|
||||||
|
EXPECT_EQ("00", screen.ToString());
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
// NOLINTEND
|
// NOLINTEND
|
||||||
|
Reference in New Issue
Block a user