]> git.saurik.com Git - wxWidgets.git/blob - samples/dataview/dataview.cpp
Implemented the same simple API for creating customized
[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
6 // Created: 06/01/06
7 // RCS-ID: $Id$
8 // Copyright: (c) Robert Roebling
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
11
12 // For compilers that support precompilation, includes "wx/wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __BORLANDC__
16 #pragma hdrstop
17 #endif
18
19 #ifndef WX_PRECOMP
20 #include "wx/wx.h"
21 #endif
22
23 #include "wx/datetime.h"
24 #include "wx/splitter.h"
25 #include "wx/aboutdlg.h"
26 #include "wx/choicdlg.h"
27 #include "wx/numdlg.h"
28 #include "wx/dataview.h"
29 #include "wx/spinctrl.h"
30
31 #ifndef __WXMSW__
32 #include "../sample.xpm"
33 #endif
34
35 #include "null.xpm"
36
37
38 #define DEFAULT_ALIGN wxALIGN_LEFT
39 #define DATAVIEW_DEFAULT_STYLE (wxDV_MULTIPLE|wxDV_HORIZ_RULES|wxDV_VERT_RULES)
40
41
42
43 // -------------------------------------
44 // MyTextModel
45 // -------------------------------------
46
47 WX_DECLARE_OBJARRAY(wxDateTime,wxArrayDate);
48 #include <wx/arrimpl.cpp>
49 WX_DEFINE_OBJARRAY(wxArrayDate)
50
51 class MyTextModel: public wxDataViewListModel
52 {
53 public:
54 MyTextModel()
55 {
56 unsigned int i;
57 for (i = 0; i < 1000; i++)
58 m_list.Add( wxT("Test") );
59 for (i = 0; i < 500; i++)
60 { m_bools.Add( 0 ); m_bools.Add( 1 ); }
61 for (i = 0; i < 500; i++)
62 { m_colours.Add( wxT("red") ); m_colours.Add( wxT("green") ); }
63 for (i = 0; i < 1000; i++)
64 { m_progress.Add( i/10 ); }
65 for (i = 0; i < 1000; i++)
66 {
67 wxDateTime date( wxDateTime::Now() );
68 m_dates.Add( date );
69 }
70 }
71
72 virtual unsigned int GetRowCount() const
73 { return 1000; }
74 virtual unsigned int GetColumnCount() const
75 { return 7; }
76
77 // as reported by wxVariant
78 virtual wxString GetColumnType( unsigned int col ) const
79 {
80 if (col == 6)
81 return wxT("datetime");
82
83 if (col == 5)
84 return wxT("long");
85
86 if (col == 3)
87 return wxT("bool");
88
89 return wxT("string");
90 }
91
92 virtual void GetValue( wxVariant &variant, unsigned int col, unsigned int row ) const
93 {
94 if (col == 6)
95 {
96 variant = (wxDateTime) m_dates[row];
97 } else
98 if (col == 5)
99 {
100 variant = (long) m_progress[row];
101 } else
102 if (col == 4)
103 {
104 variant = m_colours[row];
105 } else
106 if (col == 3)
107 {
108 variant = (bool) (m_bools[row] != 0);
109 } else
110 if (col == 2)
111 {
112 variant = m_list[row];
113 }
114 else
115 {
116 wxString tmp;
117 tmp.Printf( wxT("item(%d;%d)"), (int)row, (int)col );
118 variant = tmp;
119 }
120 }
121 virtual bool SetValue( wxVariant &value, unsigned int col, unsigned int row )
122 {
123 if (col == 6)
124 {
125 m_dates[row] = value.GetDateTime();
126 } else
127 if (col == 3)
128 {
129 m_bools[row] = (int) value.GetBool();
130 } else
131 if (col == 2)
132 {
133 m_list[row] = value.GetString();
134 }
135 return true;
136 }
137
138 wxArrayString m_list;
139 wxArrayInt m_bools;
140 wxArrayString m_colours;
141 wxArrayInt m_progress;
142 wxArrayDate m_dates;
143 };
144
145 // -------------------------------------
146 // MyTextRenderer
147 // -------------------------------------
148
149 class MyTextRenderer: public wxDataViewTextRenderer
150 {
151 public:
152 MyTextRenderer( const wxString varianttype = wxT("string"),
153 wxDataViewCellMode mode = wxDATAVIEW_CELL_INERT )
154 : wxDataViewTextRenderer( varianttype, mode ) { }
155
156 virtual bool Validate( wxVariant &value )
157 {
158 wxString str = value;
159 if (str.Length() > 10)
160 {
161 wxMessageDialog dlg( NULL, wxT("string too long") , wxT("Error") );
162 dlg.ShowModal();
163 return false;
164 }
165
166 return true;
167 }
168 };
169
170
171 // -------------------------------------
172 // MyCustomRenderer
173 // -------------------------------------
174
175 class MyCustomRenderer: public wxDataViewCustomRenderer
176 {
177 public:
178 MyCustomRenderer() :
179 wxDataViewCustomRenderer( wxT("string"), wxDATAVIEW_CELL_ACTIVATABLE )
180 {
181 m_colour = wxT("black");
182 }
183 bool SetValue( const wxVariant &value )
184 {
185 m_colour = value.GetString();
186 return true;
187 }
188
189 bool GetValue( wxVariant &value ) const
190 {
191 value = m_colour;
192 return true;
193 }
194
195 bool Render( wxRect rect, wxDC *dc, int WXUNUSED(state) )
196 {
197 dc->SetPen( *wxBLACK_PEN );
198 if (m_colour == wxT("red"))
199 dc->SetBrush( *wxRED_BRUSH );
200 else if (m_colour == wxT("green"))
201 dc->SetBrush( *wxGREEN_BRUSH );
202 else
203 dc->SetBrush( *wxBLACK_BRUSH );
204 dc->DrawRectangle( rect );
205 return true;
206 }
207 wxSize GetSize() const
208 {
209 return wxSize(20,8);
210 }
211 bool Activate( wxRect WXUNUSED(rect),
212 wxDataViewListModel *WXUNUSED(model),
213 unsigned int WXUNUSED(col),
214 unsigned int WXUNUSED(row) )
215 {
216 return false;
217 }
218
219 private:
220 wxString m_colour;
221 };
222
223 // -------------------------------------
224 // MySpinCtrlInPlaceRenderer
225 // -------------------------------------
226
227 class MySpinCtrlInPlaceRenderer: public wxDataViewCustomRenderer
228 {
229 public:
230 MySpinCtrlInPlaceRenderer() :
231 wxDataViewCustomRenderer( wxT("long"), wxDATAVIEW_CELL_EDITABLE ) { }
232
233
234 virtual bool HasEditorCtrl()
235 {
236 return true;
237 }
238 virtual wxControl* CreateEditorCtrl( wxWindow *parent, wxRect labelRect, const wxVariant &value )
239 {
240 long l = value;
241 return new wxSpinCtrl( parent, wxID_ANY, wxEmptyString,
242 labelRect.GetTopLeft(), labelRect.GetSize(), 0, 0, 100, l );
243 }
244 virtual bool GetValueFromEditorCtrl( wxControl* editor, wxVariant &value )
245 {
246 wxSpinCtrl *sc = (wxSpinCtrl*) editor;
247 long l = sc->GetValue();
248 value = l;
249 return true;
250 }
251
252 bool Render( wxRect rect, wxDC *dc, int WXUNUSED(state) )
253 {
254 wxString str;
255 str.Printf( wxT("%d"), (int) m_data );
256 dc->SetTextForeground( *wxBLACK );
257 dc->DrawText( str, rect.x, rect.y );
258 return true;
259 }
260 wxSize GetSize() const
261 {
262 return wxSize(80,16);
263 }
264 bool SetValue( const wxVariant &value )
265 {
266 m_data = value.GetLong();
267 return true;
268 }
269 bool GetValue( wxVariant &value ) const
270 {
271 value = m_data;
272 return true;
273 }
274
275
276 private:
277 long m_data;
278 };
279
280 // -------------------------------------
281 // MyUnsortedTextModel
282 // -------------------------------------
283
284 class MyUnsortedTextModel: public wxDataViewListModel
285 {
286 public:
287 MyUnsortedTextModel()
288 {
289 m_list.Add( wxT("This") );
290 m_list.Add( wxT("is") );
291 m_list.Add( wxT("an") );
292 m_list.Add( wxT("unsorted") );
293 m_list.Add( wxT("list") );
294 m_list.Add( wxT("of") );
295 m_list.Add( wxT("words.") );
296
297 m_ilist.Add( 0 );
298 m_ilist.Add( 1);
299 m_ilist.Add( 2 );
300 m_ilist.Add( 3 );
301 m_ilist.Add( 4 );
302 m_ilist.Add( 5 );
303 m_ilist.Add( 6 );
304
305 m_bitmap = wxBitmap( null_xpm );
306 }
307
308 virtual unsigned int GetRowCount() const
309 {
310 return m_list.GetCount();
311 }
312
313 virtual unsigned int GetColumnCount() const
314 {
315 return 4;
316 }
317
318 virtual wxString GetColumnType( unsigned int WXUNUSED(col) ) const
319 {
320 return wxT("string");
321 }
322
323 virtual void GetValue( wxVariant &variant, unsigned int col, unsigned int row ) const
324 {
325 if (col == 0)
326 {
327 variant = m_list[row];
328 return;
329 } else
330 if ((col == 2) || (col == 3))
331 {
332 variant << m_bitmap;
333 return;
334 } else
335 if (col == 4)
336 {
337 variant = (long) m_ilist[row];
338 return;
339 }
340
341 wxString tmp;
342 tmp.Printf( wxT("item(%d;%d)"), (int)row, (int)col );
343 variant = tmp;
344 }
345
346 virtual bool SetValue( wxVariant &variant, unsigned int col, unsigned int row )
347 {
348 if (col == 0)
349 {
350 m_list[row] = variant.GetString();
351 return true;
352 } else
353 if (col == 4)
354 {
355 m_ilist[row] = variant.GetLong();
356 return true;
357 }
358 return false;
359
360 }
361
362 void AppendRow( const wxString &text )
363 {
364 m_list.Add( text );
365 m_ilist.Add( 0 );
366 RowAppended();
367 }
368
369 void PrependRow( const wxString &text )
370 {
371 m_list.Insert( text, 0 );
372 m_ilist.Insert( 0, 0 );
373 RowPrepended();
374 }
375
376 void InsertRowAt1( const wxString &text )
377 {
378 m_list.Insert( text, 1 );
379 m_ilist.Insert( 0, 1 );
380 RowInserted( 1 );
381 }
382
383 void DeleteRow( unsigned int index )
384 {
385 m_list.RemoveAt( index );
386 m_ilist.RemoveAt( index );
387 RowDeleted( index );
388 }
389
390 wxArrayString m_list;
391 wxArrayInt m_ilist;
392 wxBitmap m_bitmap;
393 };
394
395 // -------------------------------------
396 // MyApp
397 // -------------------------------------
398
399 class MyApp: public wxApp
400 {
401 public:
402 bool OnInit(void);
403 int OnExit();
404 };
405
406 // -------------------------------------
407 // MyFrame
408 // -------------------------------------
409
410 class MyFrame : public wxFrame
411 {
412 public:
413 MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
414
415 public:
416 void OnQuit(wxCommandEvent& event);
417 void OnAbout(wxCommandEvent& event);
418 void OnNewSortingFrame(wxCommandEvent& event);
419
420 void OnStyleChange(wxCommandEvent& event);
421 void OnColumnSetting(wxCommandEvent& event);
422
423 private:
424 wxDataViewCtrl* dataview_left;
425 wxDataViewCtrl* dataview_right;
426 wxSplitterWindow *m_splitter;
427 wxPanel *m_panelLeft, *m_panelRight;
428
429 // utilities:
430
431 void CreateDataViewControls();
432
433 wxArrayInt GetFlaggedColumns(int flag);
434 wxAlignment ChooseAlign(const wxString &msg, bool onlyHorizontal);
435 void SetFlag(const wxArrayInt &idx, int flag);
436 void SetAlignment(const wxArrayInt &idx, bool header, wxAlignment align);
437 void SetWidth(const wxArrayInt &idx, bool minwidth, int width);
438
439 private:
440 DECLARE_EVENT_TABLE()
441 };
442
443 // -------------------------------------
444 // MySortingFrame
445 // -------------------------------------
446
447 enum my_events
448 {
449 ID_APPEND_ROW_LEFT = 1000,
450 ID_PREPEND_ROW_LEFT,
451 ID_INSERT_ROW_LEFT,
452 ID_DELETE_ROW_LEFT,
453 ID_EDIT_ROW_LEFT,
454
455 ID_SELECT,
456 ID_UNSELECT_ALL,
457
458 ID_APPEND_ROW_RIGHT,
459 ID_PREPEND_ROW_RIGHT,
460 ID_INSERT_ROW_RIGHT,
461 ID_DELETE_ROW_RIGHT,
462 ID_EDIT_ROW_RIGHT,
463
464 ID_SORTED,
465 ID_UNSORTED,
466 ID_ACTIVATED
467 };
468
469 class MySortingFrame: public wxFrame
470 {
471 public:
472 MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h);
473 ~MySortingFrame();
474
475 public:
476 void OnQuit(wxCommandEvent& event);
477 void OnAbout(wxCommandEvent& event);
478
479 void OnAppendRowLeft(wxCommandEvent& event);
480 void OnPrependRowLeft(wxCommandEvent& event);
481 void OnInsertRowLeft(wxCommandEvent& event);
482 void OnDeleteRowLeft(wxCommandEvent& event);
483 void OnEditRowLeft(wxCommandEvent& event);
484
485 void OnAppendRowRight(wxCommandEvent& event);
486 void OnPrependRowRight(wxCommandEvent& event);
487 void OnInsertRowRight(wxCommandEvent& event);
488 void OnDeleteRowRight(wxCommandEvent& event);
489 void OnEditRowRight(wxCommandEvent& event);
490
491 void OnSelect(wxCommandEvent& event);
492 void OnUnselectAll(wxCommandEvent& event);
493
494 void OnSelectedUnsorted(wxDataViewEvent &event);
495 void OnSelectedSorted(wxDataViewEvent &event);
496 void OnActivatedUnsorted(wxDataViewEvent &event);
497
498 void OnHeaderClickSorted(wxDataViewEvent &event);
499 void OnHeaderClickUnsorted(wxDataViewEvent &event);
500
501 private:
502 wxDataViewCtrl* dataview_left;
503 wxDataViewCtrl* dataview_right;
504
505 wxLog *m_logOld;
506 wxTextCtrl *m_logWindow;
507
508 wxObjectDataPtr<MyUnsortedTextModel> m_unsorted_model;
509 wxObjectDataPtr<wxDataViewSortedListModel> m_sorted_model;
510
511 DECLARE_EVENT_TABLE()
512 };
513
514 // -------------------------------------
515 // MyApp
516 // -------------------------------------
517
518 IMPLEMENT_APP(MyApp)
519
520 bool MyApp::OnInit(void)
521 {
522 if ( !wxApp::OnInit() )
523 return false;
524
525 // build the first frame
526 MyFrame *frame =
527 new MyFrame(NULL, wxT("wxDataViewCtrl feature test"), 10, 10, 800, 340);
528 frame->Show(true);
529
530 SetTopWindow(frame);
531 return true;
532 }
533
534 int MyApp::OnExit()
535 {
536 return 0;
537 }
538
539
540 // -------------------------------------
541 // MyFrame
542 // -------------------------------------
543
544 enum
545 {
546 // file menu
547 ID_ABOUT = wxID_ABOUT,
548 ID_NEW_SORT_FRAME = wxID_HIGHEST+1,
549 ID_EXIT = wxID_EXIT,
550
551 // dataviewctrl menu
552 ID_SINGLE_SEL_MODE = wxID_HIGHEST+2,
553 ID_MULTIPLE_SEL_MODE,
554 ID_NO_HEADER_MODE,
555 ID_HORIZ_RULES_MODE,
556 ID_VERT_RULES_MODE,
557
558 ID_RESIZEABLE_COLUMNS,
559 ID_SORTABLE_COLUMNS,
560 ID_HIDDEN_COLUMNS,
561
562 ID_CHOOSE_COLUMN_ALIGNMENT,
563 ID_CHOOSE_CONTENTS_ALIGNMENT,
564
565 ID_SET_MINWIDTH,
566 ID_SET_WIDTH
567 };
568
569 BEGIN_EVENT_TABLE(MyFrame, wxFrame)
570
571 // file menu
572 EVT_MENU( ID_ABOUT, MyFrame::OnAbout )
573 EVT_MENU( ID_NEW_SORT_FRAME, MyFrame::OnNewSortingFrame )
574 EVT_MENU( ID_EXIT, MyFrame::OnQuit )
575
576 // dataviewctrl menu
577 EVT_COMMAND_RANGE( ID_SINGLE_SEL_MODE, ID_VERT_RULES_MODE,
578 wxEVT_COMMAND_MENU_SELECTED, MyFrame::OnStyleChange )
579
580 EVT_COMMAND_RANGE( ID_RESIZEABLE_COLUMNS, ID_SET_WIDTH,
581 wxEVT_COMMAND_MENU_SELECTED, MyFrame::OnColumnSetting )
582
583 END_EVENT_TABLE()
584
585 MyFrame::MyFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
586 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
587 {
588 SetIcon(wxICON(sample));
589
590 // build the menus:
591
592 wxMenu *file_menu = new wxMenu;
593 file_menu->Append(ID_NEW_SORT_FRAME, _T("&New sorting frame"));
594 file_menu->AppendSeparator();
595 file_menu->Append(ID_ABOUT, _T("&About"));
596 file_menu->AppendSeparator();
597 file_menu->Append(ID_EXIT, _T("E&xit"));
598
599 wxMenu *data_menu = new wxMenu;
600 data_menu->AppendRadioItem(ID_SINGLE_SEL_MODE, _T("&Single selection mode"));
601 data_menu->AppendRadioItem(ID_MULTIPLE_SEL_MODE, _T("&Multiple selection mode"));
602 data_menu->AppendSeparator();
603 data_menu->AppendCheckItem(ID_NO_HEADER_MODE, _T("No header mode"));
604 data_menu->AppendCheckItem(ID_HORIZ_RULES_MODE, _T("Horizontal rules"));
605 data_menu->AppendCheckItem(ID_VERT_RULES_MODE, _T("Vertical rules"));
606 data_menu->AppendSeparator();
607 data_menu->Append(ID_RESIZEABLE_COLUMNS, _T("Set column(s) as resizeable..."));
608 data_menu->Append(ID_SORTABLE_COLUMNS, _T("Set column(s) as sortable..."));
609 data_menu->Append(ID_HIDDEN_COLUMNS, _T("Set column(s) as hidden..."));
610 data_menu->AppendSeparator();
611 data_menu->Append(ID_CHOOSE_COLUMN_ALIGNMENT, _T("Set column(s) title alignment..."));
612 data_menu->Append(ID_CHOOSE_CONTENTS_ALIGNMENT, _T("Set column(s) contents alignment..."));
613 data_menu->AppendSeparator();
614 data_menu->Append(ID_SET_MINWIDTH, _T("Set column(s) minimal width..."));
615 data_menu->Append(ID_SET_WIDTH, _T("Set column(s) width..."));
616
617 wxMenuBar *menu_bar = new wxMenuBar;
618 menu_bar->Append(file_menu, _T("&File"));
619 menu_bar->Append(data_menu, _T("&DataViewCtrl"));
620
621 SetMenuBar(menu_bar);
622 CreateStatusBar();
623
624
625 // check the menus for the default wxDataViewCtrl style
626 data_menu->Check(ID_MULTIPLE_SEL_MODE, (DATAVIEW_DEFAULT_STYLE & wxDV_MULTIPLE) != 0);
627 data_menu->Check(ID_NO_HEADER_MODE, (DATAVIEW_DEFAULT_STYLE & wxDV_NO_HEADER) != 0);
628 data_menu->Check(ID_HORIZ_RULES_MODE, (DATAVIEW_DEFAULT_STYLE & wxDV_HORIZ_RULES) != 0);
629 data_menu->Check(ID_VERT_RULES_MODE, (DATAVIEW_DEFAULT_STYLE & wxDV_VERT_RULES) != 0);
630
631
632 // build the other controls:
633
634 m_splitter = new wxSplitterWindow( this, wxID_ANY );
635 m_splitter->SetSashGravity(0.5);
636
637 m_panelLeft = new wxPanel( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
638 wxNO_BORDER );
639 m_panelRight = new wxPanel( m_splitter, wxID_ANY, wxDefaultPosition, wxDefaultSize,
640 wxNO_BORDER );
641 wxSizer *szLeft = new wxBoxSizer(wxVERTICAL);
642 wxSizer *szRight = new wxBoxSizer(wxVERTICAL);
643
644 dataview_left = NULL;
645 dataview_right = NULL;
646 CreateDataViewControls();
647
648 // left panel
649 szLeft->Add( dataview_left, 1, wxGROW|wxALL, 5 );
650 m_panelLeft->SetSizerAndFit(szLeft);
651
652 // right panel
653 wxStaticText *stattext =
654 new wxStaticText(m_panelRight, wxID_ANY,
655 wxT("This is another wxDataViewCtrl using the same wxDataViewModel ")
656 wxT("of the wxDataViewCtrl on the left but, unlike it, this window ")
657 wxT("won't react to the style/column changes done through the ")
658 wxT("'DataViewCtrl' menu"));
659 stattext->Wrap(GetClientSize().GetWidth() / 2);
660
661 szRight->Add( stattext, 0, wxALL, 5 );
662 szRight->Add( dataview_right, 1, wxGROW|wxALL, 5 );
663 m_panelRight->SetSizerAndFit(szRight);
664
665 // split the two panels
666 m_splitter->SplitVertically(m_panelLeft, m_panelRight);
667 this->SetMinSize(m_splitter->GetBestSize());
668 }
669
670 void MyFrame::CreateDataViewControls()
671 {
672 wxDataViewCtrl *old1 = NULL, *old2 = NULL;
673
674 if (dataview_left)
675 old1 = dataview_left;
676 if (dataview_right)
677 old2 = dataview_right;
678
679 // styles:
680 long style = 0;
681 if (GetMenuBar()->FindItem(ID_MULTIPLE_SEL_MODE)->IsChecked())
682 style |= wxDV_MULTIPLE;
683 if (GetMenuBar()->FindItem(ID_NO_HEADER_MODE)->IsChecked())
684 style |= wxDV_NO_HEADER;
685 if (GetMenuBar()->FindItem(ID_HORIZ_RULES_MODE)->IsChecked())
686 style |= wxDV_HORIZ_RULES;
687 if (GetMenuBar()->FindItem(ID_VERT_RULES_MODE)->IsChecked())
688 style |= wxDV_VERT_RULES;
689
690
691 // Left wxDataViewCtrl
692 dataview_left = new wxDataViewCtrl( m_panelLeft, wxID_ANY, wxDefaultPosition,
693 wxDefaultSize, style );
694
695
696 wxObjectDataPtr<MyTextModel> model(new MyTextModel);
697 dataview_left->AssociateModel( model.get() );
698
699 dataview_left->AppendTextColumn( wxT("First"), 0, wxDATAVIEW_CELL_INERT, -1,
700 DEFAULT_ALIGN );
701 dataview_left->AppendTextColumn( wxT("Second"), 1, wxDATAVIEW_CELL_INERT, -1,
702 DEFAULT_ALIGN );
703
704 wxDataViewTextRenderer *text_renderer =
705 new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
706 wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 2,
707 -1, DEFAULT_ALIGN );
708 dataview_left->AppendColumn( column );
709
710 dataview_left->AppendToggleColumn( wxT("fourth"), 3, wxDATAVIEW_CELL_INERT, -1,
711 DEFAULT_ALIGN );
712
713 MyCustomRenderer *custom_renderer = new MyCustomRenderer;
714 column = new wxDataViewColumn( wxT("custom"), custom_renderer, 4, -1, DEFAULT_ALIGN );
715 dataview_left->AppendColumn( column );
716
717 dataview_left->AppendProgressColumn( wxT("progress"), 5, wxDATAVIEW_CELL_INERT, -1,
718 DEFAULT_ALIGN );
719
720 dataview_left->AppendDateColumn( wxT("date"), 6, wxDATAVIEW_CELL_INERT, -1, DEFAULT_ALIGN );
721
722
723 // Right wxDataViewCtrl using the same model
724 dataview_right = new wxDataViewCtrl( m_panelRight, wxID_ANY );
725 dataview_right->AssociateModel( model.get() );
726
727 text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
728 column = new wxDataViewColumn( wxT("editable"), text_renderer, 2 );
729 dataview_right->AppendColumn( column );
730 dataview_right->AppendTextColumn( wxT("first"), 0 );
731 dataview_right->AppendTextColumn( wxT("second"), 1 );
732 wxDataViewToggleRenderer *toggle_renderer =
733 new wxDataViewToggleRenderer( wxT("bool"), wxDATAVIEW_CELL_ACTIVATABLE );
734 column = new wxDataViewColumn( wxT("bool"), toggle_renderer, 3, 30 );
735 dataview_right->AppendColumn( column );
736
737 dataview_right->AppendDateColumn( wxT("date"), 6 );
738
739
740 // layout the new dataview controls
741 if (old1)
742 {
743 m_panelLeft->GetSizer()->Replace(old1, dataview_left);
744 delete old1;
745
746 m_panelLeft->Layout();
747 }
748
749 if (old2)
750 {
751 m_panelRight->GetSizer()->Replace(old2, dataview_right);
752 delete old2;
753
754 m_panelRight->Layout();
755 }
756 }
757
758 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
759 {
760 Close(true);
761 }
762
763 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
764 {
765 wxAboutDialogInfo info;
766 info.SetName(_("DataView sample"));
767 info.SetDescription(_("This sample demonstrates the dataview control handling"));
768 info.SetCopyright(_T("(C) 2007 Robert Roebling"));
769
770 wxAboutBox(info);
771 }
772
773 void MyFrame::OnNewSortingFrame(wxCommandEvent& WXUNUSED(event) )
774 {
775 MySortingFrame *frame2 =
776 new MySortingFrame(NULL, wxT("wxDataViewCtrl sorting test"), 10, 150, 600, 500);
777 frame2->Show(true);
778 }
779
780 void MyFrame::OnStyleChange(wxCommandEvent& WXUNUSED(event) )
781 {
782 // recreate the wxDataViewCtrl:
783 CreateDataViewControls();
784 }
785
786 void MyFrame::OnColumnSetting(wxCommandEvent& event)
787 {
788 wxArrayInt columns;
789 int flag = 0;
790 bool header = false, minwidth = false;
791 wxString msg;
792
793 switch (event.GetId())
794 {
795 case ID_RESIZEABLE_COLUMNS:
796 flag = wxDATAVIEW_COL_RESIZABLE;
797 columns = GetFlaggedColumns(flag);
798 break;
799 case ID_SORTABLE_COLUMNS:
800 flag = wxDATAVIEW_COL_SORTABLE;
801 columns = GetFlaggedColumns(flag);
802 break;
803 case ID_HIDDEN_COLUMNS:
804 flag = wxDATAVIEW_COL_HIDDEN;
805 columns = GetFlaggedColumns(flag);
806 break;
807
808 case ID_CHOOSE_COLUMN_ALIGNMENT:
809 msg = wxT("Select the columns whose headers' alignment will be modified.");
810 header = true;
811 break;
812 case ID_CHOOSE_CONTENTS_ALIGNMENT:
813 msg = wxT("Select the columns whose contents' alignment will be modified.");
814 header = false;
815 break;
816
817 case ID_SET_MINWIDTH:
818 msg = wxT("Please provide the new minimal width:");
819 minwidth = true;
820 break;
821 case ID_SET_WIDTH:
822 msg = wxT("Please provide the new width:");
823 minwidth = false;
824 break;
825 }
826
827 // get column titles:
828
829 wxArrayString choices;
830 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
831 choices.Add(dataview_left->GetColumn(i)->GetTitle());
832
833 // ask the user
834 wxGetMultipleChoices(
835 columns,
836 wxT("Choose the columns to which apply the change."),
837 wxT("Choose the column"),
838 choices,
839 this);
840
841 switch (event.GetId())
842 {
843 case ID_RESIZEABLE_COLUMNS:
844 case ID_SORTABLE_COLUMNS:
845 case ID_HIDDEN_COLUMNS:
846 SetFlag(columns, flag);
847 break;
848
849 case ID_CHOOSE_COLUMN_ALIGNMENT:
850 case ID_CHOOSE_CONTENTS_ALIGNMENT:
851 SetAlignment(columns, header, ChooseAlign(msg, header));
852 break;
853
854 case ID_SET_MINWIDTH:
855 case ID_SET_WIDTH:
856 {
857 int def = minwidth ? wxDVC_DEFAULT_MINWIDTH : wxDVC_DEFAULT_WIDTH;
858
859 msg << wxT("\nNOTE: all non-selected columns will be reset to a width of ")
860 << def << wxT(" pixels.");
861
862 long ret =
863 wxGetNumberFromUser(msg, wxT("New value:"), wxT("Modify width"),
864 def, 0, 300, this);
865
866 if (ret != -1)
867 SetWidth(columns, minwidth, ret);
868 }
869 break;
870 }
871
872 dataview_left->Refresh();
873 }
874
875 wxAlignment MyFrame::ChooseAlign(const wxString &msg, bool onlyHorizontal)
876 {
877 const wxString choices[] =
878 {
879 wxT("Left"),
880 wxT("Center horizontally"),
881 wxT("Right"),
882 wxT("Top"),
883 wxT("Center vertically"),
884 wxT("Bottom"),
885 wxT("Center")
886 };
887
888 wxAlignment flags[] =
889 {
890 wxALIGN_LEFT,
891 wxALIGN_CENTER_HORIZONTAL,
892 wxALIGN_RIGHT,
893 wxALIGN_TOP,
894 wxALIGN_CENTER_VERTICAL,
895 wxALIGN_BOTTOM,
896 wxALIGN_CENTER
897 };
898
899 int n = WXSIZEOF(choices);
900 if (onlyHorizontal)
901 n = 3; // show only the first three choices
902
903 int choice = wxGetSingleChoiceIndex(
904 msg + wxT("\nNOTE: _all_ non-selected column's alignment will be reset to wxALIGN_LEFT!"),
905 wxT("Alignment"),
906 n, choices,
907 this);
908
909 if (choice == wxNOT_FOUND)
910 return wxALIGN_LEFT;
911
912 return flags[choice];
913 }
914
915 void MyFrame::SetFlag(const wxArrayInt &idx, int toadd)
916 {
917 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
918 {
919 int current = dataview_left->GetColumn(i)->GetFlags();
920
921 if (idx.Index(i) != wxNOT_FOUND)
922 dataview_left->GetColumn(i)->SetFlags(current | toadd);
923 else
924 dataview_left->GetColumn(i)->SetFlags(current & ~toadd);
925 }
926 }
927
928 wxArrayInt MyFrame::GetFlaggedColumns(int flag)
929 {
930 wxArrayInt ret;
931 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
932 if (dataview_left->GetColumn(i)->GetFlags() & flag)
933 ret.Add(i);
934 return ret;
935 }
936
937 void MyFrame::SetAlignment(const wxArrayInt &idx, bool header, wxAlignment align)
938 {
939 // set to DEFAULT_ALIGN all columns except those
940 // contained in 'idx' which are set to 'align'
941
942 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
943 {
944 wxAlignment toset = DEFAULT_ALIGN;
945 if (idx.Index(i) != wxNOT_FOUND)
946 toset = align;
947
948 if (header)
949 dataview_left->GetColumn(i)->SetAlignment(toset);
950 else
951 dataview_left->GetColumn(i)->GetRenderer()->SetAlignment(toset);
952 }
953 }
954
955 void MyFrame::SetWidth(const wxArrayInt &idx, bool minwidth, int width)
956 {
957 // set to wxDVC_DEFAULT_WIDTH wide all columns except those
958 // contained in 'idx' which are set to 'width'
959
960 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
961 {
962 int toset = minwidth ? wxDVC_DEFAULT_MINWIDTH : wxDVC_DEFAULT_WIDTH;
963 if (idx.Index(i) != wxNOT_FOUND)
964 toset = width;
965
966 if (minwidth)
967 dataview_left->GetColumn(i)->SetMinWidth(toset);
968 else
969 dataview_left->GetColumn(i)->SetWidth(toset);
970 }
971 }
972
973
974 // -------------------------------------
975 // MySortingFrame
976 // -------------------------------------
977
978 BEGIN_EVENT_TABLE(MySortingFrame,wxFrame)
979 EVT_BUTTON( ID_APPEND_ROW_LEFT, MySortingFrame::OnAppendRowLeft )
980 EVT_BUTTON( ID_PREPEND_ROW_LEFT, MySortingFrame::OnPrependRowLeft )
981 EVT_BUTTON( ID_INSERT_ROW_LEFT, MySortingFrame::OnInsertRowLeft )
982 EVT_BUTTON( ID_DELETE_ROW_LEFT, MySortingFrame::OnDeleteRowLeft )
983 EVT_BUTTON( ID_SELECT, MySortingFrame::OnSelect )
984 EVT_BUTTON( ID_UNSELECT_ALL, MySortingFrame::OnUnselectAll )
985 EVT_DATAVIEW_ROW_SELECTED( ID_SORTED, MySortingFrame::OnSelectedSorted )
986 EVT_DATAVIEW_ROW_SELECTED( ID_UNSORTED, MySortingFrame::OnSelectedUnsorted )
987 EVT_DATAVIEW_ROW_ACTIVATED( ID_UNSORTED, MySortingFrame::OnActivatedUnsorted )
988 EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_SORTED, MySortingFrame::OnHeaderClickSorted )
989 EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_UNSORTED, MySortingFrame::OnHeaderClickUnsorted )
990 END_EVENT_TABLE()
991
992 MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
993 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
994 {
995 m_logOld = NULL;
996
997 SetIcon(wxICON(sample));
998 CreateStatusBar();
999
1000 wxPanel *main = new wxPanel(this);
1001
1002 // Left wxDataViewCtrl
1003 dataview_left = new wxDataViewCtrl( main, ID_UNSORTED, wxDefaultPosition,
1004 wxDefaultSize, wxDV_MULTIPLE );
1005
1006 m_unsorted_model.reset(new MyUnsortedTextModel);
1007 dataview_left->AssociateModel( m_unsorted_model.get() );
1008
1009 wxDataViewTextRenderer *text_renderer =
1010 new MyTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
1011 wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 0 );
1012 dataview_left->AppendColumn( column );
1013 dataview_left->AppendTextColumn( wxT("second"), 1 );
1014 dataview_left->AppendColumn( new wxDataViewColumn( wxBitmap(null_xpm),
1015 new wxDataViewBitmapRenderer, 2, 25 ) );
1016 dataview_left->AppendColumn( new wxDataViewColumn( wxT("icon"),
1017 new wxDataViewBitmapRenderer, 3, 25 ) );
1018
1019 // Right wxDataViewCtrl using the sorting model
1020 dataview_right = new wxDataViewCtrl( main, ID_SORTED );
1021
1022 m_sorted_model.reset(new wxDataViewSortedListModel( m_unsorted_model.get() ));
1023 dataview_right->AssociateModel( m_sorted_model.get() );
1024
1025 text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
1026 column = new wxDataViewColumn( wxT("editable"), text_renderer, 0, -1,
1027 wxALIGN_CENTER,
1028 wxDATAVIEW_COL_SORTABLE|wxDATAVIEW_COL_RESIZABLE );
1029 dataview_right->AppendColumn( column );
1030
1031 dataview_right->AppendTextColumn( wxT("second"), 1 );
1032
1033 MySpinCtrlInPlaceRenderer *sr = new MySpinCtrlInPlaceRenderer;
1034 column = new wxDataViewColumn( wxT("spin"), sr, 4, -1, wxALIGN_CENTER );
1035 dataview_right->AppendColumn( column );
1036
1037 // layout dataview controls.
1038
1039 wxBoxSizer *top_sizer = new wxBoxSizer( wxHORIZONTAL );
1040 top_sizer->Add( dataview_left, 1, wxGROW );
1041 top_sizer->Add(10,10);
1042 top_sizer->Add( dataview_right, 1, wxGROW );
1043
1044 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
1045 button_sizer->Add( 10, 10, 1 );
1046 wxFlexGridSizer *left_sizer = new wxFlexGridSizer( 2 );
1047 left_sizer->Add( new wxButton( main, ID_APPEND_ROW_LEFT, wxT("Append") ), 0, wxALL, 5 );
1048 left_sizer->Add( new wxButton( main, ID_PREPEND_ROW_LEFT, wxT("Prepend") ), 0, wxALL, 5 );
1049 left_sizer->Add( new wxButton( main, ID_INSERT_ROW_LEFT, wxT("Insert") ), 0, wxALL, 5 );
1050 left_sizer->Add( new wxButton( main, ID_DELETE_ROW_LEFT, wxT("Delete second") ), 0, wxALL, 5 );
1051 left_sizer->Add( new wxButton( main, ID_EDIT_ROW_LEFT, wxT("Edit") ), 0, wxALL, 5 );
1052 left_sizer->Add( 5,5 );
1053 left_sizer->Add( new wxButton( main, ID_SELECT, wxT("Select third") ), 0, wxALL, 5 );
1054 left_sizer->Add( new wxButton( main, ID_UNSELECT_ALL, wxT("Unselect all") ), 0, wxALL, 5 );
1055 button_sizer->Add( left_sizer );
1056 button_sizer->Add( 10, 10, 2 );
1057 wxFlexGridSizer *right_sizer = new wxFlexGridSizer( 2 );
1058 right_sizer->Add( new wxButton( main, ID_APPEND_ROW_RIGHT, wxT("Append") ), 0, wxALL, 5 );
1059 right_sizer->Add( new wxButton( main, ID_PREPEND_ROW_RIGHT, wxT("Prepend") ), 0, wxALL, 5 );
1060 right_sizer->Add( new wxButton( main, ID_INSERT_ROW_RIGHT, wxT("Insert") ), 0, wxALL, 5 );
1061 right_sizer->Add( new wxButton( main, ID_DELETE_ROW_RIGHT, wxT("Delete second") ), 0, wxALL, 5 );
1062 right_sizer->Add( new wxButton( main, ID_EDIT_ROW_RIGHT, wxT("Edit") ), 0, wxALL, 5 );
1063 button_sizer->Add( right_sizer );
1064 button_sizer->Add( 10, 10, 1 );
1065
1066 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
1067 main_sizer->Add( top_sizer, 1, wxGROW );
1068 main_sizer->Add( button_sizer, 0, wxGROW );
1069
1070 m_logWindow = new wxTextCtrl(main, wxID_ANY, wxEmptyString,
1071 wxDefaultPosition, wxDefaultSize,
1072 wxTE_MULTILINE | wxSUNKEN_BORDER);
1073 main_sizer->Add( 20,20 );
1074 main_sizer->Add( m_logWindow, 1, wxGROW );
1075
1076 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
1077
1078 main->SetSizer( main_sizer );
1079 }
1080
1081 MySortingFrame::~MySortingFrame()
1082 {
1083 delete wxLog::SetActiveTarget(m_logOld);
1084 }
1085
1086 void MySortingFrame::OnSelectedUnsorted(wxDataViewEvent &event)
1087 {
1088 int row = event.GetRow();
1089 wxLogMessage( wxT("OnSelected from unsorted list, selected %d"), row );
1090 if (row >= 0)
1091 wxLogMessage( wxT("wxDataViewCtrl::IsSelected( %d ): %d (as int)"),
1092 row, (int) dataview_right->IsSelected( row ) );
1093 }
1094
1095 void MySortingFrame::OnSelectedSorted(wxDataViewEvent &event)
1096 {
1097 wxLogMessage( wxT("OnSelected from sorted list, selected %d"), (int) event.GetRow() );
1098 }
1099
1100 void MySortingFrame::OnActivatedUnsorted(wxDataViewEvent &event)
1101 {
1102 wxLogMessage( wxT("OnActivated from unsorted list, activated %d"), (int) event.GetRow() );
1103 }
1104
1105 void MySortingFrame::OnHeaderClickSorted(wxDataViewEvent &event)
1106 {
1107 wxDataViewColumn *col = event.GetDataViewColumn();
1108 wxLogMessage( wxT("OnHeaderClick from sorted list, column %s"), col->GetTitle().c_str() );
1109
1110 if (col->GetTitle() == wxT("editable"))
1111 {
1112 // this is the sorting column
1113 if (col->IsSortOrderAscending())
1114 {
1115 col->SetSortOrder( false );
1116 m_sorted_model->SetAscending( false );
1117 m_sorted_model->Resort();
1118 }
1119 else
1120 {
1121 col->SetSortOrder( true );
1122 m_sorted_model->SetAscending( true );
1123 m_sorted_model->Resort();
1124 }
1125 }
1126 }
1127
1128 void MySortingFrame::OnHeaderClickUnsorted(wxDataViewEvent &event)
1129 {
1130 wxLogMessage( wxT("OnHeaderClick from unsorted list, column %s"),
1131 event.GetDataViewColumn()->GetTitle().c_str() );
1132 }
1133
1134 void MySortingFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
1135 {
1136 Close(true);
1137 }
1138
1139 void MySortingFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
1140 {
1141 wxMessageDialog dialog(this, _T("This demonstrates the dataview control sorting"),
1142 _T("About DataView"), wxOK);
1143
1144 dialog.ShowModal();
1145 }
1146
1147 void MySortingFrame::OnSelect(wxCommandEvent& WXUNUSED(event))
1148 {
1149 dataview_left->SetSelection( 2 );
1150 }
1151
1152 void MySortingFrame::OnUnselectAll(wxCommandEvent& WXUNUSED(event))
1153 {
1154 dataview_left->ClearSelection();
1155 }
1156
1157 void MySortingFrame::OnAppendRowLeft(wxCommandEvent& WXUNUSED(event))
1158 {
1159 wxTextEntryDialog dialog( this, wxT("Enter text to append") );
1160 if (dialog.ShowModal() == wxID_OK)
1161 {
1162 wxString value = dialog.GetValue();
1163 if (!value.empty())
1164 m_unsorted_model->AppendRow( value );
1165 }
1166 }
1167
1168 void MySortingFrame::OnPrependRowLeft(wxCommandEvent& WXUNUSED(event))
1169 {
1170 wxTextEntryDialog dialog( this, wxT("Enter text to prepend") );
1171 if (dialog.ShowModal() == wxID_OK)
1172 {
1173 wxString value = dialog.GetValue();
1174 if (!value.empty())
1175 m_unsorted_model->PrependRow( value );
1176 }
1177 }
1178
1179 void MySortingFrame::OnInsertRowLeft(wxCommandEvent& WXUNUSED(event))
1180 {
1181 wxTextEntryDialog dialog( this, wxT("Enter text to insert before second") );
1182 if (dialog.ShowModal() == wxID_OK)
1183 {
1184 wxString value = dialog.GetValue();
1185 if (!value.empty())
1186 m_unsorted_model->InsertRowAt1( value );
1187 }
1188 }
1189
1190 void MySortingFrame::OnDeleteRowLeft(wxCommandEvent& WXUNUSED(event))
1191 {
1192 m_unsorted_model->DeleteRow( 1 );
1193 }
1194
1195 void MySortingFrame::OnEditRowLeft(wxCommandEvent& WXUNUSED(event))
1196 {
1197 }
1198
1199 void MySortingFrame::OnAppendRowRight(wxCommandEvent& WXUNUSED(event))
1200 {
1201 }
1202
1203 void MySortingFrame::OnPrependRowRight(wxCommandEvent& WXUNUSED(event))
1204 {
1205 }
1206
1207 void MySortingFrame::OnInsertRowRight(wxCommandEvent& WXUNUSED(event))
1208 {
1209 }
1210
1211 void MySortingFrame::OnDeleteRowRight(wxCommandEvent& WXUNUSED(event))
1212 {
1213 }
1214
1215 void MySortingFrame::OnEditRowRight(wxCommandEvent& WXUNUSED(event))
1216 {
1217 }
1218