1 ///////////////////////////////////////////////////////////////////////////// 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  11     #pragma implementation "listctrl.h" 
  12     #pragma implementation "listctrlbase.h" 
  15 // For compilers that support precompilation, includes "wx.h". 
  16 #include "wx/wxprec.h" 
  22 #include "wx/dcscreen.h" 
  24 #include "wx/listctrl.h" 
  25 #include "wx/generic/imaglist.h" 
  27 #ifndef wxUSE_GENERIC_LIST_EXTENSIONS 
  28 #define wxUSE_GENERIC_LIST_EXTENSIONS 0 
  31 //----------------------------------------------------------------------------- 
  33 //----------------------------------------------------------------------------- 
  35 IMPLEMENT_DYNAMIC_CLASS(wxListItemData
,wxObject
); 
  37 wxListItemData::wxListItemData() 
  48 wxListItemData::wxListItemData( const wxListItem 
&info 
) 
  57 void wxListItemData::SetItem( const wxListItem 
&info 
) 
  59     if (info
.m_mask 
& wxLIST_MASK_TEXT
) m_text 
= info
.m_text
; 
  60     if (info
.m_mask 
& wxLIST_MASK_IMAGE
) m_image 
= info
.m_image
; 
  61     if (info
.m_mask 
& wxLIST_MASK_DATA
) m_data 
= info
.m_data
; 
  63     if ( info
.HasAttributes() ) 
  66             *m_attr 
= *info
.GetAttributes(); 
  68             m_attr 
= new wxListItemAttr(*info
.GetAttributes()); 
  73     m_width 
= info
.m_width
; 
  77 void wxListItemData::SetText( const wxString 
&s 
) 
  82 void wxListItemData::SetImage( int image 
) 
  87 void wxListItemData::SetData( long data 
) 
  92 void wxListItemData::SetPosition( int x
, int y 
) 
  98 void wxListItemData::SetSize( int width
, int height 
) 
 100     if (width 
!= -1) m_width 
= width
; 
 101     if (height 
!= -1) m_height 
= height
; 
 104 bool wxListItemData::HasImage() const 
 106     return (m_image 
>= 0); 
 109 bool wxListItemData::HasText() const 
 111     return (!m_text
.IsNull()); 
 114 bool wxListItemData::IsHit( int x
, int y 
) const 
 116     return ((x 
>= m_xpos
) && (x 
<= m_xpos
+m_width
) && (y 
>= m_ypos
) && (y 
<= m_ypos
+m_height
)); 
 119 void wxListItemData::GetText( wxString 
&s 
) 
 124 int wxListItemData::GetX() const 
 129 int wxListItemData::GetY() const 
 134 int wxListItemData::GetWidth() const 
 139 int wxListItemData::GetHeight() const 
 144 int wxListItemData::GetImage() const 
 149 void wxListItemData::GetItem( wxListItem 
&info 
) const 
 151     info
.m_text 
= m_text
; 
 152     info
.m_image 
= m_image
; 
 153     info
.m_data 
= m_data
; 
 157         if ( m_attr
->HasTextColour() ) 
 158             info
.SetTextColour(m_attr
->GetTextColour()); 
 159         if ( m_attr
->HasBackgroundColour() ) 
 160             info
.SetBackgroundColour(m_attr
->GetBackgroundColour()); 
 161         if ( m_attr
->HasFont() ) 
 162             info
.SetFont(m_attr
->GetFont()); 
 166 //----------------------------------------------------------------------------- 
 168 //----------------------------------------------------------------------------- 
 170 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderData
,wxObject
); 
 172 wxListHeaderData::wxListHeaderData() 
 183 wxListHeaderData::wxListHeaderData( const wxListItem 
&item 
) 
 191 void wxListHeaderData::SetItem( const wxListItem 
&item 
) 
 193     m_mask 
= item
.m_mask
; 
 194     m_text 
= item
.m_text
; 
 195     m_image 
= item
.m_image
; 
 196     m_format 
= item
.m_format
; 
 197     m_width 
= item
.m_width
; 
 198     if (m_width 
< 0) m_width 
= 80; 
 199     if (m_width 
< 6) m_width 
= 6; 
 202 void wxListHeaderData::SetPosition( int x
, int y 
) 
 208 void wxListHeaderData::SetHeight( int h 
) 
 213 void wxListHeaderData::SetWidth( int w 
) 
 216     if (m_width 
< 0) m_width 
= 80; 
 217     if (m_width 
< 6) m_width 
= 6; 
 220 void wxListHeaderData::SetFormat( int format 
) 
 225 bool wxListHeaderData::HasImage() const 
 227     return (m_image 
!= 0); 
 230 bool wxListHeaderData::HasText() const 
 232     return (m_text
.Length() > 0); 
 235 bool wxListHeaderData::IsHit( int x
, int y 
) const 
 237     return ((x 
>= m_xpos
) && (x 
<= m_xpos
+m_width
) && (y 
>= m_ypos
) && (y 
<= m_ypos
+m_height
)); 
 240 void wxListHeaderData::GetItem( wxListItem 
&item 
) 
 242     item
.m_mask 
= m_mask
; 
 243     item
.m_text 
= m_text
; 
 244     item
.m_image 
= m_image
; 
 245     item
.m_format 
= m_format
; 
 246     item
.m_width 
= m_width
; 
 249 void wxListHeaderData::GetText( wxString 
&s 
) 
 254 int wxListHeaderData::GetImage() const 
 259 int wxListHeaderData::GetWidth() const 
 264 int wxListHeaderData::GetFormat() const 
 269 //----------------------------------------------------------------------------- 
 271 //----------------------------------------------------------------------------- 
 273 IMPLEMENT_DYNAMIC_CLASS(wxListLineData
,wxObject
); 
 275 wxListLineData::wxListLineData( wxListMainWindow 
*owner
, int mode
, wxBrush 
*hilightBrush 
) 
 280     m_hilightBrush 
= hilightBrush
; 
 281     m_items
.DeleteContents( TRUE 
); 
 285 void wxListLineData::CalculateSize( wxDC 
*dc
, int spacing 
) 
 292             m_bound_all
.width 
= m_spacing
; 
 293             m_bound_all
.height 
= m_spacing
+13; 
 294             wxNode 
*node 
= m_items
.First(); 
 297                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 298                 wxString s 
= item
->GetText(); 
 300                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
 301                 if (lw 
> m_spacing
) m_bound_all
.width 
= lw
; 
 307             wxNode 
*node 
= m_items
.First(); 
 310                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 311                 wxString s 
= item
->GetText(); 
 313                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
 314                 m_bound_all
.width 
= lw
; 
 315                 m_bound_all
.height 
= lh
; 
 316                 if (item
->HasImage()) 
 325                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
 326                     m_bound_all
.width 
+= 4 + w
; 
 327                     if (h 
> m_bound_all
.height
) m_bound_all
.height 
= h
; 
 334             m_bound_all
.width 
= 0; 
 335             m_bound_all
.height 
= 0; 
 336             wxNode 
*node 
= m_items
.First(); 
 339                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 342                 if (s
.IsNull()) s 
= "H"; 
 344                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
 345                 item
->SetSize( item
->GetWidth(), lh 
); 
 346                 m_bound_all
.width 
+= lw
; 
 347                 m_bound_all
.height 
= lh
; 
 355 void wxListLineData::SetPosition( wxDC 
*dc
, int x
, int y
, int window_width 
) 
 363             AssignRect( m_bound_icon
, 0, 0, 0, 0 ); 
 364             AssignRect( m_bound_label
, 0, 0, 0, 0 ); 
 365             AssignRect( m_bound_hilight
, m_bound_all 
); 
 366             wxNode 
*node 
= m_items
.First(); 
 369                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 370                 if (item
->HasImage()) 
 372                     wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 375                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
 376                     m_bound_icon
.x 
= m_bound_all
.x 
+ (m_spacing
/2) - (w
/2); 
 377                     m_bound_icon
.y 
= m_bound_all
.y 
+ m_spacing 
- h 
- 5; 
 378                     m_bound_icon
.width 
= w
; 
 379                     m_bound_icon
.height 
= h
; 
 380                     if (!item
->HasText()) 
 382                         AssignRect( m_bound_hilight
, m_bound_icon 
); 
 383                         m_bound_hilight
.x 
-= 5; 
 384                         m_bound_hilight
.y 
-= 5; 
 385                         m_bound_hilight
.width 
+= 9; 
 386                         m_bound_hilight
.height 
+= 9; 
 394                     dc
->GetTextExtent( s
, &lw
, &lh 
); 
 395                     if (m_bound_all
.width 
> m_spacing
) 
 396                         m_bound_label
.x 
= m_bound_all
.x
; 
 398                         m_bound_label
.x 
= m_bound_all
.x 
+  (m_spacing
/2) - lw
/2; 
 399                     m_bound_label
.y 
= m_bound_all
.y 
+ m_bound_all
.height 
- lh
; 
 400                     m_bound_label
.width 
= lw
; 
 401                     m_bound_label
.height 
= lh
; 
 402                     AssignRect( m_bound_hilight
, m_bound_label 
); 
 403                     m_bound_hilight
.x 
-= 2; 
 404                     m_bound_hilight
.y 
-= 2; 
 405                     m_bound_hilight
.width 
+= 4; 
 406                     m_bound_hilight
.height 
+= 4; 
 413             AssignRect( m_bound_label
, m_bound_all 
); 
 416             m_bound_all
.width 
+= 4; 
 417             m_bound_all
.height 
+= 3; 
 418             AssignRect( m_bound_hilight
, m_bound_all 
); 
 419             AssignRect( m_bound_icon
, 0, 0, 0, 0 ); 
 420             wxNode 
*node 
= m_items
.First(); 
 423                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 424                 if (item
->HasImage()) 
 426                     m_bound_icon
.x 
= m_bound_all
.x 
+ 2; 
 427                     m_bound_icon
.y 
= m_bound_all
.y 
+ 2; 
 430                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
 431                     m_bound_icon
.width 
= w
; 
 432                     m_bound_icon
.height 
= h
; 
 433                     m_bound_label
.x 
+= 4 + w
; 
 434                     m_bound_label
.width 
-= 4 + w
; 
 442             dc
->GetTextExtent( "H", &lw
, &lh 
); 
 445             m_bound_all
.height 
= lh
+3; 
 446             m_bound_all
.width 
= window_width
; 
 447             AssignRect( m_bound_hilight
, m_bound_all 
); 
 448             AssignRect( m_bound_label
, m_bound_all 
); 
 449             AssignRect( m_bound_icon
, 0, 0, 0, 0 ); 
 450             wxNode 
*node 
= m_items
.First(); 
 453                 wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 456                 if (s
.IsEmpty()) s 
= wxT("H"); 
 458                 dc
->GetTextExtent( s
, &lw
, &lh 
); 
 459                 m_bound_label
.width 
= lw
; 
 460                 m_bound_label
.height 
= lh
; 
 461                 if (item
->HasImage()) 
 463                     m_bound_icon
.x 
= m_bound_all
.x 
+ 2; 
 464                     m_bound_icon
.y 
= m_bound_all
.y 
+ 2; 
 467                     m_owner
->GetImageSize( item
->GetImage(), w
, h 
); 
 468                     m_bound_icon
.width 
= w
; 
 469                     m_bound_icon
.height 
= h
; 
 470                     m_bound_label
.x 
+= 4 + w
; 
 478 void wxListLineData::SetColumnPosition( int index
, int x 
) 
 480     wxNode 
*node 
= m_items
.Nth( (size_t)index 
); 
 483         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 484         item
