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