Allow changing horizontal alignment of numeric cells in 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 grid->SetCellAlignment(2, 8, wxALIGN_CENTRE, wxALIGN_TOP);
460 grid->SetCellValue(2, 9, "<- This numeric cell should be centred");
461
462 const wxString choices[] =
463 {
464 wxT("Please select a choice"),
465 wxT("This takes two cells"),
466 wxT("Another choice"),
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]);
471 grid->SetCellOverflow(4, 0, false);
472
473 grid->SetCellSize(7, 1, 3, 4);
474 grid->SetCellAlignment(7, 1, wxALIGN_CENTRE, wxALIGN_CENTRE);
475 grid->SetCellValue(7, 1, wxT("Big box!"));
476
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
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
491 wxBoxSizer *topSizer = new wxBoxSizer( wxVERTICAL );
492 topSizer->Add( grid,
493 1,
494 wxEXPAND );
495
496 #if wxUSE_LOG
497 topSizer->Add( logWin,
498 0,
499 wxEXPAND );
500 #endif // wxUSE_LOG
501
502 SetSizerAndFit( topSizer );
503
504 Centre();
505 SetDefaults();
506 }
507
508
509 GridFrame::~GridFrame()
510 {
511 #if wxUSE_LOG
512 delete wxLog::SetActiveTarget(m_logOld);
513 #endif // wxUSE_LOG
514 }
515
516
517 void GridFrame::SetDefaults()
518 {
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 );
524 GetMenuBar()->Check( ID_TOGGLECOLMOVING, false );
525 GetMenuBar()->Check( ID_TOGGLEGRIDSIZING, true );
526 GetMenuBar()->Check( ID_TOGGLEGRIDDRAGCELL, false );
527 GetMenuBar()->Check( ID_TOGGLEGRIDLINES, true );
528 GetMenuBar()->Check( ID_CELLOVERFLOW, true );
529 }
530
531
532 void 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
545 void 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
558 void GridFrame::ToggleEditing( wxCommandEvent& WXUNUSED(ev) )
559 {
560 grid->EnableEditing(
561 GetMenuBar()->IsChecked( ID_TOGGLEEDIT ) );
562 }
563
564
565 void GridFrame::ToggleRowSizing( wxCommandEvent& WXUNUSED(ev) )
566 {
567 grid->EnableDragRowSize(
568 GetMenuBar()->IsChecked( ID_TOGGLEROWSIZING ) );
569 }
570
571
572 void GridFrame::ToggleColSizing( wxCommandEvent& WXUNUSED(ev) )
573 {
574 grid->EnableDragColSize(
575 GetMenuBar()->IsChecked( ID_TOGGLECOLSIZING ) );
576 }
577
578 void GridFrame::ToggleColMoving( wxCommandEvent& WXUNUSED(ev) )
579 {
580 grid->EnableDragColMove(
581 GetMenuBar()->IsChecked( ID_TOGGLECOLMOVING ) );
582 }
583
584 void GridFrame::ToggleGridSizing( wxCommandEvent& WXUNUSED(ev) )
585 {
586 grid->EnableDragGridSize(
587 GetMenuBar()->IsChecked( ID_TOGGLEGRIDSIZING ) );
588 }
589
590 void GridFrame::ToggleGridDragCell( wxCommandEvent& WXUNUSED(ev) )
591 {
592 grid->EnableDragCell(
593 GetMenuBar()->IsChecked( ID_TOGGLEGRIDDRAGCELL ) );
594 }
595
596 void 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
604 void GridFrame::SetCustomColHeader( wxCommandEvent& WXUNUSED(ev) )
605 {
606 CustomColumnHeadersProvider* provider =
607 static_cast<CustomColumnHeadersProvider*>(grid->GetTable()->GetAttrProvider());
608 provider->UseCustomColHeaders(true);
609 grid->SetUseNativeColLabels(false);
610 }
611
612 void 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
621 void GridFrame::ToggleGridLines( wxCommandEvent& WXUNUSED(ev) )
622 {
623 grid->EnableGridLines(
624 GetMenuBar()->IsChecked( ID_TOGGLEGRIDLINES ) );
625 }
626
627 void GridFrame::OnSetHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
628 {
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")};
630
631 wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
632 wxT("Pen Width"), 11, choices);
633
634 int current = grid->GetCellHighlightPenWidth();
635 dlg.SetSelection(current);
636 if (dlg.ShowModal() == wxID_OK) {
637 grid->SetCellHighlightPenWidth(dlg.GetSelection());
638 }
639 }
640
641 void GridFrame::OnSetROHighlightWidth( wxCommandEvent& WXUNUSED(ev) )
642 {
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")};
644
645 wxSingleChoiceDialog dlg(this, wxT("Choose the thickness of the highlight pen:"),
646 wxT("Pen Width"), 11, choices);
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
657 void GridFrame::AutoSizeCols( wxCommandEvent& WXUNUSED(ev) )
658 {
659 grid->AutoSizeColumns();
660 grid->Refresh();
661 }
662
663 void GridFrame::CellOverflow( wxCommandEvent& ev )
664 {
665 grid->SetDefaultCellOverflow(ev.IsChecked());
666 grid->Refresh();
667 }
668
669 void 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
678 void 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
692 void 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
705 void GridFrame::SetLabelFont( wxCommandEvent& WXUNUSED(ev) )
706 {
707 wxFont font = wxGetFontFromUser(this);
708 if ( font.Ok() )
709 {
710 grid->SetLabelFont(font);
711 }
712 }
713
714 void 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
734 grid->SetRowLabelAlignment( horiz, vert );
735 }
736
737 void 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
757 grid->SetRowLabelAlignment( horiz, vert );
758 }
759
760
761 void 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
781 grid->SetColLabelAlignment( horiz, vert );
782 }
783
784
785 void 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
805 grid->SetColLabelAlignment( horiz, vert );
806 }
807
808
809 void 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
823 void GridFrame::InsertRow( wxCommandEvent& WXUNUSED(ev) )
824 {
825 grid->InsertRows( grid->GetGridCursorRow(), 1 );
826 }
827
828
829 void GridFrame::InsertCol( wxCommandEvent& WXUNUSED(ev) )
830 {
831 grid->InsertCols( grid->GetGridCursorCol(), 1 );
832 }
833
834
835 void GridFrame::DeleteSelectedRows( wxCommandEvent& WXUNUSED(ev) )
836 {
837 if ( grid->IsSelection() )
838 {
839 wxGridUpdateLocker locker(grid);
840 for ( int n = 0; n < grid->GetNumberRows(); )
841 {
842 if ( grid->IsInSelection( n , 0 ) )
843 grid->DeleteRows( n, 1 );
844 else
845 n++;
846 }
847 }
848 }
849
850
851 void 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
861 void 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
871 void 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
881 void 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
891 void GridFrame::AutoSizeLabelsCol(wxCommandEvent& WXUNUSED(event))
892 {
893 grid->SetColLabelSize( wxGRID_AUTOSIZE );
894 }
895
896 void GridFrame::AutoSizeLabelsRow(wxCommandEvent& WXUNUSED(event))
897 {
898 grid->SetRowLabelSize( wxGRID_AUTOSIZE );
899 }
900
901 void GridFrame::AutoSizeTable(wxCommandEvent& WXUNUSED(event))
902 {
903 grid->AutoSize();
904 }
905
906
907 void GridFrame::DeleteSelectedCols( wxCommandEvent& WXUNUSED(ev) )
908 {
909 if ( grid->IsSelection() )
910 {
911 wxGridUpdateLocker locker(grid);
912 for ( int n = 0; n < grid->GetNumberCols(); )
913 {
914 if ( grid->IsInSelection( 0 , n ) )
915 grid->DeleteCols( n, 1 );
916 else
917 n++;
918 }
919 }
920 }
921
922
923 void GridFrame::ClearGrid( wxCommandEvent& WXUNUSED(ev) )
924 {
925 grid->ClearGrid();
926 }
927
928 void GridFrame::SelectCells( wxCommandEvent& WXUNUSED(ev) )
929 {
930 grid->SetSelectionMode( wxGrid::wxGridSelectCells );
931 }
932
933 void GridFrame::SelectRows( wxCommandEvent& WXUNUSED(ev) )
934 {
935 grid->SetSelectionMode( wxGrid::wxGridSelectRows );
936 }
937
938 void GridFrame::SelectCols( wxCommandEvent& WXUNUSED(ev) )
939 {
940 grid->SetSelectionMode( wxGrid::wxGridSelectColumns );
941 }
942
943 void GridFrame::SelectRowsOrCols( wxCommandEvent& WXUNUSED(ev) )
944 {
945 grid->SetSelectionMode( wxGrid::wxGridSelectRowsOrColumns );
946 }
947
948 void 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
958 void 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.
965 wxPoint pt(0, 0);
966 wxRect r(pt, grid->GetSize());
967 grid->SetDefaultCellBackgroundColour(col);
968 grid->Refresh(true, &r);
969 }
970 }
971
972 void GridFrame::DeselectCell(wxCommandEvent& WXUNUSED(event))
973 {
974 grid->DeselectCell(3, 1);
975 }
976
977 void GridFrame::DeselectCol(wxCommandEvent& WXUNUSED(event))
978 {
979 grid->DeselectCol(2);
980 }
981
982 void GridFrame::DeselectRow(wxCommandEvent& WXUNUSED(event))
983 {
984 grid->DeselectRow(2);
985 }
986
987 void GridFrame::DeselectAll(wxCommandEvent& WXUNUSED(event))
988 {
989 grid->ClearSelection();
990 }
991
992 void GridFrame::SelectCell(wxCommandEvent& WXUNUSED(event))
993 {
994 grid->SelectBlock(3, 1, 3, 1, m_addToSel);
995 }
996
997 void GridFrame::SelectCol(wxCommandEvent& WXUNUSED(event))
998 {
999 grid->SelectCol(2, m_addToSel);
1000 }
1001
1002 void GridFrame::SelectRow(wxCommandEvent& WXUNUSED(event))
1003 {
1004 grid->SelectRow(2, m_addToSel);
1005 }
1006
1007 void GridFrame::SelectAll(wxCommandEvent& WXUNUSED(event))
1008 {
1009 grid->SelectAll();
1010 }
1011
1012 void GridFrame::OnAddToSelectToggle(wxCommandEvent& event)
1013 {
1014 m_addToSel = event.IsChecked();
1015 }
1016
1017 void GridFrame::OnLabelLeftClick( wxGridEvent& ev )
1018 {
1019 wxString logBuf;
1020 if ( ev.GetRow() != -1 )
1021 {
1022 logBuf << wxT("Left click on row label ") << ev.GetRow();
1023 }
1024 else if ( ev.GetCol() != -1 )
1025 {
1026 logBuf << wxT("Left click on col label ") << ev.GetCol();
1027 }
1028 else
1029 {
1030 logBuf << wxT("Left click on corner label");
1031 }
1032
1033 if ( ev.ShiftDown() )
1034 logBuf << wxT(" (shift down)");
1035 if ( ev.ControlDown() )
1036 logBuf << wxT(" (control down)");
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
1045 void GridFrame::OnCellLeftClick( wxGridEvent& ev )
1046 {
1047 wxLogMessage(wxT("Left click at row %d, col %d"), ev.GetRow(), ev.GetCol());
1048
1049 // you must call event skip if you want default grid processing
1050 // (cell highlighting etc.)
1051 //
1052 ev.Skip();
1053 }
1054
1055
1056 void GridFrame::OnRowSize( wxGridSizeEvent& ev )
1057 {
1058 const int row = ev.GetRowOrCol();
1059
1060 wxLogMessage("Resized row %d, new height = %d",
1061 row, grid->GetRowSize(row));
1062
1063 ev.Skip();
1064 }
1065
1066
1067 void GridFrame::OnColSize( wxGridSizeEvent& ev )
1068 {
1069 const int col = ev.GetRowOrCol();
1070
1071 wxLogMessage("Resized column %d, new width = %d",
1072 col, grid->GetColSize(col));
1073
1074 ev.Skip();
1075 }
1076
1077
1078 void 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();
1091 wxLogMessage(wxT("%lu cells selected:"), (unsigned long)count);
1092 if ( count > countMax )
1093 {
1094 wxLogMessage(wxT("[too many selected cells, ")
1095 wxT("showing only the first %lu]"),
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];
1103 wxLogMessage(wxT(" selected cell %lu: (%d, %d)"),
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 {
1118 plural = wxT("rows");
1119 single = wxT("row");
1120 }
1121 else // columns
1122 {
1123 plural = wxT("columns");
1124 single = wxT("column");
1125 }
1126
1127 const wxArrayInt sels((const wxArrayInt)(rows ? grid->GetSelectedRows()
1128 : grid->GetSelectedCols()));
1129 size_t count = sels.size();
1130 wxLogMessage(wxT("%lu %s selected:"),
1131 (unsigned long)count, plural);
1132 if ( count > countMax )
1133 {
1134 wxLogMessage(wxT("[too many selected %s, ")
1135 wxT("showing only the first %lu]"),
1136 plural, (unsigned long)countMax);
1137 count = countMax;
1138 }
1139
1140 for ( size_t n = 0; n < count; n++ )
1141 {
1142 wxLogMessage(wxT(" selected %s %lu: %d"),
1143 single, (unsigned long)n, sels[n]);
1144 }
1145 }
1146 break;
1147
1148 default:
1149 wxFAIL_MSG( wxT("unknown wxGrid selection mode") );
1150 break;
1151 }
1152 }
1153
1154 void GridFrame::OnSelectCell( wxGridEvent& ev )
1155 {
1156 wxString logBuf;
1157 if ( ev.Selecting() )
1158 logBuf << wxT("Selected ");
1159 else
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(" )");
1167
1168 //Indicate whether this column was moved
1169 if ( ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() ) != ev.GetCol() )
1170 logBuf << wxT(" *** Column moved, current position: ") << ((wxGrid *)ev.GetEventObject())->GetColPos( ev.GetCol() );
1171
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
1179 void GridFrame::OnRangeSelected( wxGridRangeSelectEvent& ev )
1180 {
1181 wxString logBuf;
1182 if ( ev.Selecting() )
1183 logBuf << wxT("Selected ");
1184 else
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(" )");
1194 wxLogMessage( wxT("%s"), logBuf.c_str() );
1195
1196 ev.Skip();
1197 }
1198
1199 void 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
1220 void GridFrame::OnCellValueChanged( wxGridEvent& ev )
1221 {
1222 int row = ev.GetRow(),
1223 col = ev.GetCol();
1224
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());
1229
1230 ev.Skip();
1231 }
1232
1233 void GridFrame::OnCellBeginDrag( wxGridEvent& ev )
1234 {
1235 wxLogMessage(wxT("Got request to drag cell at row %d, col %d"),
1236 ev.GetRow(), ev.GetCol());
1237
1238 ev.Skip();
1239 }
1240
1241 void GridFrame::OnEditorShown( wxGridEvent& ev )
1242 {
1243
1244 if ( (ev.GetCol() == 4) &&
1245 (ev.GetRow() == 0) &&
1246 (wxMessageBox(wxT("Are you sure you wish to edit this cell"),
1247 wxT("Checking"),wxYES_NO) == wxNO ) ) {
1248
1249 ev.Veto();
1250 return;
1251 }
1252
1253 wxLogMessage( wxT("Cell editor shown.") );
1254
1255 ev.Skip();
1256 }
1257
1258 void GridFrame::OnEditorHidden( wxGridEvent& ev )
1259 {
1260
1261 if ( (ev.GetCol() == 4) &&
1262 (ev.GetRow() == 0) &&
1263 (wxMessageBox(wxT("Are you sure you wish to finish editing this cell"),
1264 wxT("Checking"),wxYES_NO) == wxNO ) ) {
1265
1266 ev.Veto();
1267 return;
1268 }
1269
1270 wxLogMessage( wxT("Cell editor hidden.") );
1271
1272 ev.Skip();
1273 }
1274
1275 void GridFrame::About( wxCommandEvent& WXUNUSED(ev) )
1276 {
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
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
1291 wxAboutBox(aboutInfo);
1292 }
1293
1294
1295 void GridFrame::OnQuit( wxCommandEvent& WXUNUSED(ev) )
1296 {
1297 Close( true );
1298 }
1299
1300 void GridFrame::OnBugsTable(wxCommandEvent& )
1301 {
1302 BugsGridFrame *frame = new BugsGridFrame;
1303 frame->Show(true);
1304 }
1305
1306 // ----------------------------------------------------------------------------
1307 // MyGridCellAttrProvider
1308 // ----------------------------------------------------------------------------
1309
1310 MyGridCellAttrProvider::MyGridCellAttrProvider()
1311 {
1312 m_attrForOddRows = new wxGridCellAttr;
1313 m_attrForOddRows->SetBackgroundColour(*wxLIGHT_GREY);
1314 }
1315
1316 MyGridCellAttrProvider::~MyGridCellAttrProvider()
1317 {
1318 m_attrForOddRows->DecRef();
1319 }
1320
1321 wxGridCellAttr *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
1348 void GridFrame::OnVTable(wxCommandEvent& )
1349 {
1350 static long s_sizeGrid = 10000;
1351
1352 s_sizeGrid = wxGetNumberFromUser(wxT("Size of the table to create"),
1353 wxT("Size: "),
1354 wxT("wxGridDemo question"),
1355 s_sizeGrid,
1356 0, 32000, this);
1357
1358 if ( s_sizeGrid != -1 )
1359 {
1360 BigGridFrame* win = new BigGridFrame(s_sizeGrid);
1361 win->Show(true);
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
1372 void 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
1386 // ============================================================================
1387 // BigGridFrame and BigGridTable: Sample of a non-standard table
1388 // ============================================================================
1389
1390 BigGridFrame::BigGridFrame(long sizeGrid)
1391 : wxFrame(NULL, wxID_ANY, wxT("Plugin Virtual Table"),
1392 wxDefaultPosition, wxSize(500, 450))
1393 {
1394 m_grid = new wxGrid(this, wxID_ANY, wxDefaultPosition, wxDefaultSize);
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
1401 m_grid->SetTable(m_table, true);
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
1419 enum 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
1430 enum Severity
1431 {
1432 Sev_Wish,
1433 Sev_Minor,
1434 Sev_Normal,
1435 Sev_Major,
1436 Sev_Critical,
1437 Sev_Max
1438 };
1439
1440 static const wxString severities[] =
1441 {
1442 wxT("wishlist"),
1443 wxT("minor"),
1444 wxT("normal"),
1445 wxT("major"),
1446 wxT("critical"),
1447 };
1448
1449 static 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 {
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 },
1463 };
1464
1465 static const wxChar *headers[Col_Max] =
1466 {
1467 wxT("Id"),
1468 wxT("Summary"),
1469 wxT("Severity"),
1470 wxT("Priority"),
1471 wxT("Platform"),
1472 wxT("Opened?"),
1473 };
1474
1475 // ----------------------------------------------------------------------------
1476 // BugsGridTable
1477 // ----------------------------------------------------------------------------
1478
1479 wxString 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:
1491 return wxString::Format(wxT("%s:80"), wxGRID_VALUE_STRING);
1492
1493 case Col_Platform:
1494 return wxString::Format(wxT("%s:all,MSW,GTK,other"), wxGRID_VALUE_CHOICE);
1495
1496 case Col_Opened:
1497 return wxGRID_VALUE_BOOL;
1498 }
1499
1500 wxFAIL_MSG(wxT("unknown column"));
1501
1502 return wxEmptyString;
1503 }
1504
1505 int BugsGridTable::GetNumberRows()
1506 {
1507 return WXSIZEOF(gs_dataBugsGrid);
1508 }
1509
1510 int BugsGridTable::GetNumberCols()
1511 {
1512 return Col_Max;
1513 }
1514
1515 bool BugsGridTable::IsEmptyCell( int WXUNUSED(row), int WXUNUSED(col) )
1516 {
1517 return false;
1518 }
1519
1520 wxString BugsGridTable::GetValue( int row, int col )
1521 {
1522 const BugsGridData& gd = gs_dataBugsGrid[row];
1523
1524 switch ( col )
1525 {
1526 case Col_Id:
1527 return wxString::Format(wxT("%d"), gd.id);
1528
1529 case Col_Priority:
1530 return wxString::Format(wxT("%d"), gd.prio);
1531
1532 case Col_Opened:
1533 return gd.opened ? wxT("1") : wxT("0");
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
1548 void 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:
1557 wxFAIL_MSG(wxT("unexpected column"));
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 {
1574 wxLogWarning(wxT("Invalid severity value '%s'."),
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
1591 bool
1592 BugsGridTable::CanGetValueAs(int WXUNUSED(row),
1593 int col,
1594 const wxString& typeName)
1595 {
1596 if ( typeName == wxGRID_VALUE_STRING )
1597 {
1598 return true;
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 {
1610 return false;
1611 }
1612 }
1613
1614 bool BugsGridTable::CanSetValueAs( int row, int col, const wxString& typeName )
1615 {
1616 return CanGetValueAs(row, col, typeName);
1617 }
1618
1619 long 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:
1635 wxFAIL_MSG(wxT("unexpected column"));
1636 return -1;
1637 }
1638 }
1639
1640 bool BugsGridTable::GetValueAsBool( int row, int col )
1641 {
1642 if ( col == Col_Opened )
1643 {
1644 return gs_dataBugsGrid[row].opened;
1645 }
1646 else
1647 {
1648 wxFAIL_MSG(wxT("unexpected column"));
1649
1650 return false;
1651 }
1652 }
1653
1654 void 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:
1665 wxFAIL_MSG(wxT("unexpected column"));
1666 }
1667 }
1668
1669 void 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 {
1677 wxFAIL_MSG(wxT("unexpected column"));
1678 }
1679 }
1680
1681 wxString BugsGridTable::GetColLabelValue( int col )
1682 {
1683 return headers[col];
1684 }
1685
1686 // ----------------------------------------------------------------------------
1687 // BugsGridFrame
1688 // ----------------------------------------------------------------------------
1689
1690 BugsGridFrame::BugsGridFrame()
1691 : wxFrame(NULL, wxID_ANY, wxT("Bugs table"))
1692 {
1693 wxGrid *grid = new wxGrid(this, wxID_ANY);
1694 wxGridTableBase *table = new BugsGridTable();
1695 table->SetAttrProvider(new MyGridCellAttrProvider);
1696 grid->SetTable(table, true);
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
1711 grid->Fit();
1712 SetClientSize(grid->GetSize());
1713 }
1714
1715 // ============================================================================
1716 // TabularGrid: grid used for display of tabular data
1717 // ============================================================================
1718
1719 class TabularGridTable : public wxGridTableBase
1720 {
1721 public:
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
1736 TabularGridTable() { m_sortOrder = NULL; }
1737
1738 virtual int GetNumberRows() { return ROW_MAX; }
1739 virtual int GetNumberCols() { return COL_MAX; }
1740
1741 virtual wxString GetValue(int row, int col)
1742 {
1743 if ( m_sortOrder )
1744 row = m_sortOrder[row];
1745
1746 switch ( col )
1747 {
1748 case COL_NAME:
1749 case COL_EXT:
1750 return GetNameOrExt(row, col);
1751
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();
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 {
1773 // notice that column parameter here always refers to the internal
1774 // column index, independently of its position on the screen
1775 static const char *labels[] = { "Name", "Extension", "Size", "Date" };
1776 wxCOMPILE_TIME_ASSERT( WXSIZEOF(labels) == COL_MAX, LabelsMismatch );
1777
1778 return labels[col];
1779 }
1780
1781 virtual void SetColLabelValue(int, const wxString&)
1782 {
1783 wxFAIL_MSG( "shouldn't be called" );
1784 }
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
1801 private:
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;
1833 };
1834
1835 // specialized text control for column indexes entry
1836 class ColIndexEntry : public wxTextCtrl
1837 {
1838 public:
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
1857 protected:
1858 virtual wxSize DoGetBestSize() const
1859 {
1860 wxSize size = wxTextCtrl::DoGetBestSize();
1861 size.x = 3*GetCharWidth();
1862 return size;
1863 }
1864 };
1865
1866 class TabularGridFrame : public wxFrame
1867 {
1868 public:
1869 TabularGridFrame();
1870
1871 private:
1872 enum // control ids
1873 {
1874 Id_Check_UseNativeHeader,
1875 Id_Check_DrawNativeLabels,
1876 Id_Check_ShowRowLabels,
1877 Id_Check_EnableColMove
1878 };
1879
1880 // event handlers
1881
1882 void OnToggleUseNativeHeader(wxCommandEvent&)
1883 {
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);
1904 }
1905
1906 void OnToggleColMove(wxCommandEvent&)
1907 {
1908 m_grid->EnableDragColMove(m_chkEnableColMove->IsChecked());
1909 }
1910
1911 void OnShowHideColumn(wxCommandEvent& event)
1912 {
1913 int col = m_txtColShowHide->GetCol();
1914 if ( col != -1 )
1915 {
1916 m_grid->SetColSize(col,
1917 event.GetId() == wxID_ADD ? wxGRID_AUTOSIZE : 0);
1918
1919 UpdateOrderAndVisibility();
1920 }
1921 }
1922
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
1932 UpdateOrderAndVisibility();
1933 }
1934
1935 void OnResetColumnOrder(wxCommandEvent&)
1936 {
1937 m_grid->ResetColPos();
1938
1939 UpdateOrderAndVisibility();
1940 }
1941
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
1949 void OnGridColMove(wxGridEvent& event)
1950 {
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
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
1968 void OnIdle(wxIdleEvent& event)
1969 {
1970 if ( m_shouldUpdateOrder )
1971 {
1972 m_shouldUpdateOrder = false;
1973 UpdateOrderAndVisibility();
1974 }
1975
1976 event.Skip();
1977 }
1978
1979 void UpdateOrderAndVisibility()
1980 {
1981 wxString s;
1982 for ( int pos = 0; pos < TabularGridTable::COL_MAX; pos++ )
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 }
1995
1996 m_statOrder->SetLabel(s);
1997 }
1998
1999 // controls
2000 wxGrid *m_grid;
2001 TabularGridTable *m_table;
2002 wxCheckBox *m_chkUseNative,
2003 *m_chkDrawNative,
2004 *m_chkShowRowLabels,
2005 *m_chkEnableColMove;
2006
2007 ColIndexEntry *m_txtColIndex,
2008 *m_txtColPos,
2009 *m_txtColShowHide;
2010
2011 wxStaticText *m_statOrder;
2012
2013 // fla for EVT_IDLE handler
2014 bool m_shouldUpdateOrder;
2015
2016 wxDECLARE_NO_COPY_CLASS(TabularGridFrame);
2017 DECLARE_EVENT_TABLE()
2018 };
2019
2020 BEGIN_EVENT_TABLE(TabularGridFrame, wxFrame)
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)
2032
2033 EVT_BUTTON(wxID_APPLY, TabularGridFrame::OnMoveColumn)
2034 EVT_BUTTON(wxID_RESET, TabularGridFrame::OnResetColumnOrder)
2035 EVT_BUTTON(wxID_ADD, TabularGridFrame::OnShowHideColumn)
2036 EVT_BUTTON(wxID_DELETE, TabularGridFrame::OnShowHideColumn)
2037
2038 EVT_GRID_COL_SORT(TabularGridFrame::OnGridColSort)
2039 EVT_GRID_COL_MOVE(TabularGridFrame::OnGridColMove)
2040 EVT_GRID_COL_SIZE(TabularGridFrame::OnGridColSize)
2041
2042 EVT_IDLE(TabularGridFrame::OnIdle)
2043 END_EVENT_TABLE()
2044
2045 TabularGridFrame::TabularGridFrame()
2046 : wxFrame(NULL, wxID_ANY, "Tabular table")
2047 {
2048 m_shouldUpdateOrder = false;
2049
2050 wxPanel * const panel = new wxPanel(this);
2051
2052 // create and initialize the grid with the specified data
2053 m_table = new TabularGridTable;
2054 m_grid = new wxGrid(panel, wxID_ANY,
2055 wxDefaultPosition, wxDefaultSize,
2056 wxBORDER_STATIC | wxWANTS_CHARS);
2057 m_grid->SetTable(m_table, true, wxGrid::wxGridSelectRows);
2058
2059 m_grid->EnableDragColMove();
2060 m_grid->UseNativeColHeader();
2061 m_grid->HideRowLabels();
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);
2070 m_chkUseNative = new wxCheckBox(panel, Id_Check_UseNativeHeader,
2071 "&Use native header");
2072 m_chkUseNative->SetValue(true);
2073 sizerStyles->Add(m_chkUseNative, wxSizerFlags().Border());
2074
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,
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());
2095 sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&Move column"),
2096 flagsHorz);
2097 m_txtColIndex = new ColIndexEntry(panel);
2098 sizerMoveCols->Add(m_txtColIndex, flagsHorz);
2099 sizerMoveCols->Add(new wxStaticText(panel, wxID_ANY, "&to"), flagsHorz);
2100 m_txtColPos = new ColIndexEntry(panel);
2101 sizerMoveCols->Add(m_txtColPos, flagsHorz);
2102 sizerMoveCols->Add(new wxButton(panel, wxID_APPLY), flagsHorz);
2103
2104 sizerColumns->Add(sizerMoveCols, wxSizerFlags().Expand().Border(wxBOTTOM));
2105
2106 wxSizer * const sizerShowCols = new wxBoxSizer(wxHORIZONTAL);
2107 sizerShowCols->Add(new wxStaticText(panel, wxID_ANY, "Current order:"),
2108 flagsHorz);
2109 m_statOrder = new wxStaticText(panel, wxID_ANY, "<<< default >>>");
2110 sizerShowCols->Add(m_statOrder, flagsHorz);
2111 sizerShowCols->Add(new wxButton(panel, wxID_RESET, "&Reset order"));
2112 sizerColumns->Add(sizerShowCols, wxSizerFlags().Expand().Border(wxTOP));
2113
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
2123 sizerControls->Add(sizerColumns, wxSizerFlags(1).Expand().Border());
2124
2125 sizerTop->Add(sizerControls, wxSizerFlags().Expand().Border());
2126
2127 panel->SetSizer(sizerTop);
2128
2129 SetClientSize(panel->GetBestSize());
2130 SetSizeHints(GetSize());
2131
2132 Show();
2133 }
2134
2135 void GridFrame::OnTabularTable(wxCommandEvent&)
2136 {
2137 new TabularGridFrame;
2138 }