break;
case Item_Window:
+ {
+ // Use wxSIZE_FORCE_EVENT here since a sizer item might
+ // have changed alignment or some other property which would
+ // not change the size of the window. In such a case, no
+ // wxSizeEvent would normally be generated and thus the
+ // control wouldn't get layed out correctly here.
+#if 1
+ m_window->SetSize(pos.x, pos.y, size.x, size.y,
+ wxSIZE_ALLOW_MINUS_ONE|wxSIZE_FORCE_EVENT );
+#else
m_window->SetSize(pos.x, pos.y, size.x, size.y,
- wxSIZE_ALLOW_MINUS_ONE);
+ wxSIZE_ALLOW_MINUS_ONE );
+#endif
break;
-
+ }
case Item_Sizer:
m_sizer->SetDimension(pos, size);
break;
{
}
+wxSizerItem *wxGridSizer::Insert(size_t index, wxSizerItem *item)
+{
+ // if only the number of columns or the number of rows is specified for a
+ // sizer, arbitrarily many items can be added to it but if both of them are
+ // fixed, then the sizer can't have more than that many items -- check for
+ // this here to ensure that we detect errors as soon as possible
+ if ( m_cols && m_rows )
+ {
+ const int nitems = m_children.GetCount();
+ if ( nitems == m_cols*m_rows )
+ {
+ wxFAIL_MSG(
+ wxString::Format(
+ "too many items (%d > %d*%d) in grid sizer (maybe you "
+ "should omit the number of either rows or columns?)",
+ nitems + 1, m_cols, m_rows)
+ );
+
+ // additionally, continuing to use the specified number of columns
+ // and rows is not a good idea as callers of CalcRowsCols() expect
+ // that all sizer items can fit into m_cols/m_rows-sized arrays
+ // which is not the case if there are too many items and results in
+ // crashes, so let it compute the number of rows automatically by
+ // forgetting the (wrong) number of rows specified (this also has a
+ // nice side effect of giving only one assert even if there are
+ // many more items than allowed in this sizer)
+ m_rows = 0;
+ }
+ }
+
+ return wxSizer::Insert(index, item);
+}
+
int wxGridSizer::CalcRowsCols(int& nrows, int& ncols) const
{
const int nitems = m_children.GetCount();
if ( m_cols && m_rows )
{
- // if both rows and columns are specified by user, use the provided
- // values even if we don't have enough items but check that we don't
- // have too many of them as this is going to result in problems later
ncols = m_cols;
nrows = m_rows;
- wxASSERT_MSG( ncols*nrows >= nitems, "too many items in grid sizer" );
+ // this should be impossible because the too high number of items
+ // should have been detected by Insert() above
+ wxASSERT_MSG( nitems <= ncols*nrows, "logic error in wxGridSizer" );
}
else if ( m_cols )
{
void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz)
{
+#if wxDEBUG_LEVEL
+ // by the time this function is called, the sizer should be already fully
+ // initialized and hence the number of its columns and rows is known and we
+ // can check that all indices in m_growableCols/Rows are valid (see also
+ // comments in AddGrowableCol/Row())
+ if ( !m_rows || !m_cols )
+ {
+ int nrows, ncols;
+ CalcRowsCols(nrows, ncols);
+
+ if ( !m_rows )
+ {
+ for ( size_t n = 0; n < m_growableRows.size(); n++ )
+ {
+ wxASSERT_MSG( m_growableRows[n] < nrows,
+ "invalid growable row index" );
+ }
+ }
+
+ if ( !m_cols )
+ {
+ for ( size_t n = 0; n < m_growableCols.size(); n++ )
+ {
+ wxASSERT_MSG( m_growableCols[n] < ncols,
+ "invalid growable column index" );
+ }
+ }
+ }
+#endif // wxDEBUG_LEVEL
+
+
if ( (m_flexDirection & wxHORIZONTAL) || (m_growMode != wxFLEX_GROWMODE_NONE) )
{
DoAdjustForGrowables
{
int nrows, ncols;
CalcRowsCols(nrows, ncols);
- wxCHECK_RET( idx < (size_t)nrows, "invalid row index" );
wxASSERT_MSG( !IsRowGrowable( idx ),
"AddGrowableRow() called for growable row" );
+
+ // notice that we intentionally don't check the index validity here in (the
+ // common) case when the number of rows was not specified in the ctor -- in
+ // this case it will be computed only later, when all items are added to
+ // the sizer, and the check will be done in AdjustForGrowables()
+ wxCHECK_RET( !m_rows || idx < (size_t)m_rows, "invalid row index" );
+
m_growableRows.Add( idx );
m_growableRowsProportions.Add( proportion );
}
{
int nrows, ncols;
CalcRowsCols(nrows, ncols);
- wxCHECK_RET( idx < (size_t)ncols, "invalid column index" );
wxASSERT_MSG( !IsColGrowable( idx ),
"AddGrowableCol() called for growable column" );
+
+ // see comment in AddGrowableRow(): although it's less common to omit the
+ // specification of the number of columns, it still can also happen
+ wxCHECK_RET( !m_cols || idx < (size_t)ncols, "invalid column index" );
+
m_growableCols.Add( idx );
m_growableColsProportions.Add( proportion );
}
}
// NB: wxCENTRE is used here only for backwards compatibility,
// wxALIGN_CENTRE should be used in new code
- else if ( flag & (wxCENTER | wxALIGN_CENTRE) )
+ else if ( flag & (wxCENTER | (IsVertical() ? wxALIGN_CENTRE_HORIZONTAL : wxALIGN_CENTRE_VERTICAL)))
{
PosInMinorDir(posChild) += (totalMinorSize - minorSize) / 2;
}
delete m_staticBox;
}
-static void GetStaticBoxBorders( wxStaticBox *box,
- int *borderTop,
- int *borderOther)
-{
- // this has to be done platform by platform as there is no way to
- // guess the thickness of a wxStaticBox border
- box->GetBordersForSizer(borderTop, borderOther);
-}
-
void wxStaticBoxSizer::RecalcSizes()
{
int top_border, other_border;
- GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
+ m_staticBox->GetBordersForSizer(&top_border, &other_border);
m_staticBox->SetSize( m_position.x, m_position.y, m_size.x, m_size.y );
- wxPoint old_pos( m_position );
- m_position.x += other_border;
- m_position.y += top_border;
wxSize old_size( m_size );
m_size.x -= 2*other_border;
m_size.y -= top_border + other_border;
+ wxPoint old_pos( m_position );
+ if (m_staticBox->GetChildren().GetCount() > 0)
+ {
+#if defined( __WXGTK20__ )
+ // if the wxStaticBox has created a wxPizza to contain its children
+ // (see wxStaticBox::AddChild) then we need to place the items it contains
+ // in the wxBoxSizer::RecalcSizes() call below using coordinates relative
+ // to the top-left corner of the staticbox:
+ m_position.x = m_position.y = 0;
+#else
+ // if the wxStaticBox has childrens, then these windows must be placed
+ // by the wxBoxSizer::RecalcSizes() call below using coordinates relative
+ // to the top-left corner of the staticbox (but unlike wxGTK, we need
+ // to keep in count the static borders here!):
+ m_position.x = other_border;
+ m_position.y = top_border;
+#endif
+ }
+ else
+ {
+ // the windows contained in the staticbox have been created as siblings of the
+ // staticbox (this is the "old" way of staticbox contents creation); in this
+ // case we need to position them with coordinates relative to our common parent
+ m_position.x += other_border;
+ m_position.y += top_border;
+ }
+
wxBoxSizer::RecalcSizes();
m_position = old_pos;
wxSize wxStaticBoxSizer::CalcMin()
{
int top_border, other_border;
- GetStaticBoxBorders(m_staticBox, &top_border, &other_border);
+ m_staticBox->GetBordersForSizer(&top_border, &other_border);
wxSize ret( wxBoxSizer::CalcMin() );
ret.x += 2*other_border;
+
+ // ensure that we're wide enough to show the static box label (there is no
+ // need to check for the static box best size in vertical direction though)
+ const int boxWidth = m_staticBox->GetBestSize().x;
+ if ( ret.x < boxWidth )
+ ret.x = boxWidth;
+
ret.y += other_border + top_border;
return ret;
#endif // wxUSE_STATBOX
+//---------------------------------------------------------------------------
+// wxStdDialogButtonSizer
+//---------------------------------------------------------------------------
+
#if wxUSE_BUTTON
wxStdDialogButtonSizer::wxStdDialogButtonSizer()
}
// Extra space around and at the right
- Add(12, 24);
+ Add(12, 40);
#elif defined(__WXGTK20__)
Add(0, 0, 0, wxLEFT, 9);
if (m_buttonHelp)