1 /////////////////////////////////////////////////////////////////////////////
2 // Name: dataview.cpp
3 // Purpose: wxDataViewCtrl wxWidgets sample
4 // Author: Robert Roebling
5 // Modified by: Francesco Montorsi, Bo Yang
6 // Created: 06/01/06
7 // Copyright: (c) Robert Roebling
8 // Licence: wxWindows licence
9 /////////////////////////////////////////////////////////////////////////////
10
11 // ============================================================================
12 // declarations
13 // ============================================================================
14
15 // For compilers that support precompilation, includes "wx/wx.h".
16 #include "wx/wxprec.h"
17
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #include "wx/artprov.h"
24 #include "wx/dataview.h"
25 #include "wx/datetime.h"
26 #include "wx/splitter.h"
27 #include "wx/aboutdlg.h"
28 #include "wx/colordlg.h"
29 #include "wx/choicdlg.h"
30 #include "wx/numdlg.h"
31 #include "wx/spinctrl.h"
32 #include "wx/imaglist.h"
33 #include "wx/itemattr.h"
34 #include "wx/notebook.h"
35
36 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
37 #include "wx/headerctrl.h"
38 #endif // wxHAS_GENERIC_DATAVIEWCTRL
39
40 #include "mymodels.h"
41
42 // ----------------------------------------------------------------------------
43 // resources
44 // ----------------------------------------------------------------------------
45
46 #ifndef wxHAS_IMAGES_IN_RESOURCES
47 #include "../sample.xpm"
48 #endif
49
50 #include "wx_small.xpm"
51
52 // ----------------------------------------------------------------------------
53 // MyApp
54 // ----------------------------------------------------------------------------
55
56 class MyApp: public wxApp
57 {
58 public:
59 virtual bool OnInit() wxOVERRIDE;
60 };
61
62 // ----------------------------------------------------------------------------
63 // MyFrame
64 // ----------------------------------------------------------------------------
65
66 class MyFrame : public wxFrame
67 {
68 public:
69 MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int h);
70 ~MyFrame();
71
72 void BuildDataViewCtrl(wxPanel* parent,
73 unsigned int nPanel,
74 unsigned long style = 0);
75
76 private:
77 // event handlers
78 void OnStyleChange(wxCommandEvent& event);
79 void OnSetBackgroundColour(wxCommandEvent& event);
80 void OnCustomHeaderAttr(wxCommandEvent& event);
81 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
82 void OnCustomHeaderHeight(wxCommandEvent& event);
83 #endif // wxHAS_GENERIC_DATAVIEWCTRL
84 void OnGetPageInfo(wxCommandEvent& event);
85 void OnDisable(wxCommandEvent& event);
86 void OnSetForegroundColour(wxCommandEvent& event);
87 void OnIncIndent(wxCommandEvent& event);
88 void OnDecIndent(wxCommandEvent& event);
89
90 void OnQuit(wxCommandEvent& event);
91 void OnAbout(wxCommandEvent& event);
92
93 void OnClearLog(wxCommandEvent& event);
94 void OnPageChanged(wxBookCtrlEvent& event);
95
96 void OnAddMozart(wxCommandEvent& event);
97 void OnDeleteSelected(wxCommandEvent& event);
98 void OnDeleteYear(wxCommandEvent& event);
99 void OnSelectNinth(wxCommandEvent& event);
100 void OnCollapse(wxCommandEvent& event);
101 void OnExpand(wxCommandEvent& event);
102 void OnShowCurrent(wxCommandEvent& event);
103 void OnSetNinthCurrent(wxCommandEvent& event);
104 void OnChangeNinthTitle(wxCommandEvent& event);
105
106 void OnPrependList(wxCommandEvent& event);
107 void OnDeleteList(wxCommandEvent& event);
108
109 // Third (wxDataViewListCtrl) page.
110 void OnListValueChanged(wxDataViewEvent& event);
111
112 // Fourth page.
113 void OnDeleteTreeItem(wxCommandEvent& event);
114 void OnDeleteAllTreeItems(wxCommandEvent& event);
115 void OnAddTreeItem(wxCommandEvent& event);
116 void OnAddTreeContainerItem(wxCommandEvent& event);
117
OnIndexListUseEnglish(wxCommandEvent &)118 void OnIndexListUseEnglish(wxCommandEvent&) { FillIndexList(Lang_English); }
OnIndexListUseFrench(wxCommandEvent &)119 void OnIndexListUseFrench(wxCommandEvent&) { FillIndexList(Lang_French); }
120 void OnIndexListResetModel(wxCommandEvent& event);
121 void OnIndexListSelectionChanged(wxDataViewEvent& event);
122
123 void OnValueChanged( wxDataViewEvent &event );
124
125 void OnActivated( wxDataViewEvent &event );
126 void OnExpanding( wxDataViewEvent &event );
127 void OnExpanded( wxDataViewEvent &event );
128 void OnCollapsing( wxDataViewEvent &event );
129 void OnCollapsed( wxDataViewEvent &event );
130 void OnSelectionChanged( wxDataViewEvent &event );
131
132 void OnStartEditing( wxDataViewEvent &event );
133 void OnEditingStarted( wxDataViewEvent &event );
134 void OnEditingDone( wxDataViewEvent &event );
135
136 void OnHeaderClick( wxDataViewEvent &event );
137 void OnAttrHeaderClick( wxDataViewEvent &event );
138 void OnHeaderRightClick( wxDataViewEvent &event );
139 void OnHeaderClickList( wxDataViewEvent &event );
140 void OnSorted( wxDataViewEvent &event );
141 void OnSortedList( wxDataViewEvent &event );
142 void OnColumnReordered( wxDataViewEvent &event);
143
144 void OnContextMenu( wxDataViewEvent &event );
145
146 void OnGoto( wxCommandEvent &event);
147 void OnAddMany( wxCommandEvent &event);
148 void OnHideAttributes( wxCommandEvent &event);
149 void OnShowAttributes( wxCommandEvent &event);
150
151 void OnMultipleSort( wxCommandEvent &event);
152 void OnSortByFirstColumn( wxCommandEvent &event);
153
154 #if wxUSE_DRAG_AND_DROP
155 void OnBeginDrag( wxDataViewEvent &event );
156 void OnDropPossible( wxDataViewEvent &event );
157 void OnDrop( wxDataViewEvent &event );
158 #endif // wxUSE_DRAG_AND_DROP
159
160 void OnDataViewChar(wxKeyEvent& event);
161
162 // helper used by both OnDeleteSelected() and OnDataViewChar()
163 void DeleteSelectedItems();
164
165 // helper for the index list model fills the model with the weekday names
166 // in the specified language
167 enum Lang { Lang_English, Lang_French };
168 void FillIndexList(Lang lang);
169
170 // HasValue page.
171 void OnHasValueValueChanged(wxDataViewEvent& event);
172
173
174 wxNotebook* m_notebook;
175
176 // the controls stored in the various tabs of the main notebook:
177 enum Page
178 {
179 Page_Music,
180 Page_List,
181 Page_ListStore,
182 Page_TreeStore,
183 Page_VarHeight,
184 Page_IndexList,
185 Page_HasValue,
186 Page_Max
187 };
188
189 wxDataViewCtrl* m_ctrl[Page_Max];
190
191 // Some of the models associated with the controls:
192
193 wxObjectDataPtr<MyMusicTreeModel> m_music_model;
194 wxObjectDataPtr<MyLongMusicTreeModel> m_long_music_model;
195 wxObjectDataPtr<MyListModel> m_list_model;
196 wxObjectDataPtr<MyIndexListModel> m_index_list_model;
197
198 // other data:
199
200 wxDataViewColumn* m_col;
201 wxDataViewColumn* m_attributes;
202
203 wxTextCtrl* m_log;
204 wxLog *m_logOld;
205
206 private:
207 // Flag used by OnListValueChanged(), see there.
208 bool m_eventFromProgram;
209
210 wxDECLARE_EVENT_TABLE();
211 };
212
213
214 // ----------------------------------------------------------------------------
215 // MyCustomRenderer
216 // ----------------------------------------------------------------------------
217
218 class MyCustomRenderer: public wxDataViewCustomRenderer
219 {
220 public:
221 // This renderer can be either activatable or editable, for demonstration
222 // purposes. In real programs, you should select whether the user should be
223 // able to activate or edit the cell and it doesn't make sense to switch
224 // between the two -- but this is just an example, so it doesn't stop us.
MyCustomRenderer(wxDataViewCellMode mode)225 explicit MyCustomRenderer(wxDataViewCellMode mode)
226 : wxDataViewCustomRenderer("string", mode, wxALIGN_CENTER)
227 { }
228
Render(wxRect rect,wxDC * dc,int state)229 virtual bool Render( wxRect rect, wxDC *dc, int state ) wxOVERRIDE
230 {
231 dc->SetBrush( *wxLIGHT_GREY_BRUSH );
232 dc->SetPen( *wxTRANSPARENT_PEN );
233
234 rect.Deflate(2);
235 dc->DrawRoundedRectangle( rect, 5 );
236
237 RenderText(m_value,
238 0, // no offset
239 wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
240 dc,
241 state);
242 return true;
243 }
244
ActivateCell(const wxRect & WXUNUSED (cell),wxDataViewModel * WXUNUSED (model),const wxDataViewItem & WXUNUSED (item),unsigned int WXUNUSED (col),const wxMouseEvent * mouseEvent)245 virtual bool ActivateCell(const wxRect& WXUNUSED(cell),
246 wxDataViewModel *WXUNUSED(model),
247 const wxDataViewItem &WXUNUSED(item),
248 unsigned int WXUNUSED(col),
249 const wxMouseEvent *mouseEvent) wxOVERRIDE
250 {
251 wxString position;
252 if ( mouseEvent )
253 position = wxString::Format("via mouse at %d, %d", mouseEvent->m_x, mouseEvent->m_y);
254 else
255 position = "from keyboard";
256 wxLogMessage("MyCustomRenderer ActivateCell() %s", position);
257 return false;
258 }
259
GetSize() const260 virtual wxSize GetSize() const wxOVERRIDE
261 {
262 return GetView()->FromDIP(wxSize(60, 20));
263 }
264
SetValue(const wxVariant & value)265 virtual bool SetValue( const wxVariant &value ) wxOVERRIDE
266 {
267 m_value = value.GetString();
268 return true;
269 }
270
GetValue(wxVariant & WXUNUSED (value)) const271 virtual bool GetValue( wxVariant &WXUNUSED(value) ) const wxOVERRIDE { return true; }
272
273 #if wxUSE_ACCESSIBILITY
GetAccessibleDescription() const274 virtual wxString GetAccessibleDescription() const wxOVERRIDE
275 {
276 return m_value;
277 }
278 #endif // wxUSE_ACCESSIBILITY
279
HasEditorCtrl() const280 virtual bool HasEditorCtrl() const wxOVERRIDE { return true; }
281
282 virtual wxWindow*
CreateEditorCtrl(wxWindow * parent,wxRect labelRect,const wxVariant & value)283 CreateEditorCtrl(wxWindow* parent,
284 wxRect labelRect,
285 const wxVariant& value) wxOVERRIDE
286 {
287 wxTextCtrl* text = new wxTextCtrl(parent, wxID_ANY, value,
288 labelRect.GetPosition(),
289 labelRect.GetSize(),
290 wxTE_PROCESS_ENTER);
291 text->SetInsertionPointEnd();
292
293 return text;
294 }
295
296 virtual bool
GetValueFromEditorCtrl(wxWindow * ctrl,wxVariant & value)297 GetValueFromEditorCtrl(wxWindow* ctrl, wxVariant& value) wxOVERRIDE
298 {
299 wxTextCtrl* text = wxDynamicCast(ctrl, wxTextCtrl);
300 if ( !text )
301 return false;
302
303 value = text->GetValue();
304
305 return true;
306 }
307
308 private:
309 wxString m_value;
310 };
311
312
313 // ----------------------------------------------------------------------------
314 // MultiLineCustomRenderer
315 // ----------------------------------------------------------------------------
316
317 class MultiLineCustomRenderer : public wxDataViewCustomRenderer
318 {
319 public:
320 // a simple renderer that wraps each word on a new line
MultiLineCustomRenderer()321 explicit MultiLineCustomRenderer()
322 : wxDataViewCustomRenderer("string", wxDATAVIEW_CELL_INERT, 0)
323 { }
324
Render(wxRect rect,wxDC * dc,int state)325 virtual bool Render(wxRect rect, wxDC *dc, int state) wxOVERRIDE
326 {
327 RenderText(m_value, 0, rect, dc, state);
328 return true;
329 }
330
GetSize() const331 virtual wxSize GetSize() const wxOVERRIDE
332 {
333 wxSize txtSize = GetTextExtent(m_value);
334 int lines = m_value.Freq('\n') + 1;
335 txtSize.SetHeight(txtSize.GetHeight() * lines);
336 return txtSize;
337 }
338
SetValue(const wxVariant & value)339 virtual bool SetValue(const wxVariant &value) wxOVERRIDE
340 {
341 m_value = value.GetString();
342 m_value.Replace(" ", "\n");
343 return true;
344 }
345
GetValue(wxVariant & WXUNUSED (value)) const346 virtual bool GetValue(wxVariant &WXUNUSED(value)) const wxOVERRIDE { return true; }
347
348 #if wxUSE_ACCESSIBILITY
GetAccessibleDescription() const349 virtual wxString GetAccessibleDescription() const wxOVERRIDE
350 {
351 return m_value;
352 }
353 #endif // wxUSE_ACCESSIBILITY
354
355 private:
356 wxString m_value;
357 };
358
359
360 // ============================================================================
361 // implementation
362 // ============================================================================
363
364 // ----------------------------------------------------------------------------
365 // MyApp
366 // ----------------------------------------------------------------------------
367
368 wxIMPLEMENT_APP(MyApp);
369
OnInit()370 bool MyApp::OnInit()
371 {
372 if ( !wxApp::OnInit() )
373 return false;
374
375 MyFrame *frame =
376 new MyFrame(NULL, "wxDataViewCtrl sample", 40, 40, 1000, 540);
377
378 frame->Show(true);
379 return true;
380 }
381
382
383 // ----------------------------------------------------------------------------
384 // MyFrame
385 // ----------------------------------------------------------------------------
386
387 enum
388 {
389 ID_CLEARLOG = wxID_HIGHEST+1,
390 ID_GET_PAGE_INFO,
391 ID_DISABLE,
392 ID_BACKGROUND_COLOUR,
393 ID_FOREGROUND_COLOUR,
394 ID_CUSTOM_HEADER_ATTR,
395 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
396 ID_CUSTOM_HEADER_HEIGHT,
397 #endif // wxHAS_GENERIC_DATAVIEWCTRL
398 ID_STYLE_MENU,
399 ID_INC_INDENT,
400 ID_DEC_INDENT,
401
402 // file menu
403 //ID_SINGLE, wxDV_SINGLE==0 so it's always present
404 ID_MULTIPLE,
405 ID_ROW_LINES,
406 ID_HORIZ_RULES,
407 ID_VERT_RULES,
408
409 ID_EXIT = wxID_EXIT,
410
411 // about menu
412 ID_ABOUT = wxID_ABOUT,
413
414
415 // control IDs
416
417 ID_MUSIC_CTRL = 50,
418 ID_ATTR_CTRL = 51,
419
420 ID_ADD_MOZART = 100,
421 ID_DELETE_SEL = 101,
422 ID_DELETE_YEAR = 102,
423 ID_SELECT_NINTH = 103,
424 ID_COLLAPSE = 104,
425 ID_EXPAND = 105,
426 ID_SHOW_CURRENT,
427 ID_SET_NINTH_CURRENT,
428 ID_CHANGE_NINTH_TITLE,
429
430 ID_PREPEND_LIST = 200,
431 ID_DELETE_LIST = 201,
432 ID_GOTO = 202,
433 ID_ADD_MANY = 203,
434 ID_HIDE_ATTRIBUTES = 204,
435 ID_SHOW_ATTRIBUTES = 205,
436 ID_MULTIPLE_SORT = 206,
437 ID_SORT_BY_FIRST_COLUMN,
438
439 // Fourth page.
440 ID_DELETE_TREE_ITEM = 400,
441 ID_DELETE_ALL_TREE_ITEMS = 401,
442 ID_ADD_TREE_ITEM = 402,
443 ID_ADD_TREE_CONTAINER_ITEM = 403,
444
445 // Index list model page
446 ID_INDEX_LIST_USE_ENGLISH = 500,
447 ID_INDEX_LIST_USE_FRENCH,
448 ID_INDEX_LIST_RESET_MODEL
449 };
450
wxBEGIN_EVENT_TABLE(MyFrame,wxFrame)451 wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
452 EVT_MENU_RANGE( ID_MULTIPLE, ID_VERT_RULES, MyFrame::OnStyleChange )
453 EVT_MENU( ID_EXIT, MyFrame::OnQuit )
454 EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
455 EVT_MENU( ID_CLEARLOG, MyFrame::OnClearLog )
456
457 EVT_MENU( ID_GET_PAGE_INFO, MyFrame::OnGetPageInfo )
458 EVT_MENU( ID_DISABLE, MyFrame::OnDisable )
459 EVT_MENU( ID_FOREGROUND_COLOUR, MyFrame::OnSetForegroundColour )
460 EVT_MENU( ID_BACKGROUND_COLOUR, MyFrame::OnSetBackgroundColour )
461 EVT_MENU( ID_CUSTOM_HEADER_ATTR, MyFrame::OnCustomHeaderAttr )
462 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
463 EVT_MENU( ID_CUSTOM_HEADER_HEIGHT, MyFrame::OnCustomHeaderHeight )
464 #endif // wxHAS_GENERIC_DATAVIEWCTRL
465 EVT_MENU( ID_INC_INDENT, MyFrame::OnIncIndent )
466 EVT_MENU( ID_DEC_INDENT, MyFrame::OnDecIndent )
467
468 EVT_NOTEBOOK_PAGE_CHANGED( wxID_ANY, MyFrame::OnPageChanged )
469
470 EVT_BUTTON( ID_ADD_MOZART, MyFrame::OnAddMozart )
471 EVT_BUTTON( ID_DELETE_SEL, MyFrame::OnDeleteSelected )
472 EVT_BUTTON( ID_DELETE_YEAR, MyFrame::OnDeleteYear )
473 EVT_BUTTON( ID_SELECT_NINTH, MyFrame::OnSelectNinth )
474 EVT_BUTTON( ID_COLLAPSE, MyFrame::OnCollapse )
475 EVT_BUTTON( ID_EXPAND, MyFrame::OnExpand )
476 EVT_BUTTON( ID_SHOW_CURRENT, MyFrame::OnShowCurrent )
477 EVT_BUTTON( ID_SET_NINTH_CURRENT, MyFrame::OnSetNinthCurrent )
478 EVT_BUTTON( ID_CHANGE_NINTH_TITLE, MyFrame::OnChangeNinthTitle )
479
480 EVT_BUTTON( ID_PREPEND_LIST, MyFrame::OnPrependList )
481 EVT_BUTTON( ID_DELETE_LIST, MyFrame::OnDeleteList )
482 EVT_BUTTON( ID_GOTO, MyFrame::OnGoto)
483 EVT_BUTTON( ID_ADD_MANY, MyFrame::OnAddMany)
484 EVT_BUTTON( ID_HIDE_ATTRIBUTES, MyFrame::OnHideAttributes)
485 EVT_BUTTON( ID_SHOW_ATTRIBUTES, MyFrame::OnShowAttributes)
486 EVT_CHECKBOX( ID_MULTIPLE_SORT, MyFrame::OnMultipleSort)
487 EVT_CHECKBOX( ID_SORT_BY_FIRST_COLUMN, MyFrame::OnSortByFirstColumn)
488
489 // Fourth page.
490 EVT_BUTTON( ID_DELETE_TREE_ITEM, MyFrame::OnDeleteTreeItem )
491 EVT_BUTTON( ID_DELETE_ALL_TREE_ITEMS, MyFrame::OnDeleteAllTreeItems )
492 EVT_BUTTON( ID_ADD_TREE_ITEM, MyFrame::OnAddTreeItem )
493 EVT_BUTTON( ID_ADD_TREE_CONTAINER_ITEM, MyFrame::OnAddTreeContainerItem )
494
495 EVT_BUTTON( ID_INDEX_LIST_USE_ENGLISH, MyFrame::OnIndexListUseEnglish )
496 EVT_BUTTON( ID_INDEX_LIST_USE_FRENCH, MyFrame::OnIndexListUseFrench )
497 EVT_BUTTON( ID_INDEX_LIST_RESET_MODEL, MyFrame::OnIndexListResetModel )
498
499 EVT_DATAVIEW_ITEM_VALUE_CHANGED( ID_MUSIC_CTRL, MyFrame::OnValueChanged )
500
501 EVT_DATAVIEW_ITEM_ACTIVATED(ID_MUSIC_CTRL, MyFrame::OnActivated )
502 EVT_DATAVIEW_ITEM_EXPANDING(ID_MUSIC_CTRL, MyFrame::OnExpanding)
503 EVT_DATAVIEW_ITEM_EXPANDED(ID_MUSIC_CTRL, MyFrame::OnExpanded)
504 EVT_DATAVIEW_ITEM_COLLAPSING(ID_MUSIC_CTRL, MyFrame::OnCollapsing)
505 EVT_DATAVIEW_ITEM_COLLAPSED(ID_MUSIC_CTRL, MyFrame::OnCollapsed)
506 EVT_DATAVIEW_SELECTION_CHANGED(ID_MUSIC_CTRL, MyFrame::OnSelectionChanged)
507
508 EVT_DATAVIEW_ITEM_START_EDITING(ID_MUSIC_CTRL, MyFrame::OnStartEditing)
509 EVT_DATAVIEW_ITEM_EDITING_STARTED(wxID_ANY, MyFrame::OnEditingStarted)
510 EVT_DATAVIEW_ITEM_EDITING_DONE(wxID_ANY, MyFrame::OnEditingDone)
511
512 EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_MUSIC_CTRL, MyFrame::OnHeaderClick)
513 EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK(ID_MUSIC_CTRL, MyFrame::OnHeaderRightClick)
514 EVT_DATAVIEW_COLUMN_SORTED(ID_MUSIC_CTRL, MyFrame::OnSorted)
515 EVT_DATAVIEW_COLUMN_SORTED(ID_ATTR_CTRL, MyFrame::OnSortedList)
516 EVT_DATAVIEW_COLUMN_REORDERED(wxID_ANY, MyFrame::OnColumnReordered)
517 EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_ATTR_CTRL, MyFrame::OnHeaderClickList)
518
519 EVT_DATAVIEW_ITEM_CONTEXT_MENU(ID_MUSIC_CTRL, MyFrame::OnContextMenu)
520
521 #if wxUSE_DRAG_AND_DROP
522 EVT_DATAVIEW_ITEM_BEGIN_DRAG( ID_MUSIC_CTRL, MyFrame::OnBeginDrag )
523 EVT_DATAVIEW_ITEM_DROP_POSSIBLE( ID_MUSIC_CTRL, MyFrame::OnDropPossible )
524 EVT_DATAVIEW_ITEM_DROP( ID_MUSIC_CTRL, MyFrame::OnDrop )
525 #endif // wxUSE_DRAG_AND_DROP
526
527 EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_ATTR_CTRL, MyFrame::OnAttrHeaderClick)
528
529 wxEND_EVENT_TABLE()
530
531 MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int h):
532 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
533 {
534 m_log = NULL;
535 m_col = NULL;
536
537 for ( int page = 0; page < Page_Max; ++page )
538 m_ctrl[page] = NULL;
539
540 m_eventFromProgram = false;
541
542 SetIcon(wxICON(sample));
543
544
545 // build the menus
546 // ----------------
547
548 wxMenu *style_menu = new wxMenu;
549 //style_menu->AppendCheckItem(ID_SINGLE, "Single selection"));
550 style_menu->AppendCheckItem(ID_MULTIPLE, "Multiple selection");
551 style_menu->AppendCheckItem(ID_ROW_LINES, "Alternating colours");
552 style_menu->AppendCheckItem(ID_HORIZ_RULES, "Display horizontal rules");
553 style_menu->AppendCheckItem(ID_VERT_RULES, "Display vertical rules");
554
555 wxMenu *file_menu = new wxMenu;
556 file_menu->Append(ID_CLEARLOG, "&Clear log\tCtrl-L");
557 file_menu->Append(ID_GET_PAGE_INFO, "Show current &page info");
558 file_menu->AppendCheckItem(ID_DISABLE, "&Disable\tCtrl-D");
559 file_menu->Append(ID_FOREGROUND_COLOUR, "Set &foreground colour...\tCtrl-S");
560 file_menu->Append(ID_BACKGROUND_COLOUR, "Set &background colour...\tCtrl-B");
561 file_menu->AppendCheckItem(ID_CUSTOM_HEADER_ATTR, "C&ustom header attributes");
562 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
563 file_menu->AppendCheckItem(ID_CUSTOM_HEADER_HEIGHT, "Custom header &height");
564 #endif // wxHAS_GENERIC_DATAVIEWCTRL
565 file_menu->Append(ID_STYLE_MENU, "&Style", style_menu);
566 file_menu->Append(ID_INC_INDENT, "&Increase indent\tCtrl-I");
567 file_menu->Append(ID_DEC_INDENT, "&Decrease indent\tShift-Ctrl-I");
568 file_menu->AppendSeparator();
569 file_menu->Append(ID_EXIT, "E&xit");
570
571 wxMenu *about_menu = new wxMenu;
572 about_menu->Append(ID_ABOUT, "&About");
573
574 wxMenuBar *menu_bar = new wxMenuBar;
575 menu_bar->Append(file_menu, "&File");
576 menu_bar->Append(about_menu, "&About");
577
578 SetMenuBar(menu_bar);
579 CreateStatusBar();
580
581
582 // redirect logs from our event handlers to text control
583 m_log = new wxTextCtrl( this, wxID_ANY, wxString(), wxDefaultPosition,
584 wxDefaultSize, wxTE_MULTILINE );
585 m_log->SetMinSize(wxSize(-1, 100));
586 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_log));
587 wxLogMessage( "This is the log window" );
588
589
590 // first page of the notebook
591 // --------------------------
592
593 m_notebook = new wxNotebook( this, wxID_ANY );
594
595 wxPanel *firstPanel = new wxPanel( m_notebook, wxID_ANY );
596
597 BuildDataViewCtrl(firstPanel, Page_Music);
598
599 const wxSizerFlags border = wxSizerFlags().DoubleBorder();
600
601 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
602 button_sizer->Add( new wxButton( firstPanel, ID_ADD_MOZART, "Add Mozart"), border );
603 button_sizer->Add( new wxButton( firstPanel, ID_DELETE_SEL, "Delete selected"), border );
604 button_sizer->Add( new wxButton( firstPanel, ID_DELETE_YEAR, "Delete \"Year\" column"), border );
605 button_sizer->Add( new wxButton( firstPanel, ID_SELECT_NINTH,"Select ninth symphony"), border );
606 button_sizer->Add( new wxButton( firstPanel, ID_COLLAPSE, "Collapse"), border );
607 button_sizer->Add( new wxButton( firstPanel, ID_EXPAND, "Expand"), border );
608
609 wxBoxSizer *sizerCurrent = new wxBoxSizer(wxHORIZONTAL);
610 sizerCurrent->Add(new wxButton(firstPanel, ID_SHOW_CURRENT,
611 "&Show current"), border);
612 sizerCurrent->Add(new wxButton(firstPanel, ID_SET_NINTH_CURRENT,
613 "Make &ninth symphony current"), border);
614 sizerCurrent->Add(new wxButton(firstPanel, ID_CHANGE_NINTH_TITLE,
615 "Change ninth &title"), border);
616
617 wxSizer *firstPanelSz = new wxBoxSizer( wxVERTICAL );
618 m_ctrl[Page_Music]->SetMinSize(wxSize(-1, 200));
619 firstPanelSz->Add(m_ctrl[Page_Music], 1, wxGROW|wxALL, 5);
620 firstPanelSz->Add(
621 new wxStaticText(firstPanel, wxID_ANY, "Most of the cells above are editable!"),
622 0, wxGROW|wxALL, 5);
623 firstPanelSz->Add(button_sizer);
624 firstPanelSz->Add(sizerCurrent);
625 firstPanel->SetSizerAndFit(firstPanelSz);
626
627
628 // second page of the notebook
629 // ---------------------------
630
631 wxPanel *secondPanel = new wxPanel( m_notebook, wxID_ANY );
632
633 BuildDataViewCtrl(secondPanel, Page_List);
634
635 wxBoxSizer *button_sizer2 = new wxBoxSizer( wxHORIZONTAL );
636 button_sizer2->Add( new wxButton( secondPanel, ID_PREPEND_LIST,"Prepend"), 0, wxALL, 10 );
637 button_sizer2->Add( new wxButton( secondPanel, ID_DELETE_LIST, "Delete selected"), 0, wxALL, 10 );
638 button_sizer2->Add( new wxButton( secondPanel, ID_GOTO, "Goto 50"), 0, wxALL, 10 );
639 button_sizer2->Add( new wxButton( secondPanel, ID_ADD_MANY, "Add 1000"), 0, wxALL, 10 );
640 button_sizer2->Add( new wxButton( secondPanel, ID_HIDE_ATTRIBUTES, "Hide attributes"), 0, wxALL, 10 );
641 button_sizer2->Add( new wxButton( secondPanel, ID_SHOW_ATTRIBUTES, "Show attributes"), 0, wxALL, 10 );
642
643 wxBoxSizer *sortSizer = new wxBoxSizer(wxHORIZONTAL);
644 sortSizer->Add(new wxCheckBox(secondPanel, ID_SORT_BY_FIRST_COLUMN, "Sort by first column"),
645 wxSizerFlags().Centre().DoubleBorder());
646 sortSizer->Add(new wxCheckBox(secondPanel, ID_MULTIPLE_SORT, "Allow multisort"),
647 wxSizerFlags().Centre().DoubleBorder());
648
649 wxSizer *secondPanelSz = new wxBoxSizer( wxVERTICAL );
650 secondPanelSz->Add(m_ctrl[Page_List], 1, wxGROW|wxALL, 5);
651 secondPanelSz->Add(button_sizer2);
652 secondPanelSz->Add(sortSizer);
653 secondPanel->SetSizerAndFit(secondPanelSz);
654
655
656 // third page of the notebook
657 // ---------------------------
658
659 wxPanel *thirdPanel = new wxPanel( m_notebook, wxID_ANY );
660
661 BuildDataViewCtrl(thirdPanel, Page_ListStore);
662
663 wxSizer *thirdPanelSz = new wxBoxSizer( wxVERTICAL );
664 thirdPanelSz->Add(m_ctrl[Page_ListStore], 1, wxGROW|wxALL, 5);
665 thirdPanel->SetSizerAndFit(thirdPanelSz);
666
667
668 // fourth page of the notebook
669 // ---------------------------
670
671 wxPanel *fourthPanel = new wxPanel( m_notebook, wxID_ANY );
672
673 BuildDataViewCtrl(fourthPanel, Page_TreeStore);
674 // Buttons
675 wxBoxSizer *button_sizer4 = new wxBoxSizer( wxHORIZONTAL );
676 button_sizer4->Add( new wxButton( fourthPanel, ID_DELETE_TREE_ITEM, "Delete Selected"), 0, wxALL, 10 );
677 button_sizer4->Add( new wxButton( fourthPanel, ID_DELETE_ALL_TREE_ITEMS, "Delete All"), 0, wxALL, 10 );
678 button_sizer4->Add( new wxButton( fourthPanel, ID_ADD_TREE_ITEM, "Add Item"), 0, wxALL, 10 );
679 button_sizer4->Add( new wxButton( fourthPanel, ID_ADD_TREE_CONTAINER_ITEM, "Add Container"), 0, wxALL, 10 );
680
681 wxSizer *fourthPanelSz = new wxBoxSizer( wxVERTICAL );
682 fourthPanelSz->Add(m_ctrl[Page_TreeStore], 1, wxGROW|wxALL, 5);
683 fourthPanelSz->Add(button_sizer4);
684 fourthPanel->SetSizerAndFit(fourthPanelSz);
685
686 // fifth page of the notebook
687 // ---------------------------
688
689 wxPanel *fifthPanel = new wxPanel(m_notebook, wxID_ANY);
690
691 BuildDataViewCtrl(fifthPanel, Page_VarHeight);
692
693 wxSizer *fifthPanelSz = new wxBoxSizer(wxVERTICAL);
694 fifthPanelSz->Add(m_ctrl[Page_VarHeight], 1, wxGROW | wxALL, 5);
695 fifthPanel->SetSizerAndFit(fifthPanelSz);
696
697 // page showing the indexed list model
698 // -----------------------------------
699
700 wxPanel* sixthPanel = new wxPanel(m_notebook, wxID_ANY);
701
702 BuildDataViewCtrl(sixthPanel, Page_IndexList);
703
704 wxBoxSizer *button_sizer6 = new wxBoxSizer(wxHORIZONTAL);
705 button_sizer6->Add(new wxButton(sixthPanel, ID_INDEX_LIST_USE_ENGLISH, "&English"),
706 wxSizerFlags().DoubleBorder());
707 button_sizer6->Add(new wxButton(sixthPanel, ID_INDEX_LIST_USE_FRENCH, "&French"),
708 wxSizerFlags().DoubleBorder());
709 button_sizer6->Add(new wxButton(sixthPanel, ID_INDEX_LIST_RESET_MODEL, "Reset &model"),
710 wxSizerFlags().DoubleBorder());
711
712 wxSizer *sixthPanelSz = new wxBoxSizer(wxVERTICAL);
713 sixthPanelSz->Add(m_ctrl[Page_IndexList], wxSizerFlags(1).Expand().Border());
714 sixthPanelSz->Add(button_sizer6);
715 sixthPanel->SetSizerAndFit(sixthPanelSz);
716
717 // page showing that some columns don't have values for some items
718 // ---------------------------------------------------------------
719
720 wxPanel *seventhPanel = new wxPanel( m_notebook, wxID_ANY );
721
722 BuildDataViewCtrl(seventhPanel, Page_HasValue);
723
724 wxSizer *seventhPanelSz = new wxBoxSizer( wxVERTICAL );
725 seventhPanelSz->Add(m_ctrl[Page_HasValue], 1, wxGROW|wxALL, 5);
726 seventhPanel->SetSizerAndFit(seventhPanelSz);
727
728 // complete GUI
729 // ------------
730
731 m_notebook->AddPage(firstPanel, "MyMusicTreeModel");
732 m_notebook->AddPage(secondPanel, "MyListModel");
733 m_notebook->AddPage(thirdPanel, "wxDataViewListCtrl");
734 m_notebook->AddPage(fourthPanel, "wxDataViewTreeCtrl");
735 m_notebook->AddPage(fifthPanel, "Variable line height");
736 m_notebook->AddPage(sixthPanel, "MyIndexListModel");
737 m_notebook->AddPage(seventhPanel, "MyDataViewHasValue");
738
739 wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
740
741 mainSizer->Add( m_notebook, 1, wxGROW );
742 mainSizer->Add( m_log, 0, wxGROW );
743
744 SetSizerAndFit(mainSizer);
745
746 // Allow using the control from keyboard on startup.
747 m_ctrl[Page_Music]->SetFocus();
748 }
749
~MyFrame()750 MyFrame::~MyFrame()
751 {
752 delete wxLog::SetActiveTarget(m_logOld);
753 }
754
BuildDataViewCtrl(wxPanel * parent,unsigned int nPanel,unsigned long style)755 void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned long style)
756 {
757 wxASSERT(!m_ctrl[nPanel]); // should only be initialized once
758
759 switch (nPanel)
760 {
761 case Page_Music:
762 {
763 m_ctrl[Page_Music] =
764 new wxDataViewCtrl( parent, ID_MUSIC_CTRL, wxDefaultPosition,
765 wxDefaultSize, style );
766 m_ctrl[Page_Music]->Bind(wxEVT_CHAR, &MyFrame::OnDataViewChar, this);
767
768 m_music_model = new MyMusicTreeModel;
769 m_ctrl[Page_Music]->AssociateModel( m_music_model.get() );
770
771 #if wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
772 m_ctrl[Page_Music]->EnableDragSource( wxDF_UNICODETEXT );
773 m_ctrl[Page_Music]->EnableDropTarget( wxDF_UNICODETEXT );
774 #endif // wxUSE_DRAG_AND_DROP && wxUSE_UNICODE
775
776 // column 0 of the view control:
777
778 wxDataViewTextRenderer *tr =
779 new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
780 wxDataViewColumn *column0 =
781 new wxDataViewColumn( "title", tr, 0, FromDIP(200), wxALIGN_LEFT,
782 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE );
783 m_ctrl[Page_Music]->AppendColumn( column0 );
784 #if 0
785 // Call this and sorting is enabled
786 // immediately upon start up.
787 column0->SetAsSortKey();
788 #endif
789
790 // column 1 of the view control:
791
792 tr = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_EDITABLE );
793 wxDataViewColumn *column1 =
794 new wxDataViewColumn( "artist", tr, 1, FromDIP(150), wxALIGN_LEFT,
795 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE |
796 wxDATAVIEW_COL_RESIZABLE );
797 column1->SetMinWidth(FromDIP(150)); // this column can't be resized to be smaller
798 m_ctrl[Page_Music]->AppendColumn( column1 );
799
800 // column 2 of the view control:
801
802 wxDataViewSpinRenderer *sr =
803 new wxDataViewSpinRenderer( 0, 2010, wxDATAVIEW_CELL_EDITABLE,
804 wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
805 wxDataViewColumn *column2 =
806 new wxDataViewColumn( "year", sr, 2, FromDIP(60), wxALIGN_LEFT,
807 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE );
808 m_ctrl[Page_Music]->AppendColumn( column2 );
809
810 // column 3 of the view control:
811
812 wxArrayString choices;
813 choices.Add( "good" );
814 choices.Add( "bad" );
815 choices.Add( "lousy" );
816 wxDataViewChoiceRenderer *c =
817 new wxDataViewChoiceRenderer( choices, wxDATAVIEW_CELL_EDITABLE,
818 wxALIGN_RIGHT | wxALIGN_CENTRE_VERTICAL);
819 wxDataViewColumn *column3 =
820 new wxDataViewColumn( "rating", c, 3, FromDIP(100), wxALIGN_LEFT,
821 wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE );
822 m_ctrl[Page_Music]->AppendColumn( column3 );
823
824 // column 4 of the view control:
825
826 m_ctrl[Page_Music]->AppendProgressColumn( "popularity", 4, wxDATAVIEW_CELL_INERT, FromDIP(80) );
827
828 // column 5 of the view control:
829
830 MyCustomRenderer *cr = new MyCustomRenderer(wxDATAVIEW_CELL_ACTIVATABLE);
831 wxDataViewColumn *column5 =
832 new wxDataViewColumn( "custom", cr, 5, wxCOL_WIDTH_DEFAULT, wxALIGN_LEFT,
833 wxDATAVIEW_COL_RESIZABLE );
834 column5->SetBitmap(wxArtProvider::GetBitmap(wxART_INFORMATION, wxART_MENU));
835 m_ctrl[Page_Music]->AppendColumn( column5 );
836
837
838 // select initially the ninth symphony:
839 m_ctrl[Page_Music]->Select(m_music_model->GetNinthItem());
840 }
841 break;
842
843 case Page_List:
844 {
845 m_ctrl[Page_List] = new wxDataViewCtrl( parent, ID_ATTR_CTRL, wxDefaultPosition,
846 wxDefaultSize, style );
847
848 m_list_model = new MyListModel;
849 m_ctrl[Page_List]->AssociateModel( m_list_model.get() );
850
851 wxDataViewColumn* const colCheckIconText = new wxDataViewColumn
852 (
853 L"\u2714 + icon + text",
854 new wxDataViewCheckIconTextRenderer(),
855 MyListModel::Col_ToggleIconText,
856 wxCOL_WIDTH_AUTOSIZE
857 );
858 m_ctrl[Page_List]->AppendColumn(colCheckIconText);
859
860 m_ctrl[Page_List]->AppendTextColumn("editable string",
861 MyListModel::Col_EditableText,
862 wxDATAVIEW_CELL_EDITABLE,
863 wxCOL_WIDTH_AUTOSIZE,
864 wxALIGN_NOT,
865 wxDATAVIEW_COL_SORTABLE);
866
867 m_ctrl[Page_List]->AppendDateColumn("date",
868 MyListModel::Col_Date);
869
870 wxDataViewTextRenderer* const markupRenderer = new wxDataViewTextRenderer();
871 #if wxUSE_MARKUP
872 markupRenderer->EnableMarkup();
873 #endif // wxUSE_MARKUP
874 m_attributes =
875 new wxDataViewColumn("attributes",
876 markupRenderer,
877 MyListModel::Col_TextWithAttr,
878 wxCOL_WIDTH_AUTOSIZE,
879 wxALIGN_RIGHT,
880 wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE | wxDATAVIEW_COL_SORTABLE);
881 m_ctrl[Page_List]->AppendColumn( m_attributes );
882
883 m_ctrl[Page_List]->AppendColumn(
884 new wxDataViewColumn("custom renderer",
885 new MyCustomRenderer(wxDATAVIEW_CELL_EDITABLE),
886 MyListModel::Col_Custom)
887 );
888 }
889 break;
890
891 case Page_ListStore:
892 {
893 wxDataViewListCtrl* lc =
894 new wxDataViewListCtrl( parent, wxID_ANY, wxDefaultPosition,
895 wxDefaultSize, style );
896 m_ctrl[Page_ListStore] = lc;
897
898 MyListStoreDerivedModel* page2_model = new MyListStoreDerivedModel();
899 lc->AssociateModel(page2_model);
900 page2_model->DecRef();
901
902 lc->AppendToggleColumn( "Toggle" );
903
904 // We're not limited to convenience column-appending functions, it
905 // can also be done fully manually, which allows us to customize
906 // the renderer being used.
907 wxDataViewToggleRenderer* const rendererRadio =
908 new wxDataViewToggleRenderer("bool", wxDATAVIEW_CELL_ACTIVATABLE);
909 rendererRadio->ShowAsRadio();
910 wxDataViewColumn* const colRadio =
911 new wxDataViewColumn("Radio", rendererRadio, 1);
912 lc->AppendColumn(colRadio, "bool");
913
914 lc->AppendTextColumn( "Text" );
915 lc->AppendProgressColumn( "Progress" )->SetMinWidth(FromDIP(100));
916
917 wxVector<wxVariant> data;
918 for (unsigned int i=0; i<10; i++)
919 {
920 data.clear();
921 data.push_back( (i%3) == 0 );
922 data.push_back( i == 7 ); // select a single (random) radio item
923 data.push_back( wxString::Format("row %d", i) );
924 data.push_back( long(5*i) );
925
926 lc->AppendItem( data );
927 }
928
929 lc->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &MyFrame::OnListValueChanged, this);
930 }
931 break;
932
933 case Page_TreeStore:
934 {
935 wxDataViewTreeCtrl* tc =
936 new wxDataViewTreeCtrl( parent, wxID_ANY, wxDefaultPosition,
937 wxDefaultSize, style | wxDV_NO_HEADER );
938 m_ctrl[Page_TreeStore] = tc;
939
940 wxImageList *ilist = new wxImageList( 16, 16 );
941 ilist->Add( wxIcon(wx_small_xpm) );
942 tc->AssignImageList( ilist );
943
944 const wxDataViewItem root =
945 tc->AppendContainer( wxDataViewItem(0), "The Root", 0 );
946 tc->AppendItem( root, "Child 1", 0 );
947 tc->AppendItem( root, "Child 2", 0 );
948 tc->AppendItem( root, "Child 3, very long, long, long, long", 0 );
949
950 wxDataViewItem cont =
951 tc->AppendContainer( root, "Container child", 0 );
952 tc->AppendItem( cont, "Child 4", 0 );
953 tc->AppendItem( cont, "Child 5", 0 );
954
955 tc->Expand(cont);
956 }
957 break;
958
959 case Page_VarHeight:
960 {
961 m_ctrl[Page_VarHeight] =
962 new wxDataViewCtrl( parent, wxID_ANY, wxDefaultPosition,
963 wxDefaultSize, style | wxDV_VARIABLE_LINE_HEIGHT );
964
965 m_long_music_model = new MyLongMusicTreeModel;
966 m_ctrl[Page_VarHeight]->AssociateModel(m_long_music_model.get());
967
968 // column 0 of the view control:
969 MultiLineCustomRenderer *tr =
970 new MultiLineCustomRenderer();
971 wxDataViewColumn *column0 =
972 new wxDataViewColumn("title", tr, 0, FromDIP(200), wxALIGN_LEFT,
973 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE);
974 m_ctrl[Page_VarHeight]->AppendColumn(column0);
975
976 // column 1 of the view control:
977 tr = new MultiLineCustomRenderer();
978 wxDataViewColumn *column1 =
979 new wxDataViewColumn("artist", tr, 1, FromDIP(150), wxALIGN_LEFT,
980 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE |
981 wxDATAVIEW_COL_RESIZABLE);
982 column1->SetMinWidth(FromDIP(150)); // this column can't be resized to be smaller
983 m_ctrl[Page_VarHeight]->AppendColumn(column1);
984 }
985 break;
986
987 case Page_IndexList:
988 {
989 m_ctrl[Page_IndexList] = new wxDataViewCtrl(parent, wxID_ANY,
990 wxDefaultPosition,
991 wxDefaultSize,
992 style);
993
994 m_index_list_model = new MyIndexListModel;
995 m_ctrl[Page_IndexList]->AssociateModel(m_index_list_model.get());
996 m_ctrl[Page_IndexList]->AppendTextColumn("String", 0);
997
998 FillIndexList(Lang_English);
999
1000 m_ctrl[Page_IndexList]->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED,
1001 &MyFrame::OnIndexListSelectionChanged,
1002 this);
1003 }
1004 break;
1005
1006 case Page_HasValue:
1007 {
1008 wxDataViewListCtrl* lc =
1009 new wxDataViewListCtrl( parent, wxID_ANY, wxDefaultPosition,
1010 wxDefaultSize, style );
1011 m_ctrl[Page_HasValue] = lc;
1012
1013 MyListStoreDerivedModel* page7_model = new MyListStoreHasValueModel();
1014 lc->AssociateModel(page7_model);
1015 page7_model->DecRef();
1016
1017 lc->AppendToggleColumn( "Toggle" );
1018
1019 // We're not limited to convenience column-appending functions, it
1020 // can also be done fully manually, which allows us to customize
1021 // the renderer being used.
1022 wxDataViewToggleRenderer* const rendererRadio =
1023 new wxDataViewToggleRenderer("bool", wxDATAVIEW_CELL_ACTIVATABLE);
1024 rendererRadio->ShowAsRadio();
1025 wxDataViewColumn* const colRadio =
1026 new wxDataViewColumn("Radio", rendererRadio, 1);
1027 lc->AppendColumn(colRadio, "bool");
1028
1029 lc->AppendTextColumn( "Text" );
1030 lc->AppendProgressColumn( "Progress" )->SetMinWidth(FromDIP(100));
1031
1032 wxVector<wxVariant> data;
1033 for (unsigned int i=0; i<10; i++)
1034 {
1035 data.clear();
1036 data.push_back( (i%3) == 0 );
1037 data.push_back( i == 7 ); // select a single (random) radio item
1038 data.push_back( wxString::Format("row %d", i) );
1039 data.push_back( long(5*i) );
1040
1041 lc->AppendItem( data );
1042 }
1043
1044 lc->Bind(wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, &MyFrame::OnHasValueValueChanged, this);
1045 }
1046 break;
1047 }
1048
1049 }
1050
1051
1052 // ----------------------------------------------------------------------------
1053 // MyFrame - generic event handlers
1054 // ----------------------------------------------------------------------------
1055
OnClearLog(wxCommandEvent & WXUNUSED (event))1056 void MyFrame::OnClearLog( wxCommandEvent& WXUNUSED(event) )
1057 {
1058 m_log->Clear();
1059 }
1060
OnGetPageInfo(wxCommandEvent & WXUNUSED (event))1061 void MyFrame::OnGetPageInfo(wxCommandEvent& WXUNUSED(event))
1062 {
1063 wxDataViewCtrl* const dvc = m_ctrl[m_notebook->GetSelection()];
1064
1065 const wxDataViewItem top = dvc->GetTopItem();
1066 wxString topDesc;
1067 if ( top.IsOk() )
1068 {
1069 wxVariant value;
1070 dvc->GetModel()->GetValue(value, top, 0);
1071 topDesc.Printf("Top item is \"%s\"", value.GetString());
1072 }
1073 else
1074 {
1075 topDesc = "There is no top item";
1076 }
1077
1078 wxLogMessage("%s and there are %d items per page",
1079 topDesc,
1080 dvc->GetCountPerPage());
1081 }
1082
OnDisable(wxCommandEvent & event)1083 void MyFrame::OnDisable(wxCommandEvent& event)
1084 {
1085 m_ctrl[m_notebook->GetSelection()]->Enable(!event.IsChecked());
1086 }
1087
OnSetForegroundColour(wxCommandEvent & WXUNUSED (event))1088 void MyFrame::OnSetForegroundColour(wxCommandEvent& WXUNUSED(event))
1089 {
1090 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1091 wxColour col = wxGetColourFromUser(this, dvc->GetForegroundColour());
1092 if ( col.IsOk() )
1093 {
1094 dvc->SetForegroundColour(col);
1095 Refresh();
1096 }
1097 }
1098
OnSetBackgroundColour(wxCommandEvent & WXUNUSED (event))1099 void MyFrame::OnSetBackgroundColour(wxCommandEvent& WXUNUSED(event))
1100 {
1101 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1102 wxColour col = wxGetColourFromUser(this, dvc->GetBackgroundColour());
1103 if ( col.IsOk() )
1104 {
1105 dvc->SetBackgroundColour(col);
1106 Refresh();
1107 }
1108 }
1109
OnCustomHeaderAttr(wxCommandEvent & event)1110 void MyFrame::OnCustomHeaderAttr(wxCommandEvent& event)
1111 {
1112 wxItemAttr attr;
1113 if ( event.IsChecked() )
1114 {
1115 attr.SetTextColour(*wxRED);
1116 attr.SetFont(wxFontInfo(20).Bold());
1117 }
1118 //else: leave it as default to disable custom header attributes
1119
1120 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1121 if ( !dvc->SetHeaderAttr(attr) )
1122 wxLogMessage("Sorry, header attributes not supported on this platform");
1123 }
1124
1125 #ifdef wxHAS_GENERIC_DATAVIEWCTRL
OnCustomHeaderHeight(wxCommandEvent & event)1126 void MyFrame::OnCustomHeaderHeight(wxCommandEvent& event)
1127 {
1128 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1129 wxHeaderCtrl* const header = dvc->GenericGetHeader();
1130 if ( !header )
1131 {
1132 wxLogMessage("No header");
1133 return;
1134 }
1135
1136 // Use a big height to show that this works.
1137 wxSize size = event.IsChecked() ? FromDIP(wxSize(0, 80)) : wxDefaultSize;
1138 header->SetMinSize(size);
1139 header->Refresh();
1140
1141 dvc->Layout();
1142 }
1143 #endif // wxHAS_GENERIC_DATAVIEWCTRL
1144
OnIncIndent(wxCommandEvent & WXUNUSED (event))1145 void MyFrame::OnIncIndent(wxCommandEvent& WXUNUSED(event))
1146 {
1147 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1148 dvc->SetIndent(dvc->GetIndent() + 5);
1149 wxLogMessage("Indent is now %d", dvc->GetIndent());
1150 }
1151
OnDecIndent(wxCommandEvent & WXUNUSED (event))1152 void MyFrame::OnDecIndent(wxCommandEvent& WXUNUSED(event))
1153 {
1154 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
1155 dvc->SetIndent(wxMax(dvc->GetIndent() - 5, 0));
1156 wxLogMessage("Indent is now %d", dvc->GetIndent());
1157 }
1158
OnPageChanged(wxBookCtrlEvent & WXUNUSED (event))1159 void MyFrame::OnPageChanged( wxBookCtrlEvent& WXUNUSED(event) )
1160 {
1161 unsigned int nPanel = m_notebook->GetSelection();
1162
1163 GetMenuBar()->FindItem(ID_STYLE_MENU)->SetItemLabel(
1164 wxString::Format("Style of panel #%d", nPanel+1));
1165
1166 for (unsigned int id = ID_MULTIPLE; id <= ID_VERT_RULES; id++)
1167 {
1168 unsigned long style = 0;
1169 switch (id)
1170 {
1171 /*case ID_SINGLE:
1172 style = wxDV_SINGLE;
1173 break;*/
1174 case ID_MULTIPLE:
1175 style = wxDV_MULTIPLE;
1176 break;
1177 case ID_ROW_LINES:
1178 style = wxDV_ROW_LINES;
1179 break;
1180 case ID_HORIZ_RULES:
1181 style = wxDV_HORIZ_RULES;
1182 break;
1183 case ID_VERT_RULES:
1184 style = wxDV_VERT_RULES;
1185 break;
1186 default:
1187 wxFAIL;
1188 }
1189
1190 GetMenuBar()->FindItem(id)->Check( m_ctrl[nPanel]->HasFlag(style) );
1191 }
1192
1193 GetMenuBar()->FindItem(ID_DISABLE)->Check(!m_ctrl[nPanel]->IsEnabled());
1194 }
1195
OnStyleChange(wxCommandEvent & WXUNUSED (event))1196 void MyFrame::OnStyleChange( wxCommandEvent& WXUNUSED(event) )
1197 {
1198 unsigned int nPanel = m_notebook->GetSelection();
1199
1200 // build the style
1201 unsigned long style = 0;
1202 /*if (GetMenuBar()->FindItem(ID_SINGLE)->IsChecked())
1203 style |= wxDV_SINGLE;*/
1204 if (GetMenuBar()->FindItem(ID_MULTIPLE)->IsChecked())
1205 style |= wxDV_MULTIPLE;
1206 if (GetMenuBar()->FindItem(ID_ROW_LINES)->IsChecked())
1207 style |= wxDV_ROW_LINES;
1208 if (GetMenuBar()->FindItem(ID_HORIZ_RULES)->IsChecked())
1209 style |= wxDV_HORIZ_RULES;
1210 if (GetMenuBar()->FindItem(ID_VERT_RULES)->IsChecked())
1211 style |= wxDV_VERT_RULES;
1212
1213 wxSizer* sz = m_ctrl[nPanel]->GetContainingSizer();
1214 wxASSERT(sz);
1215
1216 sz->Detach(m_ctrl[nPanel]);
1217 wxDELETE(m_ctrl[nPanel]);
1218 m_ctrl[nPanel] = NULL;
1219
1220 if (nPanel == 0)
1221 m_music_model.reset(NULL);
1222 else if (nPanel == 1)
1223 m_list_model.reset(NULL);
1224 else if (nPanel == 4)
1225 m_long_music_model.reset(NULL);
1226
1227 // rebuild the DVC for the selected panel:
1228 BuildDataViewCtrl((wxPanel*)m_notebook->GetPage(nPanel), nPanel, style);
1229
1230 sz->Prepend(m_ctrl[nPanel], 1, wxGROW|wxALL, 5);
1231 sz->Layout();
1232 }
1233
OnQuit(wxCommandEvent & WXUNUSED (event))1234 void MyFrame::OnQuit( wxCommandEvent& WXUNUSED(event) )
1235 {
1236 Close(true);
1237 }
1238
OnAbout(wxCommandEvent & WXUNUSED (event))1239 void MyFrame::OnAbout( wxCommandEvent& WXUNUSED(event) )
1240 {
1241 wxAboutDialogInfo info;
1242 info.SetName(_("DataView sample"));
1243 info.SetDescription(_("This sample demonstrates wxDataViewCtrl"));
1244 info.SetCopyright("(C) 2007-2009 Robert Roebling");
1245 info.AddDeveloper("Robert Roebling");
1246 info.AddDeveloper("Francesco Montorsi");
1247
1248 wxAboutBox(info, this);
1249 }
1250
1251
1252 // ----------------------------------------------------------------------------
1253 // MyFrame - event handlers for the first page
1254 // ----------------------------------------------------------------------------
1255
1256 #if wxUSE_DRAG_AND_DROP
1257
OnBeginDrag(wxDataViewEvent & event)1258 void MyFrame::OnBeginDrag( wxDataViewEvent &event )
1259 {
1260 wxDataViewItem item( event.GetItem() );
1261
1262 // only allow drags for item, not containers
1263 if (m_music_model->IsContainer( item ) )
1264 {
1265 wxLogMessage("Forbidding starting dragging");
1266 event.Veto();
1267 return;
1268 }
1269
1270 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();
1271 wxTextDataObject *obj = new wxTextDataObject;
1272 obj->SetText( node->m_title );
1273 event.SetDataObject( obj );
1274 event.SetDragFlags(wxDrag_AllowMove); // allows both copy and move
1275
1276 wxLogMessage("Starting dragging \"%s\"", node->m_title);
1277 }
1278
OnDropPossible(wxDataViewEvent & event)1279 void MyFrame::OnDropPossible( wxDataViewEvent &event )
1280 {
1281 if (event.GetDataFormat() != wxDF_UNICODETEXT)
1282 event.Veto();
1283 else
1284 event.SetDropEffect(wxDragMove); // check 'move' drop effect
1285 }
1286
OnDrop(wxDataViewEvent & event)1287 void MyFrame::OnDrop( wxDataViewEvent &event )
1288 {
1289 wxDataViewItem item( event.GetItem() );
1290
1291 if (event.GetDataFormat() != wxDF_UNICODETEXT)
1292 {
1293 event.Veto();
1294 return;
1295 }
1296
1297 wxTextDataObject obj;
1298 obj.SetData( wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer() );
1299
1300 if ( item.IsOk() )
1301 {
1302 if (m_music_model->IsContainer(item))
1303 {
1304 wxLogMessage("Text '%s' dropped in container '%s' (proposed index = %i)",
1305 obj.GetText(), m_music_model->GetTitle(item), event.GetProposedDropIndex());
1306 }
1307 else
1308 wxLogMessage("Text '%s' dropped on item '%s'", obj.GetText(), m_music_model->GetTitle(item));
1309 }
1310 else
1311 wxLogMessage("Text '%s' dropped on background (proposed index = %i)", obj.GetText(), event.GetProposedDropIndex());
1312 }
1313
1314 #endif // wxUSE_DRAG_AND_DROP
1315
OnAddMozart(wxCommandEvent & WXUNUSED (event))1316 void MyFrame::OnAddMozart( wxCommandEvent& WXUNUSED(event) )
1317 {
1318 m_music_model->AddToClassical( "Eine kleine Nachtmusik", "Wolfgang Mozart", 1787 );
1319 }
1320
DeleteSelectedItems()1321 void MyFrame::DeleteSelectedItems()
1322 {
1323 wxDataViewItemArray items;
1324 int len = m_ctrl[Page_Music]->GetSelections( items );
1325 for( int i = 0; i < len; i ++ )
1326 if (items[i].IsOk())
1327 m_music_model->Delete( items[i] );
1328 }
1329
OnDeleteSelected(wxCommandEvent & WXUNUSED (event))1330 void MyFrame::OnDeleteSelected( wxCommandEvent& WXUNUSED(event) )
1331 {
1332 DeleteSelectedItems();
1333 }
1334
OnDeleteYear(wxCommandEvent & WXUNUSED (event))1335 void MyFrame::OnDeleteYear( wxCommandEvent& WXUNUSED(event) )
1336 {
1337 m_ctrl[Page_Music]->DeleteColumn( m_ctrl[Page_Music]->GetColumn( 2 ) );
1338 FindWindow( ID_DELETE_YEAR )->Disable();
1339 }
1340
OnSelectNinth(wxCommandEvent & WXUNUSED (event))1341 void MyFrame::OnSelectNinth( wxCommandEvent& WXUNUSED(event) )
1342 {
1343 if (!m_music_model->GetNinthItem().IsOk())
1344 {
1345 wxLogError( "Cannot select the ninth symphony: it was removed!" );
1346 return;
1347 }
1348
1349 m_ctrl[Page_Music]->Select( m_music_model->GetNinthItem() );
1350 }
1351
OnCollapse(wxCommandEvent & WXUNUSED (event))1352 void MyFrame::OnCollapse( wxCommandEvent& WXUNUSED(event) )
1353 {
1354 wxDataViewItem item = m_ctrl[Page_Music]->GetSelection();
1355 if (item.IsOk())
1356 m_ctrl[Page_Music]->Collapse( item );
1357 }
1358
OnExpand(wxCommandEvent & WXUNUSED (event))1359 void MyFrame::OnExpand( wxCommandEvent& WXUNUSED(event) )
1360 {
1361 wxDataViewItem item = m_ctrl[Page_Music]->GetSelection();
1362 if (item.IsOk())
1363 m_ctrl[Page_Music]->Expand( item );
1364 }
1365
OnShowCurrent(wxCommandEvent & WXUNUSED (event))1366 void MyFrame::OnShowCurrent(wxCommandEvent& WXUNUSED(event))
1367 {
1368 wxDataViewItem item = m_ctrl[Page_Music]->GetCurrentItem();
1369 if ( item.IsOk() )
1370 {
1371 wxLogMessage("Current item: \"%s\" by %s",
1372 m_music_model->GetTitle(item),
1373 m_music_model->GetArtist(item));
1374 }
1375 else
1376 {
1377 wxLogMessage("There is no current item.");
1378 }
1379
1380 wxDataViewColumn *col = m_ctrl[Page_Music]->GetCurrentColumn();
1381 if ( col )
1382 {
1383 wxLogMessage("Current column: %d",
1384 m_ctrl[Page_Music]->GetColumnPosition(col));
1385 }
1386 else
1387 {
1388 wxLogMessage("There is no current column.");
1389 }
1390 }
1391
OnSetNinthCurrent(wxCommandEvent & WXUNUSED (event))1392 void MyFrame::OnSetNinthCurrent(wxCommandEvent& WXUNUSED(event))
1393 {
1394 wxDataViewItem item(m_music_model->GetNinthItem());
1395 if ( !item.IsOk() )
1396 {
1397 wxLogError( "Cannot make the ninth symphony current: it was removed!" );
1398 return;
1399 }
1400
1401 m_ctrl[Page_Music]->SetCurrentItem(item);
1402 }
1403
OnChangeNinthTitle(wxCommandEvent & WXUNUSED (event))1404 void MyFrame::OnChangeNinthTitle(wxCommandEvent& WXUNUSED(event))
1405 {
1406 wxDataViewItem item(m_music_model->GetNinthItem());
1407 if ( !item.IsOk() )
1408 {
1409 wxLogError( "Cannot change the ninth symphony title: it was removed!" );
1410 return;
1411 }
1412
1413 m_music_model->SetValue("Symphony No. 9", item, 0);
1414 m_music_model->ItemChanged(item);
1415 }
1416
OnValueChanged(wxDataViewEvent & event)1417 void MyFrame::OnValueChanged( wxDataViewEvent &event )
1418 {
1419 wxString title = m_music_model->GetTitle( event.GetItem() );
1420 wxLogMessage( "wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, Item Id: %s; Column: %d",
1421 title, event.GetColumn() );
1422 }
1423
OnActivated(wxDataViewEvent & event)1424 void MyFrame::OnActivated( wxDataViewEvent &event )
1425 {
1426 wxString title = m_music_model->GetTitle( event.GetItem() );
1427 wxLogMessage( "wxEVT_DATAVIEW_ITEM_ACTIVATED, Item: %s; Column: %d",
1428 title, event.GetColumn() );
1429
1430 if (m_ctrl[Page_Music]->IsExpanded( event.GetItem() ))
1431 {
1432 wxLogMessage( "Item: %s is expanded", title );
1433 }
1434 }
1435
OnSelectionChanged(wxDataViewEvent & event)1436 void MyFrame::OnSelectionChanged( wxDataViewEvent &event )
1437 {
1438 wxString title = m_music_model->GetTitle( event.GetItem() );
1439 if (title.empty())
1440 title = "None";
1441
1442 wxLogMessage( "wxEVT_DATAVIEW_SELECTION_CHANGED, First selected Item: %s", title );
1443 }
1444
OnExpanding(wxDataViewEvent & event)1445 void MyFrame::OnExpanding( wxDataViewEvent &event )
1446 {
1447 wxString title = m_music_model->GetTitle( event.GetItem() );
1448 wxLogMessage( "wxEVT_DATAVIEW_ITEM_EXPANDING, Item: %s", title );
1449 }
1450
1451
OnStartEditing(wxDataViewEvent & event)1452 void MyFrame::OnStartEditing( wxDataViewEvent &event )
1453 {
1454 wxString artist = m_music_model->GetArtist( event.GetItem() );
1455 if (artist == "Ludwig van Beethoven")
1456 {
1457 event.Veto();
1458
1459 wxLogMessage( "wxEVT_DATAVIEW_ITEM_START_EDITING vetoed. Artist: %s", artist );
1460 }
1461 else
1462 wxLogMessage( "wxEVT_DATAVIEW_ITEM_START_EDITING not vetoed. Artist: %s", artist );
1463
1464 }
1465
OnEditingStarted(wxDataViewEvent & event)1466 void MyFrame::OnEditingStarted( wxDataViewEvent &event )
1467 {
1468 // This event doesn't, currently, carry the value, so get it ourselves.
1469 wxDataViewModel* const model = event.GetModel();
1470 wxVariant value;
1471 model->GetValue(value, event.GetItem(), event.GetColumn());
1472 wxLogMessage("wxEVT_DATAVIEW_ITEM_EDITING_STARTED, current value %s",
1473 value.GetString());
1474 }
1475
OnEditingDone(wxDataViewEvent & event)1476 void MyFrame::OnEditingDone( wxDataViewEvent &event )
1477 {
1478 wxLogMessage("wxEVT_DATAVIEW_ITEM_EDITING_DONE, new value %s",
1479 event.IsEditCancelled()
1480 ? wxString("unavailable because editing was cancelled")
1481 : event.GetValue().GetString());
1482 }
1483
OnExpanded(wxDataViewEvent & event)1484 void MyFrame::OnExpanded( wxDataViewEvent &event )
1485 {
1486 wxString title = m_music_model->GetTitle( event.GetItem() );
1487 wxLogMessage( "wxEVT_DATAVIEW_ITEM_EXPANDED, Item: %s", title );
1488 }
1489
OnCollapsing(wxDataViewEvent & event)1490 void MyFrame::OnCollapsing( wxDataViewEvent &event )
1491 {
1492 wxString title = m_music_model->GetTitle( event.GetItem() );
1493 wxLogMessage( "wxEVT_DATAVIEW_ITEM_COLLAPSING, Item: %s", title );
1494 }
1495
OnCollapsed(wxDataViewEvent & event)1496 void MyFrame::OnCollapsed( wxDataViewEvent &event )
1497 {
1498 wxString title = m_music_model->GetTitle( event.GetItem() );
1499 wxLogMessage( "wxEVT_DATAVIEW_ITEM_COLLAPSED, Item: %s", title );
1500 }
1501
OnContextMenu(wxDataViewEvent & event)1502 void MyFrame::OnContextMenu( wxDataViewEvent &event )
1503 {
1504 wxString title = m_music_model->GetTitle( event.GetItem() );
1505 wxLogMessage( "wxEVT_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s", title );
1506
1507 wxMenu menu;
1508 menu.Append( 1, "menuitem 1" );
1509 menu.Append( 2, "menuitem 2" );
1510 menu.Append( 3, "menuitem 3" );
1511
1512 m_ctrl[Page_Music]->PopupMenu(&menu);
1513 }
1514
OnAttrHeaderClick(wxDataViewEvent & event)1515 void MyFrame::OnAttrHeaderClick( wxDataViewEvent &event )
1516 {
1517 // we need to skip the event to let the default behaviour of sorting by
1518 // this column when it is clicked to take place
1519 event.Skip();
1520
1521 int pos = m_ctrl[Page_List]->GetColumnPosition( event.GetDataViewColumn() );
1522
1523 wxLogMessage( "wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, Column position: %d", pos );
1524 wxLogMessage( "Column title: %s Column width: %d", event.GetDataViewColumn()->GetTitle(), event.GetDataViewColumn()->GetWidth() );
1525 }
1526
OnHeaderClick(wxDataViewEvent & event)1527 void MyFrame::OnHeaderClick( wxDataViewEvent &event )
1528 {
1529 // we need to skip the event to let the default behaviour of sorting by
1530 // this column when it is clicked to take place
1531 event.Skip();
1532
1533 int pos = m_ctrl[Page_Music]->GetColumnPosition( event.GetDataViewColumn() );
1534
1535 wxLogMessage( "wxEVT_DATAVIEW_COLUMN_HEADER_CLICK, Column position: %d", pos );
1536 wxLogMessage( "Column width: %d", event.GetDataViewColumn()->GetWidth() );
1537 }
1538
OnHeaderRightClick(wxDataViewEvent & event)1539 void MyFrame::OnHeaderRightClick( wxDataViewEvent &event )
1540 {
1541 int pos = m_ctrl[Page_Music]->GetColumnPosition( event.GetDataViewColumn() );
1542
1543 wxLogMessage( "wxEVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, Column position: %d", pos );
1544 }
1545
OnColumnReordered(wxDataViewEvent & event)1546 void MyFrame::OnColumnReordered(wxDataViewEvent& event)
1547 {
1548 wxDataViewColumn* const col = event.GetDataViewColumn();
1549 if ( !col )
1550 {
1551 wxLogError("Unknown column reordered?");
1552 return;
1553 }
1554
1555 wxLogMessage("wxEVT_DATAVIEW_COLUMN_REORDERED: \"%s\" is now at position %d",
1556 col->GetTitle(), event.GetColumn());
1557 }
1558
OnSortedList(wxDataViewEvent &)1559 void MyFrame::OnSortedList( wxDataViewEvent &/*event*/)
1560 {
1561 wxVector<wxDataViewColumn *> const columns = m_ctrl[Page_List]->GetSortingColumns();
1562 wxLogMessage( "wxEVT_DATAVIEW_COLUMN_SORTED using the following columns");
1563
1564 for ( wxVector<wxDataViewColumn *>::const_iterator it = columns.begin(),
1565 end = columns.end();
1566 it != end;
1567 ++it )
1568 {
1569 wxDataViewColumn* const col = *it;
1570
1571 wxLogMessage("\t%d. %s %s",
1572 col->GetModelColumn(),
1573 col->GetTitle(),
1574 col->IsSortOrderAscending() ? "ascending" : "descending");
1575 }
1576 }
1577
OnHeaderClickList(wxDataViewEvent & event)1578 void MyFrame::OnHeaderClickList( wxDataViewEvent &event )
1579 {
1580 // Use control+click to toggle sorting by this column.
1581 if ( wxGetKeyState(WXK_CONTROL) )
1582 m_ctrl[Page_List]->ToggleSortByColumn(event.GetColumn());
1583 else
1584 event.Skip();
1585 }
1586
OnSorted(wxDataViewEvent & event)1587 void MyFrame::OnSorted( wxDataViewEvent &event )
1588 {
1589 int pos = m_ctrl[Page_Music]->GetColumnPosition( event.GetDataViewColumn() );
1590
1591 wxLogMessage( "wxEVT_DATAVIEW_COLUMN_SORTED, Column position: %d", pos );
1592 }
1593
OnDataViewChar(wxKeyEvent & event)1594 void MyFrame::OnDataViewChar(wxKeyEvent& event)
1595 {
1596 if ( event.GetKeyCode() == WXK_DELETE )
1597 DeleteSelectedItems();
1598 else
1599 event.Skip();
1600 }
1601
1602 // ----------------------------------------------------------------------------
1603 // MyFrame - event handlers for the second page
1604 // ----------------------------------------------------------------------------
1605
OnPrependList(wxCommandEvent & WXUNUSED (event))1606 void MyFrame::OnPrependList( wxCommandEvent& WXUNUSED(event) )
1607 {
1608 m_list_model->Prepend("Test");
1609 }
1610
OnDeleteList(wxCommandEvent & WXUNUSED (event))1611 void MyFrame::OnDeleteList( wxCommandEvent& WXUNUSED(event) )
1612 {
1613 wxDataViewItemArray items;
1614 int len = m_ctrl[Page_List]->GetSelections( items );
1615 if (len > 0)
1616 m_list_model->DeleteItems( items );
1617 }
1618
OnGoto(wxCommandEvent & WXUNUSED (event))1619 void MyFrame::OnGoto(wxCommandEvent& WXUNUSED(event))
1620 {
1621 wxDataViewItem item = m_list_model->GetItem( 50 );
1622 m_ctrl[Page_List]->EnsureVisible(item,m_col);
1623 }
1624
OnAddMany(wxCommandEvent & WXUNUSED (event))1625 void MyFrame::OnAddMany(wxCommandEvent& WXUNUSED(event))
1626 {
1627 m_list_model->AddMany();
1628 }
1629
OnHideAttributes(wxCommandEvent & WXUNUSED (event))1630 void MyFrame::OnHideAttributes(wxCommandEvent& WXUNUSED(event))
1631 {
1632 m_attributes->SetHidden(true);
1633 }
1634
OnShowAttributes(wxCommandEvent & WXUNUSED (event))1635 void MyFrame::OnShowAttributes(wxCommandEvent& WXUNUSED(event))
1636 {
1637 m_attributes->SetHidden(false);
1638 }
1639
1640 // ----------------------------------------------------------------------------
1641 // MyFrame - event handlers for the third (wxDataViewListCtrl) page
1642 // ----------------------------------------------------------------------------
1643
OnListValueChanged(wxDataViewEvent & event)1644 void MyFrame::OnListValueChanged(wxDataViewEvent& event)
1645 {
1646 // Ignore changes coming from our own SetToggleValue() calls below.
1647 if ( m_eventFromProgram )
1648 {
1649 m_eventFromProgram = false;
1650 return;
1651 }
1652
1653 wxDataViewListCtrl* const lc = static_cast<wxDataViewListCtrl*>(m_ctrl[Page_ListStore]);
1654
1655 const int columnToggle = 1;
1656
1657 // Handle selecting a radio button by unselecting all the other ones.
1658 if ( event.GetColumn() == columnToggle )
1659 {
1660 const int rowChanged = lc->ItemToRow(event.GetItem());
1661 if ( lc->GetToggleValue(rowChanged, columnToggle) )
1662 {
1663 for ( int row = 0; row < lc->GetItemCount(); ++row )
1664 {
1665 if ( row != rowChanged )
1666 {
1667 m_eventFromProgram = true;
1668 lc->SetToggleValue(false, row, columnToggle);
1669 }
1670 }
1671 }
1672 else // The item was cleared.
1673 {
1674 // Explicitly check it back, we want to always have exactly one
1675 // checked radio item in this column.
1676 m_eventFromProgram = true;
1677 lc->SetToggleValue(true, rowChanged, columnToggle);
1678 }
1679 }
1680 }
1681
1682 // ----------------------------------------------------------------------------
1683 // MyFrame - event handlers for the fourth page
1684 // ----------------------------------------------------------------------------
1685
OnDeleteTreeItem(wxCommandEvent & WXUNUSED (event))1686 void MyFrame::OnDeleteTreeItem(wxCommandEvent& WXUNUSED(event))
1687 {
1688 wxDataViewTreeCtrl* ctrl = (wxDataViewTreeCtrl*) m_ctrl[Page_TreeStore];
1689 wxDataViewItem selected = ctrl->GetSelection();
1690 if (!selected.IsOk())
1691 return;
1692
1693 ctrl->DeleteItem(selected);
1694 }
1695
OnDeleteAllTreeItems(wxCommandEvent & WXUNUSED (event))1696 void MyFrame::OnDeleteAllTreeItems(wxCommandEvent& WXUNUSED(event))
1697 {
1698 wxDataViewTreeCtrl* ctrl = (wxDataViewTreeCtrl*) m_ctrl[Page_TreeStore];
1699 ctrl->DeleteAllItems();
1700 }
1701
OnAddTreeItem(wxCommandEvent & WXUNUSED (event))1702 void MyFrame::OnAddTreeItem(wxCommandEvent& WXUNUSED(event))
1703 {
1704 wxDataViewTreeCtrl* ctrl = (wxDataViewTreeCtrl*) m_ctrl[Page_TreeStore];
1705 wxDataViewItem selected = ctrl->GetSelection();
1706 if (ctrl->IsContainer(selected)) {
1707 wxDataViewItem newitem = ctrl->AppendItem( selected, "Item", 0 );
1708 ctrl->Select(newitem);
1709 ctrl->EditItem(newitem, ctrl->GetColumn(0));
1710 }
1711 }
1712
OnAddTreeContainerItem(wxCommandEvent & WXUNUSED (event))1713 void MyFrame::OnAddTreeContainerItem(wxCommandEvent& WXUNUSED(event))
1714 {
1715 wxDataViewTreeCtrl* ctrl = (wxDataViewTreeCtrl*) m_ctrl[Page_TreeStore];
1716 wxDataViewItem selected = ctrl->GetSelection();
1717 if (ctrl->IsContainer(selected))
1718 ctrl->AppendContainer(selected, "Container", 0 );
1719 }
1720
OnMultipleSort(wxCommandEvent & event)1721 void MyFrame::OnMultipleSort( wxCommandEvent &event )
1722 {
1723 if ( !m_ctrl[Page_List]->AllowMultiColumnSort(event.IsChecked()) )
1724 wxLogMessage("Sorting by multiple columns not supported");
1725 }
1726
OnSortByFirstColumn(wxCommandEvent & event)1727 void MyFrame::OnSortByFirstColumn(wxCommandEvent& event)
1728 {
1729 wxDataViewColumn* const col = m_ctrl[Page_List]->GetColumn(0);
1730 if ( event.IsChecked() )
1731 col->SetSortOrder(true /* ascending */);
1732 else
1733 col->UnsetAsSortKey();
1734 }
1735
1736 // ----------------------------------------------------------------------------
1737 // Index list model page
1738 // ----------------------------------------------------------------------------
1739
FillIndexList(Lang lang)1740 void MyFrame::FillIndexList(Lang lang)
1741 {
1742 const int DAYS_PER_WEEK = 7;
1743 const wxString weekdays[2][DAYS_PER_WEEK] =
1744 {
1745 { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" },
1746 { "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim" },
1747 };
1748
1749 m_index_list_model->Fill(wxArrayString(DAYS_PER_WEEK, weekdays[lang]));
1750 }
1751
OnIndexListResetModel(wxCommandEvent &)1752 void MyFrame::OnIndexListResetModel(wxCommandEvent&)
1753 {
1754 m_ctrl[Page_IndexList]->AssociateModel(NULL);
1755 m_ctrl[Page_IndexList]->AssociateModel(m_index_list_model.get());
1756 }
1757
OnIndexListSelectionChanged(wxDataViewEvent & event)1758 void MyFrame::OnIndexListSelectionChanged(wxDataViewEvent& event)
1759 {
1760 // We don't expect any events during the control destruction.
1761 wxASSERT( !m_ctrl[Page_IndexList]->IsBeingDeleted() );
1762
1763 wxString weekday;
1764 wxDataViewItem item = event.GetItem();
1765 if ( !item )
1766 {
1767 weekday = "[none]";
1768 }
1769 else
1770 {
1771 wxVariant val;
1772 m_index_list_model->GetValue(val, item, 0);
1773 weekday = val.GetString();
1774 }
1775
1776 wxLogMessage("Selected week day: %s", weekday);
1777 }
1778
1779 // ----------------------------------------------------------------------------
1780 // MyFrame - event handlers for the HasValue (wxDataViewListCtrl) page
1781 // ----------------------------------------------------------------------------
1782
OnHasValueValueChanged(wxDataViewEvent & event)1783 void MyFrame::OnHasValueValueChanged(wxDataViewEvent& event)
1784 {
1785 // Ignore changes coming from our own SetToggleValue() calls below.
1786 if ( m_eventFromProgram )
1787 {
1788 m_eventFromProgram = false;
1789 return;
1790 }
1791
1792 wxDataViewListCtrl* const lc = static_cast<wxDataViewListCtrl*>(m_ctrl[Page_HasValue]);
1793
1794 const int columnToggle = 1;
1795
1796 // Handle selecting a radio button by unselecting all the other ones.
1797 if ( event.GetColumn() == columnToggle )
1798 {
1799 const int rowChanged = lc->ItemToRow(event.GetItem());
1800 if ( lc->GetToggleValue(rowChanged, columnToggle) )
1801 {
1802 for ( int row = 0; row < lc->GetItemCount(); ++row )
1803 {
1804 if ( row != rowChanged )
1805 {
1806 m_eventFromProgram = true;
1807 lc->SetToggleValue(false, row, columnToggle);
1808 }
1809 }
1810 }
1811 else // The item was cleared.
1812 {
1813 // Explicitly check it back, we want to always have exactly one
1814 // checked radio item in this column.
1815 m_eventFromProgram = true;
1816 lc->SetToggleValue(true, rowChanged, columnToggle);
1817 }
1818 }
1819 }
1820