wxWidgets/samples/grid/griddemo.cpp
Vadim Zeitlin 41dcd9ecdb Add API for ellipsization support to wxGrid
This API is not implemented yet, i.e. ellipsization mode is not
respected for now. This commit just adds the API, documents it and adds
an example of using it in the sample.
2020-01-11 19:14:23 +01:00

2590 lines
76 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: griddemo.cpp
// Purpose: Grid control wxWidgets sample
// Author: Michael Bedward
// Modified by: Santiago Palacios
// Copyright: (c) Michael Bedward, Julian Smart, Vadim Zeitlin
// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// declarations
// ============================================================================
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// For compilers that support precompilation, includes "wx/wx.h".
#include "wx/wxprec.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
#ifndef WX_PRECOMP
#include "wx/wx.h"
#endif
#include "wx/colordlg.h"
#include "wx/fontdlg.h"
#include "wx/numdlg.h"
#include "wx/aboutdlg.h"
#include "wx/grid.h"
#include "wx/headerctrl.h"
#include "wx/generic/gridctrl.h"
#include "wx/generic/grideditors.h"
#include "griddemo.h"
#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 wxOVERRIDE
{
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 wxOVERRIDE
{
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) wxOVERRIDE
{
// 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
// ----------------------------------------------------------------------------
wxIMPLEMENT_APP(GridApp);
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// GridApp
// ----------------------------------------------------------------------------
bool GridApp::OnInit()
{
GridFrame *frame = new GridFrame;
frame->Show(true);
return true;
}
// ----------------------------------------------------------------------------
// GridFrame
// ----------------------------------------------------------------------------
wxBEGIN_EVENT_TABLE( GridFrame, wxFrame )
EVT_MENU( ID_TOGGLEROWLABELS, GridFrame::ToggleRowLabels )
EVT_MENU( ID_TOGGLECOLLABELS, GridFrame::ToggleColLabels )
EVT_MENU( ID_TOGGLEEDIT, GridFrame::ToggleEditing )
EVT_MENU( ID_TOGGLEROWSIZING, GridFrame::ToggleRowSizing )
EVT_MENU( ID_TOGGLECOLSIZING, GridFrame::ToggleColSizing )
EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
EVT_MENU( ID_TOGGLECOLHIDING, GridFrame::ToggleColHiding )
EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
EVT_MENU( ID_COLNATIVEHEADER, GridFrame::SetNativeColHeader )
EVT_MENU( ID_COLNATIVELABELS, GridFrame::SetNativeColLabels )
EVT_MENU( ID_COLDEFAULTHEADER, GridFrame::SetDefaultColHeader )
EVT_MENU( ID_COLCUSTOMHEADER, GridFrame::SetCustomColHeader )
EVT_MENU_RANGE( ID_TAB_STOP, ID_TAB_LEAVE, GridFrame::SetTabBehaviour )
EVT_MENU( ID_TAB_CUSTOM, GridFrame::SetTabCustomHandler )
EVT_MENU( ID_TOGGLEGRIDLINES, GridFrame::ToggleGridLines )
EVT_MENU( ID_AUTOSIZECOLS, GridFrame::AutoSizeCols )
EVT_MENU( ID_CELLOVERFLOW, GridFrame::CellOverflow )
EVT_MENU( ID_RESIZECELL, GridFrame::ResizeCell )
EVT_MENU( ID_SETLABELCOLOUR, GridFrame::SetLabelColour )
EVT_MENU( ID_SETLABELTEXTCOLOUR, GridFrame::SetLabelTextColour )
EVT_MENU( ID_SETLABEL_FONT, GridFrame::SetLabelFont )
EVT_MENU( ID_ROWLABELHORIZALIGN, GridFrame::SetRowLabelHorizAlignment )
EVT_MENU( ID_ROWLABELVERTALIGN, GridFrame::SetRowLabelVertAlignment )
EVT_MENU( ID_COLLABELHORIZALIGN, GridFrame::SetColLabelHorizAlignment )
EVT_MENU( ID_COLLABELVERTALIGN, GridFrame::SetColLabelVertAlignment )
EVT_MENU( ID_CORNERLABELHORIZALIGN, GridFrame::SetCornerLabelHorizAlignment )
EVT_MENU( ID_CORNERLABELVERTALIGN, GridFrame::SetCornerLabelVertAlignment )
EVT_MENU( ID_CORNERLABELORIENTATION, GridFrame::ToggleCornerLabelOrientation )
EVT_MENU( ID_GRIDLINECOLOUR, GridFrame::SetGridLineColour )
EVT_MENU( ID_INSERTROW, GridFrame::InsertRow )
EVT_MENU( ID_INSERTCOL, GridFrame::InsertCol )
EVT_MENU( ID_DELETEROW, GridFrame::DeleteSelectedRows )
EVT_MENU( ID_DELETECOL, GridFrame::DeleteSelectedCols )
EVT_MENU( ID_CLEARGRID, GridFrame::ClearGrid )
EVT_MENU( ID_EDITCELL, GridFrame::EditCell )
EVT_MENU( ID_SETCORNERLABEL, GridFrame::SetCornerLabelValue )
EVT_MENU( ID_SHOWSEL, GridFrame::ShowSelection )
EVT_MENU( ID_SELCELLS, GridFrame::SelectCells )
EVT_MENU( ID_SELROWS, GridFrame::SelectRows )
EVT_MENU( ID_SELCOLS, GridFrame::SelectCols )
EVT_MENU( ID_SELROWSORCOLS, GridFrame::SelectRowsOrCols )
EVT_MENU( ID_FREEZE_OR_THAW, GridFrame::FreezeOrThaw )
EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour )
EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour )
EVT_MENU( wxID_ABOUT, GridFrame::About )
EVT_MENU( wxID_EXIT, GridFrame::OnQuit )
EVT_MENU( ID_VTABLE, GridFrame::OnVTable)
EVT_MENU( ID_BUGS_TABLE, GridFrame::OnBugsTable)
EVT_MENU( ID_TABULAR_TABLE, GridFrame::OnTabularTable)
EVT_MENU( ID_DESELECT_CELL, GridFrame::DeselectCell)
EVT_MENU( ID_DESELECT_COL, GridFrame::DeselectCol)
EVT_MENU( ID_DESELECT_ROW, GridFrame::DeselectRow)
EVT_MENU( ID_DESELECT_ALL, GridFrame::DeselectAll)
EVT_MENU( ID_SELECT_CELL, GridFrame::SelectCell)
EVT_MENU( ID_SELECT_COL, GridFrame::SelectCol)
EVT_MENU( ID_SELECT_ROW, GridFrame::SelectRow)
EVT_MENU( ID_SELECT_ALL, GridFrame::SelectAll)
EVT_MENU( ID_SELECT_UNSELECT, GridFrame::OnAddToSelectToggle)
EVT_MENU( ID_SIZE_ROW, GridFrame::AutoSizeRow )
EVT_MENU( ID_SIZE_COL, GridFrame::AutoSizeCol )
EVT_MENU( ID_SIZE_ROW_LABEL, GridFrame::AutoSizeRowLabel )
EVT_MENU( ID_SIZE_COL_LABEL, GridFrame::AutoSizeColLabel )
EVT_MENU( ID_SIZE_LABELS_COL, GridFrame::AutoSizeLabelsCol )
EVT_MENU( ID_SIZE_LABELS_ROW, GridFrame::AutoSizeLabelsRow )
EVT_MENU( ID_SIZE_GRID, GridFrame::AutoSizeTable )
EVT_MENU( ID_HIDECOL, GridFrame::HideCol )
EVT_MENU( ID_SHOWCOL, GridFrame::ShowCol )
EVT_MENU( ID_HIDEROW, GridFrame::HideRow )
EVT_MENU( ID_SHOWROW, GridFrame::ShowRow )
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 )
EVT_GRID_COL_SIZE( GridFrame::OnColSize )
EVT_GRID_COL_AUTO_SIZE( GridFrame::OnColAutoSize )
EVT_GRID_SELECT_CELL( GridFrame::OnSelectCell )
EVT_GRID_RANGE_SELECT( GridFrame::OnRangeSelected )
EVT_GRID_CELL_CHANGING( GridFrame::OnCellValueChanging )
EVT_GRID_CELL_CHANGED( GridFrame::OnCellValueChanged )
EVT_GRID_CELL_BEGIN_DRAG( GridFrame::OnCellBeginDrag )
EVT_GRID_EDITOR_SHOWN( GridFrame::OnEditorShown )
EVT_GRID_EDITOR_HIDDEN( GridFrame::OnEditorHidden )
wxEND_EVENT_TABLE()
GridFrame::GridFrame()
: wxFrame( (wxFrame *)NULL, wxID_ANY, "wxWidgets grid class demo",
wxDefaultPosition,
wxDefaultSize )
{
SetIcon(wxICON(sample));
wxMenu *fileMenu = new wxMenu;
fileMenu->Append( ID_VTABLE, "&Virtual table test\tCtrl-V");
fileMenu->Append( ID_BUGS_TABLE, "&Bugs table test\tCtrl-B");
fileMenu->Append( ID_TABULAR_TABLE, "&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, "E&xit\tAlt-X" );
wxMenu *viewMenu = new wxMenu;
viewMenu->AppendCheckItem(ID_TOGGLEROWLABELS, "&Row labels");
viewMenu->AppendCheckItem(ID_TOGGLECOLLABELS, "&Col labels");
viewMenu->AppendCheckItem(ID_TOGGLEEDIT,"&Editable");
viewMenu->AppendCheckItem(ID_TOGGLEROWSIZING, "Ro&w drag-resize");
viewMenu->AppendCheckItem(ID_TOGGLECOLSIZING, "C&ol drag-resize");
viewMenu->AppendCheckItem(ID_TOGGLECOLMOVING, "Col drag-&move");
viewMenu->AppendCheckItem(ID_TOGGLECOLHIDING, "Col hiding popup menu");
viewMenu->AppendCheckItem(ID_TOGGLEGRIDSIZING, "&Grid drag-resize");
viewMenu->AppendCheckItem(ID_TOGGLEGRIDDRAGCELL, "&Grid drag-cell");
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...");
viewMenu->AppendCheckItem(ID_AUTOSIZECOLS, "&Auto-size cols");
viewMenu->AppendCheckItem(ID_CELLOVERFLOW, "&Overflow cells");
viewMenu->AppendCheckItem(ID_RESIZECELL, "&Resize cell (7,1)");
viewMenu->Append(ID_HIDECOL, "&Hide column A");
viewMenu->Append(ID_SHOWCOL, "&Show column A");
viewMenu->Append(ID_HIDEROW, "&Hide row 2");
viewMenu->Append(ID_SHOWROW, "&Show row 2");
wxMenu *rowLabelMenu = new wxMenu;
viewMenu->Append( ID_ROWLABELALIGN, "R&ow label alignment",
rowLabelMenu,
"Change alignment of row labels" );
rowLabelMenu->AppendRadioItem( ID_ROWLABELHORIZALIGN, "&Horizontal" );
rowLabelMenu->AppendRadioItem( ID_ROWLABELVERTALIGN, "&Vertical" );
wxMenu *colLabelMenu = new wxMenu;
viewMenu->Append( ID_COLLABELALIGN, "Col l&abel alignment",
colLabelMenu,
"Change alignment of col labels" );
colLabelMenu->AppendRadioItem( ID_COLLABELHORIZALIGN, "&Horizontal" );
colLabelMenu->AppendRadioItem( ID_COLLABELVERTALIGN, "&Vertical" );
wxMenu *cornerLabelMenu = new wxMenu;
viewMenu->Append( ID_CORNERLABELALIGN, "Corner label alignment",
cornerLabelMenu,
"Change alignment of corner label" );
cornerLabelMenu->AppendRadioItem( ID_CORNERLABELHORIZALIGN, "&Horizontal" );
cornerLabelMenu->AppendRadioItem( ID_CORNERLABELVERTALIGN, "&Vertical" );
viewMenu->Append( ID_CORNERLABELORIENTATION, "Toggle corner label orientation" );
wxMenu *colHeaderMenu = new wxMenu;
viewMenu->Append( ID_ROWLABELALIGN, "Col header style",
colHeaderMenu,
"Change style of col header" );
colHeaderMenu->AppendRadioItem( ID_COLDEFAULTHEADER, "&Default" );
colHeaderMenu->AppendRadioItem( ID_COLNATIVEHEADER, "&Native" );
colHeaderMenu->AppendRadioItem( ID_COLNATIVELABELS, "Native-&like" );
colHeaderMenu->AppendRadioItem( ID_COLCUSTOMHEADER, "&Custom" );
wxMenu *tabBehaviourMenu = new wxMenu;
tabBehaviourMenu->AppendRadioItem(ID_TAB_STOP, "&Stop at the boundary");
tabBehaviourMenu->AppendRadioItem(ID_TAB_WRAP, "&Wrap at the boundary");
tabBehaviourMenu->AppendRadioItem(ID_TAB_LEAVE, "&Leave the grid");
tabBehaviourMenu->AppendRadioItem(ID_TAB_CUSTOM, "&Custom tab handler");
viewMenu->AppendSubMenu(tabBehaviourMenu, "&Tab behaviour");
wxMenu *colMenu = new wxMenu;
colMenu->Append( ID_SETLABELCOLOUR, "Set &label colour..." );
colMenu->Append( ID_SETLABELTEXTCOLOUR, "Set label &text colour..." );
colMenu->Append( ID_SETLABEL_FONT, "Set label fo&nt..." );
colMenu->Append( ID_GRIDLINECOLOUR, "&Grid line colour..." );
colMenu->Append( ID_SET_CELL_FG_COLOUR, "Set cell &foreground colour..." );
colMenu->Append( ID_SET_CELL_BG_COLOUR, "Set cell &background colour..." );
wxMenu *editMenu = new wxMenu;
editMenu->Append( ID_INSERTROW, "Insert &row" );
editMenu->Append( ID_INSERTCOL, "Insert &column" );
editMenu->Append( ID_DELETEROW, "Delete selected ro&ws" );
editMenu->Append( ID_DELETECOL, "Delete selected co&ls" );
editMenu->Append( ID_CLEARGRID, "Cl&ear grid cell contents" );
editMenu->Append( ID_EDITCELL, "&Edit current cell" );
editMenu->Append( ID_SETCORNERLABEL, "&Set corner label..." );
editMenu->AppendCheckItem( ID_FREEZE_OR_THAW, "Freeze up to cursor\tCtrl-F" );
wxMenu *selectMenu = new wxMenu;
selectMenu->Append( ID_SELECT_UNSELECT, "Add new cells to the selection",
"When off, old selection is deselected before "
"selecting the new cells", wxITEM_CHECK );
selectMenu->AppendSeparator();
selectMenu->Append( ID_SELECT_ALL, "Select all");
selectMenu->Append( ID_SELECT_ROW, "Select row 2");
selectMenu->Append( ID_SELECT_COL, "Select col 2");
selectMenu->Append( ID_SELECT_CELL, "Select cell (3, 1)");
selectMenu->AppendSeparator();
selectMenu->Append( ID_DESELECT_ALL, "Deselect all");
selectMenu->Append( ID_DESELECT_ROW, "Deselect row 2");
selectMenu->Append( ID_DESELECT_COL, "Deselect col 2");
selectMenu->Append( ID_DESELECT_CELL, "Deselect cell (3, 1)");
selectMenu->AppendSeparator();
wxMenu *selectionMenu = new wxMenu;
selectMenu->Append( ID_SHOWSEL, "&Show current selection\tCtrl-S" );
selectMenu->Append( ID_CHANGESEL, "Change &selection mode",
selectionMenu,
"Change selection mode" );
selectionMenu->Append( ID_SELCELLS, "Select &cells" );
selectionMenu->Append( ID_SELROWS, "Select &rows" );
selectionMenu->Append( ID_SELCOLS, "Select col&umns" );
selectionMenu->Append( ID_SELROWSORCOLS, "Select rows &or columns" );
wxMenu *autosizeMenu = new wxMenu;
autosizeMenu->Append( ID_SIZE_ROW, "Selected &row data" );
autosizeMenu->Append( ID_SIZE_COL, "Selected &column data" );
autosizeMenu->Append( ID_SIZE_ROW_LABEL, "Selected row la&bel" );
autosizeMenu->Append( ID_SIZE_COL_LABEL, "Selected column &label" );
autosizeMenu->Append( ID_SIZE_LABELS_COL, "Column la&bels" );
autosizeMenu->Append( ID_SIZE_LABELS_ROW, "Row label&s" );
autosizeMenu->Append( ID_SIZE_GRID, "Entire &grid" );
wxMenu *helpMenu = new wxMenu;
helpMenu->Append( wxID_ABOUT, "&About wxGrid demo" );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( fileMenu, "&File" );
menuBar->Append( viewMenu, "&Grid" );
menuBar->Append( colMenu, "&Colours" );
menuBar->Append( editMenu, "&Edit" );
menuBar->Append( selectMenu, "&Select" );
menuBar->Append( autosizeMenu, "&Autosize" );
menuBar->Append( helpMenu, "&Help" );
SetMenuBar( menuBar );
m_addToSel = false;
grid = new wxGrid( this,
wxID_ANY,
wxPoint( 0, 0 ),
wxSize( 400, 300 ) );
#if wxUSE_LOG
int gridW = 600, gridH = 300;
int logW = gridW, logH = 100;
logWin = new wxTextCtrl( this,
wxID_ANY,
wxEmptyString,
wxPoint( 0, gridH + 20 ),
wxSize( logW, logH ),
wxTE_MULTILINE );
logger = new wxLogTextCtrl( logWin );
m_logOld = wxLog::SetActiveTarget( logger );
wxLog::DisableTimestamp();
#endif // wxUSE_LOG
// 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);
int ir = grid->GetNumberRows();
grid->DeleteRows(0, ir);
grid->AppendRows(ir);
grid->SetRowSize( 0, 60 );
grid->SetCellValue( 0, 0, "Ctrl+Home\nwill go to\nthis cell" );
grid->SetCellValue( 0, 1, "A long piece of text to demonstrate wrapping." );
grid->SetCellRenderer(0 , 1, new wxGridCellAutoWrapStringRenderer);
grid->SetCellEditor( 0, 1 , new wxGridCellAutoWrapStringEditor);
grid->SetCellValue( 0, 2, "Blah" );
grid->SetCellValue( 0, 3, "Read only" );
grid->SetReadOnly( 0, 3 );
grid->SetCellValue( 0, 4, "Can veto edit this cell" );
grid->SetColSize(10, 150);
wxString longtext = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\n\n";
longtext += "With tabs :\n";
longtext += "Home,\t\thome\t\t\tagain\n";
longtext += "Long word at start :\n";
longtext += "ILikeToBeHereWhen I can\n";
longtext += "Long word in the middle :\n";
longtext += "When IComeHome,ColdAnd tired\n";
longtext += "Long last word :\n";
longtext += "It's GoodToWarmMyBonesBesideTheFire";
grid->SetCellValue( 0, 10, longtext );
grid->SetCellRenderer(0 , 10, new wxGridCellAutoWrapStringRenderer);
grid->SetCellEditor( 0, 10 , new wxGridCellAutoWrapStringEditor);
grid->SetCellValue( 0, 11, "K1 cell editor blocker" );
grid->SetCellValue( 0, 5, "Press\nCtrl+arrow\nto skip over\ncells" );
grid->SetRowSize( 99, 60 );
grid->SetCellValue(98, 98, "Test background colour setting");
grid->SetCellBackgroundColour(98, 99, wxColour(255, 127, 127));
grid->SetCellBackgroundColour(99, 98, wxColour(255, 127, 127));
grid->SetCellValue( 99, 99, "Ctrl+End\nwill go to\nthis cell" );
grid->SetCellValue( 1, 0, "This default cell will overflow into neighboring cells, but not if you turn overflow off.");
grid->SetCellValue(2, 0, "This one always overflows");
grid->SetCellFitMode(2, 0, wxGridFitMode::Overflow());
grid->SetCellTextColour(1, 2, *wxRED);
grid->SetCellBackgroundColour(1, 2, *wxGREEN);
grid->SetCellValue( 1, 4, "I'm in the middle");
grid->SetCellValue(2, 2, "red");
grid->SetCellTextColour(2, 2, *wxRED);
grid->SetCellValue(3, 3, "green on grey");
grid->SetCellTextColour(3, 3, *wxGREEN);
grid->SetCellBackgroundColour(3, 3, *wxLIGHT_GREY);
grid->SetCellValue(4, 4, "a weird looking cell");
grid->SetCellAlignment(4, 4, wxALIGN_CENTRE, wxALIGN_CENTRE);
grid->SetCellRenderer(4, 4, new MyGridCellRenderer);
grid->SetCellRenderer(3, 0, new wxGridCellBoolRenderer);
grid->SetCellEditor(3, 0, new wxGridCellBoolEditor);
grid->SetCellBackgroundColour(3, 0, wxColour(255, 127, 127));
grid->SetCellRenderer(3, 1, new wxGridCellBoolRenderer);
grid->SetCellEditor(3, 1, new wxGridCellBoolEditor);
grid->SetCellValue(3, 1, "1");
wxGridCellAttr *attr;
attr = new wxGridCellAttr;
attr->SetTextColour(*wxBLUE);
grid->SetColAttr(5, attr);
attr = new wxGridCellAttr;
attr->SetBackgroundColour(*wxRED);
grid->SetRowAttr(5, attr);
grid->SetCellValue(2, 4, "a wider column");
grid->SetColSize(4, 120);
grid->SetColMinimalWidth(4, 120);
grid->SetCellTextColour(5, 8, *wxGREEN);
grid->SetCellValue(5, 8, "Bg from row attr\nText col from cell attr");
grid->SetCellValue(5, 5, "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, "Default\nfloat format");
grid->SetCellValue(1, 6, wxString::Format("%g", 3.1415));
grid->SetCellValue(2, 6, wxString::Format("%g", 1415.0));
grid->SetCellValue(3, 6, wxString::Format("%g", 12345.67890));
grid->SetColFormatFloat(7, 6, 2);
grid->SetCellValue(0, 7, "Width 6\nprecision 2");
grid->SetCellValue(1, 7, wxString::Format("%g", 3.1415));
grid->SetCellValue(2, 7, wxString::Format("%g", 1415.0));
grid->SetCellValue(3, 7, wxString::Format("%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, "31415e-4");
grid->SetCellValue(2, 8, "1415");
grid->SetCellValue(3, 8, "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");
grid->SetCellValue(0, 13, "Localized date\ncolumn");
grid->SetColFormatDate(13); // Localized by default.
grid->SetCellValue(1, 13, "Today");
grid->SetCellValue(0, 14, "ISO 8601 date\ncolumn");
grid->SetColFormatDate(14, "%Y-%m-%d"); // ISO 8601 date format.
grid->SetCellValue(1, 14, "Tomorrow");
grid->SetCellValue(13, 0, "Date cell:");
grid->SetCellValue(13, 1, "Today");
grid->SetCellRenderer(13, 1, new wxGridCellDateRenderer);
grid->SetCellEditor(13, 1, new wxGridCellDateEditor);
grid->SetCellValue(14, 0, "ISO date cell:");
grid->SetCellValue(14, 1, "Tomorrow");
grid->SetCellRenderer(14, 1, new wxGridCellDateRenderer("%Y-%m-%d"));
grid->SetCellEditor(14, 1, new wxGridCellDateEditor);
grid->SetCellValue(13, 3, "String using default ellipsization");
grid->SetCellFitMode(13, 3, wxGridFitMode::Ellipsize());
grid->SetCellValue(13, 4, "String ellipsized in the middle");
grid->SetCellFitMode(13, 4, wxGridFitMode::Ellipsize(wxELLIPSIZE_MIDDLE));
const wxString choices[] =
{
"Please select a choice",
"This takes two cells",
"Another choice",
};
grid->SetCellEditor(4, 2, new wxGridCellChoiceEditor(WXSIZEOF(choices), choices));
grid->SetCellSize(4, 2, 1, 2);
grid->SetCellValue(4, 2, choices[0]);
grid->SetCellOverflow(4, 2, false);
grid->SetCellSize(7, 1, 3, 4);
grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
grid->SetCellValue(7, 1, "Big box!");
// create a separator-like row: it's grey and it's non-resizable
grid->DisableRowResize(10);
grid->SetRowSize(10, 30);
attr = new wxGridCellAttr;
attr->SetBackgroundColour(*wxLIGHT_GREY);
grid->SetRowAttr(10, attr);
grid->SetCellValue(10, 0, "You can't resize this row interactively -- try it");
// this does exactly nothing except testing that SetAttr() handles NULL
// attributes and does reference counting correctly
grid->SetAttr(11, 11, NULL);
grid->SetAttr(11, 11, new wxGridCellAttr);
grid->SetAttr(11, 11, NULL);
grid->Bind(wxEVT_CONTEXT_MENU, &GridFrame::OnGridContextMenu, this, grid->GetId());
wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
topSizer->Add( grid,
1,
wxEXPAND );
#if wxUSE_LOG
topSizer->Add( logWin,
0,
wxEXPAND );
#endif // wxUSE_LOG
SetSizerAndFit( topSizer );
Centre();
SetDefaults();
}
GridFrame::~GridFrame()
{
#if wxUSE_LOG
delete wxLog::SetActiveTarget(m_logOld);
#endif // wxUSE_LOG
}
void GridFrame::SetDefaults()
{
GetMenuBar()->Check( ID_TOGGLEROWLABELS, true );
GetMenuBar()->Check( ID_TOGGLECOLLABELS, true );
GetMenuBar()->Check( ID_TOGGLEEDIT, true );
GetMenuBar()->Check( ID_TOGGLEROWSIZING, true );
GetMenuBar()->Check( ID_TOGGLECOLSIZING, true );
GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
GetMenuBar()->Check( ID_TOGGLECOLHIDING, true );
GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
GetMenuBar()->Check( ID_CELLOVERFLOW, true );
}
void GridFrame::ToggleRowLabels( wxCommandEvent& WXUNUSED(ev) )
{
if ( GetMenuBar()->IsChecked( ID_TOGGLEROWLABELS ) )
{
grid->SetRowLabelSize( grid->GetDefaultRowLabelSize() );
}
else
{
grid->SetRowLabelSize( 0 );
}
}
void GridFrame::ToggleColLabels( wxCommandEvent& WXUNUSED(ev) )
{
if ( GetMenuBar()->IsChecked( ID_TOGGLECOLLABELS ) )
{
grid->SetColLabelSize( grid->GetDefaultColLabelSize() );
}
else
{
grid->SetColLabelSize( 0 );
}
}
void GridFrame::ToggleEditing( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableEditing(
GetMenuBar()->IsChecked( ID_TOGGLEEDIT ) );
}
void GridFrame::ToggleRowSizing( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragRowSize(
GetMenuBar()->IsChecked( ID_TOGGLEROWSIZING ) );
}
void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragColSize(
GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
}
void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragColMove(
GetMenuBar()->IsChecked( ID_TOGGLECOLMOVING ) );
}
void GridFrame::ToggleColHiding( wxCommandEvent& WXUNUSED(ev) )
{
if ( !grid->EnableHidingColumns(
GetMenuBar()->IsChecked( ID_TOGGLECOLHIDING ) ) )
{
GetMenuBar()->Check( ID_TOGGLECOLHIDING, grid->CanHideColumns() );
}
}
void GridFrame::ToggleGridSizing( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragGridSize(
GetMenuBar()->IsChecked( ID_TOGGLEGRIDSIZING ) );
}
void GridFrame::ToggleGridDragCell( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableDragCell(
GetMenuBar()->IsChecked( ID_TOGGLEGRIDDRAGCELL ) );
}
void GridFrame::SetNativeColHeader( wxCommandEvent& WXUNUSED(ev) )
{
CustomColumnHeadersProvider* provider =
static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
provider->UseCustomColHeaders(false);
grid->UseNativeColHeader(true);
}
void GridFrame::SetNativeColLabels( wxCommandEvent& WXUNUSED(ev) )
{
CustomColumnHeadersProvider* provider =
static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
provider->UseCustomColHeaders(false);
grid->UseNativeColHeader(false);
grid->SetUseNativeColLabels(true);
}
void GridFrame::SetCustomColHeader( wxCommandEvent& WXUNUSED(ev) )
{
CustomColumnHeadersProvider* provider =
static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
provider->UseCustomColHeaders(true);
grid->UseNativeColHeader(false);
grid->SetUseNativeColLabels(false);
}
void GridFrame::SetDefaultColHeader( wxCommandEvent& WXUNUSED(ev) )
{
CustomColumnHeadersProvider* provider =
static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
provider->UseCustomColHeaders(false);
grid->UseNativeColHeader(false);
grid->SetUseNativeColLabels(false);
}
void GridFrame::OnGridCustomTab(wxGridEvent& event)
{
// just for testing, make the cursor move up and down instead of the usual
// left and right
if ( event.ShiftDown() )
{
if ( grid->GetGridCursorRow() > 0 )
grid->MoveCursorUp( false );
}
else
{
if ( grid->GetGridCursorRow() < grid->GetNumberRows() - 1 )
grid->MoveCursorDown( false );
}
}
void GridFrame::SetTabBehaviour(wxCommandEvent& event)
{
// To make any built-in behaviour work, we need to disable the custom TAB
// handler, otherwise it would be overriding them.
grid->Unbind(wxEVT_GRID_TABBING, &GridFrame::OnGridCustomTab, this);
grid->SetTabBehaviour(
static_cast<wxGrid::TabBehaviour>(event.GetId() - ID_TAB_STOP)
);
}
void GridFrame::SetTabCustomHandler(wxCommandEvent&)
{
grid->Bind(wxEVT_GRID_TABBING, &GridFrame::OnGridCustomTab, this);
}
void GridFrame::OnGridContextMenu(wxContextMenuEvent& event)
{
// This is not supposed to happen: even if the grid consists of different
// subwindows internally, all context menu events should be seen as coming
// from the grid itself.
if ( event.GetEventObject() != grid )
{
wxLogError("Context menu unexpectedly sent from non-grid window.");
}
else
{
wxLogMessage("wxEVT_CONTEXT_MENU in the grid at at (%d, %d)",
event.GetPosition().x, event.GetPosition().y);
}
event.Skip();
}
void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableGridLines(
GetMenuBar()->IsChecked( ID_TOGGLEGRIDLINES ) );
}
void GridFrame::OnSetHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
{
wxString choices[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
wxSingleChoiceDialog dlg(this, "Choose the thickness of the highlight pen:",
"Pen Width", 11, choices);
int current = grid->GetCellHighlightPenWidth();
dlg.SetSelection(current);
if (dlg.ShowModal() == wxID_OK) {
grid->SetCellHighlightPenWidth(dlg.GetSelection());
}
}
void GridFrame::OnSetROHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
{
wxString choices[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"};
wxSingleChoiceDialog dlg(this, "Choose the thickness of the highlight pen:",
"Pen Width", 11, choices);
int current = grid->GetCellHighlightROPenWidth();
dlg.SetSelection(current);
if (dlg.ShowModal() == wxID_OK) {
grid->SetCellHighlightROPenWidth(dlg.GetSelection());
}
}
void GridFrame::AutoSizeCols( wxCommandEvent& WXUNUSED(ev) )
{
grid->AutoSizeColumns();
grid->Refresh();
}
void GridFrame::CellOverflow( wxCommandEvent& ev )
{
grid->SetDefaultCellOverflow(ev.IsChecked());
grid->Refresh();
}
void GridFrame::ResizeCell( wxCommandEvent& ev )
{
if (ev.IsChecked())
grid->SetCellSize( 7, 1, 5, 5 );
else
grid->SetCellSize( 7, 1, 1, 5 );
grid->Refresh();
}
void GridFrame::SetLabelColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColourDialog dlg( NULL );
if ( dlg.ShowModal() == wxID_OK )
{
wxColourData retData;
retData = dlg.GetColourData();
wxColour colour = retData.GetColour();
grid->SetLabelBackgroundColour( colour );
}
}
void GridFrame::SetLabelTextColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColourDialog dlg( NULL );
if ( dlg.ShowModal() == wxID_OK )
{
wxColourData retData;
retData = dlg.GetColourData();
wxColour colour = retData.GetColour();
grid->SetLabelTextColour( colour );
}
}
void GridFrame::SetLabelFont( wxCommandEvent& WXUNUSED(ev) )
{
wxFont font = wxGetFontFromUser(this);
if ( font.IsOk() )
{
grid->SetLabelFont(font);
}
}
void GridFrame::SetRowLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetRowLabelAlignment( &horiz, &vert );
switch ( horiz )
{
case wxALIGN_LEFT:
horiz = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
horiz = wxALIGN_RIGHT;
break;
case wxALIGN_RIGHT:
horiz = wxALIGN_LEFT;
break;
}
grid->SetRowLabelAlignment( horiz, vert );
}
void GridFrame::SetRowLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetRowLabelAlignment( &horiz, &vert );
switch ( vert )
{
case wxALIGN_TOP:
vert = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
vert = wxALIGN_BOTTOM;
break;
case wxALIGN_BOTTOM:
vert = wxALIGN_TOP;
break;
}
grid->SetRowLabelAlignment( horiz, vert );
}
void GridFrame::SetColLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetColLabelAlignment( &horiz, &vert );
switch ( horiz )
{
case wxALIGN_LEFT:
horiz = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
horiz = wxALIGN_RIGHT;
break;
case wxALIGN_RIGHT:
horiz = wxALIGN_LEFT;
break;
}
grid->SetColLabelAlignment( horiz, vert );
}
void GridFrame::SetColLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetColLabelAlignment( &horiz, &vert );
switch ( vert )
{
case wxALIGN_TOP:
vert = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
vert = wxALIGN_BOTTOM;
break;
case wxALIGN_BOTTOM:
vert = wxALIGN_TOP;
break;
}
grid->SetColLabelAlignment( horiz, vert );
}
void GridFrame::SetCornerLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetCornerLabelAlignment( &horiz, &vert );
switch ( horiz )
{
case wxALIGN_LEFT:
horiz = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
horiz = wxALIGN_RIGHT;
break;
case wxALIGN_RIGHT:
horiz = wxALIGN_LEFT;
break;
}
grid->SetCornerLabelAlignment( horiz, vert );
}
void GridFrame::SetCornerLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
{
int horiz, vert;
grid->GetCornerLabelAlignment( &horiz, &vert );
switch ( vert )
{
case wxALIGN_TOP:
vert = wxALIGN_CENTRE;
break;
case wxALIGN_CENTRE:
vert = wxALIGN_BOTTOM;
break;
case wxALIGN_BOTTOM:
vert = wxALIGN_TOP;
break;
}
grid->SetCornerLabelAlignment( horiz, vert );
}
void GridFrame::ToggleCornerLabelOrientation( wxCommandEvent& WXUNUSED(ev) )
{
int orientation = grid->GetCornerLabelTextOrientation();
switch(orientation)
{
case wxHORIZONTAL:
orientation = wxVERTICAL;
break;
case wxVERTICAL:
orientation = wxHORIZONTAL;
break;
}
grid->SetCornerLabelTextOrientation(orientation);
}
void GridFrame::SetGridLineColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColourDialog dlg( NULL );
if ( dlg.ShowModal() == wxID_OK )
{
wxColourData retData;
retData = dlg.GetColourData();
wxColour colour = retData.GetColour();
grid->SetGridLineColour( colour );
}
}
void GridFrame::InsertRow( wxCommandEvent& WXUNUSED(ev) )
{
grid->InsertRows( grid->GetGridCursorRow(), 1 );
}
void GridFrame::InsertCol( wxCommandEvent& WXUNUSED(ev) )
{
grid->InsertCols( grid->GetGridCursorCol(), 1 );
}
void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
{
if ( grid->IsSelection() )
{
wxGridUpdateLocker locker(grid);
for ( int n = 0; n < grid->GetNumberRows(); )
{
if ( grid->IsInSelection( n , 0 ) )
grid->DeleteRows( n, 1 );
else
n++;
}
}
}
void GridFrame::AutoSizeRow(wxCommandEvent& WXUNUSED(event))
{
wxGridUpdateLocker locker(grid);
const wxArrayInt sels = grid->GetSelectedRows();
for ( size_t n = 0, count = sels.size(); n < count; n++ )
{
grid->AutoSizeRow( sels[n], false );
}
}
void GridFrame::AutoSizeCol(wxCommandEvent& WXUNUSED(event))
{
wxGridUpdateLocker locker(grid);
const wxArrayInt sels = grid->GetSelectedCols();
for ( size_t n = 0, count = sels.size(); n < count; n++ )
{
grid->AutoSizeColumn( sels[n], false );
}
}
void GridFrame::AutoSizeRowLabel(wxCommandEvent& WXUNUSED(event))
{
wxGridUpdateLocker locker(grid);
const wxArrayInt sels = grid->GetSelectedRows();
for ( size_t n = 0, count = sels.size(); n < count; n++ )
{
grid->AutoSizeRowLabelSize( sels[n] );
}
}
void GridFrame::AutoSizeColLabel(wxCommandEvent& WXUNUSED(event))
{
wxGridUpdateLocker locker(grid);
const wxArrayInt sels = grid->GetSelectedCols();
for ( size_t n = 0, count = sels.size(); n < count; n++ )
{
grid->AutoSizeColLabelSize( sels[n] );
}
}
void GridFrame::AutoSizeLabelsCol(wxCommandEvent& WXUNUSED(event))
{
grid->SetColLabelSize( wxGRID_AUTOSIZE );
}
void GridFrame::AutoSizeLabelsRow(wxCommandEvent& WXUNUSED(event))
{
grid->SetRowLabelSize( wxGRID_AUTOSIZE );
}
void GridFrame::AutoSizeTable(wxCommandEvent& WXUNUSED(event))
{
grid->AutoSize();
Layout();
}
void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
{
if ( grid->IsSelection() )
{
wxGridUpdateLocker locker(grid);
for ( int n = 0; n < grid->GetNumberCols(); )
{
if ( grid->IsInSelection( 0 , n ) )
grid->DeleteCols( n, 1 );
else
n++;
}
}
}
void GridFrame::ClearGrid( wxCommandEvent& WXUNUSED(ev) )
{
grid->ClearGrid();
}
void GridFrame::EditCell( wxCommandEvent& WXUNUSED(ev) )
{
grid->EnableCellEditControl();
}
void GridFrame::SetCornerLabelValue( wxCommandEvent& WXUNUSED(ev) )
{
wxTextEntryDialog dialog(this,
"Please enter corner label:",
"Please enter a string",
grid->GetCornerLabelValue(),
wxOK | wxCANCEL);
if (dialog.ShowModal() == wxID_OK)
{
grid->SetCornerLabelValue(dialog.GetValue());
}
}
void GridFrame::ShowSelection( wxCommandEvent& WXUNUSED(ev) )
{
switch ( grid->GetSelectionMode() )
{
case wxGrid::wxGridSelectCells:
wxLogMessage("%zu individual cells and "
"%zu blocks of contiguous cells selected",
grid->GetSelectedCells().size(),
grid->GetSelectionBlockTopLeft().size());
return;
case wxGrid::wxGridSelectRows:
case wxGrid::wxGridSelectColumns:
case wxGrid::wxGridSelectRowsOrColumns:
const wxArrayInt& rows = grid->GetSelectedRows();
if ( !rows.empty() )
wxLogMessage("%zu rows selected", rows.size());
const wxArrayInt& cols = grid->GetSelectedCols();
if ( !cols.empty() )
wxLogMessage("%zu columns selected", rows.size());
if ( rows.empty() && cols.empty() )
wxLogMessage("No selection");
return;
}
wxLogError("Unknown grid selection mode.");
}
void GridFrame::SelectCells( wxCommandEvent& WXUNUSED(ev) )
{
grid->SetSelectionMode( wxGrid::wxGridSelectCells );
}
void GridFrame::SelectRows( wxCommandEvent& WXUNUSED(ev) )
{
grid->SetSelectionMode( wxGrid::wxGridSelectRows );
}
void GridFrame::SelectCols( wxCommandEvent& WXUNUSED(ev) )
{
grid->SetSelectionMode( wxGrid::wxGridSelectColumns );
}
void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
{
grid->SetSelectionMode( wxGrid::wxGridSelectRowsOrColumns );
}
void GridFrame::FreezeOrThaw(wxCommandEvent& ev)
{
if ( ev.IsChecked() )
{
if ( !grid->FreezeTo(grid->GetGridCursorCoords()) )
{
wxLogMessage("Failed to freeze the grid.");
GetMenuBar()->Check(ID_FREEZE_OR_THAW, false);
return;
}
wxLogMessage("Grid is now frozen");
}
else
{
// This never fails.
grid->FreezeTo(0, 0);
wxLogMessage("Grid is now thawed");
}
GetMenuBar()->Enable( ID_TOGGLECOLMOVING, !grid->IsFrozen() );
}
void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColour col = wxGetColourFromUser(this);
if ( col.IsOk() )
{
grid->SetDefaultCellTextColour(col);
grid->Refresh();
}
}
void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColour col = wxGetColourFromUser(this);
if ( col.IsOk() )
{
// Check the new Refresh function by passing it a rectangle
// which exactly fits the grid.
wxPoint pt(0, 0);
wxRect r(pt, grid->GetSize());
grid->SetDefaultCellBackgroundColour(col);
grid->Refresh(true, &r);
}
}
void GridFrame::DeselectCell(wxCommandEvent& WXUNUSED(event))
{
grid->DeselectCell(3, 1);
}
void GridFrame::DeselectCol(wxCommandEvent& WXUNUSED(event))
{
grid->DeselectCol(2);
}
void GridFrame::DeselectRow(wxCommandEvent& WXUNUSED(event))
{
grid->DeselectRow(2);
}
void GridFrame::DeselectAll(wxCommandEvent& WXUNUSED(event))
{
grid->ClearSelection();
}
void GridFrame::SelectCell(wxCommandEvent& WXUNUSED(event))
{
grid->SelectBlock(3, 1, 3, 1, m_addToSel);
}
void GridFrame::SelectCol(wxCommandEvent& WXUNUSED(event))
{
grid->SelectCol(2, m_addToSel);
}
void GridFrame::SelectRow(wxCommandEvent& WXUNUSED(event))
{
grid->SelectRow(2, m_addToSel);
}
void GridFrame::SelectAll(wxCommandEvent& WXUNUSED(event))
{
grid->SelectAll();
}
void GridFrame::OnAddToSelectToggle(wxCommandEvent& event)
{
m_addToSel = event.IsChecked();
}
void GridFrame::OnLabelLeftClick( wxGridEvent& ev )
{
wxString logBuf;
if ( ev.GetRow() != -1 )
{
logBuf << "Left click on row label " << ev.GetRow();
}
else if ( ev.GetCol() != -1 )
{
logBuf << "Left click on col label " << ev.GetCol();
}
else
{
logBuf << "Left click on corner label";
}
if ( ev.ShiftDown() )
logBuf << " (shift down)";
if ( ev.ControlDown() )
logBuf << " (control down)";
wxLogMessage( "%s", logBuf );
// you must call event skip if you want default grid processing
//
ev.Skip();
}
void GridFrame::OnCellLeftClick( wxGridEvent& ev )
{
wxLogMessage("Left click at row %d, col %d", ev.GetRow(), ev.GetCol());
// you must call event skip if you want default grid processing
// (cell highlighting etc.)
//
ev.Skip();
}
void GridFrame::OnRowSize( wxGridSizeEvent& ev )
{
const int row = ev.GetRowOrCol();
wxLogMessage("Resized row %d, new height = %d",
row, grid->GetRowSize(row));
ev.Skip();
}
void GridFrame::OnColSize( wxGridSizeEvent& ev )
{
const int col = ev.GetRowOrCol();
wxLogMessage("Resized column %d, new width = %d",
col, grid->GetColSize(col));
ev.Skip();
}
void GridFrame::OnColAutoSize( wxGridSizeEvent &event )
{
// Fit even-numbered columns to their contents while using the default
// behaviour for the odd-numbered ones to be able to see the difference.
int col = event.GetRowOrCol();
if ( col % 2 )
{
wxLogMessage("Auto-sizing column %d to fit its contents", col);
grid->AutoSizeColumn(col);
}
else
{
event.Skip();
}
}
void GridFrame::OnSelectCell( wxGridEvent& ev )
{
wxString logBuf;
if ( ev.Selecting() )
logBuf << "Selected ";
else
logBuf << "Deselected ";
logBuf << "cell at row " << ev.GetRow()
<< " col " << ev.GetCol()
<< " ( ControlDown: "<< (ev.ControlDown() ? 'T':'F')
<< ", ShiftDown: "<< (ev.ShiftDown() ? 'T':'F')
<< ", AltDown: "<< (ev.AltDown() ? 'T':'F')
<< ", MetaDown: "<< (ev.MetaDown() ? 'T':'F') << " )";
//Indicate whether this column was moved
if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
logBuf << " *** Column moved, current position: " << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
wxLogMessage( "%s", logBuf );
// you must call Skip() if you want the default processing
// to occur in wxGrid
ev.Skip();
}
void GridFrame::OnRangeSelected( wxGridRangeSelectEvent& ev )
{
wxString logBuf;
if ( ev.Selecting() )
logBuf << "Selected ";
else
logBuf << "Deselected ";
logBuf << "cells from row " << ev.GetTopRow()
<< " col " << ev.GetLeftCol()
<< " to row " << ev.GetBottomRow()
<< " col " << ev.GetRightCol()
<< " ( ControlDown: "<< (ev.ControlDown() ? 'T':'F')
<< ", ShiftDown: "<< (ev.ShiftDown() ? 'T':'F')
<< ", AltDown: "<< (ev.AltDown() ? 'T':'F')
<< ", MetaDown: "<< (ev.MetaDown() ? 'T':'F') << " )";
wxLogMessage( "%s", logBuf );
ev.Skip();
}
void GridFrame::OnCellValueChanging( wxGridEvent& ev )
{
int row = ev.GetRow(),
col = ev.GetCol();
wxLogMessage("Value of cell at (%d, %d): about to change "
"from \"%s\" to \"%s\"",
row, col,
grid->GetCellValue(row, col), ev.GetString());
// test how vetoing works
if ( ev.GetString() == "42" )
{
wxLogMessage("Vetoing the change.");
ev.Veto();
return;
}
ev.Skip();
}
void GridFrame::OnCellValueChanged( wxGridEvent& ev )
{
int row = ev.GetRow(),
col = ev.GetCol();
wxLogMessage("Value of cell at (%d, %d) changed and is now \"%s\" "
"(was \"%s\")",
row, col,
grid->GetCellValue(row, col), ev.GetString());
ev.Skip();
}
void GridFrame::OnCellBeginDrag( wxGridEvent& ev )
{
wxLogMessage("Got request to drag cell at row %d, col %d",
ev.GetRow(), ev.GetCol());
ev.Skip();
}
void GridFrame::OnEditorShown( wxGridEvent& ev )
{
if ( (ev.GetCol() == 4) &&
(ev.GetRow() == 0) &&
(wxMessageBox("Are you sure you wish to edit this cell",
"Checking",wxYES_NO) == wxNO ) ) {
ev.Veto();
return;
}
wxLogMessage( "Cell editor shown." );
ev.Skip();
}
void GridFrame::OnEditorHidden( wxGridEvent& ev )
{
if ( (ev.GetCol() == 4) &&
(ev.GetRow() == 0) &&
(wxMessageBox("Are you sure you wish to finish editing this cell",
"Checking",wxYES_NO) == wxNO ) ) {
ev.Veto();
return;
}
wxLogMessage( "Cell editor hidden." );
ev.Skip();
}
void GridFrame::About( wxCommandEvent& WXUNUSED(ev) )
{
wxAboutDialogInfo aboutInfo;
aboutInfo.SetName("wxGrid demo");
aboutInfo.SetDescription(_("wxGrid sample program"));
aboutInfo.AddDeveloper("Michael Bedward");
aboutInfo.AddDeveloper("Julian Smart");
aboutInfo.AddDeveloper("Vadim Zeitlin");
// this is just to force the generic version of the about
// dialog under wxMSW so that it's easy to test if the grid
// repaints correctly when it has lost focus and a dialog
// (different from the Windows standard message box -- it doesn't
// work with it for some reason) is moved over it.
aboutInfo.SetWebSite("http://www.wxwidgets.org");
wxAboutBox(aboutInfo, this);
}
void GridFrame::OnQuit( wxCommandEvent& WXUNUSED(ev) )
{
Close( true );
}
void GridFrame::OnBugsTable(wxCommandEvent& )
{
BugsGridFrame *frame = new BugsGridFrame;
frame->Show(true);
}
// ----------------------------------------------------------------------------
// MyGridCellAttrProvider
// ----------------------------------------------------------------------------
MyGridCellAttrProvider::MyGridCellAttrProvider()
{
m_attrForOddRows = new wxGridCellAttr;
m_attrForOddRows->SetBackgroundColour(*wxLIGHT_GREY);
}
MyGridCellAttrProvider::~MyGridCellAttrProvider()
{
m_attrForOddRows->DecRef();
}
wxGridCellAttr *MyGridCellAttrProvider::GetAttr(int row, int col,
wxGridCellAttr::wxAttrKind kind /* = wxGridCellAttr::Any */) const
{
wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row, col, kind);
if ( row % 2 )
{
if ( !attr )
{
attr = m_attrForOddRows;
attr->IncRef();
}
else
{
if ( !attr->HasBackgroundColour() )
{
wxGridCellAttr *attrNew = attr->Clone();
attr->DecRef();
attr = attrNew;
attr->SetBackgroundColour(*wxLIGHT_GREY);
}
}
}
return attr;
}
void GridFrame::OnVTable(wxCommandEvent& )
{
static long s_sizeGrid = 10000;
s_sizeGrid = wxGetNumberFromUser("Size of the table to create",
"Size: ",
"wxGridDemo question",
s_sizeGrid,
0, 32000, this);
if ( s_sizeGrid != -1 )
{
BigGridFrame* win = new BigGridFrame(s_sizeGrid);
win->Show(true);
}
}
// ----------------------------------------------------------------------------
// MyGridCellRenderer
// ----------------------------------------------------------------------------
// do something that the default renderer doesn't here just to show that it is
// possible to alter the appearance of the cell beyond what the attributes
// allow
void MyGridCellRenderer::Draw(wxGrid& grid,
wxGridCellAttr& attr,
wxDC& dc,
const wxRect& rect,
int row, int col,
bool isSelected)
{
wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
dc.SetPen(*wxGREEN_PEN);
dc.SetBrush(*wxTRANSPARENT_BRUSH);
dc.DrawEllipse(rect);
}
// ============================================================================
// BigGridFrame and BigGridTable: Sample of a non-standard table
// ============================================================================
BigGridFrame::BigGridFrame(long sizeGrid)
: wxFrame(NULL, wxID_ANY, "Plugin Virtual Table",
wxDefaultPosition, wxSize(500, 450))
{
m_grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
m_table = new BigGridTable(sizeGrid);
// VZ: I don't understand why this slows down the display that much,
// must profile it...
//m_table->SetAttrProvider(new MyGridCellAttrProvider);
m_grid->SetTable(m_table, true);
#if defined __WXMOTIF__
// MB: the grid isn't getting a sensible default size under wxMotif
int cw, ch;
GetClientSize( &cw, &ch );
m_grid->SetSize( cw, ch );
#endif
}
// ============================================================================
// BugsGridFrame: a "realistic" table
// ============================================================================
// ----------------------------------------------------------------------------
// bugs table data
// ----------------------------------------------------------------------------
enum Columns
{
Col_Id,
Col_Summary,
Col_Severity,
Col_Priority,
Col_Platform,
Col_Opened,
Col_Max
};
enum Severity
{
Sev_Wish,
Sev_Minor,
Sev_Normal,
Sev_Major,
Sev_Critical,
Sev_Max
};
static const wxString severities[] =
{
"wishlist",
"minor",
"normal",
"major",
"critical",
};
static struct BugsGridData
{
int id;
wxString summary;
Severity severity;
int prio;
wxString platform;
bool opened;
} gs_dataBugsGrid [] =
{
{ 18, "foo doesn't work", Sev_Major, 1, "wxMSW", true },
{ 27, "bar crashes", Sev_Critical, 1, "all", false },
{ 45, "printing is slow", Sev_Minor, 3, "wxMSW", true },
{ 68, "Rectangle() fails", Sev_Normal, 1, "wxMSW", false },
};
// ----------------------------------------------------------------------------
// BugsGridTable
// ----------------------------------------------------------------------------
wxString BugsGridTable::GetTypeName(int WXUNUSED(row), int col)
{
switch ( col )
{
case Col_Id:
case Col_Priority:
return wxGRID_VALUE_NUMBER;
case Col_Severity:
// fall thorugh (TODO should be a list)
case Col_Summary:
return wxString::Format("%s:80", wxGRID_VALUE_STRING);
case Col_Platform:
return wxString::Format("%s:all,MSW,GTK,other", wxGRID_VALUE_CHOICE);
case Col_Opened:
return wxGRID_VALUE_BOOL;
}
wxFAIL_MSG("unknown column");
return wxEmptyString;
}
int BugsGridTable::GetNumberRows()
{
return WXSIZEOF(gs_dataBugsGrid);
}
int BugsGridTable::GetNumberCols()
{
return Col_Max;
}
bool BugsGridTable::IsEmptyCell( int WXUNUSED(row), int WXUNUSED(col) )
{
return false;
}
wxString BugsGridTable::GetValue( int row, int col )
{
const BugsGridData& gd = gs_dataBugsGrid[row];
switch ( col )
{
case Col_Id:
return wxString::Format("%d", gd.id);
case Col_Priority:
return wxString::Format("%d", gd.prio);
case Col_Opened:
return gd.opened ? "1" : "0";
case Col_Severity:
return severities[gd.severity];
case Col_Summary:
return gd.summary;
case Col_Platform:
return gd.platform;
}
return wxEmptyString;
}
void BugsGridTable::SetValue( int row, int col, const wxString& value )
{
BugsGridData& gd = gs_dataBugsGrid[row];
switch ( col )
{
case Col_Id:
case Col_Priority:
case Col_Opened:
wxFAIL_MSG("unexpected column");
break;
case Col_Severity:
{
size_t n;
for ( n = 0; n < WXSIZEOF(severities); n++ )
{
if ( severities[n] == value )
{
gd.severity = (Severity)n;
break;
}
}
if ( n == WXSIZEOF(severities) )
{
wxLogWarning("Invalid severity value '%s'.",
value);
gd.severity = Sev_Normal;
}
}
break;
case Col_Summary:
gd.summary = value;
break;
case Col_Platform:
gd.platform = value;
break;
}
}
bool
BugsGridTable::CanGetValueAs(int WXUNUSED(row),
int col,
const wxString& typeName)
{
if ( typeName == wxGRID_VALUE_STRING )
{
return true;
}
else if ( typeName == wxGRID_VALUE_BOOL )
{
return col == Col_Opened;
}
else if ( typeName == wxGRID_VALUE_NUMBER )
{
return col == Col_Id || col == Col_Priority || col == Col_Severity;
}
else
{
return false;
}
}
bool BugsGridTable::CanSetValueAs( int row, int col, const wxString& typeName )
{
return CanGetValueAs(row, col, typeName);
}
long BugsGridTable::GetValueAsLong( int row, int col )
{
const BugsGridData& gd = gs_dataBugsGrid[row];
switch ( col )
{
case Col_Id:
return gd.id;
case Col_Priority:
return gd.prio;
case Col_Severity:
return gd.severity;
default:
wxFAIL_MSG("unexpected column");
return -1;
}
}
bool BugsGridTable::GetValueAsBool( int row, int col )
{
if ( col == Col_Opened )
{
return gs_dataBugsGrid[row].opened;
}
else
{
wxFAIL_MSG("unexpected column");
return false;
}
}
void BugsGridTable::SetValueAsLong( int row, int col, long value )
{
BugsGridData& gd = gs_dataBugsGrid[row];
switch ( col )
{
case Col_Priority:
gd.prio = value;
break;
default:
wxFAIL_MSG("unexpected column");
}
}
void BugsGridTable::SetValueAsBool( int row, int col, bool value )
{
if ( col == Col_Opened )
{
gs_dataBugsGrid[row].opened = value;
}
else
{
wxFAIL_MSG("unexpected column");
}
}
wxString BugsGridTable::GetColLabelValue( int col )
{
static const wxString headers[] = { "Id",
"Summary",
"Severity",
"Priority",
"Platform",
"Opened?" };
return headers[col];
}
// ----------------------------------------------------------------------------
// BugsGridFrame
// ----------------------------------------------------------------------------
BugsGridFrame::BugsGridFrame()
: wxFrame(NULL, wxID_ANY, "Bugs table")
{
wxGrid *grid = new wxGrid(this, wxID_ANY);
wxGridTableBase *table = new BugsGridTable();
table->SetAttrProvider(new MyGridCellAttrProvider);
grid->SetTable(table, true);
wxGridCellAttr *attrRO = new wxGridCellAttr,
*attrRangeEditor = new wxGridCellAttr,
*attrCombo = new wxGridCellAttr;
attrRO->SetReadOnly();
attrRangeEditor->SetEditor(new wxGridCellNumberEditor(1, 5));
attrCombo->SetEditor(new wxGridCellChoiceEditor(WXSIZEOF(severities),
severities));
grid->SetColAttr(Col_Id, attrRO);
grid->SetColAttr(Col_Priority, attrRangeEditor);
grid->SetColAttr(Col_Severity, attrCombo);
grid->Fit();
SetClientSize(grid->GetSize());
}
// ============================================================================
// TabularGrid: grid used for display of tabular data
// ============================================================================
class TabularGridTable : public wxGridTableBase
{
public:
enum
{
COL_NAME,
COL_EXT,
COL_SIZE,
COL_DATE,
COL_MAX
};
enum
{
ROW_MAX = 3
};
TabularGridTable() { m_sortOrder = NULL; }
virtual int GetNumberRows() wxOVERRIDE { return ROW_MAX; }
virtual int GetNumberCols() wxOVERRIDE { return COL_MAX; }
virtual wxString GetValue(int row, int col) wxOVERRIDE
{
if ( m_sortOrder )
row = m_sortOrder[row];
switch ( col )
{
case COL_NAME:
case COL_EXT:
return GetNameOrExt(row, col);
case COL_SIZE:
return wxString::Format("%lu", GetSize(row));
case COL_DATE:
return GetDate(row).FormatDate();
case COL_MAX:
default:
wxFAIL_MSG( "unknown column" );
}
return wxString();
}
virtual void SetValue(int, int, const wxString&) wxOVERRIDE
{
wxFAIL_MSG( "shouldn't be called" );
}
virtual wxString GetColLabelValue(int col) wxOVERRIDE
{
// notice that column parameter here always refers to the internal
// column index, independently of its position on the screen
static const char *labels[] = { "Name", "Extension", "Size", "Date" };
wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, LabelsMismatch );
return labels[col];
}
virtual void SetColLabelValue(int, const wxString&) wxOVERRIDE
{
wxFAIL_MSG( "shouldn't be called" );
}
void Sort(int col, bool ascending)
{
// we hardcode all sorting orders for simplicity here
static int sortOrders[COL_MAX][2][ROW_MAX] =
{
// descending ascending
{ { 2, 1, 0 }, { 0, 1, 2 } },
{ { 2, 1, 0 }, { 0, 1, 2 } },
{ { 2, 1, 0 }, { 0, 1, 2 } },
{ { 1, 0, 2 }, { 2, 0, 1 } },
};
m_sortOrder = col == wxNOT_FOUND ? NULL : sortOrders[col][ascending];
}
private:
wxString GetNameOrExt(int row, int col) const
{
static const char *
names[] = { "autoexec.bat", "boot.ini", "io.sys" };
wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == ROW_MAX, NamesMismatch );
const wxString s(names[row]);
return col == COL_NAME ? s.BeforeFirst('.') : s.AfterLast('.');
}
unsigned long GetSize(int row) const
{
static const unsigned long
sizes[] = { 412, 604, 40774 };
wxCOMPILE_TIME_ASSERT( WXSIZEOF(sizes) == ROW_MAX, SizesMismatch );
return sizes[row];
}
wxDateTime GetDate(int row) const
{
static const char *
dates[] = { "2004-04-17", "2006-05-27", "1994-05-31" };
wxCOMPILE_TIME_ASSERT( WXSIZEOF(dates) == ROW_MAX, DatesMismatch );
wxDateTime dt;
dt.ParseISODate(dates[row]);
return dt;
}
int *m_sortOrder;
};
// specialized text control for column indexes entry
class ColIndexEntry : public wxTextCtrl
{
public:
ColIndexEntry(wxWindow *parent)
: wxTextCtrl(parent, wxID_ANY, "")
{
SetValidator(wxTextValidator(wxFILTER_NUMERIC));
}
int GetCol()
{
unsigned long col;
if ( !GetValue().ToULong(&col) || col > TabularGridTable::COL_MAX )
{
SetFocus();
return -1;
}
return col;
}
protected:
virtual wxSize DoGetBestSize() const wxOVERRIDE
{
wxSize size = wxTextCtrl::DoGetBestSize();
size.x = 3*GetCharWidth();
return size;
}
};
class TabularGridFrame : public wxFrame
{
public:
TabularGridFrame();
private:
enum // control ids
{
Id_Check_UseNativeHeader,
Id_Check_DrawNativeLabels,
Id_Check_ShowRowLabels,
Id_Check_EnableColMove
};
// event handlers
void OnToggleUseNativeHeader(wxCommandEvent&)
{
m_grid->UseNativeColHeader(m_chkUseNative->IsChecked());
}
void OnUpdateDrawNativeLabelsUI(wxUpdateUIEvent& event)
{
// we don't draw labels at all, native or otherwise, if we use the
// native header control
event.Enable( !m_chkUseNative->GetValue() );
}
void OnToggleDrawNativeLabels(wxCommandEvent&)
{
m_grid->SetUseNativeColLabels(m_chkDrawNative->IsChecked());
}
void OnToggleShowRowLabels(wxCommandEvent&)
{
m_grid->SetRowLabelSize(m_chkShowRowLabels->IsChecked()
? wxGRID_AUTOSIZE
: 0);
}
void OnToggleColMove(wxCommandEvent&)
{
m_grid->EnableDragColMove(m_chkEnableColMove->IsChecked());
}
void OnShowHideColumn(wxCommandEvent& event)
{
int col = m_txtColShowHide->GetCol();
if ( col != -1 )
{
m_grid->SetColSize(col,
event.GetId() == wxID_ADD ? wxGRID_AUTOSIZE : 0);
UpdateOrderAndVisibility();
}
}
void OnMoveColumn(wxCommandEvent&)
{
int col = m_txtColIndex->GetCol();
int pos = m_txtColPos->GetCol();
if ( col == -1 || pos == -1 )
return;
m_grid->SetColPos(col, pos);
UpdateOrderAndVisibility();
}
void OnResetColumnOrder(wxCommandEvent&)
{
m_grid->ResetColPos();
UpdateOrderAndVisibility();
}
void OnGridColSort(wxGridEvent& event)
{
const int col = event.GetCol();
m_table->Sort(col, !(m_grid->IsSortingBy(col) &&
m_grid->IsSortOrderAscending()));
}
void OnGridColMove(wxGridEvent& event)
{
// can't update it yet as the order hasn't been changed, so do it a bit
// later
m_shouldUpdateOrder = true;
event.Skip();
}
void OnGridColSize(wxGridSizeEvent& event)
{
// we only catch this event to react to the user showing or hiding this
// column using the header control menu and not because we're
// interested in column resizing
UpdateOrderAndVisibility();
event.Skip();
}
void OnIdle(wxIdleEvent& event)
{
if ( m_shouldUpdateOrder )
{
m_shouldUpdateOrder = false;
UpdateOrderAndVisibility();
}
event.Skip();
}
void UpdateOrderAndVisibility()
{
wxString s;
for ( int pos = 0; pos < TabularGridTable::COL_MAX; pos++ )
{
const int col = m_grid->GetColAt(pos);
const bool isHidden = m_grid->GetColSize(col) == 0;
if ( isHidden )
s << '[';
s << col;
if ( isHidden )
s << ']';
s << ' ';
}
m_statOrder->SetLabel(s);
}
// controls
wxGrid *m_grid;
TabularGridTable *m_table;
wxCheckBox *m_chkUseNative,
*m_chkDrawNative,
*m_chkShowRowLabels,
*m_chkEnableColMove;
ColIndexEntry *m_txtColIndex,
*m_txtColPos,
*m_txtColShowHide;
wxStaticText *m_statOrder;
// fla for EVT_IDLE handler
bool m_shouldUpdateOrder;
wxDECLARE_NO_COPY_CLASS(TabularGridFrame);
wxDECLARE_EVENT_TABLE();
};
wxBEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
EVT_CHECKBOX(Id_Check_UseNativeHeader,
TabularGridFrame::OnToggleUseNativeHeader)
EVT_CHECKBOX(Id_Check_DrawNativeLabels,
TabularGridFrame::OnToggleDrawNativeLabels)
EVT_CHECKBOX(Id_Check_ShowRowLabels,
TabularGridFrame::OnToggleShowRowLabels)
EVT_CHECKBOX(Id_Check_EnableColMove,
TabularGridFrame::OnToggleColMove)
EVT_UPDATE_UI(Id_Check_DrawNativeLabels,
TabularGridFrame::OnUpdateDrawNativeLabelsUI)
EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
EVT_BUTTON(wxID_RESET, TabularGridFrame::OnResetColumnOrder)
EVT_BUTTON(wxID_ADD, TabularGridFrame::OnShowHideColumn)
EVT_BUTTON(wxID_DELETE, TabularGridFrame::OnShowHideColumn)
EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
EVT_GRID_COL_SIZE(TabularGridFrame::OnGridColSize)
EVT_IDLE(TabularGridFrame::OnIdle)
wxEND_EVENT_TABLE()
TabularGridFrame::TabularGridFrame()
: wxFrame(NULL, wxID_ANY, "Tabular table")
{
m_shouldUpdateOrder = false;
wxPanel * const panel = new wxPanel(this);
// create and initialize the grid with the specified data
m_table = new TabularGridTable;
m_grid = new wxGrid(panel, wxID_ANY,
wxDefaultPosition, wxDefaultSize,
wxBORDER_STATIC | wxWANTS_CHARS);
m_grid->SetTable(m_table, true, wxGrid::wxGridSelectRows);
m_grid->EnableDragColMove();
m_grid->UseNativeColHeader();
m_grid->HideRowLabels();
// add it and the other controls to the frame
wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
sizerTop->Add(m_grid, wxSizerFlags(1).Expand().Border());
wxSizer * const sizerControls = new wxBoxSizer(wxHORIZONTAL);
wxSizer * const sizerStyles = new wxBoxSizer(wxVERTICAL);
m_chkUseNative = new wxCheckBox(panel, Id_Check_UseNativeHeader,
"&Use native header");
m_chkUseNative->SetValue(true);
sizerStyles->Add(m_chkUseNative, wxSizerFlags().Border());
m_chkDrawNative = new wxCheckBox(panel, Id_Check_DrawNativeLabels,
"&Draw native column labels");
sizerStyles->Add(m_chkDrawNative, wxSizerFlags().Border());
m_chkShowRowLabels = new wxCheckBox(panel, Id_Check_ShowRowLabels,
"Show &row labels");
sizerStyles->Add(m_chkShowRowLabels, wxSizerFlags().Border());
m_chkEnableColMove = new wxCheckBox(panel, Id_Check_EnableColMove,
"Allow column re&ordering");
m_chkEnableColMove->SetValue(true);
sizerStyles->Add(m_chkEnableColMove, wxSizerFlags().Border());
sizerControls->Add(sizerStyles);
sizerControls->AddSpacer(10);
wxSizer * const sizerColumns = new wxBoxSizer(wxVERTICAL);
wxSizer * const sizerMoveCols = new wxBoxSizer(wxHORIZONTAL);
const wxSizerFlags
flagsHorz(wxSizerFlags().Border(wxLEFT | wxRIGHT).Centre());
sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&Move column"),
flagsHorz);
m_txtColIndex = new ColIndexEntry(panel);
sizerMoveCols->Add(m_txtColIndex, flagsHorz);
sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&to"), flagsHorz);
m_txtColPos = new ColIndexEntry(panel);
sizerMoveCols->Add(m_txtColPos, flagsHorz);
sizerMoveCols->Add(new wxButton(panel, wxID_APPLY), flagsHorz);
sizerColumns->Add(sizerMoveCols, wxSizerFlags().Expand().Border(wxBOTTOM));
wxSizer * const sizerShowCols = new wxBoxSizer(wxHORIZONTAL);
sizerShowCols->Add(new wxStaticText(panel, wxID_ANY, "Current order:"),
flagsHorz);
m_statOrder = new wxStaticText(panel, wxID_ANY, "<<< default >>>");
sizerShowCols->Add(m_statOrder, flagsHorz);
sizerShowCols->Add(new wxButton(panel, wxID_RESET, "&Reset order"));
sizerColumns->Add(sizerShowCols, wxSizerFlags().Expand().Border(wxTOP));
wxSizer * const sizerShowHide = new wxBoxSizer(wxHORIZONTAL);
sizerShowHide->Add(new wxStaticText(panel, wxID_ANY, "Show/hide column:"),
flagsHorz);
m_txtColShowHide = new ColIndexEntry(panel);
sizerShowHide->Add(m_txtColShowHide, flagsHorz);
sizerShowHide->Add(new wxButton(panel, wxID_ADD, "&Show"), flagsHorz);
sizerShowHide->Add(new wxButton(panel, wxID_DELETE, "&Hide"), flagsHorz);
sizerColumns->Add(sizerShowHide, wxSizerFlags().Expand().Border(wxTOP));
sizerControls->Add(sizerColumns, wxSizerFlags(1).Expand().Border());
sizerTop->Add(sizerControls, wxSizerFlags().Expand().Border());
panel->SetSizer(sizerTop);
SetClientSize(panel->GetBestSize());
SetSizeHints(GetSize());
Show();
}
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 sizeOffset( 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;
sizeOffset.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 = FindWindowByName( "frameRender" );
if ( win )
win->Destroy();
// create a frame large enough for the rendered bitmap
wxFrame* frame = new wxFrame( this, wxID_ANY, "Grid Render" );
frame->SetClientSize( sizeRender + sizeOffset * 2 );
frame->SetName( "frameRender" );
wxPanel* canvas = new wxPanel( frame, wxID_ANY );
// make a bitmap large enough for any top/left offset
wxBitmap bmp( sizeRender + sizeOffset );
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->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 );
}
void GridFrame::HideCol( wxCommandEvent& WXUNUSED(event) )
{
grid->HideCol(0);
}
void GridFrame::ShowCol( wxCommandEvent& WXUNUSED(event) )
{
grid->ShowCol(0);
}
void GridFrame::HideRow( wxCommandEvent& WXUNUSED(event) )
{
grid->HideRow(1);
}
void GridFrame::ShowRow( wxCommandEvent& WXUNUSED(event) )
{
grid->ShowRow(1);
}