->SetPosition( x
, m_bound_all
.y
+1 ); 
 488 void wxListLineData::GetSize( int &width
, int &height 
) 
 490     width 
= m_bound_all
.width
; 
 491     height 
= m_bound_all
.height
; 
 494 void wxListLineData::GetExtent( int &x
, int &y
, int &width
, int &height 
) 
 498     width 
= m_bound_all
.width
; 
 499     height 
= m_bound_all
.height
; 
 502 void wxListLineData::GetLabelExtent( int &x
, int &y
, int &width
, int &height 
) 
 506     width 
= m_bound_label
.width
; 
 507     height 
= m_bound_label
.height
; 
 510 void wxListLineData::GetRect( wxRect 
&rect 
) 
 512     AssignRect( rect
, m_bound_all 
); 
 515 long wxListLineData::IsHit( int x
, int y 
) 
 517     wxNode 
*node 
= m_items
.First(); 
 520         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 521         if (item
->HasImage() && IsInRect( x
, y
, m_bound_icon 
)) return wxLIST_HITTEST_ONITEMICON
; 
 522         if (item
->HasText() && IsInRect( x
, y
, m_bound_label 
)) return wxLIST_HITTEST_ONITEMLABEL
; 
 523 //      if (!(item->HasImage() || item->HasText())) return 0; 
 525     // if there is no icon or text = empty 
 526     if (IsInRect( x
, y
, m_bound_all 
)) return wxLIST_HITTEST_ONITEMICON
; 
 530 void wxListLineData::InitItems( int num 
) 
 532     for (int i 
= 0; i 
< num
; i
++) m_items
.Append( new wxListItemData() ); 
 535 void wxListLineData::SetItem( int index
, const wxListItem 
&info 
) 
 537     wxNode 
*node 
= m_items
.Nth( index 
); 
 540        wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 541        item
->SetItem( info 
); 
 545 void wxListLineData::GetItem( int index
, wxListItem 
&info 
) 
 548     wxNode 
*node 
= m_items
.Nth( i 
); 
 551         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 552         item
->GetItem( info 
); 
 556 void wxListLineData::GetText( int index
, wxString 
&s 
) 
 559     wxNode 
*node 
= m_items
.Nth( i 
); 
 563         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 568 void wxListLineData::SetText( int index
, const wxString s 
) 
 571     wxNode 
*node 
= m_items
.Nth( i 
); 
 574         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 579 int wxListLineData::GetImage( int index 
) 
 582     wxNode 
*node 
= m_items
.Nth( i 
); 
 585         wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 586         return item
->GetImage(); 
 591 void wxListLineData::SetAttributes(wxDC 
*dc
, 
 592                                    const wxListItemAttr 
*attr
, 
 593                                    const wxColour
& colText
, 
 597     // don't use foregroud colour for drawing highlighted items - this might 
 598     // make them completely invisible (and there is no way to do bit 
 599     // arithmetics on wxColour, unfortunately) 
 600     if ( !hilight 
&& attr 
&& attr
->HasTextColour() ) 
 602         dc
->SetTextForeground(attr
->GetTextColour()); 
 606         dc
->SetTextForeground(colText
); 
 609     if ( attr 
&& attr
->HasFont() ) 
 611         dc
->SetFont(attr
->GetFont()); 
 619 void wxListLineData::DoDraw( wxDC 
*dc
, bool hilight
, bool paintBG 
) 
 621     wxCoord dev_x 
= dc
->LogicalToDeviceX( m_bound_all
.x
-2 ); 
 622     wxCoord dev_y 
= dc
->LogicalToDeviceY( m_bound_all
.y
-2 ); 
 623     wxCoord dev_w 
= dc
->LogicalToDeviceXRel( m_bound_all
.width
+4 ); 
 624     wxCoord dev_h 
= dc
->LogicalToDeviceYRel( m_bound_all
.height
+4 ); 
 626     if (!m_owner
->IsExposed( dev_x
, dev_y
, dev_w
, dev_h 
)) 
 631     wxWindow 
*listctrl 
= m_owner
->GetParent(); 
 633     // default foreground colour 
 637         colText 
= wxSystemSettings::GetSystemColour( wxSYS_COLOUR_HIGHLIGHTTEXT 
); 
 641         colText 
= listctrl
->GetForegroundColour(); 
 645     wxFont font 
= listctrl
->GetFont(); 
 647     // VZ: currently we set the colours/fonts only once, but like this (i.e. 
 648     //     using SetAttributes() inside the loop), it will be trivial to 
 649     //     customize the subitems (in report mode) too. 
 650     wxListItemData 
*item 
= (wxListItemData
*)m_items
.First()->Data(); 
 651     wxListItemAttr 
*attr 
= item
->GetAttributes(); 
 652     SetAttributes(dc
, attr
, colText
, font
, hilight
); 
 654     bool hasBgCol 
= attr 
&& attr
->HasBackgroundColour(); 
 655     if ( paintBG 
|| hasBgCol 
) 
 659             dc
->SetBrush( * m_hilightBrush 
); 
 664                 dc
->SetBrush(wxBrush(attr
->GetBackgroundColour(), wxSOLID
)); 
 666                 dc
->SetBrush( * wxWHITE_BRUSH 
); 
 669         dc
->SetPen( * wxTRANSPARENT_PEN 
); 
 670         dc
->DrawRectangle( m_bound_hilight
.x
, m_bound_hilight
.y
, 
 671                            m_bound_hilight
.width
, m_bound_hilight
.height 
); 
 674     if (m_mode 
== wxLC_REPORT
) 
 676         wxNode 
*node 
= m_items
.First(); 
 679             wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 680             dc
->SetClippingRegion( item
->GetX(), item
->GetY(), item
->GetWidth()-3, item
->GetHeight() ); 
 681             int x 
= item
->GetX(); 
 682             if (item
->HasImage()) 
 685                 m_owner
->DrawImage( item
->GetImage(), dc
, x
, item
->GetY() ); 
 686                 m_owner
->GetImageSize( item
->GetImage(), x
, y 
); 
 687                 x 
+= item
->GetX() + 5; 
 691                 dc
->DrawText( item
->GetText(), x
, item
->GetY() ); 
 693             dc
->DestroyClippingRegion(); 
 699         wxNode 
*node 
= m_items
.First(); 
 702             wxListItemData 
*item 
= (wxListItemData
*)node
->Data(); 
 703             if (item
->HasImage()) 
 705                 m_owner
->DrawImage( item
->GetImage(), dc
, m_bound_icon
.x
, m_bound_icon
.y 
); 
 709                 dc
->DrawText( item
->GetText(), m_bound_label
.x
, m_bound_label
.y 
); 
 715 void wxListLineData::Hilight( bool on 
) 
 717     if (on 
== m_hilighted
) return; 
 720         m_owner
->SelectLine( this ); 
 722         m_owner
->DeselectLine( this ); 
 725 void wxListLineData::ReverseHilight( void ) 
 727     m_hilighted 
= !m_hilighted
; 
 729         m_owner
->SelectLine( this ); 
 731         m_owner
->DeselectLine( this ); 
 734 void wxListLineData::DrawRubberBand( wxDC 
*dc
, bool on 
) 
 738         dc
->SetPen( * wxBLACK_PEN 
); 
 739         dc
->SetBrush( * wxTRANSPARENT_BRUSH 
); 
 740         dc
->DrawRectangle( m_bound_hilight
.x
, m_bound_hilight
.y
, 
 741                            m_bound_hilight
.width
, m_bound_hilight
.height 
); 
 745 void wxListLineData::Draw( wxDC 
*dc 
) 
 747     DoDraw( dc
, m_hilighted
, m_hilighted 
); 
 750 bool wxListLineData::IsInRect( int x
, int y
, const wxRect 
&rect 
) 
 752     return ((x 
>= rect
.x
) && (x 
<= rect
.x
+rect
.width
) && 
 753             (y 
>= rect
.y
) && (y 
<= rect
.y
+rect
.height
)); 
 756 bool wxListLineData::IsHilighted( void ) 
 761 void wxListLineData::AssignRect( wxRect 
&dest
, int x
, int y
, int width
, int height 
) 
 766     dest
.height 
= height
; 
 769 void wxListLineData::AssignRect( wxRect 
&dest
, const wxRect 
&source 
) 
 773     dest
.width 
= source
.width
; 
 774     dest
.height 
= source
.height
; 
 777 //----------------------------------------------------------------------------- 
 778 //  wxListHeaderWindow 
 779 //----------------------------------------------------------------------------- 
 781 IMPLEMENT_DYNAMIC_CLASS(wxListHeaderWindow
,wxWindow
); 
 783 BEGIN_EVENT_TABLE(wxListHeaderWindow
,wxWindow
) 
 784     EVT_PAINT         (wxListHeaderWindow::OnPaint
) 
 785     EVT_MOUSE_EVENTS  (wxListHeaderWindow::OnMouse
) 
 786     EVT_SET_FOCUS     (wxListHeaderWindow::OnSetFocus
) 
 789 wxListHeaderWindow::wxListHeaderWindow( void ) 
 791     m_owner 
= (wxListMainWindow 
*) NULL
; 
 792     m_currentCursor 
= (wxCursor 
*) NULL
; 
 793     m_resizeCursor 
= (wxCursor 
*) NULL
; 
 794     m_isDragging 
= FALSE
; 
 797 wxListHeaderWindow::wxListHeaderWindow( wxWindow 
*win
, wxWindowID id
, wxListMainWindow 
*owner
, 
 798       const wxPoint 
&pos
, const wxSize 
&size
, 
 799       long style
, const wxString 
&name 
) : 
 800   wxWindow( win
, id
, pos
, size
, style
, name 
) 
 803 //  m_currentCursor = wxSTANDARD_CURSOR; 
 804     m_currentCursor 
= (wxCursor 
*) NULL
; 
 805     m_resizeCursor 
= new wxCursor( wxCURSOR_SIZEWE 
); 
 806     m_isDragging 
= FALSE
; 
 807     SetBackgroundColour( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNFACE 
) ); 
 810 wxListHeaderWindow::~wxListHeaderWindow( void ) 
 812     delete m_resizeCursor
; 
 815 void wxListHeaderWindow::DoDrawRect( wxDC 
*dc
, int x
, int y
, int w
, int h 
) 
 817     const int m_corner 
= 1; 
 819     dc
->SetBrush( *wxTRANSPARENT_BRUSH 
); 
 821     dc
->SetPen( *wxBLACK_PEN 
); 
 822     dc
->DrawLine( x
+w
-m_corner
+1, y
, x
+w
, y
+h 
);  // right (outer) 
 823     dc
->DrawRectangle( x
, y
+h
, w
+1, 1 );          // bottom (outer) 
 825     wxPen 
pen( wxSystemSettings::GetSystemColour( wxSYS_COLOUR_BTNSHADOW 
), 1, wxSOLID 
); 
 828     dc
->DrawLine( x
+w
-m_corner
, y
, x
+w
-1, y
+h 
);  // right (inner) 
 829     dc
->DrawRectangle( x
+1, y
+h
-1, w
-2, 1 );      // bottom (inner) 
 831     dc
->SetPen( *wxWHITE_PEN 
); 
 832     dc
->DrawRectangle( x
, y
, w
-m_corner
+1, 1 );   // top (outer) 
 833     dc
->DrawRectangle( x
, y
, 1, h 
);              // left (outer) 
 834     dc
->DrawLine( x
, y
+h
-1, x
+1, y
+h
-1 ); 
 835     dc
