1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/generic/datavgen.cpp 
   3 // Purpose:     wxDataViewCtrl generic implementation 
   4 // Author:      Robert Roebling 
   5 // Modified by: Francesco Montorsi, Guru Kathiresan, Bo Yang 
   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" 
  40 #include "wx/stockitem.h" 
  41 #include "wx/calctrl.h" 
  42 #include "wx/popupwin.h" 
  43 #include "wx/renderer.h" 
  44 #include "wx/dcbuffer.h" 
  47 #include "wx/listimpl.cpp" 
  48 #include "wx/imaglist.h" 
  49 #include "wx/headerctrl.h" 
  52 //----------------------------------------------------------------------------- 
  54 //----------------------------------------------------------------------------- 
  56 class wxDataViewColumn
; 
  57 class wxDataViewHeaderWindow
; 
  60 //----------------------------------------------------------------------------- 
  62 //----------------------------------------------------------------------------- 
  64 static const int SCROLL_UNIT_X 
= 15; 
  66 // the cell padding on the left/right 
  67 static const int PADDING_RIGHTLEFT 
= 3; 
  69 // the expander space margin 
  70 static const int EXPANDER_MARGIN 
= 4; 
  73 static const int EXPANDER_OFFSET 
= 4; 
  75 static const int EXPANDER_OFFSET 
= 1; 
  78 // Below is the compare stuff. 
  79 // For the generic implementation, both the leaf nodes and the nodes are sorted for 
  80 // fast search when needed 
  81 static wxDataViewModel
* g_model
; 
  82 static int g_column 
= -2; 
  83 static bool g_asending 
= true; 
  85 //----------------------------------------------------------------------------- 
  87 //----------------------------------------------------------------------------- 
  89 void wxDataViewColumn::Init(int width
, wxAlignment align
, int flags
) 
  91     m_width 
= width 
== wxCOL_WIDTH_DEFAULT 
? wxDVC_DEFAULT_WIDTH 
: width
; 
  96     m_sortAscending 
= true; 
  99 void wxDataViewColumn::UpdateDisplay() 
 103         int idx 
= m_owner
->GetColumnIndex( this ); 
 104         m_owner
->OnColumnChange( idx 
); 
 108 //----------------------------------------------------------------------------- 
 109 // wxDataViewHeaderWindow 
 110 //----------------------------------------------------------------------------- 
 112 class wxDataViewHeaderWindow 
: public wxHeaderCtrl
 
 115     wxDataViewHeaderWindow(wxDataViewCtrl 
*parent
) 
 116         : wxHeaderCtrl(parent
) 
 120     wxDataViewCtrl 
*GetOwner() const 
 121         { return static_cast<wxDataViewCtrl 
*>(GetParent()); } 
 124     // implement/override wxHeaderCtrl functions by forwarding them to the main 
 126     virtual const wxHeaderColumn
& GetColumn(unsigned int idx
) const 
 128         return *(GetOwner()->GetColumn(idx
)); 
 131     // FIXME: currently unused 
 132     virtual bool UpdateColumnWidthToFit(unsigned int idx
, int widthTitle
) 
 134         wxDataViewCtrl 
* const owner 
= GetOwner(); 
 136         int widthContents 
= owner
->GetBestColumnWidth(idx
); 
 137         owner
->GetColumn(idx
)->SetWidth(wxMax(widthTitle
, widthContents
)); 
 138         owner
->OnColumnChange(idx
); 
 144     bool SendEvent(wxEventType type
, unsigned int n
) 
 146         wxDataViewCtrl 
* const owner 
= GetOwner(); 
 147         wxDataViewEvent 
event(type
, owner
->GetId()); 
 149         event
.SetEventObject(owner
); 
 151         event
.SetDataViewColumn(owner
->GetColumn(n
)); 
 152         event
.SetModel(owner
->GetModel()); 
 154         // for events created by wxDataViewHeaderWindow the 
 155         // row / value fields are not valid 
 156         return owner
->GetEventHandler()->ProcessEvent(event
); 
 159     void OnClick(wxHeaderCtrlEvent
& event
) 
 161         const unsigned idx 
= event
.GetColumn(); 
 163         if ( SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_CLICK
, idx
) ) 
 166         // default handling for the column click is to sort by this column or 
 167         // toggle its sort order 
 168         wxDataViewCtrl 
* const owner 
= GetOwner(); 
 169         wxDataViewColumn 
* const col 
= owner
->GetColumn(idx
); 
 170         if ( !col
->IsSortable() ) 
 172             // no default handling for non-sortable columns 
 177         if ( col
->IsSortKey() ) 
 179             // already using this column for sorting, just change the order 
 180             col
->ToggleSortOrder(); 
 182         else // not using this column for sorting yet 
 184             // first unset the old sort column if any 
 185             int oldSortKey 
= owner
->GetSortingColumnIndex(); 
 186             if ( oldSortKey 
!= wxNOT_FOUND 
) 
 188                 owner
->GetColumn(oldSortKey
)->UnsetAsSortKey(); 
 189                 owner
->OnColumnChange(oldSortKey
); 
 192             owner
->SetSortingColumnIndex(idx
); 
 196         wxDataViewModel 
* const model 
= owner
->GetModel(); 
 200         owner
->OnColumnChange(idx
); 
 203     void OnRClick(wxHeaderCtrlEvent
& event
) 
 205         if ( !SendEvent(wxEVT_COMMAND_DATAVIEW_COLUMN_HEADER_RIGHT_CLICK
, 
 210     void OnResize(wxHeaderCtrlEvent
& event
) 
 212         wxDataViewCtrl 
* const owner 
= GetOwner(); 
 214         const unsigned col 
= event
.GetColumn(); 
 215         owner
->GetColumn(col
)->SetWidth(event
.GetWidth()); 
 216         GetOwner()->OnColumnChange(col
); 
 219     void OnEndReorder(wxHeaderCtrlEvent
& event
) 
 221         wxDataViewCtrl 
* const owner 
= GetOwner(); 
 222         owner
->ColumnMoved(owner
->GetColumn(event
.GetColumn()), 
 223                         event
.GetNewOrder()); 
 226     DECLARE_EVENT_TABLE() 
 227     wxDECLARE_NO_COPY_CLASS(wxDataViewHeaderWindow
); 
 230 BEGIN_EVENT_TABLE(wxDataViewHeaderWindow
, wxHeaderCtrl
) 
 231     EVT_HEADER_CLICK(wxID_ANY
, wxDataViewHeaderWindow::OnClick
) 
 232     EVT_HEADER_RIGHT_CLICK(wxID_ANY
, wxDataViewHeaderWindow::OnRClick
) 
 234     EVT_HEADER_RESIZING(wxID_ANY
, wxDataViewHeaderWindow::OnResize
) 
 235     EVT_HEADER_END_RESIZE(wxID_ANY
, wxDataViewHeaderWindow::OnResize
) 
 237     EVT_HEADER_END_REORDER(wxID_ANY
, wxDataViewHeaderWindow::OnEndReorder
) 
 240 //----------------------------------------------------------------------------- 
 241 // wxDataViewRenameTimer 
 242 //----------------------------------------------------------------------------- 
 244 class wxDataViewRenameTimer
: public wxTimer
 
 247     wxDataViewMainWindow 
*m_owner
; 
 250     wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
); 
 254 //----------------------------------------------------------------------------- 
 255 // wxDataViewTreeNode 
 256 //----------------------------------------------------------------------------- 
 258 class wxDataViewTreeNode
; 
 259 WX_DEFINE_ARRAY( wxDataViewTreeNode 
*, wxDataViewTreeNodes 
); 
 260 WX_DEFINE_ARRAY( void* , wxDataViewTreeLeaves
); 
 262 int LINKAGEMODE 
wxGenericTreeModelNodeCmp( wxDataViewTreeNode 
** node1
, 
 263                                            wxDataViewTreeNode 
** node2
); 
 264 int LINKAGEMODE 
wxGenericTreeModelItemCmp( void ** id1
, void ** id2
); 
 266 class wxDataViewTreeNode
 
 269     wxDataViewTreeNode( wxDataViewTreeNode 
* parent 
= NULL 
) 
 276         m_hasChildren 
= false; 
 280     ~wxDataViewTreeNode() 
 284     wxDataViewTreeNode 
* GetParent() const { return m_parent
; } 
 285     void SetParent( wxDataViewTreeNode 
* parent 
) { m_parent 
= parent
; } 
 286     wxDataViewTreeNodes 
&  GetNodes() { return m_nodes
; } 
 287     wxDataViewTreeLeaves 
& GetChildren() { return m_leaves
; } 
 289     void AddNode( wxDataViewTreeNode 
* node 
) 
 291         m_leaves
.Add( node
->GetItem().GetID() ); 
 293             m_leaves
.Sort( &wxGenericTreeModelItemCmp 
); 
 296             m_nodes
.Sort( &wxGenericTreeModelNodeCmp 
); 
 298     void AddLeaf( void * leaf 
) 
 300         m_leaves
.Add( leaf 
); 
 302             m_leaves
.Sort( &wxGenericTreeModelItemCmp 
); 
 305     wxDataViewItem 
& GetItem() { return m_item
; } 
 306     const wxDataViewItem 
& GetItem() const { return m_item
; } 
 307     void SetItem( const wxDataViewItem 
& item 
) { m_item 
= item
; } 
 309     unsigned int GetChildrenNumber() const { return m_leaves
.GetCount(); } 
 310     unsigned int GetNodeNumber() const { return m_nodes
.GetCount(); } 
 311     int GetIndentLevel() const 
 314         const wxDataViewTreeNode 
* node 
= this; 
 315         while( node
->GetParent()->GetParent() != NULL 
) 
 317             node 
= node
->GetParent(); 
 330         int len 
= m_nodes
.GetCount(); 
 332         for ( int i 
= 0;i 
< len
; i 
++) 
 333             sum 
+= m_nodes
[i
]->GetSubTreeCount(); 
 335         sum 
+= m_leaves
.GetCount(); 
 338             ChangeSubTreeCount(-sum
); 
 344             ChangeSubTreeCount(sum
); 
 347     bool HasChildren() const { return m_hasChildren
; } 
 348     void SetHasChildren( bool has 
){ m_hasChildren 
= has
; } 
 350     void SetSubTreeCount( int num 
) { m_subTreeCount 
= num
; } 
 351     int GetSubTreeCount() const { return m_subTreeCount
; } 
 352     void ChangeSubTreeCount( int num 
) 
 356         m_subTreeCount 
+= num
; 
 358             m_parent
->ChangeSubTreeCount(num
); 
 365             m_nodes
.Sort( &wxGenericTreeModelNodeCmp 
); 
 366             int len 
= m_nodes
.GetCount(); 
 367             for (int i 
= 0; i 
< len
; i 
++) 
 368                 m_nodes
[i
]->Resort(); 
 369             m_leaves
.Sort( &wxGenericTreeModelItemCmp 
); 
 374     wxDataViewTreeNode  
*m_parent
; 
 375     wxDataViewTreeNodes  m_nodes
; 
 376     wxDataViewTreeLeaves m_leaves
; 
 377     wxDataViewItem       m_item
; 
 383 int LINKAGEMODE 
wxGenericTreeModelNodeCmp( wxDataViewTreeNode 
** node1
, 
 384                                            wxDataViewTreeNode 
** node2
) 
 386     return g_model
->Compare( (*node1
)->GetItem(), (*node2
)->GetItem(), g_column
, g_asending 
); 
 389 int LINKAGEMODE 
wxGenericTreeModelItemCmp( void ** id1
, void ** id2
) 
 391     return g_model
->Compare( *id1
, *id2
, g_column
, g_asending 
); 
 395 //----------------------------------------------------------------------------- 
 396 // wxDataViewMainWindow 
 397 //----------------------------------------------------------------------------- 
 399 WX_DEFINE_SORTED_USER_EXPORTED_ARRAY_SIZE_T(unsigned int, wxDataViewSelection
, 
 401 WX_DECLARE_LIST(wxDataViewItem
, ItemList
); 
 402 WX_DEFINE_LIST(ItemList
) 
 404 class wxDataViewMainWindow
: public wxWindow
 
 407     wxDataViewMainWindow( wxDataViewCtrl 
*parent
, 
 409                             const wxPoint 
&pos 
= wxDefaultPosition
, 
 410                             const wxSize 
&size 
= wxDefaultSize
, 
 411                             const wxString 
&name 
= wxT("wxdataviewctrlmainwindow") ); 
 412     virtual ~wxDataViewMainWindow(); 
 414     bool IsList() const { return GetOwner()->GetModel()->IsListModel(); } 
 415     bool IsVirtualList() const { return m_root 
== NULL
; } 
 417     // notifications from wxDataViewModel 
 418     bool ItemAdded( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
); 
 419     bool ItemDeleted( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
); 
 420     bool ItemChanged( const wxDataViewItem 
&item 
); 
 421     bool ValueChanged( const wxDataViewItem 
&item
, unsigned int col 
); 
 425         if (!IsVirtualList()) 
 435         g_model 
= GetOwner()->GetModel(); 
 436         wxDataViewColumn
* col 
= GetOwner()->GetSortingColumn(); 
 439             if (g_model
->HasDefaultCompare()) 
 447         g_column 
= col
->GetModelColumn(); 
 448         g_asending 
= col
->IsSortOrderAscending(); 
 451     void SetOwner( wxDataViewCtrl
* owner 
) { m_owner 
= owner
; } 
 452     wxDataViewCtrl 
*GetOwner() { return m_owner
; } 
 453     const wxDataViewCtrl 
*GetOwner() const { return m_owner
; } 
 455 #if wxUSE_DRAG_AND_DROP 
 456     wxBitmap 
CreateItemBitmap( unsigned int row
, int &indent 
); 
 457 #endif // wxUSE_DRAG_AND_DROP 
 458     void OnPaint( wxPaintEvent 
&event 
); 
 459     void OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
); 
 460     void OnChar( wxKeyEvent 
&event 
); 
 461     void OnMouse( wxMouseEvent 
&event 
); 
 462     void OnSetFocus( wxFocusEvent 
&event 
); 
 463     void OnKillFocus( wxFocusEvent 
&event 
); 
 465     void UpdateDisplay(); 
 466     void RecalculateDisplay(); 
 467     void OnInternalIdle(); 
 469     void OnRenameTimer(); 
 471     void ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
= NULL 
); 
 472     void ScrollTo( int rows
, int column 
); 
 474     unsigned GetCurrentRow() const { return m_currentRow
; } 
 475     bool HasCurrentRow() { return m_currentRow 
!= (unsigned int)-1; } 
 476     void ChangeCurrentRow( unsigned int row 
); 
 478     bool IsSingleSel() const { return !GetParent()->HasFlag(wxDV_MULTIPLE
); } 
 479     bool IsEmpty() { return GetRowCount() == 0; } 
 481     int GetCountPerPage() const; 
 482     int GetEndOfLastCol() const; 
 483     unsigned int GetFirstVisibleRow() const; 
 485     // I change this method to un const because in the tree view, 
 486     // the displaying number of the tree are changing along with the 
 487     // expanding/collapsing of the tree nodes 
 488     unsigned int GetLastVisibleRow(); 
 489     unsigned int GetRowCount(); 
 491     wxDataViewItem 
GetSelection() const; 
 492     wxDataViewSelection 
GetSelections(){ return m_selection
; } 
 493     void SetSelections( const wxDataViewSelection 
& sel 
) 
 494         { m_selection 
= sel
; UpdateDisplay(); } 
 495     void Select( const wxArrayInt
& aSelections 
); 
 496     void SelectAllRows( bool on 
); 
 497     void SelectRow( unsigned int row
, bool on 
); 
 498     void SelectRows( unsigned int from
, unsigned int to
, bool on 
); 
 499     void ReverseRowSelection( unsigned int row 
); 
 500     bool IsRowSelected( unsigned int row 
); 
 501     void SendSelectionChangedEvent( const wxDataViewItem
& item
); 
 503     void RefreshRow( unsigned int row 
); 
 504     void RefreshRows( unsigned int from
, unsigned int to 
); 
 505     void RefreshRowsAfter( unsigned int firstRow 
); 
 507     // returns the colour to be used for drawing the rules 
 508     wxColour 
GetRuleColour() const 
 510         return wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT
); 
 513     wxRect 
GetLineRect( unsigned int row 
) const; 
 515     int GetLineStart( unsigned int row 
) const;  // row * m_lineHeight in fixed mode 
 516     int GetLineHeight( unsigned int row 
) const; // m_lineHeight in fixed mode 
 517     int GetLineAt( unsigned int y 
) const;       // y / m_lineHeight in fixed mode 
 519     // Some useful functions for row and item mapping 
 520     wxDataViewItem 
