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 // ---------------------------------------------------------------------------- 
  26 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) 
  27     #pragma implementation "listctrl.h" 
  28     #pragma implementation "listctrlbase.h" 
  31 // For compilers that support precompilation, includes "wx.h". 
  32 #include "wx/wxprec.h" 
  43     #include "wx/dynarray.h" 
  45     #include "wx/dcscreen.h" 
  47     #include "wx/textctrl.h" 
  50 // under Win32 we always use the native version and also may use the generic 
  51 // one, however some things should be done only if we use only the generic 
  53 #if defined(__WIN32__) && !defined(__WXUNIVERSAL__) 
  54     #define HAVE_NATIVE_LISTCTRL 
  57 // if we have the native control, wx/listctrl.h declares it and not this one 
  58 #ifdef HAVE_NATIVE_LISTCTRL 
  59     #include "wx/generic/listctrl.h" 
  60 #else // !HAVE_NATIVE_LISTCTRL 
  61     #include "wx/listctrl.h" 
  63     // if we have a native version, its implementation file does all this 
  64     IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
) 
  65     IMPLEMENT_DYNAMIC_CLASS(wxListView
, wxListCtrl
) 
  66     IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
) 
  68     IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxGenericListCtrl
) 
  69 #endif // HAVE_NATIVE_LISTCTRL/!HAVE_NATIVE_LISTCTRL 
  71 #include "wx/selstore.h" 
  73 #include "wx/renderer.h" 
  76     #include "wx/mac/private.h" 
  79 // NOTE: If using the wxListBox visual attributes works everywhere then this can 
  80 // be removed, as well as the #else case below. 
  81 #define _USE_VISATTR 0 
  84 // ---------------------------------------------------------------------------- 
  86 // ---------------------------------------------------------------------------- 
  88 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_DRAG
) 
  89 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_RDRAG
) 
  90 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
) 
  91 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_END_LABEL_EDIT
) 
  92 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ITEM
) 
  93 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
) 
  94 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_GET_INFO
) 
  95 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_SET_INFO
) 
  96 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_SELECTED
) 
  97 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_DESELECTED
) 
  98 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_KEY_DOWN
) 
  99 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_INSERT_ITEM
) 
 100 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_CLICK
) 
 101 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
) 
 102 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
) 
 103 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_DRAGGING
) 
 104 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_COL_END_DRAG
) 
 105 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
) 
 106 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK
) 
 107 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_ACTIVATED
) 
 108 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_ITEM_FOCUSED
) 
 109 DEFINE_EVENT_TYPE(wxEVT_COMMAND_LIST_CACHE_HINT
) 
 111 // ---------------------------------------------------------------------------- 
 113 // ---------------------------------------------------------------------------- 
 115 // // the height of the header window (FIXME: should depend on its font!) 
 116 // static const int HEADER_HEIGHT = 23; 
 118 static const int SCROLL_UNIT_X 
= 15; 
 120 // the spacing between the lines (in report mode) 
 121 static const int LINE_SPACING 
= 0; 
 123 // extra margins around the text label 
 124 static const int EXTRA_WIDTH 
= 4; 
 125 static const int EXTRA_HEIGHT 
= 4; 
 127 // margin between the window and the items 
 128 static const int EXTRA_BORDER_X 
= 2; 
 129 static const int EXTRA_BORDER_Y 
= 2; 
 131 // offset for the header window 
 132 static const int HEADER_OFFSET_X 
= 1; 
 133 static const int HEADER_OFFSET_Y 
= 1; 
 135 // margin between rows of icons in [small] icon view 
 136 static const int MARGIN_BETWEEN_ROWS 
= 6; 
 138 // when autosizing the columns, add some slack 
 139 static const int AUTOSIZE_COL_MARGIN 
= 10; 
 141 // default and minimal widths for the header columns 
 142 static const int WIDTH_COL_DEFAULT 
= 80; 
 143 static const int WIDTH_COL_MIN 
= 10; 
 145 // the space between the image and the text in the report mode 
 146 static const int IMAGE_MARGIN_IN_REPORT_MODE 
= 5; 
 148 // ============================================================================ 
 150 // ============================================================================ 
 152 //----------------------------------------------------------------------------- 
 153 //  wxListItemData (internal) 
 154 //----------------------------------------------------------------------------- 
 156 class WXDLLEXPORT wxListItemData
 
 159     wxListItemData(wxListMainWindow 
*owner
); 
 162     void SetItem( const wxListItem 
&info 
); 
 163     void SetImage( int image 
) { m_image 
= image
; } 
 164     void SetData( long data 
) { m_data 
= data
; } 
 165     void SetPosition( int x
, int y 
); 
 166     void SetSize( int width
, int height 
); 
 168     bool HasText() const { return !m_text
.empty(); } 
 169     const wxString
& GetText() const { return m_text
; } 
 170     void SetText(const wxString
& text
) { m_text 
= text
; } 
 172     // we can't use empty string for measuring the string width/height, so 
 173     // always return something 
 174     wxString 
GetTextForMeasuring() const 
 176         wxString s 
= GetText(); 
 183     bool IsHit( int x
, int y 
) const; 
 187     int GetWidth() const; 
 188     int GetHeight() const; 
 190     int GetImage() const { return m_image
; } 
 191     bool HasImage() const { return GetImage() != -1; } 
 193     void GetItem( wxListItem 
&info 
) const; 
 195     void SetAttr(wxListItemAttr 
*attr
) { m_attr 
= attr
; } 
 196     wxListItemAttr 
*GetAttr() const { return m_attr
; } 
 199     // the item image or -1 
 202     // user data associated with the item 
 205     // the item coordinates are not used in report mode, instead this pointer 
 206     // is NULL and the owner window is used to retrieve the item position and 
 210     // the list ctrl we are in 
 211     wxListMainWindow 
*m_owner
; 
 213     // custom attributes or NULL 
 214     wxListItemAttr 
*m_attr
; 
 217     // common part of all ctors 
 223 //----------------------------------------------------------------------------- 
 224 //  wxListHeaderData (internal) 
 225 //----------------------------------------------------------------------------- 
 227 class WXDLLEXPORT wxListHeaderData 
: public wxObject
 
 231     wxListHeaderData( const wxListItem 
&info 
); 
 232     void SetItem( const wxListItem 
&item 
); 
 233     void SetPosition( int x
, int y 
); 
 234     void SetWidth( int w 
); 
 235     void SetFormat( int format 
); 
 236     void SetHeight( int h 
); 
 237     bool HasImage() const; 
 239     bool HasText() const { return !m_text
.empty(); } 
 240     const wxString
& GetText() const { return m_text
; } 
 241     void SetText(const wxString
& text
) { m_text 
= text
; } 
 243     void GetItem( wxListItem 
&item 
); 
 245     bool IsHit( int x
, int y 
) const; 
 246     int GetImage() const; 
 247     int GetWidth() const; 
 248     int GetFormat() const; 
 264 //----------------------------------------------------------------------------- 
 265 //  wxListLineData (internal) 
 266 //----------------------------------------------------------------------------- 
 268 WX_DECLARE_LIST(wxListItemData
, wxListItemDataList
); 
 269 #include "wx/listimpl.cpp" 
 270 WX_DEFINE_LIST(wxListItemDataList
); 
 275     // the list of subitems: only may have more than one item in report mode 
 276     wxListItemDataList m_items
; 
 278     // this is not used in report view 
 290         // the part to be highlighted 
 291         wxRect m_rectHighlight
; 
 293         // extend all our rects to be centered inside theo ne of given width 
 294         void ExtendWidth(wxCoord w
) 
 296             wxASSERT_MSG( m_rectAll
.width 
<= w
, 
 297                             _T("width can only be increased") ); 
 300             m_rectLabel
.x 
= m_rectAll
.x 
+ (w 
- m_rectLabel
.width
)/2; 
 301             m_rectIcon
.x 
= m_rectAll
.x 
+ (w 
- m_rectIcon
.width
)/2; 
 302             m_rectHighlight
.x 
= m_rectAll
.x 
+ (w 
- m_rectHighlight
.width
)/2; 
 306     // is this item selected? [NB: not used in virtual mode] 
 309     // back pointer to the list ctrl 
 310     wxListMainWindow 
*m_owner
; 
 313     wxListLineData(wxListMainWindow 
*owner
); 
 317         WX_CLEAR_LIST(wxListItemDataList
, m_items
); 
 321     // are we in report mode? 
 322     inline bool InReportView() const; 
 324     // are we in virtual report mode? 
 325     inline bool IsVirtual() const; 
 327     // these 2 methods shouldn't be called for report view controls, in that 
 328     // case we determine our position/size ourselves 
 330     // calculate the size of the line 
 331     void CalculateSize( wxDC 
*dc
, int spacing 
); 
 333     // remember the position this line appears at 
 334     void SetPosition( int x
, int y
, int spacing 
); 
 338     void SetImage( int image 
) { SetImage(0, image
); } 
 339     int GetImage() const { return GetImage(0); } 
 340     bool HasImage() const { return GetImage() != -1; } 
 341     bool HasText() const { return !GetText(0).empty(); } 
 343     void SetItem( int index
, const wxListItem 
&info 
); 
 344     void GetItem( int index
, wxListItem 
&info 
); 
 346     wxString 
GetText(int index
) const; 
 347     void SetText( int index
, const wxString s 
); 
 349     wxListItemAttr 
*GetAttr() const; 
 350     void SetAttr(wxListItemAttr 
*attr
); 
 352     // return true if the highlighting really changed 
 353     bool Highlight( bool on 
); 
 355     void ReverseHighlight(); 
 357     bool IsHighlighted() const 
 359         wxASSERT_MSG( !IsVirtual(), _T("unexpected call to IsHighlighted") ); 
 361         return m_highlighted
