1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/datavgen.cpp 
   3 // Purpose:     wxDataViewCtrl generic implementation 
   4 // Author:      Robert Roebling 
   5 // Modified by: Francesco Montorsi, Guru Kathiresan, Otto Wyss 
   7 // Copyright:   (c) 1998 Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  11 // For compilers that support precompilation, includes "wx.h". 
  12 #include "wx/wxprec.h" 
  18 #if wxUSE_DATAVIEWCTRL 
  20 #include "wx/dataview.h" 
  22 #ifdef wxUSE_GENERICDATAVIEWCTRL 
  26         #include "wx/msw/private.h" 
  27         #include "wx/msw/wrapwin.h" 
  28         #include "wx/msw/wrapcctl.h" // include <commctrl.h> "properly" 
  32     #include "wx/dcclient.h" 
  34     #include "wx/settings.h" 
  35     #include "wx/msgdlg.h" 
  36     #include "wx/dcscreen.h" 
  39 #include "wx/stockitem.h" 
  40 #include "wx/calctrl.h" 
  41 #include "wx/popupwin.h" 
  42 #include "wx/renderer.h" 
  43 #include "wx/dcbuffer.h" 
  46 //----------------------------------------------------------------------------- 
  48 //----------------------------------------------------------------------------- 
  52 static const int SCROLL_UNIT_X 
= 15; 
  54 // the cell padding on the left/right 
  55 static const int PADDING_RIGHTLEFT 
= 3; 
  57 // the cell padding on the top/bottom 
  58 static const int PADDING_TOPBOTTOM 
= 1; 
  60 // the expander space margin 
  61 static const int EXPANDER_MARGIN 
= 4; 
  63 //----------------------------------------------------------------------------- 
  64 // wxDataViewHeaderWindow 
  65 //----------------------------------------------------------------------------- 
  67 #define USE_NATIVE_HEADER_WINDOW    1 
  69 // NB: for some reason, this class must be dllexport'ed or we get warnings from 
  71 class WXDLLIMPEXP_ADV wxDataViewHeaderWindowBase 
: public wxControl
 
  74     wxDataViewHeaderWindowBase() 
  77     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
  78                 const wxPoint 
&pos
, const wxSize 
&size
, 
  81         return wxWindow::Create(parent
, id
, pos
, size
, wxNO_BORDER
, name
); 
  84     void SetOwner( wxDataViewCtrl
* owner 
) { m_owner 
= owner
; } 
  85     wxDataViewCtrl 
*GetOwner() { return m_owner
; } 
  87     // called on column addition/removal 
  88     virtual void UpdateDisplay() { /* by default, do nothing */ } 
  90     // returns the n-th column 
  91     virtual wxDataViewColumn 
*GetColumn(unsigned int n
) 
  94         wxDataViewColumn 
*ret 
= m_owner
->GetColumn(n
); 
 101     wxDataViewCtrl      
*m_owner
; 
 103     // sends an event generated from the n-th wxDataViewColumn 
 104     void SendEvent(wxEventType type
, unsigned int n
); 
 107 // on wxMSW the header window (only that part however) can be made native! 
 108 #if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW 
 110 #define COLUMN_WIDTH_OFFSET         2 
 111 #define wxDataViewHeaderWindowMSW   wxDataViewHeaderWindow 
 113 class wxDataViewHeaderWindowMSW 
: public wxDataViewHeaderWindowBase
 
 117     wxDataViewHeaderWindowMSW( wxDataViewCtrl 
*parent
, 
 119                                const wxPoint 
&pos 
= wxDefaultPosition
, 
 120                                const wxSize 
&size 
= wxDefaultSize
, 
 121                                const wxString 
&name 
= wxT("wxdataviewctrlheaderwindow") ) 
 123         Create(parent
, id
, pos
, size
, name
); 
 126     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
 127                 const wxPoint 
&pos
, const wxSize 
&size
, 
 128                 const wxString 
&name
); 
 130     ~wxDataViewHeaderWindowMSW(); 
 132     // called when any column setting is changed and/or changed 
 134     virtual void UpdateDisplay(); 
 136     // called when the main window gets scrolled 
 137     virtual void ScrollWindow(int dx
, int dy
, const wxRect 
*rect 
= NULL
); 
 140     virtual bool MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
); 
 141     virtual void DoSetSize(int x
, int y
, int width
, int height
, int sizeFlags
); 
 143     unsigned int GetColumnIdxFromHeader(NMHEADER 
*nmHDR
); 
 145     wxDataViewColumn 
*GetColumnFromHeader(NMHEADER 
*nmHDR
) 
 146         { return GetColumn(GetColumnIdxFromHeader(nmHDR
)); } 
 149     DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindowMSW
) 
 152 #else       // !defined(__WXMSW__) 
 154 #define HEADER_WINDOW_HEIGHT            25 
 155 #define HEADER_HORIZ_BORDER             5 
 156 #define HEADER_VERT_BORDER              3 
 157 #define wxGenericDataViewHeaderWindow   wxDataViewHeaderWindow 
 159 class wxGenericDataViewHeaderWindow 
: public wxDataViewHeaderWindowBase
 
 162     wxGenericDataViewHeaderWindow( wxDataViewCtrl 
*parent
, 
 164                                     const wxPoint 
&pos 
= wxDefaultPosition
, 
 165                                     const wxSize 
&size 
= wxDefaultSize
, 
 166                                     const wxString 
&name 
= wxT("wxdataviewctrlheaderwindow") ) 
 169         Create(parent
, id
, pos
, size
, name
); 
 172     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
 173                 const wxPoint 
&pos
, const wxSize 
&size
, 
 174                 const wxString 
&name
); 
 176     ~wxGenericDataViewHeaderWindow() 
 178         delete m_resizeCursor
; 
 181     virtual void UpdateDisplay() { Refresh(); } 
 185     void OnPaint( wxPaintEvent 
&event 
); 
 186     void OnMouse( wxMouseEvent 
&event 
); 
 187     void OnSetFocus( wxFocusEvent 
&event 
); 
 192     // vars used for column resizing: 
 194     wxCursor            
*m_resizeCursor
; 
 195     const wxCursor      
*m_currentCursor
; 
 198     bool                 m_dirty
;     // needs refresh? 
 199     int                  m_column
;    // index of the column being resized 
 200     int                  m_currentX
;  // divider line position in logical (unscrolled) coords 
 201     int                  m_minX
;      // minimal position beyond which the divider line 
 202                                       // can't be dragged in logical coords 
 204     // the pen used to draw the current column width drag line 
 205     // when resizing the columsn 
 209     // internal utilities: 
 213         m_currentCursor 
= (wxCursor 
*) NULL
; 
 214         m_resizeCursor 
= new wxCursor( wxCURSOR_SIZEWE 
); 
 216         m_isDragging 
= false; 
 219         m_column 
= wxNOT_FOUND
; 
 223         wxColour col 
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT
); 
 224         m_penCurrent 
= wxPen(col
, 1, wxSOLID
); 
 228     void AdjustDC(wxDC
& dc
); 
 231     DECLARE_DYNAMIC_CLASS(wxGenericDataViewHeaderWindow
) 
 232     DECLARE_EVENT_TABLE() 
 235 #endif      // defined(__WXMSW__) 
 237 //----------------------------------------------------------------------------- 
 238 // wxDataViewRenameTimer 
 239 //----------------------------------------------------------------------------- 
 241 class wxDataViewRenameTimer
: public wxTimer
 
 244     wxDataViewMainWindow 
*m_owner
; 
 247     wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
); 
 251 //----------------------------------------------------------------------------- 
 252 // wxDataViewTreeNode 
 253 //----------------------------------------------------------------------------- 
 254 class wxDataViewTreeNode
;  
 255 WX_DEFINE_ARRAY_PTR( wxDataViewTreeNode 
*, wxDataViewTreeNodes 
); 
 257 class wxDataViewTreeNode
 
 260     wxDataViewTreeNode( wxDataViewTreeNode 
* parent 
) 
 261         { this->parent 
= parent
;  
 268     //I don't know what I need to do in the destructure 
 269     ~wxDataViewTreeNode() 
 272     wxDataViewTreeNode 
* GetParent() { return parent
; } 
 273     void SetParent( wxDataViewTreeNode 
* parent 
) { this->parent 
= parent
; } 
 274     wxDataViewTreeNodes 
&  GetChildren() { return children
; } 
 275     void SetChildren( wxDataViewTreeNodes  children 
) { this->children 
= children
; } 
 277     wxDataViewTreeNode 
* GetChild( unsigned int n 
) { return children
.Item( n 
); } 
 278     void InsertChild( wxDataViewTreeNode 
* child
, unsigned int n
) { children
.Insert( child
, n
); } 
 279     void AppendChild( wxDataViewTreeNode 
* child 
) { children
.Add( child 
); } 
 281     wxDataViewItem 
& GetItem() { return item
; } 
 282     void SetItem( wxDataViewItem 
& item 
) { this->item 
= item
; } 
 284     unsigned int GetChildrenNumber() { return children
.GetCount(); } 
 288          wxDataViewTreeNode 
* node 
= this; 
 289          while( node
->GetParent()->GetParent() != NULL 
) 
 291              node 
= node
->GetParent(); 
 297     bool IsOpen() { return open
; }  
 298     void ToggleOpen(){ open 
= !open
; } 
 299     bool HasChildren() { return hasChildren
; } 
 300     void SetHasChildren( bool has 
){ hasChildren 
= has
; } 
 302     wxDataViewTreeNode 
* parent
; 
 303     wxDataViewTreeNodes  children
;  
 309 //----------------------------------------------------------------------------- 
 310 // wxDataViewMainWindow 
 311 //----------------------------------------------------------------------------- 
 313 WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection
, 
 316 class wxDataViewMainWindow
: public wxWindow
 
 319     wxDataViewMainWindow( wxDataViewCtrl 
*parent
, 
 321                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 322                             const wxSize 
&size 
= wxDefaultSize
, 
 323                             const wxString 
&name 
= wxT("wxdataviewctrlmainwindow") ); 
 324     virtual ~wxDataViewMainWindow(); 
 326     // notifications from wxDataViewModel 
 327     bool ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
); 
 328     bool ItemDeleted( const wxDataViewItem 
&item 
); 
 329     bool ItemChanged( const wxDataViewItem 
&item 
); 
 330     bool ValueChanged( const wxDataViewItem 
&item
, unsigned int col 
); 
 333     void SetOwner( wxDataViewCtrl
* owner 
) { m_owner 
= owner
; } 
 334     wxDataViewCtrl 
*GetOwner() { return m_owner
; } 
 335     const wxDataViewCtrl 
*GetOwner() const { return m_owner
; } 
 337     void OnPaint( wxPaintEvent 
&event 
); 
 338     void OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
); 
 339     void OnChar( wxKeyEvent 
&event 
); 
 340     void OnMouse( wxMouseEvent 
&event 
); 
 341     void OnSetFocus( wxFocusEvent 
&event 
); 
 342     void OnKillFocus( wxFocusEvent 
&event 
); 
 344     void UpdateDisplay(); 
 345     void RecalculateDisplay(); 
 346     void OnInternalIdle(); 
 348     void OnRenameTimer(); 
 350     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
