1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        generic/listctrl.cpp 
   3 // Purpose:     generic implementation of wxListCtrl 
   4 // Author:      Robert Roebling 
   5 //              Vadim Zeitlin (virtual list control support) 
   7 // Copyright:   (c) 1998 Robert Roebling 
   8 // Licence:     wxWindows licence 
   9 ///////////////////////////////////////////////////////////////////////////// 
  14    1. we need to implement searching/sorting for virtual controls somehow 
  15    2. when changing selection the lines are refreshed twice 
  18 // ============================================================================ 
  20 // ============================================================================ 
  22 // ---------------------------------------------------------------------------- 
  24 // ---------------------------------------------------------------------------- 
  27     #pragma implementation "listctrl.h" 
  28     #pragma implementation "listctrlbase.h" 
  31 // For compilers that support precompilation, includes "wx.h". 
  32 #include "wx/wxprec.h" 
  40 #include "wx/dcscreen.h" 
  42 #include "wx/listctrl.h" 
  43 #include "wx/imaglist.h" 
  44 #include "wx/dynarray.h" 
  48 #include "wx/gtk/win_gtk.h" 
  51 // ---------------------------------------------------------------------------- 
  53 // ---------------------------------------------------------------------------- 
  55 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
) 
  56 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
) 
  57 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
) 
  58 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
) 
  59 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
) 
  60 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
) 
  61 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
) 
  62 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
) 
  63 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
) 
  64 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
) 
  65 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
) 
  66 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
) 
  67 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
) 
  68 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
) 
  69 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
) 
  70 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
) 
  71 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT
) 
  73 // ---------------------------------------------------------------------------- 
  75 // ---------------------------------------------------------------------------- 
  77 // the height of the header window (FIXME: should depend on its font!) 
  78 static const int HEADER_HEIGHT 
= 23; 
  80 // the scrollbar units 
  81 static const int SCROLL_UNIT_X 
= 15; 
  82 static const int SCROLL_UNIT_Y 
= 15; 
  84 // the spacing between the lines (in report mode) 
  85 static const int LINE_SPACING 
= 0; 
  87 // extra margins around the text label 
  88 static const int EXTRA_WIDTH 
= 3; 
  89 static const int EXTRA_HEIGHT 
= 4; 
  91 // offset for the header window 
  92 static const int HEADER_OFFSET_X 
= 1; 
  93 static const int HEADER_OFFSET_Y 
= 1; 
  95 // when autosizing the columns, add some slack 
  96 static const int AUTOSIZE_COL_MARGIN 
= 10; 
  98 // default and minimal widths for the header columns 
  99 static const int WIDTH_COL_DEFAULT 
= 80; 
 100 static const int WIDTH_COL_MIN 
= 10; 
 102 // the space between the image and the text in the report mode 
 103 static const int IMAGE_MARGIN_IN_REPORT_MODE 
= 5; 
 105 // ============================================================================ 
 107 // ============================================================================ 
 109 // ---------------------------------------------------------------------------- 
 111 // ---------------------------------------------------------------------------- 
 113 int CMPFUNC_CONV 
wxSizeTCmpFn(size_t n1
, size_t n2
) { return n1 
- n2
; } 
 115 WX_DEFINE_SORTED_EXPORTED_ARRAY(size_t, wxIndexArray
); 
 117 // this class is used to store the selected items in the virtual list control 
 118 // (but it is not tied to list control and so can be used with other controls 
 119 // such as wxListBox in wxUniv) 
 121 // the idea is to make it really smart later (i.e. store the selections as an 
 122 // array of ranes + individual items) but, as I don't have time to do it now 
 123 // (this would require writing code to merge/break ranges and much more) keep 
 124 // it simple but define a clean interface to it which allows it to be made 
 126 class WXDLLEXPORT wxSelectionStore
 
 129     wxSelectionStore() : m_itemsSel(wxSizeTCmpFn
) { Init(); } 
 131     // set the total number of items we handle 
 132     void SetItemCount(size_t count
) { m_count 
= count
; } 
 134     // special case of SetItemCount(0) 
 135     void Clear() { m_itemsSel
.Clear(); m_count 
= 0; } 
 137     // must be called when a new item is inserted/added 
 138     void OnItemAdd(size_t item
) { wxFAIL_MSG( _T("TODO") ); } 
 140     // must be called when an item is deleted 
 141     void OnItemDelete(size_t item
); 
 143     // select one item, use SelectRange() insted if possible! 
 145     // returns true if the items selection really changed 
 146     bool SelectItem(size_t item
, bool select 
= TRUE
); 
 148     // select the range of items 
 150     // return true and fill the itemsChanged array with the indices of items 
 151     // which have changed state if "few" of them did, otherwise return false 
 152     // (meaning that too many items changed state to bother counting them 
 154     bool SelectRange(size_t itemFrom
, size_t itemTo
, 
 156                      wxArrayInt 
*itemsChanged 
= NULL
); 
 158     // return true if the given item is selected 
 159     bool IsSelected(size_t item
) const; 
 161     // return the total number of selected items 
 162     size_t GetSelectedCount() const 
 164         return m_defaultState 
? m_count 
- m_itemsSel
.GetCount() 
 165                               : m_itemsSel
.GetCount(); 
 170     void Init() { m_defaultState 
= FALSE
; } 
 172     // the total number of items we handle 
 175     // the default state: normally, FALSE (i.e. off) but maybe set to TRUE if 
 176     // there are more selected items than non selected ones - this allows to 
 177     // handle selection of all items efficiently 
 180     // the array of items whose selection state is different from default 
 181     wxIndexArray m_itemsSel
; 
 183     DECLARE_NO_COPY_CLASS(wxSelectionStore
) 
 186 //----------------------------------------------------------------------------- 
 187 //  wxListItemData (internal) 
 188 //----------------------------------------------------------------------------- 
 190 class WXDLLEXPORT wxListItemData
 
 193     wxListItemData(wxListMainWindow 
*owner
); 
 196     void SetItem( const wxListItem 
&info 
); 
 197     void SetImage( int image 
) { m_image 
= image
; } 
 198     void SetData( long data 
) { m_data 
= data
; } 
 199     void SetPosition( int x
, int y 
); 
 200     void SetSize( int width
, int height 
); 
 202     bool HasText() const { return !m_text
.empty(); } 
 203     const wxString
& GetText() const { return m_text
; } 
 204     void SetText(const wxString
& text
) { m_text 
= text
; } 
 206     // we can't use empty string for measuring the string width/height, so 
 207     // always return something 
 208     wxString 
GetTextForMeasuring() const 
 210         wxString s 
= GetText(); 
 217     bool IsHit( int x
, int y 
) const; 
 221     int GetWidth() const; 
 222     int GetHeight() const; 
 224     int GetImage() const { return m_image
; } 
 225     bool HasImage() const { return GetImage() != -1; } 
 227     void GetItem( wxListItem 
&info 
) const; 
 229     void SetAttr(wxListItemAttr 
*attr
) { m_attr 
= attr
; } 
 230     wxListItemAttr 
*GetAttr() const { return m_attr
; } 
 233     // the item image or -1 
 236     // user data associated with the item 
 239     // the item coordinates are not used in report mode, instead this pointer 
 240     // is NULL and the owner window is used to retrieve the item position and 
 244     // the list ctrl we are in 
 245     wxListMainWindow 
*m_owner
; 
 247     // custom attributes or NULL 
 248     wxListItemAttr 
*m_attr
; 
 251     // common part of all ctors 
 257 //----------------------------------------------------------------------------- 
 258 //  wxListHeaderData (internal) 
 259 //----------------------------------------------------------------------------- 
 261 class WXDLLEXPORT wxListHeaderData 
: public wxObject
 
 275     wxListHeaderData( const wxListItem 
&info 
); 
 276     void SetItem( const wxListItem 
&item 
); 
 277     void SetPosition( int x
, int y 
); 
 278     void SetWidth( int w 
); 
 279     void SetFormat( int format 
); 
 280     void SetHeight( int h 
); 
 281     bool HasImage() const; 
 283     bool HasText() const { return !m_text
.empty(); } 
 284     const wxString
& GetText() const { return m_text
; } 
 285     void SetText(const wxString
& text
) { m_text 
= text
; } 
 287     void GetItem( wxListItem 
&item 
); 
 289     bool IsHit( int x
, int y 
) const; 
 290     int GetImage() const; 
 291     int GetWidth() const; 
 292     int GetFormat() const; 
 295     DECLARE_DYNAMIC_CLASS(wxListHeaderData
); 
 298 //----------------------------------------------------------------------------- 
 299 //  wxListLineData (internal) 
 300 //----------------------------------------------------------------------------- 
 302 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
); 
 303 #include "wx/listimpl.cpp" 
 304 WX_DEFINE_LIST(wxListItemDataList
); 
 306 class WXDLLEXPORT wxListLineData
 
 309     // the list of subitems: only may have more than one item in report mode 
 310     wxListItemDataList m_items
; 
 312     // this is not used in report view 
 324         // the part to be highlighted 
 325         wxRect m_rectHighlight
; 
 328     // is this item selected? [NB: not used in virtual mode] 
 331     // back pointer to the list ctrl 
 332     wxListMainWindow 
*m_owner
; 
 335     wxListLineData(wxListMainWindow 
*owner
); 
 337     ~wxListLineData() { delete m_gi
; } 
 339     // are we in report mode? 
 340     inline bool InReportView() const; 
 342     // are we in virtual report mode? 
 343     inline bool IsVirtual() const; 
 345     // these 2 methods shouldn't be called for report view controls, in that 
 346     // case we determine our position/size ourselves 
 348     // calculate the size of the line 
 349     void CalculateSize( wxDC 
*dc
, int spacing 
); 
 351     // remember the position this line appears at 
 352     void SetPosition( int x
, int y
,  int window_width
, int spacing 
); 
 356     void SetImage( int image 
) { SetImage(0, image
); } 
 357     int GetImage() const { return GetImage(0); } 
 358     bool HasImage() const { return GetImage() != -1; } 
 359     bool HasText() const { return !GetText(0).empty(); } 
 361     void SetItem( int index
, const wxListItem 
&info 
); 
 362     void GetItem( int index
, wxListItem 
&info 
); 
 364     wxString 
GetText(int index
) const; 
 365     void SetText( int index
, const wxString s 
); 
 367     wxListItemAttr 
*GetAttr() const; 
 368     void SetAttr(wxListItemAttr 
*attr
); 
 370     // return true if the highlighting really changed 
 371     bool Highlight( bool on 
); 
 373     void ReverseHighlight(); 
 375     bool IsHighlighted() const 
 377         wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") ); 
 379         return m_highlighted
; 
 382     // draw the line on the given DC in icon/list mode 
 383     void Draw( wxDC 
*dc 
); 
 385     // the same in report mode 
 386     void DrawInReportMode( wxDC 
*dc
, 
 388                            const wxRect
& rectHL
, 
 392     // set the line to contain num items (only can be > 1 in report mode) 
 393     void InitItems( int num 
); 
 395     // get the mode (i.e. style)  of the list control 
 396     inline int GetMode() const; 
 398     // prepare the DC for drawing with these item's attributes, return true if 
 399     // we need to draw the items background to highlight it, false otherwise 
 400     bool SetAttributes(wxDC 
*dc
, 
 401                        const wxListItemAttr 
*attr
, 
 404     // these are only used by GetImage/SetImage above, we don't support images 
 405     // with subitems at the public API level yet 
 406     void SetImage( int index
, int image 
); 
 407     int GetImage( int index 
) const; 
 410 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
); 
 411 #include "wx/arrimpl.cpp" 
 412 WX_DEFINE_OBJARRAY(wxListLineDataArray
); 
 414 //----------------------------------------------------------------------------- 
 415 //  wxListHeaderWindow (internal) 
 416 //----------------------------------------------------------------------------- 
 418 class WXDLLEXPORT wxListHeaderWindow 
: public wxWindow
 
 421     wxListMainWindow  
*m_owner
; 
 422     wxCursor          
*m_currentCursor
; 
 423     wxCursor          
*m_resizeCursor
; 
 426     // column being resized 
 429     // divider line position in logical (unscrolled) coords 
 432     // minimal position beyond which the divider line can't be dragged in 
 437     wxListHeaderWindow(); 
 438     virtual ~wxListHeaderWindow(); 
 440     wxListHeaderWindow( wxWindow 
*win
, 
 442                         wxListMainWindow 
*owner
, 
 443                         const wxPoint 
&pos 
= wxDefaultPosition
, 
 444                         const wxSize 
&size 
= wxDefaultSize
, 
 446                         const wxString 
&name 
= "wxlistctrlcolumntitles" ); 
 448     void DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
); 
 450     void AdjustDC(wxDC
& dc
); 
 452     void OnPaint( wxPaintEvent 
&event 
); 
 453     void OnMouse( wxMouseEvent 
&event 
); 
 454     void OnSetFocus( wxFocusEvent 
&event 
); 
 460     DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
) 
 461     DECLARE_EVENT_TABLE() 
 464 //----------------------------------------------------------------------------- 
 465 // wxListRenameTimer (internal) 
 466 //----------------------------------------------------------------------------- 
 468 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
 
 471     wxListMainWindow 
*m_owner
; 
 474     wxListRenameTimer( wxListMainWindow 
*owner 
); 
 478 //----------------------------------------------------------------------------- 
 479 //  wxListTextCtrl (internal) 
 480 //----------------------------------------------------------------------------- 
 482 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
 
 487     wxListMainWindow   
*m_owner
; 
 488     wxString            m_startValue
; 
 492     wxListTextCtrl( wxWindow 
*parent
, const wxWindowID id
, 
 493                     bool *accept
, wxString 
*res
, wxListMainWindow 
*owner
, 
 494                     const wxString 
&value 
= "", 
 495                     const wxPoint 
&pos 
= wxDefaultPosition
, const wxSize 
&size 
= wxDefaultSize
, 
 497                     const wxValidator
& validator 
= wxDefaultValidator
, 
 498                     const wxString 
&name 
= "listctrltextctrl" ); 
 499     void OnChar( wxKeyEvent 
&event 
); 
 500     void OnKeyUp( wxKeyEvent 
&event 
); 
 501     void OnKillFocus( wxFocusEvent 
&event 
); 
 504     DECLARE_DYNAMIC_CLASS(wxListTextCtrl
); 
 505     DECLARE_EVENT_TABLE() 
 508 //----------------------------------------------------------------------------- 
 509 //  wxListMainWindow (internal) 
 510 //----------------------------------------------------------------------------- 
 512 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
); 
 513 #include "wx/listimpl.cpp" 
 514 WX_DEFINE_LIST(wxListHeaderDataList
); 
 516 class WXDLLEXPORT wxListMainWindow 
: public wxScrolledWindow
 
 520     wxListMainWindow( wxWindow 
*parent
, 
 522                       const wxPoint
& pos 
= wxDefaultPosition
, 
 523                       const wxSize
& size 
= wxDefaultSize
, 
 525                       const wxString 
&name 
= _T("listctrlmainwindow") ); 
 527     virtual ~wxListMainWindow(); 
 529     bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); } 
 531     // return true if this is a virtual list control 
 532     bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); } 
 534     // return true if the control is in report mode 
 535     bool InReportView() const { return HasFlag(wxLC_REPORT
); } 
 537     // return true if we are in single selection mode, false if multi sel 
 538     bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); } 
 540     // do we have a header window? 
 541     bool HasHeader() const 
 542         { return HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
); } 
 544     void HighlightAll( bool on 
); 
 546     // all these functions only do something if the line is currently visible 
 548     // change the line "selected" state, return TRUE if it really changed 
 549     bool HighlightLine( size_t line
, bool highlight 
= TRUE
); 
 551     // as HighlightLine() but do it for the range of lines: this is incredibly 
 552     // more efficient for virtual list controls! 
 554     // NB: unlike HighlightLine() this one does refresh the lines on screen 
 555     void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on 
= TRUE 
); 
 557     // toggle the line state and refresh it 
 558     void ReverseHighlight( size_t line 
) 
 559         { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); } 
 561     // return true if the line is highlighted 
 562     bool IsHighlighted(size_t line
) const; 
 564     // refresh one or several lines at once 
 565     void RefreshLine( size_t line 
); 
 566     void RefreshLines( size_t lineFrom
, size_t lineTo 
); 
 568     // refresh all selected items 
 569     void RefreshSelected(); 
 571     // refresh all lines below the given one: the difference with 
 572     // RefreshLines() is that the index here might not be a valid one (happens 
 573     // when the last line is deleted) 
 574     void RefreshAfter( size_t lineFrom 
); 
 576     // the methods which are forwarded to wxListLineData itself in list/icon 
 577     // modes but are here because the lines don't store their positions in the 
 580     // get the bound rect for the entire line 
 581     wxRect 
