1 ///////////////////////////////////////////////////////////////////////////// 
   3 // Purpose:     wxDataViewCtrl wxWidgets sample 
   4 // Author:      Robert Roebling 
   5 // Modified by: Francesco Montorsi, Bo Yang 
   8 // Copyright:   (c) Robert Roebling 
   9 // Licence:     wxWindows license 
  10 ///////////////////////////////////////////////////////////////////////////// 
  12 // For compilers that support precompilation, includes "wx/wx.h". 
  13 #include "wx/wxprec.h" 
  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" 
  33     #include "../sample.xpm" 
  39 static const char *small1_xpm
[] = { 
  40 /* columns rows colors chars-per-pixel */ 
  68 #define DEFAULT_ALIGN                   wxALIGN_LEFT 
  69 #define DATAVIEW_DEFAULT_STYLE          (wxDV_MULTIPLE|wxDV_HORIZ_RULES|wxDV_VERT_RULES) 
  71 // ------------------------------------- 
  73 // ------------------------------------- 
  76 Implement this data model 
  78 ------------------------------------------------------------- 
  81         3:  You are not alone   Michael Jackson      1995 
  82         4:  Take a bow          Madonna              1994 
  84         6:  Ninth Symphony      Ludwig v. Beethoven  1824 
  85         7:  German Requiem      Johannes Brahms      1868 
  90 class MyMusicModelNode
; 
  91 WX_DEFINE_ARRAY_PTR( MyMusicModelNode
*, MyMusicModelNodes 
); 
  93 class MyMusicModelNode
 
  96     MyMusicModelNode( MyMusicModelNode
* parent
, 
  97                       const wxString 
&title
, const wxString 
&artist
, int year 
) 
 103         m_isContainer 
= false; 
 106     MyMusicModelNode( MyMusicModelNode
* parent
, 
 107                       const wxString 
&branch 
) 
 112         m_isContainer 
= true; 
 117         size_t count 
= m_children
.GetCount(); 
 119         for (i 
= 0; i 
< count
; i
++) 
 121             MyMusicModelNode 
*child 
= m_children
[i
]; 
 126     bool IsContainer()                                    { return m_isContainer
; } 
 128     MyMusicModelNode
* GetParent()                         { return m_parent
; } 
 129     MyMusicModelNodes 
&GetChildren()                      { return m_children
; } 
 130     MyMusicModelNode
* GetNthChild( unsigned int n 
)       { return m_children
.Item( n 
); } 
 131     void Insert( MyMusicModelNode
* child
, unsigned int n
) { m_children
.Insert( child
, n
); } 
 132     void Append( MyMusicModelNode
* child 
)                { m_children
.Add( child 
); } 
 133     unsigned int GetChildCount()                          { return m_children
.GetCount(); } 
 141     MyMusicModelNode   
*m_parent
; 
 142     MyMusicModelNodes   m_children
; 
 147 class MyMusicModel
: public wxDataViewModel
 
 155         m_root 
= new MyMusicModelNode( NULL
, wxT("My Music" )); 
 156         m_pop 
= new MyMusicModelNode( m_root
, wxT("Pop music") ); 
 157         m_root
->Append( m_pop 
); 
 158         m_pop
->Append( new MyMusicModelNode( m_pop
, 
 159             wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) ); 
 160         m_pop
->Append( new MyMusicModelNode( m_pop
, 
 161             wxT("Take a bow"), wxT("Madonna"), 1994 ) ); 
 162         m_classical 
= new MyMusicModelNode( m_root
, wxT("Classical music") ); 
 163         m_root
->Append( m_classical 
); 
 164         m_ninth 
= new MyMusicModelNode( m_classical
, 
 165             wxT("Ninth symphony"), wxT("Ludwig van Beethoven"), 1824 ); 
 166         m_classical
->Append( m_ninth 
); 
 167         m_classical
->Append( new MyMusicModelNode( m_classical
, 
 168             wxT("German Requiem"), wxT("Johannes Brahms"), 1868 ) ); 
 169         m_classicalMusicIsKnownToControl 
= false; 
 177     // helper method for wxLog 
 179     wxString 
GetTitle( const wxDataViewItem 
&item 
) const 
 181         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 183             return wxEmptyString
; 
 185         return node
->m_title
; 
 188     int GetYear( const wxDataViewItem 
&item 
) const 
 190         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 197     // helper methods to change the model 
 199     void AddToClassical( const wxString 
&title
, const wxString 
&artist
, int year 
) 
 202         MyMusicModelNode 
*child_node 
= 
 203             new MyMusicModelNode( m_classical
, title
, artist
, year 
); 
 205         m_classical
->Append( child_node 
); 
 207         if (m_classicalMusicIsKnownToControl
) 
 210             wxDataViewItem 
child( (void*) child_node 
); 
 211             wxDataViewItem 
parent( (void*) m_classical 
); 
 212             ItemAdded( parent
, child 
); 
 216     void Delete( const wxDataViewItem 
&item 
) 
 218         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 219         wxDataViewItem 
parent( node
->GetParent() ); 
 221         node
->GetParent()->GetChildren().Remove( node 
); 
 225         ItemDeleted( parent
, item 
); 
 228     // override sorting to always sort branches ascendingly 
 230     int Compare( const wxDataViewItem 
&item1
, const wxDataViewItem 
&item2
, 
 231                  unsigned int column
, bool ascending 
) 
 233         if (IsContainer(item1
) && IsContainer(item2
)) 
 235             wxVariant value1
,value2
; 
 236             GetValue( value1
, item1
, 0 ); 
 237             GetValue( value2
, item2
, 0 ); 
 239             wxString str1 
= value1
.GetString(); 
 240             wxString str2 
= value2
.GetString(); 
 241             int res 
= str1
.Cmp( str2 
); 
 244             // items must be different 
 245             wxUIntPtr litem1 
= (wxUIntPtr
) item1
.GetID(); 
 246             wxUIntPtr litem2 
= (wxUIntPtr
) item2
.GetID(); 
 248             return litem1
-litem2
; 
 251         return wxDataViewModel::Compare( item1
, item2
, column
, ascending 
); 
 254     // implementation of base class virtuals to define model 
 256     virtual unsigned int GetColumnCount() const 
 261     virtual wxString 
GetColumnType( unsigned int col 
) const 
 266         return wxT("string"); 
 269     virtual void GetValue( wxVariant 
&variant
, 
 270                            const wxDataViewItem 
&item
, unsigned int col 
) const 
 272         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 275             case 0: variant 
= node
->m_title
; break; 
 276             case 1: variant 
= node
->m_artist
; break; 
 277             case 2: variant 
= (long) node
->m_year
; break; 
 279                // wxMac doesn't conceal the popularity progress renderer, return 0 for containers 
 280                if (IsContainer(item
)) 
 283                   variant 
= (long) 80;  // all music is very 80% popular 
 286                // Make size of red square depend on year 
 287                if (GetYear(item
) < 1900) 
 294                 wxLogError( wxT("MyMusicModel::GetValue: wrong column %d"), col 
); 
 296                 // provoke a crash when mouse button down 
 297                 wxMouseState state 
= wxGetMouseState(); 
 298                 if (state
.ShiftDown()) 
 307     virtual bool SetValue( const wxVariant 
&variant
, 
 308                            const wxDataViewItem 
&item
, unsigned int col 
) 
 310         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 313             case 0: node
->m_title 
= variant
.GetString(); return true; 
 314             case 1: node
->m_artist  
= variant
.GetString(); return true; 
 315             case 2: node
->m_year  
= variant
.GetLong(); return true; 
 316             default: wxLogError( wxT("MyMusicModel::SetValue: wrong column") ); 
 321     virtual wxDataViewItem 
GetParent( const wxDataViewItem 
&item 
) const 
 323         // the invisble root node has no parent 
 325             return wxDataViewItem(0); 
 327         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 329         // "MyMusic" also has no parent 
 331             return wxDataViewItem(0); 
 333         return wxDataViewItem( (void*) node
->GetParent() ); 
 336     virtual bool IsContainer( const wxDataViewItem 
&item 
) const 
 338         // the invisble root node can have children (in 
 339         // our model always "MyMusic") 
 343         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 344         return node
->IsContainer(); 
 347     virtual unsigned int GetChildren( const wxDataViewItem 
&parent
, wxDataViewItemArray 
&array 
) const 
 349         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) parent