; 
 364     // draw the line on the given DC in icon/list mode 
 365     void Draw( wxDC 
*dc 
); 
 367     // the same in report mode 
 368     void DrawInReportMode( wxDC 
*dc
, 
 370                            const wxRect
& rectHL
, 
 374     // set the line to contain num items (only can be > 1 in report mode) 
 375     void InitItems( int num 
); 
 377     // get the mode (i.e. style)  of the list control 
 378     inline int GetMode() const; 
 380     // prepare the DC for drawing with these item's attributes, return true if 
 381     // we need to draw the items background to highlight it, false otherwise 
 382     bool SetAttributes(wxDC 
*dc
, 
 383                        const wxListItemAttr 
*attr
, 
 386     // draw the text on the DC with the correct justification; also add an 
 387     // ellipsis if the text is too large to fit in the current width 
 388     void DrawTextFormatted(wxDC 
*dc
, const wxString 
&text
, int col
, int x
, int y
, int width
); 
 390     // these are only used by GetImage/SetImage above, we don't support images 
 391     // with subitems at the public API level yet 
 392     void SetImage( int index
, int image 
); 
 393     int GetImage( int index 
) const; 
 396 WX_DECLARE_EXPORTED_OBJARRAY(wxListLineData
, wxListLineDataArray
); 
 397 #include "wx/arrimpl.cpp" 
 398 WX_DEFINE_OBJARRAY(wxListLineDataArray
); 
 400 //----------------------------------------------------------------------------- 
 401 //  wxListHeaderWindow (internal) 
 402 //----------------------------------------------------------------------------- 
 404 class WXDLLEXPORT wxListHeaderWindow 
: public wxWindow
 
 407     wxListMainWindow  
*m_owner
; 
 408     wxCursor          
*m_currentCursor
; 
 409     wxCursor          
*m_resizeCursor
; 
 412     // column being resized or -1 
 415     // divider line position in logical (unscrolled) coords 
 418     // minimal position beyond which the divider line can't be dragged in 
 423     wxListHeaderWindow(); 
 425     wxListHeaderWindow( wxWindow 
*win
, 
 427                         wxListMainWindow 
*owner
, 
 428                         const wxPoint 
&pos 
= wxDefaultPosition
, 
 429                         const wxSize 
&size 
= wxDefaultSize
, 
 431                         const wxString 
&name 
= wxT("wxlistctrlcolumntitles") ); 
 433     virtual ~wxListHeaderWindow(); 
 436     void AdjustDC(wxDC
& dc
); 
 438     void OnPaint( wxPaintEvent 
&event 
); 
 439     void OnMouse( wxMouseEvent 
&event 
); 
 440     void OnSetFocus( wxFocusEvent 
&event 
); 
 446     // common part of all ctors 
 449     // generate and process the list event of the given type, return true if 
 450     // it wasn't vetoed, i.e. if we should proceed 
 451     bool SendListEvent(wxEventType type
, wxPoint pos
); 
 453     DECLARE_DYNAMIC_CLASS(wxListHeaderWindow
) 
 454     DECLARE_EVENT_TABLE() 
 457 //----------------------------------------------------------------------------- 
 458 // wxListRenameTimer (internal) 
 459 //----------------------------------------------------------------------------- 
 461 class WXDLLEXPORT wxListRenameTimer
: public wxTimer
 
 464     wxListMainWindow 
*m_owner
; 
 467     wxListRenameTimer( wxListMainWindow 
*owner 
); 
 471 //----------------------------------------------------------------------------- 
 472 //  wxListTextCtrl (internal) 
 473 //----------------------------------------------------------------------------- 
 475 class WXDLLEXPORT wxListTextCtrl
: public wxTextCtrl
 
 478     wxListTextCtrl(wxListMainWindow 
*owner
, size_t itemEdit
); 
 481     void OnChar( wxKeyEvent 
&event 
); 
 482     void OnKeyUp( wxKeyEvent 
&event 
); 
 483     void OnKillFocus( wxFocusEvent 
&event 
); 
 485     bool AcceptChanges(); 
 489     wxListMainWindow   
*m_owner
; 
 490     wxString            m_startValue
; 
 494     DECLARE_EVENT_TABLE() 
 497 //----------------------------------------------------------------------------- 
 498 //  wxListMainWindow (internal) 
 499 //----------------------------------------------------------------------------- 
 501 WX_DECLARE_LIST(wxListHeaderData
, wxListHeaderDataList
); 
 502 #include "wx/listimpl.cpp" 
 503 WX_DEFINE_LIST(wxListHeaderDataList
); 
 505 class wxListMainWindow 
: public wxScrolledWindow
 
 509     wxListMainWindow( wxWindow 
*parent
, 
 511                       const wxPoint
& pos 
= wxDefaultPosition
, 
 512                       const wxSize
& size 
= wxDefaultSize
, 
 514                       const wxString 
&name 
= _T("listctrlmainwindow") ); 
 516     virtual ~wxListMainWindow(); 
 518     bool HasFlag(int flag
) const { return m_parent
->HasFlag(flag
); } 
 520     // return true if this is a virtual list control 
 521     bool IsVirtual() const { return HasFlag(wxLC_VIRTUAL
); } 
 523     // return true if the control is in report mode 
 524     bool InReportView() const { return HasFlag(wxLC_REPORT
); } 
 526     // return true if we are in single selection mode, false if multi sel 
 527     bool IsSingleSel() const { return HasFlag(wxLC_SINGLE_SEL
); } 
 529     // do we have a header window? 
 530     bool HasHeader() const 
 531         { return InReportView() && !HasFlag(wxLC_NO_HEADER
); } 
 533     void HighlightAll( bool on 
); 
 535     // all these functions only do something if the line is currently visible 
 537     // change the line "selected" state, return true if it really changed 
 538     bool HighlightLine( size_t line
, bool highlight 
= true); 
 540     // as HighlightLine() but do it for the range of lines: this is incredibly 
 541     // more efficient for virtual list controls! 
 543     // NB: unlike HighlightLine() this one does refresh the lines on screen 
 544     void HighlightLines( size_t lineFrom
, size_t lineTo
, bool on 
= true ); 
 546     // toggle the line state and refresh it 
 547     void ReverseHighlight( size_t line 
) 
 548         { HighlightLine(line
, !IsHighlighted(line
)); RefreshLine(line
); } 
 550     // return true if the line is highlighted 
 551     bool IsHighlighted(size_t line
) const; 
 553     // refresh one or several lines at once 
 554     void RefreshLine( size_t line 
); 
 555     void RefreshLines( size_t lineFrom
, size_t lineTo 
); 
 557     // refresh all selected items 
 558     void RefreshSelected(); 
 560     // refresh all lines below the given one: the difference with 
 561     // RefreshLines() is that the index here might not be a valid one (happens 
 562     // when the last line is deleted) 
 563     void RefreshAfter( size_t lineFrom 
); 
 565     // the methods which are forwarded to wxListLineData itself in list/icon 
 566     // modes but are here because the lines don't store their positions in the 
 569     // get the bound rect for the entire line 
 570     wxRect 
GetLineRect(size_t line
) const; 
 572     // get the bound rect of the label 
 573     wxRect 
GetLineLabelRect(size_t line
) const; 
 575     // get the bound rect of the items icon (only may be called if we do have 
 577     wxRect 
GetLineIconRect(size_t line
) const; 
 579     // get the rect to be highlighted when the item has focus 
 580     wxRect 
GetLineHighlightRect(size_t line
) const; 
 582     // get the size of the total line rect 
 583     wxSize 
GetLineSize(size_t line
) const 
 584         { return GetLineRect(line
).GetSize(); } 
 586     // return the hit code for the corresponding position (in this line) 
 587     long HitTestLine(size_t line
, int x
, int y
) const; 
 589     // bring the selected item into view, scrolling to it if necessary 
 590     void MoveToItem(size_t item
); 
 592     // bring the current item into view 
 593     void MoveToFocus() { MoveToItem(m_current
); } 
 595     // start editing the label of the given item 
 596     void EditLabel( long item 
); 
 598     // suspend/resume redrawing the control 
 604     void OnRenameTimer(); 
 605     bool OnRenameAccept(size_t itemEdit
, const wxString
& value
); 
 606     void OnRenameCancelled(size_t itemEdit
); 
 608     void OnMouse( wxMouseEvent 
&event 
); 
 610     // called to switch the selection from the current item to newCurrent, 
 611     void OnArrowChar( size_t newCurrent
, const wxKeyEvent
& event 
); 
 613     void OnChar( wxKeyEvent 
&event 
); 
 614     void OnKeyDown( wxKeyEvent 
&event 
); 
 615     void OnSetFocus( wxFocusEvent 
&event 
); 
 616     void OnKillFocus( wxFocusEvent 
&event 
); 
 617     void OnScroll(wxScrollWinEvent
& event
) ; 
 619     void OnPaint( wxPaintEvent 
&event 
); 
 621     void DrawImage( int index
, wxDC 
*dc
, int x
, int y 
); 
 622     void GetImageSize( int index
, int &width
, int &height 
) const; 
 623     int GetTextLength( const wxString 
&s 
) const; 
 625     void SetImageList( wxImageListType 
*imageList
, int which 
); 
 626     void SetItemSpacing( int spacing
, bool isSmall 
= false ); 
 627     int GetItemSpacing( bool isSmall 
= false ); 
 629     void SetColumn( int col
, wxListItem 
&item 
); 
 630     void SetColumnWidth( int col
, int width 
); 
 631     void GetColumn( int col
, wxListItem 
&item 
) const; 
 632     int GetColumnWidth( int col 
) const; 
 633     int GetColumnCount() const { return m_columns
.GetCount(); } 
 635     // returns the sum of the heights of all columns 
 636     int GetHeaderWidth() const; 
 638     int GetCountPerPage() const; 
 640     void SetItem( wxListItem 
&item 
); 
 641     void GetItem( wxListItem 
&item 
) const; 
 642     void SetItemState( long item
, long state
, long stateMask 
); 
 643     int GetItemState( long item
, long stateMask 
) const; 
 644     void GetItemRect( long index
, wxRect 
&rect 
) const; 
 645     wxRect 
GetViewRect() const; 
 646     bool GetItemPosition( long item
, wxPoint
& pos 
) const; 
 647     int GetSelectedItemCount() const; 
 649     wxString 
GetItemText(long item
) const 
 652         info
.m_itemId 
= item
; 
 657     void SetItemText(long item
, const wxString
& value
) 
 660         info
.m_mask 
= wxLIST_MASK_TEXT
; 
 661         info
.m_itemId 
= item
; 
 666     // set the scrollbars and update the positions of the items 
 667     void RecalculatePositions(bool noRefresh 
= false); 
 669     // refresh the window and the header 
 672     long GetNextItem( long item
, int geometry
, int state 
) const; 
 673     void DeleteItem( long index 
); 
 674     void DeleteAllItems(); 
 675     void DeleteColumn( int col 
); 
 676     void DeleteEverything(); 
 677     void EnsureVisible( long index 
); 
 678     long FindItem( long start
, const wxString
& str
, bool partial 
= false ); 
 679     long FindItem( long start
, long data
); 
 680     long HitTest( int x
, int y
, int &flags 
); 
 681     void InsertItem( wxListItem 
&item 
); 
 682     void InsertColumn( long col
, wxListItem 
&item 
); 
 683     void SortItems( wxListCtrlCompare fn
, long data 
); 
 685     size_t GetItemCount() const; 
 686     bool IsEmpty() const { return GetItemCount() == 0; } 
 687     void SetItemCount(long count
); 
 689     // change the current (== focused) item, send a notification event 
 690     void ChangeCurrent(size_t current
); 
 691     void ResetCurrent() { ChangeCurrent((size_t)-1); } 
 692     bool HasCurrent() const { return m_current 
!= (size_t)-1; } 
 694     // send out a wxListEvent 
 695     void SendNotify( size_t line
, 
 697                      wxPoint point 
= wxDefaultPosition 
); 
 699     // override base class virtual to reset m_lineHeight when the font changes 
 700     virtual bool SetFont(const wxFont
& font
) 
 702         if ( !wxScrolledWindow::SetFont(font
) ) 
 710     // these are for wxListLineData usage only 
 712     // get the backpointer to the list ctrl 
 713     wxGenericListCtrl 
*GetListCtrl() const 
 715         return wxStaticCast(GetParent(), wxGenericListCtrl
); 
 718     // get the height of all lines (assuming they all do have the same height) 
 719     wxCoord 
GetLineHeight() const; 
 721     // get the y position of the given line (only for report view) 
 722     wxCoord 
GetLineY(size_t line
) const; 
 724     // get the brush to use for the item highlighting 
 725     wxBrush 
*GetHighlightBrush() const 
 727         return m_hasFocus 
? m_highlightBrush 
: m_highlightUnfocusedBrush
; 
 731     // the array of all line objects for a non virtual list control (for the 
 732     // virtual list control we only ever use m_lines[0]) 
 733     wxListLineDataArray  m_lines
; 
 735     // the list of column objects 
 736     wxListHeaderDataList m_columns
; 
 738     // currently focused item or -1 
 741     // the number of lines per page 
 744     // this flag is set when something which should result in the window 
 745     // redrawing happens (i.e. an item was added or deleted, or its appearance 
 746     // changed) and OnPaint() doesn't redraw the window while it is set which 
 747     // allows to minimize the number of repaintings when a lot of items are 
 748     // being added. The real repainting occurs only after the next OnIdle() 
 752     wxColour            
*m_highlightColour
; 
 753     wxImageListType         
*m_small_image_list
; 
 754     wxImageListType         
*m_normal_image_list
; 
 756     int                  m_normal_spacing
; 
 760     wxTimer             
*m_renameTimer
; 
 765     // for double click logic 
 766     size_t m_lineLastClicked
, 
 767            m_lineBeforeLastClicked
; 
 770     // the total count of items in a virtual list control 
 773     // the object maintaining the items selection state, only used in virtual 
 775     wxSelectionStore m_selStore
; 
 777     // common part of all ctors 
 780     // get the line data for the given index 
 781     wxListLineData 
*GetLine(size_t n
) const 
 783         wxASSERT_MSG( n 
!= (size_t)-1, _T("invalid line index") ); 
 787             wxConstCast(this, wxListMainWindow
)->CacheLineData(n
); 
 795     // get a dummy line which can be used for geometry calculations and such: 
 796     // you must use GetLine() if you want to really draw the line 
 797     wxListLineData 
*GetDummyLine() const; 
 799     // cache the line data of the n-th line in m_lines[0] 
 800     void CacheLineData(size_t line
); 
 802     // get the range of visible lines 
 803     void GetVisibleLinesRange(size_t *from
, size_t *to
); 
 805     // force us to recalculate the range of visible lines 
 806     void ResetVisibleLinesRange() { m_lineFrom 
= (size_t)-1; } 
 808     // get the colour to be used for drawing the rules 
 809     wxColour 
GetRuleColour() const 
 814         return wxSystemSettings::GetColour(wxSYS_COLOUR_3DLIGHT
); 
 819     // initialize the current item if needed 
 820     void UpdateCurrent(); 
 822     // delete all items but don't refresh: called from dtor 
 823     void DoDeleteAllItems(); 
 825     // the height of one line using the current font 
 826     wxCoord m_lineHeight
; 
 828     // the total header width or 0 if not calculated yet 
 829     wxCoord m_headerWidth
; 
 831     // the first and last lines being shown on screen right now (inclusive), 
 832     // both may be -1 if they must be calculated so never access them directly: 
 833     // use GetVisibleLinesRange() above instead 
 837     // the brushes to use for item highlighting when we do/don't have focus 
 838     wxBrush 
*m_highlightBrush
, 
 839             *m_highlightUnfocusedBrush
; 
 841     // if this is > 0, the control is frozen and doesn't redraw itself 
 842     size_t m_freezeCount
; 
 844     DECLARE_DYNAMIC_CLASS(wxListMainWindow
) 
 845     DECLARE_EVENT_TABLE() 
 847     friend class wxGenericListCtrl
; 
 850 // ============================================================================ 
 852 // ============================================================================ 
 854 //----------------------------------------------------------------------------- 
 856 //----------------------------------------------------------------------------- 
 858 wxListItemData::~wxListItemData() 
 860     // in the virtual list control the attributes are managed by the main 
 861     // program, so don't delete them 
 862     if ( !m_owner
->IsVirtual() ) 
 870 void wxListItemData::Init() 
 878 wxListItemData::wxListItemData(wxListMainWindow 
*owner
) 
 884     if ( owner
->InReportView() ) 
 894 void wxListItemData::SetItem( const wxListItem 
&info 
) 
 896     if ( info
.m_mask 
& wxLIST_MASK_TEXT 
) 
 897         SetText(info
.m_text
); 
 898     if ( info
.m_mask 
& wxLIST_MASK_IMAGE 
) 
 899         m_image 
= info
.m_image
; 
 900     if ( info
.m_mask 
& wxLIST_MASK_DATA 
) 
 901         m_data 
= info
.m_data
; 
 903     if ( info
.HasAttributes() ) 
 906             *m_attr 
= *info
.GetAttributes(); 
 908             m_attr 
= new wxListItemAttr(*info
.GetAttributes()); 
 916         m_rect
->width 
= info
.m_width
; 
 920 void wxListItemData::SetPosition( int x
, int y 
) 
 922     wxCHECK_RET( m_rect
, _T("unexpected SetPosition() call") ); 
 928 void wxListItemData::SetSize( int width
, int height 
) 
 930     wxCHECK_RET( m_rect
, _T("unexpected SetSize() call") ); 
 933         m_rect
->width 
= width
; 
 935         m_rect
->height 
= height
; 
 938 bool wxListItemData::IsHit( int x
, int y 
) const 
 940     wxCHECK_MSG( m_rect
, false, _T("can't be called in this mode") ); 
 942     return wxRect(GetX(), GetY(), GetWidth(), GetHeight()).Inside(x
, y
); 
 945 int wxListItemData::GetX() const 
 947     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
 952 int wxListItemData::GetY() const 
 954     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
 959 int wxListItemData::GetWidth() const 
 961     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
 963     return m_rect
->width
; 
 966 int wxListItemData::GetHeight() const 
 968     wxCHECK_MSG( m_rect
, 0, _T("can't be called in this mode") ); 
 970     return m_rect
->height
; 
 973 void wxListItemData::GetItem( wxListItem 
&info 
) const 
 975     info
.m_text 
= m_text
; 
 976     info
.m_image 
= m_image
; 
 977     info
.m_data 
= m_data
; 
 981         if ( m_attr
->HasTextColour() ) 
 982             info
.SetTextColour(m_attr
->GetTextColour()); 
 983         if ( m_attr
->HasBackgroundColour() ) 
 984             info
.SetBackgroundColour(m_attr
->GetBackgroundColour()); 
 985         if ( m_attr
->HasFont() ) 
 986             info
.SetFont(m_attr
->GetFont()); 
 990 //----------------------------------------------------------------------------- 
 992 //----------------------------------------------------------------------------- 
 994 void wxListHeaderData::Init() 
1005 wxListHeaderData::wxListHeaderData() 
1010 wxListHeaderData::wxListHeaderData( const wxListItem 
&item 
) 
1017 void wxListHeaderData::SetItem( const wxListItem 
&item 
) 
1019     m_mask 
= item
.m_mask
; 
1021     if ( m_mask 
& wxLIST_MASK_TEXT 
) 
1022         m_text 
= item
.m_text
; 
1024     if ( m_mask 
& wxLIST_MASK_IMAGE 
) 
1025         m_image 
= item
.m_image
; 
1027     if ( m_mask 
& wxLIST_MASK_FORMAT 
) 
1028         m_format 
= item
.m_format
; 
1030     if ( m_mask 
& wxLIST_MASK_WIDTH 
) 
1031         SetWidth(item
.m_width
); 
1034 void wxListHeaderData::SetPosition( int x
, int y 
) 
1040 void wxListHeaderData::SetHeight( int h 
) 
1045 void wxListHeaderData::SetWidth( int w 
) 
1049         m_width 
= WIDTH_COL_DEFAULT
; 
1050     else if (m_width 
< WIDTH_COL_MIN
) 
1051         m_width 
= WIDTH_COL_MIN
; 
1054 void wxListHeaderData::SetFormat( int format 
) 
1059 bool wxListHeaderData::HasImage() const 
1061     return m_image 
!= -1; 
1064 bool wxListHeaderData::IsHit( int x
, int y 
) const 
1066     return ((x 
>= m_xpos
) && (x 
<= m_xpos
+m_width
) && (y 
>= m_ypos
) && (y 
<= m_ypos
+m_height
)); 
1069 void wxListHeaderData::GetItem( wxListItem
& item 
) 
1071     item
.m_mask 
= m_mask
; 
1072     item
.m_text 
= m_text
; 
1073     item
.m_image 
= m_image
; 
1074     item
.m_format 
= m_format
; 
1075     item
.m_width 
= m_width
; 
1078 int wxListHeaderData::GetImage() const 
1083 int wxListHeaderData::GetWidth() const 
1088 int wxListHeaderData::GetFormat() const 
1093 //----------------------------------------------------------------------------- 
1095 //----------------------------------------------------------------------------- 
1097 inline int wxListLineData::GetMode() const 
1099     return m_owner
->GetListCtrl()->GetWindowStyleFlag() & wxLC_MASK_TYPE
; 
1102 inline bool wxListLineData::InReportView() const 
1104     return m_owner
->HasFlag(wxLC_REPORT
); 
1107 inline bool wxListLineData::IsVirtual() const 
1109     return m_owner
->IsVirtual(); 
1112 wxListLineData::wxListLineData( wxListMainWindow 
*owner 
) 
1116     if ( InReportView() ) 
1122         m_gi 
= new GeometryInfo
; 
1125     m_highlighted 
= false; 
1127     InitItems( GetMode() == wxLC_REPORT 
? m_owner
->GetColumnCount() : 1 ); 
1130 void wxListLineData::CalculateSize( wxDC 
*dc
, int spacing 
) 
1132     wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1133     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1135     wxListItemData 
*item 
= node
->GetData(); 
1140     switch ( GetMode() ) 
1143         case wxLC_SMALL_ICON
: 
1144             m_gi
->m_rectAll
.width 
= spacing
; 
1146             s 
= item
->GetText(); 
1151                 m_gi
->m_rectLabel
.width 
= 
1152                 m_gi
->m_rectLabel
.height 
= 0; 
1156                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
1160                 m_gi
->m_rectAll
.height 
= spacing 
+ lh
; 
1162                     m_gi
->m_rectAll
.width 
= lw
; 
1164                 m_gi
->m_rectLabel
.width 
= lw
; 
1165                 m_gi
->m_rectLabel
.height 
= lh
; 
1168             if (item
->HasImage()) 
1171                 m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
1172                 m_gi
->m_rectIcon
.width 
= w 
+ 8; 
1173                 m_gi
->m_rectIcon
.height 
= h 
+ 8; 
1175                 if ( m_gi
->m_rectIcon
.width 
> m_gi
->m_rectAll
.width 
) 
1176                     m_gi
->m_rectAll
.width 
= m_gi
->m_rectIcon
.width
; 
1177                 if ( m_gi
->m_rectIcon
.height 
+ lh 
> m_gi
->m_rectAll
.height 
- 4 ) 
1178                     m_gi
->m_rectAll
.height 
= m_gi
->m_rectIcon
.height 
+ lh 
+ 4; 
1181             if ( item
->HasText() ) 
1183                 m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectLabel
.width
; 
1184                 m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectLabel
.height
; 
1186             else // no text, highlight the icon 
1188                 m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectIcon
.width
; 
1189                 m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectIcon
.height
; 
1194             s 
= item
->GetTextForMeasuring(); 
1196             dc
->GetTextExtent( s
, &lw
, &lh 
); 
1200             m_gi
->m_rectLabel
.width 
= lw
; 
1201             m_gi
->m_rectLabel
.height 
= lh
; 
1203             m_gi
->m_rectAll
.width 
= lw
; 
1204             m_gi
->m_rectAll
.height 
= lh
; 
1206             if (item
->HasImage()) 
1209                 m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
1210                 m_gi
->m_rectIcon
.width 
= w
; 
1211                 m_gi
->m_rectIcon
.height 
= h
; 
1213                 m_gi
->m_rectAll
.width 
+= 4 + w
; 
1214                 if (h 
> m_gi
->m_rectAll
.height
) 
1215                     m_gi
->m_rectAll
.height 
= h
; 
1218             m_gi
->m_rectHighlight
.width 
= m_gi
->m_rectAll
.width
; 
1219             m_gi
->m_rectHighlight
.height 
= m_gi
->m_rectAll
.height
; 
1223             wxFAIL_MSG( _T("unexpected call to SetSize") ); 
1227             wxFAIL_MSG( _T("unknown mode") ); 
1231 void wxListLineData::SetPosition( int x
, int y
, int spacing 
) 
1233     wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1234     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1236     wxListItemData 
*item 
= node
->GetData(); 
1238     switch ( GetMode() ) 
1241         case wxLC_SMALL_ICON
: 
1242             m_gi
->m_rectAll
.x 
= x
; 
1243             m_gi
->m_rectAll
.y 
= y
; 
1245             if ( item
->HasImage() ) 
1247                 m_gi
->m_rectIcon
.x 
= m_gi
->m_rectAll
.x 
+ 4 + 
1248                     (m_gi
->m_rectAll
.width 
- m_gi
->m_rectIcon
.width
) / 2; 
1249                 m_gi
->m_rectIcon
.y 
= m_gi
->m_rectAll
.y 
+ 4; 
1252             if ( item
->HasText() ) 
1254                 if (m_gi
->m_rectAll
.width 
> spacing
) 
1255                     m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1257                     m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2 + (spacing
/2) - (m_gi
->m_rectLabel
.width
/2); 
1258                 m_gi
->m_rectLabel
.y 
= m_gi
->m_rectAll
.y 
+ m_gi
->m_rectAll
.height 
+ 2 - m_gi
->m_rectLabel
.height
; 
1259                 m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectLabel
.x 
- 2; 
1260                 m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectLabel
.y 
- 2; 
1262             else // no text, highlight the icon 
1264                 m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectIcon
.x 
- 4; 
1265                 m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectIcon
.y 
- 4; 
1270             m_gi
->m_rectAll
.x 
= x
; 
1271             m_gi
->m_rectAll
.y 
= y
; 
1273             m_gi
->m_rectHighlight
.x 
= m_gi
->m_rectAll
.x
; 
1274             m_gi
->m_rectHighlight
.y 
= m_gi
->m_rectAll
.y
; 
1275             m_gi
->m_rectLabel
.y 
= m_gi
->m_rectAll
.y 
+ 2; 
1277             if (item
->HasImage()) 
1279                 m_gi
->m_rectIcon
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1280                 m_gi
->m_rectIcon
.y 
= m_gi
->m_rectAll
.y 
+ 2; 
1281                 m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 6 + m_gi
->m_rectIcon
.width
; 
1285                 m_gi
->m_rectLabel
.x 
= m_gi
->m_rectAll
.x 
+ 2; 
1290             wxFAIL_MSG( _T("unexpected call to SetPosition") ); 
1294             wxFAIL_MSG( _T("unknown mode") ); 
1298 void wxListLineData::InitItems( int num 
) 
1300     for (int i 
= 0; i 
< num
; i
++) 
1301         m_items
.Append( new wxListItemData(m_owner
) ); 
1304 void wxListLineData::SetItem( int index
, const wxListItem 
&info 
) 
1306     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1307     wxCHECK_RET( node
, _T("invalid column index in SetItem") ); 
1309     wxListItemData 
*item 
= node
->GetData(); 
1310     item
->SetItem( info 
); 
1313 void wxListLineData::GetItem( int index
, wxListItem 
&info 
) 
1315     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1318         wxListItemData 
*item 
= node
->GetData(); 
1319         item
->GetItem( info 
); 
1323 wxString 
wxListLineData::GetText(int index
) const 
1327     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1330         wxListItemData 
*item 
= node
->GetData(); 
1331         s 
= item
->GetText(); 
1337 void wxListLineData::SetText( int index
, const wxString s 
) 
1339     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1342         wxListItemData 
*item 
= node
->GetData(); 
1347 void wxListLineData::SetImage( int index
, int image 
) 
1349     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1350     wxCHECK_RET( node
, _T("invalid column index in SetImage()") ); 
1352     wxListItemData 
*item 
= node
->GetData(); 
1353     item
->SetImage(image
); 
1356 int wxListLineData::GetImage( int index 
) const 
1358     wxListItemDataList::compatibility_iterator node 
= m_items
.Item( index 
); 
1359     wxCHECK_MSG( node
, -1, _T("invalid column index in GetImage()") ); 
1361     wxListItemData 
*item 
= node
->GetData(); 
1362     return item
->GetImage(); 
1365 wxListItemAttr 
*wxListLineData::GetAttr() const 
1367     wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1368     wxCHECK_MSG( node
, NULL
, _T("invalid column index in GetAttr()") ); 
1370     wxListItemData 
*item 
= node
->GetData(); 
1371     return item
->GetAttr(); 
1374 void wxListLineData::SetAttr(wxListItemAttr 
*attr
) 
1376     wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1377     wxCHECK_RET( node
, _T("invalid column index in SetAttr()") ); 
1379     wxListItemData 
*item 
= node
->GetData(); 
1380     item
->SetAttr(attr
); 
1383 bool wxListLineData::SetAttributes(wxDC 
*dc
, 
1384                                    const wxListItemAttr 
*attr
, 
1387     wxWindow 
*listctrl 
= m_owner
->GetParent(); 
1391     // don't use foreground colour for drawing highlighted items - this might 
1392     // make them completely invisible (and there is no way to do bit 
1393     // arithmetics on wxColour, unfortunately) 
1397         colText 
= wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHTTEXT
); 
1401         if ( attr 
&& attr
->HasTextColour() ) 
1403             colText 
= attr
->GetTextColour(); 
1407             colText 
= listctrl
->GetForegroundColour(); 
1411     dc
->SetTextForeground(colText
); 
1415     if ( attr 
&& attr
->HasFont() ) 
1417         font 
= attr
->GetFont(); 
1421         font 
= listctrl
->GetFont(); 
1427     bool hasBgCol 
= attr 
&& attr
->HasBackgroundColour(); 
1428     if ( highlighted 
|| hasBgCol 
) 
1432             dc
->SetBrush( *m_owner
->GetHighlightBrush() ); 
1436             dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
1439         dc
->SetPen( *wxTRANSPARENT_PEN 
); 
1447 void wxListLineData::Draw( wxDC 
*dc 
) 
1449     wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1450     wxCHECK_RET( node
, _T("no subitems at all??") ); 
1452     bool highlighted 
= IsHighlighted(); 
1454     wxListItemAttr 
*attr 
= GetAttr(); 
1456     if ( SetAttributes(dc
, attr
, highlighted
) ) 
1458         dc
->DrawRectangle( m_gi
->m_rectHighlight 
); 
1461     // just for debugging to better see where the items are 
1463     dc
->SetPen(*wxRED_PEN
); 
1464     dc
->SetBrush(*wxTRANSPARENT_BRUSH
); 
1465     dc
->DrawRectangle( m_gi
->m_rectAll 
); 
1466     dc
->SetPen(*wxGREEN_PEN
); 
1467     dc
->DrawRectangle( m_gi
->m_rectIcon 
); 
1470     wxListItemData 
*item 
= node
->GetData(); 
1471     if (item
->HasImage()) 
1473         // centre the image inside our rectangle, this looks nicer when items 
1474         // ae aligned in a row 
1475         const wxRect
& rectIcon 
= m_gi
->m_rectIcon
; 
1477         m_owner
->DrawImage(item
->GetImage(), dc
, rectIcon
.x
, rectIcon
.y
); 
1480     if (item
->HasText()) 
1482         const wxRect
& rectLabel 
= m_gi
->m_rectLabel
; 
1484         wxDCClipper 
clipper(*dc
, rectLabel
); 
1485         dc
->DrawText(item
->GetText(), rectLabel
.x
, rectLabel
.y
); 
1489 void wxListLineData::DrawInReportMode( wxDC 
*dc
, 
1491                                        const wxRect
& rectHL
, 
1494     // TODO: later we should support setting different attributes for 
1495     //       different columns - to do it, just add "col" argument to 
1496     //       GetAttr() and move these lines into the loop below 
1497     wxListItemAttr 
*attr 
= GetAttr(); 
1498     if ( SetAttributes(dc
, attr
, highlighted
) ) 
1500         dc
->DrawRectangle( rectHL 
); 
1503     wxCoord x 
= rect
.x 
+ HEADER_OFFSET_X
, 
1504             y 
= rect
.y 
+ (LINE_SPACING 
+ EXTRA_HEIGHT
) / 2; 
1507     for ( wxListItemDataList::compatibility_iterator node 
= m_items
.GetFirst(); 
1509           node 
= node
->GetNext(), col
++ ) 
1511         wxListItemData 
*item 
= node
->GetData(); 
1513         int width 
= m_owner
->GetColumnWidth(col
); 
1517         if ( item
->HasImage() ) 
1520             m_owner
->DrawImage( item
->GetImage(), dc
, xOld
, y 
); 
1521             m_owner
->GetImageSize( item
->GetImage(), ix
, iy 
); 
1523             ix 
+= IMAGE_MARGIN_IN_REPORT_MODE
; 
1529         wxDCClipper 
clipper(*dc
, xOld
, y
, width 
- 8, rect
.height
); 
1531         if ( item
->HasText() ) 
1533             DrawTextFormatted(dc
, item
->GetText(), col
, xOld
, y
, width 
- 8); 
1538 void wxListLineData::DrawTextFormatted(wxDC 
*dc
, 
1539                                        const wxString 
&text
, 
1545     wxString drawntext
, ellipsis
; 
1546     wxCoord w
, h
, base_w
; 
1549     // determine if the string can fit inside the current width 
1550     dc
->GetTextExtent(text
, &w
, &h
); 
1553         // it can, draw it using the items alignment 
1554         m_owner
->GetColumn(col
, item
); 
1555         switch ( item
.GetAlign() ) 
1558                 wxFAIL_MSG( _T("unknown list item format") ); 
1561             case wxLIST_FORMAT_LEFT
: 
1565             case wxLIST_FORMAT_RIGHT
: 
1569             case wxLIST_FORMAT_CENTER
: 
1570                 x 
+= (width 
- w
) / 2; 
1574         dc
->DrawText(text
, x
, y
); 
1576     else // otherwise, truncate and add an ellipsis if possible 
1578         // determine the base width 
1579         ellipsis 
= wxString(wxT("...")); 
1580         dc
->GetTextExtent(ellipsis
, &base_w
, &h
); 
1582         // continue until we have enough space or only one character left 
1584         size_t len 
= text
.Length(); 
1585         drawntext 
= text
.Left(len
); 
1588             dc
->GetTextExtent(drawntext
.Last(), &w_c
, &h_c
); 
1589             drawntext
.RemoveLast(); 
1592             if (w 
+ base_w 
<= width
) 
1596         // if still not enough space, remove ellipsis characters 
1597         while (ellipsis
.Length() > 0 && w 
+ base_w 
> width
) 
1599             ellipsis 
= ellipsis
.Left(ellipsis
.Length() - 1); 
1600             dc
->GetTextExtent(ellipsis
, &base_w
, &h
); 
1603         // now draw the text 
1604         dc
->DrawText(drawntext
, x
, y
); 
1605         dc
->DrawText(ellipsis
, x 
+ w
, y
); 
1609 bool wxListLineData::Highlight( bool on 
) 
1611     wxCHECK_MSG( !IsVirtual(), false, _T("unexpected call to Highlight") ); 
1613     if ( on 
== m_highlighted 
) 
1621 void wxListLineData::ReverseHighlight( void ) 
1623     Highlight(!IsHighlighted()); 
1626 //----------------------------------------------------------------------------- 
1627 //  wxListHeaderWindow 
1628 //----------------------------------------------------------------------------- 
1630 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
) 
1632 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
) 
1633     EVT_PAINT         (wxListHeaderWindow::OnPaint
) 
1634     EVT_MOUSE_EVENTS  (wxListHeaderWindow::OnMouse
) 
1635     EVT_SET_FOCUS     (wxListHeaderWindow::OnSetFocus
) 
1638 void wxListHeaderWindow::Init() 
1640     m_currentCursor 
= (wxCursor 
*) NULL
; 
1641     m_isDragging 
= false; 
1645 wxListHeaderWindow::wxListHeaderWindow() 
1649     m_owner 
= (wxListMainWindow 
*) NULL
; 
1650     m_resizeCursor 
= (wxCursor 
*) NULL
; 
1653 wxListHeaderWindow::wxListHeaderWindow( wxWindow 
*win
, 
1655                                         wxListMainWindow 
*owner
, 
1659                                         const wxString 
&name 
) 
1660                   : wxWindow( win
, id
, pos
, size
, style
, name 
) 
1665     m_resizeCursor 
= new wxCursor( wxCURSOR_SIZEWE 
); 
1668     wxVisualAttributes attr 
= wxPanel::GetClassDefaultAttributes(); 
1669     SetOwnForegroundColour( attr
.colFg 
); 
1670     SetOwnBackgroundColour( attr
.colBg 
); 
1671     SetOwnFont( attr
.font 
); 
1673     SetOwnForegroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
)); 
1674     SetOwnBackgroundColour( wxSystemSettings::GetColour(wxSYS_COLOUR_BTNFACE
)); 
1675     SetOwnFont( wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT 
)); 
1679 wxListHeaderWindow::~wxListHeaderWindow() 
1681     delete m_resizeCursor
; 
1684 #ifdef __WXUNIVERSAL__ 
1685 #include "wx/univ/renderer.h" 
1686 #include "wx/univ/theme.h" 
1689 // shift the DC origin to match the position of the main window horz 
1690 // scrollbar: this allows us to always use logical coords 
1691 void wxListHeaderWindow::AdjustDC(wxDC
& dc
) 
1694     m_owner
->GetScrollPixelsPerUnit( &xpix
, NULL 
); 
1697     m_owner
->GetViewStart( &x
, NULL 
); 
1699     // account for the horz scrollbar offset 
1700     dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
1703 void wxListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1705     wxPaintDC 
dc( this ); 
1712     dc
.SetFont( GetFont() ); 
1714     // width and height of the entire header window 
1716     GetClientSize( &w
, &h 
); 
1717     m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1719     dc
.SetBackgroundMode(wxTRANSPARENT
); 
1721     dc
.SetTextForeground(GetForegroundColour()); 
1723     int x 
= HEADER_OFFSET_X
; 
1725     int numColumns 
= m_owner
->GetColumnCount(); 
1727     for ( int i 
= 0; i 
< numColumns 
&& x 
< w
; i
++ ) 
1729         m_owner
->GetColumn( i
, item 
); 
1730         int wCol 
= item
.m_width
; 
1732         // the width of the rect to draw: make it smaller to fit entirely 
1733         // inside the column rect 
1736         wxRendererNative::Get().DrawHeaderButton
 