GetLineRect(size_t line
) const; 
 583     // get the bound rect of the label 
 584     wxRect 
GetLineLabelRect(size_t line
) const; 
 586     // get the bound rect of the items icon (only may be called if we do have 
 588     wxRect 
GetLineIconRect(size_t line
) const; 
 590     // get the rect to be highlighted when the item has focus 
 591     wxRect 
GetLineHighlightRect(size_t line
) const; 
 593     // get the size of the total line rect 
 594     wxSize 
GetLineSize(size_t line
) const 
 595         { return GetLineRect(line
).GetSize(); } 
 597     // return the hit code for the corresponding position (in this line) 
 598     long HitTestLine(size_t line
, int x
, int y
) const; 
 600     // bring the selected item into view, scrolling to it if necessary 
 601     void MoveToItem(size_t item
); 
 603     // bring the current item into view 
 604     void MoveToFocus() { MoveToItem(m_current
); } 
 606     void EditLabel( long item 
); 
 607     void OnRenameTimer(); 
 608     void OnRenameAccept(); 
 610     void OnMouse( wxMouseEvent 
&event 
); 
 612     // called to switch the selection from the current item to newCurrent, 
 613     void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event 
); 
 615     void OnChar( wxKeyEvent 
&event 
); 
 616     void OnKeyDown( wxKeyEvent 
&event 
); 
 617     void OnSetFocus( wxFocusEvent 
&event 
); 
 618     void OnKillFocus( wxFocusEvent 
&event 
); 
 619     void OnScroll(wxScrollWinEvent
& event
) ; 
 621     void OnPaint( wxPaintEvent 
&event 
); 
 623     void DrawImage( int index
, wxDC 
*dc
, int x
, int y 
); 
 624     void GetImageSize( int index
, int &width
, int &height 
) const; 
 625     int GetTextLength( const wxString 
&s 
) const; 
 627     void SetImageList( wxImageList 
*imageList
, int which 
); 
 628     void SetItemSpacing( int spacing
, bool isSmall 
= FALSE 
); 
 629     int GetItemSpacing( bool isSmall 
= FALSE 
); 
 631     void SetColumn( int col
, wxListItem 
&item 
); 
 632     void SetColumnWidth( int col
, int width 
); 
 633     void GetColumn( int col
, wxListItem 
&item 
) const; 
 634     int GetColumnWidth( int col 
) const; 
 635     int GetColumnCount() const { return m_columns
.GetCount(); } 
 637     // returns the sum of the heights of all columns 
 638     int GetHeaderWidth() const; 
 640     int GetCountPerPage() const; 
 642     void SetItem( wxListItem 
&item 
); 
 643     void GetItem( wxListItem 
&item 
); 
 644     void SetItemState( long item
, long state
, long stateMask 
); 
 645     int GetItemState( long item
, long stateMask 
); 
 646     void GetItemRect( long index
, wxRect 
&rect 
); 
 647     bool GetItemPosition( long item
, wxPoint
& pos 
); 
 648     int GetSelectedItemCount(); 
 650     // set the scrollbars and update the positions of the items 
 651     void RecalculatePositions(bool noRefresh 
= FALSE
); 
 653     // refresh the window and the header 
 656     long GetNextItem( long item
, int geometry
, int state 
); 
 657     void DeleteItem( long index 
); 
 658     void DeleteAllItems(); 
 659     void DeleteColumn( int col 
); 
 660     void DeleteEverything(); 
 661     void EnsureVisible( long index 
); 
 662     long FindItem( long start
, const wxString
& str
, bool partial 
= FALSE 
); 
 663     long FindItem( long start
, long data
); 
 664     long HitTest( int x
, int y
, int &flags 
); 
 665     void InsertItem( wxListItem 
&item 
); 
 666     void InsertColumn( long col
, wxListItem 
&item 
); 
 667     void SortItems( wxListCtrlCompare fn
, long data 
); 
 669     size_t GetItemCount() const; 
 670     bool IsEmpty() const { return GetItemCount() == 0; } 
 671     void SetItemCount(long count
); 
 673     void ResetCurrent() { m_current 
= (size_t)-1; } 
 674     bool HasCurrent() const { return m_current 
!= (size_t)-1; } 
 676     // send out a wxListEvent 
 677     void SendNotify( size_t line
, 
 679                      wxPoint point 
= wxDefaultPosition 
); 
 681     // override base class virtual to reset m_lineHeight when the font changes 
 682     virtual bool SetFont(const wxFont
& font
) 
 684         if ( !wxScrolledWindow::SetFont(font
) ) 
 692     // these are for wxListLineData usage only 
 694     // get the backpointer to the list ctrl 
 695     wxListCtrl 
*GetListCtrl() const 
 697         return wxStaticCast(GetParent(), wxListCtrl
); 
 700     // get the height of all lines (assuming they all do have the same height) 
 701     wxCoord 
GetLineHeight() const; 
 703     // get the y position of the given line (only for report view) 
 704     wxCoord 
GetLineY(size_t line
) const; 
 706     // get the brush to use for the item highlighting 
 707     wxBrush 
*GetHighlightBrush() const 
 709         return m_hasFocus 
? m_highlightBrush 
: m_highlightUnfocusedBrush
; 
 713     // the array of all line objects for a non virtual list control 
 714     wxListLineDataArray  m_lines
; 
 716     // the list of column objects 
 717     wxListHeaderDataList m_columns
; 
 719     // currently focused item or -1 
 722     // the item currently being edited or -1 
 723     size_t               m_currentEdit
; 
 725     // the number of lines per page 
 728     // this flag is set when something which should result in the window 
 729     // redrawing happens (i.e. an item was added or deleted, or its appearance 
 730     // changed) and OnPaint() doesn't redraw the window while it is set which 
 731     // allows to minimize the number of repaintings when a lot of items are 
 732     // being added. The real repainting occurs only after the next OnIdle() 
 736     wxColour            
*m_highlightColour
; 
 739     wxImageList         
*m_small_image_list
; 
 740     wxImageList         
*m_normal_image_list
; 
 742     int                  m_normal_spacing
; 
 746     wxTimer             
*m_renameTimer
; 
 748     wxString             m_renameRes
; 
 753     // for double click logic 
 754     size_t m_lineLastClicked
, 
 755            m_lineBeforeLastClicked
; 
 758     // the total count of items in a virtual list control 
 761     // the object maintaining the items selection state, only used in virtual 
 763     wxSelectionStore m_selStore
; 
 765     // common part of all ctors 
 768     // intiialize m_[xy]Scroll 
 769     void InitScrolling(); 
 771     // get the line data for the given index 
 772     wxListLineData 
*GetLine(size_t n
) const 
 774         wxASSERT_MSG( n 
!= (size_t)-1, _T("invalid line index") ); 
 778             wxConstCast(this, wxListMainWindow
)->CacheLineData(n
); 
 786     // get a dummy line which can be used for geometry calculations and such: 
 787     // you must use GetLine() if you want to really draw the line 
 788     wxListLineData 
*GetDummyLine() const; 
 790     // cache the line data of the n-th line in m_lines[0] 
 791     void CacheLineData(size_t line
); 
 793     // get the range of visible lines 
 794     void GetVisibleLinesRange(size_t *from
, size_t *to
); 
 796     // force us to recalculate the range of visible lines 
 797     void ResetVisibleLinesRange() { m_lineFrom 
= (size_t)-1; } 
 799     // get the colour to be used for drawing the rules 
 800     wxColour 
GetRuleColour() const 
 805         return wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DLIGHT
); 
 810     // initialize the current item if needed 
 811     void UpdateCurrent(); 
 813     // delete all items but don't refresh: called from dtor 
 814     void DoDeleteAllItems(); 
 816     // called when an item is [un]focuded, i.e. becomes [not] current 
 819     void OnFocusLine( size_t line 
); 
 820     void OnUnfocusLine( size_t line 
); 
 822     // the height of one line using the current font 
 823     wxCoord m_lineHeight
; 
 825     // the total header width or 0 if not calculated yet 
 826     wxCoord m_headerWidth
; 
 828     // the first and last lines being shown on screen right now (inclusive), 
 829     // both may be -1 if they must be calculated so never access them directly: 
 830     // use GetVisibleLinesRange() above instead 
 834     // the brushes to use for item highlighting when we do/don't have focus 
 835     wxBrush 
*m_highlightBrush
, 
 836             *m_highlightUnfocusedBrush
; 
 838     DECLARE_DYNAMIC_CLASS(wxListMainWindow
); 
 839     DECLARE_EVENT_TABLE() 
 842 // ============================================================================ 
 844 // ============================================================================ 
 846 // ---------------------------------------------------------------------------- 
 848 // ---------------------------------------------------------------------------- 
 850 bool wxSelectionStore::IsSelected(size_t item
) const 
 852     bool isSel 
= m_itemsSel
.Index(item
) != wxNOT_FOUND
; 
 854     // if the default state is to be selected, being in m_itemsSel means that 
 855     // the item is not selected, so we have to inverse the logic 
 856     return m_defaultState 
? !isSel 
: isSel
; 
 859 bool wxSelectionStore::SelectItem(size_t item
, bool select
) 
 861     // search for the item ourselves as like this we get the index where to 
 862     // insert it later if needed, so we do only one search in the array instead 
 863     // of two (adding item to a sorted array requires a search) 
 864     size_t index 
= m_itemsSel
.IndexForInsert(item
); 
 865     bool isSel 
= index 
< m_itemsSel
.GetCount() && m_itemsSel
[index
] == item
; 
 867     if ( select 
!= m_defaultState 
) 
 871             m_itemsSel
.AddAt(item
, index
); 
 876     else // reset to default state 
 880             m_itemsSel
.RemoveAt(index
); 
 888 bool wxSelectionStore::SelectRange(size_t itemFrom
, size_t itemTo
, 
 890                                    wxArrayInt 
*itemsChanged
) 
 892     // 100 is hardcoded but it shouldn't matter much: the important thing is 
 893     // that we don't refresh everything when really few (e.g. 1 or 2) items 
 895     static const size_t MANY_ITEMS 
= 100; 
 897     wxASSERT_MSG( itemFrom 
<= itemTo
, _T("should be in order") ); 
 899     // are we going to have more [un]selected items than the other ones? 
 900     if ( itemTo 
- itemFrom 
> m_count
/2 ) 
 902         if ( select 
!= m_defaultState 
) 
 904             // the default state now becomes the same as 'select' 
 905             m_defaultState 
= select
; 
 907             // so all the old selections (which had state select) shouldn't be 
 908             // selected any more, but all the other ones should 
 909             wxIndexArray selOld 
= m_itemsSel
; 
 912             // TODO: it should be possible to optimize the searches a bit 
 913             //       knowing the possible range 
 916             for ( item 
= 0; item 
< itemFrom
; item
++ ) 
 918                 if ( selOld
.Index(item
) == wxNOT_FOUND 
) 
 919                     m_itemsSel
.Add(item
); 
 922             for ( item 
= itemTo 
+ 1; item 
< m_count
; item
++ ) 
 924                 if ( selOld
.Index(item
) == wxNOT_FOUND 
) 
 925                     m_itemsSel
.Add(item
); 
 928             // many items (> half) changed state 
 931         else // select == m_defaultState 
 933             // get the inclusive range of items between itemFrom and itemTo 
 934             size_t count 
= m_itemsSel
.GetCount(), 
 935                    start 
= m_itemsSel
.IndexForInsert(itemFrom
), 
 936                    end 
= m_itemsSel
.IndexForInsert(itemTo
); 
 938             if ( start 
== count 
|| m_itemsSel
[start
] < itemFrom 
) 
 943             if ( end 
== count 
|| m_itemsSel
[end
] > itemTo 
) 
 950                 // delete all of them (from end to avoid changing indices) 
 951                 for ( int i 
= end
; i 
>= (int)start
; i
-- ) 
 955                         if ( itemsChanged
->GetCount() > MANY_ITEMS 
) 
 957                             // stop counting (see comment below) 
 961                         itemsChanged
->Add(m_itemsSel
[i
]); 
 964                     m_itemsSel
.RemoveAt(i
); 
 969     else // "few" items change state 
 973             itemsChanged
->Empty(); 
 976         // just add the items to the selection 
 977         for ( size_t item 
= itemFrom
; item 
<= itemTo
; item
++ ) 
 979             if ( SelectItem(item
, select
) && itemsChanged 
) 
 981                 itemsChanged
->Add(item
); 
 983                 if ( itemsChanged
->GetCount() > MANY_ITEMS 
) 
 985                     // stop counting them, we'll just eat gobs of memory 
 986                     // for nothing at all - faster to refresh everything in 
 994     // we set it to NULL if there are many items changing state 
 995     return itemsChanged 
