+ const size_t count = sizes.size();
+ for ( size_t n = 0; n < count; n++ )
+ {
+ if ( sizes[n] != -1 )
+ {
+ if ( total )
+ total += gap; // separate from the previous column
+
+ total += sizes[n];
+ }
+ }
+
+ return total;
+}
+
+wxSize wxFlexGridSizer::CalcMin()
+{
+ int nrows,
+ ncols;
+
+ // Number of rows/columns can change as items are added or removed.
+ if ( !CalcRowsCols(nrows, ncols) )
+ return wxSize();
+
+
+ // We have to recalculate the sizes in case the item minimum size has
+ // changed since the previous layout, or the item has been hidden using
+ // wxSizer::Show(). If all the items in a row/column are hidden, the final
+ // dimension of the row/column will be -1, indicating that the column
+ // itself is hidden.
+ m_rowHeights.assign(nrows, -1);
+ m_colWidths.assign(ncols, -1);
+
+ // n is the index of the item in left-to-right top-to-bottom order
+ size_t n = 0;
+ for ( wxSizerItemList::iterator i = m_children.begin();
+ i != m_children.end();
+ ++i, ++n )
+ {
+ wxSizerItem * const item = *i;
+ if ( item->IsShown() )
+ {
+ const wxSize sz(item->CalcMin());
+
+ const int row = n / ncols;
+ const int col = n % ncols;
+
+ if ( sz.y > m_rowHeights[row] )
+ m_rowHeights[row] = sz.y;
+ if ( sz.x > m_colWidths[col] )
+ m_colWidths[col] = sz.x;
+ }
+ }
+
+ AdjustForFlexDirection();
+
+ m_calculatedMinSize = wxSize(SumArraySizes(m_colWidths, m_hgap),
+ SumArraySizes(m_rowHeights, m_vgap));
+
+ return m_calculatedMinSize;
+}
+
+void wxFlexGridSizer::AdjustForFlexDirection()
+{
+ // the logic in CalcMin works when we resize flexibly in both directions
+ // but maybe this is not the case
+ if ( m_flexDirection != wxBOTH )
+ {
+ // select the array corresponding to the direction in which we do *not*
+ // resize flexibly
+ wxArrayInt& array = m_flexDirection == wxVERTICAL ? m_colWidths
+ : m_rowHeights;
+
+ const size_t count = array.GetCount();
+
+ // find the largest value in this array
+ size_t n;
+ int largest = 0;
+
+ for ( n = 0; n < count; ++n )
+ {
+ if ( array[n] > largest )
+ largest = array[n];
+ }
+
+ // and now fill it with the largest value
+ for ( n = 0; n < count; ++n )
+ {
+ // don't touch hidden rows
+ if ( array[n] != -1 )
+ array[n] = largest;
+ }
+ }
+}
+
+// helper of AdjustForGrowables() which is called for rows/columns separately
+//
+// parameters:
+// delta: the extra space, we do nothing unless it's positive
+// growable: indices or growable rows/cols in sizes array
+// sizes: the height/widths of rows/cols to adjust
+// proportions: proportions of the growable rows/cols or NULL if they all
+// should be assumed to have proportion of 1
+static void
+DoAdjustForGrowables(int delta,
+ const wxArrayInt& growable,
+ wxArrayInt& sizes,
+ const wxArrayInt *proportions)
+{
+ if ( delta <= 0 )
+ return;
+
+ // total sum of proportions of all non-hidden rows
+ int sum_proportions = 0;
+
+ // number of currently shown growable rows
+ int num = 0;
+
+ const int max_idx = sizes.size();
+
+ const size_t count = growable.size();
+ size_t idx;
+ for ( idx = 0; idx < count; idx++ )
+ {
+ // Since the number of rows/columns can change as items are
+ // inserted/deleted, we need to verify at runtime that the
+ // requested growable rows/columns are still valid.
+ if ( growable[idx] >= max_idx )
+ continue;
+
+ // If all items in a row/column are hidden, that row/column will
+ // have a dimension of -1. This causes the row/column to be
+ // hidden completely.
+ if ( sizes[growable[idx]] == -1 )
+ continue;
+
+ if ( proportions )
+ sum_proportions += (*proportions)[idx];
+
+ num++;
+ }
+
+ if ( !num )
+ return;
+
+ // the remaining extra free space, adjusted during each iteration
+ for ( idx = 0; idx < count; idx++ )
+ {
+ if ( growable[idx] >= max_idx )
+ continue;
+
+ if ( sizes[ growable[idx] ] == -1 )
+ continue;
+
+ int cur_delta;
+ if ( sum_proportions == 0 )
+ {
+ // no growable rows -- divide extra space evenly among all
+ cur_delta = delta/num;
+ num--;
+ }
+ else // allocate extra space proportionally
+ {
+ const int cur_prop = (*proportions)[idx];
+ cur_delta = (delta*cur_prop)/sum_proportions;
+ sum_proportions -= cur_prop;
+ }
+
+ sizes[growable[idx]] += cur_delta;
+ delta -= cur_delta;
+ }
+}
+
+void wxFlexGridSizer::AdjustForGrowables(const wxSize& sz)
+{
+ if ( (m_flexDirection & wxVERTICAL) || (m_growMode != wxFLEX_GROWMODE_NONE) )
+ {
+ // pass NULL instead of proportions if the grow mode is ALL as we
+ // should treat all rows as having proportion of 1 then
+ DoAdjustForGrowables
+ (
+ sz.y - m_calculatedMinSize.y,
+ m_growableRows,
+ m_rowHeights,
+ m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableRowsProportions
+ : NULL
+ );
+ }
+
+ if ( (m_flexDirection & wxHORIZONTAL) || (m_growMode != wxFLEX_GROWMODE_NONE) )
+ {
+ DoAdjustForGrowables
+ (
+ sz.x - m_calculatedMinSize.x,
+ m_growableCols,
+ m_colWidths,
+ m_growMode == wxFLEX_GROWMODE_SPECIFIED ? &m_growableColsProportions
+ : NULL
+ );
+ }
+}
+
+
+void wxFlexGridSizer::AddGrowableRow( size_t idx, int proportion )
+{
+ m_growableRows.Add( idx );
+ m_growableRowsProportions.Add( proportion );
+}
+
+void wxFlexGridSizer::AddGrowableCol( size_t idx, int proportion )
+{
+ m_growableCols.Add( idx );
+ m_growableColsProportions.Add( proportion );
+}
+
+// helper function for RemoveGrowableCol/Row()
+static void
+DoRemoveFromArrays(size_t idx, wxArrayInt& items, wxArrayInt& proportions)
+{
+ const size_t count = items.size();
+ for ( size_t n = 0; n < count; n++ )
+ {
+ if ( (size_t)items[n] == idx )
+ {
+ items.RemoveAt(n);
+ proportions.RemoveAt(n);
+ return;
+ }
+ }
+
+ wxFAIL_MSG( _T("column/row is already not growable") );
+}
+
+void wxFlexGridSizer::RemoveGrowableCol( size_t idx )
+{
+ DoRemoveFromArrays(idx, m_growableCols, m_growableColsProportions);
+}
+
+void wxFlexGridSizer::RemoveGrowableRow( size_t idx )
+{
+ DoRemoveFromArrays(idx, m_growableRows, m_growableRowsProportions);
+}
+
+//---------------------------------------------------------------------------
+// wxBoxSizer
+//---------------------------------------------------------------------------
+
+void wxBoxSizer::RecalcSizes()
+{
+ if ( m_children.empty() )
+ return;
+
+ // the amount of free space which we should redistribute among the
+ // stretchable items (i.e. those with non zero proportion)
+ int delta = SizeInMajorDir(m_size) - SizeInMajorDir(m_minSize);
+
+ // the position at which we put the next child
+ wxPoint pt(m_position);
+
+ const wxCoord totalMinorSize = SizeInMinorDir(m_size);
+
+ int totalProportion = m_totalProportion;
+ for ( wxSizerItemList::const_iterator i = m_children.begin();
+ i != m_children.end();
+ ++i )
+ {
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ const wxSize sizeThis(item->GetMinSizeWithBorder());
+
+
+ // adjust the size in the major direction using the proportion
+ wxCoord majorSize = SizeInMajorDir(sizeThis);
+ const int propItem = item->GetProportion();
+ if ( propItem )
+ {
+ const int deltaItem = (delta * propItem) / totalProportion;
+
+ majorSize += deltaItem;
+
+ delta -= deltaItem;
+ totalProportion -= propItem;
+ }
+
+
+ // apply the alignment in the minor direction
+ wxPoint posChild(pt);
+
+ wxCoord minorSize = SizeInMinorDir(sizeThis);
+ const int flag = item->GetFlag();
+ if ( flag & (wxEXPAND | wxSHAPED) )
+ {
+ minorSize = totalMinorSize;
+ }
+ else if ( flag & (IsVertical() ? wxALIGN_RIGHT : wxALIGN_BOTTOM) )
+ {
+ PosInMinorDir(posChild) += totalMinorSize - minorSize;
+ }
+ // NB: wxCENTRE is used here only for backwards compatibility,
+ // wxALIGN_CENTRE should be used in new code
+ else if ( flag & (wxCENTER | wxALIGN_CENTRE) )
+ {
+ PosInMinorDir(posChild) += (totalMinorSize - minorSize) / 2;
+ }
+
+
+ // apply RTL adjustment for horizontal sizers:
+ if ( !IsVertical() && m_containingWindow )
+ {
+ posChild.x = m_containingWindow->AdjustForLayoutDirection
+ (
+ posChild.x,
+ majorSize,
+ m_size.x
+ );
+ }
+
+ // finally set size of this child and advance to the next one
+ item->SetDimension(posChild, SizeFromMajorMinor(majorSize, minorSize));
+
+ PosInMajorDir(pt) += majorSize;
+ }
+}
+
+wxSize wxBoxSizer::CalcMin()
+{
+ m_totalProportion = 0;
+ m_minSize = wxSize(0, 0);
+
+ // calculate the minimal sizes for all items and count sum of proportions
+ for ( wxSizerItemList::const_iterator i = m_children.begin();
+ i != m_children.end();
+ ++i )
+ {
+ wxSizerItem * const item = *i;
+
+ if ( !item->IsShown() )
+ continue;
+
+ const wxSize sizeMinThis = item->CalcMin();
+
+ SizeInMajorDir(m_minSize) += SizeInMajorDir(sizeMinThis);
+ if ( SizeInMinorDir(sizeMinThis) > SizeInMinorDir(m_minSize) )
+ SizeInMinorDir(m_minSize) = SizeInMinorDir(sizeMinThis);
+
+ m_totalProportion += item->GetProportion();
+ }
+
+ return m_minSize;
+}
+
+//---------------------------------------------------------------------------
+// wxStaticBoxSizer
+//---------------------------------------------------------------------------
+
+#if wxUSE_STATBOX
+
+wxStaticBoxSizer::wxStaticBoxSizer( wxStaticBox *box, int orient )
+ : wxBoxSizer( orient ),
+ m_staticBox( box )
+{
+ wxASSERT_MSG( box, wxT("wxStaticBoxSizer needs a static box") );
+
+ // do this so that our Detach() is called if the static box is destroyed
+ // before we are
+ m_staticBox->SetContainingSizer(this);
+}
+
+wxStaticBoxSizer::wxStaticBoxSizer(int orient, wxWindow *win, const wxString& s)
+ : wxBoxSizer(orient),
+ m_staticBox(new wxStaticBox(win, wxID_ANY, s))
+{
+ // same as above
+ m_staticBox->SetContainingSizer(this);
+}
+
+wxStaticBoxSizer::~wxStaticBoxSizer()
+{
+ 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);