diff --git a/CMakeLists.txt b/CMakeLists.txt index ba4cf1b..3ed763d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -43,6 +43,7 @@ add_library( include/wxUI/Choice.h include/wxUI/ComboBox.h include/wxUI/Custom.h + include/wxUI/ForEach.h include/wxUI/Generic.h include/wxUI/GetterSetter.h include/wxUI/HelperMacros.h diff --git a/LATEST_RELEASE_NOTES.md b/LATEST_RELEASE_NOTES.md index a1f0f0a..0f6debc 100644 --- a/LATEST_RELEASE_NOTES.md +++ b/LATEST_RELEASE_NOTES.md @@ -8,4 +8,5 @@ Other changes: * [#156](../../issues/156) We should be able to take ranges of std::string for choices, list boxes, etc * [#157](../../issues/157) Text needs withWrap * [#161](../../issues/161) Need to have a setEnabled for Widgets +* [#164](../../issues/164) Add ForEach, which would allow a list of Controllers to be added diff --git a/docs/ProgrammersGuide.md b/docs/ProgrammersGuide.md index c1cc366..fc22008 100644 --- a/docs/ProgrammersGuide.md +++ b/docs/ProgrammersGuide.md @@ -58,6 +58,10 @@ Handlers are callable items that handle events. The handler can be declared wit GenericExample dialog(this); dialog.ShowModal(); } }, + wxUI::Item { "&ForEachExample...", [this] { + ForEachExample dialog(this); + dialog.ShowModal(); + } }, wxUI::Item { "&Example Item...", [] { wxLogMessage("Hello World!"); } }, @@ -109,6 +113,10 @@ Items { "Name", "Help", Handler } GenericExample dialog(this); dialog.ShowModal(); } }, + wxUI::Item { "&ForEachExample...", [this] { + ForEachExample dialog(this); + dialog.ShowModal(); + } }, wxUI::Item { "&Example Item...", [] { wxLogMessage("Hello World!"); } }, @@ -207,6 +215,33 @@ Essentially, you supply a object that converts to `wxSizer*` or `wxWindow*`, or .attachTo(this); ``` +#### ForEach + +Often times you will need to layout several widgets which only are different in their wxWindowID and Name. Or perhaps there are cases where the items to be laid out are dynamic. `ForEach` allows you to specify a range of values or `std::tuples` that are arguements to a closure that will returns a *Controller*. These will then be added one at a time. + +``` + HSizer { + ForEach { + { wxART_PLUS, wxART_MINUS, wxART_FIND }, + [](auto identity) { + return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) }; + } }, + }, +``` + +*Ranges* are valid arguments for `ForEach`, which allows you to build up complicated layouts at run time. + +``` + HSizer { + ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }), + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, +``` + + ### Controllers *Controllers* are the general term to refer to items that behave like a [`wxContol`](https://docs.wxwidgets.org/3.0/classwx_control.html). In `wxUI` we attempt to conform a consistent style that favors the common things you do with a specific `wxControl`. diff --git a/docs/src/docs/ProgrammersGuide.md b/docs/src/docs/ProgrammersGuide.md index fdadb26..def4403 100644 --- a/docs/src/docs/ProgrammersGuide.md +++ b/docs/src/docs/ProgrammersGuide.md @@ -103,6 +103,21 @@ Essentially, you supply a object that converts to `wxSizer*` or `wxWindow*`, or {{{ examples/HelloWorld/ExtendedExample.cpp SplitterExample " // ..." }}} ``` +#### ForEach + +Often times you will need to layout several widgets which only are different in their wxWindowID and Name. Or perhaps there are cases where the items to be laid out are dynamic. `ForEach` allows you to specify a range of values or `std::tuples` that are arguements to a closure that will returns a *Controller*. These will then be added one at a time. + +``` +{{{ examples/HelloWorld/ExtendedExample.cpp ForEachExample " // ..." }}} +``` + +*Ranges* are valid arguments for `ForEach`, which allows you to build up complicated layouts at run time. + +``` +{{{ examples/HelloWorld/ExtendedExample.cpp ComplicatedForEachExample " // ..." }}} +``` + + ### Controllers *Controllers* are the general term to refer to items that behave like a [`wxContol`](https://docs.wxwidgets.org/3.0/classwx_control.html). In `wxUI` we attempt to conform a consistent style that favors the common things you do with a specific `wxControl`. diff --git a/examples/HelloWorld/ExtendedExample.cpp b/examples/HelloWorld/ExtendedExample.cpp index db21596..0fbb796 100644 --- a/examples/HelloWorld/ExtendedExample.cpp +++ b/examples/HelloWorld/ExtendedExample.cpp @@ -24,6 +24,7 @@ SOFTWARE. // wxUI "Hello World" example #include "ExtendedExample.h" +#include #include ExtendedExample::ExtendedExample(wxWindow* parent) @@ -223,3 +224,124 @@ GenericExample::GenericExample(wxWindow* parent) assert(proxy1->GetLabel() == "Raw 1"); assert(proxy2->GetLabel() == "Raw 2"); } + +ForEachExample::ForEachExample(wxWindow* parent) + : wxDialog(parent, wxID_ANY, "ForEach Example", wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) +{ + using namespace wxUI; + using namespace std::literals; + VSizer { + wxSizerFlags {}.Border(wxALL, 2), + HSizer { + ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + { "A"s, "B"s, "C"s }, + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + std::vector { wxART_PLUS, wxART_MINUS, wxART_FIND }, + [](auto identity) { + return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) }; + } }, + }, + HSizer { + ForEach { + std::vector { wxART_PLUS, wxART_MINUS, wxART_FIND }, + [](auto identity) { + return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) }; + } }, + }, + HSizer { + ForEach { + std::vector { wxART_PLUS, wxART_MINUS, wxART_FIND }, + [](auto identity) { + return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) }; + } }, + }, + // snippet ForEachExample + HSizer { + ForEach { + { wxART_PLUS, wxART_MINUS, wxART_FIND }, + [](auto identity) { + return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) }; + } }, + }, + // endsnippet ForEachExample + HSizer { + ForEach { + std::vector { "Long string", "Ball", "S", "Tools" } | std::views::filter([](auto s) { return std::string(s).size() < 5; }), + [](auto name) { + return wxUI::Button { name }; + } }, + }, + HSizer { + ForEach { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" } }, + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, + HSizer { + ForEach { + { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" } }, + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, + HSizer { + ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } }, + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, + // snippet ComplicatedForEachExample + HSizer { + ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }), + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, + // endsnippet ComplicatedForEachExample + HSizer { + ForEach { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }), + [](auto identityAndName) { + return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) }; + } }, + }, + CreateStdDialogButtonSizer(wxOK), + } + .attachTo(this); +} diff --git a/examples/HelloWorld/ExtendedExample.h b/examples/HelloWorld/ExtendedExample.h index 9560fc1..84e714a 100644 --- a/examples/HelloWorld/ExtendedExample.h +++ b/examples/HelloWorld/ExtendedExample.h @@ -59,3 +59,8 @@ class GenericExample : public wxDialog { private: }; + +class ForEachExample : public wxDialog { +public: + explicit ForEachExample(wxWindow* parent); +}; diff --git a/examples/HelloWorld/HelloWorld.cpp b/examples/HelloWorld/HelloWorld.cpp index d24b18c..2c29710 100644 --- a/examples/HelloWorld/HelloWorld.cpp +++ b/examples/HelloWorld/HelloWorld.cpp @@ -138,6 +138,10 @@ HelloWorldFrame::HelloWorldFrame() GenericExample dialog(this); dialog.ShowModal(); } }, + wxUI::Item { "&ForEachExample...", [this] { + ForEachExample dialog(this); + dialog.ShowModal(); + } }, wxUI::Item { "&Example Item...", [] { wxLogMessage("Hello World!"); } }, diff --git a/include/wxUI/ForEach.h b/include/wxUI/ForEach.h new file mode 100644 index 0000000..e30a135 --- /dev/null +++ b/include/wxUI/ForEach.h @@ -0,0 +1,113 @@ +/* +MIT License + +Copyright (c) 2022 Richard Powell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#pragma once + +#include "Widget.h" + +namespace wxUI { + +// how does this work. We want to write: +// wxUI::ForEach({ "These", "are", "some", "buttons"}, [](wxWindow*, auto str) { return wxUI::Button{str}; }); +// or is this better: +// wxUI::ForEach([](wxWindow*, auto str) { return wxUI::Button{str}; }, "These", "are", "some", "buttons" ); +// wxUI::ForEach{ { "These", "are", "some", "buttons" } | std::views::filter([](auto a) { return a.size() < 5; }), [](wxWindow*, auto str) { return wxUI::Button{str}; }}; +// would create an array of Buttons. +namespace details { + // // Concept to check if a type is callable + // template + // concept Callable = std::invocable; + + // Concept to check if a callable object returns something callable + template + concept CallableAndReturnsCreateAndAddable = requires(F func, Args... args) { + requires CreateAndAddable>; + }; + + template + concept CallableAndReturnsWindow = std::is_convertible_v, wxWindow*>; +} + +template +struct ForEach { + + using LocalCreateForEach = std::function; + + template CreateFunction> + ForEach(std::initializer_list args, CreateFunction createFunction) + : args(args) + , createFunction(createFunction) + { + } + + template CreateFunction> + ForEach(wxSizerFlags const& flags, std::initializer_list args, CreateFunction createFunction) + : flags(flags) + , args(args) + , createFunction(createFunction) + { + } + + template CreateFunction> + ForEach(details::Ranges::input_range_of auto&& args, CreateFunction createFunction) + : args(details::Ranges::ToVector(std::forward(args))) + , createFunction(createFunction) + { + } + + template CreateFunction> + ForEach(wxSizerFlags const& flags, details::Ranges::input_range_of auto&& args, CreateFunction createFunction) + : flags(flags) + , args(details::Ranges::ToVector(std::forward(args))) + , createFunction(createFunction) + { + } + + void createAndAdd(wxWindow* parent, wxSizer* parentSizer, wxSizerFlags const& parentFlags) const + { + for (auto& item : args) { + createFunction(item).createAndAdd(parent, parentSizer, flags ? *flags : parentFlags); + } + } + +private: + std::optional flags {}; + std::vector args; + LocalCreateForEach createFunction; +}; + +template +ForEach(std::initializer_list args, Function createFunction) -> ForEach, Arg>; + +template +ForEach(wxSizerFlags const& flags, std::initializer_list args, Function createFunction) -> ForEach, Arg>; + +template +ForEach(Range&& args, Function createFunction) -> ForEach>, std::ranges::range_value_t>; + +template +ForEach(wxSizerFlags const& flags, Range&& args, Function createFunction) -> ForEach>, std::ranges::range_value_t>; + +} + +#include "ZapMacros.h" diff --git a/include/wxUI/Splitter.h b/include/wxUI/Splitter.h index 4ac7977..5e8153d 100644 --- a/include/wxUI/Splitter.h +++ b/include/wxUI/Splitter.h @@ -95,11 +95,7 @@ struct HSplitter : public details::WidgetDetails, wxSplitterWi auto createImpl(wxWindow* parent) -> wxWindow* override { auto* widget = super::setProxy(new underlying_t(parent, super::getIdentity(), super::getPos(), super::getSize(), super::getStyle())); - auto* widget0 = std::get<0>(widgets).create(widget); - auto* widget1 = std::get<1>(widgets).create(widget); - - widget->SplitHorizontally(widget0, widget1); - + widget->SplitHorizontally(std::get<0>(widgets).create(widget), std::get<1>(widgets).create(widget)); return widget; } }; diff --git a/include/wxUI/wxUI.h b/include/wxUI/wxUI.h index 8ca1503..579a0d4 100644 --- a/include/wxUI/wxUI.h +++ b/include/wxUI/wxUI.h @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include diff --git a/tests/BuildTests/CMakeLists.txt b/tests/BuildTests/CMakeLists.txt index 3357432..19f6dfd 100644 --- a/tests/BuildTests/CMakeLists.txt +++ b/tests/BuildTests/CMakeLists.txt @@ -11,6 +11,7 @@ target_sources(wxUI_Tests PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/Choice.cpp ${CMAKE_CURRENT_SOURCE_DIR}/ComboBox.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Custom.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/ForEach.cpp ${CMAKE_CURRENT_SOURCE_DIR}/Generic.cpp ${CMAKE_CURRENT_SOURCE_DIR}/GetterSetter.cpp ${CMAKE_CURRENT_SOURCE_DIR}/HelperMacros.cpp diff --git a/tests/BuildTests/ForEach.cpp b/tests/BuildTests/ForEach.cpp new file mode 100644 index 0000000..a11e0b3 --- /dev/null +++ b/tests/BuildTests/ForEach.cpp @@ -0,0 +1,38 @@ +/* +MIT License + +Copyright (c) 2022 Richard Powell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +// Generated with bash command +// for i in *.cpp; do echo \#include \ > Layout.cpp; for j in RULE_OF_SIX_BOILERPLATE PROXY_BOILERPLATE WIDGET_STATIC_ASSERT_BOILERPLATE; do echo \#if defined\(WIDGET_STATIC_ASSERT_BOILERPLATE\) >> Layout.cpp; echo \#error Missed zapping WIDGET_STATIC_ASSERT_BOILERPLATE >> Layout.cpp; echo \#endif >> Layout.cpp; done; done +#include + +#if defined(RULE_OF_SIX_BOILERPLATE) +#error Missed zapping RULE_OF_SIX_BOILERPLATE +#endif + +#if defined(PROXY_BOILERPLATE) +#error Missed zapping PROXY_BOILERPLATE +#endif + +#if defined(WIDGET_STATIC_ASSERT_BOILERPLATE) +#error Missed zapping WIDGET_STATIC_ASSERT_BOILERPLATE +#endif diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 03b6e51..e3b718f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -9,6 +9,7 @@ add_executable(wxUI_Tests ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_CheckBoxTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_ChoiceTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_ComboBoxTests.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_ForEachTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_GenericTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_GetterSetterTests.cpp ${CMAKE_CURRENT_SOURCE_DIR}/wxUI_HSplitterTests.cpp diff --git a/tests/wxUI_ForEachTests.cpp b/tests/wxUI_ForEachTests.cpp new file mode 100644 index 0000000..63d299e --- /dev/null +++ b/tests/wxUI_ForEachTests.cpp @@ -0,0 +1,686 @@ +/* +MIT License + +Copyright (c) 2022 Richard Powell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +*/ +#include +#include +#include +#include + +#include + +// NOLINTBEGIN(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers, readability-function-cognitive-complexity) + +TEST_CASE("ForEach") +{ + SECTION("ForEach.Vector.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.T.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.T.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.T.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.T.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Vector.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Range.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.InitializerList.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.T.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.T.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.T.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.T.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { "A", "B", "C" } | std::views::filter([](auto str) { return str[0] == 'A'; }), + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Vector.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.Tuple.NonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector> { { wxID_CANCEL, "A" }, { wxID_OK, "B" }, { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.Range.Tuple.NonSpecificForEachNonSpecificVector") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + std::vector { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } } | std::views::filter([](auto item) { return std::get<1>(item)[0] == 'A'; }), + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.T.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.T.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + { "A", "B", "C" }, + [](auto name) { + return wxUI::Button { name }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.Tuple.Overspecified") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach> { + wxSizerFlags {}, + { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } + SECTION("ForEach.Sizer.InitializerList.Tuple.NonSpecificForEach") + { + wxFrame frame { nullptr, wxID_ANY, "" }; + auto sizer = wxBoxSizer(wxHORIZONTAL); + auto uut = wxUI::ForEach { + wxSizerFlags {}, + { std::tuple { wxID_CANCEL, "A" }, std::tuple { wxID_OK, "B" }, std::tuple { wxID_APPLY, "C" } }, + [](auto name) { + return wxUI::Button { std::get<0>(name), std::get<1>(name) }; + } + }; + uut.createAndAdd(&frame, &sizer, wxSizerFlags {}); + } +} +// NOLINTEND(cppcoreguidelines-avoid-magic-numbers, readability-magic-numbers, readability-function-cognitive-complexity)