+ // 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];
+ need_refresh[0] =
+ need_refresh[1] =
+ need_refresh[2] =
+ need_refresh[3] = FALSE;
+ int i;
+
+ // Store intermediate values
+ wxCoord oldLeft = m_selectingTopLeft.GetCol();
+ wxCoord oldTop = m_selectingTopLeft.GetRow();
+ wxCoord oldRight = m_selectingBottomRight.GetCol();
+ wxCoord oldBottom = m_selectingBottomRight.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 )
+ {
+ // Refresh the newly selected or deselected
+ // area to the left of the old or new selection.
+ need_refresh[0] = TRUE;
+ rect[0] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
+ oldLeft ),
+ wxGridCellCoords ( oldBottom,
+ leftCol - 1 ) );
+ }
+
+ if ( oldTop < topRow )
+ {
+ // Refresh the newly selected or deselected
+ // area above the old or new selection.
+ need_refresh[1] = TRUE;
+ rect[1] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
+ leftCol ),
+ wxGridCellCoords ( topRow - 1,
+ rightCol ) );
+ }
+
+ if ( oldRight > rightCol )
+ {
+ // Refresh the newly selected or deselected
+ // area to the right of the old or new selection.
+ need_refresh[2] = TRUE;
+ rect[2] = BlockToDeviceRect( wxGridCellCoords ( oldTop,
+ rightCol + 1 ),
+ wxGridCellCoords ( oldBottom,
+ oldRight ) );
+ }
+
+ if ( oldBottom > bottomRow )
+ {
+ // Refresh the newly selected or deselected
+ // area below the old or new selection.
+ need_refresh[3] = TRUE;
+ rect[3] = BlockToDeviceRect( wxGridCellCoords ( bottomRow + 1,
+ leftCol ),
+ wxGridCellCoords ( oldBottom,
+ rightCol ) );
+ }
+
+ // various Refresh() calls
+ for (i = 0; i < 4; i++ )
+ if ( need_refresh[i] && rect[i] != wxGridNoCellRect )
+ m_gridWin->Refresh( FALSE, &(rect[i]) );
+ }
+ // Change Selection
+ m_selectingTopLeft = updateTopLeft;
+ m_selectingBottomRight = updateBottomRight;
+}
+
+//
+// ------ functions to get/send data (see also public functions)
+//
+
+bool wxGrid::GetModelValues()
+{
+ // Hide the editor, so it won't hide a changed value.
+ HideCellEditControl();
+
+ if ( m_table )
+ {
+ // all we need to do is repaint the grid
+ //
+ m_gridWin->Refresh();
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+bool wxGrid::SetModelValues()
+{
+ int row, col;
+
+ // Disable the editor, so it won't hide a changed value.
+ // Do we also want to save the current value of the editor first?
+ // I think so ...
+ DisableCellEditControl();
+
+ if ( m_table )
+ {
+ for ( row = 0; row < m_numRows; row++ )
+ {
+ for ( col = 0; col < m_numCols; col++ )
+ {
+ m_table->SetValue( row, col, GetCellValue(row, col) );
+ }
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+
+// Note - this function only draws cells that are in the list of
+// exposed cells (usually set from the update region by
+// CalcExposedCells)
+//
+void wxGrid::DrawGridCellArea( wxDC& dc, const wxGridCellCoordsArray& cells )
+{
+ if ( !m_numRows || !m_numCols ) return;
+
+ int i, numCells = cells.GetCount();
+ int row, col, cell_rows, cell_cols;
+ wxGridCellCoordsArray redrawCells;
+
+ for ( i = numCells-1; i >= 0; i-- )
+ {
+ row = cells[i].GetRow();
+ col = cells[i].GetCol();
+ GetCellSize( row, col, &cell_rows, &cell_cols );
+
+ // If this cell is part of a multicell block, find owner for repaint
+ if ( cell_rows <= 0 || cell_cols <= 0 )
+ {
+ wxGridCellCoords cell(row+cell_rows, col+cell_cols);
+ bool marked = FALSE;
+ for ( int j = 0; j < numCells; j++ )
+ {
+ if ( cell == cells[j] )
+ {
+ marked = TRUE;
+ break;
+ }
+ }
+ if (!marked)
+ {
+ int count = redrawCells.GetCount();
+ for (int j = 0; j < count; j++)
+ {
+ if ( cell == redrawCells[j] )
+ {
+ marked = TRUE;
+ break;
+ }
+ }
+ if (!marked) redrawCells.Add( cell );
+ }
+ continue; // don't bother drawing this cell
+ }
+
+ // If this cell is empty, find cell to left that might want to overflow
+ if (m_table && m_table->IsEmptyCell(row, col))
+ {
+ for ( int l = 0; l < cell_rows; l++ )
+ {
+ // find a cell in this row to left alreay marked for repaint
+ int left = col;
+ for (int k = 0; k < int(redrawCells.GetCount()); k++)
+ if ((redrawCells[k].GetCol() < left) &&
+ (redrawCells[k].GetRow() == row))
+ left=redrawCells[k].GetCol();
+
+ if (left == col) left = 0; // oh well
+
+ for (int j = col-1; j >= left; j--)
+ {
+ if (!m_table->IsEmptyCell(row+l, j))
+ {
+ if (GetCellOverflow(row+l, j))
+ {
+ wxGridCellCoords cell(row+l, j);
+ bool marked = FALSE;
+
+ for (int k = 0; k < numCells; k++)
+ {
+ if ( cell == cells[k] )
+ {
+ marked = TRUE;
+ break;
+ }
+ }
+ if (!marked)
+ {
+ int count = redrawCells.GetCount();
+ for (int k = 0; k < count; k++)
+ {
+ if ( cell == redrawCells[k] )
+ {
+ marked = TRUE;
+ break;
+ }
+ }
+ if (!marked) redrawCells.Add( cell );
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+ DrawCell( dc, cells[i] );
+ }
+
+ numCells = redrawCells.GetCount();
+
+ for ( i = numCells - 1; i >= 0; i-- )
+ {
+ DrawCell( dc, redrawCells[i] );
+ }
+}
+
+
+void wxGrid::DrawGridSpace( wxDC& dc )
+{
+ int cw, ch;
+ m_gridWin->GetClientSize( &cw, &ch );
+
+ int right, bottom;
+ CalcUnscrolledPosition( cw, ch, &right, &bottom );
+
+ int rightCol = m_numCols > 0 ? GetColRight(m_numCols - 1) : 0;
+ int bottomRow = m_numRows > 0 ? GetRowBottom(m_numRows - 1) : 0 ;
+
+ if ( right > rightCol || bottom > bottomRow )
+ {
+ int left, top;
+ CalcUnscrolledPosition( 0, 0, &left, &top );
+
+ dc.SetBrush( wxBrush(GetDefaultCellBackgroundColour(), wxSOLID) );
+ dc.SetPen( *wxTRANSPARENT_PEN );
+
+ if ( right > rightCol )
+ {
+ dc.DrawRectangle( rightCol, top, right - rightCol, ch);
+ }
+
+ if ( bottom > bottomRow )
+ {
+ dc.DrawRectangle( left, bottomRow, cw, bottom - bottomRow);
+ }
+ }
+}
+
+
+void wxGrid::DrawCell( wxDC& dc, const wxGridCellCoords& coords )
+{
+ int row = coords.GetRow();
+ int col = coords.GetCol();
+
+ if ( GetColWidth(col) <= 0 || GetRowHeight(row) <= 0 )
+ return;
+
+ // we draw the cell border ourselves
+#if !WXGRID_DRAW_LINES
+ if ( m_gridLinesEnabled )
+ DrawCellBorder( dc, coords );
+#endif
+
+ wxGridCellAttr* attr = GetCellAttr(row, col);
+
+ bool isCurrent = coords == m_currentCellCoords;
+
+ wxRect rect = CellToRect( row, col );
+
+ // if the editor is shown, we should use it and not the renderer
+ // Note: However, only if it is really _shown_, i.e. not hidden!
+ if ( isCurrent && IsCellEditControlShown() )
+ {
+ wxGridCellEditor *editor = attr->GetEditor(this, row, col);
+ editor->PaintBackground(rect, attr);
+ editor->DecRef();
+ }
+ else
+ {
+ // but all the rest is drawn by the cell renderer and hence may be
+ // customized
+ wxGridCellRenderer *renderer = attr->GetRenderer(this, row, col);
+ renderer->Draw(*this, *attr, dc, rect, row, col, IsInSelection(coords));