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