]> git.saurik.com Git - wxWidgets.git/commitdiff
Add wxGrid::Render() for drawing the grid to any wxDC.
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 27 May 2012 13:00:19 +0000 (13:00 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 27 May 2012 13:00:19 +0000 (13:00 +0000)
In particular, this allows to print the grid contents easily.

Closes #14294.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@71577 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/changes.txt
include/wx/generic/grid.h
interface/wx/grid.h
samples/grid/griddemo.cpp
samples/grid/griddemo.h
src/generic/grid.cpp

index e917d2384b2d6f6d059a77a3d247091e6d98303a..0b66531330079e036f9adeaaa6dd64e3180a8725 100644 (file)
@@ -526,6 +526,7 @@ All:
 
 All (GUI):
 
+- Add wxGrid::Render() for printing wxGrid (John Roberts).
 - Added strike-through support to wxFont (Igor Korot).
 - Add support for horizontal mouse wheel events to MSW and GTK (Lauri Nurmi).
 - Fix infinite loop in wxHtmlEasyPrinting when trying to page break images
index b360283b9ca47d95dfd81955e96acf6e803dffe8..abdab46ea5aa02996e887b411140f65b8079e685 100644 (file)
@@ -65,6 +65,20 @@ enum wxGridDirection
     wxGRID_ROW
 };
 
+// Flags used with wxGrid::Render() to select parts of the grid to draw.
+enum wxGridRenderStyle
+{
+    wxGRID_DRAW_ROWS_HEADER = 0x001,
+    wxGRID_DRAW_COLS_HEADER = 0x002,
+    wxGRID_DRAW_CELL_LINES = 0x004,
+    wxGRID_DRAW_BOX_RECT = 0x008,
+    wxGRID_DRAW_SELECTION = 0x010,
+    wxGRID_DRAW_DEFAULT = wxGRID_DRAW_ROWS_HEADER |
+                          wxGRID_DRAW_COLS_HEADER |
+                          wxGRID_DRAW_CELL_LINES |
+                          wxGRID_DRAW_BOX_RECT
+};
+
 // ----------------------------------------------------------------------------
 // forward declarations
 // ----------------------------------------------------------------------------
@@ -1030,6 +1044,14 @@ public:
                             int verticalAlignment = wxALIGN_TOP,
                             int textOrientation = wxHORIZONTAL ) const;
 
+    // ------ grid render function for printing
+    //
+    void Render( wxDC& dc,
+                 const wxPoint& pos = wxDefaultPosition,
+                 const wxSize& size = wxDefaultSize,
+                 const wxGridCellCoords& topLeft = wxGridCellCoords(-1, -1),
+                 const wxGridCellCoords& bottomRight = wxGridCellCoords(-1, -1),
+                 int style = wxGRID_DRAW_DEFAULT );
 
     // Split a string containing newline characters into an array of
     // strings and return the number of lines
@@ -2253,6 +2275,10 @@ private:
     bool DoCanResizeLine(int line, const wxGridFixedIndicesSet *setFixed) const;
 
 
+    // Helper of Render(): set the scale to draw the cells at the right size.
+    void SetRenderScale( wxDC& dc, const wxPoint& pos, const wxSize& size,
+                         int gridWidth, int gridHeight );
+
 
     // these sets contain the indices of fixed, i.e. non-resizable
     // interactively, grid rows or columns and are NULL if there are no fixed
index 0f3076dbf47109aa171ff1f8730404179bb7c683..b69576f0b8955d86773c341d554bf9358ffe0ff2 100644 (file)
@@ -1850,6 +1850,50 @@ public:
         CellSpan_Main
     };
 
