]> git.saurik.com Git - wxWidgets.git/blobdiff - samples/grid/griddemo.cpp
Fix wrong configure test for abi::__forced_unwind in previous commit.
[wxWidgets.git] / samples / grid / griddemo.cpp
index 636d3674961ae53b6403a94aba19e68f6318fade..2b3ba6df6004fa7ac87352f0d3b775d41e177ed5 100644 (file)
@@ -5,7 +5,7 @@
 // Modified by: Santiago Palacios
 // RCS-ID:      $Id$
 // Copyright:   (c) Michael Bedward, Julian Smart, Vadim Zeitlin
-// Licence:     wxWindows license
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
 // ============================================================================
 
 #include "griddemo.h"
 
-#ifndef __WXMSW__
+#ifndef wxHAS_IMAGES_IN_RESOURCES
     #include "../sample.xpm"
 #endif
 
+// Custom renderer that renders column header cells without borders and in
+// italic
+class CustomColumnHeaderRenderer : public wxGridColumnHeaderRenderer
+{
+public:
+    CustomColumnHeaderRenderer(const wxColour& colFg, const wxColour& colBg)
+        : m_colFg(colFg),
+          m_colBg(colBg)
+    {
+    }
+
+    virtual void DrawLabel(const wxGrid& WXUNUSED(grid),
+                           wxDC& dc,
+                           const wxString& value,
+                           const wxRect& rect,
+                           int horizAlign,
+                           int vertAlign,
+                           int WXUNUSED(textOrientation)) const
+    {
+        dc.SetTextForeground(m_colFg);
+        dc.SetFont(wxITALIC_FONT->Bold());
+        dc.DrawLabel(value, rect, horizAlign | vertAlign);
+    }
+
+    virtual void DrawBorder(const wxGrid& WXUNUSED(grid),
+                            wxDC& dc,
+                            wxRect& rect) const
+    {
+        dc.SetPen(*wxTRANSPARENT_PEN);
+        dc.SetBrush(wxBrush(m_colBg));
+        dc.DrawRectangle(rect);
+    }
+
+private:
+    const wxColour m_colFg, m_colBg;
+
+    wxDECLARE_NO_COPY_CLASS(CustomColumnHeaderRenderer);
+};
+
+// And a custom attributes provider which uses custom column header renderer
+// defined above
+class CustomColumnHeadersProvider : public wxGridCellAttrProvider
+{
+public:
+    // by default custom column renderer is not used, call
+    // UseCustomColHeaders() to enable it
+    CustomColumnHeadersProvider()
+        : m_customOddRenderer(*wxYELLOW, *wxBLUE),
+          m_customEvenRenderer(*wxWHITE, *wxBLACK),
+          m_useCustom(false)
+    {
+    }
+
+    // enable or disable the use of custom renderer for column headers
+    void UseCustomColHeaders(bool use = true) { m_useCustom = use; }
+
+protected:
+    virtual const wxGridColumnHeaderRenderer& GetColumnHeaderRenderer(int col)
+    {
+        // if enabled, use custom renderers
+        if ( m_useCustom )
+        {
+            // and use different ones for odd and even columns -- just to show
+            // that we can
+            return col % 2 ? m_customOddRenderer : m_customEvenRenderer;
+        }
+
+        return wxGridCellAttrProvider::GetColumnHeaderRenderer(col);
+    }
+
+private:
+    CustomColumnHeaderRenderer m_customOddRenderer,
+                               m_customEvenRenderer;
+
+    bool m_useCustom;
+
+    wxDECLARE_NO_COPY_CLASS(CustomColumnHeadersProvider);
+};
+
 // ----------------------------------------------------------------------------
 // wxWin macros
 // ----------------------------------------------------------------------------
@@ -78,7 +157,9 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame )
     EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
     EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
     EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
-    EVT_MENU( ID_TOGGLENATIVEHEADER, GridFrame::ToggleNativeHeader )
+    EVT_MENU( ID_COLNATIVEHEADER, GridFrame::SetNativeColHeader )
+    EVT_MENU( ID_COLDEFAULTHEADER, GridFrame::SetDefaultColHeader )
+    EVT_MENU( ID_COLCUSTOMHEADER, GridFrame::SetCustomColHeader )
     EVT_MENU( ID_TOGGLEGRIDLINES, GridFrame::ToggleGridLines )
     EVT_MENU( ID_AUTOSIZECOLS, GridFrame::AutoSizeCols )
     EVT_MENU( ID_CELLOVERFLOW, GridFrame::CellOverflow )