1740                                     wxRect(x
, HEADER_OFFSET_Y
, cw
, h 
- 2), 
1741                                     m_parent
->IsEnabled() ? 0 
1742                                                           : wxCONTROL_DISABLED
 
1745         // see if we have enough space for the column label 
1747         // for this we need the width of the text 
1750         dc
.GetTextExtent(item
.GetText(), &wLabel
, &hLabel
); 
1751         wLabel 
+= 2*EXTRA_WIDTH
; 
1753         // and the width of the icon, if any 
1754         static const int MARGIN_BETWEEN_TEXT_AND_ICON 
= 2; 
1755         int ix 
= 0,     // init them just to suppress the compiler warnings 
1757         const int image 
= item
.m_image
; 
1758         wxImageListType 
*imageList
; 
1761             imageList 
= m_owner
->m_small_image_list
; 
1764                 imageList
->GetSize(image
, ix
, iy
); 
1765                 wLabel 
+= ix 
+ MARGIN_BETWEEN_TEXT_AND_ICON
; 
1773         // ignore alignment if there is not enough space anyhow 
1775         switch ( wLabel 
< cw 
? item
.GetAlign() : wxLIST_FORMAT_LEFT 
) 
1778                 wxFAIL_MSG( _T("unknown list item format") ); 
1781             case wxLIST_FORMAT_LEFT
: 
1785             case wxLIST_FORMAT_RIGHT
: 
1786                 xAligned 
= x 
+ cw 
- wLabel
; 
1789             case wxLIST_FORMAT_CENTER
: 
1790                 xAligned 
= x 
+ (cw 
- wLabel
) / 2; 
1795         // if we have an image, draw it on the right of the label 
1802                         xAligned 
+ wLabel 
- ix 
- MARGIN_BETWEEN_TEXT_AND_ICON
, 
1803                         HEADER_OFFSET_Y 
+ (h 
- 4 - iy
)/2, 
1804                         wxIMAGELIST_DRAW_TRANSPARENT
 
1807             cw 
-= ix 
+ MARGIN_BETWEEN_TEXT_AND_ICON
; 
1810         // draw the text clipping it so that it doesn't overwrite the column 
1812         wxDCClipper 
clipper(dc
, x
, HEADER_OFFSET_Y
, cw
, h 
- 4 ); 
1814         dc
.DrawText( item
.GetText(), 
1815                      xAligned 
+ EXTRA_WIDTH
, h 
/ 2 - hLabel 
/ 2 ); //HEADER_OFFSET_Y + EXTRA_HEIGHT ); 
1823 void wxListHeaderWindow::DrawCurrent() 
1825     int x1 
= m_currentX
; 
1827     m_owner
->ClientToScreen( &x1
, &y1 
); 
1829     int x2 
= m_currentX
; 
1831     m_owner
->GetClientSize( NULL
, &y2 
); 
1832     m_owner
->ClientToScreen( &x2
, &y2 
); 
1835     dc
.SetLogicalFunction( wxINVERT 
); 
1836     dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID 
) ); 
1837     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
1841     dc
.DrawLine( x1
, y1
, x2
, y2 
); 
1843     dc
.SetLogicalFunction( wxCOPY 
); 
1845     dc
.SetPen( wxNullPen 
); 
1846     dc
.SetBrush( wxNullBrush 
); 
1849 void wxListHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
1851     // we want to work with logical coords 
1853     m_owner
->CalcUnscrolledPosition(event
.GetX(), 0, &x
, NULL
); 
1854     int y 
= event
.GetY(); 
1858         SendListEvent(wxEVT_COMMAND_LIST_COL_DRAGGING
, event
.GetPosition()); 
1860         // we don't draw the line beyond our window, but we allow dragging it 
1863         GetClientSize( &w
, NULL 
); 
1864         m_owner
->CalcUnscrolledPosition(w
, 0, &w
, NULL
); 
1867         // erase the line if it was drawn 
1868         if ( m_currentX 
< w 
) 
1871         if (event
.ButtonUp()) 
1874             m_isDragging 
= false; 
1876             m_owner
->SetColumnWidth( m_column
, m_currentX 
- m_minX 
); 
1877             SendListEvent(wxEVT_COMMAND_LIST_COL_END_DRAG
, event
.GetPosition()); 
1884                 m_currentX 
= m_minX 
+ 7; 
1886             // draw in the new location 
1887             if ( m_currentX 
< w 
) 
1891     else // not dragging 
1894         bool hit_border 
= false; 
1896         // end of the current column 
1899         // find the column where this event occured 
1901             countCol 
= m_owner
->GetColumnCount(); 
1902         for (col 
= 0; col 
< countCol
; col
++) 
1904             xpos 
+= m_owner
->GetColumnWidth( col 
); 
1907             if ( (abs(x
-xpos
) < 3) && (y 
< 22) ) 
1909                 // near the column border 
1916                 // inside the column 
1923         if ( col 
== countCol 
) 
1926         if (event
.LeftDown() || event
.RightUp()) 
1928             if (hit_border 
&& event
.LeftDown()) 
1930                 if ( SendListEvent(wxEVT_COMMAND_LIST_COL_BEGIN_DRAG
, 
1931                                    event
.GetPosition()) ) 
1933                     m_isDragging 
= true; 
1938                 //else: column resizing was vetoed by the user code 
1940             else // click on a column 
1942                 SendListEvent( event
.LeftDown() 
1943                                     ? wxEVT_COMMAND_LIST_COL_CLICK
 
1944                                     : wxEVT_COMMAND_LIST_COL_RIGHT_CLICK
, 
1945                                 event
.GetPosition()); 
1948         else if (event
.Moving()) 
1953                 setCursor 
= m_currentCursor 
== wxSTANDARD_CURSOR
; 
1954                 m_currentCursor 
= m_resizeCursor
; 
1958                 setCursor 
= m_currentCursor 
!= wxSTANDARD_CURSOR
; 
1959                 m_currentCursor 
= wxSTANDARD_CURSOR
; 
1963                 SetCursor(*m_currentCursor
); 
1968 void wxListHeaderWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1970     m_owner
->SetFocus(); 
1974 bool wxListHeaderWindow::SendListEvent(wxEventType type
, wxPoint pos
) 
1976     wxWindow 
*parent 
= GetParent(); 
1977     wxListEvent 
le( type
, parent
->GetId() ); 
1978     le
.SetEventObject( parent 
); 
1979     le
.m_pointDrag 
= pos
; 
1981     // the position should be relative to the parent window, not 
1982     // this one for compatibility with MSW and common sense: the 
1983     // user code doesn't know anything at all about this header 
1984     // window, so why should it get positions relative to it? 
1985     le
.m_pointDrag
.y 
-= GetSize().y
; 
1987     le
.m_col 
= m_column
; 
1988     return !parent
->GetEventHandler()->ProcessEvent( le 
) || le
.IsAllowed(); 
1991 //----------------------------------------------------------------------------- 
1992 // wxListRenameTimer (internal) 
1993 //----------------------------------------------------------------------------- 
1995 wxListRenameTimer::wxListRenameTimer( wxListMainWindow 
*owner 
) 
2000 void wxListRenameTimer::Notify() 
2002     m_owner
->OnRenameTimer(); 
2005 //----------------------------------------------------------------------------- 
2006 // wxListTextCtrl (internal) 
2007 //----------------------------------------------------------------------------- 
2009 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
) 
2010     EVT_CHAR           (wxListTextCtrl::OnChar
) 
2011     EVT_KEY_UP         (wxListTextCtrl::OnKeyUp
) 
2012     EVT_KILL_FOCUS     (wxListTextCtrl::OnKillFocus
) 
2015 wxListTextCtrl::wxListTextCtrl(wxListMainWindow 
*owner
, size_t itemEdit
) 
2016               : m_startValue(owner
->GetItemText(itemEdit
)), 
2017                 m_itemEdited(itemEdit
) 
2022     wxRect rectLabel 
= owner
->GetLineLabelRect(itemEdit
); 
2024     m_owner
->CalcScrolledPosition(rectLabel
.x
, rectLabel
.y
, 
2025                                   &rectLabel
.x
, &rectLabel
.y
); 
2027     (void)Create(owner
, wxID_ANY
, m_startValue
, 
2028                  wxPoint(rectLabel
.x
-4,rectLabel
.y
-4), 
2029                  wxSize(rectLabel
.width
+11,rectLabel
.height
+8)); 
2032 void wxListTextCtrl::Finish() 
2036         wxPendingDelete
.Append(this); 
2040         m_owner
->SetFocus(); 
2044 bool wxListTextCtrl::AcceptChanges() 
2046     const wxString value 
= GetValue(); 
2048     if ( value 
== m_startValue 
) 
2050         // nothing changed, always accept 
2054     if ( !m_owner
->OnRenameAccept(m_itemEdited
, value
) ) 
2056         // vetoed by the user 
2060     // accepted, do rename the item 
2061     m_owner
->SetItemText(m_itemEdited
, value
); 
2066 void wxListTextCtrl::OnChar( wxKeyEvent 
&event 
) 
2068     switch ( event
.m_keyCode 
) 
2071             if ( !AcceptChanges() ) 
2073                 // vetoed by the user code 
2076             //else: fall through 
2080             m_owner
->OnRenameCancelled( m_itemEdited 
); 
2088 void wxListTextCtrl::OnKeyUp( wxKeyEvent 
&event 
) 
2096     // auto-grow the textctrl: 
2097     wxSize parentSize 
= m_owner
->GetSize(); 
2098     wxPoint myPos 
= GetPosition(); 
2099     wxSize mySize 
= GetSize(); 
2101     GetTextExtent(GetValue() + _T("MM"), &sx
, &sy
); 
2102     if (myPos
.x 
+ sx 
> parentSize
.x
) 
2103         sx 
= parentSize
.x 
- myPos
.x
; 
2106     SetSize(sx
, wxDefaultSize
.y
); 
2111 void wxListTextCtrl::OnKillFocus( wxFocusEvent 
&event 
) 
2115         // We must finish regardless of success, otherwise we'll get focus problems 
2118         if ( !AcceptChanges() ) 
2119             m_owner
->OnRenameCancelled( m_itemEdited 
); 
2125 //----------------------------------------------------------------------------- 
2127 //----------------------------------------------------------------------------- 
2129 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
) 
2131 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
) 
2132   EVT_PAINT          (wxListMainWindow::OnPaint
) 
2133   EVT_MOUSE_EVENTS   (wxListMainWindow::OnMouse
) 
2134   EVT_CHAR           (wxListMainWindow::OnChar
) 
2135   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown
) 
2136   EVT_SET_FOCUS      (wxListMainWindow::OnSetFocus
) 
2137   EVT_KILL_FOCUS     (wxListMainWindow::OnKillFocus
) 
2138   EVT_SCROLLWIN      (wxListMainWindow::OnScroll
) 
2141 void wxListMainWindow::Init() 
2146     m_lineTo 
= (size_t)-1; 
2152     m_small_image_list 
= (wxImageListType 
*) NULL
; 
2153     m_normal_image_list 
= (wxImageListType 
*) NULL
; 
2155     m_small_spacing 
= 30; 
2156     m_normal_spacing 
= 40; 
2160     m_isCreated 
= false; 
2162     m_lastOnSame 
= false; 
2163     m_renameTimer 
= new wxListRenameTimer( this ); 
2167     m_lineBeforeLastClicked 
= (size_t)-1; 
2172 wxListMainWindow::wxListMainWindow() 
2177     m_highlightUnfocusedBrush 
= (wxBrush 
*) NULL
; 
2180 wxListMainWindow::wxListMainWindow( wxWindow 
*parent
, 
2185                                     const wxString 
&name 
) 
2186                 : wxScrolledWindow( parent
, id
, pos
, size
, 
2187                                     style 
| wxHSCROLL 
| wxVSCROLL
, name 
) 
2191     m_highlightBrush 
= new wxBrush
 
