+void wxGrid::SetRowMinimalHeight( int row, int width )
+{
+ if (width > GetRowMinimalAcceptableHeight())
+ {
+ wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)row;
+ m_rowMinHeights[key] = width;
+ }
+}
+
+int wxGrid::GetColMinimalWidth(int col) const
+{
+ wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)col;
+ wxLongToLongHashMap::const_iterator it = m_colMinWidths.find(key);
+
+ return it != m_colMinWidths.end() ? (int)it->second : m_minAcceptableColWidth;
+}
+
+int wxGrid::GetRowMinimalHeight(int row) const
+{
+ wxLongToLongHashMap::key_type key = (wxLongToLongHashMap::key_type)row;
+ wxLongToLongHashMap::const_iterator it = m_rowMinHeights.find(key);
+
+ return it != m_rowMinHeights.end() ? (int)it->second : m_minAcceptableRowHeight;
+}
+
+void wxGrid::SetColMinimalAcceptableWidth( int width )
+{
+ // We do allow a width of 0 since this gives us
+ // an easy way to temporarily hiding columns.
+ if ( width >= 0 )
+ m_minAcceptableColWidth = width;
+}
+
+void wxGrid::SetRowMinimalAcceptableHeight( int height )
+{
+ // We do allow a height of 0 since this gives us
+ // an easy way to temporarily hiding rows.
+ if ( height >= 0 )
+ m_minAcceptableRowHeight = height;
+}
+
+int wxGrid::GetColMinimalAcceptableWidth() const
+{
+ return m_minAcceptableColWidth;
+}
+
+int wxGrid::GetRowMinimalAcceptableHeight() const
+{
+ return m_minAcceptableRowHeight;
+}
+
+// ----------------------------------------------------------------------------
+// auto sizing
+// ----------------------------------------------------------------------------
+
+void
+wxGrid::AutoSizeColOrRow(int colOrRow, bool setAsMin, wxGridDirection direction)
+{
+ const bool column = direction == wxGRID_COLUMN;
+
+ wxClientDC dc(m_gridWin);
+
+ // cancel editing of cell
+ HideCellEditControl();
+ SaveEditControlValue();
+
+ // initialize both of them just to avoid compiler warnings
+ int row = -1,
+ col = -1;
+
+ wxCoord extent, extentMax = 0;
+ int max = column ? m_numRows : m_numCols;
+ for ( int rowOrCol = 0; rowOrCol < max; rowOrCol++ )
+ {
+ if ( column )
+ {
+ row = rowOrCol;
+ col = colOrRow;
+ }
+ else
+ {
+ row = colOrRow;
+ col = rowOrCol;
+ }
+
+ // we need to account for the cells spanning multiple columns/rows:
+ // while they may need a lot of space, they don't need all of it in
+ // this column/row
+ int numRows, numCols;
+ const CellSpan span = GetCellSize(row, col, &numRows, &numCols);
+ if ( span == CellSpan_Inside )
+ {
+ // we need to get the size of the main cell, not of a cell hidden
+ // by it
+ row += numRows;
+ col += numCols;
+
+ // get the size of the main cell too
+ GetCellSize(row, col, &numRows, &numCols);
+ }
+
+ wxGridCellAttr *attr = GetCellAttr(row, col);
+ wxGridCellRenderer *renderer = attr->GetRenderer(this, row, col);
+ if ( renderer )
+ {
+ wxSize size = renderer->GetBestSize(*this, *attr, dc, row, col);
+ extent = column ? size.x : size.y;
+
+ if ( span != CellSpan_None )
+ {
+ // we spread the size of a spanning cell over all the cells it
+ // covers evenly -- this is probably not ideal but we can't
+ // really do much better here
+ //
+ // notice that numCols and numRows are never 0 as they
+ // correspond to the size of the main cell of the span and not
+ // of the cell inside it
+ extent /= column ? numCols : numRows;
+ }
+
+ if ( extent > extentMax )
+ extentMax = extent;
+
+ renderer->DecRef();
+ }
+
+ attr->DecRef();
+ }
+
+ // now also compare with the column label extent
+ wxCoord w, h;
+ dc.SetFont( GetLabelFont() );
+
+ if ( column )
+ {
+ dc.GetMultiLineTextExtent( GetColLabelValue(col), &w, &h );
+ if ( GetColLabelTextOrientation() == wxVERTICAL )
+ w = h;
+ }
+ else
+ dc.GetMultiLineTextExtent( GetRowLabelValue(row), &w, &h );
+
+ extent = column ? w : h;
+ if ( extent > extentMax )
+ extentMax = extent;
+
+ if ( !extentMax )
+ {
+ // empty column - give default extent (notice that if extentMax is less
+ // than default extent but != 0, it's OK)
+ extentMax = column ? m_defaultColWidth : m_defaultRowHeight;
+ }
+ else
+ {
+ if ( column )
+ // leave some space around text
+ extentMax += 10;
+ else
+ extentMax += 6;
+ }
+
+ if ( column )
+ {
+ // Ensure automatic width is not less than minimal width. See the
+ // comment in SetColSize() for explanation of why this isn't done
+ // in SetColSize().
+ if ( !setAsMin )
+ extentMax = wxMax(extentMax, GetColMinimalWidth(col));
+
+ SetColSize( col, extentMax );
+ if ( !GetBatchCount() )
+ {
+ if ( m_useNativeHeader )
+ {
+ GetGridColHeader()->UpdateColumn(col);
+ }
+ else
+ {
+ int cw, ch, dummy;
+ m_gridWin->GetClientSize( &cw, &ch );
+ wxRect rect ( CellToRect( 0, col ) );
+ rect.y = 0;
+ CalcScrolledPosition(rect.x, 0, &rect.x, &dummy);
+ rect.width = cw - rect.x;
+ rect.height = m_colLabelHeight;
+ GetColLabelWindow()->Refresh( true, &rect );
+ }
+ }
+ }
+ else
+ {
+ // Ensure automatic width is not less than minimal height. See the
+ // comment in SetColSize() for explanation of why this isn't done
+ // in SetRowSize().
+ if ( !setAsMin )
+ extentMax = wxMax(extentMax, GetRowMinimalHeight(row));
+
+ SetRowSize(row, extentMax);
+ if ( !GetBatchCount() )
+ {
+ int cw, ch, dummy;
+ m_gridWin->GetClientSize( &cw, &ch );
+ wxRect rect( CellToRect( row, 0 ) );
+ rect.x = 0;
+ CalcScrolledPosition(0, rect.y, &dummy, &rect.y);
+ rect.width = m_rowLabelWidth;
+ rect.height = ch - rect.y;
+ m_rowLabelWin->Refresh( true, &rect );
+ }
+ }
+
+ if ( setAsMin )
+ {
+ if ( column )
+ SetColMinimalWidth(col, extentMax);
+ else
+ SetRowMinimalHeight(row, extentMax);
+ }
+}
+
+wxCoord wxGrid::CalcColOrRowLabelAreaMinSize(wxGridDirection direction)
+{
+ // calculate size for the rows or columns?
+ const bool calcRows = direction == wxGRID_ROW;
+
+ wxClientDC dc(calcRows ? GetGridRowLabelWindow()
+ : GetGridColLabelWindow());
+ dc.SetFont(GetLabelFont());
+
+ // which dimension should we take into account for calculations?
+ //
+ // for columns, the text can be only horizontal so it's easy but for rows
+ // we also have to take into account the text orientation
+ const bool
+ useWidth = calcRows || (GetColLabelTextOrientation() == wxVERTICAL);
+
+ wxArrayString lines;
+ wxCoord extentMax = 0;
+
+ const int numRowsOrCols = calcRows ? m_numRows : m_numCols;
+ for ( int rowOrCol = 0; rowOrCol < numRowsOrCols; rowOrCol++ )
+ {
+ lines.Clear();
+
+ wxString label = calcRows ? GetRowLabelValue(rowOrCol)
+ : GetColLabelValue(rowOrCol);
+ StringToLines(label, lines);
+
+ long w, h;
+ GetTextBoxSize(dc, lines, &w, &h);
+
+ const wxCoord extent = useWidth ? w : h;
+ if ( extent > extentMax )
+ extentMax = extent;
+ }
+
+ if ( !extentMax )
+ {
+ // empty column - give default extent (notice that if extentMax is less
+ // than default extent but != 0, it's OK)
+ extentMax = calcRows ? GetDefaultRowLabelSize()
+ : GetDefaultColLabelSize();
+ }
+
+ // leave some space around text (taken from AutoSizeColOrRow)
+ if ( calcRows )
+ extentMax += 10;
+ else
+ extentMax += 6;
+
+ return extentMax;
+}
+
+int wxGrid::SetOrCalcColumnSizes(bool calcOnly, bool setAsMin)
+{
+ int width = m_rowLabelWidth;
+
+ wxGridUpdateLocker locker;
+ if(!calcOnly)
+ locker.Create(this);
+
+ for ( int col = 0; col < m_numCols; col++ )
+ {
+ if ( !calcOnly )
+ AutoSizeColumn(col, setAsMin);
+
+ width += GetColWidth(col);
+ }
+
+ return width;
+}
+
+int wxGrid::SetOrCalcRowSizes(bool calcOnly, bool setAsMin)
+{
+ int height = m_colLabelHeight;
+
+ wxGridUpdateLocker locker;
+ if(!calcOnly)
+ locker.Create(this);
+
+ for ( int row = 0; row < m_numRows; row++ )
+ {
+ if ( !calcOnly )
+ AutoSizeRow(row, setAsMin);
+
+ height += GetRowHeight(row);
+ }
+
+ return height;
+}
+
+void wxGrid::AutoSize()
+{
+ wxGridUpdateLocker locker(this);
+
+ wxSize size(SetOrCalcColumnSizes(false) - m_rowLabelWidth + m_extraWidth,
+ SetOrCalcRowSizes(false) - m_colLabelHeight + m_extraHeight);
+
+ // we know that we're not going to have scrollbars so disable them now to
+ // avoid trouble in SetClientSize() which can otherwise set the correct
+ // client size but also leave space for (not needed any more) scrollbars
+ SetScrollbars(0, 0, 0, 0, 0, 0, true);
+
+ // restore the scroll rate parameters overwritten by SetScrollbars()
+ SetScrollRate(m_scrollLineX, m_scrollLineY);
+
+ SetClientSize(size.x + m_rowLabelWidth, size.y + m_colLabelHeight);
+}
+
+void wxGrid::AutoSizeRowLabelSize( int row )
+{
+ // Hide the edit control, so it
+ // won't interfere with drag-shrinking.
+ if ( IsCellEditControlShown() )
+ {
+ HideCellEditControl();
+ SaveEditControlValue();
+ }
+
+ // autosize row height depending on label text
+ SetRowSize(row, -1);
+ ForceRefresh();
+}
+
+void wxGrid::AutoSizeColLabelSize( int col )
+{
+ // Hide the edit control, so it
+ // won't interfere with drag-shrinking.
+ if ( IsCellEditControlShown() )
+ {
+ HideCellEditControl();
+ SaveEditControlValue();
+ }
+
+ // autosize column width depending on label text
+ SetColSize(col, -1);
+ ForceRefresh();
+}
+
+wxSize wxGrid::DoGetBestSize() const
+{
+ wxGrid *self = (wxGrid *)this; // const_cast
+
+ // we do the same as in AutoSize() here with the exception that we don't
+ // change the column/row sizes, only calculate them
+ wxSize size(self->SetOrCalcColumnSizes(true) - m_rowLabelWidth + m_extraWidth,
+ self->SetOrCalcRowSizes(true) - m_colLabelHeight + m_extraHeight);
+
+ // NOTE: This size should be cached, but first we need to add calls to
+ // InvalidateBestSize everywhere that could change the results of this
+ // calculation.
+ // CacheBestSize(size);
+
+ return wxSize(size.x + m_rowLabelWidth, size.y + m_colLabelHeight)
+ + GetWindowBorderSize();
+}
+
+void wxGrid::Fit()
+{
+ AutoSize();
+}
+
+wxPen& wxGrid::GetDividerPen() const
+{
+ return wxNullPen;
+}
+
+// ----------------------------------------------------------------------------
+// cell value accessor functions
+// ----------------------------------------------------------------------------