@@ -119,7 +200,6 @@ BEGIN_EVENT_TABLE( GridFrame, wxFrame )
     EVT_MENU( ID_SELECT_ROW, GridFrame::SelectRow)
     EVT_MENU( ID_SELECT_ALL, GridFrame::SelectAll)
     EVT_MENU( ID_SELECT_UNSELECT, GridFrame::OnAddToSelectToggle)
-    EVT_MENU( ID_SHOW_SELECTION, GridFrame::OnShowSelection)
 
     EVT_MENU( ID_SIZE_ROW, GridFrame::AutoSizeRow )
     EVT_MENU( ID_SIZE_COL, GridFrame::AutoSizeCol )
@@ -132,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 )
@@ -158,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") );
 
@@ -170,7 +285,6 @@ GridFrame::GridFrame()
     viewMenu->AppendCheckItem(ID_TOGGLECOLMOVING, "Col drag-&move");
     viewMenu->AppendCheckItem(ID_TOGGLEGRIDSIZING, "&Grid drag-resize");
     viewMenu->AppendCheckItem(ID_TOGGLEGRIDDRAGCELL, "&Grid drag-cell");
-    viewMenu->AppendCheckItem(ID_TOGGLENATIVEHEADER, "&Native column headers");
     viewMenu->AppendCheckItem(ID_TOGGLEGRIDLINES, "&Grid Lines");
     viewMenu->AppendCheckItem(ID_SET_HIGHLIGHT_WIDTH, "&Set Cell Highlight Width...");
     viewMenu->AppendCheckItem(ID_SET_RO_HIGHLIGHT_WIDTH, "&Set Cell RO Highlight Width...");
@@ -184,8 +298,8 @@ GridFrame::GridFrame()
                       rowLabelMenu,
                       wxT("Change alignment of row labels") );
 
-    rowLabelMenu->Append( ID_ROWLABELHORIZALIGN, wxT("&Horizontal") );
-    rowLabelMenu->Append( ID_ROWLABELVERTALIGN, wxT("&Vertical") );
+    rowLabelMenu->AppendRadioItem( ID_ROWLABELHORIZALIGN, wxT("&Horizontal") );
+    rowLabelMenu->AppendRadioItem( ID_ROWLABELVERTALIGN, wxT("&Vertical") );
 
     wxMenu *colLabelMenu = new wxMenu;
 
@@ -193,8 +307,19 @@ GridFrame::GridFrame()
                       colLabelMenu,
                       wxT("Change alignment of col labels") );
 
-    colLabelMenu->Append( ID_COLLABELHORIZALIGN, wxT("&Horizontal") );
-    colLabelMenu->Append( ID_COLLABELVERTALIGN, wxT("&Vertical") );
+    colLabelMenu->AppendRadioItem( ID_COLLABELHORIZALIGN, wxT("&Horizontal") );
+    colLabelMenu->AppendRadioItem( ID_COLLABELVERTALIGN, wxT("&Vertical") );
+
+    wxMenu *colHeaderMenu = new wxMenu;
+
+    viewMenu->Append( ID_ROWLABELALIGN, wxT("Col header style"),
+                      colHeaderMenu,
+                      wxT("Change style of col header") );
+
+    colHeaderMenu->AppendRadioItem( ID_COLDEFAULTHEADER, wxT("&Default") );
+    colHeaderMenu->AppendRadioItem( ID_COLNATIVEHEADER, wxT("&Native") );
+    colHeaderMenu->AppendRadioItem( ID_COLCUSTOMHEADER, wxT("&Custom") );
+
 
     wxMenu *colMenu = new wxMenu;
     colMenu->Append( ID_SETLABELCOLOUR, wxT("Set &label colour...") );
@@ -215,8 +340,6 @@ GridFrame::GridFrame()
     selectMenu->Append( ID_SELECT_UNSELECT, wxT("Add new cells to the selection"),
                         wxT("When off, old selection is deselected before ")
                         wxT("selecting the new cells"), wxITEM_CHECK );
-    selectMenu->Append( ID_SHOW_SELECTION,
-                        wxT("&Show current selection\tCtrl-Alt-S"));
     selectMenu->AppendSeparator();
     selectMenu->Append( ID_SELECT_ALL, wxT("Select all"));
     selectMenu->Append( ID_SELECT_ROW, wxT("Select row 2"));