2193                             wxSystemSettings::GetColour
 
2195                                 wxSYS_COLOUR_HIGHLIGHT
 
2200     m_highlightUnfocusedBrush 
= new wxBrush
 
2202                                        wxSystemSettings::GetColour
 
2204                                            wxSYS_COLOUR_BTNSHADOW
 
2212     SetScrollbars( 0, 0, 0, 0, 0, 0 ); 
2214     wxVisualAttributes attr 
= wxGenericListCtrl::GetClassDefaultAttributes(); 
2215     SetOwnForegroundColour( attr
.colFg 
); 
2216     SetOwnBackgroundColour( attr
.colBg 
); 
2217     SetOwnFont( attr
.font 
); 
2220 wxListMainWindow::~wxListMainWindow() 
2223     WX_CLEAR_LIST(wxListHeaderDataList
, m_columns
); 
2225     delete m_highlightBrush
; 
2226     delete m_highlightUnfocusedBrush
; 
2228     delete m_renameTimer
; 
2231 void wxListMainWindow::CacheLineData(size_t line
) 
2233     wxGenericListCtrl 
*listctrl 
= GetListCtrl(); 
2235     wxListLineData 
*ld 
= GetDummyLine(); 
2237     size_t countCol 
= GetColumnCount(); 
2238     for ( size_t col 
= 0; col 
< countCol
; col
++ ) 
2240         ld
->SetText(col
, listctrl
->OnGetItemText(line
, col
)); 
2243     ld
->SetImage(listctrl
->OnGetItemImage(line
)); 
2244     ld
->SetAttr(listctrl
->OnGetItemAttr(line
)); 
2247 wxListLineData 
*wxListMainWindow::GetDummyLine() const 
2249     wxASSERT_MSG( !IsEmpty(), _T("invalid line index") ); 
2251     wxASSERT_MSG( IsVirtual(), _T("GetDummyLine() shouldn't be called") ); 
2253     wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
2255     // we need to recreate the dummy line if the number of columns in the 
2256     // control changed as it would have the incorrect number of fields 
2258     if ( !m_lines
.IsEmpty() && 
2259             m_lines
[0].m_items
.GetCount() != (size_t)GetColumnCount() ) 
2261         self
->m_lines
.Clear(); 
2264     if ( m_lines
.IsEmpty() ) 
2266         wxListLineData 
*line 
= new wxListLineData(self
); 
2267         self
->m_lines
.Add(line
); 
2269         // don't waste extra memory -- there never going to be anything 
2270         // else/more in this array 
2271         self
->m_lines
.Shrink(); 
2277 // ---------------------------------------------------------------------------- 
2278 // line geometry (report mode only) 
2279 // ---------------------------------------------------------------------------- 
2281 wxCoord 
wxListMainWindow::GetLineHeight() const 
2283     // we cache the line height as calling GetTextExtent() is slow 
2284     if ( !m_lineHeight 
) 
2286         wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
2288         wxClientDC 
dc( self 
); 
2289         dc
.SetFont( GetFont() ); 
2292         dc
.GetTextExtent(_T("H"), NULL
, &y
); 
2294         if ( m_small_image_list 
&& m_small_image_list
->GetImageCount() ) 
2298             m_small_image_list
->GetSize(0, iw
, ih
); 
2303         self
->m_lineHeight 
= y 
+ LINE_SPACING
; 
2306     return m_lineHeight
; 
2309 wxCoord 
wxListMainWindow::GetLineY(size_t line
) const 
2311     wxASSERT_MSG( InReportView(), _T("only works in report mode") ); 
2313     return LINE_SPACING 
+ line
*GetLineHeight(); 
2316 wxRect 
wxListMainWindow::GetLineRect(size_t line
) const 
2318     if ( !InReportView() ) 
2319         return GetLine(line
)->m_gi
->m_rectAll
; 
2322     rect
.x 
= HEADER_OFFSET_X
; 
2323     rect
.y 
= GetLineY(line
); 
2324     rect
.width 
= GetHeaderWidth(); 
2325     rect
.height 
= GetLineHeight(); 
2330 wxRect 
wxListMainWindow::GetLineLabelRect(size_t line
) const 
2332     if ( !InReportView() ) 
2333         return GetLine(line
)->m_gi
->m_rectLabel
; 
2336     rect
.x 
= HEADER_OFFSET_X
; 
2337     rect
.y 
= GetLineY(line
); 
2338     rect
.width 
= GetColumnWidth(0); 
2339     rect
.height 
= GetLineHeight(); 
2344 wxRect 
wxListMainWindow::GetLineIconRect(size_t line
) const 
2346     if ( !InReportView() ) 
2347         return GetLine(line
)->m_gi
->m_rectIcon
; 
2349     wxListLineData 
*ld 
= GetLine(line
); 
2350     wxASSERT_MSG( ld
->HasImage(), _T("should have an image") ); 
2353     rect
.x 
= HEADER_OFFSET_X
; 
2354     rect
.y 
= GetLineY(line
); 
2355     GetImageSize(ld
->GetImage(), rect
.width
, rect
.height
); 
2360 wxRect 
wxListMainWindow::GetLineHighlightRect(size_t line
) const 
2362     return InReportView() ? GetLineRect(line
) 
2363                           : GetLine(line
)->m_gi
->m_rectHighlight
; 
2366 long wxListMainWindow::HitTestLine(size_t line
, int x
, int y
) const 
2368     wxASSERT_MSG( line 
< GetItemCount(), _T("invalid line in HitTestLine") ); 
2370     wxListLineData 
*ld 
= GetLine(line
); 
2372     if ( ld
->HasImage() && GetLineIconRect(line
).Inside(x
, y
) ) 
2373         return wxLIST_HITTEST_ONITEMICON
; 
2375     // VS: Testing for "ld->HasText() || InReportView()" instead of 
2376     //     "ld->HasText()" is needed to make empty lines in report view 
2378     if ( ld
->HasText() || InReportView() ) 
2380         wxRect rect 
= InReportView() ? GetLineRect(line
) 
2381                                      : GetLineLabelRect(line
); 
2383         if ( rect
.Inside(x
, y
) ) 
2384             return wxLIST_HITTEST_ONITEMLABEL
; 
2390 // ---------------------------------------------------------------------------- 
2391 // highlight (selection) handling 
2392 // ---------------------------------------------------------------------------- 
2394 bool wxListMainWindow::IsHighlighted(size_t line
) const 
2398         return m_selStore
.IsSelected(line
); 
2402         wxListLineData 
*ld 
= GetLine(line
); 
2403         wxCHECK_MSG( ld
, false, _T("invalid index in IsHighlighted") ); 
2405         return ld
->IsHighlighted(); 
2409 void wxListMainWindow::HighlightLines( size_t lineFrom
, 
2415         wxArrayInt linesChanged
; 
2416         if ( !m_selStore
.SelectRange(lineFrom
, lineTo
, highlight
, 
2419             // meny items changed state, refresh everything 
2420             RefreshLines(lineFrom
, lineTo
); 
2422         else // only a few items changed state, refresh only them 
2424             size_t count 
= linesChanged
.GetCount(); 
2425             for ( size_t n 
= 0; n 
< count
; n
++ ) 
2427                 RefreshLine(linesChanged
[n
]); 
2431     else // iterate over all items in non report view 
2433         for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
2435             if ( HighlightLine(line
, highlight
) ) 
2443 bool wxListMainWindow::HighlightLine( size_t line
, bool highlight 
) 
2449         changed 
= m_selStore
.SelectItem(line
, highlight
); 
2453         wxListLineData 
*ld 
= GetLine(line
); 
2454         wxCHECK_MSG( ld
, false, _T("invalid index in HighlightLine") ); 
2456         changed 
= ld
->Highlight(highlight
); 
2461         SendNotify( line
, highlight 
? wxEVT_COMMAND_LIST_ITEM_SELECTED
 
2462                                     : wxEVT_COMMAND_LIST_ITEM_DESELECTED 
); 
2468 void wxListMainWindow::RefreshLine( size_t line 
) 
2470     if ( InReportView() ) 
2472         size_t visibleFrom
, visibleTo
; 
2473         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2475         if ( line 
< visibleFrom 
|| line 
> visibleTo 
) 
2479     wxRect rect 
= GetLineRect(line
); 
2481     CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2482     RefreshRect( rect 
); 
2485 void wxListMainWindow::RefreshLines( size_t lineFrom
, size_t lineTo 
) 
2487     // we suppose that they are ordered by caller 
2488     wxASSERT_MSG( lineFrom 
<= lineTo
, _T("indices in disorder") ); 
2490     wxASSERT_MSG( lineTo 
< GetItemCount(), _T("invalid line range") ); 
2492     if ( InReportView() ) 
2494         size_t visibleFrom
, visibleTo
; 
2495         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2497         if ( lineFrom 
< visibleFrom 
) 
2498             lineFrom 
= visibleFrom
; 
2499         if ( lineTo 
> visibleTo 
) 
2504         rect
.y 
= GetLineY(lineFrom
); 
2505         rect
.width 
= GetClientSize().x
; 
2506         rect
.height 
= GetLineY(lineTo
) - rect
.y 
+ GetLineHeight(); 
2508         CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2509         RefreshRect( rect 
); 
2513         // TODO: this should be optimized... 
2514         for ( size_t line 
= lineFrom
; line 
<= lineTo
; line
++ ) 
2521 void wxListMainWindow::RefreshAfter( size_t lineFrom 
) 
2523     if ( InReportView() ) 
2525         size_t visibleFrom
, visibleTo
; 
2526         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2528         if ( lineFrom 
< visibleFrom 
) 
2529             lineFrom 
= visibleFrom
; 
2530         else if ( lineFrom 
> visibleTo 
) 
2535         rect
.y 
= GetLineY(lineFrom
); 
2536         CalcScrolledPosition( rect
.x
, rect
.y
, &rect
.x
, &rect
.y 
); 
2538         wxSize size 
= GetClientSize(); 
2539         rect
.width 
= size
.x
; 
2540         // refresh till the bottom of the window 
2541         rect
.height 
= size
.y 
- rect
.y
; 
2543         RefreshRect( rect 
); 
2547         // TODO: how to do it more efficiently? 
2552 void wxListMainWindow::RefreshSelected() 
2558     if ( InReportView() ) 
2560         GetVisibleLinesRange(&from
, &to
); 
2565         to 
= GetItemCount() - 1; 
2568     if ( HasCurrent() && m_current 
>= from 
&& m_current 
<= to 
) 
2570         RefreshLine(m_current
); 
2573     for ( size_t line 
= from
; line 
<= to
; line
++ ) 
2575         // NB: the test works as expected even if m_current == -1 
2576         if ( line 
!= m_current 
&& IsHighlighted(line
) ) 
2583 void wxListMainWindow::Freeze() 
2588 void wxListMainWindow::Thaw() 
2590     wxCHECK_RET( m_freezeCount 
> 0, _T("thawing unfrozen list control?") ); 
2592     if ( !--m_freezeCount 
) 
2598 void wxListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
2600     // Note: a wxPaintDC must be constructed even if no drawing is 
2601     // done (a Windows requirement). 
2602     wxPaintDC 
dc( this ); 
2604     if ( IsEmpty() || m_freezeCount 
) 
2606         // nothing to draw or not the moment to draw it 
2612         // delay the repainting until we calculate all the items positions 
2619     CalcScrolledPosition( 0, 0, &dev_x
, &dev_y 
); 
2623     dc
.SetFont( GetFont() ); 
2625     if ( InReportView() ) 
2627         int lineHeight 
= GetLineHeight(); 
2629         size_t visibleFrom
, visibleTo
; 
2630         GetVisibleLinesRange(&visibleFrom
, &visibleTo
); 
2633         wxCoord xOrig
, yOrig
; 
2634         CalcUnscrolledPosition(0, 0, &xOrig
, &yOrig
); 
2636         // tell the caller cache to cache the data 
2639             wxListEvent 
evCache(wxEVT_COMMAND_LIST_CACHE_HINT
, 
2640                                 GetParent()->GetId()); 
2641             evCache
.SetEventObject( GetParent() ); 
2642             evCache
.m_oldItemIndex 
= visibleFrom
; 
2643             evCache
.m_itemIndex 
= visibleTo
; 
2644             GetParent()->GetEventHandler()->ProcessEvent( evCache 
); 
2647         for ( size_t line 
= visibleFrom
; line 
<= visibleTo
; line
++ ) 
2649             rectLine 
= GetLineRect(line
); 
2651             if ( !IsExposed(rectLine
.x 
- xOrig
, rectLine
.y 
- yOrig
, 
2652                             rectLine
.width
, rectLine
.height
) ) 
2654                 // don't redraw unaffected lines to avoid flicker 
2658             GetLine(line
)->DrawInReportMode( &dc
, 
2660                                              GetLineHighlightRect(line
), 
2661                                              IsHighlighted(line
) ); 
2664         if ( HasFlag(wxLC_HRULES
) ) 
2666             wxPen 
pen(GetRuleColour(), 1, wxSOLID
); 
2667             wxSize clientSize 
= GetClientSize(); 
2669             // Don't draw the first one 
2670             for ( size_t i 
= visibleFrom
+1; i 
<= visibleTo
; i
++ ) 
2673                 dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2674                 dc
.DrawLine(0 - dev_x
, i
*lineHeight
, 
2675                             clientSize
.x 
- dev_x
, i
*lineHeight
); 
2678             // Draw last horizontal rule 
2679             if ( visibleTo 
== GetItemCount() - 1 ) 
2682                 dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2683                 dc
.DrawLine(0 - dev_x
, (m_lineTo
+1)*lineHeight
, 
2684                             clientSize
.x 
- dev_x 
, (m_lineTo
+1)*lineHeight 
); 
2688         // Draw vertical rules if required 
2689         if ( HasFlag(wxLC_VRULES
) && !IsEmpty() ) 
2691             wxPen 
pen(GetRuleColour(), 1, wxSOLID
); 
2693             wxRect firstItemRect
; 
2694             wxRect lastItemRect
; 
2695             GetItemRect(visibleFrom
, firstItemRect
); 
2696             GetItemRect(visibleTo
, lastItemRect
); 
2697             int x 
= firstItemRect
.GetX(); 
2699             dc
.SetBrush(* wxTRANSPARENT_BRUSH
); 
2700             for (int col 
= 0; col 
< GetColumnCount(); col
++) 
2702                 int colWidth 
= GetColumnWidth(col
); 
2704                 dc
.DrawLine(x 
- dev_x 
- 2, firstItemRect
.GetY() - 1 - dev_y
, 
2705                             x 
- dev_x 
- 2, lastItemRect
.GetBottom() + 1 - dev_y
); 
2711         size_t count 
= GetItemCount(); 
2712         for ( size_t i 
= 0; i 
< count
; i
++ ) 
2714             GetLine(i
)->Draw( &dc 
); 
2719     // Don't draw rect outline under Mac at all. 
2724             dc
.SetPen( *wxBLACK_PEN 
); 
2725             dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
2726             dc
.DrawRectangle( GetLineHighlightRect(m_current
) ); 
2734 void wxListMainWindow::HighlightAll( bool on 
) 
2736     if ( IsSingleSel() ) 
2738         wxASSERT_MSG( !on
, _T("can't do this in a single sel control") ); 
2740         // we just have one item to turn off 
2741         if ( HasCurrent() && IsHighlighted(m_current
) ) 
2743             HighlightLine(m_current
, false); 
2744             RefreshLine(m_current
); 
2749         HighlightLines(0, GetItemCount() - 1, on
); 
2753 void wxListMainWindow::SendNotify( size_t line
, 
2754                                    wxEventType command
, 
2757     wxListEvent 
le( command
, GetParent()->GetId() ); 
2758     le
.SetEventObject( GetParent() ); 
2759     le
.m_itemIndex 
= line
; 
2761     // set only for events which have position 
2762     if ( point 
!= wxDefaultPosition 
) 
2763         le
.m_pointDrag 
= point
; 
2765     // don't try to get the line info for virtual list controls: the main 
2766     // program has it anyhow and if we did it would result in accessing all 
2767     // the lines, even those which are not visible now and this is precisely 
2768     // what we're trying to avoid 
2769     if ( !IsVirtual() && (command 
!= wxEVT_COMMAND_LIST_DELETE_ITEM
) ) 
2771         if ( line 
!= (size_t)-1 ) 
2773             GetLine(line
)->GetItem( 0, le
.m_item 
); 
2775         //else: this happens for wxEVT_COMMAND_LIST_ITEM_FOCUSED event 
2777     //else: there may be no more such item 
2779     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2782 void wxListMainWindow::ChangeCurrent(size_t current
) 
2784     m_current 
= current
; 
2786     SendNotify(current
, wxEVT_COMMAND_LIST_ITEM_FOCUSED
); 
2789 void wxListMainWindow::EditLabel( long item 
) 
2791     wxCHECK_RET( (item 
>= 0) && ((size_t)item 
< GetItemCount()), 
2792                  wxT("wrong index in wxGenericListCtrl::EditLabel()") ); 
2794     size_t itemEdit 
= (size_t)item
; 
2796     wxListEvent 
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() ); 
2797     le
.SetEventObject( GetParent() ); 
2798     le
.m_itemIndex 
= item
; 
2799     wxListLineData 
*data 
= GetLine(itemEdit
); 
2800     wxCHECK_RET( data
, _T("invalid index in EditLabel()") ); 
2801     data
->GetItem( 0, le
.m_item 
); 
2802     if ( GetParent()->GetEventHandler()->ProcessEvent( le 
) && !le
.IsAllowed() ) 
2804         // vetoed by user code 
2808     // We have to call this here because the label in question might just have 
2809     // been added and no screen update taken place. 
2813     wxListTextCtrl 
*text 
= new wxListTextCtrl(this, itemEdit
); 
2818 void wxListMainWindow::OnRenameTimer() 
2820     wxCHECK_RET( HasCurrent(), wxT("unexpected rename timer") ); 
2822     EditLabel( m_current 
); 
2825 bool wxListMainWindow::OnRenameAccept(size_t itemEdit
, const wxString
& value
) 
2827     wxListEvent 
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() ); 
2828     le
.SetEventObject( GetParent() ); 
2829     le
.m_itemIndex 
= itemEdit
; 
2831     wxListLineData 
*data 
= GetLine(itemEdit
); 
2832     wxCHECK_MSG( data
, false, _T("invalid index in OnRenameAccept()") ); 
2834     data
->GetItem( 0, le
.m_item 
); 
2835     le
.m_item
.m_text 
= value
; 
2836     return !GetParent()->GetEventHandler()->ProcessEvent( le 
) || 
2840 void wxListMainWindow::OnRenameCancelled(size_t itemEdit
) 
2842     // let owner know that the edit was cancelled 
2843     wxListEvent 
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() ); 
2845     le
.SetEditCanceled(true); 
2847     le
.SetEventObject( GetParent() ); 
2848     le
.m_itemIndex 
= itemEdit
; 
2850     wxListLineData 
*data 
= GetLine(itemEdit
); 
2851     wxCHECK_RET( data
, _T("invalid index in OnRenameCancelled()") ); 
2853     data
->GetItem( 0, le
.m_item 
); 
2855     GetEventHandler()->ProcessEvent( le 
); 
2858 void wxListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
2860     event
.SetEventObject( GetParent() ); 
2861     if ( GetParent()->GetEventHandler()->ProcessEvent( event
) ) 
2864     if ( !HasCurrent() || IsEmpty() ) 
2870     if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() || 
2871         event
.ButtonDClick()) ) 
2874     int x 
= event
.GetX(); 
2875     int y 
= event
.GetY(); 
2876     CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
2878     // where did we hit it (if we did)? 
2881     size_t count 
= GetItemCount(), 
2884     if ( InReportView() ) 
2886         current 
= y 
/ GetLineHeight(); 
2887         if ( current 
< count 
) 
2888             hitResult 
= HitTestLine(current
, x
, y
); 
2892         // TODO: optimize it too! this is less simple than for report view but 
2893         //       enumerating all items is still not a way to do it!! 
2894         for ( current 
= 0; current 
< count
; current
++ ) 
2896             hitResult 
= HitTestLine(current
, x
, y
); 
2902     if (event
.Dragging()) 
2904         if (m_dragCount 
== 0) 
2906             // we have to report the raw, physical coords as we want to be 
2907             // able to call HitTest(event.m_pointDrag) from the user code to 
2908             // get the item being dragged 
2909             m_dragStart 
= event
.GetPosition(); 
2914         if (m_dragCount 
!= 3) 
2917         int command 
= event
.RightIsDown() ? wxEVT_COMMAND_LIST_BEGIN_RDRAG
 
