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 
  77             Title               Artist               Year        Judgement 
  78 -------------------------------------------------------------------------- 
  81         3:  You are not alone   Michael Jackson      1995        good 
  82         4:  Take a bow          Madonna              1994        good 
  84         6:  Ninth Symphony      Ludwig v. Beethoven  1824        good 
  85         7:  German Requiem      Johannes Brahms      1868        good 
  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 
) 
 104         m_isContainer 
= false; 
 107     MyMusicModelNode( MyMusicModelNode
* parent
, 
 108                       const wxString 
&branch 
) 
 113         m_isContainer 
= true; 
 118         size_t count 
= m_children
.GetCount(); 
 120         for (i 
= 0; i 
< count
; i
++) 
 122             MyMusicModelNode 
*child 
= m_children
[i
]; 
 127     bool IsContainer()                                    { return m_isContainer
; } 
 129     MyMusicModelNode
* GetParent()                         { return m_parent
; } 
 130     MyMusicModelNodes 
&GetChildren()                      { return m_children
; } 
 131     MyMusicModelNode
* GetNthChild( unsigned int n 
)       { return m_children
.Item( n 
); } 
 132     void Insert( MyMusicModelNode
* child
, unsigned int n
) { m_children
.Insert( child
, n
); } 
 133     void Append( MyMusicModelNode
* child 
)                { m_children
.Add( child 
); } 
 134     unsigned int GetChildCount()                          { return m_children
.GetCount(); } 
 143     MyMusicModelNode   
*m_parent
; 
 144     MyMusicModelNodes   m_children
; 
 149 class MyMusicModel
: public wxDataViewModel
 
 157         m_root 
= new MyMusicModelNode( NULL
, wxT("My Music" )); 
 158         m_pop 
= new MyMusicModelNode( m_root
, wxT("Pop music") ); 
 159         m_root
->Append( m_pop 
); 
 160         m_pop
->Append( new MyMusicModelNode( m_pop
, 
 161             wxT("You are not alone"), wxT("Michael Jackson"), 1995 ) ); 
 162         m_pop
->Append( new MyMusicModelNode( m_pop
, 
 163             wxT("Take a bow"), wxT("Madonna"), 1994 ) ); 
 164         m_classical 
= new MyMusicModelNode( m_root
, wxT("Classical music") ); 
 165         m_root
->Append( m_classical 
); 
 166         m_ninth 
= new MyMusicModelNode( m_classical
, 
 167             wxT("Ninth symphony"), wxT("Ludwig van Beethoven"), 1824 ); 
 168         m_classical
->Append( m_ninth 
); 
 169         m_classical
->Append( new MyMusicModelNode( m_classical
, 
 170             wxT("German Requiem"), wxT("Johannes Brahms"), 1868 ) ); 
 171         m_classicalMusicIsKnownToControl 
= false; 
 179     // helper method for wxLog 
 181     wxString 
GetTitle( const wxDataViewItem 
&item 
) const 
 183         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 185             return wxEmptyString
; 
 187         return node
->m_title
; 
 190     int GetYear( const wxDataViewItem 
&item 
) const 
 192         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 199     // helper methods to change the model 
 201     void AddToClassical( const wxString 
&title
, const wxString 
&artist
, int year 
) 
 204         MyMusicModelNode 
*child_node 
= 
 205             new MyMusicModelNode( m_classical
, title
, artist
, year 
); 
 207         m_classical
->Append( child_node 
); 
 209         if (m_classicalMusicIsKnownToControl
) 
 212             wxDataViewItem 
child( (void*) child_node 
); 
 213             wxDataViewItem 
parent( (void*) m_classical 
); 
 214             ItemAdded( parent
, child 
); 
 218     void Delete( const wxDataViewItem 
&item 
) 
 220         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 221         wxDataViewItem 
parent( node
->GetParent() ); 
 223         node
->GetParent()->GetChildren().Remove( node 
); 
 227         ItemDeleted( parent
, item 
); 
 230     // override sorting to always sort branches ascendingly 
 232     int Compare( const wxDataViewItem 
&item1
, const wxDataViewItem 
&item2
, 
 233                  unsigned int column
, bool ascending 
) 
 235         if (IsContainer(item1
) && IsContainer(item2
)) 
 237             wxVariant value1
,value2
; 
 238             GetValue( value1
, item1
, 0 ); 
 239             GetValue( value2
, item2
, 0 ); 
 241             wxString str1 
= value1
.GetString(); 
 242             wxString str2 
= value2
.GetString(); 
 243             int res 
= str1
.Cmp( str2 
); 
 246             // items must be different 
 247             wxUIntPtr litem1 
= (wxUIntPtr
) item1
.GetID(); 
 248             wxUIntPtr litem2 
= (wxUIntPtr
) item2
.GetID(); 
 250             return litem1
