+// This is used to redraw all grid lines e.g. when the grid line colour
+// has been changed
+//
+void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & WXUNUSED(reg) )
+{
+ if ( !m_gridLinesEnabled )
+ return;
+
+ int top, bottom, left, right;
+
+ int cw, ch;
+ m_gridWin->GetClientSize(&cw, &ch);
+ CalcUnscrolledPosition( 0, 0, &left, &top );
+ CalcUnscrolledPosition( cw, ch, &right, &bottom );
+
+ // avoid drawing grid lines past the last row and col
+ if ( m_gridLinesClipHorz )
+ {
+ if ( !m_numCols )
+ return;
+
+ const int lastColRight = GetColRight(GetColAt(m_numCols - 1));
+ if ( right > lastColRight )
+ right = lastColRight;
+ }
+
+ if ( m_gridLinesClipVert )
+ {
+ if ( !m_numRows )
+ return;
+
+ const int lastRowBottom = GetRowBottom(m_numRows - 1);
+ if ( bottom > lastRowBottom )
+ bottom = lastRowBottom;
+ }
+
+ // no gridlines inside multicells, clip them out
+ int leftCol = GetColPos( internalXToCol(left) );
+ int topRow = internalYToRow(top);
+ int rightCol = GetColPos( internalXToCol(right) );
+ int bottomRow = internalYToRow(bottom);
+
+ wxRegion clippedcells(0, 0, cw, ch);
+
+ int cell_rows, cell_cols;
+ wxRect rect;
+
+ for ( int j = topRow; j <= bottomRow; j++ )
+ {
+ for ( int colPos = leftCol; colPos <= rightCol; colPos++ )
+ {
+ int i = GetColAt( colPos );
+
+ GetCellSize( j, i, &cell_rows, &cell_cols );
+ if ((cell_rows > 1) || (cell_cols > 1))
+ {
+ rect = CellToRect(j,i);
+ CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+ clippedcells.Subtract(rect);
+ }
+ else if ((cell_rows < 0) || (cell_cols < 0))
+ {
+ rect = CellToRect(j + cell_rows, i + cell_cols);
+ CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y );
+ clippedcells.Subtract(rect);
+ }
+ }
+ }
+
+ dc.SetDeviceClippingRegion( clippedcells );
+
+
+ // horizontal grid lines
+ for ( int i = internalYToRow(top); i < m_numRows; i++ )
+ {
+ int bot = GetRowBottom(i) - 1;
+
+ if ( bot > bottom )
+ break;
+
+ if ( bot >= top )
+ {
+ dc.SetPen( GetRowGridLinePen(i) );
+ dc.DrawLine( left, bot, right, bot );
+ }
+ }
+
+ // vertical grid lines
+ for ( int colPos = leftCol; colPos < m_numCols; colPos++ )
+ {
+ int i = GetColAt( colPos );
+
+ int colRight = GetColRight(i);
+#ifdef __WXGTK__
+ if (GetLayoutDirection() != wxLayout_RightToLeft)
+#endif
+ colRight--;
+
+ if ( colRight > right )
+ break;
+
+ if ( colRight >= left )
+ {
+ dc.SetPen( GetColGridLinePen(i) );
+ dc.DrawLine( colRight, top, colRight, bottom );
+ }
+ }
+
+ dc.DestroyClippingRegion();
+}
+
+void wxGrid::DrawRowLabels( wxDC& dc, const wxArrayInt& rows)
+{
+ if ( !m_numRows )
+ return;
+
+ const size_t numLabels = rows.GetCount();
+ for ( size_t i = 0; i < numLabels; i++ )
+ {
+ DrawRowLabel( dc, rows[i] );
+ }
+}
+
+void wxGrid::DrawRowLabel( wxDC& dc, int row )
+{
+ if ( GetRowHeight(row) <= 0 || m_rowLabelWidth <= 0 )
+ return;
+
+ wxGridCellAttrProvider * const
+ attrProvider = m_table ? m_table->GetAttrProvider() : NULL;
+
+ // notice that an explicit static_cast is needed to avoid a compilation
+ // error with VC7.1 which, for some reason, tries to instantiate (abstract)
+ // wxGridRowHeaderRenderer class without it
+ const wxGridRowHeaderRenderer&
+ rend = attrProvider ? attrProvider->GetRowHeaderRenderer(row)
+ : static_cast<const wxGridRowHeaderRenderer&>
+ (gs_defaultHeaderRenderers.rowRenderer);
+
+ wxRect rect(0, GetRowTop(row), m_rowLabelWidth, GetRowHeight(row));
+ rend.DrawBorder(*this, dc, rect);
+
+ int hAlign, vAlign;
+ GetRowLabelAlignment(&hAlign, &vAlign);
+
+ rend.DrawLabel(*this, dc, GetRowLabelValue(row),
+ rect, hAlign, vAlign, wxHORIZONTAL);
+}
+
+void wxGrid::UseNativeColHeader(bool native)
+{
+ if ( native == m_useNativeHeader )
+ return;
+
+ delete m_colWindow;
+ m_useNativeHeader = native;
+
+ CreateColumnWindow();
+
+ if ( m_useNativeHeader )
+ GetGridColHeader()->SetColumnCount(m_numCols);
+ CalcWindowSizes();
+}
+
+void wxGrid::SetUseNativeColLabels( bool native )
+{
+ wxASSERT_MSG( !m_useNativeHeader,
+ "doesn't make sense when using native header" );
+
+ m_nativeColumnLabels = native;
+ if (native)
+ {
+ int height = wxRendererNative::Get().GetHeaderButtonHeight( this );
+ SetColLabelSize( height );
+ }
+
+ GetColLabelWindow()->Refresh();
+ m_cornerLabelWin->Refresh();
+}
+
+void wxGrid::DrawColLabels( wxDC& dc,const wxArrayInt& cols )
+{
+ if ( !m_numCols )
+ return;
+
+ const size_t numLabels = cols.GetCount();
+ for ( size_t i = 0; i < numLabels; i++ )
+ {
+ DrawColLabel( dc, cols[i] );
+ }
+}
+
+void wxGrid::DrawCornerLabel(wxDC& dc)
+{
+ wxRect rect(wxSize(m_rowLabelWidth, m_colLabelHeight));
+
+ if ( m_nativeColumnLabels )
+ {
+ rect.Deflate(1);
+
+ wxRendererNative::Get().DrawHeaderButton(m_cornerLabelWin, dc, rect, 0);
+ }
+ else
+ {
+ rect.width++;
+ rect.height++;
+
+ wxGridCellAttrProvider * const
+ attrProvider = m_table ? m_table->GetAttrProvider() : NULL;
+ const wxGridCornerHeaderRenderer&
+ rend = attrProvider ? attrProvider->GetCornerRenderer()
+ : static_cast<wxGridCornerHeaderRenderer&>
+ (gs_defaultHeaderRenderers.cornerRenderer);
+
+ rend.DrawBorder(*this, dc, rect);
+ }
+}
+
+void wxGrid::DrawColLabel(wxDC& dc, int col)
+{
+ if ( GetColWidth(col) <= 0 || m_colLabelHeight <= 0 )
+ return;
+
+ int colLeft = GetColLeft(col);
+
+ wxRect rect(colLeft, 0, GetColWidth(col), m_colLabelHeight);
+ wxGridCellAttrProvider * const
+ attrProvider = m_table ? m_table->GetAttrProvider() : NULL;
+ const wxGridColumnHeaderRenderer&
+ rend = attrProvider ? attrProvider->GetColumnHeaderRenderer(col)
+ : static_cast<wxGridColumnHeaderRenderer&>
+ (gs_defaultHeaderRenderers.colRenderer);
+
+ if ( m_nativeColumnLabels )
+ {
+ wxRendererNative::Get().DrawHeaderButton
+ (
+ GetColLabelWindow(),
+ dc,
+ rect,
+ 0,
+ IsSortingBy(col)
+ ? IsSortOrderAscending()
+ ? wxHDR_SORT_ICON_UP
+ : wxHDR_SORT_ICON_DOWN
+ : wxHDR_SORT_ICON_NONE
+ );
+ rect.Deflate(2);
+ }
+ else
+ {
+ rend.DrawBorder(*this, dc, rect);
+ }
+
+ int hAlign, vAlign;
+ GetColLabelAlignment(&hAlign, &vAlign);
+ const int orient = GetColLabelTextOrientation();
+
+ rend.DrawLabel(*this, dc, GetColLabelValue(col), rect, hAlign, vAlign, orient);
+}
+
+// TODO: these 2 functions should be replaced with wxDC::DrawLabel() to which
+// we just have to add textOrientation support
+void wxGrid::DrawTextRectangle( wxDC& dc,
+ const wxString& value,
+ const wxRect& rect,
+ int horizAlign,
+ int vertAlign,
+ int textOrientation ) const
+{
+ wxArrayString lines;
+
+ StringToLines( value, lines );
+
+ DrawTextRectangle(dc, lines, rect, horizAlign, vertAlign, textOrientation);
+}
+
+void wxGrid::DrawTextRectangle(wxDC& dc,
+ const wxArrayString& lines,
+ const wxRect& rect,
+ int horizAlign,
+ int vertAlign,
+ int textOrientation) const
+{
+ if ( lines.empty() )
+ return;
+
+ wxDCClipper clip(dc, rect);
+
+ long textWidth,
+ textHeight;
+
+ if ( textOrientation == wxHORIZONTAL )
+ GetTextBoxSize( dc, lines, &textWidth, &textHeight );
+ else
+ GetTextBoxSize( dc, lines, &textHeight, &textWidth );
+
+ int x = 0,
+ y = 0;
+ switch ( vertAlign )
+ {
+ case wxALIGN_BOTTOM:
+ if ( textOrientation == wxHORIZONTAL )
+ y = rect.y + (rect.height - textHeight - 1);
+ else
+ x = rect.x + rect.width - textWidth;
+ break;
+
+ case wxALIGN_CENTRE:
+ if ( textOrientation == wxHORIZONTAL )
+ y = rect.y + ((rect.height - textHeight) / 2);
+ else
+ x = rect.x + ((rect.width - textWidth) / 2);
+ break;
+
+ case wxALIGN_TOP:
+ default:
+ if ( textOrientation == wxHORIZONTAL )
+ y = rect.y + 1;
+ else
+ x = rect.x + 1;
+ break;
+ }
+
+ // Align each line of a multi-line label
+ size_t nLines = lines.GetCount();
+ for ( size_t l = 0; l < nLines; l++ )
+ {
+ const wxString& line = lines[l];
+
+ if ( line.empty() )
+ {
+ *(textOrientation == wxHORIZONTAL ? &y : &x) += dc.GetCharHeight();
+ continue;
+ }
+
+ wxCoord lineWidth = 0,
+ lineHeight = 0;
+ dc.GetTextExtent(line, &lineWidth, &lineHeight);
+
+ switch ( horizAlign )
+ {
+ case wxALIGN_RIGHT:
+ if ( textOrientation == wxHORIZONTAL )
+ x = rect.x + (rect.width - lineWidth - 1);
+ else
+ y = rect.y + lineWidth + 1;
+ break;
+
+ case wxALIGN_CENTRE:
+ if ( textOrientation == wxHORIZONTAL )
+ x = rect.x + ((rect.width - lineWidth) / 2);
+ else
+ y = rect.y + rect.height - ((rect.height - lineWidth) / 2);
+ break;
+
+ case wxALIGN_LEFT:
+ default:
+ if ( textOrientation == wxHORIZONTAL )
+ x = rect.x + 1;
+ else
+ y = rect.y + rect.height - 1;
+ break;
+ }