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