-litem2
; 
 253         return wxDataViewModel::Compare( item1
, item2
, column
, ascending 
); 
 256     // implementation of base class virtuals to define model 
 258     virtual unsigned int GetColumnCount() const 
 263     virtual wxString 
GetColumnType( unsigned int col 
) const 
 268         return wxT("string"); 
 271     virtual void GetValue( wxVariant 
&variant
, 
 272                            const wxDataViewItem 
&item
, unsigned int col 
) const 
 274         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 277             case 0: variant 
= node
->m_title
; break; 
 278             case 1: variant 
= node
->m_artist
; break; 
 279             case 2: variant 
= (long) node
->m_year
; break; 
 280             case 3: variant 
= node
->m_quality
; break; 
 282                // wxMac doesn't conceal the popularity progress renderer, return 0 for containers 
 283                if (IsContainer(item
)) 
 286                   variant 
= (long) 80;  // all music is very 80% popular 
 289                // Make size of red square depend on year 
 290                if (GetYear(item
) < 1900) 
 297                 wxLogError( wxT("MyMusicModel::GetValue: wrong column %d"), col 
); 
 299                 // provoke a crash when mouse button down 
 300                 wxMouseState state 
= wxGetMouseState(); 
 301                 if (state
.ShiftDown()) 
 310     virtual bool SetValue( const wxVariant 
&variant
, 
 311                            const wxDataViewItem 
&item
, unsigned int col 
) 
 313         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 316             case 0: node
->m_title 
= variant
.GetString(); return true; 
 317             case 1: node
->m_artist  
= variant
.GetString(); return true; 
 318             case 2: node
->m_year  
= variant
.GetLong(); return true; 
 319             case 3: node
->m_quality  
= variant
.GetString(); return true; 
 320             default: wxLogError( wxT("MyMusicModel::SetValue: wrong column") ); 
 325     virtual wxDataViewItem 
GetParent( const wxDataViewItem 
&item 
) const 
 327         // the invisble root node has no parent 
 329             return wxDataViewItem(0); 
 331         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 333         // "MyMusic" also has no parent 
 335             return wxDataViewItem(0); 
 337         return wxDataViewItem( (void*) node
->GetParent() ); 
 340     virtual bool IsContainer( const wxDataViewItem 
&item 
) const 
 342         // the invisble root node can have children (in 
 343         // our model always "MyMusic") 
 347         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
 348         return node
->IsContainer(); 
 351     virtual unsigned int GetChildren( const wxDataViewItem 
&parent
, wxDataViewItemArray 
&array 
) const 
 353         MyMusicModelNode 
*node 
= (MyMusicModelNode
*) parent
.GetID(); 
 356             array
.Add( wxDataViewItem( (void*) m_root 
) ); 
 360         if (node 
== m_classical
) 
 362             MyMusicModel 
*model 
= (MyMusicModel
*)(const MyMusicModel
*) this; 
 363             model
->m_classicalMusicIsKnownToControl 
= true; 
 366         if (node
->GetChildCount() == 0) 
 371         unsigned int count 
= node
->GetChildren().GetCount(); 
 373         for (pos 
= 0; pos 
< count
; pos
++) 
 375             MyMusicModelNode 
*child 
= node
->GetChildren().Item( pos 
); 
 376             array
.Add( wxDataViewItem( (void*) child 
) ); 
 381     wxDataViewItem 
GetNinthItem() 
 383        return wxDataViewItem( m_ninth 
); 
 387     MyMusicModelNode
*   m_root
; 
 388     MyMusicModelNode
*   m_pop
; 
 389     MyMusicModelNode
*   m_classical
; 
 390     MyMusicModelNode
*   m_ninth
; 
 391     bool                m_classicalMusicIsKnownToControl
; 
 395 static int my_sort_reverse( int *v1
, int *v2 
) 
 400 static int my_sort( int *v1
, int *v2 
) 
 405 class MyListModel
: public wxDataViewVirtualListModel
 
 410         wxDataViewVirtualListModel( 1000 + 100 ) 
 412         wxDataViewVirtualListModel( 100000 + 100 ) 
 416         m_virtualItems 
= 1000; 
 418         m_virtualItems 
= 100000; 
 422         for (i 
= 0; i 
< 100; i
++) 
 425             str
.Printf( wxT("row number %d"), i 
); 
 429         m_icon 
= wxIcon( null_xpm 
); 
 432     // helper methods to change the model 
 434     void Prepend( const wxString 
&text 
) 
 436         m_array
.Insert( text
, 0 ); 
 440     void DeleteItem( const wxDataViewItem 
&item 
) 
 442         unsigned int row 
= GetRow( item 
); 
 443         if (row 
>= m_array
.GetCount()) 
 446         m_array