= NULL 
); 
 352     bool HasCurrentRow() { return m_currentRow 
!= (unsigned int)-1; } 
 353     void ChangeCurrentRow( unsigned int row 
); 
 355     bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE
); } 
 356     bool IsEmpty() { return GetRowCount() == 0; } 
 358     int GetCountPerPage() const; 
 359     int GetEndOfLastCol() const; 
 360     unsigned int GetFirstVisibleRow() const; 
 361     //I change this method to un const because in the tree view, the displaying number of the tree are changing along with the expanding/collapsing of the tree nodes 
 362     unsigned int GetLastVisibleRow(); 
 363     unsigned int GetRowCount() ; 
 365     wxDataViewItem 
GetSelection(); 
 367     void Select( const wxArrayInt
& aSelections 
); 
 368     void SelectAllRows( bool on 
); 
 369     void SelectRow( unsigned int row
, bool on 
); 
 370     void SelectRows( unsigned int from
, unsigned int to
, bool on 
); 
 371     void ReverseRowSelection( unsigned int row 
); 
 372     bool IsRowSelected( unsigned int row 
); 
 374     void RefreshRow( unsigned int row 
); 
 375     void RefreshRows( unsigned int from
, unsigned int to 
); 
 376     void RefreshRowsAfter( unsigned int firstRow 
); 
 378     // returns the colour to be used for drawing the rules 
 379     wxColour 
GetRuleColour() const 
 381         return wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT
); 
 384     //void EnsureVisible( unsigned int row ); 
 385     wxRect 
GetLineRect( unsigned int row 
) const; 
 387     //Some useful functions for row and item mapping 
 388     wxDataViewItem 
GetItemByRow( unsigned int row 
); 
 389     unsigned int GetRowByItem( const wxDataViewItem 
& item 
); 
 391     //Methods for building the mapping tree 
 392     void BuildTree( wxDataViewModel  
* model 
); 
 395     wxDataViewTreeNode 
* GetTreeNodeByRow( unsigned int row 
); 
 396     //We did not need this temporarily 
 397     //wxDataViewTreeNode * GetTreeNodeByItem( const wxDataViewItem & item ); 
 399     int RecalculateCount() ; 
 401     void OnExpanding( unsigned int row 
); 
 402     void OnCollapsing( unsigned int row 
); 
 405     wxDataViewCtrl             
*m_owner
; 
 409     wxDataViewColumn           
*m_currentCol
; 
 410     unsigned int                m_currentRow
; 
 411     wxDataViewSelection         m_selection
; 
 413     wxDataViewRenameTimer      
*m_renameTimer
; 
 421     // for double click logic 
 422     unsigned int m_lineLastClicked
, 
 423            m_lineBeforeLastClicked
, 
 424            m_lineSelectSingleOnUp
; 
 426     // the pen used to draw horiz/vertical rules 
 429     // the pen used to draw the expander and the lines 
 432     //This is the tree structure of the model 
 433     wxDataViewTreeNode 
* m_root
;  
 436     DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow
) 
 437     DECLARE_EVENT_TABLE() 
 440 // --------------------------------------------------------- 
 441 // wxGenericDataViewModelNotifier 
 442 // --------------------------------------------------------- 
 444 class wxGenericDataViewModelNotifier
: public wxDataViewModelNotifier
 
 447     wxGenericDataViewModelNotifier( wxDataViewMainWindow 
*mainWindow 
) 
 448         { m_mainWindow 
= mainWindow
; } 
 450     virtual bool ItemAdded( const wxDataViewItem 
& parent
, const wxDataViewItem 
& item 
) 
 451         { return m_mainWindow
->ItemAdded( parent 
, item 
); } 
 452     virtual bool ItemDeleted( const wxDataViewItem 
& item 
) 
 453         { return m_mainWindow
->ItemDeleted( item 
); } 
 454     virtual bool ItemChanged( const wxDataViewItem 
& item 
) 
 455         { return m_mainWindow
->ItemChanged(item
);  } 
 456     virtual bool ValueChanged( const wxDataViewItem 
& item 
, unsigned int col 
) 
 457         { return m_mainWindow
->ValueChanged( item
, col 
); } 
 458     virtual bool Cleared() 
 459         { return m_mainWindow
->Cleared(); } 
 461     wxDataViewMainWindow    
*m_mainWindow
; 
 464 // --------------------------------------------------------- 
 465 // wxDataViewRenderer 
 466 // --------------------------------------------------------- 
 468 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer
, wxDataViewRendererBase
) 
 470 wxDataViewRenderer::wxDataViewRenderer( const wxString 
&varianttype
, 
 471                                         wxDataViewCellMode mode
, 
 473     wxDataViewRendererBase( varianttype
, mode
, align 
) 
 480 wxDataViewRenderer::~wxDataViewRenderer() 
 486 wxDC 
*wxDataViewRenderer::GetDC() 
 490         if (GetOwner() == NULL
) 
 492         if (GetOwner()->GetOwner() == NULL
) 
 494         m_dc 
= new wxClientDC( GetOwner()->GetOwner() ); 
 500 // --------------------------------------------------------- 
 501 // wxDataViewCustomRenderer 
 502 // --------------------------------------------------------- 
 504 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer
, wxDataViewRenderer
) 
 506 wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString 
&varianttype
, 
 507                           wxDataViewCellMode mode
, int align 
) : 
 508     wxDataViewRenderer( varianttype
, mode
, align 
) 
 512 // --------------------------------------------------------- 
 513 // wxDataViewTextRenderer 
 514 // --------------------------------------------------------- 
 516 IMPLEMENT_CLASS(wxDataViewTextRenderer
, wxDataViewCustomRenderer
) 
 518 wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString 
&varianttype
, 
 519                                                 wxDataViewCellMode mode
, int align 
) : 
 520     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
 524 bool wxDataViewTextRenderer::SetValue( const wxVariant 
&value 
) 
 526     m_text 
= value
.GetString(); 
 531 bool wxDataViewTextRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) const 
 536 bool wxDataViewTextRenderer::HasEditorCtrl() 
 541 wxControl
* wxDataViewTextRenderer::CreateEditorCtrl( wxWindow 
*parent
, 
 542         wxRect labelRect
, const wxVariant 
&value 
) 
 544     return new wxTextCtrl( parent
, wxID_ANY
, value
,  
 545                            wxPoint(labelRect
.x
,labelRect
.y
), 
 546                            wxSize(labelRect
.width
,labelRect
.height
) ); 
 549 bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl 
*editor
, wxVariant 
&value 
) 
 551     wxTextCtrl 
*text 
= (wxTextCtrl
*) editor
; 
 552     value 
= text
->GetValue(); 
 556 bool wxDataViewTextRenderer::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
 558     wxDataViewCtrl 
*view 
= GetOwner()->GetOwner(); 
 559     wxColour col 
= (state 
& wxDATAVIEW_CELL_SELECTED
) ? 
 560                         wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) : 
 561                         view
->GetForegroundColour(); 
 563     dc
->SetTextForeground(col
); 
 564     dc
->DrawText( m_text
, cell
.x
, cell
.y 
); 
 569 wxSize 
wxDataViewTextRenderer::GetSize() const 
 571     const wxDataViewCtrl 
*view 
= GetView(); 
 575         view
->GetTextExtent( m_text
, &x
, &y 
); 
 576         return wxSize( x
, y 
); 
 578     return wxSize(80,20); 
 581 // --------------------------------------------------------- 
 582 // wxDataViewBitmapRenderer 
 583 // --------------------------------------------------------- 
 585 IMPLEMENT_CLASS(wxDataViewBitmapRenderer
, wxDataViewCustomRenderer
) 
 587 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString 
&varianttype
, 
 588                                                     wxDataViewCellMode mode
, int align 
) : 
 589     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
 593 bool wxDataViewBitmapRenderer::SetValue( const wxVariant 
&value 
) 
 595     if (value
.GetType() == wxT("wxBitmap")) 
 597     if (value
.GetType() == wxT("wxIcon")) 
 603 bool wxDataViewBitmapRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) const 
 608 bool wxDataViewBitmapRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 611         dc
->DrawBitmap( m_bitmap
, cell
.x
, cell
.y 
); 
 612     else if (m_icon
.Ok()) 
 613         dc
->DrawIcon( m_icon
, cell
.x
, cell
.y 
); 
 618 wxSize 
wxDataViewBitmapRenderer::GetSize() const 
 621         return wxSize( m_bitmap
.GetWidth(), m_bitmap
.GetHeight() ); 
 622     else if (m_icon
.Ok()) 
 623         return wxSize( m_icon
.GetWidth(), m_icon
.GetHeight() ); 
 625     return wxSize(16,16); 
 628 // --------------------------------------------------------- 
 629 // wxDataViewToggleRenderer 
 630 // --------------------------------------------------------- 
 632 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer
, wxDataViewCustomRenderer
) 
 634 wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString 
&varianttype
, 
 635                         wxDataViewCellMode mode
, int align 
) : 
 636     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
 641 bool wxDataViewToggleRenderer::SetValue( const wxVariant 
&value 
) 
 643     m_toggle 
= value
.GetBool(); 
 648 bool wxDataViewToggleRenderer::GetValue( wxVariant 
&WXUNUSED(value
) ) const 
 653 bool wxDataViewToggleRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 655     // User wxRenderer here 
 658     rect
.x 
= cell
.x 
+ cell
.width
/2 - 10; 
 660     rect
.y 
= cell
.y 
+ cell
.height
/2 - 10; 
 665         flags 
|= wxCONTROL_CHECKED
; 
 666     if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE
) 
 667         flags 
|= wxCONTROL_DISABLED
; 
 669     wxRendererNative::Get().DrawCheckBox( 
 670             GetOwner()->GetOwner(), 
 678 bool wxDataViewToggleRenderer::Activate( wxRect 
WXUNUSED(cell
), 
 679                                          wxDataViewModel 
*model
, 
 680                                          const wxDataViewItem 
& item
, unsigned int col
) 
 682     bool value 
= !m_toggle
; 
 683     wxVariant variant 
= value
; 
 684     model
->SetValue( variant
, item
, col
); 
 685     model
->ValueChanged( item
, col 
); 
 689 wxSize 
wxDataViewToggleRenderer::GetSize() const 
 691     return wxSize(20,20); 
 694 // --------------------------------------------------------- 
 695 // wxDataViewProgressRenderer 
 696 // --------------------------------------------------------- 
 698 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer
, wxDataViewCustomRenderer
) 
 700 wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString 
&label
, 
 701     const wxString 
&varianttype
, wxDataViewCellMode mode
, int align 
) : 
 702     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
 708 wxDataViewProgressRenderer::~wxDataViewProgressRenderer() 
 712 bool wxDataViewProgressRenderer::SetValue( const wxVariant 
&value 
) 
 714     m_value 
= (long) value
; 
 716     if (m_value 
< 0) m_value 
= 0; 
 717     if (m_value 
> 100) m_value 
= 100; 
 722 bool wxDataViewProgressRenderer::GetValue( wxVariant 
&value 
) const 
 724     value 
= (long) m_value
; 
 728 bool wxDataViewProgressRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 730     double pct 
= (double)m_value 
/ 100.0; 
 732     bar
.width 
= (int)(cell
.width 
* pct
); 
 733     dc
->SetPen( *wxTRANSPARENT_PEN 
); 
 734     dc
->SetBrush( *wxBLUE_BRUSH 
); 
 735     dc
->DrawRectangle( bar 
); 
 737     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
 738     dc
->SetPen( *wxBLACK_PEN 
); 
 739     dc
->DrawRectangle( cell 
); 
 744 wxSize 