.GetID(); 
 352             array
.Add( wxDataViewItem( (void*) m_root 
) ); 
 356         if (node 
== m_classical
) 
 358             MyMusicModel 
*model 
= (MyMusicModel
*)(const MyMusicModel
*) this; 
 359             model
->m_classicalMusicIsKnownToControl 
= true; 
 362         if (node
->GetChildCount() == 0) 
 367         unsigned int count 
= node
->GetChildren().GetCount(); 
 369         for (pos 
= 0; pos 
< count
; pos
++) 
 371             MyMusicModelNode 
*child 
= node
->GetChildren().Item( pos 
); 
 372             array
.Add( wxDataViewItem( (void*) child 
) ); 
 379     virtual bool IsDraggable( const wxDataViewItem 
&item 
) 
 382             return (!IsContainer(item
)); 
 385     virtual size_t GetDragDataSize( const wxDataViewItem 
&item
, const wxDataFormat 
&WXUNUSED(format
) ) 
 387             wxPrintf( "GetDragDataSize\n" ); 
 389             MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 391             data 
+= node
->m_title
; data 
+= wxT(" "); 
 392             data 
+= node
->m_artist
; 
 393             return strlen( data
.utf8_str() ) + 1; 
 395     virtual bool GetDragData( const wxDataViewItem 
&item
, const wxDataFormat 
&WXUNUSED(format
), 
 396                               void* dest
, size_t WXUNUSED(size
) ) 
 398             wxPrintf( "GetDragData\n" ); 
 400             MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 402             data 