->DrawLine( x
+w
-1, y
, x
+w
-1, y
+1 ); 
 838 void wxListHeaderWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
 840     wxPaintDC 
dc( this ); 
 842 #if wxUSE_GENERIC_LIST_EXTENSIONS 
 843         if ( m_owner
->GetMode() & wxLC_REPORT 
) 
 848                 m_owner
->GetScrollPixelsPerUnit( &xpix 
, &ypix 
) ; 
 849                 m_owner
->ViewStart( &x
, &y 
) ; 
 850             dc
.SetDeviceOrigin( -x 
* xpix
, 0 ); 
 855     dc
.SetFont( GetFont() ); 
 861     GetClientSize( &w
, &h 
); 
 863     dc
.SetBackgroundMode(wxTRANSPARENT
); 
 864     dc
.SetTextForeground( *wxBLACK 
); 
 866     // do *not* use the listctrl colour for headers - one day we will have a 
 867     // function to set it separately 
 871     int numColumns 
= m_owner
->GetColumnCount(); 
 873     for (int i 
= 0; i 
< numColumns
; i
++) 
 875         m_owner
->GetColumn( i
, item 
); 
 876         int cw 
= item
.m_width
-2; 
 877 #if wxUSE_GENERIC_LIST_EXTENSIONS 
 878         if ((i
+1 == numColumns
) || ( dc
.LogicalToDeviceX(x
+item
.m_width
) > w
-5)) 
 879             cw 
= dc
.DeviceToLogicalX(w
)-x
-1; 
 881         if ((i
+1 == numColumns
) || (x
+item
.m_width 
> w
-5)) 
 884         dc
.SetPen( *wxWHITE_PEN 
); 
 886         DoDrawRect( &dc
, x
, y
, cw
, h
-2 ); 
 887         dc
.SetClippingRegion( x
, y
, cw
-5, h
-4 ); 
 888         dc
.DrawText( item
.m_text
, x
+4, y
+3 ); 
 889         dc
.DestroyClippingRegion(); 
 891 #if wxUSE_GENERIC_LIST_EXTENSIONS 
 892         if (dc
.LogicalToDeviceX(x
) > w
+5) break; 
 900 void wxListHeaderWindow::DrawCurrent() 
 904     int x2 
= m_currentX
-1; 
 907     m_owner
->GetClientSize( &dummy
, &y2 
); 
 908     ClientToScreen( &x1
, &y1 
); 
 909     m_owner
->ClientToScreen( &x2
, &y2 
); 
 912     dc
.SetLogicalFunction( wxINVERT 
); 
 913     dc
.SetPen( wxPen( *wxBLACK
, 2, wxSOLID 
) ); 
 914     dc
.SetBrush( *wxTRANSPARENT_BRUSH 
); 
 916     dc
.DrawLine( x1
, y1
, x2
, y2 
); 
 918     dc
.SetLogicalFunction( wxCOPY 
); 
 920     dc
.SetPen( wxNullPen 
); 
 921     dc
.SetBrush( wxNullBrush 
); 
 924 void wxListHeaderWindow::OnMouse( wxMouseEvent 
&event 
) 
 926     wxCoord x 
= (wxCoord
)event
.GetX(); 
 927     wxCoord y 
= (wxCoord
)event
.GetY(); 
 931         if (event
.ButtonUp()) 
 934             m_isDragging 
= FALSE
; 
 935             m_owner
->SetColumnWidth( m_column
, m_currentX
-m_minX 
); 
 941             GetClientSize( &size_x
, & dummy 
); 
 945                 m_currentX 
= m_minX
+7; 
 946             if (m_currentX 
> size_x
-7) m_currentX 
= size_x
-7; 
 953     bool hit_border 
= FALSE
; 
 955     for (int j 
= 0; j 
< m_owner
->GetColumnCount()-1; j
++) 
 957         xpos 
+= m_owner
->GetColumnWidth( j 
); 
 959         if ((abs(x
-xpos
) < 3) && (y 
< 22)) 
 971     if (event
.LeftDown()) 
 983             wxListEvent 
le( wxEVT_COMMAND_LIST_COL_CLICK
, GetParent()->GetId() ); 
 984             le
.SetEventObject( GetParent() ); 
 986             GetParent()->GetEventHandler()->ProcessEvent( le 
); 
 995             if (m_currentCursor 
== wxSTANDARD_CURSOR
) SetCursor( * m_resizeCursor 
); 
 996             m_currentCursor 
