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
This commit is contained in:
Vadim Zeitlin 2003-01-26 00:04:24 +00:00
parent 2abb9d2f17
commit 5d76f46282
4 changed files with 231 additions and 72 deletions

View File

@ -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

View File

@ -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.

View File

@ -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);

View File

@ -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();
if ((num > 0) && (sz.y > minsz.y))
// what to do with the rows? by default, resize them proportionally
if ( (m_flexDirection & wxVERTICAL) ||
(m_growMode == wxFLEX_GROWMODE_SPECIFIED) )
{
delta = (sz.y - minsz.y) / num;
for (idx = 0; idx < num; idx++)
m_rowHeights[ temp[idx] ] += delta;
// 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))
{
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) )
{
// 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();
if ((num > 0) && (sz.x > minsz.x))
// the same logic as above but for the columns
if ( (m_flexDirection & wxHORIZONTAL) ||
(m_growMode == wxFLEX_GROWMODE_SPECIFIED) )
{
delta = (sz.x - minsz.x) / num;
for (idx = 0; idx < num; idx++)
m_colWidths[ temp[idx] ] += delta;
// 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))
{
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) )
{
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 ];