Add custom renderer column to the list model example in dataview sample.
[wxWidgets.git] / samples / dataview / dataview.cpp
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 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // ============================================================================
13 // declarations
14 // ============================================================================
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 #include "wx/dataview.h"
28 #include "wx/datetime.h"
29 #include "wx/splitter.h"
30 #include "wx/aboutdlg.h"
31 #include "wx/colordlg.h"
32 #include "wx/choicdlg.h"
33 #include "wx/numdlg.h"
34 #include "wx/spinctrl.h"
35 #include "wx/imaglist.h"
36 #include "wx/notebook.h"
37
38 #include "mymodels.h"
39
40 // ----------------------------------------------------------------------------
41 // resources
42 // ----------------------------------------------------------------------------
43
44 #ifndef __WXMSW__
45 #include "../sample.xpm"
46 #endif
47
48 #include "wx_small.xpm"
49
50 // ----------------------------------------------------------------------------
51 // MyApp
52 // ----------------------------------------------------------------------------
53
54 class MyApp: public wxApp
55 {
56 public:
57 virtual bool OnInit();
58 };
59
60 // ----------------------------------------------------------------------------
61 // MyFrame
62 // ----------------------------------------------------------------------------
63
64 class MyFrame : public wxFrame
65 {
66 public:
67 MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int h);
68 ~MyFrame();
69
70 void BuildDataViewCtrl(wxPanel* parent,
71 unsigned int nPanel,
72 unsigned long style = 0);
73
74 public: // event handlers
75
76 void OnStyleChange(wxCommandEvent& event);
77 void OnSetBackgroundColour(wxCommandEvent& event);
78 void OnSetForegroundColour(wxCommandEvent& event);
79 void OnQuit(wxCommandEvent& event);
80 void OnAbout(wxCommandEvent& event);
81
82 void OnClearLog(wxCommandEvent& event);
83 void OnPageChanged(wxBookCtrlEvent& event);
84
85 void OnAddMozart(wxCommandEvent& event);
86 void OnDeleteMusic(wxCommandEvent& event);
87 void OnDeleteYear(wxCommandEvent& event);
88 void OnSelectNinth(wxCommandEvent& event);
89 void OnCollapse(wxCommandEvent& event);
90 void OnExpand(wxCommandEvent& event);
91
92 void OnPrependList(wxCommandEvent& event);
93 void OnDeleteList(wxCommandEvent& event);
94
95 void OnValueChanged( wxDataViewEvent &event );
96
97 void OnActivated( wxDataViewEvent &event );
98 void OnExpanding( wxDataViewEvent &event );
99 void OnExpanded( wxDataViewEvent &event );
100 void OnCollapsing( wxDataViewEvent &event );
101 void OnCollapsed( wxDataViewEvent &event );
102 void OnSelectionChanged( wxDataViewEvent &event );
103
104 void OnStartEditing( wxDataViewEvent &event );
105 void OnEditingStarted( wxDataViewEvent &event );
106 void OnEditingDone( wxDataViewEvent &event );
107
108 void OnHeaderClick( wxDataViewEvent &event );
109 void OnHeaderRightClick( wxDataViewEvent &event );
110 void OnSorted( wxDataViewEvent &event );
111
112 void OnContextMenu( wxDataViewEvent &event );
113
114 void OnRightClick( wxMouseEvent &event );
115 void OnGoto( wxCommandEvent &event);
116 void OnAddMany( wxCommandEvent &event);
117
118 void OnBeginDrag( wxDataViewEvent &event );
119 void OnDropPossible( wxDataViewEvent &event );
120 void OnDrop( wxDataViewEvent &event );
121
122 private:
123 wxNotebook* m_notebook;
124
125 // the controls stored in the various tabs of the main notebook:
126
127 wxDataViewCtrl* m_ctrl[4];
128
129 // the models associated with the first two DVC:
130
131 wxObjectDataPtr<MyMusicTreeModel> m_music_model;
132 wxObjectDataPtr<MyListModel> m_list_model;
133
134 // other data:
135
136 wxDataViewColumn* m_col;
137
138 wxTextCtrl* m_log;
139 wxLog *m_logOld;
140
141 private:
142 DECLARE_EVENT_TABLE()
143 };
144
145
146 // ----------------------------------------------------------------------------
147 // MyCustomRenderer
148 // ----------------------------------------------------------------------------
149
150 class MyCustomRenderer: public wxDataViewCustomRenderer
151 {
152 public:
153 MyCustomRenderer()
154 : wxDataViewCustomRenderer("string",
155 wxDATAVIEW_CELL_ACTIVATABLE,
156 wxALIGN_CENTER)
157 { }
158
159 virtual bool Render( wxRect rect, wxDC *dc, int state )
160 {
161 dc->SetBrush( *wxLIGHT_GREY_BRUSH );
162 dc->SetPen( *wxTRANSPARENT_PEN );
163
164 rect.Deflate(2);
165 dc->DrawRoundedRectangle( rect, 5 );
166
167 RenderText(m_value,
168 0, // no offset
169 wxRect(dc->GetTextExtent(m_value)).CentreIn(rect),
170 dc,
171 state);
172 return true;
173 }
174
175 virtual bool Activate( wxRect WXUNUSED(cell),
176 wxDataViewModel *WXUNUSED(model),
177 const wxDataViewItem &WXUNUSED(item),
178 unsigned int WXUNUSED(col) )
179 {
180 wxLogMessage( "MyCustomRenderer Activate()" );
181 return false;
182 }
183
184 virtual bool LeftClick( wxPoint cursor, wxRect WXUNUSED(cell),
185 wxDataViewModel *WXUNUSED(model),
186 const wxDataViewItem &WXUNUSED(item),
187 unsigned int WXUNUSED(col) )
188 {
189 wxLogMessage( "MyCustomRenderer LeftClick( %d, %d )", cursor.x, cursor.y );
190 return false;
191 }
192
193 virtual wxSize GetSize() const
194 {
195 return wxSize(60,20);
196 }
197
198 virtual bool SetValue( const wxVariant &value )
199 {
200 m_value = value.GetString();
201 return true;
202 }
203
204 virtual bool GetValue( wxVariant &WXUNUSED(value) ) const { return true; }
205
206 private:
207 wxString m_value;
208 };
209
210
211 // ============================================================================
212 // implementation
213 // ============================================================================
214
215 // ----------------------------------------------------------------------------
216 // MyApp
217 // ----------------------------------------------------------------------------
218
219 IMPLEMENT_APP(MyApp)
220
221 bool MyApp::OnInit()
222 {
223 if ( !wxApp::OnInit() )
224 return false;
225
226 MyFrame *frame =
227 new MyFrame(NULL, "wxDataViewCtrl sample", 40, 40, 1000, 540);
228 SetTopWindow(frame);
229
230 frame->Show(true);
231 return true;
232 }
233
234
235 // ----------------------------------------------------------------------------
236 // MyFrame
237 // ----------------------------------------------------------------------------
238
239 enum
240 {
241 ID_CLEARLOG = wxID_HIGHEST+1,
242 ID_BACKGROUND_COLOUR,
243 ID_FOREGROUND_COLOUR,
244 ID_STYLE_MENU,
245
246 // file menu
247 //ID_SINGLE, wxDV_SINGLE==0 so it's always present
248 ID_MULTIPLE,
249 ID_ROW_LINES,
250 ID_HORIZ_RULES,
251 ID_VERT_RULES,
252
253 ID_EXIT = wxID_EXIT,
254
255 // about menu
256 ID_ABOUT = wxID_ABOUT,
257
258
259 // control IDs
260
261 ID_MUSIC_CTRL = 50,
262
263 ID_ADD_MOZART = 100,
264 ID_DELETE_MUSIC = 101,
265 ID_DELETE_YEAR = 102,
266 ID_SELECT_NINTH = 103,
267 ID_COLLAPSE = 104,
268 ID_EXPAND = 105,
269
270 ID_PREPEND_LIST = 200,
271 ID_DELETE_LIST = 201,
272 ID_GOTO = 202,
273 ID_ADD_MANY = 203
274 };
275
276 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
277 EVT_MENU_RANGE( ID_MULTIPLE, ID_VERT_RULES, MyFrame::OnStyleChange )
278 EVT_MENU( ID_EXIT, MyFrame::OnQuit )
279 EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
280 EVT_MENU( ID_CLEARLOG, MyFrame::OnClearLog )
281
282 EVT_MENU( ID_FOREGROUND_COLOUR, MyFrame::OnSetForegroundColour )
283 EVT_MENU( ID_BACKGROUND_COLOUR, MyFrame::OnSetBackgroundColour )
284
285 EVT_NOTEBOOK_PAGE_CHANGED( wxID_ANY, MyFrame::OnPageChanged )
286
287 EVT_BUTTON( ID_ADD_MOZART, MyFrame::OnAddMozart )
288 EVT_BUTTON( ID_DELETE_MUSIC, MyFrame::OnDeleteMusic )
289 EVT_BUTTON( ID_DELETE_YEAR, MyFrame::OnDeleteYear )
290 EVT_BUTTON( ID_SELECT_NINTH, MyFrame::OnSelectNinth )
291 EVT_BUTTON( ID_COLLAPSE, MyFrame::OnCollapse )
292 EVT_BUTTON( ID_EXPAND, MyFrame::OnExpand )
293
294 EVT_BUTTON( ID_PREPEND_LIST, MyFrame::OnPrependList )
295 EVT_BUTTON( ID_DELETE_LIST, MyFrame::OnDeleteList )
296 EVT_BUTTON( ID_GOTO, MyFrame::OnGoto)
297 EVT_BUTTON( ID_ADD_MANY, MyFrame::OnAddMany)
298
299 EVT_DATAVIEW_ITEM_VALUE_CHANGED( ID_MUSIC_CTRL, MyFrame::OnValueChanged )
300
301 EVT_DATAVIEW_ITEM_ACTIVATED(ID_MUSIC_CTRL, MyFrame::OnActivated )
302 EVT_DATAVIEW_ITEM_EXPANDING(ID_MUSIC_CTRL, MyFrame::OnExpanding)
303 EVT_DATAVIEW_ITEM_EXPANDED(ID_MUSIC_CTRL, MyFrame::OnExpanded)
304 EVT_DATAVIEW_ITEM_COLLAPSING(ID_MUSIC_CTRL, MyFrame::OnCollapsing)
305 EVT_DATAVIEW_ITEM_COLLAPSED(ID_MUSIC_CTRL, MyFrame::OnCollapsed)
306 EVT_DATAVIEW_SELECTION_CHANGED(ID_MUSIC_CTRL, MyFrame::OnSelectionChanged)
307
308 EVT_DATAVIEW_ITEM_START_EDITING(ID_MUSIC_CTRL, MyFrame::OnStartEditing)
309 EVT_DATAVIEW_ITEM_EDITING_STARTED(ID_MUSIC_CTRL, MyFrame::OnEditingStarted)
310 EVT_DATAVIEW_ITEM_EDITING_DONE(ID_MUSIC_CTRL, MyFrame::OnEditingDone)
311
312 EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_MUSIC_CTRL, MyFrame::OnHeaderClick)
313 EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICKED(ID_MUSIC_CTRL, MyFrame::OnHeaderRightClick)
314 EVT_DATAVIEW_COLUMN_SORTED(ID_MUSIC_CTRL, MyFrame::OnSorted)
315
316 EVT_DATAVIEW_ITEM_CONTEXT_MENU(ID_MUSIC_CTRL, MyFrame::OnContextMenu)
317
318 EVT_DATAVIEW_ITEM_BEGIN_DRAG( ID_MUSIC_CTRL, MyFrame::OnBeginDrag )
319 EVT_DATAVIEW_ITEM_DROP_POSSIBLE( ID_MUSIC_CTRL, MyFrame::OnDropPossible )
320 EVT_DATAVIEW_ITEM_DROP( ID_MUSIC_CTRL, MyFrame::OnDrop )
321
322 EVT_RIGHT_UP(MyFrame::OnRightClick)
323 END_EVENT_TABLE()
324
325 MyFrame::MyFrame(wxFrame *frame, const wxString &title, int x, int y, int w, int h):
326 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
327 {
328 m_log = NULL;
329 m_col = NULL;
330
331 m_ctrl[0] = NULL;
332 m_ctrl[1] = NULL;
333 m_ctrl[2] = NULL;
334 m_ctrl[3] = NULL;
335
336 SetIcon(wxICON(sample));
337
338
339 // build the menus
340 // ----------------
341
342 wxMenu *style_menu = new wxMenu;
343 //style_menu->AppendCheckItem(ID_SINGLE, "Single selection"));
344 style_menu->AppendCheckItem(ID_MULTIPLE, "Multiple selection");
345 style_menu->AppendCheckItem(ID_ROW_LINES, "Alternating colours");
346 style_menu->AppendCheckItem(ID_HORIZ_RULES, "Display horizontal rules");
347 style_menu->AppendCheckItem(ID_VERT_RULES, "Display vertical rules");
348
349 wxMenu *file_menu = new wxMenu;
350 file_menu->Append(ID_CLEARLOG, "&Clear log\tCtrl-L");
351 file_menu->Append(ID_FOREGROUND_COLOUR, "Set &foreground colour...\tCtrl-F");
352 file_menu->Append(ID_BACKGROUND_COLOUR, "Set &background colour...\tCtrl-B");
353 file_menu->Append(ID_STYLE_MENU, "&Style", style_menu);
354 file_menu->AppendSeparator();
355 file_menu->Append(ID_EXIT, "E&xit");
356
357 wxMenu *about_menu = new wxMenu;
358 about_menu->Append(ID_ABOUT, "&About");
359
360 wxMenuBar *menu_bar = new wxMenuBar;
361 menu_bar->Append(file_menu, "&File");
362 menu_bar->Append(about_menu, "&About");
363
364 SetMenuBar(menu_bar);
365 CreateStatusBar();
366
367
368 // first page of the notebook
369 // --------------------------
370
371 m_notebook = new wxNotebook( this, wxID_ANY );
372
373 wxPanel *firstPanel = new wxPanel( m_notebook, wxID_ANY );
374
375 BuildDataViewCtrl(firstPanel, 0); // sets m_ctrl[0]
376
377 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
378 button_sizer->Add( new wxButton( firstPanel, ID_ADD_MOZART, "Add Mozart"), 0, wxALL, 10 );
379 button_sizer->Add( new wxButton( firstPanel, ID_DELETE_MUSIC,"Delete selected"), 0, wxALL, 10 );
380 button_sizer->Add( new wxButton( firstPanel, ID_DELETE_YEAR, "Delete \"Year\" column"), 0, wxALL, 10 );
381 button_sizer->Add( new wxButton( firstPanel, ID_SELECT_NINTH,"Select ninth symphony"), 0, wxALL, 10 );
382 button_sizer->Add( new wxButton( firstPanel, ID_COLLAPSE, "Collapse"), 0, wxALL, 10 );
383 button_sizer->Add( new wxButton( firstPanel, ID_EXPAND, "Expand"), 0, wxALL, 10 );
384
385 wxSizer *firstPanelSz = new wxBoxSizer( wxVERTICAL );
386 m_ctrl[0]->SetMinSize(wxSize(-1, 200));
387 firstPanelSz->Add(m_ctrl[0], 1, wxGROW|wxALL, 5);
388 firstPanelSz->Add(
389 new wxStaticText(firstPanel, wxID_ANY, "Most of the cells above are editable!"),
390 0, wxGROW|wxALL, 5);
391 firstPanelSz->Add(button_sizer);
392 firstPanel->SetSizerAndFit(firstPanelSz);
393
394
395 // second page of the notebook
396 // ---------------------------
397
398 wxPanel *secondPanel = new wxPanel( m_notebook, wxID_ANY );
399
400 BuildDataViewCtrl(secondPanel, 1); // sets m_ctrl[1]
401
402 wxBoxSizer *button_sizer2 = new wxBoxSizer( wxHORIZONTAL );
403 button_sizer2->Add( new wxButton( secondPanel, ID_PREPEND_LIST,"Prepend"), 0, wxALL, 10 );
404 button_sizer2->Add( new wxButton( secondPanel, ID_DELETE_LIST, "Delete selected"), 0, wxALL, 10 );
405 button_sizer2->Add( new wxButton( secondPanel, ID_GOTO, "Goto 50"), 0, wxALL, 10 );
406 button_sizer2->Add( new wxButton( secondPanel, ID_ADD_MANY, "Add 1000"), 0, wxALL, 10 );
407
408 wxSizer *secondPanelSz = new wxBoxSizer( wxVERTICAL );
409 secondPanelSz->Add(m_ctrl[1], 1, wxGROW|wxALL, 5);
410 secondPanelSz->Add(button_sizer2);
411 secondPanel->SetSizerAndFit(secondPanelSz);
412
413
414 // third page of the notebook
415 // ---------------------------
416
417 wxPanel *thirdPanel = new wxPanel( m_notebook, wxID_ANY );
418
419 BuildDataViewCtrl(thirdPanel, 2); // sets m_ctrl[2]
420
421 wxSizer *thirdPanelSz = new wxBoxSizer( wxVERTICAL );
422 thirdPanelSz->Add(m_ctrl[2], 1, wxGROW|wxALL, 5);
423 thirdPanel->SetSizerAndFit(thirdPanelSz);
424
425
426 // fourth page of the notebook
427 // ---------------------------
428
429 wxPanel *fourthPanel = new wxPanel( m_notebook, wxID_ANY );
430
431 BuildDataViewCtrl(fourthPanel, 3); // sets m_ctrl[3]
432
433 wxSizer *fourthPanelSz = new wxBoxSizer( wxVERTICAL );
434 fourthPanelSz->Add(m_ctrl[3], 1, wxGROW|wxALL, 5);
435 fourthPanel->SetSizerAndFit(fourthPanelSz);
436
437
438
439 // complete GUI
440 // ------------
441
442 m_notebook->AddPage(firstPanel, "MyMusicTreeModel");
443 m_notebook->AddPage(secondPanel, "MyListModel");
444 m_notebook->AddPage(thirdPanel, "wxDataViewListCtrl");
445 m_notebook->AddPage(fourthPanel, "wxDataViewTreeCtrl");
446
447 wxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);
448
449 m_log = new wxTextCtrl( this, wxID_ANY, wxString(), wxDefaultPosition,
450 wxDefaultSize, wxTE_MULTILINE );
451 m_log->SetMinSize(wxSize(-1, 100));
452 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_log));
453 wxLogMessage( "This is the log window" );
454
455 mainSizer->Add( m_notebook, 1, wxGROW );
456 mainSizer->Add( m_log, 0, wxGROW );
457
458 SetSizerAndFit(mainSizer);
459 }
460
461 MyFrame::~MyFrame()
462 {
463 delete wxLog::SetActiveTarget(m_logOld);
464 }
465
466 void MyFrame::BuildDataViewCtrl(wxPanel* parent, unsigned int nPanel, unsigned long style)
467 {
468 switch (nPanel)
469 {
470 case 0:
471 {
472 wxASSERT(!m_ctrl[0] && !m_music_model);
473 m_ctrl[0] =
474 new wxDataViewCtrl( parent, ID_MUSIC_CTRL, wxDefaultPosition,
475 wxDefaultSize, style );
476
477 m_music_model = new MyMusicTreeModel;
478 m_ctrl[0]->AssociateModel( m_music_model.get() );
479
480 m_ctrl[0]->EnableDragSource( wxDF_UNICODETEXT );
481 m_ctrl[0]->EnableDropTarget( wxDF_UNICODETEXT );
482
483 // column 0 of the view control:
484
485 wxDataViewTextRenderer *tr =
486 new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_INERT );
487 wxDataViewColumn *column0 =
488 new wxDataViewColumn( "title", tr, 0, 200, wxALIGN_LEFT,
489 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_RESIZABLE );
490 m_ctrl[0]->AppendColumn( column0 );
491 #if 0
492 // Call this and sorting is enabled
493 // immediatly upon start up.
494 column0->SetAsSortKey();
495 #endif
496
497 // column 1 of the view control:
498
499 tr = new wxDataViewTextRenderer( "string", wxDATAVIEW_CELL_EDITABLE );
500 wxDataViewColumn *column1 =
501 new wxDataViewColumn( "artist", tr, 1, 150, wxALIGN_LEFT,
502 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE |
503 wxDATAVIEW_COL_RESIZABLE );
504 column1->SetMinWidth(150); // this column can't be resized to be smaller
505 m_ctrl[0]->AppendColumn( column1 );
506
507 // column 2 of the view control:
508
509 wxDataViewSpinRenderer *sr =
510 new wxDataViewSpinRenderer( 0, 2010, wxDATAVIEW_CELL_EDITABLE, wxALIGN_RIGHT );
511 wxDataViewColumn *column2 =
512 new wxDataViewColumn( "year", sr, 2, 60, wxALIGN_LEFT,
513 wxDATAVIEW_COL_SORTABLE | wxDATAVIEW_COL_REORDERABLE );
514 m_ctrl[0]->AppendColumn( column2 );
515
516 // column 3 of the view control:
517
518 wxArrayString choices;
519 choices.Add( "good" );
520 choices.Add( "bad" );
521 choices.Add( "lousy" );
522 wxDataViewChoiceRenderer *c =
523 new wxDataViewChoiceRenderer( choices, wxDATAVIEW_CELL_EDITABLE, wxALIGN_RIGHT );
524 wxDataViewColumn *column3 =
525 new wxDataViewColumn( "rating", c, 3, 100, wxALIGN_LEFT,
526 wxDATAVIEW_COL_REORDERABLE | wxDATAVIEW_COL_RESIZABLE );
527 m_ctrl[0]->AppendColumn( column3 );
528
529 // column 4 of the view control:
530
531 m_ctrl[0]->AppendProgressColumn( "popularity", 4, wxDATAVIEW_CELL_INERT, 80 );
532
533 // column 5 of the view control:
534
535 MyCustomRenderer *cr = new MyCustomRenderer;
536 wxDataViewColumn *column5 =
537 new wxDataViewColumn( "custom", cr, 5, -1, wxALIGN_LEFT,
538 wxDATAVIEW_COL_RESIZABLE );
539 m_ctrl[0]->AppendColumn( column5 );
540
541
542 // select initially the ninth symphony:
543 m_ctrl[0]->Select(m_music_model->GetNinthItem());
544 }
545 break;
546
547 case 1:
548 {
549 wxASSERT(!m_ctrl[1] && !m_list_model);
550 m_ctrl[1] = new wxDataViewCtrl( parent, wxID_ANY, wxDefaultPosition,
551 wxDefaultSize, style );
552
553 m_list_model = new MyListModel;
554 m_ctrl[1]->AssociateModel( m_list_model.get() );
555
556 // the various columns
557 m_ctrl[1]->AppendTextColumn("editable string",
558 MyListModel::Col_EditableText,
559 wxDATAVIEW_CELL_EDITABLE);
560 m_ctrl[1]->AppendIconTextColumn("icon",
561 MyListModel::Col_IconText,
562 wxDATAVIEW_CELL_EDITABLE);
563 m_ctrl[1]->AppendColumn(
564 new wxDataViewColumn("attributes",
565 new wxDataViewTextRenderer,
566 MyListModel::Col_TextWithAttr)
567 );
568
569 m_ctrl[1]->AppendColumn(
570 new wxDataViewColumn("custom renderer",
571 new MyCustomRenderer,
572 MyListModel::Col_Custom)
573 );
574 }
575 break;
576
577 case 2:
578 {
579 wxASSERT(!m_ctrl[2]);
580 wxDataViewListCtrl* lc =
581 new wxDataViewListCtrl( parent, wxID_ANY, wxDefaultPosition,
582 wxDefaultSize, style );
583 m_ctrl[2] = lc;
584
585 lc->AppendToggleColumn( "Toggle" );
586 lc->AppendTextColumn( "Text" );
587 lc->AppendProgressColumn( "Progress" );
588
589 wxVector<wxVariant> data;
590 for (unsigned int i=0; i<10; i++)
591 {
592 data.clear();
593 data.push_back( (i%3) == 0 );
594 data.push_back( wxString::Format("row %d", i) );
595 data.push_back( long(5*i) );
596
597 lc->AppendItem( data );
598 }
599 }
600 break;
601
602 case 3:
603 {
604 wxASSERT(!m_ctrl[3]);
605 wxDataViewTreeCtrl* tc =
606 new wxDataViewTreeCtrl( parent, wxID_ANY, wxDefaultPosition,
607 wxDefaultSize, style );
608 m_ctrl[3] = tc;
609
610 wxImageList *ilist = new wxImageList( 16, 16 );
611 ilist->Add( wxIcon(wx_small_xpm) );
612 tc->SetImageList( ilist );
613
614 wxDataViewItem parent =
615 tc->AppendContainer( wxDataViewItem(0), "The Root", 0 );
616 tc->AppendItem( parent, "Child 1", 0 );
617 tc->AppendItem( parent, "Child 2", 0 );
618 tc->AppendItem( parent, "Child 3, very long, long, long, long", 0 );
619
620 wxDataViewItem cont =
621 tc->AppendContainer( parent, "Container child", 0 );
622 tc->AppendItem( cont, "Child 4", 0 );
623 tc->AppendItem( cont, "Child 5", 0 );
624
625 tc->Expand(cont);
626 }
627 break;
628 }
629 }
630
631
632 // ----------------------------------------------------------------------------
633 // MyFrame - generic event handlers
634 // ----------------------------------------------------------------------------
635
636 void MyFrame::OnClearLog( wxCommandEvent& WXUNUSED(event) )
637 {
638 m_log->Clear();
639 }
640
641 void MyFrame::OnSetForegroundColour(wxCommandEvent& WXUNUSED(event))
642 {
643 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
644 wxColour col = wxGetColourFromUser(this, dvc->GetForegroundColour());
645 if ( col.IsOk() )
646 {
647 dvc->SetForegroundColour(col);
648 Refresh();
649 }
650 }
651
652 void MyFrame::OnSetBackgroundColour(wxCommandEvent& WXUNUSED(event))
653 {
654 wxDataViewCtrl * const dvc = m_ctrl[m_notebook->GetSelection()];
655 wxColour col = wxGetColourFromUser(this, dvc->GetBackgroundColour());
656 if ( col.IsOk() )
657 {
658 dvc->SetBackgroundColour(col);
659 Refresh();
660 }
661 }
662
663 void MyFrame::OnPageChanged( wxBookCtrlEvent& WXUNUSED(event) )
664 {
665 unsigned int nPanel = m_notebook->GetSelection();
666
667 GetMenuBar()->FindItem(ID_STYLE_MENU)->SetItemLabel(
668 wxString::Format("Style of panel #%d", nPanel+1));
669
670 for (unsigned int id = ID_MULTIPLE; id <= ID_VERT_RULES; id++)
671 {
672 unsigned long style = 0;
673 switch (id)
674 {
675 /*case ID_SINGLE:
676 style = wxDV_SINGLE;
677 break;*/
678 case ID_MULTIPLE:
679 style = wxDV_MULTIPLE;
680 break;
681 case ID_ROW_LINES:
682 style = wxDV_ROW_LINES;
683 break;
684 case ID_HORIZ_RULES:
685 style = wxDV_HORIZ_RULES;
686 break;
687 case ID_VERT_RULES:
688 style = wxDV_VERT_RULES;
689 break;
690 default:
691 wxFAIL;
692 }
693
694 GetMenuBar()->FindItem(id)->Check( m_ctrl[nPanel]->HasFlag(style) );
695 }
696 }
697
698 void MyFrame::OnStyleChange( wxCommandEvent& WXUNUSED(event) )
699 {
700 unsigned int nPanel = m_notebook->GetSelection();
701
702 // build the style
703 unsigned long style = 0;
704 /*if (GetMenuBar()->FindItem(ID_SINGLE)->IsChecked())
705 style |= wxDV_SINGLE;*/
706 if (GetMenuBar()->FindItem(ID_MULTIPLE)->IsChecked())
707 style |= wxDV_MULTIPLE;
708 if (GetMenuBar()->FindItem(ID_ROW_LINES)->IsChecked())
709 style |= wxDV_ROW_LINES;
710 if (GetMenuBar()->FindItem(ID_HORIZ_RULES)->IsChecked())
711 style |= wxDV_HORIZ_RULES;
712 if (GetMenuBar()->FindItem(ID_VERT_RULES)->IsChecked())
713 style |= wxDV_VERT_RULES;
714
715 wxSizer* sz = m_ctrl[nPanel]->GetContainingSizer();
716 wxASSERT(sz);
717
718 sz->Detach(m_ctrl[nPanel]);
719 wxDELETE(m_ctrl[nPanel]);
720 m_ctrl[nPanel] = NULL;
721
722 if (nPanel == 0)
723 m_music_model.reset(NULL);
724 else if (nPanel == 1)
725 m_list_model.reset(NULL);
726
727 // rebuild the DVC for the selected panel:
728 BuildDataViewCtrl((wxPanel*)m_notebook->GetPage(nPanel), nPanel, style);
729
730 sz->Prepend(m_ctrl[nPanel], 1, wxGROW|wxALL, 5);
731 sz->Layout();
732 }
733
734 void MyFrame::OnQuit( wxCommandEvent& WXUNUSED(event) )
735 {
736 Close(true);
737 }
738
739 void MyFrame::OnAbout( wxCommandEvent& WXUNUSED(event) )
740 {
741 wxAboutDialogInfo info;
742 info.SetName(_("DataView sample"));
743 info.SetDescription(_("This sample demonstrates wxDataViewCtrl"));
744 info.SetCopyright(wxT("(C) 2007-2009 Robert Roebling"));
745 info.AddDeveloper("Robert Roebling");
746 info.AddDeveloper("Francesco Montorsi");
747
748 wxAboutBox(info);
749 }
750
751
752 // ----------------------------------------------------------------------------
753 // MyFrame - event handlers for the first page
754 // ----------------------------------------------------------------------------
755
756 void MyFrame::OnBeginDrag( wxDataViewEvent &event )
757 {
758 wxDataViewItem item( event.GetItem() );
759
760 // only allow drags for item, not containers
761 if (m_music_model->IsContainer( item ) )
762 {
763 event.Veto();
764 return;
765 }
766
767 MyMusicTreeModelNode *node = (MyMusicTreeModelNode*) item.GetID();
768 wxTextDataObject *obj = new wxTextDataObject;
769 obj->SetText( node->m_title );
770 event.SetDataObject( obj );
771 }
772
773 void MyFrame::OnDropPossible( wxDataViewEvent &event )
774 {
775 wxDataViewItem item( event.GetItem() );
776
777 // only allow drags for item, not containers
778 if (m_music_model->IsContainer( item ) )
779 event.Veto();
780
781 if (event.GetDataFormat() != wxDF_UNICODETEXT)
782 event.Veto();
783 }
784
785 void MyFrame::OnDrop( wxDataViewEvent &event )
786 {
787 wxDataViewItem item( event.GetItem() );
788
789 // only allow drops for item, not containers
790 if (m_music_model->IsContainer( item ) )
791 {
792 event.Veto();
793 return;
794 }
795
796 if (event.GetDataFormat() != wxDF_UNICODETEXT)
797 {
798 event.Veto();
799 return;
800 }
801
802 wxTextDataObject obj;
803 obj.SetData( wxDF_UNICODETEXT, event.GetDataSize(), event.GetDataBuffer() );
804
805 wxLogMessage( "Text dropped: %s", obj.GetText() );
806 }
807
808 void MyFrame::OnAddMozart( wxCommandEvent& WXUNUSED(event) )
809 {
810 m_music_model->AddToClassical( "Kleine Nachtmusik", "Wolfgang Mozart", 1787 );
811 }
812
813 void MyFrame::OnDeleteMusic( wxCommandEvent& WXUNUSED(event) )
814 {
815 wxDataViewItemArray items;
816 int len = m_ctrl[0]->GetSelections( items );
817 for( int i = 0; i < len; i ++ )
818 if (items[i].IsOk())
819 m_music_model->Delete( items[i] );
820 }
821
822 void MyFrame::OnDeleteYear( wxCommandEvent& WXUNUSED(event) )
823 {
824 m_ctrl[0]->DeleteColumn( m_ctrl[0]->GetColumn( 2 ) );
825 FindWindow( ID_DELETE_YEAR )->Disable();
826 }
827
828 void MyFrame::OnSelectNinth( wxCommandEvent& WXUNUSED(event) )
829 {
830 if (!m_music_model->GetNinthItem().IsOk())
831 {
832 wxLogError( "Cannot select the ninth symphony: it was removed!" );
833 return;
834 }
835
836 m_ctrl[0]->Select( m_music_model->GetNinthItem() );
837 }
838
839 void MyFrame::OnCollapse( wxCommandEvent& WXUNUSED(event) )
840 {
841 wxDataViewItem item = m_ctrl[0]->GetSelection();
842 if (item.IsOk())
843 m_ctrl[0]->Collapse( item );
844 }
845
846 void MyFrame::OnExpand( wxCommandEvent& WXUNUSED(event) )
847 {
848 wxDataViewItem item = m_ctrl[0]->GetSelection();
849 if (item.IsOk())
850 m_ctrl[0]->Expand( item );
851 }
852
853 void MyFrame::OnValueChanged( wxDataViewEvent &event )
854 {
855 if (!m_log)
856 return;
857
858 wxLogMessage( "wxEVT_DATAVIEW_ITEM_VALUE_CHANGED, Item Id: %d; Column: %d",
859 event.GetItem().GetID(), event.GetColumn() );
860 }
861
862 void MyFrame::OnActivated( wxDataViewEvent &event )
863 {
864 if(!m_log)
865 return;
866
867 wxString title = m_music_model->GetTitle( event.GetItem() );
868 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, Item: %s", title );
869
870 if (m_ctrl[0]->IsExpanded( event.GetItem() ))
871 {
872 wxLogMessage( "Item: %s is expanded", title );
873 }
874 }
875
876 void MyFrame::OnSelectionChanged( wxDataViewEvent &event )
877 {
878 if(!m_log)
879 return;
880
881 wxString title = m_music_model->GetTitle( event.GetItem() );
882 if (title.empty())
883 title = "None";
884
885 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, First selected Item: %s", title );
886 }
887
888 void MyFrame::OnExpanding( wxDataViewEvent &event )
889 {
890 if (!m_log)
891 return;
892
893 wxString title = m_music_model->GetTitle( event.GetItem() );
894 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, Item: %s", title );
895 }
896
897
898 void MyFrame::OnStartEditing( wxDataViewEvent &event )
899 {
900 wxString artist = m_music_model->GetArtist( event.GetItem() );
901 if (artist == "Ludwig van Beethoven")
902 {
903 event.Veto();
904
905 if (!m_log)
906 return;
907
908 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING vetoed. Artist: %s", artist );
909 }
910 else
911 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_START_EDITING not vetoed. Artist: %s", artist );
912
913 }
914
915 void MyFrame::OnEditingStarted( wxDataViewEvent &event )
916 {
917 if (!m_log)
918 return;
919
920 wxString title = m_music_model->GetTitle( event.GetItem() );
921 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, Item: %s", title );
922 }
923
924 void MyFrame::OnEditingDone( wxDataViewEvent &event )
925 {
926 if (!m_log)
927 return;
928
929 wxString title = m_music_model->GetTitle( event.GetItem() );
930 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, Item: %s", title );
931 }
932
933 void MyFrame::OnExpanded( wxDataViewEvent &event )
934 {
935 if (!m_log)
936 return;
937
938 wxString title = m_music_model->GetTitle( event.GetItem() );
939 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, Item: %s", title );
940 }
941
942 void MyFrame::OnCollapsing( wxDataViewEvent &event )
943 {
944 if (!m_log)
945 return;
946
947 wxString title = m_music_model->GetTitle( event.GetItem() );
948 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, Item: %s", title );
949 }
950
951 void MyFrame::OnCollapsed( wxDataViewEvent &event )
952 {
953 if (!m_log)
954 return;
955
956 wxString title = m_music_model->GetTitle( event.GetItem() );
957 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, Item: %s", title );
958 }
959
960 void MyFrame::OnContextMenu( wxDataViewEvent &event )
961 {
962 if (!m_log)
963 return;
964
965 wxString title = m_music_model->GetTitle( event.GetItem() );
966 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s", title );
967
968 wxMenu menu;
969 menu.Append( 1, "menuitem 1" );
970 menu.Append( 2, "menuitem 2" );
971 menu.Append( 3, "menuitem 3" );
972
973 m_ctrl[0]->PopupMenu(&menu);
974 }
975
976 void MyFrame::OnHeaderClick( wxDataViewEvent &event )
977 {
978 // we need to skip the event to let the default behaviour of sorting by
979 // this column when it is clicked to take place
980 event.Skip();
981
982 if (!m_log)
983 return;
984
985 int pos = m_ctrl[0]->GetColumnPosition( event.GetDataViewColumn() );
986
987 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, Column position: %d", pos );
988 wxLogMessage( "Column width: %d", event.GetDataViewColumn()->GetWidth() );
989 }
990
991 void MyFrame::OnHeaderRightClick( wxDataViewEvent &event )
992 {
993 if(!m_log)
994 return;
995
996 int pos = m_ctrl[0]->GetColumnPosition( event.GetDataViewColumn() );
997
998 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, Column position: %d", pos );
999 }
1000
1001 void MyFrame::OnSorted( wxDataViewEvent &event )
1002 {
1003 if(!m_log)
1004 return;
1005
1006 int pos = m_ctrl[0]->GetColumnPosition( event.GetDataViewColumn() );
1007
1008 wxLogMessage( "wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, Column position: %d", pos );
1009 }
1010
1011 void MyFrame::OnRightClick( wxMouseEvent &event )
1012 {
1013 if(!m_log)
1014 return;
1015
1016 wxLogMessage( "wxEVT_MOUSE_RIGHT_UP, Click Point is X: %d, Y: %d",
1017 event.GetX(), event.GetY() );
1018 }
1019
1020
1021 // ----------------------------------------------------------------------------
1022 // MyFrame - event handlers for the second page
1023 // ----------------------------------------------------------------------------
1024
1025 void MyFrame::OnPrependList( wxCommandEvent& WXUNUSED(event) )
1026 {
1027 m_list_model->Prepend("Test");
1028 }
1029
1030 void MyFrame::OnDeleteList( wxCommandEvent& WXUNUSED(event) )
1031 {
1032 wxDataViewItemArray items;
1033 int len = m_ctrl[1]->GetSelections( items );
1034 if (len > 0)
1035 m_list_model->DeleteItems( items );
1036 }
1037
1038 void MyFrame::OnGoto(wxCommandEvent& WXUNUSED(event))
1039 {
1040 wxDataViewItem item = m_list_model->GetItem( 50 );
1041 m_ctrl[1]->EnsureVisible(item,m_col);
1042 }
1043
1044 void MyFrame::OnAddMany(wxCommandEvent& WXUNUSED(event))
1045 {
1046 m_list_model->AddMany();
1047 }
1048