GetItemByRow( unsigned int row 
) const; 
 521     int GetRowByItem( const wxDataViewItem 
& item 
) const; 
 523     // Methods for building the mapping tree 
 524     void BuildTree( wxDataViewModel  
* model 
); 
 526     void HitTest( const wxPoint 
& point
, wxDataViewItem 
& item
, wxDataViewColumn
* &column 
); 
 527     wxRect 
GetItemRect( const wxDataViewItem 
& item
, const wxDataViewColumn
* column 
); 
 529     void Expand( unsigned int row 
); 
 530     void Collapse( unsigned int row 
); 
 531     bool IsExpanded( unsigned int row 
) const; 
 532     bool HasChildren( unsigned int row 
) const; 
 534 #if wxUSE_DRAG_AND_DROP 
 535     bool EnableDragSource( const wxDataFormat 
&format 
); 
 536     bool EnableDropTarget( const wxDataFormat 
&format 
); 
 538     void RemoveDropHint(); 
 539     wxDragResult 
OnDragOver( wxDataFormat format
, wxCoord x
, wxCoord y
, wxDragResult def 
); 
 540     bool OnDrop( wxDataFormat format
, wxCoord x
, wxCoord y 
); 
 541     wxDragResult 
OnData( wxDataFormat format
, wxCoord x
, wxCoord y
, wxDragResult def 
); 
 543 #endif // wxUSE_DRAG_AND_DROP 
 546     wxDataViewTreeNode 
* GetTreeNodeByRow( unsigned int row 
) const; 
 547     // We did not need this temporarily 
 548     // wxDataViewTreeNode * GetTreeNodeByItem( const wxDataViewItem & item ); 
 550     int RecalculateCount(); 
 552     wxDataViewEvent 
SendExpanderEvent( wxEventType type
, const wxDataViewItem 
& item 
); 
 554     wxDataViewTreeNode 
* FindNode( const wxDataViewItem 
& item 
); 
 557     wxDataViewCtrl             
*m_owner
; 
 561     wxDataViewColumn           
*m_currentCol
; 
 562     unsigned int                m_currentRow
; 
 563     wxDataViewSelection         m_selection
; 
 565     wxDataViewRenameTimer      
*m_renameTimer
; 
 570 #if wxUSE_DRAG_AND_DROP 
 575     wxDataFormat                m_dragFormat
; 
 578     wxDataFormat                m_dropFormat
; 
 580     unsigned int                m_dropHintLine
; 
 581 #endif // wxUSE_DRAG_AND_DROP 
 583     // for double click logic 
 584     unsigned int m_lineLastClicked
, 
 585         m_lineBeforeLastClicked
, 
 586         m_lineSelectSingleOnUp
; 
 588     // the pen used to draw horiz/vertical rules 
 591     // the pen used to draw the expander and the lines 
 594     // This is the tree structure of the model 
 595     wxDataViewTreeNode 
* m_root
; 
 598     // This is the tree node under the cursor 
 599     wxDataViewTreeNode 
* m_underMouse
; 
 602     DECLARE_DYNAMIC_CLASS(wxDataViewMainWindow
) 
 603     DECLARE_EVENT_TABLE() 
 606 // --------------------------------------------------------- 
 607 // wxGenericDataViewModelNotifier 
 608 // --------------------------------------------------------- 
 610 class wxGenericDataViewModelNotifier
: public wxDataViewModelNotifier
 
 613     wxGenericDataViewModelNotifier( wxDataViewMainWindow 
*mainWindow 
) 
 614         { m_mainWindow 
= mainWindow
; } 
 616     virtual bool ItemAdded( const wxDataViewItem 
& parent
, const wxDataViewItem 
& item 
) 
 617         { return m_mainWindow
->ItemAdded( parent 
, item 
); } 
 618     virtual bool ItemDeleted( const wxDataViewItem 
&parent
, const wxDataViewItem 
&item 
) 
 619         { return m_mainWindow
->ItemDeleted( parent
, item 
); } 
 620     virtual bool ItemChanged( const wxDataViewItem 
& item 
) 
 621         { return m_mainWindow
->ItemChanged(item
);  } 
 622     virtual bool ValueChanged( const wxDataViewItem 
& item 
, unsigned int col 
) 
 623         { return m_mainWindow
->ValueChanged( item
, col 
); } 
 624     virtual bool Cleared() 
 625         { return m_mainWindow
->Cleared(); } 
 626     virtual void Resort() 
 627         { m_mainWindow
->Resort(); } 
 629     wxDataViewMainWindow    
*m_mainWindow
; 
 632 // --------------------------------------------------------- 
 633 // wxDataViewRenderer 
 634 // --------------------------------------------------------- 
 636 IMPLEMENT_ABSTRACT_CLASS(wxDataViewRenderer
, wxDataViewRendererBase
) 
 638 wxDataViewRenderer::wxDataViewRenderer( const wxString 
&varianttype
, 
 639                                         wxDataViewCellMode mode
, 
 641     wxDataViewCustomRendererBase( varianttype
, mode
, align 
) 
 645     m_ellipsizeMode 
= wxELLIPSIZE_MIDDLE
; 
 649 wxDataViewRenderer::~wxDataViewRenderer() 
 654 wxDC 
*wxDataViewRenderer::GetDC() 
 658         if (GetOwner() == NULL
) 
 660         if (GetOwner()->GetOwner() == NULL
) 
 662         m_dc 
= new wxClientDC( GetOwner()->GetOwner() ); 
 668 void wxDataViewRenderer::SetAlignment( int align 
) 
 673 int wxDataViewRenderer::GetAlignment() const 
 678 // --------------------------------------------------------- 
 679 // wxDataViewCustomRenderer 
 680 // --------------------------------------------------------- 
 682 IMPLEMENT_ABSTRACT_CLASS(wxDataViewCustomRenderer
, wxDataViewRenderer
) 
 684 wxDataViewCustomRenderer::wxDataViewCustomRenderer( const wxString 
&varianttype
, 
 685                         wxDataViewCellMode mode
, int align 
) : 
 686     wxDataViewRenderer( varianttype
, mode
, align 
) 
 690 // --------------------------------------------------------- 
 691 // wxDataViewTextRenderer 
 692 // --------------------------------------------------------- 
 694 IMPLEMENT_CLASS(wxDataViewTextRenderer
, wxDataViewRenderer
) 
 696 wxDataViewTextRenderer::wxDataViewTextRenderer( const wxString 
&varianttype
, 
 697                                                 wxDataViewCellMode mode
, int align 
) : 
 698     wxDataViewRenderer( varianttype
, mode
, align 
) 
 702 bool wxDataViewTextRenderer::SetValue( const wxVariant 
&value 
) 
 704     m_text 
= value
.GetString(); 
 709 bool wxDataViewTextRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) const 
 714 bool wxDataViewTextRenderer::HasEditorCtrl() const 
 719 wxControl
* wxDataViewTextRenderer::CreateEditorCtrl( wxWindow 
*parent
, 
 720         wxRect labelRect
, const wxVariant 
&value 
) 
 722     wxTextCtrl
* ctrl 
= new wxTextCtrl( parent
, wxID_ANY
, value
, 
 723                                        wxPoint(labelRect
.x
,labelRect
.y
), 
 724                                        wxSize(labelRect
.width
,labelRect
.height
) ); 
 726     // select the text in the control an place the cursor at the end 
 727     ctrl
->SetInsertionPointEnd(); 
 733 bool wxDataViewTextRenderer::GetValueFromEditorCtrl( wxControl 
*editor
, wxVariant 
&value 
) 
 735     wxTextCtrl 
*text 
= (wxTextCtrl
*) editor
; 
 736     value 
= text
->GetValue(); 
 740 bool wxDataViewTextRenderer::Render(wxRect rect
, wxDC 
*dc
, int state
) 
 742     RenderText(m_text
, 0, rect
, dc
, state
); 
 746 wxSize 
wxDataViewTextRenderer::GetSize() const 
 748     const wxDataViewCtrl 
*view 
= GetView(); 
 750         return view
->wxWindowBase::GetTextExtent( m_text 
); 
 751     return wxSize(wxDVC_DEFAULT_RENDERER_SIZE
,wxDVC_DEFAULT_RENDERER_SIZE
); 
 754 // --------------------------------------------------------- 
 755 // wxDataViewBitmapRenderer 
 756 // --------------------------------------------------------- 
 758 IMPLEMENT_CLASS(wxDataViewBitmapRenderer
, wxDataViewRenderer
) 
 760 wxDataViewBitmapRenderer::wxDataViewBitmapRenderer( const wxString 
&varianttype
, 
 761                                                     wxDataViewCellMode mode
, int align 
) : 
 762     wxDataViewRenderer( varianttype
, mode
, align 
) 
 766 bool wxDataViewBitmapRenderer::SetValue( const wxVariant 
&value 
) 
 768     if (value
.GetType() == wxT("wxBitmap")) 
 770     if (value
.GetType() == wxT("wxIcon")) 
 776 bool wxDataViewBitmapRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) const 
 781 bool wxDataViewBitmapRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 784         dc
->DrawBitmap( m_bitmap
, cell
.x
, cell
.y 
); 
 785     else if (m_icon
.Ok()) 
 786         dc
->DrawIcon( m_icon
, cell
.x
, cell
.y 
); 
 791 wxSize 
wxDataViewBitmapRenderer::GetSize() const 
 794         return wxSize( m_bitmap
.GetWidth(), m_bitmap
.GetHeight() ); 
 795     else if (m_icon
.Ok()) 
 796         return wxSize( m_icon
.GetWidth(), m_icon
.GetHeight() ); 
 798     return wxSize(wxDVC_DEFAULT_RENDERER_SIZE
,wxDVC_DEFAULT_RENDERER_SIZE
); 
 801 // --------------------------------------------------------- 
 802 // wxDataViewToggleRenderer 
 803 // --------------------------------------------------------- 
 805 IMPLEMENT_ABSTRACT_CLASS(wxDataViewToggleRenderer
, wxDataViewRenderer
) 
 807 wxDataViewToggleRenderer::wxDataViewToggleRenderer( const wxString 
&varianttype
, 
 808                         wxDataViewCellMode mode
, int align 
) : 
 809     wxDataViewRenderer( varianttype
, mode
, align 
) 
 814 bool wxDataViewToggleRenderer::SetValue( const wxVariant 
&value 
) 
 816     m_toggle 
= value
.GetBool(); 
 821 bool wxDataViewToggleRenderer::GetValue( wxVariant 
&WXUNUSED(value
) ) const 
 826 bool wxDataViewToggleRenderer::Render( wxRect cell
, wxDC 
*dc
, int WXUNUSED(state
) ) 
 830         flags 
|= wxCONTROL_CHECKED
; 
 831     if (GetMode() != wxDATAVIEW_CELL_ACTIVATABLE
) 
 832         flags 
|= wxCONTROL_DISABLED
; 
 834     // check boxes we draw must always have the same, standard size (if it's 
 835     // bigger than the cell size the checkbox will be truncated because the 
 836     // caller had set the clipping rectangle to prevent us from drawing outside 
 838     cell
