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" 
  38 #include "wx/stockitem.h" 
  39 #include "wx/calctrl.h" 
  40 #include "wx/popupwin.h" 
  41 #include "wx/renderer.h" 
  42 #include "wx/dcbuffer.h" 
  45 //----------------------------------------------------------------------------- 
  47 //----------------------------------------------------------------------------- 
  51 //----------------------------------------------------------------------------- 
  52 // wxDataViewHeaderWindow 
  53 //----------------------------------------------------------------------------- 
  55 #define USE_NATIVE_HEADER_WINDOW    1 
  57 class wxDataViewHeaderWindowBase 
: public wxControl
 
  60     wxDataViewHeaderWindowBase() 
  63     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
  64                 const wxPoint 
&pos
, const wxSize 
&size
,  
  67         return wxWindow::Create(parent
, id
, pos
, size
, wxNO_BORDER
, name
); 
  70     void SetOwner( wxDataViewCtrl
* owner 
) { m_owner 
= owner
; } 
  71     wxDataViewCtrl 
*GetOwner() { return m_owner
; } 
  73     // called on column addition/removal 
  74     virtual void UpdateDisplay() { /* by default, do nothing */ } 
  76     // updates the n-th column's width 
  77     virtual void SetColumnWidth(unsigned int n
, int width
); 
  79     // returns the n-th column 
  80     wxDataViewColumn 
*GetColumn(unsigned int n
) 
  83         wxDataViewColumn 
*ret 
= m_owner
->GetColumn(n
);  
  90     wxDataViewCtrl      
*m_owner
; 
  92     // sends an event generated from the n-th wxDataViewColumn 
  93     void SendEvent(wxEventType type
, unsigned int n
); 
  96 // on wxMSW the header window (only that part however) can be made native! 
  97 #if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW 
  99 #define wxDataViewHeaderWindowMSW   wxDataViewHeaderWindow 
 101 class wxDataViewHeaderWindowMSW 
: public wxDataViewHeaderWindowBase
 
 105     wxDataViewHeaderWindowMSW( wxDataViewCtrl 
*parent
, 
 107                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 108                             const wxSize 
&size 
= wxDefaultSize
, 
 109                                 const wxString 
&name 
= wxT("wxdataviewctrlheaderwindow") ) 
 111         Create(parent
, id
, pos
, size
, name
); 
 114     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
 115                 const wxPoint 
&pos
, const wxSize 
&size
,  
 116                 const wxString 
&name
); 
 118     ~wxDataViewHeaderWindowMSW(); 
 120     // called on column addition/removal 
 121     virtual void UpdateDisplay(); 
 123     // called when the main window gets scrolled 
 124     virtual void ScrollWindow(int dx
, int dy
, const wxRect 
*rect 
= NULL
); 
 127     virtual bool MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
); 
 130     DECLARE_DYNAMIC_CLASS(wxDataViewHeaderWindowMSW
) 
 133 #else       // !defined(__WXMSW__) 
 135 #define HEADER_WINDOW_HEIGHT            25 
 136 #define wxGenericDataViewHeaderWindow   wxDataViewHeaderWindow 
 138 class wxGenericDataViewHeaderWindow 
: public wxDataViewHeaderWindowBase
 
 141     wxGenericDataViewHeaderWindow( wxDataViewCtrl 
*parent
, 
 143                                     const wxPoint 
&pos 
= wxDefaultPosition
, 
 144                                     const wxSize 
&size 
= wxDefaultSize
, 
 145                                     const wxString 
&name 
= wxT("wxdataviewctrlheaderwindow") ) 
 148         Create(parent
, id
, pos
, size
, name
); 
 151     bool Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
 152                 const wxPoint 
&pos
, const wxSize 
&size
,  
 153                 const wxString 
&name
); 
 155     ~wxGenericDataViewHeaderWindow() 
 157         delete m_resizeCursor
; 
 162     void OnPaint( wxPaintEvent 
&event 
); 
 163     void OnMouse( wxMouseEvent 
&event 
); 
 164     void OnSetFocus( wxFocusEvent 
&event 
); 
 169     // vars used for column resizing: 
 171     wxCursor            
*m_resizeCursor
; 
 172     const wxCursor      
*m_currentCursor
; 
 175     bool                 m_dirty
;     // needs refresh? 
 176     int                  m_column
;    // index of the column being resized 
 177     int                  m_currentX
;  // divider line position in logical (unscrolled) coords 
 178     int                  m_minX
;      // minimal position beyond which the divider line  
 179                                       // can't be dragged in logical coords 
 181     // internal utilities: 
 185         m_currentCursor 
= (wxCursor 
*) NULL
; 
 186         m_resizeCursor 
= new wxCursor( wxCURSOR_SIZEWE 
); 
 188         m_isDragging 
= false; 
 191         m_column 
= wxNOT_FOUND
; 
 197     void AdjustDC(wxDC
& dc
); 
 200     DECLARE_DYNAMIC_CLASS(wxGenericDataViewHeaderWindow
) 
 201     DECLARE_EVENT_TABLE() 
 204 #endif      // defined(__WXMSW__) 
 206 //----------------------------------------------------------------------------- 
 207 // wxDataViewRenameTimer 
 208 //----------------------------------------------------------------------------- 
 210 class wxDataViewRenameTimer
: public wxTimer
 
 213     wxDataViewMainWindow 
*m_owner
; 
 216     wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
); 
 220 //----------------------------------------------------------------------------- 
 221 // wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing 
 222 //----------------------------------------------------------------------------- 
 224 class wxDataViewTextCtrlWrapper 
: public wxEvtHandler
 
 227     // NB: text must be a valid object but not Create()d yet 
 228     wxDataViewTextCtrlWrapper( wxDataViewMainWindow 
*owner
, 
 230                                wxDataViewListModel 
*model
, 
 231                                unsigned int col
, unsigned int row
, 
 234     wxTextCtrl 
*GetText() const { return m_text
; } 
 236     void AcceptChangesAndFinish(); 
 239     void OnChar( wxKeyEvent 
&event 
); 
 240     void OnKeyUp( wxKeyEvent 
&event 
); 
 241     void OnKillFocus( wxFocusEvent 
&event 
); 
 243     bool AcceptChanges(); 
 247     wxDataViewMainWindow   
*m_owner
; 
 249     wxString                m_startValue
; 
 250     wxDataViewListModel    
*m_model
; 
 254     bool                    m_aboutToFinish
; 
 256     DECLARE_EVENT_TABLE() 
 259 //----------------------------------------------------------------------------- 
 260 // wxDataViewMainWindow 
 261 //----------------------------------------------------------------------------- 
 263 WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection
,  
 266 class wxDataViewMainWindow
: public wxWindow
 
 269     wxDataViewMainWindow( wxDataViewCtrl 
*parent
, 
 271                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 272                             const wxSize 
&size 
= wxDefaultSize
, 
 273                             const wxString 
&name 
= wxT("wxdataviewctrlmainwindow") ); 
 274     virtual ~wxDataViewMainWindow(); 
 276     // notifications from wxDataViewListModel 
 279     bool RowInserted( unsigned int before 
); 
 280     bool RowDeleted( unsigned int row 
); 
 281     bool RowChanged( unsigned int row 
); 
 282     bool ValueChanged( unsigned int col
, unsigned int row 
); 
 283     bool RowsReordered( unsigned int *new_order 
); 
 286     void SetOwner( wxDataViewCtrl
* owner 
) { m_owner 
= owner
; } 
 287     wxDataViewCtrl 
*GetOwner() { return m_owner
; } 
 289     void OnPaint( wxPaintEvent 
&event 
); 
 290     void OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
); 
 291     void OnChar( wxKeyEvent 
&event 
); 
 292     void OnMouse( wxMouseEvent 
&event 
); 
 293     void OnSetFocus( wxFocusEvent 
&event 
); 
 294     void OnKillFocus( wxFocusEvent 
&event 
); 
 296     void UpdateDisplay(); 
 297     void RecalculateDisplay(); 
 298     void OnInternalIdle(); 
 300     void OnRenameTimer(); 
 301     void FinishEditing( wxTextCtrl 
*text 
); 
 303     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
); 
 305     bool HasCurrentRow() { return m_currentRow 
!= (unsigned int)-1; } 
 306     void ChangeCurrentRow( unsigned int row 
); 
 308     bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE
); }; 
 309     bool IsEmpty() { return GetRowCount() == 0; } 
 311     int GetCountPerPage(); 
 312     int GetEndOfLastCol(); 
 313     unsigned int GetFirstVisibleRow(); 
 314     unsigned int GetLastVisibleRow(); 
 315     unsigned int GetRowCount(); 
 317     void Select( const wxArrayInt
& aSelections 
); 
 318     void SelectAllRows( bool on 
); 
 319     void SelectRow( unsigned int row
, bool on 
); 
 320     void SelectRows( unsigned int from
, unsigned int to
, bool on 
); 
 321     void ReverseRowSelection( unsigned int row 
); 
 322     bool IsRowSelected( unsigned int row 
); 
 324     void RefreshRow( unsigned int row 
); 
 325     void RefreshRows( unsigned int from
, unsigned int to 
); 
 326     void RefreshRowsAfter( unsigned int firstRow 
); 
 329     wxDataViewCtrl             