+    /**
+        Rendering styles supported by wxGrid::Render() method.
+
+        @since 2.9.4
+     */
+    enum wxGridRenderStyle
+    {
+        /// Draw grid row header labels.
+        wxGRID_DRAW_ROWS_HEADER = 0x001,
+
+        /// Draw grid column header labels.
+        wxGRID_DRAW_COLS_HEADER = 0x002,
+
+        /// Draw grid cell border lines.
+        wxGRID_DRAW_CELL_LINES = 0x004,
+
+        /**
+            Draw a bounding rectangle around the rendered cell area.
+
+            Useful where row or column headers are not drawn or where there is
+            multi row or column cell clipping and therefore no cell border at
+            the rendered outer boundary.
+        */
+        wxGRID_DRAW_BOX_RECT = 0x008,
+
+        /**
+            Draw the grid cell selection highlight if a selection is present.
+
+            At present the highlight colour drawn depends on whether the grid
+            window loses focus before drawing begins.
+        */
+        wxGRID_DRAW_SELECTION = 0x010,
+
+        /**
+            The default render style.
+
+            Includes all except wxGRID_DRAW_SELECTION.
+         */
+        wxGRID_DRAW_DEFAULT = wxGRID_DRAW_ROWS_HEADER |
+                              wxGRID_DRAW_COLS_HEADER |
+                              wxGRID_DRAW_CELL_LINES |
+                              wxGRID_DRAW_BOX_RECT
+    };
+
     /**
         @name Constructors and Initialization
      */
@@ -4002,6 +4046,39 @@ public:
      */
     void RefreshAttr(int row, int col);
 