+= node
->m_title
; data 
+= wxT(" "); 
 403             data 
+= node
->m_artist
; 
 404             wxCharBuffer 
buffer( data
.utf8_str() ); 
 405             memcpy( dest
, buffer
, strlen(buffer
)+1 ); 
 409     wxDataViewItem 
GetNinthItem() 
 411        return wxDataViewItem( m_ninth 
); 
 415     MyMusicModelNode
*   m_root
; 
 416     MyMusicModelNode
*   m_pop
; 
 417     MyMusicModelNode
*   m_classical
; 
 418     MyMusicModelNode
*   m_ninth
; 
 419     bool                m_classicalMusicIsKnownToControl
; 
 423 static int my_sort_reverse( int *v1
, int *v2 
) 
 428 static int my_sort( int *v1
, int *v2 
) 
 433 class MyListModel
: public wxDataViewVirtualListModel
 
 438         wxDataViewVirtualListModel( 1000 + 100 ) 
 440         wxDataViewVirtualListModel( 100000 + 100 ) 
 444         m_virtualItems 
= 1000; 
 446         m_virtualItems 
= 100000; 
 450         for (i 
= 0; i 
< 100; i
++) 
 453             str
.Printf( wxT("row number %d"), i 
); 
 457         m_icon 
= wxIcon( null_xpm 
); 
 460     // helper methods to change the model 
 462     void Prepend( const wxString 
&text 
) 
 464         m_array
.Insert( text
, 0 ); 
 468     void DeleteItem( const wxDataViewItem 
&item 
) 
 470         unsigned int row 
= GetRow( item 
); 
 471         if (row 
>= m_array
.GetCount()) 
 474         m_array
.RemoveAt( row 
); 
 478     void DeleteItems( const wxDataViewItemArray 
&items 
) 
 482         for (i 
= 0; i 
< items
.GetCount(); i
++) 
 484             unsigned int row 
= GetRow( items
[i
] ); 
 485             if (row 
< m_array
.GetCount()) 
 489         // Sort in descending order so that the last 
 490         // row will be deleted first. Otherwise the 
 491         // remaining indeces would all be wrong. 
 492         rows
.Sort( my_sort_reverse 
); 
 493         for (i 
= 0; i 
< rows
.GetCount(); i
++) 
 494             m_array
.RemoveAt( rows
[i
] ); 
 496         // This is just to test if wxDataViewCtrl can 
 497         // cope with removing rows not sorted in 
 499         rows
.Sort( my_sort 
); 
 505         m_virtualItems 
+= 1000; 
 506         Reset( m_array
.GetCount() + m_virtualItems 
); 
 509     // implementation of base class virtuals to define model 
 511     virtual unsigned int GetColumnCount() const 
 516     virtual wxString 
GetColumnType( unsigned int col 
) const 
 519             return wxT("wxDataViewIconText"); 
 521         return wxT("string"); 
 524     virtual unsigned int GetRowCount() 
 526         return m_array
.GetCount(); 
 529     virtual void GetValue( wxVariant 
&variant
, 
 530                            unsigned int row
, unsigned int col 
) const 
 534             if (row 
>= m_array
.GetCount()) 
 537                 str
.Printf(wxT("row %d"), row 
- m_array
.GetCount() ); 
 542                 variant 
= m_array
[ row 
]; 
 547             wxDataViewIconText 
data( wxT("test"), m_icon 
); 
 552             if (row 
>= m_array
.GetCount()) 
 553                 variant 
= wxT("plain"); 
 555                 variant 
= wxT("blue"); 
 559     virtual bool GetAttr( unsigned int row
, unsigned int col
, wxDataViewItemAttr 
&attr 
) 
 564         if (row 
< m_array
.GetCount()) 
 566             attr
.SetColour( *wxBLUE 
); 
 567             attr
.SetItalic( true ); 
 573     virtual bool SetValue( const wxVariant 
&variant
, 
 574                            unsigned int row
, unsigned int col 
) 
 578             if (row 
>= m_array
.GetCount()) 
 581             m_array