*m_owner
; 
 333     wxDataViewColumn           
*m_currentCol
; 
 334     unsigned int                      m_currentRow
; 
 335     wxDataViewSelection         m_selection
; 
 337     wxDataViewRenameTimer      
*m_renameTimer
; 
 338     wxDataViewTextCtrlWrapper  
*m_textctrlWrapper
; 
 346     // for double click logic 
 347     unsigned int m_lineLastClicked
, 
 348            m_lineBeforeLastClicked
, 
 349            m_lineSelectSingleOnUp
; 
 352     DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow
) 
 353     DECLARE_EVENT_TABLE() 
 356 // --------------------------------------------------------- 
 357 // wxGenericDataViewListModelNotifier 
 358 // --------------------------------------------------------- 
 360 class wxGenericDataViewListModelNotifier
: public wxDataViewListModelNotifier
 
 363     wxGenericDataViewListModelNotifier( wxDataViewMainWindow 
*mainWindow 
) 
 364         { m_mainWindow 
= mainWindow
; } 
 366     virtual bool RowAppended() 
 367         { return m_mainWindow
->RowAppended(); } 
 368     virtual bool RowPrepended() 
 369         { return m_mainWindow
->RowPrepended(); } 
 370     virtual bool RowInserted( unsigned int before 
) 
 371         { return m_mainWindow
->RowInserted( before 
); } 
 372     virtual bool RowDeleted( unsigned int row 
) 
 373         { return m_mainWindow
->RowDeleted( row 
); } 
 374     virtual bool RowChanged( unsigned int row 
) 
 375         { return m_mainWindow
->RowChanged( row 
); } 
 376     virtual bool ValueChanged( unsigned int col
, unsigned int row 
) 
 377         { return m_mainWindow
->ValueChanged( col
, row 
); } 
 378     virtual bool RowsReordered( unsigned int *new_order 
) 
 379         { return m_mainWindow
->RowsReordered( new_order 
); } 
 380     virtual bool Cleared() 
 381         { return m_mainWindow
->Cleared(); } 
 383     wxDataViewMainWindow    
*m_mainWindow
; 
 386 // --------------------------------------------------------- 
 387 // wxDataViewRenderer 
 388 // --------------------------------------------------------- 
 390 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer
, wxDataViewRendererBase
) 
 392 wxDataViewRenderer::wxDataViewRenderer( const wxString 
&varianttype
,  
 393                                         wxDataViewCellMode mode 
) : 
 394     wxDataViewRendererBase( varianttype
, mode 
) 
 399 wxDataViewRenderer::~wxDataViewRenderer() 
 405 wxDC 
*wxDataViewRenderer::GetDC() 
 409         if (GetOwner() == NULL
) 
 411         if (GetOwner()->GetOwner() == NULL
) 
 413         m_dc 
= new wxClientDC( GetOwner()->GetOwner() ); 
 419 // --------------------------------------------------------- 
 420 // wxDataViewCustomRenderer 
 421 // --------------------------------------------------------- 
 423 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer
, wxDataViewRenderer
) 
 425 wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString 
&varianttype
, 
 426                           wxDataViewCellMode mode 
) : 
 427     wxDataViewRenderer( varianttype
, mode 
) 
 431 // --------------------------------------------------------- 
 432 // wxDataViewTextRenderer 
 433 // --------------------------------------------------------- 
 435 IMPLEMENT_CLASS(wxDataViewTextRenderer
, wxDataViewCustomRenderer
) 
 437 wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString 
&varianttype
,  
 438                                                 wxDataViewCellMode mode 
) : 
 439     wxDataViewCustomRenderer( varianttype
, mode 
) 
 443 bool wxDataViewTextRenderer::SetValue( const wxVariant 
&value 
) 
 445     m_text 
= value
.GetString(); 
 450 bool wxDataViewTextRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) 
 455 bool wxDataViewTextRenderer::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
 457     wxDataViewCtrl 
*view 
= GetOwner()->GetOwner(); 
 458     wxColour col 
= (state 
& wxDATAVIEW_CELL_SELECTED
) ? 
 459                         wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
) : 
 460                         view
->GetForegroundColour(); 
 462     dc
->SetTextForeground(col
); 
 464     // TODO: it would be much more efficient to create a clipping 
 465     //       region for the entire column being rendered (in the OnPaint 
 466     //       of wxDataViewMainWindow) instead of a single clip region for 
 467     //       each cell. However it would mean that each renderer should 
 468     //       respect the given wxRect's top & bottom coords, eventually 
 469     //       violating only the left & right coords - however the user can 
 470     //       make its own renderer and thus we cannot be sure of that. 
 471     dc
->SetClippingRegion(cell
); 
 472     dc
->DrawText( m_text
, cell
.x
, cell
.y 
); 
 473     dc
->DestroyClippingRegion(); 
 478 wxSize 
wxDataViewTextRenderer::GetSize() 
 480     wxDataViewCtrl 
*view 
= GetOwner()->GetOwner(); 
 484         view
->GetTextExtent( m_text
, &x
, &y 
); 
 485         return wxSize( x
, y 
); 
 487     return wxSize(80,20); 
 490 // --------------------------------------------------------- 
 491 // wxDataViewBitmapRenderer 
 492 // --------------------------------------------------------- 
 494 IMPLEMENT_CLASS(wxDataViewBitmapRenderer
, wxDataViewCustomRenderer
) 
 496 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString 
&varianttype
,  
 497                                                     wxDataViewCellMode mode 
) : 
 498     wxDataViewCustomRenderer( varianttype
, mode 
) 
 502 bool wxDataViewBitmapRenderer::SetValue( const wxVariant 
&value 
) 
 504     if (value
.GetType() == wxT("wxBitmap")) 
 506     if (value
.GetType() == wxT("wxIcon")) 
 512 bool wxDataViewBitmapRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) 
 517 bool wxDataViewBitmapRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 520         dc
->DrawBitmap( m_bitmap
, cell
.x
, cell
.y 
); 
 521     else if (m_icon
.Ok()) 
 522         dc
->DrawIcon( m_icon
, cell
.x
, cell
.y 
); 
 527 wxSize 
wxDataViewBitmapRenderer::GetSize() 
 530         return wxSize( m_bitmap
.GetWidth(), m_bitmap
.GetHeight() ); 
 531     else if (m_icon
.Ok()) 
 532         return wxSize( m_icon
.GetWidth(), m_icon
.GetHeight() ); 
 534     return wxSize(16,16); 
 537 // --------------------------------------------------------- 
 538 // wxDataViewToggleRenderer 
 539 // --------------------------------------------------------- 
 541 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer
, wxDataViewCustomRenderer
) 
 543 wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString 
&varianttype
, 
 544                         wxDataViewCellMode mode 
) : 
 545     wxDataViewCustomRenderer( varianttype
, mode 
) 
 550 bool wxDataViewToggleRenderer::SetValue( const wxVariant 
&value 
) 
 552     m_toggle 
= value
.GetBool(); 
 557 bool wxDataViewToggleRenderer::GetValue( wxVariant 
&WXUNUSED(value
) ) 
 562 bool wxDataViewToggleRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 564     // User wxRenderer here 
 567     rect
.x 
= cell
.x 
+ cell
.width
/2 - 10; 
 569     rect
.y 
= cell
.y 
+ cell
.height
/2 - 10; 
 574         flags 
|= wxCONTROL_CHECKED
; 
 575     if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE
) 
 576         flags 
|= wxCONTROL_DISABLED
; 
 578     wxRendererNative::Get().DrawCheckBox( 
 579             GetOwner()->GetOwner(), 
 587 bool wxDataViewToggleRenderer::Activate( wxRect 
WXUNUSED(cell
),  
 588                                          wxDataViewListModel 
*model
,  
 589                                          unsigned int col
, unsigned int row 
) 
 591     bool value 
= !m_toggle
; 
 592     wxVariant variant 
= value
; 
 593     model
->SetValue( variant
, col
, row 
); 
 594     model
->ValueChanged( col
, row 
); 
 598 wxSize 
wxDataViewToggleRenderer::GetSize() 
 600     return wxSize(20,20); 
 603 // --------------------------------------------------------- 
 604 // wxDataViewProgressRenderer 
 605 // --------------------------------------------------------- 
 607 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer
, wxDataViewCustomRenderer
) 
 609 wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString 
&label
, 
 610     const wxString 