+    /**
+        Draws part or all of a wxGrid on a wxDC for printing or display.
+
+        Pagination can be accomplished by using sequential Render() calls
+        with appropriate values in wxGridCellCoords topLeft and bottomRight.
+
+        @param dc
+            The wxDC to be drawn on.
+        @param pos
+            The position on the wxDC where rendering should begin. If not
+            specified drawing will begin at the wxDC MaxX() and MaxY().
+        @param size
+            The size of the area on the wxDC that the rendered wxGrid should
+            occupy. If not specified the drawing will be scaled to fit the
+            available dc width or height. The wxGrid's aspect ratio is
+            maintained whether or not size is specified.
+        @param topLeft
+            The top left cell of the block to be drawn. Defaults to ( 0, 0 ).
+        @param bottomRight
+            The bottom right cell of the block to be drawn. Defaults to row and
+            column counts.
+        @param style
+            A combination of values from wxGridRenderStyle.
+
+        @since 2.9.4
+     */
+    void Render( wxDC& dc,
+                 const wxPoint& pos = wxDefaultPosition,
+                 const wxSize& size = wxDefaultSize,
+                 const wxGridCellCoords& topLeft = wxGridCellCoords( -1, -1 ),
+                 const wxGridCellCoords& bottomRight = wxGridCellCoords( -1, -1 ),
+                 int style = wxGRID_DRAW_DEFAULT );
+
     /**
         Sets the cell attributes for all cells in the specified column.
 
index bc30fd739d39aff7358162c547913cbf7c6958eb..c331a34845751f7ba2faee46e6ea2aa01eb34a4c 100644 (file)
@@ -212,6 +212,9 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame )
     EVT_MENU( ID_SET_HIGHLIGHT_WIDTH, GridFrame::OnSetHighlightWidth)
     EVT_MENU( ID_SET_RO_HIGHLIGHT_WIDTH, GridFrame::OnSetROHighlightWidth)
 
+    EVT_MENU( wxID_PRINT, GridFrame::OnGridRender )
+    EVT_MENU( ID_RENDER_COORDS, GridFrame::OnGridRender )
+
     EVT_GRID_LABEL_LEFT_CLICK( GridFrame::OnLabelLeftClick )
     EVT_GRID_CELL_LEFT_CLICK( GridFrame::OnCellLeftClick )
     EVT_GRID_ROW_SIZE( GridFrame::OnRowSize )
@@ -238,6 +241,38 @@ GridFrame::GridFrame()
     fileMenu->Append( ID_VTABLE, wxT("&Virtual table test\tCtrl-V"));
     fileMenu->Append( ID_BUGS_TABLE, wxT("&Bugs table test\tCtrl-B"));
     fileMenu->Append( ID_TABULAR_TABLE, wxT("&Tabular table test\tCtrl-T"));
+    fileMenu->AppendSeparator();
+
+    wxMenu* setupMenu = new wxMenu;
+    wxMenuItem* item;
+    item = setupMenu->AppendCheckItem( ID_RENDER_ROW_LABEL,
+                                       "Render row labels" );
+    item->Check();
+    item = setupMenu->AppendCheckItem( ID_RENDER_COL_LABEL,
+                                       "Render column labels" );
+    item->Check();
+    item = setupMenu->AppendCheckItem( ID_RENDER_GRID_LINES,
+                                       "Render grid cell lines" );
+    item->Check();
+    item = setupMenu->AppendCheckItem( ID_RENDER_GRID_BORDER,
+                                       "Render border" );
+    item->Check();
+    item = setupMenu->AppendCheckItem( ID_RENDER_SELECT_HLIGHT,
+                                       "Render selection highlight" );
+    setupMenu->AppendSeparator();
+    setupMenu->AppendCheckItem( ID_RENDER_LOMETRIC,
+                                       "Use LOMETRIC mapping mode" );
+    setupMenu->AppendCheckItem( ID_RENDER_DEFAULT_SIZE,
+                                       "Use wxDefaultSize" );
+    setupMenu->AppendCheckItem( ID_RENDER_MARGIN,
+                                "Logical 50 unit margin" );
+    setupMenu->AppendCheckItem( ID_RENDER_ZOOM,
+                                "Zoom 125%" );
+
+    fileMenu->AppendSubMenu( setupMenu, "Render setup" );
+    fileMenu->Append( wxID_PRINT, "Render" );
+    fileMenu->Append( ID_RENDER_COORDS, "Render G5:P30" );
+
     fileMenu->AppendSeparator();
     fileMenu->Append( wxID_EXIT, wxT("E&xit\tAlt-X") );
 
@@ -2068,3 +2103,158 @@ void GridFrame::OnTabularTable(wxCommandEvent&)
 {
     new TabularGridFrame;
 }
+
+// Example using wxGrid::Render
+// Displays a preset selection or, if it exists, a selection block
+// Draws the selection to a wxBitmap and displays the bitmap
+void GridFrame::OnGridRender( wxCommandEvent& event )
+{
+    int styleRender = 0, i;
+    bool useLometric = false, defSize = false;
+    double zoom = 1;
+    wxSize sizeMargin( 0, 0 );
+    wxPoint pointOrigin( 0, 0 );
+
+    wxMenu* menu = GetMenuBar()->GetMenu( 0 );
+    wxMenuItem* menuItem = menu->FindItem( ID_RENDER_ROW_LABEL );
+    menu = menuItem->GetMenu();
+
+    if ( menu->FindItem( ID_RENDER_ROW_LABEL )->IsChecked() )
+        styleRender |= wxGRID_DRAW_ROWS_HEADER;
+    if ( menu->FindItem( ID_RENDER_COL_LABEL )->IsChecked() )
+        styleRender |= wxGRID_DRAW_COLS_HEADER;
+    if ( menu->FindItem( ID_RENDER_GRID_LINES )->IsChecked() )
+        styleRender |= wxGRID_DRAW_CELL_LINES;
+    if ( menu->FindItem( ID_RENDER_GRID_BORDER )->IsChecked() )
+        styleRender |= wxGRID_DRAW_BOX_RECT;
+    if ( menu->FindItem( ID_RENDER_SELECT_HLIGHT )->IsChecked() )
+        styleRender |= wxGRID_DRAW_SELECTION;
+    if ( menu->FindItem( ID_RENDER_LOMETRIC )->IsChecked() )
+        useLometric = true;
+    if ( menu->FindItem( ID_RENDER_MARGIN )->IsChecked() )
+    {
+        pointOrigin.x += 50;
+        pointOrigin.y += 50;
+        sizeMargin.IncBy( 50 );
+    }
+    if ( menu->FindItem( ID_RENDER_ZOOM )->IsChecked() )
+        zoom = 1.25;
+    if ( menu->FindItem( ID_RENDER_DEFAULT_SIZE )->IsChecked() )
+        defSize = true;
+
+    // init render area coords with a default row and col selection
+    wxGridCellCoords topLeft( 0, 0 ), bottomRight( 8, 6 );
+    // check whether we are printing a block selection
+    // other selection types not catered for here
+    if ( event.GetId() == ID_RENDER_COORDS )
+    {
+        topLeft.SetCol( 6 );
+        topLeft.SetRow( 4 );
+        bottomRight.SetCol( 15 );
+        bottomRight.SetRow( 29 );
+    }
+    else if ( grid->IsSelection() && grid->GetSelectionBlockTopLeft().Count() )
+    {
+        wxGridCellCoordsArray cells = grid->GetSelectionBlockTopLeft();
+        if ( grid->GetSelectionBlockBottomRight().Count() )
+        {
+            cells.Add( grid->GetSelectionBlockBottomRight()[ 0 ] );
+            topLeft.Set( cells[ 0 ].GetRow(),
+                            cells[ 0 ].GetCol() );
+            bottomRight.Set( cells[ 1 ].GetRow(),
+                                cells[ 1 ].GetCol() );
+        }
+    }
+
+    // sum col widths
+    wxSize sizeRender( 0, 0 );
+    wxGridSizesInfo sizeinfo = grid->GetColSizes();
+    for ( i = topLeft.GetCol(); i <= bottomRight.GetCol(); i++ )
+    {
+        sizeRender.x += sizeinfo.GetSize( i );
+    }
+
+    // sum row heights
+    sizeinfo = grid->GetRowSizes();
+    for ( i = topLeft.GetRow(); i <= bottomRight.GetRow(); i++ )
+    {
+        sizeRender.y += sizeinfo.GetSize( i );
+    }
+
+    if ( styleRender & wxGRID_DRAW_ROWS_HEADER )
+        sizeRender.x += grid->GetRowLabelSize();
+    if ( styleRender & wxGRID_DRAW_COLS_HEADER )
+        sizeRender.y += grid->GetColLabelSize();
+
+    sizeRender.x *= zoom;
+    sizeRender.y *= zoom;
+
+    // delete any existing render frame and create new one
+    wxWindow* win = FindWindow( "frameRender" );
+    if ( win )
+        win->Destroy();
+
+    wxFrame* frame = new wxFrame( this, wxID_ANY, "Grid Render" );
+    frame->SetClientSize( 780, 400 );
+    frame->SetName( "frameRender" );
+
+    wxPanel* canvas = new wxPanel( frame, wxID_ANY );
+
+    // make bitmap large enough for margins if any
+    if ( !defSize )
+        sizeRender.IncBy( sizeMargin * 2 );
+    else
+        sizeRender.IncBy( sizeMargin );
+
+    wxBitmap bmp( sizeRender );
+    // don't leave it larger or drawing will be scaled
+    sizeRender.DecBy( sizeMargin * 2 );
+
+    wxMemoryDC memDc(bmp);
+
+    // default row labels have no background colour so set background
+    memDc.SetBackground( wxBrush( canvas->GetBackgroundColour() ) );
+    memDc.Clear();
+
+    // convert sizeRender to mapping mode units if necessary
+    if ( useLometric )
+    {
+        memDc.SetMapMode( wxMM_LOMETRIC );
+        wxSize sizePPI = memDc.GetPPI();
+        sizeRender.x = memDc.DeviceToLogicalXRel( sizeRender.x );
+        sizeRender.y = memDc.DeviceToLogicalYRel( sizeRender.y );
+    }
+
+    // pass wxDefaultSize if menu item is checked
+    if ( defSize )
+        sizeRender = wxDefaultSize;
+
+    grid->Render( memDc,
+                  pointOrigin,
+                  sizeRender,
+                  topLeft, bottomRight,
+                  wxGridRenderStyle( styleRender ) );
+
+    m_gridBitmap = bmp;
+
+    canvas->Bind( wxEVT_PAINT, &GridFrame::OnRenderPaint, this );
+
+    frame->Show();
+}
+
+void GridFrame::OnRenderPaint( wxPaintEvent& event )
+{
+    wxPanel* canvas = ( wxPanel* )event.GetEventObject();
+    wxPaintDC dc( canvas );
+    canvas->PrepareDC( dc );
+
+    if ( !m_gridBitmap.IsOk() )
+        return;;
+
+    wxMemoryDC memDc( m_gridBitmap );
+
+    dc.Blit( 0, 0,
+             m_gridBitmap.GetWidth(),
+             m_gridBitmap.GetHeight(),
+             &memDc, 0, 0 );
+}
index 15e8b882237a6c2c8cb1e9639137a1cf1aa28759..401553a2ba081a2ffbf06c78a72367cd5967489b 100644 (file)
@@ -111,6 +111,8 @@ public:
     void OnVTable( wxCommandEvent& );
     void OnBugsTable( wxCommandEvent& );
     void OnTabularTable( wxCommandEvent& );
+    void OnGridRender( wxCommandEvent& event );
+    void OnRenderPaint( wxPaintEvent& event );
 
     enum
     {
@@ -174,7 +176,18 @@ public:
         ID_SET_HIGHLIGHT_WIDTH,
         ID_SET_RO_HIGHLIGHT_WIDTH,
 
-        ID_TESTFUNC
+        ID_TESTFUNC,
+
+        ID_RENDER_ROW_LABEL,
+        ID_RENDER_COL_LABEL,
+        ID_RENDER_GRID_LINES,
+        ID_RENDER_GRID_BORDER,
+        ID_RENDER_SELECT_HLIGHT,
+        ID_RENDER_LOMETRIC,
+        ID_RENDER_COORDS,
+        ID_RENDER_ZOOM,
+        ID_RENDER_MARGIN,
+        ID_RENDER_DEFAULT_SIZE,
     };
 
 #if wxUSE_LOG
@@ -184,6 +197,8 @@ public:
     // add the cells to selection when using commands from select menu?
     bool m_addToSel;
 
+    wxBitmap m_gridBitmap;
+
     DECLARE_EVENT_TABLE()
 };
 
index 85edc0dbf42b60abd3506352f6a70463a6a2c3df..fc83204fb759f64b6ee9c0a00e6674f665b50c92 100644 (file)
@@ -1776,6 +1776,267 @@ void wxGridWindow::OnPaint( wxPaintEvent &WXUNUSED(event) )
     m_owner->DrawHighlight( dc, dirtyCells );
 }
 
+void wxGrid::Render( wxDC& dc,
+                     const wxPoint& position,
+                     const wxSize& size,
+                     const wxGridCellCoords& topLeft,
+                     const wxGridCellCoords& bottomRight,
+                     int style )
+{
+    wxCHECK_RET( bottomRight.GetCol() < GetNumberCols(),
+                 "Invalid right column" );
+    wxCHECK_RET( bottomRight.GetRow() < GetNumberRows(),
+                 "Invalid bottom row" );
+
+    // store user settings and reset later
+
+    // remove grid selection, don't paint selection colour
+    // unless we have wxGRID_DRAW_SELECTION
+    // block selections are the only ones catered for here
+    wxGridCellCoordsArray selectedCells;
+    bool hasSelection = IsSelection();
+    if ( hasSelection && !( style & wxGRID_DRAW_SELECTION ) )
+    {
+        selectedCells = GetSelectionBlockTopLeft();
+        // non block selections may not have a bottom right
+        if ( GetSelectionBlockBottomRight().size() )
+            selectedCells.Add( GetSelectionBlockBottomRight()[ 0 ] );
+
+        ClearSelection();
+    }
+
+    // store user device origin
+    wxCoord userOriginX, userOriginY;
+    dc.GetDeviceOrigin( &userOriginX, &userOriginY );
+
+    // store user scale
+    double scaleUserX, scaleUserY;
+    dc.GetUserScale( &scaleUserX, &scaleUserY );
+
+    // set defaults if necessary
+    long colLeft = topLeft.GetCol() > -1 ? topLeft.GetCol() : 0;
+    long rowTop = topLeft.GetRow() > -1 ? topLeft.GetRow() : 0;
+    long colRight = bottomRight.GetCol() > -1 ? bottomRight.GetCol()
+                                              : GetNumberCols() - 1;
+    long rowBottom = bottomRight.GetRow() > -1 ? bottomRight.GetRow()
+                                               : GetNumberRows() - 1;
+
+    // get grid area size to be rendered
+    long offsetCols = 0, offsetRows = 0;
+    wxGridCellCoordsArray renderCells;
+    wxArrayInt arrayCols;
+    wxArrayInt arrayRows;
+    int col, row, gridWidth, gridHeight;
+
+    // fill array with cells to be rendered
+    // calculate width of cell drawn area
+    // and get grid column offset used where startcol > 0
+    gridWidth = 0;
+    wxGridSizesInfo sizeinfo = GetColSizes();
+    for ( col = 0; col <= colRight; col++ )
+    {
+        if ( col < colLeft )
+        {
+            offsetCols += sizeinfo.GetSize( col );
+        }
+        else
+        {
+            for ( row = rowTop; row <= rowBottom; row++ )
+            {
+                renderCells.Add( wxGridCellCoords( row, col ));
+                arrayRows.Add( row ); // column labels rendered in DrawColLabels
+            }
+            arrayCols.Add( col ); // row labels rendered in DrawRowLabels
+            gridWidth += sizeinfo.GetSize( col );
+        }
+    }
+
+    // calculate height of rendered cells
+    // and row Y offset where startrow > 0
+    gridHeight = 0;
+    sizeinfo = GetRowSizes();
+    for ( row = 0; row <= rowBottom; row++ )
+    {
+        if ( row < rowTop )
+            offsetRows += sizeinfo.GetSize( row );
+        else
+            gridHeight += sizeinfo.GetSize( row );
+    }
+
+    // add headers/labels to dimensions
+    if ( style & wxGRID_DRAW_ROWS_HEADER )
+        gridWidth += GetRowLabelSize();
+    if ( style & wxGRID_DRAW_COLS_HEADER )
+        gridHeight += GetColLabelSize();
+
+    // set drawing start position DeviceOrigin
+    // if not specified use previous dc draw extents MaxX and MaxY
+    wxPoint positionRender = position;
+    if ( !positionRender.IsFullySpecified() )
+    {
+        if ( positionRender.x == wxDefaultPosition.x )
+            positionRender.x = dc.MaxX();
+
+        if ( positionRender.y == wxDefaultPosition.y )
+            positionRender.y = dc.MaxY();
+    }
+
+    // positionRender should be in logical units
+    wxCoord originX = dc.LogicalToDeviceX( positionRender.x );
+    wxCoord originY = dc.LogicalToDeviceY( positionRender.y );
+
+    dc.SetDeviceOrigin( originX, originY );
+
+    SetRenderScale( dc, positionRender, size, gridWidth, gridHeight );
+
+    // draw row headers at specified origin
+    if ( GetRowLabelSize() > 0 && ( style & wxGRID_DRAW_ROWS_HEADER ) )
+    {
+        if ( style & wxGRID_DRAW_COLS_HEADER )
+        {
+            DrawCornerLabel( dc ); // do only if both col and row labels drawn
+            originY += dc.LogicalToDeviceYRel( GetColLabelSize() );
+        }
+
+        originY -= dc.LogicalToDeviceYRel( offsetRows );
+        dc.SetDeviceOrigin( originX, originY );
+
+        DrawRowLabels( dc, arrayRows );
+
+        // reset for columns
+        if ( style & wxGRID_DRAW_COLS_HEADER )
+            originY -= dc.LogicalToDeviceYRel( GetColLabelSize() );
+
+        originY += dc.LogicalToDeviceYRel( offsetRows );
+        // X offset so we don't overwrite row labels
+        originX += dc.LogicalToDeviceXRel( GetRowLabelSize() );
+    }
+
+    // subtract col offset where startcol > 0
+    originX -= dc.LogicalToDeviceXRel( offsetCols );
+    // no y offset for col labels, they are at the Y origin
+
+    // draw column labels
+    if ( style & wxGRID_DRAW_COLS_HEADER )
+    {
+        dc.SetDeviceOrigin( originX, originY );
+        DrawColLabels( dc, arrayCols );
+        // don't overwrite the labels, increment originY
+        originY += dc.LogicalToDeviceYRel( GetColLabelSize() );
+    }
+
+    // set device origin to draw grid cells and lines
+    originY -= dc.LogicalToDeviceYRel( offsetRows );
+    dc.SetDeviceOrigin( originX, originY );
+
+    // draw cell area background
+    dc.SetBrush( GetDefaultCellBackgroundColour() );
+    dc.SetPen( *wxTRANSPARENT_PEN );
+    // subtract headers from grid area dimensions
+    unsigned cellsWidth = gridWidth, cellsHeight = gridHeight;
+    if ( style & wxGRID_DRAW_ROWS_HEADER )
+        cellsWidth -= GetRowLabelSize();
+    if ( style & wxGRID_DRAW_COLS_HEADER )
+        cellsHeight -= GetColLabelSize();
+
+    dc.DrawRectangle( wxPoint( offsetCols, offsetRows ),
+                      wxSize( cellsWidth, cellsHeight ) );
+
+    // draw cells
+    DrawGridCellArea( dc, renderCells );
+
+    // calculate region for drawing grid lines
+    if ( style & wxGRID_DRAW_CELL_LINES )
+    {
+        wxRegion regionClip( offsetCols,
+                             offsetRows,
+                             cellsWidth,
+                             cellsHeight );
+
+        DrawRangeGridLines(dc, regionClip, renderCells[0], renderCells.Last());
+    }
+
+    // draw render rectangle bounding lines
+    // useful where there is multi cell row or col clipping and no cell border
+    if ( style & wxGRID_DRAW_BOX_RECT )
+    {
+        int bottom = offsetRows + cellsHeight,
+            right = offsetCols + cellsWidth - 1;
+
+        // horiz top line if we are not drawing column header/labels
+        if ( !( style & wxGRID_DRAW_COLS_HEADER ) )
+        {
+            int left =  offsetCols;
+            left +=  ( style & wxGRID_DRAW_COLS_HEADER )
+                      ? - GetRowLabelSize() : 0;
+            dc.SetPen( GetRowGridLinePen( rowTop ) );
+            dc.DrawLine( left,
+                         offsetRows,
+                         right,
+                         offsetRows );
+        }
+
+        // horiz bottom line
+        dc.SetPen( GetRowGridLinePen( rowBottom ) );
+        dc.DrawLine( offsetCols, bottom - 1, right, bottom - 1 );
+
+        // left vertical line if we are not drawing row header/labels
+        if ( !( style & wxGRID_DRAW_ROWS_HEADER ) )
+        {
+            int top =  offsetRows;
+            top +=  ( style & wxGRID_DRAW_COLS_HEADER )
+                      ? - GetColLabelSize() : 0;
+            dc.SetPen( GetColGridLinePen( colLeft ) );
+            dc.DrawLine( offsetCols -1,
+                         top,
+                         offsetCols - 1,
+                         bottom - 1 );
+        }
+
+        // right vertical line
+        dc.SetPen( GetColGridLinePen( colRight ) );
+        dc.DrawLine( right, offsetRows, right, bottom - 1 );
+    }
+
+    // restore user setings
+    dc.SetDeviceOrigin( userOriginX, userOriginY );
+    dc.SetUserScale( scaleUserX, scaleUserY );
+
+    if ( selectedCells.size() && !( style & wxGRID_DRAW_SELECTION ) )
+    {
+        SelectBlock( selectedCells[ 0 ].GetRow(),
+                     selectedCells[ 0 ].GetCol(),
+                     selectedCells[ selectedCells.size() -1 ].GetRow(),
+                     selectedCells[ selectedCells.size() -1 ].GetCol() );
+    }
+}
+
+void
+wxGrid::SetRenderScale(wxDC& dc,
+                       const wxPoint& pos, const wxSize& size,
+                       int gridWidth, int gridHeight)
+{
+    double scaleX, scaleY;
+    wxSize sizeTemp;
+
+    if ( size.GetX() != wxDefaultSize.GetX() ) // size.x was specified
+        sizeTemp.SetWidth( size.GetX() );
+    else
+        sizeTemp.SetWidth( dc.DeviceToLogicalXRel( dc.GetSize().GetX() )
+                           - pos.x );
+
+    if ( size.GetY() != wxDefaultSize.GetY() ) // size.y was specified
+        sizeTemp.SetHeight( size.GetY() );
+    else
+        sizeTemp.SetHeight( dc.DeviceToLogicalYRel( dc.GetSize().GetY() )
+                            - pos.y );
+
+    scaleX = (double)( (double) sizeTemp.GetX() / (double) gridWidth );
+    scaleY = (double)( (double) sizeTemp.GetY() / (double) gridHeight );
+
+    dc.SetUserScale( wxMin( scaleX, scaleY), wxMin( scaleX, scaleY ) );
+}
+
 void wxGridWindow::ScrollWindow( int dx, int dy, const wxRect *rect )
 {
     wxWindow::ScrollWindow( dx, dy, rect );