diff --git a/include/wx/statbox.h b/include/wx/statbox.h index 0e6e4f3ac3..ecb07ed92f 100644 --- a/include/wx/statbox.h +++ b/include/wx/statbox.h @@ -31,6 +31,7 @@ public: // overridden base class virtuals virtual bool HasTransparentBackground() wxOVERRIDE { return true; } + virtual bool Enable(bool enable = true) wxOVERRIDE; // implementation only: this is used by wxStaticBoxSizer to account for the // need for extra space taken by the static box diff --git a/interface/wx/statbox.h b/interface/wx/statbox.h index d7aae13cc0..c0fcac378e 100644 --- a/interface/wx/statbox.h +++ b/interface/wx/statbox.h @@ -158,4 +158,30 @@ public: const wxSize& size = wxDefaultSize, long style = 0, const wxString& name = wxStaticBoxNameStr); + + /** + Enables or disables the box without affecting its label window, if any. + + wxStaticBox overrides wxWindow::Enable() in order to avoid disabling + the control used as a label, if this box is using one. This is done in + order to allow using a wxCheckBox, for example, label and enable or + disable the box according to the state of the checkbox: if disabling + the box also disabled the checkbox in this situation, it would make it + impossible for the user to re-enable the box after disabling it, so the + checkbox stays enabled even if @c box->Enable(false) is called. + + However with the actual behaviour, implemented in this overridden + method, the following code (shown using C++11 only for convenience, + this behaviour is not C++11-specific): + @code + auto check = new wxCheckBox(parent, wxID_ANY, "Use the box"); + auto box = new wxStaticBox(parent, wxID_ANY, check); + check->Bind(wxEVT_CHECKBOX, + [box](wxCommandEvent& event) { + box->Enable(event.IsChecked()); + }); + @endcode + does work as expected. + */ + virtual bool Enable(bool enable = true); }; diff --git a/src/common/statboxcmn.cpp b/src/common/statboxcmn.cpp index 4db934146a..0e77dfe74f 100644 --- a/src/common/statboxcmn.cpp +++ b/src/common/statboxcmn.cpp @@ -78,6 +78,45 @@ void wxStaticBoxBase::WXDestroyWithoutChildren() delete this; } +bool wxStaticBoxBase::Enable(bool enable) +{ +#ifdef wxHAS_WINDOW_LABEL_IN_STATIC_BOX + // We want to keep the window label enabled even if the static box is + // disabled because this label is often used to enable/disable the box + // (e.g. a checkbox or a radio button is commonly used for this purpose) + // and it would be impossible to re-enable the box back if disabling it + // also disabled the label control. + // + // Unfortunately it is _not_ enough to just disable the box and then enable + // the label window as it would still remain disabled under some platforms + // (those where wxHAS_NATIVE_ENABLED_MANAGEMENT is defined, e.g. wxGTK) for + // as long as its parent is disabled. So we avoid disabling the box at all + // in this case and only disable its children, but still pretend that the + // box is disabled by updating its m_isEnabled, as it would be surprising + // if IsEnabled() didn't return false after disabling the box, for example. + if ( m_labelWin ) + { + if ( enable == IsThisEnabled() ) + return false; + + const wxWindowList& children = GetChildren(); + for ( wxWindowList::const_iterator i = children.begin(); + i != children.end(); + ++i ) + { + if ( *i != m_labelWin ) + (*i)->Enable(enable); + } + + m_isEnabled = enable; + + return true; + } +#endif // wxHAS_WINDOW_LABEL_IN_STATIC_BOX + + return wxNavigationEnabled::Enable(enable); +} + // ---------------------------------------------------------------------------- // XTI // ----------------------------------------------------------------------------