!= NULL
; 
 998 void wxSelectionStore::OnItemDelete(size_t item
) 
1000     size_t count 
= m_itemsSel
.GetCount(), 
1001            i 
= m_itemsSel
.IndexForInsert(item
); 
1003     if ( i 
< count 
&& m_itemsSel
[i
] == item 
) 
1005         // this item itself was in m_itemsSel, remove it from there 
1006         m_itemsSel
.RemoveAt(i
); 
1011     // and adjust the index of all which follow it 
1014         // all following elements must be greater than the one we deleted 
1015         wxASSERT_MSG( m_itemsSel
[i
] > item
, _T("logic error") ); 
1021 //----------------------------------------------------------------------------- 
1023 //----------------------------------------------------------------------------- 
1025 wxListItemData::~wxListItemData() 
1027     // in the virtual list control the attributes are managed by the main 
1028     // program, so don't delete them 
1029     if ( !m_owner
->IsVirtual() ) 
1037 void wxListItemData::Init() 
1045 wxListItemData::wxListItemData(wxListMainWindow 
*owner
) 
1051     if ( owner
->InReportView() ) 
1057         m_rect 
= new wxRect
; 
1061 void wxListItemData::SetItem( const wxListItem 
&info 
) 
1063     if ( info
.m_mask 
& wxLIST_MASK_TEXT 
) 
1064         SetText(info
.m_text
); 
1065     if ( info
.m_mask 
& wxLIST_MASK_IMAGE 
) 
1066         m_image 
= info
.m_image
; 
1067     if ( info
.m_mask 
& wxLIST_MASK_DATA 
) 
1068         m_data 
= info
.m_data
; 
1070     if ( info
.HasAttributes() ) 
1073             *m_attr 
= *info
.GetAttributes(); 
1075             m_attr 
= new wxListItemAttr(*info
.GetAttributes()); 
1083         m_rect
->width 
= info
.m_width
; 
1087 void wxListItemData::SetPosition( int x
, int y 
) 
1089     wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") ); 
1095 void wxListItemData::SetSize( int width
, int height 
) 
1097     wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") ); 
1100         m_rect
->width 
= width
; 
1102         m_rect
->height 
= height
; 
1105 bool wxListItemData::IsHit( int x
, int y 
) const 
1107     wxCHECK_MSG( m_rect
, FALSE
, _T("can't be called in this mode") ); 
1109     return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
); 
1112 int wxListItemData::GetX() const 
1114     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
1119 int wxListItemData::GetY() const 
1121     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
1126 int wxListItemData::GetWidth() const 
1128     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
1130     return m_rect
->width
; 
1133 int wxListItemData::GetHeight() const 
1135     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
1137     return m_rect
->height
; 
1140 void wxListItemData::GetItem( wxListItem 
&info 
) const 
1142     info
.m_text 
= m_text
; 
1143     info
.m_image 
= m_image
; 
1144     info
.m_data 
= m_data
; 
1148         if ( m_attr
->HasTextColour() ) 
1149             info
.SetTextColour(m_attr
->GetTextColour()); 
1150         if ( m_attr
->HasBackgroundColour() ) 
1151             info
.SetBackgroundColour(m_attr
->GetBackgroundColour()); 
1152         if ( m_attr
->HasFont() ) 
1153             info
.SetFont(m_attr
->GetFont()); 
1157 //----------------------------------------------------------------------------- 
1159 //----------------------------------------------------------------------------- 
1161 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
); 
1163 wxListHeaderData::wxListHeaderData() 
1174 wxListHeaderData::wxListHeaderData( const wxListItem 
&item 
) 
1182 void wxListHeaderData::SetItem( const wxListItem 
&item 
) 
1184     m_mask 
= item
.m_mask
; 
1185     m_text 
= item
.m_text
; 
1186     m_image 
= item
.m_image
; 
1187     m_format 
= item
.m_format
; 
1189     SetWidth(item
.m_width
); 
1192 void wxListHeaderData::SetPosition( int x
, int y 
) 
1198 void wxListHeaderData::SetHeight( int h 
) 
1203 void wxListHeaderData::SetWidth( int w 
) 
1207         m_width 
= WIDTH_COL_DEFAULT
; 
1208     if (m_width 
< WIDTH_COL_MIN
) 
1209         m_width 
= WIDTH_COL_MIN
; 
1212 void wxListHeaderData::SetFormat( int format 
) 
1217 bool wxListHeaderData::HasImage() const 
1219     return (m_image 
!= 0); 
1222 bool wxListHeaderData::IsHit( int x
, int y 
) const 
1224     return ((x 
>= m_xpos
) && (x 
<= m_xpos
+m_width
) && (y 
>= m_ypos
) && (y 
<= m_ypos
+m_height
)); 
1227 void wxListHeaderData::GetItem( wxListItem 
&item 
) 
1229     item
.m_mask 
= m_mask
; 
1230     item
.m_text 
= m_text
; 
1231     item
.m_image 
= m_image
; 
1232     item
.m_format 
= m_format
; 
1233     item
.m_width 
= m_width
; 
1236 int wxListHeaderData::GetImage() const 
1241 int wxListHeaderData::GetWidth() const 
1246 int wxListHeaderData::GetFormat() const 
1251 //----------------------------------------------------------------------------- 
1253 //----------------------------------------------------------------------------- 
1255 inline int wxListLineData::GetMode() const 
1257     return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
; 
1260 inline bool wxListLineData::InReportView() const 
1262     return m_owner
->HasFlag(wxLC_REPORT
); 
1265 inline bool wxListLineData::IsVirtual() const 
1267     return m_owner
->IsVirtual(); 
1270 wxListLineData::wxListLineData( wxListMainWindow 
*owner 
) 
1273     m_items
.DeleteContents( TRUE 
); 
1275     if ( InReportView() ) 
1281         m_gi 
= new GeometryInfo
; 
1284     m_highlighted 
= FALSE
; 
1286     InitItems( GetMode() == wxLC_REPORT 
? m_owner
->GetColumnCount() : 1 ); 
1289 void wxListLineData::CalculateSize( wxDC 
*dc
, int spacing 
) 
1291     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1292     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1294     wxListItemData 
*item 
= node
->GetData(); 
1296     switch ( GetMode() ) 
1299         case wxLC_SMALL_ICON
: 
1301                 m_gi
->m_rectAll
.width 
= spacing
; 
1303                 wxString s 
= item
->GetText(); 
1309                     m_gi
->m_rectLabel
.width 
= 
1310                     m_gi
->m_rectLabel
.height 
= 0; 
1314                     dc
->GetTextExtent( s
, &lw
, &lh 
); 
1315                     if (lh 
< SCROLL_UNIT_Y
) 
1320                     m_gi
->m_rectAll
.height 
= spacing 
+ lh
; 
1322                         m_gi
->m_rectAll
.width 
= lw
; 
1324                     m_gi
->m_rectLabel
.width 
= lw
; 
1325                     m_gi
->m_rectLabel
.height 
= lh
; 
1328                 if (item
->HasImage()) 
1331                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
1332                     m_gi
->m_rectIcon
.width 
= w 
+ 8; 
1333                     m_gi
->m_rectIcon
.height 
= h 
+ 8; 
1335                     if ( m_gi
->m_rectIcon
.width 
> m_gi
->m_rectAll
.width 
) 
1336                         m_gi
->m_rectAll
.width 
= m_gi
->m_rectIcon
.width
; 
1337                     if ( m_gi
->m_rectIcon
.height 
+ lh 
> m_gi
->m_rectAll
.height 
- 4 ) 
1338                         m_gi
->m_rectAll
.height 
= m_gi
->m_rectIcon
.height 
+ lh 
+ 4; 
1341                 if ( item
->HasText() ) 
1343                     m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectLabel
.width
; 
1344                     m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectLabel
.height
; 
1346                 else // no text, highlight the icon 
1348                     m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectIcon
.width
; 
1349                     m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectIcon
.height
; 
1356                 wxString s 
= item
->GetTextForMeasuring(); 
1359                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
1360                 if (lh 
< SCROLL_UNIT_Y
) 
1365                 m_gi
->m_rectLabel
.width 
= lw
; 
1366                 m_gi
->m_rectLabel
.height 
= lh
; 
1368                 m_gi
->m_rectAll
.width 
= lw
; 
1369                 m_gi
->m_rectAll
.height 
= lh
; 
1371                 if (item
->HasImage()) 
1374                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
1375                     m_gi
->m_rectIcon
.width 
= w
; 
1376                     m_gi
->m_rectIcon
.height 
= h
; 
1378                     m_gi
->m_rectAll
.width 
+= 4 + w
; 
1379                     if (h 
> m_gi
->m_rectAll
.height
) 
1380                         m_gi
->m_rectAll
.height 
= h
; 
1383                 m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectAll
.width
; 
1384                 m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectAll
.height
; 
1389             wxFAIL_MSG( _T("unexpected call to SetSize") ); 
1393             wxFAIL_MSG( _T("unknown mode") ); 
1397 void wxListLineData::SetPosition( int x
, int y
, 
1401     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1402     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1404     wxListItemData 
*item 
= node
->GetData(); 
1406     switch ( GetMode() ) 
1409         case wxLC_SMALL_ICON
: 
1410             m_gi
->m_rectAll
.x 
= x
; 
1411             m_gi
->m_rectAll
.y 
= y
; 
1413             if ( item
->HasImage() ) 
1415                 m_gi
->m_rectIcon
.x 
= m_gi
->m_rectAll
.x 
+ 4 
1416                                     + (spacing 
- m_gi
->m_rectIcon
.width
)/2; 
1417                 m_gi
->m_rectIcon
.y 
= m_gi
->m_rectAll
.y 
+ 4; 
1420             if ( item
->HasText() ) 
1422                 if (m_gi
->m_rectAll
.width 
> spacing
) 
1423                     m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1425                     m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2); 
1426                 m_gi
->m_rectLabel
.y 
= m_gi
->m_rectAll
.y 
+ m_gi
->m_rectAll
.height 
+ 2 - m_gi
->m_rectLabel
.height
; 
1427                 m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectLabel
.x 
- 2; 
1428                 m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectLabel
.y 
- 2; 
1430             else // no text, highlight the icon 
1432                 m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectIcon
.x 
- 4; 
1433                 m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectIcon
.y 
- 4; 
1438             m_gi
->m_rectAll
.x 
= x
; 
1439             m_gi
->m_rectAll
.y 
= y
; 
1441             m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectAll
.x
; 
1442             m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectAll
.y
; 
1443             m_gi
->m_rectLabel
.y 
= m_gi
->m_rectAll
.y 
+ 2; 
1445             if (item
->HasImage()) 
1447                 m_gi
->m_rectIcon
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1448                 m_gi
->m_rectIcon
.y 
= m_gi
->m_rectAll
.y 
+ 2; 
1449                 m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 6 + m_gi
->m_rectIcon
.width
; 
1453                 m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1458             wxFAIL_MSG( _T("unexpected call to SetPosition") ); 
1462             wxFAIL_MSG( _T("unknown mode") ); 
1466 void wxListLineData::InitItems( int num 
) 
1468     for (int i 
= 0; i 
< num
; i
++) 
1469         m_items
.Append( new wxListItemData(m_owner
) ); 
1472 void wxListLineData::SetItem( int index
, const wxListItem 
&info 
) 
1474     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1475     wxCHECK_RET( node
, _T("invalid column index in SetItem") ); 
1477     wxListItemData 
*item 
= node
->GetData(); 
1478     item
->SetItem( info 
); 
1481 void wxListLineData::GetItem( int index
, wxListItem 
&info 
) 
1483     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1486         wxListItemData 
*item 
= node
->GetData(); 
1487         item
->GetItem( info 
); 
1491 wxString 
wxListLineData::GetText(int index
) const 
1495     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1498         wxListItemData 
*item 
= node
->GetData(); 
1499         s 
= item
->GetText(); 
1505 void wxListLineData::SetText( int index
, const wxString s 
) 
1507     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1510         wxListItemData 
*item 
= node
->GetData(); 
1515 void wxListLineData::SetImage( int index
, int image 
) 
1517     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1518     wxCHECK_RET( node
, _T("invalid column index in SetImage()") ); 
1520     wxListItemData 
*item 
= node
->GetData(); 
1521     item
->SetImage(image
); 
1524 int wxListLineData::GetImage( int index 
) const 
1526     wxListItemDataList::Node 
*node 
= m_items
.Item( index 
); 
1527     wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") ); 
1529     wxListItemData 
*item 
= node
->GetData(); 
1530     return item
->GetImage(); 
1533 wxListItemAttr 
*wxListLineData::GetAttr() const 
1535     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1536     wxCHECK_MSG( node
, NULL
, _T("invalid column index in GetAttr()") ); 
1538     wxListItemData 
*item 
= node
->GetData(); 
1539     return item
->GetAttr(); 
1542 void wxListLineData::SetAttr(wxListItemAttr 
*attr
) 
1544     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1545     wxCHECK_RET( node
, _T("invalid column index in SetAttr()") ); 
1547     wxListItemData 
*item 
= node
->GetData(); 
1548     item
->SetAttr(attr
); 
1551 bool wxListLineData::SetAttributes(wxDC 
*dc
, 
1552                                    const wxListItemAttr 
*attr
, 
1555     wxWindow 
*listctrl 
= m_owner
->GetParent(); 
1559     // don't use foreground colour for drawing highlighted items - this might 
1560     // make them completely invisible (and there is no way to do bit 
1561     // arithmetics on wxColour, unfortunately) 
1565         colText 
= wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
1569         if ( attr 
&& attr
->HasTextColour() ) 
1571             colText 
= attr
->GetTextColour(); 
1575             colText 
= listctrl
->GetForegroundColour(); 
1579     dc
->SetTextForeground(colText
); 
1583     if ( attr 
&& attr
->HasFont() ) 
1585         font 
= attr
->GetFont(); 
1589         font 
= listctrl
->GetFont(); 
1595     bool hasBgCol 
= attr 
&& attr
->HasBackgroundColour(); 
1596     if ( highlighted 
|| hasBgCol 
) 
1600             dc
->SetBrush( *m_owner
->GetHighlightBrush() ); 
1604             dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
1607         dc
->SetPen( *wxTRANSPARENT_PEN 
); 
1615 void wxListLineData::Draw( wxDC 
*dc 
) 
1617     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1618     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1620     bool highlighted 
= IsHighlighted(); 
1622     wxListItemAttr 
*attr 
= GetAttr(); 
1624     if ( SetAttributes(dc
, attr
, highlighted
) ) 
1626         dc
->DrawRectangle( m_gi
->m_rectHighlight 
); 
1629     wxListItemData 
*item 
= node
->GetData(); 
1630     if (item
->HasImage()) 
1632         wxRect rectIcon 
= m_gi
->m_rectIcon
; 
1633         m_owner
->DrawImage( item
->GetImage(), dc
, 
1634                             rectIcon
.x
, rectIcon
.y 
); 
1637     if (item
->HasText()) 
1639         wxRect rectLabel 
= m_gi
->m_rectLabel
; 
1641         wxDCClipper 
clipper(*dc
, rectLabel
); 
1642         dc
->DrawText( item
->GetText(), rectLabel
.x
, rectLabel
.y 
); 
1646 void wxListLineData::DrawInReportMode( wxDC 
*dc
, 
1648                                        const wxRect
& rectHL
, 
1651     // TODO: later we should support setting different attributes for 
1652     //       different columns - to do it, just add "col" argument to 
1653     //       GetAttr() and move these lines into the loop below 
1654     wxListItemAttr 
*attr 
= GetAttr(); 
1655     if ( SetAttributes(dc
, attr
, highlighted
) ) 
1657         dc
->DrawRectangle( rectHL 
); 
1660     wxListItemDataList::Node 
*node 
= m_items
.GetFirst(); 
1661     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1664     wxCoord x 
= rect
.x 
+ HEADER_OFFSET_X
, 
1665             y 
= rect
.y 
+ (LINE_SPACING 
+ EXTRA_HEIGHT
) / 2; 
1669         wxListItemData 
*item 
= node
->GetData(); 
1671         int width 
= m_owner
->GetColumnWidth(col
++); 
1675         if ( item
->HasImage() ) 
1678             m_owner
->DrawImage( item
->GetImage(), dc
, xOld
, y 
); 
1679             m_owner
->GetImageSize( item
->GetImage(), ix
, iy 
); 
1681             ix 
+= IMAGE_MARGIN_IN_REPORT_MODE
; 
1687         wxDCClipper 
clipper(*dc
, xOld
, y
, width
, rect
.height
); 
1689         if ( item
->HasText() ) 
1691             dc
->DrawText( item
->GetText(), xOld
, y 
); 
1694         node 
= node
->GetNext(); 
1698 bool wxListLineData::Highlight( bool on 
) 
1700     wxCHECK_MSG( !m_owner
->IsVirtual(), FALSE
, _T("unexpected call to Highlight") ); 
1702     if ( on 
== m_highlighted 
) 
1710 void wxListLineData::ReverseHighlight( void ) 
1712     Highlight(!IsHighlighted()); 
1715 //----------------------------------------------------------------------------- 
1716 //  wxListHeaderWindow 
1717 //----------------------------------------------------------------------------- 
1719 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
); 
1721 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
) 
1722     EVT_PAINT         (wxListHeaderWindow::OnPaint
) 
1723     EVT_MOUSE_EVENTS  (wxListHeaderWindow::OnMouse
) 
1724     EVT_SET_FOCUS     (wxListHeaderWindow::OnSetFocus
) 
1727 wxListHeaderWindow::wxListHeaderWindow( void ) 
1729     m_owner 
= (wxListMainWindow 
*) NULL
; 
1730     m_currentCursor 
= (wxCursor 
*) NULL
; 
1731     m_resizeCursor 
= (wxCursor 
*) NULL
; 
1732     m_isDragging 
= FALSE
; 
1735 wxListHeaderWindow::wxListHeaderWindow( wxWindow 
*win
, wxWindowID id
, wxListMainWindow 
*owner
, 
1736       const wxPoint 
&pos
, const wxSize 
&size
, 
1737       long style
, const wxString 
&name 
) : 
1738   wxWindow( win
, id
, pos
, size
, style
, name 
) 
1741 //  m_currentCursor = wxSTANDARD_CURSOR; 
1742     m_currentCursor 
= (wxCursor 
*) NULL
; 
1743     m_resizeCursor 
= new wxCursor( wxCURSOR_SIZEWE 
); 
1744     m_isDragging 
= FALSE
; 
1747     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE 
) ); 
1750 wxListHeaderWindow::~wxListHeaderWindow( void ) 
1752     delete m_resizeCursor
; 
1755 void wxListHeaderWindow::DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
) 
1758     GtkStateType state 
= m_parent
->IsEnabled() ? GTK_STATE_NORMAL
 