@@ -267,6 +390,7 @@ GridFrame::GridFrame()
                        wxPoint( 0, 0 ),
                        wxSize( 400, 300 ) );
 
+
 #if wxUSE_LOG
     int gridW = 600, gridH = 300;
     int logW = gridW, logH = 100;
@@ -286,6 +410,9 @@ GridFrame::GridFrame()
     // this will create a grid and, by default, an associated grid
     // table for strings
     grid->CreateGrid( 0, 0 );
+
+    grid->GetTable()->SetAttrProvider(new CustomColumnHeadersProvider());
+
     grid->AppendRows(100);
     grid->AppendCols(100);
 
@@ -347,20 +474,33 @@ GridFrame::GridFrame()
     grid->SetCellValue(5, 8, wxT("Bg from row attr\nText col from cell attr"));
     grid->SetCellValue(5, 5, wxT("Bg from row attr Text col from col attr and this text is so long that it covers over many many empty cells but is broken by one that isn't"));
 
+    // Some numeric columns with different formatting.
     grid->SetColFormatFloat(6);
-    grid->SetCellValue(0, 6, wxString::Format(wxT("%g"), 3.1415));
-    grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 1415.0));
-    grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 12345.67890));
+    grid->SetCellValue(0, 6, "Default\nfloat format");
+    grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 3.1415));
+    grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 1415.0));
+    grid->SetCellValue(3, 6, wxString::Format(wxT("%g"), 12345.67890));
 
     grid->SetColFormatFloat(7, 6, 2);
-    grid->SetCellValue(0, 7, wxString::Format(wxT("%g"), 3.1415));
-    grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 1415.0));
-    grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 12345.67890));
-
-    grid->SetColFormatNumber(8);
-    grid->SetCellValue(0, 8, "17");
-    grid->SetCellValue(1, 8, "0");
-    grid->SetCellValue(2, 8, "-666");
+    grid->SetCellValue(0, 7, "Width 6\nprecision 2");
+    grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 3.1415));
+    grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 1415.0));
+    grid->SetCellValue(3, 7, wxString::Format(wxT("%g"), 12345.67890));
+
+    grid->SetColFormatCustom(8,
+            wxString::Format("%s:%i,%i,%s", wxGRID_VALUE_FLOAT, -1, 4, "g"));
+    grid->SetCellValue(0, 8, "Compact\nformat");
+    grid->SetCellValue(1, 8, wxT("31415e-4"));
+    grid->SetCellValue(2, 8, wxT("1415"));
+    grid->SetCellValue(3, 8, wxT("123456789e-4"));
+
+    grid->SetColFormatNumber(9);
+    grid->SetCellValue(0, 9, "Integer\ncolumn");
+    grid->SetCellValue(1, 9, "17");
+    grid->SetCellValue(2, 9, "0");
+    grid->SetCellValue(3, 9, "-666");
+    grid->SetCellAlignment(3, 9, wxALIGN_CENTRE, wxALIGN_TOP);
+    grid->SetCellValue(3, 10, "<- This numeric cell should be centred");
 
     const wxString choices[] =
     {
@@ -377,7 +517,7 @@ GridFrame::GridFrame()
     grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
     grid->SetCellValue(7, 1, wxT("Big box!"));
 
-    // create a separator-like row: it's grey and it's non-resizeable
+    // create a separator-like row: it's grey and it's non-resizable
     grid->DisableRowResize(10);
     grid->SetRowSize(10, 30);
     attr = new wxGridCellAttr;
@@ -427,7 +567,6 @@ void GridFrame::SetDefaults()
     GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
     GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
     GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
-    GetMenuBar()->Check( ID_TOGGLENATIVEHEADER, false );
     GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
     GetMenuBar()->Check( ID_CELLOVERFLOW, true );
 }
@@ -497,12 +636,31 @@ void GridFrame::ToggleGridDragCell( wxCommandEvent& WXUNUSED(ev) )
         GetMenuBar()->IsChecked( ID_TOGGLEGRIDDRAGCELL ) );
 }
 
-void GridFrame::ToggleNativeHeader( wxCommandEvent& WXUNUSED(ev) )
+void GridFrame::SetNativeColHeader( wxCommandEvent& WXUNUSED(ev) )
 {
-    grid->SetUseNativeColLabels(
-        GetMenuBar()->IsChecked( ID_TOGGLENATIVEHEADER ) );
+    CustomColumnHeadersProvider* provider =
+        static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
+    provider->UseCustomColHeaders(false);
+    grid->SetUseNativeColLabels(true);
 }
 