.SetSize(GetSize()); 
 840     wxRendererNative::Get().DrawCheckBox( 
 841             GetOwner()->GetOwner(), 
 849 void wxDataViewToggleRenderer::WXOnActivate(wxDataViewModel 
*model
, 
 850                                             const wxVariant
& valueOld
, 
 851                                             const wxDataViewItem 
& item
, 
 854     model
->ChangeValue(!valueOld
.GetBool(), item
, col
); 
 857 wxSize 
wxDataViewToggleRenderer::GetSize() const 
 859     // the window parameter is not used by GetCheckBoxSize() so it's 
 861     return wxRendererNative::Get().GetCheckBoxSize(NULL
); 
 864 // --------------------------------------------------------- 
 865 // wxDataViewProgressRenderer 
 866 // --------------------------------------------------------- 
 868 IMPLEMENT_ABSTRACT_CLASS(wxDataViewProgressRenderer
, wxDataViewRenderer
) 
 870 wxDataViewProgressRenderer::wxDataViewProgressRenderer( const wxString 
&label
, 
 871     const wxString 
&varianttype
, wxDataViewCellMode mode
, int align 
) : 
 872     wxDataViewRenderer( varianttype
, mode
, align 
) 
 878 bool wxDataViewProgressRenderer::SetValue( const wxVariant 
&value 
) 
 880     m_value 
= (long) value
; 
 882     if (m_value 
< 0) m_value 
= 0; 
 883     if (m_value 
> 100) m_value 
= 100; 
 888 bool wxDataViewProgressRenderer::GetValue( wxVariant 
&value 
) const 
 890     value 
= (long) m_value
; 
 895 wxDataViewProgressRenderer::Render(wxRect rect
, wxDC 
*dc
, int WXUNUSED(state
)) 
 897     // deflate the rect to leave a small border between bars in adjacent rows 
 898     wxRect bar 
= rect
.Deflate(0, 1); 
 900     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
 901     dc
->SetPen( *wxBLACK_PEN 
); 
 902     dc
->DrawRectangle( bar 
); 
 904     bar
.width 
= (int)(bar
.width 
* m_value 
/ 100.); 
 905     dc
->SetPen( *wxTRANSPARENT_PEN 
); 
 907     const wxDataViewItemAttr
& attr 
= GetAttr(); 
 908     dc
->SetBrush( attr
.HasColour() ? wxBrush(attr
.GetColour()) 
 910     dc
->DrawRectangle( bar 
); 
 915 wxSize 
wxDataViewProgressRenderer::GetSize() const 
 917     return wxSize(40,12); 
 920 // --------------------------------------------------------- 
 921 // wxDataViewDateRenderer 
 922 // --------------------------------------------------------- 
 924 #define wxUSE_DATE_RENDERER_POPUP (wxUSE_CALENDARCTRL && wxUSE_POPUPWIN) 
 926 #if wxUSE_DATE_RENDERER_POPUP 
 928 class wxDataViewDateRendererPopupTransient
: public wxPopupTransientWindow
 
 931     wxDataViewDateRendererPopupTransient( wxWindow
* parent
, wxDateTime 
*value
, 
 932         wxDataViewModel 
*model
, const wxDataViewItem 
& item
, unsigned int col
) : 
 933         wxPopupTransientWindow( parent
, wxBORDER_SIMPLE 
), 
 938         m_cal 
= new wxCalendarCtrl( this, wxID_ANY
, *value 
); 
 939         wxBoxSizer 
*sizer 
= new wxBoxSizer( wxHORIZONTAL 
); 
 940         sizer
->Add( m_cal
, 1, wxGROW 
); 
 945     void OnCalendar( wxCalendarEvent 
&event 
); 
 947     wxCalendarCtrl      
*m_cal
; 
 948     wxDataViewModel 
*m_model
; 
 950     const wxDataViewItem 
&   m_item
; 
 953     virtual void OnDismiss() 
 958     DECLARE_EVENT_TABLE() 
 961 BEGIN_EVENT_TABLE(wxDataViewDateRendererPopupTransient
,wxPopupTransientWindow
) 
 962     EVT_CALENDAR( wxID_ANY
, wxDataViewDateRendererPopupTransient::OnCalendar 
) 
 965 void wxDataViewDateRendererPopupTransient::OnCalendar( wxCalendarEvent 
&event 
) 
 967     m_model
->ChangeValue( event
.GetDate(), m_item
, m_col 
); 
 971 #endif // wxUSE_DATE_RENDERER_POPUP 
 973 IMPLEMENT_ABSTRACT_CLASS(wxDataViewDateRenderer
, wxDataViewRenderer
) 
 975 wxDataViewDateRenderer::wxDataViewDateRenderer( const wxString 
&varianttype
, 
 976                         wxDataViewCellMode mode
, int align 
) : 
 977     wxDataViewRenderer( varianttype
, mode
, align 
) 
 981 bool wxDataViewDateRenderer::SetValue( const wxVariant 
&value 
) 
 983     m_date 
= value
.GetDateTime(); 
 988 bool wxDataViewDateRenderer::GetValue( wxVariant 
&value 
) const 
 994 bool wxDataViewDateRenderer::Render( wxRect cell
, wxDC 
*dc
, int state 
) 
 996     wxString tmp 
= m_date
.FormatDate(); 
 997     RenderText( tmp
, 0, cell
, dc
, state 
); 
1001 wxSize 
wxDataViewDateRenderer::GetSize() const 
1003     const wxDataViewCtrl
* view 
= GetView(); 
1004     wxString tmp 
= m_date
.FormatDate(); 
1006     view
->GetTextExtent( tmp
, &x
, &y
, &d 
); 
1007     return wxSize(x
,y
+d
); 
1010 void wxDataViewDateRenderer::WXOnActivate(wxDataViewModel 
*model
, 
1011                                           const wxVariant
& valueOld
, 
1012                                           const wxDataViewItem 
& item
, 
1015     wxDateTime dtOld 
= valueOld
.GetDateTime(); 
1017 #if wxUSE_DATE_RENDERER_POPUP 
1018     wxDataViewDateRendererPopupTransient 
*popup 
= new wxDataViewDateRendererPopupTransient( 
1019         GetOwner()->GetOwner()->GetParent(), &dtOld
, model
, item
, col
); 
1020     wxPoint pos 
= wxGetMousePosition(); 
1023     popup
->Popup( popup
->m_cal 
); 
1024 #else // !wxUSE_DATE_RENDERER_POPUP 
1025     wxMessageBox(dtOld
.Format()); 
1026 #endif // wxUSE_DATE_RENDERER_POPUP/!wxUSE_DATE_RENDERER_POPUP 
1029 // --------------------------------------------------------- 
1030 // wxDataViewIconTextRenderer 
1031 // --------------------------------------------------------- 
1033 IMPLEMENT_CLASS(wxDataViewIconTextRenderer
, wxDataViewRenderer
) 
1035 wxDataViewIconTextRenderer::wxDataViewIconTextRenderer( 
1036 const wxString 
&varianttype
, wxDataViewCellMode mode
, int align 
) : 
1037     wxDataViewRenderer( varianttype
, mode
, align 
) 
1040     SetAlignment(align
); 
1043 bool wxDataViewIconTextRenderer::SetValue( const wxVariant 
&value 
) 
1049 bool wxDataViewIconTextRenderer::GetValue( wxVariant
& WXUNUSED(value
) ) const 
1054 bool wxDataViewIconTextRenderer::Render(wxRect rect
, wxDC 
*dc
, int state
) 
1058     const wxIcon
& icon 
= m_value
.GetIcon(); 
1061         dc
->DrawIcon(icon
, rect
.x
, rect
.y 
+ (rect
.height 
- icon
.GetHeight())/2); 
1062         xoffset 
= icon
.GetWidth()+4; 
1065     RenderText(m_value
.GetText(), xoffset
, rect
, dc
, state
); 
1070 wxSize 
wxDataViewIconTextRenderer::GetSize() const 
1072     const wxDataViewCtrl 
*view 
= GetView(); 
1073     if (!m_value
.GetText().empty()) 
1076         view
->GetTextExtent( m_value
.GetText(), &x
, &y 
); 
1078         if (m_value
.GetIcon().IsOk()) 
1079             x 
+= m_value
.GetIcon().GetWidth() + 4; 
1080         return wxSize( x
, y 
); 
1082     return wxSize(80,20); 
1085 wxControl
* wxDataViewIconTextRenderer::CreateEditorCtrl(wxWindow 
*parent
, wxRect labelRect
, const wxVariant
& value
) 
1087     wxDataViewIconText iconText
; 
1090     wxString text 
= iconText
.GetText(); 
1092     // adjust the label rect to take the width of the icon into account 
1093     if (iconText
.GetIcon().IsOk()) 
1095         int w 
= iconText
.GetIcon().GetWidth() + 4; 
1097         labelRect
.width 
-= w
; 
1100     wxTextCtrl
* ctrl 
= new wxTextCtrl( parent
, wxID_ANY
, text
, 
1101                                        wxPoint(labelRect
.x
,labelRect
.y
), 
1102                                        wxSize(labelRect
.width
,labelRect
.height
) ); 
1104     // select the text in the control an place the cursor at the end 
1105     ctrl
->SetInsertionPointEnd(); 
1111 bool wxDataViewIconTextRenderer::GetValueFromEditorCtrl( wxControl 
*editor
, wxVariant
& value 
) 
1113     wxTextCtrl 
*text 
= (wxTextCtrl
*) editor
; 
1115     wxDataViewIconText 
iconText(text
->GetValue(), m_value
.GetIcon()); 
1120 //----------------------------------------------------------------------------- 
1121 // wxDataViewDropTarget 
1122 //----------------------------------------------------------------------------- 
1124 #if wxUSE_DRAG_AND_DROP 
1126 class wxBitmapCanvas
: public wxWindow
 
1129     wxBitmapCanvas( wxWindow 
*parent
, const wxBitmap 
&bitmap
, const wxSize 
&size 
) : 
1130     wxWindow( parent
, wxID_ANY
, wxPoint(0,0), size 
) 
1133         Connect( wxEVT_PAINT
, wxPaintEventHandler(wxBitmapCanvas::OnPaint
) ); 
1136     void OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1139         dc
.DrawBitmap( m_bitmap
, 0, 0); 
1145 class wxDataViewDropSource
: public wxDropSource
 
1148     wxDataViewDropSource( wxDataViewMainWindow 
*win
, unsigned int row 
) : 
1156     ~wxDataViewDropSource() 
1161     virtual bool GiveFeedback( wxDragResult 
WXUNUSED(effect
) ) 
1163         wxPoint pos 
= wxGetMousePosition(); 
1167             int liney 
= m_win
->GetLineStart( m_row 
); 
1169             m_win
->GetOwner()->CalcUnscrolledPosition( 0, liney
, NULL
, &liney 
); 
1170             m_win
->ClientToScreen( &linex
, &liney 
); 
1171             m_dist_x 
= pos
.x 
- linex
; 
1172             m_dist_y 
= pos
.y 
- liney
; 
1175             wxBitmap ib 
= m_win
->CreateItemBitmap( m_row
, indent 
); 
1177             m_hint 
= new wxFrame( m_win
->GetParent(), wxID_ANY
, wxEmptyString
, 
1178                                         wxPoint(pos
.x 
- m_dist_x
, pos
.y 
+ 5 ), 
1180                                         wxFRAME_TOOL_WINDOW 
| 
1181                                         wxFRAME_FLOAT_ON_PARENT 
| 
1182                                         wxFRAME_NO_TASKBAR 
| 
1184             new wxBitmapCanvas( m_hint
, ib
, ib
.GetSize() ); 
1189             m_hint
->Move( pos
.x 
- m_dist_x
, pos
.y 
+ 5  ); 
1190             m_hint
->SetTransparent( 128 ); 
1196     wxDataViewMainWindow   
*m_win
; 
1199     int m_dist_x
,m_dist_y
; 
1203 class wxDataViewDropTarget
: public wxDropTarget
 
1206     wxDataViewDropTarget( wxDataObject 
*obj
, wxDataViewMainWindow 
*win 
) : 
1212     virtual wxDragResult 
OnDragOver( wxCoord x
, wxCoord y
, wxDragResult def 
) 
1214         wxDataFormat format 
= GetMatchingPair(); 
1215         if (format 
== wxDF_INVALID
) 
1217         return m_win
->OnDragOver( format
, x
, y
, def
); 
1220     virtual bool OnDrop( wxCoord x
, wxCoord y 
) 
1222         wxDataFormat format 
= GetMatchingPair(); 
1223         if (format 
== wxDF_INVALID
) 
1225         return m_win
->OnDrop( format
, x
, y 
); 
1228     virtual wxDragResult 
OnData( wxCoord x
, wxCoord y
, wxDragResult def 
) 
1230         wxDataFormat format 
= GetMatchingPair(); 
1231         if (format 
== wxDF_INVALID
) 
1235         return m_win
->OnData( format
, x
, y
, def 
); 
1238     virtual void OnLeave() 
1239         { m_win
->OnLeave(); } 
1241     wxDataViewMainWindow   
*m_win
; 
1244 #endif // wxUSE_DRAG_AND_DROP 
1246 //----------------------------------------------------------------------------- 
1247 // wxDataViewRenameTimer 
1248 //----------------------------------------------------------------------------- 
1250 wxDataViewRenameTimer::wxDataViewRenameTimer( wxDataViewMainWindow 
*owner 
) 
1255 void wxDataViewRenameTimer::Notify() 
1257     m_owner
->OnRenameTimer(); 
1260 //----------------------------------------------------------------------------- 
1261 // wxDataViewMainWindow 
1262 //----------------------------------------------------------------------------- 
1264 // The tree building helper, declared firstly 
1265 static void BuildTreeHelper( wxDataViewModel 
* model
,  wxDataViewItem 
& item
, 
1266                              wxDataViewTreeNode 
* node
); 
1268 int LINKAGEMODE 
wxDataViewSelectionCmp( unsigned int row1
, unsigned int row2 
) 
1270     if (row1 
> row2
) return 1; 
1271     if (row1 
== row2
) return 0; 
1275 IMPLEMENT_ABSTRACT_CLASS(wxDataViewMainWindow
, wxWindow
) 
1277 BEGIN_EVENT_TABLE(wxDataViewMainWindow
,wxWindow
) 
1278     EVT_PAINT         (wxDataViewMainWindow::OnPaint
) 
1279     EVT_MOUSE_EVENTS  (wxDataViewMainWindow::OnMouse
) 
1280     EVT_SET_FOCUS     (wxDataViewMainWindow::OnSetFocus
) 
1281     EVT_KILL_FOCUS    (wxDataViewMainWindow::OnKillFocus
) 
1282     EVT_CHAR          (wxDataViewMainWindow::OnChar
) 
1285 wxDataViewMainWindow::wxDataViewMainWindow( wxDataViewCtrl 
*parent
, wxWindowID id
, 
1286     const wxPoint 
&pos
, const wxSize 
&size
, const wxString 
&name 
) : 
1287     wxWindow( parent
, id
, pos
, size
, wxWANTS_CHARS
|wxBORDER_NONE
, name 
), 
1288     m_selection( wxDataViewSelectionCmp 
) 
1293     m_lastOnSame 
= false; 
1294     m_renameTimer 
= new wxDataViewRenameTimer( this ); 
1296     // TODO: user better initial values/nothing selected 
1297     m_currentCol 
= NULL
; 
1300     m_lineHeight 
= wxMax( 17, GetCharHeight() + 2 ); // 17 = mini icon height + 1 
1302 #if wxUSE_DRAG_AND_DROP 
1304     m_dragStart 
= wxPoint(0,0); 
1306     m_dragEnabled 
= false; 
1307     m_dropEnabled 
= false; 
1309     m_dropHintLine 
= (unsigned int) -1; 
1310 #endif // wxUSE_DRAG_AND_DROP 
1312     m_lineLastClicked 
= (unsigned int) -1; 
1313     m_lineBeforeLastClicked 
= (unsigned int) -1; 
1314     m_lineSelectSingleOnUp 
= (unsigned int) -1; 
1318     SetBackgroundColour( *wxWHITE 
); 
1320     SetBackgroundStyle(wxBG_STYLE_CUSTOM
); 
1322     m_penRule 
= wxPen(GetRuleColour()); 
1324     // compose a pen whichcan draw black lines 
1325     // TODO: maybe there is something system colour to use 
1326     m_penExpander 
= wxPen(wxColour(0,0,0)); 
1328     m_root 
= new wxDataViewTreeNode( NULL 
); 
1329     m_root
->SetHasChildren(true); 
1331     // Make m_count = -1 will cause the class recaculate the real displaying number of rows. 
1333     m_underMouse 
= NULL
; 
1337 wxDataViewMainWindow::~wxDataViewMainWindow() 
1340     delete m_renameTimer
; 
1344 #if wxUSE_DRAG_AND_DROP 
1345 bool wxDataViewMainWindow::EnableDragSource( const wxDataFormat 
&format 
) 
1347     m_dragFormat 
= format
; 
1348     m_dragEnabled 
= format 
!= wxDF_INVALID
; 
1353 bool wxDataViewMainWindow::EnableDropTarget( const wxDataFormat 
&format 
) 
1355     m_dropFormat 
= format
; 
1356     m_dropEnabled 
= format 
!= wxDF_INVALID
; 
1359         SetDropTarget( new wxDataViewDropTarget( new wxCustomDataObject( format 
), this ) ); 
1364 void wxDataViewMainWindow::RemoveDropHint() 
1369             RefreshRow( m_dropHintLine 
); 
1370             m_dropHintLine 
= (unsigned int) -1; 
1374 wxDragResult 
wxDataViewMainWindow::OnDragOver( wxDataFormat format
, wxCoord x
, 
1375                                                wxCoord y
, wxDragResult def 
) 
1379     m_owner
->CalcUnscrolledPosition( xx
, yy
, &xx
, &yy 
); 
1380     unsigned int row 
= GetLineAt( yy 
); 
1382     if ((row 
>= GetRowCount()) || (xx 
> GetEndOfLastCol())) 
1388     wxDataViewItem item 
= GetItemByRow( row 
); 
1390     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1392     wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE
, m_owner
->GetId() ); 
1393     event
.SetEventObject( m_owner 
); 
1394     event
.SetItem( item 
); 
1395     event
.SetModel( model 
); 
1396     event
.SetDataFormat( format 
); 
1397     if (!m_owner
->HandleWindowEvent( event 
)) 
1403     if (!event
.IsAllowed()) 
1410     if (m_dropHint 
&& (row 
!= m_dropHintLine
)) 
1411         RefreshRow( m_dropHintLine 
); 
1413     m_dropHintLine 
= row
; 
1419 bool wxDataViewMainWindow::OnDrop( wxDataFormat format
, wxCoord x
, wxCoord y 
) 
1425     m_owner
->CalcUnscrolledPosition( xx
, yy
, &xx
, &yy 
); 
1426     unsigned int row 
= GetLineAt( yy 
); 
1428     if ((row 
>= GetRowCount()) || (xx 
> GetEndOfLastCol())) 
1431     wxDataViewItem item 
= GetItemByRow( row 
); 
1433     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1435     wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP_POSSIBLE
, m_owner
->GetId() ); 
1436     event
.SetEventObject( m_owner 
); 
1437     event
.SetItem( item 
); 
1438     event
.SetModel( model 
); 
1439     event
.SetDataFormat( format 
); 
1440     if (!m_owner
->HandleWindowEvent( event 
)) 
1443     if (!event
.IsAllowed()) 
1449 wxDragResult 
wxDataViewMainWindow::OnData( wxDataFormat format
, wxCoord x
, wxCoord y
, 
1454     m_owner
->CalcUnscrolledPosition( xx
, yy
, &xx
, &yy 
); 
1455     unsigned int row 
= GetLineAt( yy 
); 
1457     if ((row 
>= GetRowCount()) || (xx 
> GetEndOfLastCol())) 
1460     wxDataViewItem item 
= GetItemByRow( row 
); 
1462     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1464     wxCustomDataObject 
*obj 
= (wxCustomDataObject 
*) GetDropTarget()->GetDataObject(); 
1466     wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_DROP
, m_owner
->GetId() ); 
1467     event
.SetEventObject( m_owner 
); 
1468     event
.SetItem( item 
); 
1469     event
.SetModel( model 
); 
1470     event
.SetDataFormat( format 
); 
1471     event
.SetDataSize( obj
->GetSize() ); 
1472     event
.SetDataBuffer( obj
->GetData() ); 
1473     if (!m_owner
->HandleWindowEvent( event 
)) 
1476     if (!event
.IsAllowed()) 
1482 void wxDataViewMainWindow::OnLeave() 
1487 wxBitmap 
wxDataViewMainWindow::CreateItemBitmap( unsigned int row
, int &indent 
) 
1489     int height 
= GetLineHeight( row 
); 
1491     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1493     for (col 
= 0; col 
< cols
; col
++) 
1495         wxDataViewColumn 
*column 
= GetOwner()->GetColumnAt(col
); 
1496         if (column
->IsHidden()) 
1497             continue;      // skip it! 
1498         width 
+= column
->GetWidth(); 
1504         wxDataViewTreeNode 
*node 
= GetTreeNodeByRow(row
); 
1505         indent 
= GetOwner()->GetIndent() * node
->GetIndentLevel(); 
1506         indent 
= indent 
+ m_lineHeight
; 
1507             // try to use the m_lineHeight as the expander space 
1509         if(!node
->HasChildren()) 
1514     wxBitmap 
bitmap( width
, height 
); 
1515     wxMemoryDC 
dc( bitmap 
); 
1516     dc
.SetFont( GetFont() ); 
1517     dc
.SetPen( *wxBLACK_PEN 
); 
1518     dc
.SetBrush( *wxWHITE_BRUSH 
); 
1519     dc
.DrawRectangle( 0,0,width
,height 
); 
1521     wxDataViewModel 
*model 
= m_owner
->GetModel(); 
1523     wxDataViewColumn 
*expander 
= GetOwner()->GetExpanderColumn(); 
1526         // TODO-RTL: last column for RTL support 
1527         expander 
= GetOwner()->GetColumnAt( 0 ); 
1528         GetOwner()->SetExpanderColumn(expander
); 
1533     for (col 
= 0; col 
< cols
; col
++) 
1535         wxDataViewColumn 
*column 
= GetOwner()->GetColumnAt( col 
); 
1536         wxDataViewRenderer 
*cell 
= column
->GetRenderer(); 
1538         if (column
->IsHidden()) 
1539             continue;       // skip it! 
1541         width 
= column
->GetWidth(); 
1543         if (column 
== expander
) 
1547         wxDataViewItem item 
= GetItemByRow( row 
); 
1548         model
->GetValue( value
, item
, column
->GetModelColumn()); 
1549         cell
->SetValue( value 
); 
1551         wxDataViewItemAttr attr
; 
1552         model
->GetAttr(item
, column
->GetModelColumn(), attr
); 
1553         cell
->SetAttr(attr
); 
1555         wxRect 
item_rect(x
, 0, width
, height
); 
1556         item_rect
.Deflate(PADDING_RIGHTLEFT
, 0); 
1558         // dc.SetClippingRegion( item_rect ); 
1559         cell
->WXCallRender(item_rect
, &dc
, 0); 
1560         // dc.DestroyClippingRegion(); 
1568 #endif // wxUSE_DRAG_AND_DROP 
1571 void wxDataViewMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1573     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
1574     wxAutoBufferedPaintDC 
dc( this ); 
1577     dc
.SetBrush(GetOwner()->GetBackgroundColour()); 
1578     dc
.SetPen( *wxTRANSPARENT_PEN 
); 
1579     dc
.DrawRectangle(GetClientSize()); 
1583     GetOwner()->PrepareDC( dc 
); 
1584     dc
.SetFont( GetFont() ); 
1586     wxRect update 
= GetUpdateRegion().GetBox(); 
1587     m_owner
->CalcUnscrolledPosition( update
.x
, update
.y
, &update
.x
, &update
.y 
); 
1589     // compute which items needs to be redrawn 
1590     unsigned int item_start 
= GetLineAt( wxMax(0,update
.y
) ); 
1591     unsigned int item_count 
= 
1592         wxMin( (int)(  GetLineAt( wxMax(0,update
.y
+update
.height
) ) - item_start 
+ 1), 
1593             (int)(GetRowCount( ) - item_start
)); 
1594     unsigned int item_last 
= item_start 
+ item_count
; 
1595     // Get the parent of DataViewCtrl 
1596     wxWindow 
*parent 
= GetParent()->GetParent(); 
1597     wxDataViewEvent 
cache_event(wxEVT_COMMAND_DATAVIEW_CACHE_HINT
, parent
->GetId()); 
1598     cache_event
.SetEventObject(GetParent()); 
1599     cache_event
.SetCache(item_start
, item_last 
- 1); 
1600     parent
->ProcessWindowEvent(cache_event
); 
1602     // compute which columns needs to be redrawn 
1603     unsigned int cols 
= GetOwner()->GetColumnCount(); 
1606         // we assume that we have at least one column below and painting an 
1607         // empty control is unnecessary anyhow 
1611     unsigned int col_start 
= 0; 
1612     unsigned int x_start
; 
1613     for (x_start 
= 0; col_start 
< cols
; col_start
++) 
1615         wxDataViewColumn 
*col 
= GetOwner()->GetColumnAt(col_start
); 
1616         if (col
->IsHidden()) 
1617             continue;      // skip it! 
1619         unsigned int w 
= col
->GetWidth(); 
1620         if (x_start
+w 
>= (unsigned int)update
.x
) 
1626     unsigned int col_last 
= col_start
; 
1627     unsigned int x_last 
= x_start
; 
1628     for (; col_last 
< cols
; col_last
++) 
1630         wxDataViewColumn 
*col 
= GetOwner()->GetColumnAt(col_last
); 
1631         if (col
->IsHidden()) 
1632             continue;      // skip it! 
1634         if (x_last 
> (unsigned int)update
.GetRight()) 
1637         x_last 
+= col
->GetWidth(); 
1640     // Draw horizontal rules if required 
1641     if ( m_owner
->HasFlag(wxDV_HORIZ_RULES
) ) 
1643         dc
.SetPen(m_penRule
); 
1644         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1646         for (unsigned int i 
= item_start
; i 
<= item_last
; i
++) 
1648             int y 
= GetLineStart( i 
); 
1649             dc
.DrawLine(x_start
, y
, x_last
, y
); 
1653     // Draw vertical rules if required 
1654     if ( m_owner
->HasFlag(wxDV_VERT_RULES
) ) 
1656         dc
.SetPen(m_penRule
); 
1657         dc
.SetBrush(*wxTRANSPARENT_BRUSH
); 
1660         for (unsigned int i 
= col_start
; i 
< col_last
; i
++) 
1662             wxDataViewColumn 
*col 
= GetOwner()->GetColumnAt(i
); 
1663             if (col
->IsHidden()) 
1664                 continue;       // skip it 
1666             dc
.DrawLine(x
, GetLineStart( item_start 
), 
1667                         x
, GetLineStart( item_last 
) ); 
1669             x 
+= col
->GetWidth(); 
1672         // Draw last vertical rule 
1673         dc
.DrawLine(x
, GetLineStart( item_start 
), 
1674                     x
, GetLineStart( item_last 
) ); 
1677     // redraw the background for the items which are selected/current 
1678     for (unsigned int item 
= item_start
; item 
< item_last
; item
++) 
1680         bool selected 
= m_selection
.Index( item 
) != wxNOT_FOUND
; 
1681         if (selected 
|| item 
== m_currentRow
) 
1683             int flags 
= selected 
? (int)wxCONTROL_SELECTED 
: 0; 
1684             if (item 
== m_currentRow
) 
1685                 flags 
|= wxCONTROL_CURRENT
; 
1687                 flags 
|= wxCONTROL_FOCUSED
; 
1689             wxRect 
rect( x_start
, GetLineStart( item 
), 
1690                          x_last 
- x_start
, GetLineHeight( item 
) ); 
1691             wxRendererNative::Get().DrawItemSelectionRect
 
1701 #if wxUSE_DRAG_AND_DROP 
1704         wxRect 
rect( x_start
, GetLineStart( m_dropHintLine 
), 
1705                      x_last 
- x_start
, GetLineHeight( m_dropHintLine 
) ); 
1706         dc
.SetPen( *wxBLACK_PEN 
); 
1707         dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
1708         dc
.DrawRectangle( rect 
); 
1710 #endif // wxUSE_DRAG_AND_DROP 
1712     wxDataViewColumn 
*expander 
= GetOwner()->GetExpanderColumn(); 
1715         // TODO-RTL: last column for RTL support 
1716         expander 
= GetOwner()->GetColumnAt( 0 ); 
1717         GetOwner()->SetExpanderColumn(expander
); 
1720     // redraw all cells for all rows which must be repainted and all columns 
1722     cell_rect
.x 
= x_start
; 
1723     for (unsigned int i 
= col_start
; i 
< col_last
; i
++) 
1725         wxDataViewColumn 
*col 
= GetOwner()->GetColumnAt( i 
); 
1726         wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
1727         cell_rect
.width 
= col
->GetWidth(); 
1729         if ( col
->IsHidden() || cell_rect
.width 
<= 0 ) 
1730             continue;       // skip it! 
1732         for (unsigned int item 
= item_start
; item 
< item_last
; item
++) 
1734             // get the cell value and set it into the renderer 
1736             wxDataViewTreeNode 
*node 
= NULL
; 
1737             wxDataViewItem dataitem
; 
1739             if (!IsVirtualList()) 
1741                 node 
= GetTreeNodeByRow(item
); 
1745                 dataitem 
= node
->GetItem(); 
1747                 if ((i 
> 0) && model
->IsContainer(dataitem
) && 
1748                     !model
->HasContainerColumns(dataitem
)) 
1753                 dataitem 
= wxDataViewItem( wxUIntToPtr(item
+1) ); 
1756             model
->GetValue( value
, dataitem
, col
->GetModelColumn()); 
1757             cell
->SetValue( value 
); 
1759             wxDataViewItemAttr attr
; 
1760             model
->GetAttr(dataitem
, col
->GetModelColumn(), attr
); 
1761             cell
->SetAttr(attr
); 
1764             cell_rect
.y 
= GetLineStart( item 
); 
1765             cell_rect
.height 
= GetLineHeight( item 
); 
1767             // deal with the expander 
1769             if ((!IsList()) && (col 
== expander
)) 
1771                 // Calculate the indent first 
1772                 indent 
= GetOwner()->GetIndent() * node
->GetIndentLevel(); 
1774                 // we reserve m_lineHeight of horizontal space for the expander 
1775                 // but leave EXPANDER_MARGIN around the expander itself 
1776                 int exp_x 
= cell_rect
.x 
+ indent 
+ EXPANDER_MARGIN
; 
1778                 indent 
+= m_lineHeight
; 
1780                 // draw expander if needed and visible 
1781                 if ( node
->HasChildren() && exp_x 
< cell_rect
.GetRight() ) 
1783                     dc
.SetPen( m_penExpander 
); 
1784                     dc
.SetBrush( wxNullBrush 
); 
1786                     int exp_size 
= m_lineHeight 
- 2*EXPANDER_MARGIN
; 
1787                     int exp_y 
= cell_rect
.y 
+ (cell_rect
.height 
- exp_size
)/2 
1788                                    + EXPANDER_MARGIN 
- EXPANDER_OFFSET
; 
1790                     const wxRect 
rect(exp_x
, exp_y
, exp_size
, exp_size
); 
1793                     if ( m_underMouse 
== node 
) 
1794                         flag 
|= wxCONTROL_CURRENT
; 
1795                     if ( node
->IsOpen() ) 
1796                         flag 
|= wxCONTROL_EXPANDED
; 
1798                     // ensure that we don't overflow the cell (which might 
1799                     // happen if the column is very narrow) 
1800                     wxDCClipper 
clip(dc
, cell_rect
); 
1802                     wxRendererNative::Get().DrawTreeItemButton( this, dc
, rect
, flag
); 
1805                 // force the expander column to left-center align 
1806                 cell
->SetAlignment( wxALIGN_CENTER_VERTICAL 
); 
1808             if (node 
&& !node
->HasChildren()) 
1810                 // Yes, if the node does not have any child, it must be a leaf which 
1811                 // mean that it is a temporarily created by GetTreeNodeByRow 
1815             wxRect item_rect 
= cell_rect
; 
1816             item_rect
.Deflate(PADDING_RIGHTLEFT
, 0); 
1818             // account for the tree indent (harmless if we're not indented) 
1819             item_rect
.x 
+= indent
; 
1820             item_rect
.width 
-= indent
; 
1822             if ( item_rect
.width 
<= 0 ) 
1826             if (m_hasFocus 
&& (m_selection
.Index(item
) != wxNOT_FOUND
)) 
1827                 state 
|= wxDATAVIEW_CELL_SELECTED
; 
1829             // TODO: it would be much more efficient to create a clipping 
1830             //       region for the entire column being rendered (in the OnPaint 
1831             //       of wxDataViewMainWindow) instead of a single clip region for 
1832             //       each cell. However it would mean that each renderer should 
1833             //       respect the given wxRect's top & bottom coords, eventually 
1834             //       violating only the left & right coords - however the user can 
1835             //       make its own renderer and thus we cannot be sure of that. 
1836             wxDCClipper 
clip(dc
, item_rect
); 
1838             cell
->WXCallRender(item_rect
, &dc
, state
); 
1841         cell_rect
.x 
+= cell_rect
.width
; 
1845 void wxDataViewMainWindow::OnRenameTimer() 
1847     // We have to call this here because changes may just have 
1848     // been made and no screen update taken place. 
1851         // TODO: use wxTheApp->SafeYieldFor(NULL, wxEVT_CATEGORY_UI) instead 
1852         //       (needs to be tested!) 
1856     wxDataViewItem item 
= GetItemByRow( m_currentRow 
); 
1858     wxRect labelRect 
= GetItemRect(item
, m_currentCol
); 
1860     m_currentCol
->GetRenderer()->StartEditing( item
, labelRect 
); 
1863 //----------------------------------------------------------------------------- 
1864 // Helper class for do operation on the tree node 
1865 //----------------------------------------------------------------------------- 
1870     virtual ~DoJob() { } 
1872     // The return value control how the tree-walker tranverse the tree 
1873     // 0: Job done, stop tranverse and return 
1874     // 1: Ignore the current node's subtree and continue 
1875     // 2: Job not done, continue 
1876     enum  { OK 
= 0 , IGR 
= 1, CONT 
= 2 }; 
1877     virtual int operator() ( wxDataViewTreeNode 
* node 
) = 0; 
1878     virtual int operator() ( void * n 
) = 0; 
1881 bool Walker( wxDataViewTreeNode 
* node
, DoJob 
& func 
) 
1886     switch( func( node 
) ) 
1897     wxDataViewTreeNodes nodes 
= node
->GetNodes(); 
1898     wxDataViewTreeLeaves leaves 
= node
->GetChildren(); 
1900     int len_nodes 
= nodes
.GetCount(); 
1901     int len 
= leaves
.GetCount(); 
1902     int i 
= 0, nodes_i 
= 0; 
1904     for(; i 
< len
; i 
++ ) 
1906         void * n 
= leaves
[i
]; 
1907         if( nodes_i 
< len_nodes 
&& n 
== nodes
[nodes_i
]->GetItem().GetID() ) 
1909             wxDataViewTreeNode 
* nd 
= nodes
[nodes_i
]; 
1912             if( Walker( nd 
, func 
) ) 
1931 bool wxDataViewMainWindow::ItemAdded(const wxDataViewItem 
& parent
, const wxDataViewItem 
& item
) 
1933     if (IsVirtualList()) 
1935         wxDataViewVirtualListModel 
*list_model 
= 
1936             (wxDataViewVirtualListModel
*) GetOwner()->GetModel(); 
1937         m_count 
= list_model
->GetCount(); 
1944     wxDataViewTreeNode 
* node
; 
1945     node 
= FindNode(parent
); 
1950     node
->SetHasChildren( true ); 
1952     if( g_model
->IsContainer( item 
) ) 
1954         wxDataViewTreeNode 
* newnode 
= new wxDataViewTreeNode( node 
); 
1955         newnode
->SetItem(item
); 
1956         newnode
->SetHasChildren( true ); 
1957         node
->AddNode( newnode
); 
1960         node
->AddLeaf( item
.GetID() ); 
1962     node
->ChangeSubTreeCount(1); 
1970 static void DestroyTreeHelper( wxDataViewTreeNode 
* node
); 
1972 bool wxDataViewMainWindow::ItemDeleted(const wxDataViewItem
& parent
, 
1973                                        const wxDataViewItem
& item
) 
1975     if (IsVirtualList()) 
1977         wxDataViewVirtualListModel 
*list_model 
= 
1978             (wxDataViewVirtualListModel
*) GetOwner()->GetModel(); 
1979         m_count 
= list_model
->GetCount(); 
1981         if( m_currentRow 
> GetRowCount() ) 
1982             m_currentRow 
= m_count 
- 1; 
1984         // TODO: why empty the entire selection? 
1985         m_selection
.Empty(); 
1992     wxDataViewTreeNode 
* node 
= FindNode(parent
); 
1994     // Notice that it is possible that the item being deleted is not in the 
1995     // tree at all, for example we could be deleting a never shown (because 
1996     // collapsed) item in a tree model. So it's not an error if we don't know 
1997     // about this item, just return without doing anything then. 
1998     if ( !node 
|| node
->GetChildren().Index(item
.GetID()) == wxNOT_FOUND 
) 
2002     node
->GetChildren().Remove( item
.GetID() ); 
2003     // Manipolate selection 
2004     if( m_selection
.GetCount() > 1 ) 
2006         m_selection
.Empty(); 
2008     bool isContainer 
= false; 
2009     wxDataViewTreeNodes nds 
= node
->GetNodes(); 
2010     for (size_t i 
= 0; i 
< nds
.GetCount(); i 
++) 
2012         if (nds
[i
]->GetItem() == item
) 
2020         wxDataViewTreeNode 
* n 
= NULL
; 
2021         wxDataViewTreeNodes nodes 
= node
->GetNodes(); 
2022         int len 
= nodes
.GetCount(); 
2023         for( int i 
= 0; i 
< len
; i 
++) 
2025             if( nodes
[i
]->GetItem() == item 
) 
2032         wxCHECK_MSG( n 
!= NULL
, false, "item not found" ); 
2034         node
->GetNodes().Remove( n 
); 
2035         sub 
-= n
->GetSubTreeCount(); 
2036         ::DestroyTreeHelper(n
); 
2038     // Make the row number invalid and get a new valid one when user call GetRowCount 
2040     node
->ChangeSubTreeCount(sub
); 
2042     // Change the current row to the last row if the current exceed the max row number 
2043     if( m_currentRow 
> GetRowCount() ) 
2044         m_currentRow 
= m_count 
- 1; 
2051 bool wxDataViewMainWindow::ItemChanged(const wxDataViewItem 
& item
) 
2057     wxWindow 
*parent 
= GetParent(); 
2058     wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED
, parent
->GetId()); 
2059     le
.SetEventObject(parent
); 
2060     le
.SetModel(GetOwner()->GetModel()); 
2062     parent
->GetEventHandler()->ProcessEvent(le
); 
2067 bool wxDataViewMainWindow::ValueChanged( const wxDataViewItem 
& item
, unsigned int col 
) 
2069     // NOTE: to be valid, we cannot use e.g. INT_MAX - 1 
2070 /*#define MAX_VIRTUAL_WIDTH       100000 
2072     wxRect rect( 0, row*m_lineHeight, MAX_VIRTUAL_WIDTH, m_lineHeight ); 
2073     m_owner->CalcScrolledPosition( rect.x, rect.y, &rect.x, &rect.y ); 
2074     Refresh( true, &rect ); 
2082     wxWindow 
*parent 
= GetParent(); 
2083     wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_ITEM_VALUE_CHANGED
, parent
->GetId()); 
2084     le
.SetEventObject(parent
); 
2085     le
.SetModel(GetOwner()->GetModel()); 
2088     le
.SetDataViewColumn(GetOwner()->GetColumn(col
)); 
2089     parent
->GetEventHandler()->ProcessEvent(le
); 
2094 bool wxDataViewMainWindow::Cleared() 
2099     BuildTree( GetOwner()->GetModel() ); 
2106 void wxDataViewMainWindow::UpdateDisplay() 
2109     m_underMouse 
= NULL
; 
2112 void wxDataViewMainWindow::OnInternalIdle() 
2114     wxWindow::OnInternalIdle(); 
2118         RecalculateDisplay(); 
2123 void wxDataViewMainWindow::RecalculateDisplay() 
2125     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
2132     int width 
= GetEndOfLastCol(); 
2133     int height 
= GetLineStart( GetRowCount() ); 
2135     SetVirtualSize( width
, height 
); 
2136     GetOwner()->SetScrollRate( 10, m_lineHeight 
); 
2141 void wxDataViewMainWindow::ScrollWindow( int dx
, int dy
, const wxRect 
*rect 
) 
2143     wxWindow::ScrollWindow( dx
, dy
, rect 
); 
2145     if (GetOwner()->m_headerArea
) 
2146         GetOwner()->m_headerArea
->ScrollWindow( dx
, 0 ); 
2149 void wxDataViewMainWindow::ScrollTo( int rows
, int column 
) 
2152     m_owner
->GetScrollPixelsPerUnit( &x
, &y 
); 
2153     int sy 
= GetLineStart( rows 
)/y
; 
2157         wxRect rect 
= GetClientRect(); 
2161         m_owner
->CalcUnscrolledPosition( rect
.x
, rect
.y
, &xx
, &yy 
); 
2162         for (x_start 
= 0; colnum 
< column
; colnum
++) 
2164             wxDataViewColumn 
*col 
= GetOwner()->GetColumnAt(colnum
); 
2165             if (col
->IsHidden()) 
2166                 continue;      // skip it! 
2168             w 
= col
->GetWidth(); 
2172         int x_end 
= x_start 
+ w
; 
2173         xe 
= xx 
+ rect
.width
; 
2176             sx 
= ( xx 
+ x_end 
- xe 
)/x
; 
2183     m_owner
->Scroll( sx
, sy 
); 
2186 int wxDataViewMainWindow::GetCountPerPage() const 
2188     wxSize size 
= GetClientSize(); 
2189     return size
.y 
/ m_lineHeight
; 
2192 int wxDataViewMainWindow::GetEndOfLastCol() const 
2196     for (i 
= 0; i 
< GetOwner()->GetColumnCount(); i
++) 
2198         const wxDataViewColumn 
*c 
= 
2199             const_cast<wxDataViewCtrl
*>(GetOwner())->GetColumnAt( i 
); 
2202             width 
+= c
->GetWidth(); 
2207 unsigned int wxDataViewMainWindow::GetFirstVisibleRow() const 
2211     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2213     return GetLineAt( y 
); 
2216 unsigned int wxDataViewMainWindow::GetLastVisibleRow() 
2218     wxSize client_size 
= GetClientSize(); 
2219     m_owner
->CalcUnscrolledPosition( client_size
.x
, client_size
.y
, 
2220                                     &client_size
.x
, &client_size
.y 
); 
2222     // we should deal with the pixel here 
2223     unsigned int row 
= GetLineAt(client_size
.y
) - 1; 
2225     return wxMin( GetRowCount()-1, row 
); 
2228 unsigned int wxDataViewMainWindow::GetRowCount() 
2230     if ( m_count 
== -1 ) 
2232         m_count 
= RecalculateCount(); 
2238 void wxDataViewMainWindow::ChangeCurrentRow( unsigned int row 
) 
2245 void wxDataViewMainWindow::SelectAllRows( bool on 
) 
2252         m_selection
.Clear(); 
2253         for (unsigned int i 
= 0; i 
< GetRowCount(); i
++) 
2254             m_selection
.Add( i 
); 
2259         unsigned int first_visible 
= GetFirstVisibleRow(); 
2260         unsigned int last_visible 
= GetLastVisibleRow(); 
2262         for (i 
= 0; i 
< m_selection
.GetCount(); i
++) 
2264             unsigned int row 
= m_selection
[i
]; 
2265             if ((row 
>= first_visible
) && (row 
<= last_visible
)) 
2268         m_selection
.Clear(); 
2272 void wxDataViewMainWindow::SelectRow( unsigned int row
, bool on 
) 
2274     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
2278             m_selection
.Add( row 
); 
2286             m_selection
.Remove( row 
); 
2292 void wxDataViewMainWindow::SelectRows( unsigned int from
, unsigned int to
, bool on 
) 
2296         unsigned int tmp 
= from
; 
2302     for (i 
= from
; i 
<= to
; i
++) 
2304         if (m_selection
.Index( i 
) == wxNOT_FOUND
) 
2307                 m_selection
.Add( i 
); 
2312                 m_selection
.Remove( i 
); 
2315     RefreshRows( from
, to 
); 
2318 void wxDataViewMainWindow::Select( const wxArrayInt
& aSelections 
) 
2320     for (size_t i
=0; i 
< aSelections
.GetCount(); i
++) 
2322         int n 
= aSelections
[i
]; 
2324         m_selection
.Add( n 
); 
2329 void wxDataViewMainWindow::ReverseRowSelection( unsigned int row 
) 
2331     if (m_selection
.Index( row 
) == wxNOT_FOUND
) 
2332         m_selection
.Add( row 
); 
2334         m_selection
.Remove( row 
); 
2338 bool wxDataViewMainWindow::IsRowSelected( unsigned int row 
) 
2340     return (m_selection
.Index( row 
) != wxNOT_FOUND
); 
2343 void wxDataViewMainWindow::SendSelectionChangedEvent( const wxDataViewItem
& item
) 
2345     wxWindow 
*parent 
= GetParent(); 
2346     wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_SELECTION_CHANGED
, parent
->GetId()); 
2348     le
.SetEventObject(parent
); 
2349     le
.SetModel(GetOwner()->GetModel()); 
2352     parent
->GetEventHandler()->ProcessEvent(le
); 
2355 void wxDataViewMainWindow::RefreshRow( unsigned int row 
) 
2357     wxRect 
rect( 0, GetLineStart( row 
), GetEndOfLastCol(), GetLineHeight( row 
) ); 
2358     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2360     wxSize client_size 
= GetClientSize(); 
2361     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
2362     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
2363     if (intersect_rect
.width 
> 0) 
2364         Refresh( true, &intersect_rect 
); 
2367 void wxDataViewMainWindow::RefreshRows( unsigned int from
, unsigned int to 
) 
2371         unsigned int tmp 
= to
; 
2376     wxRect 
rect( 0, GetLineStart( from 
), GetEndOfLastCol(), GetLineStart( (to
-from
+1) ) ); 
2377     m_owner
->CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2379     wxSize client_size 
= GetClientSize(); 
2380     wxRect 
client_rect( 0, 0, client_size
.x
, client_size
.y 
); 
2381     wxRect intersect_rect 
= client_rect
.Intersect( rect 
); 
2382     if (intersect_rect
.width 
> 0) 
2383         Refresh( true, &intersect_rect 
); 
2386 void wxDataViewMainWindow::RefreshRowsAfter( unsigned int firstRow 
) 
2388     wxSize client_size 
= GetClientSize(); 
2389     int start 
= GetLineStart( firstRow 
); 
2390     m_owner
->CalcScrolledPosition( start
, 0, &start
, NULL 
); 
2391     if (start 
> client_size
.y
) return; 
2393     wxRect 
rect( 0, start
, client_size
.x
, client_size
.y 
- start 
); 
2395     Refresh( true, &rect 
); 
2398 void wxDataViewMainWindow::OnArrowChar(unsigned int newCurrent
, const wxKeyEvent
& event
) 
2400     wxCHECK_RET( newCurrent 
< GetRowCount(), 
2401                 wxT("invalid item index in OnArrowChar()") ); 
2403     // if there is no selection, we cannot move it anywhere 
2404     if (!HasCurrentRow()) 
2407     unsigned int oldCurrent 
= m_currentRow
; 
2409     // in single selection we just ignore Shift as we can't select several 
2411     if ( event
.ShiftDown() && !IsSingleSel() ) 
2413         RefreshRow( oldCurrent 
); 
2415         ChangeCurrentRow( newCurrent 
); 
2417         // select all the items between the old and the new one 
2418         if ( oldCurrent 
> newCurrent 
) 
2420             newCurrent 
= oldCurrent
; 
2421             oldCurrent 
= m_currentRow
; 
2424         SelectRows( oldCurrent
, newCurrent
, true ); 
2425         if (oldCurrent
!=newCurrent
) 
2426             SendSelectionChangedEvent(GetItemByRow(m_selection
[0])); 
2430         RefreshRow( oldCurrent 
); 
2432         // all previously selected items are unselected unless ctrl is held 
2433         if ( !event
.ControlDown() ) 
2434             SelectAllRows(false); 
2436         ChangeCurrentRow( newCurrent 
); 
2438         if ( !event
.ControlDown() ) 
2440             SelectRow( m_currentRow
, true ); 
2441             SendSelectionChangedEvent(GetItemByRow(m_currentRow
)); 
2444             RefreshRow( m_currentRow 
); 
2447     GetOwner()->EnsureVisible( m_currentRow
, -1 ); 
2450 wxRect 
wxDataViewMainWindow::GetLineRect( unsigned int row 
) const 
2454     rect
.y 
= GetLineStart( row 
); 
2455     rect
.width 
= GetEndOfLastCol(); 
2456     rect
.height 
= GetLineHeight( row 
); 
2461 int wxDataViewMainWindow::GetLineStart( unsigned int row 
) const 
2463     const wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
2465     if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT
) 
2467         // TODO make more efficient 
2472         for (r 
= 0; r 
< row
; r
++) 
2474             const wxDataViewTreeNode
* node 
= GetTreeNodeByRow(r
); 
2475             if (!node
) return start
; 
2477             wxDataViewItem item 
= node
->GetItem(); 
2479             if (node 
&& !node
->HasChildren()) 
2481                 // Yes, if the node does not have any child, it must be a leaf which 
2482                 // mean that it is a temporarily created by GetTreeNodeByRow 
2486             unsigned int cols 
= GetOwner()->GetColumnCount(); 
2488             int height 
= m_lineHeight
; 
2489             for (col 
= 0; col 
< cols
; col
++) 
2491                 const wxDataViewColumn 
*column 
= GetOwner()->GetColumn(col
); 
2492                 if (column
->IsHidden()) 
2493                     continue;      // skip it! 
2496                     model
->IsContainer(item
) && 
2497                     !model
->HasContainerColumns(item
)) 
2498                     continue;      // skip it! 
2501                 model
->GetValue( value
, item
, column
->GetModelColumn() ); 
2503                 wxDataViewRenderer 
*renderer 
= 
2504                     const_cast<wxDataViewRenderer
*>(column
->GetRenderer()); 
2505                 renderer
->SetValue( value 
); 
2506                 height 
= wxMax( height
, renderer
->GetSize().y 
); 
2516         return row 
* m_lineHeight
; 
2520 int wxDataViewMainWindow::GetLineAt( unsigned int y 
) const 
2522     const wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
2524     // check for the easy case first 
2525     if ( !GetOwner()->HasFlag(wxDV_VARIABLE_LINE_HEIGHT
) ) 
2526         return y 
/ m_lineHeight
; 
2528     // TODO make more efficient 
2529     unsigned int row 
= 0; 
2530     unsigned int yy 
= 0; 
2533         const wxDataViewTreeNode
* node 
= GetTreeNodeByRow(row
); 
2536             // not really correct... 
2537             return row 
+ ((y
-yy
) / m_lineHeight
); 
2540         wxDataViewItem item 
= node
->GetItem(); 
2542         if (node 
&& !node
->HasChildren()) 
2544             // Yes, if the node does not have any child, it must be a leaf which 
2545             // mean that it is a temporarily created by GetTreeNodeByRow 
2549         unsigned int cols 
= GetOwner()->GetColumnCount(); 
2551         int height 
= m_lineHeight
; 
2552         for (col 
= 0; col 
< cols
; col
++) 
2554             const wxDataViewColumn 
*column 
= GetOwner()->GetColumn(col
); 
2555             if (column
->IsHidden()) 
2556                 continue;      // skip it! 
2559                 model
->IsContainer(item
) && 
2560                 !model
->HasContainerColumns(item
)) 
2561                 continue;      // skip it! 
2564             model
->GetValue( value
, item
, column
->GetModelColumn() ); 
2566             wxDataViewRenderer 
*renderer 
= 
2567                 const_cast<wxDataViewRenderer
*>(column
->GetRenderer()); 
2568             renderer
->SetValue( value 
); 
2569             height 
= wxMax( height
, renderer
->GetSize().y 
); 
2580 int wxDataViewMainWindow::GetLineHeight( unsigned int row 
) const 
2582     const wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
2584     if (GetOwner()->GetWindowStyle() & wxDV_VARIABLE_LINE_HEIGHT
) 
2586         wxASSERT( !IsVirtualList() ); 
2588         const wxDataViewTreeNode
* node 
= GetTreeNodeByRow(row
); 
2589         // wxASSERT( node ); 
2590         if (!node
) return m_lineHeight
; 
2592         wxDataViewItem item 
= node
->GetItem(); 
2594         if (node 
&& !node
->HasChildren()) 
2596                 // Yes, if the node does not have any child, it must be a leaf which 
2597                 // mean that it is a temporarily created by GetTreeNodeByRow 
2601         int height 
= m_lineHeight
; 
2603         unsigned int cols 
= GetOwner()->GetColumnCount(); 
2605         for (col 
= 0; col 
< cols
; col
++) 
2607             const wxDataViewColumn 
*column 
= GetOwner()->GetColumn(col
); 
2608             if (column
->IsHidden()) 
2609                 continue;      // skip it! 
2612                 model
->IsContainer(item
) && 
2613                 !model
->HasContainerColumns(item
)) 
2614                 continue;      // skip it! 
2617             model
->GetValue( value
, item
, column
->GetModelColumn() ); 
2619             wxDataViewRenderer 
*renderer 
= 
2620                 const_cast<wxDataViewRenderer
*>(column
->GetRenderer()); 
2621             renderer
->SetValue( value 
); 
2622             height 
= wxMax( height
, renderer
->GetSize().y 
); 
2629         return m_lineHeight
; 
2633 class RowToItemJob
: public DoJob
 
2636     RowToItemJob( unsigned int row 
, int current 
) 
2637         { this->row 
= row
; this->current 
= current
; } 
2638     virtual ~RowToItemJob() {} 
2640     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
2643         if( current 
== static_cast<int>(row
)) 
2645             ret 
= node
->GetItem(); 
2649         if( node
->GetSubTreeCount() + current 
< static_cast<int>(row
) ) 
2651             current 
+= node
->GetSubTreeCount(); 
2656             // If the current has no child node, we can find the desired item of the row 
2658             // This if can speed up finding in some case, and will has a very good effect 
2659             // when it comes to list view 
2660             if( node
->GetNodes().GetCount() == 0) 
2662                 int index 
= static_cast<int>(row
) - current 
- 1; 
2663                 ret 
= node
->GetChildren().Item( index 
); 
2670     virtual int operator() ( void * n 
) 
2673         if( current 
== static_cast<int>(row
)) 
2675             ret 
= wxDataViewItem( n 
); 
2681     wxDataViewItem 
GetResult() const 
2690 wxDataViewItem 
wxDataViewMainWindow::GetItemByRow(unsigned int row
) const 
2692     if (IsVirtualList()) 
2694         return wxDataViewItem( wxUIntToPtr(row
+1) ); 
2698         RowToItemJob 
job( row
, -2 ); 
2699         Walker( m_root 
, job 
); 
2700         return job
.GetResult(); 
2704 class RowToTreeNodeJob
: public DoJob
 
2707     RowToTreeNodeJob( unsigned int row 
, int current
, wxDataViewTreeNode 
* node 
) 
2710         this->current 
= current
; 
2714     virtual ~RowToTreeNodeJob(){ } 
2716     virtual int operator() ( wxDataViewTreeNode 
* node 
) 
2719         if( current 
== static_cast<int>(row
)) 
2725         if( node
->GetSubTreeCount() + current 
< static_cast<int>(row
) ) 
2727             current 
+= node
->GetSubTreeCount(); 
2734             // If the current node has no children, we can find the desired item of the 
2735             // row number directly. 
2736             // This if can speed up finding in some case, and will have a very good 
2737             // effect for list views. 
2738             if( node
->GetNodes().GetCount() == 0) 
2740                 int index 
= static_cast<int>(row
) - current 
- 1; 
2741                 void * n 
= node
->GetChildren().Item( index 
); 
2742                 ret 
= new wxDataViewTreeNode( parent 
); 
2743                 ret
->SetItem( wxDataViewItem( n 
)); 
2744                 ret
->SetHasChildren(false); 
2751     virtual int operator() ( void * n 
) 
2754         if( current 
== static_cast<int>(row
)) 
2756             ret 
= new wxDataViewTreeNode( parent 
); 
2757             ret
->SetItem( wxDataViewItem( n 
)); 
2758             ret
->SetHasChildren(false); 
2765     wxDataViewTreeNode 
* GetResult() const 
2771     wxDataViewTreeNode 
* ret
; 
2772     wxDataViewTreeNode 
* parent
; 
2775 wxDataViewTreeNode 
* wxDataViewMainWindow::GetTreeNodeByRow(unsigned int row
) const 
2777     wxASSERT( !IsVirtualList() ); 
2779     RowToTreeNodeJob 
job( row 
, -2, m_root 
); 
2780     Walker( m_root 
, job 
); 
2781     return job
.GetResult(); 
2784 wxDataViewEvent 
wxDataViewMainWindow::SendExpanderEvent( wxEventType type
, 
2785                                                          const wxDataViewItem 
& item 
) 
2787     wxWindow 
*parent 
= GetParent(); 
2788     wxDataViewEvent 
le(type
, parent
->GetId()); 
2790     le
.SetEventObject(parent
); 
2791     le
.SetModel(GetOwner()->GetModel()); 
2794     parent
->GetEventHandler()->ProcessEvent(le
); 
2798 bool wxDataViewMainWindow::IsExpanded( unsigned int row 
) const 
2803     wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(row
); 
2807     if (!node
->HasChildren()) 
2813     return node
->IsOpen(); 
2816 bool wxDataViewMainWindow::HasChildren( unsigned int row 
) const 
2821     wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(row
); 
2825     if (!node
->HasChildren()) 
2834 void wxDataViewMainWindow::Expand( unsigned int row 
) 
2839     wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(row
); 
2843     if (!node
->HasChildren()) 
2849             if (!node
->IsOpen()) 
2852                     SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDING
, node
->GetItem()); 
2854                 // Check if the user prevent expanding 
2855                 if( e
.GetSkipped() ) 
2860                 // build the children of current node 
2861                 if( node
->GetChildrenNumber() == 0 ) 
2864                     ::BuildTreeHelper(GetOwner()->GetModel(), node
->GetItem(), node
); 
2867                 // By expanding the node all row indices that are currently in the selection list 
2868                 // and are greater than our node have become invalid. So we have to correct that now. 
2869                 const unsigned rowAdjustment 
= node
->GetSubTreeCount(); 
2870                 for(unsigned i
=0; i
<m_selection
.size(); ++i
) 
2872                     const unsigned testRow 
= m_selection
[i
]; 
2873                     // all rows above us are not affected, so skip them 
2877                     m_selection
[i
] += rowAdjustment
; 
2880                 if(m_currentRow 
> row
) 
2881                     ChangeCurrentRow(m_currentRow 
+ rowAdjustment
); 
2885                 // Send the expanded event 
2886                 SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_EXPANDED
,node
->GetItem()); 
2890 void wxDataViewMainWindow::Collapse(unsigned int row
) 
2895     wxDataViewTreeNode 
*node 
= GetTreeNodeByRow(row
); 
2899     if (!node
->HasChildren()) 
2908                 SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSING
,node
->GetItem()); 
2909             if( e
.GetSkipped() ) 
2912             // Find out if there are selected items below the current node. 
2913             bool selectCollapsingRow 
= false; 
2914             const unsigned rowAdjustment 
= node
->GetSubTreeCount(); 
2915             unsigned maxRowToBeTested 
= row 
+ rowAdjustment
; 
2916             for(unsigned i
=0; i
<m_selection
.size(); ++i
) 
2918                 const unsigned testRow 
= m_selection
[i
]; 
2919                 if(testRow 
> row 
&& testRow 
<= maxRowToBeTested
) 
2921                     selectCollapsingRow 
= true; 
2922                     // get out as soon as we have found a node that is selected 
2929             // If the node to be closed has selected items the user won't see those any longer. 
2930             // We select the collapsing node in this case. 
2931             if(selectCollapsingRow
) 
2933                 SelectAllRows(false); 
2934                 ChangeCurrentRow(row
); 
2935                 SelectRow(row
, true); 
2936                 SendSelectionChangedEvent(GetItemByRow(row
)); 
2940                 // if there were no selected items below our node we still need to "fix" the 
2941                 // selection list to adjust for the changing of the row indices. 
2942                 // We actually do the opposite of what we are doing in Expand(). 
2943                 for(unsigned i
=0; i
<m_selection
.size(); ++i
) 
2945                     const unsigned testRow 
= m_selection
[i
]; 
2946                     // all rows above us are not affected, so skip them 
2950                     m_selection
[i
] -= rowAdjustment
; 
2953                 // if the "current row" is being collapsed away we change it to the current row ;-) 
2954                 if(m_currentRow 
> row 
&& m_currentRow 
<= maxRowToBeTested
) 
2955                     ChangeCurrentRow(row
); 
2956                 else if(m_currentRow 
> row
) 
2957                     ChangeCurrentRow(m_currentRow 
- rowAdjustment
); 
2962             SendExpanderEvent(wxEVT_COMMAND_DATAVIEW_ITEM_COLLAPSED
,node
->GetItem()); 
2966 wxDataViewTreeNode 
* wxDataViewMainWindow::FindNode( const wxDataViewItem 
& item 
) 
2968     wxDataViewModel 
* model 
= GetOwner()->GetModel(); 
2975     // Compose the a parent-chain of the finding item 
2977     list
.DeleteContents( true ); 
2978     wxDataViewItem 
it( item 
); 
2981         wxDataViewItem 
* pItem 
= new wxDataViewItem( it 
); 
2982         list
.Insert( pItem 
); 
2983         it 
= model
->GetParent( it 
); 
2986     // Find the item along the parent-chain. 
2987     // This algorithm is designed to speed up the node-finding method 
2988     wxDataViewTreeNode 
* node 
= m_root
; 
2989     for( ItemList::const_iterator iter 
= list
.begin(); iter 
!=list
.end(); iter
++ ) 
2991         if( node
->HasChildren() ) 
2993             if( node
->GetChildrenNumber() == 0 ) 
2996                 ::BuildTreeHelper(model
, node
->GetItem(), node
); 
2999             wxDataViewTreeNodes nodes 
= node
->GetNodes(); 
3003             for (i 
= 0; i 
< nodes
.GetCount(); i 
++) 
3005                 if (nodes
[i
]->GetItem() == (**iter
)) 
3007                     if (nodes
[i
]->GetItem() == item
) 
3024 void wxDataViewMainWindow::HitTest( const wxPoint 
& point
, wxDataViewItem 
& item
, 
3025                                     wxDataViewColumn
* &column 
) 
3027     wxDataViewColumn 
*col 
= NULL
; 
3028     unsigned int cols 
= GetOwner()->GetColumnCount(); 
3029     unsigned int colnum 
= 0; 
3031     m_owner
->CalcUnscrolledPosition( point
.x
, point
.y
, &x
, &y 
); 
3032     for (unsigned x_start 
= 0; colnum 
< cols
; colnum
++) 
3034         col 
= GetOwner()->GetColumnAt(colnum
); 
3035         if (col
->IsHidden()) 
3036             continue;      // skip it! 
3038         unsigned int w 
= col
->GetWidth(); 
3039         if (x_start
+w 
>= (unsigned int)x
) 
3046     item 
= GetItemByRow( GetLineAt( y 
) ); 
3049 wxRect 
wxDataViewMainWindow::GetItemRect( const wxDataViewItem 
& item
, 
3050                                           const wxDataViewColumn
* column 
) 
3055     unsigned int cols 
= GetOwner()->GetColumnCount(); 
3056     // If column is null the loop will compute the combined width of all columns. 
3057     // Otherwise, it will compute the x position of the column we are looking for. 
3058     for (unsigned int i 
= 0; i 
< cols
; i
++) 
3060         wxDataViewColumn
* col 
= GetOwner()->GetColumnAt( i 
); 
3065         if (col
->IsHidden()) 
3066             continue;      // skip it! 
3068         xpos 
+= col
->GetWidth(); 
3069         width 
+= col
->GetWidth(); 
3074         // If we have a column, we need can get its width directly. 
3075         if(column
->IsHidden()) 
3078             width 
= column
->GetWidth(); 
3083         // If we have no column, we reset the x position back to zero. 
3087     // we have to take an expander column into account and compute its indentation 
3088     // to get the correct x position where the actual text is 
3090     int row 
= GetRowByItem(item
); 
3091     if (!IsList() && (column 
== 0 || GetOwner()->GetExpanderColumn() == column
) ) 
3093         wxDataViewTreeNode
* node 
= GetTreeNodeByRow(row
); 
3094         indent 
= GetOwner()->GetIndent() * node
->GetIndentLevel(); 
3095         indent 
= indent 
+ m_lineHeight
; // use m_lineHeight as the width of the expander 
3097         if(!node
->HasChildren()) 
3101     wxRect 
itemRect( xpos 
+ indent
, 
3102                      GetLineStart( row 
), 
3104                      GetLineHeight( row 
) ); 
3106     GetOwner()->CalcScrolledPosition(  itemRect
.x
,  itemRect
.y
, 
3107                                       &itemRect
.x
, &itemRect
.y 
); 
3112 int wxDataViewMainWindow::RecalculateCount() 
3114     if (IsVirtualList()) 
3116         wxDataViewVirtualListModel 
*list_model 
= 
3117             (wxDataViewVirtualListModel
*) GetOwner()->GetModel(); 
3119         return list_model
->GetCount(); 
3123         return m_root
->GetSubTreeCount(); 
3127 class ItemToRowJob 
: public DoJob
 
3130     ItemToRowJob(const wxDataViewItem
& item_
, ItemList::const_iterator iter
) 
3137     // Maybe binary search will help to speed up this process 
3138     virtual int operator() ( wxDataViewTreeNode 
* node
) 
3141         if( node
->GetItem() == item 
) 
3146         if( node
->GetItem() == **m_iter 
) 
3153             ret 
+= node
->GetSubTreeCount(); 
3159     virtual int operator() ( void * n 
) 
3162         if( n 
== item
.GetID() ) 
3167     // the row number is begin from zero 
3168     int GetResult() const 
3172     ItemList::const_iterator  m_iter
; 
3173     wxDataViewItem item
; 
3178 int wxDataViewMainWindow::GetRowByItem(const wxDataViewItem 
& item
) const 
3180     const wxDataViewModel 
* model 
= GetOwner()->GetModel(); 
3184     if (IsVirtualList()) 
3186         return wxPtrToUInt( item
.GetID() ) -1; 
3193         // Compose the a parent-chain of the finding item 
3195         wxDataViewItem 
* pItem
; 
3196         list
.DeleteContents( true ); 
3197         wxDataViewItem 
it( item 
); 
3200             pItem 
= new wxDataViewItem( it 
); 
3201             list
.Insert( pItem 
); 
3202             it 
= model
->GetParent( it 
); 
3204         pItem 
= new wxDataViewItem( ); 
3205         list
.Insert( pItem 
); 
3207         ItemToRowJob 
job( item
, list
.begin() ); 
3208         Walker(m_root 
, job 
); 
3209         return job
.GetResult(); 
3213 static void BuildTreeHelper( wxDataViewModel 
* model
,  wxDataViewItem 
& item
, 
3214                              wxDataViewTreeNode 
* node
) 
3216     if( !model
->IsContainer( item 
) ) 
3219     wxDataViewItemArray children
; 
3220     unsigned int num 
= model
->GetChildren( item
, children
); 
3222     unsigned int index 
= 0; 
3223     while( index 
< num 
) 
3225         if( model
->IsContainer( children
[index
] ) ) 
3227             wxDataViewTreeNode 
* n 
= new wxDataViewTreeNode( node 
); 
3228             n
->SetItem(children
[index
]); 
3229             n
->SetHasChildren( true ); 
3234             node
->AddLeaf( children
[index
].GetID() ); 
3238     node
->SetSubTreeCount( num 
); 
3239     wxDataViewTreeNode 
* n 
= node
->GetParent(); 
3241         n
->ChangeSubTreeCount(num
); 
3245 void wxDataViewMainWindow::BuildTree(wxDataViewModel 
* model
) 
3249     if (GetOwner()->GetModel()->IsVirtualListModel()) 
3255     m_root 
= new wxDataViewTreeNode( NULL 
); 
3256     m_root
->SetHasChildren(true); 
3258     // First we define a invalid item to fetch the top-level elements 
3259     wxDataViewItem item
; 
3261     BuildTreeHelper( model
, item
, m_root
); 
3265 static void DestroyTreeHelper( wxDataViewTreeNode 
* node 
) 
3267     if( node
->GetNodeNumber() != 0 ) 
3269         int len 
= node
->GetNodeNumber(); 
3270         wxDataViewTreeNodes
& nodes 
= node
->GetNodes(); 
3271         for (int i 
= 0; i 
< len
; i
++) 
3272             DestroyTreeHelper(nodes
[i
]); 
3277 void wxDataViewMainWindow::DestroyTree() 
3279     if (!IsVirtualList()) 
3281         ::DestroyTreeHelper(m_root
); 
3287 void wxDataViewMainWindow::OnChar( wxKeyEvent 
&event 
) 
3289     wxWindow 
* const parent 
= GetParent(); 
3291     // propagate the char event upwards 
3292     wxKeyEvent 
eventForParent(event
); 
3293     eventForParent
.SetEventObject(parent
); 
3294     if ( parent
->ProcessWindowEvent(eventForParent
) ) 
3297     if ( parent
->HandleAsNavigationKey(event
) ) 
3300     // no item -> nothing to do 
3301     if (!HasCurrentRow()) 
3307     // don't use m_linesPerPage directly as it might not be computed yet 
3308     const int pageSize 
= GetCountPerPage(); 
3309     wxCHECK_RET( pageSize
, wxT("should have non zero page size") ); 
3311     switch ( event
.GetKeyCode() ) 
3315                 wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
, 
3317                 le
.SetItem( GetItemByRow(m_currentRow
) ); 
3318                 le
.SetEventObject(parent
); 
3319                 le
.SetModel(GetOwner()->GetModel()); 
3321                 parent
->GetEventHandler()->ProcessEvent(le
); 
3326             if ( m_currentRow 
> 0 ) 
3327                 OnArrowChar( m_currentRow 
- 1, event 
); 
3331             if ( m_currentRow 
< GetRowCount() - 1 ) 
3332                 OnArrowChar( m_currentRow 
+ 1, event 
); 
3334         // Add the process for tree expanding/collapsing 
3340             wxDataViewTreeNode
* node 
= GetTreeNodeByRow(m_currentRow
); 
3344             if (node
->HasChildren() && node
->IsOpen()) 
3346                 Collapse(m_currentRow
); 
3348             else    // if the node is already closed we move the selection to its parent 
3350                 wxDataViewTreeNode 
*parent_node 
= node
->GetParent(); 
3352                 if(!node
->HasChildren()) 
3357                     int parent 
= GetRowByItem( parent_node
->GetItem() ); 
3360                         unsigned int row 
= m_currentRow
; 
3361                         SelectRow( row
, false); 
3362                         SelectRow( parent
, true ); 
3363                         ChangeCurrentRow( parent 
); 
3364                         GetOwner()->EnsureVisible( parent
, -1 ); 
3365                         SendSelectionChangedEvent( parent_node
->GetItem() ); 
3373             if (!IsExpanded( m_currentRow 
)) 
3374                 Expand( m_currentRow 
); 
3377                 unsigned int row 
= m_currentRow
; 
3378                 SelectRow( row
, false ); 
3379                 SelectRow( row 
+ 1, true ); 
3380                 ChangeCurrentRow( row 
+ 1 ); 
3381                 GetOwner()->EnsureVisible( row 
+ 1, -1 ); 
3382                 SendSelectionChangedEvent( GetItemByRow(row
+1) ); 
3389                 OnArrowChar( GetRowCount() - 1, event 
); 
3394                 OnArrowChar( 0, event 
); 
3399                 int steps 
= pageSize 
- 1; 
3400                 int index 
= m_currentRow 
- steps
; 
3404                 OnArrowChar( index
, event 
); 
3410                 int steps 
= pageSize 
- 1; 
3411                 unsigned int index 
= m_currentRow 
+ steps
; 
3412                 unsigned int count 
= GetRowCount(); 
3413                 if ( index 
>= count 
) 
3416                 OnArrowChar( index
, event 
); 
3422                 if(m_selection
.size() == 1) 
3424                     // TODO: we need to revise that when we have a concept for a 'current column' 
3425                     GetOwner()->StartEditor(GetItemByRow(m_selection
[0]), 0); 
3435 void wxDataViewMainWindow::OnMouse( wxMouseEvent 
&event 
) 
3437     if (event
.GetEventType() == wxEVT_MOUSEWHEEL
) 
3439         // let the base handle mouse wheel events. 
3444     int x 
= event
.GetX(); 
3445     int y 
= event
.GetY(); 
3446     m_owner
->CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
3447     wxDataViewColumn 
*col 
= NULL
; 
3450     unsigned int cols 
= GetOwner()->GetColumnCount(); 
3452     for (i 
= 0; i 
< cols
; i
++) 
3454         wxDataViewColumn 
*c 
= GetOwner()->GetColumnAt( i 
); 
3456             continue;      // skip it! 
3458         if (x 
< xpos 
+ c
->GetWidth()) 
3463         xpos 
+= c
->GetWidth(); 
3468     wxDataViewRenderer 
*cell 
= col
->GetRenderer(); 
3469     unsigned int current 
= GetLineAt( y 
); 
3470     if ((current 
>= GetRowCount()) || (x 
> GetEndOfLastCol())) 
3472         // Unselect all if below the last row ? 
3476     // Test whether the mouse is hovered on the tree item button 
3477     bool hoverOverExpander 
= false; 
3478     if ((!IsList()) && (GetOwner()->GetExpanderColumn() == col
)) 
3480         wxDataViewTreeNode 
* node 
= GetTreeNodeByRow(current
); 
3481         if( node
!=NULL 
&& node
->HasChildren() ) 
3483             int indent 
= node
->GetIndentLevel(); 
3484             indent 
= GetOwner()->GetIndent()*indent
; 
3486             // we make the rectangle we are looking in a bit bigger than the actual 
3487             // visual expander so the user can hit that little thing reliably 
3488             wxRect 
rect( xpos 
+ indent
, 
3489                         GetLineStart( current 
) + (GetLineHeight(current
) - m_lineHeight
)/2, 
3490                         m_lineHeight
, m_lineHeight
); 
3491             if( rect
.Contains(x
, y
) ) 
3493                 // So the mouse is over the expander 
3494                 hoverOverExpander 
= true; 
3495                 if (m_underMouse 
&& m_underMouse 
!= node
) 
3497                     // wxLogMessage("Undo the row: %d", GetRowByItem(m_underMouse->GetItem())); 
3498                     RefreshRow(GetRowByItem(m_underMouse
->GetItem())); 
3500                 if (m_underMouse 
!= node
) 
3502                     // wxLogMessage("Do the row: %d", current); 
3503                     RefreshRow(current
); 
3505                 m_underMouse 
= node
; 
3508         if (node
!=NULL 
&& !node
->HasChildren()) 
3511     if (!hoverOverExpander
) 
3513         if (m_underMouse 
!= NULL
) 
3515             // wxLogMessage("Undo the row: %d", GetRowByItem(m_underMouse->GetItem())); 
3516             RefreshRow(GetRowByItem(m_underMouse
->GetItem())); 
3517             m_underMouse 
= NULL
; 
3521     wxDataViewModel 
*model 
= GetOwner()->GetModel(); 
3523 #if wxUSE_DRAG_AND_DROP 
3524     if (event
.Dragging()) 
3526         if (m_dragCount 
== 0) 
3528             // we have to report the raw, physical coords as we want to be 
3529             // able to call HitTest(event.m_pointDrag) from the user code to 
3530             // get the item being dragged 
3531             m_dragStart 
= event
.GetPosition(); 
3536         if (m_dragCount 
!= 3) 
3539         if (event
.LeftIsDown()) 
3541             m_owner
->CalcUnscrolledPosition( m_dragStart
.x
, m_dragStart
.y
, 
3542                                              &m_dragStart
.x
, &m_dragStart
.y 
); 
3543             unsigned int drag_item_row 
= GetLineAt( m_dragStart
.y 
); 
3544             wxDataViewItem item 
= GetItemByRow( drag_item_row 
); 
3546             // Notify cell about drag 
3547             wxDataViewEvent 
event( wxEVT_COMMAND_DATAVIEW_ITEM_BEGIN_DRAG
, m_owner
->GetId() ); 
3548             event
.SetEventObject( m_owner 
); 
3549             event
.SetItem( item 
); 
3550             event
.SetModel( model 
); 
3551             if (!m_owner
->HandleWindowEvent( event 
)) 
3554             if (!event
.IsAllowed()) 
3557             wxDataObject 
*obj 
= event
.GetDataObject(); 
3561             wxDataViewDropSource 
drag( this, drag_item_row 
); 
3562             drag
.SetData( *obj 
); 
3563             /* wxDragResult res = */ drag
.DoDragDrop(); 
3572 #endif // wxUSE_DRAG_AND_DROP 
3574     bool simulateClick 
= false; 
3576     if (event
.ButtonDClick()) 
3578         m_renameTimer
->Stop(); 
3579         m_lastOnSame 
= false; 
3582     wxDataViewItem item 
= GetItemByRow(current
); 
3583     bool ignore_other_columns 
= 
3584         ((GetOwner()->GetExpanderColumn() != col
) && 
3585         (model
->IsContainer(item
)) && 
3586         (!model
->HasContainerColumns(item
))); 
3588     if (event
.LeftDClick()) 
3590         if(hoverOverExpander
) 
3592             // a double click on the expander will be converted into a "simulated" normal click 
3593             simulateClick 
= true; 
3595         else if ( current 
== m_lineLastClicked 
) 
3597             if ((!ignore_other_columns
) && (cell
->GetMode() == wxDATAVIEW_CELL_ACTIVATABLE
)) 
3599                 const unsigned colIdx 
= col
->GetModelColumn(); 
3602                 model
->GetValue( value
, item
, colIdx 
); 
3604                 cell
->WXOnActivate(model
, value
, item
, colIdx
); 
3606                 if ( wxDataViewCustomRenderer 
*custom 
= cell
->WXGetAsCustom() ) 
3608                     cell
->SetValue( value 
); 
3610                     wxRect 
cell_rect( xpos
, GetLineStart( current 
), 
3611                                     col
->GetWidth(), GetLineHeight( current 
) ); 
3612                     custom
->Activate( cell_rect
, model
, item
, colIdx 
); 
3617                 wxWindow 
*parent 
= GetParent(); 
3618                 wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_ITEM_ACTIVATED
, parent
->GetId()); 
3620                 le
.SetEventObject(parent
); 
3621                 le
.SetModel(GetOwner()->GetModel()); 
3623                 parent
->GetEventHandler()->ProcessEvent(le
); 
3629             // The first click was on another item, so don't interpret this as 
3630             // a double click, but as a simple click instead 
3631             simulateClick 
= true; 
3635     if (event
.LeftUp() && !hoverOverExpander
) 
3637         if (m_lineSelectSingleOnUp 
!= (unsigned int)-1) 
3639             // select single line 
3640             SelectAllRows( false ); 
3641             SelectRow( m_lineSelectSingleOnUp
, true ); 
3642             SendSelectionChangedEvent( GetItemByRow(m_lineSelectSingleOnUp
) ); 
3645         // If the user click the expander, we do not do editing even if the column 
3646         // with expander are editable 
3647         if (m_lastOnSame 
&& !ignore_other_columns
) 
3649             if ((col 
== m_currentCol
) && (current 
== m_currentRow
) && 
3650                 (cell
->GetMode() & wxDATAVIEW_CELL_EDITABLE
) ) 
3652                 m_renameTimer
->Start( 100, true ); 
3656         m_lastOnSame 
= false; 
3657         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
3659     else if(!event
.LeftUp()) 
3661         // This is necessary, because after a DnD operation in 
3662         // from and to ourself, the up event is swallowed by the 
3663         // DnD code. So on next non-up event (which means here and 
3664         // now) m_lineSelectSingleOnUp should be reset. 
3665         m_lineSelectSingleOnUp 
= (unsigned int)-1; 
3668     if (event
.RightDown()) 
3670         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
3671         m_lineLastClicked 
= current
; 
3673         // If the item is already selected, do not update the selection. 
3674         // Multi-selections should not be cleared if a selected item is clicked. 
3675         if (!IsRowSelected(current
)) 
3677             SelectAllRows(false); 
3678             ChangeCurrentRow(current
); 
3679             SelectRow(m_currentRow
,true); 
3680             SendSelectionChangedEvent(GetItemByRow( m_currentRow 
) ); 
3683     else if (event
.RightUp()) 
3686         model
->GetValue( value
, item
, col
->GetModelColumn() ); 
3687         wxWindow 
*parent 
= GetParent(); 
3688         wxDataViewEvent 
le(wxEVT_COMMAND_DATAVIEW_ITEM_CONTEXT_MENU
, parent
->GetId()); 
3690         le
.SetEventObject(parent
); 
3691         le
.SetModel(GetOwner()->GetModel()); 
3693         parent
->GetEventHandler()->ProcessEvent(le
); 
3695     else if (event
.MiddleDown()) 
3699     if((event
.LeftDown() || simulateClick
) && hoverOverExpander
) 
3701         wxDataViewTreeNode
* node 
= GetTreeNodeByRow(current
); 
3703         // hoverOverExpander being true tells us that our node must be 
3704         // valid and have children. 
3705         // So we don't need any extra checks. 
3706         if( node
->IsOpen() ) 
3711     else if ((event
.LeftDown() || simulateClick
) && !hoverOverExpander
) 
3715         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
3716         m_lineLastClicked 
= current
; 
3718         unsigned int oldCurrentRow 
= m_currentRow
; 
3719         bool oldWasSelected 
= IsRowSelected(m_currentRow
); 
3721         bool cmdModifierDown 
= event
.CmdDown(); 
3722         if ( IsSingleSel() || !(cmdModifierDown 
|| event
.ShiftDown()) ) 
3724             if ( IsSingleSel() || !IsRowSelected(current
) ) 
3726                 SelectAllRows( false ); 
3727                 ChangeCurrentRow(current
); 
3728                 SelectRow(m_currentRow
,true); 
3729                 SendSelectionChangedEvent(GetItemByRow( m_currentRow 
) ); 
3731             else // multi sel & current is highlighted & no mod keys 
3733                 m_lineSelectSingleOnUp 
= current
; 
3734                 ChangeCurrentRow(current
); // change focus 
3737         else // multi sel & either ctrl or shift is down 
3739             if (cmdModifierDown
) 
3741                 ChangeCurrentRow(current
); 
3742                 ReverseRowSelection(m_currentRow
); 
3743                 SendSelectionChangedEvent(GetItemByRow(m_currentRow
)); 
3745             else if (event
.ShiftDown()) 
3747                 ChangeCurrentRow(current
); 
3749                 unsigned int lineFrom 
= oldCurrentRow
, 
3752                 if ( lineTo 
< lineFrom 
) 
3755                     lineFrom 
= m_currentRow
; 
3758                 SelectRows(lineFrom
, lineTo
, true); 
3759                 SendSelectionChangedEvent(GetItemByRow(m_selection
[0]) ); 
3761             else // !ctrl, !shift 
3763                 // test in the enclosing if should make it impossible 
3764                 wxFAIL_MSG( wxT("how did we get here?") ); 
3768         if (m_currentRow 
!= oldCurrentRow
) 
3769             RefreshRow( oldCurrentRow 
); 
3771         wxDataViewColumn 
*oldCurrentCol 
= m_currentCol
; 
3773         // Update selection here... 
3776         m_lastOnSame 
= !simulateClick 
&& ((col 
== oldCurrentCol
) && 
3777                         (current 
== oldCurrentRow
)) && oldWasSelected
; 
3779         // Call LeftClick after everything else as under GTK+ 
3780         if (cell
->GetMode() & wxDATAVIEW_CELL_ACTIVATABLE
) 
3782             if ( wxDataViewCustomRenderer 
*custom 
= cell
->WXGetAsCustom() ) 
3784                 // notify cell about click 
3786                 model
->GetValue( value
, item
, col
->GetModelColumn() ); 
3787                 custom
->SetValue( value 
); 
3788                 wxRect 
cell_rect( xpos
, GetLineStart( current 
), 
3789                                   col
->GetWidth(), GetLineHeight( current 
) ); 
3791                 // Report position relative to the cell's custom area, i.e. 
3792                 // no the entire space as given by the control but the one 
3793                 // used by the renderer after calculation of alignment etc. 
3795                 // adjust the rectangle ourselves to account for the alignment 
3796                 wxRect rectItem 
= cell_rect
; 
3797                 const int align 
= custom
->GetAlignment(); 
3798                 if ( align 
!= wxDVR_DEFAULT_ALIGNMENT 
) 
3800                     const wxSize size 
= custom
->GetSize(); 
3802                     if ( size
.x 
>= 0 && size
.x 
< cell_rect
.width 
) 
3804                         if ( align 
& wxALIGN_CENTER_HORIZONTAL 
) 
3805                             rectItem
.x 
+= (cell_rect
.width 
- size
.x
)/2; 
3806                         else if ( align 
& wxALIGN_RIGHT 
) 
3807                             rectItem
.x 
+= cell_rect
.width 
- size
.x
; 
3808                         // else: wxALIGN_LEFT is the default 
3811                     if ( size
.y 
>= 0 && size
.y 
< cell_rect
.height 
) 
3813                         if ( align 
& wxALIGN_CENTER_VERTICAL 
) 
3814                             rectItem
.y 
+= (cell_rect
.height 
- size
.y
)/2; 
3815                         else if ( align 
& wxALIGN_BOTTOM 
) 
3816                             rectItem
.y 
+= cell_rect
.height 
- size
.y
; 
3817                         // else: wxALIGN_TOP is the default 
3821                 wxPoint 
pos( event
.GetPosition() ); 
3822                 pos
.x 
-= rectItem
.x
; 
3823                 pos
.y 
-= rectItem
.y
; 
3825                 m_owner
->CalcUnscrolledPosition( pos
.x
, pos
.y
, &pos
.x
, &pos
.y 
); 
3827                  /* ignore ret */ custom
->LeftClick( pos
, cell_rect
, 
3828                                   model
, item
, col
->GetModelColumn()); 
3834 void wxDataViewMainWindow::OnSetFocus( wxFocusEvent 
&event 
) 
3838     if (HasCurrentRow()) 
3844 void wxDataViewMainWindow::OnKillFocus( wxFocusEvent 
&event 
) 
3848     if (HasCurrentRow()) 
3854 wxDataViewItem 
wxDataViewMainWindow::GetSelection() const 
3856     if( m_selection
.GetCount() != 1 ) 
3857         return wxDataViewItem(); 
3859     return GetItemByRow( m_selection
.Item(0)); 
3862 //----------------------------------------------------------------------------- 
3864 //----------------------------------------------------------------------------- 
3866 WX_DEFINE_LIST(wxDataViewColumnList
) 
3868 IMPLEMENT_DYNAMIC_CLASS(wxDataViewCtrl
, wxDataViewCtrlBase
) 
3869 BEGIN_EVENT_TABLE(wxDataViewCtrl
, wxDataViewCtrlBase
) 
3870     EVT_SIZE(wxDataViewCtrl::OnSize
) 
3873 wxDataViewCtrl::~wxDataViewCtrl() 
3876         GetModel()->RemoveNotifier( m_notifier 
); 
3881 void wxDataViewCtrl::Init() 
3883     m_cols
.DeleteContents(true); 
3886     // No sorting column at start 
3887     m_sortingColumnIdx 
= wxNOT_FOUND
; 
3889     m_headerArea 
= NULL
; 
3892 bool wxDataViewCtrl::Create(wxWindow 
*parent
, 
3897                             const wxValidator
& validator
, 
3898                             const wxString
& name
) 
3900 //    if ( (style & wxBORDER_MASK) == 0) 
3901 //        style |= wxBORDER_SUNKEN; 
3905     if (!wxControl::Create( parent
, id
, pos
, size
, 
3906                             style 
| wxScrolledWindowStyle
, validator
, name
)) 
3909     SetInitialSize(size
); 
3912     MacSetClipChildren( true ); 
3915     m_clientArea 
= new wxDataViewMainWindow( this, wxID_ANY 
); 
3917     // We use the cursor keys for moving the selection, not scrolling, so call 
3918     // this method to ensure wxScrollHelperEvtHandler doesn't catch all 
3919     // keyboard events forwarded to us from wxListMainWindow. 
3920     DisableKeyboardScrolling(); 
3922     if (HasFlag(wxDV_NO_HEADER
)) 
3923         m_headerArea 
= NULL
; 
3925         m_headerArea 
= new wxDataViewHeaderWindow(this); 
3927     SetTargetWindow( m_clientArea 
); 
3929     wxBoxSizer 
*sizer 
= new wxBoxSizer( wxVERTICAL 
); 
3931         sizer
->Add( m_headerArea
, 0, wxGROW 
); 
3932     sizer
->Add( m_clientArea
, 1, wxGROW 
); 
3938 wxBorder 
wxDataViewCtrl::GetDefaultBorder() const 
3940     return wxBORDER_THEME
; 
3944 WXLRESULT 
wxDataViewCtrl::MSWWindowProc(WXUINT nMsg
, 
3948     WXLRESULT rc 
= wxDataViewCtrlBase::MSWWindowProc(nMsg
, wParam
, lParam
); 
3951     // we need to process arrows ourselves for scrolling 
3952     if ( nMsg 
== WM_GETDLGCODE 
) 
3954         rc 
|= DLGC_WANTARROWS
; 
3962 wxSize 
wxDataViewCtrl::GetSizeAvailableForScrollTarget(const wxSize
& size
) 
3964     wxSize newsize 
= size
; 
3965     if (!HasFlag(wxDV_NO_HEADER
) && (m_headerArea
)) 
3966     newsize
.y 
-= m_headerArea
->GetSize().y
; 
3971 void wxDataViewCtrl::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
3973     // We need to override OnSize so that our scrolled 
3974     // window a) does call Layout() to use sizers for 
3975     // positioning the controls but b) does not query 
3976     // the sizer for their size and use that for setting 
3977     // the scrollable area as set that ourselves by 
3978     // calling SetScrollbar() further down. 
3985 void wxDataViewCtrl::SetFocus() 
3988         m_clientArea
->SetFocus(); 
3991 bool wxDataViewCtrl::AssociateModel( wxDataViewModel 
*model 
) 
3993     if (!wxDataViewCtrlBase::AssociateModel( model 
)) 
3996     m_notifier 
= new wxGenericDataViewModelNotifier( m_clientArea 
); 
3998     model
->AddNotifier( m_notifier 
); 
4000     m_clientArea
->DestroyTree(); 
4002     m_clientArea
->BuildTree(model
); 
4004     m_clientArea
->UpdateDisplay(); 
4009 #if wxUSE_DRAG_AND_DROP 
4011 bool wxDataViewCtrl::EnableDragSource( const wxDataFormat 
&format 
) 
4013     return m_clientArea
->EnableDragSource( format 
); 
4016 bool wxDataViewCtrl::EnableDropTarget( const wxDataFormat 
&format 
) 
4018     return m_clientArea
->EnableDropTarget( format 
); 
4021 #endif // wxUSE_DRAG_AND_DROP 
4023 bool wxDataViewCtrl::AppendColumn( wxDataViewColumn 
*col 
) 
4025     if (!wxDataViewCtrlBase::AppendColumn(col
)) 
4028     m_cols
.Append( col 
); 
4029     OnColumnsCountChanged(); 
4033 bool wxDataViewCtrl::PrependColumn( wxDataViewColumn 
*col 
) 
4035     if (!wxDataViewCtrlBase::PrependColumn(col
)) 
4038     m_cols
.Insert( col 
); 
4039     OnColumnsCountChanged(); 
4043 bool wxDataViewCtrl::InsertColumn( unsigned int pos
, wxDataViewColumn 
*col 
) 
4045     if (!wxDataViewCtrlBase::InsertColumn(pos
,col
)) 
4048     m_cols
.Insert( pos
, col 
); 
4049     OnColumnsCountChanged(); 
4053 void wxDataViewCtrl::OnColumnChange(unsigned int idx
) 
4056         m_headerArea
->UpdateColumn(idx
); 
4058     m_clientArea
->UpdateDisplay(); 
4061 void wxDataViewCtrl::OnColumnsCountChanged() 
4064         m_headerArea
->SetColumnCount(GetColumnCount()); 
4066     m_clientArea
->UpdateDisplay(); 
4069 void wxDataViewCtrl::DoSetExpanderColumn() 
4071     m_clientArea
->UpdateDisplay(); 
4074 void wxDataViewCtrl::DoSetIndent() 
4076     m_clientArea
->UpdateDisplay(); 
4079 unsigned int wxDataViewCtrl::GetColumnCount() const 
4081     return m_cols
.GetCount(); 
4084 wxDataViewColumn
* wxDataViewCtrl::GetColumn( unsigned int idx 
) const 
4089 wxDataViewColumn 
*wxDataViewCtrl::GetColumnAt(unsigned int pos
) const 
4091     // columns can't be reordered if there is no header window which allows 
4093     const unsigned idx 
= m_headerArea 
? m_headerArea
->GetColumnsOrder()[pos
] 
4096     return GetColumn(idx
); 
4099 int wxDataViewCtrl::GetColumnIndex(const wxDataViewColumn 
*column
) const 
4101     const unsigned count 
= m_cols
.size(); 
4102     for ( unsigned n 
= 0; n 
< count
; n
++ ) 
4104         if ( m_cols
[n
] == column 
) 
4111 void wxDataViewCtrl::ColumnMoved(wxDataViewColumn 
* WXUNUSED(col
), 
4112                                 unsigned int WXUNUSED(new_pos
)) 
4114     // do _not_ reorder m_cols elements here, they should always be in the 
4115     // order in which columns were added, we only display the columns in 
4117     m_clientArea
->UpdateDisplay(); 
4120 bool wxDataViewCtrl::DeleteColumn( wxDataViewColumn 
*column 
) 
4122     wxDataViewColumnList::compatibility_iterator ret 
= m_cols
.Find( column 
); 
4127     OnColumnsCountChanged(); 
4132 bool wxDataViewCtrl::ClearColumns() 
4135     OnColumnsCountChanged(); 
4139 int wxDataViewCtrl::GetColumnPosition( const wxDataViewColumn 
*column 
) const 
4142     unsigned int len 
= GetColumnCount(); 
4143     for ( unsigned int i 
= 0; i 
< len
; i
++ ) 
4145         wxDataViewColumn 
* col 
= GetColumnAt(i
); 
4152     // This returns the position in pixels which is not what we want. 
4155     unsigned int len 
= GetColumnCount(); 
4156     for ( unsigned int i 
= 0; i 
< len
; i
++ ) 
4158         wxDataViewColumn 
* col 
= GetColumnAt(i
); 
4159         if (col
->IsHidden()) 
4161         ret 
+= col
->GetWidth(); 
4164             CalcScrolledPosition( ret
, dummy
, &ret
, &dummy 
); 
4172 wxDataViewColumn 
*wxDataViewCtrl::GetSortingColumn() const 
4174     return m_sortingColumnIdx 
== wxNOT_FOUND 
? NULL
 
4175                                             : GetColumn(m_sortingColumnIdx
); 
4178 wxDataViewItem 
wxDataViewCtrl::DoGetCurrentItem() const 
4180     return GetItemByRow(m_clientArea
->GetCurrentRow()); 
4183 void wxDataViewCtrl::DoSetCurrentItem(const wxDataViewItem
& item
) 
4185     const int row 
= m_clientArea
->GetRowByItem(item
); 
4187     const unsigned oldCurrent 
= m_clientArea
->GetCurrentRow(); 
4188     if ( static_cast<unsigned>(row
) != oldCurrent 
) 
4190         m_clientArea
->ChangeCurrentRow(row
); 
4191         m_clientArea
->RefreshRow(oldCurrent
); 
4192         m_clientArea
->RefreshRow(row
); 
4196 // Selection code with wxDataViewItem as parameters 
4197 wxDataViewItem 
wxDataViewCtrl::GetSelection() const 
4199     return m_clientArea
->GetSelection(); 
4202 int wxDataViewCtrl::GetSelections( wxDataViewItemArray 
& sel 
) const 
4205     wxDataViewSelection selection 
= m_clientArea
->GetSelections(); 
4206     int len 
= selection
.GetCount(); 
4207     for( int i 
= 0; i 
< len
; i 
++) 
4209         unsigned int row 
= selection
[i
]; 
4210         sel
.Add( m_clientArea
->GetItemByRow( row 
) ); 
4215 void wxDataViewCtrl::SetSelections( const wxDataViewItemArray 
& sel 
) 
4217     wxDataViewSelection 
selection(wxDataViewSelectionCmp
); 
4219     wxDataViewItem last_parent
; 
4221     int len 
= sel
.GetCount(); 
4222     for( int i 
= 0; i 
< len
; i 
++ ) 
4224         wxDataViewItem item 
= sel
[i
]; 
4225         wxDataViewItem parent 
= GetModel()->GetParent( item 
); 
4228             if (parent 
!= last_parent
) 
4229                 ExpandAncestors(item
); 
4232         last_parent 
= parent
; 
4233         int row 
= m_clientArea
->GetRowByItem( item 
); 
4235             selection
.Add( static_cast<unsigned int>(row
) ); 
4238     m_clientArea
->SetSelections( selection 
); 
4241 void wxDataViewCtrl::Select( const wxDataViewItem 
& item 
) 
4243     ExpandAncestors( item 
); 
4245     int row 
= m_clientArea
->GetRowByItem( item 
); 
4248         // Unselect all rows before select another in the single select mode 
4249         if (m_clientArea
->IsSingleSel()) 
4250             m_clientArea
->SelectAllRows(false); 
4252         m_clientArea
->SelectRow(row
, true); 
4254         // Also set focus to the selected item 
4255         m_clientArea
->ChangeCurrentRow( row 
); 
4259 void wxDataViewCtrl::Unselect( const wxDataViewItem 
& item 
) 
4261     int row 
= m_clientArea
->GetRowByItem( item 
); 
4263         m_clientArea
->SelectRow(row
, false); 
4266 bool wxDataViewCtrl::IsSelected( const wxDataViewItem 
& item 
) const 
4268     int row 
= m_clientArea
->GetRowByItem( item 
); 
4271         return m_clientArea
->IsRowSelected(row
); 
4276 // Selection code with row number as parameter 
4277 int wxDataViewCtrl::GetSelections( wxArrayInt 
& sel 
) const 
4280     wxDataViewSelection selection 
= m_clientArea
->GetSelections(); 
4281     int len 
= selection
.GetCount(); 
4282     for( int i 
= 0; i 
< len
; i 
++) 
4284         unsigned int row 
= selection
[i
]; 
4290 void wxDataViewCtrl::SetSelections( const wxArrayInt 
& sel 
) 
4292     wxDataViewSelection 
selection(wxDataViewSelectionCmp
); 
4293     int len 
= sel
.GetCount(); 
4294     for( int i 
= 0; i 
< len
; i 
++ ) 
4298             selection
.Add( static_cast<unsigned int>(row
) ); 
4300     m_clientArea
->SetSelections( selection 
); 
4303 void wxDataViewCtrl::Select( int row 
) 
4307         if (m_clientArea
->IsSingleSel()) 
4308             m_clientArea
->SelectAllRows(false); 
4309         m_clientArea
->SelectRow( row
, true ); 
4313 void wxDataViewCtrl::Unselect( int row 
) 
4316         m_clientArea
->SelectRow(row
, false); 
4319 bool wxDataViewCtrl::IsSelected( int row 
) const 
4322         return m_clientArea
->IsRowSelected(row
); 
4326 void wxDataViewCtrl::SelectRange( int from
, int to 
) 
4329     for( int i 
= from
; i 
< to
; i 
++ ) 
4331     m_clientArea
->Select(sel
); 
4334 void wxDataViewCtrl::UnselectRange( int from
, int to 
) 
4336     wxDataViewSelection sel 
= m_clientArea
->GetSelections(); 
4337     for( int i 
= from
; i 
< to
; i 
++ ) 
4338         if( sel
.Index( i 
) != wxNOT_FOUND 
) 
4340     m_clientArea
->SetSelections(sel
); 
4343 void wxDataViewCtrl::SelectAll() 
4345     m_clientArea
->SelectAllRows(true); 
4348 void wxDataViewCtrl::UnselectAll() 
4350     m_clientArea
->SelectAllRows(false); 
4353 void wxDataViewCtrl::EnsureVisible( int row
, int column 
) 
4357     if( row 
> (int) m_clientArea
->GetRowCount() ) 
4358         row 
= m_clientArea
->GetRowCount(); 
4360     int first 
= m_clientArea
->GetFirstVisibleRow(); 
4361     int last 
= m_clientArea
->GetLastVisibleRow(); 
4363         m_clientArea
->ScrollTo( row
, column 
); 
4364     else if( row 
> last 
) 
4365         m_clientArea
->ScrollTo( row 
- last 
+ first
, column 
); 
4367         m_clientArea
->ScrollTo( first
, column 
); 
4370 void wxDataViewCtrl::EnsureVisible( const wxDataViewItem 
& item
, const wxDataViewColumn 
* column 
) 
4372     ExpandAncestors( item 
); 
4374     m_clientArea
->RecalculateDisplay(); 
4376     int row 
= m_clientArea
->GetRowByItem(item
); 
4379         if( column 
== NULL 
) 
4380             EnsureVisible(row
, -1); 
4382             EnsureVisible( row
, GetColumnIndex(column
) ); 
4387 void wxDataViewCtrl::HitTest( const wxPoint 
& point
, wxDataViewItem 
& item
, 
4388                               wxDataViewColumn
* &column 
) const 
4390     m_clientArea
->HitTest(point
, item
, column
); 
4393 wxRect 
wxDataViewCtrl::GetItemRect( const wxDataViewItem 
& item
, 
4394                                     const wxDataViewColumn
* column 
) const 
4396     return m_clientArea
->GetItemRect(item
, column
); 
4399 wxDataViewItem 
wxDataViewCtrl::GetItemByRow( unsigned int row 
) const 
4401     return m_clientArea
->GetItemByRow( row 
); 
4404 int wxDataViewCtrl::GetRowByItem( const wxDataViewItem 
& item 
) const 
4406     return m_clientArea
->GetRowByItem( item 
); 
4409 void wxDataViewCtrl::Expand( const wxDataViewItem 
& item 
) 
4411     int row 
= m_clientArea
->GetRowByItem( item 
); 
4413         m_clientArea
->Expand(row
); 
4416 void wxDataViewCtrl::Collapse( const wxDataViewItem 
& item 
) 
4418     int row 
= m_clientArea
->GetRowByItem( item 
); 
4420         m_clientArea
->Collapse(row
); 
4423 bool wxDataViewCtrl::IsExpanded( const wxDataViewItem 
& item 
) const 
4425     int row 
= m_clientArea
->GetRowByItem( item 
); 
4427         return m_clientArea
->IsExpanded(row
); 
4431 void wxDataViewCtrl::StartEditor( const wxDataViewItem 
& item
, unsigned int column 
) 
4433     wxDataViewColumn
* col 
= GetColumn( column 
); 
4437     wxRect itemRect 
= GetItemRect(item
, col
); 
4438     wxDataViewRenderer
* renderer 
= col
->GetRenderer(); 
4439     renderer
->StartEditing(item
, itemRect
); 
4442 #endif // !wxUSE_GENERICDATAVIEWCTRL 
4444 #endif // wxUSE_DATAVIEWCTRL