1759                                                : GTK_STATE_INSENSITIVE
; 
1761     x 
= dc
->XLOG2DEV( x 
); 
1763     gtk_paint_box (m_wxwindow
->style
, GTK_PIZZA(m_wxwindow
)->bin_window
, 
1764                    state
, GTK_SHADOW_OUT
, 
1765                    (GdkRectangle
*) NULL
, m_wxwindow
, "button", 
1766                    x
-1, y
-1, w
+2, h
+2); 
1767 #elif defined( __WXMAC__  ) 
1768     const int m_corner 
= 1; 
1770     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1772     dc
->SetPen( wxPen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW 
) , 1 , wxSOLID 
) ); 
1773     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1774     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1776     wxPen 
pen( wxColour( 0x88 , 0x88 , 0x88 ), 1, wxSOLID 
); 
1779     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1780     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1782     dc
->SetPen( *wxWHITE_PEN 
); 
1783     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1784     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1785     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1786     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1788     const int m_corner 
= 1; 
1790     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
1792     dc
->SetPen( *wxBLACK_PEN 
); 
1793     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
1794     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
1796     wxPen 
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID 
); 
1799     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
1800     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
1802     dc
->SetPen( *wxWHITE_PEN 
); 
1803     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
1804     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
1805     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
1806     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
1810 // shift the DC origin to match the position of the main window horz 
1811 // scrollbar: this allows us to always use logical coords 
1812 void wxListHeaderWindow::AdjustDC(wxDC
& dc
) 
1815     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1818     m_owner
->GetViewStart( &x
, NULL 
); 
1820     // account for the horz scrollbar offset 
1821     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1824 void wxListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1827     wxClientDC 
dc( this ); 
1829     wxPaintDC 
dc( this ); 
1837     dc
.SetFont( GetFont() ); 
1839     // width and height of the entire header window 
1841     GetClientSize( &w
, &h 
); 
1842     m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1844     dc
.SetBackgroundMode(wxTRANSPARENT
); 
1846     // do *not* use the listctrl colour for headers - one day we will have a 
1847     // function to set it separately 
1848     //dc.SetTextForeground( *wxBLACK ); 
1849     dc
.SetTextForeground(wxSystemSettings:: 
1850                             GetSystemColour( wxSYS_COLOUR_WINDOWTEXT 
)); 
1852     int x 
= HEADER_OFFSET_X
; 
1854     int numColumns 
= m_owner
->GetColumnCount(); 
1856     for (int i 
= 0; i 
< numColumns
; i
++) 
1858         m_owner
->GetColumn( i
, item 
); 
1859         int wCol 
= item
.m_width
; 
1860         int cw 
= wCol 
- 2; // the width of the rect to draw 
1862         int xEnd 
= x 
+ wCol
; 
1864         dc
.SetPen( *wxWHITE_PEN 
); 
1866         DoDrawRect( &dc
, x
, HEADER_OFFSET_Y
, cw
, h
-2 ); 
1867         wxDCClipper 
clipper(dc
, x
, HEADER_OFFSET_Y
, cw
-5, h
-4 ); 
1869         dc
.DrawText( item
.GetText(), 
1870                      x 
+ EXTRA_WIDTH
, HEADER_OFFSET_Y 
+ EXTRA_HEIGHT 
); 
1880 void wxListHeaderWindow::DrawCurrent() 
1882     int x1 
= m_currentX
; 
1884     ClientToScreen( &x1
, &y1 
); 
1886     int x2 
= m_currentX
-1; 
1888     m_owner
->GetClientSize( NULL
, &y2 
); 
1889     m_owner
->ClientToScreen( &x2
, &y2 
); 
1892     dc
.SetLogicalFunction( wxINVERT 
); 
1893     dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID 
) ); 
1894     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
1898     dc
.DrawLine( x1
, y1
, x2
, y2 
); 
1900     dc
.SetLogicalFunction( wxCOPY 
); 
1902     dc
.SetPen( wxNullPen 
); 
1903     dc
.SetBrush( wxNullBrush 
); 
1906 void wxListHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1908     // we want to work with logical coords 
1910     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1911     int y 
= event
.GetY(); 
1915         // we don't draw the line beyond our window, but we allow dragging it 
1918         GetClientSize( &w
, NULL 
); 
1919         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1922         // erase the line if it was drawn 
1923         if ( m_currentX 
< w 
) 
1926         if (event
.ButtonUp()) 
1929             m_isDragging 
= FALSE
; 
1931             m_owner
->SetColumnWidth( m_column
, m_currentX 
- m_minX 
); 
1938                 m_currentX 
= m_minX 
+ 7; 
1940             // draw in the new location 
1941             if ( m_currentX 
< w 
) 
1945     else // not dragging 
1948         bool hit_border 
= FALSE
; 
1950         // end of the current column 
1953         // find the column where this event occured 
1954         int countCol 
= m_owner
->GetColumnCount(); 
1955         for (int col 
= 0; col 
< countCol
; col
++) 
1957             xpos 
+= m_owner
->GetColumnWidth( col 
); 
1960             if ( (abs(x
-xpos
) < 3) && (y 
< 22) ) 
1962                 // near the column border 
1969                 // inside the column 
1976         if (event
.LeftDown()) 
1980                 m_isDragging 
= TRUE
; 
1987                 wxWindow 
*parent 
= GetParent(); 
1988                 wxListEvent 
le( wxEVT_COMMAND_LIST_COL_CLICK
, parent
->GetId() ); 
1989                 le
.SetEventObject( parent 
); 
1990                 le
.m_col 
= m_column
; 
1991                 parent
->GetEventHandler()->ProcessEvent( le 
); 
1994         else if (event
.Moving()) 
1999                 setCursor 
= m_currentCursor 
== wxSTANDARD_CURSOR
; 
2000                 m_currentCursor 
= m_resizeCursor
; 
2004                 setCursor 
= m_currentCursor 
!= wxSTANDARD_CURSOR
; 
2005                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
2009                 SetCursor(*m_currentCursor
); 
2014 void wxListHeaderWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
2016     m_owner
->SetFocus(); 
2019 //----------------------------------------------------------------------------- 
2020 // wxListRenameTimer (internal) 
2021 //----------------------------------------------------------------------------- 
2023 wxListRenameTimer::wxListRenameTimer( wxListMainWindow 
*owner 
) 
2028 void wxListRenameTimer::Notify() 
2030     m_owner
->OnRenameTimer(); 
2033 //----------------------------------------------------------------------------- 
2034 // wxListTextCtrl (internal) 
2035 //----------------------------------------------------------------------------- 
2037 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
); 
2039 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
) 
2040     EVT_CHAR           (wxListTextCtrl::OnChar
) 
2041     EVT_KEY_UP         (wxListTextCtrl::OnKeyUp
) 
2042     EVT_KILL_FOCUS     (wxListTextCtrl::OnKillFocus
) 
2045 wxListTextCtrl::wxListTextCtrl( wxWindow 
*parent
, 
2046                                 const wxWindowID id
, 
2049                                 wxListMainWindow 
*owner
, 
2050                                 const wxString 
&value
, 
2054                                 const wxValidator
& validator
, 
2055                                 const wxString 
&name 
) 
2056               : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name 
) 
2061     (*m_accept
) = FALSE
; 
2063     m_startValue 
= value
; 
2066 void wxListTextCtrl::OnChar( wxKeyEvent 
&event 
) 
2068     if (event
.m_keyCode 
== WXK_RETURN
) 
2071         (*m_res
) = GetValue(); 
2073         if (!wxPendingDelete
.Member(this)) 
2074             wxPendingDelete
.Append(this); 
2076         if ((*m_accept
) && ((*m_res
) != m_startValue
)) 
2077             m_owner
->OnRenameAccept(); 
2081     if (event
.m_keyCode 
== WXK_ESCAPE
) 
2083         (*m_accept
) = FALSE
; 
2086         if (!wxPendingDelete
.Member(this)) 
2087             wxPendingDelete
.Append(this); 
2095 void wxListTextCtrl::OnKeyUp( wxKeyEvent 
&event 
) 
2097     // auto-grow the textctrl: 
2098     wxSize parentSize 
= m_owner
->GetSize(); 
2099     wxPoint myPos 
= GetPosition(); 
2100     wxSize mySize 
= GetSize(); 
2102     GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); // FIXME: MM?? 
2103     if (myPos
.x 
+ sx 
> parentSize
.x
) 
2104         sx 
= parentSize
.x 
- myPos
.x
; 
2112 void wxListTextCtrl::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
2114     if (!wxPendingDelete
.Member(this)) 
2115         wxPendingDelete
.Append(this); 
2117     if ((*m_accept
) && ((*m_res
) != m_startValue
)) 
2118         m_owner
->OnRenameAccept(); 
2121 //----------------------------------------------------------------------------- 
2123 //----------------------------------------------------------------------------- 
2125 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
); 
2127 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
) 
2128   EVT_PAINT          (wxListMainWindow::OnPaint
) 
2129   EVT_MOUSE_EVENTS   (wxListMainWindow::OnMouse
) 
2130   EVT_CHAR           (wxListMainWindow::OnChar
) 
2131   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown
) 
2132   EVT_SET_FOCUS      (wxListMainWindow::OnSetFocus
) 
2133   EVT_KILL_FOCUS     (wxListMainWindow::OnKillFocus
) 
2134   EVT_SCROLLWIN      (wxListMainWindow::OnScroll
) 
2137 void wxListMainWindow::Init() 
2139     m_columns
.DeleteContents( TRUE 
); 
2143     m_lineTo 
= (size_t)-1; 
2149     m_small_image_list 
= (wxImageList 
*) NULL
; 
2150     m_normal_image_list 
= (wxImageList 
*) NULL
; 
2152     m_small_spacing 
= 30; 
2153     m_normal_spacing 
= 40; 
2157     m_isCreated 
= FALSE
; 
2159     m_lastOnSame 
= FALSE
; 
2160     m_renameTimer 
= new wxListRenameTimer( this ); 
2161     m_renameAccept 
= FALSE
; 
2166     m_lineBeforeLastClicked 
= (size_t)-1; 
2169 void wxListMainWindow::InitScrolling() 
2171     if ( HasFlag(wxLC_REPORT
) ) 
2173         m_xScroll 
= SCROLL_UNIT_X
; 
2174         m_yScroll 
= SCROLL_UNIT_Y
; 
2178         m_xScroll 
= SCROLL_UNIT_Y
; 
2183 wxListMainWindow::wxListMainWindow() 
2188     m_highlightUnfocusedBrush 
= (wxBrush 
*) NULL
; 
2194 wxListMainWindow::wxListMainWindow( wxWindow 
*parent
, 
2199                                     const wxString 
&name 
) 
2200                 : wxScrolledWindow( parent
, id
, pos
, size
, 
2201                                     style 
| wxHSCROLL 
| wxVSCROLL
, name 
) 
2205     m_highlightBrush 
= new wxBrush
 
2207                             wxSystemSettings::GetSystemColour
 
2209                                 wxSYS_COLOUR_HIGHLIGHT
 
2214     m_highlightUnfocusedBrush 
= new wxBrush
 
2216                                        wxSystemSettings::GetSystemColour
 
2218                                            wxSYS_COLOUR_BTNSHADOW
 