[row
] = variant
.GetString(); 
 588     wxArrayString    m_array
; 
 593 // ------------------------------------- 
 595 // ------------------------------------- 
 597 class MyCustomRenderer
: public wxDataViewCustomRenderer
 
 600     MyCustomRenderer( wxDataViewCellMode mode
, int alignment 
) : 
 601        wxDataViewCustomRenderer( wxString("long"), mode
, alignment 
) 
 604     virtual bool Render( wxRect rect
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 606         dc
->SetBrush( *wxRED_BRUSH 
); 
 607         dc
->SetPen( *wxTRANSPARENT_PEN 
); 
 608         dc
->DrawRectangle( rect 
); 
 613     virtual bool Activate( wxRect 
WXUNUSED(cell
), 
 614                            wxDataViewModel 
*WXUNUSED(model
), const wxDataViewItem 
&WXUNUSED(item
), unsigned int WXUNUSED(col
) ) 
 616         wxLogMessage( wxT("MyCustomRenderer Activate()") ); 
 620     virtual bool LeftClick( wxPoint cursor
, wxRect 
WXUNUSED(cell
), 
 621                            wxDataViewModel 
*WXUNUSED(model
), const wxDataViewItem 
&WXUNUSED(item
), unsigned int WXUNUSED(col
) ) 
 623         wxLogMessage( wxT("MyCustomRenderer LeftClick( %d, %d )"), cursor
.x
, cursor
.y 
); 
 627     virtual wxSize 
GetSize() const 
 629         return wxSize(60,m_height
); 
 632     virtual bool SetValue( const wxVariant 
&value 
) 
 638     virtual bool GetValue( wxVariant 
&WXUNUSED(value
) ) const { return true; } 
 644 // ------------------------------------- 
 646 // ------------------------------------- 
 648 class MyApp
: public wxApp
 
 655 // ------------------------------------- 
 657 // ------------------------------------- 
 659 class MyFrame 
: public wxFrame
 
 662     MyFrame(wxFrame 
*frame
, const wxString 
&title
, int x
, int y
, int w
, int h
); 
 666     void OnQuit(wxCommandEvent
& event
); 
 667     void OnAbout(wxCommandEvent
& event
); 
 669     void OnAddMozart(wxCommandEvent
& event
); 
 670     void OnDeleteMusic(wxCommandEvent
& event
); 
 671     void OnDeleteYear(wxCommandEvent
& event
); 
 672     void OnSelectNinth(wxCommandEvent
& event
); 
 674     void OnPrependList(wxCommandEvent
& event
); 
 675     void OnDeleteList(wxCommandEvent
& event
); 
 677     void OnValueChanged( wxDataViewEvent 
&event 
); 
 679     void OnActivated( wxDataViewEvent 
&event 
); 
 680     void OnExpanding( wxDataViewEvent 
&event 
); 
 681     void OnExpanded( wxDataViewEvent 
&event 
); 
 682     void OnCollapsing( wxDataViewEvent 
&event 
); 
 683     void OnCollapsed( wxDataViewEvent 
&event 
); 
 684     void OnSelectionChanged( wxDataViewEvent 
&event 
); 
 686     void OnEditingStarted( wxDataViewEvent 
&event 
); 
 687     void OnEditingDone( wxDataViewEvent 
&event 
); 
 689     void OnHeaderClick( wxDataViewEvent 
&event 
); 
 690     void OnHeaderRightClick( wxDataViewEvent 
&event 
); 
 691     void OnSorted( wxDataViewEvent 
&event 
); 
 693     void OnContextMenu( wxDataViewEvent 
&event 
); 
 695     void OnRightClick( wxMouseEvent 
&event 
); 
 696     void OnGoto( wxCommandEvent 
&event
); 
 697     void OnAddMany( wxCommandEvent 
&event
); 
 700     wxDataViewCtrl
* m_musicCtrl
; 
 701     wxObjectDataPtr
<MyMusicModel
> m_music_model
; 
 703     wxDataViewCtrl
* m_listCtrl
; 
 704     wxObjectDataPtr
<MyListModel
> m_list_model
; 
 706     wxDataViewColumn 
* m_col
; 
 712     DECLARE_EVENT_TABLE() 
 715 // ------------------------------------- 
 717 // ------------------------------------- 
 721 bool MyApp::OnInit(void) 
 723     if ( !wxApp::OnInit() ) 
 726     // build the first frame 
 728         new MyFrame(NULL
, wxT("wxDataViewCtrl feature test"), 40, 40, 1000, 540); 
 741 // ------------------------------------- 
 743 // ------------------------------------- 
 748     ID_ABOUT 
= wxID_ABOUT
, 
 754     ID_DELETE_MUSIC     
= 101, 
 755     ID_DELETE_YEAR      
= 102, 
 756     ID_SELECT_NINTH     
= 103, 
 758     ID_PREPEND_LIST     
= 200, 
 759     ID_DELETE_LIST      
= 201, 
 764 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
) 
 765     EVT_MENU( ID_ABOUT
, MyFrame::OnAbout 
) 
 766     EVT_MENU( ID_EXIT
, MyFrame::OnQuit 
) 
 767     EVT_BUTTON( ID_ADD_MOZART
, MyFrame::OnAddMozart 
) 
 768     EVT_BUTTON( ID_DELETE_MUSIC
, MyFrame::OnDeleteMusic 
) 
 769     EVT_BUTTON( ID_DELETE_YEAR
, MyFrame::OnDeleteYear 
) 
 770     EVT_BUTTON( ID_SELECT_NINTH
, MyFrame::OnSelectNinth 
) 
 771     EVT_BUTTON( ID_PREPEND_LIST
, MyFrame::OnPrependList 
) 
 772     EVT_BUTTON( ID_DELETE_LIST
, MyFrame::OnDeleteList 
) 
 773     EVT_BUTTON( ID_GOTO
, MyFrame::OnGoto
) 
 774     EVT_BUTTON( ID_ADD_MANY
, MyFrame::OnAddMany
) 
 776     EVT_DATAVIEW_ITEM_VALUE_CHANGED( ID_MUSIC_CTRL
, MyFrame::OnValueChanged 
) 
 778     EVT_DATAVIEW_ITEM_ACTIVATED(ID_MUSIC_CTRL
, MyFrame::OnActivated 
) 
 779     EVT_DATAVIEW_ITEM_EXPANDING(ID_MUSIC_CTRL
, MyFrame::OnExpanding
) 
 780     EVT_DATAVIEW_ITEM_EXPANDED(ID_MUSIC_CTRL
, MyFrame::OnExpanded
) 
 781     EVT_DATAVIEW_ITEM_COLLAPSING(ID_MUSIC_CTRL
, MyFrame::OnCollapsing
) 
 782     EVT_DATAVIEW_ITEM_COLLAPSED(ID_MUSIC_CTRL
, MyFrame::OnCollapsed
) 
 783     EVT_DATAVIEW_SELECTION_CHANGED(ID_MUSIC_CTRL
, MyFrame::OnSelectionChanged
) 
 785     EVT_DATAVIEW_ITEM_EDITING_STARTED(ID_MUSIC_CTRL
, MyFrame::OnEditingStarted
) 
 786     EVT_DATAVIEW_ITEM_EDITING_DONE(ID_MUSIC_CTRL
, MyFrame::OnEditingDone
) 
 788     EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_MUSIC_CTRL