&varianttype
, wxDataViewCellMode mode 
) : 
 611     wxDataViewCustomRenderer( varianttype
, mode 
) 
 617 wxDataViewProgressRenderer::~wxDataViewProgressRenderer() 
 621 bool wxDataViewProgressRenderer::SetValue( const wxVariant 
&value 
) 
 623     m_value 
= (long) value
; 
 625     if (m_value 
< 0) m_value 
= 0; 
 626     if (m_value 
> 100) m_value 
= 100; 
 631 bool wxDataViewProgressRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 633     double pct 
= (double)m_value 
/ 100.0; 
 635     bar
.width 
= (int)(cell
.width 
* pct
); 
 636     dc
->SetPen( *wxTRANSPARENT_PEN 
); 
 637     dc
->SetBrush( *wxBLUE_BRUSH 
); 
 638     dc
->DrawRectangle( bar 
); 
 640     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
 641     dc
->SetPen( *wxBLACK_PEN 
); 
 642     dc
->DrawRectangle( cell 
); 
 647 wxSize 
wxDataViewProgressRenderer::GetSize() 
 649     return wxSize(40,12); 
 652 // --------------------------------------------------------- 
 653 // wxDataViewDateRenderer 
 654 // --------------------------------------------------------- 
 656 #define wxUSE_DATE_RENDERER_POPUP (wxUSE_CALENDARCTRL && wxUSE_POPUPWIN) 
 658 #if wxUSE_DATE_RENDERER_POPUP 
 660 class wxDataViewDateRendererPopupTransient
: public wxPopupTransientWindow
 
 663     wxDataViewDateRendererPopupTransient( wxWindow
* parent
, wxDateTime 
*value
, 
 664         wxDataViewListModel 
*model
, unsigned int col
, unsigned int row 
) : 
 665         wxPopupTransientWindow( parent
, wxBORDER_SIMPLE 
) 
 670         m_cal 
= new wxCalendarCtrl( this, wxID_ANY
, *value 
); 
 671         wxBoxSizer 
*sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 672         sizer
->Add( m_cal
, 1, wxGROW 
); 
 677     void OnCalendar( wxCalendarEvent 
&event 
); 
 679     wxCalendarCtrl      
*m_cal
; 
 680     wxDataViewListModel 
*m_model
; 
 685     virtual void OnDismiss() 
 690     DECLARE_EVENT_TABLE() 
 693 BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient
,wxPopupTransientWindow
) 
 694     EVT_CALENDAR( wxID_ANY
, wxDataViewDateRendererPopupTransient::OnCalendar 
) 
 697 void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent 
&event 
) 
 699     wxDateTime date 
= event
.GetDate(); 
 700     wxVariant value 
= date
; 
 701     m_model
->SetValue( value
, m_col
, m_row 
); 
 702     m_model
->ValueChanged( m_col
, m_row 
); 
 706 #endif // wxUSE_DATE_RENDERER_POPUP 
 708 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer
, wxDataViewCustomRenderer
) 
 710 wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString 
&varianttype
, 
 711                         wxDataViewCellMode mode 
) : 
 712     wxDataViewCustomRenderer( varianttype
, mode 
) 
 716 bool wxDataViewDateRenderer::SetValue( const wxVariant 
&value 
) 
 718     m_date 
= value
.GetDateTime(); 
 723 bool wxDataViewDateRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 725     dc
->SetFont( GetOwner()->GetOwner()->GetFont() ); 
 726     wxString tmp 
= m_date
.FormatDate(); 
 727     dc
->DrawText( tmp
, cell
.x
, cell
.y 
); 
 732 wxSize 
wxDataViewDateRenderer::GetSize() 
 734     wxDataViewCtrl
* view 
= GetOwner()->GetOwner(); 
 735     wxString tmp 
= m_date
.FormatDate(); 
 737     view
->GetTextExtent( tmp
, &x
, &y
, &d 
); 
 738     return wxSize(x
,y
+d
); 
 741 bool wxDataViewDateRenderer::Activate( wxRect 
WXUNUSED(cell
), wxDataViewListModel 
*model
,  
 742                                        unsigned int col
, unsigned int row 
) 
 745     model
->GetValue( variant
, col
, row 
); 
 746     wxDateTime value 
= variant
.GetDateTime(); 
 748 #if wxUSE_DATE_RENDERER_POPUP 
 749     wxDataViewDateRendererPopupTransient 
*popup 
= new wxDataViewDateRendererPopupTransient( 
 750         GetOwner()->GetOwner()->GetParent(), &value
, model
, col
, row 
); 
 751     wxPoint pos 
= wxGetMousePosition(); 
 754     popup
->Popup( popup
->m_cal 
); 
 755 #else // !wxUSE_DATE_RENDERER_POPUP 
 756     wxMessageBox(value
.Format()); 
 757 #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP 
 761 // --------------------------------------------------------- 
 763 // --------------------------------------------------------- 
 765 IMPLEMENT_ABSTRACT_CLASS(wxDataViewColumn
, wxDataViewColumnBase
) 
 767 wxDataViewColumn::wxDataViewColumn( const wxString 
&title
, wxDataViewRenderer 
*cell
,  
 768                                     unsigned int model_column
, 
 769                                     int width
, wxAlignment align
, int flags 
) : 
 770     wxDataViewColumnBase( title
, cell
, model_column
, width
, align
, flags 
) 
 773     Init(width 
< 0 ? 80 : width
); 
 776 wxDataViewColumn::wxDataViewColumn( const wxBitmap 
&bitmap
, wxDataViewRenderer 
*cell
,  
 777                                     unsigned int model_column
, 
 778                                     int width
, wxAlignment align
, int flags 
) : 
 779     wxDataViewColumnBase( bitmap
, cell
, model_column
, width
, align
, flags 
) 
 782     Init(width 
< 0 ? 30 : width
); 
 785 void wxDataViewColumn::Init(int width
) 
 791 void wxDataViewColumn::SetSortable( bool WXUNUSED(sortable
) ) 
 796 void wxDataViewColumn::SetSortOrder( bool WXUNUSED(ascending
) ) 
 801 bool wxDataViewColumn::IsSortOrderAscending() const 
 808 wxDataViewColumn::~wxDataViewColumn() 
 812 void wxDataViewColumn::SetTitle( const wxString 
&title 
) 
 814     wxDataViewColumnBase::SetTitle( title 
); 
 818 void wxDataViewColumn::SetBitmap( const wxBitmap 
&bitmap 
) 
 820     wxDataViewColumnBase::SetBitmap( bitmap 
); 
 824 int wxDataViewColumn::GetWidth() const 
 829 //----------------------------------------------------------------------------- 
 830 // wxDataViewHeaderWindowBase 
 831 //----------------------------------------------------------------------------- 
 833 void wxDataViewHeaderWindowBase::SetColumnWidth(unsigned int n
, int width
) 
 835     GetColumn(n
)->m_width 
= width
; 
 836     m_owner
->m_clientArea
->RecalculateDisplay(); 
 839 void wxDataViewHeaderWindowBase::SendEvent(wxEventType type
, unsigned int n
) 
 841     wxWindow 
*parent 
= GetParent(); 
 842     wxDataViewEvent 
le(type
, parent
->GetId()); 
 844     le
.SetEventObject(parent
); 
 846     le
.SetDataViewColumn(GetColumn(n
)); 
 847     le
.SetModel(GetOwner()->GetModel()); 
 849     // for events created by wxDataViewHeaderWindow the 
 850     // row / value fields are not valid 
 852     parent
->GetEventHandler()->ProcessEvent(le
); 
 855 #if defined(__WXMSW__) && USE_NATIVE_HEADER_WINDOW 
 857 // implemented in msw/window.cpp: 
 858 void wxAssociateWinWithHandle(HWND hWnd
, wxWindowMSW 
*win
); 
 859 void wxRemoveHandleAssociation(wxWindowMSW 
*win
); 
 861 // implemented in msw/listctrl.cpp: 
 862 unsigned int wxMSWGetColumnClicked(NMHDR 
*nmhdr
, POINT 
*ptClick
); 
 864 IMPLEMENT_ABSTRACT_CLASS(wxDataViewHeaderWindowMSW
, wxWindow
); 
 866 bool wxDataViewHeaderWindowMSW::Create( wxDataViewCtrl 
*parent
, wxWindowID id
, 
 867                                         const wxPoint 
&pos
, const wxSize 
&size
,  
 868                                         const wxString 
&name 
) 
 872     if ( !CreateControl(parent
, id
, pos
, size
, 0, wxDefaultValidator
, name
) ) 
 875     int x 
= pos
.x 
== wxDefaultCoord 
? 0 : pos
.x
, 
 876         y 
= pos
.y 
== wxDefaultCoord 
? 0 : pos
.y
, 
 877         w 
= size
.x 
== wxDefaultCoord 
? 1 : size
.x
, 
 878         h 
