Check that all wxStaticBoxSizer items use the same parent

Using the box itself as the parent for some items and its parent window
as the parent for the other ones results in layout problems because the
correct offset is not used when positioning the items not using the box
as parent.

This has always been the case and it doesn't seem to be worth fixing, as
the scenario with the items not using the box as the parent is only
still supported for backwards compatibility anyhow, so just add an
assert checking for this and document this limitation.

Closes #23239.
This commit is contained in:
Vadim Zeitlin 2023-02-15 14:45:16 +00:00
parent e1d18b3b6c
commit d4cf530359
3 changed files with 37 additions and 2 deletions

View file

@ -1077,6 +1077,11 @@ protected:
virtual wxSizerItem* DoInsert(size_t index, wxSizerItem *item) override;
private:
// Set to true if any items _not_ using the associated static box as parent
// are added to this sizer: this is still supported for backwards
// compatibility but is not recommended.
bool m_hasNonBoxChildren = false;
wxDECLARE_CLASS(wxStaticBoxSizer);
wxDECLARE_NO_COPY_CLASS(wxStaticBoxSizer);
};

View file

@ -1944,8 +1944,12 @@ public:
Note that since wxWidgets 2.9.1 you are strongly encouraged to create the windows
which are added to wxStaticBoxSizer as children of wxStaticBox itself and
failure to do so will result in warning messages in debug builds. Please see
wxStaticBox documentation for more details.
failure to do so will result in warning messages in debug builds, even if
creating them using the static box parent as parent still works too (but
note that items using different parents can't be used inside the same
sizer, i.e. all of them should be children either of the box itself or of
its parent and an assert will be triggered if this is not the case).
Please see wxStaticBox documentation for more details.
Example of use of this class:
@code

View file

@ -2789,6 +2789,8 @@ wxSizerItem* wxStaticBoxSizer::DoInsert(size_t index, wxSizerItem* item)
// too for compatibility.
if ( !m_staticBox->IsDescendant(win) )
{
m_hasNonBoxChildren = true;
wxLogDebug("Element %s of wxStaticBoxSizer should be created "
"as child of its wxStaticBox and not of %s.",
wxDumpWindow(win),
@ -2805,6 +2807,30 @@ wxSizerItem* wxStaticBoxSizer::DoInsert(size_t index, wxSizerItem* item)
m_staticBox->MSWDisableComposited();
#endif // __WXMSW__
}
// Also check for the non-supported scenario in which both windows
// using box as their parent and the ones using its parent are used:
// this won't work correctly because the latter ones won't use the
// required offset and so won't be laid out correctly, see the code
// dealing with m_position in RepositionChildren() below.
if ( m_hasNonBoxChildren && !m_staticBox->GetChildren().empty() )
{
wxASSERT_MSG
(
!m_hasNonBoxChildren,
"All items of wxStaticBoxSizer must use the same parent.\n"
"\n"
"It is strongly recommended to use the associated static box "
"as the parent for all of them, but if not, all items must "
"use the containing window as parent.\n"
"\n"
"Mixing items using different parents inside the same sizer "
"is NOT supported."
);
// One assert is enough, so reset it to avoid giving it again.
m_hasNonBoxChildren = false;
}
}
return wxBoxSizer::DoInsert(index, item);