, MyFrame::OnHeaderClick
) 
 789     EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICKED(ID_MUSIC_CTRL
, MyFrame::OnHeaderRightClick
) 
 790     EVT_DATAVIEW_COLUMN_SORTED(ID_MUSIC_CTRL
, MyFrame::OnSorted
) 
 792     EVT_DATAVIEW_ITEM_CONTEXT_MENU(ID_MUSIC_CTRL
, MyFrame::OnContextMenu
) 
 794     EVT_RIGHT_UP(MyFrame::OnRightClick
) 
 797 MyFrame::MyFrame(wxFrame 
*frame
, const wxString 
&title
, int x
, int y
, int w
, int h
): 
 798   wxFrame(frame
, wxID_ANY
, title
, wxPoint(x
, y
), wxSize(w
, h
)) 
 803     SetIcon(wxICON(sample
)); 
 807     wxMenu 
*file_menu 
= new wxMenu
; 
 808     file_menu
->Append(ID_ABOUT
, wxT("&About")); 
 809     file_menu
->AppendSeparator(); 
 810     file_menu
->Append(ID_EXIT
, wxT("E&xit")); 
 812     wxMenuBar 
*menu_bar 
= new wxMenuBar
; 
 813     menu_bar
->Append(file_menu
, wxT("&File")); 
 815     SetMenuBar(menu_bar
); 
 818     wxBoxSizer 
*main_sizer 
= new wxBoxSizer( wxVERTICAL 
); 
 820     wxBoxSizer 
*data_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 824     m_musicCtrl 
= new wxDataViewCtrl( this, ID_MUSIC_CTRL
, wxDefaultPosition
, 
 825                                     wxSize(400,200), wxDV_MULTIPLE
|wxDV_VARIABLE_LINE_HEIGHT 
); 
 827     m_music_model 
