From 18da5b8269706472f6c0fa09dcbae605a477da19 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 15 Jun 2025 01:57:27 +0200 Subject: [PATCH] Add persistence support for groups of wxRadioButton controls Allow to easily save and restore the selected radio button. Closes #25530. --- Makefile.in | 1 + build/bakefiles/files.bkl | 1 + build/cmake/files.cmake | 1 + build/files | 1 + build/msw/wx_core.vcxproj | 1 + build/msw/wx_core.vcxproj.filters | 3 + include/wx/persist/radiobut.h | 113 ++++++++++++++++++++++++++++++ interface/wx/persist/radiobut.h | 75 ++++++++++++++++++++ tests/allheaders.h | 1 + 9 files changed, 197 insertions(+) create mode 100644 include/wx/persist/radiobut.h create mode 100644 interface/wx/persist/radiobut.h diff --git a/Makefile.in b/Makefile.in index 938518f775..574640cc88 100644 --- a/Makefile.in +++ b/Makefile.in @@ -3955,6 +3955,7 @@ COND_USE_GUI_1_ALL_GUI_HEADERS = \ wx/persist.h \ wx/persist/bookctrl.h \ wx/persist/dataview.h \ + wx/persist/radiobut.h \ wx/persist/splitter.h \ wx/persist/toplevel.h \ wx/persist/treebook.h \ diff --git a/build/bakefiles/files.bkl b/build/bakefiles/files.bkl index b6f000dc6c..8259168f61 100644 --- a/build/bakefiles/files.bkl +++ b/build/bakefiles/files.bkl @@ -1229,6 +1229,7 @@ IMPORTANT: please read docs/tech/tn0016.txt before modifying this file! wx/persist.h wx/persist/bookctrl.h wx/persist/dataview.h + wx/persist/radiobut.h wx/persist/splitter.h wx/persist/toplevel.h wx/persist/treebook.h diff --git a/build/cmake/files.cmake b/build/cmake/files.cmake index c768c4f3ef..093d06793f 100644 --- a/build/cmake/files.cmake +++ b/build/cmake/files.cmake @@ -1130,6 +1130,7 @@ set(GUI_CMN_HDR wx/persist.h wx/persist/bookctrl.h wx/persist/dataview.h + wx/persist/radiobut.h wx/persist/splitter.h wx/persist/toplevel.h wx/persist/treebook.h diff --git a/build/files b/build/files index 15bfe3e2e2..6a653ab32b 100644 --- a/build/files +++ b/build/files @@ -1158,6 +1158,7 @@ GUI_CMN_HDR = wx/persist/checkbox.h wx/persist/combobox.h wx/persist/dataview.h + wx/persist/radiobut.h wx/persist/splitter.h wx/persist/toplevel.h wx/persist/treebook.h diff --git a/build/msw/wx_core.vcxproj b/build/msw/wx_core.vcxproj index b3270f5873..ec6acc50f3 100644 --- a/build/msw/wx_core.vcxproj +++ b/build/msw/wx_core.vcxproj @@ -2049,6 +2049,7 @@ + diff --git a/build/msw/wx_core.vcxproj.filters b/build/msw/wx_core.vcxproj.filters index cf97bfbb81..603199dd6f 100644 --- a/build/msw/wx_core.vcxproj.filters +++ b/build/msw/wx_core.vcxproj.filters @@ -2086,6 +2086,9 @@ Common Headers + + Common Headers + Common Headers diff --git a/include/wx/persist/radiobut.h b/include/wx/persist/radiobut.h new file mode 100644 index 0000000000..343882512e --- /dev/null +++ b/include/wx/persist/radiobut.h @@ -0,0 +1,113 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/radiobut.h +// Purpose: Persistence support for wxRadioButton. +// Author: Vadim Zeitlin +// Created: 2025-06-12 +// Copyright: (c) 2025 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _WX_PERSIST_RADIOBUT_H_ +#define _WX_PERSIST_RADIOBUT_H_ + +#include "wx/persist/window.h" + +#include "wx/radiobut.h" + +#if wxUSE_RADIOBTN + +// ---------------------------------------------------------------------------- +// string constants used by wxPersistentRadioButton +// ---------------------------------------------------------------------------- + +#define wxPERSIST_RADIOBUTTON_KIND wxASCII_STR("RadioButton") + +#define wxPERSIST_RADIOBUTTON_VALUE wxASCII_STR("Value") + +// ---------------------------------------------------------------------------- +// wxPersistentRadioButton: supports saving/restoring radio buttons state +// ---------------------------------------------------------------------------- + +// This class should be always used with the first button in a group of radio +// buttons and it saves its state as an integer indicating the offset of the +// selected radio button in this group. +// +// Currently radio buttons with wxRB_SINGLE style are not supported. While it +// wouldn't be very difficult to add support for them if anybody really needs +// it, it seems relatively unlikely, so for now we don't bother to do it. + +class wxPersistentRadioButton : public wxPersistentWindow +{ +public: + explicit wxPersistentRadioButton(wxRadioButton* radiobutton) + : wxPersistentWindow(radiobutton) + { + wxASSERT_MSG( !radiobutton->HasFlag(wxRB_SINGLE), + "wxPersistentRadioButton doesn't support wxRB_SINGLE" ); + + wxASSERT_MSG( radiobutton->HasFlag(wxRB_GROUP), + "wxPersistentRadioButton should be used with the first " + "radio button in a group" ); + } + + virtual void Save() const override + { + const wxRadioButton* button = Get(); + for ( int n = 0;; ++n ) + { + if ( button->GetValue() ) + { + // We found the selected button, save its index. + SaveValue(wxPERSIST_RADIOBUTTON_VALUE, n); + break; + } + + button = button->GetNextInGroup(); + if ( !button ) + { + wxFAIL_MSG("Didn't find a selected radio button in the group?"); + break; + } + } + } + + virtual bool Restore() override + { + int value; + if ( !RestoreValue(wxPERSIST_RADIOBUTTON_VALUE, &value) ) + return false; + + wxRadioButton* button = Get(); + for ( int n = 0;; ++n ) + { + if ( n == value ) + { + // We found the button with the saved index, set its value. + button->SetValue(true); + break; + } + + button = button->GetNextInGroup(); + + if ( !button ) + { + // The saved value is invalid, silently ignore it because there + // doesn't seem to be much else that we can do in this case. + break; + } + } + + return true; + } + + virtual wxString GetKind() const override { return wxPERSIST_RADIOBUTTON_KIND; } +}; + +inline wxPersistentObject *wxCreatePersistentObject(wxRadioButton* radiobutton) +{ + return new wxPersistentRadioButton(radiobutton); +} + +#endif // wxUSE_RADIOBTN + +#endif // _WX_PERSIST_RADIOBUT_H_ diff --git a/interface/wx/persist/radiobut.h b/interface/wx/persist/radiobut.h new file mode 100644 index 0000000000..ca75f788c5 --- /dev/null +++ b/interface/wx/persist/radiobut.h @@ -0,0 +1,75 @@ +/////////////////////////////////////////////////////////////////////////////// +// Name: wx/persist/radiobutton.h +// Purpose: Interface of wxPersistentRadioButton +// Author: Vadim Zeitlin +// Created: 2025-06-15 +// Copyright: (c) 2025 Vadim Zeitlin +// Licence: wxWindows licence +/////////////////////////////////////////////////////////////////////////////// + +/** + Persistence adapter for wxRadioButton controls. + + This adapter saves and restores the index of the selected wxRadioButton in + a group of radio buttons, to allow to retain the selection across program + executions. + + Example of using it: + @code + // Assume that all these controls are added to some sizer elsewhere. + auto* label = new wxStaticText(this, wxID_ANY, "Play with:"); + + auto* black = new wxRadioButton(this, wxID_ANY, "&Black", + wxDefaultPosition, + wxDefaultSize, + wxRB_GROUP); + auto* white = new wxRadioButton(this, wxID_ANY, "&White"); + + // We register the first radio button here, but all radio buttons in the + // same group are potentially affected by this call. + wxPersistentRegisterAndRestore(black); + @endcode + + During the first program execution, black colour will be selected, but if + the user selects white pieces, this selection will be restored during the + subsequent run. + + @since 3.3.0 + */ +class wxPersistentRadioButton : public wxPersistentWindow +{ +public: + /** + Constructor. + + Please note that the radio button must be the first one in the group, + i.e. have ::wxRB_GROUP style set, otherwise an assertion will be + triggered. + + Also note that currently ::wxRB_SINGLE style is not supported. + + @param radiobutton + The associated radiobutton. + */ + explicit wxPersistentRadioButton(wxRadioButton *radiobutton); + + /** + Save the currently selected button index. + + The 0-based index of the selected radio button in the group is saved as + radio button value. + */ + virtual void Save() const; + + /** + Restore the previously saved selection. + + If the saved index is valid, i.e. is positive and less than the number + of radio buttons in the group, the radio button with the corresponding + index will be selected. + */ + virtual bool Restore(); +}; + +/// Overload allowing persistence adapter creation for wxRadioButton objects. +wxPersistentObject *wxCreatePersistentObject(wxRadioButton *radiobutton); diff --git a/tests/allheaders.h b/tests/allheaders.h index 02c41087ce..66a33a64c3 100644 --- a/tests/allheaders.h +++ b/tests/allheaders.h @@ -268,6 +268,7 @@ #include #include #include +#include #include #include #include