2918                                           : wxEVT_COMMAND_LIST_BEGIN_DRAG
; 
2920         wxListEvent 
le( command
, GetParent()->GetId() ); 
2921         le
.SetEventObject( GetParent() ); 
2922         le
.m_itemIndex 
= current
; 
2923         le
.m_pointDrag 
= m_dragStart
; 
2924         GetParent()->GetEventHandler()->ProcessEvent( le 
); 
2935         // outside of any item 
2939     bool forceClick 
= false; 
2940     if (event
.ButtonDClick()) 
2942         m_renameTimer
->Stop(); 
2943         m_lastOnSame 
= false; 
2945         if ( current 
== m_lineLastClicked 
) 
2947             SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
2953             // the first click was on another item, so don't interpret this as 
2954             // a double click, but as a simple click instead 
2959     if (event
.LeftUp() && m_lastOnSame
) 
2961         if ((current 
== m_current
) && 
2962             (hitResult 
== wxLIST_HITTEST_ONITEMLABEL
) && 
2963             HasFlag(wxLC_EDIT_LABELS
)  ) 
2965             m_renameTimer
->Start( 100, true ); 
2967         m_lastOnSame 
= false; 
2969     else if (event
.RightDown()) 
2971         SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK
, 
2972                     event
.GetPosition() ); 
2974     else if (event
.MiddleDown()) 
2976         SendNotify( current
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK 
); 
2978     else if ( event
.LeftDown() || forceClick 
) 
2980         m_lineBeforeLastClicked 
= m_lineLastClicked
; 
2981         m_lineLastClicked 
= current
; 
2983         size_t oldCurrent 
= m_current
; 
2984         bool cmdModifierDown 
= event
.CmdDown(); 
2985         if ( IsSingleSel() || !(cmdModifierDown 
|| event
.ShiftDown()) ) 
2987             HighlightAll( false ); 
2989             ChangeCurrent(current
); 
2991             ReverseHighlight(m_current
); 
2993         else // multi sel & either ctrl or shift is down 
2995             if (cmdModifierDown
) 
2997                 ChangeCurrent(current
); 
2999                 ReverseHighlight(m_current
); 
3001             else if (event
.ShiftDown()) 
3003                 ChangeCurrent(current
); 
3005                 size_t lineFrom 
= oldCurrent
, 
3008                 if ( lineTo 
< lineFrom 
) 
3011                     lineFrom 
= m_current
; 
3014                 HighlightLines(lineFrom
, lineTo
); 
3016             else // !ctrl, !shift 
3018                 // test in the enclosing if should make it impossible 
3019                 wxFAIL_MSG( _T("how did we get here?") ); 
3023         if (m_current 
!= oldCurrent
) 
3025             RefreshLine( oldCurrent 
); 
3028         // forceClick is only set if the previous click was on another item 
3029         m_lastOnSame 
= !forceClick 
&& (m_current 
== oldCurrent
); 
3033 void wxListMainWindow::MoveToItem(size_t item
) 
3035     if ( item 
== (size_t)-1 ) 
3038     wxRect rect 
= GetLineRect(item
); 
3040     int client_w
, client_h
; 
3041     GetClientSize( &client_w
, &client_h 
); 
3043     const int hLine 
= GetLineHeight(); 
3045     int view_x 
= SCROLL_UNIT_X
*GetScrollPos( wxHORIZONTAL 
); 
3046     int view_y 
= hLine
*GetScrollPos( wxVERTICAL 
); 
3048     if ( InReportView() ) 
3050         // the next we need the range of lines shown it might be different, so 
3052         ResetVisibleLinesRange(); 
3054         if (rect
.y 
< view_y 
) 
3055             Scroll( -1, rect
.y
/hLine 
); 
3056         if (rect
.y
+rect
.height
+5 > view_y
+client_h
) 
3057             Scroll( -1, (rect
.y
+rect
.height
-client_h
+hLine
)/hLine 
); 
3061         if (rect
.x
-view_x 
< 5) 
3062             Scroll( (rect
.x
-5)/SCROLL_UNIT_X
, -1 ); 
3063         if (rect
.x
+rect
.width
-5 > view_x
+client_w
) 
3064             Scroll( (rect
.x
+rect
.width
-client_w
+SCROLL_UNIT_X
)/SCROLL_UNIT_X
, -1 ); 
3068 // ---------------------------------------------------------------------------- 
3069 // keyboard handling 
3070 // ---------------------------------------------------------------------------- 
3072 void wxListMainWindow::OnArrowChar(size_t newCurrent
, const wxKeyEvent
& event
) 
3074     wxCHECK_RET( newCurrent 
< (size_t)GetItemCount(), 
3075                  _T("invalid item index in OnArrowChar()") ); 
3077     size_t oldCurrent 
= m_current
; 
3079     // in single selection we just ignore Shift as we can't select several 
3081     if ( event
.ShiftDown() && !IsSingleSel() ) 
3083         ChangeCurrent(newCurrent
); 
3085         // refresh the old focus to remove it 
3086         RefreshLine( oldCurrent 
); 
3088         // select all the items between the old and the new one 
3089         if ( oldCurrent 
> newCurrent 
) 
3091             newCurrent 
= oldCurrent
; 
3092             oldCurrent 
= m_current
; 
3095         HighlightLines(oldCurrent
, newCurrent
); 
3099         // all previously selected items are unselected unless ctrl is held 
3100         if ( !event
.ControlDown() ) 
3101             HighlightAll(false); 
3103         ChangeCurrent(newCurrent
); 
3105         // refresh the old focus to remove it 
3106         RefreshLine( oldCurrent 
); 
3108         if ( !event
.ControlDown() ) 
3110             HighlightLine( m_current
, true ); 
3114     RefreshLine( m_current 
); 
3119 void wxListMainWindow::OnKeyDown( wxKeyEvent 
&event 
) 
3121     wxWindow 
*parent 
= GetParent(); 
3123     /* we propagate the key event up */ 
3124     wxKeyEvent 
ke( wxEVT_KEY_DOWN 
); 
3125     ke
.m_shiftDown 
= event
.m_shiftDown
; 
3126     ke
.m_controlDown 
= event
.m_controlDown
; 
3127     ke
.m_altDown 
= event
.m_altDown
; 
3128     ke
.m_metaDown 
= event
.m_metaDown
; 
3129     ke
.m_keyCode 
= event
.m_keyCode
; 
3132     ke
.SetEventObject( parent 
); 
3133     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
3138 void wxListMainWindow::OnChar( wxKeyEvent 
&event 
) 
3140     wxWindow 
*parent 
= GetParent(); 
3142     /* we send a list_key event up */ 
3145         wxListEvent 
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() ); 
3146         le
.m_itemIndex 
= m_current
; 
3147         GetLine(m_current
)->GetItem( 0, le
.m_item 
); 
3148         le
.m_code 
= event
.GetKeyCode(); 
3149         le
.SetEventObject( parent 
); 
3150         parent
->GetEventHandler()->ProcessEvent( le 
); 
3153     /* we propagate the char event up */ 
3154     wxKeyEvent 
ke( wxEVT_CHAR 
); 
3155     ke
.m_shiftDown 
= event
.m_shiftDown
; 
3156     ke
.m_controlDown 
= event
.m_controlDown
; 
3157     ke
.m_altDown 
= event
.m_altDown
; 
3158     ke
.m_metaDown 
= event
.m_metaDown
; 
3159     ke
.m_keyCode 
= event
.m_keyCode
; 
3162     ke
.SetEventObject( parent 
); 
3163     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
3165     if (event
.GetKeyCode() == WXK_TAB
) 
3167         wxNavigationKeyEvent nevent
; 
3168         nevent
.SetWindowChange( event
.ControlDown() ); 
3169         nevent
.SetDirection( !event
.ShiftDown() ); 
3170         nevent
.SetEventObject( GetParent()->GetParent() ); 
3171         nevent
.SetCurrentFocus( m_parent 
); 
3172         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) 
3176     /* no item -> nothing to do */ 
3183     switch (event
.GetKeyCode()) 
3186             if ( m_current 
> 0 ) 
3187                 OnArrowChar( m_current 
- 1, event 
); 
3191             if ( m_current 
< (size_t)GetItemCount() - 1 ) 
3192                 OnArrowChar( m_current 
+ 1, event 
); 
3197                 OnArrowChar( GetItemCount() - 1, event 
); 
3202                 OnArrowChar( 0, event 
); 
3207                 int steps 
= InReportView() ? m_linesPerPage 
- 1 : m_current 
% m_linesPerPage
; 
3209                 int index 
= m_current 
- steps
; 
3213                 OnArrowChar( index
, event 
); 
3219                 int steps 
= InReportView() 
3220                                ? m_linesPerPage 
- 1 
3221                                : m_linesPerPage 
- (m_current 
% m_linesPerPage
) - 1; 
3223                 size_t index 
= m_current 
+ steps
; 
3224                 size_t count 
= GetItemCount(); 
3225                 if ( index 
>= count 
) 
3228                 OnArrowChar( index
, event 
); 
3233             if ( !InReportView() ) 
3235                 int index 
= m_current 
- m_linesPerPage
; 
3239                 OnArrowChar( index
, event 
); 
3244             if ( !InReportView() ) 
3246                 size_t index 
= m_current 
+ m_linesPerPage
; 
3248                 size_t count 
= GetItemCount(); 
3249                 if ( index 
>= count 
) 
3252                 OnArrowChar( index
, event 
); 
3257             if ( IsSingleSel() ) 
3259                 SendNotify( m_current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
3261                 if ( IsHighlighted(m_current
) ) 
3263                     // don't unselect the item in single selection mode 
3266                 //else: select it in ReverseHighlight() below if unselected 
3269             ReverseHighlight(m_current
); 
3274             SendNotify( m_current
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
3282 // ---------------------------------------------------------------------------- 
3284 // ---------------------------------------------------------------------------- 
3286 void wxListMainWindow::SetFocus() 
3288     // VS: wxListMainWindow derives from wxPanel (via wxScrolledWindow) and wxPanel 
3289     //     overrides SetFocus in such way that it does never change focus from 
3290     //     panel's child to the panel itself. Unfortunately, we must be able to change 
3291     //     focus to the panel from wxListTextCtrl because the text control should 
3292     //     disappear when the user clicks outside it. 
3294     wxWindow 
*oldFocus 
= FindFocus(); 
3296     if ( oldFocus 
&& oldFocus
->GetParent() == this ) 
3298         wxWindow::SetFocus(); 
3302         wxScrolledWindow::SetFocus(); 
3306 void wxListMainWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
3310         wxFocusEvent 
event( wxEVT_SET_FOCUS
, GetParent()->GetId() ); 
3311         event
.SetEventObject( GetParent() ); 
3312         if ( GetParent()->GetEventHandler()->ProcessEvent( event
) ) 
3316     // wxGTK sends us EVT_SET_FOCUS events even if we had never got 
3317     // EVT_KILL_FOCUS before which means that we finish by redrawing the items 
3318     // which are already drawn correctly resulting in horrible flicker - avoid 
3328 void wxListMainWindow::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
3332         wxFocusEvent 
event( wxEVT_KILL_FOCUS
, GetParent()->GetId() ); 
3333         event
.SetEventObject( GetParent() ); 
3334         if ( GetParent()->GetEventHandler()->ProcessEvent( event
) ) 
3341 void wxListMainWindow::DrawImage( int index
, wxDC 
*dc
, int x
, int y 
) 
3343     if ( HasFlag(wxLC_ICON
) && (m_normal_image_list
)) 
3345         m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3347     else if ( HasFlag(wxLC_SMALL_ICON
) && (m_small_image_list
)) 
3349         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3351     else if ( HasFlag(wxLC_LIST
) && (m_small_image_list
)) 
3353         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3355     else if ( InReportView() && (m_small_image_list
)) 
3357         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
3361 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height 
) const 
3363     if ( HasFlag(wxLC_ICON
) && m_normal_image_list 
) 
3365         m_normal_image_list
->GetSize( index
, width
, height 
); 
3367     else if ( HasFlag(wxLC_SMALL_ICON
) && m_small_image_list 
) 
3369         m_small_image_list
->GetSize( index
, width
, height 
); 
3371     else if ( HasFlag(wxLC_LIST
) && m_small_image_list 
) 
3373         m_small_image_list
->GetSize( index
, width
, height 
); 
3375     else if ( InReportView() && m_small_image_list 
) 
3377         m_small_image_list
->GetSize( index
, width
, height 
); 
3386 int wxListMainWindow::GetTextLength( const wxString 
&s 
) const 
3388     wxClientDC 
dc( wxConstCast(this, wxListMainWindow
) ); 
3389     dc
.SetFont( GetFont() ); 
3392     dc
.GetTextExtent( s
, &lw
, NULL 
); 
3394     return lw 
+ AUTOSIZE_COL_MARGIN
; 
3397 void wxListMainWindow::SetImageList( wxImageListType 
*imageList
, int which 
) 
3401     // calc the spacing from the icon size 
3404     if ((imageList
) && (imageList
->GetImageCount()) ) 
3406         imageList
->GetSize(0, width
, height
); 
3409     if (which 
== wxIMAGE_LIST_NORMAL
) 
3411         m_normal_image_list 
= imageList
; 
3412         m_normal_spacing 
= width 
+ 8; 
3415     if (which 
== wxIMAGE_LIST_SMALL
) 
3417         m_small_image_list 
= imageList
; 
3418         m_small_spacing 
= width 
+ 14; 
3419         m_lineHeight 
= 0;  // ensure that the line height will be recalc'd 
3423 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall 
) 
3428         m_small_spacing 
= spacing
; 
3432         m_normal_spacing 
= spacing
; 
3436 int wxListMainWindow::GetItemSpacing( bool isSmall 
) 
3438     return isSmall 
? m_small_spacing 
: m_normal_spacing
; 
3441 // ---------------------------------------------------------------------------- 
3443 // ---------------------------------------------------------------------------- 
3445 void wxListMainWindow::SetColumn( int col
, wxListItem 
&item 
) 
3447     wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
3449     wxCHECK_RET( node
, _T("invalid column index in SetColumn") ); 
3451     if ( item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER 
) 
3452         item
.m_width 
= GetTextLength( item
.m_text 
); 
3454     wxListHeaderData 
*column 
= node
->GetData(); 
3455     column
->SetItem( item 
); 
3457     wxListHeaderWindow 
*headerWin 
= GetListCtrl()->m_headerWin
; 
3459         headerWin
->m_dirty 
= true; 
3463     // invalidate it as it has to be recalculated 
3467 void wxListMainWindow::SetColumnWidth( int col
, int width 
) 
3469     wxCHECK_RET( col 
>= 0 && col 
< GetColumnCount(), 
3470                  _T("invalid column index") ); 
3472     wxCHECK_RET( InReportView(), 
3473                  _T("SetColumnWidth() can only be called in report mode.") ); 
3476     wxListHeaderWindow 
*headerWin 
= GetListCtrl()->m_headerWin
; 
3478         headerWin
->m_dirty 
= true; 
3480     wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
3481     wxCHECK_RET( node
, _T("no column?") ); 
3483     wxListHeaderData 
*column 
= node
->GetData(); 
3485     size_t count 
= GetItemCount(); 
3487     if (width 
== wxLIST_AUTOSIZE_USEHEADER
) 
3489         width 
= GetTextLength(column
->GetText()); 
3491     else if ( width 
== wxLIST_AUTOSIZE 
) 
3495             // TODO: determine the max width somehow... 
3496             width 
= WIDTH_COL_DEFAULT
; 
3500             wxClientDC 
dc(this); 
3501             dc
.SetFont( GetFont() ); 
3503             int max 
= AUTOSIZE_COL_MARGIN
; 
3505             for ( size_t i 
= 0; i 
< count
; i
++ ) 
3507                 wxListLineData 
*line 
= GetLine(i
); 
3508                 wxListItemDataList::compatibility_iterator n 
= line
->m_items
.Item( col 
); 
3510                 wxCHECK_RET( n
, _T("no subitem?") ); 
3512                 wxListItemData 
*item 
= n
->GetData(); 
3515                 if (item
->HasImage()) 
3518                     GetImageSize( item
->GetImage(), ix
, iy 
); 
3522                 if (item
->HasText()) 
3525                     dc
.GetTextExtent( item
->GetText(), &w
, NULL 
); 
3533             width 
= max 
+ AUTOSIZE_COL_MARGIN
; 
3537     column
->SetWidth( width 
); 
3539     // invalidate it as it has to be recalculated 
3543 int wxListMainWindow::GetHeaderWidth() const 
3545     if ( !m_headerWidth 
) 
3547         wxListMainWindow 
*self 
= wxConstCast(this, wxListMainWindow
); 
3549         size_t count 
= GetColumnCount(); 
3550         for ( size_t col 
= 0; col 
< count
; col
++ ) 
3552             self
->m_headerWidth 
+= GetColumnWidth(col
); 
3556     return m_headerWidth
; 
3559 void wxListMainWindow::GetColumn( int col
, wxListItem 
&item 
) const 
3561     wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
3562     wxCHECK_RET( node
, _T("invalid column index in GetColumn") ); 
3564     wxListHeaderData 
*column 
= node
->GetData(); 
3565     column
->GetItem( item 
); 
3568 int wxListMainWindow::GetColumnWidth( int col 
) const 
3570     wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
3571     wxCHECK_MSG( node
, 0, _T("invalid column index") ); 
3573     wxListHeaderData 
*column 
= node
->GetData(); 
3574     return column
->GetWidth(); 
3577 // ---------------------------------------------------------------------------- 
3579 // ---------------------------------------------------------------------------- 
3581 void wxListMainWindow::SetItem( wxListItem 
&item 
) 
3583     long id 
= item
.m_itemId
; 
3584     wxCHECK_RET( id 
>= 0 && (size_t)id 
< GetItemCount(), 
3585                  _T("invalid item index in SetItem") ); 
3589         wxListLineData 
*line 
= GetLine((size_t)id
); 
3590         line
->SetItem( item
.m_col
, item 
); 
3593     // update the item on screen 
3595     GetItemRect(id
, rectItem
); 
3596     RefreshRect(rectItem
); 
3599 void wxListMainWindow::SetItemState( long litem
, long state
, long stateMask 
) 
3601      wxCHECK_RET( litem 
>= 0 && (size_t)litem 
< GetItemCount(), 
3602                   _T("invalid list ctrl item index in SetItem") ); 
3604     size_t oldCurrent 
= m_current
; 
3605     size_t item 
= (size_t)litem
;    // safe because of the check above 
3607     // do we need to change the focus? 
3608     if ( stateMask 
& wxLIST_STATE_FOCUSED 
) 
3610         if ( state 
& wxLIST_STATE_FOCUSED 
) 
3612             // don't do anything if this item is already focused 
3613             if ( item 
!= m_current 
) 
3615                 ChangeCurrent(item
); 
3617                 if ( oldCurrent 
!= (size_t)-1 ) 
3619                     if ( IsSingleSel() ) 
3621                         HighlightLine(oldCurrent
, false); 
3624                     RefreshLine(oldCurrent
); 
3627                 RefreshLine( m_current 
); 
3632             // don't do anything if this item is not focused 
3633             if ( item 
== m_current 
) 
3637                 if ( IsSingleSel() ) 
3639                     // we must unselect the old current item as well or we 
3640                     // might end up with more than one selected item in a 
3641                     // single selection control 
3642                     HighlightLine(oldCurrent
, false); 
3645                 RefreshLine( oldCurrent 
); 
3650     // do we need to change the selection state? 
3651     if ( stateMask 
& wxLIST_STATE_SELECTED 
) 
3653         bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
3655         if ( IsSingleSel() ) 
3659                 // selecting the item also makes it the focused one in the 
3661                 if ( m_current 
!= item 
) 
3663                     ChangeCurrent(item
); 
3665                     if ( oldCurrent 
!= (size_t)-1 ) 
3667                         HighlightLine( oldCurrent
, false ); 
3668                         RefreshLine( oldCurrent 
); 
3674                 // only the current item may be selected anyhow 
3675                 if ( item 
!= m_current 
) 
3680         if ( HighlightLine(item
, on
) ) 
3687 int wxListMainWindow::GetItemState( long item
, long stateMask 
) const 
3689     wxCHECK_MSG( item 
>= 0 && (size_t)item 
< GetItemCount(), 0, 
3690                  _T("invalid list ctrl item index in GetItemState()") ); 
3692     int ret 
= wxLIST_STATE_DONTCARE
; 
3694     if ( stateMask 
& wxLIST_STATE_FOCUSED 
) 
3696         if ( (size_t)item 
== m_current 
) 
3697             ret 
|= wxLIST_STATE_FOCUSED
; 
3700     if ( stateMask 
& wxLIST_STATE_SELECTED 
) 
3702         if ( IsHighlighted(item
) ) 
3703             ret 
|= wxLIST_STATE_SELECTED
; 
3709 void wxListMainWindow::GetItem( wxListItem 
&item 
) const 
3711     wxCHECK_RET( item
.m_itemId 
>= 0 && (size_t)item
.m_itemId 
< GetItemCount(), 
3712                  _T("invalid item index in GetItem") ); 
3714     wxListLineData 
*line 
= GetLine((size_t)item
.m_itemId
); 
3715     line
->GetItem( item
.m_col
, item 
); 
3718 // ---------------------------------------------------------------------------- 
3720 // ---------------------------------------------------------------------------- 
3722 size_t wxListMainWindow::GetItemCount() const 
3724     return IsVirtual() ? m_countVirt 
: m_lines
.GetCount(); 
3727 void wxListMainWindow::SetItemCount(long count
) 
3729     m_selStore
.SetItemCount(count
); 
3730     m_countVirt 
= count
; 
3732     ResetVisibleLinesRange(); 
3734     // scrollbars must be reset 
3738 int wxListMainWindow::GetSelectedItemCount() const 
3740     // deal with the quick case first 
3741     if ( IsSingleSel() ) 
3743         return HasCurrent() ? IsHighlighted(m_current
) : false; 
3746     // virtual controls remmebers all its selections itself 
3748         return m_selStore
.GetSelectedCount(); 
3750     // TODO: we probably should maintain the number of items selected even for 
3751     //       non virtual controls as enumerating all lines is really slow... 
3752     size_t countSel 
= 0; 
3753     size_t count 
= GetItemCount(); 
3754     for ( size_t line 
= 0; line 
< count
; line
++ ) 
3756         if ( GetLine(line
)->IsHighlighted() ) 
3763 // ---------------------------------------------------------------------------- 
3764 // item position/size 
3765 // ---------------------------------------------------------------------------- 
3767 wxRect 
wxListMainWindow::GetViewRect() const 
3769     wxASSERT_MSG( !HasFlag(wxLC_REPORT 
| wxLC_LIST
), 
3770                     _T("wxListCtrl::GetViewRect() only works in icon mode") ); 
3772     // we need to find the longest/tallest label 
3775     const int count 
= GetItemCount(); 
3778         for ( int i 
= 0; i 
< count
; i
++ ) 
3783             wxCoord x 
= r
.GetRight(), 
3793     // some fudge needed to make it look prettier 
3794     xMax 
+= 2*EXTRA_BORDER_X
; 
3795     yMax 
+= 2*EXTRA_BORDER_Y
; 
3797     // account for the scrollbars if necessary 
3798     const wxSize sizeAll 
= GetClientSize(); 
3799     if ( xMax 
> sizeAll
.x 
) 
3800         yMax 
+= wxSystemSettings::GetMetric(wxSYS_HSCROLL_Y
); 
3801     if ( yMax 
> sizeAll
.y 
) 
3802         xMax 
+= wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
); 
3804     return wxRect(0, 0, xMax
, yMax
); 
3807 void wxListMainWindow::GetItemRect( long index
, wxRect 
&rect 
) const 
3809     wxCHECK_RET( index 
>= 0 && (size_t)index 
< GetItemCount(), 
3810                  _T("invalid index in GetItemRect") ); 
3812     // ensure that we're laid out, otherwise we could return nonsense 
3815         wxConstCast(this, wxListMainWindow
)-> 
3816             RecalculatePositions(true /* no refresh */); 
3819     rect 
= GetLineRect((size_t)index
); 
3821     CalcScrolledPosition(rect
.x
, rect
.y
, &rect
.x
, &rect
.y
); 
3824 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
) const 
3827     GetItemRect(item
, rect
); 
3835 // ---------------------------------------------------------------------------- 
3836 // geometry calculation 
3837 // ---------------------------------------------------------------------------- 
3839 void wxListMainWindow::RecalculatePositions(bool noRefresh
) 
3841     wxClientDC 
dc( this ); 
3842     dc
.SetFont( GetFont() ); 
3844     const size_t count 
= GetItemCount(); 
3847     if ( HasFlag(wxLC_ICON
) ) 
3848         iconSpacing 
= m_normal_spacing
; 
3849     else if ( HasFlag(wxLC_SMALL_ICON
) ) 
3850         iconSpacing 
= m_small_spacing
; 
3854     // Note that we do not call GetClientSize() here but 
3855     // GetSize() and substract the border size for sunken 
3856     // borders manually. This is technically incorrect, 
3857     // but we need to know the client area's size WITHOUT 
3858     // scrollbars here. Since we don't know if there are 
3859     // any scrollbars, we use GetSize() instead. Another 
3860     // solution would be to call SetScrollbars() here to 
3861     // remove the scrollbars and call GetClientSize() then, 
3862     // but this might result in flicker and - worse - will 
3863     // reset the scrollbars to 0 which is not good at all 
3864     // if you resize a dialog/window, but don't want to 
3865     // reset the window scrolling. RR. 
3866     // Furthermore, we actually do NOT subtract the border 
3867     // width as 2 pixels is just the extra space which we 
3868     // need around the actual content in the window. Other- 
3869     // wise the text would e.g. touch the upper border. RR. 
3872     GetSize( &clientWidth
, &clientHeight 
); 
3874     const int lineHeight 
= GetLineHeight(); 
3876     if ( InReportView() ) 
3878         // all lines have the same height and we scroll one line per step 
3879         int entireHeight 
= count
*lineHeight 
+ LINE_SPACING
; 
3881         m_linesPerPage 
= clientHeight 
/ lineHeight
; 
3883         ResetVisibleLinesRange(); 
3885         SetScrollbars( SCROLL_UNIT_X
, lineHeight
, 
3886                        GetHeaderWidth() / SCROLL_UNIT_X
, 
3887                        (entireHeight 
+ lineHeight 
- 1) / lineHeight
, 
3888                        GetScrollPos(wxHORIZONTAL
), 
3889                        GetScrollPos(wxVERTICAL
), 
3894         // we have 3 different layout strategies: either layout all items 
3895         // horizontally/vertically (wxLC_ALIGN_XXX styles explicitly given) or 
3896         // to arrange them in top to bottom, left to right (don't ask me why 
3897         // not the other way round...) order 
3898         if ( HasFlag(wxLC_ALIGN_LEFT 
| wxLC_ALIGN_TOP
) ) 
3900             int x 
= EXTRA_BORDER_X
; 
3901             int y 
= EXTRA_BORDER_Y
; 
3903             wxCoord widthMax 
= 0; 
3906             for ( i 
= 0; i 
< count
; i
++ ) 
3908                 wxListLineData 
*line 
= GetLine(i
); 
3909                 line
->CalculateSize( &dc
, iconSpacing 
); 
3910                 line
->SetPosition( x
, y
, iconSpacing 
); 
3912                 wxSize sizeLine 
= GetLineSize(i
); 
3914                 if ( HasFlag(wxLC_ALIGN_TOP
) ) 
3916                     if ( sizeLine
.x 
> widthMax 
) 
3917                         widthMax 
= sizeLine
.x
; 
3921                 else // wxLC_ALIGN_LEFT 
3923                     x 
+= sizeLine
.x 
+ MARGIN_BETWEEN_ROWS
; 
3927             if ( HasFlag(wxLC_ALIGN_TOP
) ) 
3929                 // traverse the items again and tweak their sizes so that they are 
3930                 // all the same in a row 
3931                 for ( i 
= 0; i 
< count
; i
++ ) 
3933                     wxListLineData 
*line 
= GetLine(i
); 
3934                     line
->m_gi
->ExtendWidth(widthMax
); 
3943                 (x 
+ SCROLL_UNIT_X
) / SCROLL_UNIT_X
, 
3944                 (y 
+ lineHeight
) / lineHeight
, 
3945                 GetScrollPos( wxHORIZONTAL 
), 
3946                 GetScrollPos( wxVERTICAL 
), 
3950         else // "flowed" arrangement, the most complicated case 
3952             // at first we try without any scrollbars, if the items don't fit into 
3953             // the window, we recalculate after subtracting the space taken by the 
3956             int entireWidth 
= 0; 
3958             for (int tries 
= 0; tries 
< 2; tries
++) 
3960                 entireWidth 
= 2*EXTRA_BORDER_X
; 
3964                     // Now we have decided that the items do not fit into the 
3965                     // client area, so we need a scrollbar 
3966                     entireWidth 
+= SCROLL_UNIT_X
; 
3969                 int x 
= EXTRA_BORDER_X
; 
3970                 int y 
= EXTRA_BORDER_Y
; 
3971                 int maxWidthInThisRow 
= 0; 
3974                 int currentlyVisibleLines 
= 0; 
3976                 for (size_t i 
= 0; i 
< count
; i
++) 
3978                     currentlyVisibleLines
++; 
3979                     wxListLineData 
*line 
= GetLine(i
); 
3980                     line
->CalculateSize( &dc
, iconSpacing 
); 
3981                     line
->SetPosition( x
, y
, iconSpacing 
); 
3983                     wxSize sizeLine 
= GetLineSize(i
); 
3985                     if ( maxWidthInThisRow 
< sizeLine
.x 
) 
3986                         maxWidthInThisRow 
= sizeLine
.x
; 
3989                     if (currentlyVisibleLines 
> m_linesPerPage
) 
3990                         m_linesPerPage 
= currentlyVisibleLines
; 
3992                     if ( y 
+ sizeLine
.y 
>= clientHeight 
) 
3994                         currentlyVisibleLines 
= 0; 
3996                         maxWidthInThisRow 
+= MARGIN_BETWEEN_ROWS
; 
3997                         x 
+= maxWidthInThisRow
; 
3998                         entireWidth 
+= maxWidthInThisRow
; 
3999                         maxWidthInThisRow 
= 0; 
4002                     // We have reached the last item. 
4003                     if ( i 
== count 
- 1 ) 
4004                         entireWidth 
+= maxWidthInThisRow
; 
4006                     if ( (tries 
== 0) && 
4007                             (entireWidth 
+ SCROLL_UNIT_X 
> clientWidth
) ) 
4009                         clientHeight 
-= wxSystemSettings:: 
4010                                             GetMetric(wxSYS_HSCROLL_Y
); 
4015                     if ( i 
== count 
- 1 ) 
4016                         tries 
= 1;  // Everything fits, no second try required. 
4024                 (entireWidth 
+ SCROLL_UNIT_X
) / SCROLL_UNIT_X
, 
4026                 GetScrollPos( wxHORIZONTAL 
), 
4035         // FIXME: why should we call it from here? 
4042 void wxListMainWindow::RefreshAll() 
4047     wxListHeaderWindow 
*headerWin 
= GetListCtrl()->m_headerWin
; 
4048     if ( headerWin 
&& headerWin
->m_dirty 
) 
4050         headerWin
->m_dirty 
= false; 
4051         headerWin
->Refresh(); 
4055 void wxListMainWindow::UpdateCurrent() 
4057     if ( !HasCurrent() && !IsEmpty() ) 
4063 long wxListMainWindow::GetNextItem( long item
, 
4064                                     int WXUNUSED(geometry
), 
4068          max 
= GetItemCount(); 
4069     wxCHECK_MSG( (ret 
== -1) || (ret 
< max
), -1, 
4070                  _T("invalid listctrl index in GetNextItem()") ); 
4072     // notice that we start with the next item (or the first one if item == -1) 
4073     // and this is intentional to allow writing a simple loop to iterate over 
4074     // all selected items 
4078         // this is not an error because the index was ok initially, just no 
4089     size_t count 
= GetItemCount(); 
4090     for ( size_t line 
= (size_t)ret
; line 
< count
; line
++ ) 
4092         if ( (state 
& wxLIST_STATE_FOCUSED
) && (line 
== m_current
) ) 
4095         if ( (state 
& wxLIST_STATE_SELECTED
) && IsHighlighted(line
) ) 
4102 // ---------------------------------------------------------------------------- 
4104 // ---------------------------------------------------------------------------- 
4106 void wxListMainWindow::DeleteItem( long lindex 
) 
4108     size_t count 
= GetItemCount(); 
4110     wxCHECK_RET( (lindex 
>= 0) && ((size_t)lindex 
< count
), 
4111                  _T("invalid item index in DeleteItem") ); 
4113     size_t index 
= (size_t)lindex
; 
4115     // we don't need to adjust the index for the previous items 
4116     if ( HasCurrent() && m_current 
>= index 
) 
4118         // if the current item is being deleted, we want the next one to 
4119         // become selected - unless there is no next one - so don't adjust 
4120         // m_current in this case 
4121         if ( m_current 
!= index 
|| m_current 
== count 
- 1 ) 
4127     if ( InReportView() ) 
4129         ResetVisibleLinesRange(); 
4136         m_selStore
.OnItemDelete(index
); 
4140         m_lines
.RemoveAt( index 
); 
4143     // we need to refresh the (vert) scrollbar as the number of items changed 
4146     SendNotify( index
, wxEVT_COMMAND_LIST_DELETE_ITEM 
); 
4148     RefreshAfter(index
); 
4151 void wxListMainWindow::DeleteColumn( int col 
) 
4153     wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
4155     wxCHECK_RET( node
, wxT("invalid column index in DeleteColumn()") ); 
4158     delete node
->GetData(); 
4159     m_columns
.Erase( node 
); 
4163         // update all the items 
4164         for ( size_t i 
= 0; i 
< m_lines
.GetCount(); i
++ ) 
4166             wxListLineData 
* const line 
= GetLine(i
); 
4167             wxListItemDataList::compatibility_iterator n 
= line
->m_items
.Item( col 
); 
4168             delete n
->GetData(); 
4169             line
->m_items
.Erase(n
); 
4173     // invalidate it as it has to be recalculated 
4177 void wxListMainWindow::DoDeleteAllItems() 
4181         // nothing to do - in particular, don't send the event 
4187     // to make the deletion of all items faster, we don't send the 
4188     // notifications for each item deletion in this case but only one event 
4189     // for all of them: this is compatible with wxMSW and documented in 
4190     // DeleteAllItems() description 
4192     wxListEvent 
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() ); 
4193     event
.SetEventObject( GetParent() ); 
4194     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
4203     if ( InReportView() ) 
4205         ResetVisibleLinesRange(); 
4211 void wxListMainWindow::DeleteAllItems() 
4215     RecalculatePositions(); 
4218 void wxListMainWindow::DeleteEverything() 
4220     WX_CLEAR_LIST(wxListHeaderDataList
, m_columns
); 
4225 // ---------------------------------------------------------------------------- 
4226 // scanning for an item 
4227 // ---------------------------------------------------------------------------- 
4229 void wxListMainWindow::EnsureVisible( long index 
) 
4231     wxCHECK_RET( index 
>= 0 && (size_t)index 
< GetItemCount(), 
4232                  _T("invalid index in EnsureVisible") ); 
4234     // We have to call this here because the label in question might just have 
4235     // been added and its position is not known yet 
4238         RecalculatePositions(true /* no refresh */); 
4241     MoveToItem((size_t)index
); 
4244 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) ) 
4251     size_t count 
= GetItemCount(); 
4252     for ( size_t i 
= (size_t)pos
; i 
< count
; i
++ ) 
4254         wxListLineData 
*line 
= GetLine(i
); 
4255         if ( line
->GetText(0) == tmp 
) 
4262 long wxListMainWindow::FindItem(long start
, long data
) 
4268     size_t count 
= GetItemCount(); 
4269     for (size_t i 
= (size_t)pos
; i 
< count
; i
++) 
4271         wxListLineData 
*line 
= GetLine(i
); 
4273         line
->GetItem( 0, item 
); 
4274         if (item
.m_data 
== data
) 
4281 long wxListMainWindow::HitTest( int x
, int y
, int &flags 
) 
4283     CalcUnscrolledPosition( x
, y
, &x
, &y 
); 
4285     size_t count 
= GetItemCount(); 
4287     if ( InReportView() ) 
4289         size_t current 
= y 
/ GetLineHeight(); 
4290         if ( current 
< count 
) 
4292             flags 
= HitTestLine(current
, x
, y
); 
4299         // TODO: optimize it too! this is less simple than for report view but 
4300         //       enumerating all items is still not a way to do it!! 
4301         for ( size_t current 
= 0; current 
< count
; current
++ ) 
4303             flags 
= HitTestLine(current
, x
, y
); 
4312 // ---------------------------------------------------------------------------- 
4314 // ---------------------------------------------------------------------------- 
4316 void wxListMainWindow::InsertItem( wxListItem 
&item 
) 
4318     wxASSERT_MSG( !IsVirtual(), _T("can't be used with virtual control") ); 
4320     size_t count 
= GetItemCount(); 
4321     wxCHECK_RET( item
.m_itemId 
>= 0 && (size_t)item
.m_itemId 
<= count
, 
4322                  _T("invalid item index") ); 
4324     size_t id 
= item
.m_itemId
; 
4329     // this is unused variable 
4332     if ( InReportView() ) 
4335         // this is unused variable 
4338         ResetVisibleLinesRange(); 
4340     else if ( HasFlag(wxLC_LIST
) ) 
4342         // this is unused variable 
4347     else if ( HasFlag(wxLC_ICON
) ) 
4349         // this is unused variable 
4354     else if ( HasFlag(wxLC_SMALL_ICON
) ) 
4356         // this is unused variable 
4357         mode 
= wxLC_ICON
;  // no typo 
4363         wxFAIL_MSG( _T("unknown mode") ); 
4366     wxListLineData 
*line 
= new wxListLineData(this); 
4368     line
->SetItem( 0, item 
); 
4370     m_lines
.Insert( line
, id 
); 
4374     // If an item is selected at or below the point of insertion, we need to 
4375     // increment the member variables because the current row's index has gone 
4377     if ( HasCurrent() && m_current 
>= id 
) 
4382     SendNotify(id
, wxEVT_COMMAND_LIST_INSERT_ITEM
); 
4384     RefreshLines(id
, GetItemCount() - 1); 
4387 void wxListMainWindow::InsertColumn( long col
, wxListItem 
&item 
) 
4390     if ( InReportView() ) 
4392         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) 
4393             item
.m_width 
= GetTextLength( item
.m_text 
); 
4395         wxListHeaderData 
*column 
= new wxListHeaderData( item 
); 
4396         bool insert 
= (col 
>= 0) && ((size_t)col 
< m_columns
.GetCount()); 
4399             wxListHeaderDataList::compatibility_iterator node 
= m_columns
.Item( col 
); 
4400             m_columns
.Insert( node
, column 
); 
4404             m_columns
.Append( column 
); 
4409             // update all the items 
4410             for ( size_t i 
= 0; i 
< m_lines
.GetCount(); i
++ ) 
4412                 wxListLineData 
* const line 
= GetLine(i
); 
4413                 wxListItemData 
* const data 
= new wxListItemData(this); 
4415                     line
->m_items
.Insert(col
, data
); 
4417                     line
->m_items
.Append(data
); 
4421         // invalidate it as it has to be recalculated 
4426 // ---------------------------------------------------------------------------- 
4428 // ---------------------------------------------------------------------------- 
4430 wxListCtrlCompare list_ctrl_compare_func_2
; 
4431 long              list_ctrl_compare_data
; 
4433 int LINKAGEMODE 
list_ctrl_compare_func_1( wxListLineData 
**arg1
, wxListLineData 
**arg2 
) 
4435     wxListLineData 
*line1 
= *arg1
; 
4436     wxListLineData 
*line2 
= *arg2
; 
4438     line1
->GetItem( 0, item 
); 
4439     long data1 
= item
.m_data
; 
4440     line2
->GetItem( 0, item 
); 
4441     long data2 
= item
.m_data
; 
4442     return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data 
); 
4445 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data 
) 
4447     list_ctrl_compare_func_2 
= fn
; 
4448     list_ctrl_compare_data 
= data
; 
4449     m_lines
.Sort( list_ctrl_compare_func_1 
); 
4453 // ---------------------------------------------------------------------------- 
4455 // ---------------------------------------------------------------------------- 
4457 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
4459     // update our idea of which lines are shown when we redraw the window the 
4461     ResetVisibleLinesRange(); 
4464 #if defined(__WXGTK__) && !defined(__WXUNIVERSAL__) 
4465     wxScrolledWindow::OnScroll(event
); 
4467     HandleOnScroll( event 
); 
4470     if ( event
.GetOrientation() == wxHORIZONTAL 
&& HasHeader() ) 
4472         wxGenericListCtrl
* lc 
= GetListCtrl(); 
4473         wxCHECK_RET( lc
, _T("no listctrl window?") ); 
4475         lc
->m_headerWin
->Refresh(); 
4476         lc
->m_headerWin
->Update(); 
4480 int wxListMainWindow::GetCountPerPage() const 
4482     if ( !m_linesPerPage 
) 
4484         wxConstCast(this, wxListMainWindow
)-> 
4485             m_linesPerPage 
= GetClientSize().y 
/ GetLineHeight(); 
4488     return m_linesPerPage
; 
4491 void wxListMainWindow::GetVisibleLinesRange(size_t *from
, size_t *to
) 
4493     wxASSERT_MSG( InReportView(), _T("this is for report mode only") ); 
4495     if ( m_lineFrom 
== (size_t)-1 ) 
4497         size_t count 
= GetItemCount(); 
4500             m_lineFrom 
= GetScrollPos(wxVERTICAL
); 
4502             // this may happen if SetScrollbars() hadn't been called yet 
4503             if ( m_lineFrom 
>= count 
) 
4504                 m_lineFrom 
= count 
- 1; 
4506             // we redraw one extra line but this is needed to make the redrawing 
4507             // logic work when there is a fractional number of lines on screen 
4508             m_lineTo 
= m_lineFrom 
+ m_linesPerPage
; 
4509             if ( m_lineTo 
>= count 
) 
4510                 m_lineTo 
= count 
- 1; 
4512         else // empty control 
4515             m_lineTo 
= (size_t)-1; 
4519     wxASSERT_MSG( IsEmpty() || 
4520                   (m_lineFrom 
<= m_lineTo 
&& m_lineTo 
< GetItemCount()), 
4521                   _T("GetVisibleLinesRange() returns incorrect result") ); 
4529 // ------------------------------------------------------------------------------------- 
4530 // wxGenericListCtrl 
4531 // ------------------------------------------------------------------------------------- 
4533 IMPLEMENT_DYNAMIC_CLASS(wxGenericListCtrl
, wxControl
) 
4535 BEGIN_EVENT_TABLE(wxGenericListCtrl
,wxControl
) 
4536   EVT_SIZE(wxGenericListCtrl::OnSize
) 
4539 wxGenericListCtrl::wxGenericListCtrl() 
4541     m_imageListNormal 
= (wxImageListType 
*) NULL
; 
4542     m_imageListSmall 
= (wxImageListType 
*) NULL
; 
4543     m_imageListState 
= (wxImageListType 
*) NULL
; 
4545     m_ownsImageListNormal 
= 
4546     m_ownsImageListSmall 
= 
4547     m_ownsImageListState 
= false; 
4549     m_mainWin 
= (wxListMainWindow
*) NULL
; 
4550     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
4554 wxGenericListCtrl::~wxGenericListCtrl() 
4556     if (m_ownsImageListNormal
) 
4557         delete m_imageListNormal
; 
4558     if (m_ownsImageListSmall
) 
4559         delete m_imageListSmall
; 
4560     if (m_ownsImageListState
) 
4561         delete m_imageListState
; 
4564 void wxGenericListCtrl::CalculateAndSetHeaderHeight() 
4568         // we use 'g' to get the descent, too 
4570         m_headerWin
->GetTextExtent(wxT("Hg"), &w
, &h
, &d
); 
4571         h 
+= d 
+ 2 * HEADER_OFFSET_Y 
+ EXTRA_HEIGHT
; 
4573         // only update if changed 
4574         if ( h 
!= m_headerHeight 
) 
4578             m_headerWin
->SetSize(m_headerWin
->GetSize().x
, m_headerHeight
); 
4581                 ResizeReportView(true); 
4586 void wxGenericListCtrl::CreateHeaderWindow() 
4588     m_headerWin 
= new wxListHeaderWindow
 