.RemoveAt( row 
); 
 450     void DeleteItems( const wxDataViewItemArray 
&items 
) 
 454         for (i 
= 0; i 
< items
.GetCount(); i
++) 
 456             unsigned int row 
= GetRow( items
[i
] ); 
 457             if (row 
< m_array
.GetCount()) 
 461         // Sort in descending order so that the last 
 462         // row will be deleted first. Otherwise the 
 463         // remaining indeces would all be wrong. 
 464         rows
.Sort( my_sort_reverse 
); 
 465         for (i 
= 0; i 
< rows
.GetCount(); i
++) 
 466             m_array
.RemoveAt( rows
[i
] ); 
 468         // This is just to test if wxDataViewCtrl can 
 469         // cope with removing rows not sorted in 
 471         rows
.Sort( my_sort 
); 
 477         m_virtualItems 
+= 1000; 
 478         Reset( m_array
.GetCount() + m_virtualItems 
); 
 481     // implementation of base class virtuals to define model 
 483     virtual unsigned int GetColumnCount() const 
 488     virtual wxString 
GetColumnType( unsigned int col 
) const 
 491             return wxT("wxDataViewIconText"); 
 493         return wxT("string"); 
 496     virtual unsigned int GetRowCount() 
 498         return m_array
.GetCount(); 
 501     virtual void GetValueByRow( wxVariant 
&variant
, 
 502                            unsigned int row
, unsigned int col 
) const 
 506             if (row 
>= m_array
.GetCount()) 
 509                 str
.Printf(wxT("row %d"), row 
- m_array
.GetCount() ); 
 514                 variant 
= m_array
[ row 
]; 
 519             wxDataViewIconText 
data( wxT("test"), m_icon 
); 
 524             if (row 
>= m_array
.GetCount()) 
 525                 variant 
= wxT("plain"); 
 527                 variant 
= wxT("blue"); 
 531     virtual bool GetAttrByRow( unsigned int row
, unsigned int col
, wxDataViewItemAttr 
&attr 
) 
 536         if (row 
< m_array
.GetCount()) 
 538             attr
.SetColour( *wxBLUE 
); 
 539             attr
.SetItalic( true ); 
 545     virtual bool SetValueByRow( const wxVariant 
&variant
, 
 546                            unsigned int row
, unsigned int col 
) 
 550             if (row 
>= m_array
.GetCount()) 
 553             m_array
[row
] = variant
.GetString(); 
 560     wxArrayString    m_array
; 
 565 // ------------------------------------- 
 567 // ------------------------------------- 
 569 class MyCustomRenderer
