X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/58dd5b3b3e5bf943ed42268d74efcdc95ad2f0ec..b0d6ff2f7fb82e1ba838579ae0ddda70f5de0f8a:/src/generic/grid.cpp?ds=inline diff --git a/src/generic/grid.cpp b/src/generic/grid.cpp index f98d5cb4bf..a999ea3e08 100644 --- a/src/generic/grid.cpp +++ b/src/generic/grid.cpp @@ -36,6 +36,9 @@ #include "wx/generic/grid.h" +#ifndef WXGRID_DRAW_LINES +#define WXGRID_DRAW_LINES 1 +#endif ////////////////////////////////////////////////////////////////////// @@ -47,6 +50,9 @@ wxRect wxGridNoCellRect( -1, -1, -1, -1 ); WX_DEFINE_OBJARRAY(wxGridCellCoordsArray) +// scroll line size +// TODO: fixed so far - make configurable later (and also different for x/y) +static const size_t GRID_SCROLL_LINE = 10; ////////////////////////////////////////////////////////////////////// // @@ -139,7 +145,7 @@ wxString wxGridTableBase::GetColLabelValue( int col ) unsigned int i, n; for ( n = 1; ; n++ ) { - s += ('A' + (char)( col%26 )); + s += (_T('A') + (wxChar)( col%26 )); col = col/26 - 1; if ( col < 0 ) break; } @@ -606,6 +612,7 @@ void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) case WXK_RIGHT: case WXK_PRIOR: case WXK_NEXT: + case WXK_SPACE: if ( m_isCellControl ) { // send the event to the parent grid, skipping the @@ -627,7 +634,7 @@ void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) { if ( !m_grid->ProcessEvent( event ) ) { -#ifdef __WXMOTIF__ +#if defined(__WXMOTIF__) || defined(__WXGTK__) // wxMotif needs a little extra help... // int pos = GetInsertionPoint(); @@ -639,7 +646,7 @@ void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) // the other ports can handle a Return key press // event.Skip(); -#endif +#endif } } break; @@ -670,7 +677,7 @@ void wxGridTextCtrl::OnKeyDown( wxKeyEvent& event ) void wxGridTextCtrl::SetStartValue( const wxString& s ) { startValue = s; - wxTextCtrl::SetValue( s.c_str() ); + wxTextCtrl::SetValue(s); } @@ -703,7 +710,7 @@ void wxGridRowLabelWindow::OnPaint( wxPaintEvent &event ) // // m_owner->PrepareDC( dc ); - wxCoord x, y; + int x, y; m_owner->CalcUnscrolledPosition( 0, 0, &x, &y ); dc.SetDeviceOrigin( 0, -y ); @@ -756,7 +763,7 @@ void wxGridColLabelWindow::OnPaint( wxPaintEvent &event ) // // m_owner->PrepareDC( dc ); - wxCoord x, y; + int x, y; m_owner->CalcUnscrolledPosition( 0, 0, &x, &y ); dc.SetDeviceOrigin( -x, 0 ); @@ -787,17 +794,35 @@ IMPLEMENT_DYNAMIC_CLASS( wxGridCornerLabelWindow, wxWindow ) BEGIN_EVENT_TABLE( wxGridCornerLabelWindow, wxWindow ) EVT_MOUSE_EVENTS( wxGridCornerLabelWindow::OnMouseEvent ) + EVT_PAINT( wxGridCornerLabelWindow::OnPaint) EVT_KEY_DOWN( wxGridCornerLabelWindow::OnKeyDown ) END_EVENT_TABLE() wxGridCornerLabelWindow::wxGridCornerLabelWindow( wxGrid *parent, wxWindowID id, const wxPoint &pos, const wxSize &size ) - : wxWindow( parent, id, pos, size, wxRAISED_BORDER ) + : wxWindow( parent, id, pos, size ) { m_owner = parent; } +void wxGridCornerLabelWindow::OnPaint( wxPaintEvent& WXUNUSED(event) ) +{ + wxPaintDC dc(this); + + int client_height = 0; + int client_width = 0; + GetClientSize( &client_width, &client_height ); + + dc.SetPen( *wxBLACK_PEN ); + dc.DrawLine( client_width-1, client_height-1, client_width-1, 0 ); + dc.DrawLine( client_width-1, client_height-1, 0, client_height-1 ); + + dc.SetPen( *wxWHITE_PEN ); + dc.DrawLine( 0, 0, client_width, 0 ); + dc.DrawLine( 0, 0, 0, client_height ); +} + void wxGridCornerLabelWindow::OnMouseEvent( wxMouseEvent& event ) { @@ -821,7 +846,6 @@ IMPLEMENT_DYNAMIC_CLASS( wxGridWindow, wxPanel ) BEGIN_EVENT_TABLE( wxGridWindow, wxPanel ) EVT_PAINT( wxGridWindow::OnPaint ) - EVT_SCROLLWIN( wxGridWindow::ScrollWindow ) EVT_MOUSE_EVENTS( wxGridWindow::OnMouseEvent ) EVT_KEY_DOWN( wxGridWindow::OnKeyDown ) END_EVENT_TABLE() @@ -830,7 +854,7 @@ wxGridWindow::wxGridWindow( wxGrid *parent, wxGridRowLabelWindow *rowLblWin, wxGridColLabelWindow *colLblWin, wxWindowID id, const wxPoint &pos, const wxSize &size ) - : wxPanel( parent, id, pos, size, wxSUNKEN_BORDER, "grid window" ) + : wxPanel( parent, id, pos, size, 0, "grid window" ) { m_owner = parent; m_rowLabelWin = rowLblWin; @@ -849,9 +873,12 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) ) { wxPaintDC dc( this ); m_owner->PrepareDC( dc ); - - m_owner->CalcCellsExposed( GetUpdateRegion() ); + wxRegion reg = GetUpdateRegion(); + m_owner->CalcCellsExposed( reg ); m_owner->DrawGridCellArea( dc ); +#if WXGRID_DRAW_LINES + m_owner->DrawAllGridLines( dc, reg ); +#endif } @@ -912,7 +939,7 @@ wxGrid::~wxGrid() // void wxGrid::Create() -{ +{ int colLblH = WXGRID_DEFAULT_COL_LABEL_HEIGHT; int rowLblW = WXGRID_DEFAULT_ROW_LABEL_WIDTH; @@ -1019,7 +1046,7 @@ void wxGrid::Init() m_defaultColWidth = WXGRID_DEFAULT_COL_WIDTH; m_defaultRowHeight = m_gridWin->GetCharHeight(); -#if defined (__WXMOTIF__) // see also text ctrl sizing in ShowCellEditControl() +#if defined(__WXMOTIF__) || defined(__WXGTK__) // see also text ctrl sizing in ShowCellEditControl() m_defaultRowHeight += 8; #else m_defaultRowHeight += 4; @@ -1079,7 +1106,7 @@ void wxGrid::Init() "", wxPoint(1,1), wxSize(1,1) -#ifdef __WXMSW__ +#if defined(__WXMSW__) , wxTE_MULTILINE | wxTE_NO_VSCROLL #endif ); @@ -1097,15 +1124,15 @@ void wxGrid::CalcDimensions() if ( m_numRows > 0 && m_numCols > 0 ) { - int right = m_colRights[ m_numCols-1 ] + 20; - int bottom = m_rowBottoms[ m_numRows-1 ] + 20; + int right = m_colRights[ m_numCols-1 ] + 50; + int bottom = m_rowBottoms[ m_numRows-1 ] + 50; // TODO: restore the scroll position that we had before sizing // int x, y; GetViewStart( &x, &y ); - SetScrollbars( 10, 10, - right/10, bottom/10, + SetScrollbars( GRID_SCROLL_LINE, GRID_SCROLL_LINE, + right/GRID_SCROLL_LINE, bottom/GRID_SCROLL_LINE, x, y ); } } @@ -1473,7 +1500,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); - dc.SetLogicalFunction(wxXOR); + dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { dc.DrawLine( left, m_dragLastPos, left+cw, m_dragLastPos ); @@ -1565,9 +1592,15 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) SetRowSize( m_dragRowOrCol, wxMax( y - rowTop, WXGRID_MIN_ROW_HEIGHT ) ); if ( !GetBatchCount() ) { - // TODO: optimize this - m_rowLabelWin->Refresh(); - m_gridWin->Refresh(); + // Only needed to get the correct rect.y: + wxRect rect ( CellToRect( m_dragRowOrCol, 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 ); + rect.width = cw; + m_gridWin->Refresh( FALSE, &rect ); } ShowCellEditControl(); @@ -1579,6 +1612,7 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) } } + m_cursorMode = WXGRID_CURSOR_SELECT_CELL; m_dragLastPos = -1; } @@ -1622,11 +1656,9 @@ void wxGrid::ProcessRowLabelMouseEvent( wxMouseEvent& event ) } else { - if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL ) - { - m_cursorMode = WXGRID_CURSOR_SELECT_CELL; + m_cursorMode = WXGRID_CURSOR_SELECT_CELL; + if ( m_rowLabelWin->GetCursor() == m_rowResizeCursor ) m_rowLabelWin->SetCursor( *wxSTANDARD_CURSOR ); - } } } } @@ -1654,7 +1686,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); - dc.SetLogicalFunction(wxXOR); + dc.SetLogicalFunction(wxINVERT); if ( m_dragLastPos >= 0 ) { dc.DrawLine( m_dragLastPos, top, m_dragLastPos, top+ch ); @@ -1747,9 +1779,15 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) if ( !GetBatchCount() ) { - // TODO: optimize this - m_colLabelWin->Refresh(); - m_gridWin->Refresh(); + // Only needed to get the correct rect.x: + wxRect rect ( CellToRect( 0, m_dragRowOrCol ) ); + rect.y = 0; + CalcScrolledPosition(rect.x, 0, &rect.x, &dummy); + rect.width = cw - rect.x; + rect.height = m_colLabelHeight; + m_colLabelWin->Refresh( TRUE, &rect ); + rect.height = ch; + m_gridWin->Refresh( FALSE, &rect ); } ShowCellEditControl(); @@ -1761,6 +1799,7 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) } } + m_cursorMode = WXGRID_CURSOR_SELECT_CELL; m_dragLastPos = -1; } @@ -1804,11 +1843,9 @@ void wxGrid::ProcessColLabelMouseEvent( wxMouseEvent& event ) } else { - if ( m_cursorMode != WXGRID_CURSOR_SELECT_CELL ) - { - m_cursorMode = WXGRID_CURSOR_SELECT_CELL; + m_cursorMode = WXGRID_CURSOR_SELECT_CELL; + if ( m_colLabelWin->GetCursor() == m_colResizeCursor ) m_colLabelWin->SetCursor( *wxSTANDARD_CURSOR ); - } } } } @@ -1864,10 +1901,10 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) m_isDragging = TRUE; if ( m_cursorMode == WXGRID_CURSOR_SELECT_CELL ) { - // Hide the edit control, so it - // won't interfer with drag-shrinking. - if ( IsCellEditControlEnabled() ) - HideCellEditControl(); + // Hide the edit control, so it + // won't interfer with drag-shrinking. + if ( IsCellEditControlEnabled() ) + HideCellEditControl(); if ( coords != wxGridNoCellCoords ) { if ( !IsSelection() ) @@ -1876,7 +1913,7 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) } else { - SelectBlock( m_currentCellCoords, coords ); + SelectBlock( m_currentCellCoords, coords ); } } } @@ -1931,10 +1968,10 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) } } - // Show the edit control, if it has - // been hidden for drag-shrinking. - if ( IsCellEditControlEnabled() ) - ShowCellEditControl(); + // Show the edit control, if it has + // been hidden for drag-shrinking. + if ( IsCellEditControlEnabled() ) + ShowCellEditControl(); m_dragLastPos = -1; } @@ -1966,6 +2003,13 @@ void wxGrid::ProcessGridCellMouseEvent( wxMouseEvent& event ) // no default action at the moment } } + + // ------------ Moving and no button action + // + else if ( event.Moving() && !event.IsButton() ) + { + m_cursorMode = WXGRID_CURSOR_SELECT_CELL; + } } } @@ -2417,6 +2461,17 @@ void wxGrid::OnKeyDown( wxKeyEvent& event ) MoveCursorRight(); } break; + + case WXK_SPACE: + if ( !IsEditable() ) + { + MoveCursorRight(); + } + else + { + event.Skip(); + } + break; case WXK_RETURN: if ( event.ControlDown() ) @@ -2503,7 +2558,7 @@ void wxGrid::SetCurrentCell( const wxGridCellCoords& coords ) { wxRect r( SelectionToDeviceRect() ); ClearSelection(); - if ( !GetBatchCount() ) m_gridWin->Refresh( TRUE, &r ); + if ( !GetBatchCount() ) m_gridWin->Refresh( FALSE, &r ); } } @@ -2571,8 +2626,10 @@ void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords ) if ( m_colWidths[coords.GetCol()] <=0 || m_rowHeights[coords.GetRow()] <= 0 ) return; +#if !WXGRID_DRAW_LINES if ( m_gridLinesEnabled ) DrawCellBorder( dc, coords ); +#endif DrawCellBackground( dc, coords ); @@ -2676,27 +2733,41 @@ void wxGrid::DrawCellValue( wxDC& dc, const wxGridCellCoords& coords ) // This is used to redraw all grid lines e.g. when the grid line colour // has been changed // -void wxGrid::DrawAllGridLines( wxDC& dc ) +void wxGrid::DrawAllGridLines( wxDC& dc, const wxRegion & reg ) { if ( !m_gridLinesEnabled || !m_numRows || !m_numCols ) return; - int cw, ch; - m_gridWin->GetClientSize(&cw, &ch); + int top, bottom, left, right; - // virtual coords of visible area + if (reg.IsEmpty()){ + int cw, ch; + m_gridWin->GetClientSize(&cw, &ch); + + // virtual coords of visible area + // + CalcUnscrolledPosition( 0, 0, &left, &top ); + CalcUnscrolledPosition( cw, ch, &right, &bottom ); + } + else{ + wxCoord x, y, w, h; + reg.GetBox(x, y, w, h); + CalcUnscrolledPosition( x, y, &left, &top ); + CalcUnscrolledPosition( x + w, y + h, &right, &bottom ); + } + + // avoid drawing grid lines past the last row and col // - int top, bottom, left, right; - CalcUnscrolledPosition( 0, 0, &left, &top ); - CalcUnscrolledPosition( cw, ch, &right, &bottom ); + right = wxMin( right, m_colRights[m_numCols-1] ); + bottom = wxMin( bottom, m_rowBottoms[m_numRows-1] ); dc.SetPen( wxPen(GetGridLineColour(), 1, wxSOLID) ); // horizontal grid lines // int i; - for ( i = 0; i <= m_numRows; i++ ) + for ( i = 0; i < m_numRows; i++ ) { if ( m_rowBottoms[i] > bottom ) { @@ -2711,7 +2782,7 @@ void wxGrid::DrawAllGridLines( wxDC& dc ) // vertical grid lines // - for ( i = 0; i <= m_numCols; i++ ) + for ( i = 0; i < m_numCols; i++ ) { if ( m_colRights[i] > right ) { @@ -2743,18 +2814,18 @@ void wxGrid::DrawRowLabel( wxDC& dc, int row ) { if ( m_rowHeights[row] <= 0 ) return; - // draw the label's horizontal border (the vertical border is - // provided by the cell area window margin) - // + int rowTop = m_rowBottoms[row] - m_rowHeights[row]; + dc.SetPen( *wxBLACK_PEN ); - - dc.DrawLine( 0, m_rowBottoms[row]+1, - m_rowLabelWidth, m_rowBottoms[row]+1 ); - + dc.DrawLine( m_rowLabelWidth-1, rowTop, + m_rowLabelWidth-1, m_rowBottoms[row]-1 ); + + dc.DrawLine( 0, m_rowBottoms[row]-1, + m_rowLabelWidth-1, m_rowBottoms[row]-1 ); + dc.SetPen( *wxWHITE_PEN ); - - dc.DrawLine( 0, m_rowBottoms[row]+2, - m_rowLabelWidth, m_rowBottoms[row]+2 ); + dc.DrawLine( 0, rowTop, 0, m_rowBottoms[row]-1 ); + dc.DrawLine( 0, rowTop, m_rowLabelWidth-1, rowTop ); dc.SetBackgroundMode( wxTRANSPARENT ); dc.SetTextForeground( GetLabelTextColour() ); @@ -2790,18 +2861,22 @@ void wxGrid::DrawColLabel( wxDC& dc, int col ) { if ( m_colWidths[col] <= 0 ) return; - // draw the label's vertical border (the horizontal border is - // provided by the cell area window margin) - // + int colLeft = m_colRights[col] - m_colWidths[col]; + dc.SetPen( *wxBLACK_PEN ); - - dc.DrawLine( m_colRights[col]+1, 0, - m_colRights[col]+1, m_colLabelHeight ); - + dc.DrawLine( m_colRights[col]-1, 0, + m_colRights[col]-1, m_colLabelHeight-1 ); + + dc.DrawLine( colLeft, m_colLabelHeight-1, + m_colRights[col]-1, m_colLabelHeight-1 ); + dc.SetPen( *wxWHITE_PEN ); + dc.DrawLine( colLeft, 0, colLeft, m_colLabelHeight-1 ); + dc.DrawLine( colLeft, 0, m_colRights[col]-1, 0 ); - dc.DrawLine( m_colRights[col]+2, 0, - m_colRights[col]+2, m_colLabelHeight ); + dc.SetBackgroundMode( wxTRANSPARENT ); + dc.SetTextForeground( GetLabelTextColour() ); + dc.SetFont( GetLabelFont() ); dc.SetBackgroundMode( wxTRANSPARENT ); dc.SetTextForeground( GetLabelTextColour() ); @@ -3014,7 +3089,7 @@ void wxGrid::ShowCellEditControl() // TODO: remove this if the text ctrl sizing is improved esp. for unix // int extra; -#if defined (__WXMOTIF__) +#if defined(__WXMOTIF__) if ( m_currentCellCoords.GetRow() == 0 || m_currentCellCoords.GetCol() == 0 ) { @@ -3035,12 +3110,23 @@ void wxGrid::ShowCellEditControl() extra = 2; } #endif + +#if defined(__WXGTK__) + int top_diff = 0; + int left_diff = 0; + if (left != 0) left_diff++; + if (top != 0) top_diff++; + rect.SetLeft( left + left_diff ); + rect.SetTop( top + top_diff ); + rect.SetRight( rect.GetRight() - left_diff ); + rect.SetBottom( rect.GetBottom() - top_diff ); +#else rect.SetLeft( wxMax(0, left - extra) ); rect.SetTop( wxMax(0, top - extra) ); rect.SetRight( rect.GetRight() + 2*extra ); rect.SetBottom( rect.GetBottom() + 2*extra ); +#endif - m_cellEditCtrl->SetSize( rect ); m_cellEditCtrl->Show( TRUE ); @@ -3354,6 +3440,11 @@ void wxGrid::MakeCellVisible( int row, int col ) h += m_rowHeights[i]; ypos -= m_rowHeights[i]; } + + // we divide it later by GRID_SCROLL_LINE, make sure that we don't + // have rounding errors (this is important, because if we do, we + // might not scroll at all and some cells won't be redrawn) + ypos += GRID_SCROLL_LINE / 2; } if ( left < 0 ) @@ -3371,12 +3462,15 @@ void wxGrid::MakeCellVisible( int row, int col ) w += m_colWidths[i]; xpos -= m_colWidths[i]; } + + // see comment for ypos above + xpos += GRID_SCROLL_LINE / 2; } if ( xpos != -1 || ypos != -1 ) { - if ( xpos != -1 ) xpos = xpos/10; - if ( ypos != -1 ) ypos = ypos/10; + if ( xpos != -1 ) xpos /= GRID_SCROLL_LINE; + if ( ypos != -1 ) ypos /= GRID_SCROLL_LINE; Scroll( xpos, ypos ); AdjustScrollbars(); } @@ -3788,16 +3882,157 @@ wxString wxGrid::GetColLabelValue( int col ) } } + void wxGrid::SetRowLabelSize( int width ) { - // TODO: how to do this with the box sizers ? + wxSize sz; + + width = wxMax( width, 0 ); + if ( width != m_rowLabelWidth ) + { + // Hiding the row labels (and possible the corner label) + // + if ( width == 0 ) + { + m_rowLabelWin->Show( FALSE ); + + // If the col labels are on display we need to hide the + // corner label and remove it from the top sizer + // + if ( m_colLabelHeight > 0 ) + { + m_cornerLabelWin->Show( FALSE ); + m_topSizer->Remove( m_cornerLabelWin ); + } + + m_middleSizer->Remove( m_rowLabelWin ); + } + else + { + // Displaying the row labels (and possibly the corner + // label) after being hidden + // + if ( m_rowLabelWidth == 0 ) + { + m_rowLabelWin->Show( TRUE ); + + if ( m_colLabelHeight > 0 ) + { + m_cornerLabelWin->Show( TRUE ); + m_topSizer->Prepend( m_cornerLabelWin, 0 ); + } + + m_middleSizer->Prepend( m_rowLabelWin, 0, wxEXPAND ); + } + + + // set the width of the corner label if it is on display + // + if ( m_colLabelHeight > 0 ) + { + wxList& childList = m_topSizer->GetChildren(); + wxNode *node = childList.First(); + while (node) + { + wxSizerItem *item = (wxSizerItem*)node->Data(); + if ( item->GetWindow() == m_cornerLabelWin ) + { + item->SetInitSize( width, m_colLabelHeight ); + break; + } + node = node->Next(); + } + } + + // set the width of the row labels + // + wxList& childList = m_middleSizer->GetChildren(); + wxNode *node = childList.First(); + while (node) + { + wxSizerItem *item = (wxSizerItem*)node->Data(); + if ( item->GetWindow() == m_rowLabelWin ) + { + sz = item->GetWindow()->GetSize(); + item->SetInitSize( width, sz.GetHeight() ); + break; + } + node = node->Next(); + } + } + + m_rowLabelWidth = width; + m_mainSizer->Layout(); + } } + void wxGrid::SetColLabelSize( int height ) { - // TODO: how to do this with the box sizers ? + wxSize sz; + + if ( height < 0 ) height = 0; + if ( height != m_colLabelHeight ) + { + // hiding the column labels + // + if ( height == 0 ) + { + m_cornerLabelWin->Show( FALSE ); + m_colLabelWin->Show( FALSE ); + + // Note: this call will actually delete the sizer + // + m_mainSizer->Remove( m_topSizer ); + m_topSizer = (wxBoxSizer *)NULL; + } + else + { + // column labels to be displayed after being hidden + // + if ( m_colLabelHeight == 0 ) + { + // recreate the top sizer + // + m_topSizer = new wxBoxSizer( wxHORIZONTAL ); + + if ( m_rowLabelWidth > 0 ) + m_topSizer->Add( m_cornerLabelWin, 0 ); + + m_topSizer->Add( m_colLabelWin, 1 ); + m_mainSizer->Prepend( m_topSizer, 0, wxEXPAND ); + + // only show the corner label if the row labels are + // also displayed + // + if ( m_rowLabelWidth > 0 ) + m_cornerLabelWin->Show( TRUE ); + + m_colLabelWin->Show( TRUE ); + } + + wxList& childList = m_topSizer->GetChildren(); + wxNode *node = childList.First(); + while (node) + { + wxSizerItem *item = (wxSizerItem*)node->Data(); + + if ( (item->GetWindow() == m_cornerLabelWin && m_rowLabelWidth > 0) || + item->GetWindow() == m_colLabelWin ) + { + sz = item->GetWindow()->GetSize(); + item->SetInitSize( sz.GetWidth(), height ); + } + node = node->Next(); + } + } + + m_colLabelHeight = height; + m_mainSizer->Layout(); + } } + void wxGrid::SetLabelBackgroundColour( const wxColour& colour ) { if ( m_labelBackgroundColour != colour ) @@ -3854,7 +4089,6 @@ void wxGrid::SetRowLabelAlignment( int horiz, int vert ) if ( !GetBatchCount() ) { m_rowLabelWin->Refresh(); - m_colLabelWin->Refresh(); } } @@ -3872,7 +4106,6 @@ void wxGrid::SetColLabelAlignment( int horiz, int vert ) if ( !GetBatchCount() ) { - m_rowLabelWin->Refresh(); m_colLabelWin->Refresh(); } } @@ -3884,9 +4117,14 @@ void wxGrid::SetRowLabelValue( int row, const wxString& s ) m_table->SetRowLabelValue( row, s ); if ( !GetBatchCount() ) { - // TODO: Optimize this - // - m_rowLabelWin->Refresh(); + wxRect rect = CellToRect( row, 0); + if ( rect.height > 0 ) + { + CalcScrolledPosition(0, rect.y, &rect.x, &rect.y); + rect.x = m_left; + rect.width = m_rowLabelWidth; + m_rowLabelWin->Refresh( TRUE, &rect ); + } } } } @@ -3898,9 +4136,14 @@ void wxGrid::SetColLabelValue( int col, const wxString& s ) m_table->SetColLabelValue( col, s ); if ( !GetBatchCount() ) { - // TODO: optimize this - // - m_colLabelWin->Refresh(); + wxRect rect = CellToRect( 0, col ); + if ( rect.width > 0 ) + { + CalcScrolledPosition(rect.x, 0, &rect.x, &rect.y); + rect.y = m_top; + rect.height = m_colLabelHeight; + m_colLabelWin->Refresh( TRUE, &rect ); + } } } } @@ -3913,7 +4156,7 @@ void wxGrid::SetGridLineColour( const wxColour& colour ) wxClientDC dc( m_gridWin ); PrepareDC( dc ); - DrawAllGridLines( dc ); + DrawAllGridLines( dc, wxRegion() ); } } @@ -3929,7 +4172,7 @@ void wxGrid::EnableGridLines( bool enable ) { wxClientDC dc( m_gridWin ); PrepareDC( dc ); - DrawAllGridLines( dc ); + DrawAllGridLines( dc, wxRegion() ); } else { @@ -4204,32 +4447,67 @@ void wxGrid::SelectRow( int row, bool addToSelected ) if ( IsSelection() && addToSelected ) { - if ( m_selectedTopLeft.GetRow() > row ) + wxRect rect[4]; + bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; + int i; + + wxCoord oldLeft = m_selectedTopLeft.GetCol(); + wxCoord oldTop = m_selectedTopLeft.GetRow(); + wxCoord oldRight = m_selectedBottomRight.GetCol(); + wxCoord oldBottom = m_selectedBottomRight.GetRow(); + + if ( oldTop > row ) + { + need_refresh[0] = TRUE; + rect[0] = BlockToDeviceRect( wxGridCellCoords ( row, 0 ), + wxGridCellCoords ( oldTop - 1, + m_numCols - 1 ) ); m_selectedTopLeft.SetRow( row ); + } - m_selectedTopLeft.SetCol( 0 ); + if ( oldLeft > 0 ) + { + need_refresh[1] = TRUE; + rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, 0 ), + wxGridCellCoords ( oldBottom, + oldLeft - 1 ) ); + + m_selectedTopLeft.SetCol( 0 ); + } - if ( m_selectedBottomRight.GetRow() < row ) + if ( oldBottom < row ) + { + need_refresh[2] = TRUE; + rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, 0 ), + wxGridCellCoords ( row, + m_numCols - 1 ) ); m_selectedBottomRight.SetRow( row ); + } - m_selectedBottomRight.SetCol( m_numCols - 1 ); + if ( oldRight < m_numCols - 1 ) + { + need_refresh[3] = TRUE; + rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldTop , + oldRight + 1 ), + wxGridCellCoords ( oldBottom, + m_numCols - 1 ) ); + m_selectedBottomRight.SetCol( m_numCols - 1 ); + } - // TODO: optimize this so that we only refresh the newly - // selected cells - // - r = SelectionToDeviceRect(); - if ( r != wxGridNoCellRect ) m_gridWin->Refresh( TRUE, &r ); + for (i = 0; i < 4; i++ ) + if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) + m_gridWin->Refresh( FALSE, &(rect[i]) ); } else { r = SelectionToDeviceRect(); ClearSelection(); - if ( r != wxGridNoCellRect ) m_gridWin->Refresh( TRUE, &r ); + if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r ); m_selectedTopLeft.Set( row, 0 ); m_selectedBottomRight.Set( row, m_numCols-1 ); r = SelectionToDeviceRect(); - m_gridWin->Refresh( TRUE, &r ); + m_gridWin->Refresh( FALSE, &r ); } wxGridRangeSelectEvent gridEvt( GetId(), @@ -4244,36 +4522,70 @@ void wxGrid::SelectRow( int row, bool addToSelected ) void wxGrid::SelectCol( int col, bool addToSelected ) { - wxRect r; - if ( IsSelection() && addToSelected ) { - if ( m_selectedTopLeft.GetCol() > col ) + wxRect rect[4]; + bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; + int i; + + wxCoord oldLeft = m_selectedTopLeft.GetCol(); + wxCoord oldTop = m_selectedTopLeft.GetRow(); + wxCoord oldRight = m_selectedBottomRight.GetCol(); + wxCoord oldBottom = m_selectedBottomRight.GetRow(); + + if ( oldLeft > col ) + { + need_refresh[0] = TRUE; + rect[0] = BlockToDeviceRect( wxGridCellCoords ( 0, col ), + wxGridCellCoords ( m_numRows - 1, + oldLeft - 1 ) ); m_selectedTopLeft.SetCol( col ); + } - m_selectedTopLeft.SetRow( 0 ); + if ( oldTop > 0 ) + { + need_refresh[1] = TRUE; + rect[1] = BlockToDeviceRect( wxGridCellCoords ( 0, oldLeft ), + wxGridCellCoords ( oldTop - 1, + oldRight ) ); + m_selectedTopLeft.SetRow( 0 ); + } - if ( m_selectedBottomRight.GetCol() < col ) + if ( oldRight < col ) + { + need_refresh[2] = TRUE; + rect[2] = BlockToDeviceRect( wxGridCellCoords ( 0, oldRight + 1 ), + wxGridCellCoords ( m_numRows - 1, + col ) ); m_selectedBottomRight.SetCol( col ); + } - m_selectedBottomRight.SetRow( m_numRows - 1 ); + if ( oldBottom < m_numRows - 1 ) + { + need_refresh[3] = TRUE; + rect[3] = BlockToDeviceRect( wxGridCellCoords ( oldBottom + 1, + oldLeft ), + wxGridCellCoords ( m_numRows - 1, + oldRight ) ); + m_selectedBottomRight.SetRow( m_numRows - 1 ); + } - // TODO: optimize this so that we only refresh the newly - // selected cells - // - r = SelectionToDeviceRect(); - if ( r != wxGridNoCellRect ) m_gridWin->Refresh( TRUE, &r ); + for (i = 0; i < 4; i++ ) + if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) + m_gridWin->Refresh( FALSE, &(rect[i]) ); } else { + wxRect r; + r = SelectionToDeviceRect(); ClearSelection(); - if ( r != wxGridNoCellRect ) m_gridWin->Refresh( TRUE, &r ); + if ( r != wxGridNoCellRect ) m_gridWin->Refresh( FALSE, &r ); m_selectedTopLeft.Set( 0, col ); m_selectedBottomRight.Set( m_numRows-1, col ); r = SelectionToDeviceRect(); - m_gridWin->Refresh( TRUE, &r ); + m_gridWin->Refresh( FALSE, &r ); } wxGridRangeSelectEvent gridEvt( GetId(), @@ -4289,7 +4601,6 @@ void wxGrid::SelectCol( int col, bool addToSelected ) void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol ) { int temp; - bool changed = false; wxGridCellCoords updateTopLeft, updateBottomRight; if ( topRow > bottomRow ) @@ -4305,47 +4616,101 @@ void wxGrid::SelectBlock( int topRow, int leftCol, int bottomRow, int rightCol ) leftCol = rightCol; rightCol = temp; } - - updateTopLeft = m_selectedTopLeft; - if (m_selectedTopLeft != wxGridCellCoords( topRow, leftCol ) ) - { - m_selectedTopLeft = wxGridCellCoords( topRow, leftCol ); - if (updateTopLeft == wxGridNoCellCoords) - { - updateTopLeft = m_selectedTopLeft; - } - else - { - if(updateTopLeft.GetRow() > topRow) - updateTopLeft.SetRow(topRow); - if (updateTopLeft.GetCol() > leftCol) - updateTopLeft.SetCol(leftCol); - } - changed = true; - } - - updateBottomRight = m_selectedBottomRight; - if (m_selectedBottomRight != wxGridCellCoords( bottomRow, rightCol ) ) - { - m_selectedBottomRight = wxGridCellCoords( bottomRow, rightCol ); - if (updateBottomRight == wxGridNoCellCoords) - { - updateBottomRight = m_selectedBottomRight; - } - else - { - if (updateBottomRight.GetRow() < bottomRow) - updateBottomRight.SetRow(bottomRow); - if (updateBottomRight.GetCol() < rightCol) - updateBottomRight.SetCol(rightCol); - } - changed = true; - } - - if (changed) - { - wxRect r( BlockToDeviceRect( updateTopLeft, updateBottomRight ) ); - m_gridWin->Refresh( TRUE, &r ); + + updateTopLeft = wxGridCellCoords( topRow, leftCol ); + updateBottomRight = wxGridCellCoords( bottomRow, rightCol ); + + if ( m_selectedTopLeft != updateTopLeft || + m_selectedBottomRight != updateBottomRight ) + { + // Compute two optimal update rectangles: + // Either one rectangle is a real subset of the + // other, or they are (almost) disjoint! + wxRect rect[4]; + bool need_refresh[4] = { FALSE, FALSE, FALSE, FALSE }; + int i; + + // Store intermediate values + wxCoord oldLeft = m_selectedTopLeft.GetCol(); + wxCoord oldTop = m_selectedTopLeft.GetRow(); + wxCoord oldRight = m_selectedBottomRight.GetCol(); + wxCoord oldBottom = m_selectedBottomRight.GetRow(); + + // Determine the outer/inner coordinates. + if (oldLeft > leftCol) + { + temp = oldLeft; + oldLeft = leftCol; + leftCol = temp; + } + if (oldTop > topRow ) + { + temp = oldTop; + oldTop = topRow; + topRow = temp; + } + if (oldRight < rightCol ) + { + temp = oldRight; + oldRight = rightCol; + rightCol = temp; + } + if (oldBottom < bottomRow) + { + temp = oldBottom; + oldBottom = bottomRow; + bottomRow = temp; + } + + // Now, either the stuff marked old is the outer + // rectangle or we don't have a situation where one + // is contained in the other. + + if ( oldLeft < leftCol ) + { + need_refresh[0] = TRUE; + rect[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop, + oldLeft ), + wxGridCellCoords ( oldBottom, + leftCol - 1 ) ); + } + + if ( oldTop < topRow ) + { + need_refresh[1] = TRUE; + rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop, + leftCol ), + wxGridCellCoords ( topRow - 1, + rightCol ) ); + } + + if ( oldRight > rightCol ) + { + need_refresh[2] = TRUE; + rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop, + rightCol + 1 ), + wxGridCellCoords ( oldBottom, + oldRight ) ); + } + + if ( oldBottom > bottomRow ) + { + need_refresh[3] = TRUE; + rect[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow + 1, + leftCol ), + wxGridCellCoords ( oldBottom, + rightCol ) ); + } + + + // Change Selection + m_selectedTopLeft = updateTopLeft; + m_selectedBottomRight = updateBottomRight; + + // various Refresh() calls + for (i = 0; i < 4; i++ ) + if ( need_refresh[i] && rect[i] != wxGridNoCellRect ) + m_gridWin->Refresh( FALSE, &(rect[i]) ); } // only generate an event if the block is not being selected by