2227     SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 ); 
2229     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_LISTBOX 
) ); 
2232 wxListMainWindow::~wxListMainWindow() 
2236     delete m_highlightBrush
; 
2237     delete m_highlightUnfocusedBrush
; 
2239     delete m_renameTimer
; 
2242 void wxListMainWindow::CacheLineData(size_t line
) 
2244     wxListCtrl 
*listctrl 
= GetListCtrl(); 
2246     wxListLineData 
*ld 
= GetDummyLine(); 
2248     size_t countCol 
= GetColumnCount(); 
2249     for ( size_t col 
= 0; col 
< countCol
; col
++ ) 
2251         ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
)); 
2254     ld
->SetImage(listctrl
->OnGetItemImage(line
)); 
2255     ld
->SetAttr(listctrl
->OnGetItemAttr(line
)); 
2258 wxListLineData 
*wxListMainWindow::GetDummyLine() const 
2260     wxASSERT_MSG( !IsEmpty(), _T("invalid line index") ); 
2262     if ( m_lines
.IsEmpty() ) 
2264         // normal controls are supposed to have something in m_lines 
2265         // already if it's not empty 
2266         wxASSERT_MSG( IsVirtual(), _T("logic error") ); 
2268         wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
2269         wxListLineData 
*line 
= new wxListLineData(self
); 
2270         self
->m_lines
.Add(line
); 
2276 // ---------------------------------------------------------------------------- 
2277 // line geometry (report mode only) 
2278 // ---------------------------------------------------------------------------- 
2280 wxCoord 
wxListMainWindow::GetLineHeight() const 
2282     wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") ); 
2284     // we cache the line height as calling GetTextExtent() is slow 
2285     if ( !m_lineHeight 
) 
2287         wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
2289         wxClientDC 
dc( self 
); 
2290         dc
.SetFont( GetFont() ); 
2293         dc
.GetTextExtent(_T("H"), NULL
, &y
); 
2295         if ( y 
< SCROLL_UNIT_Y 
) 
2299         self
->m_lineHeight 
= y 
+ LINE_SPACING
; 
2302     return m_lineHeight
; 
2305 wxCoord 
wxListMainWindow::GetLineY(size_t line
) const 
2307     wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("only works in report mode") ); 
2309     return LINE_SPACING 
+ line
*GetLineHeight(); 
2312 wxRect 
wxListMainWindow::GetLineRect(size_t line
) const 
2314     if ( !InReportView() ) 
2315         return GetLine(line
)->m_gi
->m_rectAll
; 
2318     rect
.x 
= HEADER_OFFSET_X
; 
2319     rect
.y 
= GetLineY(line
); 
2320     rect
.width 
= GetHeaderWidth(); 
2321     rect
.height 
= GetLineHeight(); 
2326 wxRect 
wxListMainWindow::GetLineLabelRect(size_t line
) const 
2328     if ( !InReportView() ) 
2329         return GetLine(line
)->m_gi
->m_rectLabel
; 
2332     rect
.x 
= HEADER_OFFSET_X
; 
2333     rect
.y 
= GetLineY(line
); 
2334     rect
.width 
= GetColumnWidth(0); 
2335     rect
.height 
= GetLineHeight(); 
2340 wxRect 
wxListMainWindow::GetLineIconRect(size_t line
) const 
2342     if ( !InReportView() ) 
2343         return GetLine(line
)->m_gi
->m_rectIcon
; 
2345     wxListLineData 
*ld 
= GetLine(line
); 
2346     wxASSERT_MSG( ld
->HasImage(), _T("should have an image") ); 
2349     rect
.x 
= HEADER_OFFSET_X
; 
2350     rect
.y 
= GetLineY(line
); 
2351     GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
); 
2356 wxRect 
wxListMainWindow::GetLineHighlightRect(size_t line
) const 
2358     return InReportView() ? GetLineRect(line
) 
2359                           : GetLine(line
)->m_gi
->m_rectHighlight
; 
2362 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const 
2364     wxASSERT_MSG( line 
< GetItemCount(), _T("invalid line in HitTestLine") ); 
2366     wxListLineData 
*ld 
= GetLine(line
); 
2368     if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) ) 
2369         return wxLIST_HITTEST_ONITEMICON
; 
2371     if ( ld
->HasText() ) 
2373         wxRect rect 
= InReportView() ? GetLineRect(line
) 
2374                                      : GetLineLabelRect(line
); 
2376         if ( rect
.Inside(x
, y
) ) 
2377             return wxLIST_HITTEST_ONITEMLABEL
; 
2383 // ---------------------------------------------------------------------------- 
2384 // highlight (selection) handling 
2385 // ---------------------------------------------------------------------------- 
2387 bool wxListMainWindow::IsHighlighted(size_t line
) const 
2391         return m_selStore
.IsSelected(line
); 
2395         wxListLineData 
*ld 
= GetLine(line
); 
2396         wxCHECK_MSG( ld
, FALSE
, _T("invalid index in IsHighlighted") ); 
2398         return ld
->IsHighlighted(); 
2402 void wxListMainWindow::HighlightLines( size_t lineFrom
, 
2408         wxArrayInt linesChanged
; 
2409         if ( !m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
, 
2412             // meny items changed state, refresh everything 
2413             RefreshLines(lineFrom
, lineTo
); 
2415         else // only a few items changed state, refresh only them 
2417             size_t count 
= linesChanged
.GetCount(); 
2418             for ( size_t n 
= 0; n 
< count
; n
++ ) 
2420                 RefreshLine(linesChanged
[n
]); 
2424     else // iterate over all items in non report view 
2426         for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
2428             if ( HighlightLine(line
, highlight
) ) 
2436 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight 
) 
2442         changed 
= m_selStore
.SelectItem(line
, highlight
); 
2446         wxListLineData 
*ld 
= GetLine(line
); 
2447         wxCHECK_MSG( ld
, FALSE
, _T("invalid index in HighlightLine") ); 
2449         changed 
= ld
->Highlight(highlight
); 
2454         SendNotify( line
, highlight 
? wxEVT_COMMAND_LIST_ITEM_SELECTED
 
2455                                     : wxEVT_COMMAND_LIST_ITEM_DESELECTED 
); 
2461 void wxListMainWindow::RefreshLine( size_t line 
) 
2463     if ( HasFlag(wxLC_REPORT
) ) 
2465         size_t visibleFrom
, visibleTo
; 
2466         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2468         if ( line 
< visibleFrom 
|| line 
> visibleTo 
) 
2472     wxRect rect 
= GetLineRect(line
); 
2474     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2475     RefreshRect( rect 
); 
2478 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo 
) 
2480     // we suppose that they are ordered by caller 
2481     wxASSERT_MSG( lineFrom 
<= lineTo
, _T("indices in disorder") ); 
2483     wxASSERT_MSG( lineTo 
< GetItemCount(), _T("invalid line range") ); 
2485     if ( HasFlag(wxLC_REPORT
) ) 
2487         size_t visibleFrom
, visibleTo
; 
2488         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2490         if ( lineFrom 
< visibleFrom 
) 
2491             lineFrom 
= visibleFrom
; 
2492         if ( lineTo 
> visibleTo 
) 
2497         rect
.y 
= GetLineY(lineFrom
); 
2498         rect
.width 
= GetClientSize().x
; 
2499         rect
.height 
= GetLineY(lineTo
) - rect
.y 
+ GetLineHeight(); 
2501         CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2502         RefreshRect( rect 
); 
2506         // TODO: this should be optimized... 
2507         for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
2514 void wxListMainWindow::RefreshAfter( size_t lineFrom 
) 
2516     if ( HasFlag(wxLC_REPORT
) ) 
2519         GetVisibleLinesRange(&visibleFrom
, NULL
); 
2521         if ( lineFrom 
< visibleFrom 
) 
2522             lineFrom 
= visibleFrom
; 
2526         rect
.y 
= GetLineY(lineFrom
); 
2528         wxSize size 
= GetClientSize(); 
2529         rect
.width 
= size
.x
; 
2530         // refresh till the bottom of the window 
2531         rect
.height 
= size
.y 
- rect
.y
; 
2533         CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2534         RefreshRect( rect 
); 
2538         // TODO: how to do it more efficiently? 
2543 void wxListMainWindow::RefreshSelected() 
2549     if ( InReportView() ) 
2551         GetVisibleLinesRange(&from
, &to
); 
2556         to 
= GetItemCount() - 1; 
2559     if ( HasCurrent() && m_current 
> from 
&& m_current 
<= to 
) 
2561         RefreshLine(m_current
); 
2564     for ( size_t line 
= from
; line 
<= to
; line
++ ) 
2566         // NB: the test works as expected even if m_current == -1 
2567         if ( line 
!= m_current 
&& IsHighlighted(line
) ) 
2574 void wxListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
2576     // Note: a wxPaintDC must be constructed even if no drawing is 
2577     // done (a Windows requirement). 
2578     wxPaintDC 
dc( this ); 
2582         // empty control. nothing to draw 
2588         // delay the repainting until we calculate all the items positions 
2595     CalcScrolledPosition( 0, 0, &dev_x
, &dev_y 
); 
2599     dc
.SetFont( GetFont() ); 
2601     if ( HasFlag(wxLC_REPORT
) ) 
2603         int lineHeight 
= GetLineHeight(); 
2605         size_t visibleFrom
, visibleTo
; 
2606         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2609         wxCoord xOrig
, yOrig
; 
2610         CalcUnscrolledPosition(0, 0, &xOrig
, &yOrig
); 
2612         // tell the caller cache to cache the data 
2615             wxListEvent 
evCache(wxEVT_COMMAND_LIST_CACHE_HINT
, 
2616                                 GetParent()->GetId()); 
2617             evCache
.SetEventObject( GetParent() ); 
2618             evCache
.m_oldItemIndex 
= visibleFrom
; 
2619             evCache
.m_itemIndex 
= visibleTo
; 
2620             GetParent()->GetEventHandler()->ProcessEvent( evCache 
); 
2623         for ( size_t line 
= visibleFrom
; line 
<= visibleTo
; line
++ ) 
2625             rectLine 
= GetLineRect(line
); 
2627             if ( !IsExposed(rectLine
.x 
- xOrig
, rectLine
.y 
- yOrig
, 
2628                             rectLine
.width
, rectLine
.height
) ) 
2630                 // don't redraw unaffected lines to avoid flicker 
2634             GetLine(line
)->DrawInReportMode( &dc
, 
2636                                              GetLineHighlightRect(line
), 
2637                                              IsHighlighted(line
) ); 
2640         if ( HasFlag(wxLC_HRULES
) ) 
2642             wxPen 
pen(GetRuleColour(), 1, wxSOLID
); 
2643             wxSize clientSize 
= GetClientSize(); 
2645             for ( size_t i 
= visibleFrom
; i 
<= visibleTo
; i
++ ) 
2648                 dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2649                 dc
.DrawLine(0 - dev_x
, i
*lineHeight
, 
2650                             clientSize
.x 
- dev_x
, i
*lineHeight
); 
2653             // Draw last horizontal rule 
2654             if ( visibleTo 
> visibleFrom 
) 
2657                 dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2658                 dc
.DrawLine(0 - dev_x
, m_lineTo
*lineHeight
, 
2659                             clientSize
.x 
- dev_x 
, m_lineTo
*lineHeight 
); 
2663         // Draw vertical rules if required 
2664         if ( HasFlag(wxLC_VRULES
) && !IsEmpty() ) 
2666             wxPen 
pen(GetRuleColour(), 1, wxSOLID
); 
2669             wxRect firstItemRect
; 
2670             wxRect lastItemRect
; 
2671             GetItemRect(0, firstItemRect
); 
2672             GetItemRect(GetItemCount() - 1, lastItemRect
); 
2673             int x 
= firstItemRect
.GetX(); 
2675             dc
.SetBrush(* wxTRANSPARENT_BRUSH
); 
2676             for (col 
= 0; col 
< GetColumnCount(); col
++) 
2678                 int colWidth 
= GetColumnWidth(col
); 
2680                 dc
.DrawLine(x 
- dev_x
, firstItemRect
.GetY() - 1 - dev_y
, 
2681                             x 
- dev_x
, lastItemRect
.GetBottom() + 1 - dev_y
); 
2687         size_t count 
= GetItemCount(); 
2688         for ( size_t i 
= 0; i 
< count
; i
++ ) 
2690             GetLine(i
)->Draw( &dc 
); 
2696         // don't draw rect outline under Max if we already have the background 
2697         // color but under other platforms only draw it if we do: it is a bit 
2698         // silly to draw "focus rect" if we don't have focus! 
2703 #endif // __WXMAC__/!__WXMAC__ 
2705             dc
.SetPen( *wxBLACK_PEN 
); 
2706             dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2707             dc
.DrawRectangle( GetLineHighlightRect(m_current
) ); 
2714 void wxListMainWindow::HighlightAll( bool on 
) 
2716     if ( IsSingleSel() ) 
2718         wxASSERT_MSG( !on
, _T("can't do this in a single sel control") ); 
2720         // we just have one item to turn off 
2721         if ( HasCurrent() && IsHighlighted(m_current
) ) 
2723             HighlightLine(m_current
, FALSE
); 
2724             RefreshLine(m_current
); 
2729         HighlightLines(0, GetItemCount() - 1, on
); 
2733 void wxListMainWindow::SendNotify( size_t line
, 
2734                                    wxEventType command
, 
2737     wxListEvent 
le( command
, GetParent()->GetId() ); 
2738     le
.SetEventObject( GetParent() ); 
2739     le
.m_itemIndex 
= line
; 
2741     // set only for events which have position 
2742     if ( point 
!= wxDefaultPosition 
) 
2743         le
.m_pointDrag 
= point
; 
2745     // don't try to get the line info for virtual list controls: the main 
2746     // program has it anyhow and if we did it would result in accessing all 
2747     // the lines, even those which are not visible now and this is precisely 
2748     // what we're trying to avoid 
2749     if ( !IsVirtual() && (command 
!= wxEVT_COMMAND_LIST_DELETE_ITEM
) ) 
2751         GetLine(line
)->GetItem( 0, le
.m_item 
); 
2753     //else: there may be no more such item 
2755     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2758 void wxListMainWindow::OnFocusLine( size_t WXUNUSED(line
) ) 
2760 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED ); 
2763 void wxListMainWindow::OnUnfocusLine( size_t WXUNUSED(line
) ) 
2765 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED ); 
2768 void wxListMainWindow::EditLabel( long item 
) 
2770     wxCHECK_RET( (item 
>= 0) && ((size_t)item 
< GetItemCount()), 
2771                  wxT("wrong index in wxListCtrl::EditLabel()") ); 
2773     m_currentEdit 
= (size_t)item
; 
2775     wxListEvent 
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() ); 
2776     le
.SetEventObject( GetParent() ); 
2777     le
.m_itemIndex 
= item
; 
2778     wxListLineData 
*data 
= GetLine(m_currentEdit
); 
2779     wxCHECK_RET( data
, _T("invalid index in EditLabel()") ); 
2780     data
->GetItem( 0, le
.m_item 
); 
2781     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2783     if (!le
.IsAllowed()) 
2786     // We have to call this here because the label in question might just have 
2787     // been added and no screen update taken place. 
2791     wxClientDC 
dc(this); 
2794     wxString s 
= data
->GetText(0); 
2795     wxRect rectLabel 
= GetLineLabelRect(m_currentEdit
); 
2797     rectLabel
.x 
= dc
.LogicalToDeviceX( rectLabel
.x 
); 
2798     rectLabel
.y 
= dc
.LogicalToDeviceY( rectLabel
.y 
); 
2800     wxListTextCtrl 
*text 
= new wxListTextCtrl
 
2807                                 wxPoint(rectLabel
.x
-4,rectLabel
.y
-4), 
2808                                 wxSize(rectLabel
.width
+11,rectLabel
.height
+8) 
2813 void wxListMainWindow::OnRenameTimer() 
2815     wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") ); 
2817     EditLabel( m_current 
); 
2820 void wxListMainWindow::OnRenameAccept() 
2822     wxListEvent 
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() ); 
2823     le
.SetEventObject( GetParent() ); 
2824     le
.m_itemIndex 
= m_currentEdit
; 
2826     wxListLineData 
*data 
= GetLine(m_currentEdit
); 
2827     wxCHECK_RET( data
, _T("invalid index in OnRenameAccept()") ); 
2829     data
->GetItem( 0, le
.m_item 
); 
2830     le
.m_item
.m_text 
= m_renameRes
; 
2831     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2833     if (!le
.IsAllowed()) return; 
2836     info
.m_mask 
= wxLIST_MASK_TEXT
; 
2837     info
.m_itemId 
= le
.m_itemIndex
; 
2838     info
.m_text 
= m_renameRes
; 
2839     info
.SetTextColour(le
.m_item
.GetTextColour()); 
2843 void wxListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
2845     event
.SetEventObject( GetParent() ); 
2846     if ( GetParent()->GetEventHandler()->ProcessEvent( event
) ) 
2849     if ( !HasCurrent() || IsEmpty() ) 
2855     if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() || 
2856         event
.ButtonDClick()) ) 
2859     int x 
= event
.GetX(); 
2860     int y 
= event
.GetY(); 
2861     CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2863     // where did we hit it (if we did)? 
2866     size_t count 
= GetItemCount(), 
2869     if ( HasFlag(wxLC_REPORT
) ) 
2871         current 
= y 
/ GetLineHeight(); 
2872         if ( current 
< count 
) 
2873             hitResult 
= HitTestLine(current
, x
, y
); 
2877         // TODO: optimize it too! this is less simple than for report view but 
2878         //       enumerating all items is still not a way to do it!! 
2879         for ( current 
= 0; current 
< count
; current
++ ) 
2881             hitResult 
= HitTestLine(current
, x
, y
); 
2887     if (event
.Dragging()) 
2889         if (m_dragCount 
== 0) 
2890             m_dragStart 
= wxPoint(x
,y
); 
2894         if (m_dragCount 
!= 3) 
2897         int command 
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
 