= m_resizeCursor
; 
1000             if (m_currentCursor 
!= wxSTANDARD_CURSOR
) SetCursor( * wxSTANDARD_CURSOR 
); 
1001             m_currentCursor 
= wxSTANDARD_CURSOR
; 
1006 void wxListHeaderWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1008     m_owner
->SetFocus(); 
1011 //----------------------------------------------------------------------------- 
1012 // wxListRenameTimer (internal) 
1013 //----------------------------------------------------------------------------- 
1015 wxListRenameTimer::wxListRenameTimer( wxListMainWindow 
*owner 
) 
1020 void wxListRenameTimer::Notify() 
1022     m_owner
->OnRenameTimer(); 
1025 //----------------------------------------------------------------------------- 
1026 // wxListTextCtrl (internal) 
1027 //----------------------------------------------------------------------------- 
1029 IMPLEMENT_DYNAMIC_CLASS(wxListTextCtrl
,wxTextCtrl
); 
1031 BEGIN_EVENT_TABLE(wxListTextCtrl
,wxTextCtrl
) 
1032     EVT_CHAR           (wxListTextCtrl::OnChar
) 
1033     EVT_KILL_FOCUS     (wxListTextCtrl::OnKillFocus
) 
1036 wxListTextCtrl::wxListTextCtrl( wxWindow 
*parent
, 
1037                                 const wxWindowID id
, 
1040                                 wxListMainWindow 
*owner
, 
1041                                 const wxString 
&value
, 
1045                                 const wxValidator
& validator
, 
1046                                 const wxString 
&name 
) 
1047               : wxTextCtrl( parent
, id
, value
, pos
, size
, style
, validator
, name 
) 
1052     (*m_accept
) = FALSE
; 
1054     m_startValue 
= value
; 
1057 void wxListTextCtrl::OnChar( wxKeyEvent 
&event 
) 
1059     if (event
.m_keyCode 
== WXK_RETURN
) 
1062         (*m_res
) = GetValue(); 
1063         m_owner
->SetFocus(); 
1066     if (event
.m_keyCode 
== WXK_ESCAPE
) 
1068         (*m_accept
) = FALSE
; 
1070         m_owner
->SetFocus(); 
1076 void wxListTextCtrl::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1078     if (wxPendingDelete
.Member(this)) return; 
1080     wxPendingDelete
.Append(this); 
1082     if ((*m_accept
) && ((*m_res
) != m_startValue
)) 
1083         m_owner
->OnRenameAccept(); 
1086 //----------------------------------------------------------------------------- 
1088 //----------------------------------------------------------------------------- 
1090 IMPLEMENT_DYNAMIC_CLASS(wxListMainWindow
,wxScrolledWindow
); 
1092 BEGIN_EVENT_TABLE(wxListMainWindow
,wxScrolledWindow
) 
1093   EVT_PAINT          (wxListMainWindow::OnPaint
) 
1094   EVT_SIZE           (wxListMainWindow::OnSize
) 
1095   EVT_MOUSE_EVENTS   (wxListMainWindow::OnMouse
) 
1096   EVT_CHAR           (wxListMainWindow::OnChar
) 
1097   EVT_KEY_DOWN       (wxListMainWindow::OnKeyDown
) 
1098   EVT_SET_FOCUS      (wxListMainWindow::OnSetFocus
) 
1099   EVT_KILL_FOCUS     (wxListMainWindow::OnKillFocus
) 
1100   EVT_SCROLLWIN                 (wxListMainWindow::OnScroll
) 
1103 wxListMainWindow::wxListMainWindow() 
1106     m_lines
.DeleteContents( TRUE 
); 
1107     m_columns
.DeleteContents( TRUE 
); 
1108     m_current 
= (wxListLineData 
*) NULL
; 
1110     m_hilightBrush 
= (wxBrush 
*) NULL
; 
1114     m_small_image_list 
= (wxImageList 
*) NULL
; 
1115     m_normal_image_list 
= (wxImageList 
*) NULL
; 
1116     m_small_spacing 
= 30; 
1117     m_normal_spacing 
= 40; 
1120     m_lastOnSame 
= FALSE
; 
1121     m_renameTimer 
= new wxListRenameTimer( this ); 
1122     m_isCreated 
= FALSE
; 
1126 wxListMainWindow::wxListMainWindow( wxWindow 
*parent
, wxWindowID id
, 
1127       const wxPoint 
&pos
, const wxSize 
&size
, 
1128       long style
, const wxString 
&name 
) : 
1129   wxScrolledWindow( parent
, id
, pos
, size
, style
|wxHSCROLL
|wxVSCROLL
, name 
) 
1132     m_lines
.DeleteContents( TRUE 
); 
1133     m_columns
.DeleteContents( TRUE 
); 
1134     m_current 
= (wxListLineData 
*) NULL
; 
1137     m_hilightBrush 
= new wxBrush( wxSystemSettings::GetSystemColour(wxSYS_COLOUR_HIGHLIGHT
), wxSOLID 
); 
1138     m_small_image_list 
= (wxImageList 
*) NULL
; 
1139     m_normal_image_list 
= (wxImageList 
*) NULL
; 
1140     m_small_spacing 
= 30; 
1141     m_normal_spacing 
= 40; 
1144     m_isCreated 
= FALSE
; 
1148     if (m_mode 
& wxLC_REPORT
) 
1150 #if wxUSE_GENERIC_LIST_EXTENSIONS 
1162     SetScrollbars( m_xScroll
, m_yScroll
, 0, 0, 0, 0 ); 
1165     m_lastOnSame 
= FALSE
; 
1166     m_renameTimer 
= new wxListRenameTimer( this ); 
1167     m_renameAccept 
= FALSE
; 
1169     SetBackgroundColour( *wxWHITE 
); 
1172 wxListMainWindow::~wxListMainWindow() 
1176     if (m_hilightBrush
) delete m_hilightBrush
; 
1178     delete m_renameTimer
; 
1181 void wxListMainWindow::RefreshLine( wxListLineData 
*line 
) 
1183     if (m_dirty
) return; 
1191         wxClientDC 
dc(this); 
1193         line
->GetExtent( x
, y
, w
, h 
); 
1195           dc
.LogicalToDeviceX(x
-3), 
1196           dc
.LogicalToDeviceY(y
-3), 
1197           dc
.LogicalToDeviceXRel(w
+6), 
1198           dc
.LogicalToDeviceXRel(h
+6) ); 
1199         Refresh( TRUE
, &rect 
); 
1203 void wxListMainWindow::OnPaint( wxPaintEvent 
&WXUNUSED(event
) ) 
1205     // Note: a wxPaintDC must be constructed even if no drawing is 
1206     // done (a Windows requirement). 
1207     wxPaintDC 
dc( this ); 
1210     if (m_dirty
) return; 
1212     if (m_lines
.GetCount() == 0) return; 
1216     dc
.SetFont( GetFont() ); 
1218     if (m_mode 
& wxLC_REPORT
) 
1220         int lineSpacing 
= 0; 
1221         wxListLineData 
*line 
= (wxListLineData
*)m_lines
.First()->Data(); 
1223         line
->GetSize( dummy
, lineSpacing 
); 
1226         int y_s 
= m_yScroll
*GetScrollPos( wxVERTICAL 
); 
1228         wxNode 
*node 
= m_lines
.Nth( y_s 
/ lineSpacing 
); 
1229         for (int i 
= 0; i 
< m_visibleLines
+2; i
++) 
1233             line 
= (wxListLineData
*)node
->Data(); 
1235             node 
= node
->Next(); 
1240         wxNode 
*node 
= m_lines
.First(); 
1243             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1245             node 
= node
->Next(); 
1249     if (m_current
) m_current
->DrawRubberBand( &dc
, m_hasFocus 
); 
1254 void wxListMainWindow::HilightAll( bool on 
) 
1256     wxNode 
*node 
= m_lines
.First(); 
1259         wxListLineData 
*line 
= (wxListLineData 
*)node
->Data(); 
1260         if (line
->IsHilighted() != on
) 
1262             line
->Hilight( on 
); 
1263             RefreshLine( line 
); 
1265         node 
= node
->Next(); 
1269 void wxListMainWindow::SendNotify( wxListLineData 
*line
, wxEventType command 
) 
1271     wxListEvent 
le( command
, GetParent()->GetId() ); 
1272     le
.SetEventObject( GetParent() ); 
1273     le
.m_itemIndex 
= GetIndexOfLine( line 
); 
1274     line
->GetItem( 0, le
.m_item 
); 
1275     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1276 //    GetParent()->GetEventHandler()->AddPendingEvent( le ); 
1279 void wxListMainWindow::FocusLine( wxListLineData 
*WXUNUSED(line
) ) 
1281 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_FOCUSSED ); 
1284 void wxListMainWindow::UnfocusLine( wxListLineData 
*WXUNUSED(line
) ) 
1286 //  SendNotify( line, wxEVT_COMMAND_LIST_ITEM_UNFOCUSSED ); 
1289 void wxListMainWindow::SelectLine( wxListLineData 
*line 
) 
1291     SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_SELECTED 
); 
1294 void wxListMainWindow::DeselectLine( wxListLineData 
*line 
) 
1296     SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_DESELECTED 
); 
1299 void wxListMainWindow::DeleteLine( wxListLineData 
*line 
) 
1301     SendNotify( line
, wxEVT_COMMAND_LIST_DELETE_ITEM 
); 
1306 void wxListMainWindow::EditLabel( long item 
) 
1308     wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
1309     wxCHECK_RET( node
, wxT("wrong index in wxListCtrl::Edit()") ); 
1311     m_currentEdit 
= (wxListLineData
*) node
->Data(); 
1313     wxListEvent 
le( wxEVT_COMMAND_LIST_BEGIN_LABEL_EDIT
, GetParent()->GetId() ); 
1314     le
.SetEventObject( GetParent() ); 
1315     le
.m_itemIndex 
= GetIndexOfLine( m_currentEdit 
); 
1316     m_currentEdit
->GetItem( 0, le
.m_item 
); 
1317     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1319     if (!le
.IsAllowed()) 
1322     // We have to call this here because the label in 
1323     // question might just have been added and no screen 
1324     // update taken place. 
1325     if (m_dirty
) wxYield(); 
1328     m_currentEdit
->GetText( 0, s 
); 
1333     m_currentEdit
->GetLabelExtent( x
, y
, w
, h 
); 
1335     wxClientDC 
dc(this); 
1337     x 
= dc
.LogicalToDeviceX( x 
); 
1338     y 
= dc
.LogicalToDeviceY( y 
); 
1340     wxListTextCtrl 
*text 
= new wxListTextCtrl( 
1341       this, -1, &m_renameAccept
, &m_renameRes
, this, s
, wxPoint(x
-4,y
-4), wxSize(w
+11,h
+8) ); 
1345 void wxListMainWindow::OnRenameTimer() 
1347     wxCHECK_RET( m_current
, wxT("invalid m_current") ); 
1349     Edit( m_lines
.IndexOf( m_current 
) ); 
1352 void wxListMainWindow::OnRenameAccept() 
1354     wxListEvent 
le( wxEVT_COMMAND_LIST_END_LABEL_EDIT
, GetParent()->GetId() ); 
1355     le
.SetEventObject( GetParent() ); 
1356     le
.m_itemIndex 
= GetIndexOfLine( m_currentEdit 
); 
1357     m_currentEdit
->GetItem( 0, le
.m_item 
); 
1358     le
.m_item
.m_text 
= m_renameRes
; 
1359     GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1361     if (!le
.IsAllowed()) return; 
1364     info
.m_mask 
= wxLIST_MASK_TEXT
; 
1365     info
.m_itemId 
= le
.m_itemIndex
; 
1366     info
.m_text 
= m_renameRes
; 
1367     info
.SetTextColour(le
.m_item
.GetTextColour()); 
1371 void wxListMainWindow::OnMouse( wxMouseEvent 
&event 
) 
1373     if (GetParent()->GetEventHandler()->ProcessEvent( event
)) return; 
1375     if (!m_current
) return; 
1376     if (m_dirty
) return; 
1377     if ( !(event
.Dragging() || event
.ButtonDown() || event
.LeftUp() || event
.ButtonDClick()) ) return; 
1379     wxClientDC 
dc(this); 
1381     wxCoord x 
= dc
.DeviceToLogicalX( (wxCoord
)event
.GetX() ); 
1382     wxCoord y 
= dc
.DeviceToLogicalY( (wxCoord
)event
.GetY() ); 
1384     /* Did we actually hit an item ? */ 
1386     wxNode 
*node 
= m_lines
.First(); 
1387     wxListLineData 
*line 
= (wxListLineData 
*) NULL
; 
1390         line 
= (wxListLineData
*)node
->Data(); 
1391         hitResult 
= line
->IsHit( x
, y 
); 
1392         if (hitResult
) break; 
1393         line 
= (wxListLineData 
*) NULL
; 
1394         node 
= node
->Next(); 
1397     if (event
.Dragging()) 
1399         if (m_dragCount 
== 0) 
1400             m_dragStart 
= wxPoint(x
,y
); 
1404         if (m_dragCount 
!= 3) return; 
1406         int command 
= wxEVT_COMMAND_LIST_BEGIN_DRAG
; 
1407         if (event
.RightIsDown()) command 
= wxEVT_COMMAND_LIST_BEGIN_RDRAG
; 
1409         wxListEvent 
le( command
, GetParent()->GetId() ); 
1410         le
.SetEventObject( GetParent() ); 
1411         le
.m_pointDrag 
= m_dragStart
; 
1412         GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1423     if (event
.ButtonDClick()) 
1426         m_lastOnSame 
= FALSE
; 
1427         m_renameTimer
->Stop(); 
1429         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_ACTIVATED 
); 
1434     if (event
.LeftUp() && m_lastOnSame
) 
1437         if ((line 
== m_current
) && 
1438             (hitResult 
== wxLIST_HITTEST_ONITEMLABEL
) && 
1439             (m_mode 
& wxLC_EDIT_LABELS
)  ) 
1441             m_renameTimer
->Start( 100, TRUE 
); 
1443         m_lastOnSame 
= FALSE
; 
1447     if (event
.RightDown()) 
1449         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_RIGHT_CLICK 
); 
1453     if (event
.MiddleDown()) 
1455         SendNotify( line
, wxEVT_COMMAND_LIST_ITEM_MIDDLE_CLICK 
); 
1459     if (event
.LeftDown()) 
1462         wxListLineData 
*oldCurrent 
= m_current
; 
1463         if (m_mode 
& wxLC_SINGLE_SEL
) 
1466             HilightAll( FALSE 
); 
1467             m_current
->ReverseHilight(); 
1468             RefreshLine( m_current 
); 
1472             if (event
.ControlDown()) 
1475                 m_current
->ReverseHilight(); 
1476                 RefreshLine( m_current 
); 
1478             else if (event
.ShiftDown()) 
1482                 int numOfCurrent 
= -1; 
1483                 node 
= m_lines
.First(); 
1486                     wxListLineData 
*test_line 
= (wxListLineData
*)node
->Data(); 
1488                     if (test_line 
== oldCurrent
) break; 
1489                     node 
= node
->Next(); 
1493                 node 
= m_lines
.First(); 
1496                     wxListLineData 
*test_line 
= (wxListLineData
*)node
->Data(); 
1498                     if (test_line 
== line
) break; 
1499                     node 
= node
->Next(); 
1502                 if (numOfLine 
< numOfCurrent
) 
1505                     numOfLine 
= numOfCurrent
; 
1509                 wxNode 
*node 
= m_lines
.Nth( numOfCurrent 
); 
1510                 for (int i 
= 0; i 
<= numOfLine
-numOfCurrent
; i
++) 
1512                     wxListLineData 
*test_line
= (wxListLineData
*)node
->Data(); 
1513                     test_line
->Hilight(TRUE
); 
1514                     RefreshLine( test_line 
); 
1515                     node 
= node
->Next(); 
1521                 HilightAll( FALSE 
); 
1522                 m_current
->ReverseHilight(); 
1523                 RefreshLine( m_current 
); 
1526         if (m_current 
!= oldCurrent
) 
1528             RefreshLine( oldCurrent 
); 
1529             UnfocusLine( oldCurrent 
); 
1530             FocusLine( m_current 
); 
1532         m_lastOnSame 
= (m_current 
== oldCurrent
); 
1537 void wxListMainWindow::MoveToFocus() 
1539     if (!m_current
) return; 
1545     m_current
->GetExtent( item_x
, item_y
, item_w
, item_h 
); 
1549     GetClientSize( &client_w
, &client_h 
); 
1551     int view_x 
= m_xScroll
*GetScrollPos( wxHORIZONTAL 
); 
1552     int view_y 
= m_yScroll
*GetScrollPos( wxVERTICAL 
); 
1554     if (m_mode 
& wxLC_REPORT
) 
1556         if (item_y
-5 < view_y 
)  
1557             Scroll( -1, (item_y
-5)/m_yScroll 
);  
1558         if (item_y
+item_h
+5 > view_y
+client_h
)  
1559             Scroll( -1, (item_y
+item_h
-client_h
+15)/m_yScroll 
); 
1563         if (item_x
-view_x 
< 5)  
1564             Scroll( (item_x
-5)/m_xScroll
, -1 ); 
1565         if (item_x
+item_w
-5 > view_x
+client_w
)  
1566             Scroll( (item_x
+item_w
-client_w
+15)/m_xScroll
, -1 ); 
1570 void wxListMainWindow::OnArrowChar( wxListLineData 
*newCurrent
, bool shiftDown 
) 
1572     if ((m_mode 
& wxLC_SINGLE_SEL
) || (m_usedKeys 
== FALSE
)) m_current
->Hilight( FALSE 
); 
1573     wxListLineData 
*oldCurrent 
= m_current
; 
1574     m_current 
= newCurrent
; 
1575     if (shiftDown 
|| (m_mode 
& wxLC_SINGLE_SEL
)) m_current
->Hilight( TRUE 
); 
1576     RefreshLine( m_current 
); 
1577     RefreshLine( oldCurrent 
); 
1578     FocusLine( m_current 
); 
1579     UnfocusLine( oldCurrent 
); 
1583 void wxListMainWindow::OnKeyDown( wxKeyEvent 
&event 
) 
1585     wxWindow 
*parent 
= GetParent(); 
1587     /* we propagate the key event up */ 
1588     wxKeyEvent 
ke( wxEVT_KEY_DOWN 
); 
1589     ke
.m_shiftDown 
= event
.m_shiftDown
; 
1590     ke
.m_controlDown 
= event
.m_controlDown
; 
1591     ke
.m_altDown 
= event
.m_altDown
; 
1592     ke
.m_metaDown 
= event
.m_metaDown
; 
1593     ke
.m_keyCode 
= event
.m_keyCode
; 
1596     ke
.SetEventObject( parent 
); 
1597     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
1602 void wxListMainWindow::OnChar( wxKeyEvent 
&event 
) 
1604     wxWindow 
*parent 
= GetParent(); 
1606     /* we send a list_key event up */ 
1607     wxListEvent 
le( wxEVT_COMMAND_LIST_KEY_DOWN
, GetParent()->GetId() ); 
1608     le
.m_code 
= (int)event
.KeyCode(); 
1609     le
.SetEventObject( parent 
); 
1610     parent
->GetEventHandler()->ProcessEvent( le 
); 
1612     /* we propagate the char event up */ 
1613     wxKeyEvent 
ke( wxEVT_CHAR 
); 
1614     ke
.m_shiftDown 
= event
.m_shiftDown
; 
1615     ke
.m_controlDown 
= event
.m_controlDown
; 
1616     ke
.m_altDown 
= event
.m_altDown
; 
1617     ke
.m_metaDown 
= event
.m_metaDown
; 
1618     ke
.m_keyCode 
= event
.m_keyCode
; 
1621     ke
.SetEventObject( parent 
); 
1622     if (parent
->GetEventHandler()->ProcessEvent( ke 
)) return; 
1624     if (event
.KeyCode() == WXK_TAB
) 
1626         wxNavigationKeyEvent nevent
; 
1627         nevent
.SetDirection( !event
.ShiftDown() ); 
1628         nevent
.SetEventObject( GetParent()->GetParent() ); 
1629         nevent
.SetCurrentFocus( m_parent 
); 
1630         if (GetParent()->GetParent()->GetEventHandler()->ProcessEvent( nevent 
)) return; 
1633     /* no item -> nothing to do */ 
1640     switch (event
.KeyCode()) 
1644             wxNode 
*node 
= m_lines
.Member( m_current 
)->Previous(); 
1645             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1650             wxNode 
*node 
= m_lines
.Member( m_current 
)->Next(); 
1651             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1656             wxNode 
*node 
= m_lines
.Last(); 
1657             OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1662             wxNode 
*node 
= m_lines
.First(); 
1663             OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1669             if (m_mode 
& wxLC_REPORT
) 
1671                 steps 
= m_visibleLines
-1; 
1676                 wxNode 
*node 
= m_lines
.First(); 
1677                 for (;;) { if (m_current 
== (wxListLineData
*)node
->Data()) break; pos
++; node 
= node
->Next(); } 
1678                 steps 
= pos 
% m_visibleLines
; 
1680             wxNode 
*node 
= m_lines
.Member( m_current 
); 
1681             for (int i 
= 0; i 
< steps
; i
++) if (node
->Previous()) node 
= node
->Previous(); 
1682             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1688             if (m_mode 
& wxLC_REPORT
) 
1690                 steps 
= m_visibleLines
-1; 
1694                 int pos 
= 0; wxNode 
*node 
= m_lines
.First(); 
1695                 for (;;) { if (m_current 
== (wxListLineData
*)node
->Data()) break; pos
++; node 
= node
->Next(); } 
1696                 steps 
= m_visibleLines
-(pos 
% m_visibleLines
)-1; 
1698             wxNode 
*node 
= m_lines
.Member( m_current 
); 
1699             for (int i 
= 0; i 
< steps
; i
++) if (node
->Next()) node 
= node
->Next(); 
1700             if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1705             if (!(m_mode 
& wxLC_REPORT
)) 
1707                 wxNode 
*node 
= m_lines
.Member( m_current 
); 
1708                 for (int i 
= 0; i 
<m_visibleLines
; i
++) if (node
->Previous()) node 
= node
->Previous(); 
1709                 if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1715             if (!(m_mode 
& wxLC_REPORT
)) 
1717                 wxNode 
*node 
= m_lines
.Member( m_current 
); 
1718                 for (int i 
= 0; i 
<m_visibleLines
; i
++) if (node
->Next()) node 
= node
->Next(); 
1719                 if (node
) OnArrowChar( (wxListLineData
*)node
->Data(), event
.ShiftDown() ); 
1725             m_current
->ReverseHilight(); 
1726             RefreshLine( m_current 
); 
1731             if (!(m_mode 
& wxLC_SINGLE_SEL
)) 
1733                 wxListLineData 
*oldCurrent 
= m_current
; 
1734                 m_current
->ReverseHilight(); 
1735                 wxNode 
*node 
= m_lines
.Member( m_current 
)->Next(); 
1736                 if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
1737                 RefreshLine( oldCurrent 
); 
1738                 RefreshLine( m_current 
); 
1739                 UnfocusLine( oldCurrent 
); 
1740                 FocusLine( m_current 
); 
1748             wxListEvent 
le( wxEVT_COMMAND_LIST_ITEM_ACTIVATED
, GetParent()->GetId() ); 
1749             le
.SetEventObject( GetParent() ); 
1750             le
.m_itemIndex 
= GetIndexOfLine( m_current 
); 
1751             m_current
->GetItem( 0, le
.m_item 
); 
1752             GetParent()->GetEventHandler()->ProcessEvent( le 
); 
1765 extern wxWindow 
*g_focusWindow
; 
1768 void wxListMainWindow::OnSetFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1771     RefreshLine( m_current 
); 
1773     if (!GetParent()) return; 
1776     g_focusWindow 
= GetParent(); 
1779     wxFocusEvent 
event( wxEVT_SET_FOCUS
, GetParent()->GetId() ); 
1780     event
.SetEventObject( GetParent() ); 
1781     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
1784 void wxListMainWindow::OnKillFocus( wxFocusEvent 
&WXUNUSED(event
) ) 
1787     RefreshLine( m_current 
); 
1790 void wxListMainWindow::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
1793   We don't even allow the wxScrolledWindow::AdjustScrollbars() call 
1798 void wxListMainWindow::DrawImage( int index
, wxDC 
*dc
, int x
, int y 
) 
1800     if ((m_mode 
& wxLC_ICON
) && (m_normal_image_list
)) 
1802         m_normal_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1805     if ((m_mode 
& wxLC_SMALL_ICON
) && (m_small_image_list
)) 
1807         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1809     if ((m_mode 
& wxLC_LIST
) && (m_small_image_list
)) 
1811         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1813     if ((m_mode 
& wxLC_REPORT
) && (m_small_image_list
)) 
1815         m_small_image_list
->Draw( index
, *dc
, x
, y
, wxIMAGELIST_DRAW_TRANSPARENT 
); 
1820 void wxListMainWindow::GetImageSize( int index
, int &width
, int &height 
) 
1822     if ((m_mode 
& wxLC_ICON
) && (m_normal_image_list
)) 
1824         m_normal_image_list
->GetSize( index
, width
, height 
); 
1827     if ((m_mode 
& wxLC_SMALL_ICON
) && (m_small_image_list
)) 
1829         m_small_image_list
->GetSize( index
, width
, height 
); 
1832     if ((m_mode 
& wxLC_LIST
) && (m_small_image_list
)) 
1834         m_small_image_list
->GetSize( index
, width
, height 
); 
1837     if ((m_mode 
& wxLC_REPORT
) && (m_small_image_list
)) 
1839         m_small_image_list
->GetSize( index
, width
, height 
); 
1846 int wxListMainWindow::GetTextLength( wxString 
&s 
) 
1848     wxClientDC 
dc( this ); 
1851     dc
.GetTextExtent( s
, &lw
, &lh 
); 
1855 int wxListMainWindow::GetIndexOfLine( const wxListLineData 
*line 
) 
1858     wxNode 
*node 
= m_lines
.First(); 
1861         if (line 
== (wxListLineData
*)node
->Data()) return i
; 
1863         node 
= node
->Next(); 
1868 void wxListMainWindow::SetImageList( wxImageList 
*imageList
, int which 
) 
1871     if (which 
== wxIMAGE_LIST_NORMAL
) m_normal_image_list 
= imageList
; 
1872     if (which 
== wxIMAGE_LIST_SMALL
) m_small_image_list 
= imageList
; 
1875 void wxListMainWindow::SetItemSpacing( int spacing
, bool isSmall 
) 
1880         m_small_spacing 
= spacing
; 
1884         m_normal_spacing 
= spacing
; 
1888 int wxListMainWindow::GetItemSpacing( bool isSmall 
) 
1890     if (isSmall
) return m_small_spacing
; else return m_normal_spacing
; 
1893 void wxListMainWindow::SetColumn( int col
, wxListItem 
&item 
) 
1896     wxNode 
*node 
= m_columns
.Nth( col 
); 
1899         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) item
.m_width 
= GetTextLength( item
.m_text 
)+7; 
1900         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1901         column
->SetItem( item 
); 
1903     wxListCtrl 
*lc 
= (wxListCtrl
*) GetParent(); 
1904     if (lc
->m_headerWin
) lc
->m_headerWin
->Refresh(); 
1907 void wxListMainWindow::SetColumnWidth( int col
, int width 
) 
1909     if (!(m_mode 
& wxLC_REPORT
)) return; 
1913     wxNode 
*node 
= (wxNode
*) NULL
; 
1915     if (width 
== wxLIST_AUTOSIZE_USEHEADER
) width 
= 80; 
1916     if (width 
== wxLIST_AUTOSIZE
) 
1918         wxClientDC 
dc(this); 
1919         dc
.SetFont( GetFont() ); 
1921         node 
= m_lines
.First(); 
1924             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1925             wxNode 
*n 
= line
->m_items
.Nth( col 
); 
1928                 wxListItemData 
*item 
= (wxListItemData
*)n
->Data(); 
1929                 int current 
= 0, ix 
= 0, iy 
= 0; 
1930                 wxCoord lx 
= 0, ly 
= 0; 
1931                 if (item
->HasImage()) 
1933                     GetImageSize( item
->GetImage(), ix
, iy 
); 
1936                 if (item
->HasText()) 
1939                     item
->GetText( str 
); 
1940                     dc
.GetTextExtent( str
, &lx
, &ly 
); 
1943                 if (current 
> max
) max 
= current
; 
1945             node 
= node
->Next(); 
1950     node 
= m_columns
.Nth( col 
); 
1953         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1954         column
->SetWidth( width 
); 
1957     node 
= m_lines
.First(); 
1960         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
1961         wxNode 
*n 
= line
->m_items
.Nth( col 
); 
1964             wxListItemData 
*item 
= (wxListItemData
*)n
->Data(); 
1965             item
->SetSize( width
, -1 ); 
1967         node 
= node
->Next(); 
1970     wxListCtrl 
*lc 
= (wxListCtrl
*) GetParent(); 
1971     if (lc
->m_headerWin
) lc
->m_headerWin
->Refresh(); 
1974 void wxListMainWindow::GetColumn( int col
, wxListItem 
&item 
) 
1976     wxNode 
*node 
= m_columns
.Nth( col 
); 
1979         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1980         column
->GetItem( item 
); 
1992 int wxListMainWindow::GetColumnWidth( int col 
) 
1994     wxNode 
*node 
= m_columns
.Nth( col 
); 
1997         wxListHeaderData 
*column 
= (wxListHeaderData
*)node
->Data(); 
1998         return column
->GetWidth(); 
2006 int wxListMainWindow::GetColumnCount() 
2008     return m_columns
.Number(); 
2011 int wxListMainWindow::GetCountPerPage() 
2013     return m_visibleLines
; 
2016 void wxListMainWindow::SetItem( wxListItem 
&item 
) 
2019     wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2022         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2023         if (m_mode 
& wxLC_REPORT
) item
.m_width 
= GetColumnWidth( item
.m_col 
)-3; 
2024         line
->SetItem( item
.m_col
, item 
); 
2028 void wxListMainWindow::SetItemState( long item
, long state
, long stateMask 
) 
2030     // m_dirty = TRUE; no recalcs needed 
2032     wxListLineData 
*oldCurrent 
= m_current
; 
2034     if (stateMask 
& wxLIST_STATE_FOCUSED
) 
2036         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2039             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2040             UnfocusLine( m_current 
); 
2042             FocusLine( m_current 
); 
2043             RefreshLine( m_current 
); 
2044             if (oldCurrent
) RefreshLine( oldCurrent 
); 
2048     if (stateMask 
& wxLIST_STATE_SELECTED
) 
2050         bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
2051         if (!on 
&& (m_mode 
& wxLC_SINGLE_SEL
)) return; 
2053         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2056             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2057             if (m_mode 
& wxLC_SINGLE_SEL
) 
2059                 UnfocusLine( m_current 
); 
2061                 FocusLine( m_current 
); 
2062                 if (oldCurrent
) oldCurrent
->Hilight( FALSE 
); 
2063                 RefreshLine( m_current 
); 
2064                 if (oldCurrent
) RefreshLine( oldCurrent 
); 
2066             bool on 
= (state 
& wxLIST_STATE_SELECTED
) != 0; 
2067             if (on 
!= line
->IsHilighted()) 
2069                 line
->Hilight( on 
); 
2070                 RefreshLine( line 
); 
2076 int wxListMainWindow::GetItemState( long item
, long stateMask 
) 
2078     int ret 
= wxLIST_STATE_DONTCARE
; 
2079     if (stateMask 
& wxLIST_STATE_FOCUSED
) 
2081         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2084             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2085             if (line 
== m_current
) ret 
|= wxLIST_STATE_FOCUSED
; 
2088     if (stateMask 
& wxLIST_STATE_SELECTED
) 
2090         wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2093             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2094             if (line
->IsHilighted()) ret 
|= wxLIST_STATE_FOCUSED
; 
2100 void wxListMainWindow::GetItem( wxListItem 
&item 
) 
2102     wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2105         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2106         line
->GetItem( item
.m_col
, item 
); 
2117 int wxListMainWindow::GetItemCount() 
2119     return m_lines
.Number(); 
2122 void wxListMainWindow::GetItemRect( long index
, wxRect 
&rect 
) 
2124     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2127         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2128         line
->GetRect( rect 
); 
2139 bool wxListMainWindow::GetItemPosition(long item
, wxPoint
& pos
) 
2141     wxNode 
*node 
= m_lines
.Nth( (size_t)item 
); 
2145         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2146         line
->GetRect( rect 
); 
2158 int wxListMainWindow::GetSelectedItemCount() 
2161     wxNode 
*node 
= m_lines
.First(); 
2164         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2165         if (line
->IsHilighted()) ret
++; 
2166         node 
= node
->Next(); 
2171 void wxListMainWindow::SetMode( long mode 
) 
2178     if (m_mode 
& wxLC_REPORT
) 
2180 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2194 long wxListMainWindow::GetMode() const 
2199 void wxListMainWindow::CalculatePositions() 
2201     if (!m_lines
.First()) return; 
2203     wxClientDC 
dc( this ); 
2204     dc
.SetFont( GetFont() ); 
2206     int iconSpacing 
= 0; 
2207     if (m_mode 
& wxLC_ICON
) iconSpacing 
= m_normal_spacing
; 
2208     if (m_mode 
& wxLC_SMALL_ICON
) iconSpacing 
= m_small_spacing
; 
2210     // we take the first line (which also can be an icon or 
2211     // an a text item in wxLC_ICON and wxLC_LIST modes) to 
2212     // measure the size of the line 
2216     int lineSpacing 
= 0; 
2218     wxListLineData 
*line 
= (wxListLineData
*)m_lines
.First()->Data(); 
2219     line
->CalculateSize( &dc
, iconSpacing 
); 
2221     line
->GetSize( dummy
, lineSpacing 
); 
2224     int clientWidth 
= 0; 
2225     int clientHeight 
= 0; 
2227     if (m_mode 
& wxLC_REPORT
) 
2231         int entireHeight 
= m_lines
.Number() * lineSpacing 
+ 2; 
2232         int scroll_pos 
= GetScrollPos( wxVERTICAL 
); 
2233 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2234         int x_scroll_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2236         SetScrollbars( m_xScroll
, m_yScroll
, 0, (entireHeight
+15) / m_yScroll
, 0, scroll_pos
, TRUE 
); 
2238         GetClientSize( &clientWidth
, &clientHeight 
); 
2240         wxNode
* node 
= m_lines
.First(); 
2241         int entireWidth 
= 0 ; 
2244             wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2245             line
->CalculateSize( &dc
, iconSpacing 
); 
2246             line
->SetPosition( &dc
, x
, y
, clientWidth 
); 
2248             for (int i 
= 0; i 
< GetColumnCount(); i
++) 
2250                 line
->SetColumnPosition( i
, col_x 
); 
2251                 col_x 
+= GetColumnWidth( i 
); 
2253             entireWidth 
= wxMax( entireWidth 
, col_x 
) ; 
2254 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2255             line
->SetPosition( &dc
, x
, y
, col_x 
); 
2257             y 
+= lineSpacing
;  // one pixel blank line between items 
2258             node 
= node
->Next(); 
2260                 m_visibleLines 
= clientHeight 
/ lineSpacing
; 
2261 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2262                 SetScrollbars( m_xScroll
, m_yScroll
, entireWidth 
/ m_xScroll 
, (entireHeight
+15) / m_yScroll
, x_scroll_pos  
, scroll_pos
, TRUE 
); 
2267         // at first we try without any scrollbar. if the items don't 
2268         // fit into the window, we recalculate after subtracting an 
2269         // approximated 15 pt for the horizontal scrollbar 
2271         GetSize( &clientWidth
, &clientHeight 
); 
2272         clientHeight 
-= 4;  // sunken frame 
2274         int entireWidth 
= 0; 
2276         for (int tries 
= 0; tries 
< 2; tries
++) 
2279             int x 
= 5;  // painting is done at x-2 
2280             int y 
= 5;  // painting is done at y-2 
2283             int m_currentVisibleLines 
= 0; 
2284             wxNode 
*node 
= m_lines
.First(); 
2287                 m_currentVisibleLines
++; 
2288                 wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2289                 line
->CalculateSize( &dc
, iconSpacing 
); 
2290                 line
->SetPosition( &dc
, x
, y
, clientWidth 
); 
2291                 line
->GetSize( lineWidth
, lineHeight 
); 
2292                 if (lineWidth 
> maxWidth
) maxWidth 
= lineWidth
; 
2294                 if (m_currentVisibleLines 
> m_visibleLines
) 
2295                     m_visibleLines 
= m_currentVisibleLines
; 
2296                 if (y
+lineSpacing
-6 >= clientHeight
) // -6 for earlier "line breaking" 
2298                     m_currentVisibleLines 
= 0; 
2301                     entireWidth 
+= maxWidth
+6; 
2304                 node 
= node
->Next(); 
2305                 if (!node
) entireWidth 
+= maxWidth
; 
2306                 if ((tries 
== 0) && (entireWidth 
> clientWidth
)) 
2308                     clientHeight 
-= 15; // scrollbar height 
2310                     m_currentVisibleLines 
= 0; 
2313                 if (!node
) tries 
= 1;  // everything fits, no second try required 
2317         int scroll_pos 
= GetScrollPos( wxHORIZONTAL 
); 
2318         SetScrollbars( m_xScroll
, m_yScroll
, (entireWidth
+15) / m_xScroll
, 0, scroll_pos
, 0, TRUE 
); 
2322 void wxListMainWindow::RealizeChanges( void ) 
2326         wxNode 
*node 
= m_lines
.First(); 
2327         if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
2331         FocusLine( m_current 
); 
2332         if (m_mode 
& wxLC_SINGLE_SEL
) m_current
->Hilight( TRUE 
); 
2336 long wxListMainWindow::GetNextItem( long item
, 
2337                                     int WXUNUSED(geometry
), 
2341          max 
= GetItemCount(); 
2342     wxCHECK_MSG( (ret 
== -1) || (ret 
< max
), -1, 
2343                  _T("invalid listctrl index in GetNextItem()") ); 
2345     // notice that we start with the next item (or the first one if item == -1) 
2346     // and this is intentional to allow writing a simple loop to iterate over 
2347     // all selected items 
2351         // this is not an error because the index was ok initially, just no 
2356     wxNode 
*node 
= m_lines
.Nth( (size_t)ret 
); 
2359         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2360         if ((state 
& wxLIST_STATE_FOCUSED
) && (line 
== m_current
)) 
2362         if ((state 
& wxLIST_STATE_SELECTED
) && (line
->IsHilighted())) 
2368         node 
= node
->Next(); 
2374 void wxListMainWindow::DeleteItem( long index 
) 
2377     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2380         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2381         if (m_current 
== line
) m_current 
= (wxListLineData 
*) NULL
; 
2383         m_lines
.DeleteNode( node 
); 
2387 void wxListMainWindow::DeleteColumn( int col 
) 
2389     wxCHECK_RET( col 
< (int)m_columns
.GetCount(), 
2390                wxT("attempting to delete inexistent column in wxListView") ); 
2393     wxNode 
*node 
= m_columns
.Nth( col 
); 
2394     if (node
) m_columns
.DeleteNode( node 
); 
2397 void wxListMainWindow::DeleteAllItems() 
2400     m_current 
= (wxListLineData 
*) NULL
; 
2402     // to make the deletion of all items faster, we don't send the 
2403     // notifications in this case: this is compatible with wxMSW and 
2404     // documented in DeleteAllItems() description 
2406     wxListEvent 
event( wxEVT_COMMAND_LIST_DELETE_ALL_ITEMS
, GetParent()->GetId() ); 
2407     event
.SetEventObject( GetParent() ); 
2408     GetParent()->GetEventHandler()->ProcessEvent( event 
); 
2413 void wxListMainWindow::DeleteEverything() 
2420 void wxListMainWindow::EnsureVisible( long index 
) 
2422     // We have to call this here because the label in 
2423     // question might just have been added and no screen 
2424     // update taken place. 
2425     if (m_dirty
) wxYield(); 
2427     wxListLineData 
*oldCurrent 
= m_current
; 
2428     m_current 
= (wxListLineData 
*) NULL
; 
2429     wxNode 
*node 
= m_lines
.Nth( (size_t)index 
); 
2430     if (node
) m_current 
= (wxListLineData
*)node
->Data(); 
2431     if (m_current
) MoveToFocus(); 
2432     m_current 
= oldCurrent
; 
2435 long wxListMainWindow::FindItem(long start
, const wxString
& str
, bool WXUNUSED(partial
) ) 
2439     if (pos 
< 0) pos 
= 0; 
2440     wxNode 
*node 
= m_lines
.Nth( (size_t)pos 
); 
2443         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2445         line
->GetText( 0, s 
); 
2446         if (s 
== tmp
) return pos
; 
2447         node 
= node
->Next(); 
2453 long wxListMainWindow::FindItem(long start
, long data
) 
2456     if (pos 
< 0) pos 
= 0; 
2457     wxNode 
*node 
= m_lines
.Nth( (size_t)pos 
); 
2460         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2462         line
->GetItem( 0, item 
); 
2463         if (item
.m_data 
== data
) return pos
; 
2464         node 
= node
->Next(); 
2470 long wxListMainWindow::HitTest( int x
, int y
, int &flags 
) 
2472     wxNode 
*node 
= m_lines
.First(); 
2476         wxListLineData 
*line 
= (wxListLineData
*)node
->Data(); 
2477         long ret 
= line
->IsHit( x
, y 
); 
2483         node 
= node
->Next(); 
2489 void wxListMainWindow::InsertItem( wxListItem 
&item 
) 
2493     if (m_mode 
& wxLC_REPORT
) mode 
= wxLC_REPORT
; 
2494     else if (m_mode 
& wxLC_LIST
) mode 
= wxLC_LIST
; 
2495     else if (m_mode 
& wxLC_ICON
) mode 
= wxLC_ICON
; 
2496     else if (m_mode 
& wxLC_SMALL_ICON
) mode 
= wxLC_ICON
;  // no typo 
2498     wxListLineData 
*line 
= new wxListLineData( this, mode
, m_hilightBrush 
); 
2500     if (m_mode 
& wxLC_REPORT
) 
2502         line
->InitItems( GetColumnCount() ); 
2503         item
.m_width 
= GetColumnWidth( 0 )-3; 
2507         line
->InitItems( 1 ); 
2510     line
->SetItem( 0, item 
); 
2511     if ((item
.m_itemId 
>= 0) && (item
.m_itemId 
< (int)m_lines
.GetCount())) 
2513         wxNode 
*node 
= m_lines
.Nth( (size_t)item
.m_itemId 
); 
2514         if (node
) m_lines
.Insert( node
, line 
); 
2518         m_lines
.Append( line 
); 
2522 void wxListMainWindow::InsertColumn( long col
, wxListItem 
&item 
) 
2525     if (m_mode 
& wxLC_REPORT
) 
2527         if (item
.m_width 
== wxLIST_AUTOSIZE_USEHEADER
) item
.m_width 
= GetTextLength( item
.m_text 
); 
2528         wxListHeaderData 
*column 
= new wxListHeaderData( item 
); 
2529         if ((col 
>= 0) && (col 
< (int)m_columns
.GetCount())) 
2531             wxNode 
*node 
= m_columns
.Nth( (size_t)col 
); 
2533                  m_columns
.Insert( node
, column 
); 
2537             m_columns
.Append( column 
); 
2542 wxListCtrlCompare list_ctrl_compare_func_2
; 
2543 long              list_ctrl_compare_data
; 
2545 int LINKAGEMODE 
list_ctrl_compare_func_1( const void *arg1
, const void *arg2 
) 
2547     wxListLineData 
*line1 
= *((wxListLineData
**)arg1
); 
2548     wxListLineData 
*line2 
= *((wxListLineData
**)arg2
); 
2550     line1
->GetItem( 0, item 
); 
2551     long data1 
= item
.m_data
; 
2552     line2
->GetItem( 0, item 
); 
2553     long data2 
= item
.m_data
; 
2554     return list_ctrl_compare_func_2( data1
, data2
, list_ctrl_compare_data 
); 
2557 void wxListMainWindow::SortItems( wxListCtrlCompare fn
, long data 
) 
2559     list_ctrl_compare_func_2 
= fn
; 
2560     list_ctrl_compare_data 
= data
; 
2561     m_lines
.Sort( list_ctrl_compare_func_1 
); 
2565 void wxListMainWindow::OnScroll(wxScrollWinEvent
& event
) 
2567         wxScrolledWindow::OnScroll( event 
) ; 
2568 #if wxUSE_GENERIC_LIST_EXTENSIONS 
2570     if (event
.GetOrientation() == wxHORIZONTAL 
&& ( m_mode 
& wxLC_REPORT 
)) 
2572             wxListCtrl
* lc 
= wxDynamicCast( GetParent() , wxListCtrl 
) ; 
2575                     lc
->m_headerWin
->Refresh() ; 
2577                         lc
->m_headerWin
->MacUpdateImmediately() ; 
2584 // ------------------------------------------------------------------------------------- 
2586 // ------------------------------------------------------------------------------------- 
2588 IMPLEMENT_DYNAMIC_CLASS(wxListItem
, wxObject
) 
2590 wxListItem::wxListItem() 
2599     m_format 
= wxLIST_FORMAT_CENTRE
; 
2605 void wxListItem::Clear() 
2614     m_format 
= wxLIST_FORMAT_CENTRE
; 
2616     m_text 
= wxEmptyString
; 
2618     if (m_attr
) delete m_attr
; 
2622 void wxListItem::ClearAttributes() 
2624     if (m_attr
) delete m_attr
; 
2628 // ------------------------------------------------------------------------------------- 
2630 // ------------------------------------------------------------------------------------- 
2632 IMPLEMENT_DYNAMIC_CLASS(wxListEvent
, wxNotifyEvent
) 
2634 wxListEvent::wxListEvent( wxEventType commandType
, int id 
): 
2635   wxNotifyEvent( commandType
, id 
) 
2641     m_cancelled 
= FALSE
; 
2646 void wxListEvent::CopyObject(wxObject
& object_dest
) const 
2648     wxListEvent 
*obj 
= (wxListEvent 
*)&object_dest
; 
2650     wxNotifyEvent::CopyObject(object_dest
); 
2652     obj
->m_code 
= m_code
; 
2653     obj
->m_itemIndex 
= m_itemIndex
; 
2654     obj
->m_oldItemIndex 
= m_oldItemIndex
; 
2656     obj
->m_cancelled 
= m_cancelled
; 
2657     obj
->m_pointDrag 
= m_pointDrag
; 
2658     obj
->m_item
.m_mask 
= m_item
.m_mask
; 
2659     obj
->m_item
.m_itemId 
= m_item
.m_itemId
; 
2660     obj
->m_item
.m_col 
= m_item
.m_col
; 
2661     obj
->m_item
.m_state 
= m_item
.m_state
; 
2662     obj
->m_item
.m_stateMask 
= m_item
.m_stateMask
; 
2663     obj
->m_item
.m_text 
= m_item
.m_text
; 
2664     obj
->m_item
.m_image 
= m_item
.m_image
; 
2665     obj
->m_item
.m_data 
= m_item
.m_data
; 
2666     obj
->m_item
.m_format 
= m_item
.m_format
; 
2667     obj
->m_item
.m_width 
= m_item
.m_width
; 
2669     if ( m_item
.HasAttributes() ) 
2671         obj
->m_item
.SetTextColour(m_item
.GetTextColour()); 
2675 // ------------------------------------------------------------------------------------- 
2677 // ------------------------------------------------------------------------------------- 
2679 IMPLEMENT_DYNAMIC_CLASS(wxListCtrl
, wxControl
) 
2681 BEGIN_EVENT_TABLE(wxListCtrl
,wxControl
) 
2682   EVT_SIZE          (wxListCtrl::OnSize
) 
2683   EVT_IDLE          (wxListCtrl::OnIdle
) 
2686 wxListCtrl::wxListCtrl() 
2688     m_imageListNormal 
= (wxImageList 
*) NULL
; 
2689     m_imageListSmall 
= (wxImageList 
*) NULL
; 
2690     m_imageListState 
= (wxImageList 
*) NULL
; 
2691     m_mainWin 
= (wxListMainWindow
*) NULL
; 
2692     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
2695 wxListCtrl::~wxListCtrl() 
2699 bool wxListCtrl::Create(wxWindow 
*parent
, 
2704                         const wxValidator 
&validator
, 
2705                         const wxString 
&name
) 
2707     m_imageListNormal 
= (wxImageList 
*) NULL
; 
2708     m_imageListSmall 
= (wxImageList 
*) NULL
; 
2709     m_imageListState 
= (wxImageList 
*) NULL
; 
2710     m_mainWin 
= (wxListMainWindow
*) NULL
; 
2711     m_headerWin 
= (wxListHeaderWindow
*) NULL
; 
2713     if ( !(style 
& (wxLC_REPORT 
| wxLC_LIST 
| wxLC_ICON
)) ) 
2715         style 
= style 
| wxLC_LIST
; 
2718     bool ret 
= wxControl::Create( parent
, id
, pos
, size
, style
, validator
, name 
); 
2721     if (style 
& wxSUNKEN_BORDER
) 
2722         style 
-= wxSUNKEN_BORDER
; 
2724     m_mainWin 
= new wxListMainWindow( this, -1, wxPoint(0,0), size
, style 
); 
2726     if (HasFlag(wxLC_REPORT
)) 
2728         m_headerWin 
= new wxListHeaderWindow( this, -1, m_mainWin
, wxPoint(0,0), wxSize(size
.x
,23), wxTAB_TRAVERSAL 
); 
2729         if (HasFlag(wxLC_NO_HEADER
)) 
2730             m_headerWin
->Show( FALSE 
); 
2734         m_headerWin 
= (wxListHeaderWindow 
*) NULL
; 
2737     SetBackgroundColour( *wxWHITE 
); 
2742 void wxListCtrl::OnSize( wxSizeEvent 
&WXUNUSED(event
) ) 
2744     /* handled in OnIdle */ 
2746     if (m_mainWin
) m_mainWin
->m_dirty 
= TRUE
; 
2749 void wxListCtrl::SetSingleStyle( long style
, bool add 
) 
2751     long flag 
= GetWindowStyle(); 
2755         if (style 
& wxLC_MASK_TYPE
)  flag 
= flag 
& ~wxLC_MASK_TYPE
; 
2756         if (style 
& wxLC_MASK_ALIGN
) flag 
= flag 
& ~wxLC_MASK_ALIGN
; 
2757         if (style 
& wxLC_MASK_SORT
) flag 
= flag 
& ~wxLC_MASK_SORT
; 
2766         if (flag 
& style
) flag 
-= style
; 
2769     SetWindowStyleFlag( flag 
); 
2772 void wxListCtrl::SetWindowStyleFlag( long flag 
) 
2776         m_mainWin
->DeleteEverything(); 
2780         GetClientSize( &width
, &height 
); 
2782         m_mainWin
->SetMode( flag 
); 
2784         if (flag 
& wxLC_REPORT
) 
2786             if (!HasFlag(wxLC_REPORT
)) 
2790                     m_headerWin 
= new wxListHeaderWindow( this, -1, m_mainWin
, 
2791                       wxPoint(0,0), wxSize(width
,23), wxTAB_TRAVERSAL 
); 
2792                     if (HasFlag(wxLC_NO_HEADER
)) 
2793                         m_headerWin
->Show( FALSE 
); 
2797                     if (flag 
& wxLC_NO_HEADER
) 
2798                         m_headerWin
->Show( FALSE 
); 
2800                         m_headerWin
->Show( TRUE 
); 
2806             if (HasFlag(wxLC_REPORT
) && !(HasFlag(wxLC_NO_HEADER
))) 
2808                 m_headerWin
->Show( FALSE 
); 
2813     wxWindow::SetWindowStyleFlag( flag 
); 
2816 bool wxListCtrl::GetColumn(int col
, wxListItem 
&item
) const 
2818     m_mainWin
->GetColumn( col
, item 
); 
2822 bool wxListCtrl::SetColumn( int col
, wxListItem
& item 
) 
2824     m_mainWin
->SetColumn( col
, item 
); 
2828 int wxListCtrl::GetColumnWidth( int col 
) const 
2830     return m_mainWin
->GetColumnWidth( col 
); 
2833 bool wxListCtrl::SetColumnWidth( int col
, int width 
) 
2835     m_mainWin
->SetColumnWidth( col
, width 
); 
2839 int wxListCtrl::GetCountPerPage() const 
2841   return m_mainWin
->GetCountPerPage();  // different from Windows ? 
2844 bool wxListCtrl::GetItem( wxListItem 
&info 
) const 
2846     m_mainWin
->GetItem( info 
); 
2850 bool wxListCtrl::SetItem( wxListItem 
&info 
) 
2852     m_mainWin
->SetItem( info 
); 
2856 long wxListCtrl::SetItem( long index
, int col
, const wxString
& label
, int imageId 
) 
2859     info
.m_text 
= label
; 
2860     info
.m_mask 
= wxLIST_MASK_TEXT
; 
2861     info
.m_itemId 
= index
; 
2865         info
.m_image 
= imageId
; 
2866         info
.m_mask 
|= wxLIST_MASK_IMAGE
; 
2868     m_mainWin
->SetItem(info
); 
2872 int wxListCtrl::GetItemState( long item
, long stateMask 
) const 
2874     return m_mainWin
->GetItemState( item
, stateMask 
); 
2877 bool wxListCtrl::SetItemState( long item
, long state
, long stateMask 
) 
2879     m_mainWin
->SetItemState( item
, state
, stateMask 
); 
2883 bool wxListCtrl::SetItemImage( long item
, int image
, int WXUNUSED(selImage
) ) 
2886     info
.m_image 
= image
; 
2887     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
2888     info
.m_itemId 
= item
; 
2889     m_mainWin
->SetItem( info 
); 
2893 wxString 
wxListCtrl::GetItemText( long item 
) const 
2896     info
.m_itemId 
= item
; 
2897     m_mainWin
->GetItem( info 
); 
2901 void wxListCtrl::SetItemText( long item
, const wxString 
&str 
) 
2904     info
.m_mask 
= wxLIST_MASK_TEXT
; 
2905     info
.m_itemId 
= item
; 
2907     m_mainWin
->SetItem( info 
); 
2910 long wxListCtrl::GetItemData( long item 
) const 
2913     info
.m_itemId 
= item
; 
2914     m_mainWin
->GetItem( info 
); 
2918 bool wxListCtrl::SetItemData( long item
, long data 
) 
2921     info
.m_mask 
= wxLIST_MASK_DATA
; 
2922     info
.m_itemId 
= item
; 
2924     m_mainWin
->SetItem( info 
); 
2928 bool wxListCtrl::GetItemRect( long item
, wxRect 
&rect
,  int WXUNUSED(code
) ) const 
2930     m_mainWin
->GetItemRect( item
, rect 
); 
2934 bool wxListCtrl::GetItemPosition( long item
, wxPoint
& pos 
) const 
2936     m_mainWin
->GetItemPosition( item
, pos 
); 
2940 bool wxListCtrl::SetItemPosition( long WXUNUSED(item
), const wxPoint
& WXUNUSED(pos
) ) 
2945 int wxListCtrl::GetItemCount() const 
2947     return m_mainWin
->GetItemCount(); 
2950 int wxListCtrl::GetColumnCount() const 
2952     return m_mainWin
->GetColumnCount(); 
2955 void wxListCtrl::SetItemSpacing( int spacing
, bool isSmall 
) 
2957     m_mainWin
->SetItemSpacing( spacing
, isSmall 
); 
2960 int wxListCtrl::GetItemSpacing( bool isSmall 
) const 
2962     return m_mainWin
->GetItemSpacing( isSmall 
); 
2965 int wxListCtrl::GetSelectedItemCount() const 
2967     return m_mainWin
->GetSelectedItemCount(); 
2970 wxColour 
wxListCtrl::GetTextColour() const 
2972     return GetForegroundColour(); 
2975 void wxListCtrl::SetTextColour(const wxColour
& col
) 
2977     SetForegroundColour(col
); 
2980 long wxListCtrl::GetTopItem() const 
2985 long wxListCtrl::GetNextItem( long item
, int geom
, int state 
) const 
2987     return m_mainWin
->GetNextItem( item
, geom
, state 
); 
2990 wxImageList 
*wxListCtrl::GetImageList(int which
) const 
2992     if (which 
== wxIMAGE_LIST_NORMAL
) 
2994         return m_imageListNormal
; 
2996     else if (which 
== wxIMAGE_LIST_SMALL
) 
2998         return m_imageListSmall
; 
3000     else if (which 
== wxIMAGE_LIST_STATE
) 
3002         return m_imageListState
; 
3004     return (wxImageList 
*) NULL
; 
3007 void wxListCtrl::SetImageList( wxImageList 
*imageList
, int which 
) 
3009     m_mainWin
->SetImageList( imageList
, which 
); 
3012 bool wxListCtrl::Arrange( int WXUNUSED(flag
) ) 
3017 bool wxListCtrl::DeleteItem( long item 
) 
3019     m_mainWin
->DeleteItem( item 
); 
3023 bool wxListCtrl::DeleteAllItems() 
3025     m_mainWin
->DeleteAllItems(); 
3029 bool wxListCtrl::DeleteAllColumns() 
3031     for ( size_t n 
= 0; n 
< m_mainWin
->m_columns
.GetCount(); n
++ ) 
3037 void wxListCtrl::ClearAll() 
3039     m_mainWin
->DeleteEverything(); 
3042 bool wxListCtrl::DeleteColumn( int col 
) 
3044     m_mainWin
->DeleteColumn( col 
); 
3048 void wxListCtrl::Edit( long item 
) 
3050     m_mainWin
->Edit( item 
); 
3053 bool wxListCtrl::EnsureVisible( long item 
) 
3055     m_mainWin
->EnsureVisible( item 
); 
3059 long wxListCtrl::FindItem( long start
, const wxString
& str
,  bool partial 
) 
3061     return m_mainWin
->FindItem( start
, str
, partial 
); 
3064 long wxListCtrl::FindItem( long start
, long data 
) 
3066     return m_mainWin
->FindItem( start
, data 
); 
3069 long wxListCtrl::FindItem( long WXUNUSED(start
), const wxPoint
& WXUNUSED(pt
), 
3070                            int WXUNUSED(direction
)) 
3075 long wxListCtrl::HitTest( const wxPoint 
&point
, int &flags 
) 
3077     return m_mainWin
->HitTest( (int)point
.x
, (int)point
.y
, flags 
); 
3080 long wxListCtrl::InsertItem( wxListItem
& info 
) 
3082     m_mainWin
->InsertItem( info 
); 
3083     return info
.m_itemId
; 
3086 long wxListCtrl::InsertItem( long index
, const wxString 
&label 
) 
3089     info
.m_text 
= label
; 
3090     info
.m_mask 
= wxLIST_MASK_TEXT
; 
3091     info
.m_itemId 
= index
; 
3092     return InsertItem( info 
); 
3095 long wxListCtrl::InsertItem( long index
, int imageIndex 
) 
3098     info
.m_mask 
= wxLIST_MASK_IMAGE
; 
3099     info
.m_image 
= imageIndex
; 
3100     info
.m_itemId 
= index
; 
3101     return InsertItem( info 
); 
3104 long wxListCtrl::InsertItem( long index
, const wxString 
&label
, int imageIndex 
) 
3107     info
.m_text 
= label
; 
3108     info
.m_image 
= imageIndex
; 
3109     info
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_IMAGE
; 
3110     info
.m_itemId 
= index
; 
3111     return InsertItem( info 
); 
3114 long wxListCtrl::InsertColumn( long col
, wxListItem 
&item 
) 
3116     wxASSERT( m_headerWin 
); 
3117     m_mainWin
->InsertColumn( col
, item 
); 
3118     m_headerWin
->Refresh(); 
3123 long wxListCtrl::InsertColumn( long col
, const wxString 
&heading
, 
3124                                int format
, int width 
) 
3127     item
.m_mask 
= wxLIST_MASK_TEXT 
| wxLIST_MASK_FORMAT
; 
3128     item
.m_text 
= heading
; 
3131         item
.m_mask 
|= wxLIST_MASK_WIDTH
; 
3132         item
.m_width 
= width
; 
3134     item
.m_format 
= format
; 
3136     return InsertColumn( col
, item 
); 
3139 bool wxListCtrl::ScrollList( int WXUNUSED(dx
), int WXUNUSED(dy
) ) 
3145 // fn is a function which takes 3 long arguments: item1, item2, data. 
3146 // item1 is the long data associated with a first item (NOT the index). 
3147 // item2 is the long data associated with a second item (NOT the index). 
3148 // data is the same value as passed to SortItems. 
3149 // The return value is a negative number if the first item should precede the second 
3150 // item, a positive number of the second item should precede the first, 
3151 // or zero if the two items are equivalent. 
3152 // data is arbitrary data to be passed to the sort function. 
3154 bool wxListCtrl::SortItems( wxListCtrlCompare fn
, long data 
) 
3156     m_mainWin
->SortItems( fn
, data 
); 
3160 void wxListCtrl::OnIdle( wxIdleEvent 
&WXUNUSED(event
) ) 
3162     if (!m_mainWin
->m_dirty
) return; 
3166     GetClientSize( &cw
, &ch 
); 
3173     if (HasFlag(wxLC_REPORT
) && !HasFlag(wxLC_NO_HEADER
)) 
3175         m_headerWin
->GetPosition( &x
, &y 
); 
3176         m_headerWin
->GetSize( &w
, &h 
); 
3177         if ((x 
!= 0) || (y 
!= 0) || (w 
!= cw
) || (h 
!= 23)) 
3178             m_headerWin
->SetSize( 0, 0, cw
, 23 ); 
3180         m_mainWin
->GetPosition( &x
, &y 
); 
3181         m_mainWin
->GetSize( &w
, &h 
); 
3182         if ((x 
!= 0) || (y 
!= 24) || (w 
!= cw
) || (h 
!= ch
-24)) 
3183             m_mainWin
->SetSize( 0, 24, cw
, ch
-24 ); 
3187         m_mainWin
->GetPosition( &x
, &y 
); 
3188         m_mainWin
->GetSize( &w
, &h 
); 
3189         if ((x 
!= 0) || (y 
!= 24) || (w 
!= cw
) || (h 
!= ch
)) 
3190             m_mainWin
->SetSize( 0, 0, cw
, ch 
); 
3193     m_mainWin
->CalculatePositions(); 
3194     m_mainWin
->RealizeChanges(); 
3195     m_mainWin
->m_dirty 
= FALSE
; 
3196     m_mainWin
->Refresh(); 
3199 bool wxListCtrl::SetBackgroundColour( const wxColour 
&colour 
) 
3201     if ( !wxWindow::SetBackgroundColour( colour 
) ) 
3206         m_mainWin
->SetBackgroundColour( colour 
); 
3207         m_mainWin
->m_dirty 
= TRUE
; 
3212 //        m_headerWin->SetBackgroundColour( colour ); 
3218 bool wxListCtrl::SetForegroundColour( const wxColour 
&colour 
) 
3220     if ( !wxWindow::SetForegroundColour( colour 
) ) 
3225         m_mainWin
->SetForegroundColour( colour 
); 
3226         m_mainWin
->m_dirty 
= TRUE
; 
3231         m_headerWin
->SetForegroundColour( colour 
); 
3237 bool wxListCtrl::SetFont( const wxFont 
&font 
) 
3239     if ( !wxWindow::SetFont( font 
) ) 
3244         m_mainWin
->SetFont( font 
); 
3245         m_mainWin
->m_dirty 
= TRUE
; 
3250         m_headerWin
->SetFont( font 
);