: public wxDataViewCustomRenderer
 
 572     MyCustomRenderer( wxDataViewCellMode mode
, int alignment 
) : 
 573        wxDataViewCustomRenderer( wxString("long"), mode
, alignment 
) 
 576     virtual bool Render( wxRect rect
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 578         dc
->SetBrush( *wxRED_BRUSH 
); 
 579         dc
->SetPen( *wxTRANSPARENT_PEN 
); 
 580         dc
->DrawRectangle( rect 
); 
 585     virtual bool Activate( wxRect 
WXUNUSED(cell
), 
 586                            wxDataViewModel 
*WXUNUSED(model
), const wxDataViewItem 
&WXUNUSED(item
), unsigned int WXUNUSED(col
) ) 
 588         wxLogMessage( wxT("MyCustomRenderer Activate()") ); 
 592     virtual bool LeftClick( wxPoint cursor
, wxRect 
WXUNUSED(cell
), 
 593                            wxDataViewModel 
*WXUNUSED(model
), const wxDataViewItem 
&WXUNUSED(item
), unsigned int WXUNUSED(col
) ) 
 595         wxLogMessage( wxT("MyCustomRenderer LeftClick( %d, %d )"), cursor
.x
, cursor
.y 
); 
 599     virtual wxSize 
GetSize() const 
 601         //return wxSize(60,m_height); 
 602         return wxSize(60,20); 
 605     virtual bool SetValue( const wxVariant 
&value 
) 
 611     virtual bool GetValue( wxVariant 
&WXUNUSED(value
) ) const { return true; } 
 617 // ------------------------------------- 
 619 // ------------------------------------- 
 621 class MyApp
: public wxApp
 
 628 // ------------------------------------- 
 630 // ------------------------------------- 
 632 class MyFrame 
: public wxFrame
 
 635     MyFrame(wxFrame 
*frame
, const wxString 
&title
, int x
, int y
, int w
, int h
); 
 639     void OnQuit(wxCommandEvent
& event
); 
 640     void OnAbout(wxCommandEvent
& event
); 
 642     void OnAddMozart(wxCommandEvent
& event
); 
 643     void OnDeleteMusic(wxCommandEvent
& event
); 
 644     void OnDeleteYear(wxCommandEvent
& event
); 
 645     void OnSelectNinth(wxCommandEvent
& event
); 
 647     void OnPrependList(wxCommandEvent
& event
); 
 648     void OnDeleteList(wxCommandEvent
& event
); 
 650     void OnValueChanged( wxDataViewEvent 
&event 
); 
 652     void OnActivated( wxDataViewEvent 
&event 
); 
 653     void OnExpanding( wxDataViewEvent 
&event 
); 
 654     void OnExpanded( wxDataViewEvent 
&event 
); 
 655     void OnCollapsing( wxDataViewEvent 
&event 
); 
 656     void OnCollapsed( wxDataViewEvent 
&event 
); 
 657     void OnSelectionChanged( wxDataViewEvent 
&event 
); 
 659     void OnEditingStarted( wxDataViewEvent 
&event 
); 
 660     void OnEditingDone( wxDataViewEvent 
&event 
); 
 662     void OnHeaderClick( wxDataViewEvent 
&event 
); 
 663     void OnHeaderRightClick( wxDataViewEvent 
&event 
); 
 664     void OnSorted( wxDataViewEvent 
&event 
); 
 666     void OnContextMenu( wxDataViewEvent 
&event 
); 
 668     void OnRightClick( wxMouseEvent 
&event 
); 
 669     void OnGoto( wxCommandEvent 
&event
); 
 670     void OnAddMany( wxCommandEvent 
&event
); 
 672     void OnBeginDrag( wxDataViewEvent 
&event 
); 
 673     void OnDropPossible( wxDataViewEvent 
&event 
); 
 674     void OnDrop( wxDataViewEvent 
&event 
); 
 677     wxDataViewCtrl
* m_musicCtrl
; 
 678     wxObjectDataPtr
<MyMusicModel
> m_music_model
; 
 680     wxDataViewCtrl
* m_listCtrl
; 
 681     wxObjectDataPtr
<MyListModel
> m_list_model
; 
 683     wxDataViewColumn 
* m_col
; 
 689     DECLARE_EVENT_TABLE() 
 692 // ------------------------------------- 
 694 // ------------------------------------- 
 698 bool MyApp::OnInit(void) 
 700     if ( !wxApp::OnInit() ) 
 703     // build the first frame 
 705         new MyFrame(NULL
, wxT("wxDataViewCtrl feature test"), 40, 40, 1000, 540); 
 718 // ------------------------------------- 
 720 // ------------------------------------- 
 725     ID_ABOUT 
= wxID_ABOUT
, 
 731     ID_DELETE_MUSIC     
= 101, 
 732     ID_DELETE_YEAR      
= 102, 
 733     ID_SELECT_NINTH     
= 103, 
 735     ID_PREPEND_LIST     
= 200, 
 736     ID_DELETE_LIST      
= 201, 
 741 BEGIN_EVENT_TABLE(MyFrame
, wxFrame
) 
 742     EVT_MENU( ID_ABOUT
, MyFrame::OnAbout 
) 
 743     EVT_MENU( ID_EXIT
, MyFrame::OnQuit 
) 
 744     EVT_BUTTON( ID_ADD_MOZART
, MyFrame::OnAddMozart 
) 
 745     EVT_BUTTON( ID_DELETE_MUSIC
, MyFrame::OnDeleteMusic 
) 
 746     EVT_BUTTON( ID_DELETE_YEAR
, MyFrame::OnDeleteYear 
) 
 747     EVT_BUTTON( ID_SELECT_NINTH
, MyFrame::OnSelectNinth 
) 
 748     EVT_BUTTON( ID_PREPEND_LIST
, MyFrame::OnPrependList 
) 
 749     EVT_BUTTON( ID_DELETE_LIST
, MyFrame::OnDeleteList 
) 
 750     EVT_BUTTON( ID_GOTO
, MyFrame::OnGoto
) 
 751     EVT_BUTTON( ID_ADD_MANY
, MyFrame::OnAddMany
) 
 753     EVT_DATAVIEW_ITEM_VALUE_CHANGED( ID_MUSIC_CTRL
, MyFrame::OnValueChanged 
) 
 755     EVT_DATAVIEW_ITEM_ACTIVATED(ID_MUSIC_CTRL
, MyFrame::OnActivated 
) 
 756     EVT_DATAVIEW_ITEM_EXPANDING(ID_MUSIC_CTRL
, MyFrame::OnExpanding
) 
 757     EVT_DATAVIEW_ITEM_EXPANDED(ID_MUSIC_CTRL
, MyFrame::OnExpanded
) 
 758     EVT_DATAVIEW_ITEM_COLLAPSING(ID_MUSIC_CTRL
, MyFrame::OnCollapsing
) 
 759     EVT_DATAVIEW_ITEM_COLLAPSED(ID_MUSIC_CTRL
, MyFrame::OnCollapsed
) 
 760     EVT_DATAVIEW_SELECTION_CHANGED(ID_MUSIC_CTRL
, MyFrame::OnSelectionChanged
) 
 762     EVT_DATAVIEW_ITEM_EDITING_STARTED(ID_MUSIC_CTRL
, MyFrame::OnEditingStarted
) 
 763     EVT_DATAVIEW_ITEM_EDITING_DONE(ID_MUSIC_CTRL
, MyFrame::OnEditingDone
) 
 765     EVT_DATAVIEW_COLUMN_HEADER_CLICK(ID_MUSIC_CTRL
, MyFrame::OnHeaderClick
) 
 766     EVT_DATAVIEW_COLUMN_HEADER_RIGHT_CLICKED(ID_MUSIC_CTRL
, MyFrame::OnHeaderRightClick
) 
 767     EVT_DATAVIEW_COLUMN_SORTED(ID_MUSIC_CTRL
, MyFrame::OnSorted
) 
 769     EVT_DATAVIEW_ITEM_CONTEXT_MENU(ID_MUSIC_CTRL
, MyFrame::OnContextMenu
) 
 771     EVT_DATAVIEW_ITEM_BEGIN_DRAG( ID_MUSIC_CTRL
, MyFrame::OnBeginDrag 
) 
 772     EVT_DATAVIEW_ITEM_DROP_POSSIBLE( ID_MUSIC_CTRL
, MyFrame::OnDropPossible 
) 
 773     EVT_DATAVIEW_ITEM_DROP( ID_MUSIC_CTRL
, MyFrame::OnDrop 
) 
 775     EVT_RIGHT_UP(MyFrame::OnRightClick
) 
 778 MyFrame::MyFrame(wxFrame 
*frame
, const wxString 
&title
, int x
, int y
, int w
, int h
): 
 779   wxFrame(frame
, wxID_ANY
, title
, wxPoint(x
, y
), wxSize(w
, h
)) 
 784     SetIcon(wxICON(sample
)); 
 788     wxMenu 
*file_menu 
= new wxMenu
; 
 789     file_menu
->Append(ID_ABOUT
, wxT("&About")); 
 790     file_menu
->AppendSeparator(); 
 791     file_menu
->Append(ID_EXIT
, wxT("E&xit")); 
 793     wxMenuBar 
*menu_bar 
= new wxMenuBar
; 
 794     menu_bar
->Append(file_menu
, wxT("&File")); 
 796     SetMenuBar(menu_bar
); 
 799     wxPanel 
*panel 
= new wxPanel( this, -1 ); 
 801     wxBoxSizer 
*main_sizer 
= new wxBoxSizer( wxVERTICAL 
); 
 803     wxBoxSizer 
*data_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 807     m_musicCtrl 
= new wxDataViewCtrl( panel
, ID_MUSIC_CTRL
, wxDefaultPosition
, 
 808                                     wxSize(400,200), wxDV_MULTIPLE
|wxDV_VARIABLE_LINE_HEIGHT 
); 
 810     m_music_model 
= new MyMusicModel
; 
 811     m_musicCtrl
->AssociateModel( m_music_model
.get() ); 
 813     m_musicCtrl
->EnableDragSource( wxDF_TEXT 
); 
 814     m_musicCtrl
->EnableDropTarget( wxDF_TEXT 
); 
 816     wxDataViewTextRenderer 
*tr 
= new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_INERT 
); 
 817     wxDataViewColumn 