wxDataViewProgressRenderer::GetSize() const 
 746     return wxSize(40,12); 
 749 // --------------------------------------------------------- 
 750 // wxDataViewDateRenderer 
 751 // --------------------------------------------------------- 
 753 #define wxUSE_DATE_RENDERER_POPUP (wxUSE_CALENDARCTRL && wxUSE_POPUPWIN) 
 755 #if wxUSE_DATE_RENDERER_POPUP 
 757 class wxDataViewDateRendererPopupTransient
: public wxPopupTransientWindow
 
 760     wxDataViewDateRendererPopupTransient( wxWindow
* parent
, wxDateTime 
*value
, 
 761         wxDataViewModel 
*model
, const wxDataViewItem 
& item
, unsigned int col
) : 
 762         wxPopupTransientWindow( parent
, wxBORDER_SIMPLE 
), 
 767         m_cal 
= new wxCalendarCtrl( this, wxID_ANY
, *value 
); 
 768         wxBoxSizer 
*sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 769         sizer
->Add( m_cal
, 1, wxGROW 
); 
 774     void OnCalendar( wxCalendarEvent 
&event 
); 
 776     wxCalendarCtrl      
*m_cal
; 
 777     wxDataViewModel 
*m_model
; 
 779     const wxDataViewItem 
&   m_item
; 
 782     virtual void OnDismiss() 
 787     DECLARE_EVENT_TABLE() 
 790 BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient
,wxPopupTransientWindow
) 
 791     EVT_CALENDAR( wxID_ANY
, wxDataViewDateRendererPopupTransient::OnCalendar 
) 
 794 void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent 
&event 
) 
 796     wxDateTime date 
= event
.GetDate(); 
 797     wxVariant value 
= date
; 
 798     m_model
->SetValue( value
, m_item
, m_col 
); 
 799     m_model
->ValueChanged( m_item
, m_col 
); 
 803 #endif // wxUSE_DATE_RENDERER_POPUP 
 805 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer
, wxDataViewCustomRenderer
) 
 807 wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString 
&varianttype
, 
 808                         wxDataViewCellMode mode
, int align 
) : 
 809     wxDataViewCustomRenderer( varianttype
, mode
, align 
) 
 813 bool wxDataViewDateRenderer::SetValue( const wxVariant 
&value 
) 
 815     m_date 
= value
.GetDateTime(); 
 820 bool wxDataViewDateRenderer::GetValue( wxVariant 
&value 
) const 
 826 bool wxDataViewDateRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 828     dc
->SetFont( GetOwner()->GetOwner()->GetFont() ); 
 829     wxString tmp 
= m_date
.FormatDate(); 
 830     dc
->DrawText( tmp
, cell
.x
, cell
.y 
); 
 835 wxSize 
wxDataViewDateRenderer::GetSize() const 
 837     const wxDataViewCtrl
* view 
= GetView(); 
 838     wxString tmp 
= m_date
.FormatDate(); 
 840     view
->GetTextExtent( tmp
, &x
, &y
, &d 
); 
 841     return wxSize(x
,y
+d
); 
 844 bool wxDataViewDateRenderer::Activate( wxRect 
WXUNUSED(cell
), wxDataViewModel 
*model
, 
 845                                        const wxDataViewItem 
& item
, unsigned int col 
) 
 848     model
->GetValue( variant
, item
, col 
); 
 849     wxDateTime value 
= variant
.GetDateTime(); 
 851 #if wxUSE_DATE_RENDERER_POPUP 
 852     wxDataViewDateRendererPopupTransient 
*popup 
= new wxDataViewDateRendererPopupTransient( 
 853         GetOwner()->GetOwner()->GetParent(), &value
, model
, item
, col
); 
 854     wxPoint pos 
= wxGetMousePosition(); 
 857     popup
->Popup( popup
->m_cal 
); 
 858 #else // !wxUSE_DATE_RENDERER_POPUP 
 859     wxMessageBox(value
.Format()); 
 860 #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP 
 864 // --------------------------------------------------------- 
 866 // --------------------------------------------------------- 
 868 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn
, wxDataViewColumnBase
) 
 870 wxDataViewColumn::wxDataViewColumn( const wxString 
&title
, wxDataViewRenderer 
*cell
, 
 871                                     unsigned int model_column
, 
 872                                     int width
, wxAlignment align
, int flags 
) : 
 873     wxDataViewColumnBase( title
, cell
, model_column
, width
, align
, flags 
) 
 879     Init(width 
< 0 ? wxDVC_DEFAULT_WIDTH 
: width
); 
 882 wxDataViewColumn::wxDataViewColumn( const wxBitmap 
&bitmap
, wxDataViewRenderer 
*cell
, 
 883                                     unsigned int model_column
, 
 884                                     int width
, wxAlignment align
, int flags 
) : 
 885     wxDataViewColumnBase( bitmap
, cell
, model_column
, width
, align
, flags 
) 
 890     Init(width 
< 0 ? wxDVC_TOGGLE_DEFAULT_WIDTH 
: width
); 
 893 wxDataViewColumn::~wxDataViewColumn() 
 897 void wxDataViewColumn::Init( int width 
) 
 900     m_minWidth 
= wxDVC_DEFAULT_MINWIDTH
; 
 904 void wxDataViewColumn::SetResizeable( bool resizeable 
) 
 907         m_flags 
|= wxDATAVIEW_COL_RESIZABLE
; 
 909         m_flags 
&= ~wxDATAVIEW_COL_RESIZABLE
; 
 912 void wxDataViewColumn::SetHidden( bool hidden 
) 
 915         m_flags 
|= wxDATAVIEW_COL_HIDDEN
; 
 917         m_flags 
&= ~wxDATAVIEW_COL_HIDDEN
; 
 919     // tell our owner to e.g. update its scrollbars: 
 921         GetOwner()->OnColumnChange(); 
 924 void wxDataViewColumn::SetSortable( bool sortable 
) 
 927         m_flags 
|= wxDATAVIEW_COL_SORTABLE
; 
 929         m_flags 
&= ~wxDATAVIEW_COL_SORTABLE
; 
 931     // Update header button 
 933         GetOwner()->OnColumnChange(); 
 936 void wxDataViewColumn::SetSortOrder( bool ascending 
) 
 938     m_ascending 
= ascending
; 
 940     // Update header button 
 942         GetOwner()->OnColumnChange(); 
 945 bool wxDataViewColumn::IsSortOrderAscending() const 
 950 void wxDataViewColumn::SetInternalWidth( int width 
) 
 954     // the scrollbars of the wxDataViewCtrl needs to be recalculated! 
 955     if (m_owner 
&& m_owner
->m_clientArea
) 
 956         m_owner
->m_clientArea
->RecalculateDisplay(); 
 959 void wxDataViewColumn::SetWidth( int width 
) 
 961     m_owner
->m_headerArea
->UpdateDisplay(); 
 963     SetInternalWidth(width
); 
 967 //----------------------------------------------------------------------------- 
 968 // wxDataViewHeaderWindowBase 
 969 //----------------------------------------------------------------------------- 
 971 void wxDataViewHeaderWindowBase::SendEvent(wxEventType type
, unsigned int n
) 
 973     wxWindow 
*parent 
= GetParent(); 
 974     wxDataViewEvent 
le(type
, parent
->GetId()); 
 976     le
.SetEventObject(parent
); 
 978     le
.SetDataViewColumn(GetColumn(n
)); 
 979     le
.SetModel(GetOwner()->GetModel()); 
 981     // for events created by wxDataViewHeaderWindow the 
 982     // row / value fields are not valid 
 984     parent
->GetEventHandler()->ProcessEvent(le
); 
 987 #if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW 
 989 // implemented in msw/listctrl.cpp: 
 990 int WXDLLIMPEXP_CORE 
wxMSWGetColumnClicked(NMHDR 
*nmhdr
, POINT 
*ptClick
); 
 992 IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindowMSW
, wxWindow
) 
 994 bool wxDataViewHeaderWindowMSW::Create( wxDataViewCtrl 
*parent
, wxWindowID id
, 
 995                                         const wxPoint 
&pos
, const wxSize 
&size
, 
 996                                         const wxString 
&name 
) 
1000     if ( !CreateControl(parent
, id
, pos
, size
, 0, wxDefaultValidator
, name
) ) 
1003     int x 
= pos
.x 
== wxDefaultCoord 
? 0 : pos
.x
, 
1004         y 
= pos
.y 
== wxDefaultCoord 
? 0 : pos
.y
, 
1005         w 
= size
.x 
== wxDefaultCoord 
? 1 : size
.x
, 
1006         h 
= size
.y 
== wxDefaultCoord 
? 22 : size
.y
; 
1008     // create the native WC_HEADER window: 
1009     WXHWND hwndParent 
= (HWND
)parent
->GetHandle(); 
1010     WXDWORD msStyle 
= WS_CHILD 
| HDS_BUTTONS 
| HDS_HORZ 
| HDS_HOTTRACK 
| HDS_FULLDRAG
; 
1011     m_hWnd 
= CreateWindowEx(0, 
1022         wxLogLastError(_T("CreateWindowEx")); 
1026     // we need to subclass the m_hWnd to force wxWindow::HandleNotify 
1027     // to call wxDataViewHeaderWindow::MSWOnNotify 
1028     SubclassWin(m_hWnd
); 
1030     // the following is required to get the default win's font for 
1031     // header windows and must be done befor sending the HDM_LAYOUT msg 
1038     // Retrieve the bounding rectangle of the parent window's 
1039     // client area, and then request size and position values 
1040     // from the header control. 
1041     ::GetClientRect((HWND
)hwndParent
, &rcParent
); 
1043     hdl
.prc 
= &rcParent
; 
1045     if (!SendMessage((HWND
)m_hWnd
, HDM_LAYOUT
, 0, (LPARAM
) &hdl
)) 
1047         wxLogLastError(_T("SendMessage")); 
1051     // Set the size, position, and visibility of the header control. 
1052     SetWindowPos((HWND
)m_hWnd
, 
1056                  wp
.flags 
| SWP_SHOWWINDOW
); 
1058     // set our size hints: wxDataViewCtrl will put this wxWindow inside 
1059     // a wxBoxSizer and in order to avoid super-big header windows, 
1060     // we need to set our height as fixed 
1061     SetMinSize(wxSize(-1, wp
.cy
)); 
1062     SetMaxSize(wxSize(-1, wp
.cy
)); 
1067 wxDataViewHeaderWindowMSW::~wxDataViewHeaderWindow() 
1072 void wxDataViewHeaderWindowMSW::UpdateDisplay() 
1074     // remove old columns 
1075     for (int j
=0, max
=Header_GetItemCount((HWND
)m_hWnd
); j 
< max
; j
++) 
1076         Header_DeleteItem((HWND
)m_hWnd
, 0); 
1078     // add the updated array of columns to the header control 
1079     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1080     unsigned int added 
= 0; 
1081     for (unsigned int i 
= 0; i 
< cols
; i
++) 
1083         wxDataViewColumn 
*col 
= GetColumn( i 
); 
1084         if (col
->IsHidden()) 
1085             continue;      // don't add it! 
1088         hdi
.mask 
= HDI_TEXT 
| HDI_FORMAT 
| HDI_WIDTH
; 
1089         hdi
.pszText 
= (wxChar 
*) col
->GetTitle().wx_str(); 
1090         hdi
.cxy 
= col
->GetWidth(); 
1091         hdi
.cchTextMax 
= sizeof(hdi
.pszText
)/sizeof(hdi
.pszText
[0]); 
1092         hdi
.fmt 
= HDF_LEFT 
| HDF_STRING
; 
1094         // lParam is reserved for application's use: 
1095         // we store there the column index to use it later in MSWOnNotify 
1096         // (since columns may have been hidden) 
1097         hdi
.lParam 
= (LPARAM
)i
; 
1099         // the native wxMSW implementation of the header window 
1100         // draws the column separator COLUMN_WIDTH_OFFSET pixels 
1101         // on the right: to correct this effect we make the column 
1102         // exactly COLUMN_WIDTH_OFFSET wider (for the first column): 
1104             hdi
.cxy 
+= COLUMN_WIDTH_OFFSET
; 
1106         switch (col
->GetAlignment()) 
1109             hdi
.fmt 
|= HDF_LEFT
; 
1111         case wxALIGN_CENTER
: 
1112         case wxALIGN_CENTER_HORIZONTAL
: 
1113             hdi
.fmt 
|= HDF_CENTER
; 
1116             hdi
.fmt 
|= HDF_RIGHT
; 
1120             // such alignment is not allowed for the column header! 
1124         SendMessage((HWND
)m_hWnd
, HDM_INSERTITEM
, 
1125                     (WPARAM
)added
, (LPARAM
)&hdi
); 
1130 unsigned int wxDataViewHeaderWindowMSW::GetColumnIdxFromHeader(NMHEADER 
*nmHDR
) 
1134     // NOTE: we don't just return nmHDR->iItem because when there are 
1135     //       hidden columns, nmHDR->iItem may be different from 
1136     //       nmHDR->pitem->lParam 
1138     if (nmHDR
->pitem 
&& nmHDR
->pitem
->mask 
& HDI_LPARAM
) 
1140         idx 
= (unsigned int)nmHDR
->pitem
->lParam
; 
1145     item
.mask 
= HDI_LPARAM
; 
1146     Header_GetItem((HWND
)m_hWnd
, nmHDR
->iItem
, &item
); 
1148     return (unsigned int)item
.lParam
; 
1151 bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
1153     NMHDR 
*nmhdr 
= (NMHDR 
*)lParam
; 
1155     // is it a message from the header? 
1156     if ( nmhdr
->hwndFrom 
!= (HWND
)m_hWnd 
) 
1157         return wxWindow::MSWOnNotify(idCtrl
, lParam
, result
); 
1159     NMHEADER 
*nmHDR 
= (NMHEADER 
*)nmhdr
; 
1160     switch ( nmhdr
->code 
) 
1162         case HDN_BEGINTRACK
: 
1163             // user has started to resize a column: 
1164             // do we need to veto it? 
1165             if (!GetColumn(nmHDR
->iItem
)->IsResizeable()) 
1173             // user has started to reorder a column 
1176         case HDN_ITEMCHANGING
: 
1177             if (nmHDR
->pitem 
!= NULL 
&& 
1178                 (nmHDR
->pitem
->mask 
& HDI_WIDTH
) != 0) 
1180                 int minWidth 
= GetColumnFromHeader(nmHDR
)->GetMinWidth(); 
1181                 if (nmHDR
->pitem
->cxy 
< minWidth
) 
1183                     // do not allow the user to resize this column under 
1184                     // its minimal width: 
1190         case HDN_ITEMCHANGED
:   // user is resizing a column 
1191         case HDN_ENDTRACK
:      // user has finished resizing a column 
1192         case HDN_ENDDRAG
:       // user has finished reordering a column 
1194             // update the width of the modified column: 
1195             if (nmHDR
->pitem 
!= NULL 
&& 
1196                 (nmHDR
->pitem
->mask 
& HDI_WIDTH
) != 0) 
1198                 unsigned int idx 
= GetColumnIdxFromHeader(nmHDR
); 
1199                 unsigned int w 
= nmHDR
->pitem
->cxy
; 
1200                 wxDataViewColumn 
*col 
= GetColumn(idx
); 
1202                 // see UpdateDisplay() for more info about COLUMN_WIDTH_OFFSET 
1203                 if (idx 
== 0 && w 
> COLUMN_WIDTH_OFFSET
) 
1204                     w 
-= COLUMN_WIDTH_OFFSET
; 
1206                 if (w 
>= (unsigned)col
->GetMinWidth()) 
1207                     col
->SetInternalWidth(w
); 
1213                 unsigned int idx 
= GetColumnIdxFromHeader(nmHDR
); 
1214                 wxEventType evt 
= nmHDR
->iButton 
== 0 ? 
1215                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK 
: 
1216                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
; 
1217                 SendEvent(evt
, idx
); 
1223                 // NOTE: for some reason (i.e. for a bug in Windows) 
1224                 //       the HDN_ITEMCLICK notification is not sent on 
1225                 //       right clicks, so we need to handle NM_RCLICK 
1228                 int column 
= wxMSWGetColumnClicked(nmhdr
, &ptClick
); 
1229                 if (column 
!= wxNOT_FOUND
) 
1232                     item
.mask 
= HDI_LPARAM
; 
1233                     Header_GetItem((HWND
)m_hWnd
, column
, &item
); 
1235                     // 'idx' may be different from 'column' if there are 
1236                     // hidden columns... 
1237                     unsigned int idx 
= (unsigned int)item
.lParam
; 
1238                     SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
, 
1244         case HDN_GETDISPINFOW
: 
1245             // see wxListCtrl::MSWOnNotify for more info! 
1248         case HDN_ITEMDBLCLICK
: 
1250                 unsigned int idx 
= GetColumnIdxFromHeader(nmHDR
); 
1251                 int w 
= GetOwner()->GetBestColumnWidth(idx
); 
1253                 // update the native control: 
1255                 ZeroMemory(&hd
, sizeof(hd
)); 
1256                 hd
.mask 
= HDI_WIDTH
; 
1258                 Header_SetItem(GetHwnd(), 
1259                                nmHDR
->iItem
,  // NOTE: we don't want 'idx' here! 
1262                 // update the wxDataViewColumn class: 
1263                 GetColumn(idx
)->SetInternalWidth(w
); 
1268             return wxWindow::MSWOnNotify(idCtrl
, lParam
, result
); 
1274 void wxDataViewHeaderWindowMSW::ScrollWindow(int WXUNUSED(dx
), int WXUNUSED(dy
), 
1275                                              const wxRect 
*WXUNUSED(rect
)) 
1277     wxSize ourSz 
= GetClientSize(); 
1278     wxSize ownerSz 
= m_owner
->GetClientSize(); 
1280     // where should the (logical) origin of this window be placed? 
1282     m_owner
->CalcUnscrolledPosition(0, 0, &x1
, &y1
); 
1284     // put this window on top of our parent and 
1285     SetWindowPos((HWND
)m_hWnd
, HWND_TOP
, -x1
, 0, 
1286                   ownerSz
.GetWidth() + x1
, ourSz
.GetHeight(), 
1290 void wxDataViewHeaderWindowMSW::DoSetSize(int WXUNUSED(x
), int WXUNUSED(y
), 
1291                                           int WXUNUSED(w
), int WXUNUSED(h
), 
1294     // the wxDataViewCtrl's internal wxBoxSizer will call this function when 
1295     // the wxDataViewCtrl window gets resized: the following dummy call 
1296     // to ScrollWindow() is required in order to get this header window 
1297     // correctly repainted when it's (horizontally) scrolled: 
1302 #else       // !defined(__WXMSW__) 
1304 IMPLEMENT_ABSTRACT_CLASS(wxGenericDataViewHeaderWindow
, wxWindow
) 
1305 BEGIN_EVENT_TABLE(wxGenericDataViewHeaderWindow
, wxWindow
) 
1306     EVT_PAINT         (wxGenericDataViewHeaderWindow::OnPaint
) 
1307     EVT_MOUSE_EVENTS  (wxGenericDataViewHeaderWindow::OnMouse
) 
1308     EVT_SET_FOCUS     (wxGenericDataViewHeaderWindow::OnSetFocus
) 
1311 bool wxGenericDataViewHeaderWindow::Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
1312                                            const wxPoint 
&pos
, const wxSize 
&size
, 
1313                                            const wxString 
&name 
) 
1317     if (!wxDataViewHeaderWindowBase::Create(parent
, id
, pos
, size
, name
)) 
1320     wxVisualAttributes attr 
= wxPanel::GetClassDefaultAttributes(); 
1321     SetBackgroundStyle( wxBG_STYLE_CUSTOM 
); 
1322     SetOwnForegroundColour( attr
.colFg 
); 
1323     SetOwnBackgroundColour( attr
.colBg 
); 
1325         SetOwnFont( attr
.font 
); 
1327     // set our size hints: wxDataViewCtrl will put this wxWindow inside 
1328     // a wxBoxSizer and in order to avoid super-big header windows, 
1329     // we need to set our height as fixed 
1330     SetMinSize(wxSize(-1, HEADER_WINDOW_HEIGHT
)); 
1331     SetMaxSize(wxSize(-1, HEADER_WINDOW_HEIGHT
)); 
1336 void wxGenericDataViewHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1339     GetClientSize( &w
, &h 
); 
1341     wxAutoBufferedPaintDC 
dc( this ); 
1343     dc
.SetBackground(GetBackgroundColour()); 
1347     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1350     m_owner
->GetViewStart( &x
, NULL 
); 
1352     // account for the horz scrollbar offset 
1353     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1355     dc
.SetFont( GetFont() ); 
1357     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1360     for (i 
= 0; i 
< cols
; i
++) 
1362         wxDataViewColumn 
*col 
= GetColumn( i 
); 
1363         if (col
->IsHidden()) 
1364             continue;      // skip it! 
1366         int cw 
= col
->GetWidth(); 
1369         wxHeaderSortIconType sortArrow 
= wxHDR_SORT_ICON_NONE
; 
1370         if (col
->IsSortable()) 
1372             if (col
->IsSortOrderAscending()) 
1373                 sortArrow 
= wxHDR_SORT_ICON_UP
; 
1375                 sortArrow 
= wxHDR_SORT_ICON_DOWN
; 
1378         wxRendererNative::Get().DrawHeaderButton
 
1382                                     wxRect(xpos
, 0, cw
, ch
-1), 
1383                                     m_parent
->IsEnabled() ? 0 
1384                                                           : (int)wxCONTROL_DISABLED
, 
1388         // align as required the column title: 
1390         wxSize titleSz 
= dc
.GetTextExtent(col
->GetTitle()); 
1391         switch (col
->GetAlignment()) 
1394             x 
+= HEADER_HORIZ_BORDER
; 
1396         case wxALIGN_CENTER
: 
1397         case wxALIGN_CENTER_HORIZONTAL
: 
1398             x 
+= (cw 
- titleSz
.GetWidth() - 2 * HEADER_HORIZ_BORDER
)/2; 
1401             x 
+= cw 
- titleSz
.GetWidth() - HEADER_HORIZ_BORDER
; 
1405         // always center the title vertically: 
1406         int y 
= wxMax((ch 
- titleSz
.GetHeight()) / 2, HEADER_VERT_BORDER
); 
1408         dc
.SetClippingRegion( xpos
+HEADER_HORIZ_BORDER
, 
1410                               wxMax(cw 
- 2 * HEADER_HORIZ_BORDER
, 1),  // width 
1411                               wxMax(ch 
- 2 * HEADER_VERT_BORDER
, 1));  // height 
1412         dc
.DrawText( col
->GetTitle(), x
, y 
); 
1413         dc
.DestroyClippingRegion(); 
1419 void wxGenericDataViewHeaderWindow::OnSetFocus( wxFocusEvent 
&event 
) 
1421     GetParent()->SetFocus(); 
1425 void wxGenericDataViewHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1427     // we want to work with logical coords 
1429     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1430     int y 
= event
.GetY(); 
1434         // we don't draw the line beyond our window, 
1435         // but we allow dragging it there 
1437         GetClientSize( &w
, NULL 
); 
1438         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1441         // erase the line if it was drawn 
1445         if (event
.ButtonUp()) 
1447             m_isDragging 
= false; 
1453             GetColumn(m_column
)->SetWidth(m_currentX 
- m_minX
); 
1456             GetOwner()->Refresh(); 
1460             m_currentX 
= wxMax(m_minX 
+ 7, x
); 
1462             // draw in the new location 
1463             if (m_currentX 
< w
) DrawCurrent(); 
1467     else     // not dragging 
1470         m_column 
= wxNOT_FOUND
; 
1472         bool hit_border 
= false; 
1474         // end of the current column 
1477         // find the column where this event occured 
1478         int countCol 
= m_owner
->GetColumnCount(); 
1479         for (int column 
= 0; column 
< countCol
; column
++) 
1481             wxDataViewColumn 
*p 
= GetColumn(column
); 
1484                 continue;   // skip if not shown 
1486             xpos 
+= p
->GetWidth(); 
1488             if ((abs(x
-xpos
) < 3) && (y 
< 22)) 
1496                 // inside the column 
1503         if (m_column 
== wxNOT_FOUND
) 
1506         bool resizeable 
= GetColumn(m_column
)->IsResizeable(); 
1507         if (event
.LeftDClick() && resizeable
) 
1509             GetColumn(m_column
)->SetWidth(GetOwner()->GetBestColumnWidth(m_column
)); 
1512         else if (event
.LeftDown() || event
.RightUp()) 
1514             if (hit_border 
&& event
.LeftDown() && resizeable
) 
1516                 m_isDragging 
= true; 
1521             else    // click on a column 
1523                 wxEventType evt 
= event
.LeftDown() ? 
1524                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK 
: 
1525                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
; 
1526                 SendEvent(evt
, m_column
); 
1529         else if (event
.Moving()) 
1531             if (hit_border 
&& resizeable
) 
1532                 m_currentCursor 
= m_resizeCursor
; 
1534                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1536             SetCursor(*m_currentCursor
); 
1541 void wxGenericDataViewHeaderWindow::DrawCurrent() 
1543     int x1 
= m_currentX
; 
1545     ClientToScreen (&x1
, &y1
); 
1547     int x2 
= m_currentX
-1; 
1549     ++x2
; // but why ???? 
1552     m_owner
->GetClientSize( NULL
, &y2 
); 
1553     m_owner
->ClientToScreen( &x2
, &y2 
); 
1556     dc
.SetLogicalFunction(wxINVERT
); 
1557     dc
.SetPen(m_penCurrent
); 
1558     dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1560     dc
.DrawLine(x1
, y1
, x2
, y2
); 
1563 void wxGenericDataViewHeaderWindow::AdjustDC(wxDC
& dc
) 
1567     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1568     m_owner
->GetViewStart( &x
, NULL 
); 
1570     // shift the DC origin to match the position of the main window horizontal 
1571     // scrollbar: this allows us to always use logical coords 
1572     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1575 #endif      // defined(__WXMSW__) 
1577 //----------------------------------------------------------------------------- 
1578 // wxDataViewRenameTimer 
1579 //----------------------------------------------------------------------------- 
1581 wxDataViewRenameTimer::wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
) 
1586 void wxDataViewRenameTimer::Notify() 
1588     m_owner
->OnRenameTimer(); 
1591 //----------------------------------------------------------------------------- 
1592 // wxDataViewMainWindow 
1593 //----------------------------------------------------------------------------- 
1595 //The tree building helper, declared firstly 
1596 void BuildTreeHelper( wxDataViewModel 
* model
,  wxDataViewItem 
& item
, wxDataViewTreeNode 
* node
); 
1598 int LINKAGEMODE 
wxDataViewSelectionCmp( unsigned int row1
, unsigned int row2 
) 
1600     if (row1 
> row2
) return 1; 
1601     if (row1 
== row2
) return 0; 
1606 IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow
, wxWindow
) 
1608 BEGIN_EVENT_TABLE(wxDataViewMainWindow
,wxWindow
) 
1609     EVT_PAINT         (wxDataViewMainWindow::OnPaint
) 
1610     EVT_MOUSE_EVENTS  (wxDataViewMainWindow::OnMouse
) 
1611     EVT_SET_FOCUS     (wxDataViewMainWindow::OnSetFocus
) 
1612     EVT_KILL_FOCUS    (wxDataViewMainWindow::OnKillFocus
) 
1613     EVT_CHAR          (wxDataViewMainWindow::OnChar
) 
1616 wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl 
*parent
, wxWindowID id
, 
1617     const wxPoint 
&pos
, const wxSize 
&size
, const wxString 
&name 
) : 
1618     wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
, name 
), 
1619     m_selection( wxDataViewSelectionCmp 
) 
1624     m_lastOnSame 
= false; 
1625     m_renameTimer 
= new wxDataViewRenameTimer( this ); 
1627     // TODO: user better initial values/nothing selected 
1628     m_currentCol 
= NULL
; 
1631     // TODO: we need to calculate this smartly 
1638     wxASSERT(m_lineHeight 
> 2*PADDING_TOPBOTTOM
); 
1641     m_dragStart 
= wxPoint(0,0); 
1642     m_lineLastClicked 
= (unsigned int) -1; 
1643     m_lineBeforeLastClicked 
= (unsigned int) -1; 
1644     m_lineSelectSingleOnUp 
= (unsigned int) -1; 
1648     SetBackgroundStyle( wxBG_STYLE_CUSTOM 
); 
1649     SetBackgroundColour( *wxWHITE 
); 
1651     m_penRule 
= wxPen(GetRuleColour(), 1, wxSOLID
); 
1653     //Here I compose a pen can draw black lines, maybe there are something system colour to use 
1654     m_penExpander 
= wxPen( wxColour(0,0,0), 1, wxSOLID 
); 
1655     //Some new added code to deal with the tree structure 
1656     m_root 
= new wxDataViewTreeNode( NULL 
); 
1657     m_root
->SetHasChildren(true); 
1659     //Make m_count = -1 will cause the class recaculate the real displaying number of rows. 
1664 wxDataViewMainWindow::~wxDataViewMainWindow() 
1667     delete m_renameTimer
; 
1670 void wxDataViewMainWindow::OnRenameTimer() 
1672     // We have to call this here because changes may just have 
1673     // been made and no screen update taken place. 
1678     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1680     for (i 
= 0; i 
< cols
; i
++) 
1682         wxDataViewColumn 
*c 
= GetOwner()->GetColumn( i 
); 
1684             continue;      // skip it! 
1686         if (c 
== m_currentCol
) 
1688         xpos 
+= c
->GetWidth(); 
1690     wxRect 
labelRect( xpos
, m_currentRow 
* m_lineHeight
, 
1691                       m_currentCol
->GetWidth(), m_lineHeight 
); 
1693     GetOwner()->CalcScrolledPosition( labelRect
.x
, labelRect
.y
, 
1694                                      &labelRect
.x
, &labelRect
.y
); 
1696     // TODO get wxDataViewItem from m_currentRow 
1697     m_currentCol
->GetRenderer()->StartEditing( m_currentRow
, labelRect 
); 
1700 //------------------------------------------------------------------ 
1701 // Helper class for do operation on the tree node 
1702 //------------------------------------------------------------------ 
1709     //The return value control how the tree-walker tranverse the tree 
1710     // 0: Job done, stop tranverse and return 
1711     // 1: Ignore the current node's subtree and continue 
1712     // 2: Job not done, continue 
1713     enum  { OK 
= 0 , IGR 
= 1, CONT 
= 2 }; 
1714     virtual int operator() ( wxDataViewTreeNode 
* node 
) = 0 ; 
1717 class ItemAddJob
: public DoJob
 
