Skip to content

Commit

Permalink
Issue #156: We should be able to take ranges of std::string for choic…
Browse files Browse the repository at this point in the history
…es, list boxes, etc
  • Loading branch information
rmpowell77 committed Nov 26, 2023
1 parent 900f77e commit d9a778a
Show file tree
Hide file tree
Showing 3 changed files with 74 additions and 8 deletions.
44 changes: 36 additions & 8 deletions include/wxUI/Choice.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,53 @@ namespace wxUI {
struct Choice : public details::WidgetDetails<Choice, wxChoice> {
using super = details::WidgetDetails<Choice, wxChoice>;

explicit Choice(wxWindowID identity, std::vector<wxString> choices = {})
explicit Choice(wxWindowID identity, std::initializer_list<std::string> choices = {})
: super(identity)
, choices(std::move(choices))
, choices(details::Ranges::converter(choices))
{
static_assert(std::convertible_to<std::string, wxString>);
}

explicit Choice(std::vector<wxString> choices = {})
: Choice(wxID_ANY, std::move(choices))
Choice(std::initializer_list<std::string> choices)
: Choice(wxID_ANY, choices)
{
}

explicit Choice(wxSizerFlags const& flags, wxWindowID identity, std::vector<wxString> choices = {})
explicit Choice(wxSizerFlags const& flags, wxWindowID identity, std::initializer_list<std::string> choices)
: super(flags, identity)
, choices(std::move(choices))
, choices(details::Ranges::converter(choices))
{
}

explicit Choice(wxSizerFlags const& flags, std::vector<wxString> choices = {})
: Choice(flags, wxID_ANY, std::move(choices))
Choice(wxSizerFlags const& flags, wxWindowID identity)
: super(flags, identity)
{
}

explicit Choice(wxSizerFlags const& flags, std::initializer_list<std::string> choices)
: Choice(flags, wxID_ANY, choices)
{
}

explicit Choice(wxSizerFlags const& flags)
: Choice(flags, wxID_ANY)
{
}

Choice(wxWindowID identity, details::Ranges::input_range_of<wxString> auto&& choices)
: super(identity)
, choices(details::Ranges::ToVector<wxString>(std::forward<decltype(choices)>(choices)))
{
}

explicit Choice(details::Ranges::input_range_of<wxString> auto&& choices)
: Choice(wxID_ANY, std::forward<decltype(choices)>(choices))
{
}

explicit Choice(wxSizerFlags const& flags, wxWindowID identity, details::Ranges::input_range_of<std::string_view> auto&& choices)
: super(flags, identity)
, choices(std::forward(choices))
{
}

Expand Down
26 changes: 26 additions & 0 deletions include/wxUI/Widget.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,32 @@ concept Createable = requires(T widget, wxWindow* window)
widget.create(window);
};

namespace Ranges {

template <typename T>
requires(std::is_convertible_v<T, wxString>)
inline auto converter(std::initializer_list<T> choices) -> std::vector<wxString>
{
std::vector<wxString> result;
std::ranges::copy(choices, std::back_inserter(result));
return result;
}


template <typename R, typename T>
concept input_range_of = std::ranges::input_range<R> && std::convertible_to<std::ranges::range_value_t<R>, T>;

// This is due to missing support for ranges::to()
template <typename T, std::ranges::range Range>
requires std::convertible_to<std::ranges::range_value_t<Range>, T>
inline auto ToVector(Range&& range) -> std::vector<T>
{
auto result = std::vector<T>{};
std::ranges::copy(std::forward<Range>(range), std::back_inserter(result));
return result;
}
}

// clang-format on

template <class... Ts>
Expand Down
12 changes: 12 additions & 0 deletions tests/wxUI_ChoiceTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ SOFTWARE.
*/
#include "wxUI_TestControlCommon.h"
#include <catch2/catch_test_macros.hpp>
#include <ranges>
#include <wxUI/Choice.h>

#include <wx/wx.h>
Expand Down Expand Up @@ -70,6 +71,17 @@ TEST_CASE("Choice")
CHECK("Goodbye" == window->GetString(1));
}

SECTION("choice")
{
wxFrame frame { nullptr, wxID_ANY, "" };
auto uut = TypeUnderTest { std::views::iota(0, 3) | std::views::transform([](auto i) { return std::to_string(i); }) };
auto* window = dynamic_cast<TypeUnderTest::underlying_t*>(uut.create(&frame));
CHECK(2 == window->GetCount());
CHECK(0 == window->GetSelection());
CHECK("Hello" == window->GetString(0));
CHECK("Goodbye" == window->GetString(1));
}

SECTION("id")
{
wxFrame frame { nullptr, wxID_ANY, "" };
Expand Down

0 comments on commit d9a778a

Please sign in to comment.