*column0 
= new wxDataViewColumn( wxT("title"), tr
, 0, 200, wxALIGN_LEFT
, 
 818         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 819     m_musicCtrl
->AppendColumn( column0 
); 
 821     // Call this and sorting is enabled 
 822     // immediatly upon start up. 
 823     column0
->SetAsSortKey(); 
 826     tr 
= new wxDataViewTextRenderer( wxT("string"), wxDATAVIEW_CELL_EDITABLE 
); 
 827     wxDataViewColumn 
*column1 
= new wxDataViewColumn( wxT("artist"), tr
, 1, 150, wxALIGN_LEFT
, 
 828         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_REORDERABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 829     column1
->SetMinWidth(150); // this column can't be resized to be smaller 
 830     m_musicCtrl
->AppendColumn( column1 
); 
 832     wxDataViewSpinRenderer 
*sr 
= new wxDataViewSpinRenderer( 0, 2010, wxDATAVIEW_CELL_EDITABLE
, wxALIGN_RIGHT 
); 
 833     wxDataViewColumn 
*column2 
= new wxDataViewColumn( wxT("year"), sr
, 2, 60, wxALIGN_LEFT
, 
 834         wxDATAVIEW_COL_SORTABLE 
| wxDATAVIEW_COL_REORDERABLE 
); 
 835     m_musicCtrl
->AppendColumn( column2 
); 
 837     wxArrayString choices
; 
 838     choices
.Add( "good" ); 
 839     choices
.Add( "bad" ); 
 840     choices
.Add( "lousy" ); 
 841     wxDataViewChoiceRenderer 
*c 
= new wxDataViewChoiceRenderer( choices
, wxDATAVIEW_CELL_EDITABLE
, wxALIGN_RIGHT 
); 
 842     wxDataViewColumn 
*column3 
= new wxDataViewColumn( wxT("rating"), c
, 3, 100, wxALIGN_LEFT
, 
 843         wxDATAVIEW_COL_REORDERABLE 
| wxDATAVIEW_COL_RESIZABLE 
); 
 844     m_musicCtrl
->AppendColumn( column3 
); 
 846     m_musicCtrl
->AppendProgressColumn( wxT("popularity"), 4, wxDATAVIEW_CELL_INERT
, 80 ); 
 848     MyCustomRenderer 
*cr 
= new MyCustomRenderer( wxDATAVIEW_CELL_ACTIVATABLE
, wxALIGN_RIGHT 
); 
 849     wxDataViewColumn 
*column4 
= new wxDataViewColumn( wxT("custom"), cr
, 5, -1, wxALIGN_LEFT
, 
 850         wxDATAVIEW_COL_RESIZABLE 
); 
 851     m_musicCtrl
->AppendColumn( column4 
); 
 853     data_sizer
->Add( m_musicCtrl
, 3, wxGROW 
); 
 857     m_listCtrl 
= new wxDataViewCtrl( panel
, wxID_ANY
, wxDefaultPosition
, 
 858                                      wxSize(400,200), wxDV_MULTIPLE 
| wxDV_ROW_LINES
); 
 860     m_list_model 
= new MyListModel
; 
 861     m_listCtrl
->AssociateModel( m_list_model
.get() ); 
 864     m_listCtrl
->AppendTextColumn    (wxT("editable string"), 0, wxDATAVIEW_CELL_EDITABLE
, 120 ); 
 865     m_listCtrl
->AppendIconTextColumn(wxIcon(small1_xpm
), 1, wxDATAVIEW_CELL_INERT 
)->SetTitle( wxT("icon") ); 
 867     m_listCtrl
->AppendTextColumn    (wxT("editable string"), 0, wxDATAVIEW_CELL_EDITABLE 
); 
 868     m_listCtrl
->AppendIconTextColumn(wxT("icon"),            1, wxDATAVIEW_CELL_INERT 
); 
 871     wxDataViewTextRendererAttr 
*ra 
= new wxDataViewTextRendererAttr
; 
 872     wxDataViewColumn 
*column5 
= new wxDataViewColumn(wxT("attributes"), ra
, 2 ); 
 873     m_listCtrl
->AppendColumn( column5 
); 
 875     data_sizer
->Add( m_listCtrl
, 2, wxGROW 
); 
 877     main_sizer
->Add( data_sizer
, 2, wxGROW 
); 
 879     wxBoxSizer 
*button_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 881     button_sizer
->Add( new wxButton( panel
, ID_ADD_MOZART
,  _("Add Mozart")),             0, wxALL
, 10 ); 
 882     button_sizer
->Add( new wxButton( panel
, ID_DELETE_MUSIC
,_("Delete selected")),        0, wxALL
, 10 ); 
 883     button_sizer
->Add( new wxButton( panel
, ID_DELETE_YEAR
, _("Delete \"Year\" column")), 0, wxALL
, 10 ); 
 884     button_sizer
->Add( new wxButton( panel
, ID_SELECT_NINTH
, _("Select Ninth")), 0, wxALL
, 10 ); 
 885     button_sizer
->Add( 10, 10, 1 ); 
 886     wxFlexGridSizer 
*grid_sizer 
= new wxFlexGridSizer( 2, 2 ); 
 887     grid_sizer
->Add( new wxButton( panel
, ID_PREPEND_LIST
,_("Prepend")),         0, wxALL
, 2 ); 
 888     grid_sizer
->Add( new wxButton( panel
, ID_DELETE_LIST
, _("Delete selected")), 0, wxALL
, 2 ); 
 889     grid_sizer
->Add( new wxButton( panel
, ID_GOTO
,        _("Goto 50")),         0, wxALL
, 2 ); 
 890     grid_sizer
->Add( new wxButton( panel
, ID_ADD_MANY
,    _("Add 1000")),        0, wxALL
, 2 ); 
 891     button_sizer
->Add( grid_sizer
, 0, wxALL
, 10 ); 
 893     main_sizer
->Add( button_sizer
, 0, wxGROW
, 0 ); 
 895     wxBoxSizer 
*bottom_sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 897     m_log 
= new wxTextCtrl( panel
, -1, wxString(), wxDefaultPosition
, wxSize(100,200), wxTE_MULTILINE 
); 
 898     m_logOld 
= wxLog::SetActiveTarget(new wxLogTextCtrl(m_log
)); 
 899     wxLogMessage(_("This is the log window")); 
 901     bottom_sizer
->Add( m_log
, 1, wxGROW 
); 
 903     // wxDataViewListCtrl 
 905     wxDataViewListCtrl 
*listctrl 
= new wxDataViewListCtrl( panel
, -1, 
 906         wxDefaultPosition
, wxSize(100,200) ); 
 908     listctrl
->AppendToggleColumn( wxT("Toggle") ); 
 909     listctrl
->AppendTextColumn( wxT("Text") ); 
 911     wxVector
<wxVariant
> data
; 
 912     data
.push_back( true ); 
 913     data
.push_back( "row 1" ); 
 914     listctrl
->AppendItem( data 
); 
 917     data
.push_back( false ); 
 918     data
.push_back( "row 3" ); 
 919     listctrl
->AppendItem( data 
); 
 921     bottom_sizer
->Add( listctrl
, 1 ); 
 924     // wxDataViewTreeCtrl 
 926     wxDataViewTreeCtrl 
*treectrl2 
= new wxDataViewTreeCtrl( panel
, -1, wxDefaultPosition
, wxSize(100,200) ); 
 928     wxImageList 
*ilist 
= new wxImageList( 16, 16 ); 
 929     ilist
->Add( wxIcon(small1_xpm
) ); 
 930     treectrl2
->SetImageList( ilist 
); 
 932     wxDataViewItem parent2 
= treectrl2
->AppendContainer( wxDataViewItem(0),wxT("Root 1"), 0 ); 
 933     wxDataViewItem child2 
= treectrl2
->AppendItem( parent2
, wxT("Child 1"), 0 ); 
 934     child2 
= treectrl2
->AppendItem( parent2
, wxT("Child 2"), 0 ); 
 935     child2 
= treectrl2
->AppendItem( parent2
, wxT("Child 3, very long, long, long, long"), 0 ); 
 937     bottom_sizer
->Add( treectrl2
, 1 ); 
 941     main_sizer
->Add( bottom_sizer
, 0, wxGROW 
); 
 943     panel
->SetSizer( main_sizer 
); 
 948     delete wxLog::SetActiveTarget(m_logOld
); 
 951 void MyFrame::OnQuit(wxCommandEvent
& WXUNUSED(event
) ) 
 956 void MyFrame::OnAddMozart(wxCommandEvent
& WXUNUSED(event
) ) 
 958     m_music_model
->AddToClassical( wxT("Kleine Nachtmusik"), wxT("Wolfgang Mozart"), 1787 ); 
 961 void MyFrame::OnDeleteMusic(wxCommandEvent
& WXUNUSED(event
) ) 
 963     wxDataViewItemArray items
; 
 964     int len 
= m_musicCtrl
->GetSelections( items 
); 
 965     for( int i 
= 0; i 
< len
; i 
++ ) 
 967             m_music_model
->Delete( items
[i
] ); 
 970 void MyFrame::OnDeleteYear( wxCommandEvent
& WXUNUSED(event
) ) 
 972     m_musicCtrl
->DeleteColumn( m_musicCtrl
->GetColumn( 2 ) ); 
 973     FindWindow( ID_DELETE_YEAR 
)->Disable(); 
 976 void MyFrame::OnSelectNinth( wxCommandEvent
& WXUNUSED(event
) ) 
 978     m_musicCtrl
->Select( m_music_model
->GetNinthItem() ); 
 981 void MyFrame::OnPrependList( wxCommandEvent
& WXUNUSED(event
) ) 
 983     m_list_model
->Prepend(wxT("Test")); 
 986 void MyFrame::OnDeleteList( wxCommandEvent
& WXUNUSED(event
) ) 
 988     wxDataViewItemArray items
; 
 989     int len 
= m_listCtrl
->GetSelections( items 
); 
 991         m_list_model
->DeleteItems( items 
); 
 994 void MyFrame::OnValueChanged( wxDataViewEvent 
&event 
) 
 999     wxLogMessage( wxT("EVT_DATAVIEW_ITEM_VALUE_CHANGED, Item Id: %d;  Column: %d"), event
.GetItem().GetID(), event
.GetColumn() ); 
1002 void MyFrame::OnActivated( wxDataViewEvent 
&event 
) 
1007     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1008     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED, Item: %s"), title 
); 
1010     if (m_musicCtrl
->IsExpanded( event
.GetItem() )) 
1011     wxLogMessage(wxT("Item: %s is expanded"), title 
); 
1014 void MyFrame::OnSelectionChanged( wxDataViewEvent 
&event 
) 
1019     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1021         title 
= wxT("None"); 
1023     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED, First selected Item: %s"), title 
); 
1026 void MyFrame::OnExpanding( wxDataViewEvent 
&event 
) 
1031     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1032     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING, Item: %s"), title 
); 
1036 void MyFrame::OnEditingStarted( wxDataViewEvent 
&event 
) 
1041     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1042     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_STARTED, Item: %s"), title 
); 
1045 void MyFrame::OnEditingDone( wxDataViewEvent 
&event 
) 
1050     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1051     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EDITING_DONE, Item: %s"), title 
); 
1054 void MyFrame::OnExpanded( wxDataViewEvent 
&event 
) 
1059     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1060     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED, Item: %s"), title 
); 
1063 void MyFrame::OnCollapsing( wxDataViewEvent 
&event 
) 
1068     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1069     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING, Item: %s"), title 
); 
1072 void MyFrame::OnCollapsed( wxDataViewEvent 
&event 
) 
1077     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1078     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED, Item: %s"),title
); 
1081 void MyFrame::OnContextMenu( wxDataViewEvent 
&event 
) 
1086     wxString title 
= m_music_model
->GetTitle( event
.GetItem() ); 
1087     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s"),title 
); 
1090     menu
.Append( 1, wxT("entry 1") ); 
1091     menu
.Append( 2, wxT("entry 2") ); 
1092     menu
.Append( 3, wxT("entry 3") ); 
1094     m_musicCtrl
->PopupMenu(&menu
); 
1096 //    wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU, Item: %s Value: %s"),title.GetData(), event.GetValue().GetString()); 
1099 void MyFrame::OnHeaderClick( wxDataViewEvent 
&event 
) 
1101     // we need to skip the event to let the default behaviour of sorting by 
1102     // this column when it is clicked to take place 
1108     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1110     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK, Column position: %d"), pos 
); 
1113 void MyFrame::OnHeaderRightClick( wxDataViewEvent 
&event 
) 
1118     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1120     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK, Column position: %d"), pos 
); 
1123 void MyFrame::OnSorted( wxDataViewEvent 
&event 
) 
1128     int pos 
= m_musicCtrl
->GetColumnPosition( event
.GetDataViewColumn() ); 
1130     wxLogMessage(wxT("wxEVT_COMMAND_DATAVIEW_COLUMN_SORTED, Column position: %d"), pos 
); 
1133 void MyFrame::OnRightClick( wxMouseEvent 
&event 
) 
1138     wxLogMessage(wxT("wxEVT_MOUSE_RIGHT_UP, Click Point is X: %d, Y: %d"), event
.GetX(), event
.GetY()); 
1141 void MyFrame::OnGoto(wxCommandEvent
& WXUNUSED(event
)) 
1143     wxDataViewItem item 
= m_list_model
->GetItem( 50 ); 
1144     m_listCtrl
->EnsureVisible(item
,m_col
); 
1147 void MyFrame::OnAddMany(wxCommandEvent
& WXUNUSED(event
)) 
1149     m_list_model
->AddMany(); 
1153 void MyFrame::OnAbout(wxCommandEvent
& WXUNUSED(event
) ) 
1155     wxAboutDialogInfo info
; 
1156     info
.SetName(_("DataView sample")); 
1157     info
.SetDescription(_("This sample demonstrates wxDataViewCtrl")); 
1158     info
.SetCopyright(_T("(C) 2007-2009 Robert Roebling")); 
1163 void MyFrame::OnBeginDrag( wxDataViewEvent 
&event 
) 
1165     wxDataViewItem 
item( event
.GetItem() ); 
1167     // only allow drags for item, not containers 
1168     if (m_music_model
->IsContainer( item 
) ) 
1174     MyMusicModelNode 
*node 
= (MyMusicModelNode
*) item
.GetID(); 
1175     wxTextDataObject 
*obj 
= new wxTextDataObject
; 
1176     obj
->SetText( node
->m_title 
); 
1177     event
.SetDataObject( obj 
); 
1180 void MyFrame::OnDropPossible( wxDataViewEvent 
&event 
) 
1182     wxDataViewItem 
item( event
.GetItem() ); 
1184     // only allow drags for item, not containers 
1185     if (m_music_model
->IsContainer( item 
) ) 
1188     if (event
.GetDataFormat() != wxDF_TEXT
) 
1192 void MyFrame::OnDrop( wxDataViewEvent 
&event 
) 
1194     wxDataViewItem 
item( event
.GetItem() ); 
1196     // only allow drags for item, not containers 
1197     if (m_music_model
->IsContainer( item 
) ) 
1200     if (event
.GetDataFormat() != wxDF_TEXT
) 
1203     wxTextDataObject obj
; 
1204     obj
.SetData( wxDF_TEXT
, event
.GetDataSize(), event
.GetDataBuffer() ); 
1206     wxLogMessage(wxT("Text dropped: %s"), obj
.GetText() );