= new MyMusicModel
; 
 828     m_musicCtrl
->AssociateModel( m_music_model
.get() ); 
 830     wxDataViewTextRenderer 
*tr 
= new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_INERT 
); 
 831     wxDataViewColumn 
*column0 
= new wxDataViewColumn( wxT("title"), tr
, 0, 200, wxALIGN_LEFT
, 
 832         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_REORDERABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 833     m_musicCtrl
->AppendColumn( column0 
); 
 835     // Call this and sorting is enabled 
 836     // immediatly upon start up. 
 837     column0
->SetSortOrder( true ); 
 840     tr 
= new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE 
); 
 841     wxDataViewColumn 
*column1 
= new wxDataViewColumn( wxT("artist"), tr
, 1, 150, wxALIGN_LEFT
, 
 842         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_REORDERABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 843     m_musicCtrl
->AppendColumn( column1 
); 
 846     wxDataViewSpinRenderer 
*sr 
= new wxDataViewSpinRenderer( 0, 2010, wxDATAVIEW_CELL_EDITABLE
, wxALIGN_RIGHT 
); 
 847     wxDataViewColumn 
*column2 
= new wxDataViewColumn( wxT("year"), sr
, 2, 80, wxALIGN_LEFT
, 
 848         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_REORDERABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 849     m_musicCtrl
->AppendColumn( column2 
); 
 851     m_musicCtrl
->AppendProgressColumn( wxT("popularity"), 3, wxDATAVIEW_CELL_INERT
, 80 ); 
 853     MyCustomRenderer 
*cr 
= new MyCustomRenderer( wxDATAVIEW_CELL_ACTIVATABLE
, wxALIGN_RIGHT 
); 
 854     wxDataViewColumn 
*column3 
= new wxDataViewColumn( wxT("custom"), cr
, 4, -1, wxALIGN_LEFT
, 
 855         wxDATAVIEW_COL_RESIZABLE 
); 
 856     m_musicCtrl
->AppendColumn( column3 
); 
 859     data_sizer
->Add( m_musicCtrl
, 3, wxGROW 
); 
 863     m_listCtrl 
= new wxDataViewCtrl( this, wxID_ANY
, wxDefaultPosition
, 
 864                                      wxSize(400,200), wxDV_MULTIPLE 
| wxDV_ROW_LINES
); 
 866     m_list_model 
= new MyListModel
; 
 867     m_listCtrl
->AssociateModel( m_list_model
.get() ); 
 870     m_listCtrl
->AppendTextColumn    (wxT("editable string"), 0, wxDATAVIEW_CELL_EDITABLE
, 120 ); 
 871     m_listCtrl
->AppendIconTextColumn(wxIcon(small1_xpm
), 1, wxDATAVIEW_CELL_INERT 
)->SetTitle( wxT("icon") ); 
 873     m_listCtrl
->AppendTextColumn    (wxT("editable string"), 0, wxDATAVIEW_CELL_EDITABLE 
); 
 874     m_listCtrl
->AppendIconTextColumn(wxT("icon"),            1, wxDATAVIEW_CELL_INERT 
); 
 877     wxDataViewTextRendererAttr 
*ra 
= new wxDataViewTextRendererAttr
; 
 878     wxDataViewColumn 
*column4 
= new wxDataViewColumn(wxT("attributes"), ra
, 2 ); 
 879     m_listCtrl
->AppendColumn( column4 
); 
 881     data_sizer
->Add( m_listCtrl
, 2, wxGROW 
); 
 883     main_sizer
->Add( data_sizer
, 2, wxGROW 
); 
 885     wxBoxSizer 
*button_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 887     button_sizer
->Add( new wxButton( this, ID_ADD_MOZART
,  _("Add Mozart")),             0, wxALL
, 10 ); 
 888     button_sizer
->Add( new wxButton( this, ID_DELETE_MUSIC
,_("Delete selected")),        0, wxALL
, 10 ); 
 889     button_sizer
->Add( new wxButton( this, ID_DELETE_YEAR
, _("Delete \"Year\" column")), 0, wxALL
, 10 ); 
 890     button_sizer
->Add( new wxButton( this, ID_SELECT_NINTH
, _("Select Ninth")), 0, wxALL
, 10 ); 
 891     button_sizer
->Add( 10, 10, 1 ); 
 892     wxFlexGridSizer 
*grid_sizer 
= new wxFlexGridSizer( 2, 2 ); 
 893     grid_sizer
->Add( new wxButton( this, ID_PREPEND_LIST
,_("Prepend")),         0, wxALL
, 2 ); 
 894     grid_sizer
->Add( new wxButton( this, ID_DELETE_LIST
, _("Delete selected")), 0, wxALL
, 2 ); 
 895     grid_sizer
->Add( new wxButton( this, ID_GOTO
,        _("Goto 50")),         0, wxALL
, 2 ); 
 896     grid_sizer
->Add( new wxButton( this, ID_ADD_MANY
,    _("Add 1000")),        0, wxALL
, 2 ); 
 897     button_sizer
->Add( grid_sizer
, 0, wxALL
, 10 ); 
 899     main_sizer
->Add( button_sizer
, 0, wxGROW
, 0 ); 
 901     wxBoxSizer 
*bottom_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 903     m_log 
= new wxTextCtrl( this, -1, wxString(), wxDefaultPosition
, wxSize(100,200), wxTE_MULTILINE 
); 
 904     m_logOld 
= wxLog::SetActiveTarget(new wxLogTextCtrl(m_log
)); 
 905     wxLogMessage(_("This is the log window")); 
 907     bottom_sizer
->Add( m_log
, 1, wxGROW 
); 
 910     // wxDataViewTreeStore 
 912     wxDataViewCtrl 
*treectrl 
= new wxDataViewCtrl( this, -1, 
 913         wxDefaultPosition
, wxSize(100,200), wxDV_NO_HEADER 
); 
 915     wxDataViewTreeStore 
*store 
= new wxDataViewTreeStore
; 
 916     wxDataViewItem parent 
= store
->AppendContainer( wxDataViewItem(0),wxT("Root 1"), wxIcon(small1_xpm
) ); 
 917     wxDataViewItem child 
= store
->AppendItem( parent
,wxT("Child 1"), wxIcon(small1_xpm
) ); 
 918     child 
= store
->AppendItem( parent
,wxT("Child 2"), wxIcon(small1_xpm
) ); 
 919     child 
= store
->AppendItem( parent
,wxT("Child 3, very long, long, long, long"), wxIcon(small1_xpm
) ); 
 920     treectrl
->AssociateModel( store 
); 
 923     treectrl
->AppendIconTextColumn( wxT("no label"), 0, wxDATAVIEW_CELL_INERT
, -1, (wxAlignment
) 0, 
 924         wxDATAVIEW_COL_RESIZABLE 
); 
 926     bottom_sizer
->Add( treectrl
, 1 ); 
 928     // wxDataViewTreeCtrl 
 930     wxDataViewTreeCtrl 
*treectrl2 
= new wxDataViewTreeCtrl( this, -1, wxDefaultPosition
, wxSize(100,200) ); 
 932     wxImageList 
*ilist 
= new wxImageList( 16, 16 ); 
 933     ilist
->Add( wxIcon(small1_xpm
) ); 
 934     treectrl2
->SetImageList( ilist 
); 
 936     parent 
= treectrl2
->AppendContainer( wxDataViewItem(0),wxT("Root 1"), 0 ); 
 937     child 
= treectrl2
->AppendItem( parent
,wxT("Child 1"), 0 ); 
 938     child 
= treectrl2
->AppendItem( parent
,wxT("Child 2"), 0 ); 
 939     child 
= treectrl2
->AppendItem( parent
,wxT("Child 3, very long, long, long, long"), 0 ); 
 941     bottom_sizer
->Add( treectrl2
, 1 ); 
 946     main_sizer
->Add( bottom_sizer
, 0, wxGROW 
); 
 948     SetSizer( main_sizer 
); 
 953     delete wxLog::SetActiveTarget(m_logOld
); 
 956 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
) ) 
 961 void MyFrame::OnAddMozart(wxCommandEvent
& WXUNUSED(event
) ) 
 963     m_music_model
