Check that all windows in a sizer use associated window as parent
Using a wrong parent for the window managed by the sizer of the given window or, alternatively, inserting a window into a wrong sizer, seems to be a common mistake when creating sizer-based layouts and results in hard to understand visual problems (as typically the window with the mismatched parent/sizer just remains stuck at some wrong location). So try to help detect it sooner and provide more information about the problem by checking the parent of the window either when it is added to the sizer -- if we already know which sizer the window is associated with at that moment -- or when associating the sizer with the window later.
This commit is contained in:
parent
a809b6f058
commit
62c3d921b2
@ -187,6 +187,21 @@ wxString MakeFlagsCheckMessage(const char* start, const char* whatToRemove)
|
||||
);
|
||||
}
|
||||
|
||||
wxString MakeExpectedParentMessage(wxWindow* w, wxWindow* expectedParent)
|
||||
{
|
||||
return wxString::Format
|
||||
(
|
||||
"Windows managed by the sizer associated with the given "
|
||||
"window must have this window as parent, otherwise they "
|
||||
"will not be repositioned correctly.\n"
|
||||
"\n"
|
||||
"Please use the window %s with which this sizer is associated, "
|
||||
"as the parent when creating the window %s managed by it.",
|
||||
wxDumpWindow(expectedParent),
|
||||
wxDumpWindow(w)
|
||||
);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
#endif // wxDEBUG_LEVEL
|
||||
@ -225,6 +240,18 @@ wxString MakeFlagsCheckMessage(const char* start, const char* whatToRemove)
|
||||
ASSERT_INCOMPATIBLE_NOT_USED(f, wxALIGN_CENTRE_HORIZONTAL, wxALIGN_RIGHT); \
|
||||
ASSERT_INCOMPATIBLE_NOT_USED(f, wxALIGN_CENTRE_VERTICAL, wxALIGN_BOTTOM)
|
||||
|
||||
// Verify that the given window has the expected parent.
|
||||
//
|
||||
// Both pointers must be non-null.
|
||||
//
|
||||
// Note that this is a serious error and that, unlike for benign sizer flag
|
||||
// checks, it can't be disabled by setting some environment variable.
|
||||
#define ASSERT_WINDOW_PARENT_IS(w, expectedParent) \
|
||||
wxASSERT_MSG \
|
||||
( \
|
||||
w->GetParent() == expectedParent, \
|
||||
MakeExpectedParentMessage(w, expectedParent) \
|
||||
)
|
||||
|
||||
/* static */
|
||||
void wxSizerFlags::DisableConsistencyChecks()
|
||||
@ -779,8 +806,18 @@ wxSizerItem* wxSizer::DoInsert( size_t index, wxSizerItem *item )
|
||||
|
||||
ContainingSizerGuard guard( item );
|
||||
|
||||
if ( item->GetWindow() )
|
||||
item->GetWindow()->SetContainingSizer( this );
|
||||
if ( wxWindow* const w = item->GetWindow() )
|
||||
{
|
||||
w->SetContainingSizer( this );
|
||||
|
||||
// If possible, detect adding windows with a wrong parent to the sizer
|
||||
// as early as possible, as this allows to see where exactly it happens
|
||||
// (otherwise this will be checked when the containing window is set
|
||||
// later, but by this time the stack trace at the moment of assertion
|
||||
// won't point out the culprit any longer).
|
||||
if ( m_containingWindow )
|
||||
ASSERT_WINDOW_PARENT_IS(w, m_containingWindow);
|
||||
}
|
||||
|
||||
if ( item->GetSizer() )
|
||||
item->GetSizer()->SetContainingWindow( m_containingWindow );
|
||||
@ -810,6 +847,9 @@ void wxSizer::SetContainingWindow(wxWindow *win)
|
||||
{
|
||||
sizer->SetContainingWindow(win);
|
||||
}
|
||||
|
||||
if ( wxWindow* const w = item->GetWindow() )
|
||||
ASSERT_WINDOW_PARENT_IS(w, m_containingWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user