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