= size
.y 
== wxDefaultCoord 
? 22 : size
.y
; 
 880     // create the native WC_HEADER window: 
 881     WXHWND hwndParent 
= (HWND
)parent
->GetHandle(); 
 882     WXDWORD msStyle 
= WS_CHILD 
| HDS_BUTTONS 
| HDS_HORZ 
| HDS_HOTTRACK 
| HDS_FULLDRAG
; 
 883     m_hWnd 
= CreateWindowEx(0,  
 894         wxLogLastError(_T("CreateWindowEx")); 
 898     // we need to do the association to force wxWindow::HandleNotify 
 899     // to call wxDataViewHeaderWindow::MSWOnNotify 
 900     wxAssociateWinWithHandle((HWND
)m_hWnd
, this); 
 907     // Retrieve the bounding rectangle of the parent window's  
 908     // client area, and then request size and position values  
 909     // from the header control.  
 910     ::GetClientRect((HWND
)hwndParent
, &rcParent
);  
 914     if (!SendMessage((HWND
)m_hWnd
, HDM_LAYOUT
, 0, (LPARAM
) &hdl
))  
 916         wxLogLastError(_T("SendMessage")); 
 920     // Set the size, position, and visibility of the header control.  
 921     SetWindowPos((HWND
)m_hWnd
,  
 925                  wp
.flags 
| SWP_SHOWWINDOW
); 
 927     // set our size hints: wxDataViewCtrl will put this wxWindow inside 
 928     // a wxBoxSizer and in order to avoid super-big header windows, 
 929     // we need to set our height as fixed 
 930     SetMinSize(wxSize(-1, wp
.cy
)); 
 931     SetMaxSize(wxSize(-1, wp
.cy
)); 
 933     // the following is required to get the default win's font for header windows 
 939 wxDataViewHeaderWindowMSW::~wxDataViewHeaderWindow() 
 941     wxRemoveHandleAssociation(this); 
 944 void wxDataViewHeaderWindowMSW::UpdateDisplay() 
 946     // remove old columns 
 947     for (int i
=0, max
=Header_GetItemCount((HWND
)m_hWnd
); i 
< max
; i
++) 
 948         Header_DeleteItem((HWND
)m_hWnd
, 0); 
 950     // add the updated array of columns to the header control 
 951     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
 952     for (unsigned int i 
= 0; i 
< cols
; i
++) 
 954         wxDataViewColumn 
*col 
= GetColumn( i 
); 
 956             continue;      // don't add it! 
 959         hdi
.mask 
= HDI_TEXT 
| HDI_FORMAT 
| HDI_WIDTH
; 
 960         hdi
.pszText 
= (WCHAR
*) col
->GetTitle().c_str(); 
 961         hdi
.cxy 
= col
->GetWidth(); 
 962         hdi
.cchTextMax 
= sizeof(hdi
.pszText
)/sizeof(hdi
.pszText
[0]); 
 963         hdi
.fmt 
= HDF_LEFT 
| HDF_STRING
; 
 965         SendMessage((HWND
)m_hWnd
, HDM_INSERTITEM
, (WPARAM
)i
, (LPARAM
)&hdi
);  
 969 bool wxDataViewHeaderWindowMSW::MSWOnNotify(int idCtrl
, WXLPARAM lParam
, WXLPARAM 
*result
) 
 971     NMHDR 
*nmhdr 
= (NMHDR 
*)lParam
; 
 973     // is it a message from the header? 
 974     if ( nmhdr
->hwndFrom 
!= (HWND
)m_hWnd 
) 
 975         return wxWindow::MSWOnNotify(idCtrl
, lParam
, result
); 
 977     NMHEADER 
*nmHDR 
= (NMHEADER 
*)nmhdr
; 
 978     switch ( nmhdr
->code 
) 
 981             // user has started to resize a column: 
 982             // do we need to veto it? 
 983             if (!GetColumn(nmHDR
->iItem
)->IsResizeable()) 
 991             // user has started to reorder a column 
 994         case HDN_ITEMCHANGED
:   // user is resizing a column 
 995         case HDN_ENDTRACK
:      // user has finished resizing a column 
 996         case HDN_ENDDRAG
:       // user has finished reordering a column 
 998             // update the width of the modified column: 
 999             if ((nmHDR
->pitem
->mask 
& HDI_WIDTH
) != 0 && 
1000                     nmHDR
->pitem 
!= NULL
) 
1001                 SetColumnWidth(nmHDR
->iItem
, nmHDR
->pitem
->cxy
); 
1006                 wxEventType evt 
= nmHDR
->iButton 
== 0 ?  
1007                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK 
: 
1008                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
; 
1009                 SendEvent(evt
, nmHDR
->iItem
); 
1015                 // NOTE: for some reason (i.e. for a bug in Windows) 
1016                 //       the HDN_ITEMCLICK notification is not sent on 
1017                 //       right clicks, so we need to handle NM_RCLICK 
1020                 unsigned int column 
=  
1021                     wxMSWGetColumnClicked(nmhdr
, &ptClick
); 
1023                 if (column 
!= wxNOT_FOUND
) 
1024                     SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
, 
1029         case HDN_GETDISPINFOW
: 
1030             // see wxListCtrl::MSWOnNotify for more info! 
1033         case HDN_ITEMDBLCLICK
: 
1035                 unsigned int idx 
= nmHDR
->iItem
; 
1036                 int w 
= GetOwner()->GetBestColumnWidth(idx
); 
1038                 // update the native control: 
1040                 ZeroMemory(&hd
, sizeof(hd
)); 
1041                 hd
.mask 
= HDI_WIDTH
; 
1043                 Header_SetItem(GetHwnd(), idx
, &hd
); 
1045                 // update the wxDataViewColumn class: 
1046                 SetColumnWidth(idx
, w
); 
1051             return wxWindow::MSWOnNotify(idCtrl
, lParam
, result
); 
1057 void wxDataViewHeaderWindowMSW::ScrollWindow(int WXUNUSED(dx
), int WXUNUSED(dy
),  
1058                                              const wxRect 
*WXUNUSED(rect
)) 
1060     wxSize ourSz 
= GetClientSize(); 
1061     wxSize ownerSz 
= m_owner
->GetClientSize(); 
1063     // where should the (logical) origin of this window be placed? 
1065     m_owner
->CalcUnscrolledPosition(0, 0, &x1
, &y1
); 
1067     // put this window on top of our parent and  
1068     SetWindowPos((HWND
)m_hWnd
, HWND_TOP
, -x1
, y1
,  
1069                   ownerSz
.GetWidth() + x1
, ourSz
.GetHeight(),  
1073 #else       // !defined(__WXMSW__) 
1075 IMPLEMENT_ABSTRACT_CLASS(wxGenericDataViewHeaderWindow
, wxWindow
) 
1076 BEGIN_EVENT_TABLE(wxGenericDataViewHeaderWindow
, wxWindow
) 
1077     EVT_PAINT         (wxGenericDataViewHeaderWindow::OnPaint
) 
1078     EVT_MOUSE_EVENTS  (wxGenericDataViewHeaderWindow::OnMouse
) 
1079     EVT_SET_FOCUS     (wxGenericDataViewHeaderWindow::OnSetFocus
) 
1082 bool wxGenericDataViewHeaderWindow::Create(wxDataViewCtrl 
*parent
, wxWindowID id
, 
1083                                            const wxPoint 
&pos
, const wxSize 
&size
,  
1084                                            const wxString 
&name 
)  
1088     if (!wxDataViewHeaderWindowBase::Create(parent
, id
, pos
, size
, name
)) 
1091     wxVisualAttributes attr 
= wxPanel::GetClassDefaultAttributes(); 
1092     SetBackgroundStyle( wxBG_STYLE_CUSTOM 
); 
1093     SetOwnForegroundColour( attr
.colFg 
); 
1094     SetOwnBackgroundColour( attr
.colBg 
); 
1096         SetOwnFont( attr
.font 
); 
1098     // set our size hints: wxDataViewCtrl will put this wxWindow inside 
1099     // a wxBoxSizer and in order to avoid super-big header windows, 
1100     // we need to set our height as fixed 
1101     SetMinSize(wxSize(-1, HEADER_WINDOW_HEIGHT
)); 
1102     SetMaxSize(wxSize(-1, HEADER_WINDOW_HEIGHT
)); 
1107 void wxGenericDataViewHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1110     GetClientSize( &w
, &h 
); 
1112     wxAutoBufferedPaintDC 
dc( this ); 
1114     dc
.SetBackground(GetBackgroundColour()); 
1118     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1121     m_owner
->GetViewStart( &x
, NULL 
); 
1123     // account for the horz scrollbar offset 
1124     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1126     dc
.SetFont( GetFont() ); 
1128     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
1131     for (i 
= 0; i 
< cols
; i
++) 
1133         wxDataViewColumn 
*col 
= GetColumn( i 
); 
1134         if (col
->IsHidden()) 
1135             break;      // don't draw it! 
1137         int cw 
= col
->GetWidth(); 
1140         wxRendererNative::Get().DrawHeaderButton
 
1144                                     wxRect(xpos
, 0, cw
, ch
-1), 
1145                                     m_parent
->IsEnabled() ? 0 
1146                                                           : (int)wxCONTROL_DISABLED
 
1149         dc
.DrawText( col
->GetTitle(), xpos
+3, 3 ); 
1155 void wxGenericDataViewHeaderWindow::OnSetFocus( wxFocusEvent 
&event 
) 
1157     GetParent()->SetFocus(); 
1161 void wxGenericDataViewHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1163     // we want to work with logical coords 
1165     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1166     int y 
= event
.GetY(); 
1170         // we don't draw the line beyond our window,  
1171         // but we allow dragging it there 
1173         GetClientSize( &w
, NULL 
); 
1174         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1177         // erase the line if it was drawn 
1181         if (event
.ButtonUp())  
1183             m_isDragging 
= false; 
1189             SetColumnWidth(m_column
, m_currentX 
- m_minX
); 
1192             GetOwner()->Refresh(); 
1196             m_currentX 
= wxMax(m_minX 
+ 7, x
); 
1198             // draw in the new location 
1199             if (m_currentX 
< w
) DrawCurrent(); 
1203     else     // not dragging 
1206         m_column 
= wxNOT_FOUND
; 
1208         bool hit_border 
= false; 
1210         // end of the current column 
1213         // find the column where this event occured 
1214         int countCol 
= m_owner
->GetNumberOfColumns(); 
1215         for (int column 
= 0; column 
< countCol
; column
++)  
1217             wxDataViewColumn 
*p 
= GetColumn(column
); 
1220                 continue;   // skip if not shown 
1222             xpos 
+= p
->GetWidth(); 
1224             if ((abs(x
-xpos
) < 3) && (y 
< 22))  
1232                 // inside the column 
1239         if (m_column 
== wxNOT_FOUND
) 
1242         bool resizeable 
= GetColumn(m_column
)->IsResizeable(); 
1243         if (event
.LeftDClick() && resizeable
) 
1245             SetColumnWidth(m_column
, GetOwner()->GetBestColumnWidth(m_column
)); 
1248         else if (event
.LeftDown() || event
.RightUp()) 
1250             if (hit_border 
&& event
.LeftDown() && resizeable
)  
1252                 m_isDragging 
= true; 
1257             else    // click on a column 
1259                 wxEventType evt 
= event
.LeftDown() ?  
1260                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK 
: 
1261                         wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
; 
1262                 SendEvent(evt
, m_column
); 
1265         else if (event
.Moving()) 
1267             if (hit_border 
&& resizeable
)  
1268                 m_currentCursor 
= m_resizeCursor
; 
1270                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1272             SetCursor(*m_currentCursor
); 
1277 void wxGenericDataViewHeaderWindow::DrawCurrent() 
1279     int x1 
= m_currentX
; 
1281     ClientToScreen (&x1
, &y1
); 
1283     int x2 
= m_currentX
-1; 
1285     ++x2
; // but why ???? 
1288     m_owner
->GetClientSize( NULL
, &y2 
); 
1289     m_owner
->ClientToScreen( &x2
, &y2 
); 
1292     dc
.SetLogicalFunction (wxINVERT
); 
1293     //dc.SetPen (wxPen (*wxBLACK, 2, wxSOLID)); 
1294     dc
.SetPen(wxPen(wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT
),1, wxSOLID
)); 
1295     dc
.SetBrush (*wxTRANSPARENT_BRUSH
); 
1298     dc
.DrawLine (x1
, y1
, x2
, y2
); 
1299     dc
.SetLogicalFunction (wxCOPY
); 
1300     dc
.SetPen (wxNullPen
); 
1301     dc
.SetBrush (wxNullBrush
); 
1304 void wxGenericDataViewHeaderWindow::AdjustDC(wxDC
& dc
) 
1308     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1309     m_owner
->GetViewStart( &x
, NULL 
); 
1311     // shift the DC origin to match the position of the main window horizontal 
1312     // scrollbar: this allows us to always use logical coords 
1313     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1316 #endif      // defined(__WXMSW__) 
1318 //----------------------------------------------------------------------------- 
1319 // wxDataViewRenameTimer 
1320 //----------------------------------------------------------------------------- 
1322 wxDataViewRenameTimer::wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
) 
1327 void wxDataViewRenameTimer::Notify() 
1329     m_owner
->OnRenameTimer(); 
1332 //----------------------------------------------------------------------------- 
1333 // wxDataViewTextCtrlWrapper: wraps a wxTextCtrl for inline editing 
1334 //----------------------------------------------------------------------------- 
1336 BEGIN_EVENT_TABLE(wxDataViewTextCtrlWrapper
, wxEvtHandler
) 
1337     EVT_CHAR           (wxDataViewTextCtrlWrapper::OnChar
) 
1338     EVT_KEY_UP         (wxDataViewTextCtrlWrapper::OnKeyUp
) 
1339     EVT_KILL_FOCUS     (wxDataViewTextCtrlWrapper::OnKillFocus
) 
1342 wxDataViewTextCtrlWrapper::wxDataViewTextCtrlWrapper( 
1343                         wxDataViewMainWindow 
*owner
, 
1345                         wxDataViewListModel 
*model
, 
1346                         unsigned int col
, unsigned int row
, 
1356     m_aboutToFinish 
= false; 
1359     model
->GetValue( value
, col
, row 
); 
1360     m_startValue 
= value
.GetString(); 
1362     m_owner
->GetOwner()->CalcScrolledPosition( 
1363         rectLabel
.x
, rectLabel
.y
, &rectLabel
.x
, &rectLabel
.y 
); 
1365     m_text
->Create( owner
, wxID_ANY
, m_startValue
, 
1366                     wxPoint(rectLabel
.x
-2,rectLabel
.y
-2), 
1367                     wxSize(rectLabel
.width
+7,rectLabel
.height
+4) ); 
1370     m_text
->PushEventHandler(this); 
1373 void wxDataViewTextCtrlWrapper::AcceptChangesAndFinish() 
1375     m_aboutToFinish 
= true; 
1377     // Notify the owner about the changes 
1380     // Even if vetoed, close the control (consistent with MSW) 
1384 void wxDataViewTextCtrlWrapper::OnChar( wxKeyEvent 
&event 
) 
1386     switch ( event
.m_keyCode 
) 
1389             AcceptChangesAndFinish(); 
1393             // m_owner->OnRenameCancelled( m_itemEdited ); 
1402 void wxDataViewTextCtrlWrapper::OnKeyUp( wxKeyEvent 
&event 
) 
1410     // auto-grow the textctrl 
1411     wxSize parentSize 
= m_owner
->GetSize(); 
1412     wxPoint myPos 
= m_text
->GetPosition(); 
1413     wxSize mySize 
= m_text
->GetSize(); 
1415     m_text
->GetTextExtent(m_text
->GetValue() + _T("MM"), &sx
, &sy
); 
1416     if (myPos
.x 
+ sx 
> parentSize
.x
) 
1417         sx 
= parentSize
.x 
- myPos
.x
; 
1420     m_text
->SetSize(sx
, wxDefaultCoord
); 
1425 void wxDataViewTextCtrlWrapper::OnKillFocus( wxFocusEvent 
&event 
) 
1427     if ( !m_finished 
&& !m_aboutToFinish 
) 
1430         //if ( !AcceptChanges() ) 
1431         //    m_owner->OnRenameCancelled( m_itemEdited ); 
1436     // We must let the native text control handle focus 
1440 bool wxDataViewTextCtrlWrapper::AcceptChanges() 
1442     const wxString value 
= m_text
->GetValue(); 
1444     if ( value 
== m_startValue 
) 
1445         // nothing changed, always accept 
1448 //    if ( !m_owner->OnRenameAccept(m_itemEdited, value) ) 
1449         // vetoed by the user 
1452     // accepted, do rename the item 
1455     m_model
->SetValue( variant
, m_col
, m_row 
); 
1456     m_model
->ValueChanged( m_col
, m_row 
); 
1461 void wxDataViewTextCtrlWrapper::Finish() 
1467         m_text
->RemoveEventHandler(this); 
1468         m_owner
->FinishEditing(m_text
); 
1471         wxPendingDelete
.Append( this ); 
1475 //----------------------------------------------------------------------------- 
1476 // wxDataViewMainWindow 
1477 //----------------------------------------------------------------------------- 
1479 int LINKAGEMODE 
wxDataViewSelectionCmp( unsigned int row1
, unsigned int row2 
) 
1481     if (row1 
> row2
) return 1; 
1482     if (row1 
== row2
) return 0; 
1487 IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow
, wxWindow
) 
1489 BEGIN_EVENT_TABLE(wxDataViewMainWindow
,wxWindow
) 
1490     EVT_PAINT         (wxDataViewMainWindow::OnPaint
) 
1491     EVT_MOUSE_EVENTS  (wxDataViewMainWindow::OnMouse
) 
1492     EVT_SET_FOCUS     (wxDataViewMainWindow::OnSetFocus
) 
1493     EVT_KILL_FOCUS    (wxDataViewMainWindow::OnKillFocus
) 
1494     EVT_CHAR          (wxDataViewMainWindow::OnChar
) 
1497 wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl 
*parent
, wxWindowID id
, 
1498     const wxPoint 
&pos
, const wxSize 
&size
, const wxString 
&name 
) : 
1499     wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
, name 
), 
1500     m_selection( wxDataViewSelectionCmp 
) 
1505     m_lastOnSame 
= false; 
1506     m_renameTimer 
= new wxDataViewRenameTimer( this ); 
1507     m_textctrlWrapper 
= NULL
; 
1509     // TODO: user better initial values/nothing selected 
1510     m_currentCol 
= NULL
; 
1513     // TODO: we need to calculate this smartly 
1522     m_dragStart 
= wxPoint(0,0); 
1523     m_lineLastClicked 
= (unsigned int) -1; 
1524     m_lineBeforeLastClicked 
= (unsigned int) -1; 
1525     m_lineSelectSingleOnUp 
= (unsigned int) -1; 
1529     SetBackgroundStyle( wxBG_STYLE_CUSTOM 
); 
1530     SetBackgroundColour( *wxWHITE 
); 
1535 wxDataViewMainWindow::~wxDataViewMainWindow() 
1537     delete m_renameTimer
; 
1540 void wxDataViewMainWindow::OnRenameTimer() 
1542     // We have to call this here because changes may just have 
1543     // been made and no screen update taken place. 
1549     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
1551     for (i 
= 0; i 
< cols
; i
++) 
1553         wxDataViewColumn 
*c 
= GetOwner()->GetColumn( i 
); 
1554         if (c 
== m_currentCol
) 
1556         xpos 
+= c
->GetWidth(); 
1558     wxRect 
labelRect( xpos
, m_currentRow 
* m_lineHeight
,  
1559                       m_currentCol
->GetWidth(), m_lineHeight 
); 
1561     wxClassInfo 
*textControlClass 
= CLASSINFO(wxTextCtrl
); 
1563     wxTextCtrl 
* const text 
= (wxTextCtrl 
*)textControlClass
->CreateObject(); 
1564     m_textctrlWrapper 
= new wxDataViewTextCtrlWrapper(this, text
, GetOwner()->GetModel(), 
1565         m_currentCol
->GetModelColumn(), m_currentRow
, labelRect 
); 
1568 void wxDataViewMainWindow::FinishEditing( wxTextCtrl 
*text 
) 
1571     m_textctrlWrapper 
= NULL
; 
1573   //  SetFocusIgnoringChildren(); 
1576 bool wxDataViewMainWindow::RowAppended() 
1581 bool wxDataViewMainWindow::RowPrepended() 
1586 bool wxDataViewMainWindow::RowInserted( unsigned int WXUNUSED(before
) ) 
1591 bool wxDataViewMainWindow::RowDeleted( unsigned int WXUNUSED(row
) ) 
1596 bool wxDataViewMainWindow::RowChanged( unsigned int WXUNUSED(row
) ) 
1601 bool wxDataViewMainWindow::ValueChanged( unsigned int WXUNUSED(col
), unsigned int row 
) 
1603     wxRect 
rect( 0, row
*m_lineHeight
, 10000, m_lineHeight 
); 
1604     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
1605     Refresh( true, &rect 
); 
1610 bool wxDataViewMainWindow::RowsReordered( unsigned int *WXUNUSED(new_order
) ) 
1617 bool wxDataViewMainWindow::Cleared() 
1622 void wxDataViewMainWindow::UpdateDisplay() 
1627 void wxDataViewMainWindow::OnInternalIdle() 
1629     wxWindow::OnInternalIdle(); 
1633         RecalculateDisplay(); 
1638 void wxDataViewMainWindow::RecalculateDisplay() 
1640     wxDataViewListModel 
*model 
= GetOwner()->GetModel(); 
1648     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
1650     for (i 
= 0; i 
< cols
; i
++) 
1652         wxDataViewColumn 
*col 
= GetOwner()->GetColumn( i 
); 
1653         width 
+= col
->GetWidth(); 
1656     int height 
= model
->GetNumberOfRows() * m_lineHeight
; 
1658     SetVirtualSize( width
, height 
); 
1659     GetOwner()->SetScrollRate( 10, m_lineHeight 
); 
1664 void wxDataViewMainWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
1666     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
1667     GetOwner()->m_headerArea
->ScrollWindow( dx
, 0 ); 
1670 void wxDataViewMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1672     wxAutoBufferedPaintDC 
dc( this ); 
1674     dc
.SetBackground(GetBackgroundColour()); 
1677     GetOwner()->PrepareDC( dc 
); 
1679     dc
.SetFont( GetFont() ); 
1681     wxRect update 
= GetUpdateRegion().GetBox(); 
1682     m_owner
->CalcUnscrolledPosition( update
.x
, update
.y
, &update
.x
, &update
.y 
); 
1684     wxDataViewListModel 
*model 
= GetOwner()->GetModel(); 
1686     unsigned int item_start 
= wxMax( 0, (update
.y 
/ m_lineHeight
) ); 
1687     unsigned int item_count 
=  
1688         wxMin( (int)(((update
.y 
+ update
.height
) / m_lineHeight
) - item_start 
+ 1), 
1689                                (int)(model
->GetNumberOfRows()-item_start
) ); 
1692     for (item 
= item_start
; item 
< item_start
+item_count
; item
++) 
1694         bool selected 
= m_selection
.Index( item 
) != wxNOT_FOUND
; 
1695         if (selected 
|| item 
== m_currentRow
) 
1697             int flags 
= selected 
? wxCONTROL_SELECTED 
: 0; 
1698             if (item 
== m_currentRow
) 
1699                 flags 
|= wxCONTROL_CURRENT
; 
1701                 flags 
|= wxCONTROL_FOCUSED
; 
1702             wxRect 
rect( 0, item
*m_lineHeight
, GetEndOfLastCol(), m_lineHeight 
); 
1703             wxRendererNative::Get().DrawItemSelectionRect
 