->AddToClassical( wxT("Kleine Nachtmusik"), wxT("Wolfgang Mozart"), 1787 ); 
 966 void MyFrame::OnDeleteMusic(wxCommandEvent
& WXUNUSED(event
) ) 
 968     wxDataViewItemArray items
; 
 969     int len 
= m_musicCtrl
->GetSelections( items 
); 
 970     for( int i 
= 0; i 
< len
; i 
++ ) 
 972             m_music_model
->Delete( items
[i
] ); 
 975 void MyFrame::OnDeleteYear( wxCommandEvent
& WXUNUSED(event
) ) 
 977     m_musicCtrl
->DeleteColumn( m_musicCtrl
->GetColumn( 2 ) ); 
 978     FindWindow( ID_DELETE_YEAR 
)->Disable(); 
 981 void MyFrame::OnSelectNinth( wxCommandEvent
& WXUNUSED(event
) ) 
 983     m_musicCtrl
->Select( m_music_model
->GetNinthItem() ); 
 986 void MyFrame::OnPrependList( wxCommandEvent
& WXUNUSED(event
) ) 
 988     m_list_model
->Prepend(wxT("Test")); 
 991 void MyFrame::OnDeleteList( wxCommandEvent
& WXUNUSED(event
) ) 
 993     wxDataViewItemArray items