1720     ItemAddJob( const wxDataViewItem 
& parent
, const wxDataViewItem 
& item
, int * count 
) 
1721         { this->parent 
= parent 
; this->item 
= item 
; m_count 
= count
; } 
1722     virtual ~ItemAddJob(){}; 
1724     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
1726         if( node
->GetItem() == parent 
) 
1728             node
->SetHasChildren( true ); 
1729             wxDataViewTreeNode 
* newnode 
= new wxDataViewTreeNode( node 
); 
1730             newnode
->SetItem(item
); 
1731             node
->AppendChild( newnode
); 
1740     wxDataViewItem parent
, item
; 
1743 bool Walker( wxDataViewTreeNode 
* node
, DoJob 
& func 
) 
1745     if( node
==NULL 
||  !node
->HasChildren()) 
1748     wxDataViewTreeNodes nodes 
= node
->GetChildren(); 
1749     int len 
= node
->GetChildrenNumber(); 
1751     for( ; i 
< len 
; i 
++ ) 
1753         wxDataViewTreeNode 
* n 
= nodes
[i
]; 
1765         if( Walker( n 
, func 
) ) 
1771 bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem 
& parent
, const wxDataViewItem 
& item
) 
1773     ItemAddJob 
job( parent
, item
, &m_count
);  
1774     Walker( m_root 
, job
); 
1779 class ItemDeleteJob
: public DoJob
 