2898                                           : wxEVT_COMMAND_LIST_BEGIN_DRAG
; 
2900         wxListEvent 
le( command
, GetParent()->GetId() ); 
2901         le
.SetEventObject( GetParent() ); 
2902         le
.m_pointDrag 
= m_dragStart
; 
2903         GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2914         // outside of any item 
2918     bool forceClick 
= FALSE
; 
2919     if (event
.ButtonDClick()) 
2921         m_renameTimer
->Stop(); 
2922         m_lastOnSame 
= FALSE
; 
2924         if ( current 
== m_lineBeforeLastClicked 
) 
2926             SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
2932             // the first click was on another item, so don't interpret this as 
2933             // a double click, but as a simple click instead 
2938     if (event
.LeftUp() && m_lastOnSame
) 
2940         if ((current 
== m_current
) && 
2941             (hitResult 
== wxLIST_HITTEST_ONITEMLABEL
) && 
2942             HasFlag(wxLC_EDIT_LABELS
)  ) 
2944             m_renameTimer
->Start( 100, TRUE 
); 
2946         m_lastOnSame 
= FALSE
; 
2948     else if (event
.RightDown()) 
2950         SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
, 
2951                     event
.GetPosition() ); 
2953     else if (event
.MiddleDown()) 
2955         SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK 
); 
2957     else if ( event
.LeftDown() || forceClick 
) 
2959         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2960         m_lineLastClicked 
= current
; 
2962         size_t oldCurrent 
= m_current
; 
2964         if ( IsSingleSel() || !(event
.ControlDown() || event
.ShiftDown()) ) 
2966             HighlightAll( FALSE 
); 
2967             m_current 
= current
; 
2969             ReverseHighlight(m_current
); 
2971         else // multi sel & either ctrl or shift is down 
2973             if (event
.ControlDown()) 
2975                 m_current 
= current
; 
2977                 ReverseHighlight(m_current
); 
2979             else if (event
.ShiftDown()) 
2981                 m_current 
= current
; 
2983                 size_t lineFrom 
= oldCurrent
, 
2986                 if ( lineTo 
< lineFrom 
) 
2989                     lineFrom 
= m_current
; 
2992                 HighlightLines(lineFrom
, lineTo
); 
2994             else // !ctrl, !shift 
2996                 // test in the enclosing if should make it impossible 
2997                 wxFAIL_MSG( _T("how did we get here?") ); 
3001         if (m_current 
!= oldCurrent
) 
3003             RefreshLine( oldCurrent 
); 
3004             OnUnfocusLine( oldCurrent 
); 
3005             OnFocusLine( m_current 
); 
3008         // forceClick is only set if the previous click was on another item 
3009         m_lastOnSame 
= !forceClick 
&& (m_current 
== oldCurrent
); 
3013 void wxListMainWindow::MoveToItem(size_t item
) 
3015     if ( item 
== (size_t)-1 ) 
3018     wxRect rect 
= GetLineRect(item
); 
3020     int client_w
, client_h
; 
3021     GetClientSize( &client_w
, &client_h 
); 
3023     int view_x 
= m_xScroll
*GetScrollPos( wxHORIZONTAL 
); 
3024     int view_y 
= m_yScroll
*GetScrollPos( wxVERTICAL 
); 
3026     if ( HasFlag(wxLC_REPORT
) ) 
3028         // the next we need the range of lines shown it might be different, so 
3030         ResetVisibleLinesRange(); 
3032         if (rect
.y 
< view_y 
) 
3033             Scroll( -1, rect
.y
/m_yScroll 
); 
3034         if (rect
.y
+rect
.height
+5 > view_y
+client_h
) 
3035             Scroll( -1, (rect
.y
+rect
.height
-client_h
+SCROLL_UNIT_Y
)/m_yScroll 
); 
3039         if (rect
.x
-view_x 
< 5) 
3040             Scroll( (rect
.x
-5)/m_xScroll
, -1 ); 
3041         if (rect
.x
+rect
.width
-5 > view_x
+client_w
) 
3042             Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/m_xScroll
, -1 ); 
3046 // ---------------------------------------------------------------------------- 
3047 // keyboard handling 
3048 // ---------------------------------------------------------------------------- 
3050 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
) 
3052     wxCHECK_RET( newCurrent 
< (size_t)GetItemCount(), 
3053                  _T("invalid item index in OnArrowChar()") ); 
3055     size_t oldCurrent 
= m_current
; 
3057     // in single selection we just ignore Shift as we can't select several 
3059     if ( event
.ShiftDown() && !IsSingleSel() ) 
3061         m_current 
= newCurrent
; 
3063         // select all the items between the old and the new one 
3064         if ( oldCurrent 
> newCurrent 
) 
3066             newCurrent 
= oldCurrent
; 
3067             oldCurrent 
= m_current
; 
3070         HighlightLines(oldCurrent
, newCurrent
); 
3074         // all previously selected items are unselected unless ctrl is held 
3075         if ( !event
.ControlDown() ) 
3076             HighlightAll(FALSE
); 
3078         m_current 
= newCurrent
; 
3080         HighlightLine( oldCurrent
, FALSE 
); 
3081         RefreshLine( oldCurrent 
); 
3083         if ( !event
.ControlDown() ) 
3085             HighlightLine( m_current
, TRUE 
); 
3089     OnUnfocusLine( oldCurrent 
); 
3090     OnFocusLine( m_current 
); 
3091     RefreshLine( m_current 
); 
3096 void wxListMainWindow::OnKeyDown( wxKeyEvent 
&event 
) 
3098     wxWindow 
*parent 
= GetParent(); 
3100     /* we propagate the key event up */ 
3101     wxKeyEvent 
ke( wxEVT_KEY_DOWN 
); 
3102     ke
.m_shiftDown 
= event
.m_shiftDown
; 
3103     ke
.m_controlDown 
= event
.m_controlDown
; 
3104     ke
.m_altDown 
= event
.m_altDown
; 
3105     ke
.m_metaDown 
= event
.m_metaDown
; 
3106     ke
.m_keyCode 
= event
.m_keyCode
; 
3109     ke
.SetEventObject( parent 
); 
3110     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
3115 void wxListMainWindow::OnChar( wxKeyEvent 
&event 
) 
3117     wxWindow 
*parent 
= GetParent(); 
3119     /* we send a list_key event up */ 
3122         wxListEvent 
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() ); 
3123         le
.m_itemIndex 
= m_current
; 
3124         GetLine(m_current
)->GetItem( 0, le
.m_item 
); 
3125         le
.m_code 
= (int)event
.KeyCode(); 
3126         le
.SetEventObject( parent 
); 
3127         parent
->GetEventHandler()->ProcessEvent( le 
); 
3130     /* we propagate the char event up */ 
3131     wxKeyEvent 
ke( wxEVT_CHAR 
); 
3132     ke
.m_shiftDown 
= event
.m_shiftDown
; 
3133     ke
.m_controlDown 
= event
.m_controlDown
; 
3134     ke
.m_altDown 
= event
.m_altDown
; 
3135     ke
.m_metaDown 
= event
.m_metaDown
; 
3136     ke
.m_keyCode 
= event
.m_keyCode
; 
3139     ke
.SetEventObject( parent 
); 
3140     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
3142     if (event
.KeyCode() == WXK_TAB
) 
3144         wxNavigationKeyEvent nevent
; 
3145         nevent
.SetWindowChange( event
.ControlDown() ); 
3146         nevent
.SetDirection( !event
.ShiftDown() ); 
3147         nevent
.SetEventObject( GetParent()->GetParent() ); 
3148         nevent
.SetCurrentFocus( m_parent 
); 
3149         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) return; 
3152     /* no item -> nothing to do */ 
3159     switch (event
.KeyCode()) 
3162             if ( m_current 
> 0 ) 
3163                 OnArrowChar( m_current 
- 1, event 
); 
3167             if ( m_current 
< (size_t)GetItemCount() - 1 ) 
3168                 OnArrowChar( m_current 
+ 1, event 
); 
3173                 OnArrowChar( GetItemCount() - 1, event 
); 
3178                 OnArrowChar( 0, event 
); 
3184                 if ( HasFlag(wxLC_REPORT
) ) 
3186                     steps 
= m_linesPerPage 
- 1; 
3190                     steps 
= m_current 
% m_linesPerPage
; 
3193                 int index 
= m_current 
- steps
; 
3197                 OnArrowChar( index
, event 
); 
3204                 if ( HasFlag(wxLC_REPORT
) ) 
3206                     steps 
= m_linesPerPage 
- 1; 
3210                     steps 
= m_linesPerPage 
- (m_current 
% m_linesPerPage
) - 1; 
3213                 size_t index 
= m_current 
+ steps
; 
3214                 size_t count 
= GetItemCount(); 
3215                 if ( index 
>= count 
) 
3218                 OnArrowChar( index
, event 
); 
3223             if ( !HasFlag(wxLC_REPORT
) ) 
3225                 int index 
= m_current 
- m_linesPerPage
; 
3229                 OnArrowChar( index
, event 
); 
3234             if ( !HasFlag(wxLC_REPORT
) ) 
3236                 size_t index 
= m_current 
+ m_linesPerPage
; 
3238                 size_t count 
= GetItemCount(); 
3239                 if ( index 
>= count 
) 
3242                 OnArrowChar( index
, event 
); 
3247             if ( IsSingleSel() ) 
3249                 wxListEvent 
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
, 
3250                                 GetParent()->GetId() ); 
3251                 le
.SetEventObject( GetParent() ); 
3252                 le
.m_itemIndex 
= m_current
; 
3253                 GetLine(m_current
)->GetItem( 0, le
.m_item 
); 
3254                 GetParent()->GetEventHandler()->ProcessEvent( le 
); 
3256                 if ( IsHighlighted(m_current
) ) 
3258                     // don't unselect the item in single selection mode 
3261                 //else: select it in ReverseHighlight() below if unselected 
3264             ReverseHighlight(m_current
); 
3270                 wxListEvent 
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
, 
3271                                 GetParent()->GetId() ); 
3272                 le
.SetEventObject( GetParent() ); 
3273                 le
.m_itemIndex 
= m_current
; 
3274                 GetLine(m_current
)->GetItem( 0, le
.m_item 
); 
3275                 GetParent()->GetEventHandler()->ProcessEvent( le 
); 
3284 // ---------------------------------------------------------------------------- 
3286 // ---------------------------------------------------------------------------- 
3289 extern wxWindow 
*g_focusWindow
; 
3292 void wxListMainWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
3302     g_focusWindow 
= GetParent(); 
3305     wxFocusEvent 
event( wxEVT_SET_FOCUS
, GetParent()->GetId() ); 
3306     event
.SetEventObject( GetParent() ); 
3307     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
3310 void wxListMainWindow::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
3317 void wxListMainWindow::DrawImage( int index
, wxDC 
*dc
, int x
, int y 
) 
3319     if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
)) 
3321         m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3323     else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
)) 
3325         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3327     else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
)) 
3329         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3331     else if ( HasFlag(wxLC_REPORT
) && (m_small_image_list
)) 
3333         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3337 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height 
) const 
3339     if ( HasFlag(wxLC_ICON
) && m_normal_image_list 
) 
3341         m_normal_image_list
->GetSize( index
, width
, height 
); 
3343     else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list 
) 
3345         m_small_image_list
->GetSize( index
, width
, height 
); 
3347     else if ( HasFlag(wxLC_LIST
) && m_small_image_list 
) 
3349         m_small_image_list
->GetSize( index
, width
, height 
); 
3351     else if ( HasFlag(wxLC_REPORT
) && m_small_image_list 
) 
3353         m_small_image_list
->GetSize( index
, width
, height 
); 
3362 int wxListMainWindow::GetTextLength( const wxString 
&s 
) const 
3364     wxClientDC 
dc( wxConstCast(this, wxListMainWindow
) ); 
3365     dc
.SetFont( GetFont() ); 
3368     dc
.GetTextExtent( s
, &lw
, NULL 
); 
3370     return lw 
+ AUTOSIZE_COL_MARGIN
; 
3373 void wxListMainWindow::SetImageList( wxImageList 
*imageList
, int which 
) 
3377     // calc the spacing from the icon size 
3380     if ((imageList
) && (imageList
->GetImageCount()) ) 
3382         imageList
->GetSize(0, width
, height
); 
3385     if (which 
== wxIMAGE_LIST_NORMAL
) 
3387         m_normal_image_list 
= imageList
; 
3388         m_normal_spacing 
= width 
+ 8; 
3391     if (which 
== wxIMAGE_LIST_SMALL
) 
3393         m_small_image_list 
= imageList
; 
3394         m_small_spacing 
= width 
+ 14; 
3398 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall 
) 
3403         m_small_spacing 
= spacing
; 
3407         m_normal_spacing 
= spacing
; 
3411 int wxListMainWindow::GetItemSpacing( bool isSmall 
) 
3413     return isSmall 
? m_small_spacing 
: m_normal_spacing
; 
3416 // ---------------------------------------------------------------------------- 
3418 // ---------------------------------------------------------------------------- 
3420 void wxListMainWindow::SetColumn( int col
, wxListItem 
&item 
) 
3422     wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
3424     wxCHECK_RET( node
, _T("invalid column index in SetColumn") ); 
3426     if ( item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER 
) 
3427         item
.m_width 
= GetTextLength( item
.m_text 
); 
3429     wxListHeaderData 
*column 
= node
->GetData(); 
3430     column
->SetItem( item 
); 
3432     wxListHeaderWindow 
*headerWin 
= GetListCtrl()->m_headerWin
; 
3434         headerWin
->m_dirty 
= TRUE
; 
3438     // invalidate it as it has to be recalculated 
3442 void wxListMainWindow::SetColumnWidth( int col
, int width 
) 
3444     wxCHECK_RET( col 
>= 0 && col 
< GetColumnCount(), 
3445                  _T("invalid column index") ); 
3447     wxCHECK_RET( HasFlag(wxLC_REPORT
), 
3448                  _T("SetColumnWidth() can only be called in report mode.") ); 
3452     wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
3453     wxCHECK_RET( node
, _T("no column?") ); 
3455     wxListHeaderData 
*column 
= node
->GetData(); 
3457     size_t count 
= GetItemCount(); 
3459     if (width 
== wxLIST_AUTOSIZE_USEHEADER
) 
3461         width 
= GetTextLength(column
->GetText()); 
3463     else if ( width 
== wxLIST_AUTOSIZE 
) 
3467             // TODO: determine the max width somehow... 
3468             width 
= WIDTH_COL_DEFAULT
; 
3472             wxClientDC 
dc(this); 
3473             dc
.SetFont( GetFont() ); 
3475             int max 
= AUTOSIZE_COL_MARGIN
; 
3477             for ( size_t i 
= 0; i 
< count
; i
++ ) 
3479                 wxListLineData 
*line 
= GetLine(i
); 
3480                 wxListItemDataList::Node 
*n 
= line
->m_items
.Item( col 
); 
3482                 wxCHECK_RET( n
, _T("no subitem?") ); 
3484                 wxListItemData 
*item 
= n
->GetData(); 
3487                 if (item
->HasImage()) 
3490                     GetImageSize( item
->GetImage(), ix
, iy 
); 
3494                 if (item
->HasText()) 
3497                     dc
.GetTextExtent( item
->GetText(), &w
, NULL 
); 
3505             width 
= max 
+ AUTOSIZE_COL_MARGIN
; 
3509     column
->SetWidth( width 
); 
3511     // invalidate it as it has to be recalculated 
3515 int wxListMainWindow::GetHeaderWidth() const 
3517     if ( !m_headerWidth 
) 
3519         wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
3521         size_t count 
= GetColumnCount(); 
3522         for ( size_t col 
= 0; col 
< count
; col
++ ) 
3524             self
->m_headerWidth 
+= GetColumnWidth(col
); 
3528     return m_headerWidth
; 
3531 void wxListMainWindow::GetColumn( int col
, wxListItem 
&item 
) const 
3533     wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
3534     wxCHECK_RET( node
, _T("invalid column index in GetColumn") ); 
3536     wxListHeaderData 
*column 
= node
->GetData(); 
3537     column
->GetItem( item 
); 
3540 int wxListMainWindow::GetColumnWidth( int col 
) const 
3542     wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
3543     wxCHECK_MSG( node
, 0, _T("invalid column index") ); 
3545     wxListHeaderData 
*column 
= node
->GetData(); 
3546     return column
->GetWidth(); 
3549 // ---------------------------------------------------------------------------- 
3551 // ---------------------------------------------------------------------------- 
3553 void wxListMainWindow::SetItem( wxListItem 
&item 
) 
3555     long id 
= item
.m_itemId
; 
3556     wxCHECK_RET( id 
>= 0 && (size_t)id 
< GetItemCount(), 
3557                  _T("invalid item index in SetItem") ); 
3561         wxListLineData 
*line 
= GetLine((size_t)id
); 
3562         line
->SetItem( item
.m_col
, item 
); 
3565     if ( InReportView() ) 
3567         // just refresh the line to show the new value of the text/image 
3568         RefreshLine((size_t)id
); 
3572         // refresh everything (resulting in horrible flicker - FIXME!) 
3577 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask 
) 
3579      wxCHECK_RET( litem 
>= 0 && (size_t)litem 
< GetItemCount(), 
3580                   _T("invalid list ctrl item index in SetItem") ); 
3582     size_t oldCurrent 
= m_current
; 
3583     size_t item 
= (size_t)litem
;    // safe because of the check above 
3585     // do we need to change the focus? 
3586     if ( stateMask 
& wxLIST_STATE_FOCUSED 
) 
3588         if ( state 
& wxLIST_STATE_FOCUSED 
) 
3590             // don't do anything if this item is already focused 
3591             if ( item 
!= m_current 
) 
3593                 OnUnfocusLine( m_current 
); 
3595                 OnFocusLine( m_current 
); 
3597                 if ( oldCurrent 
!= (size_t)-1 ) 
3599                     if ( IsSingleSel() ) 
3601                         HighlightLine(oldCurrent
, FALSE
); 
3604                     RefreshLine(oldCurrent
); 
3607                 RefreshLine( m_current 
); 
3612             // don't do anything if this item is not focused 
3613             if ( item 
== m_current 
) 
3615                 OnUnfocusLine( m_current 
); 
3616                 m_current 
= (size_t)-1; 
3618                 RefreshLine( oldCurrent 
); 
3623     // do we need to change the selection state? 
3624     if ( stateMask 
& wxLIST_STATE_SELECTED 
) 
3626         bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
3628         if ( IsSingleSel() ) 
3632                 // selecting the item also makes it the focused one in the 
3634                 if ( m_current 
!= item 
) 
3636                     OnUnfocusLine( m_current 
); 
3638                     OnFocusLine( m_current 
); 
3640                     if ( oldCurrent 
!= (size_t)-1 ) 
3642                         HighlightLine( oldCurrent
, FALSE 
); 
3643                         RefreshLine( oldCurrent 
); 
3649                 // only the current item may be selected anyhow 
3650                 if ( item 
!= m_current 
) 
3655         if ( HighlightLine(item
, on
) ) 
3662 int wxListMainWindow::GetItemState( long item
, long stateMask 
) 
3664     wxCHECK_MSG( item 
>= 0 && (size_t)item 
< GetItemCount(), 0, 
3665                  _T("invalid list ctrl item index in GetItemState()") ); 
3667     int ret 
= wxLIST_STATE_DONTCARE
; 
3669     if ( stateMask 
& wxLIST_STATE_FOCUSED 
) 
3671         if ( (size_t)item 
== m_current 
) 
3672             ret 
|= wxLIST_STATE_FOCUSED
; 
3675     if ( stateMask 
& wxLIST_STATE_SELECTED 
) 
3677         if ( IsHighlighted(item
) ) 
3678             ret 
|= wxLIST_STATE_SELECTED
; 
3684 void wxListMainWindow::GetItem( wxListItem 
&item 
) 
3686     wxCHECK_RET( item
.m_itemId 
>= 0 && (size_t)item
.m_itemId 
< GetItemCount(), 
3687                  _T("invalid item index in GetItem") ); 
3689     wxListLineData 
*line 
= GetLine((size_t)item
.m_itemId
); 
3690     line
->GetItem( item
.m_col
, item 
); 
3693 // ---------------------------------------------------------------------------- 
3695 // ---------------------------------------------------------------------------- 
3697 size_t wxListMainWindow::GetItemCount() const 
3699     return IsVirtual() ? m_countVirt 
: m_lines
.GetCount(); 
3702 void wxListMainWindow::SetItemCount(long count
) 
3704     m_selStore
.SetItemCount(count
); 
3705     m_countVirt 
= count
; 
3707     ResetVisibleLinesRange(); 
3709     // scrollbars must be reset 
3713 int wxListMainWindow::GetSelectedItemCount() 
3715     // deal with the quick case first 
3716     if ( IsSingleSel() ) 
3718         return HasCurrent() ? IsHighlighted(m_current
) : FALSE
; 
3721     // virtual controls remmebers all its selections itself 
3723         return m_selStore
.GetSelectedCount(); 
3725     // TODO: we probably should maintain the number of items selected even for 
3726     //       non virtual controls as enumerating all lines is really slow... 
3727     size_t countSel 
= 0; 
3728     size_t count 
= GetItemCount(); 
3729     for ( size_t line 
= 0; line 
< count
; line
++ ) 
3731         if ( GetLine(line
)->IsHighlighted() ) 
3738 // ---------------------------------------------------------------------------- 
3739 // item position/size 
3740 // ---------------------------------------------------------------------------- 
3742 void wxListMainWindow::GetItemRect( long index
, wxRect 
&rect 
) 
3744     wxCHECK_RET( index 
>= 0 && (size_t)index 
< GetItemCount(), 
3745                  _T("invalid index in GetItemRect") ); 
3747     rect 
= GetLineRect((size_t)index
); 
3749     CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
); 
3752 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
) 
3755     GetItemRect(item
, rect
); 
3763 // ---------------------------------------------------------------------------- 
3764 // geometry calculation 
3765 // ---------------------------------------------------------------------------- 
3767 void wxListMainWindow::RecalculatePositions(bool noRefresh
) 
3769     wxClientDC 
dc( this ); 
3770     dc
.SetFont( GetFont() ); 
3773     if ( HasFlag(wxLC_ICON
) ) 
3774         iconSpacing 
= m_normal_spacing
; 
3775     else if ( HasFlag(wxLC_SMALL_ICON
) ) 
3776         iconSpacing 
= m_small_spacing
; 
3782     GetClientSize( &clientWidth
, &clientHeight 
); 
3784     if ( HasFlag(wxLC_REPORT
) ) 
3786         // all lines have the same height 
3787         int lineHeight 
= GetLineHeight(); 
3789         // scroll one line per step 
3790         m_yScroll 
= lineHeight
; 
3792         size_t lineCount 
= GetItemCount(); 
3793         int entireHeight 
= lineCount
*lineHeight 
+ LINE_SPACING
; 
3795         m_linesPerPage 
= clientHeight 
/ lineHeight
; 
3797         ResetVisibleLinesRange(); 
3799         SetScrollbars( m_xScroll
, m_yScroll
, 
3800                        (GetHeaderWidth() + m_xScroll 
- 1)/m_xScroll
, 
3801                        (entireHeight 
+ m_yScroll 
- 1)/m_yScroll
, 
3802                        GetScrollPos(wxHORIZONTAL
), 
3803                        GetScrollPos(wxVERTICAL
), 
3808         // at first we try without any scrollbar. if the items don't 
3809         // fit into the window, we recalculate after subtracting an 
3810         // approximated 15 pt for the horizontal scrollbar 
3812         clientHeight 
-= 4;  // sunken frame 
3814         int entireWidth 
= 0; 
3816         for (int tries 
= 0; tries 
< 2; tries
++) 
3823             int currentlyVisibleLines 
= 0; 
3825             size_t count 
= GetItemCount(); 
3826             for (size_t i 
= 0; i 
< count
; i
++) 
3828                 currentlyVisibleLines
++; 
3829                 wxListLineData 
*line 
= GetLine(i
); 
3830                 line
->CalculateSize( &dc
, iconSpacing 
); 
3831                 line
->SetPosition( x
, y
, clientWidth
, iconSpacing 
); 
3833                 wxSize sizeLine 
= GetLineSize(i
); 
3835                 if ( maxWidth 
< sizeLine
.x 
) 
3836                     maxWidth 
= sizeLine
.x
; 
3839                 if (currentlyVisibleLines 
> m_linesPerPage
) 
3840                     m_linesPerPage 
= currentlyVisibleLines
; 
3842                 // assume that the size of the next one is the same... (FIXME) 
3843                 if ( y 
+ sizeLine
.y 
- 6 >= clientHeight 
) 
3845                     currentlyVisibleLines 
= 0; 
3848                     entireWidth 
+= maxWidth
+6; 
3851                 if ( i 
== count 
- 1 ) 
3852                     entireWidth 
+= maxWidth
; 
3853                 if ((tries 
== 0) && (entireWidth 
> clientWidth
)) 
3855                     clientHeight 
-= 15; // scrollbar height 
3857                     currentlyVisibleLines 
= 0; 
3860                 if ( i 
== count 
- 1 ) 
3861                     tries 
= 1;  // everything fits, no second try required 
3865         int scroll_pos 
= GetScrollPos( wxHORIZONTAL 
); 
3866         SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+SCROLL_UNIT_X
) / m_xScroll
, 0, scroll_pos
, 0, TRUE 
); 
3871         // FIXME: why should we call it from here? 
3878 void wxListMainWindow::RefreshAll() 
3883     wxListHeaderWindow 
*headerWin 
= GetListCtrl()->m_headerWin
; 
3884     if ( headerWin 
&& headerWin
->m_dirty 
) 
3886         headerWin
->m_dirty 
= FALSE
; 
3887         headerWin
->Refresh(); 
3891 void wxListMainWindow::UpdateCurrent() 
3893     if ( !HasCurrent() && !IsEmpty() ) 
3898     if ( m_current 
!= (size_t)-1 ) 
3900         OnFocusLine( m_current 
); 
3904 long wxListMainWindow::GetNextItem( long item
, 
3905                                     int WXUNUSED(geometry
), 
3909          max 
= GetItemCount(); 
3910     wxCHECK_MSG( (ret 
== -1) || (ret 
< max
), -1, 
3911                  _T("invalid listctrl index in GetNextItem()") ); 
3913     // notice that we start with the next item (or the first one if item == -1) 
3914     // and this is intentional to allow writing a simple loop to iterate over 
3915     // all selected items 
3919         // this is not an error because the index was ok initially, just no 
3930     size_t count 
= GetItemCount(); 
3931     for ( size_t line 
= (size_t)ret
; line 
< count
; line
++ ) 
3933         if ( (state 
& wxLIST_STATE_FOCUSED
) && (line 
== m_current
) ) 
3936         if ( (state 
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) ) 
3943 // ---------------------------------------------------------------------------- 
3945 // ---------------------------------------------------------------------------- 
3947 void wxListMainWindow::DeleteItem( long lindex 
) 
3949     size_t count 
= GetItemCount(); 
3951     wxCHECK_RET( (lindex 
>= 0) && ((size_t)lindex 
< count
), 
3952                  _T("invalid item index in DeleteItem") ); 
3954     size_t index 
= (size_t)lindex
; 
3956     // we don't need to adjust the index for the previous items 
3957     if ( HasCurrent() && m_current 
>= index 
) 
3959         // if the current item is being deleted, we want the next one to 
3960         // become selected - unless there is no next one - so don't adjust 
3961         // m_current in this case 
3962         if ( m_current 
!= index 
|| m_current 
== count 
- 1 ) 
3968     if ( InReportView() ) 
3970         ResetVisibleLinesRange(); 
3977         m_selStore
.OnItemDelete(index
); 
3981         m_lines
.RemoveAt( index 
); 
3984     // we need to refresh the (vert) scrollbar as the number of items changed 
3987     SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM 
); 
3989     RefreshAfter(index
); 
3992 void wxListMainWindow::DeleteColumn( int col 
) 
3994     wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
3996     wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") ); 
3999     m_columns
.DeleteNode( node 
); 
4002 void wxListMainWindow::DoDeleteAllItems() 
4006         // nothing to do - in particular, don't send the event 
4012     // to make the deletion of all items faster, we don't send the 
4013     // notifications for each item deletion in this case but only one event 
4014     // for all of them: this is compatible with wxMSW and documented in 
4015     // DeleteAllItems() description 
4017     wxListEvent 
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() ); 
4018     event
.SetEventObject( GetParent() ); 
4019     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
4028     if ( InReportView() ) 
4030         ResetVisibleLinesRange(); 
4036 void wxListMainWindow::DeleteAllItems() 
4040     RecalculatePositions(); 
4043 void wxListMainWindow::DeleteEverything() 
4050 // ---------------------------------------------------------------------------- 
4051 // scanning for an item 
4052 // ---------------------------------------------------------------------------- 
4054 void wxListMainWindow::EnsureVisible( long index 
) 
4056     wxCHECK_RET( index 
>= 0 && (size_t)index 
< GetItemCount(), 
4057                  _T("invalid index in EnsureVisible") ); 
4059     // We have to call this here because the label in question might just have 
4060     // been added and its position is not known yet 
4063         RecalculatePositions(TRUE 
/* no refresh */); 
4066     MoveToItem((size_t)index
); 
4069 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) ) 
4076     size_t count 
= GetItemCount(); 
4077     for ( size_t i 
= (size_t)pos
; i 
< count
; i
++ ) 
4079         wxListLineData 
*line 
= GetLine(i
); 
4080         if ( line
->GetText(0) == tmp 
) 
4087 long wxListMainWindow::FindItem(long start
, long data
) 
4093     size_t count 
= GetItemCount(); 
4094     for (size_t i 
= (size_t)pos
; i 
< count
; i
++) 
4096         wxListLineData 
*line 
= GetLine(i
); 
4098         line
->GetItem( 0, item 
); 
4099         if (item
.m_data 
== data
) 
4106 long wxListMainWindow::HitTest( int x
, int y
, int &flags 
) 
4108     CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
4110     size_t count 
= GetItemCount(); 
4112     if ( HasFlag(wxLC_REPORT
) ) 
4114         size_t current 
= y 
/ GetLineHeight(); 
4115         if ( current 
< count 
) 
4117             flags 
= HitTestLine(current
, x
, y
); 
4124         // TODO: optimize it too! this is less simple than for report view but 
4125         //       enumerating all items is still not a way to do it!! 
4126         for ( size_t current 
= 0; current 
< count
; current
++ ) 
4128             flags 
= HitTestLine(current
, x
, y
); 
4137 // ---------------------------------------------------------------------------- 
4139 // ---------------------------------------------------------------------------- 
4141 void wxListMainWindow::InsertItem( wxListItem 
&item 
) 
4143     wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") ); 
4145     size_t count 
= GetItemCount(); 
4146     wxCHECK_RET( item
.m_itemId 
>= 0 && (size_t)item
.m_itemId 
<= count
, 
4147                  _T("invalid item index") ); 
4149     size_t id 
= item
.m_itemId
; 
4154     if ( HasFlag(wxLC_REPORT
) ) 
4156     else if ( HasFlag(wxLC_LIST
) ) 
4158     else if ( HasFlag(wxLC_ICON
) ) 
4160     else if ( HasFlag(wxLC_SMALL_ICON
) ) 
4161         mode 
= wxLC_ICON
;  // no typo 
4164         wxFAIL_MSG( _T("unknown mode") ); 
4167     wxListLineData 
*line 
= new wxListLineData(this); 
4169     line
->SetItem( 0, item 
); 
4171     m_lines
.Insert( line
, id 
); 
4174     RefreshLines(id
, GetItemCount() - 1); 
4177 void wxListMainWindow::InsertColumn( long col
, wxListItem 
&item 
) 
4180     if ( HasFlag(wxLC_REPORT
) ) 
4182         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) 
4183             item
.m_width 
= GetTextLength( item
.m_text 
); 
4184         wxListHeaderData 
*column 
= new wxListHeaderData( item 
); 
4185         if ((col 
>= 0) && (col 
< (int)m_columns
.GetCount())) 
4187             wxListHeaderDataList::Node 
*node 
= m_columns
.Item( col 
); 
4188             m_columns
.Insert( node
, column 
); 
4192             m_columns
.Append( column 
); 
4197 // ---------------------------------------------------------------------------- 
4199 // ---------------------------------------------------------------------------- 
4201 wxListCtrlCompare list_ctrl_compare_func_2
; 
4202 long              list_ctrl_compare_data
; 
4204 int LINKAGEMODE 
list_ctrl_compare_func_1( wxListLineData 
**arg1
, wxListLineData 
**arg2 
) 
4206     wxListLineData 
*line1 
= *arg1
; 
4207     wxListLineData 
*line2 
= *arg2
; 
4209     line1
->GetItem( 0, item 
); 
4210     long data1 
= item
.m_data
; 
4211     line2
->GetItem( 0, item 
); 
4212     long data2 
= item
.m_data
; 
4213     return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data 
); 
4216 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data 
) 
4218     list_ctrl_compare_func_2 
= fn
; 
4219     list_ctrl_compare_data 
= data
; 
4220     m_lines
.Sort( list_ctrl_compare_func_1 
); 
4224 // ---------------------------------------------------------------------------- 
4226 // ---------------------------------------------------------------------------- 
4228 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
4230     // update our idea of which lines are shown when we redraw the window the 
4232     ResetVisibleLinesRange(); 
4235 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) 
4236     wxScrolledWindow::OnScroll(event
); 
4238     HandleOnScroll( event 
); 
4241     if ( event
.GetOrientation() == wxHORIZONTAL 
&& HasHeader() ) 
4243         wxListCtrl
* lc 
= GetListCtrl(); 
4244         wxCHECK_RET( lc
, _T("no listctrl window?") ); 
4246         lc
->m_headerWin
->Refresh() ; 
4248         lc
->m_headerWin
->MacUpdateImmediately() ; 
4253 int wxListMainWindow::GetCountPerPage() const 
4255     if ( !m_linesPerPage 
) 
4257         wxConstCast(this, wxListMainWindow
)-> 
4258             m_linesPerPage 
= GetClientSize().y 
/ GetLineHeight(); 
4261     return m_linesPerPage
; 
4264 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
) 
4266     wxASSERT_MSG( HasFlag(wxLC_REPORT
), _T("this is for report mode only") ); 
4268     if ( m_lineFrom 
== (size_t)-1 ) 
4270         size_t count 
= GetItemCount(); 
4273             m_lineFrom 
= GetScrollPos(wxVERTICAL
); 
4275             // this may happen if SetScrollbars() hadn't been called yet 
4276             if ( m_lineFrom 
>= count 
) 
4277                 m_lineFrom 
= count 
- 1; 
4279             // we redraw one extra line but this is needed to make the redrawing 
4280             // logic work when there is a fractional number of lines on screen 
4281             m_lineTo 
= m_lineFrom 
+ m_linesPerPage
; 
4282             if ( m_lineTo 
>= count 
) 
4283                 m_lineTo 
= count 
- 1; 
4285         else // empty control 
4288             m_lineTo 
= (size_t)-1; 
4292     wxASSERT_MSG( IsEmpty() || 
4293                   (m_lineFrom 
<= m_lineTo 
&& m_lineTo 
< GetItemCount()), 
4294                   _T("GetVisibleLinesRange() returns incorrect result") ); 
4302 // ------------------------------------------------------------------------------------- 
4304 // ------------------------------------------------------------------------------------- 
4306 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
) 
4308 wxListItem::wxListItem() 
4317     m_format 
= wxLIST_FORMAT_CENTRE
; 
4323 void wxListItem::Clear() 
4332     m_format 
= wxLIST_FORMAT_CENTRE
; 
4339 void wxListItem::ClearAttributes() 
4348 // ------------------------------------------------------------------------------------- 
4350 // ------------------------------------------------------------------------------------- 
4352 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
) 
4354 wxListEvent::wxListEvent( wxEventType commandType
, int id 
) 
4355            : wxNotifyEvent( commandType
, id 
) 
4361     m_cancelled 
= FALSE
; 
4366 void wxListEvent::CopyObject(wxObject
& object_dest
) const 
4368     wxListEvent 
*obj 
= (wxListEvent 
*)&object_dest
; 
4370     wxNotifyEvent::CopyObject(object_dest
); 
4372     obj
->m_code 
= m_code
; 
4373     obj
->m_itemIndex 
= m_itemIndex
; 
4374     obj
->m_oldItemIndex 
= m_oldItemIndex
; 
4376     obj
->m_cancelled 
= m_cancelled
; 
4377     obj
->m_pointDrag 
= m_pointDrag
; 
4378     obj
->m_item
.m_mask 
= m_item
.m_mask
; 
4379     obj
->m_item
.m_itemId 
= m_item
.m_itemId
; 
4380     obj
->m_item
.m_col 
= m_item
.m_col
; 
4381     obj
->m_item
.m_state 
= m_item
.m_state
; 
4382     obj
->m_item
.m_stateMask 
= m_item
.m_stateMask
; 
4383     obj
->m_item
.m_text 
= m_item
.m_text
; 
4384     obj
->m_item
.m_image 
= m_item
.m_image
; 
4385     obj
->m_item
.m_data 
= m_item
.m_data
; 
4386     obj
->m_item
.m_format 
= m_item
.m_format
; 
4387     obj
->m_item
.m_width 
= m_item
.m_width
; 
4389     if ( m_item
.HasAttributes() ) 
4391         obj
->m_item
.SetTextColour(m_item
.GetTextColour()); 
4395 // ------------------------------------------------------------------------------------- 
4397 // ------------------------------------------------------------------------------------- 
4399 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
) 
4400 IMPLEMENT_DYNAMIC_CLASS(wxListView
, wxListCtrl
) 
4402 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
) 
4403   EVT_SIZE(wxListCtrl::OnSize
) 
4404   EVT_IDLE(wxListCtrl::OnIdle
) 
4407 wxListCtrl::wxListCtrl() 
4409     m_imageListNormal 
= (wxImageList 
*) NULL
; 
4410     m_imageListSmall 
= (wxImageList 
*) NULL
; 
4411     m_imageListState 
= (wxImageList 
*) NULL
; 
4413     m_ownsImageListNormal 
= 
4414     m_ownsImageListSmall 
= 
4415     m_ownsImageListState 
= FALSE
; 
4417     m_mainWin 
= (wxListMainWindow
*) NULL
; 
4418     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
4421 wxListCtrl::~wxListCtrl() 
4424         m_mainWin
->ResetCurrent(); 
4426     if (m_ownsImageListNormal
) 
4427         delete m_imageListNormal
; 
4428     if (m_ownsImageListSmall
) 
4429         delete m_imageListSmall
; 
4430     if (m_ownsImageListState
) 
4431         delete m_imageListState
; 
4434 void wxListCtrl::CreateHeaderWindow() 
4436     m_headerWin 
= new wxListHeaderWindow
 
