From: Vadim Zeitlin Date: Sun, 26 Jan 2003 00:04:24 +0000 (+0000) Subject: added support for non flexible (in one direction only) flexible sizers X-Git-Url: https://git.saurik.com/wxWidgets.git/commitdiff_plain/5d76f4628261a5d80ca18e45b311efa2e79f3d57 added support for non flexible (in one direction only) flexible sizers git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@18931 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- diff --git a/docs/changes.txt b/docs/changes.txt index fa5ab9811c..ddc9309b7a 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -17,6 +17,7 @@ All: - use true/false throughout the library instead of TRUE/FALSE - wxStopWatch::Start() resumes the stop watch if paused, as per the docs - added wxDirTraverser::OnOpenError() to customize the error handling +- added wxArray::SetCount() wxBase: @@ -24,6 +25,7 @@ wxBase: All GUI ports: +- added wxFlexGridSizer::SetFlexibleDirection() (Szczepan Holyszewski) - implemented GetEditControl for wxGenericTreeCtrl (Peter Stieber) - improved contrib/utils/convertrc parsing (David J. Cooke) - fixed handling of URLs and filenames in wxFileSystem diff --git a/docs/latex/wx/flexsizr.tex b/docs/latex/wx/flexsizr.tex index d7456bbc21..0ce1e99fe4 100644 --- a/docs/latex/wx/flexsizr.tex +++ b/docs/latex/wx/flexsizr.tex @@ -6,6 +6,15 @@ height and all fields in one column having the same width, but all rows or all columns are not necessarily the same height or width as in the \helpref{wxGridSizer}{wxgridsizer}. +Since wxWindows 2.5.0, wxFlexGridSizer can also size items equally in one +direction but unequally ("flexibly") in the other. If the sizer is only +flexible in one direction (this can be changed using +\helpref{SetFlexibleDrection}{wxflexgridsizersetflexibledrection}), +it needs to be decided how the sizer should grow in the other ("non flexible") +direction in order to fill the available space. The +\helpref{SetNonFlexibleGrowMode}{wxflexgridsizersetnonflexiblegrowmode} method +serves this purpose. + \wxheading{Derived from} \helpref{wxGridSizer}{wxgridsizer}\\ @@ -16,6 +25,7 @@ the \helpref{wxGridSizer}{wxgridsizer}. \helpref{wxSizer}{wxsizer}, \helpref{Sizer overview}{sizeroverview} + \membersection{wxFlexGridSizer::wxFlexGridSizer}\label{wxflexgridsizerwxflexgridsizer} \func{}{wxFlexGridSizer}{\param{int }{rows}, \param{int }{cols}, \param{int }{vgap}, \param{int }{hgap}} @@ -43,15 +53,94 @@ there is extra space available to the sizer. Specifies that row idx (starting from zero) should be grown if there is extra space available to the sizer. +\membersection{wxFlexGridSizer::GetFlexibleDirection}\label{wxflexgridsizergetflexibledrection} + +\constfunc{int}{GetFlexibleDirections}{\void} + +Returns a wxOrientation value that specifies whether the sizer flexibly +resizes its columns, rows, or both (default). + +\wxheading{Return value} + +One of the following values: + +\begin{twocollist} +\twocolitem{wxVERTICAL}{Rows are flexibly sized.} +\twocolitem{wxHORIZONTAL}{Columns are flexibly sized.} +\twocolitem{wxBOTH}{Both rows and columns are flexibly sized (this is the default value).} +\end{twocollist} + +\wxheading{See also} + +\helpref{SetFlexibleDrection}{wxflexgridsizersetflexibledrection} + + +\membersection{wxFlexGridSizer::GetNonFlexibleGrowMode}\label{wxflexgridsizergetnonflexiblegrowmode} + +\constfunc{int}{GetNonFlexibleGrowMode}{\void} + +Returns the value that specifies how the sizer grows in the "non flexible" +direction if there is one. + +\wxheading{Return value} + +One of the following values: + +\begin{twocollist} +\twocolitem{wxFLEX\_GROWMODE\_NONE}{Sizer doesn't grow in the non flexible direction.} +\twocolitem{wxFLEX\_GROWMODE\_SPECIFIED}{Sizer honors growable columns/rows set with +\helpref{AddGrowableCol}{wxflexgridsizeraddgrowablecol} and +\helpref{AddGrowableRow}{wxflexgridsizeraddgrowablerow}. +In this case equal sizing applies to minimum sizes of columns or +rows (this is the default value).} +\twocolitem{wxFLEX\_GROWMODE\_ALL}{Sizer equally stretches all columns or rows +in the non flexible direction, whether they are growable or not in the flexbile +direction.} +\end{twocollist} + +\wxheading{See also} + +\helpref{SetFlexibleDrection}{wxflexgridsizersetflexibledrection}, +\helpref{SetNonFlexibleGrowMode}{wxflexgridsizersetnonflexiblegrowmode} + + \membersection{wxFlexGridSizer::RemoveGrowableCol}\label{wxflexgridsizerremovegrowablecol} \func{void}{RemoveGrowableCol}{\param{size\_t }{idx}} Specifies that column idx is no longer growable. + \membersection{wxFlexGridSizer::RemoveGrowableRow}\label{wxflexgridsizerremovegrowablerow} \func{void}{RemoveGrowableRow}{\param{size\_t }{idx}} Specifies that row idx is no longer growable. + +\membersection{wxFlexGridSizer::SetFlexibleDirection}{wxflexgridsizersetflexibledrection} + +\func{void}{SetFlexibleDirections}{\param{int }{direction}} + +Specifies whether the sizer should flexibly resize its columns, rows, or +both. Argument {\t direction} can be {\tt wxVERTICAL}, {\tt wxHORIZONTAL} +or {\tt wxBOTH} (which is the default value). Any other value is ignored. See +\helpref{GetFlexibleDirection()}{wxflexgridsizergetflexibledrection} for the +explanation of these values. + +Note that this method does not trigger relayout. + + +\membersection{wxFlexGridSizer::SetNonFlexibleGrowMode}{wxflexgridsizersetnonflexiblegrowmode} + +\func{void}{SetNonFlexibleGrowMode}{\param{int }{mode}} + +Specifies how the sizer should grow in the non flexible direction if +there is one (so +\helpref{SetFlexibleDirections()}{wxflexgridsizersetflexibledrection} must have +been called previously). Argument {\it mode} can be one of those documented in +\helpref{GetNonFlexibleGrowMode}{wxflexgridsizergetnonflexiblegrowmode}, please +see there for their explanation. + +Note that this method does not trigger relayout. + diff --git a/include/wx/sizer.h b/include/wx/sizer.h index 913d9131a2..b5f0665955 100644 --- a/include/wx/sizer.h +++ b/include/wx/sizer.h @@ -339,8 +339,8 @@ public: wxGridSizer( int rows, int cols, int vgap, int hgap ); wxGridSizer( int cols, int vgap = 0, int hgap = 0 ); - void RecalcSizes(); - wxSize CalcMin(); + virtual void RecalcSizes(); + virtual wxSize CalcMin(); void SetCols( int cols ) { m_cols = cols; } void SetRows( int rows ) { m_rows = rows; } @@ -370,28 +370,67 @@ private: // wxFlexGridSizer //--------------------------------------------------------------------------- +// the bevaiour for resizing wxFlexGridSizer cells in the "non-flexible" +// direction +enum wxFlexSizerGrowMode +{ + // don't resize the cells in non-flexible direction at all + wxFLEX_GROWMODE_NONE, + + // uniformly resize only the specified ones (default) + wxFLEX_GROWMODE_SPECIFIED, + + // uniformly resize all cells + wxFLEX_GROWMODE_ALL +}; + class WXDLLEXPORT wxFlexGridSizer: public wxGridSizer { public: + // ctors/dtor wxFlexGridSizer( int rows, int cols, int vgap, int hgap ); wxFlexGridSizer( int cols, int vgap = 0, int hgap = 0 ); - ~wxFlexGridSizer(); + virtual ~wxFlexGridSizer(); - void RecalcSizes(); - wxSize CalcMin(); + // set the rows/columns which will grow (the others will remain of the + // constant initial size) void AddGrowableRow( size_t idx ); void RemoveGrowableRow( size_t idx ); void AddGrowableCol( size_t idx ); void RemoveGrowableCol( size_t idx ); -protected: - int *m_rowHeights; - int *m_colWidths; - wxArrayInt m_growableRows; - wxArrayInt m_growableCols; - void CreateArrays(); + // the sizer cells may grow in both directions, not grow at all or only + // grow in one direction but not the other + + // the direction may be wxVERTICAL, wxHORIZONTAL or wxBOTH (default) + void SetFlexibleDirection(int direction) { m_flexDirection = direction; } + int GetFlexibleDirection() const { return m_flexDirection; } + + // note that the grow mode only applies to the direction which is not + // flexible + void SetNonFlexibleGrowMode(wxFlexSizerGrowMode mode) { m_growMode = mode; } + wxFlexSizerGrowMode GetNonFlexibleGrowMode() const { return m_growMode; } + + + // implementation + virtual void RecalcSizes(); + virtual wxSize CalcMin(); + +protected: + // the heights/widths of all rows/columns + wxArrayInt m_rowHeights, + m_colWidths; + + // indices of the growable columns and rows + wxArrayInt m_growableRows, + m_growableCols; + + // parameters describing whether the growable cells should be resized in + // both directions or only one + int m_flexDirection; + wxFlexSizerGrowMode m_growMode; private: DECLARE_CLASS(wxFlexGridSizer); diff --git a/src/common/sizer.cpp b/src/common/sizer.cpp index 1d7ed91c2c..a0ee65773c 100644 --- a/src/common/sizer.cpp +++ b/src/common/sizer.cpp @@ -1000,48 +1000,21 @@ void wxGridSizer::SetItemBounds( wxSizerItem *item, int x, int y, int w, int h ) //--------------------------------------------------------------------------- wxFlexGridSizer::wxFlexGridSizer( int rows, int cols, int vgap, int hgap ) - : wxGridSizer( rows, cols, vgap, hgap ) - , m_rowHeights( NULL ) - , m_colWidths( NULL ) + : wxGridSizer( rows, cols, vgap, hgap ), + m_flexDirection(wxBOTH), + m_growMode(wxFLEX_GROWMODE_SPECIFIED) { } wxFlexGridSizer::wxFlexGridSizer( int cols, int vgap, int hgap ) - : wxGridSizer( cols, vgap, hgap ) - , m_rowHeights( NULL ) - , m_colWidths( NULL ) + : wxGridSizer( cols, vgap, hgap ), + m_flexDirection(wxBOTH), + m_growMode(wxFLEX_GROWMODE_SPECIFIED) { } wxFlexGridSizer::~wxFlexGridSizer() { - if (m_rowHeights) - delete[] m_rowHeights; - if (m_colWidths) - delete[] m_colWidths; -} - -void wxFlexGridSizer::CreateArrays() -{ - if (m_rowHeights) - delete[] m_rowHeights; - if (m_colWidths) - delete[] m_colWidths; - - int nitems, nrows, ncols; - if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 ) - { - m_rowHeights = - m_colWidths = NULL; - } - - m_rowHeights = new int[nrows]; - m_colWidths = new int[ncols]; - - for (int col = 0; col < ncols; col++) - m_colWidths[ col ] = 0; - for (int row = 0; row < nrows; row++) - m_rowHeights[ row ] = 0; } void wxFlexGridSizer::RecalcSizes() @@ -1054,36 +1027,63 @@ void wxFlexGridSizer::RecalcSizes() wxSize minsz( CalcMin() ); wxPoint pt( GetPosition() ); int delta; - size_t idx,num; + size_t idx, num; wxArrayInt temp; - // Transfer only those rows into temp which exist in the sizer - // ignoring the superflouus ones. This prevents a segfault when - // calling AddGrowableRow( 3 ) if the sizer only has 2 rows. - for (idx = 0; idx < m_growableRows.GetCount(); idx++) - if (m_growableRows[idx] < nrows) - temp.Add( m_growableRows[idx] ); - num = temp.GetCount(); + // what to do with the rows? by default, resize them proportionally + if ( (m_flexDirection & wxVERTICAL) || + (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) + { + // Transfer only those rows into temp which exist in the sizer + // ignoring the superfluous ones. This prevents a segfault when + // calling AddGrowableRow( 3 ) if the sizer only has 2 rows. + for (idx = 0; idx < m_growableRows.GetCount(); idx++) + { + if (m_growableRows[idx] < nrows) + temp.Add( m_growableRows[idx] ); + } + + num = temp.GetCount(); - if ((num > 0) && (sz.y > minsz.y)) + if ((num > 0) && (sz.y > minsz.y)) + { + delta = (sz.y - minsz.y) / num; + for (idx = 0; idx < num; idx++) + m_rowHeights[ temp[idx] ] += delta; + } + temp.Empty(); + } + else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.y > minsz.y) ) { - delta = (sz.y - minsz.y) / num; - for (idx = 0; idx < num; idx++) - m_rowHeights[ temp[idx] ] += delta; + // rounding problem? + for ( int row = 0; row < nrows; ++row ) + m_rowHeights[ row ] = sz.y / nrows; } - temp.Empty(); - // See above - for (idx = 0; idx < m_growableCols.GetCount(); idx++) - if (m_growableCols[idx] < ncols) - temp.Add( m_growableCols[idx] ); - num = temp.GetCount(); + // the same logic as above but for the columns + if ( (m_flexDirection & wxHORIZONTAL) || + (m_growMode == wxFLEX_GROWMODE_SPECIFIED) ) + { + // See above + for (idx = 0; idx < m_growableCols.GetCount(); idx++) + { + if (m_growableCols[idx] < ncols) + temp.Add( m_growableCols[idx] ); + } + + num = temp.GetCount(); - if ((num > 0) && (sz.x > minsz.x)) + if ((num > 0) && (sz.x > minsz.x)) + { + delta = (sz.x - minsz.x) / num; + for (idx = 0; idx < num; idx++) + m_colWidths[ temp[idx] ] += delta; + } + } + else if ( (m_growMode == wxFLEX_GROWMODE_ALL) && (sz.x > minsz.x) ) { - delta = (sz.x - minsz.x) / num; - for (idx = 0; idx < num; idx++) - m_colWidths[ temp[idx] ] += delta; + for ( int col=0; col < ncols; ++col ) + m_colWidths[ col ] = sz.x / ncols; } sz = wxSize( pt.x + sz.x, pt.y + sz.y ); @@ -1114,11 +1114,12 @@ void wxFlexGridSizer::RecalcSizes() wxSize wxFlexGridSizer::CalcMin() { - int nitems, nrows, ncols; - if ( (nitems = CalcRowsCols(nrows, ncols)) == 0 ) - return wxSize(10,10); + int nrows, ncols; + if ( !CalcRowsCols(nrows, ncols) ) + return wxSize(10, 10); - CreateArrays(); + m_rowHeights.SetCount(nrows); + m_colWidths.SetCount(ncols); int i = 0; wxSizerItemList::Node *node = m_children.GetFirst(); @@ -1137,6 +1138,34 @@ wxSize wxFlexGridSizer::CalcMin() i++; } + // the logic above 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 int count = array.GetCount(); + + // find the largest value in this array + int n, + 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 ) + { + array[n] = largest; + } + } + + int width = 0; for (int col = 0; col < ncols; col++) width += m_colWidths[ col ];