1782     ItemDeleteJob( const wxDataViewItem 
& item
, int * count 
) { m_item 
= item
; m_count 
= count
; } 
1783     virtual ~ItemDeleteJob(){} 
1784     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
1786         if( node
->GetItem() == m_item 
) 
1788             node
->GetParent()->GetChildren().Remove( node 
); 
1798     wxDataViewItem m_item
; 
1801 bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem 
& item
) 
1803     ItemDeleteJob 
job( item
, &m_count
); 
1804     Walker( m_root
, job
); 
1809 bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem 
& item
) 
1811     unsigned int row 
= GetRowByItem(item
); 
1816 bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem 
& item
, unsigned int WXUNUSED(col
) ) 
1818     // NOTE: to be valid, we cannot use e.g. INT_MAX - 1 
1819 /*#define MAX_VIRTUAL_WIDTH       100000 
1821     wxRect rect( 0, row*m_lineHeight, MAX_VIRTUAL_WIDTH, m_lineHeight ); 
1822     m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); 
1823     Refresh( true, &rect ); 
1827     unsigned int row 
= GetRowByItem(item
); 
1832 bool wxDataViewMainWindow::Cleared() 
1839 void wxDataViewMainWindow::UpdateDisplay() 
1844 void wxDataViewMainWindow::OnInternalIdle() 
1846     wxWindow::OnInternalIdle(); 
1850         RecalculateDisplay(); 
1855 void wxDataViewMainWindow::RecalculateDisplay() 
1857     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1864     int width 
= GetEndOfLastCol(); 
1865     int height 
= GetRowCount() * m_lineHeight
; 
1867     SetVirtualSize( width
, height 
); 
1868     GetOwner()->SetScrollRate( 10, m_lineHeight 
); 
1873 void wxDataViewMainWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
1875     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
1877     if (GetOwner()->m_headerArea
) 
1878         GetOwner()->m_headerArea
->ScrollWindow( dx
, 0 ); 
1881 void wxDataViewMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1883     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1884     wxAutoBufferedPaintDC 
dc( this ); 
1887     dc
.SetBackground(GetBackgroundColour()); 
1889     GetOwner()->PrepareDC( dc 
); 
1890     dc
.SetFont( GetFont() ); 
1892     wxRect update 
= GetUpdateRegion().GetBox(); 
1893     m_owner
->CalcUnscrolledPosition( update
.x
, update
.y
, &update
.x
, &update
.y 
); 
1895     // compute which items needs to be redrawn 
1896     unsigned int item_start 
= wxMax( 0, (update
.y 
/ m_lineHeight
) ); 
1897     unsigned int item_count 
= 
1898         wxMin( (int)(((update
.y 
+ update
.height
) / m_lineHeight
) - item_start 
+ 1), 
1899                (int)(GetRowCount( )- item_start
) ); 
1900     unsigned int item_last 
= item_start 
+ item_count
; 
1902     // compute which columns needs to be redrawn 
1903     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1904     unsigned int col_start 
= 0; 
1905     unsigned int x_start 
= 0; 
1906     for (x_start 
= 0; col_start 
< cols
; col_start
++) 
1908         wxDataViewColumn 
*col 
= GetOwner()->GetColumn(col_start
); 
1909         if (col
->IsHidden()) 
1910             continue;      // skip it! 
1912         unsigned int w 
= col
->GetWidth(); 
1913         if (x_start
+w 
>= (unsigned int)update
.x
) 
1919     unsigned int col_last 
= col_start
; 
1920     unsigned int x_last 
= x_start
; 
1921     for (; col_last 
< cols
; col_last
++) 
1923         wxDataViewColumn 
*col 
= GetOwner()->GetColumn(col_last
); 
1924         if (col
->IsHidden()) 
1925             continue;      // skip it! 
1927         if (x_last 
> (unsigned int)update
.GetRight()) 
1930         x_last 
+= col
->GetWidth(); 
1933     // Draw horizontal rules if required 
1934     if ( m_owner
->HasFlag(wxDV_HORIZ_RULES
) ) 
1936         dc
.SetPen(m_penRule
); 
1937         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1939         for (unsigned int i 
= item_start
; i 
<= item_last
+1; i
++) 
1941             int y 
= i 
* m_lineHeight
; 
1942             dc
.DrawLine(x_start
, y
, x_last
, y
); 
1946     // Draw vertical rules if required 
1947     if ( m_owner
->HasFlag(wxDV_VERT_RULES
) ) 
1949         dc
.SetPen(m_penRule
); 
1950         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1953         for (unsigned int i 
= col_start
; i 
< col_last
; i
++) 
1955             wxDataViewColumn 
*col 
= GetOwner()->GetColumn(i
); 
1956             if (col
->IsHidden()) 
1957                 continue;       // skip it 
1959             dc
.DrawLine(x
, item_start 
* m_lineHeight
, 
1960                         x
, item_last 
* m_lineHeight
); 
1962             x 
+= col
->GetWidth(); 
1965         // Draw last vertical rule 
1966         dc
.DrawLine(x
, item_start 
* m_lineHeight
, 
1967                     x
, item_last 
* m_lineHeight
); 
1970     // redraw the background for the items which are selected/current 
1971     for (unsigned int item 
= item_start
; item 
< item_last
; item
++) 
1973         bool selected 
= m_selection
.Index( item 
) != wxNOT_FOUND
; 
1974         if (selected 
|| item 
== m_currentRow
) 
1976             int flags 
= selected 
? (int)wxCONTROL_SELECTED 
: 0; 
1977             if (item 
== m_currentRow
) 
1978                 flags 
|= wxCONTROL_CURRENT
; 
1980                 flags 
|= wxCONTROL_FOCUSED
; 
1982             wxRect 
rect( x_start
, item
*m_lineHeight
, x_last
, m_lineHeight 
); 
1983             wxRendererNative::Get().DrawItemSelectionRect
 
1993     // redraw all cells for all rows which must be repainted and for all columns 
1995     cell_rect
.x 
= x_start
; 
1996     cell_rect
.height 
= m_lineHeight
;        // -1 is for the horizontal rules 
1997     for (unsigned int i 
= col_start
; i 
< col_last
; i
++) 
1999         wxDataViewColumn 
*col 
= GetOwner()->GetColumn( i 
); 
2000         wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
2001         cell_rect
.width 
= col
->GetWidth(); 
2003         if (col
->IsHidden()) 
2004             continue;       // skipt it! 
2006         for (unsigned int item 
= item_start
; item 
< item_last
; item
++) 
2008             // get the cell value and set it into the renderer 
2010              wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(item
); 
2014             wxDataViewItem dataitem 
= node
->GetItem(); 
2015              model
->GetValue( value
, dataitem
, col
->GetModelColumn()); 
2016             cell
->SetValue( value 
); 
2018             // update the y offset 
2019             cell_rect
.y 
= item 
* m_lineHeight
; 
2021             //Draw the expander here. Please notice that I use const number for all pixel data. When the final API are determined 
2022             //I will change this to the data member of the class wxDataViewCtrl 
2023             int indent 
= node
->GetIndentLevel(); 
2024             if( col
->GetModelColumn() == GetOwner()->GetExpanderColumn() ) 
2026                 //Calculate the indent first 
2027                 indent 
= cell_rect
.x 
+ GetOwner()->GetIndent() * indent
; 
2029                 int expander_width 
= m_lineHeight 
- 2*EXPANDER_MARGIN
; 
2030                 // change the cell_rect.x to the appropriate pos 
2031                 int  expander_x 
= indent 
+ EXPANDER_MARGIN 
, expander_y 
= cell_rect
.y 
+ EXPANDER_MARGIN 
; 
2032                 indent 
= indent 
+ m_lineHeight 
;  //try to use the m_lineHeight as the expander space 
2033                 dc
.SetPen( m_penExpander 
); 
2034                 dc
.SetBrush( wxNullBrush 
); 
2035                 if( node
->HasChildren() ) 
2037                     //dc.DrawRoundedRectangle( expander_x,expander_y,expander_width,expander_width, 1.0); 
2038                     //dc.DrawLine( expander_x + 2 , expander_y + expander_width/2, expander_x + expander_width - 2, expander_y + expander_width/2 ); 
2039                     wxRect 
rect( expander_x 
, expander_y
, expander_width
, expander_width
); 
2040                     if( node
->IsOpen() ) 
2041                         wxRendererNative::Get().DrawTreeItemButton( this, dc
, rect
, wxCONTROL_EXPANDED 
); 
2043                         wxRendererNative::Get().DrawTreeItemButton( this, dc
, rect 
); 
2047                  // I am wandering whether we should draw dot lines between tree nodes 
2050                  //force the expander column to left-center align 
2051                  cell
->SetAlignment( wxALIGN_CENTER_VERTICAL 
); 
2055             // cannot be bigger than allocated space  
2056             wxSize size 
= cell
->GetSize(); 
2057             // Because of the tree structure indent, here we should minus the width of the cell for drawing 
2058             size
.x 
= wxMin( size
.x 
+ 2*PADDING_RIGHTLEFT
, cell_rect
.width 
- indent 
); 
2059             size
.y 
= wxMin( size
.y 
+ 2*PADDING_TOPBOTTOM
, cell_rect
.height 
); 
2061             wxRect 
item_rect(cell_rect
.GetTopLeft(), size
); 
2062             int align 
= cell
->GetAlignment(); 
2064             // horizontal alignment: 
2065             item_rect
.x 
= cell_rect
.x
; 
2066             if (align 
& wxALIGN_CENTER_HORIZONTAL
) 
2067                 item_rect
.x 
= cell_rect
.x 
+ (cell_rect
.width 
/ 2) - (size
.x 
/ 2); 
2068             else if (align 
& wxALIGN_RIGHT
) 
2069                 item_rect
.x 
= cell_rect
.x 
+ cell_rect
.width 
- size
.x
; 
2070             //else: wxALIGN_LEFT is the default 
2072             // vertical alignment: 
2073             item_rect
.y 
= cell_rect
.y
; 
2074             if (align 
& wxALIGN_CENTER_VERTICAL
) 
2075                 item_rect
.y 
= cell_rect
.y 
+ (cell_rect
.height 
/ 2) - (size
.y 
/ 2); 
2076             else if (align 
& wxALIGN_BOTTOM
) 
2077                 item_rect
.y 
= cell_rect
.y 
+ cell_rect
.height 
- size
.y
; 
2078             //else: wxALIGN_TOP is the default 
2081             item_rect
.x 
+= PADDING_RIGHTLEFT
; 
2082             item_rect
.y 
+= PADDING_TOPBOTTOM
; 
2083             item_rect
.width 
= size
.x 
- 2 * PADDING_RIGHTLEFT
; 
2084             item_rect
.height 
= size
.y 
- 2 * PADDING_TOPBOTTOM
; 
2086             //Here we add the tree indent 
2087             item_rect
.x 
+= indent
; 
2090             if (m_selection
.Index(item
) != wxNOT_FOUND
) 
2091                 state 
|= wxDATAVIEW_CELL_SELECTED
; 
2093             // TODO: it would be much more efficient to create a clipping 
2094             //       region for the entire column being rendered (in the OnPaint 
2095             //       of wxDataViewMainWindow) instead of a single clip region for 
2096             //       each cell. However it would mean that each renderer should 
2097             //       respect the given wxRect's top & bottom coords, eventually 
2098             //       violating only the left & right coords - however the user can 
2099             //       make its own renderer and thus we cannot be sure of that. 
2100             dc
.SetClippingRegion( item_rect 
); 
2101             cell
->Render( item_rect
, &dc
, state 
); 
2102             dc
.DestroyClippingRegion(); 
2105         cell_rect
.x 
+= cell_rect
.width
; 
2109 int wxDataViewMainWindow::GetCountPerPage() const 
2111     wxSize size 
= GetClientSize(); 
2112     return size
.y 
/ m_lineHeight
; 
2115 int wxDataViewMainWindow::GetEndOfLastCol() const 
2119     for (i 
= 0; i 
< GetOwner()->GetColumnCount(); i
++) 
2121         const wxDataViewColumn 
*c 
= 
2122             wx_const_cast(wxDataViewCtrl
*, GetOwner())->GetColumn( i 
); 
2125             width 
+= c
->GetWidth(); 
2130 unsigned int wxDataViewMainWindow::GetFirstVisibleRow() const 
2134     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2136     return y 
/ m_lineHeight
; 
2139 unsigned int wxDataViewMainWindow::GetLastVisibleRow()  
2141     wxSize client_size 
= GetClientSize(); 
2142     m_owner
->CalcUnscrolledPosition( client_size
.x
, client_size
.y
, 
2143                                      &client_size
.x
, &client_size
.y 
); 
2145     return wxMin( GetRowCount()-1, ((unsigned)client_size
.y
/m_lineHeight
)+1 ); 
2148 unsigned int wxDataViewMainWindow::GetRowCount()  
2150     if ( m_count 
== -1 ) 
2152         m_count 
= RecalculateCount(); 
2154         GetVirtualSize( &width
, &height 
); 
2155         height 
= m_count 
* m_lineHeight
; 
2157         SetVirtualSize( width
, height 
); 
2162 void wxDataViewMainWindow::ChangeCurrentRow( unsigned int row 
) 
2169 void wxDataViewMainWindow::SelectAllRows( bool on 
) 
2176         m_selection
.Clear(); 
2177         for (unsigned int i 
= 0; i 
< GetRowCount(); i
++) 
2178             m_selection
.Add( i 
); 
2183         unsigned int first_visible 
= GetFirstVisibleRow(); 
2184         unsigned int last_visible 
= GetLastVisibleRow(); 
2186         for (i 
= 0; i 
< m_selection
.GetCount(); i
++) 
2188             unsigned int row 
= m_selection
[i
]; 
2189             if ((row 
>= first_visible
) && (row 
<= last_visible
)) 
2192         m_selection
.Clear(); 
2196 void wxDataViewMainWindow::SelectRow( unsigned int row
, bool on 
) 
2198     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
2202             m_selection
.Add( row 
); 
2210             m_selection
.Remove( row 
); 
2216 void wxDataViewMainWindow::SelectRows( unsigned int from
, unsigned int to
, bool on 
) 
2220         unsigned int tmp 
= from
; 
2226     for (i 
= from
; i 
<= to
; i
++) 
2228         if (m_selection
.Index( i 
) == wxNOT_FOUND
) 
2231                 m_selection
.Add( i 
); 
2236                 m_selection
.Remove( i 
); 
2239     RefreshRows( from
, to 
); 
2242 void wxDataViewMainWindow::Select( const wxArrayInt
& aSelections 
) 
2244     for (size_t i
=0; i 
< aSelections
.GetCount(); i
++) 
2246         int n 
= aSelections
[i
]; 
2248         m_selection
.Add( n 
); 
2253 void wxDataViewMainWindow::ReverseRowSelection( unsigned int row 
) 
2255     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
2256         m_selection
.Add( row 
); 
2258         m_selection
.Remove( row 
); 
2262 bool wxDataViewMainWindow::IsRowSelected( unsigned int row 
) 
2264     return (m_selection
.Index( row 
) != wxNOT_FOUND
); 
2267 void wxDataViewMainWindow::RefreshRow( unsigned int row 
) 
2269     wxRect 
rect( 0, row
*m_lineHeight
, GetEndOfLastCol(), m_lineHeight 
); 
2270     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2272     wxSize client_size 
= GetClientSize(); 
2273     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
2274     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
2275     if (intersect_rect
.width 
> 0) 
2276         Refresh( true, &intersect_rect 
); 
2279 void wxDataViewMainWindow::RefreshRows( unsigned int from
, unsigned int to 
) 
2283         unsigned int tmp 
= to
; 
2288     wxRect 
rect( 0, from
*m_lineHeight
, GetEndOfLastCol(), (to
-from
+1) * m_lineHeight 
); 
2289     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2291     wxSize client_size 
= GetClientSize(); 
2292     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
2293     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
2294     if (intersect_rect
.width 
> 0) 
2295         Refresh( true, &intersect_rect 
); 
2298 void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow 
) 
2300     unsigned int count 
= GetRowCount(); 
2301     if (firstRow 
> count
) 
2304     wxRect 
rect( 0, firstRow
*m_lineHeight
, GetEndOfLastCol(), count 
* m_lineHeight 
); 
2305     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2307     wxSize client_size 
= GetClientSize(); 
2308     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
2309     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
2310     if (intersect_rect
.width 
> 0) 
2311         Refresh( true, &intersect_rect 
); 
2314 void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
) 
2316     wxCHECK_RET( newCurrent 
< GetRowCount(), 
2317                  _T("invalid item index in OnArrowChar()") ); 
2319     // if there is no selection, we cannot move it anywhere 
2320     if (!HasCurrentRow()) 
2323     unsigned int oldCurrent 
= m_currentRow
; 
2325     // in single selection we just ignore Shift as we can't select several 
2327     if ( event
.ShiftDown() && !IsSingleSel() ) 
2329         RefreshRow( oldCurrent 
); 
2331         ChangeCurrentRow( newCurrent 
); 
2333         // select all the items between the old and the new one 
2334         if ( oldCurrent 
> newCurrent 
) 
2336             newCurrent 
= oldCurrent
; 
2337             oldCurrent 
= m_currentRow
; 
2340         SelectRows( oldCurrent
, newCurrent
, true ); 
2344         RefreshRow( oldCurrent 
); 
2346         // all previously selected items are unselected unless ctrl is held 
2347         if ( !event
.ControlDown() ) 
2348             SelectAllRows(false); 
2350         ChangeCurrentRow( newCurrent 
); 
2352         if ( !event
.ControlDown() ) 
2353             SelectRow( m_currentRow
, true ); 
2355             RefreshRow( m_currentRow 
); 
2358     //EnsureVisible( m_currentRow ); 
2361 wxRect 
wxDataViewMainWindow::GetLineRect( unsigned int row 
) const 
2365     rect
.y 
= m_lineHeight 
* row
; 
2366     rect
.width 
= GetEndOfLastCol(); 
2367     rect
.height 
= m_lineHeight
; 
2372 class RowToItemJob
: public DoJob
 
2375     RowToItemJob( unsigned int row 
, int current 
) { this->row 
= row
; this->current 
= current 
;} 
2376     virtual ~RowToItemJob(){}; 
2378     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
2380             if( current 
== static_cast<int>(row
)) 
2382                ret 
= node
->GetItem() ; 
2386            if ( node
->IsOpen()) 
2392     wxDataViewItem 
GetResult(){ return ret
; } 
2399 wxDataViewItem 
wxDataViewMainWindow::GetItemByRow(unsigned int row
) 
2401     RowToItemJob 
job( row
, 0 ); 
2402     Walker( m_root 
, job 
); 
2403     return job
.GetResult(); 
2406 class RowToTreeNodeJob
: public DoJob
 
2409     RowToTreeNodeJob( unsigned int row 
, int current 
) { this->row 
= row
; this->current 
= current 
; ret 
= NULL 
; } 
2410     virtual ~RowToTreeNodeJob(){}; 
2412     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
2414         if( current 
== static_cast<int>(row
)) 
2420         if ( node
->IsOpen()) 
2426     wxDataViewTreeNode 
* GetResult(){ return ret
; } 
2430     wxDataViewTreeNode 
* ret
; 
2434 wxDataViewTreeNode 
* wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row
) 
2436     RowToTreeNodeJob 
job( row 
, 0 ); 
2437     Walker( m_root 
, job 
); 
2438     return job
.GetResult(); 
2441 class CountJob 
: public DoJob
 
2444     CountJob(){ count 
= 0 ; } 
2445     virtual ~CountJob(){}; 
2447     virtual int operator () (  wxDataViewTreeNode 
* node 
) 
2450          if ( node
->IsOpen()) 
2456     unsigned int GetResult() 
2464 void wxDataViewMainWindow::OnExpanding( unsigned int row 
) 
2466     wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(row
); 
2469         if( node
->HasChildren()) 
2470             if( !node
->IsOpen()) 
2473                //Here I build the children of current node 
2474                if( node
->GetChildrenNumber() == 0 ) 
2475                    BuildTreeHelper(GetOwner()->GetModel(), node
->GetItem(), node
); 
2482 void wxDataViewMainWindow::OnCollapsing(unsigned int row
) 
2484     wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(row
); 
2487         if( node
->HasChildren() && node
->IsOpen() ) 
2492             //RefreshRows(row,GetLastVisibleRow()); 
2496              node 
= node
->GetParent(); 
2499                  int  parent 
= GetRowByItem( node
->GetItem()) ; 
2500                  SelectRow( row
, false); 
2501                  SelectRow(parent 
, true ); 
2502                  ChangeCurrentRow( parent 
); 
2508 int wxDataViewMainWindow::RecalculateCount()  
2511     Walker( m_root
, job 
); 
2512     return job
.GetResult(); 
2515 class ItemToRowJob 
: public DoJob
 
2518     ItemToRowJob(const wxDataViewItem 
& item
){ this->item 
= item 
; ret 
= 0 ; } 
2519     virtual ~ItemToRowJob(){}; 
2521     virtual int operator() ( wxDataViewTreeNode 
* node
) 
2524          if( node
->GetItem() == item 
) 
2533     //the row number is begin from zero 
2534     int GetResult(){ return ret 
-1 ; } 
2536     wxDataViewItem item
; 
2540 unsigned int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem 
& item
) 
2542     ItemToRowJob 
job( item 
); 
2543     Walker(m_root 
, job 
); 
2544     return job
.GetResult(); 
2547 void BuildTreeHelper( wxDataViewModel 
* model
,  wxDataViewItem 
& item
, wxDataViewTreeNode 
* node
) 
2549     if( !model
->HasChildren( item 
) ) 
2552     wxDataViewItem i 
= model
->GetFirstChild( item 
); 
2555         wxDataViewTreeNode 
* n 
= new wxDataViewTreeNode( node 
); 
2557         n
->SetHasChildren( model
->HasChildren( i 
)) ; 
2558         node
->AppendChild(n
); 
2559         //BuildTreeHelper( model, i, n) ;         
2560         i 
= model
->GetNextSibling( i 
); 
2564 void wxDataViewMainWindow::BuildTree(wxDataViewModel 
* model
) 
2566     //First we define a invalid item to fetch the top-level elements 
2567     wxDataViewItem item
; 
2568     BuildTreeHelper( model
, item
, m_root
); 
2572 void DestroyTreeHelper( wxDataViewTreeNode 
* node 
) 
2574     if( node
->HasChildren() ) 
2576         int len 
= node
->GetChildrenNumber(); 
2578         wxDataViewTreeNodes nodes 
= node
->GetChildren(); 
2579         for( ; i 
< len
; i 
++ ) 
2581             DestroyTreeHelper(nodes
[i
]); 
2587 void wxDataViewMainWindow::DestroyTree() 
2589     DestroyTreeHelper(m_root
); 
2593 void wxDataViewMainWindow::OnChar( wxKeyEvent 
&event 
) 
2595     if (event
.GetKeyCode() == WXK_TAB
) 
2597         wxNavigationKeyEvent nevent
; 
2598         nevent
.SetWindowChange( event
.ControlDown() ); 
2599         nevent
.SetDirection( !event
.ShiftDown() ); 
2600         nevent
.SetEventObject( GetParent()->GetParent() ); 
2601         nevent
.SetCurrentFocus( m_parent 
); 
2602         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) 
2606     // no item -> nothing to do 
2607     if (!HasCurrentRow()) 
2613     // don't use m_linesPerPage directly as it might not be computed yet 
2614     const int pageSize 
= GetCountPerPage(); 
2615     wxCHECK_RET( pageSize
, _T("should have non zero page size") ); 
2617     switch ( event
.GetKeyCode() ) 
2620             if ( m_currentRow 
> 0 ) 
2621                 OnArrowChar( m_currentRow 
- 1, event 
); 
2625             if ( m_currentRow 
< GetRowCount() - 1 ) 
2626                 OnArrowChar( m_currentRow 
+ 1, event 
); 
2628         //Add the process for tree expanding/collapsing 
2630              OnCollapsing(m_currentRow
); 
2633              OnExpanding( m_currentRow
); 
2637                 OnArrowChar( GetRowCount() - 1, event 
); 
2642                 OnArrowChar( 0, event 
); 
2647                 int steps 
= pageSize 
- 1; 
2648                 int index 
= m_currentRow 
- steps
; 
2652                 OnArrowChar( index
, event 
); 
2658                 int steps 
= pageSize 
- 1; 
2659                 unsigned int index 
= m_currentRow 
+ steps
; 
2660                 unsigned int count 
= GetRowCount(); 
2661                 if ( index 
>= count 
) 
2664                 OnArrowChar( index
, event 
); 
2673 void wxDataViewMainWindow::OnMouse( wxMouseEvent 
&event 
) 
2675     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
2677         // let the base handle mouse wheel events. 
2682     int x 
= event
.GetX(); 
2683     int y 
= event
.GetY(); 
2684     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2686     wxDataViewColumn 
*col 
= NULL
; 
2689     unsigned int cols 
= GetOwner()->GetColumnCount(); 
2691     for (i 
= 0; i 
< cols
; i
++) 
2693         wxDataViewColumn 
*c 
= GetOwner()->GetColumn( i 
); 
2695             continue;      // skip it! 
2697         if (x 
< xpos 
+ c
->GetWidth()) 
2702         xpos 
+= c
->GetWidth(); 
2706     wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
2708     unsigned int current 
= y 
/ m_lineHeight
; 
2710     if ((current 
> GetRowCount()) || (x 
> GetEndOfLastCol())) 
2712         // Unselect all if below the last row ? 
2716     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
2718     if (event
.Dragging()) 
2720         if (m_dragCount 
== 0) 
2722             // we have to report the raw, physical coords as we want to be 
2723             // able to call HitTest(event.m_pointDrag) from the user code to 
2724             // get the item being dragged 
2725             m_dragStart 
= event
.GetPosition(); 
2730         if (m_dragCount 
!= 3) 
2733         if (event
.LeftIsDown()) 
2735             // Notify cell about drag 
2744     bool forceClick 
= false; 
2746     if (event
.ButtonDClick()) 
2748         m_renameTimer
->Stop(); 
2749         m_lastOnSame 
= false; 
2752     if (event
.LeftDClick()) 
2754         if ( current 
== m_lineLastClicked 
) 
2756             if (cell
->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE
) 
2759                 model
->GetValue( value
, col
->GetModelColumn(), current 
); 
2760                 cell
->SetValue( value 
); 
2761                 wxRect 
cell_rect( xpos
, current 
* m_lineHeight
, 
2762                                   col
->GetWidth(), m_lineHeight 
); 
2763                   wxDataViewItem dataitem 
= GetItemByRow(current
); 
2764                 cell
->Activate( cell_rect
, model
, dataitem
, col
->GetModelColumn() ); 
2770             // The first click was on another item, so don't interpret this as 
2771             // a double click, but as a simple click instead 
2778         if (m_lineSelectSingleOnUp 
!= (unsigned int)-1) 
2780             // select single line 
2781             SelectAllRows( false ); 
2782             SelectRow( m_lineSelectSingleOnUp
, true ); 
2785         //Process the event of user clicking the expander 
2786         bool expander 
= false; 
2787         wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(current
); 
2788         if( node
!=NULL 
&& node
->HasChildren() ) 
2790             int indent 
= node
->GetIndentLevel(); 
2791             indent 
= GetOwner()->GetIndent()*indent
; 
2792             wxRect 
rect( xpos 
+ indent 
+ EXPANDER_MARGIN
, current 
* m_lineHeight 
+ EXPANDER_MARGIN
, m_lineHeight
-2*EXPANDER_MARGIN
,m_lineHeight
-2*EXPANDER_MARGIN
); 
2793             if( rect
.Contains( x
, y
) ) 
2796                 if( node
->IsOpen() ) 
2797                     OnCollapsing(current
); 
2799                     OnExpanding( current 
); 
2803         //If the user click the expander, we do not do editing even if the column with expander are editable 
2804         if (m_lastOnSame 
&& !expander 
) 
2806             if ((col 
== m_currentCol
) && (current 
== m_currentRow
) && 
2807                 (cell
->GetMode() == wxDATAVIEW_CELL_EDITABLE
) ) 
2809                 m_renameTimer
->Start( 100, true ); 
2813         m_lastOnSame 
= false; 
2814         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
2818         // This is necessary, because after a DnD operation in 
2819         // from and to ourself, the up event is swallowed by the 
2820         // DnD code. So on next non-up event (which means here and 
2821         // now) m_lineSelectSingleOnUp should be reset. 
2822         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
2825     if (event
.RightDown()) 
2827         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2828         m_lineLastClicked 
= current
; 
2830         // If the item is already selected, do not update the selection. 
2831         // Multi-selections should not be cleared if a selected item is clicked. 
2832         if (!IsRowSelected(current
)) 
2834             SelectAllRows(false); 
2835             ChangeCurrentRow(current
); 
2836             SelectRow(m_currentRow
,true); 
2839         // notify cell about right click 
2842         // Allow generation of context menu event 
2845     else if (event
.MiddleDown()) 
2847         // notify cell about middle click 
2850     if (event
.LeftDown() || forceClick
) 
2856         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2857         m_lineLastClicked 
= current
; 
2859         unsigned int oldCurrentRow 
= m_currentRow
; 
2860         bool oldWasSelected 
= IsRowSelected(m_currentRow
); 
2862         bool cmdModifierDown 
= event
.CmdDown(); 
2863         if ( IsSingleSel() || !(cmdModifierDown 
|| event
.ShiftDown()) ) 
2865             if ( IsSingleSel() || !IsRowSelected(current
) ) 
2867                 SelectAllRows( false ); 
2869                 ChangeCurrentRow(current
); 
2871                 SelectRow(m_currentRow
,true); 
2873             else // multi sel & current is highlighted & no mod keys 
2875                 m_lineSelectSingleOnUp 
= current
; 
2876                 ChangeCurrentRow(current
); // change focus 
2879         else // multi sel & either ctrl or shift is down 
2881             if (cmdModifierDown
) 
2883                 ChangeCurrentRow(current
); 
2885                 ReverseRowSelection(m_currentRow
); 
2887             else if (event
.ShiftDown()) 
2889                 ChangeCurrentRow(current
); 
2891                 unsigned int lineFrom 
= oldCurrentRow
, 
2894                 if ( lineTo 
< lineFrom 
) 
2897                     lineFrom 
= m_currentRow
; 
2900                 SelectRows(lineFrom
, lineTo
, true); 
2902             else // !ctrl, !shift 
2904                 // test in the enclosing if should make it impossible 
2905                 wxFAIL_MSG( _T("how did we get here?") ); 
2909         if (m_currentRow 
!= oldCurrentRow
) 
2910             RefreshRow( oldCurrentRow 
); 
2912         wxDataViewColumn 
*oldCurrentCol 
= m_currentCol
; 
2914         // Update selection here... 
2917         m_lastOnSame 
= !forceClick 
&& ((col 
== oldCurrentCol
) && 
2918                         (current 
== oldCurrentRow
)) && oldWasSelected
; 
2922 void wxDataViewMainWindow::OnSetFocus( wxFocusEvent 
&event 
) 
2926     if (HasCurrentRow()) 
2932 void wxDataViewMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
2936     if (HasCurrentRow()) 
2942 wxDataViewItem 
wxDataViewMainWindow::GetSelection() 
2944     if( m_selection
.GetCount() != 1 ) 
2945         return wxDataViewItem(); 
2946     return GetItemByRow( m_selection
.Item( 0 ) ); 
2949 //----------------------------------------------------------------------------- 
2951 //----------------------------------------------------------------------------- 
2953 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
2955 BEGIN_EVENT_TABLE(wxDataViewCtrl
, wxDataViewCtrlBase
) 
2956     EVT_SIZE(wxDataViewCtrl::OnSize
) 
2959 wxDataViewCtrl::~wxDataViewCtrl() 
2962         GetModel()->RemoveNotifier( m_notifier 
); 
2965 void wxDataViewCtrl::Init() 
2970 bool wxDataViewCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
2971            const wxPoint
& pos
, const wxSize
& size
, 
2972            long style
, const wxValidator
& validator 
) 
2974     if (!wxControl::Create( parent
, id
, pos
, size
, 
2975                             style 
| wxScrolledWindowStyle
|wxSUNKEN_BORDER
, validator
)) 
2981     MacSetClipChildren( true ) ; 
2984     m_clientArea 
= new wxDataViewMainWindow( this, wxID_ANY 
); 
2986     if (HasFlag(wxDV_NO_HEADER
)) 
2987         m_headerArea 
= NULL
; 
2989         m_headerArea 
= new wxDataViewHeaderWindow( this, wxID_ANY 
); 
2991     SetTargetWindow( m_clientArea 
); 
2993     wxBoxSizer 
*sizer 
= new wxBoxSizer( wxVERTICAL 
); 
2995         sizer
->Add( m_headerArea
, 0, wxGROW 
); 
2996     sizer
->Add( m_clientArea
, 1, wxGROW 
); 
3003 WXLRESULT 
wxDataViewCtrl::MSWWindowProc(WXUINT nMsg
, 
3007     WXLRESULT rc 
= wxDataViewCtrlBase::MSWWindowProc(nMsg
, wParam
, lParam
); 
3010     // we need to process arrows ourselves for scrolling 
3011     if ( nMsg 
== WM_GETDLGCODE 
) 
3013         rc 
|= DLGC_WANTARROWS
; 
3021 void wxDataViewCtrl::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
3023     // We need to override OnSize so that our scrolled 
3024     // window a) does call Layout() to use sizers for 
3025     // positioning the controls but b) does not query 
3026     // the sizer for their size and use that for setting 
3027     // the scrollable area as set that ourselves by 
3028     // calling SetScrollbar() further down. 
3035 bool wxDataViewCtrl::AssociateModel( wxDataViewModel 
*model 
) 
3037     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
3040     m_notifier 
= new wxGenericDataViewModelNotifier( m_clientArea 
); 
3042     model
->AddNotifier( m_notifier 
); 
3044     m_clientArea
->BuildTree(model
); 
3046     m_clientArea
->UpdateDisplay(); 
3051 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn 
*col 
) 
3053     if (!wxDataViewCtrlBase::AppendColumn(col
)) 
3060 void wxDataViewCtrl::OnColumnChange() 
3063         m_headerArea
->UpdateDisplay(); 
3065     m_clientArea
->UpdateDisplay(); 
3068 void wxDataViewCtrl::DoSetExpanderColumn() 
3070     m_clientArea
->UpdateDisplay(); 
3073 void wxDataViewCtrl::DoSetIndent() 
3075     m_clientArea
->UpdateDisplay(); 
3078 wxDataViewItem 
wxDataViewCtrl::GetSelection()  
3080     return m_clientArea
->GetSelection(); 
3083 /******************************************************************** 
3084 void wxDataViewCtrl::SetSelection( int row ) 
3086     m_clientArea->SelectRow(row, true); 
3089 void wxDataViewCtrl::SetSelectionRange( unsigned int from, unsigned int to ) 
3091     m_clientArea->SelectRows(from, to, true); 
3094 void wxDataViewCtrl::SetSelections( const wxArrayInt& aSelections ) 
3096     m_clientArea->Select(aSelections); 
3099 void wxDataViewCtrl::Unselect( unsigned int WXUNUSED(row) ) 
3104 bool wxDataViewCtrl::IsSelected( unsigned int WXUNUSED(row) ) const 
3111 int wxDataViewCtrl::GetSelection() const 
3118 int wxDataViewCtrl::GetSelections(wxArrayInt& WXUNUSED(aSelections) ) const 
3124 *********************************************************************/ 
3126     // !wxUSE_GENERICDATAVIEWCTRL 
3129     // wxUSE_DATAVIEWCTRL