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