1715     cell_rect
.height 
= m_lineHeight
; 
1716     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
1718     for (i 
= 0; i 
< cols
; i
++) 
1720         wxDataViewColumn 
*col 
= GetOwner()->GetColumn( i 
); 
1721         wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
1722         cell_rect
.width 
= col
->GetWidth(); 
1724         if (col
->IsHidden()) 
1725             continue;       // skipt it! 
1727         for (item 
= item_start
; item 
< item_start
+item_count
; item
++) 
1729             // get the cell value and set it into the renderer 
1731             model
->GetValue( value
, col
->GetModelColumn(), item 
); 
1732             cell
->SetValue( value 
); 
1734             // update the y offset 
1735             cell_rect
.y 
= item
*m_lineHeight
; 
1737             // cannot be bigger than allocated space 
1738             wxSize size 
= cell
->GetSize(); 
1739             size
.x 
= wxMin( size
.x
, cell_rect
.width 
); 
1740             size
.y 
= wxMin( size
.y
, cell_rect
.height 
); 
1742             wxRect 
item_rect(cell_rect
.GetTopLeft(), size
); 
1744             // horizontal alignment: 
1745             if (col
->GetAlignment() & wxALIGN_CENTER_HORIZONTAL
) 
1746             item_rect
.x 
= cell_rect
.x 
+ (cell_rect
.width 
/ 2) - (size
.x 
/ 2); 
1747             else if (col
->GetAlignment() & wxALIGN_RIGHT
) 
1748                 item_rect
.x 
= cell_rect
.x 
+ cell_rect
.width 
- size
.x
; 
1749             //else: wxALIGN_LEFT is the default 
1751             // vertical alignment: 
1752             if (col
->GetAlignment() & wxALIGN_CENTER_VERTICAL
) 
1753                 item_rect
.y 
= cell_rect
.y 
+ (cell_rect
.height 
/ 2) - (size
.y 
/ 2); 
1754             else if (col
->GetAlignment() & wxALIGN_BOTTOM
) 
1755                 item_rect
.y 
= cell_rect
.y 
+ cell_rect
.height 
- size
.y
; 
1756             //else: wxALIGN_TOP is the default 
1758             item_rect
.y 
= cell_rect
.y 
+ (cell_rect
.height 
/ 2) - (size
.y 
/ 2); 
1760             item_rect
.width 
= size
.x
; 
1761             item_rect
.height
= size
.y
; 
1764             //if (item == m_currentRow)     -- seems wrong to me... 
1765             if (m_selection
.Index(item
) != wxNOT_FOUND
) 
1766                 state 
|= wxDATAVIEW_CELL_SELECTED
; 
1768             cell
->Render( item_rect
, &dc
, state 
); 
1771         cell_rect
.x 
+= cell_rect
.width
; 
1775 int wxDataViewMainWindow::GetCountPerPage() 
1777     wxSize size 
= GetClientSize(); 
1778     return size
.y 
/ m_lineHeight
; 
1781 int wxDataViewMainWindow::GetEndOfLastCol() 
1785     for (i 
= 0; i 
< GetOwner()->GetNumberOfColumns(); i
++) 
1787         wxDataViewColumn 
*c 
= GetOwner()->GetColumn( i 
); 
1788         width 
+= c
->GetWidth(); 
1793 unsigned int wxDataViewMainWindow::GetFirstVisibleRow() 
1797     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
1799     return y 
/ m_lineHeight
; 
1802 unsigned int wxDataViewMainWindow::GetLastVisibleRow() 
1804     wxSize client_size 
= GetClientSize(); 
1805     m_owner
->CalcUnscrolledPosition( client_size
.x
, client_size
.y
,  
1806                                      &client_size
.x
, &client_size
.y 
); 
1808     return wxMin( GetRowCount()-1, ((unsigned)client_size
.y
/m_lineHeight
)+1 ); 
1811 unsigned int wxDataViewMainWindow::GetRowCount() 
1813     return GetOwner()->GetModel()->GetNumberOfRows(); 
1816 void wxDataViewMainWindow::ChangeCurrentRow( unsigned int row 
) 
1823 void wxDataViewMainWindow::SelectAllRows( bool on 
) 
1830         m_selection
.Clear(); 
1831         for (unsigned int i 
= 0; i 
< GetRowCount(); i
++) 
1832             m_selection
.Add( i 
); 
1837         unsigned int first_visible 
= GetFirstVisibleRow(); 
1838         unsigned int last_visible 
= GetLastVisibleRow(); 
1840         for (i 
= 0; i 
< m_selection
.GetCount(); i
++) 
1842             unsigned int row 
= m_selection
[i
]; 
1843             if ((row 
>= first_visible
) && (row 
<= last_visible
)) 
1846         m_selection
.Clear(); 
1850 void wxDataViewMainWindow::SelectRow( unsigned int row
, bool on 
) 
1852     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
1856             m_selection
.Add( row 
); 
1864             m_selection
.Remove( row 
); 
1870 void wxDataViewMainWindow::SelectRows( unsigned int from
, unsigned int to
, bool on 
) 
1874         unsigned int tmp 
= from
; 
1880     for (i 
= from
; i 
<= to
; i
++) 
1882         if (m_selection
.Index( i 
) == wxNOT_FOUND
) 
1885                 m_selection
.Add( i 
); 
1890                 m_selection
.Remove( i 
); 
1893     RefreshRows( from
, to 
); 
1896 void wxDataViewMainWindow::Select( const wxArrayInt
& aSelections 
) 
1898     for (size_t i
=0; i 
< aSelections
.GetCount(); i
++) 
1900         int n 
= aSelections
[i
]; 
1902         m_selection
.Add( n 
); 
1907 void wxDataViewMainWindow::ReverseRowSelection( unsigned int row 
) 
1909     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
1910         m_selection
.Add( row 
); 
1912         m_selection
.Remove( row 
); 
1916 bool wxDataViewMainWindow::IsRowSelected( unsigned int row 
) 
1918     return (m_selection
.Index( row 
) != wxNOT_FOUND
); 
1921 void wxDataViewMainWindow::RefreshRow( unsigned int row 
) 
1923     wxRect 
rect( 0, row
*m_lineHeight
, GetEndOfLastCol(), m_lineHeight 
); 
1924     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
1926     wxSize client_size 
= GetClientSize(); 
1927     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
1928     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
1929     if (intersect_rect
.width 
> 0) 
1930         Refresh( true, &intersect_rect 
); 
1933 void wxDataViewMainWindow::RefreshRows( unsigned int from
, unsigned int to 
) 
1937         unsigned int tmp 
= to
; 
1942     wxRect 
rect( 0, from
*m_lineHeight
, GetEndOfLastCol(), (to
-from
+1) * m_lineHeight 
); 
1943     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
1945     wxSize client_size 
= GetClientSize(); 
1946     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
1947     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
1948     if (intersect_rect
.width 
> 0) 
1949         Refresh( true, &intersect_rect 
); 
1952 void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow 
) 
1954     unsigned int count 
= GetRowCount(); 
1955     if (firstRow 
> count
) 
1958     wxRect 
rect( 0, firstRow
*m_lineHeight
, GetEndOfLastCol(), count 
* m_lineHeight 
); 
1959     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
1961     wxSize client_size 
= GetClientSize(); 
1962     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
1963     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
1964     if (intersect_rect
.width 
> 0) 
1965         Refresh( true, &intersect_rect 
); 
1968 void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
) 
1970     wxCHECK_RET( newCurrent 
< GetRowCount(), 
1971                  _T("invalid item index in OnArrowChar()") ); 
1973     // if there is no selection, we cannot move it anywhere 
1974     if (!HasCurrentRow()) 
1977     unsigned int oldCurrent 
= m_currentRow
; 
1979     // in single selection we just ignore Shift as we can't select several 
1981     if ( event
.ShiftDown() && !IsSingleSel() ) 
1983         RefreshRow( oldCurrent 
); 
1985         ChangeCurrentRow( newCurrent 
); 
1987         // select all the items between the old and the new one 
1988         if ( oldCurrent 
> newCurrent 
) 
1990             newCurrent 
= oldCurrent
; 
1991             oldCurrent 
= m_currentRow
; 
1994         SelectRows( oldCurrent
, newCurrent
, true ); 
1998         RefreshRow( oldCurrent 
); 
2000         // all previously selected items are unselected unless ctrl is held 
2001         if ( !event
.ControlDown() ) 
2002             SelectAllRows(false); 
2004         ChangeCurrentRow( newCurrent 
); 
2006         if ( !event
.ControlDown() ) 
2007             SelectRow( m_currentRow
, true ); 
2009             RefreshRow( m_currentRow 
); 
2015 void wxDataViewMainWindow::OnChar( wxKeyEvent 
&event 
) 
2017     if (event
.GetKeyCode() == WXK_TAB
) 
2019         wxNavigationKeyEvent nevent
; 
2020         nevent
.SetWindowChange( event
.ControlDown() ); 
2021         nevent
.SetDirection( !event
.ShiftDown() ); 
2022         nevent
.SetEventObject( GetParent()->GetParent() ); 
2023         nevent
.SetCurrentFocus( m_parent 
); 
2024         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) 
2028     // no item -> nothing to do 
2029     if (!HasCurrentRow()) 
2035     // don't use m_linesPerPage directly as it might not be computed yet 
2036     const int pageSize 
= GetCountPerPage(); 
2037     wxCHECK_RET( pageSize
, _T("should have non zero page size") ); 
2039     switch ( event
.GetKeyCode() ) 
2042             if ( m_currentRow 
> 0 ) 
2043                 OnArrowChar( m_currentRow 
- 1, event 
); 
2047             if ( m_currentRow 
< GetRowCount() - 1 ) 
2048                 OnArrowChar( m_currentRow 
+ 1, event 
); 
2053                 OnArrowChar( GetRowCount() - 1, event 
); 
2058                 OnArrowChar( 0, event 
); 
2063                 int steps 
= pageSize 
- 1; 
2064                 int index 
= m_currentRow 
- steps
; 
2068                 OnArrowChar( index
, event 
); 
2074                 int steps 
= pageSize 
- 1; 
2075                 unsigned int index 
= m_currentRow 
+ steps
; 
2076                 unsigned int count 
= GetRowCount(); 
2077                 if ( index 
>= count 
) 
2080                 OnArrowChar( index
, event 
); 
2089 void wxDataViewMainWindow::OnMouse( wxMouseEvent 
&event 
) 
2091     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
2093         // let the base handle mouse wheel events. 
2098     int x 
= event
.GetX(); 
2099     int y 
= event
.GetY(); 
2100     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2102     wxDataViewColumn 
*col 
= NULL
; 
2105     unsigned int cols 
= GetOwner()->GetNumberOfColumns(); 
2107     for (i 
= 0; i 
< cols
; i
++) 
2109         wxDataViewColumn 
*c 
= GetOwner()->GetColumn( i 
); 
2110         if (x 
< xpos 
+ c
->GetWidth()) 
2115         xpos 
+= c
->GetWidth(); 
2119     wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
2121     unsigned int current 
= y 
/ m_lineHeight
; 
2123     if ((current 
> GetRowCount()) || (x 
> GetEndOfLastCol())) 
2125         // Unselect all if below the last row ? 
2129     wxDataViewListModel 
*model 
= GetOwner()->GetModel(); 
2131     if (event
.Dragging()) 
2133         if (m_dragCount 
== 0) 
2135             // we have to report the raw, physical coords as we want to be 
2136             // able to call HitTest(event.m_pointDrag) from the user code to 
2137             // get the item being dragged 
2138             m_dragStart 
= event
.GetPosition(); 
2143         if (m_dragCount 
!= 3) 
2146         if (event
.LeftIsDown()) 
2148             // Notify cell about drag 
2157     bool forceClick 
= false; 
2159     if (event
.ButtonDClick()) 
2161         m_renameTimer
->Stop(); 
2162         m_lastOnSame 
= false; 
2165     if (event
.LeftDClick()) 
2167         if ( current 
== m_lineLastClicked 
) 
2169             if (cell
->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE
) 
2172                 model
->GetValue( value
, col
->GetModelColumn(), current 
); 
2173                 cell
->SetValue( value 
); 
2174                 wxRect 
cell_rect( xpos
, current 
* m_lineHeight
,  
2175                                   col
->GetWidth(), m_lineHeight 
); 
2176                 cell
->Activate( cell_rect
, model
, col
->GetModelColumn(), current 
); 
2182             // The first click was on another item, so don't interpret this as 
2183             // a double click, but as a simple click instead 
2190         if (m_lineSelectSingleOnUp 
!= (unsigned int)-1) 
2192             // select single line 
2193             SelectAllRows( false ); 
2194             SelectRow( m_lineSelectSingleOnUp
, true ); 
2199             if ((col 
== m_currentCol
) && (current 
== m_currentRow
) && 
2200                 (cell
->GetMode() == wxDATAVIEW_CELL_EDITABLE
) ) 
2202                 m_renameTimer
->Start( 100, true ); 
2206         m_lastOnSame 
= false; 
2207         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
2211         // This is necessary, because after a DnD operation in 
2212         // from and to ourself, the up event is swallowed by the 
2213         // DnD code. So on next non-up event (which means here and 
2214         // now) m_lineSelectSingleOnUp should be reset. 
2215         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
2218     if (event
.RightDown()) 
2220         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2221         m_lineLastClicked 
= current
; 
2223         // If the item is already selected, do not update the selection. 
2224         // Multi-selections should not be cleared if a selected item is clicked. 
2225         if (!IsRowSelected(current
)) 
2227             SelectAllRows(false); 
2228             ChangeCurrentRow(current
); 
2229             SelectRow(m_currentRow
,true); 
2232         // notify cell about right click 
2235         // Allow generation of context menu event 
2238     else if (event
.MiddleDown()) 
2240         // notify cell about middle click 
2243     if (event
.LeftDown() || forceClick
) 
2249         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2250         m_lineLastClicked 
= current
; 
2252         unsigned int oldCurrentRow 
= m_currentRow
; 
2253         bool oldWasSelected 
= IsRowSelected(m_currentRow
); 
2255         bool cmdModifierDown 
= event
.CmdDown(); 
2256         if ( IsSingleSel() || !(cmdModifierDown 
|| event
.ShiftDown()) ) 
2258             if ( IsSingleSel() || !IsRowSelected(current
) ) 
2260                 SelectAllRows( false ); 
2262                 ChangeCurrentRow(current
); 
2264                 SelectRow(m_currentRow
,true); 
2266             else // multi sel & current is highlighted & no mod keys 
2268                 m_lineSelectSingleOnUp 
= current
; 
2269                 ChangeCurrentRow(current
); // change focus 
2272         else // multi sel & either ctrl or shift is down 
2274             if (cmdModifierDown
) 
2276                 ChangeCurrentRow(current
); 
2278                 ReverseRowSelection(m_currentRow
); 
2280             else if (event
.ShiftDown()) 
2282                 ChangeCurrentRow(current
); 
2284                 unsigned int lineFrom 
= oldCurrentRow
, 
2287                 if ( lineTo 
< lineFrom 
) 
2290                     lineFrom 
= m_currentRow
; 
2293                 SelectRows(lineFrom
, lineTo
, true); 
2295             else // !ctrl, !shift 
2297                 // test in the enclosing if should make it impossible 
2298                 wxFAIL_MSG( _T("how did we get here?") ); 
2302         if (m_currentRow 
!= oldCurrentRow
) 
2303             RefreshRow( oldCurrentRow 
); 
2305         wxDataViewColumn 
*oldCurrentCol 
= m_currentCol
; 
2307         // Update selection here... 
2310         m_lastOnSame 
= !forceClick 
&& ((col 
== oldCurrentCol
) &&  
2311                         (current 
== oldCurrentRow
)) && oldWasSelected
; 
2315 void wxDataViewMainWindow::OnSetFocus( wxFocusEvent 
&event 
) 
2319     if (HasCurrentRow()) 
2325 void wxDataViewMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
2329     if (HasCurrentRow()) 
2335 //----------------------------------------------------------------------------- 
2337 //----------------------------------------------------------------------------- 
2339 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
2341 BEGIN_EVENT_TABLE(wxDataViewCtrl
, wxDataViewCtrlBase
) 
2342     EVT_SIZE(wxDataViewCtrl::OnSize
) 
2345 wxDataViewCtrl::~wxDataViewCtrl() 
2348         GetModel()->RemoveNotifier( m_notifier 
); 
2351 void wxDataViewCtrl::Init() 
2356 bool wxDataViewCtrl::Create(wxWindow 
*parent
, wxWindowID id
, 
2357            const wxPoint
& pos
, const wxSize
& size
, 
2358            long style
, const wxValidator
& validator 
) 
2360     if (!wxControl::Create( parent
, id
, pos
, size
,  
2361                             style 
| wxScrolledWindowStyle
|wxSUNKEN_BORDER
, validator
)) 
2367     MacSetClipChildren( true ) ; 
2370     m_clientArea 
= new wxDataViewMainWindow( this, wxID_ANY 
); 
2371     m_headerArea 
= new wxDataViewHeaderWindow( this, wxID_ANY 
); 
2373     SetTargetWindow( m_clientArea 
); 
2375     wxBoxSizer 
*sizer 
= new wxBoxSizer( wxVERTICAL 
); 
2376     sizer
->Add( m_headerArea
, 0, wxGROW 
); 
2377     sizer
->Add( m_clientArea
, 1, wxGROW 
); 
2384 WXLRESULT 
wxDataViewCtrl::MSWWindowProc(WXUINT nMsg
, 
2388     WXLRESULT rc 
= wxDataViewCtrlBase::MSWWindowProc(nMsg
, wParam
, lParam
); 
2391     // we need to process arrows ourselves for scrolling 
2392     if ( nMsg 
== WM_GETDLGCODE 
) 
2394         rc 
|= DLGC_WANTARROWS
; 
2402 void wxDataViewCtrl::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
2404     // We need to override OnSize so that our scrolled 
2405     // window a) does call Layout() to use sizers for 
2406     // positioning the controls but b) does not query 
2407     // the sizer for their size and use that for setting 
2408     // the scrollable area as set that ourselves by 
2409     // calling SetScrollbar() further down. 
2416 bool wxDataViewCtrl::AssociateModel( wxDataViewListModel 
*model 
) 
2418     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
2421     m_notifier 
= new wxGenericDataViewListModelNotifier( m_clientArea 
); 
2423     model
->AddNotifier( m_notifier 
); 
2425     m_clientArea
->UpdateDisplay(); 
2430 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn 
*col 
) 
2432     if (!wxDataViewCtrlBase::AppendColumn(col
)) 
2435     m_clientArea
->UpdateDisplay(); 
2436     m_headerArea
->UpdateDisplay(); 
2441 void wxDataViewCtrl::SetSelection( int row 
) 
2443     m_clientArea
->SelectRow(row
, true); 
2446 void wxDataViewCtrl::SetSelectionRange( unsigned int from
, unsigned int to 
) 
2448     m_clientArea
->SelectRows(from
, to
, true); 
2451 void wxDataViewCtrl::SetSelections( const wxArrayInt
& aSelections 
) 
2453     m_clientArea
->Select(aSelections
); 
2456 void wxDataViewCtrl::Unselect( unsigned int WXUNUSED(row
) ) 
2461 bool wxDataViewCtrl::IsSelected( unsigned int WXUNUSED(row
) ) const 
2468 int wxDataViewCtrl::GetSelection() const 
2475 int wxDataViewCtrl::GetSelections(wxArrayInt
& WXUNUSED(aSelections
) ) const 
2483     // !wxUSE_GENERICDATAVIEWCTRL 
2486     // wxUSE_DATAVIEWCTRL