pcbjam/tests/apps/standalone/radiogroups/radiogroups_test.cpp
Istvan Matejcsok 13cac06778 fix(wasm): radio groups no longer merge into one
Bump wxwidgets to the %p->%zu radio-group name fix and add a standalone
wxWidgets harness plus an e2e regression that asserts three radio groups
in one window select independently. Build artifacts are gitignored; only
radiogroups_test.cpp is tracked.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 12:54:35 +02:00

143 lines
5.4 KiB
C++

// wxRadioButton Group Test - exercises MULTIPLE radio-button groups in one window
//
// KiCad's Preferences "Mouse and Touchpad" panel lays out three independent
// scroll-gesture radio groups (Zoom / Pan up-down / Pan left-right), each as a
// row of [--, Ctrl, Shift, Alt] radios with the first button flagged wxRB_GROUP.
//
// In the WASM DOM port the per-group HTML "name" must be unique per group so the
// browser keeps the groups independent. This harness reproduces that layout: it
// pre-selects a DIFFERENT column in each of the three groups, so a correctly
// grouped build shows exactly one selection PER ROW (three total). If the groups
// collapse into one (the %p-empty-name bug), only one radio across all three
// rows can stay checked.
#include "wx/wxprec.h"
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/statline.h"
#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#endif
class RadioGroupsFrame : public wxFrame
{
public:
RadioGroupsFrame()
: wxFrame(nullptr, wxID_ANY, "wxRadioButton Group Test",
wxDefaultPosition, wxSize(640, 420))
{
wxPanel* panel = new wxPanel(this);
wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
wxStaticText* desc = new wxStaticText(panel, wxID_ANY,
"Three INDEPENDENT radio groups (mirrors KiCad's scroll-gesture panel).\n"
"Each row pre-selects a different column, so a correct build shows one\n"
"selection per row (three total). If the groups merge, only one survives.");
mainSizer->Add(desc, 0, wxALL, 8);
// 5-column grid: row label + [--, Ctrl, Shift, Alt]
wxFlexGridSizer* grid = new wxFlexGridSizer(5, 6, 12);
grid->Add(new wxStaticText(panel, wxID_ANY, ""));
grid->Add(new wxStaticText(panel, wxID_ANY, "--"), 0, wxALIGN_CENTER);
grid->Add(new wxStaticText(panel, wxID_ANY, "Ctrl"), 0, wxALIGN_CENTER);
grid->Add(new wxStaticText(panel, wxID_ANY, "Shift"), 0, wxALIGN_CENTER);
grid->Add(new wxStaticText(panel, wxID_ANY, "Alt"), 0, wxALIGN_CENTER);
// Row order and wxRB_GROUP flags MUST match the real panel: each row's
// first radio starts a new group; the rest join it.
addGroupRow(panel, grid, "Group A (Zoom)", m_groupA);
addGroupRow(panel, grid, "Group B (Pan up/down)", m_groupB);
addGroupRow(panel, grid, "Group C (Pan left/right)", m_groupC);
mainSizer->Add(grid, 0, wxALL, 12);
wxButton* check = new wxButton(panel, wxID_ANY, "Check selections");
check->Bind(wxEVT_BUTTON, &RadioGroupsFrame::OnCheck, this);
mainSizer->Add(check, 0, wxLEFT | wxBOTTOM, 12);
mainSizer->Add(new wxStaticText(panel, wxID_ANY, "Log"), 0, wxLEFT, 12);
m_log = new wxTextCtrl(panel, wxID_ANY, "", wxDefaultPosition, wxSize(-1, 110),
wxTE_MULTILINE | wxTE_READONLY);
mainSizer->Add(m_log, 1, wxEXPAND | wxALL, 12);
panel->SetSizer(mainSizer);
CreateStatusBar();
SetStatusText("radio groups test app started");
Log("radio groups test app started");
// Pre-select a DIFFERENT column per group (distinct, like the real
// defaults: Zoom=--, Pan up/down=Shift, Pan left/right=Ctrl). Deferred
// until after the frame is shown, mirroring how real panels apply
// settings in TransferDataToWindow(); SetValue() from the ctor runs
// before the DOM radio nodes are realized and would not paint.
CallAfter([this]
{
m_groupA[COL_NONE]->SetValue(true);
m_groupB[COL_SHIFT]->SetValue(true);
m_groupC[COL_CTRL]->SetValue(true);
Log("Initial selection: A=--, B=Shift, C=Ctrl (one per group)");
});
}
private:
enum Col { COL_NONE = 0, COL_CTRL, COL_SHIFT, COL_ALT, COL_COUNT };
void addGroupRow(wxWindow* parent, wxFlexGridSizer* grid, const wxString& label,
wxRadioButton* (&out)[COL_COUNT])
{
grid->Add(new wxStaticText(parent, wxID_ANY, label), 0, wxALIGN_CENTER_VERTICAL);
for (int c = 0; c < COL_COUNT; ++c)
{
// First radio of the row starts a fresh group.
long style = (c == 0) ? wxRB_GROUP : 0;
out[c] = new wxRadioButton(parent, wxID_ANY, "", wxDefaultPosition,
wxDefaultSize, style);
grid->Add(out[c], 0, wxALIGN_CENTER);
}
}
void OnCheck(wxCommandEvent&)
{
Log(wxString::Format("Group A: %s", selectedCol(m_groupA)));
Log(wxString::Format("Group B: %s", selectedCol(m_groupB)));
Log(wxString::Format("Group C: %s", selectedCol(m_groupC)));
}
wxString selectedCol(wxRadioButton* (&group)[COL_COUNT])
{
static const char* names[COL_COUNT] = { "--", "Ctrl", "Shift", "Alt" };
for (int c = 0; c < COL_COUNT; ++c)
{
if (group[c]->GetValue())
return names[c];
}
return "(none!)";
}
void Log(const wxString& msg) { m_log->AppendText(msg + "\n"); }
wxRadioButton* m_groupA[COL_COUNT];
wxRadioButton* m_groupB[COL_COUNT];
wxRadioButton* m_groupC[COL_COUNT];
wxTextCtrl* m_log;
};
class RadioGroupsApp : public wxApp
{
public:
virtual bool OnInit() override
{
RadioGroupsFrame* frame = new RadioGroupsFrame();
frame->Show();
return true;
}
};
wxIMPLEMENT_APP(RadioGroupsApp);