You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Working on the Addon Settings window, I'm really fed up with the task of manually laying out controls. Is there interest in a set of helper classes to simplify building GUI layouts?
I envision a two-step process, first, defining the layout using a builder pattern API, that computes a bunch of rectangles, then adding the controls using those rectangles in order. The builder API would require some redundancy, to spot certain errors early in the build phase and not later in the use phase, where they may be more difficult to locate.
Every node in the layout would be named, auto-generated from the associated control ID using a macro, if applicable. Again, this is to provide meaningful error messages.
Here's what I've come up with so far (this is based on iwAddons.cpp and uses the IDs defined there):
// gives us a string of the ID for helpful error messages
#defineLAYOUT_ID(x) static_cast<unsigned>(x), STRINGIZE(x)
#defineLAYOUT_NAME(x) STRINGIZE(x)
// clang-format offauto lyt = LayoutBuilder(/* Window* */this) // Window* for GetSize()
.Vertical(/* name for error message */"root", /* num items */3, layout::Spacing(10))
.Item(LAYOUT_ID(ID_txtAddFeatures), layout::Height(NormalFont.getHeight()))
.Horizontal(LAYOUT_NAME(ID_grpAddonGroup), 5, layout::Spacing(10), layout::Height(22))
.Item(LAYOUT_ID(AddonGroup::All))
// the other buttons
.Done() // report an error if number of added layout items != 5
.Horizontal("scrollView", 2, layout::Spacing(10))
.Item(LAYOUT_ID(ID_grpAddonsStart))
.Item(LAYOUT_ID(ID_scroll), layout::Width(SCROLLBAR_WIDTH))
.Done()
.Done()
.Done(); // compute rectangles for each leaf node; easy, right?// clang-format on// calls lyt(id) -> Rect, forwards to AddText() overload with DrawPoint// lyt(id) makes sure id matches the expected ID and generates an error otherwiseAddText(ID_txtAddFeatures, lyt, _("Additional features:"), COLOR_YELLOW, FontStyle{}, NormalFont);
ctrlOptionGroup* optiongroup = AddOptionGroup(ID_grpAddonGroup, GroupSelectType::Check);
// could also do the static_cast in the overload and SFINAE on std::is_unsigned_v(std::underlying_type_t<>)
optiongroup->AddTextButton(static_cast<unsigned>(AddonGroup::All), lyt, TextureColor::Green2, _("All"), NormalFont);
// ...
I'm using strong typing for things like widths, heights, etc. to provide more concise overloads. Would probably rely on some TMP to not repeat myself.
No strings would be stored in Release builds and error checking would only be active in Debug builds.
This is just a start. I've put more thought into some aspects and implementation details. Just let me know if I should pursue this or spend my time elsewhere. (I really want this – or something like it – for more UI work I'd like to do.)
The text was updated successfully, but these errors were encountered:
I also like that especially with the similar structure to other GUI frameworks.
What bothers me a bit is the duplication (of the IDs) but I guess splitting the layout from the control-adding also has its benefits.
I'm not sure about the num_items param though: What do we gain by that? I think being able to just add items as you go is a feature. Especially for changes: Adding a new item would then be a single line change instead of 2.
Working on the Addon Settings window, I'm really fed up with the task of manually laying out controls. Is there interest in a set of helper classes to simplify building GUI layouts?
I envision a two-step process, first, defining the layout using a builder pattern API, that computes a bunch of rectangles, then adding the controls using those rectangles in order. The builder API would require some redundancy, to spot certain errors early in the build phase and not later in the use phase, where they may be more difficult to locate.
Every node in the layout would be named, auto-generated from the associated control ID using a macro, if applicable. Again, this is to provide meaningful error messages.
Here's what I've come up with so far (this is based on
iwAddons.cpp
and uses the IDs defined there):I'm using strong typing for things like widths, heights, etc. to provide more concise overloads. Would probably rely on some TMP to not repeat myself.
No strings would be stored in Release builds and error checking would only be active in Debug builds.
This is just a start. I've put more thought into some aspects and implementation details. Just let me know if I should pursue this or spend my time elsewhere. (I really want this – or something like it – for more UI work I'd like to do.)
The text was updated successfully, but these errors were encountered: