Skip to content

Commit

Permalink
Merge pull request #165 from rmpowell77/dev/foreach
Browse files Browse the repository at this point in the history
Issue #164: Add ForEach, which would allow a list of Controllers to b…
  • Loading branch information
rmpowell77 authored Dec 26, 2023
2 parents 7df2c33 + 1423280 commit bf3af5d
Show file tree
Hide file tree
Showing 18 changed files with 974 additions and 138 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions LATEST_RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

3 changes: 3 additions & 0 deletions cmake/compiler.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@ macro(wxUI_SetupCompilerForTarget arg)
set_property(TARGET ${arg} PROPERTY COMPILE_WARNING_AS_ERROR ON)
endmacro()

# Adding address sanitizer (see https://stackoverflow.com/questions/44320465/whats-the-proper-way-to-enable-addresssanitizer-in-cmake-that-works-in-xcode)
add_compile_options(-fsanitize=address)
add_link_options(-fsanitize=address)
43 changes: 43 additions & 0 deletions docs/ProgrammersGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
} },
Expand Down Expand Up @@ -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!");
} },
Expand Down Expand Up @@ -207,6 +215,41 @@ 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.

```
HForEach(
std::vector<std::tuple<wxWindowID, std::string>> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }),
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
```

Often times you would be laying out a set of buttons in a horizontal sizer. The `HForEach` and `VForEach` functions are provided as convenience functions:

```
HForEach(
std::vector { wxART_PLUS, wxART_MINUS, wxART_FIND },
[](auto identity) {
return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) };
}),
```


### 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`.
Expand Down
21 changes: 21 additions & 0 deletions docs/src/docs/ProgrammersGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,27 @@ 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 " // ..." }}}
```

Often times you would be laying out a set of buttons in a horizontal sizer. The `HForEach` and `VForEach` functions are provided as convenience functions:

```
{{{ examples/HelloWorld/ExtendedExample.cpp HForEach " // ..." }}}
```


### 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`.
Expand Down
118 changes: 118 additions & 0 deletions examples/HelloWorld/ExtendedExample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ SOFTWARE.
// wxUI "Hello World" example

#include "ExtendedExample.h"
#include <wx/artprov.h>
#include <wxUI/wxUI.h>

ExtendedExample::ExtendedExample(wxWindow* parent)
Expand Down Expand Up @@ -223,3 +224,120 @@ 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<std::string> { "A", "B", "C" },
[](auto name) {
return wxUI::Button { name };
} },
},
HForEach(
std::vector<std::string> { "A", "B", "C" },
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
std::vector { "A", "B", "C" },
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
{ "A"s, "B"s, "C"s },
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
{ "A", "B", "C" },
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
std::vector { "A", "B", "C" },
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
std::vector<wxArtID> { wxART_PLUS, wxART_MINUS, wxART_FIND },
[](auto identity) {
return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) };
}),
HForEach(
std::vector<wxArtID> { wxART_PLUS, wxART_MINUS, wxART_FIND },
[](auto identity) {
return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) };
}),
HForEach(
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
// snippet HForEach
HForEach(
std::vector { wxART_PLUS, wxART_MINUS, wxART_FIND },
[](auto identity) {
return wxUI::BitmapButton { wxArtProvider::GetBitmap(identity) };
}),
// endsnippet HForEach
HForEach(
std::vector { "Long string", "Ball", "S", "Tools" } | std::views::filter([](auto s) { return std::string(s).size() < 5; }),
[](auto name) {
return wxUI::Button { name };
}),
HForEach(
std::vector { std::tuple<wxWindowID, std::string> { wxID_CANCEL, "A" }, std::tuple<wxWindowID, std::string> { wxID_OK, "B" } },
[](auto identityAndName) {
return wxUI::Button { std::get<0>(identityAndName), std::get<1>(identityAndName) };
}),
HForEach(
std::vector { std::tuple<wxWindowID, std::string> { wxID_CANCEL, "A" }, std::tuple<wxWindowID, std::string> { wxID_OK, "B" } },
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
HForEach(
{ std::tuple<wxWindowID, std::string> { wxID_CANCEL, "A" }, std::tuple<wxWindowID, std::string> { wxID_OK, "B" } },
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
HForEach(
std::vector<std::tuple<wxWindowID, std::string>> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } },
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
// snippet ComplicatedForEachExample
HForEach(
std::vector<std::tuple<wxWindowID, std::string>> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }),
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
// endsnippet ComplicatedForEachExample
HForEach(
std::vector<std::tuple<wxWindowID, std::string>> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }),
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
HForEach(
std::vector<std::tuple<wxWindowID, std::string>> { { wxID_CANCEL, "A" }, { wxID_OK, "B" } } | std::views::filter([](auto s) { return std::get<1>(s) == "B"; }),
[](auto identity, auto name) {
return wxUI::Button { identity, name };
}),
CreateStdDialogButtonSizer(wxOK),
}
.attachTo(this);
}
5 changes: 5 additions & 0 deletions examples/HelloWorld/ExtendedExample.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,8 @@ class GenericExample : public wxDialog {

private:
};

class ForEachExample : public wxDialog {
public:
explicit ForEachExample(wxWindow* parent);
};
4 changes: 4 additions & 0 deletions examples/HelloWorld/HelloWorld.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
} },
Expand Down
Loading

0 comments on commit bf3af5d

Please sign in to comment.