4438                         this, -1, m_mainWin
, 
4440                         wxSize(GetClientSize().x
, HEADER_HEIGHT
), 
4445 bool wxListCtrl::Create(wxWindow 
*parent
, 
4450                         const wxValidator 
&validator
, 
4451                         const wxString 
&name
) 
4455     m_imageListState 
= (wxImageList 
*) NULL
; 
4456     m_ownsImageListNormal 
= 
4457     m_ownsImageListSmall 
= 
4458     m_ownsImageListState 
= FALSE
; 
4460     m_mainWin 
= (wxListMainWindow
*) NULL
; 
4461     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
4463     if ( !(style 
& wxLC_MASK_TYPE
) ) 
4465         style 
= style 
| wxLC_LIST
; 
4468     if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
4471     // don't create the inner window with the border 
4472     style 
&= ~wxSUNKEN_BORDER
; 
4474     m_mainWin 
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style 
); 
4476     if ( HasFlag(wxLC_REPORT
) ) 
4478         CreateHeaderWindow(); 
4480         if ( HasFlag(wxLC_NO_HEADER
) ) 
4482             // VZ: why do we create it at all then? 
4483             m_headerWin
->Show( FALSE 
); 
4490 void wxListCtrl::SetSingleStyle( long style
, bool add 
) 
4492     wxASSERT_MSG( !(style 
& wxLC_VIRTUAL
), 
4493                   _T("wxLC_VIRTUAL can't be [un]set") ); 
4495     long flag 
= GetWindowStyle(); 
4499         if (style 
& wxLC_MASK_TYPE
) 
4500             flag 
&= ~(wxLC_MASK_TYPE 
| wxLC_VIRTUAL
); 
4501         if (style 
& wxLC_MASK_ALIGN
) 
4502             flag 
&= ~wxLC_MASK_ALIGN
; 
4503         if (style 
& wxLC_MASK_SORT
) 
4504             flag 
&= ~wxLC_MASK_SORT
; 
4516     SetWindowStyleFlag( flag 
); 
4519 void wxListCtrl::SetWindowStyleFlag( long flag 
) 
4523         m_mainWin
->DeleteEverything(); 
4525         // has the header visibility changed? 
4526         bool hasHeader 
= HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
), 
4527              willHaveHeader 
= (flag 
& wxLC_REPORT
) && !(flag 
& wxLC_NO_HEADER
); 
4529         if ( hasHeader 
!= willHaveHeader 
) 
4536                     // don't delete, just hide, as we can reuse it later 
4537                     m_headerWin
->Show(FALSE
); 
4539                 //else: nothing to do 
4541             else // must show header 
4545                     CreateHeaderWindow(); 
4547                 else // already have it, just show 
4549                     m_headerWin
->Show( TRUE 
); 
4553             ResizeReportView(willHaveHeader
); 
4557     wxWindow::SetWindowStyleFlag( flag 
); 
4560 bool wxListCtrl::GetColumn(int col
, wxListItem 
&item
) const 
4562     m_mainWin
->GetColumn( col
, item 
); 
4566 bool wxListCtrl::SetColumn( int col
, wxListItem
& item 
) 
4568     m_mainWin
->SetColumn( col
, item 
); 
4572 int wxListCtrl::GetColumnWidth( int col 
) const 
4574     return m_mainWin
->GetColumnWidth( col 
); 
4577 bool wxListCtrl::SetColumnWidth( int col
, int width 
) 
4579     m_mainWin
->SetColumnWidth( col
, width 
); 
4583 int wxListCtrl::GetCountPerPage() const 
4585   return m_mainWin
->GetCountPerPage();  // different from Windows ? 
4588 bool wxListCtrl::GetItem( wxListItem 
&info 
) const 
4590     m_mainWin
->GetItem( info 
); 
4594 bool wxListCtrl::SetItem( wxListItem 
&info 
) 
4596     m_mainWin
->SetItem( info 
); 
4600 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId 
) 
4603     info
.m_text 
= label
; 
4604     info
.m_mask 
= wxLIST_MASK_TEXT
; 
4605     info
.m_itemId 
= index
; 
4609         info
.m_image 
= imageId
; 
4610         info
.m_mask 
|= wxLIST_MASK_IMAGE
; 
4612     m_mainWin
->SetItem(info
); 
4616 int wxListCtrl::GetItemState( long item
, long stateMask 
) const 
4618     return m_mainWin
->GetItemState( item
, stateMask 
); 
4621 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask 
) 
4623     m_mainWin
->SetItemState( item
, state
, stateMask 
); 
4627 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) ) 
4630     info
.m_image 
= image
; 
4631     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
4632     info
.m_itemId 
= item
; 
4633     m_mainWin
->SetItem( info 
); 
4637 wxString 
wxListCtrl::GetItemText( long item 
) const 
4640     info
.m_itemId 
= item
; 
4641     m_mainWin
->GetItem( info 
); 
4645 void wxListCtrl::SetItemText( long item
, const wxString 
&str 
) 
4648     info
.m_mask 
= wxLIST_MASK_TEXT
; 
4649     info
.m_itemId 
= item
; 
4651     m_mainWin
->SetItem( info 
); 
4654 long wxListCtrl::GetItemData( long item 
) const 
4657     info
.m_itemId 
= item
; 
4658     m_mainWin
->GetItem( info 
); 
4662 bool wxListCtrl::SetItemData( long item
, long data 
) 
4665     info
.m_mask 
= wxLIST_MASK_DATA
; 
4666     info
.m_itemId 
= item
; 
4668     m_mainWin
->SetItem( info 
); 
4672 bool wxListCtrl::GetItemRect( long item
, wxRect 
&rect
,  int WXUNUSED(code
) ) const 
4674     m_mainWin
->GetItemRect( item
, rect 
); 
4678 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos 
) const 
4680     m_mainWin
->GetItemPosition( item
, pos 
); 
4684 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) ) 
4689 int wxListCtrl::GetItemCount() const 
4691     return m_mainWin
->GetItemCount(); 
4694 int wxListCtrl::GetColumnCount() const 
4696     return m_mainWin
->GetColumnCount(); 
4699 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall 
) 
4701     m_mainWin
->SetItemSpacing( spacing
, isSmall 
); 
4704 int wxListCtrl::GetItemSpacing( bool isSmall 
) const 
4706     return m_mainWin
->GetItemSpacing( isSmall 
); 
4709 int wxListCtrl::GetSelectedItemCount() const 
4711     return m_mainWin
->GetSelectedItemCount(); 
4714 wxColour 
wxListCtrl::GetTextColour() const 
4716     return GetForegroundColour(); 
4719 void wxListCtrl::SetTextColour(const wxColour
& col
) 
4721     SetForegroundColour(col
); 
4724 long wxListCtrl::GetTopItem() const 
4729 long wxListCtrl::GetNextItem( long item
, int geom
, int state 
) const 
4731     return m_mainWin
->GetNextItem( item
, geom
, state 
); 
4734 wxImageList 
*wxListCtrl::GetImageList(int which
) const 
4736     if (which 
== wxIMAGE_LIST_NORMAL
) 
4738         return m_imageListNormal
; 
4740     else if (which 
== wxIMAGE_LIST_SMALL
) 
4742         return m_imageListSmall
; 
4744     else if (which 
== wxIMAGE_LIST_STATE
) 
4746         return m_imageListState
; 
4748     return (wxImageList 
*) NULL
; 
4751 void wxListCtrl::SetImageList( wxImageList 
*imageList
, int which 
) 
4753     if ( which 
== wxIMAGE_LIST_NORMAL 
) 
4755         if (m_ownsImageListNormal
) delete m_imageListNormal
; 
4756         m_imageListNormal 
= imageList
; 
4757         m_ownsImageListNormal 
= FALSE
; 
4759     else if ( which 
== wxIMAGE_LIST_SMALL 
) 
4761         if (m_ownsImageListSmall
) delete m_imageListSmall
; 
4762         m_imageListSmall 
= imageList
; 
4763         m_ownsImageListSmall 
= FALSE
; 
4765     else if ( which 
== wxIMAGE_LIST_STATE 
) 
4767         if (m_ownsImageListState
) delete m_imageListState
; 
4768         m_imageListState 
= imageList
; 
4769         m_ownsImageListState 
= FALSE
; 
4772     m_mainWin
->SetImageList( imageList
, which 
); 
4775 void wxListCtrl::AssignImageList(wxImageList 
*imageList
, int which
) 
4777     SetImageList(imageList
, which
); 
4778     if ( which 
== wxIMAGE_LIST_NORMAL 
) 
4779         m_ownsImageListNormal 
= TRUE
; 
4780     else if ( which 
== wxIMAGE_LIST_SMALL 
) 
4781         m_ownsImageListSmall 
= TRUE
; 
4782     else if ( which 
== wxIMAGE_LIST_STATE 
) 
4783         m_ownsImageListState 
= TRUE
; 
4786 bool wxListCtrl::Arrange( int WXUNUSED(flag
) ) 
4791 bool wxListCtrl::DeleteItem( long item 
) 
4793     m_mainWin
->DeleteItem( item 
); 
4797 bool wxListCtrl::DeleteAllItems() 
4799     m_mainWin
->DeleteAllItems(); 
4803 bool wxListCtrl::DeleteAllColumns() 
4805     size_t count 
= m_mainWin
->m_columns
.GetCount(); 
4806     for ( size_t n 
= 0; n 
< count
; n
++ ) 
4812 void wxListCtrl::ClearAll() 
4814     m_mainWin
->DeleteEverything(); 
4817 bool wxListCtrl::DeleteColumn( int col 
) 
4819     m_mainWin
->DeleteColumn( col 
); 
4823 void wxListCtrl::Edit( long item 
) 
4825     m_mainWin
->EditLabel( item 
); 
4828 bool wxListCtrl::EnsureVisible( long item 
) 
4830     m_mainWin
->EnsureVisible( item 
); 
4834 long wxListCtrl::FindItem( long start
, const wxString
& str
,  bool partial 
) 
4836     return m_mainWin
->FindItem( start
, str
, partial 
); 
4839 long wxListCtrl::FindItem( long start
, long data 
) 
4841     return m_mainWin
->FindItem( start
, data 
); 
4844 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
), 
4845                            int WXUNUSED(direction
)) 
4850 long wxListCtrl::HitTest( const wxPoint 
&point
, int &flags 
) 
4852     return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags 
); 
4855 long wxListCtrl::InsertItem( wxListItem
& info 
) 
4857     m_mainWin
->InsertItem( info 
); 
4858     return info
.m_itemId
; 
4861 long wxListCtrl::InsertItem( long index
, const wxString 
&label 
) 
4864     info
.m_text 
= label
; 
4865     info
.m_mask 
= wxLIST_MASK_TEXT
; 
4866     info
.m_itemId 
= index
; 
4867     return InsertItem( info 
); 
4870 long wxListCtrl::InsertItem( long index
, int imageIndex 
) 
4873     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
4874     info
.m_image 
= imageIndex
; 
4875     info
.m_itemId 
= index
; 
4876     return InsertItem( info 
); 
4879 long wxListCtrl::InsertItem( long index
, const wxString 
&label
, int imageIndex 
) 
4882     info
.m_text 
= label
; 
4883     info
.m_image 
= imageIndex
; 
4884     info
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_IMAGE
; 
4885     info
.m_itemId 
= index
; 
4886     return InsertItem( info 
); 
4889 long wxListCtrl::InsertColumn( long col
, wxListItem 
&item 
) 
4891     wxASSERT( m_headerWin 
); 
4892     m_mainWin
->InsertColumn( col
, item 
); 
4893     m_headerWin
->Refresh(); 
4898 long wxListCtrl::InsertColumn( long col
, const wxString 
&heading
, 
4899                                int format
, int width 
) 
4902     item
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_FORMAT
; 
4903     item
.m_text 
= heading
; 
4906         item
.m_mask 
|= wxLIST_MASK_WIDTH
; 
4907         item
.m_width 
= width
; 
4909     item
.m_format 
= format
; 
4911     return InsertColumn( col
, item 
); 
4914 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) ) 
4920 // fn is a function which takes 3 long arguments: item1, item2, data. 
4921 // item1 is the long data associated with a first item (NOT the index). 
4922 // item2 is the long data associated with a second item (NOT the index). 
4923 // data is the same value as passed to SortItems. 
4924 // The return value is a negative number if the first item should precede the second 
4925 // item, a positive number of the second item should precede the first, 
4926 // or zero if the two items are equivalent. 
4927 // data is arbitrary data to be passed to the sort function. 
4929 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data 
) 
4931     m_mainWin
->SortItems( fn
, data 
); 
4935 // ---------------------------------------------------------------------------- 
4937 // ---------------------------------------------------------------------------- 
4939 void wxListCtrl::OnSize(wxSizeEvent
& event
) 
4944     ResizeReportView(m_mainWin
->HasHeader()); 
4946     m_mainWin
->RecalculatePositions(); 
4949 void wxListCtrl::ResizeReportView(bool showHeader
) 
4952     GetClientSize( &cw
, &ch 
); 
4956         m_headerWin
->SetSize( 0, 0, cw
, HEADER_HEIGHT 
); 
4957         m_mainWin
->SetSize( 0, HEADER_HEIGHT 
+ 1, cw
, ch 
- HEADER_HEIGHT 
- 1 ); 
4959     else // no header window 
4961         m_mainWin
->SetSize( 0, 0, cw
, ch 
); 
4965 void wxListCtrl::OnIdle( wxIdleEvent 
& event 
) 
4969     // do it only if needed 
4970     if ( !m_mainWin
->m_dirty 
) 
4973     m_mainWin
->RecalculatePositions(); 
4976 // ---------------------------------------------------------------------------- 
4978 // ---------------------------------------------------------------------------- 
4980 bool wxListCtrl::SetBackgroundColour( const wxColour 
&colour 
) 
4984         m_mainWin
->SetBackgroundColour( colour 
); 
4985         m_mainWin
->m_dirty 
= TRUE
; 
4991 bool wxListCtrl::SetForegroundColour( const wxColour 
&colour 
) 
4993     if ( !wxWindow::SetForegroundColour( colour 
) ) 
4998         m_mainWin
->SetForegroundColour( colour 
); 
4999         m_mainWin
->m_dirty 
= TRUE
; 
5004         m_headerWin
->SetForegroundColour( colour 
); 
5010 bool wxListCtrl::SetFont( const wxFont 
&font 
) 
5012     if ( !wxWindow::SetFont( font 
) ) 
5017         m_mainWin
->SetFont( font 
); 
5018         m_mainWin
->m_dirty 
= TRUE
; 
5023         m_headerWin
->SetFont( font 
); 
5029 // ---------------------------------------------------------------------------- 
5030 // methods forwarded to m_mainWin 
5031 // ---------------------------------------------------------------------------- 
5033 #if wxUSE_DRAG_AND_DROP 
5035 void wxListCtrl::SetDropTarget( wxDropTarget 
*dropTarget 
) 
5037     m_mainWin
->SetDropTarget( dropTarget 
); 
5040 wxDropTarget 
*wxListCtrl::GetDropTarget() const 
5042     return m_mainWin
->GetDropTarget(); 
5045 #endif // wxUSE_DRAG_AND_DROP 
5047 bool wxListCtrl::SetCursor( const wxCursor 
&cursor 
) 
5049     return m_mainWin 
? m_mainWin
->wxWindow::SetCursor(cursor
) : FALSE
; 
5052 wxColour 
wxListCtrl::GetBackgroundColour() const 
5054     return m_mainWin 
? m_mainWin
->GetBackgroundColour() : wxColour(); 
5057 wxColour 
wxListCtrl::GetForegroundColour() const 
5059     return m_mainWin 
? m_mainWin
->GetForegroundColour() : wxColour(); 
5062 bool wxListCtrl::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
5065     return m_mainWin
->PopupMenu( menu
, x
, y 
); 
5068 #endif // wxUSE_MENUS 
5071 void wxListCtrl::SetFocus() 
5073     /* The test in window.cpp fails as we are a composite 
5074        window, so it checks against "this", but not m_mainWin. */ 
5075     if ( FindFocus() != this ) 
5076         m_mainWin
->SetFocus(); 
5079 // ---------------------------------------------------------------------------- 
5080 // virtual list control support 
5081 // ---------------------------------------------------------------------------- 
5083 wxString 
wxListCtrl::OnGetItemText(long item
, long col
) const 
5085     // this is a pure virtual function, in fact - which is not really pure 
5086     // because the controls which are not virtual don't need to implement it 
5087     wxFAIL_MSG( _T("not supposed to be called") ); 
5089     return wxEmptyString
; 
5092 int wxListCtrl::OnGetItemImage(long item
) const 
5095     wxFAIL_MSG( _T("not supposed to be called") ); 
5100 wxListItemAttr 
*wxListCtrl::OnGetItemAttr(long item
) const 
5102     wxASSERT_MSG( item 
>= 0 && item 
< GetItemCount(), 
5103                   _T("invalid item index in OnGetItemAttr()") ); 
5105     // no attributes by default 
5109 void wxListCtrl::SetItemCount(long count
) 
5111     wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") ); 
5113     m_mainWin
->SetItemCount(count
); 
5116 void wxListCtrl::RefreshItem(long item
) 
5118     m_mainWin
->RefreshLine(item
); 
5121 void wxListCtrl::RefreshItems(long itemFrom
, long itemTo
) 
5123     m_mainWin
->RefreshLines(itemFrom
, itemTo
); 
5126 #endif // wxUSE_LISTCTRL