]> git.saurik.com Git - wxWidgets.git/blame - samples/grid/griddemo.cpp
remove TestTimer() (adds nothing to existing tests) and move wxStopWatch tests to...
[wxWidgets.git] / samples / grid / griddemo.cpp
CommitLineData
f7556ff0
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: griddemo.cpp
be5a51fb 3// Purpose: Grid control wxWidgets sample
f7556ff0 4// Author: Michael Bedward
d4175745 5// Modified by: Santiago Palacios
f7556ff0 6// RCS-ID: $Id$
e9a67fc2 7// Copyright: (c) Michael Bedward, Julian Smart, Vadim Zeitlin
f7556ff0
JS
8// Licence: wxWindows license
9/////////////////////////////////////////////////////////////////////////////
10
11// ============================================================================
12// declarations
13// ============================================================================
14
15// ----------------------------------------------------------------------------
16// headers
17// ----------------------------------------------------------------------------
18
f7556ff0
JS
19// For compilers that support precompilation, includes "wx/wx.h".
20#include "wx/wxprec.h"
21
22#ifdef __BORLANDC__
23#pragma hdrstop
24#endif
25
26#ifndef WX_PRECOMP
27 #include "wx/wx.h"
28#endif
29
30#include "wx/colordlg.h"
31#include "wx/fontdlg.h"
af870ed8 32#include "wx/numdlg.h"
7dfb6dc4 33#include "wx/aboutdlg.h"
f7556ff0
JS
34
35#include "wx/grid.h"
e8f25dbb 36#include "wx/headerctrl.h"
f7556ff0 37#include "wx/generic/gridctrl.h"
85fe9f6f 38#include "wx/generic/grideditors.h"
f7556ff0
JS
39
40#include "griddemo.h"
41
41f02b9a
FM
42#ifndef __WXMSW__
43 #include "../sample.xpm"
44#endif
45
ba9574c3
VZ
46// Custom renderer that renders column header cells without borders and in
47// italic
48class CustomColumnHeaderRenderer : public wxGridColumnHeaderRenderer
49{
50public:
51 CustomColumnHeaderRenderer(const wxColour& colFg, const wxColour& colBg)
52 : m_colFg(colFg),
53 m_colBg(colBg)
54 {
55 }
56
57 virtual void DrawLabel(const wxGrid& WXUNUSED(grid),
58 wxDC& dc,
59 const wxString& value,
60 const wxRect& rect,
61 int horizAlign,
62 int vertAlign,
63 int WXUNUSED(textOrientation)) const
64 {
65 dc.SetTextForeground(m_colFg);
66 dc.SetFont(wxITALIC_FONT->Bold());
67 dc.DrawLabel(value, rect, horizAlign | vertAlign);
68 }
69
70 virtual void DrawBorder(const wxGrid& WXUNUSED(grid),
71 wxDC& dc,
72 wxRect& rect) const
73 {
74 dc.SetPen(*wxTRANSPARENT_PEN);
75 dc.SetBrush(wxBrush(m_colBg));
76 dc.DrawRectangle(rect);
77 }
78
79private:
80 const wxColour m_colFg, m_colBg;
81
82 wxDECLARE_NO_COPY_CLASS(CustomColumnHeaderRenderer);
83};
84
85// And a custom attributes provider which uses custom column header renderer
86// defined above
87class CustomColumnHeadersProvider : public wxGridCellAttrProvider
88{
89public:
90 // by default custom column renderer is not used, call
91 // UseCustomColHeaders() to enable it
92 CustomColumnHeadersProvider()
93 : m_customOddRenderer(*wxYELLOW, *wxBLUE),
94 m_customEvenRenderer(*wxWHITE, *wxBLACK),
95 m_useCustom(false)
96 {
97 }
98
99 // enable or disable the use of custom renderer for column headers
100 void UseCustomColHeaders(bool use = true) { m_useCustom = use; }
101
102protected:
103 virtual const wxGridColumnHeaderRenderer& GetColumnHeaderRenderer(int col)
104 {
105 // if enabled, use custom renderers
106 if ( m_useCustom )
107 {
108 // and use different ones for odd and even columns -- just to show
109 // that we can
110 return col % 2 ? m_customOddRenderer : m_customEvenRenderer;
111 }
112
113 return wxGridCellAttrProvider::GetColumnHeaderRenderer(col);
114 }
115
116private:
117 CustomColumnHeaderRenderer m_customOddRenderer,
118 m_customEvenRenderer;
119
120 bool m_useCustom;
121
122 wxDECLARE_NO_COPY_CLASS(CustomColumnHeadersProvider);
123};
124
f7556ff0
JS
125// ----------------------------------------------------------------------------
126// wxWin macros
127// ----------------------------------------------------------------------------
128
129IMPLEMENT_APP( GridApp )
130
131// ============================================================================
132// implementation
133// ============================================================================
134
135// ----------------------------------------------------------------------------
136// GridApp
137// ----------------------------------------------------------------------------
138
139bool GridApp::OnInit()
140{
141 GridFrame *frame = new GridFrame;
af870ed8 142 frame->Show(true);
f7556ff0 143
af870ed8 144 return true;
f7556ff0
JS
145}
146
147// ----------------------------------------------------------------------------
148// GridFrame
149// ----------------------------------------------------------------------------
150
151BEGIN_EVENT_TABLE( GridFrame, wxFrame )
152 EVT_MENU( ID_TOGGLEROWLABELS, GridFrame::ToggleRowLabels )
153 EVT_MENU( ID_TOGGLECOLLABELS, GridFrame::ToggleColLabels )
154 EVT_MENU( ID_TOGGLEEDIT, GridFrame::ToggleEditing )
155 EVT_MENU( ID_TOGGLEROWSIZING, GridFrame::ToggleRowSizing )
156 EVT_MENU( ID_TOGGLECOLSIZING, GridFrame::ToggleColSizing )
d4175745 157 EVT_MENU( ID_TOGGLECOLMOVING, GridFrame::ToggleColMoving )
f7556ff0 158 EVT_MENU( ID_TOGGLEGRIDSIZING, GridFrame::ToggleGridSizing )
79dbea21 159 EVT_MENU( ID_TOGGLEGRIDDRAGCELL, GridFrame::ToggleGridDragCell )
ba9574c3
VZ
160 EVT_MENU( ID_COLNATIVEHEADER, GridFrame::SetNativeColHeader )
161 EVT_MENU( ID_COLDEFAULTHEADER, GridFrame::SetDefaultColHeader )
162 EVT_MENU( ID_COLCUSTOMHEADER, GridFrame::SetCustomColHeader )
f7556ff0
JS
163 EVT_MENU( ID_TOGGLEGRIDLINES, GridFrame::ToggleGridLines )
164 EVT_MENU( ID_AUTOSIZECOLS, GridFrame::AutoSizeCols )
165 EVT_MENU( ID_CELLOVERFLOW, GridFrame::CellOverflow )
166 EVT_MENU( ID_RESIZECELL, GridFrame::ResizeCell )
167 EVT_MENU( ID_SETLABELCOLOUR, GridFrame::SetLabelColour )
168 EVT_MENU( ID_SETLABELTEXTCOLOUR, GridFrame::SetLabelTextColour )
169 EVT_MENU( ID_SETLABEL_FONT, GridFrame::SetLabelFont )
170 EVT_MENU( ID_ROWLABELHORIZALIGN, GridFrame::SetRowLabelHorizAlignment )
171 EVT_MENU( ID_ROWLABELVERTALIGN, GridFrame::SetRowLabelVertAlignment )
172 EVT_MENU( ID_COLLABELHORIZALIGN, GridFrame::SetColLabelHorizAlignment )
173 EVT_MENU( ID_COLLABELVERTALIGN, GridFrame::SetColLabelVertAlignment )
174 EVT_MENU( ID_GRIDLINECOLOUR, GridFrame::SetGridLineColour )
175 EVT_MENU( ID_INSERTROW, GridFrame::InsertRow )
176 EVT_MENU( ID_INSERTCOL, GridFrame::InsertCol )
177 EVT_MENU( ID_DELETEROW, GridFrame::DeleteSelectedRows )
178 EVT_MENU( ID_DELETECOL, GridFrame::DeleteSelectedCols )
179 EVT_MENU( ID_CLEARGRID, GridFrame::ClearGrid )
180 EVT_MENU( ID_SELCELLS, GridFrame::SelectCells )
181 EVT_MENU( ID_SELROWS, GridFrame::SelectRows )
182 EVT_MENU( ID_SELCOLS, GridFrame::SelectCols )
8a3e536c 183 EVT_MENU( ID_SELROWSORCOLS, GridFrame::SelectRowsOrCols )
f7556ff0
JS
184
185 EVT_MENU( ID_SET_CELL_FG_COLOUR, GridFrame::SetCellFgColour )
186 EVT_MENU( ID_SET_CELL_BG_COLOUR, GridFrame::SetCellBgColour )
187
91b07357 188 EVT_MENU( wxID_ABOUT, GridFrame::About )
f7556ff0
JS
189 EVT_MENU( wxID_EXIT, GridFrame::OnQuit )
190 EVT_MENU( ID_VTABLE, GridFrame::OnVTable)
191 EVT_MENU( ID_BUGS_TABLE, GridFrame::OnBugsTable)
e7ae8a69 192 EVT_MENU( ID_TABULAR_TABLE, GridFrame::OnTabularTable)
f7556ff0
JS
193
194 EVT_MENU( ID_DESELECT_CELL, GridFrame::DeselectCell)
195 EVT_MENU( ID_DESELECT_COL, GridFrame::DeselectCol)
196 EVT_MENU( ID_DESELECT_ROW, GridFrame::DeselectRow)
197 EVT_MENU( ID_DESELECT_ALL, GridFrame::DeselectAll)
198 EVT_MENU( ID_SELECT_CELL, GridFrame::SelectCell)
199 EVT_MENU( ID_SELECT_COL, GridFrame::SelectCol)
200 EVT_MENU( ID_SELECT_ROW, GridFrame::SelectRow)
201 EVT_MENU( ID_SELECT_ALL, GridFrame::SelectAll)
202 EVT_MENU( ID_SELECT_UNSELECT, GridFrame::OnAddToSelectToggle)
1ecf2613 203 EVT_MENU( ID_SHOW_SELECTION, GridFrame::OnShowSelection)
f7556ff0 204
733f486a
VZ
205 EVT_MENU( ID_SIZE_ROW, GridFrame::AutoSizeRow )
206 EVT_MENU( ID_SIZE_COL, GridFrame::AutoSizeCol )
207 EVT_MENU( ID_SIZE_ROW_LABEL, GridFrame::AutoSizeRowLabel )
208 EVT_MENU( ID_SIZE_COL_LABEL, GridFrame::AutoSizeColLabel )
209 EVT_MENU( ID_SIZE_LABELS_COL, GridFrame::AutoSizeLabelsCol )
210 EVT_MENU( ID_SIZE_LABELS_ROW, GridFrame::AutoSizeLabelsRow )
211 EVT_MENU( ID_SIZE_GRID, GridFrame::AutoSizeTable )
212
f7556ff0
JS
213 EVT_MENU( ID_SET_HIGHLIGHT_WIDTH, GridFrame::OnSetHighlightWidth)
214 EVT_MENU( ID_SET_RO_HIGHLIGHT_WIDTH, GridFrame::OnSetROHighlightWidth)
215
216 EVT_GRID_LABEL_LEFT_CLICK( GridFrame::OnLabelLeftClick )
217 EVT_GRID_CELL_LEFT_CLICK( GridFrame::OnCellLeftClick )
218 EVT_GRID_ROW_SIZE( GridFrame::OnRowSize )
219 EVT_GRID_COL_SIZE( GridFrame::OnColSize )
220 EVT_GRID_SELECT_CELL( GridFrame::OnSelectCell )
221 EVT_GRID_RANGE_SELECT( GridFrame::OnRangeSelected )
763163a8 222 EVT_GRID_CELL_CHANGING( GridFrame::OnCellValueChanging )
48715f60 223 EVT_GRID_CELL_CHANGED( GridFrame::OnCellValueChanged )
79dbea21 224 EVT_GRID_CELL_BEGIN_DRAG( GridFrame::OnCellBeginDrag )
f7556ff0
JS
225
226 EVT_GRID_EDITOR_SHOWN( GridFrame::OnEditorShown )
227 EVT_GRID_EDITOR_HIDDEN( GridFrame::OnEditorHidden )
228END_EVENT_TABLE()
229
230
231GridFrame::GridFrame()
9a83f860 232 : wxFrame( (wxFrame *)NULL, wxID_ANY, wxT("wxWidgets grid class demo"),
f7556ff0
JS
233 wxDefaultPosition,
234 wxDefaultSize )
235{
41f02b9a
FM
236 SetIcon(wxICON(sample));
237
f7556ff0 238 wxMenu *fileMenu = new wxMenu;
9a83f860
VZ
239 fileMenu->Append( ID_VTABLE, wxT("&Virtual table test\tCtrl-V"));
240 fileMenu->Append( ID_BUGS_TABLE, wxT("&Bugs table test\tCtrl-B"));
241 fileMenu->Append( ID_TABULAR_TABLE, wxT("&Tabular table test\tCtrl-T"));
f7556ff0 242 fileMenu->AppendSeparator();
9a83f860 243 fileMenu->Append( wxID_EXIT, wxT("E&xit\tAlt-X") );
f7556ff0
JS
244
245 wxMenu *viewMenu = new wxMenu;
4a25320b
VZ
246 viewMenu->AppendCheckItem(ID_TOGGLEROWLABELS, "&Row labels");
247 viewMenu->AppendCheckItem(ID_TOGGLECOLLABELS, "&Col labels");
248 viewMenu->AppendCheckItem(ID_TOGGLEEDIT,"&Editable");
249 viewMenu->AppendCheckItem(ID_TOGGLEROWSIZING, "Ro&w drag-resize");
250 viewMenu->AppendCheckItem(ID_TOGGLECOLSIZING, "C&ol drag-resize");
251 viewMenu->AppendCheckItem(ID_TOGGLECOLMOVING, "Col drag-&move");
252 viewMenu->AppendCheckItem(ID_TOGGLEGRIDSIZING, "&Grid drag-resize");
253 viewMenu->AppendCheckItem(ID_TOGGLEGRIDDRAGCELL, "&Grid drag-cell");
4a25320b
VZ
254 viewMenu->AppendCheckItem(ID_TOGGLEGRIDLINES, "&Grid Lines");
255 viewMenu->AppendCheckItem(ID_SET_HIGHLIGHT_WIDTH, "&Set Cell Highlight Width...");
256 viewMenu->AppendCheckItem(ID_SET_RO_HIGHLIGHT_WIDTH, "&Set Cell RO Highlight Width...");
257 viewMenu->AppendCheckItem(ID_AUTOSIZECOLS, "&Auto-size cols");
258 viewMenu->AppendCheckItem(ID_CELLOVERFLOW, "&Overflow cells");
259 viewMenu->AppendCheckItem(ID_RESIZECELL, "&Resize cell (7,1)");
f7556ff0
JS
260
261 wxMenu *rowLabelMenu = new wxMenu;
262
9a83f860 263 viewMenu->Append( ID_ROWLABELALIGN, wxT("R&ow label alignment"),
f7556ff0 264 rowLabelMenu,
9a83f860 265 wxT("Change alignment of row labels") );
f7556ff0 266
ba9574c3
VZ
267 rowLabelMenu->AppendRadioItem( ID_ROWLABELHORIZALIGN, wxT("&Horizontal") );
268 rowLabelMenu->AppendRadioItem( ID_ROWLABELVERTALIGN, wxT("&Vertical") );
f7556ff0
JS
269
270 wxMenu *colLabelMenu = new wxMenu;
271
9a83f860 272 viewMenu->Append( ID_COLLABELALIGN, wxT("Col l&abel alignment"),
f7556ff0 273 colLabelMenu,
9a83f860 274 wxT("Change alignment of col labels") );
f7556ff0 275
ba9574c3
VZ
276 colLabelMenu->AppendRadioItem( ID_COLLABELHORIZALIGN, wxT("&Horizontal") );
277 colLabelMenu->AppendRadioItem( ID_COLLABELVERTALIGN, wxT("&Vertical") );
278
279 wxMenu *colHeaderMenu = new wxMenu;
280
281 viewMenu->Append( ID_ROWLABELALIGN, wxT("Col header style"),
282 colHeaderMenu,
283 wxT("Change style of col header") );
284
285 colHeaderMenu->AppendRadioItem( ID_COLDEFAULTHEADER, wxT("&Default") );
286 colHeaderMenu->AppendRadioItem( ID_COLNATIVEHEADER, wxT("&Native") );
287 colHeaderMenu->AppendRadioItem( ID_COLCUSTOMHEADER, wxT("&Custom") );
288
f7556ff0
JS
289
290 wxMenu *colMenu = new wxMenu;
9a83f860
VZ
291 colMenu->Append( ID_SETLABELCOLOUR, wxT("Set &label colour...") );
292 colMenu->Append( ID_SETLABELTEXTCOLOUR, wxT("Set label &text colour...") );
293 colMenu->Append( ID_SETLABEL_FONT, wxT("Set label fo&nt...") );
294 colMenu->Append( ID_GRIDLINECOLOUR, wxT("&Grid line colour...") );
295 colMenu->Append( ID_SET_CELL_FG_COLOUR, wxT("Set cell &foreground colour...") );
296 colMenu->Append( ID_SET_CELL_BG_COLOUR, wxT("Set cell &background colour...") );
f7556ff0
JS
297
298 wxMenu *editMenu = new wxMenu;
9a83f860
VZ
299 editMenu->Append( ID_INSERTROW, wxT("Insert &row") );
300 editMenu->Append( ID_INSERTCOL, wxT("Insert &column") );
301 editMenu->Append( ID_DELETEROW, wxT("Delete selected ro&ws") );
302 editMenu->Append( ID_DELETECOL, wxT("Delete selected co&ls") );
303 editMenu->Append( ID_CLEARGRID, wxT("Cl&ear grid cell contents") );
f7556ff0
JS
304
305 wxMenu *selectMenu = new wxMenu;
9a83f860
VZ
306 selectMenu->Append( ID_SELECT_UNSELECT, wxT("Add new cells to the selection"),
307 wxT("When off, old selection is deselected before ")
308 wxT("selecting the new cells"), wxITEM_CHECK );
1ecf2613 309 selectMenu->Append( ID_SHOW_SELECTION,
9a83f860 310 wxT("&Show current selection\tCtrl-Alt-S"));
1ecf2613 311 selectMenu->AppendSeparator();
9a83f860
VZ
312 selectMenu->Append( ID_SELECT_ALL, wxT("Select all"));
313 selectMenu->Append( ID_SELECT_ROW, wxT("Select row 2"));
314 selectMenu->Append( ID_SELECT_COL, wxT("Select col 2"));
315 selectMenu->Append( ID_SELECT_CELL, wxT("Select cell (3, 1)"));
1ecf2613 316 selectMenu->AppendSeparator();
9a83f860
VZ
317 selectMenu->Append( ID_DESELECT_ALL, wxT("Deselect all"));
318 selectMenu->Append( ID_DESELECT_ROW, wxT("Deselect row 2"));
319 selectMenu->Append( ID_DESELECT_COL, wxT("Deselect col 2"));
320 selectMenu->Append( ID_DESELECT_CELL, wxT("Deselect cell (3, 1)"));
f7556ff0 321 wxMenu *selectionMenu = new wxMenu;
9a83f860 322 selectMenu->Append( ID_CHANGESEL, wxT("Change &selection mode"),
f7556ff0 323 selectionMenu,
9a83f860 324 wxT("Change selection mode") );
f7556ff0 325
9a83f860
VZ
326 selectionMenu->Append( ID_SELCELLS, wxT("Select &cells") );
327 selectionMenu->Append( ID_SELROWS, wxT("Select &rows") );
328 selectionMenu->Append( ID_SELCOLS, wxT("Select col&umns") );
329 selectionMenu->Append( ID_SELROWSORCOLS, wxT("Select rows &or columns") );
f7556ff0 330
733f486a 331 wxMenu *autosizeMenu = new wxMenu;
9a83f860
VZ
332 autosizeMenu->Append( ID_SIZE_ROW, wxT("Selected &row data") );
333 autosizeMenu->Append( ID_SIZE_COL, wxT("Selected &column data") );
334 autosizeMenu->Append( ID_SIZE_ROW_LABEL, wxT("Selected row la&bel") );
335 autosizeMenu->Append( ID_SIZE_COL_LABEL, wxT("Selected column &label") );
336 autosizeMenu->Append( ID_SIZE_LABELS_COL, wxT("Column la&bels") );
337 autosizeMenu->Append( ID_SIZE_LABELS_ROW, wxT("Row label&s") );
338 autosizeMenu->Append( ID_SIZE_GRID, wxT("Entire &grid") );
f7556ff0
JS
339
340 wxMenu *helpMenu = new wxMenu;
9a83f860 341 helpMenu->Append( wxID_ABOUT, wxT("&About wxGrid demo") );
f7556ff0
JS
342
343 wxMenuBar *menuBar = new wxMenuBar;
9a83f860
VZ
344 menuBar->Append( fileMenu, wxT("&File") );
345 menuBar->Append( viewMenu, wxT("&Grid") );
346 menuBar->Append( colMenu, wxT("&Colours") );
347 menuBar->Append( editMenu, wxT("&Edit") );
348 menuBar->Append( selectMenu, wxT("&Select") );
349 menuBar->Append( autosizeMenu, wxT("&Autosize") );
350 menuBar->Append( helpMenu, wxT("&Help") );
f7556ff0
JS
351
352 SetMenuBar( menuBar );
353
af870ed8 354 m_addToSel = false;
f7556ff0
JS
355
356 grid = new wxGrid( this,
af870ed8 357 wxID_ANY,
f7556ff0
JS
358 wxPoint( 0, 0 ),
359 wxSize( 400, 300 ) );
360
ba9574c3 361
f07941fc
WS
362#if wxUSE_LOG
363 int gridW = 600, gridH = 300;
364 int logW = gridW, logH = 100;
365
f7556ff0 366 logWin = new wxTextCtrl( this,
af870ed8 367 wxID_ANY,
f7556ff0
JS
368 wxEmptyString,
369 wxPoint( 0, gridH + 20 ),
370 wxSize( logW, logH ),
371 wxTE_MULTILINE );
372
373 logger = new wxLogTextCtrl( logWin );
2a1f999f 374 m_logOld = wxLog::SetActiveTarget( logger );
7b1bf3ad 375 wxLog::DisableTimestamp();
f07941fc 376#endif // wxUSE_LOG
f7556ff0
JS
377
378 // this will create a grid and, by default, an associated grid
379 // table for strings
380 grid->CreateGrid( 0, 0 );
ba9574c3
VZ
381
382 grid->GetTable()->SetAttrProvider(new CustomColumnHeadersProvider());
383
f7556ff0
JS
384 grid->AppendRows(100);
385 grid->AppendCols(100);
386
387 int ir = grid->GetNumberRows();
388 grid->DeleteRows(0, ir);
389 grid->AppendRows(ir);
390
391 grid->SetRowSize( 0, 60 );
9a83f860 392 grid->SetCellValue( 0, 0, wxT("Ctrl+Home\nwill go to\nthis cell") );
f7556ff0 393
9a83f860 394 grid->SetCellValue( 0, 1, wxT("A long piece of text to demonstrate wrapping.") );
f7556ff0
JS
395 grid->SetCellRenderer(0 , 1, new wxGridCellAutoWrapStringRenderer);
396 grid->SetCellEditor( 0, 1 , new wxGridCellAutoWrapStringEditor);
397
9a83f860
VZ
398 grid->SetCellValue( 0, 2, wxT("Blah") );
399 grid->SetCellValue( 0, 3, wxT("Read only") );
f7556ff0
JS
400 grid->SetReadOnly( 0, 3 );
401
9a83f860 402 grid->SetCellValue( 0, 4, wxT("Can veto edit this cell") );
f7556ff0 403
9a83f860 404 grid->SetCellValue( 0, 5, wxT("Press\nCtrl+arrow\nto skip over\ncells") );
f7556ff0
JS
405
406 grid->SetRowSize( 99, 60 );
9a83f860
VZ
407 grid->SetCellValue( 99, 99, wxT("Ctrl+End\nwill go to\nthis cell") );
408 grid->SetCellValue( 1, 0, wxT("This default cell will overflow into neighboring cells, but not if you turn overflow off."));
f7556ff0
JS
409
410 grid->SetCellTextColour(1, 2, *wxRED);
411 grid->SetCellBackgroundColour(1, 2, *wxGREEN);
412
9a83f860 413 grid->SetCellValue( 1, 4, wxT("I'm in the middle"));
f7556ff0 414
9a83f860 415 grid->SetCellValue(2, 2, wxT("red"));
f7556ff0
JS
416
417 grid->SetCellTextColour(2, 2, *wxRED);
9a83f860 418 grid->SetCellValue(3, 3, wxT("green on grey"));
f7556ff0
JS
419 grid->SetCellTextColour(3, 3, *wxGREEN);
420 grid->SetCellBackgroundColour(3, 3, *wxLIGHT_GREY);
421
9a83f860 422 grid->SetCellValue(4, 4, wxT("a weird looking cell"));
f7556ff0
JS
423 grid->SetCellAlignment(4, 4, wxALIGN_CENTRE, wxALIGN_CENTRE);
424 grid->SetCellRenderer(4, 4, new MyGridCellRenderer);
425
f7556ff0
JS
426 grid->SetCellRenderer(3, 0, new wxGridCellBoolRenderer);
427 grid->SetCellEditor(3, 0, new wxGridCellBoolEditor);
428
429 wxGridCellAttr *attr;
430 attr = new wxGridCellAttr;
431 attr->SetTextColour(*wxBLUE);
432 grid->SetColAttr(5, attr);
433 attr = new wxGridCellAttr;
434 attr->SetBackgroundColour(*wxRED);
435 grid->SetRowAttr(5, attr);
436
9a83f860 437 grid->SetCellValue(2, 4, wxT("a wider column"));
f7556ff0
JS
438 grid->SetColSize(4, 120);
439 grid->SetColMinimalWidth(4, 120);
440
441 grid->SetCellTextColour(5, 8, *wxGREEN);
9a83f860
VZ
442 grid->SetCellValue(5, 8, wxT("Bg from row attr\nText col from cell attr"));
443 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"));
f7556ff0
JS
444
445 grid->SetColFormatFloat(6);
1bf55f4c
VZ
446 grid->SetCellValue(0, 6, wxString::Format(wxT("%g"), 3.1415));
447 grid->SetCellValue(1, 6, wxString::Format(wxT("%g"), 1415.0));
448 grid->SetCellValue(2, 6, wxString::Format(wxT("%g"), 12345.67890));
f7556ff0
JS
449
450 grid->SetColFormatFloat(7, 6, 2);
1bf55f4c
VZ
451 grid->SetCellValue(0, 7, wxString::Format(wxT("%g"), 3.1415));
452 grid->SetCellValue(1, 7, wxString::Format(wxT("%g"), 1415.0));
453 grid->SetCellValue(2, 7, wxString::Format(wxT("%g"), 12345.67890));
f7556ff0 454
4f6c80fe
VZ
455 grid->SetColFormatNumber(8);
456 grid->SetCellValue(0, 8, "17");
457 grid->SetCellValue(1, 8, "0");
458 grid->SetCellValue(2, 8, "-666");
cfbc15ee
VZ
459 grid->SetCellAlignment(2, 8, wxALIGN_CENTRE, wxALIGN_TOP);
460 grid->SetCellValue(2, 9, "<- This numeric cell should be centred");
4f6c80fe 461
f7556ff0
JS
462 const wxString choices[] =
463 {
9a83f860
VZ
464 wxT("Please select a choice"),
465 wxT("This takes two cells"),
466 wxT("Another choice"),
f7556ff0
JS
467 };
468 grid->SetCellEditor(4, 0, new wxGridCellChoiceEditor(WXSIZEOF(choices), choices));
469 grid->SetCellSize(4, 0, 1, 2);
470 grid->SetCellValue(4, 0, choices[0]);
af870ed8 471 grid->SetCellOverflow(4, 0, false);
f7556ff0
JS
472
473 grid->SetCellSize(7, 1, 3, 4);
474 grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
9a83f860 475 grid->SetCellValue(7, 1, wxT("Big box!"));
f7556ff0 476
82edfbe7
VZ
477 // create a separator-like row: it's grey and it's non-resizeable
478 grid->DisableRowResize(10);
479 grid->SetRowSize(10, 30);
480 attr = new wxGridCellAttr;
481 attr->SetBackgroundColour(*wxLIGHT_GREY);
482 grid->SetRowAttr(10, attr);
483 grid->SetCellValue(10, 0, "You can't resize this row interactively -- try it");
484
6f292345
VZ
485 // this does exactly nothing except testing that SetAttr() handles NULL
486 // attributes and does reference counting correctly
487 grid->SetAttr(11, 11, NULL);
488 grid->SetAttr(11, 11, new wxGridCellAttr);
489 grid->SetAttr(11, 11, NULL);
490
f7556ff0
JS
491 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
492 topSizer->Add( grid,
493 1,
494 wxEXPAND );
495
f07941fc 496#if wxUSE_LOG
f7556ff0
JS
497 topSizer->Add( logWin,
498 0,
499 wxEXPAND );
f07941fc 500#endif // wxUSE_LOG
f7556ff0 501
92c01615 502 SetSizerAndFit( topSizer );
f7556ff0
JS
503
504 Centre();
505 SetDefaults();
506}
507
508
509GridFrame::~GridFrame()
510{
f07941fc 511#if wxUSE_LOG
f7556ff0 512 delete wxLog::SetActiveTarget(m_logOld);
f07941fc 513#endif // wxUSE_LOG
f7556ff0
JS
514}
515
516
517void GridFrame::SetDefaults()
518{
af870ed8
WS
519 GetMenuBar()->Check( ID_TOGGLEROWLABELS, true );
520 GetMenuBar()->Check( ID_TOGGLECOLLABELS, true );
521 GetMenuBar()->Check( ID_TOGGLEEDIT, true );
522 GetMenuBar()->Check( ID_TOGGLEROWSIZING, true );
523 GetMenuBar()->Check( ID_TOGGLECOLSIZING, true );
d4175745 524 GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
af870ed8 525 GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
79dbea21 526 GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
af870ed8
WS
527 GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
528 GetMenuBar()->Check( ID_CELLOVERFLOW, true );
f7556ff0
JS
529}
530
531
532void GridFrame::ToggleRowLabels( wxCommandEvent& WXUNUSED(ev) )
533{
534 if ( GetMenuBar()->IsChecked( ID_TOGGLEROWLABELS ) )
535 {
536 grid->SetRowLabelSize( grid->GetDefaultRowLabelSize() );
537 }
538 else
539 {
540 grid->SetRowLabelSize( 0 );
541 }
542}
543
544
545void GridFrame::ToggleColLabels( wxCommandEvent& WXUNUSED(ev) )
546{
547 if ( GetMenuBar()->IsChecked( ID_TOGGLECOLLABELS ) )
548 {
549 grid->SetColLabelSize( grid->GetDefaultColLabelSize() );
550 }
551 else
552 {
553 grid->SetColLabelSize( 0 );
554 }
555}
556
557
558void GridFrame::ToggleEditing( wxCommandEvent& WXUNUSED(ev) )
559{
560 grid->EnableEditing(
561 GetMenuBar()->IsChecked( ID_TOGGLEEDIT ) );
562}
563
564
565void GridFrame::ToggleRowSizing( wxCommandEvent& WXUNUSED(ev) )
566{
567 grid->EnableDragRowSize(
568 GetMenuBar()->IsChecked( ID_TOGGLEROWSIZING ) );
569}
570
571
572void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
573{
574 grid->EnableDragColSize(
575 GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
576}
577
d4175745
VZ
578void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
579{
580 grid->EnableDragColMove(
581 GetMenuBar()->IsChecked( ID_TOGGLECOLMOVING ) );
582}
583
f7556ff0
JS
584void GridFrame::ToggleGridSizing( wxCommandEvent& WXUNUSED(ev) )
585{
586 grid->EnableDragGridSize(
587 GetMenuBar()->IsChecked( ID_TOGGLEGRIDSIZING ) );
588}
589
79dbea21
RD
590void GridFrame::ToggleGridDragCell( wxCommandEvent& WXUNUSED(ev) )
591{
592 grid->EnableDragCell(
593 GetMenuBar()->IsChecked( ID_TOGGLEGRIDDRAGCELL ) );
594}
f7556ff0 595
ba9574c3
VZ
596void GridFrame::SetNativeColHeader( wxCommandEvent& WXUNUSED(ev) )
597{
598 CustomColumnHeadersProvider* provider =
599 static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
600 provider->UseCustomColHeaders(false);
601 grid->SetUseNativeColLabels(true);
602}
603
604void GridFrame::SetCustomColHeader( wxCommandEvent& WXUNUSED(ev) )
4a25320b 605{
ba9574c3
VZ
606 CustomColumnHeadersProvider* provider =
607 static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
608 provider->UseCustomColHeaders(true);
609 grid->SetUseNativeColLabels(false);
4a25320b
VZ
610}
611
ba9574c3
VZ
612void GridFrame::SetDefaultColHeader( wxCommandEvent& WXUNUSED(ev) )
613{
614 CustomColumnHeadersProvider* provider =
615 static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
616 provider->UseCustomColHeaders(false);
617 grid->SetUseNativeColLabels(false);
618}
619
620
f7556ff0
JS
621void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
622{
623 grid->EnableGridLines(
624 GetMenuBar()->IsChecked( ID_TOGGLEGRIDLINES ) );
625}
626
627void GridFrame::OnSetHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
628{
9a83f860 629 wxString choices[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
f7556ff0 630
9a83f860
VZ
631 wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
632 wxT("Pen Width"), 11, choices);
f7556ff0
JS
633
634 int current = grid->GetCellHighlightPenWidth();
635 dlg.SetSelection(current);
636 if (dlg.ShowModal() == wxID_OK) {
637 grid->SetCellHighlightPenWidth(dlg.GetSelection());
638 }
639}
640
641void GridFrame::OnSetROHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
642{
9a83f860 643 wxString choices[] = { wxT("0"), wxT("1"), wxT("2"), wxT("3"), wxT("4"), wxT("5"), wxT("6"), wxT("7"), wxT("8"), wxT("9"), wxT("10")};
f7556ff0 644
9a83f860
VZ
645 wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
646 wxT("Pen Width"), 11, choices);
f7556ff0
JS
647
648 int current = grid->GetCellHighlightROPenWidth();
649 dlg.SetSelection(current);
650 if (dlg.ShowModal() == wxID_OK) {
651 grid->SetCellHighlightROPenWidth(dlg.GetSelection());
652 }
653}
654
655
656
657void GridFrame::AutoSizeCols( wxCommandEvent& WXUNUSED(ev) )
658{
659 grid->AutoSizeColumns();
660 grid->Refresh();
661}
662
663void GridFrame::CellOverflow( wxCommandEvent& ev )
664{
665 grid->SetDefaultCellOverflow(ev.IsChecked());
666 grid->Refresh();
667}
668
669void GridFrame::ResizeCell( wxCommandEvent& ev )
670{
671 if (ev.IsChecked())
672 grid->SetCellSize( 7, 1, 5, 5 );
673 else
674 grid->SetCellSize( 7, 1, 1, 5 );
675 grid->Refresh();
676}
677
678void GridFrame::SetLabelColour( wxCommandEvent& WXUNUSED(ev) )
679{
680 wxColourDialog dlg( NULL );
681 if ( dlg.ShowModal() == wxID_OK )
682 {
683 wxColourData retData;
684 retData = dlg.GetColourData();
685 wxColour colour = retData.GetColour();
686
687 grid->SetLabelBackgroundColour( colour );
688 }
689}
690
691
692void GridFrame::SetLabelTextColour( wxCommandEvent& WXUNUSED(ev) )
693{
694 wxColourDialog dlg( NULL );
695 if ( dlg.ShowModal() == wxID_OK )
696 {
697 wxColourData retData;
698 retData = dlg.GetColourData();
699 wxColour colour = retData.GetColour();
700
701 grid->SetLabelTextColour( colour );
702 }
703}
704
705void GridFrame::SetLabelFont( wxCommandEvent& WXUNUSED(ev) )
706{
707 wxFont font = wxGetFontFromUser(this);
708 if ( font.Ok() )
709 {
710 grid->SetLabelFont(font);
711 }
712}
713
714void GridFrame::SetRowLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
715{
716 int horiz, vert;
717 grid->GetRowLabelAlignment( &horiz, &vert );
718
719 switch ( horiz )
720 {
721 case wxALIGN_LEFT:
722 horiz = wxALIGN_CENTRE;
723 break;
724
725 case wxALIGN_CENTRE:
726 horiz = wxALIGN_RIGHT;
727 break;
728
729 case wxALIGN_RIGHT:
730 horiz = wxALIGN_LEFT;
731 break;
732 }
733
af870ed8 734 grid->SetRowLabelAlignment( horiz, vert );
f7556ff0
JS
735}
736
737void GridFrame::SetRowLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
738{
739 int horiz, vert;
740 grid->GetRowLabelAlignment( &horiz, &vert );
741
742 switch ( vert )
743 {
744 case wxALIGN_TOP:
745 vert = wxALIGN_CENTRE;
746 break;
747
748 case wxALIGN_CENTRE:
749 vert = wxALIGN_BOTTOM;
750 break;
751
752 case wxALIGN_BOTTOM:
753 vert = wxALIGN_TOP;
754 break;
755 }
756
af870ed8 757 grid->SetRowLabelAlignment( horiz, vert );
f7556ff0
JS
758}
759
760
761void GridFrame::SetColLabelHorizAlignment( wxCommandEvent& WXUNUSED(ev) )
762{
763 int horiz, vert;
764 grid->GetColLabelAlignment( &horiz, &vert );
765
766 switch ( horiz )
767 {
768 case wxALIGN_LEFT:
769 horiz = wxALIGN_CENTRE;
770 break;
771
772 case wxALIGN_CENTRE:
773 horiz = wxALIGN_RIGHT;
774 break;
775
776 case wxALIGN_RIGHT:
777 horiz = wxALIGN_LEFT;
778 break;
779 }
780
af870ed8 781 grid->SetColLabelAlignment( horiz, vert );
f7556ff0
JS
782}
783
784
785void GridFrame::SetColLabelVertAlignment( wxCommandEvent& WXUNUSED(ev) )
786{
787 int horiz, vert;
788 grid->GetColLabelAlignment( &horiz, &vert );
789
790 switch ( vert )
791 {
792 case wxALIGN_TOP:
793 vert = wxALIGN_CENTRE;
794 break;
795
796 case wxALIGN_CENTRE:
797 vert = wxALIGN_BOTTOM;
798 break;
799
800 case wxALIGN_BOTTOM:
801 vert = wxALIGN_TOP;
802 break;
803 }
804
af870ed8 805 grid->SetColLabelAlignment( horiz, vert );
f7556ff0
JS
806}
807
808
809void GridFrame::SetGridLineColour( wxCommandEvent& WXUNUSED(ev) )
810{
811 wxColourDialog dlg( NULL );
812 if ( dlg.ShowModal() == wxID_OK )
813 {
814 wxColourData retData;
815 retData = dlg.GetColourData();
816 wxColour colour = retData.GetColour();
817
818 grid->SetGridLineColour( colour );
819 }
820}
821
822
823void GridFrame::InsertRow( wxCommandEvent& WXUNUSED(ev) )
824{
825 grid->InsertRows( grid->GetGridCursorRow(), 1 );
826}
827
828
829void GridFrame::InsertCol( wxCommandEvent& WXUNUSED(ev) )
830{
831 grid->InsertCols( grid->GetGridCursorCol(), 1 );
832}
833
834
835void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
836{
837 if ( grid->IsSelection() )
838 {
b62f94ff 839 wxGridUpdateLocker locker(grid);
f7556ff0 840 for ( int n = 0; n < grid->GetNumberRows(); )
bfd84575 841 {
f7556ff0
JS
842 if ( grid->IsInSelection( n , 0 ) )
843 grid->DeleteRows( n, 1 );
bfd84575
WS
844 else
845 n++;
846 }
f7556ff0
JS
847 }
848}
849
850
733f486a
VZ
851void GridFrame::AutoSizeRow(wxCommandEvent& WXUNUSED(event))
852{
853 wxGridUpdateLocker locker(grid);
854 const wxArrayInt sels = grid->GetSelectedRows();
855 for ( size_t n = 0, count = sels.size(); n < count; n++ )
856 {
857 grid->AutoSizeRow( sels[n], false );
858 }
859}
860
861void GridFrame::AutoSizeCol(wxCommandEvent& WXUNUSED(event))
862{
863 wxGridUpdateLocker locker(grid);
864 const wxArrayInt sels = grid->GetSelectedCols();
865 for ( size_t n = 0, count = sels.size(); n < count; n++ )
866 {
867 grid->AutoSizeColumn( sels[n], false );
868 }
869}
870
871void GridFrame::AutoSizeRowLabel(wxCommandEvent& WXUNUSED(event))
872{
873 wxGridUpdateLocker locker(grid);
874 const wxArrayInt sels = grid->GetSelectedRows();
875 for ( size_t n = 0, count = sels.size(); n < count; n++ )
876 {
877 grid->AutoSizeRowLabelSize( sels[n] );
878 }
879}
880
881void GridFrame::AutoSizeColLabel(wxCommandEvent& WXUNUSED(event))
882{
883 wxGridUpdateLocker locker(grid);
884 const wxArrayInt sels = grid->GetSelectedCols();
885 for ( size_t n = 0, count = sels.size(); n < count; n++ )
886 {
887 grid->AutoSizeColLabelSize( sels[n] );
888 }
889}
890
891void GridFrame::AutoSizeLabelsCol(wxCommandEvent& WXUNUSED(event))
892{
893 grid->SetColLabelSize( wxGRID_AUTOSIZE );
894}
895
896void GridFrame::AutoSizeLabelsRow(wxCommandEvent& WXUNUSED(event))
897{
898 grid->SetRowLabelSize( wxGRID_AUTOSIZE );
899}
900
901void GridFrame::AutoSizeTable(wxCommandEvent& WXUNUSED(event))
902{
903 grid->AutoSize();
904}
905
906
f7556ff0
JS
907void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
908{
909 if ( grid->IsSelection() )
910 {
b62f94ff 911 wxGridUpdateLocker locker(grid);
f7556ff0 912 for ( int n = 0; n < grid->GetNumberCols(); )
bfd84575 913 {
f7556ff0
JS
914 if ( grid->IsInSelection( 0 , n ) )
915 grid->DeleteCols( n, 1 );
bfd84575
WS
916 else
917 n++;
918 }
f7556ff0
JS
919 }
920}
921
922
923void GridFrame::ClearGrid( wxCommandEvent& WXUNUSED(ev) )
924{
925 grid->ClearGrid();
926}
927
928void GridFrame::SelectCells( wxCommandEvent& WXUNUSED(ev) )
929{
930 grid->SetSelectionMode( wxGrid::wxGridSelectCells );
931}
932
933void GridFrame::SelectRows( wxCommandEvent& WXUNUSED(ev) )
934{
935 grid->SetSelectionMode( wxGrid::wxGridSelectRows );
936}
937
938void GridFrame::SelectCols( wxCommandEvent& WXUNUSED(ev) )
939{
940 grid->SetSelectionMode( wxGrid::wxGridSelectColumns );
941}
942
8a3e536c
VZ
943void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
944{
945 grid->SetSelectionMode( wxGrid::wxGridSelectRowsOrColumns );
946}
947
f7556ff0
JS
948void GridFrame::SetCellFgColour( wxCommandEvent& WXUNUSED(ev) )
949{
950 wxColour col = wxGetColourFromUser(this);
951 if ( col.Ok() )
952 {
953 grid->SetDefaultCellTextColour(col);
954 grid->Refresh();
955 }
956}
957
958void GridFrame::SetCellBgColour( wxCommandEvent& WXUNUSED(ev) )
959{
960 wxColour col = wxGetColourFromUser(this);
961 if ( col.Ok() )
962 {
963 // Check the new Refresh function by passing it a rectangle
964 // which exactly fits the grid.
925e9792
WS
965 wxPoint pt(0, 0);
966 wxRect r(pt, grid->GetSize());
f7556ff0 967 grid->SetDefaultCellBackgroundColour(col);
af870ed8 968 grid->Refresh(true, &r);
f7556ff0
JS
969 }
970}
971
972void GridFrame::DeselectCell(wxCommandEvent& WXUNUSED(event))
973{
974 grid->DeselectCell(3, 1);
975}
976
977void GridFrame::DeselectCol(wxCommandEvent& WXUNUSED(event))
978{
979 grid->DeselectCol(2);
980}
981
982void GridFrame::DeselectRow(wxCommandEvent& WXUNUSED(event))
983{
984 grid->DeselectRow(2);
985}
986
987void GridFrame::DeselectAll(wxCommandEvent& WXUNUSED(event))
988{
989 grid->ClearSelection();
990}
991
992void GridFrame::SelectCell(wxCommandEvent& WXUNUSED(event))
993{
994 grid->SelectBlock(3, 1, 3, 1, m_addToSel);
995}
996
997void GridFrame::SelectCol(wxCommandEvent& WXUNUSED(event))
998{
999 grid->SelectCol(2, m_addToSel);
1000}
1001
1002void GridFrame::SelectRow(wxCommandEvent& WXUNUSED(event))
1003{
1004 grid->SelectRow(2, m_addToSel);
1005}
1006
1007void GridFrame::SelectAll(wxCommandEvent& WXUNUSED(event))
1008{
1009 grid->SelectAll();
1010}
1011
1012void GridFrame::OnAddToSelectToggle(wxCommandEvent& event)
1013{
1014 m_addToSel = event.IsChecked();
1015}
1016
1017void GridFrame::OnLabelLeftClick( wxGridEvent& ev )
1018{
5b313974 1019 wxString logBuf;
f7556ff0
JS
1020 if ( ev.GetRow() != -1 )
1021 {
9a83f860 1022 logBuf << wxT("Left click on row label ") << ev.GetRow();
f7556ff0
JS
1023 }
1024 else if ( ev.GetCol() != -1 )
1025 {
9a83f860 1026 logBuf << wxT("Left click on col label ") << ev.GetCol();
f7556ff0
JS
1027 }
1028 else
1029 {
9a83f860 1030 logBuf << wxT("Left click on corner label");
f7556ff0
JS
1031 }
1032
5b313974 1033 if ( ev.ShiftDown() )
9a83f860 1034 logBuf << wxT(" (shift down)");
5b313974 1035 if ( ev.ControlDown() )
9a83f860 1036 logBuf << wxT(" (control down)");
f7556ff0
JS
1037 wxLogMessage( wxT("%s"), logBuf.c_str() );
1038
1039 // you must call event skip if you want default grid processing
1040 //
1041 ev.Skip();
1042}
1043
1044
1045void GridFrame::OnCellLeftClick( wxGridEvent& ev )
1046{
9a83f860 1047 wxLogMessage(wxT("Left click at row %d, col %d"), ev.GetRow(), ev.GetCol());
f7556ff0
JS
1048
1049 // you must call event skip if you want default grid processing
1050 // (cell highlighting etc.)
1051 //
1052 ev.Skip();
1053}
1054
1055
1056void GridFrame::OnRowSize( wxGridSizeEvent& ev )
1057{
c6b22707
VZ
1058 const int row = ev.GetRowOrCol();
1059
1060 wxLogMessage("Resized row %d, new height = %d",
1061 row, grid->GetRowSize(row));
f7556ff0
JS
1062
1063 ev.Skip();
1064}
1065
1066
1067void GridFrame::OnColSize( wxGridSizeEvent& ev )
1068{
c6b22707
VZ
1069 const int col = ev.GetRowOrCol();
1070
1071 wxLogMessage("Resized column %d, new width = %d",
1072 col, grid->GetColSize(col));
f7556ff0
JS
1073
1074 ev.Skip();
1075}
1076
1077
1ecf2613
VZ
1078void GridFrame::OnShowSelection(wxCommandEvent& WXUNUSED(event))
1079{
1080 // max number of elements to dump -- otherwise it can take too much time
1081 static const size_t countMax = 100;
1082
1083 bool rows = false;
1084
1085 switch ( grid->GetSelectionMode() )
1086 {
1087 case wxGrid::wxGridSelectCells:
1088 {
1089 const wxGridCellCoordsArray cells(grid->GetSelectedCells());
1090 size_t count = cells.size();
9a83f860 1091 wxLogMessage(wxT("%lu cells selected:"), (unsigned long)count);
1ecf2613
VZ
1092 if ( count > countMax )
1093 {
9a83f860
VZ
1094 wxLogMessage(wxT("[too many selected cells, ")
1095 wxT("showing only the first %lu]"),
1ecf2613
VZ
1096 (unsigned long)countMax);
1097 count = countMax;
1098 }
1099
1100 for ( size_t n = 0; n < count; n++ )
1101 {
1102 const wxGridCellCoords& c = cells[n];
9a83f860 1103 wxLogMessage(wxT(" selected cell %lu: (%d, %d)"),
1ecf2613
VZ
1104 (unsigned long)n, c.GetCol(), c.GetRow());
1105 }
1106 }
1107 break;
1108
1109 case wxGrid::wxGridSelectRows:
1110 rows = true;
1111 // fall through
1112
1113 case wxGrid::wxGridSelectColumns:
1114 {
1115 const wxChar *plural, *single;
1116 if ( rows )
1117 {
9a83f860
VZ
1118 plural = wxT("rows");
1119 single = wxT("row");
1ecf2613
VZ
1120 }
1121 else // columns
1122 {
9a83f860
VZ
1123 plural = wxT("columns");
1124 single = wxT("column");
1ecf2613
VZ
1125 }
1126
15836000
CE
1127 const wxArrayInt sels((const wxArrayInt)(rows ? grid->GetSelectedRows()
1128 : grid->GetSelectedCols()));
1ecf2613 1129 size_t count = sels.size();
9a83f860 1130 wxLogMessage(wxT("%lu %s selected:"),
1ecf2613
VZ
1131 (unsigned long)count, plural);
1132 if ( count > countMax )
1133 {
9a83f860
VZ
1134 wxLogMessage(wxT("[too many selected %s, ")
1135 wxT("showing only the first %lu]"),
1ecf2613
VZ
1136 plural, (unsigned long)countMax);
1137 count = countMax;
1138 }
1139
1140 for ( size_t n = 0; n < count; n++ )
1141 {
9a83f860 1142 wxLogMessage(wxT(" selected %s %lu: %d"),
1ecf2613
VZ
1143 single, (unsigned long)n, sels[n]);
1144 }
1145 }
1146 break;
1147
1148 default:
9a83f860 1149 wxFAIL_MSG( wxT("unknown wxGrid selection mode") );
1ecf2613
VZ
1150 break;
1151 }
1152}
1153
f7556ff0
JS
1154void GridFrame::OnSelectCell( wxGridEvent& ev )
1155{
5b313974 1156 wxString logBuf;
f7556ff0 1157 if ( ev.Selecting() )
9a83f860 1158 logBuf << wxT("Selected ");
f7556ff0 1159 else
9a83f860
VZ
1160 logBuf << wxT("Deselected ");
1161 logBuf << wxT("cell at row ") << ev.GetRow()
1162 << wxT(" col ") << ev.GetCol()
1163 << wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
1164 << wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
1165 << wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
1166 << wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
d4175745
VZ
1167
1168 //Indicate whether this column was moved
1169 if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
9a83f860 1170 logBuf << wxT(" *** Column moved, current position: ") << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
d4175745 1171
f7556ff0
JS
1172 wxLogMessage( wxT("%s"), logBuf.c_str() );
1173
1174 // you must call Skip() if you want the default processing
1175 // to occur in wxGrid
1176 ev.Skip();
1177}
1178
1179void GridFrame::OnRangeSelected( wxGridRangeSelectEvent& ev )
1180{
5b313974 1181 wxString logBuf;
f7556ff0 1182 if ( ev.Selecting() )
9a83f860 1183 logBuf << wxT("Selected ");
f7556ff0 1184 else
9a83f860
VZ
1185 logBuf << wxT("Deselected ");
1186 logBuf << wxT("cells from row ") << ev.GetTopRow()
1187 << wxT(" col ") << ev.GetLeftCol()
1188 << wxT(" to row ") << ev.GetBottomRow()
1189 << wxT(" col ") << ev.GetRightCol()
1190 << wxT(" ( ControlDown: ")<< (ev.ControlDown() ? 'T':'F')
1191 << wxT(", ShiftDown: ")<< (ev.ShiftDown() ? 'T':'F')
1192 << wxT(", AltDown: ")<< (ev.AltDown() ? 'T':'F')
1193 << wxT(", MetaDown: ")<< (ev.MetaDown() ? 'T':'F') << wxT(" )");
f7556ff0
JS
1194 wxLogMessage( wxT("%s"), logBuf.c_str() );
1195
1196 ev.Skip();
1197}
1198
763163a8
VZ
1199void GridFrame::OnCellValueChanging( wxGridEvent& ev )
1200{
1201 int row = ev.GetRow(),
1202 col = ev.GetCol();
1203
1204 wxLogMessage("Value of cell at (%d, %d): about to change "
1205 "from \"%s\" to \"%s\"",
1206 row, col,
1207 grid->GetCellValue(row, col), ev.GetString());
1208
1209 // test how vetoing works
1210 if ( ev.GetString() == "42" )
1211 {
1212 wxLogMessage("Vetoing the change.");
1213 ev.Veto();
1214 return;
1215 }
1216
1217 ev.Skip();
1218}
1219
f7556ff0
JS
1220void GridFrame::OnCellValueChanged( wxGridEvent& ev )
1221{
5b313974
VZ
1222 int row = ev.GetRow(),
1223 col = ev.GetCol();
f7556ff0 1224
763163a8
VZ
1225 wxLogMessage("Value of cell at (%d, %d) changed and is now \"%s\" "
1226 "(was \"%s\")",
1227 row, col,
1228 grid->GetCellValue(row, col), ev.GetString());
79dbea21
RD
1229
1230 ev.Skip();
1231}
1232
1233void GridFrame::OnCellBeginDrag( wxGridEvent& ev )
1234{
9a83f860 1235 wxLogMessage(wxT("Got request to drag cell at row %d, col %d"),
5b313974 1236 ev.GetRow(), ev.GetCol());
f7556ff0
JS
1237
1238 ev.Skip();
1239}
1240
1241void GridFrame::OnEditorShown( wxGridEvent& ev )
1242{
1243
1244 if ( (ev.GetCol() == 4) &&
1245 (ev.GetRow() == 0) &&
9a83f860
VZ
1246 (wxMessageBox(wxT("Are you sure you wish to edit this cell"),
1247 wxT("Checking"),wxYES_NO) == wxNO ) ) {
f7556ff0
JS
1248
1249 ev.Veto();
1250 return;
1251 }
1252
1253 wxLogMessage( wxT("Cell editor shown.") );
1254
1255 ev.Skip();
1256}
1257
1258void GridFrame::OnEditorHidden( wxGridEvent& ev )
1259{
1260
1261 if ( (ev.GetCol() == 4) &&
1262 (ev.GetRow() == 0) &&
9a83f860
VZ
1263 (wxMessageBox(wxT("Are you sure you wish to finish editing this cell"),
1264 wxT("Checking"),wxYES_NO) == wxNO ) ) {
f7556ff0
JS
1265
1266 ev.Veto();
1267 return;
1268 }
1269
1270 wxLogMessage( wxT("Cell editor hidden.") );
1271
1272 ev.Skip();
1273}
1274
1275void GridFrame::About( wxCommandEvent& WXUNUSED(ev) )
1276{
7dfb6dc4
FM
1277 wxAboutDialogInfo aboutInfo;
1278 aboutInfo.SetName(wxT("wxGrid demo"));
1279 aboutInfo.SetDescription(_("wxGrid sample program"));
1280 aboutInfo.AddDeveloper(wxT("Michael Bedward"));
1281 aboutInfo.AddDeveloper(wxT("Julian Smart"));
1282 aboutInfo.AddDeveloper(wxT("Vadim Zeitlin"));
1283
e6f1eb56
FM
1284 // this is just to force the generic version of the about
1285 // dialog under wxMSW so that it's easy to test if the grid
1286 // repaints correctly when it has lost focus and a dialog
1287 // (different from the Windows standard message box -- it doesn't
1288 // work with it for some reason) is moved over it.
1289 aboutInfo.SetWebSite(wxT("http://www.wxwidgets.org"));
1290
7dfb6dc4 1291 wxAboutBox(aboutInfo);
f7556ff0
JS
1292}
1293
1294
1295void GridFrame::OnQuit( wxCommandEvent& WXUNUSED(ev) )
1296{
af870ed8 1297 Close( true );
f7556ff0
JS
1298}
1299
1300void GridFrame::OnBugsTable(wxCommandEvent& )
1301{
1302 BugsGridFrame *frame = new BugsGridFrame;
af870ed8 1303 frame->Show(true);
f7556ff0
JS
1304}
1305
71cf399f
RR
1306// ----------------------------------------------------------------------------
1307// MyGridCellAttrProvider
1308// ----------------------------------------------------------------------------
1309
1310MyGridCellAttrProvider::MyGridCellAttrProvider()
1311{
1312 m_attrForOddRows = new wxGridCellAttr;
1313 m_attrForOddRows->SetBackgroundColour(*wxLIGHT_GREY);
1314}
1315
1316MyGridCellAttrProvider::~MyGridCellAttrProvider()
1317{
1318 m_attrForOddRows->DecRef();
1319}
1320
1321wxGridCellAttr *MyGridCellAttrProvider::GetAttr(int row, int col,
1322 wxGridCellAttr::wxAttrKind kind /* = wxGridCellAttr::Any */) const
1323{
1324 wxGridCellAttr *attr = wxGridCellAttrProvider::GetAttr(row, col, kind);
1325
1326 if ( row % 2 )
1327 {
1328 if ( !attr )
1329 {
1330 attr = m_attrForOddRows;
1331 attr->IncRef();
1332 }
1333 else
1334 {
1335 if ( !attr->HasBackgroundColour() )
1336 {
1337 wxGridCellAttr *attrNew = attr->Clone();
1338 attr->DecRef();
1339 attr = attrNew;
1340 attr->SetBackgroundColour(*wxLIGHT_GREY);
1341 }
1342 }
1343 }
1344
1345 return attr;
1346}
1347
f7556ff0
JS
1348void GridFrame::OnVTable(wxCommandEvent& )
1349{
1350 static long s_sizeGrid = 10000;
1351
9a83f860
VZ
1352 s_sizeGrid = wxGetNumberFromUser(wxT("Size of the table to create"),
1353 wxT("Size: "),
1354 wxT("wxGridDemo question"),
f7556ff0
JS
1355 s_sizeGrid,
1356 0, 32000, this);
f7556ff0
JS
1357
1358 if ( s_sizeGrid != -1 )
1359 {
1360 BigGridFrame* win = new BigGridFrame(s_sizeGrid);
af870ed8 1361 win->Show(true);
f7556ff0
JS
1362 }
1363}
1364
1365// ----------------------------------------------------------------------------
1366// MyGridCellRenderer
1367// ----------------------------------------------------------------------------
1368
1369// do something that the default renderer doesn't here just to show that it is
1370// possible to alter the appearance of the cell beyond what the attributes
1371// allow
1372void MyGridCellRenderer::Draw(wxGrid& grid,
1373 wxGridCellAttr& attr,
1374 wxDC& dc,
1375 const wxRect& rect,
1376 int row, int col,
1377 bool isSelected)
1378{
1379 wxGridCellStringRenderer::Draw(grid, attr, dc, rect, row, col, isSelected);
1380
1381 dc.SetPen(*wxGREEN_PEN);
1382 dc.SetBrush(*wxTRANSPARENT_BRUSH);
1383 dc.DrawEllipse(rect);
1384}
1385
f7556ff0
JS
1386// ============================================================================
1387// BigGridFrame and BigGridTable: Sample of a non-standard table
1388// ============================================================================
1389
1390BigGridFrame::BigGridFrame(long sizeGrid)
9a83f860 1391 : wxFrame(NULL, wxID_ANY, wxT("Plugin Virtual Table"),
f7556ff0
JS
1392 wxDefaultPosition, wxSize(500, 450))
1393{
af870ed8 1394 m_grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
f7556ff0
JS
1395 m_table = new BigGridTable(sizeGrid);
1396
1397 // VZ: I don't understand why this slows down the display that much,
1398 // must profile it...
1399 //m_table->SetAttrProvider(new MyGridCellAttrProvider);
1400
af870ed8 1401 m_grid->SetTable(m_table, true);
f7556ff0
JS
1402
1403#if defined __WXMOTIF__
1404 // MB: the grid isn't getting a sensible default size under wxMotif
1405 int cw, ch;
1406 GetClientSize( &cw, &ch );
1407 m_grid->SetSize( cw, ch );
1408#endif
1409}
1410
1411// ============================================================================
1412// BugsGridFrame: a "realistic" table
1413// ============================================================================
1414
1415// ----------------------------------------------------------------------------
1416// bugs table data
1417// ----------------------------------------------------------------------------
1418
1419enum Columns
1420{
1421 Col_Id,
1422 Col_Summary,
1423 Col_Severity,
1424 Col_Priority,
1425 Col_Platform,
1426 Col_Opened,
1427 Col_Max
1428};
1429
1430enum Severity
1431{
1432 Sev_Wish,
1433 Sev_Minor,
1434 Sev_Normal,
1435 Sev_Major,
1436 Sev_Critical,
1437 Sev_Max
1438};
1439
1440static const wxString severities[] =
1441{
9a83f860
VZ
1442 wxT("wishlist"),
1443 wxT("minor"),
1444 wxT("normal"),
1445 wxT("major"),
1446 wxT("critical"),
f7556ff0
JS
1447};
1448
1449static struct BugsGridData
1450{
1451 int id;
1452 wxChar summary[80];
1453 Severity severity;
1454 int prio;
1455 wxChar platform[12];
1456 bool opened;
1457} gs_dataBugsGrid [] =
1458{
9a83f860
VZ
1459 { 18, wxT("foo doesn't work"), Sev_Major, 1, wxT("wxMSW"), true },
1460 { 27, wxT("bar crashes"), Sev_Critical, 1, wxT("all"), false },
1461 { 45, wxT("printing is slow"), Sev_Minor, 3, wxT("wxMSW"), true },
1462 { 68, wxT("Rectangle() fails"), Sev_Normal, 1, wxT("wxMSW"), false },
f7556ff0
JS
1463};
1464
1465static const wxChar *headers[Col_Max] =
1466{
9a83f860
VZ
1467 wxT("Id"),
1468 wxT("Summary"),
1469 wxT("Severity"),
1470 wxT("Priority"),
1471 wxT("Platform"),
1472 wxT("Opened?"),
f7556ff0
JS
1473};
1474
1475// ----------------------------------------------------------------------------
1476// BugsGridTable
1477// ----------------------------------------------------------------------------
1478
1479wxString BugsGridTable::GetTypeName(int WXUNUSED(row), int col)
1480{
1481 switch ( col )
1482 {
1483 case Col_Id:
1484 case Col_Priority:
1485 return wxGRID_VALUE_NUMBER;;
1486
1487 case Col_Severity:
1488 // fall thorugh (TODO should be a list)
1489
1490 case Col_Summary:
9a83f860 1491 return wxString::Format(wxT("%s:80"), wxGRID_VALUE_STRING);
f7556ff0
JS
1492
1493 case Col_Platform:
9a83f860 1494 return wxString::Format(wxT("%s:all,MSW,GTK,other"), wxGRID_VALUE_CHOICE);
f7556ff0
JS
1495
1496 case Col_Opened:
1497 return wxGRID_VALUE_BOOL;
1498 }
1499
9a83f860 1500 wxFAIL_MSG(wxT("unknown column"));
f7556ff0
JS
1501
1502 return wxEmptyString;
1503}
1504
1505int BugsGridTable::GetNumberRows()
1506{
1507 return WXSIZEOF(gs_dataBugsGrid);
1508}
1509
1510int BugsGridTable::GetNumberCols()
1511{
1512 return Col_Max;
1513}
1514
87728739 1515bool BugsGridTable::IsEmptyCell( int WXUNUSED(row), int WXUNUSED(col) )
f7556ff0 1516{
af870ed8 1517 return false;
f7556ff0
JS
1518}
1519
1520wxString BugsGridTable::GetValue( int row, int col )
1521{
1522 const BugsGridData& gd = gs_dataBugsGrid[row];
1523
1524 switch ( col )
1525 {
1526 case Col_Id:
9a83f860 1527 return wxString::Format(wxT("%d"), gd.id);
e9a67fc2 1528
f7556ff0 1529 case Col_Priority:
9a83f860 1530 return wxString::Format(wxT("%d"), gd.prio);
e9a67fc2 1531
f7556ff0 1532 case Col_Opened:
9a83f860 1533 return gd.opened ? wxT("1") : wxT("0");
f7556ff0
JS
1534
1535 case Col_Severity:
1536 return severities[gd.severity];
1537
1538 case Col_Summary:
1539 return gd.summary;
1540
1541 case Col_Platform:
1542 return gd.platform;
1543 }
1544
1545 return wxEmptyString;
1546}
1547
1548void BugsGridTable::SetValue( int row, int col, const wxString& value )
1549{
1550 BugsGridData& gd = gs_dataBugsGrid[row];
1551
1552 switch ( col )
1553 {
1554 case Col_Id:
1555 case Col_Priority:
1556 case Col_Opened:
9a83f860 1557 wxFAIL_MSG(wxT("unexpected column"));
f7556ff0
JS
1558 break;
1559
1560 case Col_Severity:
1561 {
1562 size_t n;
1563 for ( n = 0; n < WXSIZEOF(severities); n++ )
1564 {
1565 if ( severities[n] == value )
1566 {
1567 gd.severity = (Severity)n;
1568 break;
1569 }
1570 }
1571
1572 if ( n == WXSIZEOF(severities) )
1573 {
9a83f860 1574 wxLogWarning(wxT("Invalid severity value '%s'."),
f7556ff0
JS
1575 value.c_str());
1576 gd.severity = Sev_Normal;
1577 }
1578 }
1579 break;
1580
1581 case Col_Summary:
1582 wxStrncpy(gd.summary, value, WXSIZEOF(gd.summary));
1583 break;
1584
1585 case Col_Platform:
1586 wxStrncpy(gd.platform, value, WXSIZEOF(gd.platform));
1587 break;
1588 }
1589}
1590
e9a67fc2
VZ
1591bool
1592BugsGridTable::CanGetValueAs(int WXUNUSED(row),
1593 int col,
1594 const wxString& typeName)
f7556ff0
JS
1595{
1596 if ( typeName == wxGRID_VALUE_STRING )
1597 {
af870ed8 1598 return true;
f7556ff0
JS
1599 }
1600 else if ( typeName == wxGRID_VALUE_BOOL )
1601 {
1602 return col == Col_Opened;
1603 }
1604 else if ( typeName == wxGRID_VALUE_NUMBER )
1605 {
1606 return col == Col_Id || col == Col_Priority || col == Col_Severity;
1607 }
1608 else
1609 {
af870ed8 1610 return false;
f7556ff0
JS
1611 }
1612}
1613
1614bool BugsGridTable::CanSetValueAs( int row, int col, const wxString& typeName )
1615{
1616 return CanGetValueAs(row, col, typeName);
1617}
1618
1619long BugsGridTable::GetValueAsLong( int row, int col )
1620{
1621 const BugsGridData& gd = gs_dataBugsGrid[row];
1622
1623 switch ( col )
1624 {
1625 case Col_Id:
1626 return gd.id;
1627
1628 case Col_Priority:
1629 return gd.prio;
1630
1631 case Col_Severity:
1632 return gd.severity;
1633
1634 default:
9a83f860 1635 wxFAIL_MSG(wxT("unexpected column"));
f7556ff0
JS
1636 return -1;
1637 }
1638}
1639
1640bool BugsGridTable::GetValueAsBool( int row, int col )
1641{
1642 if ( col == Col_Opened )
1643 {
1644 return gs_dataBugsGrid[row].opened;
1645 }
1646 else
1647 {
9a83f860 1648 wxFAIL_MSG(wxT("unexpected column"));
f7556ff0 1649
af870ed8 1650 return false;
f7556ff0
JS
1651 }
1652}
1653
1654void BugsGridTable::SetValueAsLong( int row, int col, long value )
1655{
1656 BugsGridData& gd = gs_dataBugsGrid[row];
1657
1658 switch ( col )
1659 {
1660 case Col_Priority:
1661 gd.prio = value;
1662 break;
1663
1664 default:
9a83f860 1665 wxFAIL_MSG(wxT("unexpected column"));
f7556ff0
JS
1666 }
1667}
1668
1669void BugsGridTable::SetValueAsBool( int row, int col, bool value )
1670{
1671 if ( col == Col_Opened )
1672 {
1673 gs_dataBugsGrid[row].opened = value;
1674 }
1675 else
1676 {
9a83f860 1677 wxFAIL_MSG(wxT("unexpected column"));
f7556ff0
JS
1678 }
1679}
1680
1681wxString BugsGridTable::GetColLabelValue( int col )
1682{
1683 return headers[col];
1684}
1685
f7556ff0
JS
1686// ----------------------------------------------------------------------------
1687// BugsGridFrame
1688// ----------------------------------------------------------------------------
1689
1690BugsGridFrame::BugsGridFrame()
9a83f860 1691 : wxFrame(NULL, wxID_ANY, wxT("Bugs table"))
f7556ff0 1692{
e7ae8a69 1693 wxGrid *grid = new wxGrid(this, wxID_ANY);
f7556ff0
JS
1694 wxGridTableBase *table = new BugsGridTable();
1695 table->SetAttrProvider(new MyGridCellAttrProvider);
af870ed8 1696 grid->SetTable(table, true);
f7556ff0
JS
1697
1698 wxGridCellAttr *attrRO = new wxGridCellAttr,
1699 *attrRangeEditor = new wxGridCellAttr,
1700 *attrCombo = new wxGridCellAttr;
1701
1702 attrRO->SetReadOnly();
1703 attrRangeEditor->SetEditor(new wxGridCellNumberEditor(1, 5));
1704 attrCombo->SetEditor(new wxGridCellChoiceEditor(WXSIZEOF(severities),
1705 severities));
1706
1707 grid->SetColAttr(Col_Id, attrRO);
1708 grid->SetColAttr(Col_Priority, attrRangeEditor);
1709 grid->SetColAttr(Col_Severity, attrCombo);
1710
f7556ff0
JS
1711 grid->Fit();
1712 SetClientSize(grid->GetSize());
1713}
1714
e7ae8a69
VZ
1715// ============================================================================
1716// TabularGrid: grid used for display of tabular data
1717// ============================================================================
1718
1719class TabularGridTable : public wxGridTableBase
1720{
1721public:
1722 enum
1723 {
1724 COL_NAME,
1725 COL_EXT,
1726 COL_SIZE,
1727 COL_DATE,
1728 COL_MAX
1729 };
1730
1731 enum
1732 {
1733 ROW_MAX = 3
1734 };
1735
11393d29
VZ
1736 TabularGridTable() { m_sortOrder = NULL; }
1737
e7ae8a69
VZ
1738 virtual int GetNumberRows() { return ROW_MAX; }
1739 virtual int GetNumberCols() { return COL_MAX; }
1740
1741 virtual wxString GetValue(int row, int col)
1742 {
11393d29
VZ
1743 if ( m_sortOrder )
1744 row = m_sortOrder[row];
1745
1746 switch ( col )
e7ae8a69 1747 {
11393d29
VZ
1748 case COL_NAME:
1749 case COL_EXT:
1750 return GetNameOrExt(row, col);
e7ae8a69 1751
11393d29
VZ
1752 case COL_SIZE:
1753 return wxString::Format("%lu", GetSize(row));
1754
1755 case COL_DATE:
1756 return GetDate(row).FormatDate();
1757
1758 case COL_MAX:
1759 default:
1760 wxFAIL_MSG( "unknown column" );
1761 }
1762
1763 return wxString();
e7ae8a69
VZ
1764 }
1765
1766 virtual void SetValue(int, int, const wxString&)
1767 {
1768 wxFAIL_MSG( "shouldn't be called" );
1769 }
1770
1771 virtual wxString GetColLabelValue(int col)
1772 {
11393d29
VZ
1773 // notice that column parameter here always refers to the internal
1774 // column index, independently of its position on the screen
e7ae8a69 1775 static const char *labels[] = { "Name", "Extension", "Size", "Date" };
11393d29 1776 wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, LabelsMismatch );
e7ae8a69
VZ
1777
1778 return labels[col];
1779 }
1780
1781 virtual void SetColLabelValue(int, const wxString&)
1782 {
1783 wxFAIL_MSG( "shouldn't be called" );
1784 }
11393d29
VZ
1785
1786 void Sort(int col, bool ascending)
1787 {
1788 // we hardcode all sorting orders for simplicity here
1789 static int sortOrders[COL_MAX][2][ROW_MAX] =
1790 {
1791 // descending ascending
1792 { { 2, 1, 0 }, { 0, 1, 2 } },
1793 { { 2, 1, 0 }, { 0, 1, 2 } },
1794 { { 2, 1, 0 }, { 0, 1, 2 } },
1795 { { 1, 0, 2 }, { 2, 0, 1 } },
1796 };
1797
1798 m_sortOrder = col == wxNOT_FOUND ? NULL : sortOrders[col][ascending];
1799 }
1800
1801private:
1802 wxString GetNameOrExt(int row, int col) const
1803 {
1804 static const char *
1805 names[] = { "autoexec.bat", "boot.ini", "io.sys" };
1806 wxCOMPILE_TIME_ASSERT( WXSIZEOF(names) == ROW_MAX, NamesMismatch );
1807
1808 const wxString s(names[row]);
1809 return col == COL_NAME ? s.BeforeFirst('.') : s.AfterLast('.');
1810 }
1811
1812 unsigned long GetSize(int row) const
1813 {
1814 static const unsigned long
1815 sizes[] = { 412, 604, 40774 };
1816 wxCOMPILE_TIME_ASSERT( WXSIZEOF(sizes) == ROW_MAX, SizesMismatch );
1817
1818 return sizes[row];
1819 }
1820
1821 wxDateTime GetDate(int row) const
1822 {
1823 static const char *
1824 dates[] = { "2004-04-17", "2006-05-27", "1994-05-31" };
1825 wxCOMPILE_TIME_ASSERT( WXSIZEOF(dates) == ROW_MAX, DatesMismatch );
1826
1827 wxDateTime dt;
1828 dt.ParseISODate(dates[row]);
1829 return dt;
1830 }
1831
1832 int *m_sortOrder;
e7ae8a69
VZ
1833};
1834
1835// specialized text control for column indexes entry
1836class ColIndexEntry : public wxTextCtrl
1837{
1838public:
1839 ColIndexEntry(wxWindow *parent)
1840 : wxTextCtrl(parent, wxID_ANY, "")
1841 {
1842 SetValidator(wxTextValidator(wxFILTER_NUMERIC));
1843 }
1844
1845 int GetCol()
1846 {
1847 unsigned long col;
1848 if ( !GetValue().ToULong(&col) || col > TabularGridTable::COL_MAX )
1849 {
1850 SetFocus();
1851 return -1;
1852 }
1853
1854 return col;
1855 }
1856
1857protected:
1858 virtual wxSize DoGetBestSize() const
1859 {
1860 wxSize size = wxTextCtrl::DoGetBestSize();
1861 size.x = 3*GetCharWidth();
1862 return size;
1863 }
1864};
1865
1866class TabularGridFrame : public wxFrame
1867{
1868public:
1869 TabularGridFrame();
1870
1871private:
1872 enum // control ids
1873 {
cd68daf5
VZ
1874 Id_Check_UseNativeHeader,
1875 Id_Check_DrawNativeLabels,
1876 Id_Check_ShowRowLabels,
e7ae8a69
VZ
1877 Id_Check_EnableColMove
1878 };
1879
1880 // event handlers
1881
1882 void OnToggleUseNativeHeader(wxCommandEvent&)
1883 {
cd68daf5
VZ
1884 m_grid->UseNativeColHeader(m_chkUseNative->IsChecked());
1885 }
1886
1887 void OnUpdateDrawNativeLabelsUI(wxUpdateUIEvent& event)
1888 {
1889 // we don't draw labels at all, native or otherwise, if we use the
1890 // native header control
1891 event.Enable( !m_chkUseNative->GetValue() );
1892 }
1893
1894 void OnToggleDrawNativeLabels(wxCommandEvent&)
1895 {
1896 m_grid->SetUseNativeColLabels(m_chkDrawNative->IsChecked());
1897 }
1898
1899 void OnToggleShowRowLabels(wxCommandEvent&)
1900 {
1901 m_grid->SetRowLabelSize(m_chkShowRowLabels->IsChecked()
1902 ? wxGRID_AUTOSIZE
1903 : 0);
e7ae8a69
VZ
1904 }
1905
1906 void OnToggleColMove(wxCommandEvent&)
1907 {
1908 m_grid->EnableDragColMove(m_chkEnableColMove->IsChecked());
1909 }
1910
009c7216
VZ
1911 void OnShowHideColumn(wxCommandEvent& event)
1912 {
1913 int col = m_txtColShowHide->GetCol();
1914 if ( col != -1 )
3b367af8 1915 {
613de0e8
VZ
1916 m_grid->SetColSize(col,
1917 event.GetId() == wxID_ADD ? wxGRID_AUTOSIZE : 0);
3b367af8
VZ
1918
1919 UpdateOrderAndVisibility();
1920 }
009c7216
VZ
1921 }
1922
e7ae8a69
VZ
1923 void OnMoveColumn(wxCommandEvent&)
1924 {
1925 int col = m_txtColIndex->GetCol();
1926 int pos = m_txtColPos->GetCol();
1927 if ( col == -1 || pos == -1 )
1928 return;
1929
1930 m_grid->SetColPos(col, pos);
1931
3b367af8
VZ
1932 UpdateOrderAndVisibility();
1933 }
1934
1935 void OnResetColumnOrder(wxCommandEvent&)
1936 {
1937 m_grid->ResetColPos();
1938
1939 UpdateOrderAndVisibility();
e7ae8a69
VZ
1940 }
1941
11393d29
VZ
1942 void OnGridColSort(wxGridEvent& event)
1943 {
1944 const int col = event.GetCol();
1945 m_table->Sort(col, !(m_grid->IsSortingBy(col) &&
1946 m_grid->IsSortOrderAscending()));
1947 }
1948
e7ae8a69
VZ
1949 void OnGridColMove(wxGridEvent& event)
1950 {
cd68daf5
VZ
1951 // can't update it yet as the order hasn't been changed, so do it a bit
1952 // later
1953 m_shouldUpdateOrder = true;
1954
1955 event.Skip();
1956 }
1957
613de0e8
VZ
1958 void OnGridColSize(wxGridSizeEvent& event)
1959 {
1960 // we only catch this event to react to the user showing or hiding this
1961 // column using the header control menu and not because we're
1962 // interested in column resizing
1963 UpdateOrderAndVisibility();
1964
1965 event.Skip();
1966 }
1967
cd68daf5
VZ
1968 void OnIdle(wxIdleEvent& event)
1969 {
1970 if ( m_shouldUpdateOrder )
1971 {
1972 m_shouldUpdateOrder = false;
3b367af8 1973 UpdateOrderAndVisibility();
cd68daf5 1974 }
e7ae8a69
VZ
1975
1976 event.Skip();
1977 }
1978
3b367af8 1979 void UpdateOrderAndVisibility()
e7ae8a69
VZ
1980 {
1981 wxString s;
1982 for ( int pos = 0; pos < TabularGridTable::COL_MAX; pos++ )
3b367af8
VZ
1983 {
1984 const int col = m_grid->GetColAt(pos);
1985 const bool isHidden = m_grid->GetColSize(col) == 0;
1986
1987 if ( isHidden )
1988 s << '[';
1989 s << col;
1990 if ( isHidden )
1991 s << ']';
1992
1993 s << ' ';
1994 }
e7ae8a69
VZ
1995
1996 m_statOrder->SetLabel(s);
1997 }
1998
1999 // controls
2000 wxGrid *m_grid;
11393d29 2001 TabularGridTable *m_table;
e7ae8a69 2002 wxCheckBox *m_chkUseNative,
cd68daf5
VZ
2003 *m_chkDrawNative,
2004 *m_chkShowRowLabels,
e7ae8a69
VZ
2005 *m_chkEnableColMove;
2006
2007 ColIndexEntry *m_txtColIndex,
009c7216
VZ
2008 *m_txtColPos,
2009 *m_txtColShowHide;
e7ae8a69
VZ
2010
2011 wxStaticText *m_statOrder;
2012
cd68daf5
VZ
2013 // fla for EVT_IDLE handler
2014 bool m_shouldUpdateOrder;
2015
c0c133e1 2016 wxDECLARE_NO_COPY_CLASS(TabularGridFrame);
e7ae8a69
VZ
2017 DECLARE_EVENT_TABLE()
2018};
2019
2020BEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
cd68daf5
VZ
2021 EVT_CHECKBOX(Id_Check_UseNativeHeader,
2022 TabularGridFrame::OnToggleUseNativeHeader)
2023 EVT_CHECKBOX(Id_Check_DrawNativeLabels,
2024 TabularGridFrame::OnToggleDrawNativeLabels)
2025 EVT_CHECKBOX(Id_Check_ShowRowLabels,
2026 TabularGridFrame::OnToggleShowRowLabels)
2027 EVT_CHECKBOX(Id_Check_EnableColMove,
2028 TabularGridFrame::OnToggleColMove)
2029
2030 EVT_UPDATE_UI(Id_Check_DrawNativeLabels,
2031 TabularGridFrame::OnUpdateDrawNativeLabelsUI)
e7ae8a69
VZ
2032
2033 EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
3b367af8 2034 EVT_BUTTON(wxID_RESET, TabularGridFrame::OnResetColumnOrder)
009c7216
VZ
2035 EVT_BUTTON(wxID_ADD, TabularGridFrame::OnShowHideColumn)
2036 EVT_BUTTON(wxID_DELETE, TabularGridFrame::OnShowHideColumn)
e7ae8a69 2037
11393d29 2038 EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
e7ae8a69 2039 EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
613de0e8 2040 EVT_GRID_COL_SIZE(TabularGridFrame::OnGridColSize)
cd68daf5
VZ
2041
2042 EVT_IDLE(TabularGridFrame::OnIdle)
e7ae8a69
VZ
2043END_EVENT_TABLE()
2044
2045TabularGridFrame::TabularGridFrame()
2046 : wxFrame(NULL, wxID_ANY, "Tabular table")
2047{
cd68daf5
VZ
2048 m_shouldUpdateOrder = false;
2049
2050 wxPanel * const panel = new wxPanel(this);
2051
e7ae8a69 2052 // create and initialize the grid with the specified data
11393d29 2053 m_table = new TabularGridTable;
cd68daf5
VZ
2054 m_grid = new wxGrid(panel, wxID_ANY,
2055 wxDefaultPosition, wxDefaultSize,
2056 wxBORDER_STATIC | wxWANTS_CHARS);
11393d29 2057 m_grid->SetTable(m_table, true, wxGrid::wxGridSelectRows);
e7ae8a69 2058
e7ae8a69 2059 m_grid->EnableDragColMove();
cd68daf5
VZ
2060 m_grid->UseNativeColHeader();
2061 m_grid->HideRowLabels();
e7ae8a69
VZ
2062
2063 // add it and the other controls to the frame
2064 wxSizer * const sizerTop = new wxBoxSizer(wxVERTICAL);
2065 sizerTop->Add(m_grid, wxSizerFlags(1).Expand().Border());
2066
2067 wxSizer * const sizerControls = new wxBoxSizer(wxHORIZONTAL);
2068
2069 wxSizer * const sizerStyles = new wxBoxSizer(wxVERTICAL);
cd68daf5 2070 m_chkUseNative = new wxCheckBox(panel, Id_Check_UseNativeHeader,
e7ae8a69
VZ
2071 "&Use native header");
2072 m_chkUseNative->SetValue(true);
2073 sizerStyles->Add(m_chkUseNative, wxSizerFlags().Border());
2074
cd68daf5
VZ
2075 m_chkDrawNative = new wxCheckBox(panel, Id_Check_DrawNativeLabels,
2076 "&Draw native column labels");
2077 sizerStyles->Add(m_chkDrawNative, wxSizerFlags().Border());
2078
2079 m_chkShowRowLabels = new wxCheckBox(panel, Id_Check_ShowRowLabels,
2080 "Show &row labels");
2081 sizerStyles->Add(m_chkShowRowLabels, wxSizerFlags().Border());
2082
2083 m_chkEnableColMove = new wxCheckBox(panel, Id_Check_EnableColMove,
e7ae8a69
VZ
2084 "Allow column re&ordering");
2085 m_chkEnableColMove->SetValue(true);
2086 sizerStyles->Add(m_chkEnableColMove, wxSizerFlags().Border());
2087 sizerControls->Add(sizerStyles);
2088
2089 sizerControls->AddSpacer(10);
2090
2091 wxSizer * const sizerColumns = new wxBoxSizer(wxVERTICAL);
2092 wxSizer * const sizerMoveCols = new wxBoxSizer(wxHORIZONTAL);
2093 const wxSizerFlags
2094 flagsHorz(wxSizerFlags().Border(wxLEFT | wxRIGHT).Centre());
cd68daf5 2095 sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&Move column"),
e7ae8a69 2096 flagsHorz);
cd68daf5 2097 m_txtColIndex = new ColIndexEntry(panel);
e7ae8a69 2098 sizerMoveCols->Add(m_txtColIndex, flagsHorz);
cd68daf5
VZ
2099 sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&to"), flagsHorz);
2100 m_txtColPos = new ColIndexEntry(panel);
e7ae8a69 2101 sizerMoveCols->Add(m_txtColPos, flagsHorz);
cd68daf5 2102 sizerMoveCols->Add(new wxButton(panel, wxID_APPLY), flagsHorz);
e7ae8a69
VZ
2103
2104 sizerColumns->Add(sizerMoveCols, wxSizerFlags().Expand().Border(wxBOTTOM));
2105
2106 wxSizer * const sizerShowCols = new wxBoxSizer(wxHORIZONTAL);
cd68daf5 2107 sizerShowCols->Add(new wxStaticText(panel, wxID_ANY, "Current order:"),
e7ae8a69 2108 flagsHorz);
e8f25dbb 2109 m_statOrder = new wxStaticText(panel, wxID_ANY, "<<< default >>>");
e7ae8a69 2110 sizerShowCols->Add(m_statOrder, flagsHorz);
3b367af8 2111 sizerShowCols->Add(new wxButton(panel, wxID_RESET, "&Reset order"));
e7ae8a69
VZ
2112 sizerColumns->Add(sizerShowCols, wxSizerFlags().Expand().Border(wxTOP));
2113
009c7216
VZ
2114 wxSizer * const sizerShowHide = new wxBoxSizer(wxHORIZONTAL);
2115 sizerShowHide->Add(new wxStaticText(panel, wxID_ANY, "Show/hide column:"),
2116 flagsHorz);
2117 m_txtColShowHide = new ColIndexEntry(panel);
2118 sizerShowHide->Add(m_txtColShowHide, flagsHorz);
2119 sizerShowHide->Add(new wxButton(panel, wxID_ADD, "&Show"), flagsHorz);
2120 sizerShowHide->Add(new wxButton(panel, wxID_DELETE, "&Hide"), flagsHorz);
2121 sizerColumns->Add(sizerShowHide, wxSizerFlags().Expand().Border(wxTOP));
2122
e7ae8a69
VZ
2123 sizerControls->Add(sizerColumns, wxSizerFlags(1).Expand().Border());
2124
2125 sizerTop->Add(sizerControls, wxSizerFlags().Expand().Border());
2126
cd68daf5
VZ
2127 panel->SetSizer(sizerTop);
2128
2129 SetClientSize(panel->GetBestSize());
2130 SetSizeHints(GetSize());
2131
e7ae8a69
VZ
2132 Show();
2133}
2134
2135void GridFrame::OnTabularTable(wxCommandEvent&)
2136{
2137 new TabularGridFrame;
2138}