4590                         this, wxID_ANY
, m_mainWin
, 
4592                         wxSize(GetClientSize().x
, m_headerHeight
), 
4595     CalculateAndSetHeaderHeight(); 
4598 bool wxGenericListCtrl::Create(wxWindow 
*parent
, 
4603                         const wxValidator 
&validator
, 
4604                         const wxString 
&name
) 
4608     m_imageListState 
= (wxImageListType 
*) NULL
; 
4609     m_ownsImageListNormal 
= 
4610     m_ownsImageListSmall 
= 
4611     m_ownsImageListState 
= false; 
4613     m_mainWin 
= (wxListMainWindow
*) NULL
; 
4614     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
4618     if ( !(style 
& wxLC_MASK_TYPE
) ) 
4620         style 
= style 
| wxLC_LIST
; 
4623     if ( !wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name 
) ) 
4626     // don't create the inner window with the border 
4627     style 
&= ~wxBORDER_MASK
; 
4629     m_mainWin 
= new wxListMainWindow( this, wxID_ANY
, wxPoint(0,0), size
, style 
); 
4631 #if defined( __WXMAC__ ) && __WXMAC_CARBON__ 
4633     font
.MacCreateThemeFont( kThemeViewsFont 
) ; 
4636     if ( InReportView() ) 
4638         CreateHeaderWindow(); 
4640         if ( HasFlag(wxLC_NO_HEADER
) ) 
4642             // VZ: why do we create it at all then? 
4643             m_headerWin
->Show( false ); 
4652 void wxGenericListCtrl::SetSingleStyle( long style
, bool add 
) 
4654     wxASSERT_MSG( !(style 
& wxLC_VIRTUAL
), 
4655                   _T("wxLC_VIRTUAL can't be [un]set") ); 
4657     long flag 
= GetWindowStyle(); 
4661         if (style 
& wxLC_MASK_TYPE
) 
4662             flag 
&= ~(wxLC_MASK_TYPE 
| wxLC_VIRTUAL
); 
4663         if (style 
& wxLC_MASK_ALIGN
) 
4664             flag 
&= ~wxLC_MASK_ALIGN
; 
4665         if (style 
& wxLC_MASK_SORT
) 
4666             flag 
&= ~wxLC_MASK_SORT
; 
4678     SetWindowStyleFlag( flag 
); 
4681 void wxGenericListCtrl::SetWindowStyleFlag( long flag 
) 
4685         m_mainWin
->DeleteEverything(); 
4687         // has the header visibility changed? 
4688         bool hasHeader 
= HasHeader(); 
4689         bool willHaveHeader 
= (flag 
& wxLC_REPORT
) && !(flag 
& wxLC_NO_HEADER
); 
4691         if ( hasHeader 
!= willHaveHeader 
) 
4698                     // don't delete, just hide, as we can reuse it later 
4699                     m_headerWin
->Show(false); 
4701                 //else: nothing to do 
4703             else // must show header 
4707                     CreateHeaderWindow(); 
4709                 else // already have it, just show 
4711                     m_headerWin
->Show( true ); 
4715             ResizeReportView(willHaveHeader
); 
4719     wxWindow::SetWindowStyleFlag( flag 
); 
4722 bool wxGenericListCtrl::GetColumn(int col
, wxListItem 
&item
) const 
4724     m_mainWin
->GetColumn( col
, item 
); 
4728 bool wxGenericListCtrl::SetColumn( int col
, wxListItem
& item 
) 
4730     m_mainWin
->SetColumn( col
, item 
); 
4734 int wxGenericListCtrl::GetColumnWidth( int col 
) const 
4736     return m_mainWin
->GetColumnWidth( col 
); 
4739 bool wxGenericListCtrl::SetColumnWidth( int col
, int width 
) 
4741     m_mainWin
->SetColumnWidth( col
, width 
); 
4745 int wxGenericListCtrl::GetCountPerPage() const 
4747   return m_mainWin
->GetCountPerPage();  // different from Windows ? 
4750 bool wxGenericListCtrl::GetItem( wxListItem 
&info 
) const 
4752     m_mainWin
->GetItem( info 
); 
4756 bool wxGenericListCtrl::SetItem( wxListItem 
&info 
) 
4758     m_mainWin
->SetItem( info 
); 
4762 long wxGenericListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId 
) 
4765     info
.m_text 
= label
; 
4766     info
.m_mask 
= wxLIST_MASK_TEXT
; 
4767     info
.m_itemId 
= index
; 
4771         info
.m_image 
= imageId
; 
4772         info
.m_mask 
|= wxLIST_MASK_IMAGE
; 
4774     m_mainWin
->SetItem(info
); 
4778 int wxGenericListCtrl::GetItemState( long item
, long stateMask 
) const 
4780     return m_mainWin
->GetItemState( item
, stateMask 
); 
4783 bool wxGenericListCtrl::SetItemState( long item
, long state
, long stateMask 
) 
4785     m_mainWin
->SetItemState( item
, state
, stateMask 
); 
4789 bool wxGenericListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) ) 
4792     info
.m_image 
= image
; 
4793     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
4794     info
.m_itemId 
= item
; 
4795     m_mainWin
->SetItem( info 
); 
4799 wxString 
wxGenericListCtrl::GetItemText( long item 
) const 
4801     return m_mainWin
->GetItemText(item
); 
4804 void wxGenericListCtrl::SetItemText( long item
, const wxString
& str 
) 
4806     m_mainWin
->SetItemText(item
, str
); 
4809 long wxGenericListCtrl::GetItemData( long item 
) const 
4812     info
.m_itemId 
= item
; 
4813     m_mainWin
->GetItem( info 
); 
4817 bool wxGenericListCtrl::SetItemData( long item
, long data 
) 
4820     info
.m_mask 
= wxLIST_MASK_DATA
; 
4821     info
.m_itemId 
= item
; 
4823     m_mainWin
->SetItem( info 
); 
4827 wxRect 
wxGenericListCtrl::GetViewRect() const 
4829     return m_mainWin
->GetViewRect(); 
4832 bool wxGenericListCtrl::GetItemRect( long item
, wxRect 
&rect
,  int WXUNUSED(code
) ) const 
4834     m_mainWin
->GetItemRect( item
, rect 
); 
4835     if ( m_mainWin
->HasHeader() ) 
4836         rect
.y 
+= m_headerHeight 
+ 1; 
4840 bool wxGenericListCtrl::GetItemPosition( long item
, wxPoint
& pos 
) const 
4842     m_mainWin
->GetItemPosition( item
, pos 
); 
4846 bool wxGenericListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) ) 
4851 int wxGenericListCtrl::GetItemCount() const 
4853     return m_mainWin
->GetItemCount(); 
4856 int wxGenericListCtrl::GetColumnCount() const 
4858     return m_mainWin
->GetColumnCount(); 
4861 void wxGenericListCtrl::SetItemSpacing( int spacing
, bool isSmall 
) 
4863     m_mainWin
->SetItemSpacing( spacing
, isSmall 
); 
4866 wxSize 
wxGenericListCtrl::GetItemSpacing() const 
4868     const int spacing 
= m_mainWin
->GetItemSpacing(HasFlag(wxLC_SMALL_ICON
)); 
4870     return wxSize(spacing
, spacing
); 
4873 int wxGenericListCtrl::GetItemSpacing( bool isSmall 
) const 
4875     return m_mainWin
->GetItemSpacing( isSmall 
); 
4878 void wxGenericListCtrl::SetItemTextColour( long item
, const wxColour 
&col 
) 
4881     info
.m_itemId 
= item
; 
4882     info
.SetTextColour( col 
); 
4883     m_mainWin
->SetItem( info 
); 
4886 wxColour 
wxGenericListCtrl::GetItemTextColour( long item 
) const 
4889     info
.m_itemId 
= item
; 
4890     m_mainWin
->GetItem( info 
); 
4891     return info
.GetTextColour(); 
4894 void wxGenericListCtrl::SetItemBackgroundColour( long item
, const wxColour 
&col 
) 
4897     info
.m_itemId 
= item
; 
4898     info
.SetBackgroundColour( col 
); 
4899     m_mainWin
->SetItem( info 
); 
4902 wxColour 
wxGenericListCtrl::GetItemBackgroundColour( long item 
) const 
4905     info
.m_itemId 
= item
; 
4906     m_mainWin
->GetItem( info 
); 
4907     return info
.GetBackgroundColour(); 
4910 int wxGenericListCtrl::GetSelectedItemCount() const 
4912     return m_mainWin
->GetSelectedItemCount(); 
4915 wxColour 
wxGenericListCtrl::GetTextColour() const 
4917     return GetForegroundColour(); 
4920 void wxGenericListCtrl::SetTextColour(const wxColour
& col
) 
4922     SetForegroundColour(col
); 
4925 long wxGenericListCtrl::GetTopItem() const 
4928     m_mainWin
->GetVisibleLinesRange(&top
, NULL
); 
4932 long wxGenericListCtrl::GetNextItem( long item
, int geom
, int state 
) const 
4934     return m_mainWin
->GetNextItem( item
, geom
, state 
); 
4937 wxImageListType 
*wxGenericListCtrl::GetImageList(int which
) const 
4939     if (which 
== wxIMAGE_LIST_NORMAL
) 
4941         return m_imageListNormal
; 
4943     else if (which 
== wxIMAGE_LIST_SMALL
) 
4945         return m_imageListSmall
; 
4947     else if (which 
== wxIMAGE_LIST_STATE
) 
4949         return m_imageListState
; 
4951     return (wxImageListType 
*) NULL
; 
4954 void wxGenericListCtrl::SetImageList( wxImageListType 
*imageList
, int which 
) 
4956     if ( which 
== wxIMAGE_LIST_NORMAL 
) 
4958         if (m_ownsImageListNormal
) delete m_imageListNormal
; 
4959         m_imageListNormal 
= imageList
; 
4960         m_ownsImageListNormal 
= false; 
4962     else if ( which 
== wxIMAGE_LIST_SMALL 
) 
4964         if (m_ownsImageListSmall
) delete m_imageListSmall
; 
4965         m_imageListSmall 
= imageList
; 
4966         m_ownsImageListSmall 
= false; 
4968     else if ( which 
== wxIMAGE_LIST_STATE 
) 
4970         if (m_ownsImageListState
) delete m_imageListState
; 
4971         m_imageListState 
= imageList
; 
4972         m_ownsImageListState 
= false; 
4975     m_mainWin
->SetImageList( imageList
, which 
); 
4978 void wxGenericListCtrl::AssignImageList(wxImageListType 
*imageList
, int which
) 
4980     SetImageList(imageList
, which
); 
4981     if ( which 
== wxIMAGE_LIST_NORMAL 
) 
4982         m_ownsImageListNormal 
= true; 
4983     else if ( which 
== wxIMAGE_LIST_SMALL 
) 
4984         m_ownsImageListSmall 
= true; 
4985     else if ( which 
== wxIMAGE_LIST_STATE 
) 
4986         m_ownsImageListState 
= true; 
4989 bool wxGenericListCtrl::Arrange( int WXUNUSED(flag
) ) 
4994 bool wxGenericListCtrl::DeleteItem( long item 
) 
4996     m_mainWin
->DeleteItem( item 
); 
5000 bool wxGenericListCtrl::DeleteAllItems() 
5002     m_mainWin
->DeleteAllItems(); 
5006 bool wxGenericListCtrl::DeleteAllColumns() 
5008     size_t count 
= m_mainWin
->m_columns
.GetCount(); 
5009     for ( size_t n 
= 0; n 
< count
; n
++ ) 
5015 void wxGenericListCtrl::ClearAll() 
5017     m_mainWin
->DeleteEverything(); 
5020 bool wxGenericListCtrl::DeleteColumn( int col 
) 
5022     m_mainWin
->DeleteColumn( col 
); 
5024     // if we don't have the header any longer, we need to relayout the window 
5025     if ( !GetColumnCount() ) 
5027         ResizeReportView(false /* no header */); 
5033 void wxGenericListCtrl::Edit( long item 
) 
5035     m_mainWin
->EditLabel( item 
); 
5038 bool wxGenericListCtrl::EnsureVisible( long item 
) 
5040     m_mainWin
->EnsureVisible( item 
); 
5044 long wxGenericListCtrl::FindItem( long start
, const wxString
& str
,  bool partial 
) 
5046     return m_mainWin
->FindItem( start
, str
, partial 
); 
5049 long wxGenericListCtrl::FindItem( long start
, long data 
) 
5051     return m_mainWin
->FindItem( start
, data 
); 
5054 long wxGenericListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
), 
5055                            int WXUNUSED(direction
)) 
5060 long wxGenericListCtrl::HitTest( const wxPoint 
&point
, int &flags 
) 
5062     return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags 
); 
5065 long wxGenericListCtrl::InsertItem( wxListItem
& info 
) 
5067     m_mainWin
->InsertItem( info 
); 
5068     return info
.m_itemId
; 
5071 long wxGenericListCtrl::InsertItem( long index
, const wxString 
&label 
) 
5074     info
.m_text 
= label
; 
5075     info
.m_mask 
= wxLIST_MASK_TEXT
; 
5076     info
.m_itemId 
= index
; 
5077     return InsertItem( info 
); 
5080 long wxGenericListCtrl::InsertItem( long index
, int imageIndex 
) 
5083     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
5084     info
.m_image 
= imageIndex
; 
5085     info
.m_itemId 
= index
; 
5086     return InsertItem( info 
); 
5089 long wxGenericListCtrl::InsertItem( long index
, const wxString 
&label
, int imageIndex 
) 
5092     info
.m_text 
= label
; 
5093     info
.m_image 
= imageIndex
; 
5094     info
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_IMAGE
; 
5095     info
.m_itemId 
= index
; 
5096     return InsertItem( info 
); 
5099 long wxGenericListCtrl::InsertColumn( long col
, wxListItem 
&item 
) 
5101     wxCHECK_MSG( m_headerWin
, -1, _T("can't add column in non report mode") ); 
5103     m_mainWin
->InsertColumn( col
, item 
); 
5105     // if we hadn't had header before and have it now we need to relayout the 
5107     if ( GetColumnCount() == 1 && m_mainWin
->HasHeader() ) 
5109         ResizeReportView(true /* have header */); 
5112     m_headerWin
->Refresh(); 
5117 long wxGenericListCtrl::InsertColumn( long col
, const wxString 
&heading
, 
5118                                int format
, int width 
) 
5121     item
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_FORMAT
; 
5122     item
.m_text 
= heading
; 
5125         item
.m_mask 
|= wxLIST_MASK_WIDTH
; 
5126         item
.m_width 
= width
; 
5128     item
.m_format 
= format
; 
5130     return InsertColumn( col
, item 
); 
5133 bool wxGenericListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) ) 
5139 // fn is a function which takes 3 long arguments: item1, item2, data. 
5140 // item1 is the long data associated with a first item (NOT the index). 
5141 // item2 is the long data associated with a second item (NOT the index). 
5142 // data is the same value as passed to SortItems. 
5143 // The return value is a negative number if the first item should precede the second 
5144 // item, a positive number of the second item should precede the first, 
5145 // or zero if the two items are equivalent. 
5146 // data is arbitrary data to be passed to the sort function. 
5148 bool wxGenericListCtrl::SortItems( wxListCtrlCompare fn
, long data 
) 
5150     m_mainWin
->SortItems( fn
, data 
); 
5154 // ---------------------------------------------------------------------------- 
5156 // ---------------------------------------------------------------------------- 
5158 void wxGenericListCtrl::OnSize(wxSizeEvent
& WXUNUSED(event
)) 
5163     ResizeReportView(m_mainWin
->HasHeader()); 
5165     m_mainWin
->RecalculatePositions(); 
5168 void wxGenericListCtrl::ResizeReportView(bool showHeader
) 
5171     GetClientSize( &cw
, &ch 
); 
5175         m_headerWin
->SetSize( 0, 0, cw
, m_headerHeight 
); 
5176         m_mainWin
->SetSize( 0, m_headerHeight 
+ 1, cw
, ch 
- m_headerHeight 
- 1 ); 
5178     else // no header window 
5180         m_mainWin
->SetSize( 0, 0, cw
, ch 
); 
5184 void wxGenericListCtrl::OnInternalIdle() 
5186     wxWindow::OnInternalIdle(); 
5188     // do it only if needed 
5189     if ( !m_mainWin
->m_dirty 
) 
5192     m_mainWin
->RecalculatePositions(); 
5195 // ---------------------------------------------------------------------------- 
5197 // ---------------------------------------------------------------------------- 
5199 bool wxGenericListCtrl::SetBackgroundColour( const wxColour 
&colour 
) 
5203         m_mainWin
->SetBackgroundColour( colour 
); 
5204         m_mainWin
->m_dirty 
= true; 
5210 bool wxGenericListCtrl::SetForegroundColour( const wxColour 
&colour 
) 
5212     if ( !wxWindow::SetForegroundColour( colour 
) ) 
5217         m_mainWin
->SetForegroundColour( colour 
); 
5218         m_mainWin
->m_dirty 
= true; 
5223         m_headerWin
->SetForegroundColour( colour 
); 
5229 bool wxGenericListCtrl::SetFont( const wxFont 
&font 
) 
5231     if ( !wxWindow::SetFont( font 
) ) 
5236         m_mainWin
->SetFont( font 
); 
5237         m_mainWin
->m_dirty 
= true; 
5242         m_headerWin
->SetFont( font 
); 
5243         CalculateAndSetHeaderHeight(); 
5254 #include "wx/listbox.h" 
5259 wxGenericListCtrl::GetClassDefaultAttributes(wxWindowVariant variant
) 
5262     // Use the same color scheme as wxListBox 
5263     return wxListBox::GetClassDefaultAttributes(variant
); 
5265     wxUnusedVar(variant
); 
5266     wxVisualAttributes attr
; 
5267     attr
.colFg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT
); 
5268     attr
.colBg 
= wxSystemSettings::GetColour(wxSYS_COLOUR_LISTBOX
); 
5269     attr
.font  
= wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT
); 
5274 // ---------------------------------------------------------------------------- 
5275 // methods forwarded to m_mainWin 
5276 // ---------------------------------------------------------------------------- 
5278 #if wxUSE_DRAG_AND_DROP 
5280 void wxGenericListCtrl::SetDropTarget( wxDropTarget 
*dropTarget 
) 
5282     m_mainWin
->SetDropTarget( dropTarget 
); 
5285 wxDropTarget 
*wxGenericListCtrl::GetDropTarget() const 
5287     return m_mainWin
->GetDropTarget(); 
5290 #endif // wxUSE_DRAG_AND_DROP 
5292 bool wxGenericListCtrl::SetCursor( const wxCursor 
&cursor 
) 
5294     return m_mainWin 
? m_mainWin
->wxWindow::SetCursor(cursor
) : false; 
5297 wxColour 
wxGenericListCtrl::GetBackgroundColour() const 
5299     return m_mainWin 
? m_mainWin
->GetBackgroundColour() : wxColour(); 
5302 wxColour 
wxGenericListCtrl::GetForegroundColour() const 
5304     return m_mainWin 
? m_mainWin
->GetForegroundColour() : wxColour(); 
5307 bool wxGenericListCtrl::DoPopupMenu( wxMenu 
*menu
, int x
, int y 
) 
5310     return m_mainWin
->PopupMenu( menu
, x
, y 
); 
5313 #endif // wxUSE_MENUS 
5316 void wxGenericListCtrl::SetFocus() 
5318     /* The test in window.cpp fails as we are a composite 
5319        window, so it checks against "this", but not m_mainWin. */ 
5320     if ( FindFocus() != this ) 
5321         m_mainWin
->SetFocus(); 
5324 // ---------------------------------------------------------------------------- 
5325 // virtual list control support 
5326 // ---------------------------------------------------------------------------- 
5328 wxString 
wxGenericListCtrl::OnGetItemText(long WXUNUSED(item
), long WXUNUSED(col
)) const 
5330     // this is a pure virtual function, in fact - which is not really pure 
5331     // because the controls which are not virtual don't need to implement it 
5332     wxFAIL_MSG( _T("wxGenericListCtrl::OnGetItemText not supposed to be called") ); 
5334     return wxEmptyString
; 
5337 int wxGenericListCtrl::OnGetItemImage(long WXUNUSED(item
)) const 
5340     wxFAIL_MSG( _T("wxGenericListCtrl::OnGetItemImage not supposed to be called") ); 
5346 wxGenericListCtrl::OnGetItemAttr(long WXUNUSED_UNLESS_DEBUG(item
)) const 
5348     wxASSERT_MSG( item 
>= 0 && item 
< GetItemCount(), 
5349                   _T("invalid item index in OnGetItemAttr()") ); 
5351     // no attributes by default 
5355 void wxGenericListCtrl::SetItemCount(long count
) 
5357     wxASSERT_MSG( IsVirtual(), _T("this is for virtual controls only") ); 
5359     m_mainWin
->SetItemCount(count
); 
5362 void wxGenericListCtrl::RefreshItem(long item
) 
5364     m_mainWin
->RefreshLine(item
); 
5367 void wxGenericListCtrl::RefreshItems(long itemFrom
, long itemTo
) 
5369     m_mainWin
->RefreshLines(itemFrom
, itemTo
); 
5373  * Generic wxListCtrl is more or less a container for two other 
5374  * windows which drawings are done upon. These are namely 
5375  * 'm_headerWin' and 'm_mainWin'. 
5376  * Here we override 'virtual wxWindow::Refresh()' to mimic the 
5377  * behaviour wxListCtrl has under wxMSW. 
5379 void wxGenericListCtrl::Refresh(bool eraseBackground
, const wxRect 
*rect
) 
5383         // The easy case, no rectangle specified. 
5385             m_headerWin
->Refresh(eraseBackground
); 
5388             m_mainWin
->Refresh(eraseBackground
); 
5392         // Refresh the header window 
5395             wxRect rectHeader 
= m_headerWin
->GetRect(); 
5396             rectHeader
.Intersect(*rect
); 
5397             if (rectHeader
.GetWidth() && rectHeader
.GetHeight()) 
5400                 m_headerWin
->GetPosition(&x
, &y
); 
5401                 rectHeader
.Offset(-x
, -y
); 
5402                 m_headerWin
->Refresh(eraseBackground
, &rectHeader
); 
5407         // Refresh the main window 
5410             wxRect rectMain 
= m_mainWin
->GetRect(); 
5411             rectMain
.Intersect(*rect
); 
5412             if (rectMain
.GetWidth() && rectMain
.GetHeight()) 
5415                 m_mainWin
->GetPosition(&x
, &y
); 
5416                 rectMain
.Offset(-x
, -y
); 
5417                 m_mainWin
->Refresh(eraseBackground
, &rectMain
); 
5423 void wxGenericListCtrl::Freeze() 
5425     m_mainWin
->Freeze(); 
5428 void wxGenericListCtrl::Thaw() 
5433 #endif // wxUSE_LISTCTRL