+void GridFrame::SetCustomColHeader( wxCommandEvent& WXUNUSED(ev) )
+{
+    CustomColumnHeadersProvider* provider =
+        static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
+    provider->UseCustomColHeaders(true);
+    grid->SetUseNativeColLabels(false);
+}
+
+void GridFrame::SetDefaultColHeader( wxCommandEvent& WXUNUSED(ev) )
+{
+    CustomColumnHeadersProvider* provider =
+        static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
+    provider->UseCustomColHeaders(false);
+    grid->SetUseNativeColLabels(false);
+}
+
+
 void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
 {
     grid->EnableGridLines(
@@ -590,7 +748,7 @@ void GridFrame::SetLabelTextColour( wxCommandEvent& WXUNUSED(ev) )
 void GridFrame::SetLabelFont( wxCommandEvent& WXUNUSED(ev) )
 {
     wxFont font = wxGetFontFromUser(this);
-    if ( font.Ok() )
+    if ( font.IsOk() )
     {
         grid->SetLabelFont(font);
     }
@@ -833,7 +991,7 @@ void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
 void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
 {
     wxColour col = wxGetColourFromUser(this);
-    if ( col.Ok() )
+    if ( col.IsOk() )
     {
         grid->SetDefaultCellTextColour(col);
         grid->Refresh();
@@ -843,7 +1001,7 @@ void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
 void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
 {
     wxColour col = wxGetColourFromUser(this);
-    if ( col.Ok() )
+    if ( col.IsOk() )
     {
         // Check the new Refresh function by passing it a rectangle
         // which exactly fits the grid.
@@ -960,82 +1118,6 @@ void GridFrame::OnColSize( wxGridSizeEvent& ev )
 }
 
 
-void GridFrame::OnShowSelection(wxCommandEvent& WXUNUSED(event))
-{
-    // max number of elements to dump -- otherwise it can take too much time
-    static const size_t countMax = 100;
-
-    bool rows = false;
-
-    switch ( grid->GetSelectionMode() )
-    {
-        case wxGrid::wxGridSelectCells:
-            {
-                const wxGridCellCoordsArray cells(grid->GetSelectedCells());
-                size_t count = cells.size();
-                wxLogMessage(wxT("%lu cells selected:"), (unsigned long)count);
-                if ( count > countMax )
-                {
-                    wxLogMessage(wxT("[too many selected cells, ")
-                                 wxT("showing only the first %lu]"),
-                                 (unsigned long)countMax);
-                    count = countMax;
-                }
-
-                for ( size_t n = 0; n < count; n++ )
-                {
-                    const wxGridCellCoords& c = cells[n];
-                    wxLogMessage(wxT("  selected cell %lu: (%d, %d)"),
-                                 (unsigned long)n, c.GetCol(), c.GetRow());
-                }
-            }
-            break;
-
-        case wxGrid::wxGridSelectRows:
-            rows = true;
-            // fall through
-
-        case wxGrid::wxGridSelectColumns:
-            {
-                const wxChar *plural, *single;
-                if ( rows )
-                {
-                    plural = wxT("rows");
-                    single = wxT("row");
-                }
-                else // columns
-                {
-                    plural = wxT("columns");
-                    single = wxT("column");
-                }
-
-                const wxArrayInt sels((const wxArrayInt)(rows ? grid->GetSelectedRows()
-                                           : grid->GetSelectedCols()));
-                size_t count = sels.size();
-                wxLogMessage(wxT("%lu %s selected:"),
-                             (unsigned long)count, plural);
-                if ( count > countMax )
-                {
-                    wxLogMessage(wxT("[too many selected %s, ")
-                                 wxT("showing only the first %lu]"),
-                                 plural, (unsigned long)countMax);
-                    count = countMax;
-                }
-
-                for ( size_t n = 0; n < count; n++ )
-                {
-                    wxLogMessage(wxT("  selected %s %lu: %d"),
-                                 single, (unsigned long)n, sels[n]);
-                }
-            }
-            break;
-
-        default:
-            wxFAIL_MSG( wxT("unknown wxGrid selection mode") );
-            break;
-    }
-}
-
 void GridFrame::OnSelectCell( wxGridEvent& ev )
 {
     wxString logBuf;
@@ -2021,3 +2103,160 @@ 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 );
+        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->Connect( wxEVT_PAINT,
+                     wxPaintEventHandler(GridFrame::OnRenderPaint),
+                     NULL,
+                     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 );
+}