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