Implement wxRB_SINGLE support in wxGTK

Create hidden radio button in wxGTK when using wxRB_SINGLE, as
this lets us deactivate the shown button by activating the hidden one.
GTK does not allow deactivating radio buttons by calling them with
gtk_toggle_button_set_active( ..., FALSE), so we need to work around
it like this.

Also update the documentation to mention that this works in wxGTK now.

See #17022.

Closes #23652.

Closes #23677.
This commit is contained in:
Stefan Hansson 2023-07-02 18:50:16 +02:00 committed by Vadim Zeitlin
parent c3bc4c16c5
commit b84b45161a
3 changed files with 28 additions and 7 deletions

View file

@ -55,6 +55,8 @@ protected:
private: private:
typedef wxControl base_type; typedef wxControl base_type;
// Only used by wxRB_SINGLE
GtkWidget* m_hiddenButton = nullptr;
wxDECLARE_DYNAMIC_CLASS(wxRadioButton); wxDECLARE_DYNAMIC_CLASS(wxRadioButton);
}; };

View file

@ -33,9 +33,10 @@
When this style is used, no other radio buttons will be turned off When this style is used, no other radio buttons will be turned off
automatically when this button is turned on and such behaviour will automatically when this button is turned on and such behaviour will
need to be implemented manually, in the event handler for this need to be implemented manually, in the event handler for this
button. This style is currently only supported in wxMSW, in the button. This style is currently only supported in wxMSW and wxGTK
other ports it can be specified, but single radio buttons can't be (since version 3.3.0). In the other ports it can be specified, but
turned off, making them not very useful. single radio buttons can't be turned off, making them not very
useful.
@endStyleTable @endStyleTable
@beginEventEmissionTable{wxCommandEvent} @beginEventEmissionTable{wxCommandEvent}

View file

@ -92,7 +92,22 @@ bool wxRadioButton::Create( wxWindow *parent,
} }
} }
m_widget = gtk_radio_button_new_with_label( radioButtonGroup, label.utf8_str() ); // GTK does not allow a radio button to be inactive if it is the only radio
// button in its group, so we need to work around this by creating a second
// hidden radio button.
if (HasFlag(wxRB_SINGLE))
{
m_hiddenButton = gtk_radio_button_new( nullptr );
m_widget = gtk_radio_button_new_with_label_from_widget( GTK_RADIO_BUTTON(m_hiddenButton), label.utf8_str() );
// Since this is the second button in the group, we need to ensure it
// is active by default and not the first hidden one.
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_widget), TRUE );
}
else
{
m_widget = gtk_radio_button_new_with_label( radioButtonGroup, label.utf8_str() );
}
g_object_ref(m_widget); g_object_ref(m_widget);
SetLabel(label); SetLabel(label);
@ -133,9 +148,12 @@ void wxRadioButton::SetValue( bool val )
} }
else else
{ {
// should give an assert // Normal radio buttons can only be turned off by turning on another
// RL - No it shouldn't. A wxGenericValidator might try to set it // button in the same group, but the single ones can be turned off
// as FALSE. Failing silently is probably TRTTD here. // manually, which is implemented by turning a hidden button on, as
// it's the only way to do it with GTK.
if (HasFlag(wxRB_SINGLE))
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(m_hiddenButton), TRUE );
} }
g_signal_handlers_unblock_by_func( g_signal_handlers_unblock_by_func(