; 
 994     int len 
= m_listCtrl
->GetSelections( items 
); 
 996         m_list_model
->DeleteItems( items 
); 
1000 #define ENABLE_LOGGING 
1003 void MyFrame::OnValueChanged( wxDataViewEvent 
&event 
) 
1008 #ifdef ENABLE_LOGGING 
1009     wxLogMessage( wxT("EVT_DATAVIEW_ITEM_VALUE_CHANGED, Item Id: %d;  Column: %d"), event
.GetItem().GetID(), event
.GetColumn() ); 
1013 void MyFrame::OnActivated( wxDataViewEvent 
&event 
) 
1018     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1019 #ifdef ENABLE_LOGGING 
1020     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, Item: %s"), title 
); 
1024 void MyFrame::OnSelectionChanged( wxDataViewEvent 
&event 
) 
1029     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1031         title 
= wxT("None"); 
1033 #ifdef ENABLE_LOGGING 
1034     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, First selected Item: %s"), title 
); 
1038 void MyFrame::OnExpanding( wxDataViewEvent 
&event 
) 
1043     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1044 #ifdef ENABLE_LOGGING 
1045     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, Item: %s"), title 
); 
1050 void MyFrame::OnEditingStarted( wxDataViewEvent 
&event 
) 
1055     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1056 #ifdef ENABLE_LOGGING 
1057     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, Item: %s"), title 
); 
1061 void MyFrame::OnEditingDone( wxDataViewEvent 
&event 
) 
1066     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1067 #ifdef ENABLE_LOGGING 
1068     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, Item: %s"), title 
); 
1072 void MyFrame::OnExpanded( wxDataViewEvent 
&event 
) 
1077     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1078 #ifdef ENABLE_LOGGING 
1079     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, Item: %s"), title 
); 
1083 void MyFrame::OnCollapsing( wxDataViewEvent 
&event 
) 
1088     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1089 #ifdef ENABLE_LOGGING 
1090     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, Item: %s"), title 
); 
1094 void MyFrame::OnCollapsed( wxDataViewEvent 
&event 
) 
1099     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1100 #ifdef ENABLE_LOGGING 
1101     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, Item: %s"),title
); 
1105 void MyFrame::OnContextMenu( wxDataViewEvent 
&event 
) 
1110     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1111 #ifdef ENABLE_LOGGING 
1112     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s"),title 
); 
1116     menu
.Append( 1, wxT("entry 1") ); 
1117     menu
.Append( 2, wxT("entry 2") ); 
1118     menu
.Append( 3, wxT("entry 3") ); 
1120     m_musicCtrl
->PopupMenu(&menu
); 
1122 //    wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s Value: %s"),title.GetData(), event.GetValue().GetString()); 
1125 void MyFrame::OnHeaderClick( wxDataViewEvent 
&event 
) 
1130     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1132 #ifdef ENABLE_LOGGING 
1133     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, Column position: %d"), pos 
); 
1137 void MyFrame::OnHeaderRightClick( wxDataViewEvent 
&event 
) 
1142     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1144 #ifdef ENABLE_LOGGING 
1145     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, Column position: %d"), pos 
); 
1149 void MyFrame::OnSorted( wxDataViewEvent 
&event 
) 
1154     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1156 #ifdef ENABLE_LOGGING 
1157     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, Column position: %d"), pos 
); 
1161 void MyFrame::OnRightClick( wxMouseEvent 
&event 
) 
1166 #ifdef ENABLE_LOGGING 
1167     wxLogMessage(wxT("wxEVT_MOUSE_RIGHT_UP, Click Point is X: %d, Y: %d"), event
.GetX(), event
.GetY()); 
1171 void MyFrame::OnGoto(wxCommandEvent
& WXUNUSED(event
)) 
1173     wxDataViewItem item 
= m_list_model
->GetItem( 50 ); 
1174     m_listCtrl
->EnsureVisible(item
,m_col
); 
1177 void MyFrame::OnAddMany(wxCommandEvent
& WXUNUSED(event
)) 
1179     m_list_model
->AddMany(); 
1183 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
) ) 
1185     wxAboutDialogInfo info
; 
1186     info
.SetName(_("DataView sample")); 
1187     info
.SetDescription(_("This sample demonstrates the dataview control handling")); 
1188     info
.SetCopyright(_T("(C) 2007 Robert Roebling"));