]> git.saurik.com Git - wxWidgets.git/blob - samples/dataview/dataview.cpp
make File->Exit work
[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( const 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( const 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 0
686 if (GetMenuBar()->FindItem(ID_HORIZ_RULES_MODE)->IsChecked())
687 style |= wxDV_HORIZ_RULES;
688 if (GetMenuBar()->FindItem(ID_VERT_RULES_MODE)->IsChecked())
689 style |= wxDV_VERT_RULES;
690 #endif
691
692
693 // Left wxDataViewCtrl
694 dataview_left = new wxDataViewCtrl( m_panelLeft, wxID_ANY, wxDefaultPosition,
695 wxDefaultSize, style );
696
697
698 wxDataViewTextRenderer *text_renderer;
699 wxDataViewColumn *column;
700
701 wxObjectDataPtr<MyTextModel> model(new MyTextModel);
702 dataview_left->AssociateModel( model.get() );
703
704 dataview_left->AppendTextColumn( wxT("First"), 0, wxDATAVIEW_CELL_INERT, -1,
705 DEFAULT_ALIGN );
706 dataview_left->AppendTextColumn( wxT("Second"), 1, wxDATAVIEW_CELL_INERT, -1,
707 DEFAULT_ALIGN );
708
709 text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
710 column = new wxDataViewColumn( wxT("editable"), text_renderer, 2, -1, DEFAULT_ALIGN );
711 dataview_left->AppendColumn( column );
712
713 dataview_left->AppendToggleColumn( wxT("fourth"), 3, wxDATAVIEW_CELL_INERT, -1,
714 DEFAULT_ALIGN );
715
716 MyCustomRenderer *custom_renderer = new MyCustomRenderer;
717 column = new wxDataViewColumn( wxT("custom"), custom_renderer, 4, -1, DEFAULT_ALIGN );
718 dataview_left->AppendColumn( column );
719
720 dataview_left->AppendProgressColumn( wxT("progress"), 5, wxDATAVIEW_CELL_INERT, -1,
721 DEFAULT_ALIGN );
722
723 dataview_left->AppendDateColumn( wxT("date"), 6, wxDATAVIEW_CELL_INERT, -1, DEFAULT_ALIGN );
724
725 // Right wxDataViewCtrl using the same model
726 dataview_right = new wxDataViewCtrl( m_panelRight, wxID_ANY );
727 dataview_right->AssociateModel( model.get() );
728
729 text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
730 column = new wxDataViewColumn( wxT("editable"), text_renderer, 2 );
731 dataview_right->AppendColumn( column );
732 dataview_right->AppendTextColumn( wxT("first"), 0 );
733 dataview_right->AppendTextColumn( wxT("second"), 1 );
734 wxDataViewToggleRenderer *toggle_renderer =
735 new wxDataViewToggleRenderer( wxT("bool"), wxDATAVIEW_CELL_ACTIVATABLE );
736 column = new wxDataViewColumn( wxT("bool"), toggle_renderer, 3, 30 );
737 dataview_right->AppendColumn( column );
738
739 dataview_right->AppendDateColumn( wxT("date"), 6 );
740
741
742 // layout the new dataview controls
743 if (old1)
744 {
745 m_panelLeft->GetSizer()->Replace(old1, dataview_left);
746 delete old1;
747
748 m_panelLeft->Layout();
749 }
750
751 if (old2)
752 {
753 m_panelRight->GetSizer()->Replace(old2, dataview_right);
754 delete old2;
755
756 m_panelRight->Layout();
757 }
758 }
759
760 void MyFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
761 {
762 Close(true);
763 }
764
765 void MyFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
766 {
767 wxAboutDialogInfo info;
768 info.SetName(_("DataView sample"));
769 info.SetDescription(_("This sample demonstrates the dataview control handling"));
770 info.SetCopyright(_T("(C) 2007 Robert Roebling"));
771
772 wxAboutBox(info);
773 }
774
775 void MyFrame::OnNewSortingFrame(wxCommandEvent& WXUNUSED(event) )
776 {
777 MySortingFrame *frame2 =
778 new MySortingFrame(NULL, wxT("wxDataViewCtrl sorting test"), 10, 150, 600, 500);
779 frame2->Show(true);
780 }
781
782 void MyFrame::OnStyleChange(wxCommandEvent& WXUNUSED(event) )
783 {
784 // recreate the wxDataViewCtrl:
785 CreateDataViewControls();
786 }
787
788 void MyFrame::OnColumnSetting(wxCommandEvent& event)
789 {
790 wxArrayInt columns;
791 int flag = 0;
792 bool header = false, minwidth = false;
793 wxString msg;
794
795 switch (event.GetId())
796 {
797 case ID_RESIZEABLE_COLUMNS:
798 flag = wxDATAVIEW_COL_RESIZABLE;
799 columns = GetFlaggedColumns(flag);
800 break;
801 case ID_SORTABLE_COLUMNS:
802 flag = wxDATAVIEW_COL_SORTABLE;
803 columns = GetFlaggedColumns(flag);
804 break;
805 case ID_HIDDEN_COLUMNS:
806 flag = wxDATAVIEW_COL_HIDDEN;
807 columns = GetFlaggedColumns(flag);
808 break;
809
810 case ID_CHOOSE_COLUMN_ALIGNMENT:
811 msg = wxT("Select the columns whose headers' alignment will be modified.");
812 header = true;
813 break;
814 case ID_CHOOSE_CONTENTS_ALIGNMENT:
815 msg = wxT("Select the columns whose contents' alignment will be modified.");
816 header = false;
817 break;
818
819 case ID_SET_MINWIDTH:
820 msg = wxT("Please provide the new minimal width:");
821 minwidth = true;
822 break;
823 case ID_SET_WIDTH:
824 msg = wxT("Please provide the new width:");
825 minwidth = false;
826 break;
827 }
828
829 // get column titles:
830
831 wxArrayString choices;
832 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
833 choices.Add(dataview_left->GetColumn(i)->GetTitle());
834
835 // ask the user
836 wxGetMultipleChoices(
837 columns,
838 wxT("Choose the columns to which apply the change."),
839 wxT("Choose the column"),
840 choices,
841 this);
842
843 switch (event.GetId())
844 {
845 case ID_RESIZEABLE_COLUMNS:
846 case ID_SORTABLE_COLUMNS:
847 case ID_HIDDEN_COLUMNS:
848 SetFlag(columns, flag);
849 break;
850
851 case ID_CHOOSE_COLUMN_ALIGNMENT:
852 case ID_CHOOSE_CONTENTS_ALIGNMENT:
853 SetAlignment(columns, header, ChooseAlign(msg, header));
854 break;
855
856 case ID_SET_MINWIDTH:
857 case ID_SET_WIDTH:
858 {
859 int def = minwidth ? wxDVC_DEFAULT_MINWIDTH : wxDVC_DEFAULT_WIDTH;
860
861 msg << wxT("\nNOTE: all non-selected columns will be reset to a width of ")
862 << def << wxT(" pixels.");
863
864 long ret =
865 wxGetNumberFromUser(msg, wxT("New value:"), wxT("Modify width"),
866 def, 0, 300, this);
867
868 if (ret != -1)
869 SetWidth(columns, minwidth, ret);
870 }
871 break;
872 }
873
874 dataview_left->Refresh();
875 }
876
877 wxAlignment MyFrame::ChooseAlign(const wxString &msg, bool onlyHorizontal)
878 {
879 const wxString choices[] =
880 {
881 wxT("Left"),
882 wxT("Center horizontally"),
883 wxT("Right"),
884 wxT("Top"),
885 wxT("Center vertically"),
886 wxT("Bottom"),
887 wxT("Center")
888 };
889
890 wxAlignment flags[] =
891 {
892 wxALIGN_LEFT,
893 wxALIGN_CENTER_HORIZONTAL,
894 wxALIGN_RIGHT,
895 wxALIGN_TOP,
896 wxALIGN_CENTER_VERTICAL,
897 wxALIGN_BOTTOM,
898 wxALIGN_CENTER
899 };
900
901 int n = WXSIZEOF(choices);
902 if (onlyHorizontal)
903 n = 3; // show only the first three choices
904
905 int choice = wxGetSingleChoiceIndex(
906 msg + wxT("\nNOTE: _all_ non-selected column's alignment will be reset to wxALIGN_LEFT!"),
907 wxT("Alignment"),
908 n, choices,
909 this);
910
911 if (choice == wxNOT_FOUND)
912 return wxALIGN_LEFT;
913
914 return flags[choice];
915 }
916
917 void MyFrame::SetFlag(const wxArrayInt &idx, int toadd)
918 {
919 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
920 {
921 int current = dataview_left->GetColumn(i)->GetFlags();
922
923 if (idx.Index(i) != wxNOT_FOUND)
924 dataview_left->GetColumn(i)->SetFlags(current | toadd);
925 else
926 dataview_left->GetColumn(i)->SetFlags(current & ~toadd);
927 }
928 }
929
930 wxArrayInt MyFrame::GetFlaggedColumns(int flag)
931 {
932 wxArrayInt ret;
933 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
934 if (dataview_left->GetColumn(i)->GetFlags() & flag)
935 ret.Add(i);
936 return ret;
937 }
938
939 void MyFrame::SetAlignment(const wxArrayInt &idx, bool header, wxAlignment align)
940 {
941 // set to DEFAULT_ALIGN all columns except those
942 // contained in 'idx' which are set to 'align'
943
944 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
945 {
946 wxAlignment toset = DEFAULT_ALIGN;
947 if (idx.Index(i) != wxNOT_FOUND)
948 toset = align;
949
950 if (header)
951 dataview_left->GetColumn(i)->SetAlignment(toset);
952 else
953 dataview_left->GetColumn(i)->GetRenderer()->SetAlignment(toset);
954 }
955 }
956
957 void MyFrame::SetWidth(const wxArrayInt &idx, bool minwidth, int width)
958 {
959 // set to wxDVC_DEFAULT_WIDTH wide all columns except those
960 // contained in 'idx' which are set to 'width'
961
962 for (size_t i=0; i<dataview_left->GetColumnCount(); i++)
963 {
964 int toset = minwidth ? wxDVC_DEFAULT_MINWIDTH : wxDVC_DEFAULT_WIDTH;
965 if (idx.Index(i) != wxNOT_FOUND)
966 toset = width;
967
968 if (minwidth)
969 dataview_left->GetColumn(i)->SetMinWidth(toset);
970 else
971 dataview_left->GetColumn(i)->SetWidth(toset);
972 }
973 }
974
975
976 // -------------------------------------
977 // MySortingFrame
978 // -------------------------------------
979
980 BEGIN_EVENT_TABLE(MySortingFrame,wxFrame)
981 EVT_BUTTON( ID_APPEND_ROW_LEFT, MySortingFrame::OnAppendRowLeft )
982 EVT_BUTTON( ID_PREPEND_ROW_LEFT, MySortingFrame::OnPrependRowLeft )
983 EVT_BUTTON( ID_INSERT_ROW_LEFT, MySortingFrame::OnInsertRowLeft )
984 EVT_BUTTON( ID_DELETE_ROW_LEFT, MySortingFrame::OnDeleteRowLeft )
985 EVT_BUTTON( ID_SELECT, MySortingFrame::OnSelect )
986 EVT_BUTTON( ID_UNSELECT_ALL, MySortingFrame::OnUnselectAll )
987 EVT_DATAVIEW_ROW_SELECTED( ID_SORTED, MySortingFrame::OnSelectedSorted )
988 EVT_DATAVIEW_ROW_SELECTED( ID_UNSORTED, MySortingFrame::OnSelectedUnsorted )
989 EVT_DATAVIEW_ROW_ACTIVATED( ID_UNSORTED, MySortingFrame::OnActivatedUnsorted )
990 EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_SORTED, MySortingFrame::OnHeaderClickSorted )
991 EVT_DATAVIEW_COLUMN_HEADER_CLICK( ID_UNSORTED, MySortingFrame::OnHeaderClickUnsorted )
992 END_EVENT_TABLE()
993
994 MySortingFrame::MySortingFrame(wxFrame *frame, wxChar *title, int x, int y, int w, int h):
995 wxFrame(frame, wxID_ANY, title, wxPoint(x, y), wxSize(w, h))
996 {
997 m_logOld = NULL;
998
999 SetIcon(wxICON(sample));
1000 CreateStatusBar();
1001
1002 wxPanel *main = new wxPanel(this);
1003
1004 // Left wxDataViewCtrl
1005 dataview_left = new wxDataViewCtrl( main, ID_UNSORTED, wxDefaultPosition,
1006 wxDefaultSize, wxDV_MULTIPLE );
1007
1008 m_unsorted_model.reset(new MyUnsortedTextModel);
1009 dataview_left->AssociateModel( m_unsorted_model.get() );
1010
1011 wxDataViewTextRenderer *text_renderer =
1012 new MyTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
1013 wxDataViewColumn *column = new wxDataViewColumn( wxT("editable"), text_renderer, 0 );
1014 dataview_left->AppendColumn( column );
1015 dataview_left->AppendTextColumn( wxT("second"), 1 );
1016 dataview_left->AppendColumn( new wxDataViewColumn( wxBitmap(null_xpm),
1017 new wxDataViewBitmapRenderer, 2, 25 ) );
1018 dataview_left->AppendColumn( new wxDataViewColumn( wxT("icon"),
1019 new wxDataViewBitmapRenderer, 3, 25 ) );
1020
1021 // Right wxDataViewCtrl using the sorting model
1022 dataview_right = new wxDataViewCtrl( main, ID_SORTED );
1023
1024 m_sorted_model.reset(new wxDataViewSortedListModel( m_unsorted_model.get() ));
1025 dataview_right->AssociateModel( m_sorted_model.get() );
1026
1027 text_renderer = new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE );
1028 column = new wxDataViewColumn( wxT("editable"), text_renderer, 0, -1,
1029 wxALIGN_CENTER,
1030 wxDATAVIEW_COL_SORTABLE|wxDATAVIEW_COL_RESIZABLE );
1031 dataview_right->AppendColumn( column );
1032
1033 dataview_right->AppendTextColumn( wxT("second"), 1 );
1034
1035 MySpinCtrlInPlaceRenderer *sr = new MySpinCtrlInPlaceRenderer;
1036 column = new wxDataViewColumn( wxT("spin"), sr, 4, -1, wxALIGN_CENTER );
1037 dataview_right->AppendColumn( column );
1038
1039 // layout dataview controls.
1040
1041 wxBoxSizer *top_sizer = new wxBoxSizer( wxHORIZONTAL );
1042 top_sizer->Add( dataview_left, 1, wxGROW );
1043 top_sizer->Add(10,10);
1044 top_sizer->Add( dataview_right, 1, wxGROW );
1045
1046 wxBoxSizer *button_sizer = new wxBoxSizer( wxHORIZONTAL );
1047 button_sizer->Add( 10, 10, 1 );
1048 wxFlexGridSizer *left_sizer = new wxFlexGridSizer( 2 );
1049 left_sizer->Add( new wxButton( main, ID_APPEND_ROW_LEFT, wxT("Append") ), 0, wxALL, 5 );
1050 left_sizer->Add( new wxButton( main, ID_PREPEND_ROW_LEFT, wxT("Prepend") ), 0, wxALL, 5 );
1051 left_sizer->Add( new wxButton( main, ID_INSERT_ROW_LEFT, wxT("Insert") ), 0, wxALL, 5 );
1052 left_sizer->Add( new wxButton( main, ID_DELETE_ROW_LEFT, wxT("Delete second") ), 0, wxALL, 5 );
1053 left_sizer->Add( new wxButton( main, ID_EDIT_ROW_LEFT, wxT("Edit") ), 0, wxALL, 5 );
1054 left_sizer->Add( 5,5 );
1055 left_sizer->Add( new wxButton( main, ID_SELECT, wxT("Select third") ), 0, wxALL, 5 );
1056 left_sizer->Add( new wxButton( main, ID_UNSELECT_ALL, wxT("Unselect all") ), 0, wxALL, 5 );
1057 button_sizer->Add( left_sizer );
1058 button_sizer->Add( 10, 10, 2 );
1059 wxFlexGridSizer *right_sizer = new wxFlexGridSizer( 2 );
1060 right_sizer->Add( new wxButton( main, ID_APPEND_ROW_RIGHT, wxT("Append") ), 0, wxALL, 5 );
1061 right_sizer->Add( new wxButton( main, ID_PREPEND_ROW_RIGHT, wxT("Prepend") ), 0, wxALL, 5 );
1062 right_sizer->Add( new wxButton( main, ID_INSERT_ROW_RIGHT, wxT("Insert") ), 0, wxALL, 5 );
1063 right_sizer->Add( new wxButton( main, ID_DELETE_ROW_RIGHT, wxT("Delete second") ), 0, wxALL, 5 );
1064 right_sizer->Add( new wxButton( main, ID_EDIT_ROW_RIGHT, wxT("Edit") ), 0, wxALL, 5 );
1065 button_sizer->Add( right_sizer );
1066 button_sizer->Add( 10, 10, 1 );
1067
1068 wxBoxSizer *main_sizer = new wxBoxSizer( wxVERTICAL );
1069 main_sizer->Add( top_sizer, 1, wxGROW );
1070 main_sizer->Add( button_sizer, 0, wxGROW );
1071
1072 m_logWindow = new wxTextCtrl(main, wxID_ANY, wxEmptyString,
1073 wxDefaultPosition, wxDefaultSize,
1074 wxTE_MULTILINE | wxSUNKEN_BORDER);
1075 main_sizer->Add( 20,20 );
1076 main_sizer->Add( m_logWindow, 1, wxGROW );
1077
1078 m_logOld = wxLog::SetActiveTarget(new wxLogTextCtrl(m_logWindow));
1079
1080 main->SetSizer( main_sizer );
1081 }
1082
1083 MySortingFrame::~MySortingFrame()
1084 {
1085 delete wxLog::SetActiveTarget(m_logOld);
1086 }
1087
1088 void MySortingFrame::OnSelectedUnsorted(wxDataViewEvent &event)
1089 {
1090 int row = event.GetRow();
1091 wxLogMessage( wxT("OnSelected from unsorted list, selected %d"), row );
1092 if (row >= 0)
1093 wxLogMessage( wxT("wxDataViewCtrl::IsSelected( %d ): %d (as int)"),
1094 row, (int) dataview_right->IsSelected( row ) );
1095 }
1096
1097 void MySortingFrame::OnSelectedSorted(wxDataViewEvent &event)
1098 {
1099 wxLogMessage( wxT("OnSelected from sorted list, selected %d"), (int) event.GetRow() );
1100 }
1101
1102 void MySortingFrame::OnActivatedUnsorted(wxDataViewEvent &event)
1103 {
1104 wxLogMessage( wxT("OnActivated from unsorted list, activated %d"), (int) event.GetRow() );
1105 }
1106
1107 void MySortingFrame::OnHeaderClickSorted(wxDataViewEvent &event)
1108 {
1109 wxDataViewColumn *col = event.GetDataViewColumn();
1110 wxLogMessage( wxT("OnHeaderClick from sorted list, column %s"), col->GetTitle().c_str() );
1111
1112 if (col->GetTitle() == wxT("editable"))
1113 {
1114 // this is the sorting column
1115 if (col->IsSortOrderAscending())
1116 {
1117 col->SetSortOrder( false );
1118 m_sorted_model->SetAscending( false );
1119 m_sorted_model->Resort();
1120 }
1121 else
1122 {
1123 col->SetSortOrder( true );
1124 m_sorted_model->SetAscending( true );
1125 m_sorted_model->Resort();
1126 }
1127 }
1128 }
1129
1130 void MySortingFrame::OnHeaderClickUnsorted(wxDataViewEvent &event)
1131 {
1132 wxLogMessage( wxT("OnHeaderClick from unsorted list, column %s"),
1133 event.GetDataViewColumn()->GetTitle().c_str() );
1134 }
1135
1136 void MySortingFrame::OnQuit(wxCommandEvent& WXUNUSED(event) )
1137 {
1138 Close(true);
1139 }
1140
1141 void MySortingFrame::OnAbout(wxCommandEvent& WXUNUSED(event) )
1142 {
1143 wxMessageDialog dialog(this, _T("This demonstrates the dataview control sorting"),
1144 _T("About DataView"), wxOK);
1145
1146 dialog.ShowModal();
1147 }
1148
1149 void MySortingFrame::OnSelect(wxCommandEvent& WXUNUSED(event))
1150 {
1151 dataview_left->SetSelection( 2 );
1152 }
1153
1154 void MySortingFrame::OnUnselectAll(wxCommandEvent& WXUNUSED(event))
1155 {
1156 dataview_left->ClearSelection();
1157 }
1158
1159 void MySortingFrame::OnAppendRowLeft(wxCommandEvent& WXUNUSED(event))
1160 {
1161 wxTextEntryDialog dialog( this, wxT("Enter text to append") );
1162 if (dialog.ShowModal() == wxID_OK)
1163 {
1164 wxString value = dialog.GetValue();
1165 if (!value.empty())
1166 m_unsorted_model->AppendRow( value );
1167 }
1168 }
1169
1170 void MySortingFrame::OnPrependRowLeft(wxCommandEvent& WXUNUSED(event))
1171 {
1172 wxTextEntryDialog dialog( this, wxT("Enter text to prepend") );
1173 if (dialog.ShowModal() == wxID_OK)
1174 {
1175 wxString value = dialog.GetValue();
1176 if (!value.empty())
1177 m_unsorted_model->PrependRow( value );
1178 }
1179 }
1180
1181 void MySortingFrame::OnInsertRowLeft(wxCommandEvent& WXUNUSED(event))
1182 {
1183 wxTextEntryDialog dialog( this, wxT("Enter text to insert before second") );
1184 if (dialog.ShowModal() == wxID_OK)
1185 {
1186 wxString value = dialog.GetValue();
1187 if (!value.empty())
1188 m_unsorted_model->InsertRowAt1( value );
1189 }
1190 }
1191
1192 void MySortingFrame::OnDeleteRowLeft(wxCommandEvent& WXUNUSED(event))
1193 {
1194 m_unsorted_model->DeleteRow( 1 );
1195 }
1196
1197 void MySortingFrame::OnEditRowLeft(wxCommandEvent& WXUNUSED(event))
1198 {
1199 }
1200
1201 void MySortingFrame::OnAppendRowRight(wxCommandEvent& WXUNUSED(event))
1202 {
1203 }
1204
1205 void MySortingFrame::OnPrependRowRight(wxCommandEvent& WXUNUSED(event))
1206 {
1207 }
1208
1209 void MySortingFrame::OnInsertRowRight(wxCommandEvent& WXUNUSED(event))
1210 {
1211 }
1212
1213 void MySortingFrame::OnDeleteRowRight(wxCommandEvent& WXUNUSED(event))
1214 {
1215 }
1216
1217 void MySortingFrame::OnEditRowRight(wxCommandEvent& WXUNUSED(event))
1218 {
1219 }
1220