wxWidgets/samples/grid/griddemo.cpp
Vadim Zeitlin cfbc15ee04 Allow changing horizontal alignment of numeric cells in wxGrid.
wxGridCellAttr didn't provide any way to query its alignment attributes
without falling back to the (always defined) default alignment so the code in
wxGridCellNumberRenderer and similar classes simply always used right
alignment,

Add a new wxGridCellAttr::GetNonDefaultAlignment() function which allows to
retrieve the alignment defined in the attribute and use it to use right
alignment by default but allow overriding it.

Add a test to the sample showing a non right-aligned numeric cell.

Incidentally fix a long-standing bug in wxGridCell{DateTime,Enum}Renderers
which used wxRIGHT instead of wxALIGN_RIGHT and so were not aligned properly
even by default.

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@62728 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
2009-11-27 01:47:38 +00:00

2139 lines
62 KiB
C++

/////////////////////////////////////////////////////////////////////////////
// Name: griddemo.cpp
// Purpose: Grid control wxWidgets sample
// Author: Michael Bedward
// Modified by: Santiago Palacios
// RCS-ID: $Id$
// Copyright: (c) Michael Bedward, Julian Smart, Vadim Zeitlin
// Licence: wxWindows license
/////////////////////////////////////////////////////////////////////////////
// ============================================================================
// 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 __WXMSW__
#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
// ----------------------------------------------------------------------------
IMPLEMENT_APP( GridApp )
// ============================================================================
// implementation
// ============================================================================
// ----------------------------------------------------------------------------
// GridApp
// ----------------------------------------------------------------------------
bool GridApp::OnInit()
{
GridFrame *frame = new GridFrame;
frame->Show(true);
return true;
}
// ----------------------------------------------------------------------------
// GridFrame
// ----------------------------------------------------------------------------
BEGIN_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_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
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 )
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_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_SELCELLS, GridFrame::SelectCells )
EVT_MENU( ID_SELROWS, GridFrame::SelectRows )
EVT_MENU( ID_SELCOLS, GridFrame::SelectCols )
EVT_MENU( ID_SELROWSORCOLS, GridFrame::SelectRowsOrCols )
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_SHOW_SELECTION, GridFrame::OnShowSelection)
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_SET_HIGHLIGHT_WIDTH, GridFrame::OnSetHighlightWidth)
EVT_MENU( ID_SET_RO_HIGHLIGHT_WIDTH, GridFrame::OnSetROHighlightWidth)
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_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 )
END_EVENT_TABLE()
GridFrame::GridFrame()
: wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxWidgets grid class demo"),
wxDefaultPosition,
wxDefaultSize )
{
SetIcon(wxICON(sample));
wxMenu *fileMenu = new wxMenu;
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();
fileMenu->Append( wxID_EXIT, wxT("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_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)");
wxMenu *rowLabelMenu = new wxMenu;
viewMenu->Append( ID_ROWLABELALIGN, wxT("R&ow label alignment"),
rowLabelMenu,
wxT("Change alignment of row labels") );
rowLabelMenu->AppendRadioItem( ID_ROWLABELHORIZALIGN, wxT("&Horizontal") );
rowLabelMenu->AppendRadioItem( ID_ROWLABELVERTALIGN, wxT("&Vertical") );
wxMenu *colLabelMenu = new wxMenu;
viewMenu->Append( ID_COLLABELALIGN, wxT("Col l&abel alignment"),
colLabelMenu,
wxT("Change alignment of col labels") );
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...") );
colMenu->Append( ID_SETLABELTEXTCOLOUR, wxT("Set label &text colour...") );
colMenu->Append( ID_SETLABEL_FONT, wxT("Set label fo&nt...") );
colMenu->Append( ID_GRIDLINECOLOUR, wxT("&Grid line colour...") );
colMenu->Append( ID_SET_CELL_FG_COLOUR, wxT("Set cell &foreground colour...") );
colMenu->Append( ID_SET_CELL_BG_COLOUR, wxT("Set cell &background colour...") );
wxMenu *editMenu = new wxMenu;
editMenu->Append( ID_INSERTROW, wxT("Insert &row") );
editMenu->Append( ID_INSERTCOL, wxT("Insert &column") );
editMenu->Append( ID_DELETEROW, wxT("Delete selected ro&ws") );
editMenu->Append( ID_DELETECOL, wxT("Delete selected co&ls") );
editMenu->Append( ID_CLEARGRID, wxT("Cl&ear grid cell contents") );
wxMenu *selectMenu = new wxMenu;
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"));
selectMenu->Append( ID_SELECT_COL, wxT("Select col 2"));
selectMenu->Append( ID_SELECT_CELL, wxT("Select cell (3, 1)"));
selectMenu->AppendSeparator();
selectMenu->Append( ID_DESELECT_ALL, wxT("Deselect all"));
selectMenu->Append( ID_DESELECT_ROW, wxT("Deselect row 2"));
selectMenu->Append( ID_DESELECT_COL, wxT("Deselect col 2"));
selectMenu->Append( ID_DESELECT_CELL, wxT("Deselect cell (3, 1)"));
wxMenu *selectionMenu = new wxMenu;
selectMenu->Append( ID_CHANGESEL, wxT("Change &selection mode"),
selectionMenu,
wxT("Change selection mode") );
selectionMenu->Append( ID_SELCELLS, wxT("Select &cells") );
selectionMenu->Append( ID_SELROWS, wxT("Select &rows") );
selectionMenu->Append( ID_SELCOLS, wxT("Select col&umns") );
selectionMenu->Append( ID_SELROWSORCOLS, wxT("Select rows &or columns") );
wxMenu *autosizeMenu = new wxMenu;
autosizeMenu->Append( ID_SIZE_ROW, wxT("Selected &row data") );
autosizeMenu->Append( ID_SIZE_COL, wxT("Selected &column data") );
autosizeMenu->Append( ID_SIZE_ROW_LABEL, wxT("Selected row la&bel") );
autosizeMenu->Append( ID_SIZE_COL_LABEL, wxT("Selected column &label") );
autosizeMenu->Append( ID_SIZE_LABELS_COL, wxT("Column la&bels") );
autosizeMenu->Append( ID_SIZE_LABELS_ROW, wxT("Row label&s") );
autosizeMenu->Append( ID_SIZE_GRID, wxT("Entire &grid") );
wxMenu *helpMenu = new wxMenu;
helpMenu->Append( wxID_ABOUT, wxT("&About wxGrid demo") );
wxMenuBar *menuBar = new wxMenuBar;
menuBar->Append( fileMenu, wxT("&File") );
menuBar->Append( viewMenu, wxT("&Grid") );
menuBar->Append( colMenu, wxT("&Colours") );
menuBar->Append( editMenu, wxT("&Edit") );
menuBar->Append( selectMenu, wxT("&Select") );
menuBar->Append( autosizeMenu, wxT("&Autosize") );
menuBar->Append( helpMenu, wxT("&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, wxT("Ctrl+Home\nwill go to\nthis cell") );
grid->SetCellValue( 0, 1, wxT("A long piece of text to demonstrate wrapping.") );
grid->SetCellRenderer(0 , 1, new wxGridCellAutoWrapStringRenderer);
grid->SetCellEditor( 0, 1 , new wxGridCellAutoWrapStringEditor);
grid->SetCellValue( 0, 2, wxT("Blah") );
grid->SetCellValue( 0, 3, wxT("Read only") );
grid->SetReadOnly( 0, 3 );
grid->SetCellValue( 0, 4, wxT("Can veto edit this cell") );
grid->SetCellValue( 0, 5, wxT("Press\nCtrl+arrow\nto skip over\ncells") );
grid->SetRowSize( 99, 60 );
grid->SetCellValue( 99, 99, wxT("Ctrl+End\nwill go to\nthis cell") );
grid->SetCellValue( 1, 0, wxT("This default cell will overflow into neighboring cells, but not if you turn overflow off."));
grid->SetCellTextColour(1, 2, *wxRED);
grid->SetCellBackgroundColour(1, 2, *wxGREEN);
grid->SetCellValue( 1, 4, wxT("I'm in the middle"));
grid->SetCellValue(2, 2, wxT("red"));
grid->SetCellTextColour(2, 2, *wxRED);
grid->SetCellValue(3, 3, wxT("green on grey"));
grid->SetCellTextColour(3, 3, *wxGREEN);
grid->SetCellBackgroundColour(3, 3, *wxLIGHT_GREY);
grid->SetCellValue(4, 4, wxT("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);
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, wxT("a wider column"));
grid->SetColSize(4, 120);
grid->SetColMinimalWidth(4, 120);
grid->SetCellTextColour(5, 8, *wxGREEN);
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"));
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->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->SetCellAlignment(2, 8, wxALIGN_CENTRE, wxALIGN_TOP);
grid->SetCellValue(2, 9, "<- This numeric cell should be centred");
const wxString choices[] =
{
wxT("Please select a choice"),
wxT("This takes two cells"),
wxT("Another choice"),
};
grid->SetCellEditor(4, 0, new wxGridCellChoiceEditor(WXSIZEOF(choices), choices));
grid->SetCellSize(4, 0, 1, 2);
grid->SetCellValue(4, 0, choices[0]);
grid->SetCellOverflow(4, 0, false);
grid->SetCellSize(7, 1, 3, 4);
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
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);
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_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::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->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(
GetMenuBar()->IsChecked( ID_TOGGLEGRIDLINES ) );
}
void GridFrame::OnSetHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
{
wxString choices[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
wxT("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[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
wxT("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.Ok() )
{
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::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();
}
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::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::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColour col = wxGetColourFromUser(this);
if ( col.Ok() )
{
grid->SetDefaultCellTextColour(col);
grid->Refresh();
}
}
void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
{
wxColour col = wxGetColourFromUser(this);
if ( col.Ok() )
{
// 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 << wxT("Left click on row label ") << ev.GetRow();
}
else if ( ev.GetCol() != -1 )
{
logBuf << wxT("Left click on col label ") << ev.GetCol();
}
else
{
logBuf << wxT("Left click on corner label");
}
if ( ev.ShiftDown() )
logBuf << wxT(" (shift down)");
if ( ev.ControlDown() )
logBuf << wxT(" (control down)");
wxLogMessage( wxT("%s"), logBuf.c_str() );
// you must call event skip if you want default grid processing
//
ev.Skip();
}
void GridFrame::OnCellLeftClick( wxGridEvent& ev )
{
wxLogMessage(wxT("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::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;
if ( ev.Selecting() )
logBuf << wxT("Selected ");
else
logBuf << wxT("Deselected ");
logBuf << wxT("cell at row ") << ev.GetRow()
<< wxT(" col ") << ev.GetCol()
<< wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
<< wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
<< wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
<< wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
//Indicate whether this column was moved
if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
logBuf << wxT(" *** Column moved, current position: ") << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
wxLogMessage( wxT("%s"), logBuf.c_str() );
// 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 << wxT("Selected ");
else
logBuf << wxT("Deselected ");
logBuf << wxT("cells from row ") << ev.GetTopRow()
<< wxT(" col ") << ev.GetLeftCol()
<< wxT(" to row ") << ev.GetBottomRow()
<< wxT(" col ") << ev.GetRightCol()
<< wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
<< wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
<< wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
<< wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
wxLogMessage( wxT("%s"), logBuf.c_str() );
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(wxT("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(wxT("Are you sure you wish to edit this cell"),
wxT("Checking"),wxYES_NO) == wxNO ) ) {
ev.Veto();
return;
}
wxLogMessage( wxT("Cell editor shown.") );
ev.Skip();
}
void GridFrame::OnEditorHidden( wxGridEvent& ev )
{
if ( (ev.GetCol() == 4) &&
(ev.GetRow() == 0) &&
(wxMessageBox(wxT("Are you sure you wish to finish editing this cell"),
wxT("Checking"),wxYES_NO) == wxNO ) ) {
ev.Veto();
return;
}
wxLogMessage( wxT("Cell editor hidden.") );
ev.Skip();
}
void GridFrame::About( wxCommandEvent& WXUNUSED(ev) )
{
wxAboutDialogInfo aboutInfo;
aboutInfo.SetName(wxT("wxGrid demo"));
aboutInfo.SetDescription(_("wxGrid sample program"));
aboutInfo.AddDeveloper(wxT("Michael Bedward"));
aboutInfo.AddDeveloper(wxT("Julian Smart"));
aboutInfo.AddDeveloper(wxT("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(wxT("http://www.wxwidgets.org"));
wxAboutBox(aboutInfo);
}
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(wxT("Size of the table to create"),
wxT("Size: "),
wxT("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, wxT("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[] =
{
wxT("wishlist"),
wxT("minor"),
wxT("normal"),
wxT("major"),
wxT("critical"),
};
static struct BugsGridData
{
int id;
wxChar summary[80];
Severity severity;
int prio;
wxChar platform[12];
bool opened;
} gs_dataBugsGrid [] =
{
{ 18, wxT("foo doesn't work"), Sev_Major, 1, wxT("wxMSW"), true },
{ 27, wxT("bar crashes"), Sev_Critical, 1, wxT("all"), false },
{ 45, wxT("printing is slow"), Sev_Minor, 3, wxT("wxMSW"), true },
{ 68, wxT("Rectangle() fails"), Sev_Normal, 1, wxT("wxMSW"), false },
};
static const wxChar *headers[Col_Max] =
{
wxT("Id"),
wxT("Summary"),
wxT("Severity"),
wxT("Priority"),
wxT("Platform"),
wxT("Opened?"),
};
// ----------------------------------------------------------------------------
// 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(wxT("%s:80"), wxGRID_VALUE_STRING);
case Col_Platform:
return wxString::Format(wxT("%s:all,MSW,GTK,other"), wxGRID_VALUE_CHOICE);
case Col_Opened:
return wxGRID_VALUE_BOOL;
}
wxFAIL_MSG(wxT("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(wxT("%d"), gd.id);
case Col_Priority:
return wxString::Format(wxT("%d"), gd.prio);
case Col_Opened:
return gd.opened ? wxT("1") : wxT("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(wxT("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(wxT("Invalid severity value '%s'."),
value.c_str());
gd.severity = Sev_Normal;
}
}
break;
case Col_Summary:
wxStrncpy(gd.summary, value, WXSIZEOF(gd.summary));
break;
case Col_Platform:
wxStrncpy(gd.platform, value, WXSIZEOF(gd.platform));
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(wxT("unexpected column"));
return -1;
}
}
bool BugsGridTable::GetValueAsBool( int row, int col )
{
if ( col == Col_Opened )
{
return gs_dataBugsGrid[row].opened;
}
else
{
wxFAIL_MSG(wxT("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(wxT("unexpected column"));
}
}
void BugsGridTable::SetValueAsBool( int row, int col, bool value )
{
if ( col == Col_Opened )
{
gs_dataBugsGrid[row].opened = value;
}
else
{
wxFAIL_MSG(wxT("unexpected column"));
}
}
wxString BugsGridTable::GetColLabelValue( int col )
{
return headers[col];
}
// ----------------------------------------------------------------------------
// BugsGridFrame
// ----------------------------------------------------------------------------
BugsGridFrame::BugsGridFrame()
: wxFrame(NULL, wxID_ANY, wxT("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() { return ROW_MAX; }
virtual int GetNumberCols() { return COL_MAX; }
virtual wxString GetValue(int row, int col)
{
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&)
{
wxFAIL_MSG( "shouldn't be called" );
}
virtual wxString GetColLabelValue(int col)
{
// 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&)
{
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
{
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);
DECLARE_EVENT_TABLE()
};
BEGIN_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)
END_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;
}